Skip to content

Commit

Permalink
fixup! editoast: add stdcm v2 endpoint for editoast
Browse files Browse the repository at this point in the history
  • Loading branch information
flomonster committed May 3, 2024
1 parent 28ee9de commit 6e920c3
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 25 deletions.
29 changes: 23 additions & 6 deletions editoast/src/views/v2/path/pathfinding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use crate::views::get_app_version;
use crate::views::v2::path::PathfindingError;
use editoast_schemas::infra::OperationalPoint;

type TrackOffsetResult = std::result::Result<Vec<Vec<TrackOffset>>, PathfindingResult>;
type TrackOffsetResult = std::result::Result<Vec<Vec<TrackOffset>>, TrackOffsetExtractionError>;

crate::routes! {
"/v2/infra/{infra_id}/pathfinding/blocks" => {
Expand Down Expand Up @@ -125,7 +125,7 @@ async fn pathfinding_blocks(
let result = extract_location_from_path_items(conn, infra.id, &path_items).await?;
let track_offsets = match result {
Ok(track_offsets) => track_offsets,
Err(e) => return Ok(e),
Err(e) => return Ok(e.into()),
};

// Check if tracks exist
Expand Down Expand Up @@ -273,6 +273,23 @@ async fn retrieve_op_from_locations(
Ok((uic_to_ops, trigrams_to_ops, ids_to_ops))
}

/// Error when extracting track offsets from path items
pub struct TrackOffsetExtractionError {
/// The index of the path item that caused the error
pub index: usize,
/// The path item that caused the error
pub path_item: PathItemLocation,
}

impl From<TrackOffsetExtractionError> for PathfindingResult {
fn from(error: TrackOffsetExtractionError) -> Self {
PathfindingResult::InvalidPathItem {
index: error.index,
path_item: error.path_item,
}
}
}

/// extract locations from path items
pub async fn extract_location_from_path_items(
conn: &mut DbConnection,
Expand All @@ -297,10 +314,10 @@ pub async fn extract_location_from_path_items(
match ids_to_ops.get(&operational_point.0) {
Some(op) => OperationalPoint::track_offset(op),
None => {
return Ok(Err(PathfindingResult::InvalidPathItem {
return Ok(Err(TrackOffsetExtractionError {
index,
path_item: path_item.clone(),
}))
}));
}
}
}
Expand All @@ -311,7 +328,7 @@ pub async fn extract_location_from_path_items(
let ops = trigrams_to_ops.get(&trigram.0).cloned().unwrap_or_default();
let ops = secondary_code_filter(secondary_code, ops);
if ops.is_empty() {
return Ok(Err(PathfindingResult::InvalidPathItem {
return Ok(Err(TrackOffsetExtractionError {
index,
path_item: path_item.clone(),
}));
Expand All @@ -325,7 +342,7 @@ pub async fn extract_location_from_path_items(
let ops = uic_to_ops.get(&(*uic as i64)).cloned().unwrap_or_default();
let ops = secondary_code_filter(secondary_code, ops);
if ops.is_empty() {
return Ok(Err(PathfindingResult::InvalidPathItem {
return Ok(Err(TrackOffsetExtractionError {
index,
path_item: path_item.clone(),
}));
Expand Down
2 changes: 1 addition & 1 deletion editoast/src/views/v2/timetable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ pub async fn conflicts(
.await?;

// 2. Build core request
let mut trains_requirements = HashMap::new();
let mut trains_requirements = HashMap::with_capacity(trains.len());
for (train, sim) in trains.into_iter().zip(simulations) {
let final_output = match sim {
SimulationResponse::Success { final_output, .. } => final_output,
Expand Down
52 changes: 34 additions & 18 deletions editoast/src/views/v2/timetable/stdcm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use crate::modelsv2::train_schedule::TrainSchedule;
use crate::modelsv2::Infra;
use crate::modelsv2::RollingStockModel;
use crate::views::v2::path::pathfinding::extract_location_from_path_items;
use crate::views::v2::path::pathfinding::TrackOffsetExtractionError;
use crate::views::v2::train_schedule::train_simulation_batch;
use crate::DbConnectionPool;
use crate::RedisClient;
Expand Down Expand Up @@ -56,13 +57,18 @@ enum StdcmError {
TimetableNotFound { timetable_id: i64 },
#[error("Rolling stock {rolling_stock_id} does not exist")]
RollingStockNotFound { rolling_stock_id: i64 },
#[error("Path item {index} is invalid")]
InvalidPathItem {
index: usize,
path_item: PathItemLocation,
},
}

/// An STDCM request
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, ToSchema)]
pub struct STDCMRequestPayload {
start_time: DateTime<Utc>,
steps: Vec<PathfindingStep>,
steps: Vec<PathfindingItem>,
rolling_stock_id: i64,
comfort: Comfort,
/// By how long we can shift the departure time in milliseconds
Expand Down Expand Up @@ -91,11 +97,11 @@ pub struct STDCMRequestPayload {
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, ToSchema)]
pub struct PathfindingStep {
pub struct PathfindingItem {
/// The stop duration in milliseconds, None if the train does not stop.
pub duration: Option<u64>,
/// The list of allowed locations for this step
pub path_items: PathItemLocation,
/// The associated location
pub location: PathItemLocation,
}

const TWO_HOURS_IN_MILLISECONDS: u64 = 2 * 60 * 60 * 60;
Expand Down Expand Up @@ -217,23 +223,33 @@ async fn parse_stdcm_steps(
data: &STDCMRequestPayload,
infra: &Infra,
) -> Result<Vec<STDCMPathItem>> {
let steps = data.steps.clone();
let path_items: Vec<_> = steps
.iter()
.map(|steps| steps.path_locations.clone())
.collect();
let path_items = data.steps.clone();
let mut locations = Vec::with_capacity(path_items.len());
let mut durations = Vec::with_capacity(path_items.len());
for item in path_items {
locations.push(item.location);
durations.push(item.duration);
}

let conn = &mut db_pool.get().await?;
let track_offsets = extract_location_from_path_items(conn, infra.id, &path_items).await?;
let track_offsets = extract_location_from_path_items(conn, infra.id, &locations).await?;
let track_offsets = track_offsets.map_err::<StdcmError, _>(|err| err.into())?;

Ok(track_offsets
.unwrap()
.iter()
.zip(steps.iter())
.map(
|(track_offset, PathfindingStep { duration, .. })| STDCMPathItem {
stop_duration: *duration,
locations: track_offset.to_vec(),
},
)
.zip(durations)
.map(|(track_offset, duration)| STDCMPathItem {
stop_duration: duration,
locations: track_offset.to_vec(),
})
.collect())
}

impl From<TrackOffsetExtractionError> for StdcmError {
fn from(error: TrackOffsetExtractionError) -> Self {
StdcmError::InvalidPathItem {
index: error.index,
path_item: error.path_item,
}
}
}

0 comments on commit 6e920c3

Please sign in to comment.