Initilization new impl CGG
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
nyyu 2021-03-13 23:02:26 +01:00
parent 456f2e9624
commit 215f922020
5 changed files with 114 additions and 109 deletions

View file

@ -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 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);
}
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![];
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));
}
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));
}
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
}
}
}

View file

@ -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);
}
}
}

View file

@ -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) => {

View file

@ -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);

View file

@ -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)> {