use indexmap::IndexMap; use lazy_static::lazy_static; use regex::Regex; use serde_derive::Deserialize; use serde_json::{json, Value}; use crate::data_source::DataSource; use crate::ChampInfo; #[derive(Deserialize, Debug)] struct BuildResponse { lol: Lol } #[derive(Deserialize, Debug)] struct Lol { #[serde(rename = "championsReport")] champions_report: Vec } #[derive(Deserialize, Debug)] struct ChampionReport { champion_id: u32, role: String, patch: String, stats: Stats } #[derive(Deserialize, Debug)] struct Stats { starting_items: Build, core_builds: Build } #[derive(Deserialize, Debug)] struct Build { build: Vec, win_rate: f64, games: u32 } static mut CHAMPIONS_REPORT: Vec = Vec::new(); pub struct CGGDataSource; impl CGGDataSource { fn make_item_set(&self, build: &Build, label: &str) -> Value { json!({ "items": build.build.iter().map(|x| json!({"id": x, "count": 1})).collect::>(), "type": format!("{} ({:.2}% - {} games)", label, build.win_rate * 100., build.games) }) } fn make_item_set_from_list( &self, list: &[u32], label: &str, key: &str, data: &Value, ) -> Value { let mut key_order = String::new(); if data["skills"].get("skillInfo").is_some() { key_order = data["skills"][key]["order"] .as_array() .unwrap() .iter() .map(|x| { data["skills"]["skillInfo"].as_array().unwrap() [x.as_str().unwrap().parse::().unwrap() - 1]["key"] .as_str() .unwrap() }) .collect::>() .join("."); } json!({ "items": list.iter().map(|x| json!({"id": x.to_string(), "count": 1})).collect::>(), "type": format!("{} {}", label, key_order) }) } } impl DataSource for CGGDataSource { fn get_alias(&self) -> &str { "CGG" } fn get_champs_with_positions_and_patch( &self, client: &ureq::Agent, ) -> (IndexMap>, String) { let req = client .get("https://champion.gg") .call() .unwrap(); lazy_static! { static ref RE: Regex = Regex::new(r"(?m)^\s+window.__PRELOADED_STATE__ = (.*);$").unwrap(); } let datas: BuildResponse = serde_json::from_str(&RE.captures(&req.into_string().unwrap()).unwrap()[1].replace("undefined", "null")).unwrap(); let patch = datas.lol.champions_report[0].patch.clone(); let mut champions: IndexMap> = IndexMap::new(); for champ in &datas.lol.champions_report { let id = champ.champion_id.to_string(); let mut roles: Vec = Vec::new(); if champions.contains_key(&id) { let c = champions.get(&id).unwrap(); let mut new_roles = c.clone(); new_roles.push(champ.role.clone()); } else { roles.push(champ.role.clone()); } champions.insert(id, roles); } unsafe { CHAMPIONS_REPORT = datas.lol.champions_report; } (champions, patch) } fn get_champ_data_with_win_pourcentage( &self, champ: &ChampInfo, position: &str, _client: &ureq::Agent, ) -> Option<(Vec, f64)> { let mut some_champ: Option<&ChampionReport> = None; unsafe { for champion in &CHAMPIONS_REPORT { if champion.champion_id.to_string() == champ.key && champion.role == position { some_champ = Some(champion); } } } if let Some(champ) = some_champ { let mut blocks = vec![]; blocks.push(self.make_item_set(&champ.stats.starting_items, "Highest % Win Starting Items")); blocks.push(self.make_item_set(&champ.stats.core_builds, "Highest % Win Core Build Path:")); return Some((blocks, 42.0)); } None } }