Skip to main content

lightning_distance/
lib.rs

1//! # lightning-distance
2//!
3//! Estimate how far away a lightning strike is from the delay between the flash and
4//! the thunder, and apply the standard 30-second safety rule.
5//!
6//! Sound takes roughly 5 seconds to travel one mile (3 seconds per kilometer).
7//!
8//! ```
9//! use lightning_distance::{miles, is_dangerous};
10//! assert!((miles(10.0) - 2.0).abs() < 1e-9);  // 10 s ~ 2 miles
11//! assert_eq!(is_dangerous(10.0), true);        // <= 30 s is dangerous
12//! ```
13
14/// Seconds for sound to travel one statute mile (~5.0).
15pub const SECS_PER_MILE: f64 = 5.0;
16/// Seconds for sound to travel one kilometer (~3.0).
17pub const SECS_PER_KM: f64 = 3.0;
18/// The standard "go inside" threshold (seconds).
19pub const DANGER_THRESHOLD_SECS: f64 = 30.0;
20
21/// Distance in miles from the flash-to-thunder delay in seconds.
22pub fn miles(seconds: f64) -> f64 { seconds / SECS_PER_MILE }
23
24/// Distance in kilometers from the delay in seconds.
25pub fn kilometers(seconds: f64) -> f64 { seconds / SECS_PER_KM }
26
27/// The 30-second rule: if the gap is <= 30 s the storm is close enough to be dangerous.
28pub fn is_dangerous(seconds: f64) -> bool { seconds <= DANGER_THRESHOLD_SECS }
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33    #[test]
34    fn ten_seconds_is_two_miles() { assert!((miles(10.0) - 2.0).abs() < 1e-9); }
35    #[test]
36    fn km_matches_mile_conversion() {
37        // 1 mile = 1.609 km; 5 s/mile vs 3 s/km -> consistent within rounding
38        let m = miles(15.0); let km = kilometers(15.0);
39        assert!((km / m - 1.667).abs() < 0.01);
40    }
41    #[test]
42    fn danger_rule() {
43        assert!(is_dangerous(30.0));
44        assert!(is_dangerous(5.0));
45        assert!(!is_dangerous(45.0));
46    }
47}