CGGItemSets/src/cgg_data_source.rs

189 lines
5.7 KiB
Rust
Raw Normal View History

2018-06-16 10:48:46 +02:00
use indexmap::IndexMap;
use log::error;
2021-03-13 23:02:26 +01:00
use serde_derive::Deserialize;
use serde_json::{json, Value};
2021-03-14 10:52:27 +01:00
use std::sync::Mutex;
2018-06-16 10:48:46 +02:00
2021-03-14 14:25:37 +01:00
use crate::data_source::{DataSource, Stat};
2021-03-13 23:02:26 +01:00
use crate::ChampInfo;
2021-05-13 14:38:31 +02:00
use crate::Champion;
2018-06-16 10:48:46 +02:00
2021-10-31 09:39:43 +01:00
#[derive(Deserialize)]
2021-03-13 23:02:26 +01:00
struct BuildResponse {
2021-03-14 11:21:49 +01:00
lol: Lol,
2021-03-13 23:02:26 +01:00
}
2021-10-31 09:39:43 +01:00
#[derive(Deserialize)]
2021-03-13 23:02:26 +01:00
struct Lol {
#[serde(rename = "championsReport")]
2021-03-14 11:21:49 +01:00
champions_report: Vec<ChampionReport>,
2021-03-13 23:02:26 +01:00
}
2021-10-31 09:39:43 +01:00
#[derive(Deserialize)]
2021-03-13 23:02:26 +01:00
struct ChampionReport {
champion_id: u32,
role: String,
patch: String,
2021-03-14 11:21:49 +01:00
stats: Stats,
2021-03-13 23:02:26 +01:00
}
2021-10-31 09:39:43 +01:00
#[derive(Deserialize)]
2021-03-13 23:02:26 +01:00
struct Stats {
starting_items: Build,
2021-03-14 09:49:18 +01:00
core_builds: Build,
big_item_builds: Build,
skills: Build,
most_common_starting_items: Build,
most_common_core_builds: Build,
most_common_big_item_builds: Build,
2021-03-14 11:21:49 +01:00
most_common_skills: Build,
2021-10-30 11:54:32 +02:00
games: u32,
kills: u32,
deaths: u32,
wins: u32,
2021-10-31 09:22:49 +01:00
assists: u32,
2021-03-13 23:02:26 +01:00
}
2021-10-31 09:39:43 +01:00
#[derive(Deserialize)]
2021-03-13 23:02:26 +01:00
struct Build {
build: Vec<u32>,
2021-11-01 08:35:19 +01:00
win_rate: f32,
2021-03-14 11:21:49 +01:00
games: u32,
2021-03-13 23:02:26 +01:00
}
2023-01-03 11:13:33 +01:00
pub struct CGGDataSource {
champions_report: Mutex<Vec<ChampionReport>>,
2021-03-14 10:52:27 +01:00
}
impl CGGDataSource {
2023-01-03 11:13:33 +01:00
pub fn new() -> CGGDataSource {
Self {
champions_report: Mutex::new(Vec::new()),
}
}
2021-03-13 23:02:26 +01:00
fn make_item_set(&self, build: &Build, label: &str) -> Value {
json!({
2021-03-14 09:49:18 +01:00
"items": build.build.iter().map(|x| json!({"id": x.to_string(), "count": 1})).collect::<Vec<Value>>(),
2021-03-13 23:02:26 +01:00
"type": format!("{} ({:.2}% - {} games)", label, build.win_rate * 100., build.games)
})
}
2021-03-14 11:21:49 +01:00
fn make_item_set_from_list(&self, build: &Build, label: &str, skills: &Build) -> Value {
let key_order = skills
.build
.iter()
.map(|x| x.to_string())
.collect::<Vec<String>>()
.join("");
2021-03-14 09:49:18 +01:00
2021-08-01 09:56:15 +02:00
self.make_item_set(build, [label, key_order.as_str()].join(" ").as_str())
}
}
2021-03-14 16:43:29 +01:00
fn extract_json(pattern: &str, page: &str) -> String {
2021-03-14 17:17:29 +01:00
let json = page[page.find(pattern).unwrap() + pattern.len()..].to_owned();
2021-03-14 18:10:51 +01:00
json[..json.find("};").unwrap() + 1].replace("undefined", "null")
2021-03-14 16:43:29 +01:00
}
2018-06-16 10:48:46 +02:00
impl DataSource for CGGDataSource {
fn get_alias(&self) -> &str {
"CGG"
}
2021-03-14 09:49:18 +01:00
fn get_timeout(&self) -> u64 {
0
}
2021-05-13 14:38:31 +02:00
fn get_champs_with_positions(
&self,
client: &ureq::Agent,
_champion: &Champion,
) -> IndexMap<u32, Vec<String>> {
let mut champions: IndexMap<u32, Vec<String>> = IndexMap::new();
match client.get("https://champion.gg").call() {
Ok(req) => {
let page = &req.into_string().unwrap();
2021-03-14 10:52:27 +01:00
let datas: BuildResponse =
serde_json::from_str(&extract_json("window.__PRELOADED_STATE__ = ", page))
.unwrap();
2021-03-14 10:52:27 +01:00
for champ in &datas.lol.champions_report {
let id = champ.champion_id;
if champions.contains_key(&id) {
let mut roles = champions.get(&id).unwrap().to_owned();
roles.push(champ.role.to_owned());
champions.insert(id, roles);
} else {
champions.insert(id, vec![champ.role.to_owned()]);
}
}
2018-06-16 10:48:46 +02:00
for report in datas.lol.champions_report {
2023-01-03 11:13:33 +01:00
self.champions_report.lock().unwrap().push(report);
}
2021-03-14 14:25:37 +01:00
}
Err(e) => error!("Error retrieving data: {}", e),
2018-06-16 10:48:46 +02:00
}
2021-03-16 11:13:54 +01:00
champions
2018-06-16 10:48:46 +02:00
}
fn get_champ_data_with_win_pourcentage(
&self,
2021-03-13 23:02:26 +01:00
champ: &ChampInfo,
2021-03-15 23:11:40 +01:00
positions: &[String],
2021-03-13 23:02:26 +01:00
_client: &ureq::Agent,
2021-03-15 23:00:20 +01:00
) -> Vec<(String, Vec<Value>, Stat)> {
let mut data = vec![];
for position in positions {
let mut some_champ: Option<&ChampionReport> = None;
2023-01-03 11:13:33 +01:00
let reports = self.champions_report.lock().unwrap();
2021-03-15 23:00:20 +01:00
for champion in reports.iter() {
2021-03-17 09:13:19 +01:00
if champion.champion_id.to_string() == champ.key && champion.role == *position {
2021-03-15 23:00:20 +01:00
some_champ = Some(champion);
break;
2021-03-14 10:52:27 +01:00
}
}
2021-03-15 23:00:20 +01:00
if let Some(champ) = some_champ {
2021-08-01 09:56:15 +02:00
let blocks = vec![
self.make_item_set_from_list(
&champ.stats.starting_items,
"Highest % Win Starting Items | Skills: ",
&champ.stats.skills,
),
2021-03-15 23:00:20 +01:00
self.make_item_set(&champ.stats.core_builds, "Highest % Win Core Build Path:"),
self.make_item_set(&champ.stats.big_item_builds, "Highest % Win Big Items:"),
2021-08-01 09:56:15 +02:00
self.make_item_set_from_list(
&champ.stats.most_common_starting_items,
"Most Frequent Starting Items | Skills: ",
&champ.stats.most_common_skills,
),
self.make_item_set(
&champ.stats.most_common_core_builds,
"Most Frequent Build Path",
),
self.make_item_set(
&champ.stats.most_common_big_item_builds,
"Most Frequent Big Items:",
),
];
2021-03-15 23:00:20 +01:00
2021-10-30 11:54:32 +02:00
data.push((
position.to_owned(),
blocks,
Stat {
2021-11-01 08:35:19 +01:00
win_rate: (champ.stats.wins as f32 / champ.stats.games as f32) * 100f32,
2021-10-30 11:54:32 +02:00
games: champ.stats.games,
2021-11-01 08:35:19 +01:00
kda: (champ.stats.kills + champ.stats.assists) as f32
/ champ.stats.deaths as f32,
2021-10-30 11:54:32 +02:00
patch: champ.patch.to_owned(),
},
));
2021-03-15 23:00:20 +01:00
}
2018-06-16 10:48:46 +02:00
}
2021-03-15 23:00:20 +01:00
data
2018-06-16 10:48:46 +02:00
}
}