diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml index 73a4c53..d026aa0 100644 --- a/.github/workflows/build-and-release.yml +++ b/.github/workflows/build-and-release.yml @@ -24,13 +24,13 @@ jobs: run: uv sync --group dev - name: Build with PyInstaller - run: uv run tools/package.py + run: uv run python src/cannotmax/tools/package.py - name: Upload build artifact uses: actions/upload-artifact@v7 with: name: cannotmax-build - path: output/main/ + path: output/cannotmax/ retention-days: 1 release: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..e348cbf --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,18 @@ +name: Test + +on: [push, pull_request] + +jobs: + test: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v3 + + - name: Install dependencies + run: uv sync --extra cpu + + - name: Run tests + run: uv run pytest tests/ -v --tb=short diff --git a/.gitignore b/.gitignore index c454f11..b22e652 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,10 @@ venv/ .venv/ __pycache__/ .mypy_cache/ +.pytest_cache/ +.ruff_cache/ +*.pyc +*.pyo # =========================== # 2. Pixi 包管理环境 @@ -21,55 +25,36 @@ __pycache__/ # =========================== # 4. AI 辅助工具配置 # =========================== +.agents/ .claude/ .codex/ .copilot/ .codeartsdoer +docs/superpowers/ # =========================== # 5. 模型权重与构建产物 # =========================== # 模型文件 -models/*.png -*.pth -*.onnx -*.onnx.data - +models +!models/update.md # 构建与输出目录 build/ output/ +outputs/ # =========================== # 6. 数据集与媒体资源 # =========================== -# 基础数据目录 -data/images/ -data/[0-9][0-9][0-9][0-9]_[0-1][0-9]_[0-3][0-9]__[0-2][0-9]_[0-5][0-9]_[0-5][0-9]/ -images/nums/ - -arknights_package_[0-9][0-9][0-9][0-9][0-1][0-9][0-3][0-9]_[0-2][0-9][0-5][0-9][0-5][0-9].zip - -# 训练相关数据 -data_train/tmp/ -data_train/package/*.zip -data_train/data_images/ - -# 单独的截图文件 -screenshot.png +data/* +!data/compressed/.gitkeep +images/tmp/ # =========================== # 7. 日志与临时文件 # =========================== -# 日志 log.txt *.log -# 临时目录 -tmp - -# =========================== -# 8. 其他杂项文件 -# =========================== -arknights.csv multi_ports.txt *.bak diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..e7eab97 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,20 @@ +repos: + - repo: local + hooks: + - id: ruff-lint + name: ruff (lint) + entry: ruff check + language: system + types: [python] + - id: ruff-check-imports + name: ruff (import sorting) + entry: ruff check --select I --fix + language: system + types: [python] + pass_filenames: false + - id: ruff-format + name: ruff (format) + entry: ruff format + language: system + types: [python] + pass_filenames: false diff --git a/platform-tools/AdbWinApi.dll b/3rdparty/platform-tools/AdbWinApi.dll similarity index 100% rename from platform-tools/AdbWinApi.dll rename to 3rdparty/platform-tools/AdbWinApi.dll diff --git a/platform-tools/AdbWinUsbApi.dll b/3rdparty/platform-tools/AdbWinUsbApi.dll similarity index 100% rename from platform-tools/AdbWinUsbApi.dll rename to 3rdparty/platform-tools/AdbWinUsbApi.dll diff --git a/platform-tools/NOTICE.txt b/3rdparty/platform-tools/NOTICE.txt similarity index 100% rename from platform-tools/NOTICE.txt rename to 3rdparty/platform-tools/NOTICE.txt diff --git a/platform-tools/adb.exe b/3rdparty/platform-tools/adb.exe similarity index 100% rename from platform-tools/adb.exe rename to 3rdparty/platform-tools/adb.exe diff --git a/platform-tools/etc1tool.exe b/3rdparty/platform-tools/etc1tool.exe similarity index 100% rename from platform-tools/etc1tool.exe rename to 3rdparty/platform-tools/etc1tool.exe diff --git a/platform-tools/fastboot.exe b/3rdparty/platform-tools/fastboot.exe similarity index 100% rename from platform-tools/fastboot.exe rename to 3rdparty/platform-tools/fastboot.exe diff --git a/platform-tools/hprof-conv.exe b/3rdparty/platform-tools/hprof-conv.exe similarity index 100% rename from platform-tools/hprof-conv.exe rename to 3rdparty/platform-tools/hprof-conv.exe diff --git a/platform-tools/libwinpthread-1.dll b/3rdparty/platform-tools/libwinpthread-1.dll similarity index 100% rename from platform-tools/libwinpthread-1.dll rename to 3rdparty/platform-tools/libwinpthread-1.dll diff --git a/platform-tools/make_f2fs.exe b/3rdparty/platform-tools/make_f2fs.exe similarity index 100% rename from platform-tools/make_f2fs.exe rename to 3rdparty/platform-tools/make_f2fs.exe diff --git a/platform-tools/make_f2fs_casefold.exe b/3rdparty/platform-tools/make_f2fs_casefold.exe similarity index 100% rename from platform-tools/make_f2fs_casefold.exe rename to 3rdparty/platform-tools/make_f2fs_casefold.exe diff --git a/platform-tools/mke2fs.conf b/3rdparty/platform-tools/mke2fs.conf similarity index 100% rename from platform-tools/mke2fs.conf rename to 3rdparty/platform-tools/mke2fs.conf diff --git a/platform-tools/mke2fs.exe b/3rdparty/platform-tools/mke2fs.exe similarity index 100% rename from platform-tools/mke2fs.exe rename to 3rdparty/platform-tools/mke2fs.exe diff --git a/platform-tools/source.properties b/3rdparty/platform-tools/source.properties similarity index 100% rename from platform-tools/source.properties rename to 3rdparty/platform-tools/source.properties diff --git a/platform-tools/sqlite3.exe b/3rdparty/platform-tools/sqlite3.exe similarity index 100% rename from platform-tools/sqlite3.exe rename to 3rdparty/platform-tools/sqlite3.exe diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..792a442 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,163 @@ +# CannotMax-Greenvine Agent Instructions + +## Quick Start + +```bash +uv sync # Install dependencies (includes Windows-only packages) +uv sync --extra cu128 # CUDA 12.8 support (PyTorch cu128) +uv sync --extra cpu # CPU-only fallback + +uv run cannotmax # Launch GUI +uv run cannotmax multi # Multi-instance manager + +uv run cannotdl train # Train model +uv run cannotdl eval # Evaluate model +uv run cannotdl convert -i model.pth -o model.onnx # PyTorch → ONNX +uv run cannotdl tools # Run dev tool (e.g., statistics) +uv run cannotdl pipelines # Run data pipeline (e.g., merge_data) + +uv run cannotsim sim # Battle simulator (PyQt6) +uv run cannotsim sim_mc # Tkinter Monte Carlo simulator + +uv run pytest tests/ # Run all tests +uv run pytest tests/ -m "not e2e" # Skip e2e (needs emulator) +``` + +## Critical Environment Constraints + +- **Windows-only**: `windows-capture` (WinRT), `pywin32`, `maafw` are not available on Linux/macOS +- **PC mode requires admin**: SendInput click operations require administrator privileges. `console.py` auto-elevates via `_ensure_admin()`. +- **PyTorch cu128**: Domestic mirrors don't host CUDA 12.8 wheels. Source must be `https://download.pytorch.org/whl/cu128/` (configured in `pyproject.toml`). Fallback: `--extra cpu`. +- **OpenCV**: `opencv-python` only. Do NOT add `opencv-python-headless` — they conflict. +- **Resolution**: Target 1920×1080 (16:9). PC mode state templates available at `images/process/pc_*.png` for non-1080p resolutions. + +## Architecture + +### Package Structure + +``` +src/cannotdl/ # 模型训练与数据处理 +├── config/ # MONSTER_COUNT, FIELD_FEATURE_COUNT, MONSTER_DATA (dict) +├── core/ # PyTorch 推理(CannotModel) + TorchFieldRecognizer +│ ├── field_model.py # TorchFieldRecognizer(PyTorch 地形识别) +│ └── predict.py # CannotModel 推理 +├── models/ # UnitAwareTransformer, ArknightsDataset +├── training/ # 训练器、评估器、Muon+Lion 优化器 +├── pipelines/ # 数据清洗、合并、打包流水线 +├── tools/ # 统计、模型转换、数据审查 +└── console.py # uv run cannotdl 入口 + +src/cannotsim/ # 战斗模拟引擎 +├── battle_field.py # 战场状态与帧模拟 +├── main_sim.py # PyQt6 模拟器 GUI +├── sim_mc.py # Tkinter 多核模拟器 +├── console.py # uv run cannotsim 入口 +└── utils.py # MONSTER_MAPPING, REVERSE_MONSTER_MAPPING + +src/cannotmax/ # 主包 (GUI + 运行时) +├── config/ +│ ├── __init__.py # DEBUG_MODE, DISABLE_MAAFW (运行时配置) +│ ├── paths.py # 所有路径常量(集中管理) +│ └── settings.py # app.json 加载 +├── core/ # 识别(ONNX)、自动获取、连接器 +├── gui/ # PyQt6 图形界面 +├── tools/ # 打包(package.py) + ROI 选取 +└── utils/ # 延迟加载的图像/数据、匹配、区域检测 +``` + +### Entry Points + +- **cannotmax** (`uv run cannotmax`): GUI 运行时、多开管理 +- **cannotdl** (`uv run cannotdl`): train, eval, convert, tools, pipelines +- **cannotsim** (`uv run cannotsim`): sim, sim_mc, simulate + +### Path Constants + +All paths are defined in `cannotmax/config/paths.py`. Rules: + +1. No hardcoded path strings in code — all paths from `paths.py` +2. Directory constants end with `DIR` (e.g., `DATA_DIR`) +3. File constants end with format extension (e.g., `MONSTER_CSV`, `APP_CONFIG_JSON`) + +Key constants: `DATA_DIR`, `MODELS_DIR`, `CONFIG_DIR`, `IMAGES_DIR`, `MONSTER_IMAGES_DIR`, `PROCESS_IMAGES_DIR`, `TMP_IMAGES_DIR`, `MONSTER_CSV`, `PACKAGE_OUTPUT_DIR`, `PACKAGE_FORMAT`, `OUTPUT_DIR`, `ICO_DIR`, `THIRDPARTY_DIR`, `ADB_EXE` + +### Capture Modes + +1. **ADB**: `AdbConnector` in `core/connector/adb_connector.py` — emulators (LDPlayer, MuMu, BlueStacks) +2. **PC**: `PcConnector` in `core/connector/pc_connector.py` — official Arknights PC client (**requires admin**) +3. **WIN**: `WinRTScreenCapture` in `core/connector/winrt_capture.py` — window/monitor capture via WinRT + +### Model Loading + +- `cannotmax` uses `predict_onnx.py` (ONNX only, zero `import torch` at module level) +- `cannotdl` uses `predict.py` (PyTorch, for training/evaluation) +- `cannotdl.core.field_model.TorchFieldRecognizer` contains full PyTorch field recognition +- `cannotmax.core.field_recognition.FieldRecognizer` is a zero-torch stub that delegates to `TorchFieldRecognizer` when `FIELD_FEATURE_COUNT > 0` +- Default model path: `models/predictor/` (set via `paths.MODELS_DIR`) +- Fallback: if no pattern-matching model found, picks any `.pth` file by mtime + +### Data Files + +- `monster_greenvine.csv` (root): Monster data indexed by `id` (78 monsters) +- `data/compressed/*.zip`: Archived training data packages +- `config/app.json`: Runtime config (auto-created from defaults if missing) +- `images/monsters/`: Monster template images (named by 原始名称) +- `images/process/{0-15}.png` + `images/process/pc_{i}.png`: State detection templates + +## Conventions + +### Import Rules + +- **Same-package**: Use relative (`from .xxx import YYY`, `from ..xxx import YYY`) +- **Cross-package**: Use absolute with package prefix (`from cannotmax.config import MONSTER_COUNT`) +- **Tests**: Use `from src.cannotmax.xxx import YYY` (run from project root) + +### Git Commit Style + +Format: `type: description` (e.g., `fix:`, `refactor:`, `feat:`, `chore:`, `docs:`, `style:`) + +## MAA Framework Integration + +- Binaries auto-loaded from `maafw` Python package — no local copy needed +- `DISABLE_MAAFW` flag in `config/app.json` → `settings.py` for legacy ADB fallback +- `@patch` paths in tests must use `cannotmax.xxx` (not `src.cannotmax.xxx`) +- Packaged build: `hiddenimports=['maa', ...]` + `collect_dynamic_libs('maa')` in spec + +## PC Mode + +- **Admin required**: `console.py:_ensure_admin()` auto-elevates on startup +- **State templates**: `images/process/pc_{i}.png` added for PC UI scale; multi-template matching picks best +- **Click**: MAA Win32Controller preferred, SendInput as fallback +- **Auto-fetch**: Now works in PC mode (was restricted to ADB only) + +## Testing + +```bash +uv run pytest tests/ # All tests +uv run pytest tests/ -m "not e2e" # Skip e2e +uv run pytest tests/test_imports.py # Import checks only +``` +- Pytest marker: `@pytest.mark.e2e` for tests requiring real ADB simulator +- CI: Windows runner only (`runs-on: windows-latest`), uses `uv sync --extra cpu` + +## Pre-commit Hooks + +- `ruff (lint)` — static analysis on staged Python files +- `ruff (import sorting)` — auto-sort imports +- `ruff (format)` — auto-format code +- Config uses `ruff` directly (not `uv run ruff`) to avoid `uv sync` interference + +## Common Pitfalls + +1. **Don't rename/delete `core/connector/winrt_capture.py`**: Imported by `pc_connector.py` and `main_window.py` +2. **OpenCV**: Only `opencv-python`, never `opencv-python-headless` +3. **cu128 network issues**: Frequent on Chinese networks; provide CPU fallback +4. **`UnitAwareTransformer` namespace**: Must be importable from `__main__` before `torch.load()` +5. **Lazy torch imports**: `field_recognition.py` imports torch inside methods — safe for ONNX-only builds +6. **Packaged build**: `cannotdl.core` excluded; `core/__init__.py` has try/except fallback to `predict_onnx` +7. **Multi-instance data**: Stop ALL instances before running data packaging +8. **`monster_greenvine.csv`**: `MONSTER_COUNT` derives from its row count (currently 78) +9. **`FIELD_FEATURE_COUNT = 0`**: Set in `config/app.json` — terrain pipeline not active +10. **PC mode state detection**: Uses `images/process/pc_{i}.png` when available, falling back to `{i}.png` +11. **MONSTER_DATA in cannotmax**: Use `cannotmax.utils.monster_data.get_monster_data()` (DataFrame), not `cannotdl.config.MONSTER_DATA` (dict) +12. **Monster avatar paths**: Use `cannotmax.utils.monster_data.get_monster_avatar_path(id)` instead of `MONSTER_IMAGES_DIR / f"{MONSTER_DATA['原始名称'][id]}.png"` \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c992d8d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,172 @@ +# CannotMax-Greenvine v2.0.0 更新日志 + +## Unreleased + +### WIN 模式识别重构 +- 重写 `process_regions` 中 WIN 模式逻辑:用户 ROI → find_monster_zone 识别 → 坐标映射回全屏截图 → 裁剪完整怪物条 +- 新增 `utils/roi_transform.py` 坐标变换工具,支持归一化坐标与像素坐标间的批量转换 +- 修复 `find_monster_zone` 返回坐标超出 [0,1] 范围时导致的除零错误,添加边界检查和 debug 日志 + +### PC 模式与连接器 +- WinRT 截屏新增首帧就绪等待(超时 3 秒),避免"首帧未就绪"错误 +- ADB/PC 模式切换时自动从 `RECOGNITION_PARAMS` 加载 `crop_ratio`、`avatar_regions`、`number_regions` +- WIN 模式禁用自动获取按钮 +- `reselect_roi` 添加截图可用性检查 + +### 窗口选择器优化(未提交) +- 显示所有窗口(包括同名窗口),通过 hwnd 区分 +- 鼠标悬浮窗口时绘制黄色边框高亮 +- 新增 `PcConnector.list_arknights_windows()` 静态方法用于筛选明日方舟窗口 +- PC 模式启用"选择截屏窗口"按钮,可重新选择明日方舟窗口 + +### 路径表重构 +- 扩展 `config/paths.py`,新增 14 个路径常量:`ICO_DIR`、`MONSTER_IMAGES_DIR`(修复了之前错误指向 `images/` 的问题)、`PROCESS_IMAGES_DIR`、`LOGIN_IMAGES_DIR`、`SAMPLES_IMAGES_DIR`、`THIRDPARTY_DIR`、`ADB_PATH`、`BATTLEFIELD_RECOGNIZE_DIR`、`ARKNIGHTS_DATA_CSV`、`MONSTER_GREENVINE_CSV`、`MONSTER_CSV`、`MULTI_PORTS_FILE`、`OUTPUT_DIR` +- 替换 `gui/`、`core/`、`config/` 中所有硬编码路径字符串,改为引用 `paths.py` 常量 + +### 代码组织 +- `main_window.py` 48 个方法按逻辑分组重排(初始化、连接器、设备列表、截屏、识别、预测、输入展示、自动获取、模拟器、数据打包、设置回调),添加分组注释 +- `login.py` 移除硬编码的 `C:\Program Files\Arknights\` 游戏路径,改为通过 Windows API `QueryFullProcessImageName` 从运行中进程获取 exe 路径 + +### 重构 +- **CLI 三入口**: `uv run cannotmax`(GUI/运行时)、`uv run cannotdl`(训练/ML 管线)、`uv run cannotsim`(战斗模拟器)独立入口,移除了 `cannotmax console.py` 中的 train/eval/convert/tools/pipelines 子命令 +- **cannotdeeper → cannotdl 包重命名**: 目录、导入、pyproject.toml entry point、文档引用全面更新 +- **config 包精简**: `config/__init__.py` 只保留运行时配置(`DEBUG_MODE`、`DISABLE_MAAFW`),删除 `MONSTER_IMAGES`、`MONSTER_DATA`、`load_images`、`load_monster_data`;删除空的 `constants.py` +- **settings.py 清理**: 移除 `data` 配置段及 `get_package_format()`、`get_data_package_output_dir()` 函数;`_DEFAULT_CONFIG` 不再包含 `data` 段 +- **路径常量集中**: `PACKAGE_OUTPUT_DIR`(`output/data`)、`PACKAGE_FORMAT`(zip 格式)移至 `paths.py`,`app.json` 不再包含 `data` 段 + +### 怪物数据与图像 +- **utils 模块化**: `MONSTER_IMAGES` / `MONSTER_DATA` 从 `config` 移至 `utils/images.py` 和 `utils/monster_data.py`,支持延迟加载 +- **新增 `get_monster_avatar_path(id)`**: 根据怪物 ID 返回头像 PNG 路径,统一替代 `MONSTER_IMAGES_DIR / f"{MONSTER_DATA['原始名称'][id]}.png"` 模式 +- **修复 recognize.py 怪物名错位 bug**: `MONSTER_DATA["原始名称"][i]` 用整数位置访问改为 `.at[id, "原始名称"]` 标签访问 +- **图标路径修复**: `cannotsim` 加载图标从 `images/{id}.png` 改为 `images/monsters/{原始名称}.png`(匹配实际文件名) +- **REVERSE_MONSTER_MAPPING 修复**: 同时包含 CSV 的 `名称` 和 `原始名称` 列,补充 `小喷蛛` → 大喷蛛 ID 映射 + +### 修复 +- `adb_connector.py` 中 adb.exe 路径改为绝对路径(`.resolve()`),修复 auto_fetch 中工作目录变化后找不到 adb.exe 的问题 +- PC 端状态模板加载前检查文件存在,消除 OpenCV 对缺失 `pc_{i}.png` 的警告 +- 打包版 exe 不再因 `_ensure_admin()` 通过 `python -m cannotmax` 重新启动而闪退(frozen 环境使用自身 exe 路径重新启动) +- `find_monster_zone.py` 修复 `TMP_IMAGE_DIR` 拼写错误(应为 `TMP_IMAGES_DIR`) + +### 命令行 +- 新增 `uv run tools