1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7#[non_exhaustive]
8pub enum DoorState {
9 Closed,
11 Opening {
13 ticks_remaining: u32,
15 open_duration: u32,
17 close_duration: u32,
19 },
20 Open {
22 ticks_remaining: u32,
24 close_duration: u32,
26 },
27 Closing {
29 ticks_remaining: u32,
31 },
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
36#[non_exhaustive]
37pub enum DoorTransition {
38 None,
40 FinishedOpening,
42 FinishedOpen,
44 FinishedClosing,
46}
47
48impl std::fmt::Display for DoorState {
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 match self {
51 Self::Closed => write!(f, "Closed"),
52 Self::Opening {
53 ticks_remaining, ..
54 } => write!(f, "Opening({ticks_remaining})"),
55 Self::Open {
56 ticks_remaining, ..
57 } => write!(f, "Open({ticks_remaining})"),
58 Self::Closing { ticks_remaining } => write!(f, "Closing({ticks_remaining})"),
59 }
60 }
61}
62
63impl DoorState {
64 #[must_use]
66 pub const fn is_open(&self) -> bool {
67 matches!(self, Self::Open { .. })
68 }
69
70 #[must_use]
72 pub const fn is_closed(&self) -> bool {
73 matches!(self, Self::Closed)
74 }
75
76 #[must_use]
78 pub const fn request_open(transition_ticks: u32, open_ticks: u32) -> Self {
79 Self::Opening {
80 ticks_remaining: transition_ticks,
81 open_duration: open_ticks,
82 close_duration: transition_ticks,
83 }
84 }
85
86 pub const fn tick(&mut self) -> DoorTransition {
88 match self {
89 Self::Closed => DoorTransition::None,
90 Self::Opening {
91 ticks_remaining,
92 open_duration,
93 close_duration,
94 } => {
95 if *ticks_remaining <= 1 {
96 let od = *open_duration;
97 let cd = *close_duration;
98 *self = Self::Open {
99 ticks_remaining: od,
100 close_duration: cd,
101 };
102 DoorTransition::FinishedOpening
103 } else {
104 *ticks_remaining -= 1;
105 DoorTransition::None
106 }
107 }
108 Self::Open {
109 ticks_remaining,
110 close_duration,
111 } => {
112 if *ticks_remaining <= 1 {
113 let cd = *close_duration;
114 *self = Self::Closing {
115 ticks_remaining: cd,
116 };
117 DoorTransition::FinishedOpen
118 } else {
119 *ticks_remaining -= 1;
120 DoorTransition::None
121 }
122 }
123 Self::Closing { ticks_remaining } => {
124 if *ticks_remaining <= 1 {
125 *self = Self::Closed;
126 DoorTransition::FinishedClosing
127 } else {
128 *ticks_remaining -= 1;
129 DoorTransition::None
130 }
131 }
132 }
133 }
134}