open-wether / Sources /App /Helper /Reader /GenericReaderDerived.swift
soiz1's picture
Migrated from GitHub
6ee917b verified
import Foundation
/// The required functions to implement a reader that provides derived variables
protocol GenericReaderDerived: GenericReaderProtocol {
associatedtype Derived: RawRepresentableString
associatedtype ReaderNext: GenericReaderProtocol
var reader: ReaderNext { get }
func get(derived: Derived, time: TimerangeDtAndSettings) throws -> DataAndUnit
func prefetchData(derived: Derived, time: TimerangeDtAndSettings) throws
func get(raw: ReaderNext.MixingVar, time: TimerangeDtAndSettings) throws -> DataAndUnit
func prefetchData(raw: ReaderNext.MixingVar, time: TimerangeDtAndSettings) throws
}
/// Parameters for tilted radiation calculation
struct GenericReaderOptions {
/// Tilt of a solar panel for GTI calculation. 0° horizontal, 90° vertical.
private var tilt: Float
/// Azimuth of a solar panel for GTI calculation. 0° south, -90° east, 90° west
private var azimuth: Float
public init(tilt: Float? = nil, azimuth: Float? = nil) {
self.tilt = tilt ?? 0
self.azimuth = azimuth ?? 0
}
/// Tilt of a solar panel for GTI calculation. 0° horizontal, 90° vertical. Throws out of bounds error.
func getTilt() throws -> Float {
guard tilt.isNaN || (tilt >= 0 && tilt <= 90) else {
throw ForecastapiError.generic(message: "Parameter `&tilt=` must be within 0° and 90°")
}
return tilt
}
/// Azimuth of a solar panel for GTI calculation. 0° south, -90° east, 90° west. Throws out of bounds error.
func getAzimuth() throws -> Float {
guard azimuth.isNaN || (azimuth >= -180 && azimuth <= 180) else {
throw ForecastapiError.generic(message: "Parameter `&azimuth=` must be within -180° and 180°")
}
return azimuth
}
}
extension GenericReaderDerived {
var modelLat: Float {
reader.modelLat
}
/*var domain: ReaderNext.Domain {
return reader.domain
}*/
var modelLon: Float {
reader.modelLon
}
var modelElevation: ElevationOrSea {
reader.modelElevation
}
var modelDtSeconds: Int {
reader.modelDtSeconds
}
var targetElevation: Float {
reader.targetElevation
}
func prefetchData(variable: VariableOrDerived<ReaderNext.MixingVar, Derived>, time: TimerangeDtAndSettings) throws {
switch variable {
case .raw(let raw):
return try prefetchData(raw: raw, time: time)
case .derived(let derived):
return try prefetchData(derived: derived, time: time)
}
}
func get(variable: VariableOrDerived<ReaderNext.MixingVar, Derived>, time: TimerangeDtAndSettings) throws -> DataAndUnit {
switch variable {
case .raw(let raw):
return try get(raw: raw, time: time)
case .derived(let derived):
return try get(derived: derived, time: time)
}
}
func getStatic(type: ReaderStaticVariable) throws -> Float? {
return try reader.getStatic(type: type)
}
func prefetchData(variables: [VariableOrDerived<ReaderNext.MixingVar, Derived>], time: TimerangeDtAndSettings) throws {
try variables.forEach { variable in
try prefetchData(variable: variable, time: time)
}
}
}
/// A reader that does not modify reader. E.g. pass all reads directly to reader
protocol GenericReaderDerivedSimple: GenericReaderDerived {
}
extension GenericReaderDerivedSimple {
func get(raw: ReaderNext.MixingVar, time: TimerangeDtAndSettings) throws -> DataAndUnit {
try reader.get(variable: raw, time: time)
}
func prefetchData(raw: ReaderNext.MixingVar, time: TimerangeDtAndSettings) throws {
try reader.prefetchData(variable: raw, time: time)
}
}