planter_core/resources.rs
1use crate::person::Person;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4/// Represents a resource that can be used in a project. A resource can be either a material or personnel.
5pub enum Resource {
6 /// Represents a material resource that can be used in a project.
7 Material(Material),
8 /// Represents a personnel resource. Personnel is usually a resource that can complete tasks
9 Personnel {
10 /// Information about the person.
11 person: Person,
12 /// Hourly rate of the person.
13 hourly_rate: Option<u16>,
14 },
15}
16
17#[derive(Debug, Clone, PartialEq, Eq)]
18/// Represents a material resource that can be used in a project.
19/// It can be either consumable or non-consumable.
20pub enum Material {
21 /// A consumable resource is a material that needs to be resupplied after use.
22 Consumable(Consumable),
23 /// A non-consumable resource is a material that does not need to be resupplied after use.
24 NonConsumable(NonConsumable),
25}
26
27impl Default for Material {
28 fn default() -> Self {
29 Material::new("")
30 }
31}
32
33#[derive(Debug, Clone, Default, PartialEq, Eq)]
34/// Represents a consumable material resource that can be used in a project.
35pub struct Consumable {
36 /// Name of the consumable material.
37 name: String,
38 /// Available quantity of the consumable material.
39 quantity: Option<u16>,
40 /// Cost to buy this material.
41 cost_per_unit: Option<u16>,
42}
43
44#[derive(Debug, Clone, Default, PartialEq, Eq)]
45/// Represents a non-consumable material resource that can be used in a project.
46pub struct NonConsumable {
47 /// Name of the non-consumable material.
48 name: String,
49 /// Available quantity of the non-consumable material.
50 quantity: Option<u16>,
51 /// Cost to buy this material.
52 cost_per_unit: Option<u16>,
53 /// Some non consumable materials can have a hourly rate. For example, due to energy consumption.
54 hourly_rate: Option<u16>,
55}
56
57impl From<NonConsumable> for Consumable {
58 fn from(value: NonConsumable) -> Self {
59 Consumable {
60 name: value.name,
61 quantity: value.quantity,
62 cost_per_unit: value.quantity,
63 }
64 }
65}
66
67impl From<Consumable> for NonConsumable {
68 fn from(value: Consumable) -> Self {
69 NonConsumable {
70 name: value.name,
71 quantity: value.quantity,
72 cost_per_unit: value.cost_per_unit,
73 hourly_rate: None,
74 }
75 }
76}
77
78impl Material {
79 /// Returns a consumable material by default, with the given name.
80 pub fn new(name: impl Into<String>) -> Self {
81 Material::Consumable(Consumable::new(name))
82 }
83
84 /// Returns the name of the material.
85 /// # Example
86 /// ```
87 /// use planter_core::resources::Material;
88 ///
89 /// let material = Material::new("Steel".to_owned());
90 /// assert_eq!(material.name(), "Steel");
91 /// ```
92 pub fn name(&self) -> &str {
93 match self {
94 Material::Consumable(consumable) => &consumable.name,
95 Material::NonConsumable(non_consumable) => &non_consumable.name,
96 }
97 }
98
99 /// Updates the name of the material.
100 /// # Example
101 /// ```
102 /// use planter_core::resources::Material;
103 ///
104 /// let mut material = Material::new("Steel".to_owned());
105 /// material.update_name("Iron".to_owned());
106 /// assert_eq!(material.name(), "Iron");
107 /// ```
108 pub fn update_name(&mut self, name: impl Into<String>) {
109 match self {
110 Material::Consumable(consumable) => consumable.name = name.into(),
111 Material::NonConsumable(non_consumable) => non_consumable.name = name.into(),
112 }
113 }
114
115 /// Returns the quantity of materials.
116 /// # Example
117 /// ```
118 /// use planter_core::resources::Material;
119 ///
120 /// let material = Material::new("Steel".to_owned());
121 /// assert_eq!(material.quantity(), None);
122 /// ```
123 pub fn quantity(&self) -> Option<u16> {
124 match self {
125 Material::Consumable(consumable) => consumable.quantity,
126 Material::NonConsumable(non_consumable) => non_consumable.quantity,
127 }
128 }
129
130 /// Updates the quantity of materials.
131 /// # Example
132 /// ```
133 /// use planter_core::resources::Material;
134 ///
135 /// let mut material = Material::new("Steel".to_owned());
136 /// material.update_quantity(3);
137 /// assert_eq!(material.quantity(), Some(3));
138 /// ```
139 pub fn update_quantity(&mut self, quantity: u16) {
140 match self {
141 Material::Consumable(consumable) => consumable.quantity = Some(quantity),
142 Material::NonConsumable(non_consumable) => non_consumable.quantity = Some(quantity),
143 }
144 }
145
146 /// Remove the quantity of materials.
147 /// # Example
148 /// ```
149 /// use planter_core::resources::Material;
150 ///
151 /// let mut material = Material::new("Steel".to_owned());
152 /// material.update_quantity(3);
153 /// assert_eq!(material.quantity(), Some(3));
154 /// material.remove_quantity();
155 /// assert_eq!(material.quantity(), None);
156 /// ```
157 pub fn remove_quantity(&mut self) {
158 match self {
159 Material::Consumable(consumable) => consumable.quantity = None,
160 Material::NonConsumable(non_consumable) => non_consumable.quantity = None,
161 }
162 }
163 /// Returns the cost per unit of the material.
164 /// # Example
165 /// ```
166 /// use planter_core::resources::Material;
167 ///
168 /// let material = Material::new("Steel".to_owned());
169 /// assert_eq!(material.cost_per_unit(), None);
170 /// ```
171 pub fn cost_per_unit(&self) -> Option<u16> {
172 match self {
173 Material::Consumable(consumable) => consumable.cost_per_unit,
174 Material::NonConsumable(non_consumable) => non_consumable.cost_per_unit,
175 }
176 }
177
178 /// Updates the cost per unit of the material.
179 /// # Example
180 /// ```
181 /// use planter_core::resources::Material;
182 ///
183 /// let mut material = Material::new("Steel".to_owned());
184 /// material.update_cost_per_unit(3);
185 /// assert_eq!(material.cost_per_unit(), Some(3));
186 /// ```
187 pub fn update_cost_per_unit(&mut self, cost_per_unit: u16) {
188 match self {
189 Material::Consumable(consumable) => consumable.cost_per_unit = Some(cost_per_unit),
190 Material::NonConsumable(non_consumable) => {
191 non_consumable.cost_per_unit = Some(cost_per_unit)
192 }
193 }
194 }
195
196 /// Remove the cost per unit of the material.
197 /// # Example
198 /// ```
199 /// use planter_core::resources::Material;
200 ///
201 /// let mut material = Material::new("Steel".to_owned());
202 /// material.update_cost_per_unit(3);
203 /// assert_eq!(material.cost_per_unit(), Some(3));
204 /// material.remove_cost_per_unit();
205 /// assert_eq!(material.cost_per_unit(), None);
206 /// ```
207 pub fn remove_cost_per_unit(&mut self) {
208 match self {
209 Material::Consumable(consumable) => consumable.cost_per_unit = None,
210 Material::NonConsumable(non_consumable) => non_consumable.cost_per_unit = None,
211 }
212 }
213}
214
215impl Consumable {
216 /// Creates a new consumable material resource.
217 pub fn new(name: impl Into<String>) -> Self {
218 Consumable {
219 name: name.into(),
220 quantity: None,
221 cost_per_unit: None,
222 }
223 }
224}
225
226impl NonConsumable {
227 /// Creates a new non-consumable material resource.
228 pub fn new(name: impl Into<String>) -> Self {
229 NonConsumable {
230 name: name.into(),
231 quantity: None,
232 hourly_rate: None,
233 cost_per_unit: None,
234 }
235 }
236
237 /// Returns the hourly rate of the non-consumable material.
238 /// # Example
239 /// ```
240 /// use planter_core::resources::NonConsumable;
241 ///
242 /// let non_consumable = NonConsumable::new("Steel".to_owned());
243 /// assert_eq!(non_consumable.hourly_rate(), None);
244 /// ```
245 pub fn hourly_rate(&self) -> Option<u16> {
246 self.hourly_rate
247 }
248
249 /// Updates the hourly_rate of the non consumable material.
250 /// # Example
251 /// ```
252 /// use planter_core::resources::NonConsumable;
253 ///
254 /// let mut non_consumable = NonConsumable::new("Steel".to_owned());
255 /// non_consumable.update_hourly_rate(3);
256 /// assert_eq!(non_consumable.hourly_rate(), Some(3));
257 /// ```
258 pub fn update_hourly_rate(&mut self, hourly_rate: u16) {
259 self.hourly_rate = Some(hourly_rate);
260 }
261
262 /// Remove the cost per unit of the non consumable material.
263 /// # Example
264 /// ```
265 /// use planter_core::resources::NonConsumable;
266 ///
267 /// let mut non_consumable = NonConsumable::new("Steel".to_owned());
268 /// non_consumable.update_hourly_rate(3);
269 /// assert_eq!(non_consumable.hourly_rate(), Some(3));
270 /// non_consumable.remove_hourly_rate();
271 /// assert_eq!(non_consumable.hourly_rate(), None);
272 /// ```
273 pub fn remove_hourly_rate(&mut self) {
274 self.hourly_rate = None;
275 }
276}