Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
90 lines
3.0 KiB
C++
90 lines
3.0 KiB
C++
// SPDX-License-Identifier: MIT
|
|
#include "status_text.hpp"
|
|
|
|
#include <cmath>
|
|
#include <cstdio>
|
|
|
|
namespace udpscope {
|
|
|
|
/// `12 s`, `3m 07s`, `2h 14m` -- one unit coarser as soon as the finer one would need
|
|
/// three digits, so the field never grows past six characters and the status line's shape
|
|
/// does not depend on how long the wait has been.
|
|
std::string format_elapsed(double seconds) {
|
|
if (!(seconds >= 0.0)) return "--";
|
|
char buf[32];
|
|
if (seconds < 60.0) {
|
|
std::snprintf(buf, sizeof(buf), "%.0f s", std::floor(seconds));
|
|
} else if (seconds < 3600.0) {
|
|
const int m = static_cast<int>(seconds) / 60;
|
|
std::snprintf(buf, sizeof(buf), "%dm %02ds", m, static_cast<int>(seconds) % 60);
|
|
} else {
|
|
const int h = static_cast<int>(seconds) / 3600;
|
|
std::snprintf(buf, sizeof(buf), "%dh %02dm", h, (static_cast<int>(seconds) / 60) % 60);
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
/// A sample rate in the unit it reads shortest in. Rates here span six decades (a 1 Hz
|
|
/// housekeeping signal next to a 1 MS/s acquisition), so a fixed unit makes one of the
|
|
/// two unreadable.
|
|
std::string format_rate(double per_s) {
|
|
char buf[32];
|
|
if (!(per_s > 0.0)) {
|
|
return "0 S/s";
|
|
} else if (per_s >= 1.0e6) {
|
|
std::snprintf(buf, sizeof(buf), "%.3g MS/s", per_s / 1.0e6);
|
|
} else if (per_s >= 1.0e3) {
|
|
std::snprintf(buf, sizeof(buf), "%.3g kS/s", per_s / 1.0e3);
|
|
} else {
|
|
std::snprintf(buf, sizeof(buf), "%.3g S/s", per_s);
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
std::string format_glance(const StatusSnapshot& s) {
|
|
std::string out = s.state_word;
|
|
out += " · ";
|
|
out += s.rate_text.empty() ? "no data" : s.rate_text;
|
|
out += " · ";
|
|
out += s.window_text;
|
|
out += " window";
|
|
if (s.trigger_on) {
|
|
out += " · ";
|
|
if (s.have_event) {
|
|
out += "event " + format_elapsed(s.since_event_s) + " ago";
|
|
} else {
|
|
out += "no event yet";
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
|
|
std::string format_detail(const StatusSnapshot& s) {
|
|
char buf[1024];
|
|
std::snprintf(buf, sizeof(buf),
|
|
"[%s] %s %s | rate %s | packets %llu frames %llu gaps %llu | %zu signals, "
|
|
"%zu channels | plot 1: %d trace(s), %zu samples | buffer %.1f MB, %.2f s "
|
|
"span, time x%llu",
|
|
s.state_detail.c_str(), s.connected ? "connected" : "waiting",
|
|
s.have_config ? "configured" : "-",
|
|
s.rate_text.empty() ? "--" : s.rate_text.c_str(),
|
|
static_cast<unsigned long long>(s.packets),
|
|
static_cast<unsigned long long>(s.frames),
|
|
static_cast<unsigned long long>(s.gaps), s.signals, s.channels,
|
|
s.plot1_traces, s.plot1_samples, s.buffer_mb, s.span_s,
|
|
static_cast<unsigned long long>(s.time_stride));
|
|
std::string out = buf;
|
|
if (s.trigger_on) {
|
|
out += s.have_event ? " | last event " + format_elapsed(s.since_event_s) + " ago"
|
|
: " | no event yet";
|
|
}
|
|
if (s.reconnects > 0) {
|
|
char note[48];
|
|
std::snprintf(note, sizeof(note), " | %d reconnects", s.reconnects);
|
|
out += note;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
} // namespace udpscope
|