- cafe.py: room 2 now invites the lowest-affection candidate instead of highest (room 1 unchanged), plus OCR'd invited-student name logging - exit_game.py: alert (AP_ALERT: log tag, picked up by ba_cron_run.sh's Discord alerting) if AP is still unspent above threshold when the game closes - login.py: re-check window_exists() after the stabilization wait to catch a startup window-flicker race that could crash a run - config.py/mapping.md: supporting constants and reference-mapping updates Also rewrites plan.md: retires the phase-by-phase changelog (now fully superseded by CLAUDE.md's own documentation) down to forward-looking backlog items, and adds a performance-improvement plan from a cron-log time analysis (lesson.py's per-cell screenshot redundancy, event_sweep's multi-call design). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
101 lines
8.7 KiB
Markdown
101 lines
8.7 KiB
Markdown
# ba-auto-daily implementation plan
|
||
|
||
Personal Blue Archive JP daily-automation project. `CLAUDE.md` is the authoritative, actively-maintained reference for architecture, deployment, conventions, and the incident history behind current design decisions — read it first. This file is intentionally scoped to **forward-looking work only**: the not-yet-implemented backlog and active improvement plans. It no longer carries a phase-by-phase changelog; that history (30+ phases of live-testing retrospectives) has been retired now that every feature it covered has shipped and CLAUDE.md's "Existing features" section carries the load-bearing lessons from it.
|
||
|
||
The reference implementation lives at `~/repo/baas-reference/` (read-only — study and adapt, never edit). See `ba_auto/reference_notes/mapping.md` for the current, maintained local-feature → reference-module mapping table.
|
||
|
||
## Currently implemented (for context, not a todo list)
|
||
|
||
`login`, `mailbox`, `cafe`, `stamina`, `gem_shop`, `circle`, `battle_pass`, `story_sweep`/`story_sweep_force`, `story_sweep_hard`/`story_sweep_hard_force`, `event_sweep`, `shop_common`, `shop_tactical`, `lesson`, `arena`, `bounty`, `scrimmage`, `exit_game` — see `ba_daily.py`'s `TASKS` dict for the exact CLI surface and `CLAUDE.md`'s "Existing features" section for behavior/known gaps.
|
||
|
||
## Backlog — not yet implemented
|
||
|
||
### Commissions (Base Defense + Item Retrieval)
|
||
|
||
Reference: `~/repo/baas-reference/module/clear_special_task_power.py`
|
||
Local target: `ba_auto/tasks/commission.py`
|
||
|
||
Two sub-dungeons. OCR: port the reference's approach if it uses OCR here — do not default to a fixed-target workaround just to avoid OCR (see `CLAUDE.md`'s OCR policy).
|
||
|
||
### Crafting
|
||
|
||
Reference: `~/repo/baas-reference/module/create.py`
|
||
Local target: `ba_auto/tasks/crafting.py`
|
||
|
||
Very complex — material selection, priority lists, rarity tiers, stepper/quantity UI, filtering/sorting, OCR-like decision points. Do not start until there's a concrete need; this is the most complex remaining reference module.
|
||
|
||
### Momo Talk
|
||
|
||
Reference: `~/repo/baas-reference/module/momo_talk.py`
|
||
Local target: `ba_auto/tasks/momo_talk.py`
|
||
|
||
Runs on a different cadence from daily reset, which is why it's still worth doing despite being low-value. Likely no OCR — mostly state scanning and click flow.
|
||
|
||
### Main story push (new-stage clearing, not sweeping)
|
||
|
||
Reference: `~/repo/baas-reference/module/main_story.py`, `~/repo/baas-reference/module/explore_tasks/explore_task.py`
|
||
|
||
Distinct from `story_sweep`/`story_sweep_hard` (which only re-sweep already-cleared stages). Low priority — full grid-mode support needs a lot of per-stage scripting; a simple auto-fight-only mode could be a smaller first cut. No reusable auto-fight primitive exists yet — `arena.py` implements its battle-commit/result-detection inline rather than as a shared module, so this would either need extracting that or building fresh.
|
||
|
||
### Group Story / Mini Story
|
||
|
||
Reference: `~/repo/baas-reference/module/group_story.py`, `~/repo/baas-reference/module/mini_story.py`
|
||
|
||
Convenience only, low priority.
|
||
|
||
### Event content beyond the AP sweep panel
|
||
|
||
`event_sweep.py` already covers the sweep panel for a currently-running event (see `CLAUDE.md`). Still not built: `explore_activity_story`/`explore_activity_mission`/`explore_activity_challenge` (walking the event's map / fighting stages manually — only needed for a stage that hasn't been SSS-cleared yet) and `exchange_reward` (the reward-exchange shop). Event-specific content expires, so any calibration work here (stage-count, row positions) is only valid for whichever event is running at the time.
|
||
|
||
### Daily Free Power
|
||
|
||
Reference: `~/repo/baas-reference/module/collect_daily_free_power.py`
|
||
|
||
Deliberately deferred, not merely unstarted — its entry point is a real-money purchase menu, and automating it needs explicit user confirmation before any implementation attempt.
|
||
|
||
## Skip list
|
||
|
||
| Feature | Why skip |
|
||
|---|---|
|
||
| Total Assault / Raid | Low value and risky to automate. Reference support may be limited/stubbed. |
|
||
| Joint Firing Drill | Not worth prioritizing for JP if reference has server-specific limitations. |
|
||
| De-clothes localization toggle | CN-only / irrelevant. |
|
||
| Restart / refresh-uiautomator2 | Android/ADB backend maintenance, not applicable to PC/Steam/Proton. |
|
||
| Auto-unfriend | Risky, low value, destructive. |
|
||
| Daily minigame dispatcher | Event-specific and unstable. Handle ad hoc only. |
|
||
|
||
## Performance improvement plan (opened 2026-08-14)
|
||
|
||
Prompted by a request to review real cron run logs (`scratchpad/ba_logs/{daily,q4h}.log`, pulled from nik-gpu, covering 3 `q4h` runs + 2 `daily` runs on 2026-08-14) for where automation time actually goes and what's worth speeding up. Timestamps come from the per-line logging added in the "timestamped log output" work (see git history / `CLAUDE.md`'s log-format notes).
|
||
|
||
### Measured totals
|
||
|
||
| Run | Total | Notes |
|
||
|---|---|---|
|
||
| q4h #1 (10:00) | 9m56s | |
|
||
| q4h #2 (13:00) | 8m45s | |
|
||
| q4h #3 (17:00) | 9m13s | |
|
||
| daily #1 (03:30) | 15m32s | |
|
||
| daily #2 (04:30) | **27m20s** | full run, 7 lesson tickets spent |
|
||
|
||
### Finding 1 (top priority, not yet implemented): `lesson.py` re-screenshots per cell instead of per region
|
||
|
||
In the 27m20s `daily` run, `lesson` alone took 9m50s (36% of the run), and ~7 minutes of that is the "scanning all regions" phase — 12 regions × ~30-38s each — that runs *before any ticket is spent*, just to build the priority queue.
|
||
|
||
Root cause, confirmed by reading the code: `_scan_open_grid_cells` (`ba_auto/tasks/lesson.py:196`) loops 3 rows × 3 cols × 3 slots = 27 cells per region, and `_read_slot_affection` (`lesson.py:185`) calls both `detector.region_contains_color` (checkmark check) and, if not done, `detector.read_int_on_heart_badge` (OCR). Both independently call `driver.read_screenshot()`, and `read_screenshot()` fires a **brand-new `scrot` capture every call** (`ba_auto/driver.py:97-127`) — there's no reuse of a prior frame. That means a single region scan can trigger up to ~50 fresh `scrot` processes against a screen that hasn't changed at all between them (no clicks happen mid-scan, per `_scan_all_regions`'s own docstring: "a pure read, spends no tickets").
|
||
|
||
**Proposed fix:** take one screenshot per region (or even once for the whole scan pass, if nothing changes on-screen until a click happens), decode it once, and pass the decoded image into the per-cell checkmark/OCR reads instead of each one re-capturing. This is a pure efficiency fix — the detection logic itself (color masking thresholds, heart-badge OCR contamination handling) doesn't change at all, so it doesn't touch anything CLAUDE.md's OCR policy cares about. Expected to cut the scan phase from ~7 minutes to well under a minute.
|
||
|
||
**Scope note:** `_run_queue`'s actual ticket-spending clicks (`lesson.py:306`) happen between scans, so only the *scan* phase's screenshots are provably safe to batch this way — anything read after a click still needs a fresh capture.
|
||
|
||
### Finding 2 (secondary, informational — do not touch without care): `event_sweep` is called 2-4x per run by design
|
||
|
||
`ba_daily.py`'s `daily` preset calls `event_sweep` four times, `q4h` twice (`ba_daily.py:132-144`) — deliberately, per the preset's own comment, "to re-check a rotating target" as AP regenerates from `circle`/`gem_shop`/`battle_pass` claims during the run. Each call that doesn't short-circuit on insufficient AP costs 56s-153s in the logs, mostly navigation to the event badge/page. Total `event_sweep` cost across a run's multiple calls ranged from ~112s (2 skips + 2 clean 56s sweeps) to ~430s (3 calls, one hitting the slow "wrong page" retry path) in the sampled runs.
|
||
|
||
This is **not recommended as a fix target right now**: the retry/settle budget the "wrong page" path uses (badge-carousel navigation, cold-start OCR settle time) was tuned across many rounds of real live-testing failures before it reached its current reliability — shrinking it risks reintroducing missed/silently-failed sweeps, which is a strictly worse outcome than a slow-but-correct run. If run time here ever needs to come down, the safer lever is reducing *how many times* `event_sweep` is invoked per run (e.g. consolidating to fewer, better-timed calls once AP-granting tasks have run) rather than shrinking any per-call retry/wait constant.
|
||
|
||
### Other observations (not action items)
|
||
|
||
- `cafe`'s pat-loop panning cost (~4-5 min/run) is inherent to the sparkle-hunt approach and matches reference behavior — not a target.
|
||
- `shop_common`'s full-grid OCR name scan costs ~100-120s/run when most/all configured items are sold out — inherent to the OCR-based item-identification fix from the sold-out-reordering incident (see `CLAUDE.md`'s Common Shop notes); not a target without changing correctness guarantees.
|