File size: 2,974 Bytes
6ee917b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import Foundation
import enum OpenMeteoSdk.openmeteo_sdk_Unit

typealias SiUnit = openmeteo_sdk_Unit

enum TemperatureUnit: String, Codable {
    case celsius
    case fahrenheit
}

enum WindspeedUnit: String, Codable {
    case kmh
    case mph
    case kn
    case ms
}

enum PrecipitationUnit: String, Codable {
    case mm
    case inch
}

enum LengthUnit: String, Codable {
    case metric
    case imperial
}

struct ApiUnits: ApiUnitsSelectable {
    let temperature_unit: TemperatureUnit?
    let windspeed_unit: WindspeedUnit?
    let wind_speed_unit: WindspeedUnit?
    let precipitation_unit: PrecipitationUnit?
    let length_unit: LengthUnit?
}

protocol ApiUnitsSelectable {
    var temperature_unit: TemperatureUnit? { get }
    var windspeed_unit: WindspeedUnit? { get }
    var wind_speed_unit: WindspeedUnit? { get }
    var precipitation_unit: PrecipitationUnit? { get }
    var length_unit: LengthUnit? { get }
}

struct DataAndUnit {
    let data: [Float]
    let unit: SiUnit
    
    public init(_ data: [Float], _ unit: SiUnit) {
        self.data = data
        self.unit = unit
    }
    
    /// Convert a given array to target units
    /// Note: Rounding is now done in the writers
    func convertAndRound<Query: ApiUnitsSelectable>(params: Query) -> DataAndUnit {
        var data = self.data
        var unit = self.unit
        
        let windspeedUnit = params.windspeed_unit ?? params.wind_speed_unit ?? .kmh
        let temperatureUnit = params.temperature_unit
        let precipitationUnit = params.precipitation_unit ?? (params.length_unit == .imperial ? .inch : nil)
        if unit == .celsius && temperatureUnit == .fahrenheit {
            
            for i in data.indices {
                data[i] = (data[i] * 9/5) + 32
            }
            unit = .fahrenheit
        }
        if unit == .metrePerSecond && windspeedUnit == .kmh {
            for i in data.indices {
                data[i] *= 3.6
            }
            unit = .kilometresPerHour
        }
        if unit == .metrePerSecond && windspeedUnit == .mph {
            for i in data.indices {
                data[i] *= 2.237
            }
            unit = .milesPerHour
        }
        if unit == .metrePerSecond && windspeedUnit == .kn {
            for i in data.indices {
                data[i] *= 1.94384
            }
            unit = .knots
        }
        if unit == .millimetre && precipitationUnit == .inch {
            for i in data.indices {
                data[i] /= 25.4
            }
            unit = .inch
        }
        if unit == .centimetre && precipitationUnit == .inch {
            for i in data.indices {
                data[i] /= 2.54
            }
            unit = .inch
        }
        if unit == .metre && precipitationUnit == .inch {
            for i in data.indices {
                data[i] *= 3.280839895
            }
            unit = .feet
        }
        return DataAndUnit(data, unit)
    }
}