refactor(battle-xp): retire ArenaTwoPickConfig.ClassXpPerBattle for shared BattleXpService

- ArenaTwoPickService now delegates class-XP grants to IBattleXpService
  with BattleXpMode.ArenaTwoPick. Inline GrantClassXp/ResolveClassLevel
  helpers deleted.
- ClassXpPerBattle field removed from ArenaTwoPickConfig; TK2 XP now
  configurable via ArenaTwoPickXpPerWin/XpPerLoss overrides or the global
  BattleXpConfig defaults (100/25).
- Updated 5 test files (ArenaTwoPickService callers) for the new
  constructor arg. Added loss-XP assertion to Finish tests.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-07-04 08:54:52 -04:00
parent 81771bb0a0
commit f85f221bfa
7 changed files with 31 additions and 23 deletions

View File

@@ -64,6 +64,7 @@ public class ArenaTwoPickServiceDraftTests
scope.ServiceProvider.GetRequiredService<IGameConfigService>(),
scope.ServiceProvider.GetRequiredService<IViewerRepository>(),
scope.ServiceProvider.GetRequiredService<IInventoryService>(),
scope.ServiceProvider.GetRequiredService<SVSim.Database.Services.BattleXp.IBattleXpService>(),
new SystemRandom(seed: 1),
db);

View File

@@ -59,6 +59,7 @@ public class ArenaTwoPickServiceEntryTests
config,
scope.ServiceProvider.GetRequiredService<IViewerRepository>(),
inv,
scope.ServiceProvider.GetRequiredService<SVSim.Database.Services.BattleXp.IBattleXpService>(),
new SystemRandom(seed: 1234),
db);

View File

@@ -80,6 +80,7 @@ public class ArenaTwoPickServiceFinishTests
scope.ServiceProvider.GetRequiredService<IGameConfigService>(),
scope.ServiceProvider.GetRequiredService<IViewerRepository>(),
scope.ServiceProvider.GetRequiredService<IInventoryService>(),
scope.ServiceProvider.GetRequiredService<SVSim.Database.Services.BattleXp.IBattleXpService>(),
new SystemRandom(seed: 1),
db);
@@ -136,13 +137,30 @@ public class ArenaTwoPickServiceFinishTests
var result = await svc.RecordBattleResultAsync(vid, isWin: true);
Assert.That(result.BattleResult, Is.EqualTo(1));
Assert.That(result.GetClassExperience, Is.EqualTo(100));
Assert.That(result.GetClassExperience, Is.EqualTo(100),
"Default BattleXpConfig.XpPerWin");
Assert.That(result.AddSpotPoint, Is.EqualTo(10));
var run = await db.ViewerArenaTwoPickRuns.FirstAsync(r => r.ViewerId == vid);
Assert.That(run.WinCount, Is.EqualTo(2));
Assert.That(JsonSerializer.Deserialize<List<bool>>(run.ResultListJson)!.Count, Is.EqualTo(2));
}
[Test]
public async Task RecordBattleResultAsync_loss_grants_loss_xp()
{
var (db, svc, vid) = await SetupWithRunAsync(winCount: 0, lossCount: 0);
await using var _ = db;
var result = await svc.RecordBattleResultAsync(vid, isWin: false);
Assert.That(result.BattleResult, Is.EqualTo(0));
Assert.That(result.GetClassExperience, Is.EqualTo(25),
"Default BattleXpConfig.XpPerLoss");
Assert.That(result.ClassExperience, Is.EqualTo(25),
"Fresh viewer with Exp=0, +25 loss XP < curve[1]=50 so no level-up.");
Assert.That(result.ClassLevel, Is.EqualTo(1));
}
[Test]
public async Task RecordBattleResultAsync_increments_loss_without_terminating()
{

View File

@@ -82,6 +82,6 @@ public class ArenaTwoPickServiceTopTests
{
// GetTopAsync only uses _runs — every other dep can be null! because the test path
// never touches them.
return new ArenaTwoPickService(runRepo, null!, null!, null!, null!, null!, null!, db);
return new ArenaTwoPickService(runRepo, null!, null!, null!, null!, null!, null!, null!, db);
}
}

View File

@@ -90,6 +90,7 @@ public class ArenaTwoPickServiceWeightedRewardsTests
scope.ServiceProvider.GetRequiredService<IGameConfigService>(),
scope.ServiceProvider.GetRequiredService<IViewerRepository>(),
scope.ServiceProvider.GetRequiredService<IInventoryService>(),
scope.ServiceProvider.GetRequiredService<SVSim.Database.Services.BattleXp.IBattleXpService>(),
rng,
db);