fix(tk2): match original SV (5-battle cap, no loss limit)
User clarified: the 0..7 win reward tiers came from Shadowverse Worlds Beyond (sequel), not the original game we're emulating. Original SV's Take Two caps at 5 total battles played and has no loss limit (verified on prod: queueing continues with 2+ losses). - arena-two-pick-rewards.json: drop 6w + 7w tiers (12 rows remain). - ArenaTwoPickConfig: remove MaxLosses property. - ArenaTwoPickService: termination is now battlesPlayed >= maxBattles (5 from MAX(reward.WinCount)). RecordBattleResult no longer flips IsSelectCompleted on the 2nd loss. - ResolveMaxBattleCountAsync empty-catalog default 7 → 5. - Tests updated for the new counts (16 → 12 rows, max 7 → 5). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -18,25 +18,26 @@ public class ArenaTwoPickRewardImporterTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Import_loads_all_16_rows_from_seed_file()
|
||||
public async Task Import_loads_all_12_rows_from_seed_file()
|
||||
{
|
||||
await using var db = await CreateContextAsync();
|
||||
var importer = new ArenaTwoPickRewardImporter();
|
||||
|
||||
await importer.ImportAsync(db, FindSeedDir());
|
||||
|
||||
// 6 WinCount tiers (0..5) × 2 reward rows each = 12. Classic SV TK2 caps at 5 battles.
|
||||
var rows = await db.ArenaTwoPickRewards.OrderBy(r => r.WinCount).ThenBy(r => r.RewardType).ToListAsync();
|
||||
Assert.That(rows.Count, Is.EqualTo(16));
|
||||
Assert.That(rows.Max(r => r.WinCount), Is.EqualTo(7));
|
||||
Assert.That(rows.Count, Is.EqualTo(12));
|
||||
Assert.That(rows.Max(r => r.WinCount), Is.EqualTo(5));
|
||||
|
||||
var w0 = rows.Where(r => r.WinCount == 0).ToList();
|
||||
Assert.That(w0.Count, Is.EqualTo(2));
|
||||
Assert.That(w0.Single(r => r.RewardType == 4).RewardNum, Is.EqualTo(1));
|
||||
Assert.That(w0.Single(r => r.RewardType == 9).RewardNum, Is.EqualTo(100));
|
||||
|
||||
var w7 = rows.Where(r => r.WinCount == 7).ToList();
|
||||
Assert.That(w7.Single(r => r.RewardType == 4).RewardNum, Is.EqualTo(2));
|
||||
Assert.That(w7.Single(r => r.RewardType == 9).RewardNum, Is.EqualTo(1500));
|
||||
var w5 = rows.Where(r => r.WinCount == 5).ToList();
|
||||
Assert.That(w5.Single(r => r.RewardType == 4).RewardNum, Is.EqualTo(1));
|
||||
Assert.That(w5.Single(r => r.RewardType == 9).RewardNum, Is.EqualTo(1000));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -49,7 +50,7 @@ public class ArenaTwoPickRewardImporterTests
|
||||
await importer.ImportAsync(db, FindSeedDir());
|
||||
|
||||
var count = await db.ArenaTwoPickRewards.CountAsync();
|
||||
Assert.That(count, Is.EqualTo(16), "second import should upsert, not duplicate");
|
||||
Assert.That(count, Is.EqualTo(12), "second import should upsert, not duplicate");
|
||||
}
|
||||
|
||||
private static string FindSeedDir()
|
||||
|
||||
@@ -26,7 +26,7 @@ public class ArenaTwoPickRewardRepositoryTests
|
||||
await using var db = await SeededContextAsync();
|
||||
var repo = new ArenaTwoPickRewardRepository(db);
|
||||
|
||||
for (int w = 0; w <= 7; w++)
|
||||
for (int w = 0; w <= 5; w++)
|
||||
{
|
||||
var rows = await repo.GetRewardsByWinCountAsync(w);
|
||||
Assert.That(rows.Count, Is.EqualTo(2), $"WinCount={w} should have 2 reward rows");
|
||||
@@ -34,12 +34,12 @@ public class ArenaTwoPickRewardRepositoryTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetMaxWinCount_returns_7()
|
||||
public async Task GetMaxWinCount_returns_5()
|
||||
{
|
||||
await using var db = await SeededContextAsync();
|
||||
var repo = new ArenaTwoPickRewardRepository(db);
|
||||
var max = await repo.GetMaxWinCountAsync();
|
||||
Assert.That(max, Is.EqualTo(7));
|
||||
Assert.That(max, Is.EqualTo(5));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -87,7 +87,7 @@ public class ArenaTwoPickServiceEntryTests
|
||||
var dto = await svc.EntryAsync(viewerId, consumeItemType: 3);
|
||||
|
||||
Assert.That(dto.EntryInfo.Id, Is.GreaterThan(0));
|
||||
Assert.That(dto.EntryInfo.MaxBattleCount, Is.EqualTo(7));
|
||||
Assert.That(dto.EntryInfo.MaxBattleCount, Is.EqualTo(5));
|
||||
Assert.That(dto.CandidateClassIds.Count, Is.EqualTo(3));
|
||||
Assert.That(dto.RewardList.Count, Is.EqualTo(1));
|
||||
Assert.That(dto.RewardList[0].RewardType, Is.EqualTo(4));
|
||||
@@ -96,7 +96,7 @@ public class ArenaTwoPickServiceEntryTests
|
||||
|
||||
var run = await db.ViewerArenaTwoPickRuns.FirstAsync(r => r.ViewerId == viewerId);
|
||||
Assert.That(run.ClassId, Is.EqualTo(0));
|
||||
Assert.That(run.MaxBattleCount, Is.EqualTo(7));
|
||||
Assert.That(run.MaxBattleCount, Is.EqualTo(5));
|
||||
|
||||
// Re-read viewer to verify ticket was debited.
|
||||
var updated = await db.Viewers.Include(v => v.Items).ThenInclude(i => i.Item).FirstAsync(v => v.Id == viewerId);
|
||||
|
||||
@@ -128,9 +128,11 @@ public class ArenaTwoPickServiceFinishTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FinishAsync_at_2_losses_grants_loss_rewards_and_deletes_run()
|
||||
public async Task FinishAsync_at_5_total_battles_with_0_wins_grants_loss_rewards_and_deletes_run()
|
||||
{
|
||||
var (db, svc, vid) = await SetupWithRunAsync(winCount: 0, lossCount: 2);
|
||||
// Classic Take Two: run ends after 5 total battles played, regardless of W/L split.
|
||||
// 0W 5L = floor-tier reward (1 ticket + 100 rupies).
|
||||
var (db, svc, vid) = await SetupWithRunAsync(winCount: 0, lossCount: 5);
|
||||
await using var _ = db;
|
||||
|
||||
var dto = await svc.FinishAsync(vid);
|
||||
@@ -155,14 +157,17 @@ public class ArenaTwoPickServiceFinishTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task RecordBattleResultAsync_2nd_loss_terminates_run()
|
||||
public async Task RecordBattleResultAsync_increments_loss_without_terminating()
|
||||
{
|
||||
// No 2-loss cap (that's a Worlds Beyond rule). Run termination is purely battles-played
|
||||
// based and handled at Finish/Retire time, not in RecordBattleResult.
|
||||
var (db, svc, vid) = await SetupWithRunAsync(winCount: 0, lossCount: 1);
|
||||
await using var _ = db;
|
||||
|
||||
await svc.RecordBattleResultAsync(vid, isWin: false);
|
||||
var run = await db.ViewerArenaTwoPickRuns.FirstAsync();
|
||||
Assert.That(run.LossCount, Is.EqualTo(2));
|
||||
Assert.That(run.IsSelectCompleted, Is.True);
|
||||
// Run still alive — IsSelectCompleted only flips when the 30-card draft finishes.
|
||||
Assert.That(run.IsSelectCompleted, Is.True, "the test setup pre-sets isSelectCompleted=true");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user