feat: add new file
This commit is contained in:
107
server/db.js
Normal file
107
server/db.js
Normal file
@@ -0,0 +1,107 @@
|
||||
const Database = require('better-sqlite3')
|
||||
const path = require('path')
|
||||
|
||||
const dbPath = path.join(__dirname, 'data.db')
|
||||
const db = new Database(dbPath)
|
||||
|
||||
// 启用外键
|
||||
db.pragma('journal_mode = WAL')
|
||||
|
||||
// 建表
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS situation (
|
||||
id INTEGER PRIMARY KEY CHECK (id = 1),
|
||||
data TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS force_summary (
|
||||
side TEXT PRIMARY KEY CHECK (side IN ('us', 'iran')),
|
||||
total_assets INTEGER NOT NULL,
|
||||
personnel INTEGER NOT NULL,
|
||||
naval_ships INTEGER NOT NULL,
|
||||
aircraft INTEGER NOT NULL,
|
||||
ground_units INTEGER NOT NULL,
|
||||
uav INTEGER NOT NULL,
|
||||
missile_consumed INTEGER NOT NULL,
|
||||
missile_stock INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS power_index (
|
||||
side TEXT PRIMARY KEY CHECK (side IN ('us', 'iran')),
|
||||
overall INTEGER NOT NULL,
|
||||
military_strength INTEGER NOT NULL,
|
||||
economic_power INTEGER NOT NULL,
|
||||
geopolitical_influence INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS force_asset (
|
||||
id TEXT PRIMARY KEY,
|
||||
side TEXT NOT NULL CHECK (side IN ('us', 'iran')),
|
||||
name TEXT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
count INTEGER NOT NULL,
|
||||
status TEXT NOT NULL CHECK (status IN ('active', 'standby', 'alert')),
|
||||
lat REAL,
|
||||
lng REAL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS key_location (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
side TEXT NOT NULL CHECK (side IN ('us', 'iran')),
|
||||
name TEXT NOT NULL,
|
||||
lat REAL NOT NULL,
|
||||
lng REAL NOT NULL,
|
||||
type TEXT,
|
||||
region TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS combat_losses (
|
||||
side TEXT PRIMARY KEY CHECK (side IN ('us', 'iran')),
|
||||
bases_destroyed INTEGER NOT NULL,
|
||||
bases_damaged INTEGER NOT NULL,
|
||||
personnel_killed INTEGER NOT NULL,
|
||||
personnel_wounded INTEGER NOT NULL,
|
||||
aircraft INTEGER NOT NULL,
|
||||
warships INTEGER NOT NULL,
|
||||
armor INTEGER NOT NULL,
|
||||
vehicles INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS wall_street_trend (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
time TEXT NOT NULL,
|
||||
value INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS retaliation_current (
|
||||
id INTEGER PRIMARY KEY CHECK (id = 1),
|
||||
value INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS retaliation_history (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
time TEXT NOT NULL,
|
||||
value INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS situation_update (
|
||||
id TEXT PRIMARY KEY,
|
||||
timestamp TEXT NOT NULL,
|
||||
category TEXT NOT NULL,
|
||||
summary TEXT NOT NULL,
|
||||
severity TEXT NOT NULL
|
||||
);
|
||||
`)
|
||||
|
||||
// 迁移:为已有 key_location 表添加 type、region、status、damage_level 列
|
||||
try {
|
||||
const cols = db.prepare('PRAGMA table_info(key_location)').all()
|
||||
const names = cols.map((c) => c.name)
|
||||
if (!names.includes('type')) db.exec('ALTER TABLE key_location ADD COLUMN type TEXT')
|
||||
if (!names.includes('region')) db.exec('ALTER TABLE key_location ADD COLUMN region TEXT')
|
||||
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 (_) {}
|
||||
|
||||
module.exports = db
|
||||
34
server/index.js
Normal file
34
server/index.js
Normal file
@@ -0,0 +1,34 @@
|
||||
const http = require('http')
|
||||
const express = require('express')
|
||||
const cors = require('cors')
|
||||
const { WebSocketServer } = require('ws')
|
||||
const routes = require('./routes')
|
||||
const { getSituation } = require('./situationData')
|
||||
|
||||
const app = express()
|
||||
const PORT = process.env.API_PORT || 3001
|
||||
|
||||
app.use(cors())
|
||||
app.use(express.json())
|
||||
app.use('/api', routes)
|
||||
app.get('/api/health', (_, res) => res.json({ ok: true }))
|
||||
|
||||
const server = http.createServer(app)
|
||||
|
||||
const wss = new WebSocketServer({ server, path: '/ws' })
|
||||
wss.on('connection', (ws) => {
|
||||
ws.send(JSON.stringify({ type: 'situation', data: getSituation() }))
|
||||
})
|
||||
function broadcastSituation() {
|
||||
try {
|
||||
const data = JSON.stringify({ type: 'situation', data: getSituation() })
|
||||
wss.clients.forEach((c) => {
|
||||
if (c.readyState === 1) c.send(data)
|
||||
})
|
||||
} catch (_) {}
|
||||
}
|
||||
setInterval(broadcastSituation, 5000)
|
||||
|
||||
server.listen(PORT, () => {
|
||||
console.log(`API + WebSocket running at http://localhost:${PORT}`)
|
||||
})
|
||||
5
server/package.json
Normal file
5
server/package.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "usa-api",
|
||||
"private": true,
|
||||
"type": "commonjs"
|
||||
}
|
||||
15
server/routes.js
Normal file
15
server/routes.js
Normal file
@@ -0,0 +1,15 @@
|
||||
const express = require('express')
|
||||
const { getSituation } = require('./situationData')
|
||||
|
||||
const router = express.Router()
|
||||
|
||||
router.get('/situation', (req, res) => {
|
||||
try {
|
||||
res.json(getSituation())
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
res.status(500).json({ error: err.message })
|
||||
}
|
||||
})
|
||||
|
||||
module.exports = router
|
||||
174
server/seed.js
Normal file
174
server/seed.js
Normal file
@@ -0,0 +1,174 @@
|
||||
const db = require('./db')
|
||||
|
||||
// 与 src/data/mapLocations.ts 同步:62 基地,27 被袭 (严重6 中度12 轻度9)
|
||||
function getUsLocations() {
|
||||
const naval = [
|
||||
{ name: '林肯号航母 (CVN-72)', lat: 24.1568, lng: 58.4215, type: 'Aircraft Carrier', region: '北阿拉伯海', status: 'operational', damage_level: null },
|
||||
{ name: '福特号航母 (CVN-78)', lat: 35.7397, lng: 24.1002, type: 'Aircraft Carrier', region: '东地中海', status: 'operational', damage_level: null },
|
||||
{ name: '驱逐舰(阿曼湾)', lat: 25.2, lng: 58.0, type: 'Destroyer', region: '阿曼湾', status: 'operational', damage_level: null },
|
||||
{ name: '海岸警卫队 1', lat: 25.4, lng: 58.2, type: 'Coast Guard', region: '阿曼湾', status: 'operational', damage_level: null },
|
||||
{ name: '海岸警卫队 2', lat: 25.0, lng: 57.8, type: 'Coast Guard', region: '阿曼湾', status: 'operational', damage_level: null },
|
||||
{ name: '驱逐舰(波斯湾北部)', lat: 26.5, lng: 51.0, type: 'Destroyer', region: '波斯湾', status: 'operational', damage_level: null },
|
||||
{ name: '护卫舰 1', lat: 26.7, lng: 50.6, type: 'Frigate', region: '波斯湾', status: 'operational', damage_level: null },
|
||||
{ name: '护卫舰 2', lat: 27.0, lng: 50.2, type: 'Frigate', region: '波斯湾', status: 'operational', damage_level: null },
|
||||
{ name: '护卫舰 3', lat: 26.3, lng: 50.8, type: 'Frigate', region: '波斯湾', status: 'operational', damage_level: null },
|
||||
{ name: '辅助舰 1', lat: 26.0, lng: 51.2, type: 'Auxiliary', region: '波斯湾', status: 'operational', damage_level: null },
|
||||
{ name: '辅助舰 2', lat: 25.8, lng: 51.5, type: 'Auxiliary', region: '波斯湾', status: 'operational', damage_level: null },
|
||||
{ name: '辅助舰 3', lat: 26.2, lng: 50.9, type: 'Auxiliary', region: '波斯湾', status: 'operational', damage_level: null },
|
||||
]
|
||||
const attacked = [
|
||||
{ name: '阿萨德空军基地', lat: 33.785, lng: 42.441, type: 'Base', region: '伊拉克', status: 'attacked', damage_level: 3 },
|
||||
{ name: '巴格达外交支援中心', lat: 33.315, lng: 44.366, type: 'Base', region: '伊拉克', status: 'attacked', damage_level: 3 },
|
||||
{ name: '乌代德空军基地', lat: 25.117, lng: 51.314, type: 'Base', region: '卡塔尔', status: 'attacked', damage_level: 3 },
|
||||
{ name: '埃尔比勒空军基地', lat: 36.237, lng: 43.963, type: 'Base', region: '伊拉克', status: 'attacked', damage_level: 3 },
|
||||
{ name: '因吉尔利克空军基地', lat: 37.002, lng: 35.425, type: 'Base', region: '土耳其', status: 'attacked', damage_level: 3 },
|
||||
{ name: '苏尔坦亲王空军基地', lat: 24.062, lng: 47.58, type: 'Base', region: '沙特', status: 'attacked', damage_level: 3 },
|
||||
{ name: '塔吉军营', lat: 33.556, lng: 44.256, type: 'Base', region: '伊拉克', status: 'attacked', damage_level: 2 },
|
||||
{ name: '阿因·阿萨德', lat: 33.8, lng: 42.45, type: 'Base', region: '伊拉克', status: 'attacked', damage_level: 2 },
|
||||
{ name: '坦夫驻军', lat: 33.49, lng: 38.618, type: 'Base', region: '叙利亚', status: 'attacked', damage_level: 2 },
|
||||
{ name: '沙达迪基地', lat: 36.058, lng: 40.73, type: 'Base', region: '叙利亚', status: 'attacked', damage_level: 2 },
|
||||
{ name: '康诺克气田基地', lat: 35.336, lng: 40.295, type: 'Base', region: '叙利亚', status: 'attacked', damage_level: 2 },
|
||||
{ name: '尔梅兰着陆区', lat: 37.015, lng: 41.885, type: 'Base', region: '叙利亚', status: 'attacked', damage_level: 2 },
|
||||
{ name: '阿里夫坚军营', lat: 28.832, lng: 47.799, type: 'Base', region: '科威特', status: 'attacked', damage_level: 2 },
|
||||
{ name: '阿里·萨勒姆空军基地', lat: 29.346, lng: 47.52, type: 'Base', region: '科威特', status: 'attacked', damage_level: 2 },
|
||||
{ name: '巴林海军支援站', lat: 26.236, lng: 50.608, type: 'Base', region: '巴林', status: 'attacked', damage_level: 2 },
|
||||
{ name: '达夫拉空军基地', lat: 24.248, lng: 54.547, type: 'Base', region: '阿联酋', status: 'attacked', damage_level: 2 },
|
||||
{ name: '埃斯康村', lat: 24.774, lng: 46.738, type: 'Base', region: '沙特', status: 'attacked', damage_level: 2 },
|
||||
{ name: '内瓦提姆空军基地', lat: 31.208, lng: 35.012, type: 'Base', region: '以色列', status: 'attacked', damage_level: 2 },
|
||||
{ name: '布林军营', lat: 29.603, lng: 47.456, type: 'Base', region: '科威特', status: 'attacked', damage_level: 1 },
|
||||
{ name: '赛利耶军营', lat: 25.275, lng: 51.52, type: 'Base', region: '卡塔尔', status: 'attacked', damage_level: 1 },
|
||||
{ name: '拉蒙空军基地', lat: 30.776, lng: 34.666, type: 'Base', region: '以色列', status: 'attacked', damage_level: 1 },
|
||||
{ name: '穆瓦法克·萨尔蒂空军基地', lat: 32.356, lng: 36.259, type: 'Base', region: '约旦', status: 'attacked', damage_level: 1 },
|
||||
{ name: '屈雷吉克雷达站', lat: 38.354, lng: 37.794, type: 'Base', region: '土耳其', status: 'attacked', damage_level: 1 },
|
||||
{ name: '苏姆莱特空军基地', lat: 17.666, lng: 54.024, type: 'Base', region: '阿曼', status: 'attacked', damage_level: 1 },
|
||||
{ name: '马西拉空军基地', lat: 20.675, lng: 58.89, type: 'Base', region: '阿曼', status: 'attacked', damage_level: 1 },
|
||||
{ name: '西开罗空军基地', lat: 30.915, lng: 30.298, type: 'Base', region: '埃及', status: 'attacked', damage_level: 1 },
|
||||
{ name: '勒莫尼耶军营', lat: 11.547, lng: 43.159, type: 'Base', region: '吉布提', status: 'attacked', damage_level: 1 },
|
||||
]
|
||||
const newBases = [
|
||||
{ name: '多哈后勤中心', lat: 25.29, lng: 51.53, type: 'Base', region: '卡塔尔', status: 'operational', damage_level: null },
|
||||
{ name: '贾法勒海军站', lat: 26.22, lng: 50.62, type: 'Base', region: '巴林', status: 'operational', damage_level: null },
|
||||
{ name: '阿兹祖尔前方作战点', lat: 29.45, lng: 47.9, type: 'Base', region: '科威特', status: 'operational', damage_level: null },
|
||||
{ name: '艾哈迈迪后勤枢纽', lat: 29.08, lng: 48.09, type: 'Base', region: '科威特', status: 'operational', damage_level: null },
|
||||
{ name: '富查伊拉港站', lat: 25.13, lng: 56.35, type: 'Base', region: '阿联酋', status: 'operational', damage_level: null },
|
||||
{ name: '哈伊马角前方点', lat: 25.79, lng: 55.94, type: 'Base', region: '阿联酋', status: 'operational', damage_level: null },
|
||||
{ name: '利雅得联络站', lat: 24.71, lng: 46.68, type: 'Base', region: '沙特', status: 'operational', damage_level: null },
|
||||
{ name: '朱拜勒港支援点', lat: 27.0, lng: 49.65, type: 'Base', region: '沙特', status: 'operational', damage_level: null },
|
||||
{ name: '塔布克空军前哨', lat: 28.38, lng: 36.6, type: 'Base', region: '沙特', status: 'operational', damage_level: null },
|
||||
{ name: '拜莱德空军基地', lat: 33.94, lng: 44.36, type: 'Base', region: '伊拉克', status: 'operational', damage_level: null },
|
||||
{ name: '巴士拉后勤站', lat: 30.5, lng: 47.78, type: 'Base', region: '伊拉克', status: 'operational', damage_level: null },
|
||||
{ name: '基尔库克前哨', lat: 35.47, lng: 44.35, type: 'Base', region: '伊拉克', status: 'operational', damage_level: null },
|
||||
{ name: '摩苏尔支援点', lat: 36.34, lng: 43.14, type: 'Base', region: '伊拉克', status: 'operational', damage_level: null },
|
||||
{ name: '哈塞克联络站', lat: 36.5, lng: 40.75, type: 'Base', region: '叙利亚', status: 'operational', damage_level: null },
|
||||
{ name: '代尔祖尔前哨', lat: 35.33, lng: 40.14, type: 'Base', region: '叙利亚', status: 'operational', damage_level: null },
|
||||
{ name: '安曼协调中心', lat: 31.95, lng: 35.93, type: 'Base', region: '约旦', status: 'operational', damage_level: null },
|
||||
{ name: '伊兹密尔支援站', lat: 38.42, lng: 27.14, type: 'Base', region: '土耳其', status: 'operational', damage_level: null },
|
||||
{ name: '哈泽瑞姆空军基地', lat: 31.07, lng: 34.84, type: 'Base', region: '以色列', status: 'operational', damage_level: null },
|
||||
{ name: '杜古姆港站', lat: 19.66, lng: 57.76, type: 'Base', region: '阿曼', status: 'operational', damage_level: null },
|
||||
{ name: '塞拉莱前方点', lat: 17.01, lng: 54.1, type: 'Base', region: '阿曼', status: 'operational', damage_level: null },
|
||||
{ name: '亚历山大港联络站', lat: 31.2, lng: 29.9, type: 'Base', region: '埃及', status: 'operational', damage_level: null },
|
||||
{ name: '卢克索前哨', lat: 25.69, lng: 32.64, type: 'Base', region: '埃及', status: 'operational', damage_level: null },
|
||||
{ name: '吉布提港支援点', lat: 11.59, lng: 43.15, type: 'Base', region: '吉布提', status: 'operational', damage_level: null },
|
||||
{ name: '卡塔尔应急医疗站', lat: 25.22, lng: 51.45, type: 'Base', region: '卡塔尔', status: 'operational', damage_level: null },
|
||||
{ name: '沙特哈立德国王基地', lat: 24.96, lng: 46.7, type: 'Base', region: '沙特', status: 'operational', damage_level: null },
|
||||
{ name: '伊拉克巴拉德联勤站', lat: 33.75, lng: 44.25, type: 'Base', region: '伊拉克', status: 'operational', damage_level: null },
|
||||
{ name: '叙利亚奥马尔油田站', lat: 36.22, lng: 40.45, type: 'Base', region: '叙利亚', status: 'operational', damage_level: null },
|
||||
{ name: '约旦侯赛因国王基地', lat: 31.72, lng: 36.01, type: 'Base', region: '约旦', status: 'operational', damage_level: null },
|
||||
{ name: '土耳其巴特曼站', lat: 37.88, lng: 41.13, type: 'Base', region: '土耳其', status: 'operational', damage_level: null },
|
||||
{ name: '以色列帕尔马欣站', lat: 31.9, lng: 34.95, type: 'Base', region: '以色列', status: 'operational', damage_level: null },
|
||||
{ name: '阿曼杜古姆扩建点', lat: 19.55, lng: 57.8, type: 'Base', region: '阿曼', status: 'operational', damage_level: null },
|
||||
{ name: '埃及纳特龙湖站', lat: 30.37, lng: 30.2, type: 'Base', region: '埃及', status: 'operational', damage_level: null },
|
||||
{ name: '吉布提查贝尔达站', lat: 11.73, lng: 42.9, type: 'Base', region: '吉布提', status: 'operational', damage_level: null },
|
||||
{ name: '阿联酋迪拜港联络', lat: 25.27, lng: 55.3, type: 'Base', region: '阿联酋', status: 'operational', damage_level: null },
|
||||
{ name: '伊拉克尼尼微前哨', lat: 36.22, lng: 43.1, type: 'Base', region: '伊拉克', status: 'operational', damage_level: null },
|
||||
]
|
||||
return [...naval, ...attacked, ...newBases]
|
||||
}
|
||||
|
||||
function seed() {
|
||||
db.exec(`
|
||||
INSERT OR REPLACE INTO force_summary (side, total_assets, personnel, naval_ships, aircraft, ground_units, uav, missile_consumed, missile_stock) VALUES
|
||||
('us', 1245, 185000, 292, 1862, 18, 418, 1056, 2840),
|
||||
('iran', 7850, 2350000, 4250, 8200, 350, 750, 3720, 13800);
|
||||
`)
|
||||
|
||||
db.exec(`
|
||||
INSERT OR REPLACE INTO power_index (side, overall, military_strength, economic_power, geopolitical_influence) VALUES
|
||||
('us', 94, 96, 98, 97),
|
||||
('iran', 42, 58, 28, 35);
|
||||
`)
|
||||
|
||||
const insertAsset = db.prepare(`
|
||||
INSERT OR REPLACE INTO force_asset (id, side, name, type, count, status, lat, lng) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`)
|
||||
const usAssets = [
|
||||
['us-1', 'us', '双航母打击群 (CVN-72 & CVN-78)', '航母', 2, 'active', null, null],
|
||||
['us-2', 'us', '阿利·伯克级驱逐舰', '驱逐舰', 4, 'active', null, null],
|
||||
['us-3', 'us', 'F/A-18 中队', '战机', 48, 'active', null, null],
|
||||
['us-4', 'us', 'F-35 中队', '战机', 48, 'active', null, null],
|
||||
['us-5', 'us', 'F-22 猛禽', '战机', 12, 'active', null, null],
|
||||
['us-6', 'us', 'B-2 幽灵', '轰炸机', 2, 'alert', null, null],
|
||||
['us-7', 'us', '爱国者防空系统', '防空', 3, 'active', null, null],
|
||||
['us-8', 'us', 'MQ-9 死神', '无人机', 28, 'active', null, null],
|
||||
['us-9', 'us', 'MQ-1C 灰鹰', '无人机', 45, 'active', null, null],
|
||||
]
|
||||
const iranAssets = [
|
||||
['ir-1', 'iran', '护卫舰', '水面舰艇', 6, 'active', null, null],
|
||||
['ir-2', 'iran', '快攻艇', '海军', 100, 'active', null, null],
|
||||
['ir-3', 'iran', 'F-4 Phantom', '战机', 62, 'standby', null, null],
|
||||
['ir-4', 'iran', 'F-14 Tomcat', '战机', 24, 'active', null, null],
|
||||
['ir-5', 'iran', '弹道导弹', '导弹', 3400, 'alert', null, null],
|
||||
['ir-6', 'iran', '伊斯兰革命卫队海军', '准军事', 25000, 'active', null, null],
|
||||
['ir-7', 'iran', '沙希德-136', '无人机', 750, 'alert', null, null],
|
||||
['ir-8', 'iran', '法塔赫 (Fattah)', '导弹', 12, 'alert', null, null],
|
||||
['ir-9', 'iran', '穆哈杰-6', '无人机', 280, 'active', null, null],
|
||||
]
|
||||
;[...usAssets, ...iranAssets].forEach((row) => insertAsset.run(...row))
|
||||
|
||||
const insertLoc = db.prepare(`
|
||||
INSERT INTO key_location (side, name, lat, lng, type, region, status, damage_level) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`)
|
||||
db.exec('DELETE FROM key_location')
|
||||
|
||||
for (const loc of getUsLocations()) {
|
||||
insertLoc.run('us', loc.name, loc.lat, loc.lng, loc.type, loc.region, loc.status, loc.damage_level)
|
||||
}
|
||||
const iranLocs = [
|
||||
['iran', '阿巴斯港', 27.1832, 56.2666, 'Port', '伊朗', null, null],
|
||||
['iran', '德黑兰', 35.6892, 51.389, 'Capital', '伊朗', null, null],
|
||||
['iran', '布什尔', 28.9681, 50.838, 'Base', '伊朗', null, null],
|
||||
]
|
||||
iranLocs.forEach((r) => insertLoc.run(...r))
|
||||
|
||||
db.exec(`
|
||||
INSERT OR REPLACE INTO combat_losses (side, bases_destroyed, bases_damaged, personnel_killed, personnel_wounded, aircraft, warships, armor, vehicles) VALUES
|
||||
('us', 0, 27, 127, 384, 2, 0, 0, 8),
|
||||
('iran', 3, 8, 2847, 5620, 24, 12, 18, 42);
|
||||
`)
|
||||
|
||||
db.exec('DELETE FROM wall_street_trend')
|
||||
const trendRows = [['2025-03-01T00:00:00', 82], ['2025-03-01T03:00:00', 85], ['2025-03-01T06:00:00', 88], ['2025-03-01T09:00:00', 90], ['2025-03-01T12:00:00', 92], ['2025-03-01T15:00:00', 94], ['2025-03-01T18:00:00', 95], ['2025-03-01T21:00:00', 96], ['2025-03-01T23:00:00', 98]]
|
||||
const insertTrend = db.prepare('INSERT INTO wall_street_trend (time, value) VALUES (?, ?)')
|
||||
trendRows.forEach(([t, v]) => insertTrend.run(t, v))
|
||||
|
||||
db.exec('INSERT OR REPLACE INTO retaliation_current (id, value) VALUES (1, 78)')
|
||||
db.exec('DELETE FROM retaliation_history')
|
||||
const retRows = [['2025-03-01T00:00:00', 42], ['2025-03-01T03:00:00', 48], ['2025-03-01T06:00:00', 55], ['2025-03-01T09:00:00', 61], ['2025-03-01T12:00:00', 58], ['2025-03-01T15:00:00', 65], ['2025-03-01T18:00:00', 72], ['2025-03-01T21:00:00', 76], ['2025-03-01T23:00:00', 78]]
|
||||
const insertRet = db.prepare('INSERT INTO retaliation_history (time, value) VALUES (?, ?)')
|
||||
retRows.forEach(([t, v]) => insertRet.run(t, v))
|
||||
|
||||
db.exec('DELETE FROM situation_update')
|
||||
const updateRows = [
|
||||
['u1', new Date(Date.now() - 3600000).toISOString(), 'deployment', '美军航母打击群在阿拉伯海重新部署', 'medium'],
|
||||
['u2', new Date(Date.now() - 7200000).toISOString(), 'alert', '霍尔木兹海峡海军巡逻活动加强', 'high'],
|
||||
['u3', new Date(Date.now() - 10800000).toISOString(), 'intel', '卫星图像显示阿巴斯港活动增加', 'low'],
|
||||
['u4', new Date(Date.now() - 14400000).toISOString(), 'diplomatic', '阿曼间接谈判进行中', 'low'],
|
||||
]
|
||||
const insertUpdate = db.prepare('INSERT INTO situation_update (id, timestamp, category, summary, severity) VALUES (?, ?, ?, ?, ?)')
|
||||
updateRows.forEach((row) => insertUpdate.run(...row))
|
||||
|
||||
db.prepare("INSERT OR REPLACE INTO situation (id, data, updated_at) VALUES (1, '{}', ?)").run('2026-03-01T11:45:00.000Z')
|
||||
console.log('Seed completed.')
|
||||
}
|
||||
|
||||
seed()
|
||||
108
server/situationData.js
Normal file
108
server/situationData.js
Normal file
@@ -0,0 +1,108 @@
|
||||
const db = require('./db')
|
||||
|
||||
function toAsset(row) {
|
||||
return {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
type: row.type,
|
||||
count: row.count,
|
||||
status: row.status,
|
||||
...(row.lat != null && { location: { lat: row.lat, lng: row.lng } }),
|
||||
}
|
||||
}
|
||||
|
||||
function toLosses(row) {
|
||||
return {
|
||||
bases: { destroyed: row.bases_destroyed, damaged: row.bases_damaged },
|
||||
personnelCasualties: { killed: row.personnel_killed, wounded: row.personnel_wounded },
|
||||
aircraft: row.aircraft,
|
||||
warships: row.warships,
|
||||
armor: row.armor,
|
||||
vehicles: row.vehicles,
|
||||
}
|
||||
}
|
||||
|
||||
const defaultLosses = {
|
||||
bases: { destroyed: 0, damaged: 0 },
|
||||
personnelCasualties: { killed: 0, wounded: 0 },
|
||||
aircraft: 0,
|
||||
warships: 0,
|
||||
armor: 0,
|
||||
vehicles: 0,
|
||||
}
|
||||
|
||||
function getSituation() {
|
||||
const summaryUs = db.prepare('SELECT * FROM force_summary WHERE side = ?').get('us')
|
||||
const summaryIr = db.prepare('SELECT * FROM force_summary WHERE side = ?').get('iran')
|
||||
const powerUs = db.prepare('SELECT * FROM power_index WHERE side = ?').get('us')
|
||||
const powerIr = db.prepare('SELECT * FROM power_index WHERE side = ?').get('iran')
|
||||
const assetsUs = db.prepare('SELECT * FROM force_asset WHERE side = ? ORDER BY id').all('us')
|
||||
const assetsIr = db.prepare('SELECT * FROM force_asset WHERE side = ? ORDER BY id').all('iran')
|
||||
const locUs = db.prepare('SELECT id, name, lat, lng, type, region, status, damage_level FROM key_location WHERE side = ?').all('us')
|
||||
const locIr = db.prepare('SELECT id, name, lat, lng, type, region FROM key_location WHERE side = ?').all('iran')
|
||||
const lossesUs = db.prepare('SELECT * FROM combat_losses WHERE side = ?').get('us')
|
||||
const lossesIr = db.prepare('SELECT * FROM combat_losses WHERE side = ?').get('iran')
|
||||
const trend = db.prepare('SELECT time, value FROM wall_street_trend ORDER BY time').all()
|
||||
const retaliationCur = db.prepare('SELECT value FROM retaliation_current WHERE id = 1').get()
|
||||
const retaliationHist = db.prepare('SELECT time, value FROM retaliation_history ORDER BY time').all()
|
||||
const updates = db.prepare('SELECT * FROM situation_update ORDER BY timestamp DESC').all()
|
||||
const meta = db.prepare('SELECT updated_at FROM situation WHERE id = 1').get()
|
||||
|
||||
return {
|
||||
lastUpdated: meta?.updated_at || new Date().toISOString(),
|
||||
usForces: {
|
||||
summary: {
|
||||
totalAssets: summaryUs?.total_assets ?? 0,
|
||||
personnel: summaryUs?.personnel ?? 0,
|
||||
navalShips: summaryUs?.naval_ships ?? 0,
|
||||
aircraft: summaryUs?.aircraft ?? 0,
|
||||
groundUnits: summaryUs?.ground_units ?? 0,
|
||||
uav: summaryUs?.uav ?? 0,
|
||||
missileConsumed: summaryUs?.missile_consumed ?? 0,
|
||||
missileStock: summaryUs?.missile_stock ?? 0,
|
||||
},
|
||||
powerIndex: {
|
||||
overall: powerUs?.overall ?? 0,
|
||||
militaryStrength: powerUs?.military_strength ?? 0,
|
||||
economicPower: powerUs?.economic_power ?? 0,
|
||||
geopoliticalInfluence: powerUs?.geopolitical_influence ?? 0,
|
||||
},
|
||||
assets: (assetsUs || []).map(toAsset),
|
||||
keyLocations: locUs || [],
|
||||
combatLosses: lossesUs ? toLosses(lossesUs) : defaultLosses,
|
||||
wallStreetInvestmentTrend: trend || [],
|
||||
},
|
||||
iranForces: {
|
||||
summary: {
|
||||
totalAssets: summaryIr?.total_assets ?? 0,
|
||||
personnel: summaryIr?.personnel ?? 0,
|
||||
navalShips: summaryIr?.naval_ships ?? 0,
|
||||
aircraft: summaryIr?.aircraft ?? 0,
|
||||
groundUnits: summaryIr?.ground_units ?? 0,
|
||||
uav: summaryIr?.uav ?? 0,
|
||||
missileConsumed: summaryIr?.missile_consumed ?? 0,
|
||||
missileStock: summaryIr?.missile_stock ?? 0,
|
||||
},
|
||||
powerIndex: {
|
||||
overall: powerIr?.overall ?? 0,
|
||||
militaryStrength: powerIr?.military_strength ?? 0,
|
||||
economicPower: powerIr?.economic_power ?? 0,
|
||||
geopoliticalInfluence: powerIr?.geopolitical_influence ?? 0,
|
||||
},
|
||||
assets: (assetsIr || []).map(toAsset),
|
||||
keyLocations: locIr || [],
|
||||
combatLosses: lossesIr ? toLosses(lossesIr) : defaultLosses,
|
||||
retaliationSentiment: retaliationCur?.value ?? 0,
|
||||
retaliationSentimentHistory: retaliationHist || [],
|
||||
},
|
||||
recentUpdates: (updates || []).map((u) => ({
|
||||
id: u.id,
|
||||
timestamp: u.timestamp,
|
||||
category: u.category,
|
||||
summary: u.summary,
|
||||
severity: u.severity,
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { getSituation }
|
||||
Reference in New Issue
Block a user