125 lines
3.7 KiB
Rust
125 lines
3.7 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, profile as profile_svc, upgrades as upgrade_svc},
|
||
};
|
||
|
||
/// GET /chemistry-styles — list all available styles with their stat boosts.
|
||
pub async fn get_chemistry_styles(State(state): State<AppState>) -> AppResult<Json<Value>> {
|
||
Ok(Json(json!({
|
||
"chemistry_styles": *state.chem_styles,
|
||
"total": state.chem_styles.len(),
|
||
})))
|
||
}
|
||
|
||
#[derive(Deserialize)]
|
||
pub struct ApplyChemStyleRequest {
|
||
pub style_id: String,
|
||
}
|
||
|
||
/// POST /collection/:owned_card_id/chemistry-style
|
||
pub async fn post_apply_chemistry_style(
|
||
State(state): State<AppState>,
|
||
game: GameId,
|
||
Path(owned_card_id): Path<String>,
|
||
Json(req): Json<ApplyChemStyleRequest>,
|
||
) -> 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 updated = upgrade_svc::apply_chemistry_style(
|
||
&state.pool,
|
||
&club.id,
|
||
&owned_card_id,
|
||
&req.style_id,
|
||
&state.chem_styles,
|
||
)
|
||
.await?;
|
||
|
||
let style = state
|
||
.chem_styles
|
||
.iter()
|
||
.find(|s| s.id == updated.chemistry_style);
|
||
|
||
Ok(Json(json!({
|
||
"owned_card_id": updated.id,
|
||
"card_id": updated.card_id,
|
||
"chemistry_style": updated.chemistry_style,
|
||
"style_details": style,
|
||
})))
|
||
}
|
||
|
||
#[derive(Deserialize)]
|
||
pub struct ChangePositionRequest {
|
||
pub position: String,
|
||
}
|
||
|
||
/// POST /collection/:owned_card_id/position — costs 500 coins.
|
||
pub async fn post_change_position(
|
||
State(state): State<AppState>,
|
||
game: GameId,
|
||
Path(owned_card_id): Path<String>,
|
||
Json(req): Json<ChangePositionRequest>,
|
||
) -> 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 updated = upgrade_svc::change_position(
|
||
&state.pool,
|
||
&club.id,
|
||
&owned_card_id,
|
||
&req.position,
|
||
)
|
||
.await?;
|
||
|
||
let card_def = state.card_db.get(&updated.card_id);
|
||
|
||
Ok(Json(json!({
|
||
"owned_card_id": updated.id,
|
||
"card_id": updated.card_id,
|
||
"original_position": card_def.map(|c| &c.position),
|
||
"position_override": updated.position_override,
|
||
"cost_coins": upgrade_svc::POSITION_CHANGE_COST,
|
||
})))
|
||
}
|
||
|
||
#[derive(Deserialize)]
|
||
pub struct ApplyTrainingRequest {
|
||
/// OVR points to add. Must be 1–3. Total capped at +3.
|
||
pub boost: i64,
|
||
}
|
||
|
||
/// POST /collection/:owned_card_id/training — applies a training boost (up to +3 OVR total).
|
||
pub async fn post_apply_training(
|
||
State(state): State<AppState>,
|
||
game: GameId,
|
||
Path(owned_card_id): Path<String>,
|
||
Json(req): Json<ApplyTrainingRequest>,
|
||
) -> 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 updated =
|
||
upgrade_svc::apply_training(&state.pool, &club.id, &owned_card_id, req.boost).await?;
|
||
|
||
let card_def = state.card_db.get(&updated.card_id);
|
||
let base_overall = card_def.map(|c| c.overall as i64).unwrap_or(0);
|
||
|
||
Ok(Json(json!({
|
||
"owned_card_id": updated.id,
|
||
"card_id": updated.card_id,
|
||
"base_overall": base_overall,
|
||
"training_bonus": updated.training_bonus,
|
||
"effective_overall": base_overall + updated.training_bonus,
|
||
"max_bonus": upgrade_svc::MAX_TRAINING_BONUS,
|
||
})))
|
||
}
|