///|
pub(all) struct SimulatedTrain {
train_id : String
route_id : @interlocking.RouteId
mut current_section_index : Int
mut distance_in_current_section : Double
speed_m_per_s : Double
mut is_finished : Bool
} derive(Debug)
///|
pub fn SimulatedTrain::new(
train_id : String,
route_id : @interlocking.RouteId,
speed_kmh : Double,
) -> SimulatedTrain {
{
train_id,
route_id,
current_section_index: 0,
distance_in_current_section: 0.0,
speed_m_per_s: speed_kmh / 3.6,
is_finished: false,
}
}
///|
pub fn SimulatedTrain::step_movement(
self : SimulatedTrain,
delta_time_seconds : Double,
rule : @interlocking.InterlockingRule,
station : @topology.Station,
) -> SimulationEvent? {
if self.is_finished {
return None
}
let sections = rule.track_sections
if self.current_section_index >= sections.length() {
self.is_finished = true
return None
}
let current_track_id = sections[self.current_section_index]
let current_track = match station.graph.get_track(current_track_id) {
None => {
self.is_finished = true
return None
}
Some(tr) => tr
}
// Ensure initial occupation
if self.distance_in_current_section == 0.0 && current_track.state != Occupied {
let _ = station.set_track_state(current_track_id, Occupied, self.train_id)
return Some({
event_id: 0,
event_type: EventOccupyTrack,
route_id: Some(self.route_id),
track_id: Some(current_track_id),
turnout_id: None,
target_position: None,
train_id: self.train_id,
timestamp_ms: 0,
})
}
let advance_dist = self.speed_m_per_s * delta_time_seconds
self.distance_in_current_section = self.distance_in_current_section +
advance_dist
if self.distance_in_current_section >= current_track.length_meters {
// Train moves to next section
let _ = station.set_track_state(current_track_id, Clear, "")
self.current_section_index = self.current_section_index + 1
self.distance_in_current_section = 0.0
if self.current_section_index >= sections.length() {
self.is_finished = true
return Some({
event_id: 0,
event_type: EventClearTrack,
route_id: Some(self.route_id),
track_id: Some(current_track_id),
turnout_id: None,
target_position: None,
train_id: self.train_id,
timestamp_ms: 0,
})
} else {
let next_track_id = sections[self.current_section_index]
let _ = station.set_track_state(next_track_id, Occupied, self.train_id)
return Some({
event_id: 0,
event_type: EventOccupyTrack,
route_id: Some(self.route_id),
track_id: Some(next_track_id),
turnout_id: None,
target_position: None,
train_id: self.train_id,
timestamp_ms: 0,
})
}
}
None
}