Files
eqn.ios/Sources/Earthquake Network/Models/EQNSeismic.swift
T

221 lines
8.1 KiB
Swift

//
// EQNSeismic.swift
// Earthquake Network
//
// Created by Busi Andrea on 20/09/2020.
// Copyright © 2020 Earthquake Network. All rights reserved.
//
import Foundation
@objc class EQNSeismic: NSObject {
@objc enum FilterType: Int {
case inRadius
case positionRelevant
case worldWide
case userFelt
}
enum Sort: Int, CaseIterable {
case time
case position
case magnitude
}
@objc static let shared = EQNSeismic()
@objc var filterOption: FilterType
var sort: Sort
var maximumDistance: String
@objc var minimumMagnitude: String
// MARK: - Init
override init() {
Self.migrate_v5_8()
let defaults = UserDefaults.standard
filterOption = defaults.enumObject(forKey: UserDefaults.SeismicFilterOption, or: .positionRelevant)
sort = defaults.enumObject(forKey: UserDefaults.SeismicSort, or: .time)
maximumDistance = defaults.object(forKey: UserDefaults.SeismicDistanzaMassima, or: EQNData.DefaultFilterRadius.value)
minimumMagnitude = defaults.object(forKey: UserDefaults.SeismicMagnitudoMinima, or: EQNData.DefaultFilterMagnitude.value)
super.init()
}
// MARK: - Public
public func saveFilters() {
let defaults = UserDefaults.standard
defaults.set(filterOption.rawValue, forKey: UserDefaults.SeismicFilterOption)
defaults.set(sort.rawValue, forKey: UserDefaults.SeismicSort)
defaults.set(maximumDistance, forKey: UserDefaults.SeismicDistanzaMassima)
defaults.set(minimumMagnitude, forKey: UserDefaults.SeismicMagnitudoMinima)
}
// MARK: - Private
private class func migrate_v5_8() {
let defaults = UserDefaults.standard
let alreadyMigrated = defaults.bool(forKey: UserDefaults.SismicFiltersMigrationV5_8)
if alreadyMigrated {
return
}
if let savedMagnitude = defaults.object(forKey: UserDefaults.SeismicMagnitudoMinima) as? String {
let minMagnitude = switch savedMagnitude {
case "0.0": "0.0"
case "0.5", "1.0": "1.0"
case "1.5", "2.0": "2.0"
case "2.5", "3.0": "3.0"
case "3.5", "4.0": "4.0"
case "4.5", "5.0": "5.0"
case "5.5", "6.0": "6.0"
default: "0.0"
}
defaults.set(minMagnitude, forKey: UserDefaults.SeismicMagnitudoMinima)
}
if let savedDistance = defaults.object(forKey: UserDefaults.SeismicDistanzaMassima) as? String {
let maxDistance = switch savedDistance {
case "50", "100": "100"
case "200", "300": "250"
case "400", "500", "600": "500"
case "800": "750"
case "1000": "1000"
default:
// 2000, 4000, qualsiasi distanza
"2000"
}
defaults.set(maxDistance, forKey: UserDefaults.SeismicDistanzaMassima)
}
defaults.set(true, forKey: UserDefaults.SismicFiltersMigrationV5_8)
}
// MARK: - Class
@objc func filterSeismicList(_ list: [EQNSisma]) -> [EQNSisma] {
// filtri
let filter_radius = Double(maximumDistance)
let filter_min_magnitude = Double(minimumMagnitude)
// filter seismic list
var filtered = [EQNSisma]()
for (i, seismic) in list.enumerated() {
var keep = true
let latitude = seismic.coordinate.coordinate.latitude
let longitude = seismic.coordinate.coordinate.longitude
let provider = seismic.provider.uppercased()
//Ricerca di sismi duplicati in lista
for j in -3...3 {
if (j != 0) && (i + j > 0) && (i+j < list.count) {
let seismic_j = list[i+j]
let latitude_j = seismic_j.coordinate.coordinate.latitude
let longitude_j = seismic_j.coordinate.coordinate.longitude
let provider_j = seismic_j.provider.uppercased()
let delta_lat = abs(latitude - latitude_j)
let delta_lon = abs(longitude - longitude_j)
let delta_time = abs(EQNUtility.getDeltaMinute(seismic.date ?? Date()) - EQNUtility.getDeltaMinute(seismic_j.date ?? Date()))
let ratio = seismic.magnitude.doubleValue/seismic_j.magnitude.doubleValue
if ratio > 0.8 && ratio < 1.2 && delta_lat < 0.5 && delta_lon < 0.5 && delta_time <= 2 {
if provider == "EMSC" {
keep = false
}
if provider == "USGS" && !(provider_j == "EMSC") {
keep = false
}
}
}
}
if keep {
let distance = seismic.userDistance
let magnitude = seismic.magnitude.doubleValue
if filterOption == .inRadius {
//filtro basato su magnitudo e raggio
if let filter_radius, let filter_min_magnitude, distance > filter_radius || magnitude < filter_min_magnitude {
keep = false
}
} else if filterOption == .positionRelevant {
//filtro sismi significativi
if magnitude < 7.0 && distance > 2000 {
keep = false
} else if magnitude < 6.5 && distance > 1600 {
keep = false
} else if magnitude < 6.0 && distance > 1300 {
keep = false
} else if magnitude < 5.5 && distance > 1000 {
keep = false
} else if magnitude < 5.0 && distance > 700 {
keep = false
} else if magnitude < 4.5 && distance > 500 {
keep = false
} else if magnitude < 4.0 && distance > 350 {
keep = false
} else if magnitude < 3.5 && distance > 200 {
keep = false
} else if magnitude < 3.0 && distance > 125 {
keep = false
} else if magnitude < 2.5 && distance > 70 {
keep = false
} else if magnitude < 2.0 && distance > 35 {
keep = false
} else if magnitude < 1.5 && distance > 20 {
keep = false
}
} else if filterOption == .worldWide {
//filtro che mostra tutti i sismi a livello mondiale di magnitudo>=2
if magnitude < 2 {
keep = false
}
} else if filterOption == .userFelt {
//filtro che mostra i sismi segnalati da più di 1 utente
if seismic.userNumber.intValue < 2 {
keep = false
}
}
}
if keep {
filtered.append(seismic)
}
}
switch sort {
case .time:
filtered.sort(by: { seismic1, seismic2 in
guard let date1 = seismic1.date else {
return false
}
guard let date2 = seismic2.date else {
return true
}
return date1 > date2
})
case .position:
filtered.sort { seismic1, seismic2 in
seismic1.userDistance < seismic2.userDistance
}
case .magnitude:
filtered.sort { seismic1, seismic2 in
seismic1.magnitude.doubleValue > seismic2.magnitude.doubleValue
}
}
return filtered
}
}