Files
nba-fan-hub/seed_seasons.py

165 lines
7.8 KiB
Python

# -*- coding: utf-8 -*-
"""
赛季补充数据(独立于主 seed,不覆盖现有数据):
1. 补齐 2025-26 季后赛首轮缺失系列(每系列 2 场,高顺位 2-0 晋级)
2. 生成 2024-25 赛季:常规赛排名(30 队)+ 完整季后赛对阵(首轮 8 系列 / 次轮 4 / 分区决赛 2 / 总决赛 3 场)
用法:python3 seed_seasons.py
"""
import logging
import random
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
log = logging.getLogger("seed_seasons")
from db import init_db, execute, query, query_one # noqa: E402
random.seed(42)
# ---------------------------------------------------------------- 2025-26 季后赛补充
# (轮次, 时间, 主队code, 客队code, 主分, 客分)
R1_2026 = [
("季后赛首轮", "2026-04-20 08:00", "CLE", "ORL", 120, 98),
("季后赛首轮", "2026-04-23 07:30", "CLE", "ORL", 115, 102),
("季后赛首轮", "2026-04-20 07:00", "NYK", "MIA", 108, 96),
("季后赛首轮", "2026-04-23 08:00", "NYK", "MIA", 110, 104),
("季后赛首轮", "2026-04-21 08:00", "MIL", "IND", 112, 101),
("季后赛首轮", "2026-04-24 08:30", "MIL", "IND", 109, 105),
("季后赛首轮", "2026-04-19 10:00", "DEN", "HOU", 121, 110),
("季后赛首轮", "2026-04-22 09:30", "DEN", "HOU", 118, 109),
# 已有系列补第 2 场(胜方再胜 → 2-0)
("季后赛首轮", "2026-04-22 10:00", "OKC", "MIN", 126, 110),
("季后赛首轮", "2026-04-25 08:00", "BOS", "PHI", 118, 99),
("季后赛首轮", "2026-05-01 10:30", "LAL", "MEM", 117, 105),
# 次轮补第 2 场(胜方再胜 → 2-0)
("季后赛次轮", "2026-05-09 08:30", "BOS", "MIL", 114, 101),
("季后赛次轮", "2026-05-19 08:00", "CLE", "NYK", 118, 105),
("季后赛次轮", "2026-05-18 09:30", "DEN", "LAL", 116, 108),
]
# ---------------------------------------------------------------- 2024-25 赛季
# 常规赛战绩:基于 2025-26 战绩微调(保证排名接近,冠军悬念不同)
_W25 = { # code -> (wins, losses) 与 standings 排名一致
"BOS": (61, 21), "CLE": (57, 25), "NYK": (53, 29), "MIL": (50, 32),
"IND": (48, 34), "MIA": (45, 37), "ORL": (44, 38), "PHI": (42, 40),
"ATL": (40, 42), "CHI": (37, 45), "BKN": (34, 48), "TOR": (31, 51),
"DET": (28, 54), "WAS": (21, 61), "CHA": (20, 62),
"OKC": (66, 16), "DEN": (56, 26), "LAL": (54, 28), "GSW": (52, 30),
"DAL": (50, 32), "MEM": (49, 33), "HOU": (48, 34), "MIN": (47, 35),
"LAC": (46, 36), "SAC": (43, 39), "PHX": (41, 41), "SAS": (37, 45),
"POR": (29, 53), "UTA": (24, 58), "NOP": (23, 59),
}
CONF25 = { # code -> (conference, rank)
"BOS": ("东部", 1), "CLE": ("东部", 2), "NYK": ("东部", 3), "MIL": ("东部", 4),
"IND": ("东部", 5), "MIA": ("东部", 6), "ORL": ("东部", 7), "PHI": ("东部", 8),
"ATL": ("东部", 9), "CHI": ("东部", 10), "BKN": ("东部", 11), "TOR": ("东部", 12),
"DET": ("东部", 13), "WAS": ("东部", 14), "CHA": ("东部", 15),
"OKC": ("西部", 1), "DEN": ("西部", 2), "LAL": ("西部", 3), "GSW": ("西部", 4),
"DAL": ("西部", 5), "MEM": ("西部", 6), "HOU": ("西部", 7), "MIN": ("西部", 8),
"LAC": ("西部", 9), "SAC": ("西部", 10), "PHX": ("西部", 11), "SAS": ("西部", 12),
"POR": ("西部", 13), "UTA": ("西部", 14), "NOP": ("西部", 15),
}
# 2024-25 季后赛对阵(每系列 2 场,高顺位 2-0 晋级;总决赛 3 场 2-1,凯尔特人夺冠)
# 格式: (轮次, [(主队, 客队, 主分, 客分), ...])
PLAYOFFS25 = [
("季后赛首轮", [
("BOS", "PHI", 124, 102), ("BOS", "PHI", 118, 96), # 1 vs 8
("CLE", "ORL", 112, 95), ("CLE", "ORL", 109, 98),
("NYK", "MIA", 105, 97), ("NYK", "MIA", 111, 103),
("MIL", "IND", 110, 101), ("MIL", "IND", 107, 99),
("OKC", "MIN", 123, 108), ("OKC", "MIN", 117, 104),
("DEN", "HOU", 119, 106), ("DEN", "HOU", 114, 107),
("LAL", "MEM", 116, 110), ("LAL", "MEM", 121, 112),
("GSW", "DAL", 120, 113), ("GSW", "DAL", 115, 109),
]),
("季后赛次轮", [
("BOS", "MIL", 116, 105), ("BOS", "MIL", 112, 100), # 上半区
("CLE", "NYK", 108, 101), ("CLE", "NYK", 114, 106), # 下半区
("OKC", "GSW", 125, 117), ("OKC", "GSW", 121, 110),
("DEN", "LAL", 117, 111), ("DEN", "LAL", 113, 108),
]),
("东部决赛", [
("BOS", "CLE", 115, 102), ("BOS", "CLE", 110, 104),
]),
("西部决赛", [
("OKC", "DEN", 118, 112), ("OKC", "DEN", 121, 116),
]),
("总决赛", [
("BOS", "OKC", 108, 105), ("OKC", "BOS", 118, 112), ("BOS", "OKC", 117, 110),
]),
]
VENUES = {
"BOS": "TD花园", "CLE": "速贷中心", "NYK": "麦迪逊广场花园", "MIL": "费哲论坛球馆",
"OKC": "佩科姆中心", "DEN": "波尔球馆", "LAL": "加密网球馆", "GSW": "大通中心",
"ORL": "安利中心", "MIA": "卡塞亚中心", "IND": "甘布里吉球场", "PHI": "富国银行中心",
"MIN": "目标中心", "HOU": "丰田中心", "MEM": "联邦快递球馆", "DAL": "美航中心",
}
def _team_ids():
return {r["code"]: r["id"] for r in query("SELECT id, code FROM teams")}
def _insert_game(league_id, season, rnd, gt, home_id, away_id, hs, as_, venue, bcast="TNT"):
execute("""INSERT INTO games(league_id,season,round_name,game_time,status,home_team_id,away_team_id,
home_score,away_score,venue,broadcast) VALUES(?,?,?,?,?,?,?,?,?,?,?)""",
(league_id, season, rnd, gt, "finished", home_id, away_id, hs, as_, venue, bcast))
def add_2025_26_round1():
tid = _team_ids()
league_id = query_one("SELECT id FROM leagues WHERE code='NBA'")["id"]
n = 0
for rnd, gt, h, a, hs, as_ in R1_2026:
if query_one("SELECT 1 FROM games WHERE round_name=? AND game_time=?", (rnd, gt)):
continue
_insert_game(league_id, "2025-26", rnd, gt, tid[h], tid[a], hs, as_, VENUES.get(h, "球馆"))
n += 1
log.info("2025-26 季后赛首轮补充 %d 场", n)
def seed_2024_25():
tid = _team_ids()
league_id = query_one("SELECT id FROM leagues WHERE code='NBA'")["id"]
# 排名
n_s = 0
for code, (w, l) in _W25.items():
conf, rk = CONF25[code]
if not query_one("SELECT 1 FROM standings WHERE season='2024-25' AND team_id=?", (tid[code],)):
execute("""INSERT INTO standings(league_id,season,team_id,wins,losses,win_pct,conference,rank)
VALUES(?,?,?,?,?,?,?,?)""",
(league_id, "2024-25", tid[code], w, l, round(w / (w + l), 4), conf, rk))
n_s += 1
# 比赛
n_g = 0
for rnd, games in PLAYOFFS25:
for i, (h, a, hs, as_) in enumerate(games):
gt = _gt25(rnd, i)
if query_one("SELECT 1 FROM games WHERE round_name=? AND game_time=?", (rnd, gt)):
continue
_insert_game(league_id, "2024-25", rnd, gt, tid[h], tid[a], hs, as_,
VENUES.get(h, "球馆"))
n_g += 1
log.info("2024-25 赛季:排名 %d 行,季后赛 %d 场", n_s, n_g)
def _gt25(rnd, i):
base = {"季后赛首轮": "2025-04-19", "季后赛次轮": "2025-05-06",
"东部决赛": "2025-05-20", "西部决赛": "2025-05-21", "总决赛": "2025-06-03"}[rnd]
from datetime import datetime, timedelta
d = datetime.strptime(base, "%Y-%m-%d") + timedelta(days=i)
hour = "08:30" if rnd == "总决赛" else "09:00"
return f"{d.strftime('%Y-%m-%d')} {hour}"
if __name__ == "__main__":
init_db()
add_2025_26_round1()
seed_2024_25()
from db import table_count
for r in query("SELECT season, COUNT(*) c FROM games GROUP BY season"):
log.info("games %s: %d 场", r["season"], r["c"])
for r in query("SELECT season, COUNT(*) c FROM standings GROUP BY season"):
log.info("standings %s: %d 行", r["season"], r["c"])