Commit Graph

10 Commits

Author SHA1 Message Date
tiennm99 44c1f1a57c chore: run biome format across the repo
Broaden `npm run format` / `npm run lint` to biome's full scan (`.`)
instead of a fixed src/tests/scripts list, so root-level files and any
new top-level directories stay formatted. Drop the stale ignore entry
for the deleted champions-data.js.
2026-04-22 14:14:29 +07:00
tiennm99 61f1cd79b7 refactor(loldle): align display labels with loldle.net grid
Column headers now match loldle.net's classic-mode grid verbatim:
Range → Range type, Region → Region(s), Lane → Position(s),
Year → Release year. The champion row header becomes Champion (was
Name). Data field names already matched; only labels diverged.
2026-04-22 13:54:23 +07:00
tiennm99 e1f7cdf645 refactor(loldle): trim module to current behavior only
KV payload cleanup:
- drop lastResultAt from stats (never read)
- drop solved/giveup flags from game state (round is immediately
  replaced after finish, making the flags transient noise)
- skip redundant saveGame on winning/giveup/out-of-guesses paths;
  startFreshGame overwrites anyway

Code cleanup:
- delete daily.js + daily.test.js (pickDaily/todayUtc were speculative
  "future use" — only pickRandom was wired in, inlined into handlers)
- drop the dead switch default in compare.js
- trim file preambles across the module

Docs: rewrite README around current behavior with loldle.net as the
sole data source; update scraper header to match the raw schema.
2026-04-22 13:49:38 +07:00
tiennm99 df46e4ee22 refactor(loldle): consume loldle.net's raw schema directly
Drop the in-scraper normalization step — champions.json now mirrors the
exact shape emitted by loldle.net's JS bundle. Records use _id,
championId, championName, arrays for positions/species/regions/
range_type, "Male"/"Female"/"Other" gender strings, and a full
YYYY-MM-DD release_date.

Comparison is schema-aware: multi-value keys accept arrays directly,
the year axis parses YYYY out of the ISO date, and exact compares stay
case-insensitive.
2026-04-22 13:29:55 +07:00
tiennm99 0836f02ab8 refactor(loldle): source all champion data from loldle.net
loldle.net's JS bundle ships the complete set of classic-mode axes in
plaintext, so ddragon merging is no longer needed. Scraper now produces
the final schema directly.

Schema changes: drop title, skinCount, image, and genre (ddragon-only).
Replace genre (class tags like Fighter/Mage) with species (Human/Darkin/
Vastayan) — the axis loldle.net actually uses. Promote region to a
multi-value field so multi-region champions compare correctly.

Handlers no longer show "Name — Title" on win/giveup.
2026-04-22 13:19:10 +07:00
tiennm99 405a0391e2 feat(loldle): sticker reactions + per-attempt flavor + solve time
- Send a random sticker from WIN/LOSE/GIVEUP pools before the text reply
  (errors swallowed so a rotten file_id never blocks the message).
- Win message includes attempt-count flavor ("First try!" / "Sharp!" /
  "Close call!" / "Phew — last one!") and elapsed solve time.
- Lose and giveup messages now also include the champion's title.
- Extract stickers.js and flavor.js so handlers.js stays at ~200 LoC.
2026-04-22 00:00:50 +07:00
tiennm99 fb5006b0f6 feat(loldle): monospace aligned board, auto-restart round
- Remove /loldle_new; finished rounds (solve/giveup/out-of-guesses)
  immediately roll into a fresh round.
- Render guesses as an HTML <pre> monospace table with auto-widthed
  label column and a 🎯 Name row (uppercase champion name).
- Year direction uses ⬆️ / ⬇️.
2026-04-21 23:03:49 +07:00
tiennm99 a2f67a7758 fix: project-wide review — trading safety, loldle drift guard, doc refresh
Code fixes:
- trading/handlers + stats-handler: guard ctx.from?.id to prevent
  cross-user state corruption when channel posts or inline queries lack
  a sender
- trading/prices + trading/symbols: encodeURIComponent on ticker before
  interpolating into TCBS API URLs
- trading/stats-handler: parallelize per-stock price fetches with
  Promise.allSettled so N-stock portfolios don't stack serial latency
- loldle/handlers: guard target champion lookup against champions.json
  refresh drift — start a fresh round or fall back to the stored id
- wordle + loldle: explicitly initialize giveup:false in startFreshGame
  for stable state shape
- wordle/lookup: fix stale JSDoc that claimed null return
- biome: ignore auto-generated champions.json / champions-data.js /
  words-data.js
- Apply formatter to src/index.js, loldle/handlers.js imports, and
  loldle/compare.test.js (previously red)

Docs refresh:
- README: 105+ tests -> 200+; wordle/loldle described as real modules
- architecture: module tree updated, test count 105 -> 200, runtime
  ~500ms -> ~2s, stub list narrowed to misc only
- codebase-summary: module table rewritten (wordle/loldle now Complete
  with real command lists and KV schema); test coverage table updated
- loldle/README: full rewrite matching the current implementation
  (was describing the original stub)
- New docs/development-roadmap.md tracking upcoming features
  (daily-mode for wordle + loldle, crypto/gold/forex trading, shared
  picker util, handler-level tests, coverage reporting, staging env)

Tests: 200/200 passing. Lint: clean.
2026-04-20 22:08:58 +07:00
dependabot[bot] 6de35d3e4f chore(deps): bump vite and vitest (#1)
* build(deps): bump vite and vitest

Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) to 8.0.8 and updates ancestor dependency [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest). These dependencies need to be updated together.


Updates `vite` from 5.4.21 to 8.0.8
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v8.0.8/packages/vite)

Updates `vitest` from 2.1.9 to 4.1.4
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.4/packages/vitest)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 8.0.8
  dependency-type: indirect
- dependency-name: vitest
  dependency-version: 4.1.4
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

* feat(loldle): share game state per-chat in groups

Groups and supergroups now share one daily puzzle + one stats counter
across all members. Private chats remain per-user.

- state.js: renamed key arg from userId to subject (user|chat id)
- handlers.js: getSubject(ctx) picks user id in DM, chat id in groups
- /loldle_stats labels scope as "your" vs "group" accordingly

* feat(loldle): add /loldle_new + switch to self-paced rounds

- /loldle_new starts a new random round. If the previous round is not
  solved/given-up, it's recorded as a loss (auto-giveup) before rerolling.
- Drop daily-seeded targets: each round picks a uniformly-random champion
  (pickRandom in daily.js; pickDaily kept for future use).
- state.js: one active round per subject (no date in key). TTL raised to
  7 days; streak = consecutive wins (round-based, not date-based).
- Register /loldle_new in module index; now 8 public loldle commands.
- Tests: add pickRandom cases; bump expected command count to 12.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: tiennm99 <tiennm99@outlook.com>
2026-04-20 17:55:40 +07:00
tiennm99 1e01437766 feat(loldle): port classic-mode game from loldle repo
Adds loldle module with classic-mode champion guessing. Ports comparison
logic from tiennm99/loldle (lib/classic-mode.js) and bundles champion
data from tiennm99/loldle-data. Adds GH Actions workflow that re-syncs
champions.json on cross-repo dispatch from loldle-data.

- Three public commands: /loldle, /loldle_giveup, /loldle_stats
- Per-user daily state + streak stats in KV (3-day TTL on games)
- champions-data.js wrapper sidesteps Node 24 / esbuild disagreement on
  JSON import attributes; generator script + npm run build:loldle-data
- register script now tolerates missing .env.deploy (env-file-if-exists)
  so Workers Builds can inject env vars directly
- fix(scripts): escape stray */ in migrate.js docstring that broke node
- 16 new unit tests (compare, daily, lookup); dispatcher test updated
  for the new command set
2026-04-20 17:10:08 +07:00