Skip to content
This repository has been archived by the owner on Jul 19, 2023. It is now read-only.

Commit

Permalink
Refactored attribute access
Browse files Browse the repository at this point in the history
  • Loading branch information
devmaximilian committed Feb 11, 2021
1 parent f3e9c7d commit c9d1b96
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 64 deletions.
17 changes: 12 additions & 5 deletions Sources/Weather/Models/Forecast.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,27 @@
import struct Foundation.Date


/// A `Forecast` is a collection of `Value`s for a set of `Parameter`s
/// A `Forecast` is a collection of `Parameter`s
public struct Forecast: Decodable {
/// A timestamp for when the `Forecast` is valid
internal let validTime: Date
public let validTime: Date

/// An array of `Value` instances
internal let parameters: [Parameter]

/// Get `Value` for a `Parameter`
/// Get a `Parameter` by name.
///
/// - Parameter parameter: The `Parameter` to get `Value` for
internal func get(_ name: Parameter.Name) -> Parameter? {
public func get(_ name: Parameter.Name) -> Parameter {
return self.parameters.first { (value) -> Bool in
value.name == name
}
}.unsafelyUnwrapped
}

/// Get `Value` for a `Parameter`
///
/// - Parameter parameter: The `Parameter` to get `Value` for
public func get<T>(_ name: Parameter.Name, _ keyPath: KeyPath<Parameter, T>) -> T {
return self.get(name)[keyPath: keyPath]
}
}
6 changes: 6 additions & 0 deletions Sources/Weather/Models/Parameter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,9 @@ public struct Parameter: Decodable {
/// An array of raw parameter values
public let values: [Double]
}

extension Parameter {
public var value: Double {
return values.first ?? 0
}
}
70 changes: 11 additions & 59 deletions Sources/Weather/Models/Weather.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,76 +42,28 @@ public struct Weather: Decodable {

/// An extension to house convenience attributes
extension Weather {
/// - Returns: Whether or not the forecast is valid for the current date
/// - Returns: Whether or not any relevant forecasts are available
public var isRelevant: Bool {
let now = Date()
return self.timeSeries.contains { forecast -> Bool in
return timeSeries.contains { forecast -> Bool in
forecast.validTime > now
}
}

/// - Returns: The current `Forecast`
public func get(by date: Date = .init()) -> Forecast? {
return self.timeSeries.sorted(by: { $0.validTime < $1.validTime })
.first { forecast -> Bool in
forecast.validTime >= date
}
}
}

// MARK: Convenience

extension Array {
func first<Value>(where keyPath: KeyPath<Element, Value>, _ value: Value) -> Element? where Value: Equatable {
self.first { element in
element[keyPath: keyPath] == value
}
}
}

extension Parameter {
fileprivate var value: Double {
return values.first ?? 0
}
}

extension Forecast {
fileprivate func parameter<T>(byName name: Parameter.Name, transform: (Parameter) -> T) -> T {
return transform(parameters.first(where: \.name, name).unsafelyUnwrapped)
}
}

extension Weather {
fileprivate var forecast: Forecast {
return self.get() ?? Forecast(validTime: .distantPast, parameters: [])
}

fileprivate var forecasts: [Forecast] {
return self.timeSeries.sorted(by: { $0.validTime < $1.validTime })
}

public func get<T>(_ keyPath: KeyPath<Parameter, T>, for name: Parameter.Name) -> T {
return forecast.parameter(byName: name) {
$0[keyPath: keyPath]
}
public var forecast: Forecast? {
return get()
}

public func get(_ name: Parameter.Name) -> Parameter {
return forecast.parameter(byName: name) { $0 }
public var unsafeForecast: Forecast {
return forecast.unsafelyUnwrapped
}

public func getAll<T>(_ keyPath: KeyPath<Parameter, T>, for name: Parameter.Name) -> [T] {
return forecasts.map {
$0.parameter(byName: name) {
$0[keyPath: keyPath]
/// - Returns: The most relevant `Forecast`
public func get(by date: Date = .init()) -> Forecast? {
return timeSeries.sorted(by: { $0.validTime < $1.validTime })
.first { forecast -> Bool in
forecast.validTime >= date
}
}
}

public func getAll(_ name: Parameter.Name) -> [(validTime: Date, parameter: Parameter)] {
return forecasts.map {
($0.validTime, $0.parameter(byName: name) { $0 })
}
}
}

Expand Down

0 comments on commit c9d1b96

Please sign in to comment.