fix: 优化数据
This commit is contained in:
Binary file not shown.
Binary file not shown.
18
server/db.js
18
server/db.js
@@ -123,12 +123,28 @@ try {
|
||||
if (!names.includes('status')) db.exec('ALTER TABLE key_location ADD COLUMN status TEXT DEFAULT "operational"')
|
||||
if (!names.includes('damage_level')) db.exec('ALTER TABLE key_location ADD COLUMN damage_level INTEGER')
|
||||
} catch (_) {}
|
||||
// 迁移:combat_losses 添加平民伤亡
|
||||
// 迁移:combat_losses 添加平民伤亡、updated_at
|
||||
try {
|
||||
const lossCols = db.prepare('PRAGMA table_info(combat_losses)').all()
|
||||
const lossNames = lossCols.map((c) => c.name)
|
||||
if (!lossNames.includes('civilian_killed')) db.exec('ALTER TABLE combat_losses ADD COLUMN civilian_killed INTEGER NOT NULL DEFAULT 0')
|
||||
if (!lossNames.includes('civilian_wounded')) db.exec('ALTER TABLE combat_losses ADD COLUMN civilian_wounded INTEGER NOT NULL DEFAULT 0')
|
||||
if (!lossNames.includes('updated_at')) db.exec('ALTER TABLE combat_losses ADD COLUMN updated_at TEXT DEFAULT (datetime("now"))')
|
||||
} catch (_) {}
|
||||
|
||||
// 迁移:所有表添加 updated_at 用于数据回放
|
||||
const addUpdatedAt = (table) => {
|
||||
try {
|
||||
const cols = db.prepare(`PRAGMA table_info(${table})`).all()
|
||||
if (!cols.some((c) => c.name === 'updated_at')) {
|
||||
db.exec(`ALTER TABLE ${table} ADD COLUMN updated_at TEXT DEFAULT (datetime("now"))`)
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
addUpdatedAt('force_summary')
|
||||
addUpdatedAt('power_index')
|
||||
addUpdatedAt('force_asset')
|
||||
addUpdatedAt('key_location')
|
||||
addUpdatedAt('retaliation_current')
|
||||
|
||||
module.exports = db
|
||||
|
||||
@@ -31,7 +31,7 @@ function broadcastSituation() {
|
||||
})
|
||||
} catch (_) {}
|
||||
}
|
||||
setInterval(broadcastSituation, 5000)
|
||||
setInterval(broadcastSituation, 3000)
|
||||
|
||||
// 供爬虫调用:更新 situation.updated_at 并立即广播
|
||||
function notifyCrawlerUpdate() {
|
||||
|
||||
@@ -1,8 +1,58 @@
|
||||
const express = require('express')
|
||||
const { getSituation } = require('./situationData')
|
||||
const db = require('./db')
|
||||
|
||||
const router = express.Router()
|
||||
|
||||
// 数据库 Dashboard:返回各表原始数据
|
||||
router.get('/db/dashboard', (req, res) => {
|
||||
try {
|
||||
const tables = [
|
||||
'situation',
|
||||
'force_summary',
|
||||
'power_index',
|
||||
'force_asset',
|
||||
'key_location',
|
||||
'combat_losses',
|
||||
'wall_street_trend',
|
||||
'retaliation_current',
|
||||
'retaliation_history',
|
||||
'situation_update',
|
||||
'gdelt_events',
|
||||
'conflict_stats',
|
||||
]
|
||||
const data = {}
|
||||
const timeSort = {
|
||||
situation: 'updated_at DESC',
|
||||
situation_update: 'timestamp DESC',
|
||||
gdelt_events: 'event_time DESC',
|
||||
wall_street_trend: 'time DESC',
|
||||
retaliation_history: 'time DESC',
|
||||
conflict_stats: 'updated_at DESC',
|
||||
}
|
||||
for (const name of tables) {
|
||||
try {
|
||||
const order = timeSort[name]
|
||||
let rows
|
||||
try {
|
||||
rows = order
|
||||
? db.prepare(`SELECT * FROM ${name} ORDER BY ${order}`).all()
|
||||
: db.prepare(`SELECT * FROM ${name}`).all()
|
||||
} catch (qerr) {
|
||||
rows = db.prepare(`SELECT * FROM ${name}`).all()
|
||||
}
|
||||
data[name] = rows
|
||||
} catch (e) {
|
||||
data[name] = { error: e.message }
|
||||
}
|
||||
}
|
||||
res.json(data)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
res.status(500).json({ error: err.message })
|
||||
}
|
||||
})
|
||||
|
||||
router.get('/situation', (req, res) => {
|
||||
try {
|
||||
res.json(getSituation())
|
||||
|
||||
@@ -58,18 +58,23 @@ function getSituation() {
|
||||
if (statsRow) conflictStats = statsRow
|
||||
} catch (_) {}
|
||||
|
||||
// 根据爬虫 conflict_stats 实时合并平民伤亡估算(GDELT 数据)
|
||||
// 平民伤亡:合计显示,不区分阵营
|
||||
const civUsK = lossesUs?.civilian_killed ?? 0
|
||||
const civUsW = lossesUs?.civilian_wounded ?? 0
|
||||
const civIrK = lossesIr?.civilian_killed ?? 0
|
||||
const civIrW = lossesIr?.civilian_wounded ?? 0
|
||||
const dbKilled = civUsK + civIrK
|
||||
const dbWounded = civUsW + civIrW
|
||||
const est = conflictStats.estimated_casualties || 0
|
||||
const civilianCasualtiesTotal = {
|
||||
killed: est > 0 ? Math.max(dbKilled, est) : dbKilled,
|
||||
wounded: dbWounded,
|
||||
}
|
||||
|
||||
const usLossesBase = lossesUs ? toLosses(lossesUs) : defaultLosses
|
||||
const irLossesBase = lossesIr ? toLosses(lossesIr) : defaultLosses
|
||||
const est = conflictStats.estimated_casualties || 0
|
||||
const mergeCivilian = (base, share) => {
|
||||
if (est <= 0) return base.civilianCasualties || { killed: 0, wounded: 0 }
|
||||
const gdeltKilled = Math.round(est * share)
|
||||
const cur = base.civilianCasualties || { killed: 0, wounded: 0 }
|
||||
return { killed: Math.max(cur.killed, gdeltKilled), wounded: cur.wounded }
|
||||
}
|
||||
const usLosses = { ...usLossesBase, civilianCasualties: mergeCivilian(usLossesBase, 0.35) }
|
||||
const irLosses = { ...irLossesBase, civilianCasualties: mergeCivilian(irLossesBase, 0.65) }
|
||||
const usLosses = { ...usLossesBase, civilianCasualties: { killed: 0, wounded: 0 } }
|
||||
const irLosses = { ...irLossesBase, civilianCasualties: { killed: 0, wounded: 0 } }
|
||||
|
||||
return {
|
||||
lastUpdated: meta?.updated_at || new Date().toISOString(),
|
||||
@@ -135,6 +140,7 @@ function getSituation() {
|
||||
url: e.url,
|
||||
})),
|
||||
conflictStats,
|
||||
civilianCasualtiesTotal,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user