Debut implementation KB
* Datasource créé * Auth fait * Récupération des champions fait * Rework à faire au niveau du datasource (signature méthode + déplacement code propre à CGG) Refacto DataSource Avancement implementation KB Lint code Implementation KB ok
This commit is contained in:
parent
c7d557e2f8
commit
9fdde8f4de
5 changed files with 526 additions and 92 deletions
|
@ -1,14 +1,68 @@
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use select::document::Document;
|
use select::document::Document;
|
||||||
use select::predicate::{Class, Name};
|
use select::predicate::{Class, Name};
|
||||||
use serde_json::Value;
|
use serde_json::{json, Value};
|
||||||
use lazy_static::{lazy_static};
|
|
||||||
|
|
||||||
use crate::data_source::DataSource;
|
use crate::data_source::DataSource;
|
||||||
|
|
||||||
|
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"]),
|
||||||
|
];
|
||||||
|
|
||||||
pub struct CGGDataSource;
|
pub struct CGGDataSource;
|
||||||
|
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl DataSource for CGGDataSource {
|
impl DataSource for CGGDataSource {
|
||||||
|
fn get_alias(&self) -> &str {
|
||||||
|
"CGG"
|
||||||
|
}
|
||||||
|
|
||||||
fn get_champs_with_positions_and_patch(
|
fn get_champs_with_positions_and_patch(
|
||||||
&self,
|
&self,
|
||||||
client: &reqwest::Client,
|
client: &reqwest::Client,
|
||||||
|
@ -60,7 +114,12 @@ impl DataSource for CGGDataSource {
|
||||||
(champions, patch)
|
(champions, patch)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_champ_data(&self, id: &str, position: &str, client: &reqwest::Client) -> Option<Value> {
|
fn get_champ_data_with_win_pourcentage(
|
||||||
|
&self,
|
||||||
|
id: &str,
|
||||||
|
position: &str,
|
||||||
|
client: &reqwest::Client,
|
||||||
|
) -> Option<(Vec<Value>, f64)> {
|
||||||
let mut req = client
|
let mut req = client
|
||||||
.get(&format!(
|
.get(&format!(
|
||||||
"https://champion.gg/champion/{}/{}?league=",
|
"https://champion.gg/champion/{}/{}?league=",
|
||||||
|
@ -73,7 +132,27 @@ impl DataSource for CGGDataSource {
|
||||||
static ref RE: Regex =
|
static ref RE: Regex =
|
||||||
Regex::new(r"(?m)^\s+matchupData\.championData = (.*)$").unwrap();
|
Regex::new(r"(?m)^\s+matchupData\.championData = (.*)$").unwrap();
|
||||||
}
|
}
|
||||||
serde_json::from_str(&RE.captures(&req.text().unwrap())?[1]).unwrap()
|
let data: Value = serde_json::from_str(&RE.captures(&req.text().unwrap())?[1]).unwrap();
|
||||||
|
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.))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use serde_json::{Value, json};
|
use log::{error, info};
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
use serde_json::Value;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use log::{info, error};
|
|
||||||
use serde_derive::{Serialize, Deserialize};
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct ItemSet {
|
struct ItemSet {
|
||||||
|
@ -17,59 +17,34 @@ struct ItemSet {
|
||||||
blocks: Vec<Value>,
|
blocks: Vec<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const CONSUMABLES: [u32; 9] = [2003, 2004, 2055, 2031, 2032, 2033, 2138, 2140, 2139];
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
const TRINKETS: [u32; 3] = [3340, 3364, 3363];
|
pub struct Build {
|
||||||
const ITEM_TYPES: &'static [(&str, [&str; 2]); 4] = &[
|
#[serde(rename = "type")]
|
||||||
("Most Frequent Starters", ["firstItems", "mostGames"]),
|
pub type_: String,
|
||||||
(
|
pub items: Vec<Item>,
|
||||||
"Highest Win % Starters",
|
}
|
||||||
["firstItems", "highestWinPercent"],
|
|
||||||
),
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
("Most Frequent Core Build", ["items", "mostGames"]),
|
pub struct Item {
|
||||||
("Highest Win % Core Build", ["items", "highestWinPercent"]),
|
pub id: String,
|
||||||
];
|
pub count: u8,
|
||||||
|
}
|
||||||
|
|
||||||
pub trait DataSource {
|
pub trait DataSource {
|
||||||
|
fn get_alias(&self) -> &str;
|
||||||
|
|
||||||
fn get_champs_with_positions_and_patch(
|
fn get_champs_with_positions_and_patch(
|
||||||
&self,
|
&self,
|
||||||
client: &reqwest::Client,
|
client: &reqwest::Client,
|
||||||
) -> (IndexMap<String, Vec<String>>, String);
|
) -> (IndexMap<String, Vec<String>>, String);
|
||||||
fn get_champ_data(&self, id: &str, position: &str, client: &reqwest::Client) -> Option<Value>;
|
|
||||||
|
|
||||||
fn make_item_set(&self, data: &Value, label: &str) -> Value {
|
fn get_champ_data_with_win_pourcentage(
|
||||||
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,
|
&self,
|
||||||
list: &Vec<u32>,
|
id: &str,
|
||||||
label: &str,
|
position: &str,
|
||||||
key: &str,
|
client: &reqwest::Client,
|
||||||
data: &Value,
|
) -> Option<(Vec<Value>, f64)>;
|
||||||
) -> 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)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
fn write_item_set(
|
fn write_item_set(
|
||||||
&self,
|
&self,
|
||||||
id: &str,
|
id: &str,
|
||||||
|
@ -80,49 +55,23 @@ pub trait DataSource {
|
||||||
client: &reqwest::Client,
|
client: &reqwest::Client,
|
||||||
) {
|
) {
|
||||||
info!("Retrieving data for {} at {}", name, pos);
|
info!("Retrieving data for {} at {}", name, pos);
|
||||||
let data = self.get_champ_data(id, pos, client);
|
let data = self.get_champ_data_with_win_pourcentage(id, pos, client);
|
||||||
|
|
||||||
match data {
|
match data {
|
||||||
Some(data) => {
|
Some(data) => {
|
||||||
let mut item_set = ItemSet {
|
let item_set = ItemSet {
|
||||||
title: format!(
|
title: format!("{} {} {} - {:.2}%", self.get_alias(), pos, ver, data.1),
|
||||||
"CGG {} {} - {:.2}%",
|
|
||||||
pos,
|
|
||||||
ver,
|
|
||||||
data["stats"]["winRate"].as_f64().unwrap() * 100.
|
|
||||||
),
|
|
||||||
type_: "custom".to_string(),
|
type_: "custom".to_string(),
|
||||||
map: "any".to_string(),
|
map: "any".to_string(),
|
||||||
mode: "any".to_string(),
|
mode: "any".to_string(),
|
||||||
priority: false,
|
priority: false,
|
||||||
sortrank: 0,
|
sortrank: 0,
|
||||||
blocks: vec![],
|
blocks: data.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (label, path) in ITEM_TYPES.iter() {
|
|
||||||
if !data[&path[0]].get(&path[1]).is_none() {
|
|
||||||
item_set
|
|
||||||
.blocks
|
|
||||||
.push(self.make_item_set(&data[&path[0]][&path[1]], label));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
item_set.blocks.push(self.make_item_set_from_list(
|
|
||||||
&CONSUMABLES.to_vec(),
|
|
||||||
"Consumables | Frequent:",
|
|
||||||
"mostGames",
|
|
||||||
&data,
|
|
||||||
));
|
|
||||||
item_set.blocks.push(self.make_item_set_from_list(
|
|
||||||
&TRINKETS.to_vec(),
|
|
||||||
"Trinkets | Wins:",
|
|
||||||
"highestWinPercent",
|
|
||||||
&data,
|
|
||||||
));
|
|
||||||
|
|
||||||
info!("Writing item set for {} at {}", name, pos);
|
info!("Writing item set for {} at {}", name, pos);
|
||||||
fs::write(
|
fs::write(
|
||||||
path.join(format!("CGG_{}_{}.json", id, pos)),
|
path.join(format!("{}_{}_{}.json", self.get_alias(), id, pos)),
|
||||||
serde_json::to_string_pretty(&item_set).unwrap(),
|
serde_json::to_string_pretty(&item_set).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
392
src/kb_data_source.rs
Normal file
392
src/kb_data_source.rs
Normal file
|
@ -0,0 +1,392 @@
|
||||||
|
use crate::data_source::{Build, DataSource, Item};
|
||||||
|
use indexmap::IndexMap;
|
||||||
|
use regex::Regex;
|
||||||
|
use serde_derive::Deserialize;
|
||||||
|
use serde_json::{json, Value};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
pub struct KBDataSource {
|
||||||
|
token: Option<String>,
|
||||||
|
internal_classname_mapping: IndexMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
struct ChampionResponse {
|
||||||
|
patches: Vec<Patch>,
|
||||||
|
champions: Vec<Champion>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
struct Patch {
|
||||||
|
enabled: bool,
|
||||||
|
#[serde(rename = "patchVersion")]
|
||||||
|
patch_version: String,
|
||||||
|
patchid: u32,
|
||||||
|
start: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
struct Champion {
|
||||||
|
id: u32,
|
||||||
|
name: String,
|
||||||
|
#[serde(rename = "className")]
|
||||||
|
classname: String,
|
||||||
|
builds: Option<Position>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
struct Position {
|
||||||
|
bot: u16,
|
||||||
|
jungle: u16,
|
||||||
|
mid: u16,
|
||||||
|
support: u16,
|
||||||
|
top: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
struct BuildResponse {
|
||||||
|
builds2: Vec<KBBuild>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
struct KBBuild {
|
||||||
|
item0: KBItem,
|
||||||
|
item1: KBItem,
|
||||||
|
item2: KBItem,
|
||||||
|
item3: KBItem,
|
||||||
|
item4: KBItem,
|
||||||
|
item5: KBItem,
|
||||||
|
item6: KBItem,
|
||||||
|
#[serde(rename = "startItem0")]
|
||||||
|
start_item0: KBItem,
|
||||||
|
#[serde(rename = "startItem1")]
|
||||||
|
start_item1: KBItem,
|
||||||
|
#[serde(rename = "startItem2")]
|
||||||
|
start_item2: KBItem,
|
||||||
|
#[serde(rename = "startItem3")]
|
||||||
|
start_item3: KBItem,
|
||||||
|
#[serde(rename = "startItem4")]
|
||||||
|
start_item4: KBItem,
|
||||||
|
#[serde(rename = "startItem5")]
|
||||||
|
start_item5: KBItem,
|
||||||
|
#[serde(rename = "skillOrder")]
|
||||||
|
skill_order: String,
|
||||||
|
wins: f64,
|
||||||
|
games: f64,
|
||||||
|
summoner: Summoner,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
struct KBItem {
|
||||||
|
#[serde(rename = "itemId")]
|
||||||
|
item_id: u32,
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
struct Summoner {
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KBDataSource {
|
||||||
|
pub fn new(client: &reqwest::Client) -> KBDataSource {
|
||||||
|
let mut datasource = KBDataSource {
|
||||||
|
token: None,
|
||||||
|
internal_classname_mapping: IndexMap::new(),
|
||||||
|
};
|
||||||
|
datasource.token = datasource.get_auth_token(client);
|
||||||
|
datasource.internal_classname_mapping = datasource.get_classname_mapping(client);
|
||||||
|
datasource
|
||||||
|
}
|
||||||
|
|
||||||
|
// It will be better to use Result...
|
||||||
|
fn get_auth_token(&self, client: &reqwest::Client) -> Option<String> {
|
||||||
|
let bundle = match client.get("https://koreanbuilds.net/bundle.js").send() {
|
||||||
|
Ok(mut resp) => match resp.text() {
|
||||||
|
Ok(val) => val,
|
||||||
|
Err(_) => return None,
|
||||||
|
},
|
||||||
|
Err(_) => return None,
|
||||||
|
};
|
||||||
|
let regex = match Regex::new(r##"Authorization:\s*"(\w+)""##) {
|
||||||
|
Ok(reg) => reg,
|
||||||
|
Err(_) => return None,
|
||||||
|
};
|
||||||
|
let result = match regex.captures(&bundle) {
|
||||||
|
Some(res) => res,
|
||||||
|
None => return None,
|
||||||
|
};
|
||||||
|
return match result.get(1) {
|
||||||
|
Some(token) => Some(token.as_str().to_string()),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_classname_mapping(&self, client: &reqwest::Client) -> IndexMap<String, String> {
|
||||||
|
let mut mapping = IndexMap::new();
|
||||||
|
match self.get_champion_response(client) {
|
||||||
|
Some(data) => {
|
||||||
|
for champ in data.champions {
|
||||||
|
mapping.insert(champ.classname, champ.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => { /* Nothing to do */ }
|
||||||
|
};
|
||||||
|
mapping
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_champion_response(&self, client: &reqwest::Client) -> Option<ChampionResponse> {
|
||||||
|
let token = match self.token.clone() {
|
||||||
|
Some(t) => t,
|
||||||
|
None => return None,
|
||||||
|
};
|
||||||
|
match client
|
||||||
|
.get("https://api.koreanbuilds.net/champions?patchid=-1")
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.header("Authorization", token)
|
||||||
|
.send()
|
||||||
|
{
|
||||||
|
Ok(mut resp) => match resp.json() {
|
||||||
|
Ok(val) => return val,
|
||||||
|
Err(_) => return None,
|
||||||
|
},
|
||||||
|
Err(_) => return None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_positions(position: Option<Position>) -> Vec<String> {
|
||||||
|
let mut positions = Vec::new();
|
||||||
|
match position {
|
||||||
|
Some(pos) => {
|
||||||
|
if pos.top > 0 {
|
||||||
|
positions.push("TOP".to_owned());
|
||||||
|
}
|
||||||
|
if pos.jungle > 0 {
|
||||||
|
positions.push("JUNGLE".to_owned());
|
||||||
|
}
|
||||||
|
if pos.mid > 0 {
|
||||||
|
positions.push("MID".to_owned());
|
||||||
|
}
|
||||||
|
if pos.bot > 0 {
|
||||||
|
positions.push("BOT".to_owned());
|
||||||
|
}
|
||||||
|
if pos.support > 0 {
|
||||||
|
positions.push("SUPPORT".to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => { /* Nothing to do */ }
|
||||||
|
}
|
||||||
|
positions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DataSource for KBDataSource {
|
||||||
|
fn get_alias(&self) -> &str {
|
||||||
|
"KB"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_champs_with_positions_and_patch(
|
||||||
|
&self,
|
||||||
|
client: &reqwest::Client,
|
||||||
|
) -> (IndexMap<String, Vec<String>>, String) {
|
||||||
|
let mut champions = IndexMap::new();
|
||||||
|
let data: ChampionResponse = match self.get_champion_response(client) {
|
||||||
|
Some(val) => val,
|
||||||
|
None => {
|
||||||
|
return (champions, String::new());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let patch = match data.patches.get(0) {
|
||||||
|
Some(p) => p.patch_version.clone(),
|
||||||
|
None => return (champions, String::new()),
|
||||||
|
};
|
||||||
|
for champ in data.champions {
|
||||||
|
champions.insert(champ.classname, KBDataSource::get_positions(champ.builds));
|
||||||
|
}
|
||||||
|
(champions, patch)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_champ_data_with_win_pourcentage(
|
||||||
|
&self,
|
||||||
|
id: &str,
|
||||||
|
position: &str,
|
||||||
|
client: &reqwest::Client,
|
||||||
|
) -> Option<(Vec<Value>, f64)> {
|
||||||
|
let token = match self.token.clone() {
|
||||||
|
Some(t) => t,
|
||||||
|
None => return None,
|
||||||
|
};
|
||||||
|
let map_id = match self.internal_classname_mapping.get(id) {
|
||||||
|
Some(m_id) => m_id,
|
||||||
|
None => return None,
|
||||||
|
};
|
||||||
|
let data: BuildResponse = match client
|
||||||
|
.get(&format!(
|
||||||
|
"https://api.koreanbuilds.net/builds?chmpname={}&patchid=-2&position={}",
|
||||||
|
map_id, position
|
||||||
|
))
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.header("Authorization", token)
|
||||||
|
.send()
|
||||||
|
{
|
||||||
|
Ok(mut resp) => match resp.json() {
|
||||||
|
Ok(val) => val,
|
||||||
|
Err(_) => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut blocks = vec![];
|
||||||
|
let winrate = (data.builds2[0].wins / data.builds2[0].games) * 100.;
|
||||||
|
let mut starting_items: Vec<Item> = vec![];
|
||||||
|
if data.builds2[0].start_item0.item_id != 0 {
|
||||||
|
starting_items.push(Item {
|
||||||
|
id: data.builds2[0].start_item0.item_id.to_string(),
|
||||||
|
count: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if data.builds2[0].start_item1.item_id != 0 {
|
||||||
|
starting_items.push(Item {
|
||||||
|
id: data.builds2[0].start_item1.item_id.to_string(),
|
||||||
|
count: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if data.builds2[0].start_item2.item_id != 0 {
|
||||||
|
starting_items.push(Item {
|
||||||
|
id: data.builds2[0].start_item2.item_id.to_string(),
|
||||||
|
count: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if data.builds2[0].start_item3.item_id != 0 {
|
||||||
|
starting_items.push(Item {
|
||||||
|
id: data.builds2[0].start_item3.item_id.to_string(),
|
||||||
|
count: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if data.builds2[0].start_item4.item_id != 0 {
|
||||||
|
starting_items.push(Item {
|
||||||
|
id: data.builds2[0].start_item4.item_id.to_string(),
|
||||||
|
count: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if data.builds2[0].start_item5.item_id != 0 {
|
||||||
|
starting_items.push(Item {
|
||||||
|
id: data.builds2[0].start_item5.item_id.to_string(),
|
||||||
|
count: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
blocks.push(json!(Build {
|
||||||
|
type_: format!(
|
||||||
|
"Early game items | skillOrder : {}",
|
||||||
|
data.builds2[0].skill_order
|
||||||
|
),
|
||||||
|
items: starting_items
|
||||||
|
}));
|
||||||
|
let mut final_items: Vec<Item> = vec![];
|
||||||
|
if data.builds2[0].item0.item_id != 0 {
|
||||||
|
final_items.push(Item {
|
||||||
|
id: data.builds2[0].item0.item_id.to_string(),
|
||||||
|
count: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if data.builds2[0].item1.item_id != 0 {
|
||||||
|
final_items.push(Item {
|
||||||
|
id: data.builds2[0].item1.item_id.to_string(),
|
||||||
|
count: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if data.builds2[0].item2.item_id != 0 {
|
||||||
|
final_items.push(Item {
|
||||||
|
id: data.builds2[0].item2.item_id.to_string(),
|
||||||
|
count: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if data.builds2[0].item3.item_id != 0 {
|
||||||
|
final_items.push(Item {
|
||||||
|
id: data.builds2[0].item3.item_id.to_string(),
|
||||||
|
count: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if data.builds2[0].item4.item_id != 0 {
|
||||||
|
final_items.push(Item {
|
||||||
|
id: data.builds2[0].item4.item_id.to_string(),
|
||||||
|
count: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if data.builds2[0].item5.item_id != 0 {
|
||||||
|
final_items.push(Item {
|
||||||
|
id: data.builds2[0].item5.item_id.to_string(),
|
||||||
|
count: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if data.builds2[0].item6.item_id != 0 {
|
||||||
|
final_items.push(Item {
|
||||||
|
id: data.builds2[0].item6.item_id.to_string(),
|
||||||
|
count: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
blocks.push(json!(Build {
|
||||||
|
type_: format!(
|
||||||
|
"Item order by time finished | Summoner : {}",
|
||||||
|
data.builds2[0].summoner.name
|
||||||
|
),
|
||||||
|
items: final_items
|
||||||
|
}));
|
||||||
|
Some((blocks, winrate))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_auth_token() {
|
||||||
|
let datasource = KBDataSource {
|
||||||
|
token: None,
|
||||||
|
internal_classname_mapping: IndexMap::new(),
|
||||||
|
};
|
||||||
|
let client = reqwest::Client::builder()
|
||||||
|
.timeout(Duration::from_secs(10))
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
match datasource.get_auth_token(&client) {
|
||||||
|
Some(token) => assert!(token.len() > 0),
|
||||||
|
None => assert!(false),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_champs_with_positions_and_patch() {
|
||||||
|
let client = reqwest::Client::builder()
|
||||||
|
.timeout(Duration::from_secs(10))
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
let datasource = KBDataSource::new(&client);
|
||||||
|
let champs_with_positions_and_patch =
|
||||||
|
datasource.get_champs_with_positions_and_patch(&client);
|
||||||
|
assert!(champs_with_positions_and_patch.0.len() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_champ_data_with_win_pourcentage() {
|
||||||
|
let client = reqwest::Client::builder()
|
||||||
|
.timeout(Duration::from_secs(10))
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
let datasource = KBDataSource::new(&client);
|
||||||
|
let result = datasource.get_champ_data_with_win_pourcentage("Aatrox", "TOP", &client);
|
||||||
|
assert!(result.is_some());
|
||||||
|
match result {
|
||||||
|
Some(value) => {
|
||||||
|
assert!(value.0.len() > 0);
|
||||||
|
assert!(value.1 > 0.);
|
||||||
|
}
|
||||||
|
None => assert!(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
src/main.rs
24
src/main.rs
|
@ -1,21 +1,23 @@
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
use log::{error, info};
|
||||||
use reqwest::header;
|
use reqwest::header;
|
||||||
|
use serde_derive::Deserialize;
|
||||||
|
use simple_logger;
|
||||||
use std::io::{Error, ErrorKind};
|
use std::io::{Error, ErrorKind};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::{fs, thread, time};
|
use std::{fs, thread, time};
|
||||||
use time::Duration;
|
use time::Duration;
|
||||||
use winreg::RegKey;
|
use winreg::RegKey;
|
||||||
use simple_logger;
|
|
||||||
use log::{info, error};
|
|
||||||
use serde_derive::{Deserialize};
|
|
||||||
|
|
||||||
mod cgg_data_source;
|
mod cgg_data_source;
|
||||||
mod data_source;
|
mod 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 pb_data_source::PBDataSource;
|
|
||||||
use data_source::DataSource;
|
use data_source::DataSource;
|
||||||
|
use kb_data_source::KBDataSource;
|
||||||
|
use pb_data_source::PBDataSource;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct Realm {
|
struct Realm {
|
||||||
|
@ -78,13 +80,21 @@ 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] = [Box::new(PBDataSource), Box::new(CGGDataSource)];
|
let data_sources: [Box<dyn DataSource>; 3] = [
|
||||||
|
Box::new(PBDataSource),
|
||||||
|
Box::new(CGGDataSource),
|
||||||
|
Box::new(KBDataSource::new(&client)),
|
||||||
|
];
|
||||||
|
|
||||||
for data_source in data_sources.iter() {
|
for data_source in data_sources.iter() {
|
||||||
let (champs, patch) = data_source.get_champs_with_positions_and_patch(&client);
|
let (champs, patch) = data_source.get_champs_with_positions_and_patch(&client);
|
||||||
|
|
||||||
info!("CGG version: {}", patch);
|
info!("{} version: {}", data_source.get_alias(), patch);
|
||||||
info!("CGG numbers of champs: {}", champs.len());
|
info!(
|
||||||
|
"{} numbers of champs: {}",
|
||||||
|
data_source.get_alias(),
|
||||||
|
champs.len()
|
||||||
|
);
|
||||||
|
|
||||||
for (id, positions) in &champs {
|
for (id, positions) in &champs {
|
||||||
if champion.data.contains_key(id) {
|
if champion.data.contains_key(id) {
|
||||||
|
|
|
@ -5,6 +5,10 @@ use crate::data_source::DataSource;
|
||||||
|
|
||||||
pub struct PBDataSource;
|
pub struct PBDataSource;
|
||||||
impl DataSource for PBDataSource {
|
impl DataSource for PBDataSource {
|
||||||
|
fn get_alias(&self) -> &str {
|
||||||
|
"PB"
|
||||||
|
}
|
||||||
|
|
||||||
fn get_champs_with_positions_and_patch(
|
fn get_champs_with_positions_and_patch(
|
||||||
&self,
|
&self,
|
||||||
_client: &reqwest::Client,
|
_client: &reqwest::Client,
|
||||||
|
@ -12,12 +16,12 @@ impl DataSource for PBDataSource {
|
||||||
(IndexMap::new(), String::new())
|
(IndexMap::new(), String::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_champ_data(
|
fn get_champ_data_with_win_pourcentage(
|
||||||
&self,
|
&self,
|
||||||
_id: &str,
|
_id: &str,
|
||||||
_position: &str,
|
_position: &str,
|
||||||
_client: &reqwest::Client,
|
_client: &reqwest::Client,
|
||||||
) -> Option<Value> {
|
) -> Option<(Vec<Value>, f64)> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue