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
|
||||
)
|
||||
|
||||
@@ -21,12 +21,10 @@ struct FavouritesView: View {
|
||||
/// still never touches the Settings default.
|
||||
let fuelSavingsSettings: FuelSavingsSettings
|
||||
@Binding var fuelSavingsAmount: FuelSavingsFillAmount
|
||||
/// Estimated saving for a favourite, against the closest eligible station by
|
||||
/// Estimated saving for a favourite, against the closest station by
|
||||
/// journey distance — the same baseline and definition the Stations list uses.
|
||||
var savingsForStation: (FuelStation) -> FuelSavingsAvailability? = { _ in nil }
|
||||
var journeyDiagnosticsForStation: (FuelStation) -> FuelSavingsJourneyDiagnostics? = { _ in nil }
|
||||
var savingsPriceConfidenceForStation: (FuelStation) -> FuelPriceFreshness.ComparisonConfidence
|
||||
var savingsPriceWarningForStation: (FuelStation) -> String? = { _ in nil }
|
||||
var onToggleFavourite: (FuelStation, FuelType) -> Void = { _, _ in }
|
||||
/// Persists a reordered favourites array (after drag-and-drop).
|
||||
var onReorder: ([FavouriteEntry]) -> Void = { _ in }
|
||||
@@ -86,8 +84,6 @@ struct FavouritesView: View {
|
||||
fuelSavingsAmount: Binding<FuelSavingsFillAmount>,
|
||||
savingsForStation: @escaping (FuelStation) -> FuelSavingsAvailability? = { _ in nil },
|
||||
journeyDiagnosticsForStation: @escaping (FuelStation) -> FuelSavingsJourneyDiagnostics? = { _ in nil },
|
||||
savingsPriceConfidenceForStation: @escaping (FuelStation) -> FuelPriceFreshness.ComparisonConfidence = { _ in .ineligible },
|
||||
savingsPriceWarningForStation: @escaping (FuelStation) -> String? = { _ in nil },
|
||||
onToggleFavourite: @escaping (FuelStation, FuelType) -> Void = { _, _ in },
|
||||
onReorder: @escaping ([FavouriteEntry]) -> Void = { _ in },
|
||||
onHistoryUnavailable: (() -> Void)? = nil,
|
||||
@@ -102,8 +98,6 @@ struct FavouritesView: View {
|
||||
_fuelSavingsAmount = fuelSavingsAmount
|
||||
self.savingsForStation = savingsForStation
|
||||
self.journeyDiagnosticsForStation = journeyDiagnosticsForStation
|
||||
self.savingsPriceConfidenceForStation = savingsPriceConfidenceForStation
|
||||
self.savingsPriceWarningForStation = savingsPriceWarningForStation
|
||||
self.onToggleFavourite = onToggleFavourite
|
||||
self.onReorder = onReorder
|
||||
self.onHistoryUnavailable = onHistoryUnavailable
|
||||
@@ -152,7 +146,7 @@ struct FavouritesView: View {
|
||||
Section {
|
||||
FuelSavingsAdjustmentView(amount: $fuelSavingsAmount)
|
||||
} footer: {
|
||||
Text(String(localized: "Savings below are estimated against the closest eligible station by journey distance — the same baseline as the Stations list.", comment: "Favourites fuel-savings explanation"))
|
||||
Text(String(localized: "Savings below are estimated against the closest station by journey distance — the same baseline as the Stations list.", comment: "Favourites fuel-savings explanation"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,8 +165,6 @@ struct FavouritesView: View {
|
||||
tapAction: stationTapAction,
|
||||
fuelSavings: savingsForStation(station),
|
||||
fuelSavingsAmount: fuelSavingsAmount,
|
||||
savingsPriceConfidence: savingsPriceConfidenceForStation(station),
|
||||
savingsPriceWarning: savingsPriceWarningForStation(station),
|
||||
onToggleFavourite: { onToggleFavourite(station, activeFuel) },
|
||||
onShowDetails: { detailStation = $0 }
|
||||
)
|
||||
@@ -224,8 +216,6 @@ struct FavouritesView: View {
|
||||
selectedFuel: activeFuel,
|
||||
fuelSavings: savingsForStation(station),
|
||||
fuelSavingsAmount: fuelSavingsAmount,
|
||||
savingsPriceConfidence: savingsPriceConfidenceForStation(station),
|
||||
savingsPriceWarning: savingsPriceWarningForStation(station),
|
||||
journeyDiagnostics: journeyDiagnosticsForStation(station),
|
||||
// Every station listed here IS a favourite for the tab's
|
||||
// fuel, so the star starts filled; tapping it unstars.
|
||||
|
||||
@@ -80,9 +80,6 @@ struct FuelSavingsAdjustmentView: View {
|
||||
struct FuelSavingsSummaryView: View {
|
||||
let availability: FuelSavingsAvailability?
|
||||
let amount: FuelSavingsFillAmount
|
||||
/// Candidate/baseline price confidence for every Best Value result.
|
||||
var priceConfidence: FuelPriceFreshness.ComparisonConfidence = .ineligible
|
||||
var priceWarning: String? = nil
|
||||
var baselineStationName: String? = nil
|
||||
var compact: Bool = false
|
||||
/// Sizes the "extra return travel" caption in the user's own unit (the
|
||||
@@ -120,12 +117,6 @@ struct FuelSavingsSummaryView: View {
|
||||
.lineLimit(1)
|
||||
.minimumScaleFactor(0.85)
|
||||
.accessibilityLabel("Comparison: \(comparisonLabel(for: result))")
|
||||
if let warning = priceWarning ?? priceConfidence.warningText {
|
||||
Text(warning)
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.orange)
|
||||
.accessibilityLabel(warning)
|
||||
}
|
||||
if let extraTravel = FuelSavingsFormat.extraTravelLabel(
|
||||
extraDistanceMiles: result.extraDistanceMiles,
|
||||
unit: distanceUnit,
|
||||
@@ -166,16 +157,10 @@ struct FuelSavingsSummaryView: View {
|
||||
LabeledContent("Fuel you'll receive", value: String(format: "%.2f litres", result.fillLitres))
|
||||
.monospacedDigit()
|
||||
if amount.unit == .pounds {
|
||||
Text("You pay the selected budget here. The saving compares the same litres at your closest eligible station; litres differ between stations, and this is not a refund.")
|
||||
Text("You pay the selected budget here. The saving compares the same litres at your closest station; litres differ between stations, and this is not a refund.")
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
if let warning = priceWarning ?? priceConfidence.warningText {
|
||||
Text(warning)
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.orange)
|
||||
.accessibilityLabel(warning)
|
||||
}
|
||||
if let extraTravel = FuelSavingsFormat.extraTravelLabel(
|
||||
extraDistanceMiles: result.extraDistanceMiles,
|
||||
unit: distanceUnit,
|
||||
@@ -187,11 +172,11 @@ struct FuelSavingsSummaryView: View {
|
||||
.accessibilityLabel(spokenExtraTravel(for: result, fallback: extraTravel))
|
||||
}
|
||||
if result.status == .baseline {
|
||||
Text("Your closest eligible station by journey distance is the baseline — every other saving is measured against it.")
|
||||
Text("Your closest station by journey distance is the baseline — every other saving is measured against it.")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
} else {
|
||||
Text(baselineStationName.map { "Compared with \($0)." } ?? "Compared with your closest eligible station.")
|
||||
Text(baselineStationName.map { "Compared with \($0)." } ?? "Compared with your closest station.")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
LabeledContent(
|
||||
@@ -266,8 +251,8 @@ struct FuelSavingsSummaryView: View {
|
||||
}
|
||||
|
||||
/// VoiceOver form of the verdict. `spokenHeadline()` spells "Approx." out for
|
||||
/// and leaves the plain words ("Break even", "Closest eligible
|
||||
/// station") alone — one source, so visible and spoken copy cannot drift.
|
||||
/// and leaves the plain words ("Break even", "Closest station") alone —
|
||||
/// one source, so visible and spoken copy cannot drift.
|
||||
private func accessibilityHeadline(for result: FuelSavingsResult) -> String {
|
||||
result.spokenHeadline()
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@ struct HowBestValueSheet: View {
|
||||
List {
|
||||
Section {
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
Text("Best Value compares each station with the closest eligible station by journey distance. It works out what you could save at the pump, then takes off the fuel used for the extra return journey.")
|
||||
Text("Best Value compares each station with the closest station by journey distance. It works out what you could save at the pump, then takes off the fuel used for the extra return journey.")
|
||||
Text("Your fill-up amount and MPG are used to show whether you could save overall.")
|
||||
Text("With a £ budget you spend that amount at each station; the litres differ by station. Savings compare those litres with the same quantity at your closest eligible station, then deduct extra journey fuel. You do not receive cash back.")
|
||||
Text("With a £ budget you spend that amount at each station; the litres differ by station. Savings compare those litres with the same quantity at your closest station, then deduct extra journey fuel. You do not receive cash back.")
|
||||
Text("With Litres, every station is compared for the fixed quantity you selected.")
|
||||
Text("Results are marked “Approx.” until road distances are available.")
|
||||
.foregroundStyle(.secondary)
|
||||
|
||||
@@ -21,8 +21,6 @@ struct StationDetailView: View {
|
||||
var selectedFuel: FuelType = FuelStore.loadSelectedFuel()
|
||||
var fuelSavings: FuelSavingsAvailability? = nil
|
||||
var fuelSavingsAmount: FuelSavingsFillAmount = FuelSavingsSettings.defaultPreferredAmount
|
||||
var savingsPriceConfidence: FuelPriceFreshness.ComparisonConfidence = .ineligible
|
||||
var savingsPriceWarning: String? = nil
|
||||
var savingsBaselineStationName: String? = nil
|
||||
var journeyDiagnostics: FuelSavingsJourneyDiagnostics? = nil
|
||||
/// Whether this station is starred for the fuel currently being viewed, and
|
||||
@@ -62,11 +60,11 @@ struct StationDetailView: View {
|
||||
}
|
||||
|
||||
private var priceFreshness: FuelPriceFreshness.Assessment {
|
||||
FuelPriceFreshness.assessment(for: station, fuel: selectedFuel)
|
||||
FuelPriceFreshness.assessment(for: station)
|
||||
}
|
||||
|
||||
/// The selected grade's current price, when present. Kept separate from
|
||||
/// the freshness label so a stale price remains visible rather than being
|
||||
/// the price-age row so an old price remains visible rather than being
|
||||
/// silently hidden.
|
||||
private var selectedFuelPriceText: String {
|
||||
guard let price = station.prices[selectedFuel] else { return "—" }
|
||||
@@ -215,8 +213,7 @@ struct StationDetailView: View {
|
||||
}
|
||||
LabeledContent("\(selectedFuel.displayName) price", value: selectedFuelPriceText)
|
||||
.monospacedDigit()
|
||||
LabeledContent("Price updated", value: priceFreshness.updateAgeLabel)
|
||||
.monospacedDigit()
|
||||
StationPriceAgeView(assessment: priceFreshness)
|
||||
ForEach(StationNotice.notices(for: station)) { notice in
|
||||
Label(notice.title, systemImage: notice.symbolName)
|
||||
.font(.subheadline.weight(.semibold))
|
||||
@@ -257,8 +254,6 @@ struct StationDetailView: View {
|
||||
FuelSavingsSummaryView(
|
||||
availability: fuelSavings,
|
||||
amount: fuelSavingsAmount,
|
||||
priceConfidence: savingsPriceConfidence,
|
||||
priceWarning: savingsPriceWarning,
|
||||
baselineStationName: savingsBaselineStationName,
|
||||
distanceUnit: distanceUnit,
|
||||
showInfoAction: { showBestValueInfo = true }
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import SwiftUI
|
||||
|
||||
/// The More info sheet's price-age row.
|
||||
///
|
||||
/// Station-level by design: the relay publishes a single `price_updated` per
|
||||
/// station (the newest grade it maps), so the copy says "Price updated" and
|
||||
/// never claims the selected grade itself was updated.
|
||||
///
|
||||
/// Past `FuelPriceFreshness.outdatedAge` a discreet note flags the information
|
||||
/// as possibly out of date. It is informational only — it gates nothing, and
|
||||
/// the station's own price row above it is unaffected.
|
||||
///
|
||||
/// Its own view rather than inlined into `StationDetailView`: that body sits at
|
||||
/// the compiler's type-checking limit, so one extra statement there fails the
|
||||
/// build. One statement here, one there.
|
||||
struct StationPriceAgeView: View {
|
||||
let assessment: FuelPriceFreshness.Assessment
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
LabeledContent("Price updated", value: assessment.updateAgeLabel)
|
||||
.monospacedDigit()
|
||||
if let notice = assessment.outdatedNotice {
|
||||
Text(notice)
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.secondary)
|
||||
.accessibilityLabel(notice)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,6 @@ struct StationsView: View {
|
||||
@Binding var fuelSavingsAmount: FuelSavingsFillAmount
|
||||
var savingsForStation: (FuelStation) -> FuelSavingsAvailability? = { _ in nil }
|
||||
var journeyDiagnosticsForStation: (FuelStation) -> FuelSavingsJourneyDiagnostics? = { _ in nil }
|
||||
var savingsPriceConfidenceForStation: (FuelStation) -> FuelPriceFreshness.ComparisonConfidence
|
||||
var savingsPriceWarningForStation: (FuelStation) -> String?
|
||||
var onToggleFavourite: (FuelStation, FuelType) -> Void = { _, _ in }
|
||||
var onRefresh: () async -> Void = {}
|
||||
|
||||
@@ -123,11 +121,6 @@ struct StationsView: View {
|
||||
// for a switched-off feature.
|
||||
if sortMode == .worthTheDrive && fuelSavingsSettings.isConfigured {
|
||||
FuelSavingsAdjustmentView(amount: $fuelSavingsAmount)
|
||||
if !stations.isEmpty && stations.allSatisfy({ savingsPriceConfidenceForStation($0) == .ineligible }) {
|
||||
Text("Best Value unavailable: no eligible price comparison. Stations and prices remain visible below.")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.orange)
|
||||
}
|
||||
}
|
||||
|
||||
if isLoading && stations.isEmpty {
|
||||
@@ -264,8 +257,6 @@ struct StationsView: View {
|
||||
selectedFuel: selectedFuel,
|
||||
fuelSavings: savingsForStation(station),
|
||||
fuelSavingsAmount: fuelSavingsAmount,
|
||||
savingsPriceConfidence: savingsPriceConfidenceForStation(station),
|
||||
savingsPriceWarning: savingsPriceWarningForStation(station),
|
||||
journeyDiagnostics: journeyDiagnosticsForStation(station),
|
||||
isFavourite: favouriteIDs.contains(station.id),
|
||||
onToggleFavourite: { onToggleFavourite(station, selectedFuel) }
|
||||
@@ -369,8 +360,6 @@ struct StationsView: View {
|
||||
tapAction: stationTapAction,
|
||||
fuelSavings: savingsForStation(station),
|
||||
fuelSavingsAmount: fuelSavingsAmount,
|
||||
savingsPriceConfidence: savingsPriceConfidenceForStation(station),
|
||||
savingsPriceWarning: savingsPriceWarningForStation(station),
|
||||
onToggleFavourite: { onToggleFavourite(station, selectedFuel) },
|
||||
onShowDetails: { detailStation = $0 }
|
||||
)
|
||||
|
||||
@@ -36,10 +36,10 @@
|
||||
"Remove from favourites" = "Remove from favourites";
|
||||
"Price differences are shown in pence per litre (p/litre). Colours match each station's rating on the list." = "Price differences are shown in pence per litre (p/litre). Colours match each station's rating on the list.";
|
||||
"How Best Value works" = "How Best Value works";
|
||||
"Best Value compares each station with the closest eligible station by journey distance. It works out what you could save at the pump, then takes off the fuel used for the extra return journey." = "Best Value compares each station with the closest eligible station by journey distance. It works out what you could save at the pump, then takes off the fuel used for the extra return journey.";
|
||||
"With a £ budget you spend that amount at each station; the litres differ by station. Savings compare those litres with the same quantity at your closest eligible station, then deduct extra journey fuel. You do not receive cash back." = "With a £ budget you spend that amount at each station; the litres differ by station. Savings compare those litres with the same quantity at your closest eligible station, then deduct extra journey fuel. You do not receive cash back.";
|
||||
"Your closest eligible station by journey distance is the baseline — every other saving is measured against it." = "Your closest eligible station by journey distance is the baseline — every other saving is measured against it.";
|
||||
"Savings below are estimated against the closest eligible station by journey distance — the same baseline as the Stations list." = "Savings below are estimated against the closest eligible station by journey distance — the same baseline as the Stations list.";
|
||||
"Best Value compares each station with the closest station by journey distance. It works out what you could save at the pump, then takes off the fuel used for the extra return journey." = "Best Value compares each station with the closest station by journey distance. It works out what you could save at the pump, then takes off the fuel used for the extra return journey.";
|
||||
"With a £ budget you spend that amount at each station; the litres differ by station. Savings compare those litres with the same quantity at your closest station, then deduct extra journey fuel. You do not receive cash back." = "With a £ budget you spend that amount at each station; the litres differ by station. Savings compare those litres with the same quantity at your closest station, then deduct extra journey fuel. You do not receive cash back.";
|
||||
"Your closest station by journey distance is the baseline — every other saving is measured against it." = "Your closest station by journey distance is the baseline — every other saving is measured against it.";
|
||||
"Savings below are estimated against the closest station by journey distance — the same baseline as the Stations list." = "Savings below are estimated against the closest station by journey distance — the same baseline as the Stations list.";
|
||||
"Your fill-up amount and MPG are used to show whether you could save overall." = "Your fill-up amount and MPG are used to show whether you could save overall.";
|
||||
"Results are marked “Approx.” until road distances are available." = "Results are marked “Approx.” until road distances are available.";
|
||||
|
||||
@@ -220,17 +220,14 @@
|
||||
"Long-distance journeys. Maximum reach: a ping when a cheap station is coming up from far out. In town this essentially never fires." = "Long-distance journeys. Maximum reach: a ping when a cheap station is coming up from far out. In town this essentially never fires.";
|
||||
"%@ — %@" = "%@ — %@";
|
||||
|
||||
/* Best Value calculation and price confidence */
|
||||
/* Best Value calculation and station price age */
|
||||
"£ compares the litres your budget buys at each station; Litres compares one fixed quantity." = "£ compares the litres your budget buys at each station; Litres compares one fixed quantity.";
|
||||
"You pay the selected budget here. The saving compares the same litres at your closest eligible station; litres differ between stations, and this is not a refund." = "You pay the selected budget here. The saving compares the same litres at your closest eligible station; litres differ between stations, and this is not a refund.";
|
||||
"Best Value unavailable · price confidence insufficient" = "Best Value unavailable · price confidence insufficient";
|
||||
"You pay the selected budget here. The saving compares the same litres at your closest station; litres differ between stations, and this is not a refund." = "You pay the selected budget here. The saving compares the same litres at your closest station; litres differ between stations, and this is not a refund.";
|
||||
"Best Value unavailable · location needed" = "Best Value unavailable · location needed";
|
||||
"price order · Best Value unavailable" = "price order · Best Value unavailable";
|
||||
"your order" = "your order";
|
||||
"Price updated" = "Price updated";
|
||||
"Price age unavailable or too old — not a Best Value recommendation." = "Price age unavailable or too old — not a Best Value recommendation.";
|
||||
"%@ ago" = "%@ ago";
|
||||
"Not provided" = "Not provided";
|
||||
"May be outdated" = "May be outdated";
|
||||
"Fuel you'll receive" = "Fuel you'll receive";
|
||||
"Best Value unavailable: no eligible price comparison. Stations and prices remain visible below." = "Best Value unavailable: no eligible price comparison. Stations and prices remain visible below.";
|
||||
"Compared with your closest eligible station." = "Compared with your closest eligible station.";
|
||||
"Compared with your closest station." = "Compared with your closest station.";
|
||||
|
||||
Reference in New Issue
Block a user