Best Value: baseline on the closest eligible price and gate on freshness
- Add FuelPriceFreshness: selected-fuel-aware eligibility plus a shared comparison confidence, so a saving is presented as verified only when both the candidate and the baseline pass the gate for the fuel on screen. - Rank against the closest station with an eligible selected-fuel price instead of the physically closest station, so a single stale neighbour can no longer invalidate every comparison in the list. Ordinary Closest sorting still includes every priced station. - Keep ineligible prices visible, fall back to pump-price order, and label Best Value unavailable when no comparison qualifies. - Widget: same baseline and confidence path as the app. - Tests: stale-closest baseline, alert baseline, eligibility policy, boundary and missing-timestamp regressions.
This commit is contained in:
@@ -48,6 +48,42 @@ final class FuelSavingsCalculationAuditTests: XCTestCase {
|
||||
|
||||
// MARK: - 1. Unit conversion
|
||||
|
||||
func testBudgetExamplesAcrossAllFuelTypes() throws {
|
||||
for fuel in FuelType.allCases {
|
||||
let base = FuelStation(id: "base", name: "Base", brand: "", address: "", postcode: "", lat: 53, lng: -1, prices: [fuel: 199.9], priceUpdated: nil)
|
||||
let other = FuelStation(id: "other", name: "Other", brand: "", address: "", postcode: "", lat: 53, lng: -1, prices: [fuel: 129.9], priceUpdated: nil)
|
||||
let settings = FuelSavingsSettings(enabled: true, mpg: 30, preferredAmount: .init(value: 40, unit: .pounds))
|
||||
for budget in [20.0, 40, 60, 73, 100] {
|
||||
let result = FuelSavingsEstimator.availability(station: other, fuel: fuel, baseline: base,
|
||||
settings: settings, amount: .init(value: budget, unit: .pounds),
|
||||
journey: .init(miles: 8.3, basis: .roadRoute),
|
||||
baselineJourney: .init(miles: 0.9, basis: .roadRoute))?.result
|
||||
let volume = budget / 1.299
|
||||
XCTAssertEqual(result?.fillLitres ?? 0, volume, accuracy: 1e-9)
|
||||
XCTAssertEqual(result?.grossSavingGBP ?? 0, volume * 0.7, accuracy: 1e-9)
|
||||
XCTAssertEqual(result?.netSavingGBP ?? 0, volume * 0.7 - 7.4 / 30 * 4.54609 * 1.299, accuracy: 1e-9)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testCandidateBudgetAndEqualQuantitySavingsForEveryFuel() throws {
|
||||
for fuel in FuelType.allCases {
|
||||
let candidate = FuelStation(id: "candidate-\(fuel.rawValue)", name: "Candidate", brand: "", address: "", postcode: "", lat: 53.7, lng: -1.8, prices: [fuel: 129.9], priceUpdated: nil)
|
||||
let baseline = FuelStation(id: "baseline-\(fuel.rawValue)", name: "Nearest", brand: "", address: "", postcode: "", lat: 53.7, lng: -1.8, prices: [fuel: 199.9], priceUpdated: nil)
|
||||
let configured = FuelSavingsSettings(enabled: true, mpg: 30, preferredAmount: .init(value: 60, unit: .pounds))
|
||||
let money = FuelSavingsEstimator.availability(station: candidate, fuel: fuel, baseline: baseline, settings: configured,
|
||||
amount: .init(value: 60, unit: .pounds), journey: .init(miles: 8.3, basis: .roadRoute),
|
||||
baselineJourney: .init(miles: 0.9, basis: .roadRoute))?.result
|
||||
let litres = FuelSavingsEstimator.availability(station: candidate, fuel: fuel, baseline: baseline, settings: configured,
|
||||
amount: .init(value: 60 / 1.299, unit: .litres), journey: .init(miles: 8.3, basis: .roadRoute),
|
||||
baselineJourney: .init(miles: 0.9, basis: .roadRoute))?.result
|
||||
XCTAssertEqual(money?.fillLitres ?? 0, 60 / 1.299, accuracy: 1e-8, fuel.rawValue)
|
||||
XCTAssertEqual(money?.grossSavingGBP ?? 0, litres?.grossSavingGBP ?? -1, accuracy: 1e-8, fuel.rawValue)
|
||||
XCTAssertEqual(money?.netSavingGBP ?? 0, litres?.netSavingGBP ?? -1, accuracy: 1e-8, fuel.rawValue)
|
||||
XCTAssertEqual(money?.netSavingGBP ?? 0, (money?.grossSavingGBP ?? 0) - (money?.extraDrivingCostGBP ?? 0), accuracy: 1e-8, fuel.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
func testImperialGallonIsUsedNotTheUSGallon() {
|
||||
XCTAssertEqual(FuelSavingsCalculator.imperialGallonLitres, 4.54609)
|
||||
XCTAssertNotEqual(FuelSavingsCalculator.imperialGallonLitres, 3.785411784,
|
||||
@@ -497,6 +533,6 @@ final class FuelSavingsCalculationAuditTests: XCTestCase {
|
||||
)?.result
|
||||
XCTAssertEqual(result?.status, .baseline)
|
||||
XCTAssertEqual(result?.netSavingGBP, 0)
|
||||
XCTAssertEqual(result?.headline(), "Closest station")
|
||||
XCTAssertEqual(result?.headline(), "Closest eligible station")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user