94 lines
3.2 KiB
C++
94 lines
3.2 KiB
C++
/**
|
|
* @file StatsPanel.cpp
|
|
* @brief Statistics table implementation.
|
|
*/
|
|
|
|
#include "StatsPanel.h"
|
|
#include "App.h"
|
|
|
|
#include "imgui.h"
|
|
#include "implot.h"
|
|
|
|
#include <cstdio>
|
|
|
|
namespace StreamHubClient {
|
|
|
|
void RenderStatsPanel(App& app) {
|
|
const auto& sources = app.sources();
|
|
|
|
ImGuiTableFlags flags =
|
|
ImGuiTableFlags_Borders |
|
|
ImGuiTableFlags_RowBg |
|
|
ImGuiTableFlags_ScrollX |
|
|
ImGuiTableFlags_SizingFixedFit;
|
|
|
|
if (!ImGui::BeginTable("##statstbl", 9, flags)) { return; }
|
|
|
|
ImGui::TableSetupScrollFreeze(1, 1);
|
|
ImGui::TableSetupColumn("Source");
|
|
ImGui::TableSetupColumn("State");
|
|
ImGui::TableSetupColumn("Cycles Rx");
|
|
ImGui::TableSetupColumn("Lost");
|
|
ImGui::TableSetupColumn("Rate Hz");
|
|
ImGui::TableSetupColumn("Frags/cyc");
|
|
ImGui::TableSetupColumn("Bytes/cyc");
|
|
ImGui::TableSetupColumn("Cycle ms (avg±std)");
|
|
ImGui::TableSetupColumn("Cycle ms (min/max)");
|
|
ImGui::TableHeadersRow();
|
|
|
|
for (const auto& src : sources) {
|
|
const SourceStats& st = src.stats;
|
|
|
|
ImGui::TableNextRow();
|
|
ImGui::TableNextColumn(); ImGui::TextUnformatted(src.id.c_str());
|
|
|
|
/* State cell with color */
|
|
ImGui::TableNextColumn();
|
|
ImVec4 stColor = (st.state == "connected")
|
|
? ImVec4(0.2f,0.9f,0.3f,1.f)
|
|
: ImVec4(0.9f,0.3f,0.3f,1.f);
|
|
ImGui::TextColored(stColor, "%s", st.state.c_str());
|
|
|
|
ImGui::TableNextColumn(); ImGui::Text("%llu", (unsigned long long)st.totalReceived);
|
|
ImGui::TableNextColumn(); ImGui::Text("%llu", (unsigned long long)st.totalLost);
|
|
ImGui::TableNextColumn(); ImGui::Text("%.2f ± %.2f", st.rateHz, st.rateStdHz);
|
|
ImGui::TableNextColumn(); ImGui::Text("%.1f", st.fragsPerCycle);
|
|
ImGui::TableNextColumn(); ImGui::Text("%.0f", st.bytesPerCycle);
|
|
ImGui::TableNextColumn(); ImGui::Text("%.3f ± %.3f", st.cycleAvgMs, st.cycleStdMs);
|
|
ImGui::TableNextColumn(); ImGui::Text("%.3f / %.3f", st.cycleMinMs, st.cycleMaxMs);
|
|
}
|
|
|
|
ImGui::EndTable();
|
|
|
|
/* ── Cycle-time histograms (20 bins, mirrors web UI) ────────────── */
|
|
for (const auto& src : sources) {
|
|
const SourceStats& st = src.stats;
|
|
if (st.cycleHistMax <= st.cycleHistMin) { continue; }
|
|
|
|
char title[160];
|
|
snprintf(title, sizeof(title), "Cycle time %s##hist_%s",
|
|
src.id.c_str(), src.id.c_str());
|
|
if (ImPlot::BeginPlot(title, ImVec2(-1.f, 140.f),
|
|
ImPlotFlags_NoMouseText | ImPlotFlags_NoMenus)) {
|
|
const double binW =
|
|
(st.cycleHistMax - st.cycleHistMin) / 20.0;
|
|
double xs[20];
|
|
for (int b = 0; b < 20; b++) {
|
|
xs[b] = st.cycleHistMin + (b + 0.5) * binW;
|
|
}
|
|
ImPlot::SetupAxes("cycle ms", "count",
|
|
ImPlotAxisFlags_AutoFit,
|
|
ImPlotAxisFlags_AutoFit);
|
|
ImPlot::PlotBars("##bars", xs, st.cycleHist, 20, binW * 0.9);
|
|
ImPlot::EndPlot();
|
|
}
|
|
}
|
|
|
|
ImGui::Spacing();
|
|
if (ImGui::Button("Refresh")) {
|
|
app.ws().sendText(BuildGetStats());
|
|
}
|
|
}
|
|
|
|
} /* namespace StreamHubClient */
|