use swarmkit_sailing::spherical::haversine;
use swarmkit_sailing::{Boat, Path, get_segment_fuel_and_time, get_segment_land_metres};
use crate::landmass::landmass_grid;
use crate::route::RouteEvolution;
use crate::route_evolution_match;
use crate::wind_map::BakedWindMap;
const SPEED_INTERNAL_TO_KMH: f64 = 3.6;
#[derive(Clone, Copy, Debug)]
pub struct SegmentMetrics {
pub mcr_01: f64,
pub fuel: f64,
pub time: f64,
pub speed_kmh: f64,
pub land_metres: f64,
}
pub fn gbest_segment_metrics(
re: &RouteEvolution,
iter: usize,
boat: &Boat,
baked: &BakedWindMap,
step_distance_max: f64,
) -> Option<Vec<SegmentMetrics>> {
route_evolution_match!(re, |evo| {
let frames = evo.frames();
let iter_idx = iter.min(frames.len().saturating_sub(1));
let particles = frames.get(iter_idx)?;
let best = particles.iter().max_by(|a, b| {
a.best_fit
.partial_cmp(&b.best_fit)
.unwrap_or(std::cmp::Ordering::Equal)
})?;
Some(compute_segment_metrics(
boat,
baked,
best.best_pos,
step_distance_max,
))
})
}
pub fn compute_segment_metrics<const N: usize>(
boat: &Boat,
bwm: &BakedWindMap,
path: Path<N>,
step_distance_max: f64,
) -> Vec<SegmentMetrics> {
let raw = get_segment_fuel_and_time(boat, bwm, path, 0.0, step_distance_max);
let landmass = landmass_grid();
raw.into_iter()
.enumerate()
.map(|(i, (mcr_01, fuel, time))| {
let a = path.lat_lon(i);
let b = path.lat_lon(i + 1);
let distance_m = haversine(a, b);
let speed_kmh = if time > 0.0 {
(distance_m / time) * SPEED_INTERNAL_TO_KMH
} else {
0.0
};
let land_metres = get_segment_land_metres(landmass, a, b, step_distance_max);
SegmentMetrics {
mcr_01,
fuel,
time,
speed_kmh,
land_metres,
}
})
.collect()
}