127 lines
3.8 KiB
Rust
127 lines
3.8 KiB
Rust
use crate::extractors::GameId;
|
|
use axum::{
|
|
extract::{Path, State},
|
|
Json,
|
|
};
|
|
use serde::Deserialize;
|
|
use serde_json::{json, Value};
|
|
|
|
use crate::{
|
|
app::AppState,
|
|
error::AppResult,
|
|
services::{club as club_svc, fut_champs as champs_svc, profile as profile_svc, season as season_svc},
|
|
};
|
|
|
|
/// GET /fut-champs — current active session, or null if none.
|
|
pub async fn get_fut_champs(State(state): State<AppState>, game: GameId) -> AppResult<Json<Value>> {
|
|
let profile = profile_svc::get_active_profile(&state.pool, game.as_str()).await?;
|
|
let session = champs_svc::get_active_session(&state.pool, &profile.id).await?;
|
|
|
|
Ok(Json(json!({
|
|
"session": session,
|
|
"max_matches": crate::models::fut_champs::MAX_MATCHES,
|
|
})))
|
|
}
|
|
|
|
/// POST /fut-champs/start — open a new FUT Champions week.
|
|
pub async fn post_start_fut_champs(State(state): State<AppState>, game: GameId) -> AppResult<Json<Value>> {
|
|
let profile = profile_svc::get_active_profile(&state.pool, game.as_str()).await?;
|
|
let session = champs_svc::start_session(&state.pool, &profile.id).await?;
|
|
|
|
Ok(Json(json!({
|
|
"session": session,
|
|
"message": "FUT Champions week started — play up to 30 matches",
|
|
})))
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct ChampsMatchRequest {
|
|
pub goals_for: i64,
|
|
pub goals_against: i64,
|
|
}
|
|
|
|
/// POST /fut-champs/:session_id/result — record a match in this session.
|
|
pub async fn post_champs_result(
|
|
State(state): State<AppState>,
|
|
game: GameId,
|
|
Path(session_id): Path<String>,
|
|
Json(req): Json<ChampsMatchRequest>,
|
|
) -> AppResult<Json<Value>> {
|
|
let profile = profile_svc::get_active_profile(&state.pool, game.as_str()).await?;
|
|
|
|
let session = champs_svc::record_match(
|
|
&state.pool,
|
|
&profile.id,
|
|
&session_id,
|
|
req.goals_for,
|
|
req.goals_against,
|
|
)
|
|
.await?;
|
|
|
|
let outcome = if req.goals_for > req.goals_against {
|
|
"win"
|
|
} else if req.goals_for == req.goals_against {
|
|
"draw"
|
|
} else {
|
|
"loss"
|
|
};
|
|
|
|
Ok(Json(json!({
|
|
"session": session,
|
|
"outcome": outcome,
|
|
"matches_remaining": session.matches_remaining(),
|
|
"auto_completed": session.is_complete(),
|
|
})))
|
|
}
|
|
|
|
/// POST /fut-champs/:session_id/claim — claim end-of-week rewards.
|
|
pub async fn post_claim_champs_rewards(
|
|
State(state): State<AppState>,
|
|
game: GameId,
|
|
Path(session_id): Path<String>,
|
|
) -> AppResult<Json<Value>> {
|
|
let profile = profile_svc::get_active_profile(&state.pool, game.as_str()).await?;
|
|
let club = club_svc::get_club_by_profile(&state.pool, &profile.id).await?;
|
|
|
|
let result = champs_svc::claim_rewards(
|
|
&state.pool,
|
|
&profile.id,
|
|
&session_id,
|
|
&club.id,
|
|
&state.pack_defs,
|
|
)
|
|
.await?;
|
|
|
|
Ok(Json(result))
|
|
}
|
|
|
|
/// GET /fut-champs/history — past sessions, newest first.
|
|
pub async fn get_champs_history(State(state): State<AppState>, game: GameId) -> AppResult<Json<Value>> {
|
|
let profile = profile_svc::get_active_profile(&state.pool, game.as_str()).await?;
|
|
let history = champs_svc::get_history(&state.pool, &profile.id).await?;
|
|
|
|
Ok(Json(json!({
|
|
"history": history,
|
|
"total": history.len(),
|
|
})))
|
|
}
|
|
|
|
/// POST /rivals/claim-weekly — claim weekly Division Rivals reward.
|
|
pub async fn post_claim_rivals_reward(State(state): State<AppState>, game: GameId) -> AppResult<Json<Value>> {
|
|
let profile = profile_svc::get_active_profile(&state.pool, game.as_str()).await?;
|
|
let club = club_svc::get_club_by_profile(&state.pool, &profile.id).await?;
|
|
|
|
// Ensure a season row exists
|
|
season_svc::get_or_create(&state.pool, &profile.id).await?;
|
|
|
|
let result = champs_svc::claim_rivals_reward(
|
|
&state.pool,
|
|
&profile.id,
|
|
&club.id,
|
|
&state.pack_defs,
|
|
)
|
|
.await?;
|
|
|
|
Ok(Json(result))
|
|
}
|