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
//! The `railway_objects` module contains traits for different types of railway objects,
//! their positions within an internal model, target management, and geographical locations.
use geo::Coord;
use std::any::Any;
use std::collections::VecDeque;
mod train;
use crate::types::{NodeId, RailwayObjectId};
pub use train::Train;
use uom::si::f64::{Acceleration, Velocity};

/// The `RailwayObject` trait represents the basic properties of a railway object,
/// including a unique identifier and a position within an internal model. Objects
/// implementing this trait can be used in a railway simulation.
pub trait RailwayObject: std::fmt::Debug + Any {
    /// Returns the unique identifier of the railway object.
    ///
    /// # Returns
    ///
    /// A `RailwayObjectId` representing the unique identifier of the railway object.
    ///
    fn id(&self) -> RailwayObjectId;

    /// Returns the position of the railway object within the internal model.
    ///
    /// # Returns
    ///
    /// An `Option<NodeId>` representing the position of the railway object in the
    /// internal model. Returns `None` if the object has no position.
    ///
    fn position(&self) -> Option<NodeId>;

    /// Sets the position of the railway object within the internal model.
    ///
    /// # Arguments
    ///
    /// * `position` - An `Option<NodeId>` representing the new position of the railway
    /// object in the internal model. Pass `None` to remove the object's position.
    ///
    fn set_position(&mut self, position: Option<NodeId>);

    /// Returns a reference to the `Any` trait for this object.
    ///
    /// This method is useful for downcasting the object to a concrete type
    /// when working with trait objects.
    ///
    /// # Returns
    ///
    /// A reference to the `Any` trait for the object.
    ///
    fn as_any(&self) -> &dyn Any;

    /// Returns a mutable reference to the `Any` trait for this object.
    ///
    /// This method is useful for downcasting the object to a concrete type
    /// when working with trait objects.
    ///
    /// # Returns
    ///
    /// A mutable reference to the `Any` trait for the object.
    ///
    fn as_any_mut(&mut self) -> &mut dyn Any;
}

/// The `NextTarget` trait provides methods for managing a single target for a railway object.
pub trait NextTarget: RailwayObject {
    /// Returns the next target of the railway object, if any.
    fn next_target(&self) -> Option<NodeId>;

    /// Sets the next target of the railway object.
    fn set_next_target(&mut self, target: Option<NodeId>);
}

/// The `MultipleTargets` trait provides methods for managing a list of targets for a railway object.
pub trait MultipleTargets: RailwayObject {
    /// Returns the list of targets for the railway object.
    fn targets(&self) -> &VecDeque<NodeId>;

    /// Adds a target to the list of targets for the railway object.
    fn add_target(&mut self, target: NodeId);

    /// Removes and returns the first target from the list of targets for the railway object, if any.
    fn remove_target(&mut self) -> Option<NodeId>;
}

/// The `GeoLocation` trait provides a method for obtaining the geographical location of a railway object.
pub trait GeoLocation {
    /// Returns the geographical location of the railway object as a coordinate.
    fn geo_location(&self) -> Option<Coord<f64>>;
    /// Sets the geographical location of the railway object
    fn set_geo_location(&mut self, location: Option<Coord<f64>>);
}

/// The Movable trait
pub trait Movable {
    /// Returns the max speed of the object as a Velocity.
    fn max_speed(&self) -> Velocity;

    /// Sets the max speed of the object as a Velocity.
    fn set_max_speed(&mut self, max_speed: Velocity);

    /// Returns the current speed of the object as a Velocity.
    fn speed(&self) -> Velocity;

    /// Sets the speed of the object as a Velocity.
    fn set_speed(&mut self, speed: Velocity);

    /// Returns the current acceleration of the object as an Acceleration.
    fn acceleration(&self) -> Acceleration;

    /// Sets the acceleration of the object as an Acceleration.
    fn set_acceleration(&mut self, acceleration: Acceleration);
}