feat: record bot games results
This commit is contained in:
parent
592dfe52af
commit
203825e28f
8 changed files with 98 additions and 14 deletions
|
|
@ -321,6 +321,34 @@ pub async fn insert_participant(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Records a completed bot game for a logged-in user in a single transaction.
|
||||
pub async fn insert_bot_game(
|
||||
pool: &Pool,
|
||||
user_id: i64,
|
||||
result: &str,
|
||||
outcome: &str,
|
||||
) -> Result<(), DbError> {
|
||||
let mut client = pool.get().await?;
|
||||
let tx = client.transaction().await?;
|
||||
let now = now_unix();
|
||||
let row = tx
|
||||
.query_one(
|
||||
"INSERT INTO game_records (game_id, room_code, started_at, ended_at, result) \
|
||||
VALUES ('trictrac', 'bot', $1, $1, $2) RETURNING id",
|
||||
&[&now, &result],
|
||||
)
|
||||
.await?;
|
||||
let record_id: i64 = row.get(0);
|
||||
tx.execute(
|
||||
"INSERT INTO game_participants (game_record_id, user_id, player_id, outcome) \
|
||||
VALUES ($1, $2, 0, $3)",
|
||||
&[&record_id, &user_id, &outcome],
|
||||
)
|
||||
.await?;
|
||||
tx.commit().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns win/loss/draw counts for a user. All values are 0 when the user has no games.
|
||||
pub async fn get_user_stats(pool: &Pool, user_id: i64) -> Result<UserStats, DbError> {
|
||||
let client = pool.get().await?;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
//! GET /users/:username/games?page=0&per_page=20
|
||||
//! GET /games/:id
|
||||
//! POST /games/result
|
||||
//! POST /games/bot-result
|
||||
|
||||
use axum::{
|
||||
Json, Router,
|
||||
|
|
@ -52,6 +53,7 @@ pub fn router() -> Router<Arc<AppState>> {
|
|||
.route("/users/{username}", get(user_profile))
|
||||
.route("/users/{username}/games", get(user_games))
|
||||
.route("/games/result", post(game_result))
|
||||
.route("/games/bot-result", post(bot_game_result))
|
||||
.route("/games/{id}", get(game_detail))
|
||||
.route("/pages/{slug}", get(get_page))
|
||||
}
|
||||
|
|
@ -548,6 +550,26 @@ async fn game_result(
|
|||
Ok(Json(GameResultResponse { game_record_id }))
|
||||
}
|
||||
|
||||
// ── Bot game result ───────────────────────────────────────────────────────────
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct BotGameResultBody {
|
||||
result: String,
|
||||
outcome: String,
|
||||
}
|
||||
|
||||
/// Called by the WASM client when a logged-in user finishes a bot game.
|
||||
async fn bot_game_result(
|
||||
auth_session: AuthSession<AuthBackend>,
|
||||
State(state): State<Arc<AppState>>,
|
||||
Json(body): Json<BotGameResultBody>,
|
||||
) -> Result<impl IntoResponse, AppError> {
|
||||
let user = auth_session.user.ok_or(AppError::Unauthorized)?;
|
||||
db::insert_bot_game(&state.db, user.id, &body.result, &body.outcome).await?;
|
||||
tracing::info!(user_id = user.id, outcome = body.outcome, "Bot game recorded");
|
||||
Ok(StatusCode::OK)
|
||||
}
|
||||
|
||||
// ── Static content pages ──────────────────────────────────────────────────────
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue