2018-06-16 10:48:46 +02:00
|
|
|
use indexmap::IndexMap;
|
2019-09-30 17:56:03 +02:00
|
|
|
use lazy_static::lazy_static;
|
2018-06-16 10:48:46 +02:00
|
|
|
use regex::Regex;
|
|
|
|
use select::document::Document;
|
|
|
|
use select::predicate::{Class, Name};
|
2019-09-30 17:56:03 +02:00
|
|
|
use serde_json::{json, Value};
|
2018-06-16 10:48:46 +02:00
|
|
|
|
2019-09-26 22:39:25 +02:00
|
|
|
use crate::data_source::DataSource;
|
2018-06-16 10:48:46 +02:00
|
|
|
|
2019-09-30 17:56:03 +02:00
|
|
|
const CONSUMABLES: [u32; 9] = [2003, 2004, 2055, 2031, 2032, 2033, 2138, 2140, 2139];
|
|
|
|
const TRINKETS: [u32; 3] = [3340, 3364, 3363];
|
|
|
|
const ITEM_TYPES: &'static [(&str, [&str; 2]); 4] = &[
|
|
|
|
("Most Frequent Starters", ["firstItems", "mostGames"]),
|
|
|
|
(
|
|
|
|
"Highest Win % Starters",
|
|
|
|
["firstItems", "highestWinPercent"],
|
|
|
|
),
|
|
|
|
("Most Frequent Core Build", ["items", "mostGames"]),
|
|
|
|
("Highest Win % Core Build", ["items", "highestWinPercent"]),
|
|
|
|
];
|
|
|
|
|
2018-06-16 10:48:46 +02:00
|
|
|
pub struct CGGDataSource;
|
2019-09-30 17:56:03 +02:00
|
|
|
|
|
|
|
impl CGGDataSource {
|
|
|
|
fn make_item_set(&self, data: &Value, label: &str) -> Value {
|
|
|
|
json!({
|
|
|
|
"items": data["items"].as_array().unwrap().iter().map(|x| json!({"id": x["id"].as_str(), "count": 1})).collect::<Vec<Value>>(),
|
|
|
|
"type": format!("{} ({:.2}% - {} games)", label, data["winPercent"].as_f64().unwrap() * 100., data["games"].as_u64().unwrap())
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn make_item_set_from_list(
|
|
|
|
&self,
|
|
|
|
list: &Vec<u32>,
|
|
|
|
label: &str,
|
|
|
|
key: &str,
|
|
|
|
data: &Value,
|
|
|
|
) -> Value {
|
|
|
|
let mut key_order = String::new();
|
|
|
|
if !data["skills"].get("skillInfo").is_none() {
|
|
|
|
key_order = data["skills"][key]["order"]
|
|
|
|
.as_array()
|
|
|
|
.unwrap()
|
|
|
|
.iter()
|
|
|
|
.map(|x| {
|
|
|
|
data["skills"]["skillInfo"].as_array().unwrap()
|
|
|
|
[x.as_str().unwrap().parse::<usize>().unwrap() - 1]["key"]
|
|
|
|
.as_str()
|
|
|
|
.unwrap()
|
|
|
|
})
|
|
|
|
.collect::<Vec<&str>>()
|
|
|
|
.join(".");
|
|
|
|
}
|
|
|
|
json!({
|
|
|
|
"items": list.iter().map(|x| json!({"id": x.to_string(), "count": 1})).collect::<Vec<Value>>(),
|
|
|
|
"type": format!("{} {}", label, key_order)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-16 10:48:46 +02:00
|
|
|
impl DataSource for CGGDataSource {
|
2019-09-30 17:56:03 +02:00
|
|
|
fn get_alias(&self) -> &str {
|
|
|
|
"CGG"
|
|
|
|
}
|
|
|
|
|
2018-06-16 10:48:46 +02:00
|
|
|
fn get_champs_with_positions_and_patch(
|
2018-06-16 12:48:14 +02:00
|
|
|
&self,
|
2021-03-10 12:22:00 +01:00
|
|
|
client: &ureq::Agent,
|
2018-06-16 10:48:46 +02:00
|
|
|
) -> (IndexMap<String, Vec<String>>, String) {
|
|
|
|
let page = client
|
|
|
|
.get("https://champion.gg")
|
2021-03-10 12:22:00 +01:00
|
|
|
.call()
|
2018-06-16 10:48:46 +02:00
|
|
|
.unwrap()
|
2021-03-10 12:22:00 +01:00
|
|
|
.into_string()
|
2018-06-16 10:48:46 +02:00
|
|
|
.unwrap();
|
|
|
|
let document = Document::from(&*page);
|
|
|
|
|
|
|
|
let patch = document
|
|
|
|
.find(Class("analysis-holder"))
|
|
|
|
.next()
|
|
|
|
.unwrap()
|
|
|
|
.find(Name("strong"))
|
|
|
|
.next()
|
|
|
|
.unwrap()
|
|
|
|
.text();
|
|
|
|
|
|
|
|
let mut champions = IndexMap::new();
|
|
|
|
for node in document.find(Class("champ-height")) {
|
|
|
|
let id = node
|
|
|
|
.find(Class("home-champion"))
|
|
|
|
.next()
|
|
|
|
.unwrap()
|
|
|
|
.attr("class")
|
|
|
|
.unwrap()
|
|
|
|
.split(' ')
|
|
|
|
.last()
|
|
|
|
.unwrap()
|
|
|
|
.to_string();
|
|
|
|
let positions = node
|
|
|
|
.find(Name("a"))
|
|
|
|
.skip(1)
|
|
|
|
.map(|x| {
|
|
|
|
x.attr("href")
|
|
|
|
.unwrap()
|
|
|
|
.split('/')
|
|
|
|
.last()
|
|
|
|
.unwrap()
|
|
|
|
.to_string()
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
champions.insert(id, positions);
|
|
|
|
}
|
|
|
|
|
|
|
|
(champions, patch)
|
|
|
|
}
|
|
|
|
|
2019-09-30 17:56:03 +02:00
|
|
|
fn get_champ_data_with_win_pourcentage(
|
|
|
|
&self,
|
|
|
|
id: &str,
|
|
|
|
position: &str,
|
2021-03-10 12:22:00 +01:00
|
|
|
client: &ureq::Agent,
|
2019-09-30 17:56:03 +02:00
|
|
|
) -> Option<(Vec<Value>, f64)> {
|
2020-06-28 18:34:31 +02:00
|
|
|
let req = client
|
2018-06-16 10:48:46 +02:00
|
|
|
.get(&format!(
|
|
|
|
"https://champion.gg/champion/{}/{}?league=",
|
|
|
|
id, position
|
|
|
|
))
|
2021-03-10 12:22:00 +01:00
|
|
|
.call()
|
2018-06-16 10:48:46 +02:00
|
|
|
.unwrap();
|
2021-03-10 12:22:00 +01:00
|
|
|
let response_status = req.status();
|
|
|
|
if 300 > response_status && response_status >= 200 {
|
2018-06-16 10:48:46 +02:00
|
|
|
lazy_static! {
|
|
|
|
static ref RE: Regex =
|
|
|
|
Regex::new(r"(?m)^\s+matchupData\.championData = (.*)$").unwrap();
|
|
|
|
}
|
2021-03-10 12:22:00 +01:00
|
|
|
let data: Value =
|
|
|
|
serde_json::from_str(&RE.captures(&req.into_string().unwrap())?[1]).unwrap();
|
2019-09-30 17:56:03 +02:00
|
|
|
let mut blocks = vec![];
|
|
|
|
for (label, path) in ITEM_TYPES.iter() {
|
|
|
|
if !data[&path[0]].get(&path[1]).is_none() {
|
|
|
|
blocks.push(self.make_item_set(&data[&path[0]][&path[1]], label));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
blocks.push(self.make_item_set_from_list(
|
|
|
|
&CONSUMABLES.to_vec(),
|
|
|
|
"Consumables | Frequent:",
|
|
|
|
"mostGames",
|
|
|
|
&data,
|
|
|
|
));
|
|
|
|
blocks.push(self.make_item_set_from_list(
|
|
|
|
&TRINKETS.to_vec(),
|
|
|
|
"Trinkets | Wins:",
|
|
|
|
"highestWinPercent",
|
|
|
|
&data,
|
|
|
|
));
|
|
|
|
Some((blocks, data["stats"]["winRate"].as_f64().unwrap() * 100.))
|
2018-06-16 10:48:46 +02:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|