use crate::errors::ConfigError; use crate::radarg_data::ProbeDataType; use crate::utils::color_tools::hex_to_rgba_u8; use crate::Asset; use dirs; use num_traits::{AsPrimitive, FromPrimitive}; use serde::{Deserialize, Serialize}; use std::env; use toml; macro_rules! find_cmap { ($c:ident,$find_on:ident,$({$b:tt => $name:literal}),*) => { { let mut cmap = None; match $c { $( $b => { let find_v = $find_on.iter().find(|cb| cb.type_name == $name).map(|cb| cb); cmap = find_v; } )* _ => {} } cmap } }; } #[derive(Deserialize, Serialize)] pub struct Setting { pub cmap: Vec, } impl Setting { pub fn new() -> Self { use std::fs::read_to_string; use std::io::*; let current_dir = env::current_dir().unwrap(); if !current_dir.join("config.toml").exists() { let default_config = Asset::get("config.toml").unwrap(); let folder_path = current_dir.clone(); let conf = folder_path.join("config.toml"); let mut file = std::fs::File::create_new(&conf).unwrap(); file.write_all(&default_config.data).unwrap(); } let file = read_to_string(current_dir.join("config.toml")).unwrap(); let setting: Setting = toml::from_str(&file).unwrap(); setting } pub fn find(&self, name: &ProbeDataType) -> Option<&CB> { let cmap = &self.cmap; use ProbeDataType::*; find_cmap!( name, cmap, {DBZ => "DBZ"}, {V => "VEL"}, {VIL => "VIL"}, {CC => "CC"}, {KDP => "KDP"}, {ZDR => "ZDR"}, {PHIDP => "PHIDP"} ) } } #[derive(Deserialize, Serialize)] pub struct CB { #[serde(rename = "type")] pub type_name: String, pub colors: Vec, pub levels: Vec, } impl CB { pub fn value_range(&self) -> [f32; 2] { let mut range = [0.0, 0.0]; let levels = &self.levels; range[0] = levels[0]; range[1] = levels[levels.len() - 1]; range } pub fn color(&self) -> Result, ConfigError> { if self.colors.len() != self.levels.len() - 1 { return Err(ConfigError::FormatError( "The number of colors and levels are not matched".to_string(), )); } let mut result = self .colors .iter() .map(|v| hex_to_rgba_u8(v)) .collect::, String>>() .map_err(|v| ConfigError::FormatError(v.to_string()))?; let mut span = Vec::with_capacity(self.levels.len() - 1); for idx in 0..self.levels.len() - 1 { let start = self.levels[idx]; let end = self.levels[idx + 1]; let range = end - start; span.push(range); } let range = self.value_range(); let all_range = range[1] - range[0]; for (level, r) in span.iter().zip(result.iter_mut()) { r[3] = ((*level / all_range) * 255.0) as u8; } Ok(result) } }