mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 00:32:40 +00:00
Two longstanding warts surfaced when the user inspected today's TwinBee
daily report:
1. Active players were rendering "Acted today — no log recorded." The
adventure_activity_log path only captures !rest now; harvest/zone/
expedition action logging was lost during Phase R/L migration. The
stale HasActedToday() check fired on fossil harvest_actions_used
counters that nothing modern increments.
2. Per-player headline still rendered legacy four-skill line ("Combat
Lv.X | Mining Lv.Y | Forage Lv.Z | Fishing Lv.W"). No D&D level,
race, class, or HP — discoverability gap for the layer that's now
canonical.
Fix both:
- adventure_activity_unified.go: new loadAdvDailyActivity(date) unions
dnd_zone_run (zone runs touched today) + dnd_expedition_log
(expedition activity rolled up per expedition) + legacy
adventure_activity_log (mostly !rest). One source of truth.
- adventure_render.go: AdvPlayerDaySummary gains HasDnDChar/DnDLevel/
DnDRace/DnDClass/HPCurrent/HPMax. New advPlayerHeadline helper
renders "Lv.N Race Class — HP cur/max" when a dnd_character row
exists, falls back to the legacy four-skill line plus an inline
"(no D&D sheet — run !setup)" nudge for accounts that haven't
completed setup yet. titleizeDnDToken("half_elf") → "Half-Elf".
- adventure_scheduler.go: postDailySummary swaps loadAdvLogsForDate
for loadAdvDailyActivity. IsResting now derives from "len(acts)==0"
rather than the fossil HasActedToday() counter check, so dead
harvest_actions_used bytes can't trip the active-player branch.
- proddb_daily_report_test.go: renders the report against a copy of
data/gogobee.db and prints it for visual confirmation. Verified
output for 2026-05-09 shows real zone-run outcomes (Withdrew from
Sunken Temple at room 1/6, etc.) instead of the previous "no log
recorded" placeholder.
go vet + go test ./... clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
102 lines
2.6 KiB
Go
102 lines
2.6 KiB
Go
package plugin
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"gogobee/internal/db"
|
|
)
|
|
|
|
// TestProdDB_DailyReportPreview renders the Adv 2.0 daily summary against a
|
|
// copy of the prod DB and prints it. Manual smoke for the D&D-aware
|
|
// renderer.
|
|
func TestProdDB_DailyReportPreview(t *testing.T) {
|
|
src := "/home/reala-misaki/git/gogobee/data/gogobee.db"
|
|
if _, err := os.Stat(src); err != nil {
|
|
t.Skip("prod db not present")
|
|
}
|
|
dir := t.TempDir()
|
|
dst := filepath.Join(dir, "gogobee.db")
|
|
copyTestFile(t, src, dst)
|
|
|
|
db.Close()
|
|
if err := db.Init(dir); err != nil {
|
|
t.Fatalf("db.Init: %v", err)
|
|
}
|
|
t.Cleanup(db.Close)
|
|
|
|
bootstrapPlayerMetaFromLegacy()
|
|
|
|
chars, err := loadAllAdvCharacters()
|
|
if err != nil {
|
|
t.Fatalf("loadAllAdvCharacters: %v", err)
|
|
}
|
|
|
|
// Use the most recent activity date in the DB so we render against real
|
|
// data instead of an empty "today".
|
|
now := time.Now().UTC()
|
|
dateKey := now.Format("2006-01-02")
|
|
if acts, _ := loadAdvDailyActivity(dateKey); len(acts) == 0 {
|
|
// No activity today; walk back up to 7 days for a date that has rows.
|
|
for i := 1; i <= 7; i++ {
|
|
cand := now.AddDate(0, 0, -i).Format("2006-01-02")
|
|
if acts, _ := loadAdvDailyActivity(cand); len(acts) > 0 {
|
|
dateKey = cand
|
|
break
|
|
}
|
|
}
|
|
}
|
|
t.Logf("rendering report for date=%s", dateKey)
|
|
|
|
todayActs, _ := loadAdvDailyActivity(dateKey)
|
|
activityMap := make(map[string][]AdvDailyActivity)
|
|
for uid, e := range todayActs {
|
|
activityMap[string(uid)] = e
|
|
}
|
|
|
|
var players []AdvPlayerDaySummary
|
|
for _, c := range chars {
|
|
dispName, _ := loadDisplayName(c.UserID)
|
|
ps := AdvPlayerDaySummary{
|
|
DisplayName: dispName,
|
|
Level: c.CombatLevel,
|
|
MiningSkill: c.MiningSkill,
|
|
ForagingSkill: c.ForagingSkill,
|
|
FishingSkill: c.FishingSkill,
|
|
}
|
|
if dnd, _ := LoadDnDCharacter(c.UserID); dnd != nil {
|
|
ps.HasDnDChar = true
|
|
ps.DnDLevel = dnd.Level
|
|
ps.DnDRace = string(dnd.Race)
|
|
ps.DnDClass = string(dnd.Class)
|
|
ps.HPCurrent = dnd.HPCurrent
|
|
ps.HPMax = dnd.HPMax
|
|
}
|
|
|
|
acts := activityMap[string(c.UserID)]
|
|
if !c.Alive {
|
|
ps.IsDead = true
|
|
ps.DeathSource = c.DeathSource
|
|
ps.DeathLocation = c.DeathLocation
|
|
if c.DeadUntil != nil {
|
|
ps.DeadUntil = c.DeadUntil.Format("15:04") + " UTC"
|
|
}
|
|
} else if len(acts) == 0 {
|
|
ps.IsResting = true
|
|
ps.SummaryLine = "Stayed in town. The world's still here tomorrow."
|
|
} else {
|
|
last := acts[len(acts)-1]
|
|
ps.Activity = last.Activity
|
|
ps.Location = last.Location
|
|
ps.Outcome = last.Outcome
|
|
ps.SummaryLine = last.Summary
|
|
}
|
|
players = append(players, ps)
|
|
}
|
|
|
|
out := renderAdvDailySummary(dateKey, nil, TwinBeeRewardSummary{}, players, "")
|
|
t.Logf("\n%s", out)
|
|
}
|