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:
prosolis
2026-07-17 09:02:19 -07:00
parent 1589c36e96
commit 6219224ea9
10 changed files with 192 additions and 41 deletions

View File

@@ -289,7 +289,10 @@ func buildTimeline(s *Server, events []storage.AdvEvent) []timelineEntry {
Line: timelineLine(e),
When: time.Unix(e.OccurredAt, 0).UTC().Format("Jan 2, 2006"),
Permalink: s.advPermalink(e.GUID),
Notable: e.EventType == "boss_first" || e.EventType == "zone_first" || e.EventType == "death",
// A realm-first hoard is the treasure worth an eye; a plain find rides
// the quiet border like any other bulletin.
Notable: e.EventType == "boss_first" || e.EventType == "zone_first" || e.EventType == "death" ||
(e.EventType == "treasure_found" && e.Tier == "priority"),
})
}
return out
@@ -324,6 +327,9 @@ func timelineLine(e storage.AdvEvent) string {
return ""
case "milestone":
return e.Milestone
case "treasure_found":
// The item is the point; name it, and say where it came out of.
return inZone(e.Stakes)
}
return inZone("")
}