202 lines
7.5 KiB
Swift
202 lines
7.5 KiB
Swift
//
|
|
// SeismicNetworkViewModel.swift
|
|
// Earthquake Network
|
|
//
|
|
// Created by Andrea Busi on 15/03/21.
|
|
// Copyright © 2021 Earthquake Network. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
struct MagnitudeColors {
|
|
let textColor: UIColor
|
|
let startColor: UIColor
|
|
let endColor: UIColor
|
|
}
|
|
|
|
|
|
struct SeismicNetworkMinimalViewModel {
|
|
private let seismic: EQNSisma
|
|
let place: String
|
|
let isPreliminary: Bool
|
|
let magnitude: String
|
|
let time: String
|
|
let distance: String
|
|
let smartphones: String
|
|
let users: String
|
|
let colors: MagnitudeColors
|
|
|
|
// MARK: - Init
|
|
|
|
init(seismic: EQNSisma) {
|
|
self.seismic = seismic
|
|
self.place = seismic.place
|
|
let isPreliminary = seismic.preliminary.intValue > 0
|
|
self.isPreliminary = isPreliminary
|
|
self.magnitude = String(format: "%.1f", seismic.magnitude.doubleValue)
|
|
|
|
let time = EQNUtility.formattedString(forTimeDifference: Int(seismic.timeDifference))
|
|
self.time = time
|
|
|
|
let distanceRounded = Int(round(seismic.userDistance))
|
|
self.distance = "\(distanceRounded) km"
|
|
|
|
if seismic.smartphoneNumber.intValue > 0 {
|
|
self.smartphones = String(format: NSLocalizedString("official_smartphones", comment: ""), seismic.smartphoneNumber)
|
|
} else {
|
|
self.smartphones = ""
|
|
}
|
|
if seismic.userNumber.intValue > 0 {
|
|
self.users = String(format: NSLocalizedString("official_reports", comment: ""), seismic.userNumber)
|
|
} else {
|
|
self.users = ""
|
|
}
|
|
|
|
self.colors = calculateColors(for: seismic.magnitude.doubleValue)
|
|
}
|
|
}
|
|
|
|
|
|
struct SeismicNetworkViewModel {
|
|
|
|
private let seismic: EQNSisma
|
|
let place: String
|
|
let network: String
|
|
let isPreliminary: Bool
|
|
let magnitude: String
|
|
let depth: String
|
|
let time: String
|
|
let distance: String
|
|
let coordinate: String
|
|
let population: String
|
|
let smartphones: String
|
|
let users: String
|
|
let colors: MagnitudeColors
|
|
|
|
// MARK: - Init
|
|
|
|
init(seismic: EQNSisma) {
|
|
self.seismic = seismic
|
|
self.place = seismic.place
|
|
self.network = seismic.provider
|
|
|
|
let isPreliminary = seismic.preliminary.intValue > 0
|
|
self.isPreliminary = isPreliminary
|
|
if isPreliminary {
|
|
let lowerValue = seismic.magnitude.doubleValue - seismic.magnitudeRange.doubleValue/2.0
|
|
let upperValue = seismic.magnitude.doubleValue + seismic.magnitudeRange.doubleValue/2.0
|
|
self.magnitude = String(format: "%.1f-%.1f\(seismic.magnitudeType)", lowerValue, upperValue)
|
|
self.depth = ""
|
|
} else {
|
|
self.magnitude = String(format: "%.1f%@", seismic.magnitude.doubleValue, seismic.magnitudeType)
|
|
self.depth = String(format: "%.1f km ↓", seismic.depth.doubleValue)
|
|
}
|
|
|
|
// we need to check agains null values, because sometimes WS returns invalid dates
|
|
if let date = seismic.date {
|
|
let formattedDate = EQNUtility.formattedDate(from: date)
|
|
let time = EQNUtility.formattedString(forTimeDifference: Int(seismic.timeDifference))
|
|
self.time = "\(formattedDate) - \(time)"
|
|
} else {
|
|
self.time = "no time available"
|
|
}
|
|
|
|
// distance
|
|
let distanceRounded = Int(round(seismic.userDistance))
|
|
self.distance = String(format: NSLocalizedString("official_distance", comment: ""), distanceRounded)
|
|
let coordinateText = EQNUtility.coordinateString(coordinate: seismic.coordinate.coordinate)
|
|
self.coordinate = "\(coordinateText)"
|
|
|
|
let population = formatPopulation(seismic.population100km)
|
|
self.population = String(format: NSLocalizedString("share_radius100", comment: ""), population)
|
|
|
|
if seismic.smartphoneNumber.intValue > 0 {
|
|
self.smartphones = String(format: NSLocalizedString("official_smartphones", comment: ""), seismic.smartphoneNumber)
|
|
} else {
|
|
self.smartphones = ""
|
|
}
|
|
if seismic.userNumber.intValue > 0 {
|
|
self.users = String(format: NSLocalizedString("official_reports", comment: ""), seismic.userNumber)
|
|
} else {
|
|
self.users = ""
|
|
}
|
|
|
|
self.colors = calculateColors(for: seismic.magnitude.doubleValue)
|
|
}
|
|
}
|
|
|
|
extension SeismicNetworkViewModel: Equatable {
|
|
static func == (lhs: SeismicNetworkViewModel, rhs: SeismicNetworkViewModel) -> Bool {
|
|
return lhs.seismic == rhs.seismic
|
|
}
|
|
}
|
|
|
|
// MARK: - Helpers
|
|
|
|
/// Calculate colors to use for text and background of the cell
|
|
private func calculateColors(for magnitude: Double) -> MagnitudeColors {
|
|
var textColor = UIColor.black
|
|
|
|
var r = 0, g = 0, b = 0
|
|
if (magnitude < 2.0) {
|
|
let fraction: Double = 1 - (magnitude - 0.0) / (2.0 - 0.0)
|
|
r = Int(round(200.0 + (255.0 - 200.0) * fraction))
|
|
g = Int(round(226.0 + (255.0 - 226.0) * fraction))
|
|
b = Int(round(196.0 + (255.0 - 196.0) * fraction))
|
|
textColor = UIColor(red: 12.0 / 255.0, green: 115.0 / 255.0, blue: 160.0 / 255.0, alpha: 1.0)
|
|
}
|
|
if (magnitude >= 2.0 && magnitude < 3.5) {
|
|
let fraction: Double = 1 - (magnitude - 2) / (3.5 - 2)
|
|
r = Int(round(136.0 + (200.0 - 136.0) * fraction))
|
|
g = Int(round(175.0 + (226.0 - 175.0) * fraction))
|
|
b = Int(round(131.0 + (196.0 - 131.0) * fraction))
|
|
textColor = UIColor(red: 12.0 / 255.0, green: 160.0 / 255.0, blue: 35.0 / 255.0, alpha: 1.0)
|
|
}
|
|
if (magnitude >= 3.5 && magnitude < 4.5) {
|
|
let fraction: Double = 1 - (magnitude - 3.5) / (4.5 - 3.5)
|
|
r = 252
|
|
g = Int(round(233.0 + (253.0 - 233.0) * fraction))
|
|
b = Int(round(179.0 + (209.0 - 179.0) * fraction))
|
|
textColor = UIColor(red: 244.0 / 255.0, green: 195.0 / 255.0, blue: 0.0 / 255.0, alpha: 1.0)
|
|
}
|
|
if (magnitude >= 4.5 && magnitude < 5.5) {
|
|
let fraction: Double = 1 - (magnitude - 4.5) / (5.5 - 4.5)
|
|
r = 252
|
|
g = Int(round(159.0 + (197.0 - 159.0) * fraction))
|
|
b = Int(round(161.0 + (197.0 - 161.0) * fraction))
|
|
textColor = UIColor(red: 255.0 / 255.0, green: 0.0 / 255.0, blue: 0.0 / 255.0, alpha: 1.0)
|
|
}
|
|
if (magnitude >= 5.5) {
|
|
let fraction: Double = 1 - (magnitude - 5.5) / (10 - 5.5)
|
|
r = Int(round(190.0 + (254.0 - 190.0) * fraction))
|
|
g = Int(round(124.0 + (219.0 - 124.0) * fraction))
|
|
b = 255
|
|
textColor = UIColor(red: 183.0 / 255.0, green: 60.0 / 255.0, blue: 252.0 / 255.0, alpha: 1.0)
|
|
}
|
|
|
|
let r2 = min(r + 30, 255)
|
|
let g2 = min(g + 30, 255)
|
|
let b2 = min(b + 30, 255)
|
|
|
|
let startColor = UIColor(red: CGFloat(r) / 255.0, green: CGFloat(g) / 255.0, blue: CGFloat(b) / 255.0, alpha: 1.0)
|
|
let endColor = UIColor(red: CGFloat(r2) / 255.0, green: CGFloat(g2) / 255.0, blue: CGFloat(b2) / 255.0, alpha: 1.0)
|
|
|
|
return .init(textColor: textColor, startColor: startColor, endColor: endColor)
|
|
}
|
|
|
|
/// Format population value (ex. 1.5M, 2.4k)
|
|
private func formatPopulation(_ population: Double) -> String {
|
|
var populationString = ""
|
|
if population > 999_999 {
|
|
let roundedPopulation = round(population / 100_000) / 10
|
|
populationString = "\(roundedPopulation)M"
|
|
} else if population > 999 {
|
|
let roundedPopulation = round(population / 100) / 10
|
|
populationString = "\(roundedPopulation)K"
|
|
} else {
|
|
let roundedPopulation = round(population)
|
|
populationString = "\(roundedPopulation)"
|
|
}
|
|
return populationString
|
|
}
|