┌─ GO ───────────────────────────────────────────────────────────────────────┐
│ package cmd │
│ │
│ import ( │
│ "errors" │
│ "fmt" │
│ "os" │
│ "path/filepath" │
│ "strings" │
│ │
│ "github.com/spf13/cobra" │
│ "ookstats/internal/database" │
│ "ookstats/internal/generator" │
│ "ookstats/internal/generator/indexes" │
│ ) │
│ │
│ var generateCmd = &cobra.Command{ │
│ Use: "generate", │
│ Short: "Generate static artifacts", │
│ Long: `Generate static API endpoints and other build artifacts from the local da │
│ tabase.`, │
│ } │
│ │
│ var generateAPICmd = &cobra.Command{ │
│ Use: "api", │
│ Short: "Generate static JSON API endpoints", │
│ RunE: func(cmd *cobra.Command, args []string) error { │
│ outDir, _ := cmd.Flags().GetString("out") │
│ onlyPlayers, _ := cmd.Flags().GetBool("players") │
│ doLeaderboards, _ := cmd.Flags().GetBool("leaderboards") │
│ doSearch, _ := cmd.Flags().GetBool("search") │
│ doIndexes, _ := cmd.Flags().GetBool("indexes") │
│ pageSize, _ := cmd.Flags().GetInt("page-size") │
│ shardSize, _ := cmd.Flags().GetInt("shard-size") │
│ regionsCSV, _ := cmd.Flags().GetString("regions") │
│ workers, _ := cmd.Flags().GetInt("workers") │
│ │
│ if strings.TrimSpace(outDir) == "" { │
│ return errors.New("--out is required") │
│ } │
│ // Connect to local DB (file:) │
│ db, err := database.Connect() │
│ if err != nil { │
│ return fmt.Errorf("failed to connect to db: %w", err) │
│ } │
│ defer db.Close() │
│ │
│ base := filepath.Join(outDir, "api") │
│ if err := os.MkdirAll(base, 0o755); err != nil { │
│ return fmt.Errorf("mkdir base: %w", err) │
│ } │
│ │
│ if onlyPlayers { │
│ if err := generator.GeneratePlayers(db, filepath.Join(base, "player"), ""); err │
│ != nil { │
│ return err │
│ } │
│ } │
│ │
│ if doLeaderboards { │
│ regions := parseRegions(regionsCSV) │
│ if err := generator.GenerateLeaderboards(db, filepath.Join(base, "leaderboard") │
│ , pageSize, regions, workers); err != nil { │
│ return err │
│ } │
│ if err := generator.GeneratePlayerLeaderboards(db, filepath.Join(base, "leaderb │
│ oard"), pageSize, regions, workers); err != nil { │
│ return err │
│ } │
│ if err := generator.GenerateTotalRunsLeaderboard(db, filepath.Join(base, "leade │
│ rboard"), pageSize, regions, workers); err != nil { │
│ return err │
│ } │
│ if err := generator.GenerateAccountTotalRunsLeaderboard(db, filepath.Join(base, │
│ "leaderboard"), pageSize, regions, workers); err != nil { │
│ return err │
│ } │
│ if err := generator.GenerateAccountLeaderboards(db, filepath.Join(base, "leader │
│ board"), pageSize, regions, workers); err != nil { │
│ return err │
│ } │
│ if err := generator.GenerateAllTimePlayerLeaderboard(db, filepath.Join(base, "l │
│ eaderboard"), pageSize, regions, workers); err != nil { │
│ return err │
│ } │
│ if err := generator.GenerateAllTimeAccountLeaderboard(db, filepath.Join(base, " │
│ leaderboard"), pageSize, regions, workers); err != nil { │
│ return err │
│ } │
│ if err := generator.GeneratePlayerSeasonRunsLeaderboard(db, filepath.Join(base, │
│ "leaderboard"), pageSize, regions, workers); err != nil { │
│ return err │
│ } │
│ if err := generator.GenerateAccountSeasonRunsLeaderboard(db, filepath.Join(base │
│ , "leaderboard"), pageSize, regions, workers); err != nil { │
│ return err │
│ } │
│ } │
│ │
│ if doSearch { │
│ if err := generator.GenerateSearchIndex(db, filepath.Join(base, "search"), shar │
│ dSize); err != nil { │
│ return err │
│ } │
│ } │
│ │
│ if doIndexes { │
│ if err := indexes.GenerateAllIndexes(db, outDir); err != nil { │
│ return err │
│ } │
│ } │
│ │
│ fmt.Printf("\nStatic API generated at %s\n", base) │
│ return nil │
│ }, │
│ } │
│ │
│ var generateHomeCmd = &cobra.Command{ │
│ Use: "home", │
│ Short: "Generate home page JSON (top runs + top players + recent feed)", │
│ RunE: func(cmd *cobra.Command, args []string) error { │
│ outDir, _ := cmd.Flags().GetString("out") │
│ if strings.TrimSpace(outDir) == "" { │
│ return errors.New("--out is required") │
│ } │
│ db, err := database.Connect() │
│ if err != nil { │
│ return fmt.Errorf("failed to connect to db: %w", err) │
│ } │
│ defer db.Close() │
│ │
│ if err := os.MkdirAll(filepath.Join(outDir, "api"), 0o755); err != nil { │
│ return fmt.Errorf("mkdir base: %w", err) │
│ } │
│ │
│ if err := generator.GenerateHome(db, outDir); err != nil { │
│ return err │
│ } │
│ fmt.Printf("\nHome JSON generated at %s/api/home.json\n", outDir) │
│ return nil │
│ }, │
│ } │
│ │
│ var generateStatsCmd = &cobra.Command{ │
│ Use: "stats", │
│ Short: "Generate stats page JSON (totals, completion tiers, spec counts, top runn │
│ ers, weekly activity)", │
│ RunE: func(cmd *cobra.Command, args []string) error { │
│ outDir, _ := cmd.Flags().GetString("out") │
│ if strings.TrimSpace(outDir) == "" { │
│ return errors.New("--out is required") │
│ } │
│ db, err := database.Connect() │
│ if err != nil { │
│ return fmt.Errorf("failed to connect to db: %w", err) │
│ } │
│ defer db.Close() │
│ │
│ if err := os.MkdirAll(filepath.Join(outDir, "api"), 0o755); err != nil { │
│ return fmt.Errorf("mkdir base: %w", err) │
│ } │
│ │
│ if err := generator.GenerateStats(db, outDir); err != nil { │
│ return err │
│ } │
│ fmt.Printf("\nStats JSON generated at %s/api/stats.json\n", outDir) │
│ return nil │
│ }, │
│ } │
│ │
│ var generatePlayerLeaderboardsCmd = &cobra.Command{ │
│ Use: "player-leaderboards", │
│ Short: "Generate the per-season player leaderboard JSON (Overall Time, all scopes │
│ )", │
│ RunE: func(cmd *cobra.Command, args []string) error { │
│ outDir, _ := cmd.Flags().GetString("out") │
│ pageSize, _ := cmd.Flags().GetInt("page-size") │
│ regionsCSV, _ := cmd.Flags().GetString("regions") │
│ workers, _ := cmd.Flags().GetInt("workers") │
│ │
│ if strings.TrimSpace(outDir) == "" { │
│ return errors.New("--out is required") │
│ } │
│ db, err := database.Connect() │
│ if err != nil { │
│ return fmt.Errorf("failed to connect to db: %w", err) │
│ } │
│ defer db.Close() │
│ │
│ base := filepath.Join(outDir, "api", "leaderboard") │
│ if err := os.MkdirAll(base, 0o755); err != nil { │
│ return fmt.Errorf("mkdir base: %w", err) │
│ } │
│ │
│ regions := parseRegions(regionsCSV) │
│ if err := generator.GeneratePlayerLeaderboards(db, base, pageSize, regions, work │
│ ers); err != nil { │
│ return err │
│ } │
│ if err := generator.GenerateAllTimePlayerLeaderboard(db, base, pageSize, regions │
│ , workers); err != nil { │
│ return err │
│ } │
│ fmt.Printf("\nPlayer leaderboards generated at %s/season/<id>/players/... and %s │
│ /all-time/characters/by-time/...\n", base, base) │
│ return nil │
│ }, │
│ } │
│ │
│ var generateTotalRunsLeaderboardCmd = &cobra.Command{ │
│ Use: "total-runs-leaderboard", │
│ Short: "Generate the cross-season Total Runs leaderboard JSON (all scopes)", │
│ RunE: func(cmd *cobra.Command, args []string) error { │
│ outDir, _ := cmd.Flags().GetString("out") │
│ pageSize, _ := cmd.Flags().GetInt("page-size") │
│ regionsCSV, _ := cmd.Flags().GetString("regions") │
│ workers, _ := cmd.Flags().GetInt("workers") │
│ │
│ if strings.TrimSpace(outDir) == "" { │
│ return errors.New("--out is required") │
│ } │
│ db, err := database.Connect() │
│ if err != nil { │
│ return fmt.Errorf("failed to connect to db: %w", err) │
│ } │
│ defer db.Close() │
│ │
│ base := filepath.Join(outDir, "api", "leaderboard") │
│ if err := os.MkdirAll(base, 0o755); err != nil { │
│ return fmt.Errorf("mkdir base: %w", err) │
│ } │
│ │
│ regions := parseRegions(regionsCSV) │
│ if err := generator.GenerateTotalRunsLeaderboard(db, base, pageSize, regions, wo │
│ rkers); err != nil { │
│ return err │
│ } │
│ if err := generator.GenerateAccountTotalRunsLeaderboard(db, base, pageSize, regi │
│ ons, workers); err != nil { │
│ return err │
│ } │
│ if err := generator.GeneratePlayerSeasonRunsLeaderboard(db, base, pageSize, regi │
│ ons, workers); err != nil { │
│ return err │
│ } │
│ if err := generator.GenerateAccountSeasonRunsLeaderboard(db, base, pageSize, reg │
│ ions, workers); err != nil { │
│ return err │
│ } │
│ fmt.Printf("\nTotal Runs leaderboards generated at %s/players/total-runs/... and │
│ %s/season{N}/{characters,players}/by-runs/...\n", base, base) │
│ return nil │
│ }, │
│ } │
│ │
│ var generateAccountLeaderboardsCmd = &cobra.Command{ │
│ Use: "account-leaderboards", │
│ Short: "Generate the per-season account-grouped leaderboard JSON", │
│ RunE: func(cmd *cobra.Command, args []string) error { │
│ outDir, _ := cmd.Flags().GetString("out") │
│ pageSize, _ := cmd.Flags().GetInt("page-size") │
│ regionsCSV, _ := cmd.Flags().GetString("regions") │
│ workers, _ := cmd.Flags().GetInt("workers") │
│ │
│ if strings.TrimSpace(outDir) == "" { │
│ return errors.New("--out is required") │
│ } │
│ db, err := database.Connect() │
│ if err != nil { │
│ return fmt.Errorf("failed to connect to db: %w", err) │
│ } │
│ defer db.Close() │
│ │
│ base := filepath.Join(outDir, "api", "leaderboard") │
│ if err := os.MkdirAll(base, 0o755); err != nil { │
│ return fmt.Errorf("mkdir base: %w", err) │
│ } │
│ │
│ regions := parseRegions(regionsCSV) │
│ if err := generator.GenerateAccountLeaderboards(db, base, pageSize, regions, wor │
│ kers); err != nil { │
│ return err │
│ } │
│ if err := generator.GenerateAllTimeAccountLeaderboard(db, base, pageSize, region │
│ s, workers); err != nil { │
│ return err │
│ } │
│ fmt.Printf("\nAccount leaderboards generated at %s/season/<id>/accounts/... and │
│ %s/all-time/players/by-time/...\n", base, base) │
│ return nil │
│ }, │
│ } │
│ │
│ func parseRegions(csv string) []string { │
│ out := []string{} │
│ if strings.TrimSpace(csv) == "" { │
│ return out │
│ } │
│ for _, r := range strings.Split(csv, ",") { │
│ rr := strings.TrimSpace(r) │
│ if rr != "" { │
│ out = append(out, rr) │
│ } │
│ } │
│ return out │
│ } │
│ │
│ var generateGearCmd = &cobra.Command{ │
│ Use: "gear", │
│ Short: "Generate gear popularity JSON (per-spec top items per slot, validated by │
│ spec primary stat)", │
│ RunE: func(cmd *cobra.Command, args []string) error { │
│ outDir, _ := cmd.Flags().GetString("out") │
│ if strings.TrimSpace(outDir) == "" { │
│ return errors.New("--out is required") │
│ } │
│ db, err := database.Connect() │
│ if err != nil { │
│ return fmt.Errorf("failed to connect to db: %w", err) │
│ } │
│ defer db.Close() │
│ │
│ if err := os.MkdirAll(filepath.Join(outDir, "api"), 0o755); err != nil { │
│ return fmt.Errorf("mkdir base: %w", err) │
│ } │
│ │
│ if err := generator.GenerateGear(db, outDir); err != nil { │
│ return err │
│ } │
│ fmt.Printf("\nGear JSON generated at %s/api/gear.json\n", outDir) │
│ return nil │
│ }, │
│ } │
│ │
│ func init() { │
│ rootCmd.AddCommand(generateCmd) │
│ generateCmd.AddCommand(generateAPICmd) │
│ generateAPICmd.Flags().String("out", "public", "Output directory for static API") │
│ generateAPICmd.Flags().Bool("players", true, "Generate player profile JSON endpoi │
│ nts") │
│ generateAPICmd.Flags().Bool("leaderboards", true, "Generate leaderboard JSON endp │
│ oints") │
│ generateAPICmd.Flags().Bool("search", true, "Generate search index JSON shards") │
│ generateAPICmd.Flags().Bool("indexes", true, "Generate API discovery indexes") │
│ generateAPICmd.Flags().Int("page-size", 25, "Leaderboard page size") │
│ generateAPICmd.Flags().Int("shard-size", 5000, "Search index shard size") │
│ generateAPICmd.Flags().String("regions", "us,eu,kr,tw", "Regions to include for r │
│ egional leaderboards") │
│ generateAPICmd.Flags().Int("workers", 10, "Number of parallel workers for leaderb │
│ oard generation") │
│ │
│ generateCmd.AddCommand(generateHomeCmd) │
│ generateHomeCmd.Flags().String("out", "web/public", "Output directory (api/home.j │
│ son will be written under it)") │
│ │
│ generateCmd.AddCommand(generateStatsCmd) │
│ generateStatsCmd.Flags().String("out", "web/public", "Output directory (api/stats │
│ .json will be written under it)") │
│ │
│ generateCmd.AddCommand(generateGearCmd) │
│ generateGearCmd.Flags().String("out", "web/public", "Output directory (api/gear.j │
│ son will be written under it)") │
│ │
│ generateCmd.AddCommand(generatePlayerLeaderboardsCmd) │
│ generatePlayerLeaderboardsCmd.Flags().String("out", "web/public", "Output directo │
│ ry (api/leaderboard/... will be written under it)") │
│ generatePlayerLeaderboardsCmd.Flags().Int("page-size", 25, "Leaderboard page size │
│ ") │
│ generatePlayerLeaderboardsCmd.Flags().String("regions", "us,eu,kr,tw", "Regions t │
│ o include for regional/realm/class leaderboards") │
│ generatePlayerLeaderboardsCmd.Flags().Int("workers", 10, "Number of parallel work │
│ ers for leaderboard generation") │
│ │
│ generateCmd.AddCommand(generateTotalRunsLeaderboardCmd) │
│ generateTotalRunsLeaderboardCmd.Flags().String("out", "web/public", "Output direc │
│ tory (api/leaderboard/players/total-runs/... will be written under it)") │
│ generateTotalRunsLeaderboardCmd.Flags().Int("page-size", 25, "Leaderboard page si │
│ ze") │
│ generateTotalRunsLeaderboardCmd.Flags().String("regions", "us,eu,kr,tw", "Regions │
│ to include for regional/realm/class leaderboards") │
│ generateTotalRunsLeaderboardCmd.Flags().Int("workers", 10, "Number of parallel wo │
│ rkers for leaderboard generation") │
│ │
│ generateCmd.AddCommand(generateAccountLeaderboardsCmd) │
│ generateAccountLeaderboardsCmd.Flags().String("out", "web/public", "Output direct │
│ ory (api/leaderboard/season/<id>/accounts/... will be written under it)") │
│ generateAccountLeaderboardsCmd.Flags().Int("page-size", 25, "Leaderboard page siz │
│ e") │
│ generateAccountLeaderboardsCmd.Flags().String("regions", "us,eu,kr,tw", "Regions │
│ to include for regional account leaderboards") │
│ generateAccountLeaderboardsCmd.Flags().Int("workers", 4, "Number of parallel work │
│ ers for account leaderboard generation") │
│ } │
└────────────────────────────────────────────────────────────────────────────────────┘
┌─ GO ─────────────────────────────────┐
│ package cmd │
│ │
│ import ( │
│ "errors" │
│ "fmt" │
│ "os" │
│ "path/filepath" │
│ "strings" │
│ │
│ "github.com/spf13/cobra" │
│ "ookstats/internal/database" │
│ "ookstats/internal/generator" │
│ "ookstats/internal/generator/indexes" │
│ ) │
│ │
│ var generateCmd = &cobra.Command{ │
│ Use: "generate", │
│ Short: "Generate static artifacts", │
│ Long: `Generate static API endpoints and o │
│ ther build artifacts from the local database │
│ .`, │
│ } │
│ │
│ var generateAPICmd = &cobra.Command{ │
│ Use: "api", │
│ Short: "Generate static JSON API endpoints" │
│ , │
│ RunE: func(cmd *cobra.Command, args []strin │
│ g) error { │
│ outDir, _ := cmd.Flags().GetString("out") │
│ onlyPlayers, _ := cmd.Flags().GetBool("pla │
│ yers") │
│ doLeaderboards, _ := cmd.Flags().GetBool(" │
│ leaderboards") │
│ doSearch, _ := cmd.Flags().GetBool("search │
│ ") │
│ doIndexes, _ := cmd.Flags().GetBool("index │
│ es") │
│ pageSize, _ := cmd.Flags().GetInt("page-si │
│ ze") │
│ shardSize, _ := cmd.Flags().GetInt("shard- │
│ size") │
│ regionsCSV, _ := cmd.Flags().GetString("re │
│ gions") │
│ workers, _ := cmd.Flags().GetInt("workers" │
│ ) │
│ │
│ if strings.TrimSpace(outDir) == "" { │
│ return errors.New("--out is required") │
│ } │
│ // Connect to local DB (file:) │
│ db, err := database.Connect() │
│ if err != nil { │
│ return fmt.Errorf("failed to connect to d │
│ b: %w", err) │
│ } │
│ defer db.Close() │
│ │
│ base := filepath.Join(outDir, "api") │
│ if err := os.MkdirAll(base, 0o755); err != │
│ nil { │
│ return fmt.Errorf("mkdir base: %w", err) │
│ } │
│ │
│ if onlyPlayers { │
│ if err := generator.GeneratePlayers(db, f │
│ ilepath.Join(base, "player"), ""); err != ni │
│ l { │
│ return err │
│ } │
│ } │
│ │
│ if doLeaderboards { │
│ regions := parseRegions(regionsCSV) │
│ if err := generator.GenerateLeaderboards( │
│ db, filepath.Join(base, "leaderboard"), page │
│ Size, regions, workers); err != nil { │
│ return err │
│ } │
│ if err := generator.GeneratePlayerLeaderb │
│ oards(db, filepath.Join(base, "leaderboard") │
│ , pageSize, regions, workers); err != nil { │
│ return err │
│ } │
│ if err := generator.GenerateTotalRunsLead │
│ erboard(db, filepath.Join(base, "leaderboard │
│ "), pageSize, regions, workers); err != nil │
│ { │
│ return err │
│ } │
│ if err := generator.GenerateAccountTotalR │
│ unsLeaderboard(db, filepath.Join(base, "lead │
│ erboard"), pageSize, regions, workers); err │
│ != nil { │
│ return err │
│ } │
│ if err := generator.GenerateAccountLeader │
│ boards(db, filepath.Join(base, "leaderboard" │
│ ), pageSize, regions, workers); err != nil { │
│ return err │
│ } │
│ if err := generator.GenerateAllTimePlayer │
│ Leaderboard(db, filepath.Join(base, "leaderb │
│ oard"), pageSize, regions, workers); err != │
│ nil { │
│ return err │
│ } │
│ if err := generator.GenerateAllTimeAccoun │
│ tLeaderboard(db, filepath.Join(base, "leader │
│ board"), pageSize, regions, workers); err != │
│ nil { │
│ return err │
│ } │
│ if err := generator.GeneratePlayerSeasonR │
│ unsLeaderboard(db, filepath.Join(base, "lead │
│ erboard"), pageSize, regions, workers); err │
│ != nil { │
│ return err │
│ } │
│ if err := generator.GenerateAccountSeason │
│ RunsLeaderboard(db, filepath.Join(base, "lea │
│ derboard"), pageSize, regions, workers); err │
│ != nil { │
│ return err │
│ } │
│ } │
│ │
│ if doSearch { │
│ if err := generator.GenerateSearchIndex(d │
│ b, filepath.Join(base, "search"), shardSize) │
│ ; err != nil { │
│ return err │
│ } │
│ } │
│ │
│ if doIndexes { │
│ if err := indexes.GenerateAllIndexes(db, │
│ outDir); err != nil { │
│ return err │
│ } │
│ } │
│ │
│ fmt.Printf("\nStatic API generated at %s\n │
│ ", base) │
│ return nil │
│ }, │
│ } │
│ │
│ var generateHomeCmd = &cobra.Command{ │
│ Use: "home", │
│ Short: "Generate home page JSON (top runs + │
│ top players + recent feed)", │
│ RunE: func(cmd *cobra.Command, args []strin │
│ g) error { │
│ outDir, _ := cmd.Flags().GetString("out") │
│ if strings.TrimSpace(outDir) == "" { │
│ return errors.New("--out is required") │
│ } │
│ db, err := database.Connect() │
│ if err != nil { │
│ return fmt.Errorf("failed to connect to d │
│ b: %w", err) │
│ } │
│ defer db.Close() │
│ │
│ if err := os.MkdirAll(filepath.Join(outDir │
│ , "api"), 0o755); err != nil { │
│ return fmt.Errorf("mkdir base: %w", err) │
│ } │
│ │
│ if err := generator.GenerateHome(db, outDi │
│ r); err != nil { │
│ return err │
│ } │
│ fmt.Printf("\nHome JSON generated at %s/ap │
│ i/home.json\n", outDir) │
│ return nil │
│ }, │
│ } │
│ │
│ var generateStatsCmd = &cobra.Command{ │
│ Use: "stats", │
│ Short: "Generate stats page JSON (totals, c │
│ ompletion tiers, spec counts, top runners, w │
│ eekly activity)", │
│ RunE: func(cmd *cobra.Command, args []strin │
│ g) error { │
│ outDir, _ := cmd.Flags().GetString("out") │
│ if strings.TrimSpace(outDir) == "" { │
│ return errors.New("--out is required") │
│ } │
│ db, err := database.Connect() │
│ if err != nil { │
│ return fmt.Errorf("failed to connect to d │
│ b: %w", err) │
│ } │
│ defer db.Close() │
│ │
│ if err := os.MkdirAll(filepath.Join(outDir │
│ , "api"), 0o755); err != nil { │
│ return fmt.Errorf("mkdir base: %w", err) │
│ } │
│ │
│ if err := generator.GenerateStats(db, outD │
│ ir); err != nil { │
│ return err │
│ } │
│ fmt.Printf("\nStats JSON generated at %s/a │
│ pi/stats.json\n", outDir) │
│ return nil │
│ }, │
│ } │
│ │
│ var generatePlayerLeaderboardsCmd = &cobra.C │
│ ommand{ │
│ Use: "player-leaderboards", │
│ Short: "Generate the per-season player lead │
│ erboard JSON (Overall Time, all scopes)", │
│ RunE: func(cmd *cobra.Command, args []strin │
│ g) error { │
│ outDir, _ := cmd.Flags().GetString("out") │
│ pageSize, _ := cmd.Flags().GetInt("page-si │
│ ze") │
│ regionsCSV, _ := cmd.Flags().GetString("re │
│ gions") │
│ workers, _ := cmd.Flags().GetInt("workers" │
│ ) │
│ │
│ if strings.TrimSpace(outDir) == "" { │
│ return errors.New("--out is required") │
│ } │
│ db, err := database.Connect() │
│ if err != nil { │
│ return fmt.Errorf("failed to connect to d │
│ b: %w", err) │
│ } │
│ defer db.Close() │
│ │
│ base := filepath.Join(outDir, "api", "lead │
│ erboard") │
│ if err := os.MkdirAll(base, 0o755); err != │
│ nil { │
│ return fmt.Errorf("mkdir base: %w", err) │
│ } │
│ │
│ regions := parseRegions(regionsCSV) │
│ if err := generator.GeneratePlayerLeaderbo │
│ ards(db, base, pageSize, regions, workers); │
│ err != nil { │
│ return err │
│ } │
│ if err := generator.GenerateAllTimePlayerL │
│ eaderboard(db, base, pageSize, regions, work │
│ ers); err != nil { │
│ return err │
│ } │
│ fmt.Printf("\nPlayer leaderboards generate │
│ d at %s/season/<id>/players/... and %s/all-t │
│ ime/characters/by-time/...\n", base, base) │
│ return nil │
│ }, │
│ } │
│ │
│ var generateTotalRunsLeaderboardCmd = &cobra │
│ .Command{ │
│ Use: "total-runs-leaderboard", │
│ Short: "Generate the cross-season Total Run │
│ s leaderboard JSON (all scopes)", │
│ RunE: func(cmd *cobra.Command, args []strin │
│ g) error { │
│ outDir, _ := cmd.Flags().GetString("out") │
│ pageSize, _ := cmd.Flags().GetInt("page-si │
│ ze") │
│ regionsCSV, _ := cmd.Flags().GetString("re │
│ gions") │
│ workers, _ := cmd.Flags().GetInt("workers" │
│ ) │
│ │
│ if strings.TrimSpace(outDir) == "" { │
│ return errors.New("--out is required") │
│ } │
│ db, err := database.Connect() │
│ if err != nil { │
│ return fmt.Errorf("failed to connect to d │
│ b: %w", err) │
│ } │
│ defer db.Close() │
│ │
│ base := filepath.Join(outDir, "api", "lead │
│ erboard") │
│ if err := os.MkdirAll(base, 0o755); err != │
│ nil { │
│ return fmt.Errorf("mkdir base: %w", err) │
│ } │
│ │
│ regions := parseRegions(regionsCSV) │
│ if err := generator.GenerateTotalRunsLeade │
│ rboard(db, base, pageSize, regions, workers) │
│ ; err != nil { │
│ return err │
│ } │
│ if err := generator.GenerateAccountTotalRu │
│ nsLeaderboard(db, base, pageSize, regions, w │
│ orkers); err != nil { │
│ return err │
│ } │
│ if err := generator.GeneratePlayerSeasonRu │
│ nsLeaderboard(db, base, pageSize, regions, w │
│ orkers); err != nil { │
│ return err │
│ } │
│ if err := generator.GenerateAccountSeasonR │
│ unsLeaderboard(db, base, pageSize, regions, │
│ workers); err != nil { │
│ return err │
│ } │
│ fmt.Printf("\nTotal Runs leaderboards gene │
│ rated at %s/players/total-runs/... and %s/se │
│ ason{N}/{characters,players}/by-runs/...\n", │
│ base, base) │
│ return nil │
│ }, │
│ } │
│ │
│ var generateAccountLeaderboardsCmd = &cobra. │
│ Command{ │
│ Use: "account-leaderboards", │
│ Short: "Generate the per-season account-gro │
│ uped leaderboard JSON", │
│ RunE: func(cmd *cobra.Command, args []strin │
│ g) error { │
│ outDir, _ := cmd.Flags().GetString("out") │
│ pageSize, _ := cmd.Flags().GetInt("page-si │
│ ze") │
│ regionsCSV, _ := cmd.Flags().GetString("re │
│ gions") │
│ workers, _ := cmd.Flags().GetInt("workers" │
│ ) │
│ │
│ if strings.TrimSpace(outDir) == "" { │
│ return errors.New("--out is required") │
│ } │
│ db, err := database.Connect() │
│ if err != nil { │
│ return fmt.Errorf("failed to connect to d │
│ b: %w", err) │
│ } │
│ defer db.Close() │
│ │
│ base := filepath.Join(outDir, "api", "lead │
│ erboard") │
│ if err := os.MkdirAll(base, 0o755); err != │
│ nil { │
│ return fmt.Errorf("mkdir base: %w", err) │
│ } │
│ │
│ regions := parseRegions(regionsCSV) │
│ if err := generator.GenerateAccountLeaderb │
│ oards(db, base, pageSize, regions, workers); │
│ err != nil { │
│ return err │
│ } │
│ if err := generator.GenerateAllTimeAccount │
│ Leaderboard(db, base, pageSize, regions, wor │
│ kers); err != nil { │
│ return err │
│ } │
│ fmt.Printf("\nAccount leaderboards generat │
│ ed at %s/season/<id>/accounts/... and %s/all │
│ -time/players/by-time/...\n", base, base) │
│ return nil │
│ }, │
│ } │
│ │
│ func parseRegions(csv string) []string { │
│ out := []string{} │
│ if strings.TrimSpace(csv) == "" { │
│ return out │
│ } │
│ for _, r := range strings.Split(csv, ",") { │
│ rr := strings.TrimSpace(r) │
│ if rr != "" { │
│ out = append(out, rr) │
│ } │
│ } │
│ return out │
│ } │
│ │
│ var generateGearCmd = &cobra.Command{ │
│ Use: "gear", │
│ Short: "Generate gear popularity JSON (per- │
│ spec top items per slot, validated by spec p │
│ rimary stat)", │
│ RunE: func(cmd *cobra.Command, args []strin │
│ g) error { │
│ outDir, _ := cmd.Flags().GetString("out") │
│ if strings.TrimSpace(outDir) == "" { │
│ return errors.New("--out is required") │
│ } │
│ db, err := database.Connect() │
│ if err != nil { │
│ return fmt.Errorf("failed to connect to d │
│ b: %w", err) │
│ } │
│ defer db.Close() │
│ │
│ if err := os.MkdirAll(filepath.Join(outDir │
│ , "api"), 0o755); err != nil { │
│ return fmt.Errorf("mkdir base: %w", err) │
│ } │
│ │
│ if err := generator.GenerateGear(db, outDi │
│ r); err != nil { │
│ return err │
│ } │
│ fmt.Printf("\nGear JSON generated at %s/ap │
│ i/gear.json\n", outDir) │
│ return nil │
│ }, │
│ } │
│ │
│ func init() { │
│ rootCmd.AddCommand(generateCmd) │
│ generateCmd.AddCommand(generateAPICmd) │
│ generateAPICmd.Flags().String("out", "publi │
│ c", "Output directory for static API") │
│ generateAPICmd.Flags().Bool("players", true │
│ , "Generate player profile JSON endpoints") │
│ generateAPICmd.Flags().Bool("leaderboards", │
│ true, "Generate leaderboard JSON endpoints" │
│ ) │
│ generateAPICmd.Flags().Bool("search", true, │
│ "Generate search index JSON shards") │
│ generateAPICmd.Flags().Bool("indexes", true │
│ , "Generate API discovery indexes") │
│ generateAPICmd.Flags().Int("page-size", 25, │
│ "Leaderboard page size") │
│ generateAPICmd.Flags().Int("shard-size", 50 │
│ 00, "Search index shard size") │
│ generateAPICmd.Flags().String("regions", "u │
│ s,eu,kr,tw", "Regions to include for regiona │
│ l leaderboards") │
│ generateAPICmd.Flags().Int("workers", 10, " │
│ Number of parallel workers for leaderboard g │
│ eneration") │
│ │
│ generateCmd.AddCommand(generateHomeCmd) │
│ generateHomeCmd.Flags().String("out", "web/ │
│ public", "Output directory (api/home.json wi │
│ ll be written under it)") │
│ │
│ generateCmd.AddCommand(generateStatsCmd) │
│ generateStatsCmd.Flags().String("out", "web │
│ /public", "Output directory (api/stats.json │
│ will be written under it)") │
│ │
│ generateCmd.AddCommand(generateGearCmd) │
│ generateGearCmd.Flags().String("out", "web/ │
│ public", "Output directory (api/gear.json wi │
│ ll be written under it)") │
│ │
│ generateCmd.AddCommand(generatePlayerLeader │
│ boardsCmd) │
│ generatePlayerLeaderboardsCmd.Flags().Strin │
│ g("out", "web/public", "Output directory (ap │
│ i/leaderboard/... will be written under it)" │
│ ) │
│ generatePlayerLeaderboardsCmd.Flags().Int(" │
│ page-size", 25, "Leaderboard page size") │
│ generatePlayerLeaderboardsCmd.Flags().Strin │
│ g("regions", "us,eu,kr,tw", "Regions to incl │
│ ude for regional/realm/class leaderboards") │
│ generatePlayerLeaderboardsCmd.Flags().Int(" │
│ workers", 10, "Number of parallel workers fo │
│ r leaderboard generation") │
│ │
│ generateCmd.AddCommand(generateTotalRunsLea │
│ derboardCmd) │
│ generateTotalRunsLeaderboardCmd.Flags().Str │
│ ing("out", "web/public", "Output directory ( │
│ api/leaderboard/players/total-runs/... will │
│ be written under it)") │
│ generateTotalRunsLeaderboardCmd.Flags().Int │
│ ("page-size", 25, "Leaderboard page size") │
│ generateTotalRunsLeaderboardCmd.Flags().Str │
│ ing("regions", "us,eu,kr,tw", "Regions to in │
│ clude for regional/realm/class leaderboards" │
│ ) │
│ generateTotalRunsLeaderboardCmd.Flags().Int │
│ ("workers", 10, "Number of parallel workers │
│ for leaderboard generation") │
│ │
│ generateCmd.AddCommand(generateAccountLeade │
│ rboardsCmd) │
│ generateAccountLeaderboardsCmd.Flags().Stri │
│ ng("out", "web/public", "Output directory (a │
│ pi/leaderboard/season/<id>/accounts/... will │
│ be written under it)") │
│ generateAccountLeaderboardsCmd.Flags().Int( │
│ "page-size", 25, "Leaderboard page size") │
│ generateAccountLeaderboardsCmd.Flags().Stri │
│ ng("regions", "us,eu,kr,tw", "Regions to inc │
│ lude for regional account leaderboards") │
│ generateAccountLeaderboardsCmd.Flags().Int( │
│ "workers", 4, "Number of parallel workers fo │
│ r account leaderboard generation") │
│ } │
└──────────────────────────────────────────────┘