add w2l results to leaderboard (wip)

This commit is contained in:
Brandon Thomas committed 2021-09-06 07:43:02 -04:00
1 parent eeef9cc916
commit b59d19a7c8
7 files changed
+193 -1

No files matched your search

Whitespace-only changes.
@@ -0,0 +1,81 @@
use anyhow::anyhow;
use crate::util::anyhow_result::AnyhowResult;
use log::warn;
use sqlx::MySqlPool;
#[derive(Serialize)]
pub struct W2lLeaderboardRecordForList {
pub username: String,
pub display_name: String,
pub gravatar_hash: String,
pub creator_user_token: String,
pub uploaded_count: i64,
}
#[derive(Serialize)]
pub struct W2lLeaderboardRecordForListRaw {
pub username: String,
pub display_name: String,
pub gravatar_hash: String,
pub creator_user_token: String,
pub uploaded_count: i64,
}
// NB: This may need to become an offline query if it is expensive.
pub async fn calculate_w2l_template_leaderboard(
mysql_pool: &MySqlPool
) -> AnyhowResult<Vec<W2lLeaderboardRecordForList>> {
let maybe_results = sqlx::query_as!(
W2lLeaderboardRecordForListRaw,
r#"
SELECT
users.username,
users.display_name,
users.email_gravatar_hash as gravatar_hash,
creator_user_token,
count(*) as uploaded_count
FROM w2l_templates
JOIN users
ON
users.token = creator_user_token
WHERE
is_public_listing_approved IS TRUE
AND
users.is_banned IS FALSE
GROUP BY creator_user_token
ORDER BY uploaded_count desc
LIMIT 25;
"#,
)
.fetch_all(mysql_pool)
.await;
let results : Vec<W2lLeaderboardRecordForListRaw> = match maybe_results {
Ok(results) => results,
Err(err) => {
warn!("Error: {:?}", err);
match err {
RowNotFound => {
return Ok(Vec::new());
},
_ => {
warn!("w2l leaderboard query error: {:?}", err);
return Err(anyhow!("w2l leaderboard query error"));
}
}
}
};
Ok(results.into_iter()
.map(|result| {
W2lLeaderboardRecordForList {
username: result.username.to_string(),
display_name: result.display_name.to_string(),
gravatar_hash: result.gravatar_hash.to_string(),
creator_user_token: result.creator_user_token.to_string(),
uploaded_count: result.uploaded_count,
}
})
.collect::<Vec<W2lLeaderboardRecordForList>>())
}
+3 -1
View File
@@ -1,9 +1,12 @@
pub mod badges;
pub mod calculate_tts_model_leaderboard;
pub mod calculate_w2l_template_leaderboard;
pub mod create_session;
pub mod delete_tts_model;
pub mod delete_tts_result;
pub mod delete_w2l_result;
pub mod delete_w2l_template;
pub mod get_user_profile_by_username;
pub mod list_ip_bans;
pub mod list_tts_models;
pub mod list_user_badges;
@@ -11,6 +14,5 @@ pub mod list_user_roles;
pub mod list_w2l_templates;
pub mod query_tts_model;
pub mod query_tts_result;
pub mod get_user_profile_by_username;
pub mod query_w2l_result;
pub mod query_w2l_template;
@@ -0,0 +1,101 @@
use actix_http::Error;
use actix_http::http::header;
use actix_web::cookie::Cookie;
use actix_web::dev::HttpResponseBuilder;
use actix_web::error::ResponseError;
use actix_web::http::StatusCode;
use actix_web::{Responder, web, HttpResponse, error, HttpRequest, HttpMessage};
use chrono::{DateTime, Utc};
use crate::AnyhowResult;
use crate::database::queries::calculate_w2l_template_leaderboard::W2lLeaderboardRecordForList;
use crate::database::queries::calculate_w2l_template_leaderboard::calculate_w2l_template_leaderboard;
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
use crate::http_server::web_utils::serialize_as_json_error::serialize_as_json_error;
use crate::server_state::ServerState;
use derive_more::{Display, Error};
use log::{info, warn, log};
use regex::Regex;
use sqlx::MySqlPool;
use sqlx::error::DatabaseError;
use sqlx::error::Error::Database;
use sqlx::mysql::MySqlDatabaseError;
use std::fmt;
use std::sync::Arc;
#[derive(Serialize)]
pub struct LeaderboardResponse {
success: bool,
w2l_leaderboard: Vec<W2lLeaderboardRecordForList>
}
#[derive(Serialize, Debug)]
pub struct LeaderboardErrorResponse {
pub success: bool,
pub error_type: LeaderboardErrorType,
pub error_message: String,
}
#[derive(Copy, Clone, Debug, Serialize)]
pub enum LeaderboardErrorType {
ServerError,
}
impl LeaderboardErrorResponse {
fn server_error() -> Self {
Self {
success: false,
error_type: LeaderboardErrorType::ServerError,
error_message: "server error".to_string()
}
}
}
impl ResponseError for LeaderboardErrorResponse {
fn status_code(&self) -> StatusCode {
match self.error_type {
LeaderboardErrorType::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
}
}
fn error_response(&self) -> HttpResponse {
serialize_as_json_error(self)
}
}
// NB: Not using DeriveMore since Clion doesn't understand it.
impl fmt::Display for LeaderboardErrorResponse {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.error_type)
}
}
pub async fn leaderboard_handler(
http_request: HttpRequest,
server_state: web::Data<Arc<ServerState>>
) -> Result<HttpResponse, LeaderboardErrorResponse> {
// TODO: Fire off both requests in parallel.
let maybe_results =
calculate_w2l_template_leaderboard(&server_state.mysql_pool).await;
let results = match maybe_results {
Ok(results) => results,
Err(e) => {
warn!("Query error: {:?}", e);
return Err(LeaderboardErrorResponse::server_error());
}
};
let response = LeaderboardResponse {
success: true,
w2l_leaderboard: results,
};
let body = serde_json::to_string(&response)
.map_err(|e| LeaderboardErrorResponse::server_error())?;
Ok(HttpResponse::Ok()
.content_type("application/json")
.body(body))
}
@@ -0,0 +1 @@
pub mod get_leaderboard;
+1
View File
@@ -1,5 +1,6 @@
pub mod default_route_404;
pub mod events;
pub mod leaderboard;
pub mod misc;
pub mod moderation;
pub mod root_index;
+6
View File
@@ -106,6 +106,7 @@ use sqlx::mysql::MySqlPoolOptions;
use std::sync::Arc;
use std::time::Duration;
use crate::http_server::endpoints::moderation::users::list_users::list_users_handler;
use crate::http_server::endpoints::leaderboard::get_leaderboard::leaderboard_handler;
// TODO TODO TODO TODO
// TODO TODO TODO TODO
@@ -591,6 +592,11 @@ pub async fn serve(server_state: ServerState) -> AnyhowResult<()>
.route(web::get().to(list_events_handler))
.route(web::head().to(|| HttpResponse::Ok()))
)
.service(
web::resource("/leaderboard")
.route(web::get().to(leaderboard_handler))
.route(web::head().to(|| HttpResponse::Ok()))
)
.service(get_root_index)
.service(enable_alpha_handler)
.service(enable_alpha_easy_handler)