package model // LeagueID identifies a supported league. type LeagueID string const ( WorldCup LeagueID = "worldcup" MLB LeagueID = "mlb" NBA LeagueID = "nba" WNBA LeagueID = "wnba" NHL LeagueID = "nhl" NFL LeagueID = "nfl" ) // League is static metadata for a supported competition. type League struct { ID LeagueID Name string // display name, e.g. "World Cup" Abbr string // short tag, e.g. "WC" Sport string // ESPN sport path segment, e.g. "baseball" Path string // ESPN league path segment, e.g. "mlb" Color string // accent hex (no '#') for UI theming Icon string // single-rune emoji/glyph // Fetch window in days, tuned to game cadence: daily sports (MLB) need // only a couple days to surface last/next; weekly sports (NFL, soccer) // need ~10. Zero means fall back to DefaultWindowBack/Forward. WindowBack int WindowForward int // SeasonDays is the ± window (days) used to decide whether the league is // "in season" for auto-hide (TASK-019): a league with no games within this // span of today is hidden until it returns. Quadrennial events (World Cup, // Olympics) use a wide span so they surface ahead of time. 0 → DefaultSeasonDays. SeasonDays int } // Leagues is the ordered, canonical set the app polls and displays. // Order here is the display/cycle order in the dashboard. World Cup and // MLB lead because they are the current in-season priorities. // Windows are tuned to surface roughly each team's last game and next game, // not a whole stretch of fixtures: just wide enough to span one game-to-game // gap each way for the league's cadence (daily sports stay tight; weekly NFL // needs ~a week each side). Wider windows pull a "ton more" than last/next. var Leagues = []League{ {WorldCup, "World Cup", "WC", "soccer", "fifa.world", "6CABDD", "⚽", 7, 7, 90}, {MLB, "MLB", "MLB", "baseball", "mlb", "C8102E", "⚾", 2, 3, 0}, {NBA, "NBA", "NBA", "basketball", "nba", "C9082F", "🏀", 3, 4, 0}, {WNBA, "WNBA", "WNBA", "basketball", "wnba", "FF6F1E", "🏀", 3, 4, 0}, {NHL, "NHL", "NHL", "hockey", "nhl", "6B7280", "🏒", 3, 4, 0}, {NFL, "NFL", "NFL", "football", "nfl", "013369", "🏈", 8, 8, 0}, } // Default fetch window (days) for leagues that don't specify one. const ( DefaultWindowBack = 4 DefaultWindowForward = 5 // DefaultSeasonDays is the ± in-season detection span for leagues that // don't set SeasonDays — roughly a month covers normal between-game gaps. DefaultSeasonDays = 30 ) // Window returns the league's fetch window in days, applying defaults. func (l League) Window() (back, forward int) { back, forward = l.WindowBack, l.WindowForward if back == 0 { back = DefaultWindowBack } if forward == 0 { forward = DefaultWindowForward } return back, forward } // SeasonWindow returns the league's in-season detection span in days. func (l League) SeasonWindow() int { if l.SeasonDays == 0 { return DefaultSeasonDays } return l.SeasonDays } // LeagueByID returns the League metadata for id, ok=false if unknown. func LeagueByID(id LeagueID) (League, bool) { for _, l := range Leagues { if l.ID == id { return l, true } } return League{}, false }