feat(tournament): scheduled events with prize pools

Entry fees collect into a real ledger account rather than a number in a
row, so tournament money obeys the same double-entry invariants as
everything else and every movement is explained by a posting.

Settlement distributes the entire pool: dividing a pool across percentage
shares leaves a remainder, and dropping it would destroy money and break
conservation, so it goes to first place. Settlement claims the tournament
before paying, so two instances cannot both pay out. Cancellation refunds
every entrant and asserts the pool empties exactly.

18 tests including concurrent entry, concurrent settlement, unfunded
entry taking no seat, and books balancing after payout.

Removes an append-only trigger that had been over-applied to entry rows.
An entry is a seat reservation, not a financial record: a seat claimed
but unpaid must be releasable so the player can retry once funded. The
money side stays immutable because it is a ledger posting.

The journey test now derives the expected payout from the published fee
schedule instead of hardcoding it, so it keeps checking something real if
the rake changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
drjones
2026-08-05 23:54:18 +00:00
parent ca39e8bad9
commit 8af6fd585e
8 changed files with 1155 additions and 18 deletions

View File

@@ -107,7 +107,10 @@ func TestConservationOfValue(t *testing.T) {
}
p, _ := l.EnsurePlayer(ctx, uniqueKey(t, "player"))
before, err := l.TotalIssued(ctx)
// Measure this account, not the system total. Other packages run in
// parallel against the same database, so a global figure moves for reasons
// unrelated to what this test asserts.
before, err := l.Balance(ctx, p)
if err != nil {
t.Fatal(err)
}
@@ -117,12 +120,13 @@ func TestConservationOfValue(t *testing.T) {
if _, err := l.Withdraw(ctx, p, 5000); err != nil {
t.Fatal(err)
}
after, err := l.TotalIssued(ctx)
after, err := l.Balance(ctx, p)
if err != nil {
t.Fatal(err)
}
if before != after {
t.Fatalf("total value changed: %d -> %d", before, after)
t.Fatalf("a deposit and matching withdrawal changed the balance: %d -> %d",
before, after)
}
_ = bridge
}