Phase 17: profile level-up system
CI / Build, lint & test (push) Failing after 57s

XP thresholds (500→1200→2000→…→11000→+2500/level) drive automatic level
increases. add_xp_with_levelup() replaces bare add_xp() in match
processing: for each level gained it grants level×500 coins and milestone
packs (bronze@5, silver@10, gold@15, rare_gold@20, gold every 5 after).

GET /profile now returns computed level (recalculated from XP so it
stays consistent), xp_to_next_level, and xp_for_next_level so the
dashboard can render a progress bar without a second call.

POST /matches/result response gains level_ups array (empty when no
level-up occurred) with new_level, coins_granted, pack_granted per event.

Four new tests: profile level fields, level_for_xp boundary checks,
level-up event in match result, milestone pack unit test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-06-25 17:41:13 -07:00
parent 3d50da3589
commit d97695d414
6 changed files with 257 additions and 6 deletions
+7
View File
@@ -1,3 +1,4 @@
use crate::models::profile::LevelUpEvent;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
@@ -77,4 +78,10 @@ pub struct MatchRewardResult {
pub coins_awarded: i64,
pub xp_awarded: i64,
pub objectives_updated: Vec<String>,
/// Owned card IDs removed because the loan expired this match.
pub expired_loans: Vec<String>,
/// Present when this match completed the current season.
pub season_end: Option<crate::models::season::SeasonEndSummary>,
/// Non-empty when the player levelled up one or more times from this match's XP.
pub level_ups: Vec<LevelUpEvent>,
}