这段代码是一个完整的军事模拟应用,使用Streamlit框架构建了一个智能作战推演系统。该系统包括了三维地图显示、作战单位管理、应急事件处理等功能。用户可以通过界面控制推演的开始和暂停,调整时间加速倍率,并查看实时的战斗情况和系统状态。
import streamlit as st
import pandas as pd
import numpy as np
import pydeck as pdk
from datetime import datetime, timedelta
import time
import threading
from PIL import Image
# 深度定制化配置
st.set_page_config(
page_title="智能作战推演系统-战术版",
layout="wide",
initial_sidebar_state="collapsed",
menu_items={
'Get Help': 'https://example.com',
'Report a bug': None,
'About': "战术推演系统 v3.2 [机密]"
}
)
# ----------------- 核心数据模型 -----------------
class TacticalUnit:
def __init__(self, name, unit_type, position):
self.name = name
self.unit_type = unit_type
self.position = position
self.status = "active"
self.last_update = datetime.now()
def update_position(self, new_pos):
self.position = [
self.position[0] + np.random.uniform(-0.02, 0.02),
self.position[1] + np.random.uniform(-0.02, 0.02)
]
self.last_update = datetime.now()
class EmergencyEvent:
EVENT_TYPES = ['火灾', '设备故障', '群众报警', '线路抢修']
def __init__(self):
self.event_id = f"EVENT-{int(time.time())}"
self.event_type = np.choice(self.EVENT_TYPES)
self.location = [116.3975 + np.random.uniform(-0.1, 0.1),
39.9085 + np.random.uniform(-0.1, 0.1)]
self.status = "处置中"
self.timestamp = datetime.now()
# ----------------- 全局状态初始化 -----------------
def init_session_state():
required_states = {
'sim_running': False,
'speed_ratio': 100,
'tactical_units': {
'红方': [TacticalUnit(f"Fighter{i + 1}", "歼-20", [116.3 + i * 0.02, 39.9]) for i in range(6)],
'蓝方': [TacticalUnit(f"Striker{i + 1}", "F-35", [116.5 + i * 0.02, 39.8]) for i in range(6)]
},
'emergency_events': [],
'communication_status': {
'ghost_attack': False,
'last_incident': None
},
'system_status': {
'radar_angle': 45,
'missile_status': "待发",
'3d_mode': True
}
}
for key, val in required_states.items():
if key not in st.session_state:
st.session_state[key] = val
# ----------------- 三维可视化引擎 -----------------
def render_combat_map():
unit_data = []
# 生成红蓝双方单位数据
for side in ['红方', '蓝方']:
for unit in st.session_state.tactical_units[side]:
unit_data.append({
"position": unit.position,
"name": unit.name,
"color": [255, 0, 0] if side == '红方' else [0, 0, 255]
})
# 核心图层配置
layers = [
pdk.Layer(
"ScatterplotLayer",
id="combat-units",
data=unit_data,
get_position="position",
get_fill_color="color",
get_radius=500,
pickable=True,
opacity=0.8,
stroked=True
),
pdk.Layer(
"TextLayer",
id="unit-labels",
data=unit_data,
get_position="position",
get_text="name",
get_color=[255, 255, 255],
get_size=16,
get_angle=0,
font_settings={"fontFamily": "Arial Black"}
)
]
# 应急事件图层
if st.session_state.emergency_events:
emergency_layer = pdk.Layer(
"HeatmapLayer",
data=[e.location for e in st.session_state.emergency_events],
get_position="[lon, lat]",
radius=10000,
threshold=0.85,
intensity=0.7,
color_range=[
[255, 255, 0, 150],
[255, 165, 0, 200],
[255, 0, 0, 255]
]
)
layers.append(emergency_layer)
return pdk.Deck(
layers=layers,
initial_view_state=pdk.ViewState(
latitude=39.9,
longitude=116.4,
zoom=9,
pitch=60,
bearing=0
),
tooltip={"html": "<b>作战单位:</b> {name}"},
map_style='mapbox://styles/mapbox/dark-v10'
)
# ----------------- 界面组件 -----------------
def left_control_panel():
with st.container():
st.header("🛡️ 作战序列")
for side in ['红方', '蓝方']:
with st.expander(f"**{side} 作战单位**", expanded=True):
df = pd.DataFrame([
{
"名称": unit.name,
"类型": unit.unit_type,
"状态": unit.status,
"最后更新": unit.last_update.strftime("%H:%M:%S")
} for unit in st.session_state.tactical_units[side]
])
st.dataframe(
df,
use_container_width=True,
hide_index=True,
column_config={
"最后更新": st.column_config.DatetimeColumn(format="HH:mm:ss")
}
)
def right_status_panel():
with st.container():
# 战术时钟
st.markdown(f"""
<div class="tactical-clock">
<span>作战时间:</span>
<span class="time-digital">
{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
</span>
</div>
""", unsafe_allow_html=True)
# 应急响应
st.subheader("🚨 实时警情", divider="grey")
if st.session_state.emergency_events:
event = st.session_state.emergency_events[-1]
cols = st.columns([1, 3])
cols[0].image(Image.open("alert_icon.png"), width=60)
cols[1].markdown(f"""
**{event.event_type}** 事件\n
🔥 等级:{np.random.randint(1, 5)}级\n
📍 坐标:{event.location[0]:.4f}, {event.location[1]:.4f}
""")
# 通信状态
st.subheader("📶 战场通信", divider="grey")
comm_status = st.session_state.communication_status
if comm_status['ghost_attack']:
cols = st.columns([1, 4])
cols[0].image(Image.open("ghost_icon.png"), width=40)
cols[1].error("**Ghost协议攻击检测中!**")
else:
st.success("量子信道加密正常")
# 系统参数
st.subheader("⚙️ 战术参数", divider="grey")
sys = st.session_state.system_status
st.metric("雷达扫描角度", f"{sys['radar_angle']}°")
st.metric("导弹发射状态", sys['missile_status'])
st.toggle("3D战术视图", value=sys['3d_mode'])
# ----------------- 主界面布局 -----------------
def main_interface():
st.title("智能作战推演系统")
# 顶部控制栏
with st.container(height=60):
cols = st.columns([2, 3, 2, 2])
selected_scenario = cols[0].selectbox("推演剧本", ["红蓝对抗", "城市防空", "海上拦截"])
speed_ratio = cols[1].slider("时间加速", 1, 1000, 100)
sim_button = cols[2].button("▶️ 启动推演" if not st.session_state.sim_running else "⏸️ 暂停推演")
current_time = cols[3].metric("系统时间", datetime.now().strftime("%H:%M:%S"))
if sim_button:
st.session_state.sim_running = not st.session_state.sim_running
st.session_state.speed_ratio = speed_ratio
# 主战场布局
col1, col2, col3 = st.columns([2.5, 6, 2.5])
with col1:
left_control_panel()
with col2:
deck = render_combat_map()
st.pydeck_chart(deck)
# 更新单位位置
if st.session_state.sim_running:
for side in ['红方', '蓝方']:
for unit in st.session_state.tactical_units[side]:
unit.update_position(unit.position)
# 底部状态栏
with st.container(height=80):
cols = st.columns(4)
cols[0].metric("当前信道", "腾讯火山通道")
cols[1].progress(0.85, text="通信质量")
cols[2].code("Ghost防御协议: ACTIVE" if not st.session_state.communication_status[
'ghost_attack'] else "DEFENSE BREACHED!")
cols[3].button("🆘 应急响应协议")
with col3:
right_status_panel()
# ----------------- 样式定制 -----------------
st.markdown("""
<style>
.stApp {
background: #0a0a1a;
color: #e0e0ff;
}
.deckgl-wrapper {
border: 2px solid #303060 !important;
border-radius: 8px;
box-shadow: 0 0 15px #00ffff55;
}
.tactical-clock {
background: #000033;
padding: 12px;
border-left: 4px solid #00a8ff;
margin: 10px 0;
}
.time-digital {
font-family: 'Courier New', monospace;
color: #00ff00;
font-size: 1.3em;
text-shadow: 0 0 5px #00ff0077;
}
.st-emergency {
border: 1px solid #ff4444;
background: #ff000022;
padding: 10px;
border-radius: 5px;
}
</style>
""", unsafe_allow_html=True)
# ----------------- 初始化执行 -----------------
if __name__ == "__main__":
init_session_state()
main_interface()