Add metrics for player statistics

This commit is contained in:
Daan Boerlage 2023-04-06 02:33:32 +02:00
parent 58f6d57571
commit feb39ec8ef
Signed by: daan
GPG key ID: FCE070E1E4956606
3 changed files with 147 additions and 4 deletions

View file

@ -1,5 +1,5 @@
pub mod player_count; pub mod player_count;
// pub mod stats; pub mod stats;
pub trait PromMetric { pub trait PromMetric {
fn to_metric_string(self: &Self) -> String; fn to_metric_string(self: &Self) -> String;

133
src/collectors/stats.rs Normal file
View file

@ -0,0 +1,133 @@
use std::fmt::{Display, Formatter};
use eyre::eyre;
#[derive(Debug)]
pub struct SkillInfo {
pub rank: String,
pub level: String,
pub xp: String,
pub name: String,
pub player: String,
pub profile: PlayerProfiles,
}
#[derive(Debug)]
pub enum PlayerProfiles {
Standard,
// Beta,
// QuestSpeedrunning,
// Deadman,
// PVPArena,
// TrailblazerLeague,
// DeadmanReborn,
// ShatteredRelicsLeague,
}
impl Display for PlayerProfiles {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
PlayerProfiles::Standard => write!(f, "Standard"),
// PlayerProfiles::Beta => write!(f, "Beta"),
// PlayerProfiles::QuestSpeedrunning => write!(f, "QuestSpeedrunning"),
// PlayerProfiles::Deadman => write!(f, "Deadman"),
// PlayerProfiles::PVPArena => write!(f, "PVPArena"),
// PlayerProfiles::TrailblazerLeague => write!(f, "TrailblazerLeague"),
// PlayerProfiles::DeadmanReborn => write!(f, "DeadmanReborn"),
// PlayerProfiles::ShatteredRelicsLeague => write!(f, "ShatteredRelicsLeague"),
}
}
}
const SKILLS: [&str; 25] = [
"Overall",
"Attack",
"Defence",
"Strength",
"Hitpoints",
"Ranged",
"Prayer",
"Magic",
"Cooking",
"Woodcutting",
"Fletching",
"Fishing",
"Firemaking",
"Crafting",
"Smithing",
"Mining",
"Herblore",
"Agility",
"Thieving",
"Slayer",
"Farming",
"Runecrafting",
"Hunter",
"Construction",
"Stuff",
];
pub async fn get_player_stats(rsn: &str) -> eyre::Result<Vec<SkillInfo>> {
let req_url = format!("https://oldschool.runescape.wiki/cors/m=hiscore_oldschool/index_lite.ws?player={}", rsn);
let resp = reqwest::Client::new()
.get(req_url)
.header("User-Agent", super::USER_AGENT)
.send()
.await?;
if resp.status() != 200 {
return Err(eyre!("Player not found"));
}
let raw = resp.text().await?;
let mut n = SKILLS.into_iter();
let skills: Vec<SkillInfo> = raw
.split("\n")
.into_iter()
.map(|x| x.split(',').collect::<Vec<&str>>())
.filter(|x| x.len() == 3)
.map(|x| {
let name = n.next().unwrap();
SkillInfo {
rank: x[0].to_string(),
level: x[1].to_string(),
xp: x[2].to_string(),
name: name.to_string(),
profile: PlayerProfiles::Standard,
player: rsn.to_string(),
}
})
.collect();
Ok(skills)
}
impl super::PromMetric for SkillInfo {
fn to_metric_string(self: &Self) -> String {
let lines: Vec<String> = vec![
format!(
"osrs_player_rank{{skill=\"{}\",player=\"{}\",profile=\"{}\"}} {}",
self.name,
self.player,
self.profile,
self.rank
),
format!(
"osrs_player_level{{skill=\"{}\",player=\"{}\",profile=\"{}\"}} {}",
self.name,
self.player,
self.profile,
self.level
),
format!(
"osrs_player_xp{{skill=\"{}\",player=\"{}\",profile=\"{}\"}} {}",
self.name,
self.player,
self.profile,
self.xp
),
];
lines.join("\n")
}
}

View file

@ -1,4 +1,4 @@
mod collector; mod collectors;
use axum::routing::get; use axum::routing::get;
use axum::Router; use axum::Router;
@ -25,11 +25,21 @@ async fn worlds() -> impl IntoResponse {
(StatusCode::OK, convert_into_metrics(resp)) (StatusCode::OK, convert_into_metrics(resp))
} }
async fn stats(Path(rsn): Path<String>) -> impl IntoResponse {
let resp = match collectors::stats::get_player_stats(&rsn).await {
Ok(r) => r,
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "Nope".to_string())
};
(StatusCode::OK, convert_into_metrics(resp))
}
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let app = Router::new() let app = Router::new()
.route("/worlds", get(worlds)); .route("/worlds", get(worlds))
// .route("/stats/:rsn", get(stats)); .route("/stats/:rsn", get(stats));
println!("Starting..."); println!("Starting...");