Spaces:
Sleeping
Sleeping
| use super::*; | |
| use crate::data::data_seed::types::LocationData; | |
| use solverforge_maps::{BoundingBox, Coord, NetworkConfig, RoadNetwork}; | |
| fn parses_demo_data_ids_case_insensitively() { | |
| assert!(matches!( | |
| "philadelphia".parse::<DemoData>(), | |
| Ok(DemoData::Philadelphia) | |
| )); | |
| assert!(matches!( | |
| "HARTFORD".parse::<DemoData>(), | |
| Ok(DemoData::Hartford) | |
| )); | |
| } | |
| fn generates_city_demo_plan() { | |
| for (demo, expected_stops, expected_name) in [ | |
| ( | |
| DemoData::Philadelphia, | |
| visit_count(philadelphia::VISIT_GROUPS), | |
| "Philadelphia", | |
| ), | |
| ( | |
| DemoData::Hartford, | |
| visit_count(hartford::VISIT_GROUPS), | |
| "Hartford", | |
| ), | |
| ( | |
| DemoData::Firenze, | |
| visit_count(firenze::VISIT_GROUPS), | |
| "Firenze", | |
| ), | |
| ] { | |
| let plan = generate(demo); | |
| assert_eq!(plan.name, expected_name); | |
| assert_eq!(plan.vehicles.len(), 10); | |
| assert_eq!(plan.deliveries.len(), expected_stops); | |
| assert!(plan | |
| .vehicles | |
| .iter() | |
| .all(|vehicle| vehicle.delivery_order.is_empty())); | |
| } | |
| } | |
| fn visit_count(groups: &[&[LocationData]]) -> usize { | |
| groups.iter().map(|group| group.len()).sum() | |
| } | |
| fn demo_delivery_counts_scale_with_ten_vehicles() { | |
| assert_eq!(generate(DemoData::Philadelphia).deliveries.len(), 82); | |
| assert_eq!(generate(DemoData::Hartford).deliveries.len(), 50); | |
| assert_eq!(generate(DemoData::Firenze).deliveries.len(), 80); | |
| } | |
| fn demo_plans_have_enough_vehicle_capacity() { | |
| for demo in [ | |
| DemoData::Philadelphia, | |
| DemoData::Hartford, | |
| DemoData::Firenze, | |
| ] { | |
| let plan = generate(demo); | |
| let total_capacity: i32 = plan.vehicles.iter().map(|vehicle| vehicle.capacity).sum(); | |
| let total_demand: i32 = plan.deliveries.iter().map(|delivery| delivery.demand).sum(); | |
| assert!( | |
| total_capacity >= total_demand, | |
| "{demo:?} demo should be capacity-feasible before route ordering: capacity={total_capacity}, demand={total_demand}" | |
| ); | |
| } | |
| } | |
| async fn live_demo_locations_are_mutually_reachable_when_enabled() { | |
| if std::env::var("SOLVERFORGE_RUN_LIVE_TESTS").ok().as_deref() != Some("1") { | |
| return; | |
| } | |
| for demo in [ | |
| DemoData::Philadelphia, | |
| DemoData::Hartford, | |
| DemoData::Firenze, | |
| ] { | |
| let plan = generate(demo); | |
| let mut named_coords = Vec::new(); | |
| for delivery in &plan.deliveries { | |
| named_coords.push(( | |
| format!("delivery {}", delivery.label), | |
| delivery.coord().unwrap(), | |
| )); | |
| } | |
| for vehicle in &plan.vehicles { | |
| named_coords.push(( | |
| format!("depot {}", vehicle.name), | |
| vehicle.depot_coord().unwrap(), | |
| )); | |
| } | |
| let coords: Vec<Coord> = named_coords.iter().map(|(_, coord)| *coord).collect(); | |
| let bbox = BoundingBox::from_coords(&coords).expand_for_routing(&coords); | |
| let network = RoadNetwork::load_or_fetch(&bbox, &NetworkConfig::default(), None) | |
| .await | |
| .unwrap(); | |
| let matrix = network.compute_matrix(&coords, None).await; | |
| let unreachable = matrix | |
| .unreachable_pairs() | |
| .into_iter() | |
| .map(|(from_idx, to_idx)| { | |
| let from_name = &named_coords[from_idx].0; | |
| let to_name = &named_coords[to_idx].0; | |
| format!("{from_name} -> {to_name}") | |
| }) | |
| .collect::<Vec<_>>(); | |
| assert!( | |
| unreachable.is_empty(), | |
| "{demo:?} has unreachable directed routes: {unreachable:?}" | |
| ); | |
| } | |
| } | |