{"id":50412268,"url":"https://github.com/s045pd/wargame-replay","last_synced_at":"2026-05-31T04:04:15.176Z","repository":{"id":348731527,"uuid":"1197481116","full_name":"s045pd/wargame-replay","owner":"s045pd","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-30T17:01:03.000Z","size":96617,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-30T18:14:07.613Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/s045pd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-31T16:04:13.000Z","updated_at":"2026-04-13T07:46:18.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/s045pd/wargame-replay","commit_stats":null,"previous_names":["s045pd/wargame-replay"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/s045pd/wargame-replay","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s045pd%2Fwargame-replay","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s045pd%2Fwargame-replay/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s045pd%2Fwargame-replay/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s045pd%2Fwargame-replay/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/s045pd","download_url":"https://codeload.github.com/s045pd/wargame-replay/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s045pd%2Fwargame-replay/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33718484,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-31T02:00:06.040Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-31T04:04:14.461Z","updated_at":"2026-05-31T04:04:15.171Z","avatar_url":"https://github.com/s045pd.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MilSim Replay\n\n[![CI](https://img.shields.io/github/actions/workflow/status/s045pd/wargame-replay/ci.yml?branch=main\u0026label=CI\u0026style=flat-square)](https://github.com/s045pd/wargame-replay/actions/workflows/ci.yml)\n[![Release](https://img.shields.io/github/v/release/s045pd/wargame-replay?style=flat-square)](https://github.com/s045pd/wargame-replay/releases)\n[![Go](https://img.shields.io/badge/Go-1.25-00ADD8?style=flat-square\u0026logo=go)](https://go.dev)\n[![React](https://img.shields.io/badge/React-19-61DAFB?style=flat-square\u0026logo=react)](https://react.dev)\n[![License](https://img.shields.io/github/license/s045pd/wargame-replay?style=flat-square)](LICENSE)\n\nMilSim 对局回放系统 — 将 `.db` 对局数据库文件可视化为交互式战场回放。\n\n单文件可执行程序，内嵌前端，开箱即用。\n\n**[在线体验 (Lite 版)](https://s045pd.github.io/wargame-replay/)** — 无需安装，浏览器直接打开 `.db` 文件回放\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"media/demo.gif\" alt=\"MilSim Replay Demo\" width=\"800\"\u003e\n\u003c/p\u003e\n\n## 功能特性\n\n### 核心功能\n\n- **交互式战场地图** — 基于 MapLibre GL 的实时单位渲染、移动轨迹、HP 系统\n- **热点检测引擎** — 自动识别交火、连杀、大规模伤亡、远距离击杀、轰炸等战场关键事件\n- **导播模式** — AI 辅助镜头切换，多预览窗格，自动追踪热点事件，聚焦模式（地图压暗 + 减速）\n- **时间轴与回放** — 多轨时间轴、1x–128x 变速播放、热点事件标记、沉浸模式\n- **书签与片段** — 标记关键时刻、创建/编辑片段、视频录制导出、热点自动建议\n- **89 项可配置参数** — 8 页设置面板，覆盖颜色、动画、镜头、弹道、导播等，支持 JSON 导入/导出/重置\n\n### 地图与图层\n\n- **6 种地图源** — 卫星 (ESRI)、暗色 (CARTO)、地形 (CARTO)、亮色 (CARTO)、OSM、等高线 (OpenTopo)；可选 Mapbox 高清升级\n- **单位图层** — 步枪、机枪、狙击、医疗兵等 5 种兵种 Canvas 图标，存活/阵亡状态\n- **轨迹图层** — 单位移动历史轨迹\n- **热点图层** — 战斗热点圆圈 + 标签 + 实时活动指示环\n- **POI 图层** — 基地、补给点、控制点等战场设施\n- **基地图层** — 红蓝双方基地标记\n- **轰炸图层** — 轰炸事件可视化（含爆炸半径）\n- **狙击弹道图层** — 远距离击杀弹道线（可配速度、宽度、拖尾、发光）\n- **栅格图层** — 战区坐标网格（R→A 列，1→15 行）\n- **击杀排行榜** — 实时击杀/阵亡排行\n- **事件 Toast** — 击杀、复活、治疗等事件即时弹窗通知\n\n### 其他特性\n\n- **文件上传** — Web 界面直接拖拽上传 `.db` 对局文件\n- **双坐标系** — 支持 WGS84 (GPS) 和相对坐标，自动检测\n- **中英双语** — 界面支持中文 / English 切换\n- **单文件部署** — Go 编译为单个可执行文件，内嵌全部前端资源\n- **自动打开浏览器** — 启动后自动打开 Chrome --app 模式（无地址栏），支持 `-open` / `-app` 参数\n- **玩家搜索** — 按名称搜索并跟踪指定单位\n- **视频录制** — 录制回放为 WebM 视频文件，支持片段导出\n- **免费瓦片缩放保护** — 使用免费地图源时自动限制最大缩放级别，防止 \"Map data not yet available\"\n\n## 快速开始\n\n### 使用预编译版本\n\n从 [Releases](https://github.com/s045pd/wargame-replay/releases) 下载对应平台的压缩包：\n\n| 平台 | 文件 |\n|------|------|\n| Windows x64 | `wargame-replay-windows-amd64.zip` |\n| Windows ARM64 | `wargame-replay-windows-arm64.zip` |\n| macOS Intel | `wargame-replay-darwin-amd64.tar.gz` |\n| macOS Apple Silicon | `wargame-replay-darwin-arm64.tar.gz` |\n| Linux x64 | `wargame-replay-linux-amd64.tar.gz` |\n| Linux ARM64 | `wargame-replay-linux-arm64.tar.gz` |\n\n**macOS** — 解压后双击 `MilSim Replay.app`，自动启动服务并打开浏览器。数据默认存放在 `~/MilSimReplay/`。\n\n\u003e ⚠️ 首次打开 macOS 可能提示\"无法验证开发者\"，请：\n\u003e - 右键点击 → 打开（推荐），或\n\u003e - 终端运行：`xattr -cr MilSim\\ Replay.app`\n\n**Windows / Linux** — 解压后命令行启动：\n\n```bash\n./wargame-replay -dir ./data\n\n# 浏览器打开 http://127.0.0.1:8080\n```\n\n也可以启动后通过 Web 界面直接拖拽上传 `.db` 文件。\n\n\u003e macOS 压缩包同时包含 `.app` 和裸二进制文件 `wargame-replay`，命令行用户可直接使用后者。\n\n### 命令行参数\n\n```\nUsage:\n  wargame-replay [flags]\n\nFlags:\n  -dir string    包含 .db 文件的目录 (默认 \".\")\n  -host string   监听地址 (默认 \"127.0.0.1\")\n  -port int      监听端口 (默认 8080)\n  -open          自动打开浏览器 (默认 true，-open=false 禁用)\n  -app           优先使用 Chrome/Edge --app 模式 (默认 true，无地址栏)\n```\n\n### 数据库文件命名\n\n`.db` 文件需遵循以下命名格式：\n\n```\n{场次}_{开始时间}_{结束时间}.db\n```\n\n示例：`69_2026-03-28-12-15-00_2026-03-28-18-00-00.db`\n\n可选的 `.txt` 元数据文件与 `.db` 同名，包含地图坐标校准和栅格信息。\n\n## 从源码构建\n\n### 前置依赖\n\n- [Go](https://go.dev/dl/) \u003e= 1.25（需要 CGO 支持，SQLite 驱动要求）\n- [Node.js](https://nodejs.org/) \u003e= 20\n- C 编译器（macOS: Xcode CLT, Linux: gcc, Windows: mingw-w64）\n\n### 一键构建\n\n```bash\nmake build\n```\n\n生成的 `wargame-replay` 即为包含前端的完整可执行文件。\n\n### 分步构建\n\n```bash\n# 1. 构建前端\ncd web \u0026\u0026 npm ci \u0026\u0026 npm run build \u0026\u0026 cd ..\n\n# 2. 复制到 Go embed 目录\nrm -rf server/static \u0026\u0026 cp -r web/dist server/static\n\n# 3. 编译 Go 二进制（需要 CGO）\ncd server \u0026\u0026 CGO_ENABLED=1 go build -trimpath \\\n  -ldflags=\"-s -w -X main.version=$(git describe --tags)\" \\\n  -o ../wargame-replay .\n```\n\n### 开发模式\n\n需要两个终端：\n\n```bash\n# 终端 1: Go 后端（热重载需手动重启）\ncd server \u0026\u0026 go run . -dir /path/to/db/files -port 8081\n\n# 终端 2: Vite 前端开发服务器（自动热更新）\ncd web \u0026\u0026 npm run dev\n```\n\n前端开发服务器会自动代理 `/api` 和 `/ws` 请求到后端（端口 8081）。\n\n## 项目结构\n\n```\nwargame-replay/\n├── Makefile                  # 构建脚本\n├── .github/workflows/\n│   ├── ci.yml                # CI: lint + test + smoke build\n│   └── release.yml           # Release: 6 平台交叉编译 + GitHub Release\n├── assets/                   # 应用图标资源 (SVG, PNG, ICO)\n├── server/                   # Go 后端\n│   ├── main.go               # HTTP/WS 服务入口\n│   ├── embed.go              # 前端静态资源嵌入\n│   ├── api/                  # REST API (Gin)\n│   │   ├── games.go          # 游戏列表、元数据\n│   │   ├── frames.go         # 帧数据查询\n│   │   ├── upload.go         # 文件上传（原子写入）\n│   │   ├── bookmarks.go      # 书签 CRUD\n│   │   ├── clips.go          # 片段 CRUD \u0026 导出\n│   │   └── unitclasses.go    # 单位分类覆盖\n│   ├── decoder/              # .db 二进制协议解析\n│   ├── game/                 # 游戏服务层（帧组装、HP 校准）\n│   ├── hotspot/              # 热点检测引擎（聚类、分类、缓存）\n│   ├── scanner/              # 目录扫描器\n│   ├── index/                # 时间索引 \u0026 100MB LRU 缓存\n│   ├── ws/                   # WebSocket 实时帧推流\n│   └── winres/               # Windows 可执行文件资源（图标、清单）\n├── web/                      # React 前端\n│   └── src/\n│       ├── map/              # MapLibre GL 地图组件（15 个图层）\n│       ├── timeline/         # 时间轴 \u0026 播放控制\n│       ├── director/         # 导播模式面板\n│       ├── clips/            # 书签 \u0026 片段编辑器 \u0026 视频录制\n│       ├── store/            # Zustand 状态管理（5 个 store）\n│       ├── hooks/            # 自定义 Hooks（自动导播逻辑）\n│       ├── components/       # 通用 UI 组件（8 页设置面板、搜索、快捷键）\n│       └── lib/              # API 客户端、WebSocket、i18n、设置 API\n```\n\n详细代码结构参见 [ARCHITECTURE.md](ARCHITECTURE.md)。\n\n## API 接口\n\n| 方法 | 路径 | 说明 |\n|------|------|------|\n| `GET` | `/api/health` | 健康检查 + 版本号 |\n| `GET` | `/api/games` | 获取游戏列表 |\n| `GET` | `/api/games/:id/meta` | 获取游戏元数据（玩家、边界、栅格） |\n| `GET` | `/api/games/:id/frame/:ts` | 获取指定时间帧快照 |\n| `GET` | `/api/games/:id/hotspots` | 获取全部热点事件 |\n| `POST` | `/api/upload` | 上传 .db 文件（支持拖拽多文件） |\n| `DELETE` | `/api/games/:id` | 删除游戏及所有伴随文件 |\n| `GET` | `/api/games/:id/bookmarks` | 获取书签列表 |\n| `POST` | `/api/games/:id/bookmarks` | 创建书签 |\n| `DELETE` | `/api/games/:id/bookmarks/:idx` | 删除书签 |\n| `GET` | `/api/games/:id/bookmarks/suggest` | 热点自动建议书签 |\n| `GET` | `/api/games/:id/clips` | 获取片段列表 |\n| `POST` | `/api/games/:id/clips` | 创建片段 |\n| `PUT` | `/api/games/:id/clips/:idx` | 更新片段 |\n| `DELETE` | `/api/games/:id/clips/:idx` | 删除片段 |\n| `GET` | `/api/games/:id/clips/:idx/export` | 导出片段数据 |\n| `GET` | `/api/games/:id/unitclasses` | 获取单位分类 |\n| `PUT` | `/api/games/:id/unitclasses` | 保存单位分类 |\n| `WS` | `/ws/games/:id/stream` | 实时帧推流 |\n\n## 技术栈\n\n**后端**\n- Go 1.25 + Gin (HTTP) + Gorilla WebSocket\n- SQLite3 (CGO, `mattn/go-sqlite3`, 只读模式)\n- 内嵌静态文件 (`go:embed`)\n- go-winres (Windows 可执行文件图标/清单)\n\n**前端**\n- React 19 + TypeScript 5.8\n- MapLibre GL JS 5 (开源地图引擎)\n- Zustand 5 (状态管理)\n- Tailwind CSS 4\n- Lucide React (图标)\n- Vite 6 (构建工具)\n\n**CI/CD**\n- GitHub Actions\n- Zig CC 交叉编译 (Linux + Windows targets)\n- 6 平台矩阵构建 (Windows/macOS/Linux × x64/ARM64)\n- 自动 Release + SHA256 校验和\n\n## 键盘快捷键\n\n| 按键 | 功能 |\n|------|------|\n| `Space` | 播放 / 暂停 |\n| `H` | 切换沉浸模式（隐藏 UI） |\n| `Tab` | 切换回放 / 导播模式 |\n| `A` | 开关自动导播 |\n| `T` | 切换 3D 倾斜模式 |\n| `D` | 切换热点调试叠加层 |\n| `B` | 切换书签面板 |\n| `Shift+B` | 在当前时间添加书签 |\n| `C` | 切换片段编辑器 |\n| `,` | 打开设置面板 |\n| `?` | 显示快捷键帮助 |\n| `Esc` | 关闭弹窗 |\n\n## 版本发布\n\n```bash\n# 创建带注释的 tag 并推送，自动触发 GitHub Actions 构建 + 发布\nmake release V=v1.0.0\n```\n\n版本号注入到 Go 二进制 (`main.version`)，可通过 `/api/health` 查询。\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fs045pd%2Fwargame-replay","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fs045pd%2Fwargame-replay","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fs045pd%2Fwargame-replay/lists"}