Moveet:事件、录制与回放、icon rail UI,以及 500 多个测试
Source: Dev.to
What shipped
🚦 Fleet management
车辆现在可以被分组为 具名、颜色编码的车队。您可以创建车队、将车辆分配到车队中,界面会根据车队为路线和标记着色——这对于模拟多个运营商共享同一道路网络非常方便。
REST API
POST /fleets
GET /fleets
DELETE /fleets/:id
POST /fleets/:id/assign
POST /fleets/:id/unassignWebSocket events
fleet:createdfleet:deletedfleet:assigned
⚠️ Incidents and dynamic rerouting
在网络的任意位置投放道路事故。所有当前正通过受影响路段的车辆都会实时重新规划路径——A* 会从车辆的当前位置重新计算,绕过被封锁的边。
REST API
POST /incidents # create incident, triggers rerouting
GET /incidents # list active incidents
DELETE /incidents/:id # clear it, vehicles return to normal paths
POST /incidents/random # random incident for testingWebSocket event
vehicle:rerouted– 为每一辆被重新规划路径的车辆触发
事故标记会显示在地图上。
🎬 Session recording and replay
每个仿真会话都可以记录为带时间戳的 NDJSON 文件。文件格式为一行标题,随后每行一个事件(方向指派、车辆快照、事故等)。
REST API
POST /recording/start
POST /recording/stop
GET /recordingsReplay control API
POST /replay/start { "file": "path/to/recording.ndjson" }
POST /replay/pause
POST /replay/resume
POST /replay/stop
POST /replay/seek { "timestamp": 12000 }
POST /replay/speed { "speed": 2 }
GET /replay/status回放支持 1×、2×、4× 速度。UI 显示一个插值进度条,在服务器 tick 之间平滑前进,避免每 500 ms 的跳动。
🖥 UI redesign – icon rail + panel sidebar
旧的浮动覆盖层已被左侧边缘的 图标轨道 取代——一条垂直的图标按钮条,每个按钮切换一个面板。
| Icon | Panel |
|---|---|
| 🚗 | Vehicles – 列表、过滤、选择 |
| 🗂 | Fleets – 创建、分配、颜色 |
| ⚠️ | Incidents – 带徽章计数的活动列表 |
| ⏺ | Recordings – 开始/停止/浏览/回放 |
| 👁 | Visibility – 切换地图图层 |
| ⚡ | Speed – 仿真速度控制 |
| ⚙️ | Adapter – 热插拔源/汇插件 |
底部停靠栏保存实时仿真控制(播放/停止/重置/录制),在回放时会折叠为回放传输条。
所有面板组件均基于共享的原语集(PanelShell、PanelHeader、PanelSection)和统一的主题令牌集合构建,因而每个面板外观一致,无需为单个组件单独写样式。
✅ Test coverage – from 410 to 502 tests
仿真器的测试套件显著增长。新增文件如下:
| File | What it covers |
|---|---|
rateLimiter.test.ts | 窗口限制、429 响应、按 IP 追踪、清理间隔 |
helpers.test.ts | calculateBearing、interpolatePosition、calculateDistance、nonCircularRouteEdges、estimateRouteDuration |
serializer.test.ts | 包含或不包含车队分配的 serializeVehicle |
config.test.ts | verifyConfig – 缺失文件、端口范围、速度顺序、所有数值约束 |
SimulationController.test.ts | 完整生命周期:start、stop、getStatus、setOptions、getVehicles、getInterval,以及所有回放方法 |
值得注意的测试模式 – SimulationController 测试会 stub VehicleManager.prototype.setRandomDestination,以防在小型测试网络 fixture 上调用 A*,随后再恢复。回放测试在每个测试之前向临时目录写入最小的 NDJSON 文件,所有资源在 afterEach 中清理。
📡 WebSocket – 100 ms batching + back‑pressure
车辆位置更新现在 每 100 ms 批量发送一次,在发送前进行合并,以降低带宽占用并提供后压机制,确保在高负载情况下客户端不会被淹没。
adcast. 如果客户端的写缓冲区被堵塞,广播器会跳过该客户端,而不是让队列无限增长。这使得模拟器在 50–100 辆车辆的情况下仍能保持可用,且不会出现连接退化。
所有广播事件类型
vehicles – batched position array (100 ms window)
status – simulation state (running / ready / interval)
options – current StartOptions
heatzones – HeatZoneFeature[]
direction – active dispatch assignment
waypoint:reached – vehicle reached a waypoint
route:completed – vehicle completed its full route
reset – simulation was reset
fleet:created / fleet:deleted / fleet:assigned
incident:created / incident:cleared
vehicle:rerouted – live A* reroute triggered🔧 CI 改进
GitHub Actions 工作流之前在并行的三个作业中各运行一次 npm ci(每个作业一次)。现在它有一个专门的 setup 作业,只安装一次并根据 package-lock.json 对 node_modules 进行缓存。Lint、测试和构建作业从该缓存恢复。构建作业还会使用每次提交的键以及分支级别的恢复键来缓存 .turbo/。
架构图(已更新)
┌──────────────────────────────────────┐
│ apps/ui │
│ React 19 · D3 7 · Vite · TS 5.8 │
│ Mercator SVG map, 1×–15× zoom │
│ Icon rail · Panel sidebar · Dock │
└──────────────┬───────────────────────┘架构概览
│ REST + WebSocket
▼
┌──────────────────────────────────────┐
│ apps/simulator │
│ Express 4 · ws 8 · Turf.js 7 │
│ GeoJSON graph · A* · LRU cache │
│ WS broadcaster · 100ms batching │
└──────────────┬───────────────────────┘
│ GET /vehicles · POST /sync
▼
┌──────────────────────────────────────┐
│ apps/adapter (optional) │
│ Source plugins: static / graphql / │
│ rest / mysql / postgres │
│ Sink plugins: console / graphql / │
│ rest / redpanda / redis / webhook │
└──────────────────────────────────────┘快速开始
curl -O https://raw.githubusercontent.com/ivannovazzi/moveet/main/docker-compose.ghcr.yml
docker compose -f docker-compose.ghcr.yml up打开 . 无需配置,也不需要 API 密钥。
仓库:
欢迎在评论中提出关于 A 实现、D3 渲染器或录制格式的任何问题。*