Multi-Decimal Resource Consumption Rounding in Real-Time Dashboard Aggregation
Problem Statement
The real-time resource consumption dashboard in src/components/dashboard/ConsumptionPanel.tsx aggregates live telemetry readings from multiple utility resources (water in megaliters, energy in kWh, bandwidth in GB) into a unified "resource units" display. The aggregateReadings() function at src/utils/aggregation/resourceMath.ts:55 applies resource-specific conversion factors (WATER_FACTOR = 1000.0, ENERGY_FACTOR = 3.6e6, BANDWIDTH_FACTOR = 1.0e9) to raw meter readings before summing. Each conversion uses JavaScript Number arithmetic. When ENERGY_FACTOR = 3,600,000 is multiplied by a reading of 999999999999 (1 trillion micro-joules), the product is 3.5999999999964e18 instead of 3.6e18, a loss of 360,000 resource units. This 0.01% error is visually imperceptible per-reading but accumulates to a 3.5% dashboard discrepancy over a 24-hour window, causing operators to misjudge resource availability by millions of units.
State Invariants & Parameters
- Resource factors:
WATER = 10^3, ENERGY = 3.6×10^6, BANDWIDTH = 10^9
- Max readings per aggregation window: 10,000
- Dashboard refresh interval: 5 seconds
- Precision target: < 0.001% cumulative error over 24h
- JavaScript
Number.MAX_SAFE_INTEGER: 9,007,199,254,740,991
- Invariant:
|displayed_total - exact_total| / exact_total < 10^-5
Affected Code Paths
src/utils/aggregation/resourceMath.ts:50-95 — aggregateReadings() using Number multiplication
src/utils/aggregation/unitConversion.ts:30-60 — Per-resource conversion factors as number literals
src/components/dashboard/ConsumptionPanel.tsx:80-120 — Dashboard display of aggregated values
src/utils/aggregation/tests/resourceMath.test.ts — No high-precision overflow tests
Resolution Blueprint
- Replace
Number arithmetic with BigInt throughout the aggregation pipeline. Define conversion factors as BigInt constants: WATER_FACTOR = 1000n, ENERGY_FACTOR = 3600000n, BANDWIDTH_FACTOR = 1000000000n. Perform all multiplication in BigInt space, then convert to Number only at the final display step using Number(aggregated / DISPLAY_DIVISOR).
- Implement a
ResourceUnits class in src/utils/aggregation/ResourceUnits.ts that stores the value as BigInt with an explicit scale (default 18). Provides add(), multiply(), toDisplay(decimals) methods that preserve precision.
- For the dashboard display, use
Intl.NumberFormat with maximumFractionDigits: 4 and minimumFractionDigits: 2 for the final formatted string, but only after converting from BigInt to Number at the tail of the pipeline (single lossy conversion point).
- Add a precision audit log:
resourceMath.ts computes both the BigInt exact value and the Number approximate value, logging a warning if |approx - exact| / exact > 10^-5. This provides observability for precision degradation.
- Add property-based tests generating 10,000 random reading tuples covering all three resource types with values spanning
[0, 10^15], verifying aggregateReadings() relative error is always < 10^-5.
Labels
Complexity: Hardcore
Layer: Core-Engine
Type: Race-Condition
Multi-Decimal Resource Consumption Rounding in Real-Time Dashboard Aggregation
Problem Statement
The real-time resource consumption dashboard in
src/components/dashboard/ConsumptionPanel.tsxaggregates live telemetry readings from multiple utility resources (water in megaliters, energy in kWh, bandwidth in GB) into a unified "resource units" display. TheaggregateReadings()function atsrc/utils/aggregation/resourceMath.ts:55applies resource-specific conversion factors (WATER_FACTOR = 1000.0,ENERGY_FACTOR = 3.6e6,BANDWIDTH_FACTOR = 1.0e9) to raw meter readings before summing. Each conversion uses JavaScriptNumberarithmetic. WhenENERGY_FACTOR = 3,600,000is multiplied by a reading of999999999999(1 trillion micro-joules), the product is3.5999999999964e18instead of3.6e18, a loss of 360,000 resource units. This 0.01% error is visually imperceptible per-reading but accumulates to a 3.5% dashboard discrepancy over a 24-hour window, causing operators to misjudge resource availability by millions of units.State Invariants & Parameters
WATER = 10^3,ENERGY = 3.6×10^6,BANDWIDTH = 10^9Number.MAX_SAFE_INTEGER: 9,007,199,254,740,991|displayed_total - exact_total| / exact_total < 10^-5Affected Code Paths
src/utils/aggregation/resourceMath.ts:50-95—aggregateReadings()usingNumbermultiplicationsrc/utils/aggregation/unitConversion.ts:30-60— Per-resource conversion factors asnumberliteralssrc/components/dashboard/ConsumptionPanel.tsx:80-120— Dashboard display of aggregated valuessrc/utils/aggregation/tests/resourceMath.test.ts— No high-precision overflow testsResolution Blueprint
Numberarithmetic withBigIntthroughout the aggregation pipeline. Define conversion factors asBigIntconstants:WATER_FACTOR = 1000n,ENERGY_FACTOR = 3600000n,BANDWIDTH_FACTOR = 1000000000n. Perform all multiplication inBigIntspace, then convert toNumberonly at the final display step usingNumber(aggregated / DISPLAY_DIVISOR).ResourceUnitsclass insrc/utils/aggregation/ResourceUnits.tsthat stores the value asBigIntwith an explicitscale(default 18). Providesadd(),multiply(),toDisplay(decimals)methods that preserve precision.Intl.NumberFormatwithmaximumFractionDigits: 4andminimumFractionDigits: 2for the final formatted string, but only after converting fromBigInttoNumberat the tail of the pipeline (single lossy conversion point).resourceMath.tscomputes both theBigIntexact value and theNumberapproximate value, logging a warning if|approx - exact| / exact > 10^-5. This provides observability for precision degradation.[0, 10^15], verifyingaggregateReadings()relative error is always <10^-5.Labels
Complexity: HardcoreLayer: Core-EngineType: Race-Condition