feat(battle-xp): wire free-battle /finish through IBattleXpService

- FreeBattleController.Finish (rotation + unlimited URLs) now grants
  win/loss XP via IBattleXpService with BattleXpMode.Free.
- Preserves the strict field subset (no rank/master fields).
- Tests updated: win asserts XP+level-up; new loss test on rotation URL.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-07-04 09:00:29 -04:00
parent 1e9693e56d
commit 91ec14fc7e
2 changed files with 39 additions and 8 deletions

View File

@@ -1,7 +1,10 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SVSim.BattleNode.Bridge;
using SVSim.Database;
using SVSim.Database.Enums;
using SVSim.Database.Repositories.Viewer;
using SVSim.Database.Services.BattleXp;
using SVSim.Database.Services.Friend;
using SVSim.Database.Services.Replay;
using SVSim.EmulatedEntrypoint.Constants;
@@ -32,6 +35,9 @@ public sealed class FreeBattleController : ControllerBase
private readonly IBattleContextStore _battleContextStore;
private readonly IBattleHistoryWriter _historyWriter;
private readonly IPlayedTogetherWriter _playedTogetherWriter;
private readonly IViewerRepository _viewers;
private readonly IBattleXpService _xp;
private readonly SVSimDbContext _db;
private readonly ILogger<FreeBattleController> _log;
public FreeBattleController(
@@ -40,6 +46,9 @@ public sealed class FreeBattleController : ControllerBase
IBattleContextStore battleContextStore,
IBattleHistoryWriter historyWriter,
IPlayedTogetherWriter playedTogetherWriter,
IViewerRepository viewers,
IBattleXpService xp,
SVSimDbContext db,
ILogger<FreeBattleController> log)
{
_resolver = resolver;
@@ -47,6 +56,9 @@ public sealed class FreeBattleController : ControllerBase
_battleContextStore = battleContextStore;
_historyWriter = historyWriter;
_playedTogetherWriter = playedTogetherWriter;
_viewers = viewers;
_xp = xp;
_db = db;
_log = log;
}
@@ -97,10 +109,23 @@ public sealed class FreeBattleController : ControllerBase
ct);
}
int gainXp = 0, totalXp = 0, level = 1;
var viewer = await _viewers.LoadForBattleXpGrantAsync(vid, ct);
if (viewer is not null)
{
var xp = await _xp.GrantAsync(viewer, req.ClassId, isWin, BattleXpMode.Free, ct);
await _db.SaveChangesAsync(ct);
gainXp = xp.GetXp;
totalXp = xp.TotalXp;
level = xp.Level == 0 ? 1 : xp.Level;
}
return Ok(new FreeBattleFinishResponseDto
{
BattleResult = req.BattleResult,
// All other fields default to 0 (ClassLevel defaults to 1).
GetClassExperience = gainXp,
ClassExperience = totalXp,
ClassLevel = level,
});
}