wip: checkpoint multi-game core work
This commit is contained in:
+22
-8
@@ -5,33 +5,41 @@ use crate::{
|
||||
};
|
||||
use chrono::Utc;
|
||||
|
||||
pub async fn get_active_profile(pool: &Pool) -> AppResult<Profile> {
|
||||
/// Fetch the active profile for a game. Single-profile-per-game: there is exactly
|
||||
/// one profile row per `game_id`, so we take the earliest for that game.
|
||||
pub async fn get_active_profile(pool: &Pool, game_id: &str) -> AppResult<Profile> {
|
||||
sqlx::query_as::<_, Profile>(
|
||||
"SELECT id, username, level, xp, created_at, updated_at FROM profiles ORDER BY created_at ASC LIMIT 1"
|
||||
"SELECT id, username, level, xp, game_id, created_at, updated_at \
|
||||
FROM profiles WHERE game_id = ? ORDER BY created_at ASC LIMIT 1",
|
||||
)
|
||||
.bind(game_id)
|
||||
.fetch_optional(pool)
|
||||
.await?
|
||||
.ok_or_else(|| AppError::NotFound("no profile exists; call POST /auth/local first".into()))
|
||||
}
|
||||
|
||||
pub async fn create_profile(pool: &Pool, username: &str) -> AppResult<Profile> {
|
||||
let existing = sqlx::query_scalar::<_, i64>("SELECT COUNT(*) FROM profiles")
|
||||
pub async fn create_profile(pool: &Pool, username: &str, game_id: &str) -> AppResult<Profile> {
|
||||
// Single-player per game: one profile per game_id, not one globally.
|
||||
let existing = sqlx::query_scalar::<_, i64>("SELECT COUNT(*) FROM profiles WHERE game_id = ?")
|
||||
.bind(game_id)
|
||||
.fetch_one(pool)
|
||||
.await?;
|
||||
if existing > 0 {
|
||||
return Err(AppError::Conflict(
|
||||
"a profile already exists; OpenFUT is single-player only".into(),
|
||||
"a profile already exists for this game; OpenFUT is single-player per game".into(),
|
||||
));
|
||||
}
|
||||
|
||||
let profile = Profile::new(username);
|
||||
let profile = Profile::new(username, game_id);
|
||||
sqlx::query(
|
||||
"INSERT INTO profiles (id, username, level, xp, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)"
|
||||
"INSERT INTO profiles (id, username, level, xp, game_id, created_at, updated_at) \
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||
)
|
||||
.bind(&profile.id)
|
||||
.bind(&profile.username)
|
||||
.bind(profile.level)
|
||||
.bind(profile.xp)
|
||||
.bind(&profile.game_id)
|
||||
.bind(profile.created_at)
|
||||
.bind(profile.updated_at)
|
||||
.execute(pool)
|
||||
@@ -59,7 +67,13 @@ pub async fn add_xp_with_levelup(
|
||||
club_id: &str,
|
||||
xp_to_add: i64,
|
||||
) -> AppResult<Vec<LevelUpEvent>> {
|
||||
let profile = get_active_profile(pool).await?;
|
||||
let profile = sqlx::query_as::<_, Profile>(
|
||||
"SELECT id, username, level, xp, game_id, created_at, updated_at FROM profiles WHERE id = ?",
|
||||
)
|
||||
.bind(profile_id)
|
||||
.fetch_optional(pool)
|
||||
.await?
|
||||
.ok_or_else(|| AppError::NotFound(format!("profile '{profile_id}' not found")))?;
|
||||
let old_level = level_for_xp(profile.xp);
|
||||
let new_total_xp = profile.xp + xp_to_add;
|
||||
let new_level = level_for_xp(new_total_xp);
|
||||
|
||||
Reference in New Issue
Block a user