166 lines
6.1 KiB
Swift
166 lines
6.1 KiB
Swift
//
|
|
// PasquakesMapViewController.swift
|
|
// Earthquake Network
|
|
//
|
|
// Created by Andrea Busi on 10/03/21.
|
|
// Copyright © 2021 Earthquake Network. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import MapKit
|
|
|
|
class PasquakesMapViewController: EQNBaseMapViewController {
|
|
|
|
override var availableFilters: [EQNBaseMapFilter] {
|
|
[ .oneMonth, .oneWeek, .oneDay, .oneHour ]
|
|
}
|
|
|
|
// MARK: - Internal
|
|
|
|
/// Pasquakes currently showned on the map
|
|
private var filteredPastquakes = [EQNPastquakes]()
|
|
/// Keep track of the evaluated center, to show circles around it
|
|
private var centerLocation: CLLocation?
|
|
/// Contains circles drawed on the map
|
|
private var mapCircles = [MKCircle]()
|
|
|
|
// MARK: - View Lifecycle
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
}
|
|
|
|
// MARK: - Public
|
|
|
|
override func registerMapAnnotationViews() {
|
|
mapView.register(EQNCustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: EQNCustomAnnotationView.SingleLineIdentifier)
|
|
}
|
|
|
|
override func loadDataSource() {
|
|
guard let list = EQNManager.manager().datiPastQuakes else { return }
|
|
|
|
// set the base filter
|
|
setDefaultFilter(for: list)
|
|
|
|
// filter report based on selected filter
|
|
let filterDate = filter.date
|
|
filteredPastquakes = list.filter { $0.date > filterDate }
|
|
|
|
// create annotations to display on the map
|
|
let annotations = filteredPastquakes.compactMap { EQNMapAnnotationPastquake(pastquake: $0) }
|
|
// elaborate the center
|
|
centerLocation = elaborateCenter(for: filteredPastquakes)
|
|
|
|
// update map and center
|
|
updateMap(with: annotations)
|
|
if let centerLocation = centerLocation {
|
|
addCircles(for: centerLocation)
|
|
}
|
|
}
|
|
|
|
override func elaborateMapCenter() {
|
|
guard let centerLocation = centerLocation else { return }
|
|
|
|
setMapCenter(for: centerLocation)
|
|
}
|
|
|
|
override func didTapAnnotation(_ annotation: MKAnnotation) {
|
|
mapView.deselectAnnotation(annotation, animated: true)
|
|
|
|
guard let annotation = annotation as? EQNMapAnnotationPastquake, let pastquake = annotation.pastquake else {
|
|
return
|
|
}
|
|
|
|
let difference = Int(Date().timeIntervalSince(pastquake.date) / 60.0)
|
|
let title = EQNUtility.formattedString(forTimeDifference: difference)
|
|
|
|
let message = ""
|
|
+ "📱 " + String(format: NSLocalizedString("map_number", comment: ""), "\(pastquake.users)")
|
|
+ "\n⏱ " + EQNUtility.formattedDate(from: pastquake.date) + " \(NSLocalizedString("share_yourtime", comment: ""))"
|
|
|
|
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
|
alert.addAction(UIAlertAction(title: NSLocalizedString("official_close", comment: ""), style: .cancel, handler: nil))
|
|
present(alert, animated: true, completion: nil)
|
|
}
|
|
|
|
// MARK: - Private
|
|
|
|
private func elaborateCenter(for pastquakes: [EQNPastquakes]) -> CLLocation? {
|
|
var center: CLLocation?
|
|
|
|
// Se c'è un rilevamento distante dall'utente meno del raggio di notifica,
|
|
// allora il centro è su quel rilevamento
|
|
if let userPosition = CLLocationManager().location {
|
|
let nearestPastquake = filteredPastquakes
|
|
.sorted(by: { (pastquake1, pastquake2) -> Bool in
|
|
abs(userPosition.distance(from: pastquake1.coordinate)) < abs(userPosition.distance(from: pastquake2.coordinate))
|
|
})
|
|
.first
|
|
|
|
// controlliamo che sia inferiore al raggio massimo impostato per le notifiche
|
|
if let radiusLow = Double(EQNSettingRealTimeAlert.shared.raggioSismiLievi),
|
|
let radiusStrong = Double(EQNSettingRealTimeAlert.shared.raggioSismiForti),
|
|
let nearestPastquake = nearestPastquake {
|
|
let radius = max(radiusLow, radiusStrong)
|
|
if abs(nearestPastquake.coordinate.distance(from: userPosition)) < radius {
|
|
center = nearestPastquake.coordinate
|
|
}
|
|
}
|
|
}
|
|
|
|
// altrimenti il centro è sul rilevamento più recente
|
|
if center == nil, let newestPastquake = filteredPastquakes.sorted(by: { $0.date > $1.date }).first {
|
|
center = newestPastquake.coordinate
|
|
}
|
|
|
|
return center
|
|
}
|
|
|
|
private func addCircles(for location: CLLocation) {
|
|
// aggiungiamo 3 cerchi concentrici per il punto specificato
|
|
// li inseriamo a a 50, 100 e 200 km.
|
|
|
|
let circles = [
|
|
MKCircle(center: location.coordinate, radius: 25_000),
|
|
MKCircle(center: location.coordinate, radius: 100_000),
|
|
MKCircle(center: location.coordinate, radius: 200_000)
|
|
]
|
|
|
|
// elimino vecchie circonferenze
|
|
mapView.removeOverlays(mapCircles)
|
|
|
|
// !!note: is important to assign here the circles
|
|
// otherwise `addOverlays` will not work
|
|
mapCircles = circles
|
|
|
|
// creo nuovi cerchi
|
|
mapView.addOverlays(circles)
|
|
}
|
|
|
|
// MARK: - Map
|
|
|
|
override func setupAnnotationView(for annotation: MKAnnotation, on mapView: MKMapView) -> MKAnnotationView? {
|
|
guard let annotation = annotation as? EQNMapAnnotationPastquake else {
|
|
return nil
|
|
}
|
|
|
|
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: EQNCustomAnnotationView.SingleLineIdentifier, for: annotation) as! EQNCustomAnnotationView
|
|
|
|
annotationView.image = annotation.image
|
|
annotationView.title = annotation.title
|
|
|
|
return annotationView
|
|
}
|
|
|
|
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
|
|
guard let circleOverlay = overlay as? MKCircle else {
|
|
return MKOverlayRenderer(overlay: overlay)
|
|
}
|
|
|
|
let circle = MKCircleRenderer(overlay: circleOverlay)
|
|
circle.strokeColor = AppTheme.Colors.darkGray
|
|
circle.lineWidth = 1.0
|
|
return circle
|
|
}
|
|
}
|