Spaces:
Sleeping
Sleeping
File size: 3,822 Bytes
03e3b1b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | use super::*;
use crate::data::data_seed::types::LocationData;
use solverforge_maps::{BoundingBox, Coord, NetworkConfig, RoadNetwork};
#[test]
fn parses_demo_data_ids_case_insensitively() {
assert!(matches!(
"philadelphia".parse::<DemoData>(),
Ok(DemoData::Philadelphia)
));
assert!(matches!(
"HARTFORD".parse::<DemoData>(),
Ok(DemoData::Hartford)
));
}
#[test]
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()
}
#[test]
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);
}
#[test]
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}"
);
}
}
#[tokio::test]
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:?}"
);
}
}
|