Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

editoast: refactoring STDCM handler #9509

Merged
merged 1 commit into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
342 changes: 167 additions & 175 deletions editoast/openapi.yaml

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions editoast/src/core/conflict_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,31 @@ pub struct WorkSchedulesRequest {
pub start_time: DateTime<Utc>,
pub work_schedule_requirements: HashMap<i64, WorkSchedule>,
}
impl WorkSchedulesRequest {
pub fn new(
work_schedules: Vec<crate::models::work_schedules::WorkSchedule>,
earliest_departure_time: DateTime<Utc>,
latest_simulation_end: DateTime<Utc>,
) -> Option<Self> {
if work_schedules.is_empty() {
return None;
}
// Filter the provided work schedules to find those that conflict with the given parameters
// This identifies any work schedules that may overlap with the earliest departure time and latest simulation end.
let work_schedule_requirements = work_schedules
.into_iter()
.filter_map(|ws| {
ws.as_core_work_schedule(earliest_departure_time, latest_simulation_end)
.map(|core_ws| (ws.id, core_ws))
})
.collect();

Some(Self {
start_time: earliest_departure_time,
work_schedule_requirements,
})
}
}

#[derive(Debug, Deserialize, ToSchema)]
pub struct ConflictDetectionResponse {
Expand Down
19 changes: 17 additions & 2 deletions editoast/src/core/simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ pub struct PhysicsConsist {
/// Mapping of power restriction code to power class
#[serde(default)]
pub power_restrictions: BTreeMap<String, String>,
/// The time the train takes before actually using electrical power (in miliseconds).
/// The time the train takes before actually using electrical power (in milliseconds).
/// Is null if the train is not electric or the value not specified.
pub electrical_power_startup_time: Option<u64>,
/// The time it takes to raise this train's pantograph in miliseconds.
/// The time it takes to raise this train's pantograph in milliseconds.
/// Is null if the train is not electric or the value not specified.
pub raise_pantograph_time: Option<u64>,
}
Expand Down Expand Up @@ -476,6 +476,21 @@ impl AsCoreRequest<Json<SimulationResponse>> for SimulationRequest {
}
}

impl SimulationResponse {
pub fn simulation_run_time(&self) -> Option<u64> {
if let SimulationResponse::Success { provisional, .. } = self {
Some(
*provisional
.times
.last()
.expect("core error: empty simulation result"),
)
} else {
None
}
}
}

#[cfg(test)]
mod tests {
use editoast_schemas::rolling_stock::RollingResistance;
Expand Down
15 changes: 5 additions & 10 deletions editoast/src/core/stdcm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@ use serde::Deserialize;
use serde::Serialize;
use utoipa::ToSchema;

use super::conflict_detection::Conflict;
use super::conflict_detection::TrainRequirements;
use super::pathfinding::PathfindingResultSuccess;
use super::pathfinding::TrackRange;
use super::simulation::PhysicsConsist;
use super::simulation::SimulationResponse;
use crate::core::{AsCoreRequest, Json};
use crate::views::path::pathfinding::PathfindingResult;
use crate::core::AsCoreRequest;
use crate::core::Json;

#[derive(Debug, Serialize)]
pub struct STDCMRequest {
Expand Down Expand Up @@ -115,28 +114,24 @@ pub struct UndirectedTrackRange {
pub end: u64,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, ToSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(tag = "status", rename_all = "snake_case")]
// We accepted the difference of memory size taken by variants
// Since there is only on success and others are error cases
#[allow(clippy::large_enum_variant)]
pub enum STDCMResponse {
pub enum Response {
Success {
simulation: SimulationResponse,
path: PathfindingResultSuccess,
departure_time: DateTime<Utc>,
},
PathNotFound,
Conflicts {
pathfinding_result: PathfindingResult,
conflicts: Vec<Conflict>,
},
leovalais marked this conversation as resolved.
Show resolved Hide resolved
PreprocessingSimulationError {
error: SimulationResponse,
},
}

impl AsCoreRequest<Json<STDCMResponse>> for STDCMRequest {
impl AsCoreRequest<Json<Response>> for STDCMRequest {
const METHOD: reqwest::Method = reqwest::Method::POST;
const URL_PATH: &'static str = "/v2/stdcm";

Expand Down
40 changes: 40 additions & 0 deletions editoast/src/models/work_schedules.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::cmp::max;

use chrono::DateTime;
use chrono::Utc;
use editoast_derive::Model;
Expand All @@ -8,6 +10,8 @@ use serde::Deserialize;
use serde::Serialize;
use utoipa::ToSchema;

use crate::core::stdcm::UndirectedTrackRange;

#[derive(Debug, Clone, Model)]
#[model(table = editoast_models::tables::work_schedule_group)]
#[model(gen(ops = crd, batch_ops = c, list))]
Expand Down Expand Up @@ -39,3 +43,39 @@ pub struct WorkSchedule {
pub work_schedule_type: WorkScheduleType,
pub work_schedule_group_id: i64,
}

impl WorkSchedule {
pub fn as_core_work_schedule(
&self,
earliest_departure_time: DateTime<Utc>,
latest_simulation_end: DateTime<Utc>,
) -> Option<crate::core::stdcm::WorkSchedule> {
let search_window_duration =
(latest_simulation_end - earliest_departure_time).num_milliseconds() as u64;

let start_time = elapsed_time_since_ms(&self.start_date_time, &earliest_departure_time);
let end_time = elapsed_time_since_ms(&self.end_date_time, &earliest_departure_time);

if end_time == 0 || start_time >= search_window_duration {
return None;
}

Some(crate::core::stdcm::WorkSchedule {
start_time,
end_time,
track_ranges: self
.track_ranges
.iter()
.map(|track| UndirectedTrackRange {
track_section: track.track.to_string(),
begin: (track.begin * 1000.0) as u64,
end: (track.end * 1000.0) as u64,
})
.collect(),
})
}
}

fn elapsed_time_since_ms(time: &DateTime<Utc>, since: &DateTime<Utc>) -> u64 {
max(0, (*time - since).num_milliseconds()) as u64
}
Loading
Loading