NBA球迷大全 v1.0.0:对话问答+数据浏览系统(DeepSeek+RAG+SQLite)
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
数据库层:SQLite 统一存储结构化数据。
|
||||
Schema 采用"运动-联赛-球队-球员-比赛"分层设计,天然支持扩展:
|
||||
- 新增 CBA → sports 表加一行 basketball,leagues 表加 CBA(复用全部代码)
|
||||
- 新增足球 → sports 表加 football,league 可加 英超/西甲,球员字段可扩展
|
||||
- 新增人物角色 → persons.role 自由扩展(coach/agent/commentator/host/gm...)
|
||||
"""
|
||||
import sqlite3
|
||||
import threading
|
||||
|
||||
from config import DB_PATH
|
||||
|
||||
_SCHEMA = """
|
||||
CREATE TABLE IF NOT EXISTS sports (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
code TEXT UNIQUE NOT NULL, -- 'basketball' / 'football' ...
|
||||
name TEXT NOT NULL, -- '篮球' / '足球'
|
||||
name_en TEXT,
|
||||
created_at TEXT DEFAULT (datetime('now','localtime'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS leagues (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
sport_id INTEGER NOT NULL REFERENCES sports(id),
|
||||
code TEXT UNIQUE NOT NULL, -- 'NBA' / 'CBA' / 'EPL'
|
||||
name TEXT NOT NULL, -- '美国职业篮球联赛'
|
||||
name_en TEXT,
|
||||
country TEXT,
|
||||
season TEXT, -- '2025-26'
|
||||
created_at TEXT DEFAULT (datetime('now','localtime'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS teams (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
league_id INTEGER NOT NULL REFERENCES leagues(id),
|
||||
code TEXT, -- 'LAL'
|
||||
name TEXT NOT NULL, -- '洛杉矶湖人'
|
||||
name_en TEXT, -- 'Los Angeles Lakers'
|
||||
city TEXT,
|
||||
arena TEXT,
|
||||
founded INTEGER,
|
||||
champion_count INTEGER,
|
||||
head_coach TEXT,
|
||||
logo_url TEXT,
|
||||
intro TEXT,
|
||||
created_at TEXT DEFAULT (datetime('now','localtime'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS players (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
team_id INTEGER REFERENCES teams(id),
|
||||
name TEXT NOT NULL,
|
||||
name_en TEXT,
|
||||
position TEXT, -- PG/SG/SF/PF/C
|
||||
number INTEGER,
|
||||
height_cm INTEGER,
|
||||
weight_kg INTEGER,
|
||||
birth_date TEXT,
|
||||
country TEXT,
|
||||
draft_year INTEGER,
|
||||
draft_pick INTEGER, -- 0 = 落选
|
||||
salary_m REAL, -- 年薪(万美元)
|
||||
season_pts REAL, season_reb REAL, season_ast REAL,
|
||||
season_stl REAL, season_blk REAL, season_min REAL, -- 本赛季场均
|
||||
career_pts REAL, career_reb REAL, career_ast REAL, -- 生涯场均
|
||||
career_games INTEGER,
|
||||
career_steals INTEGER, career_blocks INTEGER, -- 生涯总数
|
||||
awards TEXT, -- 主要荣誉
|
||||
bio TEXT,
|
||||
created_at TEXT DEFAULT (datetime('now','localtime'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS games (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
league_id INTEGER NOT NULL REFERENCES leagues(id),
|
||||
season TEXT,
|
||||
round_name TEXT, -- 常规赛/季后赛首轮/总决赛...
|
||||
game_time TEXT, -- '2026-06-05 09:00'
|
||||
status TEXT, -- scheduled / finished / live
|
||||
home_team_id INTEGER REFERENCES teams(id),
|
||||
away_team_id INTEGER REFERENCES teams(id),
|
||||
home_score INTEGER,
|
||||
away_score INTEGER,
|
||||
venue TEXT,
|
||||
broadcast TEXT,
|
||||
created_at TEXT DEFAULT (datetime('now','localtime'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS game_player_stats (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
game_id INTEGER NOT NULL REFERENCES games(id),
|
||||
player_id INTEGER NOT NULL REFERENCES players(id),
|
||||
team_id INTEGER NOT NULL REFERENCES teams(id),
|
||||
points INTEGER DEFAULT 0, rebounds INTEGER DEFAULT 0,
|
||||
assists INTEGER DEFAULT 0, steals INTEGER DEFAULT 0,
|
||||
blocks INTEGER DEFAULT 0, minutes INTEGER DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS standings (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
league_id INTEGER NOT NULL REFERENCES leagues(id),
|
||||
season TEXT,
|
||||
team_id INTEGER NOT NULL REFERENCES teams(id),
|
||||
wins INTEGER DEFAULT 0, losses INTEGER DEFAULT 0,
|
||||
win_pct REAL DEFAULT 0,
|
||||
conference TEXT, -- 西部/东部
|
||||
rank INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS news (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
sport_id INTEGER NOT NULL REFERENCES sports(id),
|
||||
league_id INTEGER REFERENCES leagues(id),
|
||||
team_id INTEGER REFERENCES teams(id),
|
||||
title TEXT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
author TEXT,
|
||||
source TEXT,
|
||||
publish_time TEXT,
|
||||
tags TEXT,
|
||||
kind TEXT DEFAULT 'news', -- news / wiki(百科词条)
|
||||
created_at TEXT DEFAULT (datetime('now','localtime'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS persons (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
sport_id INTEGER NOT NULL REFERENCES sports(id),
|
||||
league_id INTEGER REFERENCES leagues(id),
|
||||
team_id INTEGER REFERENCES teams(id),
|
||||
name TEXT NOT NULL,
|
||||
name_en TEXT,
|
||||
role TEXT, -- coach/agent/commentator/host/gm/legend...
|
||||
role_cn TEXT, -- 教练/经纪人/评论员/主持人/总经理...
|
||||
title TEXT,
|
||||
bio TEXT,
|
||||
achievements TEXT,
|
||||
created_at TEXT DEFAULT (datetime('now','localtime'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_players_team ON players(team_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_players_name ON players(name);
|
||||
CREATE INDEX IF NOT EXISTS idx_games_time ON games(game_time);
|
||||
CREATE INDEX IF NOT EXISTS idx_games_team ON games(home_team_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_news_time ON news(publish_time);
|
||||
CREATE INDEX IF NOT EXISTS idx_persons_role ON persons(role);
|
||||
"""
|
||||
|
||||
_lock = threading.Lock()
|
||||
|
||||
|
||||
def get_conn():
|
||||
conn = sqlite3.connect(DB_PATH, timeout=30)
|
||||
conn.row_factory = sqlite3.Row
|
||||
conn.execute("PRAGMA journal_mode=WAL")
|
||||
conn.execute("PRAGMA foreign_keys=ON")
|
||||
return conn
|
||||
|
||||
|
||||
def init_db():
|
||||
with _lock:
|
||||
conn = get_conn()
|
||||
try:
|
||||
conn.executescript(_SCHEMA)
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def query(sql, args=()):
|
||||
conn = get_conn()
|
||||
try:
|
||||
cur = conn.execute(sql, args)
|
||||
return [dict(r) for r in cur.fetchall()]
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def query_one(sql, args=()):
|
||||
rows = query(sql, args)
|
||||
return rows[0] if rows else None
|
||||
|
||||
|
||||
def execute(sql, args=()):
|
||||
conn = get_conn()
|
||||
try:
|
||||
cur = conn.execute(sql, args)
|
||||
conn.commit()
|
||||
return cur.lastrowid
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def executemany(sql, rows):
|
||||
conn = get_conn()
|
||||
try:
|
||||
conn.executemany(sql, rows)
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def table_count(table):
|
||||
return query_one(f"SELECT COUNT(*) AS c FROM {table}")["c"]
|
||||
|
||||
|
||||
def fuzzy(expr): # SQL LIKE 模糊匹配(转义 % _)
|
||||
return expr.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_")
|
||||
Reference in New Issue
Block a user