Initilization new impl CGG
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
456f2e9624
commit
215f922020
5 changed files with 114 additions and 109 deletions
|
@ -1,31 +1,54 @@
|
|||
use indexmap::IndexMap;
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
use select::document::Document;
|
||||
use select::predicate::{Class, Name};
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::{json, Value};
|
||||
|
||||
use crate::data_source::DataSource;
|
||||
use crate::ChampInfo;
|
||||
|
||||
const CONSUMABLES: [u32; 9] = [2003, 2004, 2055, 2031, 2032, 2033, 2138, 2140, 2139];
|
||||
const TRINKETS: [u32; 3] = [3340, 3364, 3363];
|
||||
const ITEM_TYPES: & [(&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"]),
|
||||
];
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct BuildResponse {
|
||||
lol: Lol
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct Lol {
|
||||
#[serde(rename = "championsReport")]
|
||||
champions_report: Vec<ChampionReport>
|
||||
}
|
||||
|
||||
#[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<u32>,
|
||||
win_rate: f64,
|
||||
games: u32
|
||||
}
|
||||
|
||||
static mut CHAMPIONS_REPORT: Vec<ChampionReport> = Vec::new();
|
||||
|
||||
pub struct CGGDataSource;
|
||||
|
||||
impl CGGDataSource {
|
||||
fn make_item_set(&self, data: &Value, label: &str) -> Value {
|
||||
fn make_item_set(&self, build: &Build, 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())
|
||||
"items": build.build.iter().map(|x| json!({"id": x, "count": 1})).collect::<Vec<Value>>(),
|
||||
"type": format!("{} ({:.2}% - {} games)", label, build.win_rate * 100., build.games)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -67,96 +90,59 @@ impl DataSource for CGGDataSource {
|
|||
&self,
|
||||
client: &ureq::Agent,
|
||||
) -> (IndexMap<String, Vec<String>>, String) {
|
||||
let page = client
|
||||
let req = client
|
||||
.get("https://champion.gg")
|
||||
.call()
|
||||
.unwrap()
|
||||
.into_string()
|
||||
.unwrap();
|
||||
let document = Document::from(&*page);
|
||||
|
||||
let patch = document
|
||||
.find(Class("analysis-holder"))
|
||||
.next()
|
||||
.unwrap()
|
||||
.find(Name("strong"))
|
||||
.next()
|
||||
.unwrap()
|
||||
.text();
|
||||
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 = String::from(datas.lol.champions_report[0].patch.as_str());
|
||||
|
||||
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();
|
||||
for champ in &datas.lol.champions_report {
|
||||
let id = champ.champion_id.to_string();
|
||||
let positions = [String::from(&champ.role)].to_vec();
|
||||
champions.insert(id, positions);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
CHAMPIONS_REPORT = datas.lol.champions_report;
|
||||
}
|
||||
|
||||
(champions, patch)
|
||||
}
|
||||
|
||||
fn get_champ_data_with_win_pourcentage(
|
||||
&self,
|
||||
id: &str,
|
||||
champ: &ChampInfo,
|
||||
position: &str,
|
||||
client: &ureq::Agent,
|
||||
_client: &ureq::Agent,
|
||||
) -> Option<(Vec<Value>, f64)> {
|
||||
let req = client
|
||||
.get(&format!(
|
||||
"https://champion.gg/champion/{}/{}?league=",
|
||||
id, position
|
||||
))
|
||||
.call()
|
||||
.unwrap();
|
||||
let response_status = req.status();
|
||||
if (200..300).contains(&response_status) {
|
||||
lazy_static! {
|
||||
static ref RE: Regex =
|
||||
Regex::new(r"(?m)^\s+matchupData\.championData = (.*)$").unwrap();
|
||||
}
|
||||
let data: Value =
|
||||
serde_json::from_str(&RE.captures(&req.into_string().unwrap())?[1]).unwrap();
|
||||
let mut blocks = vec![];
|
||||
for (label, path) in ITEM_TYPES.iter() {
|
||||
if data[&path[0]].get(&path[1]).is_some() {
|
||||
blocks.push(self.make_item_set(&data[&path[0]][&path[1]], label));
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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.))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use serde_derive::{Deserialize, Serialize};
|
|||
use serde_json::Value;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use crate::ChampInfo;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct ItemSet {
|
||||
|
@ -40,22 +41,21 @@ pub trait DataSource {
|
|||
|
||||
fn get_champ_data_with_win_pourcentage(
|
||||
&self,
|
||||
id: &str,
|
||||
champ: &ChampInfo,
|
||||
position: &str,
|
||||
client: &ureq::Agent,
|
||||
) -> Option<(Vec<Value>, f64)>;
|
||||
|
||||
fn write_item_set(
|
||||
&self,
|
||||
id: &str,
|
||||
name: &str,
|
||||
champ: &ChampInfo,
|
||||
pos: &str,
|
||||
ver: &str,
|
||||
path: &PathBuf,
|
||||
client: &ureq::Agent,
|
||||
) {
|
||||
info!("Retrieving data for {} at {}", name, pos);
|
||||
let data = self.get_champ_data_with_win_pourcentage(id, pos, client);
|
||||
info!("Retrieving data for {} at {}", champ.name, pos);
|
||||
let data = self.get_champ_data_with_win_pourcentage(champ, pos, client);
|
||||
|
||||
match data {
|
||||
Some(data) => {
|
||||
|
@ -69,15 +69,15 @@ pub trait DataSource {
|
|||
blocks: data.0,
|
||||
};
|
||||
|
||||
info!("Writing item set for {} at {}", name, pos);
|
||||
info!("Writing item set for {} at {}", champ.name, pos);
|
||||
fs::write(
|
||||
path.join(format!("{}_{}_{}.json", self.get_alias(), id, pos)),
|
||||
path.join(format!("{}_{}_{}.json", self.get_alias(), champ.id, pos)),
|
||||
serde_json::to_string_pretty(&item_set).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
None => {
|
||||
error!("Can't get data for {} at {}", id, pos);
|
||||
error!("Can't get data for {} at {}", champ.id, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ use indexmap::IndexMap;
|
|||
use regex::Regex;
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::{json, Value};
|
||||
use crate::ChampInfo;
|
||||
|
||||
pub struct KBDataSource {
|
||||
token: Option<String>,
|
||||
|
@ -203,7 +204,7 @@ impl DataSource for KBDataSource {
|
|||
|
||||
fn get_champ_data_with_win_pourcentage(
|
||||
&self,
|
||||
id: &str,
|
||||
champ: &ChampInfo,
|
||||
position: &str,
|
||||
client: &ureq::Agent,
|
||||
) -> Option<(Vec<Value>, f64)> {
|
||||
|
@ -211,7 +212,7 @@ impl DataSource for KBDataSource {
|
|||
Some(t) => t,
|
||||
None => return None,
|
||||
};
|
||||
let map_id = match self.internal_classname_mapping.get(id) {
|
||||
let map_id = match self.internal_classname_mapping.get(&champ.id) {
|
||||
Some(m_id) => m_id,
|
||||
None => return None,
|
||||
};
|
||||
|
@ -375,7 +376,8 @@ mod tests {
|
|||
.timeout(Duration::from_secs(10))
|
||||
.build();
|
||||
let datasource = KBDataSource::new(&client);
|
||||
let result = datasource.get_champ_data_with_win_pourcentage("Aatrox", "TOP", &client);
|
||||
let champ = ChampInfo{id: String::from("Aatrox"), name: String::from("Aatrox"), key: String::from("1")};
|
||||
let result = datasource.get_champ_data_with_win_pourcentage(&champ, "TOP", &client);
|
||||
assert!(result.is_some());
|
||||
match result {
|
||||
Some(value) => {
|
||||
|
|
34
src/main.rs
34
src/main.rs
|
@ -16,7 +16,7 @@ mod data_source;
|
|||
mod kb_data_source;
|
||||
mod pb_data_source;
|
||||
|
||||
// use cgg_data_source::CGGDataSource;
|
||||
use cgg_data_source::CGGDataSource;
|
||||
use data_source::DataSource;
|
||||
use kb_data_source::KBDataSource;
|
||||
use pb_data_source::PBDataSource;
|
||||
|
@ -32,13 +32,15 @@ struct Champion {
|
|||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ChampInfo {
|
||||
pub struct ChampInfo {
|
||||
id: String,
|
||||
name: String,
|
||||
key: String
|
||||
}
|
||||
|
||||
const USER_AGENT_KEY: &str = "User-Agent";
|
||||
const USER_AGENT_VALUE: &str =
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0";
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0";
|
||||
const LOL_CHAMPS_DIR: &str = ".\\champs";
|
||||
|
||||
fn main() {
|
||||
|
@ -81,9 +83,9 @@ fn main() {
|
|||
.unwrap();
|
||||
info!("LoL numbers of champs: {}", champion.data.len());
|
||||
|
||||
let data_sources: [Box<dyn DataSource>; 2] = [
|
||||
let data_sources: [Box<dyn DataSource>; 3] = [
|
||||
Box::new(PBDataSource),
|
||||
// Box::new(CGGDataSource),
|
||||
Box::new(CGGDataSource),
|
||||
Box::new(KBDataSource::new(&client)),
|
||||
];
|
||||
|
||||
|
@ -98,13 +100,18 @@ fn main() {
|
|||
);
|
||||
|
||||
for (id, positions) in &champs {
|
||||
if champion.data.contains_key(id) {
|
||||
let path = lol_champs_dir.join(&id).join("Recommended");
|
||||
let mut champ_id: String = String::from(id);
|
||||
|
||||
if !champion.data.contains_key(&champ_id) {
|
||||
champ_id = get_champ_from_key(&champion, &champ_id);
|
||||
}
|
||||
|
||||
if champion.data.contains_key(&champ_id) {
|
||||
let path = lol_champs_dir.join(&champ_id).join("Recommended");
|
||||
fs::create_dir_all(&path).unwrap();
|
||||
for pos in positions {
|
||||
data_source.write_item_set(
|
||||
&id,
|
||||
&champion.data.get(id).unwrap().name,
|
||||
&champion.data.get(&champ_id).unwrap(),
|
||||
&pos,
|
||||
&patch,
|
||||
&path,
|
||||
|
@ -119,6 +126,15 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_champ_from_key(champs: &Champion, key: &String) -> String {
|
||||
for champ in champs.data.values() {
|
||||
if key == &champ.key {
|
||||
return champ.id.clone();
|
||||
}
|
||||
}
|
||||
String::new()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn lol_champ_dir() -> Result<PathBuf, Error> {
|
||||
let hklm = RegKey::predef(winreg::enums::HKEY_LOCAL_MACHINE);
|
||||
|
|
|
@ -2,6 +2,7 @@ use indexmap::IndexMap;
|
|||
use serde_json::Value;
|
||||
|
||||
use crate::data_source::DataSource;
|
||||
use crate::ChampInfo;
|
||||
|
||||
pub struct PBDataSource;
|
||||
impl DataSource for PBDataSource {
|
||||
|
@ -18,7 +19,7 @@ impl DataSource for PBDataSource {
|
|||
|
||||
fn get_champ_data_with_win_pourcentage(
|
||||
&self,
|
||||
_id: &str,
|
||||
_champ: &ChampInfo,
|
||||
_position: &str,
|
||||
_client: &ureq::Agent,
|
||||
) -> Option<(Vec<Value>, f64)> {
|
||||
|
|
Loading…
Add table
Reference in a new issue