spec.rs
1 use candid::{CandidType, Deserialize}; 2 use interface::item::spec::SpecValue; 3 use std::collections::BTreeMap; 4 5 type SpecUpperCategoryKey = u8; 6 #[derive(CandidType, Deserialize, Debug, Clone)] 7 pub struct SpecUpperCategory { 8 name: String, 9 lower_category_map: BTreeMap<SpecLowerCategoryKey, SpecLowerCategory>, 10 } 11 12 impl SpecUpperCategory { 13 pub fn new_str(name: &str, lower_categories: Vec<SpecLowerCategory>) -> Self { 14 let lower_category_map = lower_categories 15 .into_iter() 16 .enumerate() 17 .map(|(i, v)| (i as u8, v)) 18 .collect(); 19 20 Self { 21 name: name.to_string(), 22 lower_category_map, 23 } 24 } 25 26 pub fn get_lower_category(&self, key: SpecLowerCategoryKey) -> Option<&SpecLowerCategory> { 27 self.lower_category_map.get(&key) 28 } 29 } 30 31 type SpecLowerCategoryKey = u8; 32 #[derive(CandidType, Deserialize, Debug, Clone)] 33 pub struct SpecLowerCategory { 34 name: String, 35 value_map: BTreeMap<SpecValueKey, SpecValue>, 36 } 37 38 impl SpecLowerCategory { 39 pub fn new_str(name: &str, values: Vec<Vec<&str>>) -> Self { 40 let value_map = values 41 .into_iter() 42 .enumerate() 43 .map(|(i, v)| (i as u8, v.into_iter().map(|v| v.to_string()).collect())) 44 .collect(); 45 46 Self { 47 name: name.to_string(), 48 value_map, 49 } 50 } 51 52 pub fn get_value(&self, key: &SpecValueKey) -> Option<&interface::item::spec::SpecValue> { 53 self.value_map.get(key) 54 } 55 } 56 57 type SpecValueKey = u8; 58 59 pub type SpecIndexKey = u8; 60 61 #[derive(CandidType, Deserialize, Debug, Clone)] 62 pub struct SpecKey { 63 upper_category_key: SpecUpperCategoryKey, 64 lower_category_vec: Vec<SpecKeyLowerCategory>, 65 } 66 67 impl SpecKey { 68 pub fn new( 69 upper_category_key: SpecUpperCategoryKey, 70 lower_category_vec: Vec<(u8, u8)>, 71 ) -> Self { 72 let lower_category_vec = lower_category_vec 73 .into_iter() 74 .map(|(lower_category_key, value_key)| { 75 SpecKeyLowerCategory::new(lower_category_key, value_key) 76 }) 77 .collect(); 78 79 Self { 80 upper_category_key, 81 lower_category_vec, 82 } 83 } 84 } 85 86 #[derive(CandidType, Deserialize, Debug, Clone)] 87 pub struct SpecKeyLowerCategory { 88 lower_category_key: SpecLowerCategoryKey, 89 value_key: SpecValueKey, 90 } 91 92 impl SpecKeyLowerCategory { 93 pub fn new(lower_category_key: SpecLowerCategoryKey, value_key: SpecValueKey) -> Self { 94 Self { 95 lower_category_key, 96 value_key, 97 } 98 } 99 } 100 101 #[derive(CandidType, Deserialize, Debug, Clone)] 102 pub struct ItemSpecs { 103 // Actual data of specs 104 pub map: BTreeMap<SpecUpperCategoryKey, SpecUpperCategory>, 105 // Mapping of combination of specs 106 pub index_map: BTreeMap<SpecIndexKey, SpecKey>, 107 } 108 109 impl ItemSpecs { 110 pub fn new_str( 111 data: Vec<(&str, Vec<(&str, Vec<Vec<&str>>)>)>, 112 index: Vec<(u8, Vec<(u8, u8)>)>, 113 ) -> Self { 114 let map = data 115 .into_iter() 116 .enumerate() 117 .map(|(i, v)| { 118 ( 119 i as u8, 120 SpecUpperCategory::new_str( 121 v.0, 122 v.1.into_iter() 123 .map(|v| SpecLowerCategory::new_str(v.0, v.1)) 124 .collect(), 125 ), 126 ) 127 }) 128 .collect(); 129 130 let index_map = index 131 .into_iter() 132 .enumerate() 133 .map(|(i, v)| (i as u8, SpecKey::new(v.0, v.1))) 134 .collect(); 135 136 Self { map, index_map } 137 } 138 139 pub fn get_specs(&self, keys: &Vec<SpecIndexKey>) -> Option<interface::item::spec::SpecResult> { 140 let mut result = Vec::new(); 141 142 for key in keys { 143 let mut lower_category_vec = Vec::new(); 144 let spec_key = self.get_spec_key(key)?; 145 146 let upper_category = self.get_upper_category(spec_key.upper_category_key)?; 147 for spec_key_lower_category in &spec_key.lower_category_vec { 148 let lower_category = upper_category 149 .get_lower_category(spec_key_lower_category.lower_category_key)?; 150 let value = lower_category.get_value(&spec_key_lower_category.value_key)?; 151 lower_category_vec.push(interface::item::spec::SpecResultLowerCategory { 152 lower_category_name: lower_category.name.clone(), 153 value: value.clone(), 154 }); 155 } 156 157 result.push(interface::item::spec::SpecResultUpperCategory { 158 upper_category_name: upper_category.name.clone(), 159 lower_category_vec, 160 }); 161 } 162 163 Some(result) 164 } 165 166 fn get_spec_key(&self, key: &SpecIndexKey) -> Option<&SpecKey> { 167 self.index_map.get(key) 168 } 169 170 fn get_upper_category(&self, key: SpecUpperCategoryKey) -> Option<&SpecUpperCategory> { 171 self.map.get(&key) 172 } 173 }