Files
2026-09-13 18:43:25 +08:00
..
2026-09-13 18:43:25 +08:00
2026-09-13 18:43:25 +08:00
6
2026-09-11 11:36:08 +08:00
2026-09-13 18:43:25 +08:00

mcm26b-referee — CUMCM 2026 B 题独立评测机

自建的官方模拟器复现:模拟器引擎 + 机器狗 HTTP 接口 + 官方流程 WebUI, 作为一个独立包发布(本目录),零第三方依赖,且不导入任何参赛队代码。 与参赛队实现(仓库根的 mcm26b 包)完全解耦:双方只通过附件2 定义的 HTTP 协议耦合——评测机换任何客户端都成立,参赛队代码对接官方模拟器也无需改动。

uv sync                                  # 根工作区会同时挂载本包(dev 依赖)
uv run python -m referee                 # WebUI http://127.0.0.1:8026,接口 :2026
uv run pytest referee/tests              # 本包测试
  • 浏览器打开 http://127.0.0.1:8026:选择测试模块 → 确认开始 → 5 秒倒计时 → 接口开放,地图/状态/指令与反馈实时可见;
  • 回放器("回放"Tab):按案例加载存档回放,也可手动选定 JSONL 文件(点击 选择或拖拽导入,纯前端解析;兼容评测机行为日志与参赛队客户端会话日志两种格式), 支持播放/暂停、逐步±、倍速快进、缩放/平移、进度条定位;
  • 机器狗程序照常对接 http://127.0.0.1:2026(如 uv run mcm26b run --robot-id TEAM-0001 --base-url http://127.0.0.1:2026, 或一键 uv run mcm26b run --robot-id TEAM-0001 --local-judge)。

包结构

referee/src/referee/
├── spec.py        # 题面常量:目标区域/频道/半径/限时/耗时模型([题面] 逐条标注)
├── rules.py       # 服务端字段表、结果码与 HTTP 语义(附件2 §5-9 的可执行表格)
├── timing.py      # 纯计时模型:移动+换频道+动作,整数微秒累计(105/111/194/199 锚点)
├── simulator.py   # 评测引擎:观测判定、状态机、幂等、并发 409、截止与断连
├── jsonio.py      # 请求严格解析(BOM/重复键/NaN/深度)+ 响应规范化序列化
├── interface.py   # 机器狗接口完整边界(与传输无关;HTTP 服务器与内存直连共用)
├── server.py      # 接口 HTTP 承载:仅回环、仅窗口期监听、关闭即断连
├── session.py     # 官方流程状态机:四模块/次数/倒计时/窗口/中止/结束原因/日志
├── scenes.py      # 一局真值的数据准备(q3 全向 / q4 混合,可固定种子)
├── webui.py       # 界面服务器与 /ui/api/*
└── static/        # 单页前端(原生 HTML/CSS/JS,离线可用)

题意符合性对照(附件1《模拟器使用说明》/附件2《通信接口说明》)

题意条款 实现 固化测试
表1 动作与耗时(移动=距离/5、换频道 1s、检测 5s、清除 5s/3s,逐段整数微秒累计) timing.py + simulator.py test_timing_examples.py(105/111/194/199)
观测判定:no_signal/near(≤5m)/direction(±1° 误差、两位小数、[0,360) 归一化);定向 ±90° 含边界;清除 ≤20m 与朝向无关、仅一次 simulator.py test_simulator_conformance.py
协议边界:路径精确/仅 POST/415/413/严格 JSON/未知字段 accepted=false/幂等回放/409/并发 409 interface.py + simulator.py test_interface_boundary.py、test_http_server.py(真实 HTTP)
时限:5s 倒计时、25min 窗口、/enter 后 20min(取早)、虚拟 100h;截止后接口关闭、已登记动作允许完成 session.py 看门狗 + simulator.py test_session_flow.py
四个测试模块;演练不限次;正式各 3 次、启动成功即占用、中止仍占用;正式开始前再次确认 session.py + WebUI test_session_flow.py
指令与反馈:默认最新 1000 条、可调 100..5000、不限请求总数、完整行为入日志 session.py + WebUI 设置 test_session_flow.py
中止测试需两次确认;结束后不能复位或继续,只能开始新一局;结束原因显示 WebUI + session.py test_session_flow.py
测试案例编码;演练结束显示 总数/全向/定向;正式任何界面不显示真值 session.py 真值策略 + WebUI test_session_flow.py
接口地址默认 127.0.0.1:2026、只监听回环、空闲可改端口;非开放期连接失败属正常 server.py + WebUI 设置 test_http_server.py
robot_id/request_id 格式(1..64/128 字节、无控制/格式字符);arena_id="default" simulator.py + session.py test_simulator_conformance.py
响应 virtual_time_s 微秒累计、最多 6 位小数去尾零;accepted=false 时恒为 0 jsonio.py + simulator.py test_jsonio.py
行为日志可导出;加密上传上限 2MB 提示 WebUI 日志导出 + 大小告警 test_session_flow.py

自建差异声明(题面未规定,均为 [工程] 假设,不代表官方实现)

  • 联网登录/官方校时/17:30 启动截止/加密上传队列:属官方服务器侧策略,本地评测机 不实现;robot_id 由界面填写并照常参与逐字节校验。
  • 示向度误差场:同一(频道,位置)误差由种子确定性决定(重复测量不变, 题面仅要求"同一地点误差不变"),不同位置独立白噪声;分布不代表官方。
  • 场景分布:源位置在目标圆域内均匀、r_eff 在 [1000,1500] 均匀、频道无重复抽样; q4 定向源数量默认 3;均可用种子复现。
  • 429 流量保护/幂等记录上限:正常串行合法请求无速率上限 [题面],本地不设限。
  • 案例编码格式:4×4 大写字母数字(去易混字符),格式自拟。