1pub fn distance(lat1: f64, lon1: f64, lat2: f64, lon2: f64) -> f64 {
9 let radius = 6371.0; let dlat = (lat2 - lat1).to_radians();
12 let dlon = (lon2 - lon1).to_radians();
13
14 let a = (dlat / 2.0).sin().powi(2)
15 + lat1.to_radians().cos() * lat2.to_radians().cos() * (dlon / 2.0).sin().powi(2);
16
17 let c = 2.0 * a.sqrt().atan2((1.0 - a).sqrt());
18
19 radius * c
20}
21
22pub fn build_user_agent() -> String {
24 format!(
25 "Mozilla/5.0 ({} {}) speedtest/1.0.0",
26 std::env::consts::OS,
27 std::env::consts::ARCH
28 )
29}
30
31pub fn cache_buster() -> String {
33 use std::time::{SystemTime, UNIX_EPOCH};
34 let timestamp = SystemTime::now()
35 .duration_since(UNIX_EPOCH)
36 .unwrap()
37 .as_millis();
38 format!("{}", timestamp)
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn test_distance() {
47 let d = distance(40.7128, -74.0060, 51.5074, -0.1278);
49 assert!((d - 5570.0).abs() < 50.0);
51 }
52
53 #[test]
54 fn test_user_agent() {
55 let ua = build_user_agent();
56 assert!(ua.contains("Mozilla/5.0"));
57 assert!(ua.contains("speedtest"));
58 }
59
60 #[test]
61 fn test_cache_buster() {
62 let cb1 = cache_buster();
63 std::thread::sleep(std::time::Duration::from_millis(10));
64 let cb2 = cache_buster();
65 assert_ne!(cb1, cb2);
66 }
67}