fix: 优化后端数据更新机制
This commit is contained in:
@@ -12,6 +12,23 @@ from typing import Any, Dict, Optional
|
||||
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
||||
DB_PATH = os.environ.get("DB_PATH", str(PROJECT_ROOT / "server" / "data.db"))
|
||||
|
||||
# 单次合并时各字段增量的上限,防止误把「累计总数」当增量导致数据剧增(可选,设为 0 表示不设限)
|
||||
MAX_DELTA_PER_MERGE = {
|
||||
"personnel_killed": 500, "personnel_wounded": 1000, "civilian_killed": 300, "civilian_wounded": 500,
|
||||
"bases_destroyed": 5, "bases_damaged": 10,
|
||||
"aircraft": 50, "warships": 10, "armor": 30, "vehicles": 100,
|
||||
"drones": 50, "missiles": 200, "helicopters": 20, "submarines": 5, "carriers": 2,
|
||||
"civilian_ships": 20, "airport_port": 10,
|
||||
}
|
||||
|
||||
|
||||
def _clamp_delta(key: str, value: int) -> int:
|
||||
"""单次增量上限,避免误提「累计」导致波动"""
|
||||
cap = MAX_DELTA_PER_MERGE.get(key, 0)
|
||||
if cap <= 0:
|
||||
return max(0, value)
|
||||
return max(0, min(value, cap))
|
||||
|
||||
|
||||
def _ensure_tables(conn: sqlite3.Connection) -> None:
|
||||
"""确保所需表存在(与 db.js 一致)"""
|
||||
@@ -41,7 +58,7 @@ def _ensure_tables(conn: sqlite3.Connection) -> None:
|
||||
conn.execute("ALTER TABLE combat_losses ADD COLUMN updated_at TEXT DEFAULT (datetime('now'))")
|
||||
except sqlite3.OperationalError:
|
||||
pass
|
||||
for col in ("drones", "missiles", "helicopters", "submarines", "tanks", "civilian_ships", "airport_port"):
|
||||
for col in ("drones", "missiles", "helicopters", "submarines", "tanks", "carriers", "civilian_ships", "airport_port"):
|
||||
try:
|
||||
conn.execute(f"ALTER TABLE combat_losses ADD COLUMN {col} INTEGER NOT NULL DEFAULT 0")
|
||||
except sqlite3.OperationalError:
|
||||
@@ -72,19 +89,19 @@ def merge(extracted: Dict[str, Any], db_path: Optional[str] = None) -> bool:
|
||||
)
|
||||
if conn.total_changes > 0:
|
||||
updated = True
|
||||
# combat_losses:增量叠加到当前值,无行则先插入初始行
|
||||
# combat_losses:统一按增量处理。AI 输出为本则报道的新增数,此处叠加到库内当前值,避免把「累计总数」当增量导致数据波动。
|
||||
if "combat_losses_delta" in extracted:
|
||||
for side, delta in extracted["combat_losses_delta"].items():
|
||||
if side not in ("us", "iran"):
|
||||
continue
|
||||
try:
|
||||
row = conn.execute(
|
||||
"SELECT personnel_killed,personnel_wounded,civilian_killed,civilian_wounded,bases_destroyed,bases_damaged,aircraft,warships,armor,vehicles,drones,missiles,helicopters,submarines,tanks,civilian_ships,airport_port FROM combat_losses WHERE side = ?",
|
||||
"SELECT personnel_killed,personnel_wounded,civilian_killed,civilian_wounded,bases_destroyed,bases_damaged,aircraft,warships,armor,vehicles,drones,missiles,helicopters,submarines,tanks,carriers,civilian_ships,airport_port FROM combat_losses WHERE side = ?",
|
||||
(side,),
|
||||
).fetchone()
|
||||
cur = {"personnel_killed": 0, "personnel_wounded": 0, "civilian_killed": 0, "civilian_wounded": 0,
|
||||
"bases_destroyed": 0, "bases_damaged": 0, "aircraft": 0, "warships": 0, "armor": 0, "vehicles": 0,
|
||||
"drones": 0, "missiles": 0, "helicopters": 0, "submarines": 0, "tanks": 0, "civilian_ships": 0, "airport_port": 0}
|
||||
"drones": 0, "missiles": 0, "helicopters": 0, "submarines": 0, "tanks": 0, "carriers": 0, "civilian_ships": 0, "airport_port": 0}
|
||||
if row:
|
||||
cur = {
|
||||
"personnel_killed": row[0], "personnel_wounded": row[1], "civilian_killed": row[2] or 0,
|
||||
@@ -92,38 +109,39 @@ def merge(extracted: Dict[str, Any], db_path: Optional[str] = None) -> bool:
|
||||
"aircraft": row[6], "warships": row[7], "armor": row[8], "vehicles": row[9],
|
||||
"drones": row[10] if len(row) > 10 else 0, "missiles": row[11] if len(row) > 11 else 0,
|
||||
"helicopters": row[12] if len(row) > 12 else 0, "submarines": row[13] if len(row) > 13 else 0,
|
||||
"tanks": row[14] if len(row) > 14 else 0, "civilian_ships": row[15] if len(row) > 15 else 0, "airport_port": row[16] if len(row) > 16 else 0,
|
||||
"tanks": row[14] if len(row) > 14 else 0, "carriers": row[15] if len(row) > 15 else (row[14] if len(row) > 14 else 0),
|
||||
"civilian_ships": row[16] if len(row) > 16 else 0, "airport_port": row[17] if len(row) > 17 else 0,
|
||||
}
|
||||
pk = max(0, (cur["personnel_killed"] or 0) + delta.get("personnel_killed", 0))
|
||||
pw = max(0, (cur["personnel_wounded"] or 0) + delta.get("personnel_wounded", 0))
|
||||
ck = max(0, (cur["civilian_killed"] or 0) + delta.get("civilian_killed", 0))
|
||||
cw = max(0, (cur["civilian_wounded"] or 0) + delta.get("civilian_wounded", 0))
|
||||
bd = max(0, (cur["bases_destroyed"] or 0) + delta.get("bases_destroyed", 0))
|
||||
bm = max(0, (cur["bases_damaged"] or 0) + delta.get("bases_damaged", 0))
|
||||
ac = max(0, (cur["aircraft"] or 0) + delta.get("aircraft", 0))
|
||||
ws = max(0, (cur["warships"] or 0) + delta.get("warships", 0))
|
||||
ar = max(0, (cur["armor"] or 0) + delta.get("armor", 0))
|
||||
vh = max(0, (cur["vehicles"] or 0) + delta.get("vehicles", 0))
|
||||
dr = max(0, (cur["drones"] or 0) + delta.get("drones", 0))
|
||||
ms = max(0, (cur["missiles"] or 0) + delta.get("missiles", 0))
|
||||
hp = max(0, (cur["helicopters"] or 0) + delta.get("helicopters", 0))
|
||||
sb = max(0, (cur["submarines"] or 0) + delta.get("submarines", 0))
|
||||
tk = max(0, (cur["tanks"] or 0) + delta.get("tanks", 0))
|
||||
cs = max(0, (cur["civilian_ships"] or 0) + delta.get("civilian_ships", 0))
|
||||
ap = max(0, (cur["airport_port"] or 0) + delta.get("airport_port", 0))
|
||||
pk = max(0, (cur["personnel_killed"] or 0) + _clamp_delta("personnel_killed", delta.get("personnel_killed", 0)))
|
||||
pw = max(0, (cur["personnel_wounded"] or 0) + _clamp_delta("personnel_wounded", delta.get("personnel_wounded", 0)))
|
||||
ck = max(0, (cur["civilian_killed"] or 0) + _clamp_delta("civilian_killed", delta.get("civilian_killed", 0)))
|
||||
cw = max(0, (cur["civilian_wounded"] or 0) + _clamp_delta("civilian_wounded", delta.get("civilian_wounded", 0)))
|
||||
bd = max(0, (cur["bases_destroyed"] or 0) + _clamp_delta("bases_destroyed", delta.get("bases_destroyed", 0)))
|
||||
bm = max(0, (cur["bases_damaged"] or 0) + _clamp_delta("bases_damaged", delta.get("bases_damaged", 0)))
|
||||
ac = max(0, (cur["aircraft"] or 0) + _clamp_delta("aircraft", delta.get("aircraft", 0)))
|
||||
ws = max(0, (cur["warships"] or 0) + _clamp_delta("warships", delta.get("warships", 0)))
|
||||
ar = max(0, (cur["armor"] or 0) + _clamp_delta("armor", delta.get("armor", 0)))
|
||||
vh = max(0, (cur["vehicles"] or 0) + _clamp_delta("vehicles", delta.get("vehicles", 0)))
|
||||
dr = max(0, (cur["drones"] or 0) + _clamp_delta("drones", delta.get("drones", 0)))
|
||||
ms = max(0, (cur["missiles"] or 0) + _clamp_delta("missiles", delta.get("missiles", 0)))
|
||||
hp = max(0, (cur["helicopters"] or 0) + _clamp_delta("helicopters", delta.get("helicopters", 0)))
|
||||
sb = max(0, (cur["submarines"] or 0) + _clamp_delta("submarines", delta.get("submarines", 0)))
|
||||
cr = max(0, (cur["carriers"] or 0) + _clamp_delta("carriers", delta.get("carriers", 0)))
|
||||
cs = max(0, (cur["civilian_ships"] or 0) + _clamp_delta("civilian_ships", delta.get("civilian_ships", 0)))
|
||||
ap = max(0, (cur["airport_port"] or 0) + _clamp_delta("airport_port", delta.get("airport_port", 0)))
|
||||
ts = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.000Z")
|
||||
if row:
|
||||
conn.execute(
|
||||
"""UPDATE combat_losses SET personnel_killed=?, personnel_wounded=?, civilian_killed=?, civilian_wounded=?,
|
||||
bases_destroyed=?, bases_damaged=?, aircraft=?, warships=?, armor=?, vehicles=?,
|
||||
drones=?, missiles=?, helicopters=?, submarines=?, tanks=?, civilian_ships=?, airport_port=?, updated_at=? WHERE side=?""",
|
||||
(pk, pw, ck, cw, bd, bm, ac, ws, ar, vh, dr, ms, hp, sb, tk, cs, ap, ts, side),
|
||||
drones=?, missiles=?, helicopters=?, submarines=?, tanks=?, carriers=?, civilian_ships=?, airport_port=?, updated_at=? WHERE side=?""",
|
||||
(pk, pw, ck, cw, bd, bm, ac, ws, ar, vh, dr, ms, hp, sb, cur.get("tanks", 0), cr, cs, ap, ts, side),
|
||||
)
|
||||
else:
|
||||
conn.execute(
|
||||
"""INSERT OR REPLACE INTO combat_losses (side, personnel_killed, personnel_wounded, civilian_killed, civilian_wounded,
|
||||
bases_destroyed, bases_damaged, aircraft, warships, armor, vehicles, drones, missiles, helicopters, submarines, tanks, civilian_ships, airport_port, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
(side, pk, pw, ck, cw, bd, bm, ac, ws, ar, vh, dr, ms, hp, sb, tk, cs, ap, ts),
|
||||
bases_destroyed, bases_damaged, aircraft, warships, armor, vehicles, drones, missiles, helicopters, submarines, tanks, carriers, civilian_ships, airport_port, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
(side, pk, pw, ck, cw, bd, bm, ac, ws, ar, vh, dr, ms, hp, sb, 0, cr, cs, ap, ts),
|
||||
)
|
||||
if conn.total_changes > 0:
|
||||
updated = True
|
||||
@@ -140,7 +158,7 @@ def merge(extracted: Dict[str, Any], db_path: Optional[str] = None) -> bool:
|
||||
w = extracted["wall_street"]
|
||||
conn.execute("INSERT INTO wall_street_trend (time, value) VALUES (?, ?)", (w["time"], w["value"]))
|
||||
updated = True
|
||||
# key_location:更新受袭基地 status/damage_level
|
||||
# key_location:更新双方攻击地点(美军基地被打击 side=us,伊朗设施被打击 side=iran)的 status/damage_level
|
||||
if "key_location_updates" in extracted:
|
||||
try:
|
||||
for u in extracted["key_location_updates"]:
|
||||
|
||||
Reference in New Issue
Block a user