use super::SimpleTimetable;
type Tt = SimpleTimetable<usize, usize, usize>;
pub fn build_linear(stops: usize, trips: usize) -> Tt {
let stop_ids: Vec<usize> = (0..stops).collect();
let trip_defs: Vec<(usize, Vec<(crate::SecondOfDay, crate::SecondOfDay)>)> = (0..trips)
.map(|t| {
let times: Vec<(crate::SecondOfDay, crate::SecondOfDay)> = (0..stops)
.map(|s| {
let base = t * stops * 2;
(
crate::SecondOfDay((base + s * 2) as u32),
crate::SecondOfDay((base + s * 2 + 1) as u32),
)
})
.collect();
(t, times)
})
.collect();
let mut tt = SimpleTimetable::new();
let trip_refs: Vec<(usize, &[(crate::SecondOfDay, crate::SecondOfDay)])> = trip_defs
.iter()
.map(|(id, times)| (*id, times.as_slice()))
.collect();
tt = tt.route(0, &stop_ids, &trip_refs);
tt
}
pub fn build_grid(routes: usize, stops_per_route: usize, connectors: usize) -> Tt {
let mut tt = SimpleTimetable::new();
let mut route_id = 0usize;
let mut trip_id = 0usize;
for r in 0..routes {
let stop_ids: Vec<usize> = (0..stops_per_route)
.map(|s| r * stops_per_route + s)
.collect();
let times: Vec<(crate::SecondOfDay, crate::SecondOfDay)> = (0..stops_per_route)
.map(|s| {
(
crate::SecondOfDay((s * 10) as u32),
crate::SecondOfDay((s * 10 + 5) as u32),
)
})
.collect();
tt = tt.route(route_id, &stop_ids, &[(trip_id, times.as_slice())]);
route_id += 1;
trip_id += 1;
}
let connector_step = stops_per_route.max(1) / connectors.max(1);
for c in 0..connectors {
let col = c * connector_step;
let stop_ids: Vec<usize> = (0..routes).map(|r| r * stops_per_route + col).collect();
let times: Vec<(crate::SecondOfDay, crate::SecondOfDay)> = (0..routes)
.map(|r| {
let base = col * 10 + r * 3;
(
crate::SecondOfDay((base) as u32),
crate::SecondOfDay((base + 1) as u32),
)
})
.collect();
tt = tt.route(route_id, &stop_ids, &[(trip_id, times.as_slice())]);
route_id += 1;
trip_id += 1;
}
tt
}
pub fn build_hub_spoke(hubs: usize, routes_per_hub: usize, spokes: usize) -> Tt {
let mut tt = SimpleTimetable::new();
let mut route_id = 0usize;
let mut trip_id = 0usize;
let mut stop_id = 0usize;
let hub_stops: Vec<usize> = (0..hubs)
.map(|_| {
let s = stop_id;
stop_id += 1;
s
})
.collect();
for (h, &hub) in hub_stops.iter().enumerate() {
for r in 0..routes_per_hub {
let mut stops = vec![hub];
for _ in 0..spokes {
stops.push(stop_id);
stop_id += 1;
}
let times: Vec<(crate::SecondOfDay, crate::SecondOfDay)> = stops
.iter()
.enumerate()
.map(|(i, _)| {
let base = (h * routes_per_hub + r) * (spokes + 1) * 10;
(
crate::SecondOfDay((base + i * 10) as u32),
crate::SecondOfDay((base + i * 10 + 5) as u32),
)
})
.collect();
tt = tt.route(route_id, &stops, &[(trip_id, times.as_slice())]);
route_id += 1;
trip_id += 1;
}
}
for i in 0..hubs {
for j in 0..hubs {
if i != j {
tt = tt.footpath(hub_stops[i], hub_stops[j]);
tt = tt.transfer_time(hub_stops[i], hub_stops[j], crate::Duration(2));
}
}
}
tt
}
pub fn build_chain(segments: usize) -> Tt {
let mut tt = SimpleTimetable::new();
for seg in 0..segments {
let from = seg;
let to = seg + 1;
let base_time = seg * 20;
tt = tt.route(
seg,
&[from, to],
&[(
seg,
&[
(
crate::SecondOfDay(base_time as u32),
crate::SecondOfDay((base_time + 5) as u32),
),
(
crate::SecondOfDay((base_time + 10) as u32),
crate::SecondOfDay((base_time + 15) as u32),
),
],
)],
);
}
tt
}
pub fn build_parallel_paths(path_count: usize, max_legs: usize) -> Tt {
let mut tt = SimpleTimetable::new();
let mut route_id = 0usize;
let mut trip_id = 0usize;
let mut next_stop = 2usize;
let source = 0usize;
let target = 1usize;
for p in 0..path_count {
let legs = ((p % max_legs) + 1).min(max_legs);
let total_time = 1000 - p * 50;
let leg_time = total_time / legs;
let mut prev_stop = source;
for leg in 0..legs {
let is_last = leg == legs - 1;
let curr_stop = if is_last { target } else { next_stop };
if !is_last {
next_stop += 1;
}
let depart = leg * leg_time;
let arrive = depart + leg_time - 5;
tt = tt.route(
route_id,
&[prev_stop, curr_stop],
&[(
trip_id,
&[
(
crate::SecondOfDay(depart as u32),
crate::SecondOfDay((depart + 1) as u32),
),
(
crate::SecondOfDay(arrive as u32),
crate::SecondOfDay((arrive + 1) as u32),
),
],
)],
);
route_id += 1;
trip_id += 1;
prev_stop = curr_stop;
}
}
tt
}