feat: Add simulator function

This commit is contained in:
Andrea Busi
2020-11-15 15:43:30 +01:00
parent 90426c21f1
commit e15b7bcca2
13 changed files with 333 additions and 16 deletions
@@ -209,6 +209,7 @@
DCAA913F24F68A1D00145A3D /* SettingMultivaluesTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCAA913E24F68A1D00145A3D /* SettingMultivaluesTableViewCell.swift */; };
DCB28CEE24FB8400001F557E /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCB28CED24FB8400001F557E /* SettingsViewController.swift */; };
DCB45BC8250E86E100DB2D0C /* SeismicSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCB45BC7250E86E100DB2D0C /* SeismicSettingsViewController.swift */; };
DCB528212560161C005288E5 /* AlertSimulatorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCB528202560161C005288E5 /* AlertSimulatorViewController.swift */; };
DCB6FBEC24D0B40600ED23B8 /* Colors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DCB6FBEB24D0B40600ED23B8 /* Colors.xcassets */; };
DCBB267A24D1E7F500F04559 /* SubscriptionsHeaderTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCBB267924D1E7F500F04559 /* SubscriptionsHeaderTableViewCell.swift */; };
DCBB267C24D1E98300F04559 /* EQNInsetTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCBB267B24D1E98300F04559 /* EQNInsetTableViewCell.swift */; };
@@ -517,6 +518,7 @@
DCAA913E24F68A1D00145A3D /* SettingMultivaluesTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingMultivaluesTableViewCell.swift; sourceTree = "<group>"; };
DCB28CED24FB8400001F557E /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
DCB45BC7250E86E100DB2D0C /* SeismicSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicSettingsViewController.swift; sourceTree = "<group>"; };
DCB528202560161C005288E5 /* AlertSimulatorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertSimulatorViewController.swift; sourceTree = "<group>"; };
DCB6FBEB24D0B40600ED23B8 /* Colors.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Colors.xcassets; sourceTree = "<group>"; };
DCBB267924D1E7F500F04559 /* SubscriptionsHeaderTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionsHeaderTableViewCell.swift; sourceTree = "<group>"; };
DCBB267B24D1E98300F04559 /* EQNInsetTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNInsetTableViewCell.swift; sourceTree = "<group>"; };
@@ -993,6 +995,14 @@
path = Commands;
sourceTree = "<group>";
};
DCB5281F256015EB005288E5 /* Simulator */ = {
isa = PBXGroup;
children = (
DCB528202560161C005288E5 /* AlertSimulatorViewController.swift */,
);
path = Simulator;
sourceTree = "<group>";
};
DCB528252560171A005288E5 /* Reports */ = {
isa = PBXGroup;
children = (
@@ -1039,6 +1049,7 @@
DCD3E3BE24D1555F007C78D4 /* InApp */,
DCEFF21024F57163009D3FE1 /* Settings */,
DC141968250E769B0059E060 /* Seismic Networks */,
DCB5281F256015EB005288E5 /* Simulator */,
);
path = Controllers;
sourceTree = "<group>";
@@ -1560,6 +1571,7 @@
DC105641251E7ECE002579BB /* UIFont+Extensions.swift in Sources */,
8CA46BA12194532E00C63C16 /* SismaAnnotation.m in Sources */,
DCB28CEE24FB8400001F557E /* SettingsViewController.swift in Sources */,
DCB528212560161C005288E5 /* AlertSimulatorViewController.swift in Sources */,
DCC76BD8251F56050005C4DC /* SeismicCardSettingsViewController.swift in Sources */,
DC3CE50A250EB7A8005A7DD5 /* EQNGenericPickerViewController.swift in Sources */,
8C602246218D9DB200C799C2 /* PastquakesDettagliMappa.m in Sources */,
@@ -195,11 +195,11 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
[self presentViewController:controller animated:YES completion:nil];
}
- (void)actionComingSoon
- (void)actionOpenSimulator
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Coming soon..." message:@"🚀" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
AlertSimulatorViewController *controller = [[AlertSimulatorViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
[self presentViewController:navController animated:YES completion:nil];
}
- (void)actionHowItWorks
@@ -281,7 +281,7 @@ typedef NS_ENUM(NSInteger, AllerteTableRow) {
[weakSelf actionTestPush];
};
cell.onTapSimulator = ^{
[weakSelf actionComingSoon];
[weakSelf actionOpenSimulator];
};
cell.onTapHowItWorks = ^{
[weakSelf actionHowItWorks];
@@ -0,0 +1,244 @@
//
// AlertSimulatorViewController.swift
// Earthquake Network
//
// Created by Busi Andrea on 14/11/2020.
// Copyright © 2020 Earthquake Network. All rights reserved.
//
import UIKit
import MapKit
class AlertSimulatorViewController: UIViewController, MKMapViewDelegate {
struct MapCircle {
let identifier: String
let distance: CLLocationDistance
let color: UIColor
}
// MARK: - Internal
private let mapCircles = [
MapCircle(identifier: "circle_internal", distance: 50_000, color: AppTheme.Colors.red),
MapCircle(identifier: "circle_external", distance: 750_000, color: AppTheme.Colors.green)
]
private lazy var viewfinderView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .clear
view.isUserInteractionEnabled = false
// add central vertiacl and horizontal lines
let viewfinderVertical = UIView()
view.addSubview(viewfinderVertical)
viewfinderVertical.translatesAutoresizingMaskIntoConstraints = false
viewfinderVertical.backgroundColor = AppTheme.Colors.lightBlue
viewfinderVertical.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
viewfinderVertical.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
viewfinderVertical.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
viewfinderVertical.widthAnchor.constraint(equalToConstant: 2.0).isActive = true
let viewfinderHorizontal = UIView()
view.addSubview(viewfinderHorizontal)
viewfinderHorizontal.translatesAutoresizingMaskIntoConstraints = false
viewfinderHorizontal.backgroundColor = AppTheme.Colors.lightBlue
viewfinderHorizontal.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
viewfinderHorizontal.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
viewfinderHorizontal.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
viewfinderHorizontal.heightAnchor.constraint(equalToConstant: 2.0).isActive = true
return view
}()
private lazy var mapView: MKMapView = {
let map = MKMapView()
map.translatesAutoresizingMaskIntoConstraints = false
map.showsUserLocation = true
map.delegate = self
return map
}()
private lazy var calculateButton: UIButton = {
let button = EQNRoundedButton(type: .custom)
button.backgroundColor = .lightGray
button.setTitleColor(AppTheme.Colors.darkGray, for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle(NSLocalizedString("globe_simulation_button", comment: "").uppercased(), for: .normal)
button.addTarget(self, action: #selector(calculateTapped(_:)), for: .touchUpInside)
return button
}()
// MARK: - View Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
let closeButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(closeTapped(_:)))
navigationItem.rightBarButtonItem = closeButton
setupUI()
configureMap()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// show an alert view functionality details
let alert = UIAlertController(title: NSLocalizedString("main_simulator", comment: ""), message: NSLocalizedString("globe_simulation", comment: ""), preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("main_understood", comment: ""), style: .default))
present(alert, animated: true)
}
// MARK: - Private
private func setupUI() {
view.addSubview(mapView)
view.addSubview(viewfinderView)
view.addSubview(calculateButton)
mapView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
mapView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
mapView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
mapView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
viewfinderView.topAnchor.constraint(equalTo: mapView.topAnchor).isActive = true
viewfinderView.bottomAnchor.constraint(equalTo: mapView.bottomAnchor).isActive = true
viewfinderView.leftAnchor.constraint(equalTo: mapView.leftAnchor).isActive = true
viewfinderView.rightAnchor.constraint(equalTo: mapView.rightAnchor).isActive = true
calculateButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20.0).isActive = true
calculateButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20.0).isActive = true
calculateButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -10.0).isActive = true
calculateButton.heightAnchor.constraint(equalToConstant: 40.0).isActive = true
}
private func configureMap() {
guard let lastPosition = EQNUser.default().lastPosition else { return }
let span = MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)
let region = MKCoordinateRegion(center: lastPosition.coordinate, span: span)
mapView.setCenter(lastPosition.coordinate, animated: false)
mapView.setRegion(region, animated: true)
mapCircles.forEach { (mapCircle) in
addCircle(location: lastPosition, radius: mapCircle.distance, id: mapCircle.identifier)
}
}
private func addCircle(location: CLLocation, radius: CLLocationDistance, id: String) {
let circle = MKCircle(center: location.coordinate, radius: radius)
circle.title = id
mapView.addOverlay(circle)
}
// MARK: - Actions
@objc func closeTapped(_ sender: Any) {
dismiss(animated: true)
}
@objc func calculateTapped(_ sender: Any) {
guard let lastPosition = EQNUser.default().lastPosition,
let circleMin = mapCircles.sorted(by: { $0.distance < $1.distance }).first,
let circleMax = mapCircles.sorted(by: { $0.distance > $1.distance }).first else { return }
let location = CLLocation(latitude: mapView.centerCoordinate.latitude, longitude: mapView.centerCoordinate.longitude)
let distance = lastPosition.distance(from: location)
// check for a valid point selected by the user
if distance < circleMin.distance || distance > circleMax.distance {
let message = distance < circleMin.distance ? "globe_simulation_outside" : "globe_simulation_inside"
let alert = UIAlertController(title: NSLocalizedString("Attenzione", comment: ""), message: NSLocalizedString(message, comment: ""), preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("Ok", comment: ""), style: .cancel, handler: nil))
present(alert, animated: true)
return
}
let url = EQNGeneratoreURLServer.urlAlertSimulator()
ServerRequest.default().inviaInformazioniAlServer(with: url, richiesta: .alertSimulator) { (result) in
if let result = result as? String {
DispatchQueue.main.async {
self.elaborateServerResponse(result, distance: distance)
}
}
} failure: { (error) in
DispatchQueue.main.async {
let alert = UIAlertController(title: NSLocalizedString("Attenzione", comment: ""), message: error?.localizedDescription, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("Ok", comment: ""), style: .cancel, handler: nil))
self.present(alert, animated: true)
return
}
}
}
private func elaborateServerResponse(_ response: String, distance: CLLocationDistance) {
let isTop10k = EQNPurchaseUtility.isTop10kEnabled()
let isTop100k = EQNPurchaseUtility.isTop100kEnabled()
// server response (like '3411#12')
let split = response.split(separator: "#")
let people: Int
let popleTop10k: Int
if split.count > 1 {
//caso top10k=0 e top100k=0
people = Int(split[0]) ?? 0
popleTop10k = Int(split[1]) ?? 0
} else {
//caso top10k=1 oppure top100k=1
people = Int(split[0]) ?? 0
popleTop10k = 0
}
let distanceKm = distance / 1000
let delay = round(Double(people) / 1000.0 * 0.15) //calcolo il ritardo di allerta dovuto alla coda di utenti
let leadTime = round(Double(distanceKm) / 8.0 - 3.0) //calcolo il tempo di allerta teorico nel caso di 0 utenti in coda
let actualTime = leadTime - delay //calcolo il tempo di allerta per l'utente
//il messaggio mostrato all'utente cambia in base al fatto di possedere un abbonamento ed al tempo di allerta calcolato
//il messaggio include tag html perché cambio il colore di parte delle stringa, non so se si fa così anche in iOS
var message = ""
if (isTop10k) {
if (people == 0) {
message = String(format: NSLocalizedString("globe_simulation_message6", comment: ""), "TOP 10K", leadTime)
} else {
message = String(format: NSLocalizedString("globe_simulation_message4", comment: ""), "TOP 10K", leadTime, Double(people))
}
} else if (isTop100k) {
message = String(format: NSLocalizedString("globe_simulation_message5", comment: ""), "TOP 100K", leadTime, Double(people), "TOP 10K")
} else {
if (leadTime / actualTime < 1.4) {
message = String(format: NSLocalizedString("globe_simulation_message3", comment: ""), leadTime, Double(people), Double(popleTop10k))
} else {
if (actualTime > 0) {
message = String(format: NSLocalizedString("globe_simulation_message1", comment: ""), leadTime, Double(people), actualTime, Double(popleTop10k))
} else {
let updatedActualTime = actualTime * -1;
message = String(format: NSLocalizedString("globe_simulation_message2", comment: ""), leadTime, Double(people), updatedActualTime, Double(popleTop10k))
}
}
}
let alert = UIAlertController(title: NSLocalizedString("main_simulator", comment: ""), message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("Ok", comment: ""), style: .cancel, handler: nil))
present(alert, animated: true)
}
// MARK: MKMapViewDelegate
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let overlay = overlay as? MKCircle, let mapCircle = mapCircles.first(where: { $0.identifier == overlay.title }) {
let circle = MKCircleRenderer(overlay: overlay)
circle.strokeColor = mapCircle.color
circle.fillColor = AppTheme.Colors.green.withAlphaComponent(0.1)
circle.lineWidth = 2.0
return circle
}
return MKOverlayRenderer(overlay: overlay)
}
}
+5 -2
View File
@@ -37,7 +37,7 @@ static NSString * const EQNServerUrlOfferTimeRemaining = @"https://srv.earthquak
static NSString * const EQNServerUrlAvailableSubscriptionsCounter = @"https://srv.earthquakenetwork.it/distquake_count_top_redis.php";
/// Carica le impostazioni delle notifiche definite dall'utente
static NSString * const EQNServerUrlUploadSettings = @"https://srv.earthquakenetwork.it/distquake_upload_settings_ios.php";
// URL registrazione server
// URL EQNTipoChiamataRegistrazione server
static NSString * const EQNServerUrlRegistration = @"https://srv.earthquakenetwork.it/distquake_upload_gcm_regid2.php";
// URL posizione server
static NSString * const EQNServerUrlUserLocation = @"https://srv.earthquakenetwork.it/distquake_upload_gcm_latlon.php";
@@ -56,6 +56,8 @@ static NSString * const EQNServerUrlSendUserReport = @"https://srv.earthquakenet
static NSString * const EQNServerUrlSendUserReportMessage = @"https://srv.earthquakenetwork.it/distquake_upload_manual_message.php";
/// Effettua un test delle notifiche push
static NSString * const EQNServerUrlTestAlarm = @"https://srv.earthquakenetwork.it/distquake_upload_testalarm.php";
/// Simulatore per calcolo pre-allerta
static NSString * const EQNServerUrlAlertSimulator = @"https://srv.earthquakenetwork.it/distquake_download_alertposition.php";
#pragma mark - UserDefaults Keys
@@ -142,7 +144,8 @@ typedef NS_ENUM(NSInteger, EQNTipoChiamata) {
EQNTipoChiamataCommentoTerremoto,
EQNTipoChiamataImpostazioniNotifiche,
EQNTipoChiamataOfferTimeRemaining,
EQNTipoChiamataAlertPushTest
EQNTipoChiamataAlertPushTest,
EQNTipoChiamataAlertSimulator
};
@@ -12,3 +12,5 @@
#import "ReteSismiDettagliMappa.h"
#import "SettingsBaseViewController.h"
#import "PastquakesAnnotation.h"
#import "EQNGeneratoreURLServer.h"
#import "ServerRequest.h"
+1 -1
View File
@@ -20,7 +20,7 @@ typedef void (^errorCompletionHandler)(NSError * _Nullable error);
@property (nonatomic) BOOL isConnect;
+ (instancetype)defaultServerConnectionSingleton;
+ (instancetype)defaultServerConnectionSingleton NS_SWIFT_NAME(default());
- (void)inviaInformazioniAlServerWithURL:(NSURL *)url richiesta:(EQNTipoChiamata)chiamata success:(successCompletionHandler)onSuccess failure:(errorCompletionHandler)onFailure;
+4 -2
View File
@@ -112,6 +112,9 @@
case EQNTipoChiamataPosizione:
onSuccess(@"success");
break;
case EQNTipoChiamataAlertSimulator:
onSuccess([NSString stringWithFormat:@"%@", JSON]);
break;
default:
onSuccess(JSON);
break;
@@ -135,9 +138,8 @@
onSuccess([EQNUtility clearStringMessaggi:newStr]);
break;
case EQNTipoChiamataCalibrazione:
onSuccess(newStr);
break;
case EQNTipoChiamataImpostazioniNotifiche:
case EQNTipoChiamataAlertSimulator:
onSuccess(newStr);
default:
// don't call the callback
@@ -3,7 +3,7 @@
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17125"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17126"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
@@ -2001,7 +2001,7 @@ Sisma rilevato da 10 smartphone</string>
<rect key="frame" x="8" y="68" width="382" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="BjK-4E-Vhw" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="382" height="40"/>
<rect key="frame" x="0.0" y="0.0" width="187" height="40"/>
<color key="backgroundColor" white="1" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="TEST ALERT 🚨">
<color key="titleColor" name="Gray (dark)"/>
@@ -2010,8 +2010,8 @@ Sisma rilevato da 10 smartphone</string>
<action selector="testAlertTapped" destination="vSa-gk-t22" eventType="touchUpInside" id="HNp-eo-vpW"/>
</connections>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qkR-Lg-s4B" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="0.0" height="40"/>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qkR-Lg-s4B" customClass="EQNRoundedButton" customModule="Earthquake_Network" customModuleProvider="target">
<rect key="frame" x="195" y="0.0" width="187" height="40"/>
<color key="backgroundColor" white="1" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="SIMULATOR ⏱">
<color key="titleColor" name="Gray (dark)"/>
@@ -2107,13 +2107,13 @@ Sisma rilevato da 10 smartphone</string>
<stackView opaque="NO" contentMode="scaleToFill" distribution="equalSpacing" alignment="center" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="0lY-aw-fec">
<rect key="frame" x="11.5" y="0.0" width="106.5" height="25"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Last 24h:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hbH-vC-Yma">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Last 24h:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hbH-vC-Yma">
<rect key="frame" x="0.0" y="0.0" width="89" height="25"/>
<fontDescription key="fontDescription" type="system" pointSize="22"/>
<color key="textColor" name="Gray (dark)"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="BRv-IS-2fA">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="0" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="BRv-IS-2fA">
<rect key="frame" x="93" y="0.0" width="13.5" height="25"/>
<fontDescription key="fontDescription" type="system" pointSize="22"/>
<color key="textColor" name="Gray (dark)"/>
@@ -642,3 +642,17 @@
"hours_other" = "%lu hours ago";
"days_one" = "%lu day ago";
"days_other" = "%lu days ago";
// Simulatore
"main_simulator" = "Simulator";
"globe_simulation_button" = "Compute warning time";
"globe_simulation" = "If the earthquake epicentre is outside the red disk and the quake is immediately detected by the smartphones, you will receive the alert more than 5 seconds in advance. Select on map the possible epicentre in order to compute the warning time.";
"globe_simulation_inside" = "Select a location inside the green disk";
"globe_simulation_outside" = "Select a location outside the red disk";
"globe_simulation_message1" = "With this epicentre, you should receive the alert %.0f seconds in advance. However, %.0f people will be alerted before you. The warning time will be of %.0f seconds. By subscribing now to the TOP 10K priority service, only %.0f people will be alerted before you (in order of distance from the epicenter)";
"globe_simulation_message2" = "With this epicentre, you should receive the alert %.0f seconds in advance. However, %.0f people will be alerted before you. You will receive the alert %.0f seconds after the seismic waves. By subscribing now to the TOP 10K priority service, only %.0f people will be alerted before you (in order of distance from the epicenter)";
"globe_simulation_message3" = "With this epicentre, you should receive the alert %.0f seconds in advance. However, %.0f people will be alerted before you. By subscribing now to the TOP 10K priority service, only %.0f people will be alerted before you (in order of distance from the epicenter)";
"globe_simulation_message4" = "With this epicentre, thanks to the %@ priority service you should receive the alert %.0f seconds in advance. Only %.0f people will be alerted before you.";
"globe_simulation_message5" = "With this epicentre, thanks to the %@ priority service you should receive the alert %.0f seconds in advance. %.0f people will be alerted before you. To increase the warning time you can subscribe to the %@ priority service";
"globe_simulation_message6" = "With this epicentre, thanks to the %@ priority service you should receive the alert %.0f seconds in advance. You will be the first to be alerted!";
"globe_simulation_priority" = "Priority service";
@@ -638,3 +638,17 @@
"hours_other" = "%lu horas";
"days_one" = "%lu día";
"days_other" = "%lu días";
// Simulatore
"main_simulator" = "Simulador";
"globe_simulation_button" = "Calcular el tiempo de alerta";
"globe_simulation" = "Si el epicentro del sismo está fuera del disco rojo y los smartphones lo detectan de inmediato, recibirá la alerta con más de 5 segundos de anticipación. Seleccionas en el mapa el posible epicentro para calcular el tiempo de alerta.";
"globe_simulation_inside" = "Seleccionas una ubicación dentro del disco verde";
"globe_simulation_outside" = "Seleccionas una ubicación fuera del disco rojo";
"globe_simulation_message1" = "Con este epicentro, deberías recibir la alerta %.0f segundos antes. Sin embargo, %.0f personas serán alertadas antes que tú. El tiempo de aviso será de %.0f segundos. Al suscribirse hoy al servicio de prioridad TOP 10K, solo %.0f personas recibirán la alerta antes que usted (en orden de distancia del epicentro)";
"globe_simulation_message2" = "Con este epicentro, deberías recibir la alerta %.0f segundos antes. Sin embargo, %.0f personas serán alertadas antes que tú. Recibirá la alerta %.0f segundos después de las ondas sísmicas. Al suscribirse hoy al servicio de prioridad TOP 10K, solo %.0f personas recibirán la alerta antes que usted (en orden de distancia del epicentro)";
"globe_simulation_message3" = "Con este epicentro, deberías recibir la alerta %.0f segundos antes. Sin embargo, %.0f personas serán alertadas antes que tú. Al suscribirse hoy al servicio de prioridad TOP 10K, solo %.0f personas recibirán la alerta antes que usted (en orden de distancia del epicentro)";
"globe_simulation_message4" = "Con este epicentro, gracias al servicio de prioridad %@, deberías recibir la alerta %.0f segundos antes. Solo %.0f personas serán alertadas antes que tú";
"globe_simulation_message5" = "Con este epicentro, gracias al servicio de prioridad %@, deberías recibir la alerta %.0f segundos antes. %.0f personas serán alertadas antes que tú. Para aumentar el tiempo de advertencia, puede suscribirse al servicio de prioridad %@";
"globe_simulation_message6" = "Con este epicentro, gracias al servicio de prioridad %@, deberías recibir la alerta %.0f segundos antes. ¡Serás la primera persona en ser alertada!";
"globe_simulation_priority" = "Servicio prioritario";
@@ -630,3 +630,18 @@
"hours_other" = "%lu ore fa";
"days_one" = "%lu giorno fa";
"days_other" = "%lu giorni fa";
// Simulatore
"main_simulator" = "Simulatore";
"globe_simulation_button" = "Calcola pre-allerta";
"globe_simulation" = "Se l'epicentro del sisma è al di fuori del cerchio rosso ed è rilevato immediatamente dagli smartphone, potrai ricevere l'allerta con più di 5 secondi di anticipo. Seleziona su mappa il possibile epicentro del sisma per calcolare il tempo di pre-allerta.";
"globe_simulation_inside" = "Seleziona un punto dentro il cerchio verde";
"globe_simulation_outside" = "Seleziona un punto fuori dal cerchio rosso";
"globe_simulation_message1" = "Con epicentro nella posizione scelta, dovresti ricevere l'allerta con %.0f secondi di anticipo. Tuttavia, prima di te devono essere allertate %.0f persone. Il tempo di preavviso sarà di %.0f secondi. Iscrivendoti oggi al servizio di priorità TOP 10K, solamente %.0f persone saranno allertate prima di te (in ordine di distanza dall'epicentro)";
"globe_simulation_message2" = "Con epicentro nella posizione scelta, dovresti ricevere l'allerta con %.0f secondi di anticipo. Tuttavia, prima di te devono essere allertate %.0f persone. L'allerta sarà ricevuta con %.0f secondi di ritardo. Iscrivendoti oggi al servizio di priorità TOP 10K, solamente %.0f persone saranno allertate prima di te (in ordine di distanza dall'epicentro)";
"globe_simulation_message3" = "Con epicentro nella posizione scelta, dovresti ricevere l'allerta con %.0f secondi di anticipo. Tuttavia, prima di te devono essere allertate %.0f persone. Iscrivendoti oggi al servizio di priorità TOP 10K, solamente %.0f persone saranno allertate prima di te (in ordine di distanza dall'epicentro)";
"globe_simulation_message4" = "Con epicentro nella posizione scelta, grazie al servizio prioritario %@ dovresti ricevere l'allerta con %.0f secondi di anticipo. Prima di te devono essere allertate solo %.0f persone.";
"globe_simulation_message5" = "Con epicentro nella posizione scelta, grazie al servizio prioritario %@ dovresti ricevere l'allerta con %.0f secondi di anticipo. Prima di te devono essere allertate %.0f persone. Puoi aumentare il tempo di pre-allerta iscrivendoti al servizio di priorità %@";
"globe_simulation_message6" = "Con epicentro nella posizione scelta, grazie al servizio prioritario %@ dovresti ricevere l'allerta con %.0f secondi di anticipo. Sarai il primo ad essere allertato!";
"globe_simulation_priority" = "Servizio priorità";
@@ -23,6 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (NSURL *)urlInvioImpostazioniNotifiche;
+ (NSURL *)urlDownloadOfferTimeRemaining;
+ (NSURL *)urlAlertPushTest;
+ (NSURL *)urlAlertSimulator;
@end
@@ -251,6 +251,16 @@
return [NSURL URLWithString:stringUrl];
}
+ (NSURL *)urlAlertSimulator
{
CLLocationCoordinate2D userLastPosition = [EQNUser defaultUser].lastPosition.coordinate;
CLLocationDistance distance = 100;
NSInteger top10k = EQNPurchaseUtility.isTop10kEnabled ? 1 : 0;
NSInteger top100k = EQNPurchaseUtility.isTop100kEnabled ? 1 : 0;
NSString *stringUrl = [NSString stringWithFormat:@"%@?lat=%f&lon=%f&dis=%f&top10k=%lu&top100k=%lu", EQNServerUrlAlertSimulator, userLastPosition.latitude, userLastPosition.longitude, distance, (long)top10k, (long)top100k];
return [NSURL URLWithString:stringUrl];
}
@end