adventure: count the treasures an adventurer has actually found
A treasure_found fact turns loot into a trophy: a story-grade find lands on the who page as a stat tile, a named row in a Treasures found showcase, and a trail entry linking back to the dispatch. A realm-first hoard rides the priority tier the way zone_first does, and gets the same star and callout. The item name travels in the fact's stakes field, which the events log now keeps (a new nullable column, backfilled to NULL for older rows). Counting is only ever from the fact, never the vault snapshot, so a bought sword is never a trophy and a history that predates the fact is a clean zero. This is a new event_type, so Pete's ingest must be deployed before gogobee emits one, or the first finds park forever on the retry ladder.
This commit is contained in:
@@ -88,6 +88,50 @@ func TestTrophyCaseCounts(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestTrophyCaseTreasures: story-grade finds count out of the treasure_found
|
||||
// fact, the priority tier marks a realm-first hoard, and the item name rides the
|
||||
// stakes field into a per-find row. A find with no name still counts but earns no
|
||||
// showcase row.
|
||||
func TestTrophyCaseTreasures(t *testing.T) {
|
||||
setupTestDB(t)
|
||||
|
||||
hoard := ev("treasure_found:1:1", "treasure_found", "Josie", 100)
|
||||
hoard.Tier, hoard.Stakes, hoard.Zone = "priority", "Crown of the Drowned King", "The Ossuary"
|
||||
find := ev("treasure_found:2:2", "treasure_found", "Josie", 200)
|
||||
find.Tier, find.Stakes, find.Zone = "bulletin", "Ring of Nine Sorrows", "The Sump"
|
||||
nameless := ev("treasure_found:3:3", "treasure_found", "Josie", 300)
|
||||
nameless.Tier = "bulletin" // a find gogobee sent without a stakes noun
|
||||
|
||||
for _, e := range []*AdvEvent{hoard, find, nameless} {
|
||||
if err := InsertAdventureEvent(e); err != nil {
|
||||
t.Fatalf("insert %s: %v", e.GUID, err)
|
||||
}
|
||||
}
|
||||
|
||||
events, err := EventsBySubject("Josie", 0)
|
||||
if err != nil {
|
||||
t.Fatalf("EventsBySubject: %v", err)
|
||||
}
|
||||
tc := BuildTrophyCase("Josie", events)
|
||||
|
||||
if tc.TreasuresFound != 3 {
|
||||
t.Errorf("treasures found: got %d, want 3 (a nameless find still happened)", tc.TreasuresFound)
|
||||
}
|
||||
if tc.TreasureFirsts != 1 {
|
||||
t.Errorf("treasure firsts: got %d, want 1 (only the priority hoard)", tc.TreasureFirsts)
|
||||
}
|
||||
// Only the two named finds earn a showcase row, newest first.
|
||||
if len(tc.Treasures) != 2 {
|
||||
t.Fatalf("treasure rows: got %d, want 2 (nameless earns no row)", len(tc.Treasures))
|
||||
}
|
||||
if tc.Treasures[0].Item != "Ring of Nine Sorrows" || tc.Treasures[0].First {
|
||||
t.Errorf("newest row wrong: %+v", tc.Treasures[0])
|
||||
}
|
||||
if tc.Treasures[1].Item != "Crown of the Drowned King" || !tc.Treasures[1].First || tc.Treasures[1].Zone != "The Ossuary" {
|
||||
t.Errorf("hoard row wrong: %+v", tc.Treasures[1])
|
||||
}
|
||||
}
|
||||
|
||||
// TestTrophyCaseIgnoresOpponentCredit is the one that matters for honesty. A
|
||||
// duel Josie *lost* still names her, as the opponent in Quack's dispatch. It
|
||||
// belongs on her timeline but must never be credited to her trophy case.
|
||||
|
||||
Reference in New Issue
Block a user