Refactor directory labels and update task migration status
- Changed directory labels from ".scratchpad/" to "scratchpad/" in graph.json and related documentation for consistency. - Updated plan.md to reflect the current status of the Stamina/AP task migration, including details on the mission claim process and identified bugs. - Modified setup.sh to include 'stamina' in the run command options for the daily script.
This commit is contained in:
parent
a04ef5d0c5
commit
0b16399948
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,4 +3,4 @@ graphify-out/cost.json
|
|||||||
graphify-out/cache/
|
graphify-out/cache/
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.pyc
|
*.pyc
|
||||||
.scratchpad/
|
scratchpad/
|
||||||
|
|||||||
@ -197,7 +197,7 @@ Do not introduce OCR casually. Add it only when implementing a feature that actu
|
|||||||
|
|
||||||
## Working conventions
|
## Working conventions
|
||||||
|
|
||||||
Use `.scratchpad/` (create if missing) in the project root for temporary/intermediate files — e.g. cropped calibration images from `screenshots/cafe/sparkle/`, one-off debug output. Never write to `/tmp` or `/private/tmp`.
|
Use `scratchpad/` (create if missing) in the project root for temporary/intermediate files — e.g. cropped calibration images from `screenshots/cafe/sparkle/`, one-off debug output. Never write to `/tmp` or `/private/tmp`.
|
||||||
|
|
||||||
## Bash policy
|
## Bash policy
|
||||||
|
|
||||||
@ -319,7 +319,7 @@ The detector should support:
|
|||||||
- threshold tuning
|
- threshold tuning
|
||||||
- masked matching
|
- masked matching
|
||||||
- click-offset handling
|
- click-offset handling
|
||||||
- debug image output to `.scratchpad/`
|
- debug image output to `scratchpad/`
|
||||||
|
|
||||||
Avoid one Python cold start per click attempt where possible. Prefer long-running Python task logic that can take repeated screenshots and click repeatedly from one process.
|
Avoid one Python cold start per click attempt where possible. Prefer long-running Python task logic that can take repeated screenshots and click repeatedly from one process.
|
||||||
|
|
||||||
@ -385,7 +385,7 @@ Use this format:
|
|||||||
|
|
||||||
## Working conventions
|
## Working conventions
|
||||||
|
|
||||||
Use `.scratchpad/` for temporary or intermediate files.
|
Use `scratchpad/` for temporary or intermediate files.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
@ -421,7 +421,7 @@ Example:
|
|||||||
ssh nik-gpu "~/ba_dailies.sh cafe"
|
ssh nik-gpu "~/ba_dailies.sh cafe"
|
||||||
```
|
```
|
||||||
|
|
||||||
When debugging image matching, write debug images to `.scratchpad/`.
|
When debugging image matching, write debug images to `scratchpad/`.
|
||||||
|
|
||||||
## Existing features
|
## Existing features
|
||||||
|
|
||||||
|
|||||||
@ -29,6 +29,7 @@ Current task status:
|
|||||||
|---|---|
|
|---|---|
|
||||||
| `mailbox` | Real Python (`ba_auto/tasks/mailbox.py`). Verifies the mailbox panel actually opened (via a pixel-color probe, `driver.color_at`) before clicking "claim all" or pressing any further keys. Retries the open-click up to 3 times before giving up safely. |
|
| `mailbox` | Real Python (`ba_auto/tasks/mailbox.py`). Verifies the mailbox panel actually opened (via a pixel-color probe, `driver.color_at`) before clicking "claim all" or pressing any further keys. Retries the open-click up to 3 times before giving up safely. |
|
||||||
| `cafe` | Real Python (`ba_auto/tasks/cafe.py`). Verifies each room/dialog transition the same way as `mailbox` before acting; sparkle detection runs in-process via `ba_auto/detector.py` instead of shelling out per click. See "Fixed: the exit-game dialog bug" below for what this replaced, and `plan.md` Phase 6 follow-up for the multi-scale detection + persistent-polling changes made after a "farming affection doesn't happen" report. |
|
| `cafe` | Real Python (`ba_auto/tasks/cafe.py`). Verifies each room/dialog transition the same way as `mailbox` before acting; sparkle detection runs in-process via `ba_auto/detector.py` instead of shelling out per click. See "Fixed: the exit-game dialog bug" below for what this replaced, and `plan.md` Phase 6 follow-up for the multi-scale detection + persistent-polling changes made after a "farming affection doesn't happen" report. |
|
||||||
|
| `stamina` | Real Python (`ba_auto/tasks/stamina.py`). Opens the Mission panel and claims via its bulk "一括受取" button (Enter key) when enabled. Does **not** touch the Pyroxene Purchase (青輝石購入) menu's free-AP claim — that's a real-money purchase screen and was deliberately left unautomated; see `plan.md` Phase 8. |
|
||||||
|
|
||||||
## Prerequisites on nik-gpu
|
## Prerequisites on nik-gpu
|
||||||
|
|
||||||
@ -62,9 +63,10 @@ ssh nik-gpu "cd ~/repo/ba-auto-daily && ./setup.sh"
|
|||||||
The game must already be running on `nik-gpu` (window titled `BlueArchive`). Then, on `nik-gpu`:
|
The game must already be running on `nik-gpu` (window titled `BlueArchive`). Then, on `nik-gpu`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~/ba_dailies.sh # default: mailbox, then cafe
|
~/ba_dailies.sh # default: mailbox, cafe, then stamina
|
||||||
~/ba_dailies.sh mailbox # just mailbox
|
~/ba_dailies.sh mailbox # just mailbox
|
||||||
~/ba_dailies.sh cafe # just cafe
|
~/ba_dailies.sh cafe # just cafe
|
||||||
|
~/ba_dailies.sh stamina # just the Mission-panel bulk claim
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also run these remotely without a separate `ssh` login step:
|
You can also run these remotely without a separate `ssh` login step:
|
||||||
@ -73,7 +75,7 @@ You can also run these remotely without a separate `ssh` login step:
|
|||||||
ssh nik-gpu "~/ba_dailies.sh mailbox"
|
ssh nik-gpu "~/ba_dailies.sh mailbox"
|
||||||
```
|
```
|
||||||
|
|
||||||
Exit code `0` means the script ran to completion without a Python exception — it does **not** by itself guarantee the in-game action succeeded. Both `mailbox` and `cafe` log what they actually detected and did (or why they safely aborted), so check the log output, not just the exit code.
|
Exit code `0` means the script ran to completion without a Python exception — it does **not** by itself guarantee the in-game action succeeded. `mailbox`, `cafe`, and `stamina` all log what they actually detected and did (or why they safely aborted), so check the log output, not just the exit code.
|
||||||
|
|
||||||
## How to watch/verify it
|
## How to watch/verify it
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,12 @@ os.makedirs(SCRATCHPAD_DIR, exist_ok=True)
|
|||||||
MAILBOX_ICON = (1732, 50)
|
MAILBOX_ICON = (1732, 50)
|
||||||
CLAIM_ALL = (1691, 1128)
|
CLAIM_ALL = (1691, 1128)
|
||||||
|
|
||||||
|
MISSION_ICON = (75, 350)
|
||||||
|
# Background pixel inside the "一括受取" (claim all) button on the Mission
|
||||||
|
# panel: bright yellow (r~250, r-b~180+) when something is claimable, flat
|
||||||
|
# grey (r-b<20) when not. Calibrated live at 1920x1200.
|
||||||
|
MISSION_CLAIM_PROBE = (1600, 1100)
|
||||||
|
|
||||||
CAFE_ICON = (165, 1100)
|
CAFE_ICON = (165, 1100)
|
||||||
CAFE_ROOM_SWITCH = (190, 160)
|
CAFE_ROOM_SWITCH = (190, 160)
|
||||||
CAFE_INCOME = (1780, 1105)
|
CAFE_INCOME = (1780, 1105)
|
||||||
|
|||||||
@ -29,7 +29,13 @@ def focus_game():
|
|||||||
|
|
||||||
|
|
||||||
def click(x, y):
|
def click(x, y):
|
||||||
run_command(["xdotool", "mousemove", str(x), str(y), "click", "1"])
|
# A combined "mousemove X Y click 1" invocation is unreliable here --
|
||||||
|
# empirically (see plan.md's click-flakiness writeups) the game's input
|
||||||
|
# handler sometimes misses clicks fired before it's processed the move.
|
||||||
|
# Splitting into separate commands with a short pause between fixes it.
|
||||||
|
run_command(["xdotool", "mousemove", str(x), str(y)])
|
||||||
|
wait(0.2)
|
||||||
|
run_command(["xdotool", "click", "1"])
|
||||||
wait(0.5)
|
wait(0.5)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ Maps each local feature to the corresponding `~/repo/baas-reference/module/...`
|
|||||||
|---|---|---|---|---|---|
|
|---|---|---|---|---|---|
|
||||||
| Mailbox | `module/mail.py` | `to_mail`, `implement` | `ba_auto/tasks/mailbox.py` | tap/click via xdotool, screenshot via scrot, `color.rgb_in_range` → `driver.color_at` pixel-probe check | Migrated: real Python, state-verified via color probe (no legacy bridge) |
|
| Mailbox | `module/mail.py` | `to_mail`, `implement` | `ba_auto/tasks/mailbox.py` | tap/click via xdotool, screenshot via scrot, `color.rgb_in_range` → `driver.color_at` pixel-probe check | Migrated: real Python, state-verified via color probe (no legacy bridge) |
|
||||||
| Cafe | `module/cafe_reward.py` | `to_cafe`, `interaction_for_cafe_solve_method3`, `collect` | `ba_auto/tasks/cafe.py` | `picture.co_detect`/`color.rgb_in_range` → `driver.color_at` pixel-probe checks; sparkle template match ported in-process into `ba_auto/detector.py` (`find_cafe_sparkle`, now multi-scale) | Migrated: real Python, state-verified via color probes (no legacy bridge). Pat loop now polls for the full attempt budget instead of stopping on the first miss (see `plan.md` Phase 6 follow-up) — not yet confirmed against a live sparkle since none was available during testing |
|
| Cafe | `module/cafe_reward.py` | `to_cafe`, `interaction_for_cafe_solve_method3`, `collect` | `ba_auto/tasks/cafe.py` | `picture.co_detect`/`color.rgb_in_range` → `driver.color_at` pixel-probe checks; sparkle template match ported in-process into `ba_auto/detector.py` (`find_cafe_sparkle`, now multi-scale) | Migrated: real Python, state-verified via color probes (no legacy bridge). Pat loop now polls for the full attempt budget instead of stopping on the first miss (see `plan.md` Phase 6 follow-up) — not yet confirmed against a live sparkle since none was available during testing |
|
||||||
| Stamina/AP | `module/collect_daily_free_power.py`, `module/collect_daily_task_power.py` | Need to inspect | `ba_auto/tasks/stamina.py` | color checks/clicks via local driver | Not started |
|
| Stamina/AP | `module/collect_daily_free_power.py`, `module/collect_daily_task_power.py` | `to_tasks`/`implement` (task-power, ported); `to_purchase_pyroxenes_menu` (free-power, not ported) | `ba_auto/tasks/stamina.py` | `color.rgb_in_range` → `driver.color_at`; reference's per-tab claim loop → live UI's single "一括受取" bulk-claim button + Enter | Partially migrated: Mission-panel claim done (see `plan.md` Phase 8). Daily Free Power (real-money purchase menu) deliberately not automated |
|
||||||
| Group/Club AP | `module/group.py` | Need to inspect | `ba_auto/tasks/group.py` | fixed click + state check via local driver | Not started |
|
| Group/Club AP | `module/group.py` | Need to inspect | `ba_auto/tasks/group.py` | fixed click + state check via local driver | Not started |
|
||||||
| Bounty | `module/rewarded_task.py` | Need to inspect | `ba_auto/tasks/bounty.py` | sweep/color/OCR adaptation | Not started |
|
| Bounty | `module/rewarded_task.py` | Need to inspect | `ba_auto/tasks/bounty.py` | sweep/color/OCR adaptation | Not started |
|
||||||
| Commissions | `module/clear_special_task_power.py` | Need to inspect | `ba_auto/tasks/commission.py` | sweep/color adaptation | Not started |
|
| Commissions | `module/clear_special_task_power.py` | Need to inspect | `ba_auto/tasks/commission.py` | sweep/color adaptation | Not started |
|
||||||
|
|||||||
59
ba_auto/tasks/stamina.py
Normal file
59
ba_auto/tasks/stamina.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
"""Mission/task-menu AP+pyroxene claim. Ported from baas-reference module/collect_daily_task_power.py's claim-loop pattern (its rgb_in_range checks replaced with driver.color_at probes)."""
|
||||||
|
|
||||||
|
from ba_auto import navigation
|
||||||
|
|
||||||
|
OPEN_RETRIES = 3
|
||||||
|
# One claim-all round is normally enough (button goes grey right after), but
|
||||||
|
# bound it in case multiple reward reveals need dismissing in sequence.
|
||||||
|
CLAIM_MAX_ROUNDS = 5
|
||||||
|
|
||||||
|
# Yellow "one-click claim all" button vs. its own flat-grey disabled state --
|
||||||
|
# same background-pixel-probe idea as mailbox.CLAIM_ALL_PROBE/cafe.CLAIM_PROBE,
|
||||||
|
# but distinguished by hue (yellow has a big r-b gap; grey doesn't) since the
|
||||||
|
# button's grey isn't a single fixed RGB the way mailbox/cafe's are.
|
||||||
|
CLAIM_ENABLED_MIN_R = 230
|
||||||
|
CLAIM_ENABLED_MIN_RB_GAP = 100
|
||||||
|
|
||||||
|
|
||||||
|
def _claim_enabled(driver, config):
|
||||||
|
r, g, b = driver.color_at(*config.MISSION_CLAIM_PROBE)
|
||||||
|
return r > CLAIM_ENABLED_MIN_R and (r - b) > CLAIM_ENABLED_MIN_RB_GAP
|
||||||
|
|
||||||
|
|
||||||
|
def run(driver, config):
|
||||||
|
driver.focus_game()
|
||||||
|
|
||||||
|
opened = False
|
||||||
|
for attempt in range(1, OPEN_RETRIES + 1):
|
||||||
|
driver.focus_game()
|
||||||
|
driver.click(*config.MISSION_ICON)
|
||||||
|
driver.wait(2)
|
||||||
|
if navigation.is_on_subscreen(driver):
|
||||||
|
opened = True
|
||||||
|
break
|
||||||
|
print(f"[stamina] mission panel not detected after click (attempt {attempt}/{OPEN_RETRIES})")
|
||||||
|
|
||||||
|
if not opened:
|
||||||
|
print("[stamina] could not confirm mission panel is open, aborting without pressing further keys")
|
||||||
|
return
|
||||||
|
|
||||||
|
claimed_any = False
|
||||||
|
for _ in range(CLAIM_MAX_ROUNDS):
|
||||||
|
if not _claim_enabled(driver, config):
|
||||||
|
break
|
||||||
|
print("[stamina] claiming mission rewards")
|
||||||
|
driver.keypress("Return")
|
||||||
|
driver.wait(1.5)
|
||||||
|
# dismiss the reward-reveal popup ("TOUCH" prompt); harmless no-op if
|
||||||
|
# nothing is actually showing, same assumption as cafe's room-entry dismiss
|
||||||
|
driver.keypress("Return")
|
||||||
|
driver.wait(1.5)
|
||||||
|
claimed_any = True
|
||||||
|
|
||||||
|
if not claimed_any:
|
||||||
|
print("[stamina] nothing to claim")
|
||||||
|
|
||||||
|
if navigation.is_on_subscreen(driver):
|
||||||
|
driver.keypress("Escape")
|
||||||
|
driver.wait(1.5)
|
||||||
|
print("[stamina] Done.")
|
||||||
@ -3,13 +3,14 @@
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from ba_auto import config, driver
|
from ba_auto import config, driver
|
||||||
from ba_auto.tasks import cafe, mailbox
|
from ba_auto.tasks import cafe, mailbox, stamina
|
||||||
|
|
||||||
TASKS = {
|
TASKS = {
|
||||||
"mailbox": mailbox.run,
|
"mailbox": mailbox.run,
|
||||||
"cafe": cafe.run,
|
"cafe": cafe.run,
|
||||||
|
"stamina": stamina.run,
|
||||||
}
|
}
|
||||||
DEFAULT_ORDER = ["mailbox", "cafe"]
|
DEFAULT_ORDER = ["mailbox", "cafe", "stamina"]
|
||||||
|
|
||||||
|
|
||||||
def main(argv):
|
def main(argv):
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -348,7 +348,7 @@
|
|||||||
"norm_label": "screenshots/ reference-capture directory"
|
"norm_label": "screenshots/ reference-capture directory"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": ".scratchpad/ working-file convention",
|
"label": "scratchpad/ working-file convention",
|
||||||
"file_type": "concept",
|
"file_type": "concept",
|
||||||
"source_file": "CLAUDE.md",
|
"source_file": "CLAUDE.md",
|
||||||
"source_location": "L38",
|
"source_location": "L38",
|
||||||
@ -358,7 +358,7 @@
|
|||||||
"contributor": null,
|
"contributor": null,
|
||||||
"id": "claude_scratchpad_dir",
|
"id": "claude_scratchpad_dir",
|
||||||
"community": 0,
|
"community": 0,
|
||||||
"norm_label": ".scratchpad/ working-file convention"
|
"norm_label": "scratchpad/ working-file convention"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "~/.venvs/ba-auto-daily Python venv (opencv-python, numpy)",
|
"label": "~/.venvs/ba-auto-daily Python venv (opencv-python, numpy)",
|
||||||
|
|||||||
34
plan.md
34
plan.md
@ -136,7 +136,7 @@ Initial seed:
|
|||||||
|---|---|---|---|---|---|
|
|---|---|---|---|---|---|
|
||||||
| Mailbox | Need to confirm in reference | Need to inspect | `ba_auto/tasks/mailbox.py` | tap/click via xdotool, screenshot via scrot | Existing Bash behavior; migrate to Python |
|
| Mailbox | Need to confirm in reference | Need to inspect | `ba_auto/tasks/mailbox.py` | tap/click via xdotool, screenshot via scrot | Existing Bash behavior; migrate to Python |
|
||||||
| Cafe | `module/cafe_reward.py` | `to_cafe`, `interaction_for_cafe_solve_method3`, `collect` | `ba_auto/tasks/cafe.py` | `picture.co_detect`/`color.rgb_in_range` → `driver.color_at` pixel-probe checks; sparkle template match ported in-process into `ba_auto/detector.py` | Migrated: real Python, state-verified via color probes, no legacy bridge |
|
| Cafe | `module/cafe_reward.py` | `to_cafe`, `interaction_for_cafe_solve_method3`, `collect` | `ba_auto/tasks/cafe.py` | `picture.co_detect`/`color.rgb_in_range` → `driver.color_at` pixel-probe checks; sparkle template match ported in-process into `ba_auto/detector.py` | Migrated: real Python, state-verified via color probes, no legacy bridge |
|
||||||
| Stamina/AP | `module/collect_daily_free_power.py`, `module/collect_daily_task_power.py` | Need to inspect | `ba_auto/tasks/stamina.py` | color checks/clicks via local driver | Not started |
|
| Stamina/AP | `module/collect_daily_free_power.py`, `module/collect_daily_task_power.py` | `to_tasks`/`implement` (task-power, ported); `to_purchase_pyroxenes_menu`/`detect_free_power_availability` (free-power, not ported — real-money purchase menu) | `ba_auto/tasks/stamina.py` | `color.rgb_in_range` → `driver.color_at`; reference's per-tab claim loop replaced by the live UI's single "一括受取" (claim-all) button, triggered via Enter | Partially migrated (Phase 8): Mission-panel task/weekly/achievement claim done. Daily Free Power deliberately not implemented. |
|
||||||
| Group/Club AP | `module/group.py` | Need to inspect | `ba_auto/tasks/group.py` | fixed click + state check via local driver | Not started |
|
| Group/Club AP | `module/group.py` | Need to inspect | `ba_auto/tasks/group.py` | fixed click + state check via local driver | Not started |
|
||||||
| Bounty | `module/rewarded_task.py` | Need to inspect | `ba_auto/tasks/bounty.py` | sweep/color/OCR adaptation | Not started |
|
| Bounty | `module/rewarded_task.py` | Need to inspect | `ba_auto/tasks/bounty.py` | sweep/color/OCR adaptation | Not started |
|
||||||
| Commissions | `module/clear_special_task_power.py` | Need to inspect | `ba_auto/tasks/commission.py` | sweep/color adaptation | Not started |
|
| Commissions | `module/clear_special_task_power.py` | Need to inspect | `ba_auto/tasks/commission.py` | sweep/color adaptation | Not started |
|
||||||
@ -153,8 +153,9 @@ Do not implement a feature without filling at least the relevant row.
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Mailbox claim | Migrated: `ba_auto/tasks/mailbox.py` uses `driver.color_at` to verify the panel opened before acting (found live-testing bug: a marginal icon coordinate could miss and cascade into pressing Escape on the home screen, which triggers Blue Archive's own exit-game confirmation) | Done |
|
| Mailbox claim | Migrated: `ba_auto/tasks/mailbox.py` uses `driver.color_at` to verify the panel opened before acting (found live-testing bug: a marginal icon coordinate could miss and cascade into pressing Escape on the home screen, which triggers Blue Archive's own exit-game confirmation) | Done |
|
||||||
| Cafe pats + income | Migrated: `ba_auto/tasks/cafe.py` verifies each room/dialog opened via `driver.color_at` before acting; sparkle detection now runs in-process via `ba_auto/detector.py` instead of a per-click subprocess | Done |
|
| Cafe pats + income | Migrated: `ba_auto/tasks/cafe.py` verifies each room/dialog opened via `driver.color_at` before acting; sparkle detection now runs in-process via `ba_auto/detector.py` instead of a per-click subprocess | Done |
|
||||||
| Shared driver | `ba_auto/driver.py` built (`run_command`, `focus_game`, `click`, `keypress`, `screenshot`, `wait`, `color_at`); wired into both `mailbox.py` and `cafe.py` | Extend with new primitives as future tasks need them |
|
| Stamina/AP (mission claim) | Migrated (partial, Phase 8): `ba_auto/tasks/stamina.py` claims the Mission panel's bulk "一括受取" button. Daily Free Power (real-money purchase menu) intentionally not implemented | Daily Free Power still not started |
|
||||||
| Python CLI | Built: `ba_daily.py` dispatches `mailbox`/`cafe`/default flow | Extend as new tasks are added |
|
| Shared driver | `ba_auto/driver.py` built (`run_command`, `focus_game`, `click`, `move_mouse`, `keypress`, `screenshot`, `wait`, `color_at`); `click()` now splits `mousemove`/`click` into two xdotool calls (Phase 8 finding — fixes a real source of click flakiness); wired into `mailbox.py`, `cafe.py`, `stamina.py` | Extend with new primitives as future tasks need them |
|
||||||
|
| Python CLI | Built: `ba_daily.py` dispatches `mailbox`/`cafe`/`stamina`/default flow | Extend as new tasks are added |
|
||||||
| Reference mapping | Built: `ba_auto/reference_notes/mapping.md` | Fill in reference file/function columns per feature |
|
| Reference mapping | Built: `ba_auto/reference_notes/mapping.md` | Fill in reference file/function columns per feature |
|
||||||
| Everything else | Not started | Implement reference-first in Python |
|
| Everything else | Not started | Implement reference-first in Python |
|
||||||
|
|
||||||
@ -289,6 +290,19 @@ What was directly verified live after these changes:
|
|||||||
|
|
||||||
**Not yet verified**: an actual end-to-end pat (detect → click → affection-up dialog dismissed) succeeding after this round's changes, because no interactable sparkle was available during testing to exercise it against. Re-run `~/ba_dailies.sh cafe` once interactions have had time to regenerate and confirm `[cafe] patted N sparkle(s)` appears with N > 0.
|
**Not yet verified**: an actual end-to-end pat (detect → click → affection-up dialog dismissed) succeeding after this round's changes, because no interactable sparkle was available during testing to exercise it against. Re-run `~/ba_dailies.sh cafe` once interactions have had time to regenerate and confirm `[cafe] patted N sparkle(s)` appears with N > 0.
|
||||||
|
|
||||||
|
### Phase 8: Stamina/AP mission claim
|
||||||
|
|
||||||
|
**Status: Partially done.** Read `module/collect_daily_task_power.py` (the "Tasks" menu claim loop — `to_tasks` + `rgb_in_range` checks against two fixed pixel pairs, click, dismiss, repeat) and `module/collect_daily_free_power.py` (a `picture.co_detect` state-machine walk into the Pyroxene Purchase menu's Package tab to claim a genuinely free 10 AP item). Live reconnaissance on the home screen found the direct local equivalents: a `ミッション` (Mission) icon opening a panel with per-tab claim buttons *and* a single bulk "一括受取" (claim all) button whose keyboard shortcut is literally Enter — much simpler than porting the reference's per-tab color-probe loop. `ba_auto/tasks/stamina.py` opens the Mission panel, checks whether "一括受取" is enabled (bright yellow vs. flat grey background probe at `config.MISSION_CLAIM_PROBE`), and if so presses Enter to claim, Enter again to dismiss the reward-reveal card (same "harmless no-op if absent" assumption as cafe's room-entry dismiss), bounded to a few rounds in case multiple rewards queue up.
|
||||||
|
|
||||||
|
The 青輝石購入 (Pyroxene Purchase) icon — reference's Daily Free Power entry point — was opened once to confirm the free-claim flow's location, but turned out to be a real-money purchase menu (¥3,000–¥4,900 package buttons visible immediately) with the genuinely-free item buried in a further tab. Given `plan.md`'s own purchase-safety rules ("avoid unbounded spending", "avoid buying unknown items"), this was **deliberately not automated this round** — the dialog was closed without navigating further. Treat this as a separate, explicitly-confirmed piece of future work, not an oversight.
|
||||||
|
|
||||||
|
Two real bugs found and fixed during live calibration, both worth remembering for future coordinate-hunting:
|
||||||
|
|
||||||
|
- **Visual gridline coordinate estimates were wrong twice in a row.** Reading icon bounds off a scaled/annotated screenshot crop by eye put the Mission icon's center at `(146, 352)` — which is actually in the dead space between the Mission and Pyroxene-Purchase icons, close enough to the latter's edge that clicks there landed on Pyroxene Purchase instead. The fix was sampling actual pixel colors along a scanline (`img.getpixel`) to find each icon's true left/right edge against the background, rather than eyeballing gridlines — this put the real center at `(75, 350)`, squarely inside the icon graphic, confirmed live. Lesson: for icon coordinates, prefer a pixel-boundary scan over a visual grid-overlay estimate.
|
||||||
|
- **`driver.click()`'s combined `xdotool mousemove X Y click 1` invocation is unreliable; splitting it fixed a chunk of this project's long-documented click flakiness.** Repeated single-click tests at a *verified-correct* coordinate still missed intermittently until the mousemove and click were issued as two separate `xdotool` calls with a short (0.2s) pause between them — after that, every subsequent click registered. This plausibly explains some of the "icon click missed on the first attempt, worked on retry" flakiness documented in Phases 5–6 (mailbox/cafe icons). Applied to `driver.click()` itself (project-wide, since all tasks share it) rather than special-cased in `stamina.py`; regression-tested live against `mailbox` and `cafe` after the change — both still work.
|
||||||
|
|
||||||
|
Not yet done: Group/Club AP, and Daily Free Power (see above).
|
||||||
|
|
||||||
### Phase 7: setup.sh update
|
### Phase 7: setup.sh update
|
||||||
|
|
||||||
**Status: Done — `setup.sh` deploys `ba_daily.py` and `ba_auto/`.** `scripts/ba_dailies_legacy.sh` and `scripts/detect_and_click.py` were deleted once mailbox and cafe both migrated off them (Phases 5–6); `setup.sh` no longer references either.
|
**Status: Done — `setup.sh` deploys `ba_daily.py` and `ba_auto/`.** `scripts/ba_dailies_legacy.sh` and `scripts/detect_and_click.py` were deleted once mailbox and cafe both migrated off them (Phases 5–6); `setup.sh` no longer references either.
|
||||||
@ -380,12 +394,12 @@ Goal (all done):
|
|||||||
|
|
||||||
### 2. Stamina/AP sweep
|
### 2. Stamina/AP sweep
|
||||||
|
|
||||||
|
**Status: Partially done — see Phase 8.**
|
||||||
|
|
||||||
Claim:
|
Claim:
|
||||||
|
|
||||||
- daily free AP purchase
|
- ~~daily free AP purchase~~ — deferred; entry point is a real-money purchase menu, needs explicit confirmation before automating
|
||||||
- daily task-menu AP/pyroxene rewards
|
- daily task-menu AP/pyroxene rewards — done, via the Mission panel's bulk claim button
|
||||||
|
|
||||||
Likely mostly color/state detection and fixed clicks.
|
|
||||||
|
|
||||||
Reference:
|
Reference:
|
||||||
|
|
||||||
@ -396,7 +410,7 @@ Reference:
|
|||||||
|
|
||||||
Local target: `ba_auto/tasks/stamina.py`
|
Local target: `ba_auto/tasks/stamina.py`
|
||||||
|
|
||||||
OCR: Probably not needed for first version.
|
OCR: Not needed — turned out to be a single bulk-claim button + Enter, no per-item detection required.
|
||||||
|
|
||||||
### 3. Club/Group AP claim
|
### 3. Club/Group AP claim
|
||||||
|
|
||||||
@ -717,7 +731,7 @@ server = JP
|
|||||||
game_window_name = BlueArchive
|
game_window_name = BlueArchive
|
||||||
display = :0
|
display = :0
|
||||||
asset_dir = ~/ba_assets
|
asset_dir = ~/ba_assets
|
||||||
screenshot_dir = .scratchpad/
|
screenshot_dir = scratchpad/
|
||||||
cafe_max_clicks_per_room
|
cafe_max_clicks_per_room
|
||||||
story_sweep_target
|
story_sweep_target
|
||||||
shop_buy_list
|
shop_buy_list
|
||||||
@ -730,7 +744,7 @@ Keep config explicit. Do not bury user-specific settings deep inside task logic.
|
|||||||
|
|
||||||
## Debugging conventions
|
## Debugging conventions
|
||||||
|
|
||||||
Use `.scratchpad/` for:
|
Use `scratchpad/` for:
|
||||||
|
|
||||||
- temporary screenshots
|
- temporary screenshots
|
||||||
- cropped templates
|
- cropped templates
|
||||||
|
|||||||
2
setup.sh
2
setup.sh
@ -47,5 +47,5 @@ rm -rf "$HOME/ba_auto"
|
|||||||
cp -r ba_auto "$HOME/ba_auto"
|
cp -r ba_auto "$HOME/ba_auto"
|
||||||
|
|
||||||
echo "== Done =="
|
echo "== Done =="
|
||||||
echo "Run with: ~/ba_dailies.sh [mailbox|cafe]"
|
echo "Run with: ~/ba_dailies.sh [mailbox|cafe|stamina]"
|
||||||
echo "(requires the game already running, window titled 'BlueArchive')"
|
echo "(requires the game already running, window titled 'BlueArchive')"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user