Commit Graph

679 Commits

Author SHA1 Message Date
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
6ed614814f feat: add i18n glossary in CSV format (Phase 0) (#67) 2026-01-20 20:54:33 +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
a1241a9156 fix: make cooldown_action decorator properly await async finish() (#75)
* 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
2026-01-20 15:32:14 +08:00
Zihao Xu
5f236361dc feat: add Ollama preset for local LLM deployment (#76) 2026-01-19 23:31:36 -08:00
Zihao Xu
a8666950b1 test: add comprehensive tests for mutual actions (talk, spar, impart) (#73)
- Talk: 31% -> 98% coverage
- Spar: 49% -> 100% coverage
- Impart: 37% -> 95% coverage
- Add 30 new test cases
- Overall coverage: 58.64% -> 60% (meets CI threshold)

Testing strategy: Mock LLM calls via call_llm_with_task_name

Closes #69
2026-01-19 23:09:38 -08:00
bridge
325c72e513 update: readme 2026-01-20 01:01:45 +08:00
bridge
2c9ef96c36 update: contributing 2026-01-19 21:56:09 +08:00
bridge
a7ab18ea1c fix: package bug v1.2.2 2026-01-19 21:26:09 +08:00
bridge
bf13cdf2d2 fix: incorrect relationship for new avatar 2026-01-19 21:14:20 +08:00
Zihao Xu
31d0c060e8 feat: enhance README with activity graph and contributor avatars (#65) 2026-01-19 20:50:33 +08:00
Zihao Xu
7f31d9884f test: add comprehensive tests for ai.py (13% -> 98% coverage) (#64)
- Test LLM response parsing (list and dict formats)
- Test null params conversion to empty dict
- Test invalid format handling and skipping
- Test emotion update logic with all emotion types
- Test fallback to CALM on invalid/missing emotion
- Test batch avatar processing
- Test AI.decide wrapper returns NULL_EVENT
- Test thinking field variants (avatar_thinking vs thinking)
- Add testing strategy documentation to test file

Closes #63
2026-01-19 20:49:24 +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
9677055faa fix: use sect_id instead of sect in fortune technique filter (#55)
PR #32 changed Technique.sect (str) to Technique.sect_id (int), but
fortune.py was not updated. This caused AttributeError when fortune
event triggered and tried to access t.sect.

Error: 'Technique' object has no attribute 'sect'
2026-01-19 20:48:05 +08:00
Zihao Xu
8f7c2cfa66 docs: add Codecov coverage badge to README (#54)
Closes #49
2026-01-19 20:47:49 +08:00
Zihao Xu
ee2964e151 ci: add coverage reporting, 60% threshold, and Codecov integration (#53)
- Add pytest-cov to CI dependencies
- Generate coverage report (xml + terminal)
- Set minimum coverage threshold to 60% (current: 63%, target: 90%)
- Upload coverage to Codecov
- Add 10 minute timeout

Closes #46, closes #47, closes #48
2026-01-19 20:47:26 +08:00
Zihao Xu
daa7a20679 test: add fixed_random_seed fixture with autouse=True (#52)
Ensures all tests have deterministic random behavior by setting
random.seed(42) before each test. This prevents flaky tests caused
by random number generation.

Closes #44
2026-01-19 20:46:59 +08:00
Zihao Xu
ed2d8720aa chore: configure coverage settings in pyproject.toml (#51)
- Add [tool.coverage.run] with source and branch coverage
- Add [tool.coverage.report] with exclude patterns and show_missing

Closes #43
2026-01-19 20:46:42 +08:00
Zihao Xu
5a82a186a7 chore: add pytest-cov to requirements (#50)
Closes #42
2026-01-19 20:46:09 +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
bridge
a075c1cc59 update: history prompt 2026-01-18 21:44:47 +08:00
bridge
bc6725b302 update: version v1.2.1 2026-01-18 17:25:27 +08:00
4thfever
6185d314af refactor: remove region_names dict, use regions traversal instead (#40)
The region_names dictionary was a redundant index that needed manual
sync when HistoryManager modified region names. This caused bugs where
resolve_query couldn't find regions by their new (history-modified) names.

Instead of maintaining two data structures (regions[id] and region_names[name]),
we now only use regions[id] as the single source of truth. The _resolve_region
function iterates over regions.values() to find matches by name.

This approach:
- Eliminates the sync bug entirely
- Simplifies the codebase
- Has negligible performance impact (region count is small)

Co-authored-by: Zihao Xu <xzhseh@gmail.com>
2026-01-18 17:13:28 +08:00
Zihao Xu
b68403e601 fix: mock StoryTeller in mock_llm_managers to prevent flaky test (#36)
The test_passive_update_loop test was flaky because when misfortune
randomly triggers during sim.step(), it calls StoryTeller.tell_story
which wasn't mocked, causing real LLM API calls to fail in CI.

Added StoryTeller.tell_story to the mock_llm_managers fixture.
2026-01-18 17:00:42 +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
47ad330b35 feat: data reload system 2026-01-18 16:53:24 +08:00
bridge
094a8fdd00 feat: data reload system 2026-01-18 16:47:54 +08:00
bridge
eb2c715069 feat: data reload system 2026-01-18 16:37:08 +08:00
bridge
bd563b10f4 feat: add splash mp4 video 2026-01-18 16:11:34 +08:00
Zihao Xu
e3bf36bcd4 test: add tests for Avatar._init_known_regions (#34)
Verify that:
1. Avatar without sect knows current location's region
2. Avatar with sect knows their sect headquarters
3. Avatar without sect does not automatically know sect regions
4. Avatar only knows their own sect's headquarters, not others
2026-01-18 15:31:41 +08:00
Zihao Xu
7edae9188b fix(misc): CSV column name mismatches in data loading (#32)
* fix: CSV column name mismatches in data loading

- sect.py: Fix headquarter_name/headquarter_desc -> name/desc when reading sect_region.csv
- sect.py: Move sid initialization before technique lookup to fix unbound variable bug
- technique.py: Change sect (name) to sect_id (int) to match technique.csv column
- elixir.py: Remove redundant get_int(row, "id") that reads non-existent column

These fixes ensure:
1. Sect headquarters display correct location names (e.g., "大千光极城" instead of "不夜城")
2. Sect techniques are correctly associated and displayed
3. Technique sect restrictions work properly

* fix: update main.py to use sect_id, add CSV loading tests

- main.py: Change technique.sect to technique.sect_id in API response
- Add tests/test_csv_loading.py to verify CSV column names match code

* test: add API test for /api/meta/game_data endpoint

Verify that techniques in API response use sect_id field (not sect)

* fix: add None check for hq_region in AvatarFactory

Remove redundant code that adds sect headquarters to known_regions.
This logic is already handled by Avatar._init_known_regions() which
uses sect_id matching (more reliable than name-based lookup).

The removed code was causing a flaky test (~1% failure rate) because
resolve_query returns None in test environments with simplified maps.
2026-01-18 15:31:15 +08:00
bridge
0acf72a313 fix: remove tmp 2026-01-18 14:42:45 +08:00
bridge
4fea4b6a9b update: contributing md 2026-01-15 09:35:34 +08:00
bridge
e5ed418949 update: readme 2026-01-15 09:01:02 +08:00
bridge
9b294ccba3 fix: game control bug 2026-01-15 08:55:01 +08:00
bridge
e900c3e098 fix pytest v1.2.0 2026-01-14 17:17:21 +08:00
4thfever
df8b1b9433 Refactor/event (#31)
重构事件机制和部分拍卖会机制
2026-01-14 16:58:50 +08:00
4thfever
63fc2f828e Feat/auction (#30)
Add gathering events, in which multiple avatars participate
Add auction event

Closes #24
2026-01-14 02:33:13 +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
bridge
224e3e76f0 fix: pytest llm error only existed in github online CI 2026-01-13 00:08:42 +08:00
4thfever
bb2e010930 refactor readme (#26)
refactor readme, simulate style of
https://github.com/vladelaina/Catime
Closes #23
2026-01-13 00:03:09 +08:00
4thfever
95e1f11502 Refactor/history (#25)
add multi process history modification
2026-01-12 23:25:53 +08:00
4thfever
176fa95425 Merge pull request #21 from AI-Cultivation/feat/history
Feat/history
2026-01-12 00:40:56 +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
57cf5ca51a add history class 2026-01-11 23:53:26 +08:00