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 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
use super::payload::*; use super::position::*; use std::hash::Hash; #[derive(Copy, Clone, PartialEq, Debug)] /// Library supports different kind of slots /// /// Type | Meaning /// --------|-------- /// CLASSIC | Slot with the ability to store single payload /// PIT | Slot which is always empty and carriers can drop anything into it (i.e. payload that is of no use and must be removed) /// SPAWNER | Slot which produces any payload that might be needed by carriers to fill the payload shortage pub enum SlotKind { CLASSIC, PIT, SPAWNER, } /// Represnets the `Slot` object. Slots have their target payload specified /// and carriers will do their best to find appropriate payload and /// bring it to the slot. #[derive(Copy, Clone, Debug)] pub struct Slot<T: PartialEq + Eq + Hash + Copy> { // TODO: Do not require Copy - get_payloads() should return reference pos: Position, pub(crate) current_payload: Option<Payload<T>>, target_payload: Option<Payload<T>>, pub(crate) taken_care_of: bool, kind: SlotKind, } impl<T: PartialEq + Eq + Hash + Copy> Slot<T> { /// Creates new Slot at the position specified and with the payloads specified /// /// # Example /// /// ``` /// let empty_slot = swarm_it::Slot::<char>::new(100.0, 100.0, None, None, swarm_it::SlotKind::CLASSIC); /// let slot_with_current_payload = swarm_it::Slot::<char>::new( /// 100.0, 100.0, /// Some(swarm_it::Payload::new('X')), /// None, /// swarm_it::SlotKind::CLASSIC); /// ``` pub fn new( x: f64, y: f64, current_payload: Option<Payload<T>>, target_payload: Option<Payload<T>>, kind: SlotKind, ) -> Slot<T> { Slot { pos: Position::new(x, y), current_payload, target_payload, taken_care_of: false, kind, } } /// Returns current slot position /// /// # Example /// /// ``` /// let x = 100.0; /// let y = 200.0; /// let slot = swarm_it::Slot::<char>::new(x, y, None, None, swarm_it::SlotKind::CLASSIC); /// let position = slot.get_position(); /// approx::assert_abs_diff_eq!(position.x, x); /// approx::assert_abs_diff_eq!(position.y, y); /// ``` pub fn get_position(&self) -> &Position { &self.pos } /// Returns current carrier payloads. /// /// Index | Content /// ------|--------------- /// 0 | current payload /// 1 | target payload /// /// # Example /// /// ``` /// let slot_with_current_payload = swarm_it::Slot::<char>::new( /// 100.0, 100.0, /// Some(swarm_it::Payload::new('X')), /// None, /// swarm_it::SlotKind::CLASSIC); /// let payloads = slot_with_current_payload.get_payloads(); /// assert_eq!(payloads[0], Some(swarm_it::Payload::new('X'))); /// assert_eq!(payloads[1], None); /// ``` pub fn get_payloads(&self) -> [Option<Payload<T>>; 2] { [self.current_payload, self.target_payload] } /// Sets target payload /// /// # Example /// /// ``` /// let mut empty_slot = swarm_it::Slot::<char>::new(100.0, 100.0, None, None, swarm_it::SlotKind::CLASSIC); /// empty_slot.set_target_payload(Some(swarm_it::Payload::new('X'))); /// let payloads = empty_slot.get_payloads(); /// assert_eq!(payloads[0], None); /// assert_eq!(payloads[1], Some(swarm_it::Payload::new('X'))); /// ``` pub fn set_target_payload(&mut self, p: Option<Payload<T>>) { self.target_payload = p; } /// Sets both current and target payloads /// /// # Example /// /// ``` /// let mut empty_slot = swarm_it::Slot::<char>::new(100.0, 100.0, None, None, swarm_it::SlotKind::CLASSIC); /// empty_slot.set_payloads(Some(swarm_it::Payload::new('X'))); /// let payloads = empty_slot.get_payloads(); /// assert_eq!(payloads[0], Some(swarm_it::Payload::new('X'))); /// assert_eq!(payloads[1], Some(swarm_it::Payload::new('X'))); /// ``` pub fn set_payloads(&mut self, p: Option<Payload<T>>) { self.current_payload = p; self.target_payload = p; } /// Returns `true` if this slot is already addressed by any of the carriers. /// It is mainly used by the library internals, but is also exposed /// for the user, so it is possible to, for example, prepare different /// visualization for these kind of slots. /// /// # Example /// /// ``` /// let slot = swarm_it::Slot::<char>::new(100.0, 100.0, None, None, swarm_it::SlotKind::CLASSIC); /// assert_eq!(slot.is_taken_care_of(), false); /// ``` pub fn is_taken_care_of(&self) -> bool { self.taken_care_of } /// Returns `true` is slot is a pit /// /// # Example /// /// ``` /// let slot_classic = swarm_it::Slot::<char>::new(100.0, 100.0, None, None, swarm_it::SlotKind::CLASSIC); /// let slot_pit = swarm_it::Slot::<char>::new(100.0, 100.0, None, None, swarm_it::SlotKind::PIT); /// let slot_spawner = swarm_it::Slot::<char>::new(100.0, 100.0, None, None, swarm_it::SlotKind::SPAWNER); /// assert!(slot_pit.is_pit()); /// assert!(!slot_classic.is_pit()); /// assert!(!slot_spawner.is_pit()); /// ``` pub fn is_pit(&self) -> bool { self.kind == SlotKind::PIT } /// Returns `true` is slot is a spawner /// /// # Example /// /// ``` /// let slot_classic = swarm_it::Slot::<char>::new(100.0, 100.0, None, None, swarm_it::SlotKind::CLASSIC); /// let slot_pit = swarm_it::Slot::<char>::new(100.0, 100.0, None, None, swarm_it::SlotKind::PIT); /// let slot_spawner = swarm_it::Slot::<char>::new(100.0, 100.0, None, None, swarm_it::SlotKind::SPAWNER); /// assert!(!slot_pit.is_spawner()); /// assert!(!slot_classic.is_spawner()); /// assert!(slot_spawner.is_spawner()); /// ``` pub fn is_spawner(&self) -> bool { self.kind == SlotKind::SPAWNER } pub(crate) fn accepts(&self, p: Option<Payload<T>>) -> bool { self.target_payload == p } }