@@ -4,10 +4,10 @@ import (
44 "log"55 "time"66 7- "github.com/FelineStateMachine/puzzletea/catalog"87 "github.com/FelineStateMachine/puzzletea/config"98 "github.com/FelineStateMachine/puzzletea/daily"109 "github.com/FelineStateMachine/puzzletea/game"10+ "github.com/FelineStateMachine/puzzletea/registry"1111 "github.com/FelineStateMachine/puzzletea/resolve"1212 sessionflow "github.com/FelineStateMachine/puzzletea/session"1313 "github.com/FelineStateMachine/puzzletea/stats"@@ -98,11 +98,11 @@ func categoryPickerSize(width, height int) categoryPickerMetrics {
9898 }9999 100100 func selectedCategoryName(item list.Item) string {101- cat, ok := item.(game.Category)101+ entry, ok := selectedCategoryEntry(item)102102 if !ok {103103 return ""104104 }105- return cat.Name105+ return entry.Definition.Name106106 }107107 108108 func activeFilterList(m model) *list.Model {@@ -131,13 +131,13 @@ func (m model) updateCategoryDetailViewport() model {
131131 m.nav.categoryDetail.SetHeight(contentHeight)132132 m.nav.categoryDetail.FillHeight = true133133 134- cat, ok := m.nav.gameSelectList.SelectedItem().(game.Category)134+ entry, ok := selectedCategoryEntry(m.nav.gameSelectList.SelectedItem())135135 if !ok {136136 m.nav.categoryDetail.SetContent("")137137 return m138138 }139139 140- m.nav.categoryDetail.SetContent(renderCategoryDetailContent(cat, contentWidth))140+ m.nav.categoryDetail.SetContent(renderCategoryDetailContent(entry, contentWidth))141141 m.nav.categoryDetail.GotoTop()142142 return m143143 }@@ -186,7 +186,7 @@ func (m model) updateStatsViewport() model {
186186 statsWidth, statsHeight := statsViewportSize(m.width, m.height, m.stats.cards)187187 m.stats.viewport.SetWidth(statsWidth)188188 m.stats.viewport.SetHeight(statsHeight)189- m.stats.viewport.SetContent(stats.RenderCardGrid(m.stats.cards, statsWidth))189+ m.stats.viewport.SetContent(ui.RenderStatsCardGrid(m.stats.cards, statsWidth))190190 return m191191 }192192 @@ -507,7 +507,7 @@ func (m model) handleOptionsMenuEnter() (tea.Model, tea.Cmd) {
507507 case "Theme":508508 return m.handleThemeEnter()509509 case "Guides":510- m.nav.helpSelectList = ui.InitList(GameCategories, "How to Play")510+ m.nav.helpSelectList = ui.InitList(gameCategoryItems, "How to Play")511511 m.nav.helpSelectList.SetSize(min(m.width, 64), min(m.height, ui.ListHeight(m.nav.helpSelectList)))512512 m.state = helpSelectView513513 }@@ -546,13 +546,13 @@ func (m model) handleSeedConfirm() (tea.Model, tea.Cmd) {
546546 var gameType string547547 modeTitle := ""548548 if selectedMode.key == "" {549- spawner, gameType, modeTitle, err = resolve.SeededMode(seed, catalog.All)549+ spawner, gameType, modeTitle, err = resolve.SeededMode(seed, registry.Entries())550550 if err != nil {551551 log.Printf("failed to select seeded mode: %v", err)552552 return m, nil553553 }554554 } else {555- spawner, gameType, modeTitle, err = resolve.SeededModeForGame(seed, selectedMode.gameType, catalog.All)555+ spawner, gameType, modeTitle, err = resolve.SeededModeForGame(seed, selectedMode.gameType, registry.Entries())556556 if err != nil {557557 log.Printf("failed to select seeded mode for %s: %v", selectedMode.gameType, err)558558 return m, nil@@ -614,12 +614,12 @@ func (m model) handleDailyPuzzle() (tea.Model, tea.Cmd) {
614614 }615615 616616 func (m model) handleGameSelectEnter() (tea.Model, tea.Cmd) {617- cat, ok := m.nav.gameSelectList.SelectedItem().(game.Category)617+ entry, ok := selectedCategoryEntry(m.nav.gameSelectList.SelectedItem())618618 if !ok {619619 return m, nil620620 }621- m.nav.selectedCategory = cat622- m.nav.modeSelectList = ui.InitList(buildModeDisplayItems(cat), cat.Name+" - Select Mode")621+ m.nav.selectedCategory = entry622+ m.nav.modeSelectList = ui.InitList(buildModeDisplayItems(entry), entry.Definition.Name+" - Select Mode")623623 m.nav.modeSelectList.SetSize(min(m.width, 64), min(m.height, ui.ListHeight(m.nav.modeSelectList)))624624 m.state = modeSelectView625625 return m, nil@@ -627,26 +627,22 @@ func (m model) handleGameSelectEnter() (tea.Model, tea.Cmd) {
627627 628628 func (m model) handleModeSelectEnter() (tea.Model, tea.Cmd) {629629 item := unwrapModeDisplayItem(m.nav.modeSelectList.SelectedItem())630- mode, ok := item.(game.Mode)630+ mode, ok := item.(registry.ModeEntry)631631 if !ok {632632 return m, nil633633 }634- spawner, ok := item.(game.Spawner)635- if !ok {636- return m, nil637- }638- m.nav.selectedModeTitle = mode.Title()634+ m.nav.selectedModeTitle = mode.Definition.Title639635 ctx, jobID := m.beginSpawnContext()640636 m.session.spawn = &spawnRequest{641637 source: spawnSourceNormal,642638 name: sessionflow.GenerateUniqueName(m.store),643- gameType: m.nav.selectedCategory.Name,639+ gameType: m.nav.selectedCategory.Definition.Name,644640 modeTitle: m.nav.selectedModeTitle,645641 returnState: modeSelectView,646642 exitState: mainMenuView,647643 }648644 m.state = generatingView649- return m, tea.Batch(m.spinner.Tick, spawnCmd(spawner, ctx, jobID))645+ return m, tea.Batch(m.spinner.Tick, spawnCmd(mode.Spawner, ctx, jobID))650646 }651647 652648 func (m model) handleContinueEnter() (tea.Model, tea.Cmd) {@@ -660,11 +656,11 @@ func (m model) handleContinueEnter() (tea.Model, tea.Cmd) {
660656 }661657 662658 func (m model) handleHelpSelectEnter() (tea.Model, tea.Cmd) {663- cat, ok := m.nav.helpSelectList.SelectedItem().(game.Category)659+ entry, ok := selectedCategoryEntry(m.nav.helpSelectList.SelectedItem())664660 if !ok {665661 return m, nil666662 }667- m.help.category = cat663+ m.help.category = entry668664 m = m.updateHelpDetailViewport()669665 m.state = helpDetailView670666 return m, nil@@ -785,10 +781,12 @@ func (m model) handleStatsEnter() (tea.Model, tea.Cmd) {
785781 currentDaily = rec != nil786782 }787783 788- m.stats.cards = stats.BuildCards(catStats, modeStats)784+ weights := stats.WeightsFromDefinitions(registry.Definitions())785+ m.stats.cards = stats.BuildCards(weights, catStats, modeStats)789786 m.stats.profile = stats.BuildProfileBanner(790787 catStats,791788 modeStats,789+ weights,792790 streakDates,793791 currentDaily,794792 weekliesCompleted,@@ -800,7 +798,7 @@ func (m model) handleStatsEnter() (tea.Model, tea.Cmd) {
800798 viewport.WithWidth(statsWidth),801799 viewport.WithHeight(statsHeight),802800 )803- m.stats.viewport.SetContent(stats.RenderCardGrid(m.stats.cards, statsWidth))801+ m.stats.viewport.SetContent(ui.RenderStatsCardGrid(m.stats.cards, statsWidth))804802 m.state = statsView805803 return m, nil806804 }