fix: calculate jt808 mileage from total range

This commit is contained in:
lingniu
2026-07-01 05:05:52 +08:00
parent 6016e3f99c
commit 6c9459bb64
2 changed files with 52 additions and 18 deletions

View File

@@ -63,25 +63,26 @@ public final class JdbcVehicleStatMetricRepository implements VehicleStatReposit
} }
String normalizedVin = clean(vin); String normalizedVin = clean(vin);
Date date = Date.valueOf(statDate); Date date = Date.valueOf(statDate);
OptionalDouble existingStart = findMetric(normalizedVin, date, DAILY_MILEAGE_START_TOTAL_KEY);
double startTotalMileage = existingStart.orElse(totalMileageKm);
if (existingStart.isEmpty()) {
upsertMetric(normalizedVin, date, DAILY_MILEAGE_START_TOTAL_KEY, startTotalMileage,
DAILY_MILEAGE_UNIT, DailyMileageStrategy.JT808_TOTAL_MILEAGE_DIFF.name());
}
OptionalDouble existingLatest = findMetric(normalizedVin, date, DAILY_MILEAGE_LATEST_TOTAL_KEY);
if (existingLatest.isPresent() && totalMileageKm < existingLatest.getAsDouble()) {
return findDailyStat(normalizedVin, statDate);
}
if (totalMileageKm < startTotalMileage) {
return findDailyStat(normalizedVin, statDate);
}
String strategy = DailyMileageStrategy.JT808_TOTAL_MILEAGE_DIFF.name(); String strategy = DailyMileageStrategy.JT808_TOTAL_MILEAGE_DIFF.name();
upsertMetric(normalizedVin, date, DAILY_MILEAGE_LATEST_TOTAL_KEY, totalMileageKm, OptionalDouble existingMin = findMetric(normalizedVin, date, DAILY_MILEAGE_START_TOTAL_KEY);
DAILY_MILEAGE_UNIT, strategy); double minTotalMileage = existingMin.isPresent()
double dailyMileageKm = totalMileageKm - startTotalMileage; ? Math.min(existingMin.getAsDouble(), totalMileageKm)
: totalMileageKm;
if (existingMin.isEmpty() || Double.compare(minTotalMileage, existingMin.getAsDouble()) != 0) {
upsertMetric(normalizedVin, date, DAILY_MILEAGE_START_TOTAL_KEY, minTotalMileage,
DAILY_MILEAGE_UNIT, strategy);
}
OptionalDouble existingMax = findMetric(normalizedVin, date, DAILY_MILEAGE_LATEST_TOTAL_KEY);
double maxTotalMileage = existingMax.isPresent()
? Math.max(existingMax.getAsDouble(), totalMileageKm)
: totalMileageKm;
if (existingMax.isEmpty() || Double.compare(maxTotalMileage, existingMax.getAsDouble()) != 0) {
upsertMetric(normalizedVin, date, DAILY_MILEAGE_LATEST_TOTAL_KEY, maxTotalMileage,
DAILY_MILEAGE_UNIT, strategy);
}
double dailyMileageKm = maxTotalMileage - minTotalMileage;
VehicleDailyStatResult result = new VehicleDailyStatResult( VehicleDailyStatResult result = new VehicleDailyStatResult(
normalizedVin, normalizedVin,
statDate, statDate,

View File

@@ -78,6 +78,39 @@ class JdbcVehicleStatMetricRepositoryTest {
String.class)).isEmpty(); String.class)).isEmpty();
} }
@Test
void recalculatesJt808MileageFromDailyMinAndMaxTotalsWhenSamplesArriveOutOfOrder() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(new DriverManagerDataSource(
"jdbc:h2:mem:vehicle_stat_metric_jt808_out_of_order;MODE=MySQL;DATABASE_TO_LOWER=TRUE;DB_CLOSE_DELAY=-1",
"sa",
""));
JdbcVehicleStatMetricRepository repository = new JdbcVehicleStatMetricRepository(jdbcTemplate);
repository.recordDailyMileageSample("VIN001", LocalDate.of(2026, 7, 1), 1008.75).orElseThrow();
VehicleDailyStatResult lowerSample = repository.recordDailyMileageSample(
"VIN001", LocalDate.of(2026, 7, 1), 1000.5).orElseThrow();
VehicleDailyStatResult higherSample = repository.recordDailyMileageSample(
"VIN001", LocalDate.of(2026, 7, 1), 1010.0).orElseThrow();
assertThat(lowerSample.dailyMileageKm()).hasValue(8.25);
assertThat(higherSample.dailyMileageKm()).hasValue(9.5);
assertThat(jdbcTemplate.queryForObject("""
SELECT metric_value
FROM vehicle_stat_metric
WHERE vin = 'VIN001' AND metric_key = 'daily_mileage_start_total_km'
""", Double.class)).isEqualTo(1000.5);
assertThat(jdbcTemplate.queryForObject("""
SELECT metric_value
FROM vehicle_stat_metric
WHERE vin = 'VIN001' AND metric_key = 'daily_mileage_latest_total_km'
""", Double.class)).isEqualTo(1010.0);
assertThat(jdbcTemplate.queryForObject("""
SELECT metric_value
FROM vehicle_stat_metric
WHERE vin = 'VIN001' AND metric_key = 'daily_mileage_km'
""", Double.class)).isEqualTo(9.5);
}
@Test @Test
void readsLegacyCalculationMethodAsTotalMileageDifference() { void readsLegacyCalculationMethodAsTotalMileageDifference() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(new DriverManagerDataSource( JdbcTemplate jdbcTemplate = new JdbcTemplate(new DriverManagerDataSource(