Skip to content

Commit c321c20

Browse files
Khoyoeckter
authored andcommitted
editoast: adapt to the new stdcm endpoint
1 parent 707d6fa commit c321c20

File tree

4 files changed

+69
-90
lines changed

4 files changed

+69
-90
lines changed

editoast/src/core/stdcm.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use serde::{Deserialize, Serialize};
22

3-
use crate::models::RollingStockModel;
3+
use crate::models::{RollingStockModel, SpacingRequirement};
44

55
use crate::core::{pathfinding::Waypoint, simulation::SimulationResponse};
66
use crate::schema::rolling_stock::RollingStockComfortType;
@@ -15,7 +15,7 @@ pub struct STDCMCoreRequest {
1515
pub expected_version: String,
1616
pub rolling_stock: RollingStockModel,
1717
pub comfort: RollingStockComfortType,
18-
pub route_occupancies: Vec<STDCMCoreRouteOccupancy>,
18+
pub spacing_requirements: Vec<SpacingRequirement>,
1919
pub steps: Vec<STDCMCoreStep>,
2020
#[serde(skip_serializing_if = "Option::is_none")]
2121
pub start_time: Option<f64>,
@@ -43,13 +43,6 @@ pub struct STDCMCoreStep {
4343
pub waypoints: Vec<Waypoint>,
4444
}
4545

46-
#[derive(Serialize, Deserialize, Debug)]
47-
pub struct STDCMCoreRouteOccupancy {
48-
pub id: String,
49-
pub start_occupancy_time: f64,
50-
pub end_occupancy_time: f64,
51-
}
52-
5346
#[derive(Serialize, Deserialize, Debug)]
5447
pub struct STDCMCoreResponse {
5548
pub simulation: SimulationResponse,

editoast/src/models/train_schedule.rs

-1
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,6 @@ pub struct ResultTrain {
265265
pub speeds: Vec<ResultSpeed>,
266266
pub head_positions: Vec<ResultPosition>,
267267
pub stops: Vec<ResultStops>,
268-
pub route_occupancies: HashMap<String, ResultOccupancyTiming>,
269268
pub mechanical_energy_consumed: f64,
270269
pub signal_sightings: Vec<SignalSighting>,
271270
pub zone_updates: Vec<ZoneUpdate>,

editoast/src/views/stdcm/mod.rs

+31-48
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
use crate::core::stdcm::{
2-
STDCMCoreRequest, STDCMCoreResponse, STDCMCoreRouteOccupancy, STDCMCoreStep,
3-
};
1+
use crate::core::stdcm::{STDCMCoreRequest, STDCMCoreResponse, STDCMCoreStep};
42
use crate::core::{AsCoreRequest, CoreClient};
5-
use crate::diesel::BelongingToDsl;
3+
64
use crate::error::Result;
7-
use crate::models::train_schedule::filter_invalid_trains;
85
pub use crate::models::train_schedule::AllowanceValue;
9-
use crate::models::{Create, SimulationOutput};
6+
use crate::models::{Create, SpacingRequirement};
107
use crate::models::{
118
CurveGraph, Infra, PathWaypoint, Pathfinding, PathfindingChangeset, PathfindingPayload,
129
Retrieve, SlopeGraph, TrainSchedule,
@@ -16,14 +13,15 @@ use crate::DbPool;
1613
use actix_web::dev::HttpServiceFactory;
1714
use actix_web::web::{self, Data, Json};
1815
use actix_web::{post, HttpResponse, Responder};
19-
use diesel_async::RunQueryDsl;
16+
2017
use editoast_derive::EditoastError;
2118
use serde::{Deserialize, Serialize};
2219
use thiserror::Error;
2320

2421
use super::pathfinding::{
2522
fetch_pathfinding_payload_track_map, parse_pathfinding_payload_waypoints, StepPayload,
2623
};
24+
use super::timetable::get_simulated_schedules_from_timetable;
2725
use super::train_schedule::process_simulation_response;
2826
use super::train_schedule::projection::Projection;
2927
use super::train_schedule::simulation_report::{create_simulation_report, SimulationReport};
@@ -153,15 +151,14 @@ async fn call_core_stdcm(
153151
let infra_version = infra.clone().version.unwrap();
154152
let rolling_stock = retrieve_existing_rolling_stock(&db_pool, data.rolling_stock_id).await?;
155153
let steps = parse_stdcm_steps(db_pool.clone(), data, &infra).await?;
156-
let route_occupancies =
157-
make_route_occupancies(infra_version.clone(), db_pool, data.timetable_id).await?;
154+
let spacing_requirements = make_spacing_requirements(db_pool, data.timetable_id).await?;
158155
STDCMCoreRequest {
159156
infra: infra.id.unwrap().to_string(),
160157
expected_version: infra_version,
161158
rolling_stock,
162159
comfort: data.comfort.clone(),
163160
steps,
164-
route_occupancies,
161+
spacing_requirements,
165162
// end_time is not used by backend currently
166163
// but at least one must be defined
167164
start_time: data.start_time,
@@ -207,47 +204,33 @@ async fn parse_stdcm_steps(
207204

208205
/// Create route occupancies, adjusted by simulation departure time.
209206
/// uses base_simulation by default, or eco_simulation if given
210-
async fn make_route_occupancies(
211-
infra_version: String,
207+
async fn make_spacing_requirements(
212208
db_pool: Data<DbPool>,
213209
timetable_id: i64,
214-
) -> Result<Vec<STDCMCoreRouteOccupancy>> {
215-
let schedules = filter_invalid_trains(db_pool.clone(), timetable_id, infra_version).await?;
216-
let mut conn = db_pool.get().await?;
217-
let (simulations, schedules): (Vec<SimulationOutput>, Vec<TrainSchedule>) = (
218-
SimulationOutput::belonging_to(&schedules)
219-
.load::<SimulationOutput>(&mut conn)
220-
.await?,
221-
schedules,
222-
);
223-
Ok(simulations
224-
.iter()
225-
.filter_map(|simulation| {
226-
if let Some(schedule) = schedules
227-
.iter()
228-
.find(|s| s.id == simulation.train_schedule_id)
229-
{
230-
let sim = simulation
231-
.eco_simulation
232-
.as_ref()
233-
.unwrap_or(&simulation.base_simulation);
234-
Some(
235-
sim.route_occupancies
236-
.iter()
237-
.map(|(route_id, occupancy)| STDCMCoreRouteOccupancy {
238-
id: route_id.to_string(),
239-
start_occupancy_time: occupancy.time_head_occupy
240-
+ schedule.departure_time,
241-
end_occupancy_time: occupancy.time_tail_free + schedule.departure_time,
242-
})
243-
.collect::<Vec<_>>(),
244-
)
245-
} else {
246-
None
247-
}
210+
) -> Result<Vec<SpacingRequirement>> {
211+
let (schedules, simulations) =
212+
get_simulated_schedules_from_timetable(timetable_id, db_pool).await?;
213+
214+
let res = simulations
215+
.into_iter()
216+
.zip(schedules)
217+
.flat_map(|(simulation, schedule)| {
218+
let sim = simulation
219+
.eco_simulation
220+
.map(|sim| sim.0)
221+
.unwrap_or(simulation.base_simulation.0);
222+
223+
sim.spacing_requirements
224+
.into_iter()
225+
.map(|req| SpacingRequirement {
226+
zone: req.zone,
227+
begin_time: req.begin_time + schedule.departure_time,
228+
end_time: req.end_time + schedule.departure_time,
229+
})
230+
.collect::<Vec<_>>()
248231
})
249-
.flatten()
250-
.collect())
232+
.collect();
233+
Ok(res)
251234
}
252235

253236
/// Creates a Pathfinding using the same function used with core /pathfinding response

editoast/src/views/timetable.rs

+36-32
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,40 @@ struct Conflict {
9595
conflict_type: ConflictType,
9696
}
9797

98+
pub async fn get_simulated_schedules_from_timetable(
99+
timetable_id: i64,
100+
db_pool: Data<DbPool>,
101+
) -> Result<(Vec<TrainSchedule>, Vec<SimulationOutput>)> {
102+
let mut conn = db_pool.get().await?;
103+
use crate::tables::train_schedule;
104+
use diesel::{BelongingToDsl, ExpressionMethods, GroupedBy, QueryDsl};
105+
use diesel_async::RunQueryDsl;
106+
107+
let train_schedules = train_schedule::table
108+
.filter(train_schedule::timetable_id.eq(timetable_id))
109+
.load::<TrainSchedule>(&mut conn)
110+
.await?;
111+
112+
SimulationOutput::belonging_to(&train_schedules)
113+
.load::<SimulationOutput>(&mut conn)
114+
.await?
115+
.grouped_by(&train_schedules)
116+
.into_iter()
117+
.zip(train_schedules)
118+
.map(|(mut sim_output, train_schedule)| {
119+
if sim_output.is_empty() {
120+
return Err(TrainScheduleError::UnsimulatedTrainSchedule {
121+
train_schedule_id: train_schedule.id.expect("TrainSchedule should have an id"),
122+
}
123+
.into());
124+
}
125+
assert!(sim_output.len() == 1);
126+
Ok((train_schedule, sim_output.remove(0)))
127+
})
128+
.collect::<Result<Vec<(TrainSchedule, SimulationOutput)>>>()
129+
.map(|v| v.into_iter().unzip())
130+
}
131+
98132
/// Compute spacing conflicts for a given timetable
99133
/// TODO: This should compute itinary conflicts too
100134
#[utoipa::path(
@@ -114,38 +148,8 @@ async fn get_conflicts(
114148
) -> Result<Json<Vec<Conflict>>> {
115149
let timetable_id = timetable_id.into_inner();
116150

117-
let (schedules, simulations): (Vec<TrainSchedule>, Vec<SimulationOutput>) = {
118-
let mut conn = db_pool.get().await?;
119-
use crate::tables::train_schedule;
120-
use diesel::{BelongingToDsl, ExpressionMethods, GroupedBy, QueryDsl};
121-
use diesel_async::RunQueryDsl;
122-
123-
let train_schedules = train_schedule::table
124-
.filter(train_schedule::timetable_id.eq(timetable_id))
125-
.load::<TrainSchedule>(&mut conn)
126-
.await?;
127-
128-
SimulationOutput::belonging_to(&train_schedules)
129-
.load::<SimulationOutput>(&mut conn)
130-
.await?
131-
.grouped_by(&train_schedules)
132-
.into_iter()
133-
.zip(train_schedules)
134-
.map(|(mut sim_output, train_schedule)| {
135-
if sim_output.is_empty() {
136-
return Err(TrainScheduleError::UnsimulatedTrainSchedule {
137-
train_schedule_id: train_schedule
138-
.id
139-
.expect("TrainSchedule should have an id"),
140-
}
141-
.into());
142-
}
143-
assert!(sim_output.len() == 1);
144-
Ok((train_schedule, sim_output.remove(0)))
145-
})
146-
.collect::<Result<Vec<(TrainSchedule, SimulationOutput)>>>()
147-
.map(|v| v.into_iter().unzip())
148-
}?;
151+
let (schedules, simulations) =
152+
get_simulated_schedules_from_timetable(timetable_id, db_pool).await?;
149153

150154
let mut id_to_name = HashMap::new();
151155
let mut trains_requirements = Vec::new();

0 commit comments

Comments
 (0)