Added class clearance fixes and improvements
Some checks failed
Release / meta (push) Successful in 18s
Release / android-build (push) Successful in 11m48s
Release / linux-build (push) Successful in 1m24s
Release / web-build (push) Successful in 6m15s
Release / release-dev (push) Has been cancelled
Release / release-master (push) Has been cancelled

This commit is contained in:
2026-01-22 23:17:15 +00:00
parent 559f79b805
commit d8312a3f1b
19 changed files with 865 additions and 63 deletions

View File

@@ -519,6 +519,8 @@ class StatsAbout {
final networkByYear = <int, List<StatsNetworkMileage>>{};
final stationByYear = <int, List<StatsStationVisits>>{};
final winnersByYear = <int, int>{};
final winnerTypeCountsByYear = <int, Map<String, int>>{};
final totalTypeCountsByYear = <int, Map<String, int>>{};
void addYearMileage(dynamic entry) {
if (entry is Map<String, dynamic>) {
@@ -589,6 +591,16 @@ class StatsAbout {
}
}
Map<String, int> parseTypeCounts(dynamic value) {
if (value is Map) {
final entries = value.entries
.map((entry) => MapEntry(entry.key.toString(), _asInt(entry.value)))
.where((entry) => entry.key.isNotEmpty);
return Map<String, int>.fromEntries(entries);
}
return const {};
}
parseYearMap<List<StatsClassMileage>>(
json['top_classes'],
classByYear,
@@ -610,6 +622,19 @@ class StatsAbout {
if (year == null) return;
if (value is List) {
winnersByYear[year] = value.length;
} else if (value is Map) {
final mapped = value.map(
(entryKey, entryValue) =>
MapEntry(entryKey.toString(), entryValue),
);
final winners = mapped['winners'];
if (winners is List) {
winnersByYear[year] = winners.length;
}
winnerTypeCountsByYear[year] =
parseTypeCounts(mapped['winner_type_counts']);
totalTypeCountsByYear[year] =
parseTypeCounts(mapped['total_type_counts']);
}
});
}
@@ -620,6 +645,8 @@ class StatsAbout {
...networkByYear.keys,
...stationByYear.keys,
...winnersByYear.keys,
...winnerTypeCountsByYear.keys,
...totalTypeCountsByYear.keys,
}..removeWhere((year) => year == 0);
final yearMap = <int, StatsYear>{};
@@ -631,6 +658,8 @@ class StatsAbout {
topNetworks: networkByYear[year] ?? const [],
topStations: stationByYear[year] ?? const [],
winnerCount: winnersByYear[year] ?? 0,
winnerTypeCounts: winnerTypeCountsByYear[year] ?? const {},
totalTypeCounts: totalTypeCountsByYear[year] ?? const {},
);
}
@@ -651,6 +680,8 @@ class StatsYear {
final List<StatsNetworkMileage> topNetworks;
final List<StatsStationVisits> topStations;
final int winnerCount;
final Map<String, int> winnerTypeCounts;
final Map<String, int> totalTypeCounts;
StatsYear({
required this.year,
@@ -659,6 +690,8 @@ class StatsYear {
required this.topNetworks,
required this.topStations,
required this.winnerCount,
required this.winnerTypeCounts,
required this.totalTypeCounts,
});
}
@@ -1779,12 +1812,18 @@ class ClassClearanceProgress {
final int completed;
final int total;
final double percentComplete;
final int activeCompleted;
final int activeTotal;
final double activePercent;
ClassClearanceProgress({
required this.className,
required this.completed,
required this.total,
required this.percentComplete,
required this.activeCompleted,
required this.activeTotal,
required this.activePercent,
});
factory ClassClearanceProgress.fromJson(Map<String, dynamic> json) {
@@ -1802,11 +1841,34 @@ class ClassClearanceProgress {
if (percent == 0 && total > 0) {
percent = (completed / total) * 100;
}
final activeCompleted = _asInt(
json['active_completed'] ??
json['active_done'] ??
json['active_count'] ??
json['active_had'] ??
json['had_active'],
);
final activeTotal =
_asInt(json['active_total'] ??
json['active_required'] ??
json['active_goal'] ??
json['total_active']);
double activePercent = _asDouble(
json['active_percent'] ??
json['active_pct'] ??
json['active_completion'],
);
if (activePercent == 0 && activeTotal > 0) {
activePercent = (activeCompleted / activeTotal) * 100;
}
return ClassClearanceProgress(
className: name.isNotEmpty ? name : 'Class',
completed: completed,
total: total,
percentComplete: percent,
activeCompleted: activeCompleted,
activeTotal: activeTotal,
activePercent: activePercent,
);
}
}