feat: stats — per-band mode split (CW / phone / data) stacked bar chart

Adds Stats.ByBandCategory (per band: CW/phone/data counts, band-plan order) via a
modeCategory() bucketing in stats.go, and a StackedBandBars chart in the Stats
panel showing the split per band with a legend.
This commit is contained in:
2026-07-20 21:20:29 +02:00
parent 3ec23bc613
commit 19c91f32a0
4 changed files with 120 additions and 6 deletions
+22
View File
@@ -3411,6 +3411,26 @@ export namespace qslcard {
export namespace qso {
export class BandCategory {
band: string;
cw: number;
phone: number;
data: number;
total: number;
static createFrom(source: any = {}) {
return new BandCategory(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.band = source["band"];
this.cw = source["cw"];
this.phone = source["phone"];
this.data = source["data"];
this.total = source["total"];
}
}
export class BandMode {
band: string;
mode: string;
@@ -3900,6 +3920,7 @@ export namespace qso {
confirmed_any: number;
by_mode: Bucket[];
by_band: Bucket[];
by_band_category: BandCategory[];
by_operator: Bucket[];
by_station: Bucket[];
by_continent: Bucket[];
@@ -3939,6 +3960,7 @@ export namespace qso {
this.confirmed_any = source["confirmed_any"];
this.by_mode = this.convertValues(source["by_mode"], Bucket);
this.by_band = this.convertValues(source["by_band"], Bucket);
this.by_band_category = this.convertValues(source["by_band_category"], BandCategory);
this.by_operator = this.convertValues(source["by_operator"], Bucket);
this.by_station = this.convertValues(source["by_station"], Bucket);
this.by_continent = this.convertValues(source["by_continent"], Bucket);