Make station price age informational only
The relay's price_updated is the maximum price_last_updated across the grades it maps, so it cannot vouch for the selected grade: stop using it to score, gate or warn about Best Value. - FuelPriceFreshness is now station-level and display-only: one age per station, fresh/outdated/unknown/invalid, "May be outdated" past 30 days, with future-tolerance and non-finite guards. - Best Value restores the closest-station-selling-the-selected-fuel baseline and its savings ranking; eligibility gating, eligible-first sorting and the unavailable banner are gone. - Price age appears in the More info sheet only - no listing-row warnings, no extra banners. - Copy reverted from "closest eligible station" to "closest station"; stale price-confidence strings removed, "May be outdated" added. - Dormant per-grade timestamp plumbing removed, and regression tests added for every fuel type, missing/invalid/future stamps and the bundled offline dump.
This commit is contained in:
+11
-31
@@ -401,9 +401,9 @@ struct ContentView: View {
|
||||
/// (computing a journey for each) and `savingsLookup` immediately scanned them
|
||||
/// all AGAIN to fill the per-station map. Both now share one result.
|
||||
///
|
||||
/// The baseline is chosen with the same journey and selected-fuel freshness
|
||||
/// guards as `FuelSavingsEstimator.bestValueBaselineStation` when configured;
|
||||
/// with the feature off, the ordinary Closest station still names that row.
|
||||
/// The baseline is chosen with the same journey guards as
|
||||
/// `FuelSavingsEstimator.baselineStation` when configured; with the feature
|
||||
/// off, the ordinary Closest station still names that row.
|
||||
private func savingsScaffold() -> (baseline: FuelStation?, journeys: [String: FuelSavingsJourney]) {
|
||||
guard let location else { return (nil, [:]) }
|
||||
guard fuelSavingsSettings.isConfigured else {
|
||||
@@ -418,7 +418,7 @@ struct ContentView: View {
|
||||
journeys[station.id] = journey
|
||||
}
|
||||
}
|
||||
let baseline = FuelSavingsEstimator.bestValueBaselineStation(stations, fuel: selectedFuel) {
|
||||
let baseline = FuelSavingsEstimator.baselineStation(stations, fuel: selectedFuel) {
|
||||
journeys[$0.id]
|
||||
}
|
||||
return (baseline, journeys)
|
||||
@@ -454,15 +454,15 @@ struct ContentView: View {
|
||||
}
|
||||
}
|
||||
|
||||
/// The Closest station with an eligible selected-fuel price — the Best Value
|
||||
/// comparison baseline. Ordinary Closest sorting still includes stale stations.
|
||||
/// It uses the same journey values as the savings calculation, so a cached
|
||||
/// road route can change the baseline and keep the "extra return travel"
|
||||
/// labels synchronized with the cost calculation. Without a cached route,
|
||||
/// the journey falls back to straight-line and the result is an estimate.
|
||||
/// The nearest station that sells the selected fuel — the Best Value
|
||||
/// comparison baseline. It is chosen with the SAME journey values used by
|
||||
/// the savings calculation, so a cached road route can change the baseline
|
||||
/// and keep the "extra return travel" labels synchronized with the
|
||||
/// cost calculation. When no road route is cached, the journey falls back to
|
||||
/// straight-line out-and-back, and the result is marked as an estimate.
|
||||
private var nearestSavingsBaseline: FuelStation? {
|
||||
guard let location else { return nil }
|
||||
return FuelSavingsEstimator.bestValueBaselineStation(
|
||||
return FuelSavingsEstimator.baselineStation(
|
||||
stations,
|
||||
fuel: selectedFuel,
|
||||
journeyMiles: { [self] station in savingsJourneyMiles(for: station, location: location) }
|
||||
@@ -802,10 +802,6 @@ struct ContentView: View {
|
||||
fuelSavings: savingsLookup(baseline: scaffold.baseline,
|
||||
journeys: scaffold.journeys)(station),
|
||||
fuelSavingsAmount: sessionFuelSavingsAmount,
|
||||
savingsPriceConfidence: FuelPriceFreshness.ComparisonConfidence.assess(
|
||||
station: station, fuel: selectedFuel, baseline: scaffold.baseline),
|
||||
savingsPriceWarning: FuelPriceFreshness.comparisonWarning(
|
||||
station: station, fuel: selectedFuel, baseline: scaffold.baseline),
|
||||
savingsBaselineStationName: scaffold.baseline?.name,
|
||||
journeyDiagnostics: journeyDiagnostics(for: station, baseline: scaffold.baseline),
|
||||
isFavourite: favouriteIDs.contains(station.id),
|
||||
@@ -1532,12 +1528,6 @@ struct ContentView: View {
|
||||
fuelSavingsAmount: $sessionFuelSavingsAmount,
|
||||
savingsForStation: savingsLookup(baseline: baselineStation, journeys: scaffold.journeys),
|
||||
journeyDiagnosticsForStation: { station in journeyDiagnostics(for: station, baseline: baselineStation) },
|
||||
savingsPriceConfidenceForStation: { station in
|
||||
FuelPriceFreshness.ComparisonConfidence.assess(station: station, fuel: selectedFuel, baseline: baselineStation)
|
||||
},
|
||||
savingsPriceWarningForStation: { station in
|
||||
FuelPriceFreshness.comparisonWarning(station: station, fuel: selectedFuel, baseline: baselineStation)
|
||||
},
|
||||
onToggleFavourite: toggleFavourite,
|
||||
onRefresh: { await refresh(force: true) }
|
||||
)
|
||||
@@ -1559,12 +1549,6 @@ struct ContentView: View {
|
||||
fuelSavingsAmount: $sessionFuelSavingsAmount,
|
||||
savingsForStation: savingsLookup(baseline: baselineStation, journeys: scaffold.journeys),
|
||||
journeyDiagnosticsForStation: { station in journeyDiagnostics(for: station, baseline: baselineStation) },
|
||||
savingsPriceConfidenceForStation: { station in
|
||||
FuelPriceFreshness.ComparisonConfidence.assess(station: station, fuel: selectedFuel, baseline: baselineStation)
|
||||
},
|
||||
savingsPriceWarningForStation: { station in
|
||||
FuelPriceFreshness.comparisonWarning(station: station, fuel: selectedFuel, baseline: baselineStation)
|
||||
},
|
||||
onToggleFavourite: toggleFavourite,
|
||||
onReorder: reorderFavourites,
|
||||
onHistoryUnavailable: { if dataStatus == .live { dataStatus = .connectionProblem } },
|
||||
@@ -1802,8 +1786,6 @@ struct StationRow: View {
|
||||
/// compact banner does not print it today, but a row that carried a hard
|
||||
/// zero would print "for £0" the moment it did — pass the real figure.
|
||||
var fuelSavingsAmount: FuelSavingsFillAmount = FuelSavingsSettings.defaultPreferredAmount
|
||||
var savingsPriceConfidence: FuelPriceFreshness.ComparisonConfidence = .ineligible
|
||||
var savingsPriceWarning: String? = nil
|
||||
var onToggleFavourite: () -> Void = {}
|
||||
var onShowDetails: (FuelStation) -> Void = { _ in }
|
||||
|
||||
@@ -1964,8 +1946,6 @@ struct StationRow: View {
|
||||
FuelSavingsSummaryView(
|
||||
availability: fuelSavings,
|
||||
amount: fuelSavingsAmount,
|
||||
priceConfidence: savingsPriceConfidence,
|
||||
priceWarning: savingsPriceWarning,
|
||||
compact: true,
|
||||
distanceUnit: distanceUnit
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user