feat(rank-progress): RankProgressResult carries TierAdvanced signal
RankProgressResult gains a TierAdvanced bool (defaulted false so the 7-arg positional-constructor sites don't break). Set true iff the grant is a win AND RankTier.Name resolves both pre-grant and post-grant to distinct strings — i.e. a promotion crossed a tier boundary. Explicitly guards on isWin so a demotion (in principle possible after a loss below a tier floor, though the current floor rules prevent it) never fires the achievement backward. Three new tests: no-cross win, beginner→d cross, loss stays false. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -242,4 +242,45 @@ public class RankProgressServiceTests
|
||||
Assert.That(r.AfterMasterPoint, Is.EqualTo(0));
|
||||
Assert.That(v.RankProgress, Is.Empty);
|
||||
}
|
||||
|
||||
// ---- TierAdvanced ----
|
||||
|
||||
[Test]
|
||||
public async Task TierAdvanced_is_false_when_win_stays_within_same_tier()
|
||||
{
|
||||
// Point 100 (Beginner 1, rank 2) + 100 win = 200 (Beginner 3, rank 4). Still beginner.
|
||||
var svc = NewService();
|
||||
var v = NewViewer(Format.Rotation, point: 100, masterPoint: 0);
|
||||
|
||||
var r = await svc.GrantAsync(v, Format.Rotation, isWin: true);
|
||||
|
||||
Assert.That(RankTier.Name(r.Rank), Is.EqualTo("beginner"));
|
||||
Assert.That(r.TierAdvanced, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TierAdvanced_is_true_when_win_crosses_beginner_to_d()
|
||||
{
|
||||
// Point 1150 (Beginner 3, rank 4 — needs 1200 to leave beginner) + 100 = 1250 = D0 (rank 5).
|
||||
var svc = NewService();
|
||||
var v = NewViewer(Format.Rotation, point: 1150, masterPoint: 0);
|
||||
|
||||
var r = await svc.GrantAsync(v, Format.Rotation, isWin: true);
|
||||
|
||||
Assert.That(r.Rank, Is.EqualTo(5), "Expected promotion to rank 5 (D0)");
|
||||
Assert.That(r.TierAdvanced, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TierAdvanced_is_false_on_loss_even_if_tier_string_changes()
|
||||
{
|
||||
// Loss can't advance a tier — even if it demoted, the achievement doesn't fire backward.
|
||||
// Point 1200 (D0, rank 5) - 50 loss = 1200 (floored). Still D0. Prove flag stays false.
|
||||
var svc = NewService();
|
||||
var v = NewViewer(Format.Rotation, point: 1200, masterPoint: 0);
|
||||
|
||||
var r = await svc.GrantAsync(v, Format.Rotation, isWin: false);
|
||||
|
||||
Assert.That(r.TierAdvanced, Is.False);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user