-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathpath_not_found_handler.rs
118 lines (102 loc) · 4.3 KB
/
path_not_found_handler.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use std::sync::Arc;
use chrono::DateTime;
use chrono::Utc;
use crate::core::conflict_detection::ConflictDetectionRequest;
use crate::core::conflict_detection::WorkSchedulesRequest;
use crate::core::simulation::SimulationResponse;
use crate::core::AsCoreRequest;
use crate::core::CoreClient;
use crate::error::Result;
use crate::models::train_schedule::TrainSchedule;
use crate::models::work_schedules::WorkSchedule;
use crate::views::path::pathfinding::PathfindingResult;
use crate::views::timetable::stdcm::STDCMResponse;
use super::stdcm::build_train_requirements;
pub struct PathNotFoundHandler {
pub core_client: Arc<CoreClient>,
pub infra_id: i64,
pub infra_version: String,
pub train_schedules: Vec<TrainSchedule>,
pub simulations: Vec<(SimulationResponse, PathfindingResult)>,
pub work_schedules: Vec<WorkSchedule>,
pub virtual_train_schedule: TrainSchedule,
pub virtual_train_sim_result: SimulationResponse,
pub virtual_train_pathfinding_result: PathfindingResult,
pub earliest_departure_time: DateTime<Utc>,
pub latest_simulation_end: DateTime<Utc>,
}
impl PathNotFoundHandler {
pub async fn handle(self) -> Result<STDCMResponse> {
let virtual_train_id = self.virtual_train_schedule.id;
// Combine the original train schedules with the virtual train schedule.
let train_schedules = [self.train_schedules, vec![self.virtual_train_schedule]].concat();
// Combine the original simulations with the virtual train's simulation results.
let simulations = [
self.simulations,
vec![(
self.virtual_train_sim_result,
self.virtual_train_pathfinding_result.clone(),
)],
]
.concat();
// Build train requirements based on the combined train schedules and simulations
// This prepares the data structure required for conflict detection.
let trains_requirements = build_train_requirements(
train_schedules,
simulations,
self.earliest_departure_time,
self.latest_simulation_end,
);
// 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 maximum run time.
let conflict_work_schedules = make_work_schedules_request(
&self.work_schedules,
self.earliest_departure_time,
self.latest_simulation_end,
);
// Prepare the conflict detection request.
let conflict_detection_request = ConflictDetectionRequest {
infra: self.infra_id,
expected_version: self.infra_version,
trains_requirements,
work_schedules: conflict_work_schedules,
};
// Send the conflict detection request and await the response.
let conflict_detection_response =
conflict_detection_request.fetch(&self.core_client).await?;
// Filter the conflicts to find those specifically related to the virtual train.
let conflicts: Vec<_> = conflict_detection_response
.conflicts
.into_iter()
.filter(|conflict| conflict.train_ids.contains(&virtual_train_id))
.map(|mut conflict| {
conflict.train_ids.retain(|id| id != &virtual_train_id);
conflict
})
.collect();
// Return the conflicts found along with the pathfinding result for the virtual train.
Ok(STDCMResponse::Conflicts {
pathfinding_result: self.virtual_train_pathfinding_result,
conflicts,
})
}
}
fn make_work_schedules_request(
work_schedules: &[WorkSchedule],
start_time: DateTime<Utc>,
latest_simulation_end: DateTime<Utc>,
) -> Option<WorkSchedulesRequest> {
if work_schedules.is_empty() {
return None;
}
let search_window_duration = (latest_simulation_end - start_time).num_milliseconds() as u64;
let work_schedule_requirements = work_schedules
.iter()
.map(|ws| (ws.id, ws.map_to_core_work_schedule(start_time)))
.filter(|(_, ws)| ws.end_time > 0 && ws.start_time < search_window_duration)
.collect();
Some(WorkSchedulesRequest {
start_time,
work_schedule_requirements,
})
}