[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-105295":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":15,"stars7d":15,"stars30d":15,"stars90d":14,"forks30d":14,"starsTrendScore":16,"compositeScore":17,"rankGlobal":9,"rankLanguage":9,"license":18,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":21,"hasPages":19,"topics":22,"createdAt":9,"pushedAt":9,"updatedAt":23,"readmeContent":24,"aiSummary":9,"trendingCount":14,"starSnapshotCount":14,"syncStatus":25,"lastSyncTime":26,"discoverSource":27},105295,"CodeWar","zklmiao\u002FCodeWar","zklmiao","网页端 Python 编程对抗游戏：解题速度即战斗力 · A turn-based competitive Python programming game",null,"Go",149,1,51,0,58,174,81.8,"Other",false,"main",true,[],"2026-11-01 00:13:45","\u003Cdiv align=\"center\">\n\n# CodeWar · 代码战争\n\n**把解题速度变成战斗力。**\n\n网页端 Python 编程对抗游戏：两名玩家在 5×5 竞技场各控一名角色，每回合四道题只能解一道——攻击、走位、格挡、放大招。解题越快伤害越高，HP 先归零者败。\n\n\u003Csub>A turn-based competitive Python programming game — solve faster, hit harder.\u003C\u002Fsub>\n\n[玩法](#玩法) · [对局实况](#对局实况) · [技术架构](#技术架构) · [快速开始](#快速开始) · [测试](#测试) · [文档](#文档地图) · [Roadmap](#roadmap)\n\n![对局实况：左栏棋盘与战报，右栏四张题卡与共享工作区](docs\u002Fassets\u002Fscreenshot-match.png)\n\n![Go 1.26](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FGo_1.26-00ADD8?logo=go&logoColor=white) ![Vue 3.5](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FVue_3.5-4FC08D?logo=vuedotjs&logoColor=white) ![TypeScript 5](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FTypeScript_5-3178C6?logo=typescript&logoColor=white) ![Python 3.12](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FPython_3.12-3776AB?logo=python&logoColor=white) ![PostgreSQL 16](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FPostgreSQL_16-4169E1?logo=postgresql&logoColor=white) ![Docker Compose](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FDocker_Compose-2496ED?logo=docker&logoColor=white) ![gRPC](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FgRPC-244C5A) [![License](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicense-PolyForm_NC_1.0.0-D97706)](LICENSE)\n\n\u003C\u002Fdiv>\n\n## 玩法\n\n### 一回合，一个行动\n\n四道题同时展示，但一回合只能提交一道——取舍本身就是战术。\n\n| 行动 | 题面性质 | 结算效果 |\n|---|---|---|\n| ⚔ **攻击** | 镜像题（双方同题竞速） | 完成越快伤害越高；对手不在攻击形状覆盖格内即闪避 |\n| 🏃 **移动** | 私有题 + 棋盘点选 | 直线移动 1-2 格（游侠 3 格）；走出对方攻击形状即闪避 |\n| 🛡 **防御** | 私有题 | 本回合所受伤害 ×0.4（减伤 60%） |\n| ✨ **技能** | 私有题（难度 = 所选上限档） | 职业专属伤害 \u002F 治疗，冷却 2-4 回合；冷却中灰置 |\n\n```mermaid\nflowchart LR\n  S[\"回合开始\u003Cbr\u002F>四题同屏 · 75 秒\"] --> A{\"只选一道作答\"}\n  A --> AT[\"⚔ 攻击\u003Cbr\u002F>镜像竞速\"]\n  A --> MV[\"🏃 移动\u003Cbr\u002F>走位闪避\"]\n  A --> DF[\"🛡 防御\u003Cbr\u002F>减伤 60%\"]\n  A --> SK[\"✨ 技能\u003Cbr\u002F>职业大招\"]\n  AT --> R[\"按解题耗时排序结算\u003Cbr\u002F>事件流广播\"]\n  MV --> R\n  DF --> R\n  SK --> R\n  R --> S\n```\n\n### 三职业\n\n| 职业 | HP | 普攻 | 普攻形状 | 移动 | 技能（伤害 \u002F 治疗 · 冷却） |\n|---|---|---|---|---|---|\n| **剑士** | 110 | 26 | 相邻 4 格十字（无方向） | 1-2 | 巨力斩 55 · CD4 \u002F 求生本能 30 · CD3 |\n| **法师** | 90 | 18 | 直线 2 格线扫 | 1-2 | 烈焰风暴 40 · CD3 \u002F 秘法汲取 25 + 自疗 20 · CD3 |\n| **游侠** | 95 | 20 | 1-3 格点狙 | **1-3** | 穿云箭 45 · CD4 \u002F 风行回复 28 · CD2 |\n\n### 伤害与风险\n\n```txt\n伤害 = 基础伤害 × 时间系数(0.6~1.0) × 难度系数(L1 ×0.85 → L5 ×1.20)\n             × 形状命中判定 × 防御减伤(×0.4)\n```\n\n- **难度是风险回报**：开局自选题型、难度上限与抽题策略（爬坡 \u002F 均匀）；上限越高，全局伤害与结算奖励系数越高。\n- **错误有代价**：提交错误锁定 5 秒并自损 3 HP；一道题全部用例通过才生效。\n- **胜负**：HP 归零 KO；10 回合打满按剩余 HP 裁决；同时归零平局，ELO 双方 +0。\n\n### 模式\n\n- **本机热座 1v1** —— 两个浏览器窗口各控一方；双方账号登录时结算 ELO。\n- **人机练习** —— 简单 \u002F 普通 \u002F 困难三档 Bot，走与真人相同的 `SubmissionPort`；不记战绩。\n- **4 关交互式教程** —— 读题作答 → 走位闪避 → 防御与技能冷却 → 难度收益；完成解锁 PvP 入口，进度随账号保存。\n- **账号与战绩** —— 注册登录、历史对局、胜率与 ELO 跨会话保留。\n\n> 在线排位 1v1 尚未实现：事件流同步协议（ADR-0002）与认输握手已就绪，匹配与在线同步归 08 号票。\n\n## 对局实况\n\n| 入口：题型 \u002F 难度 \u002F 抽题策略 + 职业盲选 | 教程：每关只教一个机制，实操过关 |\n|:---:|:---:|\n| ![入口页](docs\u002Fassets\u002Fscreenshot-entry.png) | ![教程关](docs\u002Fassets\u002Fscreenshot-tutorial.png) |\n\n## 技术架构\n\n```mermaid\nflowchart LR\n  subgraph Browser[\"浏览器 · Vue 3 + Pinia + CodeMirror\"]\n    C[\"事件流渲染\u003Cbr\u002F>提交上行 \u002F 快照重连\"]\n  end\n\n  subgraph Server[\"Go 服务 · 服务端权威\"]\n    H[\"Hub\u003Cbr\u002F>WebSocket · 席位 · 广播\"]\n    E[\"MatchEngine\u003Cbr\u002F>回合状态机 + 事件流\"]\n    Q[\"QuestionFactory\u003Cbr\u002F>模板 × seed\"]\n    B[\"PvE Bot\u003Cbr\u002F>决策层\"]\n    U[\"账号 · 战绩 · ELO\"]\n  end\n\n  J[\"Judge\u003Cbr\u002F>Python gRPC · 一次性容器沙箱\"]\n  P[(\"PostgreSQL 16\")]\n\n  C \u003C-->|\"提交上行 \u002F 事件流下行\"| H\n  H --> E\n  E --> Q\n  B -->|\"SubmissionPort\"| E\n  E -->|\"SubmissionPort\"| J\n  H --> U\n  U --> P\n```\n\n架构以三个 seam 为骨架，实现与测试都围绕它们展开：\n\n| seam | 边界契约 |\n|---|---|\n| **MatchEngine**（唯一集成 seam） | 回合状态机（回合开始 → 面板组装 → 作答窗口 → 结算 → 回合结束），对外只发布**带序号的对局事件流**，依赖 `QuestionPort` \u002F `SubmissionPort` \u002F `ClockPort`。全部战斗规则在此边界内实现；真人、PvE Bot、脚本回放走同一条提交入口，引擎对 Bot 零特判。 |\n| **Judge**（纯函数 seam） | `judge(code, testCases) → {passed, category, durationMs}`。独立 Python 微服务，每次判题起一次性容器：禁网、限时、限资源，100% 用例通过才生效；支持链表 \u002F 树 \u002F 有状态类等结构体题契约，题作者的构造器与比较器与玩家代码过同一套静态卫兵。 |\n| **QuestionFactory**（纯函数 seam） | `create(spec, seed) → {instance, answerKey, testCases}`。124 个模板按「题型 × 难度档 × 动作类型 × 题面形式」四维标注并参数化；同 seed 必出同实例（测试可复现），不同 seed 实例不同（背答案无用）。 |\n\n### 几处值得一提的工程取舍\n\n| 主题 | 做法 |\n|---|---|\n| 事件流同步 | 客户端只渲染事件、只上行提交，状态永远由服务端裁决；断线以快照 + 尾随事件重建，序号断裂自动重连自愈。 |\n| 判题不持引擎锁 | `solveMs` 按提交到达时刻计算，后到玩家不会因对手判题排队而被记慢——镜像竞速公平。 |\n| 连接卫生 | 读写 deadline + ping\u002Fpong 保活 + 并发上限；慢消费者丢事件而非阻塞全场广播，断号由客户端快照重连兜底。 |\n| verdict 防伪造 | 判题 harness 只接受恰好一行结论，玩家代码无法用 `atexit` 伪造协议行；异常一律 fail-closed。 |\n| 测试纪律 | 行为断言集中在三个 seam 的外部边界（事件流 \u002F Judge \u002F QuestionFactory），错误路径优先；关键断言经过变异电池验证——写错实现必须让测试变红。 |\n\n## 快速开始\n\n### Docker Compose（推荐，一键起全栈）\n\n```bash\ndocker compose -f deploy\u002Fdocker-compose.yml up -d --build\n```\n\n打开 **http:\u002F\u002Flocalhost:3001** —— app、judge 沙箱与 PostgreSQL 一并启动，账号、战绩与 ELO 可直接使用。首次构建会拉取 `python:3.12-slim` 沙箱镜像，需要本机 Docker daemon 运行（判题容器经 `docker.sock` 创建）。\n\n上手路径：\n\n- **单窗口最快**：入口页选职业 → 开始人机练习（一局 10 回合）。\n- **热座对战**：窗口 A 点「以 P1 接入」，窗口 B 打开同地址点「以 P2 接入」。\n- **教程与 ELO**：注册登录 → 完成 4 关教程 → PvP 解锁；两个账号登录对局即结算 ELO。\n\n### 本地开发\n\n```bash\n# 1) 数据库（宿主 25432 → 容器 5432）\ndocker compose -f deploy\u002Fdocker-compose.yml up -d postgres\n\n# 2) judge 服务（需要 Docker daemon，沙箱经 docker.sock 创建）\ncd judge && pip install -r requirements.txt && python -m judgesvc.server\n\n# 3) Go 服务（:3001）\ncd server\nDATABASE_URL='postgres:\u002F\u002Fcodewar:codewar-dev@localhost:25432\u002Fcodewar?sslmode=disable' \\\n  go run .\u002Fcmd\u002Fcodewar\n\n# 4) 客户端 dev server（:5173，已代理 \u002Fws 与 \u002Fapi 到 :3001）\npnpm -C client dev\n```\n\n开发约定（worktree 并行、端口规范、票据流程）见 [AGENTS.md](AGENTS.md)。\n\n## 测试\n\n```bash\n# Go：全包竞态门控\ncd server && go test -race .\u002F...\n\n# Go：真实 Postgres 集成测试（按包独立测试库，自动创建）\ncd server && CODEWAR_TEST_DSN='postgres:\u002F\u002Fcodewar:codewar-dev@localhost:25432\u002Fcodewar_test?sslmode=disable' go test .\u002F...\n\n# Judge：沙箱与判题契约\npython -m pytest judge\u002Ftests -q\n\n# 客户端\npnpm -C client test\npnpm -C client build\n```\n\nCI 三门并行：Go `-race`、judge pytest、client test + build（见 [.github\u002Fworkflows\u002Fci.yml](.github\u002Fworkflows\u002Fci.yml)）。\n\n## 项目结构\n\n```txt\nclient\u002F                 Vue 3 + Pinia + CodeMirror；事件流驱动渲染\nserver\u002F\n  cmd\u002Fcodewar\u002F          主服务入口（HTTP\u002FWS + 静态托管）\n  cmd\u002Fsmoke\u002F            headless 端到端冒烟客户端\n  internal\u002Fmatch\u002F       对局引擎、形状判定、事件流\n  internal\u002Fhub\u002F         WebSocket 席位、广播、重连、结算\n  internal\u002Fquestion\u002F    出题工厂与模板库\n  internal\u002Fbot\u002F         PvE 决策层\n  internal\u002Faccounts\u002F    账号、战绩、ELO\njudge\u002F                  Python gRPC 判题服务 + 容器沙箱\nproto\u002F                  match.proto \u002F judge.proto（Go \u002F TS \u002F Python 三端生成）\ndb\u002F                     迁移的权威源（app 内嵌副本执行）\ndesign\u002F                 设计 token、占位组件与风格页\ndocs\u002F\n  specs\u002F                产品规格（设计与数值的唯一真相源）\n  adr\u002F                  8 篇架构决策记录\n  design\u002F               出题系统、职业数值、占位美术规范\n  assets\u002F               README 截图\n```\n\n## 文档地图\n\n- [产品规格](docs\u002Fspecs\u002F001-codewar-mvp.md)：37 条用户故事、实现决策、测试决策、数值初稿\n- [架构决策（ADR）](docs\u002Fadr\u002F)：技术栈、同步模型、判题沙箱、结构体题契约、PvE Bot 边界、教程模式、沙箱威胁模型\n- [出题系统设计](docs\u002Fdesign\u002F002-question-system.md) \u002F [职业与技能表](docs\u002Fdesign\u002F003-classes-skills.md) \u002F [占位美术规范](docs\u002Fdesign\u002F004-placeholder-art-standard.md)\n- [票据与优化清单](.scratch\u002Fcodewar-mvp\u002F)：逐票交付记录、验收证据与后续 backlog\n- [AGENTS.md](AGENTS.md)：面向 AI 协作者的工作流与仓库约定（本项目由 spec + 票据 + ADR 驱动）\n\n## Roadmap\n\n**已交付**\n\n- [x] 本地热座对局 · 三行动与攻击形状 · 技能与三职业\n- [x] 出题工厂（124 模板 · seed 确定性）· 对局配置与难度风险\n- [x] 判题沙箱硬化 · 结构体题契约 · 判题结论防伪造 · 判题锁外并发\n- [x] 账号 \u002F 战绩 \u002F ELO · PvE 三档 Bot · 4 关交互式教程\n- [x] 认输握手 · 连接保活与并发上限 · 结算统计与日志着色\n\n**下一步**\n\n- [ ] **在线排位 1v1**：段位就近匹配、服务端权威同步、断线判负 \u002F 重连（08）\n- [ ] 反作弊硬化：禁粘贴编辑器、节奏与粘贴指纹、管理端（11）\n- [ ] 视觉打磨：SVG 图标、动效落地、职业色血条、难度徽标（25）\n- [ ] 对局回放与错题本、排行榜、CI 门控补全\n\n## 许可\n\n本项目采用 **源码可见（source-available）** 模式，不是 OSI 开源项目：\n\n| 范围 | 许可 |\n|---|---|\n| 代码（`client\u002F` `server\u002F` `judge\u002F` `proto\u002F` `db\u002F` `deploy\u002F` `scripts\u002F`，含题库模板） | [PolyForm Noncommercial 1.0.0](LICENSE) —— 非商用自由使用、修改与分发；含专利授权；须保留 [NOTICE](NOTICE) 署名 |\n| 内容（`docs\u002F` `design\u002F` `.scratch\u002F` 与项目文档） | [CC BY-NC-SA 4.0](LICENSE-CONTENT) —— 署名、非商用、相同方式共享 |\n\n- **商用需授权**：任何商业用途（商业产品集成、付费服务、商业分发）须获得作者书面许可，联系 \u003Chysytess@gmail.com>。\n- **署名**：保留 `NOTICE` 中的 `Required Notice: Copyright (c) 2026 zklmiao` 行；内容转载须注明「CodeWar · 代码战争 \u002F zklmiao」及许可链接。\n- **贡献**：欢迎 PR，提交即表示同意按相同许可并入；商用授权仅覆盖作者本人创作部分，含外部贡献的部分需另行取得相应贡献者同意。\n\n## 说明\n\n- 美术资产为统一占位系统（设计 token 单源，可整包替换为正式美术）。\n- `ref_resources\u002F`（外部项目参考）不入库；本仓库未复制任何第三方代码或美术资产。\n- README 截图取自真实对局与教程界面（1366×768 与 1440×900）。\n",2,"2026-10-31 04:26:22","CREATED_QUERY"]