- Implemented `serialize_active_domains` function to gather and format active hidden domains from the game world.
- Updated `game_loop` to include active domains in the broadcast state.
- Enhanced `StatusBar` component to display active domains with a new `StatusWidget`, including dynamic labels and colors based on the number of active domains.
- Added localization support for hidden domain messages in both English and Chinese.
- Updated the world store to manage active domains state and synchronize with the backend.
* feat: add avatar metrics tracking feature (#110)
Add AvatarMetrics dataclass for tracking avatar state snapshots
- Add AvatarMetrics dataclass for recording monthly snapshots
- Add metrics_history field to Avatar with opt-in tracking
- Implement automatic monthly snapshot recording in Simulator
- Add backward compatibility support for existing save files
- Set default tracking limit to 1200 months (100 years)
- Add comprehensive tests with 100% coverage
- Move documentation to specs directory with simplified chinese
* fix: convert Traditional Chinese comments to Simplified Chinese
修正程式碼中的繁體中文註解為簡體中文,以符合專案規範。
Fix Traditional Chinese comments to Simplified Chinese in codebase.
* feat: add draggable sidebar resizer
- Add resizer handle between map and event panel
- Sidebar width adjustable from 300px to 50% screen width
- Default width remains 400px
- Auto-adjust on window resize
* fix: preserve map zoom when resizing sidebar
Only update viewport screen size without re-fitting the map
* fix: use window size for canvas to prevent map scaling on resize
- Canvas size now based on window instead of container
- Sidebar resize only clips the visible area, map stays same size
- Remove CSS stretch on canvas element
* docs: update sidebar-resizer spec with canvas fix
* fix: use str() instead of .value for realm i18n display
Fix bug where user-facing messages displayed raw enum values like
"FOUNDATION_ESTABLISHMENT" instead of translated names like "筑基".
The Realm and Stage classes already have __str__ methods that return
i18n translated text, but several places were incorrectly using
.value which returns the raw enum string.
Changed files:
- src/classes/single_choice.py: item exchange messages
- src/classes/kill_and_grab.py: loot messages
- src/classes/fortune.py: fortune discovery messages
- src/classes/avatar/inventory_mixin.py: purchase error messages
Also added unit tests and integration tests to prevent regression.
* test: add integration tests for all modified files
Add tests covering:
- kill_and_grab.py: context string realm display
- fortune.py: weapon/auxiliary intro realm display
- inventory_mixin.py: can_buy_item error message realm display
* test(web): add comprehensive tests for all Pinia stores
* test(web): add edge case tests for Pinia stores
* test(web): document race condition bugs in ui and world stores
* fix(web): fix race condition bugs in ui and world stores
- ui.ts: Add detailRequestId counter to prevent stale responses from
overwriting fresh data when reselecting the same target
- world.ts: Add eventsRequestId counter to prevent stale responses
when filter changes rapidly via resetEvents
- Update tests to verify the fix works correctly
* fix(web): fix race condition in fetchInitStatus
- Add fetchStatusRequestId counter to prevent stale responses from
overwriting fresh data when fetchInitStatus is called rapidly
- Add test that first proves the bug exists, then verifies the fix
* fix(web): fix race condition in fetchState
Add fetchStateRequestId counter to prevent stale responses from
overwriting fresh data when fetchState is called rapidly.
* test(web): add missing edge case tests for world store
- Add changePhenomenon API failure test
- Add initialize concurrent calls test
- Add getPhenomenaList concurrent calls test
Total: 108 tests
* test(web): add comprehensive socket store tests
- Add init() duplicate call guard test
- Add setup listener tests
- Add message handling tests (tick, game_reinitialized)
- Add status change handling tests
Total: 118 tests
* test(web): add missing socket message handling tests
- Add llm_config_required message tests
- Add unknown message type test
Total: 121 tests
* test(web): add handleTick edge case tests
- Add test for avatars without id (ignored)
- Add test for empty events array
- Add test for events filtered to empty
Total: 124 tests
* test: add edge case tests for game initialization
* test: add 3 more edge case tests for game initialization
* test: add 8 more edge case tests for comprehensive coverage
* docs: add comprehensive coverage report to test file header
Use single-pass regex replacement instead of multiple replaceAll calls.
This prevents shorter names from matching inside already-replaced longer names.
For example, with names '张三' and '张三丰', the text '张三丰是大师' now
correctly highlights only '张三丰', not '张三' within it.
* fix: make cooldown_action decorator properly await async finish()
The decorator was incorrectly wrapping the async finish() method with a sync
wrapper, causing cooldown to be recorded BEFORE the action actually executed.
This fix:
- Changes wrapper to async def finish()
- Awaits original_finish() before recording cooldown
- Ensures cooldown is only recorded on successful execution
Fixes#74
* test: add test to verify cooldown not recorded on failure
This test actually reveals the async/await bug:
- Creates a FailingAction that raises in finish()
- Verifies cooldown is NOT recorded when action fails
- Fails with buggy sync wrapper, passes with async fix