Commit Graph

123 Commits

Author SHA1 Message Date
Zihao Xu
406d62f983 test(web): add tests for utility functions (#102)
Add tests for utility modules:
- formatters/number.ts: formatHp, formatAge
- mapStyles.ts: REGION_STYLES, getRegionTextStyle
- procedural.ts: getClusteredTileVariant
- theme.ts: GRADE_COLORS, getEntityColor

Total: 52 new tests added

Closes #87
2026-01-26 10:01:38 +08:00
Zihao Xu
c406d2988f feat: add draggable sidebar resizer (#100)
* 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
2026-01-25 18:44:54 +08:00
Zihao Xu
2b5ec24455 test(web): add tests for all composables (#101)
Add comprehensive tests for Vue composables:
- useSharedTicker (100% coverage)
- useTextures (97% coverage)
- useGameControl (92% coverage)
- useGameInit (69% coverage)

Tests cover:
- Lifecycle hooks (mount/unmount)
- State management
- Function exports
- Error handling
- LLM configuration flow
- Keyboard event handling

Closes #86
2026-01-25 01:17:02 -08:00
Zihao Xu
0d8a001f8c feat: add Gemini preset template for LLM settings (#97)
* feat: add Gemini preset template for LLM settings

* docs: add comment explaining Gemini /openai suffix requirement

* feat: update Gemini preset to use latest 3-pro and 3-flash models

* docs: improve comment to reference backend client.py implementation
2026-01-24 22:42:46 -08:00
4thfever
e1091fdf5a Feat/i18n (#92)
* feat: add vue-i18n

* feat: add vue-i18n

* feat: add vue-i18n

* feat: add language class

* add: en templates and configs

* add: en names

* refactor: name gender id and sect id

* feat(i18n): add gettext infrastructure for dynamic text translation (#81)

* feat(i18n): add gettext infrastructure for dynamic text translation

- Add src/i18n/ module with t() translation function
- Add .po/.mo files for zh_CN and en_US locales
- Update LanguageManager to reload translations on language change
- Add comprehensive tests (14 tests, all passing)
- Add implementation spec at docs/specs/i18n-dynamic-text.md

Phase 1 of i18n dynamic text implementation.

* feat(i18n): expand .po files with comprehensive translation entries

Add translation messages for:
- Battle result messages (fatal/non-fatal outcomes)
- Fortune event messages (item discovery, cultivation gains)
- Misfortune event messages (losses, damage, regression)
- Death reason messages
- Item exchange messages (equip, sell, discard)
- Single choice context and option labels
- Common labels (weapon, auxiliary, technique, elixir)

Both zh_CN and en_US locales updated with matching entries.

* test: add .po file integrity tests

* feat: i18n for actions

* feat: i18n for effects

* feat: i18n for gathering

* feat: i18n for classes

* feat: i18n for classes

* feat: i18n for classes

* feat: i18n for classes

* fix bugs

* fix bugs

* fix bugs

* fix bugs

* fix bugs

* fix bugs

* fix bugs

* fix bugs

* update csv

* update world info

* update prompt

* update prompt

* fix bug

* fix bug

* fix bug

* fix bug

* fix bug

* fix bug

* fix bug

* fix bug

* fix bug

* update

* update

* update

* update

* update

* update

* update

---------

Co-authored-by: Zihao Xu <xzhseh@gmail.com>
2026-01-24 13:47:23 +08:00
Zihao Xu
6f4b648d6e test(web): add comprehensive tests for all Pinia stores (#90)
* 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
2026-01-23 03:07:33 -08:00
bridge
2b8812852c feat: code owner 2026-01-20 23:23:14 +08:00
bridge
64732d6912 update: license & contributing 2026-01-20 21:12:55 +08:00
Zihao Xu
498249e83b fix: handle overlapping avatar names in highlightAvatarNames (#77)
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.
2026-01-19 23:46:42 -08:00
Zihao Xu
d4b9b7303d ci: add frontend tests to CI workflow (#68)
* ci: add frontend tests to CI workflow

* chore: sync package-lock.json with test dependencies

* test: skip failing overlapping names test (known bug)
2026-01-19 23:32:23 -08:00
Zihao Xu
5f236361dc feat: add Ollama preset for local LLM deployment (#76) 2026-01-19 23:31:36 -08:00
bridge
a7ab18ea1c fix: package bug 2026-01-19 21:26:09 +08:00
Zihao Xu
665d94addb test(web): add example frontend tests (#61)
* test(web): setup frontend test infrastructure

- Add testing dependencies (vitest, vue-test-utils, testing-library, jsdom, msw)
- Create vitest.config.ts with jsdom environment and coverage settings
- Create setup.ts with Pinia initialization and fake timers
- Add test scripts to package.json (test, test:run, test:coverage)

Closes #56, closes #57

* test(web): add example frontend tests

- Add system store tests (initial state, getters, togglePause)
- Add eventHelper utility tests (processNewEvents, mergeAndSortEvents, avatarIdToColor, highlightAvatarNames)

Closes #59
2026-01-19 20:48:43 +08:00
Zihao Xu
8bf5f64bc3 test(web): setup frontend test infrastructure (#60)
- Add testing dependencies (vitest, vue-test-utils, testing-library, jsdom, msw)
- Create vitest.config.ts with jsdom environment and coverage settings
- Create setup.ts with Pinia initialization and fake timers
- Add test scripts to package.json (test, test:run, test:coverage)

Closes #56, closes #57
2026-01-19 20:48:28 +08:00
Zihao Xu
1a34b7724b feat(web): make avatar names in event log clickable (#41)
When avatars overlap (e.g., during sparring, talking, dual cultivation),
it's hard to click on them directly. This adds the ability to click on
colored avatar names in the event panel to open their detail view.

- Modify highlightAvatarNames to include data-avatar-id attribute
- Add click event delegation in EventPanel
- Add hover styles for clickable names
2026-01-19 20:45:44 +08:00
bridge
2e04b718e8 update: splash 2026-01-18 21:49:13 +08:00
Zihao Xu
ce64c6b048 fix(web): decouple manual pause state from system pause behavior (#37)
The pause indicator was showing 'paused' while the game was still running
because isManualPaused was being modified by both user actions (clicking
pause button) and system actions (opening menu).

Changes:
- systemStore: pause()/resume() no longer modify isManualPaused, only
  togglePause() does (with optimistic update + rollback on failure)
- useGameControl: consolidate 3 overlapping watches into 1 clean watch
  that only handles menu open/close without polluting manual pause state
- App.vue: explicitly call resumeGame() API when game initializes
2026-01-18 16:59:44 +08:00
bridge
bd563b10f4 feat: add splash mp4 video 2026-01-18 16:11:34 +08:00
bridge
9b294ccba3 fix: game control bug 2026-01-15 08:55:01 +08:00
4thfever
df8b1b9433 Refactor/event (#31)
重构事件机制和部分拍卖会机制
2026-01-14 16:58:50 +08:00
4thfever
0d34b27fff Feat: Add splash layer (#29)
Add splash layer, support game start, settings, exit
Modify settings layer, add "go back to splash" and "exit"
Add character threshold for history input
Closes #28
2026-01-13 22:00:23 +08:00
4thfever
95e1f11502 Refactor/history (#25)
add multi process history modification
2026-01-12 23:25:53 +08:00
bridge
2caa5586be refactor history archi 2026-01-12 00:36:10 +08:00
bridge
287f9d2ae4 update history pytest 2026-01-12 00:20:15 +08:00
bridge
19b9ddd8ba refactor frontend 2026-01-11 22:44:05 +08:00
bridge
879a3c0d1f refactor frontend (not done) 2026-01-11 22:29:53 +08:00
bridge
08e28f52c7 refactor frontend (not done) 2026-01-11 22:15:45 +08:00
bridge
f33cfab0d5 refactor frontend (not done) 2026-01-11 22:08:01 +08:00
bridge
ff6038b786 fix: incorrect order in event panel 2026-01-11 19:26:05 +08:00
bridge
88cc7cd966 feat: add color to map avatar names 2026-01-11 18:54:34 +08:00
bridge
ac8c6c1c73 update tips 2026-01-10 00:50:30 +08:00
bridge
33b01fa0e9 fix web 2026-01-10 00:34:44 +08:00
bridge
59824d9cd5 update readme and tips 2026-01-09 00:49:16 +08:00
bridge
f8f0e8a59c update tips 2026-01-08 23:06:36 +08:00
bridge
f7d6554e9b update objective front end 2026-01-08 22:49:23 +08:00
bridge
a4dd29145f update tips 2026-01-08 22:35:42 +08:00
bridge
9c21259577 refactor: add store mixin into city regions & refactor buying action 2026-01-08 22:16:33 +08:00
Zihao Xu
9e75d8dd2e revert: remove SaveLoadPanel.vue changes 2026-01-08 21:12:18 +08:00
Zihao Xu
9485b62cfd feat: add loading screen with progress tracking
- Add async initialization with 6 phases: scanning_assets, loading_map,
  initializing_sects, generating_avatars, checking_llm, generating_initial_events
- Add /api/init-status endpoint for frontend polling
- Add /api/control/reinit endpoint for error recovery
- Add LoadingOverlay.vue component with:
  - Progress ring with gradient
  - Phase text in xianxia style (rotating messages for LLM phase)
  - Tips that rotate every 5 seconds
  - Time-based background transparency (fades to 80% over 20s)
  - Backdrop blur effect
  - Error state with retry button
- Preload map and avatars during LLM initialization for smoother UX
- Add comprehensive tests for init status API
2026-01-08 21:12:18 +08:00
Zihao Xu
8631be501b fix: prevent game from auto-starting to avoid stale initialization events
Problem:
When loading a save (e.g., from year 106), events from year 100 would appear.
This happened because the game auto-started on server startup and client
connection, generating initialization events before the user could load a save.

Solution:
1. Backend: Keep game paused on startup even if LLM check passes
2. Backend: Remove auto-resume on first WebSocket connection
3. Frontend: Start with game paused (isManualPaused = true)

Now the user must explicitly click 'resume' to start a new game, or load a
save first. This prevents the race condition where game_loop generates events
with stale world state.
2026-01-08 21:10:05 +08:00
Zihao Xu
a6b8198c3f Merge branch 'main' into xzhseh/sqlite-event-manager 2026-01-07 20:05:02 -08:00
bridge
b2a021bf8a rename item -> material & refactor buying action 2026-01-07 22:43:26 +08:00
bridge
1dfce734ef fix occupy & gift given bug 2026-01-07 20:11:01 +08:00
Zihao Xu
2e5a2c3c12 style: add comment to separate state and functions in world.ts 2026-01-07 01:02:17 -08:00
Zihao Xu
a1f08dd0ab feat: SQLite event storage with pagination and filtering
Implement SQLite-based event persistence as specified in sqlite-event-manager.md.

## Changes

### Backend
- **EventStorage** (`src/classes/event_storage.py`): New SQLite storage layer
  - Cursor-based pagination with compound cursor `{month_stamp}_{rowid}`
  - Avatar filtering (single and pair queries)
  - Major/minor event separation
  - Cleanup API with `keep_major` and `before_month_stamp` filters

- **EventManager** (`src/classes/event_manager.py`): Refactored to use SQLite
  - Delegates to EventStorage for persistence
  - Memory fallback mode for testing
  - New `get_events_paginated()` method

- **API** (`src/server/main.py`):
  - `GET /api/events` - Paginated event retrieval with filtering
  - `DELETE /api/events/cleanup` - User-triggered cleanup

### Frontend
- **EventPanel.vue**: Scroll-to-load pagination, dual-person filter UI
- **world.ts**: Event state management with pagination
- **game.ts**: New API client methods

### Testing
- 81 new tests for EventStorage, EventManager, and API
- Added `pytest-asyncio` and `httpx` to requirements.txt

## Known Issues: Save/Load is Currently Broken

After loading a saved game, the following issues occur:

1. **Wrong database used**: API returns events from the startup database instead
   of the loaded save's `_events.db` file
2. **Events from wrong time period**: Shows events from year 115 when loaded
   save is at year 114
3. **Pagination broken after load**: `has_more` returns `False` despite hundreds
   of events in the saved database
4. **Filter functionality broken**: Character selection filter stops working
   after loading a game

Root cause: `load_game.py` does not properly switch the EventManager's database
connection to the loaded save's events database.
2026-01-07 00:40:34 -08:00
bridge
649f66213e refactor cast action 2026-01-06 23:06:28 +08:00
bridge
5793c4d2b9 add lode 2026-01-06 23:04:56 +08:00
bridge
8a23dc5576 add lode 2026-01-06 23:01:25 +08:00
bridge
fa909e5a2a update frontend 2026-01-06 01:08:51 +08:00
bridge
b74014f9f2 add emotion 2026-01-04 22:49:20 +08:00