#[derive(Debug, Clone, PartialEq)]
pub struct TravelAssessment {
pub distance_km: f64,
pub mode: String,
pub needed_days: f64,
pub claimed_days: f64,
pub plausible: bool,
}
pub fn speed_km_per_day(mode: &str) -> f64 {
match mode {
"ship" | "sail" | "sea" => 120.0,
"horse" | "ride" | "mounted" => 55.0,
"cart" | "wagon" => 25.0,
_ => 30.0, }
}
pub fn assess(distance_km: f64, claimed_days: f64, mode: &str) -> TravelAssessment {
let needed = distance_km / speed_km_per_day(mode).max(1.0);
let plausible = claimed_days >= needed * 0.85;
TravelAssessment {
distance_km,
mode: mode.to_string(),
needed_days: needed,
claimed_days,
plausible,
}
}
pub fn km_per_cell(radius_earth: f64, grid_width: usize) -> f64 {
const EARTH_RADIUS_KM: f64 = 6371.0;
let circumference = 2.0 * std::f64::consts::PI * radius_earth.max(0.01) * EARTH_RADIUS_KM;
circumference / (grid_width.max(1) as f64)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_day_on_foot_across_a_hundred_km_is_implausible() {
let a = assess(100.0, 1.0, "foot");
assert!(!a.plausible);
assert!(a.needed_days > 3.0);
assert!(assess(100.0, 4.0, "foot").plausible);
}
#[test]
fn ships_are_faster_than_marching() {
assert!(speed_km_per_day("ship") > speed_km_per_day("foot"));
assert!(assess(300.0, 3.0, "ship").plausible);
assert!(!assess(300.0, 3.0, "foot").plausible);
}
#[test]
fn km_per_cell_scales_with_planet_and_grid() {
let k = km_per_cell(1.0, 360);
assert!((k - 111.2).abs() < 2.0, "got {k}");
assert!(km_per_cell(2.0, 360) > k);
}
}