OOKNET                             [ /  search the index  ]  
──────────────────────────────────────────────────────────────────────────────────────
══════════════════════════════════════════════════════════════════════════════════════
OOKNET   [ /  search  ]  
────────────────────────────────────────────────
════════════════════════════════════════════════
 
 
master @ 428 LINES
 
[ HISTORY ]  [ UP ]
 

package generator

import (
	"database/sql"
	"fmt"
	"ookstats/internal/loader"
	"ookstats/internal/writer"
	"os"
	"path/filepath"
	"sync"
	"sync/atomic"
)

// LeaderboardPageJSON represents a paginated leaderboard response
type LeaderboardPageJSON struct {
	LeadingGroups []LeaderboardRowJSON `json:"leading_groups"`
	Map           struct {
		Name map[string]any `json:"name"`
	} `json:"map"`
	ConnectedRealm *struct {
		Name string `json:"name"`
	} `json:"connected_realm,omitempty"`
	Pagination struct {
		CurrentPage int  `json:"currentPage"`
		PageSize    int  `json:"pageSize"`
		TotalRuns   int  `json:"totalRuns"`
		TotalPages  int  `json:"totalPages"`
		HasNextPage bool `json:"hasNextPage"`
		HasPrevPage bool `json:"hasPrevPage"`
	} `json:"pagination"`
}

// LeaderboardRowJSON represents a run in the leaderboard
type LeaderboardRowJSON struct {
	ID                 int64                   `json:"id"`
	Duration           int64                   `json:"duration"`
	CompletedTimestamp int64                   `json:"completed_timestamp"`
	KeystoneLevel      int                     `json:"keystone_level"`
	DungeonName        string                  `json:"dungeon_name"`
	RealmName          string                  `json:"realm_name"`
	Region             string                  `json:"region"`
	RankingPercentile  string                  `json:"ranking_percentile,omitempty"`
	Members            []LeaderboardMemberJSON `json:"members"`
}

// LeaderboardMemberJSON represents a team member in a leaderboard row
type LeaderboardMemberJSON struct {
	Name      string `json:"name"`
	SpecID    *int   `json:"spec_id,omitempty"`
	Region    string `json:"region"`
	RealmSlug string `json:"realm_slug"`
}

// dungeonInfo holds dungeon metadata
type dungeonInfo struct {
	ID         int
	Slug, Name string
}

// leaderboardJob represents a single leaderboard generation task
type leaderboardJob struct {
	seasonID   int
	seasonName string
	dungeon    dungeonInfo
	region     string // empty for global
	realmSlug  string // empty for global/regional
	out        string
	pageSize   int
}

// GenerateLeaderboards generates leaderboard JSON files for all scopes (global, r
egional, realm) per season
// Uses a worker pool for parallel generation
func GenerateLeaderboards(db *sql.DB, out string, pageSize int, regions []string, 
workers int) error {
	if pageSize <= 0 {
		pageSize = 25
	}
	if workers <= 0 {
		workers = 10
	}
	if err := os.MkdirAll(out, 0o755); err != nil {
		return err
	}

	// Load dungeons
	dungeons, err := loadDungeons(db)
	if err != nil {
		return err
	}

	// Load seasons
	seasons, err := loadSeasons(db)
	if err != nil {
		return err
	}

	if len(seasons) == 0 {
		fmt.Println("Warning: No seasons found - skipping leaderboard generation")
		return nil
	}

	// Regions
	if len(regions) == 0 {
		regions = []string{"us", "eu", "kr", "tw"}
	}

	// Pre-load all realm slugs per region
	realmSlugs := make(map[string][]string)
	for _, reg := range regions {
		slugs, err := loadRealmSlugs(db, reg)
		if err != nil {
			return err
		}
		realmSlugs[reg] = slugs
	}

	// Count total jobs for progress reporting
	var totalJobs int
	for range seasons {
		totalJobs += len(dungeons) // global
		for _, reg := range regions {
			totalJobs += len(dungeons)                        // regional
			totalJobs += len(realmSlugs[reg]) * len(dungeons) // realm
		}
	}

	fmt.Printf("Generating leaderboards with %d workers (%d total jobs)...\n", worker
s, totalJobs)

	// Create job channel and error channel
	jobs := make(chan leaderboardJob, 100)
	var firstErr atomic.Value
	var completed atomic.Int64
	var wg sync.WaitGroup

	// Start workers
	for i := 0; i < workers; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for job := range jobs {
				// Skip if we already have an error
				if firstErr.Load() != nil {
					continue
				}

				var err error
				if job.realmSlug != "" {
					err = generateRealmLeaderboard(db, job.out, job.region, job.realmSlug, job.du
ngeon, job.seasonID, job.pageSize)
				} else if job.region != "" {
					err = generateRegionalLeaderboard(db, job.out, job.region, job.dungeon, job.s
easonID, job.pageSize)
				} else {
					err = generateGlobalLeaderboard(db, job.out, job.dungeon, job.seasonID, job.p
ageSize)
				}

				if err != nil {
					firstErr.CompareAndSwap(nil, err)
					continue
				}

				c := completed.Add(1)
				if c%100 == 0 {
					fmt.Printf("  ... %d/%d leaderboards generated\n", c, totalJobs)
				}
			}
		}()
	}

	// Queue all jobs
	for _, season := range seasons {
		fmt.Printf("\n=== Queuing Season %d (%s) ===\n", season.ID, season.Name)
		seasonOut := filepath.Join(out, "season", fmt.Sprintf("%d", season.ID))

		// Global leaderboards
		for _, d := range dungeons {
			jobs <- leaderboardJob{
				seasonID:   season.ID,
				seasonName: season.Name,
				dungeon:    d,
				region:     "",
				realmSlug:  "",
				out:        seasonOut,
				pageSize:   pageSize,
			}
		}

		// Regional leaderboards
		for _, reg := range regions {
			for _, d := range dungeons {
				jobs <- leaderboardJob{
					seasonID:   season.ID,
					seasonName: season.Name,
					dungeon:    d,
					region:     reg,
					realmSlug:  "",
					out:        seasonOut,
					pageSize:   pageSize,
				}
			}
		}

		// Realm leaderboards
		for _, reg := range regions {
			for _, rslug := range realmSlugs[reg] {
				for _, d := range dungeons {
					jobs <- leaderboardJob{
						seasonID:   season.ID,
						seasonName: season.Name,
						dungeon:    d,
						region:     reg,
						realmSlug:  rslug,
						out:        seasonOut,
						pageSize:   pageSize,
					}
				}
			}
		}
	}
	close(jobs)

	// Wait for all workers to complete
	wg.Wait()

	// Check for errors
	if err := firstErr.Load(); err != nil {
		return err.(error)
	}

	fmt.Printf("\n[OK] Generated %d leaderboards\n", completed.Load())
	return nil
}

// loadDungeons loads all dungeons from the database
func loadDungeons(db *sql.DB) ([]dungeonInfo, error) {
	rows, err := db.Query(`SELECT id, slug, name FROM dungeons ORDER BY name`)
	if err != nil {
		return nil, fmt.Errorf("dungeons query: %w", err)
	}
	defer rows.Close()

	var dungeons []dungeonInfo
	for rows.Next() {
		var d dungeonInfo
		if err := rows.Scan(&d.ID, &d.Slug, &d.Name); err != nil {
			return nil, err
		}
		dungeons = append(dungeons, d)
	}
	return dungeons, nil
}

// seasonInfo holds season metadata
type seasonInfo struct {
	ID   int
	Name string
}

// loadSeasons loads all distinct season numbers from the database
func loadSeasons(db *sql.DB) ([]seasonInfo, error) {
	rows, err := db.Query(`
		SELECT DISTINCT season_number, season_name
		FROM seasons
		ORDER BY season_number ASC
	`)
	if err != nil {
		return nil, fmt.Errorf("seasons query: %w", err)
	}
	defer rows.Close()

	var seasons []seasonInfo
	for rows.Next() {
		var s seasonInfo
		if err := rows.Scan(&s.ID, &s.Name); err != nil {
			return nil, err
		}
		seasons = append(seasons, s)
	}
	return seasons, nil
}

// loadRealmSlugs loads realm slugs for a given region
func loadRealmSlugs(db *sql.DB, region string) ([]string, error) {
	rows, err := db.Query(`SELECT slug FROM realms WHERE region = ? ORDER BY slug`, r
egion)
	if err != nil {
		return nil, fmt.Errorf("realms list: %w", err)
	}
	defer rows.Close()

	var slugs []string
	for rows.Next() {
		var s string
		if err := rows.Scan(&s); err != nil {
			return nil, err
		}
		slugs = append(slugs, s)
	}
	return slugs, nil
}

// children collapse upward via parent_realm_slug
func loadParentRealmSlugs(db *sql.DB, region string) ([]string, error) {
	rows, err := db.Query(`
		SELECT slug
		FROM realms
		WHERE region = ? AND (parent_realm_slug IS NULL OR parent_realm_slug = '')
		ORDER BY slug
	`, region)
	if err != nil {
		return nil, fmt.Errorf("parent realms list: %w", err)
	}
	defer rows.Close()

	var slugs []string
	for rows.Next() {
		var s string
		if err := rows.Scan(&s); err != nil {
			return nil, err
		}
		slugs = append(slugs, s)
	}
	return slugs, nil
}

func generateGlobalLeaderboard(db *sql.DB, out string, d dungeonInfo, seasonID, pa
geSize int) error {
	dir := filepath.Join(out, "global", d.Slug)
	if err := os.MkdirAll(dir, 0o755); err != nil {
		return err
	}
	all, err := loader.LoadAllCanonicalRuns(db, d.ID, "", "", seasonID)
	if err != nil {
		return err
	}
	return writeLeaderboardPages(dir, all, d.Name, "", pageSize)
}

func generateRegionalLeaderboard(db *sql.DB, out, region string, d dungeonInfo, se
asonID, pageSize int) error {
	dir := filepath.Join(out, region, "all", d.Slug)
	if err := os.MkdirAll(dir, 0o755); err != nil {
		return err
	}
	all, err := loader.LoadAllCanonicalRuns(db, d.ID, region, "", seasonID)
	if err != nil {
		return err
	}
	return writeLeaderboardPages(dir, all, d.Name, "", pageSize)
}

func generateRealmLeaderboard(db *sql.DB, out, region, realmSlug string, d dungeon
Info, seasonID, pageSize int) error {
	dir := filepath.Join(out, region, realmSlug, d.Slug)
	if err := os.MkdirAll(dir, 0o755); err != nil {
		return err
	}
	var realmName string
	if err := db.QueryRow(`SELECT name FROM realms WHERE region = ? AND slug = ?`, re
gion, realmSlug).Scan(&realmName); err != nil {
		realmName = realmSlug
	}
	all, err := loader.LoadAllCanonicalRuns(db, d.ID, region, realmSlug, seasonID)
	if err != nil {
		return err
	}
	return writeLeaderboardPages(dir, all, d.Name, realmName, pageSize)
}

func writeLeaderboardPages(dir string, all []loader.LeaderboardRow, dungeonName, r
ealmName string, pageSize int) error {
	total := len(all)
	pages := (total + pageSize - 1) / pageSize
	for p := 1; p <= pages; p++ {
		start := (p - 1) * pageSize
		end := start + pageSize
		if end > total {
			end = total
		}
		page := buildLeaderboardPage(all[start:end], dungeonName, realmName, total, page
s, p, pageSize)
		if err := writer.WriteJSONFileCompact(filepath.Join(dir, fmt.Sprintf("%d.json", 
p)), page); err != nil {
			return err
		}
	}
	return nil
}

// buildLeaderboardPage converts loader data to JSON page structure
func buildLeaderboardPage(rows []loader.LeaderboardRow, dungeonName, realmName str
ing, total, totalPages, currentPage, pageSize int) LeaderboardPageJSON {
	page := LeaderboardPageJSON{
		LeadingGroups: make([]LeaderboardRowJSON, len(rows)),
	}

	// Convert loader types to JSON types
	for i, row := range rows {
		jsonRow := LeaderboardRowJSON{
			ID:                 row.ID,
			Duration:           row.Duration,
			CompletedTimestamp: row.CompletedTimestamp,
			KeystoneLevel:      row.KeystoneLevel,
			DungeonName:        row.DungeonName,
			RealmName:          row.RealmName,
			Region:             row.Region,
			RankingPercentile:  row.RankingPercentile,
			Members:            make([]LeaderboardMemberJSON, len(row.Members)),
		}

		for j, member := range row.Members {
			jsonRow.Members[j] = LeaderboardMemberJSON{
				Name:      member.Name,
				SpecID:    member.SpecID,
				Region:    member.Region,
				RealmSlug: member.RealmSlug,
			}
		}

		page.LeadingGroups[i] = jsonRow
	}

	page.Map.Name = map[string]any{"en_US": dungeonName}

	if realmName != "" {
		page.ConnectedRealm = &struct {
			Name string `json:"name"`
		}{Name: realmName}
	}

	page.Pagination.CurrentPage = currentPage
	page.Pagination.PageSize = pageSize
	page.Pagination.TotalRuns = total
	page.Pagination.TotalPages = totalPages
	page.Pagination.HasNextPage = currentPage < totalPages
	page.Pagination.HasPrevPage = currentPage > 1

	return page
}

package generator

import (
	"database/sql"
	"fmt"
	"ookstats/internal/loader"
	"ookstats/internal/writer"
	"os"
	"path/filepath"
	"sync"
	"sync/atomic"
)

// LeaderboardPageJSON represents a paginate
d leaderboard response
type LeaderboardPageJSON struct {
	LeadingGroups []LeaderboardRowJSON `json:"l
eading_groups"`
	Map           struct {
		Name map[string]any `json:"name"`
	} `json:"map"`
	ConnectedRealm *struct {
		Name string `json:"name"`
	} `json:"connected_realm,omitempty"`
	Pagination struct {
		CurrentPage int  `json:"currentPage"`
		PageSize    int  `json:"pageSize"`
		TotalRuns   int  `json:"totalRuns"`
		TotalPages  int  `json:"totalPages"`
		HasNextPage bool `json:"hasNextPage"`
		HasPrevPage bool `json:"hasPrevPage"`
	} `json:"pagination"`
}

// LeaderboardRowJSON represents a run in th
e leaderboard
type LeaderboardRowJSON struct {
	ID                 int64                   
`json:"id"`
	Duration           int64                   
`json:"duration"`
	CompletedTimestamp int64                   
`json:"completed_timestamp"`
	KeystoneLevel      int                     
`json:"keystone_level"`
	DungeonName        string                  
`json:"dungeon_name"`
	RealmName          string                  
`json:"realm_name"`
	Region             string                  
`json:"region"`
	RankingPercentile  string                  
`json:"ranking_percentile,omitempty"`
	Members            []LeaderboardMemberJSON 
`json:"members"`
}

// LeaderboardMemberJSON represents a team m
ember in a leaderboard row
type LeaderboardMemberJSON struct {
	Name      string `json:"name"`
	SpecID    *int   `json:"spec_id,omitempty"`
	Region    string `json:"region"`
	RealmSlug string `json:"realm_slug"`
}

// dungeonInfo holds dungeon metadata
type dungeonInfo struct {
	ID         int
	Slug, Name string
}

// leaderboardJob represents a single leader
board generation task
type leaderboardJob struct {
	seasonID   int
	seasonName string
	dungeon    dungeonInfo
	region     string // empty for global
	realmSlug  string // empty for global/regio
nal
	out        string
	pageSize   int
}

// GenerateLeaderboards generates leaderboar
d JSON files for all scopes (global, regiona
l, realm) per season
// Uses a worker pool for parallel generatio
n
func GenerateLeaderboards(db *sql.DB, out st
ring, pageSize int, regions []string, worker
s int) error {
	if pageSize <= 0 {
		pageSize = 25
	}
	if workers <= 0 {
		workers = 10
	}
	if err := os.MkdirAll(out, 0o755); err != n
il {
		return err
	}

	// Load dungeons
	dungeons, err := loadDungeons(db)
	if err != nil {
		return err
	}

	// Load seasons
	seasons, err := loadSeasons(db)
	if err != nil {
		return err
	}

	if len(seasons) == 0 {
		fmt.Println("Warning: No seasons found - s
kipping leaderboard generation")
		return nil
	}

	// Regions
	if len(regions) == 0 {
		regions = []string{"us", "eu", "kr", "tw"}
	}

	// Pre-load all realm slugs per region
	realmSlugs := make(map[string][]string)
	for _, reg := range regions {
		slugs, err := loadRealmSlugs(db, reg)
		if err != nil {
			return err
		}
		realmSlugs[reg] = slugs
	}

	// Count total jobs for progress reporting
	var totalJobs int
	for range seasons {
		totalJobs += len(dungeons) // global
		for _, reg := range regions {
			totalJobs += len(dungeons)               
         // regional
			totalJobs += len(realmSlugs[reg]) * len(d
ungeons) // realm
		}
	}

	fmt.Printf("Generating leaderboards with %d
 workers (%d total jobs)...\n", workers, tot
alJobs)

	// Create job channel and error channel
	jobs := make(chan leaderboardJob, 100)
	var firstErr atomic.Value
	var completed atomic.Int64
	var wg sync.WaitGroup

	// Start workers
	for i := 0; i < workers; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for job := range jobs {
				// Skip if we already have an error
				if firstErr.Load() != nil {
					continue
				}

				var err error
				if job.realmSlug != "" {
					err = generateRealmLeaderboard(db, job.
out, job.region, job.realmSlug, job.dungeon,
 job.seasonID, job.pageSize)
				} else if job.region != "" {
					err = generateRegionalLeaderboard(db, j
ob.out, job.region, job.dungeon, job.seasonI
D, job.pageSize)
				} else {
					err = generateGlobalLeaderboard(db, job
.out, job.dungeon, job.seasonID, job.pageSiz
e)
				}

				if err != nil {
					firstErr.CompareAndSwap(nil, err)
					continue
				}

				c := completed.Add(1)
				if c%100 == 0 {
					fmt.Printf("  ... %d/%d leaderboards ge
nerated\n", c, totalJobs)
				}
			}
		}()
	}

	// Queue all jobs
	for _, season := range seasons {
		fmt.Printf("\n=== Queuing Season %d (%s) =
==\n", season.ID, season.Name)
		seasonOut := filepath.Join(out, "season", 
fmt.Sprintf("%d", season.ID))

		// Global leaderboards
		for _, d := range dungeons {
			jobs <- leaderboardJob{
				seasonID:   season.ID,
				seasonName: season.Name,
				dungeon:    d,
				region:     "",
				realmSlug:  "",
				out:        seasonOut,
				pageSize:   pageSize,
			}
		}

		// Regional leaderboards
		for _, reg := range regions {
			for _, d := range dungeons {
				jobs <- leaderboardJob{
					seasonID:   season.ID,
					seasonName: season.Name,
					dungeon:    d,
					region:     reg,
					realmSlug:  "",
					out:        seasonOut,
					pageSize:   pageSize,
				}
			}
		}

		// Realm leaderboards
		for _, reg := range regions {
			for _, rslug := range realmSlugs[reg] {
				for _, d := range dungeons {
					jobs <- leaderboardJob{
						seasonID:   season.ID,
						seasonName: season.Name,
						dungeon:    d,
						region:     reg,
						realmSlug:  rslug,
						out:        seasonOut,
						pageSize:   pageSize,
					}
				}
			}
		}
	}
	close(jobs)

	// Wait for all workers to complete
	wg.Wait()

	// Check for errors
	if err := firstErr.Load(); err != nil {
		return err.(error)
	}

	fmt.Printf("\n[OK] Generated %d leaderboard
s\n", completed.Load())
	return nil
}

// loadDungeons loads all dungeons from the 
database
func loadDungeons(db *sql.DB) ([]dungeonInfo
, error) {
	rows, err := db.Query(`SELECT id, slug, nam
e FROM dungeons ORDER BY name`)
	if err != nil {
		return nil, fmt.Errorf("dungeons query: %w
", err)
	}
	defer rows.Close()

	var dungeons []dungeonInfo
	for rows.Next() {
		var d dungeonInfo
		if err := rows.Scan(&d.ID, &d.Slug, &d.Nam
e); err != nil {
			return nil, err
		}
		dungeons = append(dungeons, d)
	}
	return dungeons, nil
}

// seasonInfo holds season metadata
type seasonInfo struct {
	ID   int
	Name string
}

// loadSeasons loads all distinct season num
bers from the database
func loadSeasons(db *sql.DB) ([]seasonInfo, 
error) {
	rows, err := db.Query(`
		SELECT DISTINCT season_number, season_name
		FROM seasons
		ORDER BY season_number ASC
	`)
	if err != nil {
		return nil, fmt.Errorf("seasons query: %w"
, err)
	}
	defer rows.Close()

	var seasons []seasonInfo
	for rows.Next() {
		var s seasonInfo
		if err := rows.Scan(&s.ID, &s.Name); err !
= nil {
			return nil, err
		}
		seasons = append(seasons, s)
	}
	return seasons, nil
}

// loadRealmSlugs loads realm slugs for a gi
ven region
func loadRealmSlugs(db *sql.DB, region strin
g) ([]string, error) {
	rows, err := db.Query(`SELECT slug FROM rea
lms WHERE region = ? ORDER BY slug`, region)
	if err != nil {
		return nil, fmt.Errorf("realms list: %w", 
err)
	}
	defer rows.Close()

	var slugs []string
	for rows.Next() {
		var s string
		if err := rows.Scan(&s); err != nil {
			return nil, err
		}
		slugs = append(slugs, s)
	}
	return slugs, nil
}

// children collapse upward via parent_realm
_slug
func loadParentRealmSlugs(db *sql.DB, region
 string) ([]string, error) {
	rows, err := db.Query(`
		SELECT slug
		FROM realms
		WHERE region = ? AND (parent_realm_slug IS
 NULL OR parent_realm_slug = '')
		ORDER BY slug
	`, region)
	if err != nil {
		return nil, fmt.Errorf("parent realms list
: %w", err)
	}
	defer rows.Close()

	var slugs []string
	for rows.Next() {
		var s string
		if err := rows.Scan(&s); err != nil {
			return nil, err
		}
		slugs = append(slugs, s)
	}
	return slugs, nil
}

func generateGlobalLeaderboard(db *sql.DB, o
ut string, d dungeonInfo, seasonID, pageSize
 int) error {
	dir := filepath.Join(out, "global", d.Slug)
	if err := os.MkdirAll(dir, 0o755); err != n
il {
		return err
	}
	all, err := loader.LoadAllCanonicalRuns(db,
 d.ID, "", "", seasonID)
	if err != nil {
		return err
	}
	return writeLeaderboardPages(dir, all, d.Na
me, "", pageSize)
}

func generateRegionalLeaderboard(db *sql.DB,
 out, region string, d dungeonInfo, seasonID
, pageSize int) error {
	dir := filepath.Join(out, region, "all", d.
Slug)
	if err := os.MkdirAll(dir, 0o755); err != n
il {
		return err
	}
	all, err := loader.LoadAllCanonicalRuns(db,
 d.ID, region, "", seasonID)
	if err != nil {
		return err
	}
	return writeLeaderboardPages(dir, all, d.Na
me, "", pageSize)
}

func generateRealmLeaderboard(db *sql.DB, ou
t, region, realmSlug string, d dungeonInfo, 
seasonID, pageSize int) error {
	dir := filepath.Join(out, region, realmSlug
, d.Slug)
	if err := os.MkdirAll(dir, 0o755); err != n
il {
		return err
	}
	var realmName string
	if err := db.QueryRow(`SELECT name FROM rea
lms WHERE region = ? AND slug = ?`, region, 
realmSlug).Scan(&realmName); err != nil {
		realmName = realmSlug
	}
	all, err := loader.LoadAllCanonicalRuns(db,
 d.ID, region, realmSlug, seasonID)
	if err != nil {
		return err
	}
	return writeLeaderboardPages(dir, all, d.Na
me, realmName, pageSize)
}

func writeLeaderboardPages(dir string, all [
]loader.LeaderboardRow, dungeonName, realmNa
me string, pageSize int) error {
	total := len(all)
	pages := (total + pageSize - 1) / pageSize
	for p := 1; p <= pages; p++ {
		start := (p - 1) * pageSize
		end := start + pageSize
		if end > total {
			end = total
		}
		page := buildLeaderboardPage(all[start:end
], dungeonName, realmName, total, pages, p, 
pageSize)
		if err := writer.WriteJSONFileCompact(file
path.Join(dir, fmt.Sprintf("%d.json", p)), p
age); err != nil {
			return err
		}
	}
	return nil
}

// buildLeaderboardPage converts loader data
 to JSON page structure
func buildLeaderboardPage(rows []loader.Lead
erboardRow, dungeonName, realmName string, t
otal, totalPages, currentPage, pageSize int)
 LeaderboardPageJSON {
	page := LeaderboardPageJSON{
		LeadingGroups: make([]LeaderboardRowJSON, 
len(rows)),
	}

	// Convert loader types to JSON types
	for i, row := range rows {
		jsonRow := LeaderboardRowJSON{
			ID:                 row.ID,
			Duration:           row.Duration,
			CompletedTimestamp: row.CompletedTimestam
p,
			KeystoneLevel:      row.KeystoneLevel,
			DungeonName:        row.DungeonName,
			RealmName:          row.RealmName,
			Region:             row.Region,
			RankingPercentile:  row.RankingPercentile
,
			Members:            make([]LeaderboardMem
berJSON, len(row.Members)),
		}

		for j, member := range row.Members {
			jsonRow.Members[j] = LeaderboardMemberJSO
N{
				Name:      member.Name,
				SpecID:    member.SpecID,
				Region:    member.Region,
				RealmSlug: member.RealmSlug,
			}
		}

		page.LeadingGroups[i] = jsonRow
	}

	page.Map.Name = map[string]any{"en_US": dun
geonName}

	if realmName != "" {
		page.ConnectedRealm = &struct {
			Name string `json:"name"`
		}{Name: realmName}
	}

	page.Pagination.CurrentPage = currentPage
	page.Pagination.PageSize = pageSize
	page.Pagination.TotalRuns = total
	page.Pagination.TotalPages = totalPages
	page.Pagination.HasNextPage = currentPage <
 totalPages
	page.Pagination.HasPrevPage = currentPage >
 1

	return page
}
 
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET