From 5584eb9d4ed22330f9b5894aa9eca6889d646857 Mon Sep 17 00:00:00 2001 From: Austin Chang Date: Wed, 11 Feb 2026 20:54:42 +0800 Subject: [PATCH 1/2] fix: Use correct SI units for speed test conversion - Change "Kb" to "kb" for kilo prefix (SI standard uses lowercase k) - Replace binary conversion (* 1024) with SI conversion (* 1000) for Kbps to bps - Fix dashboard history chart to use SI conversion (/ 1000.0) and handle unit variations - Update related test expectations Co-Authored-By: Claude Opus 4.5 --- .../components/widgets/atomic/speed_test.dart | 20 +++++++++++++------ .../providers/health_check_provider.dart | 2 +- .../services/health_check_service.dart | 4 ++-- .../shared_widgets/speed_test_widget.dart | 4 ++-- lib/utils.dart | 4 ++-- .../providers/health_check_provider_test.dart | 2 +- test/utils_test.dart | 8 ++++---- 7 files changed, 26 insertions(+), 18 deletions(-) diff --git a/lib/page/dashboard/views/components/widgets/atomic/speed_test.dart b/lib/page/dashboard/views/components/widgets/atomic/speed_test.dart index a0a18498e..095dce664 100644 --- a/lib/page/dashboard/views/components/widgets/atomic/speed_test.dart +++ b/lib/page/dashboard/views/components/widgets/atomic/speed_test.dart @@ -444,24 +444,32 @@ class _HistoryChartPainter extends CustomPainter { // Ideally we use uploadBandwidthKbps if available. final downloads = data.map((e) { if (e.downloadBandwidthKbps != null && e.downloadBandwidthKbps! > 0) { - return e.downloadBandwidthKbps! / 1024.0; // Mbps + return e.downloadBandwidthKbps! / 1000.0; // Mbps (SI: 1 Mbps = 1000 kbps) } // Fallback to parsing string value final speed = double.tryParse(e.downloadSpeed) ?? 0; - if (e.downloadUnit.toUpperCase() == 'KBPS') { - return speed / 1024.0; + final unit = e.downloadUnit.toLowerCase(); + if (unit == 'kb' || unit == 'kbps') { + return speed / 1000.0; + } + if (unit == 'gb' || unit == 'gbps') { + return speed * 1000.0; } return speed; // Assume Mbps }).toList(); final uploads = data.map((e) { if (e.uploadBandwidthKbps != null && e.uploadBandwidthKbps! > 0) { - return e.uploadBandwidthKbps! / 1024.0; // Mbps + return e.uploadBandwidthKbps! / 1000.0; // Mbps (SI: 1 Mbps = 1000 kbps) } // Fallback to parsing string value final speed = double.tryParse(e.uploadSpeed) ?? 0; - if (e.uploadUnit.toUpperCase() == 'KBPS') { - return speed / 1024.0; + final unit = e.uploadUnit.toLowerCase(); + if (unit == 'kb' || unit == 'kbps') { + return speed / 1000.0; + } + if (unit == 'gb' || unit == 'gbps') { + return speed * 1000.0; } return speed; // Assume Mbps }).toList(); diff --git a/lib/page/health_check/providers/health_check_provider.dart b/lib/page/health_check/providers/health_check_provider.dart index 00b662f50..445a139ec 100644 --- a/lib/page/health_check/providers/health_check_provider.dart +++ b/lib/page/health_check/providers/health_check_provider.dart @@ -155,7 +155,7 @@ class HealthCheckProvider extends Notifier { }); } else { // Add a random value to simulate a fluctuating meter during tests. - final randomValue = (_random.nextDouble() * (15 - (-3)) + (-3)) * 1024; + final randomValue = (_random.nextDouble() * (15 - (-3)) + (-3)) * 1000; meterValue += randomValue; } diff --git a/lib/page/health_check/services/health_check_service.dart b/lib/page/health_check/services/health_check_service.dart index e4a5e5ba8..9aacb7078 100644 --- a/lib/page/health_check/services/health_check_service.dart +++ b/lib/page/health_check/services/health_check_service.dart @@ -186,11 +186,11 @@ class SpeedTestService { return SpeedTestUIModel.empty(); } final download = NetworkUtils.formatBitsWithUnit( - (speedTestResult.downloadBandwidth ?? 0) * 1024, + (speedTestResult.downloadBandwidth ?? 0) * 1000, decimals: 1, ); final upload = NetworkUtils.formatBitsWithUnit( - (speedTestResult.uploadBandwidth ?? 0) * 1024, + (speedTestResult.uploadBandwidth ?? 0) * 1000, decimals: 1, ); final (formattedTimestamp, _) = _formatTimestamp(timestamp ?? ''); diff --git a/lib/page/health_check/shared_widgets/speed_test_widget.dart b/lib/page/health_check/shared_widgets/speed_test_widget.dart index ee53c151e..efecc3be0 100644 --- a/lib/page/health_check/shared_widgets/speed_test_widget.dart +++ b/lib/page/health_check/shared_widgets/speed_test_widget.dart @@ -225,13 +225,13 @@ class SpeedTestWidget extends ConsumerWidget { final result = state.result ?? SpeedTestUIModel.empty(); // Format the live meter value for display. final formattedLiveValue = NetworkUtils.formatBitsWithUnit( - (state.meterValue * 1024).toInt(), + (state.meterValue * 1000).toInt(), decimals: 1); final bandwidthValue = formattedLiveValue.value; final bandwidthUnit = formattedLiveValue.unit; - final meterValueMbps = (state.meterValue / 1024); + final meterValueMbps = (state.meterValue / 1000); return Center( child: AppGauge( diff --git a/lib/utils.dart b/lib/utils.dart index 9bb6b93d9..2061a469a 100644 --- a/lib/utils.dart +++ b/lib/utils.dart @@ -330,7 +330,7 @@ extension MediaQueryUtils on Utils { extension NetworkUtils on Utils { /// Formats a bit count into a human-readable string with SI units (base 1000). /// - /// Example: 1000 bits -> "1 Kb" + /// Example: 1000 bits -> "1 kb" static String formatBits(int bits, {int decimals = 0}) { final result = formatBitsWithUnit(bits, decimals: decimals); return '${result.value} ${result.unit}'; @@ -342,7 +342,7 @@ extension NetworkUtils on Utils { static ({String value, String unit}) formatBitsWithUnit(int bits, {int decimals = 0}) { if (bits <= 0) return (value: '0', unit: "b"); - const suffixes = ["b", "Kb", "Mb", "Gb", "Tb", "Pb"]; + const suffixes = ["b", "kb", "Mb", "Gb", "Tb", "Pb"]; var i = (log(bits) / log(1000)).floor(); var number = (bits / pow(1000, i)); return ( diff --git a/test/page/health_check/providers/health_check_provider_test.dart b/test/page/health_check/providers/health_check_provider_test.dart index fc7225e3b..79393cb3e 100644 --- a/test/page/health_check/providers/health_check_provider_test.dart +++ b/test/page/health_check/providers/health_check_provider_test.dart @@ -266,7 +266,7 @@ void main() { expect(state.result, partialResult); expect(state.step, HealthCheckStep.uploadBandwidth); // Meter value should have changed from 0.0 (initial) to a predictable non-zero value - const expectedRandomValue = (0.5 * (15 - (-3)) + (-3)) * 1024; + const expectedRandomValue = (0.5 * (15 - (-3)) + (-3)) * 1000; expect(state.meterValue, expectedRandomValue); }); diff --git a/test/utils_test.dart b/test/utils_test.dart index bae77126d..566b6b682 100644 --- a/test/utils_test.dart +++ b/test/utils_test.dart @@ -510,7 +510,7 @@ void main() { test('formatBits: formats bits in kilobytes range with specified decimals', () { const bits = 1234; - const expected = '1.234 Kb'; + const expected = '1.234 kb'; final formattedBits = NetworkUtils.formatBits(bits, decimals: 3); expect(formattedBits, expected); @@ -565,7 +565,7 @@ void main() { expect(result.unit, 'b'); }); - test('formats bits (less than 1Kb)', () { + test('formats bits (less than 1kb)', () { const bits = 500; final result = NetworkUtils.formatBitsWithUnit(bits); expect(result.value, '500'); @@ -573,10 +573,10 @@ void main() { }); test('formats kilobytes with 0 decimal places', () { - const bits = 2000; // 2 Kb + const bits = 2000; // 2 kb final result = NetworkUtils.formatBitsWithUnit(bits); expect(result.value, '2'); - expect(result.unit, 'Kb'); + expect(result.unit, 'kb'); }); test('formats megabytes with 2 decimal places', () { From f41b7cebd8c8e1349e12215414417093134ea557 Mon Sep 17 00:00:00 2001 From: Austin Chang Date: Wed, 11 Feb 2026 21:15:40 +0800 Subject: [PATCH 2/2] fix format --- .../dashboard/views/components/widgets/atomic/speed_test.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/page/dashboard/views/components/widgets/atomic/speed_test.dart b/lib/page/dashboard/views/components/widgets/atomic/speed_test.dart index 095dce664..cdbce1e82 100644 --- a/lib/page/dashboard/views/components/widgets/atomic/speed_test.dart +++ b/lib/page/dashboard/views/components/widgets/atomic/speed_test.dart @@ -444,7 +444,8 @@ class _HistoryChartPainter extends CustomPainter { // Ideally we use uploadBandwidthKbps if available. final downloads = data.map((e) { if (e.downloadBandwidthKbps != null && e.downloadBandwidthKbps! > 0) { - return e.downloadBandwidthKbps! / 1000.0; // Mbps (SI: 1 Mbps = 1000 kbps) + return e.downloadBandwidthKbps! / + 1000.0; // Mbps (SI: 1 Mbps = 1000 kbps) } // Fallback to parsing string value final speed = double.tryParse(e.downloadSpeed) ?? 0;