fish_lib/models/item/
attributes_container.rs1use crate::models::item::attributes::bait::BaitAttributes;
2use crate::models::item::attributes::purchasable::PurchasableAttributes;
3use crate::models::item::attributes::rod::RodAttributes;
4use crate::models::item::attributes::{ItemAttributes, ItemAttributesType};
5use serde::{Deserialize, Serialize};
6use std::collections::{HashMap, HashSet};
7
8pub trait ItemAttributesContainerInterface {
9 fn get_attributes(&self) -> &HashMap<ItemAttributesType, ItemAttributes>;
10
11 fn get_bait_attributes(&self) -> Option<&BaitAttributes> {
12 match self.get_attributes().get(&ItemAttributesType::Bait) {
13 Some(ItemAttributes::Bait(bait)) => Some(bait),
14 Some(_) | None => None,
15 }
16 }
17
18 fn get_purchasable_attributes(&self) -> Option<&PurchasableAttributes> {
19 match self.get_attributes().get(&ItemAttributesType::Purchasable) {
20 Some(ItemAttributes::Purchasable(purchasable)) => Some(purchasable),
21 Some(_) | None => None,
22 }
23 }
24
25 fn get_rod_attributes(&self) -> Option<&RodAttributes> {
26 match self.get_attributes().get(&ItemAttributesType::Rod) {
27 Some(ItemAttributes::Rod(rod)) => Some(rod),
28 Some(_) | None => None,
29 }
30 }
31
32 fn is_bait(&self) -> bool {
33 self.get_bait_attributes().is_some()
34 }
35
36 fn is_purchasable(&self) -> bool {
37 self.get_purchasable_attributes().is_some()
38 }
39
40 fn is_rod(&self) -> bool {
41 self.get_rod_attributes().is_some()
42 }
43
44 fn get_bait_level(&self) -> Option<u64> {
46 self.get_bait_attributes().map(|bait| bait.get_level())
47 }
48
49 fn get_cost(&self) -> Option<u32> {
50 self.get_purchasable_attributes()
51 .map(|purchasable| purchasable.get_cost())
52 }
53
54 fn get_rod_level(&self) -> Option<u64> {
55 self.get_rod_attributes().map(|rod| rod.get_level())
56 }
57}
58
59#[derive(Debug, Default, Clone, PartialEq, Serialize)]
60pub struct ItemAttributesContainer {
61 components: HashMap<ItemAttributesType, ItemAttributes>,
62}
63
64impl ItemAttributesContainer {
65 pub fn new() -> Self {
66 Self::default()
67 }
68
69 pub fn get_attributes_types(&self) -> HashSet<ItemAttributesType> {
70 self.components.keys().copied().collect()
71 }
72
73 pub fn add_component(&mut self, component: ItemAttributes) {
74 match component {
75 ItemAttributes::Bait(_) => self.components.insert(ItemAttributesType::Bait, component),
76 ItemAttributes::Purchasable(_) => self
77 .components
78 .insert(ItemAttributesType::Purchasable, component),
79 ItemAttributes::Rod(_) => self.components.insert(ItemAttributesType::Rod, component),
80 };
81 }
82
83 pub fn with_bait(mut self, level: u64) -> Self {
84 let component = ItemAttributes::bait(level);
85 self.add_component(component);
86 self
87 }
88
89 pub fn with_purchasable(mut self, cost: u32) -> Self {
90 let component = ItemAttributes::purchasable(cost);
91 self.add_component(component);
92 self
93 }
94
95 pub fn with_rod(mut self, level: u64) -> Self {
96 let component = ItemAttributes::rod(level);
97 self.add_component(component);
98 self
99 }
100}
101
102impl ItemAttributesContainerInterface for ItemAttributesContainer {
103 fn get_attributes(&self) -> &HashMap<ItemAttributesType, ItemAttributes> {
104 &self.components
105 }
106}
107
108impl<'de> Deserialize<'de> for ItemAttributesContainer {
110 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
111 where
112 D: serde::Deserializer<'de>,
113 {
114 #[derive(Deserialize)]
115 struct Helper {
116 components: HashMap<String, serde_json::Value>,
117 }
118
119 let helper = Helper::deserialize(deserializer)?;
120 let mut container = ItemAttributesContainer::new();
121
122 for (type_str, attr_value) in helper.components {
123 let (attr_type, attribute) = match type_str.as_str() {
124 "Bait" => {
125 let bait =
126 serde_json::from_value(attr_value).map_err(serde::de::Error::custom)?;
127 (ItemAttributesType::Bait, ItemAttributes::Bait(bait))
128 }
129 "Purchasable" => {
130 let purchasable =
131 serde_json::from_value(attr_value).map_err(serde::de::Error::custom)?;
132 (
133 ItemAttributesType::Purchasable,
134 ItemAttributes::Purchasable(purchasable),
135 )
136 }
137 "Rod" => {
138 let rod =
139 serde_json::from_value(attr_value).map_err(serde::de::Error::custom)?;
140 (ItemAttributesType::Rod, ItemAttributes::Rod(rod))
141 }
142 _ => continue,
143 };
144
145 container.components.insert(attr_type, attribute);
146 }
147
148 Ok(container)
149 }
150}