Add a leaderboard with Redis
This commit is contained in:
@@ -15,3 +15,5 @@ tungstenite = "0.18.0"
|
|||||||
anyhow = "1.0.69"
|
anyhow = "1.0.69"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
serde_json = "1.0.93"
|
serde_json = "1.0.93"
|
||||||
|
redis = { version = "0.22.3", features = ["aio", "async-std-comp"] }
|
||||||
|
async-trait = "0.1.66"
|
||||||
|
62
board-server/src/leaderboard.rs
Normal file
62
board-server/src/leaderboard.rs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
use async_trait::async_trait;
|
||||||
|
use redis::{AsyncCommands, RedisError};
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
const LEADERBOARD: &str = "leaderboard";
|
||||||
|
type LeaderboardEntry = (String, i32);
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
trait Leaderboard {
|
||||||
|
async fn add_score(&self, player_name: &str, score: i32) -> Result<(), RedisError>;
|
||||||
|
async fn get_highscores(&self) -> Result<Vec<LeaderboardEntry>, RedisError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RedisLeaderboard {
|
||||||
|
client: redis::Client,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RedisLeaderboard {
|
||||||
|
fn new(client: redis::Client) -> Self {
|
||||||
|
Self { client }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Leaderboard for RedisLeaderboard {
|
||||||
|
async fn add_score(&self, player_name: &str, score: i32) -> Result<(), RedisError> {
|
||||||
|
let mut con = self.client.get_async_connection().await?;
|
||||||
|
con.zadd(LEADERBOARD, player_name, score).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_highscores(&self) -> Result<Vec<LeaderboardEntry>, RedisError> {
|
||||||
|
let mut con = self.client.get_async_connection().await?;
|
||||||
|
let count: isize = con.zcard(LEADERBOARD).await?;
|
||||||
|
let leaderboard: Vec<LeaderboardEntry> =
|
||||||
|
con.zrange_withscores(LEADERBOARD, 0, count - 1).await?;
|
||||||
|
Ok(leaderboard)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct InMemoryLeaderboard();
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Leaderboard for InMemoryLeaderboard {
|
||||||
|
async fn add_score(&self, _: &str, _: i32) -> Result<(), RedisError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_highscores(&self) -> Result<Vec<LeaderboardEntry>, RedisError> {
|
||||||
|
Ok(Vec::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn provide_leaderboard() -> Box<dyn Leaderboard> {
|
||||||
|
match env::var("REDIS_HOSTNAME") {
|
||||||
|
Ok(redis_host_name) => match redis::Client::open(format!("redis://{redis_host_name}/")) {
|
||||||
|
Ok(client) => Box::new(RedisLeaderboard::new(client)),
|
||||||
|
Err(_) => Box::new(InMemoryLeaderboard()),
|
||||||
|
},
|
||||||
|
Err(_) => Box::new(InMemoryLeaderboard()),
|
||||||
|
}
|
||||||
|
}
|
@@ -1,3 +1,4 @@
|
|||||||
|
mod leaderboard;
|
||||||
mod player;
|
mod player;
|
||||||
mod room;
|
mod room;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user