use geo::point;
use routers_network::mock::{MockEntryId, MockNetwork, MockNetworkBuilder};
use routers_realtime::event::MatchedDiff;
use routers_transition::costing::{CostingStrategies, DefaultEmissionCost, DefaultTransitionCost};
use routers_transition::layer::generation::StandardGenerator;
use routers_transition::weigh::AllCompute;
use routers_transition::{Matcher, Origin};
type Costing = CostingStrategies<DefaultEmissionCost, DefaultTransitionCost, MockEntryId>;
fn bent_road() -> MockNetwork {
MockNetworkBuilder::new()
.node(1, point!(x: -118.15, y: 34.15))
.node(2, point!(x: -118.16, y: 34.15))
.node(3, point!(x: -118.17, y: 34.15))
.node(4, point!(x: -118.17, y: 34.14))
.node(5, point!(x: -118.18, y: 34.14))
.edge(1, 2)
.edge(2, 3)
.edge(3, 4)
.edge(4, 5)
.build()
}
fn observations() -> Vec<Origin> {
[
point!(x: -118.151, y: 34.1503),
point!(x: -118.155, y: 34.1503),
point!(x: -118.165, y: 34.1503),
point!(x: -118.170, y: 34.1490),
point!(x: -118.172, y: 34.1403),
point!(x: -118.179, y: 34.1403),
]
.into_iter()
.enumerate()
.map(|(index, point)| Origin::new(point, 1_775_000_000_000_000 + index as i64 * 5_000_000))
.collect()
}
#[test]
fn diff_lifts_every_layer_with_its_timestamp() {
let net = bent_road();
let costing = Costing::default();
let generator = StandardGenerator::new(&net, &costing.emission);
let m = Matcher::new(&net, &costing, generator, AllCompute::default(), &());
let origins = observations();
let mut trip = m.begin();
for &origin in &origins {
m.push(&mut trip, origin).expect("push must anchor");
}
let solution = m.snapshot(&mut trip).expect("trip must solve");
let diff = MatchedDiff::new(&solution, &origins, &net, 42);
assert_eq!(diff.revision, 42);
assert!(!diff.downgraded);
assert_eq!(
diff.layers.len(),
origins.len(),
"one emitted layer per observation"
);
for (layer, origin) in diff.layers.iter().zip(&origins) {
assert_eq!(
layer.timestamp, origin.timestamp,
"layers are addressed by their observation's timestamp"
);
}
assert!(
diff.layers[0].path.is_empty(),
"the first layer has no inbound hop"
);
assert!(
diff.layers.iter().any(|layer| !layer.path.is_empty()),
"hop geometry must resolve against the network"
);
}
#[test]
fn diff_layers_flatten_into_a_connected_trace() {
let net = bent_road();
let costing = Costing::default();
let generator = StandardGenerator::new(&net, &costing.emission);
let m = Matcher::new(&net, &costing, generator, AllCompute::default(), &());
let origins = observations();
let mut trip = m.begin();
for &origin in &origins {
m.push(&mut trip, origin).expect("push must anchor");
}
let solution = m.snapshot(&mut trip).expect("trip must solve");
let interpolated = solution.interpolated(&net);
let diff = MatchedDiff::new(&solution, &origins, &net, 0);
let rendered: Vec<geo::Point> = diff
.layers
.iter()
.flat_map(|layer| {
layer
.path
.iter()
.copied()
.chain(core::iter::once(layer.position))
})
.collect();
let expected: Vec<geo::Point> = interpolated.into_points();
assert_eq!(
rendered, expected,
"the diff must carry exactly the interpolated geometry"
);
}