Load and process a dataset of BarDatum points.
(mut self, data: &Vec<impl BarDatum>)
| 75 | |
| 76 | /// Load and process a dataset of BarDatum points. |
| 77 | pub fn load_data(mut self, data: &Vec<impl BarDatum>) -> Result<Self, String> { |
| 78 | match self.x_scale { |
| 79 | Some(scale) if scale.get_type() == ScaleType::Band => {}, |
| 80 | _ => return Err("The X axis scale should be a Band scale.".to_string()), |
| 81 | } |
| 82 | match self.y_scale { |
| 83 | Some(scale) if scale.get_type() == ScaleType::Linear => {}, |
| 84 | _ => return Err("The Y axis scale should be a Linear scale.".to_string()), |
| 85 | } |
| 86 | |
| 87 | // If no keys were explicitly provided, extract the keys from the data. |
| 88 | if self.keys.len() == 0 { |
| 89 | self.keys = Self::extract_keys(&data); |
| 90 | } |
| 91 | |
| 92 | // HashMap to group all data related to a category. This is needed when there |
| 93 | // are many data entries under a single category as in a stacked bar chart. |
| 94 | let mut categories: HashMap<String, Vec<(&String, f32)>> = HashMap::new(); |
| 95 | |
| 96 | // Organize entries based on the order of the keys first, since displayed data |
| 97 | // should keep the order defined in the `keys` attribute. |
| 98 | for (i, key) in self.keys.iter_mut().enumerate() { |
| 99 | // Map the key to the corresponding color. |
| 100 | self.color_map.insert(key.clone(), self.colors[i].as_hex()); |
| 101 | |
| 102 | for entry in data.iter() { |
| 103 | if entry.get_key() == *key { |
| 104 | let entry_category = entry.get_category(); |
| 105 | |
| 106 | if !categories.contains_key(&entry_category) { |
| 107 | categories.insert(entry.get_category(), Vec::new()); |
| 108 | } |
| 109 | if let Some(category_entries) = categories.get_mut(&entry_category) { |
| 110 | category_entries.push((key, entry.get_value())); |
| 111 | } |
| 112 | } |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | // Create a Bar entry for each category data that was grouped in the previous step. |
| 117 | let mut bars = Vec::new(); |
| 118 | let y_range_is_reversed = self.y_scale.unwrap().is_range_reversed(); |
| 119 | |
| 120 | for (category, key_value_pairs) in categories.iter_mut() { |
| 121 | let mut value_acc = 0_f32; |
| 122 | let mut bar_blocks = Vec::new(); |
| 123 | let mut stacked_start = self.y_scale.unwrap().scale(&value_acc); |
| 124 | let mut stacked_end = stacked_start; |
| 125 | |
| 126 | for (key, value) in key_value_pairs.iter() { |
| 127 | value_acc += *value; |
| 128 | // If Y axis' scale has the range in reversed order, then adjust the computation of |
| 129 | // the start and end positions to account for SVG coordinate system origin. |
| 130 | if y_range_is_reversed { |
| 131 | stacked_end = stacked_start; |
| 132 | stacked_start = self.y_scale.unwrap().scale(&value_acc); |
| 133 | } else { |
| 134 | stacked_start = stacked_end; |
nothing calls this directly
no test coverage detected