refactor: 以 bzzoiro 为唯一数据源的全面重构
数据源统一为 bzzoiro,移除 Understat 与 injuries:
- 删除 src/data/understat.py / injuries.py 及相关测试
- 删除 injuries 模型与表;扩展 match_stats(xG 之外增加 big_chances/fouls)
- 新增 standings 表(联赛积分榜:位置/积分/xG/走势/分区)
- matches 表增加 source_event_id 血缘列,支撑统计回填
采集管线(bzzoiro 三条管线):
- events:赛程/比分(/events/),记录 source_event_id
- standings:积分榜快照(/leagues/{id}/standings/)
- stats:已完赛比赛详细统计回填(/events/{id}/stats/)
预测增强:
- standings_slice 替代 injuries_slice;积分榜专家替代阵容完整性专家
- AGENT_META runtime_config 同步更新
管理后台:
- ingest 路由重写为单一 bzzoiro 入口 + task 参数(events/standings/stats/all)
- 新增 /admin/data-completeness 数据完整性分析 API
- 数据源状态页简化为 bzzoiro 单源
前端:
- 采集页重构为任务驱动(比赛/积分榜/统计回填/全量)
- 新增「数据完整性」可视化页(覆盖率矩阵/字段完整率/健康摘要)
- 新增主站积分榜页(/standings)与比赛详情完整统计面板
- agent 名称同步更新(injuries→standings)
迁移 0015_bzzoiro_single_source 已在容器内验证通过,后端测试全部通过。
Co-Authored-By: new-provider/LongCat-2.0 <<EMAIL>>
This commit is contained in:
co-authored by
new-provider/LongCat-2.0 <
parent
ec8f36abb2
commit
f05dc1ae15
+5
-17
@@ -29,6 +29,8 @@ class MatchOut(BaseModel):
|
||||
match_stage: str | None
|
||||
home_xg: float | None = None
|
||||
away_xg: float | None = None
|
||||
# 比赛详细统计(bzzoiro /events/{id}/stats/),无统计为 None
|
||||
stats: dict | None = None
|
||||
# 该场比赛的最近预测摘要(按时间倒序,最多 5 条;无预测为空)
|
||||
recent_predictions: list[PredictionOut] = []
|
||||
|
||||
@@ -107,6 +109,9 @@ class IngestBzzoiroRequest(BaseModel):
|
||||
date_from: str | None = None
|
||||
date_to: str | None = None
|
||||
status: str | None = Field(None, description="finished/scheduled;空 = 两者都采集")
|
||||
task: str = Field("events", description="采集任务: events(比赛)/standings(积分榜)/stats(统计回填)/all")
|
||||
limit: int = Field(100, ge=1, le=500, description="stats 回填单次最大比赛数")
|
||||
season: str | None = Field(None, description="standings 赛季,如 '2026-2027';空 = 当前赛季")
|
||||
|
||||
|
||||
class IngestResponse(BaseModel):
|
||||
@@ -116,23 +121,6 @@ class IngestResponse(BaseModel):
|
||||
errors: list[str] = []
|
||||
|
||||
|
||||
class IngestUnderstatRequest(BaseModel):
|
||||
league: str | None = Field(None, description="联赛代码,如 'E0';空 = 全部已知联赛")
|
||||
season: int = Field(default_factory=lambda: date.today().year, description="赛季起始年,如 2025 表示 2025-2026 赛季")
|
||||
|
||||
|
||||
class IngestInjuriesRequest(BaseModel):
|
||||
date: str | None = Field(None, description="日期 YYYY-MM-DD,为空则采集当天")
|
||||
|
||||
|
||||
class IngestSimpleResponse(BaseModel):
|
||||
count: int = 0
|
||||
updated: int = 0
|
||||
skipped: int = 0
|
||||
unmatched: int = 0
|
||||
errors: list[str] = []
|
||||
|
||||
|
||||
class SettleRequest(BaseModel):
|
||||
prediction_id: int
|
||||
home_goals: int = Field(ge=0, le=30)
|
||||
|
||||
Reference in New Issue
Block a user