From 5c5070502a7f3aa7f1af7d41c3a3d55fe8e9ff53 Mon Sep 17 00:00:00 2001 From: tolelom <98kimsungmin@naver.com> Date: Tue, 24 Mar 2026 15:33:16 +0900 Subject: [PATCH] feat: enhanced leaderboard with floor/gold rankings and class info Co-Authored-By: Claude Sonnet 4.6 --- store/db_test.go | 14 ++++++------ ui/leaderboard_view.go | 51 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 ui/leaderboard_view.go diff --git a/store/db_test.go b/store/db_test.go index 3025074..82e1bee 100644 --- a/store/db_test.go +++ b/store/db_test.go @@ -38,9 +38,9 @@ func TestRanking(t *testing.T) { os.Remove("test_rank.db") }() - db.SaveRun("Alice", 20, 1500) - db.SaveRun("Bob", 15, 1000) - db.SaveRun("Charlie", 20, 2000) + db.SaveRun("Alice", 20, 1500, "Warrior") + db.SaveRun("Bob", 15, 1000, "Mage") + db.SaveRun("Charlie", 20, 2000, "Rogue") rankings, err := db.TopRuns(10) if err != nil { @@ -63,10 +63,10 @@ func TestGetStats(t *testing.T) { defer db.Close() // Save some runs - db.SaveRun("Alice", 5, 100) - db.SaveRun("Alice", 10, 250) - db.SaveRun("Alice", 20, 500) // victory (floor >= 20) - db.SaveRun("Bob", 3, 50) + db.SaveRun("Alice", 5, 100, "Warrior") + db.SaveRun("Alice", 10, 250, "Warrior") + db.SaveRun("Alice", 20, 500, "Warrior") // victory (floor >= 20) + db.SaveRun("Bob", 3, 50, "") stats, err := db.GetStats("Alice") if err != nil { diff --git a/ui/leaderboard_view.go b/ui/leaderboard_view.go new file mode 100644 index 0000000..d8ce493 --- /dev/null +++ b/ui/leaderboard_view.go @@ -0,0 +1,51 @@ +package ui + +import ( + "fmt" + + "github.com/charmbracelet/lipgloss" + "github.com/tolelom/catacombs/store" +) + +func renderLeaderboard(byFloor, byGold []store.RunRecord, width, height int) string { + title := styleHeader.Render("── Leaderboard ──") + + // By Floor + var floorSection string + floorSection += styleCoop.Render(" Top by Floor") + "\n" + for i, r := range byFloor { + if i >= 5 { + break + } + medal := fmt.Sprintf(" %d.", i+1) + cls := "" + if r.Class != "" { + cls = fmt.Sprintf(" [%s]", r.Class) + } + floorSection += fmt.Sprintf(" %s %s%s B%d %s\n", + medal, stylePlayer.Render(r.Player), styleSystem.Render(cls), + r.Floor, styleGold.Render(fmt.Sprintf("%dg", r.Score))) + } + + // By Gold + var goldSection string + goldSection += styleCoop.Render("\n Top by Gold") + "\n" + for i, r := range byGold { + if i >= 5 { + break + } + medal := fmt.Sprintf(" %d.", i+1) + cls := "" + if r.Class != "" { + cls = fmt.Sprintf(" [%s]", r.Class) + } + goldSection += fmt.Sprintf(" %s %s%s B%d %s\n", + medal, stylePlayer.Render(r.Player), styleSystem.Render(cls), + r.Floor, styleGold.Render(fmt.Sprintf("%dg", r.Score))) + } + + footer := styleSystem.Render("\n[L] Back") + + return lipgloss.Place(width, height, lipgloss.Center, lipgloss.Center, + lipgloss.JoinVertical(lipgloss.Center, title, "", floorSection, goldSection, footer)) +}