Commit f77af241 by Demid Merzlyakov

Wdt -> App model conversion in model objects.

parent 7897d466
......@@ -108,6 +108,27 @@ public enum WeekDay: String, Codable {
case friday = "Friday"
case saturday = "Saturday"
case sunday = "Sunday"
public init?(grigorianWeekDayNumber: Int) {
switch grigorianWeekDayNumber {
case 1:
self = WeekDay.sunday
case 2:
self = WeekDay.monday
case 3:
self = WeekDay.tuesday
case 4:
self = WeekDay.wednesday
case 5:
self = WeekDay.thursday
case 6:
self = WeekDay.friday
case 7:
self = WeekDay.saturday
default:
return nil
}
}
}
......@@ -220,3 +241,15 @@ public typealias WindSpeed = Measurement<UnitSpeed>
public typealias Percent = UInt
public typealias Visibility = Measurement<UnitLength>
public typealias Pressure = Measurement<UnitPressure>
extension Measurement {
public init?(valueString: String?, unit: UnitType) {
guard let valueString = valueString else {
return nil
}
guard let value = Double(valueString) else {
return nil
}
self.init(value: value, unit: unit)
}
}
......@@ -26,11 +26,11 @@ public struct CurrentWeather {
public var visibility: Visibility?
public var pressure: Pressure?
public var sunrise: Time?
public var sunset: Time?
public var sunrise: Date?
public var sunset: Date?
public var sunState: CelestialState? = .normal
public var moonrise: Time?
public var moonset: Time?
public var moonrise: Date?
public var moonset: Date?
public var moonState: CelestialState? = .normal
public var moonPhase: MoonPhase? = .unknown
}
......
......@@ -17,4 +17,12 @@ struct WdtDailySummariesArray: Codable {
/// This is actually a key that will be used for daily_summaries individual elements.
case items = "daily_summary"
}
func toAppModel(timeZone: TimeZone) throws -> [DailyWeather] {
var result = [DailyWeather]()
for item in items {
result.append(try item.toAppModel(timeZone: timeZone))
}
return result
}
}
......@@ -16,4 +16,12 @@ struct WdtHourlySummariesArray: Codable {
/// This is actually a key that will be used for hourly_summaries individual elements.
case items = "hourly_summary"
}
func toAppModel(timeZone: TimeZone) throws -> [HourlyWeather] {
var result = [HourlyWeather]()
for item in items {
result.append(try item.toAppModel(timeZone: timeZone))
}
return result
}
}
......@@ -69,4 +69,56 @@ enum WdtWeatherCode: String, Codable {
case mostlyCloudy = "103"
case overcast = "104"
// "ic_static_no_report"
public func toAppModel() -> WeatherType {
switch self {
case .smoke:
return .smoke
case .haze:
return .haze
case .blowingDust, .duststorm, .severeDuststorm:
return .blowingDust
case .lightFog, .patchyFog, .fog:
return .lightFog
case .squall, .driftingSnow, .blowingSnow:
return .snowyDay
//TODO: handle snowyNight
case .freezingFog:
return .freezingFog
case .lightDrizzle, .drizzle, .heavyDrizzle, .lightRain, .lightRainShower:
return .lightDrizzle
case .freezingDrizzle, .lightFreezingRain, .lightRainAndSnow, .rainAndSnow, .lightRainAndSnowShower, .rainAndSnowShower, .freezingRain, .sleet:
return .freezingRain
case .rain, .rainShower:
// TODO: no light rain here?
return .heavyRain
case .heavyRain:
return .heavyRain
case .lightSnow, .lightSnowShower:
return .lightSnow
case .snow, .snowShower:
//TODO: handle snowyNight
return .snowyDay
case .heavySnow:
return .heavySnow
case .lightHail, .hail:
return .lightHail
case .thunderstorm, .heavyThunderstorm:
return .thunderstorm
// isDay ? "ic_static_sunny" : "ic_static_clear_night"
case .clear:
//TODO: handle clear night
return .clearDay
// isDay ? "ic_static_partly_cloudy" : "ic_static_partly_cloudy_night"
case .mostlyClear, .partlyCloudy:
// TODO: handle partly cloudy night
return .partlyCloudyDay
// isDay ? "ic_static_heavy_cloudy" : "ic_static_heavy_cloudy_night"
case .mostlyCloudy, .overcast:
//TODO: handle mostly cloudy night
return .mostlyCloudyDay
default:
return .unknown
}
}
}
......@@ -40,4 +40,57 @@ struct WdtDailySummary: Codable {
case moonriseUtc = "solunar_moonrise_utc"
case moonsetUtc = "solunar_moonset_utc"
}
public func toAppModel(timeZone: TimeZone) throws -> DailyWeather {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/YYYY"
dateFormatter.timeZone = timeZone
guard let date = dateFormatter.date(from: dateLocal) else {
throw WdtWeatherSourceError.dataMergeError
}
var weekDay = WeekDay(rawValue: self.weekDay)
if weekDay == nil {
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = timeZone
weekDay = WeekDay(grigorianWeekDayNumber: calendar.component(.weekday, from: date))
}
guard let weekDayUnwrapped = weekDay else {
throw WdtWeatherSourceError.dataMergeError
}
var result = DailyWeather(date: date, timeZone: timeZone, weekDay: weekDayUnwrapped)
if let weatherCode = self.weatherCode {
result.type = WdtWeatherCode(rawValue: weatherCode)?.toAppModel() ?? .unknown
}
result.minTemp = Temperature(valueString: minTempF, unit: .fahrenheit)
result.maxTemp = Temperature(valueString: maxTempF, unit: .fahrenheit)
result.windSpeed = WindSpeed(valueString: self.windSpeedKph, unit: .kilometersPerHour)
result.windDirection = WindDirection(rawValue: windDirection ?? "")
if let precipitationProbability = Percent(self.precipitationProbability ?? ""), precipitationProbability >= 0, precipitationProbability <= 100 {
result.precipitationProbability = precipitationProbability
}
let sunMoonDateFormatter = DateFormatter()
sunMoonDateFormatter.timeZone = TimeZone(identifier: "UTC")
sunMoonDateFormatter.dateFormat = "YYYY-MM-dd hh:mm:ss"
if let sunriseUtc = sunriseUtc {
result.sunrise = sunMoonDateFormatter.date(from: sunriseUtc)
}
if let sunsetUtc = sunsetUtc {
result.sunset = sunMoonDateFormatter.date(from: sunsetUtc)
}
result.sunState = sunState
if let moonriseUtc = moonriseUtc {
result.moonrise = sunMoonDateFormatter.date(from: moonriseUtc)
}
if let moonsetUtc = moonsetUtc {
result.moonset = sunMoonDateFormatter.date(from: moonsetUtc)
}
result.moonState = moonState
result.moonPhase = moonPhase
return result
}
}
......@@ -14,7 +14,7 @@ struct WdtHourlySummary: Codable {
public var tempF: String?
public var apparentTempF: String?
public var windSpeedKph: Double?
public var windSpeedKph: String?
public var windDirection: String?
public var humidity: String?
public var precipitationProbability: String?
......@@ -33,4 +33,46 @@ struct WdtHourlySummary: Codable {
case precipitationProbability = "pop"
case weatherCode = "wx_code"
}
func toAppModel(timeZone: TimeZone) throws -> HourlyWeather {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "YYYY-MM-dd hh:mm:ss"
dateFormatter.timeZone = timeZone
guard let date = dateFormatter.date(from: self.dateTimeLocal) else {
throw WdtWeatherSourceError.dataMergeError
}
var weekDay = WeekDay(rawValue: self.weekDay)
if weekDay == nil {
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = timeZone
weekDay = WeekDay(grigorianWeekDayNumber: calendar.component(.weekday, from: date))
}
guard let weekDayUnwrapped = weekDay else {
throw WdtWeatherSourceError.dataMergeError
}
let isDay = dayNight.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() == "day"
var result = HourlyWeather(date: date, timeZone: timeZone, weekDay: weekDayUnwrapped, isDay: isDay)
if let weatherCode = self.weatherCode {
result.type = WdtWeatherCode(rawValue: weatherCode)?.toAppModel() ?? .unknown
}
result.temp = Temperature(valueString: tempF, unit: .fahrenheit)
result.apparentTemp = Temperature(valueString: apparentTempF, unit: .fahrenheit)
result.windSpeed = WindSpeed(valueString: self.windSpeedKph, unit: .kilometersPerHour)
result.windDirection = WindDirection(rawValue: windDirection ?? "")
if let precipitationProbability = Percent(self.precipitationProbability ?? ""), precipitationProbability >= 0, precipitationProbability <= 100 {
result.precipitationProbability = precipitationProbability
}
if let humidity = Percent(self.humidity ?? ""), humidity >= 0, humidity <= 100 {
result.humidity = humidity
}
return result
}
}
......@@ -6,6 +6,7 @@
//
import Foundation
import CoreLocation
struct WdtLocation: Codable {
public private (set) var lat: String?
......@@ -30,4 +31,27 @@ struct WdtLocation: Codable {
case dailySummaries = "daily_summaries"
case hourlySummaries = "hourly_summaries"
}
public func toAppModel(timeZone: TimeZone) throws -> Location {
var coordinates: CLLocationCoordinate2D? = nil
if let lat = CLLocationDegrees(lat ?? ""), let lon = CLLocationDegrees(lon ?? "") {
coordinates = CLLocationCoordinate2D(latitude: lat, longitude: lon)
}
let today = try surfaceObservation.toAppModel(timeZone: timeZone)
let dailyWeather = try dailySummaries?.toAppModel(timeZone: timeZone) ?? [DailyWeather]()
let hourlyWeather = try hourlySummaries?.toAppModel(timeZone: timeZone) ?? [HourlyWeather]()
return Location(coordinates: coordinates,
imageName: nil,
countryCode: nil,
countryName: country,
region: region,
cityName: city,
nickname: nil,
zip: zipcode,
fipsCode: nil,
today: today,
daily: dailyWeather,
hourly: hourlyWeather)
}
}
......@@ -39,4 +39,63 @@ struct WdtSurfaceObservation: Codable {
case sunriseLocalTime = "sunrise_local"
case sunsetLocalTime = "sunset_local"
}
public func toAppModel(timeZone: TimeZone) throws -> CurrentWeather {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "YYYY-MM-dd hh:mm:ss"
dateFormatter.timeZone = timeZone
guard let date = dateFormatter.date(from: self.dateTimeLocal) else {
throw WdtWeatherSourceError.dataMergeError
}
var weekDay = WeekDay(rawValue: self.weekDay)
if weekDay == nil {
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = timeZone
weekDay = WeekDay(grigorianWeekDayNumber: calendar.component(.weekday, from: date))
}
guard let weekDayUnwrapped = weekDay else {
throw WdtWeatherSourceError.dataMergeError
}
let isDay = dayNight.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() == "day"
var result = CurrentWeather(date: date, timeZone: timeZone, weekDay: weekDayUnwrapped, isDay: isDay)
if let weatherCode = self.weatherCode {
result.type = WdtWeatherCode(rawValue: weatherCode)?.toAppModel() ?? .unknown
}
// TODO: gotta fill up values from daily:
// minTemp
// maxTemp
// precipitationProbability
// sunState
// moonState
// moonPhase
result.windSpeed = WindSpeed(valueString: self.windSpeedKph, unit: .kilometersPerHour)
result.windDirection = WindDirection(rawValue: windDirection ?? "")
result.temp = Temperature(valueString: tempF, unit: .fahrenheit)
result.apparentTemp = Temperature(valueString: apparentTempF, unit: .fahrenheit)
if let humidity = Percent(self.humidity ?? ""), humidity >= 0, humidity <= 100 {
result.humidity = humidity
}
result.visibility = Visibility(valueString: visibilityFt, unit: .feet)
result.pressure = Pressure(valueString: pressureMb, unit: .millibars)
// Doesn't it make life great when the server sends local time, but doesn't send a timezone?
if let localDateWithoutTime = dateTimeLocal.split(separator: " ").first {
if let sunriseLocalTime = self.sunriseLocalTime, let sunsetLocalTime = self.sunsetLocalTime {
let sunriseLocalDateTime = "\(localDateWithoutTime) \(sunriseLocalTime)"
let sunsetLocalDateTime = "\(localDateWithoutTime) \(sunsetLocalTime)"
let sunDateFormatter = DateFormatter()
sunDateFormatter.timeZone = timeZone
sunDateFormatter.dateFormat = "YYYY-MM-dd hh:mm a"
result.sunrise = sunDateFormatter.date(from: sunriseLocalDateTime)
result.sunset = sunDateFormatter.date(from: sunsetLocalDateTime)
}
}
return result
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment