diff --git a/src/router.rs b/src/router.rs index 56f8ada..cc453ab 100644 --- a/src/router.rs +++ b/src/router.rs @@ -170,7 +170,7 @@ async fn api_req(req: HttpRequest, body: String) -> HttpResponse { pub async fn request(req: HttpRequest, body: String) -> HttpResponse { let args = crate::get_args(); let headers = req.headers(); - if args.hidden && req.path().starts_with("/api/webui/") { + if args.hidden && (req.path().starts_with("/api/webui/") || req.path().starts_with("/live_clear_rate.html")) { return not_found(headers); } if headers.get("aoharu-asset-version").is_none() && req.path().starts_with("/api") && !req.path().starts_with("/api/webui") { @@ -212,6 +212,7 @@ pub async fn request(req: HttpRequest, body: String) -> HttpResponse { "/v1.0/payment/balance" => gree::balance(req), "/web/announcement" => web::announcement(req), "/api/webui/userInfo" => webui::user(req), + "/live_clear_rate.html" => clear_rate::clearrate_html(req).await, "/webui/logout" => webui::logout(req), "/api/webui/export" => webui::export(req), "/api/webui/serverInfo" => webui::server_info(req), diff --git a/src/router/clear_rate.rs b/src/router/clear_rate.rs index 3990cbd..19bbd17 100644 --- a/src/router/clear_rate.rs +++ b/src/router/clear_rate.rs @@ -1,5 +1,5 @@ use json::{object, array, JsonValue}; -use actix_web::{HttpRequest}; +use actix_web::{HttpRequest, HttpResponse, http::header::ContentType}; use rusqlite::params; use std::sync::Mutex; use lazy_static::lazy_static; @@ -7,6 +7,7 @@ use lazy_static::lazy_static; use crate::encryption; use crate::sql::SQLite; use crate::router::{global, databases}; +use crate::include_file; trait SqlClearRate { fn get_live_data(&self, id: i64) -> Result; @@ -34,6 +35,7 @@ impl SqlClearRate for SQLite { lazy_static! { static ref DATABASE: SQLite = SQLite::new("live_statistics.db", setup_tables); static ref CACHED_DATA: Mutex> = Mutex::new(None); + static ref CACHED_HTML_DATA: Mutex> = Mutex::new(None); } pub struct Live { @@ -150,6 +152,18 @@ pub fn live_completed(id: i64, level: i32, failed: bool, score: i64, uid: i64) { }; } +fn get_song_title(live_id: i32, english: bool) -> String { + let details = if english { + databases::MUSIC_EN[live_id.to_string()].clone() + } else { + databases::MUSIC[live_id.to_string()].clone() + }; + if !details.is_null() { + return details["name"].to_string(); + } + String::from("Unknown Song") +} + fn get_pass_percent(failed: i64, pass: i64) -> String { let total = (failed + pass) as f64; if failed + pass == 0 { @@ -236,3 +250,101 @@ pub fn ranking(_req: HttpRequest, body: String) -> Option { "ranking_list": rank }) } + +fn get_html() -> JsonValue { + let lives = DATABASE.lock_and_select_all("SELECT live_id FROM lives", params!()).unwrap(); + + let mut table = String::new(); + + for id in lives.members() { + let live_id = id.as_i64().unwrap(); + + let info = match DATABASE.get_live_data(live_id) { + Ok(i) => i, + Err(_) => continue, + }; + + let calc_rate = |pass: i64, fail: i64| -> f64 { + let total = pass + fail; + if total == 0 { 0.0 } else { pass as f64 / total as f64 } + }; + + let title_jp = get_song_title(info.live_id, false); + let title_en = get_song_title(info.live_id, true); + + let normal_txt = get_pass_percent(info.normal_failed, info.normal_pass); + let hard_txt = get_pass_percent(info.hard_failed, info.hard_pass); + let expert_txt = get_pass_percent(info.expert_failed, info.expert_pass); + let master_txt = get_pass_percent(info.master_failed, info.master_pass); + + let normal_plays = info.normal_pass + info.normal_failed; + let hard_plays = info.hard_pass + info.hard_failed; + let expert_plays = info.expert_pass + info.expert_failed; + let master_plays = info.master_pass + info.master_failed; + + let normal_rate_sort = calc_rate(info.normal_pass, info.normal_failed); + let hard_rate_sort = calc_rate(info.hard_pass, info.hard_failed); + let expert_rate_sort = calc_rate(info.expert_pass, info.expert_failed); + let master_rate_sort = calc_rate(info.master_pass, info.master_failed); + + table.push_str(&format!( + r#" + + {title_jp} + + + + {normal_txt} + {normal_plays} plays + + + + {hard_txt} + {hard_plays} plays + + + + {expert_txt} + {expert_plays} plays + + + + {master_txt} + {master_plays} plays + + "# + )); + } + + let html = include_file!("src/router/clear_rate_template.html").replace("{{TABLEBODY}}", &table); + object!{ + "cache": html, + "last_updated": global::timestamp() + } +} + +async fn get_clearrate_html() -> String { + let cache = { + let mut result = crate::lock_onto_mutex!(CACHED_HTML_DATA); + if result.is_none() { + result.replace(get_html()); + } + result.as_ref().unwrap().clone() + }; + if cache["last_updated"].as_u64().unwrap() + (60 * 60) < global::timestamp() { + let mut result = crate::lock_onto_mutex!(CACHED_HTML_DATA); + result.replace(get_html()); + } + cache["cache"].to_string() +} + +pub async fn clearrate_html(_req: HttpRequest) -> HttpResponse { + let html = get_clearrate_html().await; + + HttpResponse::Ok() + .content_type(ContentType::html()) + .body(html) +} diff --git a/src/router/clear_rate_template.html b/src/router/clear_rate_template.html new file mode 100644 index 0000000..4e9e2e9 --- /dev/null +++ b/src/router/clear_rate_template.html @@ -0,0 +1,239 @@ + + + + + Live Clear Rates + + + +

Live Clear Rates

+ +
+ + + + + +
+ +
+ + + + + + + + + + + + {{TABLEBODY}} + +
Song TitleNormalHardExpertMaster
+
+ + + + diff --git a/src/router/databases/mod.rs b/src/router/databases/mod.rs index 1b9b408..be88c0d 100644 --- a/src/router/databases/mod.rs +++ b/src/router/databases/mod.rs @@ -277,9 +277,35 @@ lazy_static! { pub static ref MUSIC: JsonValue = { let mut info = object!{}; let items = json::parse(&include_file!("src/router/databases/json/music.json")).unwrap(); - for data in items.members() { - info[data["id"].to_string()] = data.clone(); - } + for live in LIVE_LIST.entries() { + info[live.1["id"].to_string()] = loop { + let mut val = object!{}; + for data in items.members() { + if live.1["masterMusicId"] == data["id"] { + val = data.clone(); + break; + } + } + break val; + }; + }; + info + }; + pub static ref MUSIC_EN: JsonValue = { + let mut info = object!{}; + let items = json::parse(&include_file!("src/router/databases/json/global/music.json")).unwrap(); + for live in LIVE_LIST.entries() { + info[live.1["id"].to_string()] = loop { + let mut val = object!{}; + for data in items.members() { + if live.1["masterMusicId"] == data["id"] { + val = data.clone(); + break; + } + } + break val; + }; + }; info }; pub static ref RANKS: JsonValue = {