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 indexmap::IndexMap;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use select::document::Document;
|
use serde_derive::Deserialize;
|
||||||
use select::predicate::{Class, Name};
|
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
use crate::data_source::DataSource;
|
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];
|
#[derive(Deserialize, Debug)]
|
||||||
const ITEM_TYPES: & [(&str, [&str; 2]); 4] = &[
|
struct BuildResponse {
|
||||||
("Most Frequent Starters", ["firstItems", "mostGames"]),
|
lol: Lol
|
||||||
(
|
}
|
||||||
"Highest Win % Starters",
|
|
||||||
["firstItems", "highestWinPercent"],
|
#[derive(Deserialize, Debug)]
|
||||||
),
|
struct Lol {
|
||||||
("Most Frequent Core Build", ["items", "mostGames"]),
|
#[serde(rename = "championsReport")]
|
||||||
("Highest Win % Core Build", ["items", "highestWinPercent"]),
|
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;
|
pub struct CGGDataSource;
|
||||||
|
|
||||||
impl CGGDataSource {
|
impl CGGDataSource {
|
||||||
fn make_item_set(&self, data: &Value, label: &str) -> Value {
|
fn make_item_set(&self, build: &Build, label: &str) -> Value {
|
||||||
json!({
|
json!({
|
||||||
"items": data["items"].as_array().unwrap().iter().map(|x| json!({"id": x["id"].as_str(), "count": 1})).collect::<Vec<Value>>(),
|
"items": build.build.iter().map(|x| json!({"id": x, "count": 1})).collect::<Vec<Value>>(),
|
||||||
"type": format!("{} ({:.2}% - {} games)", label, data["winPercent"].as_f64().unwrap() * 100., data["games"].as_u64().unwrap())
|
"type": format!("{} ({:.2}% - {} games)", label, build.win_rate * 100., build.games)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,96 +90,59 @@ impl DataSource for CGGDataSource {
|
||||||
&self,
|
&self,
|
||||||
client: &ureq::Agent,
|
client: &ureq::Agent,
|
||||||
) -> (IndexMap<String, Vec<String>>, String) {
|
) -> (IndexMap<String, Vec<String>>, String) {
|
||||||
let page = client
|
let req = client
|
||||||
.get("https://champion.gg")
|
.get("https://champion.gg")
|
||||||
.call()
|
.call()
|
||||||
.unwrap()
|
|
||||||
.into_string()
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let document = Document::from(&*page);
|
|
||||||
|
|
||||||
let patch = document
|
lazy_static! {
|
||||||
.find(Class("analysis-holder"))
|
static ref RE: Regex =
|
||||||
.next()
|
Regex::new(r"(?m)^\s+window.__PRELOADED_STATE__ = (.*);$").unwrap();
|
||||||
.unwrap()
|
}
|
||||||
.find(Name("strong"))
|
|
||||||
.next()
|
let datas: BuildResponse =
|
||||||
.unwrap()
|
serde_json::from_str(&RE.captures(&req.into_string().unwrap()).unwrap()[1].replace("undefined", "null")).unwrap();
|
||||||
.text();
|
|
||||||
|
let patch = String::from(datas.lol.champions_report[0].patch.as_str());
|
||||||
|
|
||||||
let mut champions = IndexMap::new();
|
let mut champions = IndexMap::new();
|
||||||
for node in document.find(Class("champ-height")) {
|
for champ in &datas.lol.champions_report {
|
||||||
let id = node
|
let id = champ.champion_id.to_string();
|
||||||
.find(Class("home-champion"))
|
let positions = [String::from(&champ.role)].to_vec();
|
||||||
.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.insert(id, positions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
CHAMPIONS_REPORT = datas.lol.champions_report;
|
||||||
|
}
|
||||||
|
|
||||||
(champions, patch)
|
(champions, patch)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_champ_data_with_win_pourcentage(
|
fn get_champ_data_with_win_pourcentage(
|
||||||
&self,
|
&self,
|
||||||
id: &str,
|
champ: &ChampInfo,
|
||||||
position: &str,
|
position: &str,
|
||||||
client: &ureq::Agent,
|
_client: &ureq::Agent,
|
||||||
) -> Option<(Vec<Value>, f64)> {
|
) -> Option<(Vec<Value>, f64)> {
|
||||||
let req = client
|
|
||||||
.get(&format!(
|
let mut some_champ: Option<&ChampionReport> = None;
|
||||||
"https://champion.gg/champion/{}/{}?league=",
|
unsafe {
|
||||||
id, position
|
for champion in &CHAMPIONS_REPORT {
|
||||||
))
|
if champion.champion_id.to_string() == champ.key && champion.role == position {
|
||||||
.call()
|
some_champ = Some(champion);
|
||||||
.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();
|
}
|
||||||
|
if let Some(champ) = some_champ {
|
||||||
let mut blocks = vec![];
|
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(&champ.stats.starting_items, "Highest % Win Starting Items"));
|
||||||
blocks.push(self.make_item_set(&data[&path[0]][&path[1]], label));
|
blocks.push(self.make_item_set(&champ.stats.core_builds, "Highest % Win Core Build Path:"));
|
||||||
}
|
|
||||||
|
return Some((blocks, 42.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ use serde_derive::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use crate::ChampInfo;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct ItemSet {
|
struct ItemSet {
|
||||||
|
@ -40,22 +41,21 @@ pub trait DataSource {
|
||||||
|
|
||||||
fn get_champ_data_with_win_pourcentage(
|
fn get_champ_data_with_win_pourcentage(
|
||||||
&self,
|
&self,
|
||||||
id: &str,
|
champ: &ChampInfo,
|
||||||
position: &str,
|
position: &str,
|
||||||
client: &ureq::Agent,
|
client: &ureq::Agent,
|
||||||
) -> Option<(Vec<Value>, f64)>;
|
) -> Option<(Vec<Value>, f64)>;
|
||||||
|
|
||||||
fn write_item_set(
|
fn write_item_set(
|
||||||
&self,
|
&self,
|
||||||
id: &str,
|
champ: &ChampInfo,
|
||||||
name: &str,
|
|
||||||
pos: &str,
|
pos: &str,
|
||||||
ver: &str,
|
ver: &str,
|
||||||
path: &PathBuf,
|
path: &PathBuf,
|
||||||
client: &ureq::Agent,
|
client: &ureq::Agent,
|
||||||
) {
|
) {
|
||||||
info!("Retrieving data for {} at {}", name, pos);
|
info!("Retrieving data for {} at {}", champ.name, pos);
|
||||||
let data = self.get_champ_data_with_win_pourcentage(id, pos, client);
|
let data = self.get_champ_data_with_win_pourcentage(champ, pos, client);
|
||||||
|
|
||||||
match data {
|
match data {
|
||||||
Some(data) => {
|
Some(data) => {
|
||||||
|
@ -69,15 +69,15 @@ pub trait DataSource {
|
||||||
blocks: data.0,
|
blocks: data.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("Writing item set for {} at {}", name, pos);
|
info!("Writing item set for {} at {}", champ.name, pos);
|
||||||
fs::write(
|
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(),
|
serde_json::to_string_pretty(&item_set).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
None => {
|
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 regex::Regex;
|
||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
use crate::ChampInfo;
|
||||||
|
|
||||||
pub struct KBDataSource {
|
pub struct KBDataSource {
|
||||||
token: Option<String>,
|
token: Option<String>,
|
||||||
|
@ -203,7 +204,7 @@ impl DataSource for KBDataSource {
|
||||||
|
|
||||||
fn get_champ_data_with_win_pourcentage(
|
fn get_champ_data_with_win_pourcentage(
|
||||||
&self,
|
&self,
|
||||||
id: &str,
|
champ: &ChampInfo,
|
||||||
position: &str,
|
position: &str,
|
||||||
client: &ureq::Agent,
|
client: &ureq::Agent,
|
||||||
) -> Option<(Vec<Value>, f64)> {
|
) -> Option<(Vec<Value>, f64)> {
|
||||||
|
@ -211,7 +212,7 @@ impl DataSource for KBDataSource {
|
||||||
Some(t) => t,
|
Some(t) => t,
|
||||||
None => return None,
|
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,
|
Some(m_id) => m_id,
|
||||||
None => return None,
|
None => return None,
|
||||||
};
|
};
|
||||||
|
@ -375,7 +376,8 @@ mod tests {
|
||||||
.timeout(Duration::from_secs(10))
|
.timeout(Duration::from_secs(10))
|
||||||
.build();
|
.build();
|
||||||
let datasource = KBDataSource::new(&client);
|
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());
|
assert!(result.is_some());
|
||||||
match result {
|
match result {
|
||||||
Some(value) => {
|
Some(value) => {
|
||||||
|
|
34
src/main.rs
34
src/main.rs
|
@ -16,7 +16,7 @@ mod data_source;
|
||||||
mod kb_data_source;
|
mod kb_data_source;
|
||||||
mod pb_data_source;
|
mod pb_data_source;
|
||||||
|
|
||||||
// use cgg_data_source::CGGDataSource;
|
use cgg_data_source::CGGDataSource;
|
||||||
use data_source::DataSource;
|
use data_source::DataSource;
|
||||||
use kb_data_source::KBDataSource;
|
use kb_data_source::KBDataSource;
|
||||||
use pb_data_source::PBDataSource;
|
use pb_data_source::PBDataSource;
|
||||||
|
@ -32,13 +32,15 @@ struct Champion {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct ChampInfo {
|
pub struct ChampInfo {
|
||||||
|
id: String,
|
||||||
name: String,
|
name: String,
|
||||||
|
key: String
|
||||||
}
|
}
|
||||||
|
|
||||||
const USER_AGENT_KEY: &str = "User-Agent";
|
const USER_AGENT_KEY: &str = "User-Agent";
|
||||||
const USER_AGENT_VALUE: &str =
|
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";
|
const LOL_CHAMPS_DIR: &str = ".\\champs";
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -81,9 +83,9 @@ fn main() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
info!("LoL numbers of champs: {}", champion.data.len());
|
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(PBDataSource),
|
||||||
// Box::new(CGGDataSource),
|
Box::new(CGGDataSource),
|
||||||
Box::new(KBDataSource::new(&client)),
|
Box::new(KBDataSource::new(&client)),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -98,13 +100,18 @@ fn main() {
|
||||||
);
|
);
|
||||||
|
|
||||||
for (id, positions) in &champs {
|
for (id, positions) in &champs {
|
||||||
if champion.data.contains_key(id) {
|
let mut champ_id: String = String::from(id);
|
||||||
let path = lol_champs_dir.join(&id).join("Recommended");
|
|
||||||
|
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();
|
fs::create_dir_all(&path).unwrap();
|
||||||
for pos in positions {
|
for pos in positions {
|
||||||
data_source.write_item_set(
|
data_source.write_item_set(
|
||||||
&id,
|
&champion.data.get(&champ_id).unwrap(),
|
||||||
&champion.data.get(id).unwrap().name,
|
|
||||||
&pos,
|
&pos,
|
||||||
&patch,
|
&patch,
|
||||||
&path,
|
&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")]
|
#[cfg(target_os = "windows")]
|
||||||
fn lol_champ_dir() -> Result<PathBuf, Error> {
|
fn lol_champ_dir() -> Result<PathBuf, Error> {
|
||||||
let hklm = RegKey::predef(winreg::enums::HKEY_LOCAL_MACHINE);
|
let hklm = RegKey::predef(winreg::enums::HKEY_LOCAL_MACHINE);
|
||||||
|
|
|
@ -2,6 +2,7 @@ use indexmap::IndexMap;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::data_source::DataSource;
|
use crate::data_source::DataSource;
|
||||||
|
use crate::ChampInfo;
|
||||||
|
|
||||||
pub struct PBDataSource;
|
pub struct PBDataSource;
|
||||||
impl DataSource for PBDataSource {
|
impl DataSource for PBDataSource {
|
||||||
|
@ -18,7 +19,7 @@ impl DataSource for PBDataSource {
|
||||||
|
|
||||||
fn get_champ_data_with_win_pourcentage(
|
fn get_champ_data_with_win_pourcentage(
|
||||||
&self,
|
&self,
|
||||||
_id: &str,
|
_champ: &ChampInfo,
|
||||||
_position: &str,
|
_position: &str,
|
||||||
_client: &ureq::Agent,
|
_client: &ureq::Agent,
|
||||||
) -> Option<(Vec<Value>, f64)> {
|
) -> Option<(Vec<Value>, f64)> {
|
||||||
|
|
Loading…
Add table
Reference in a new issue