Skip to content

Commit

Permalink
feat: janky stuff that is unfinished and probably never will be
Browse files Browse the repository at this point in the history
  • Loading branch information
ashhhleyyy committed Nov 29, 2023
1 parent ee7b6c0 commit 204f7d4
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 20 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 69 additions & 0 deletions src/discord/parser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
enum ParseState {
Whitespace {
expecting: bool,
},
String {
s: String,
},
QuotedString {
s: String,
quote: char,
prev_char: char,
},
}

pub enum ParseString {
Unquoted(String),
Quoted {
s: String,
quote: char,
}
}

pub fn parse_command(s: &str) -> Option<Vec<ParseString>> {
// TODO: some *probably* unnecessary usages of s.clone() in here :/

let mut result = vec![];

let mut state = ParseState::Whitespace {
expecting: false,
};

for c in s.chars() {
let m_state = &mut state;
match m_state {
ParseState::Whitespace { expecting } => {
if c.is_ascii_whitespace() {
continue;
} else if *expecting {
return None; // fail parsing
} else if c == '"' || c == '\'' {
state = ParseState::QuotedString { s: String::new(), quote: c, prev_char: '\0' };
} else {
let mut s = String::new();
s.push(c);
state = ParseState::String { s };
}
},
ParseState::String { s } => {
if c.is_ascii_whitespace() {
result.push(ParseString::Unquoted(s.clone()));
state = ParseState::Whitespace { expecting: false };
} else {
s.push(c);
}
},
ParseState::QuotedString { s, quote, prev_char } => {
if c == *quote && *prev_char != '\\' {
result.push(ParseString::Quoted { quote: *quote, s: s.clone() });
state = ParseState::Whitespace { expecting: true };
} else {
s.push(c);
*prev_char = c;
}
},
}
}

Some(result)
}
21 changes: 21 additions & 0 deletions src/statistics/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ use crate::statistics::model::{
};
use crate::{Controller, StatisticsConfig};

use super::leaderboards::database::LeaderboardMetadata;

pub struct StatisticDatabaseController {
_controller: Address<Controller>,
pool: Pool,
Expand Down Expand Up @@ -536,6 +538,25 @@ impl Handler<GetLeaderboard> for StatisticDatabaseController {
}
}

pub struct GetLeaderboardV2(pub String);

impl Message for GetLeaderboardV2 {
type Result = StatisticsDatabaseResult<Option<(LeaderboardMetadata, Vec<LeaderboardEntry>)>>;
}

#[async_trait]
impl Handler<GetLeaderboardV2> for StatisticDatabaseController {
async fn handle(
&mut self,
message: GetLeaderboardV2,
_ctx: &mut Context<Self>,
) -> <GetLeaderboardV2 as Message>::Result {
let metadata = self.leaderboards.get_leaderboard_metadata(&message.0).await?;
let entries = self.leaderboards.get_leaderboard(&message.0).await?;
Ok(metadata.zip(entries))
}
}

pub struct GetAllLeaderboards;

impl Message for GetAllLeaderboards {
Expand Down
26 changes: 25 additions & 1 deletion src/statistics/leaderboards/database.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use clickhouse_rs::Pool;
use futures::StreamExt;
use nucleoid_leaderboards::model::LeaderboardDefinition;
use nucleoid_leaderboards::model::{LeaderboardDefinition, LeaderboardQuery, ValueFormat};
use serde::Serialize;
use std::collections::HashMap;
use uuid::Uuid;

Expand All @@ -25,6 +26,12 @@ pub async fn setup_leaderboard_tables(
Ok(())
}

#[derive(Serialize)]
pub struct LeaderboardMetadata {
pub id: String,
pub value_format: ValueFormat,
}

pub struct LeaderboardsDatabase {
postgres_pool: deadpool_postgres::Pool,
clickhouse_pool: clickhouse_rs::Pool,
Expand Down Expand Up @@ -121,6 +128,23 @@ impl LeaderboardsDatabase {
})
}

pub async fn get_leaderboard_metadata(
&self,
id: &str,
) -> StatisticsDatabaseResult<Option<LeaderboardMetadata>> {
let metadata = self.generator.definitions.get(id).map(|(definition, _sql)| {
let value_format = match definition.query {
LeaderboardQuery::Sql { value_format, .. } => value_format,
LeaderboardQuery::Statistic { value_format, .. } => value_format,
};
LeaderboardMetadata {
id: id.to_owned(),
value_format,
}
});
Ok(metadata)
}

pub async fn get_player_rankings(
&self,
player: &Uuid,
Expand Down
13 changes: 7 additions & 6 deletions src/statistics/leaderboards/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::collections::HashMap;

use futures::{Stream, StreamExt};
use nucleoid_leaderboards::model::{
Aggregate, LeaderboardDefinition, LeaderboardQuery, Ranking, UnitConversion, ValueType,
Aggregate, LeaderboardDefinition, LeaderboardQuery, Ranking, ValueType, ValueFormat,
};
use serde::Serialize;
use uuid::Uuid;
Expand Down Expand Up @@ -86,6 +86,7 @@ fn build_sql(definition: &LeaderboardDefinition) -> LeaderboardSql {
player,
value,
value_type,
..
} => LeaderboardSql {
sql: query.clone(),
player: player.clone(),
Expand All @@ -97,7 +98,7 @@ fn build_sql(definition: &LeaderboardDefinition) -> LeaderboardSql {
key,
aggregate,
ranking,
convert,
value_format,
} => LeaderboardSql {
// TODO: Sanitize SQL here?
sql: format!(
Expand All @@ -116,7 +117,7 @@ fn build_sql(definition: &LeaderboardDefinition) -> LeaderboardSql {
namespace = namespace,
key = key,
aggregate = aggregate_sql(aggregate),
convert = convert_sql(convert),
convert = convert_sql(value_format),
ranking = ranking_sql(ranking),
),
player: "player_id".to_string(),
Expand All @@ -135,10 +136,10 @@ fn aggregate_sql(aggregate: &Aggregate) -> &'static str {
}
}

fn convert_sql(convert: &Option<UnitConversion>) -> &'static str {
fn convert_sql(convert: &ValueFormat) -> &'static str {
match convert {
Some(UnitConversion::TicksToSeconds) => " / 20",
None => "",
ValueFormat::Time => " / 20",
_ => "",
}
}

Expand Down
42 changes: 30 additions & 12 deletions src/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use crate::statistics::database::*;
use crate::statistics::model::DataQueryType;
use crate::WebServerConfig;

pub mod v2;

pub async fn run(controller: Address<Controller>, config: WebServerConfig) {
let cors = warp::cors().allow_any_origin();

Expand All @@ -24,7 +26,8 @@ pub async fn run(controller: Address<Controller>, config: WebServerConfig) {
let controller = controller.clone();
move |channel| get_status(controller.clone(), channel)
})
.with(&cors);
.with(&cors)
.boxed();

let player_game_stats = warp::path("stats")
.and(warp::path("player"))
Expand All @@ -34,7 +37,8 @@ pub async fn run(controller: Address<Controller>, config: WebServerConfig) {
let controller = controller.clone();
move |uuid, namespace| get_player_stats(controller.clone(), uuid, Some(namespace))
})
.with(&cors);
.with(&cors)
.boxed();

let all_player_game_stats = warp::path("stats")
.and(warp::path("player"))
Expand All @@ -43,7 +47,8 @@ pub async fn run(controller: Address<Controller>, config: WebServerConfig) {
let controller = controller.clone();
move |uuid| get_player_stats(controller.clone(), uuid, None)
})
.with(&cors);
.with(&cors)
.boxed();

let all_game_stats = warp::path("stats")
.and(warp::path("game"))
Expand All @@ -52,7 +57,8 @@ pub async fn run(controller: Address<Controller>, config: WebServerConfig) {
let controller = controller.clone();
move |uuid| get_game_stats(controller.clone(), uuid)
})
.with(&cors);
.with(&cors)
.boxed();

let get_recent_games = warp::path("games")
.and(warp::path("recent"))
Expand All @@ -64,22 +70,25 @@ pub async fn run(controller: Address<Controller>, config: WebServerConfig) {
get_recent_games(controller.clone(), config.clone(), query)
}
})
.with(&cors);
.with(&cors)
.boxed();

let get_leaderboard = warp::path("leaderboard")
.and(warp::path::param::<String>())
.and_then({
let controller = controller.clone();
move |id| get_leaderboard(controller.clone(), id)
})
.with(&cors);
.with(&cors)
.boxed();

let list_leaderboards = warp::path("leaderboards")
.and_then({
let controller = controller.clone();
move || list_leaderboards(controller.clone())
})
.with(&cors);
.with(&cors)
.boxed();

let get_player_rankings = warp::path("player")
.and(warp::path::param::<Uuid>())
Expand All @@ -88,15 +97,17 @@ pub async fn run(controller: Address<Controller>, config: WebServerConfig) {
let controller = controller.clone();
move |id| get_player_rankings(controller.clone(), id)
})
.with(&cors);
.with(&cors)
.boxed();

let get_statistics_stats = warp::path("stats")
.and(warp::path("stats"))
.and_then({
let controller = controller.clone();
move || get_statistics_stats(controller.clone())
})
.with(&cors);
.with(&cors)
.boxed();

let data_query = warp::path("stats")
.and(warp::path("data"))
Expand All @@ -107,7 +118,8 @@ pub async fn run(controller: Address<Controller>, config: WebServerConfig) {
let controller = controller.clone();
move |query: DataQueryQuery| data_query(controller.clone(), query)
})
.with(&cors);
.with(&cors)
.boxed();

let get_player_username = warp::path("player")
.and(warp::path::param::<Uuid>())
Expand All @@ -116,7 +128,12 @@ pub async fn run(controller: Address<Controller>, config: WebServerConfig) {
let mojang_client = mojang_client.clone();
move |id| get_player_username(mojang_client.clone(), id)
})
.with(&cors);
.with(&cors)
.boxed();

let v2 = warp::path("v2")
.and(v2::build_v2(controller))
.boxed();

let combined = status
.or(player_game_stats)
Expand All @@ -128,7 +145,8 @@ pub async fn run(controller: Address<Controller>, config: WebServerConfig) {
.or(list_leaderboards)
.or(get_player_rankings)
.or(data_query)
.or(get_player_username);
.or(get_player_username)
.or(v2);

warp::serve(combined)
.run(([127, 0, 0, 1], config.port))
Expand Down
30 changes: 30 additions & 0 deletions src/web/v2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use warp::{Filter, Reply};
use xtra::prelude::*;

use crate::{Controller, statistics::database::GetLeaderboardV2};

use super::{get_statistics_controller, handle_option_result, ApiResult};

pub fn build_v2(controller: Address<Controller>) -> warp::filters::BoxedFilter<(impl Reply,)> {
let cors = warp::cors().allow_any_origin();

let leaderboards = warp::path("leaderboard")
.and(warp::path::param::<String>())
.and_then({
let controller = controller.clone();
move |id| get_leaderboard(controller.clone(), id)
})
.with(&cors)
.boxed();

leaderboards
}

async fn get_leaderboard(controller: Address<Controller>, id: String) -> ApiResult {
let statistics = get_statistics_controller(controller).await?;
let res = statistics
.send(GetLeaderboardV2(id))
.await
.expect("controller disconnected");
handle_option_result(res)
}

0 comments on commit 204f7d4

Please sign in to comment.