Add Best Value small widget and standardise Closest wording
This commit is contained in:
@@ -95,7 +95,8 @@ struct FuelPriceTimelineProvider<Configuration: WidgetConfigurationIntent & Widg
|
||||
data: FuelPriceWidgetEntryData(
|
||||
date: Date(), stations: Array(sample.prefix(8)),
|
||||
fuel: .e10, sort: .cheapest, isFavourites: false,
|
||||
location: nil, locationSource: "none", unit: unit
|
||||
location: nil, locationSource: "none", unit: unit,
|
||||
bestValueResult: nil
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -146,7 +147,8 @@ struct FuelPriceTimelineProvider<Configuration: WidgetConfigurationIntent & Widg
|
||||
// Per-widget config: fuel + sort + distance come from THIS widget instance.
|
||||
let fuel = FuelType(rawValue: configuration.fuel.rawValue) ?? .e10
|
||||
let isFavourites = configuration.sort == .favourites
|
||||
let sort: SortMode = configuration.sort == .closest ? .closest : .cheapest
|
||||
let sort: SortMode = configuration.sort == .closest ? .closest :
|
||||
(configuration.sort == .worthTheDrive ? .worthTheDrive : .cheapest)
|
||||
let radiusKM = Double(configuration.distance.miles) * FuelSavingsCalculator.kilometresPerMile
|
||||
|
||||
// 1) Try a fresh location fix (bounded to a few seconds). The fix's own
|
||||
@@ -200,6 +202,7 @@ struct FuelPriceTimelineProvider<Configuration: WidgetConfigurationIntent & Widg
|
||||
|
||||
// 3) Load + order stations per widget mode.
|
||||
let ordered: [FuelStation]
|
||||
var bestValueResult: FuelSavingsResult?
|
||||
if isFavourites {
|
||||
let favourites = FuelStore.loadFavourites()
|
||||
.filter { $0.station.prices[$0.fuel] != nil }
|
||||
@@ -265,7 +268,7 @@ struct FuelPriceTimelineProvider<Configuration: WidgetConfigurationIntent & Widg
|
||||
let filtered = stations.filter { $0.prices[fuel] != nil }
|
||||
switch sort {
|
||||
case .closest:
|
||||
// Nearest first; price only breaks ties.
|
||||
// Closest first; price only breaks ties.
|
||||
ordered = filtered.sorted { lhs, rhs in
|
||||
if let origin {
|
||||
let lDist = FuelStore.displayDistanceKM(station: lhs, userLat: origin.lat, userLng: origin.lng)
|
||||
@@ -274,9 +277,59 @@ struct FuelPriceTimelineProvider<Configuration: WidgetConfigurationIntent & Widg
|
||||
}
|
||||
return lhs.prices[fuel]! < rhs.prices[fuel]!
|
||||
}
|
||||
case .cheapest, .worthTheDrive:
|
||||
// Cheapest first; distance only breaks ties. Worth-the-Drive is app-only;
|
||||
// widgets fall back to cheapest ordering if a stored config ever carries it.
|
||||
case .worthTheDrive:
|
||||
guard let origin else {
|
||||
ordered = filtered.sorted { $0.prices[fuel]! < $1.prices[fuel]! }
|
||||
break
|
||||
}
|
||||
let journey: (FuelStation) -> FuelSavingsJourney? = { station in
|
||||
if let meters = FuelStore.roadJourneyMeters(for: station, userLat: origin.lat, userLng: origin.lng) {
|
||||
let confidence: JourneyConfidence = FuelStore.hasMeasuredReturnRoadDistance(
|
||||
for: station, userLat: origin.lat, userLng: origin.lng
|
||||
) ? .confirmed : .estimated
|
||||
return FuelSavingsJourney(
|
||||
miles: meters / FuelSavingsCalculator.metresPerMile,
|
||||
basis: .roadRoute,
|
||||
confidence: confidence
|
||||
)
|
||||
}
|
||||
return FuelSavingsJourney(
|
||||
miles: FuelStore.displayDistanceKM(station: station, userLat: origin.lat, userLng: origin.lng) /
|
||||
FuelSavingsCalculator.kilometresPerMile * 2,
|
||||
basis: .straightLine,
|
||||
confidence: .estimated
|
||||
)
|
||||
}
|
||||
let settings = FuelStore.loadFuelSavingsSettings()
|
||||
guard settings.isConfigured else {
|
||||
ordered = filtered.sorted { $0.prices[fuel]! < $1.prices[fuel]! }
|
||||
break
|
||||
}
|
||||
let amount = settings.preferredAmount
|
||||
let baseline = FuelSavingsEstimator.baselineStation(filtered, fuel: fuel, journeyMiles: journey)
|
||||
let ranked = FuelSavingsEstimator.ranked(
|
||||
filtered,
|
||||
fuel: fuel,
|
||||
baseline: baseline,
|
||||
settings: settings,
|
||||
amount: amount,
|
||||
journeyMiles: journey
|
||||
)
|
||||
ordered = ranked
|
||||
if let first = ranked.first, let baseline {
|
||||
let baselineJourney = journey(baseline)
|
||||
let result = FuelSavingsEstimator.availability(
|
||||
station: first,
|
||||
fuel: fuel,
|
||||
baseline: baseline,
|
||||
settings: settings,
|
||||
amount: amount,
|
||||
journey: journey(first),
|
||||
baselineJourney: baselineJourney
|
||||
)
|
||||
bestValueResult = result?.result
|
||||
}
|
||||
case .cheapest:
|
||||
ordered = filtered.sorted { lhs, rhs in
|
||||
let lPrice = lhs.prices[fuel]!
|
||||
let rPrice = rhs.prices[fuel]!
|
||||
@@ -295,7 +348,7 @@ struct FuelPriceTimelineProvider<Configuration: WidgetConfigurationIntent & Widg
|
||||
date: Date(), stations: Array(ordered.prefix(8)),
|
||||
fuel: fuel, sort: sort, isFavourites: isFavourites,
|
||||
location: origin, locationSource: source,
|
||||
unit: unit
|
||||
unit: unit, bestValueResult: bestValueResult
|
||||
)
|
||||
), originSource)
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ enum WidgetFuel: String, AppEnum, CaseIterable, Codable {
|
||||
enum WidgetSort: String, AppEnum, CaseIterable, Codable {
|
||||
case cheapest
|
||||
case closest
|
||||
case worthTheDrive
|
||||
case favourites
|
||||
|
||||
static var typeDisplayRepresentation: TypeDisplayRepresentation = "Sort by"
|
||||
@@ -37,6 +38,7 @@ enum WidgetSort: String, AppEnum, CaseIterable, Codable {
|
||||
static var caseDisplayRepresentations: [WidgetSort: DisplayRepresentation] = [
|
||||
.cheapest: "Cheapest",
|
||||
.closest: "Closest",
|
||||
.worthTheDrive: "Best Value",
|
||||
.favourites: "Favourites",
|
||||
]
|
||||
}
|
||||
@@ -112,9 +114,17 @@ struct FuelBoardWidgetConfigurationIntent: WidgetConfigurationIntent, WidgetConf
|
||||
\.$sort
|
||||
}
|
||||
} otherwise: {
|
||||
Summary("Show \(\.$fuel) by \(\.$sort)") {
|
||||
\.$fuel
|
||||
\.$sort
|
||||
When(\.$sort, .equalTo, WidgetSort.worthTheDrive) {
|
||||
Summary("Show \(\.$fuel) by \(\.$sort) within \(\.$distance)") {
|
||||
\.$fuel
|
||||
\.$sort
|
||||
\.$distance
|
||||
}
|
||||
} otherwise: {
|
||||
Summary("Show \(\.$fuel) by \(\.$sort)") {
|
||||
\.$fuel
|
||||
\.$sort
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user