mirror of
https://github.com/tiennm99/tiennm99bot.git
synced 2026-10-11 03:13:46 +00:00
chore(plans): archive completed plans + mark atlas migration code-complete
Three feature plans (semantle, twentyq, loldle-new-modes) are status:completed in their frontmatter and the corresponding modules exist in src/modules/. Move them to plans/archive/ to keep the active plans/ dir focused on in-flight work. Atlas migration (260425-1945-mongodb-atlas-migration/plan.md): bump status from `planning` to `code-complete` and annotate each phase row with its commit SHA + whether operator action is still pending. Plan stays in active plans/ until cutover lands or the Upstash standby (phase-07-alt-pivot.md) executes. No code changes. Tests, lint, register:dry unaffected (733 passing). Operator-facing summary in the plan.md status note: 8 phases of implementation are committed on dev (6f0b5ff..e2e3112). Outstanding operator work: Atlas provisioning, real-cluster smoke tests, backfill runs, soak, cutover stages, Stage 3 code cleanup.
This commit is contained in:
1 parent
b660692eb2
commit
5cb1a812d4
21 files changed
+224
-10
No files matched your search
@@ -1,173 +0,0 @@
|
||||
# Phase 02 — Emoji module (`loldle-emoji`)
|
||||
|
||||
## Context
|
||||
|
||||
- [Research: overview + emoji](../reports/researcher-260424-2215-loldle-emoji-and-modes-overview.md)
|
||||
- Template: `src/modules/loldle/` (classic)
|
||||
- Dependency: phase 01 (`emojis.json` written by scraper, `normalize` helper).
|
||||
|
||||
## Overview
|
||||
|
||||
**Priority:** P1 (ship first — simplest mode).
|
||||
**Status:** pending.
|
||||
|
||||
Guess the champion from an emoji clue. All text-rendered — Telegram renders
|
||||
emojis natively. No images, no audio, no DDragon.
|
||||
|
||||
## Key insights
|
||||
|
||||
- Emoji sequences are handcrafted by loldle.net (not algorithmic). We only
|
||||
have what they ship — can't compute our own.
|
||||
- Progressive reveal on loldle.net works by "unlock one emoji per wrong
|
||||
guess". On Telegram, we keep it simpler: **show all emojis upfront, fewer
|
||||
guesses**. Saves edit-message roundtrips.
|
||||
- Reuse classic's `stats:<subject>` shape verbatim.
|
||||
|
||||
## Requirements
|
||||
|
||||
**Functional**
|
||||
- `/loldle_emoji` → show current round or start fresh; submit a guess if
|
||||
`<champion>` arg provided.
|
||||
- `/loldle_emoji_giveup` → reveal answer, record loss.
|
||||
- `/loldle_emoji_stats` → show per-subject play stats.
|
||||
- 5 guesses per round.
|
||||
- Subject = user (DM) or chat (group), same rule as classic.
|
||||
- Champion name lookup identical to classic (case/space/punctuation-
|
||||
insensitive, unique-prefix fallback).
|
||||
|
||||
**Non-functional**
|
||||
- Pure KV storage (no D1). Auto-prefixed key `loldle-emoji:game:<subject>`.
|
||||
- Round state: `{ target, guesses, startedAt }` — same shape as classic.
|
||||
- Champion pool comes from `emojis.json` (phase 01). Only champions with a
|
||||
non-empty emoji string are eligible.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
src/modules/loldle-emoji/
|
||||
├── index.js # { name, commands, init } export
|
||||
├── handlers.js # handleEmoji, handleGiveup, handleStats
|
||||
├── state.js # loadGame/saveGame/clearGame/loadStats/recordResult
|
||||
├── lookup.js # findChampion over emojis.json (thin wrapper, uses util/normalize-name.js)
|
||||
├── render.js # board render: emoji block + guesses list
|
||||
├── emojis.json # [{ championName, emojis:"🦊✨💫" }, ...] (generated)
|
||||
└── README.md # usage + data source notes
|
||||
```
|
||||
|
||||
## Related code files
|
||||
|
||||
**Modify**
|
||||
- `src/modules/index.js` — add `"loldle-emoji"` to static import map.
|
||||
- `wrangler.toml` `[vars].MODULES` — append `,loldle-emoji`.
|
||||
- `.env.deploy` (local) — append `,loldle-emoji` to MODULES.
|
||||
|
||||
**Create**
|
||||
- Six files listed in Architecture above.
|
||||
|
||||
**Delete:** none.
|
||||
|
||||
## Implementation steps
|
||||
|
||||
1. **Copy `src/modules/loldle/state.js`** → `src/modules/loldle-emoji/state.js`.
|
||||
Change `MAX_GUESSES = 5`. No other changes needed; same KV shape.
|
||||
|
||||
2. **Create `lookup.js`**:
|
||||
```js
|
||||
import { normalize } from "../../util/normalize-name.js";
|
||||
export function findChampion(pool, input) {
|
||||
const q = normalize(input);
|
||||
if (!q) return null;
|
||||
const exact = pool.find((c) => normalize(c.championName) === q);
|
||||
if (exact) return exact;
|
||||
const prefix = pool.filter((c) =>
|
||||
normalize(c.championName).startsWith(q));
|
||||
return prefix.length === 1 ? prefix[0] : null;
|
||||
}
|
||||
```
|
||||
|
||||
3. **Create `render.js`** — render the current board:
|
||||
```
|
||||
🎭 <emoji sequence>
|
||||
|
||||
Guesses (<n>/<MAX>):
|
||||
• <name1> ❌
|
||||
• <name2> ❌
|
||||
```
|
||||
HTML-escape every champion name via `src/util/escape-html.js`.
|
||||
|
||||
4. **Create `handlers.js`** modelled on `loldle/handlers.js`:
|
||||
- Same subject resolution (`getSubject`).
|
||||
- Same arg parsing.
|
||||
- `pickRandomChampion()` picks from `emojisData` (skip champions with
|
||||
empty emoji string, if any).
|
||||
- Win / loss / giveup messages reuse classic's tone; swap "classic" →
|
||||
"emoji" in copy. No stickers for v1 (YAGNI — can add later).
|
||||
- On win: "🎉 Got it! <champ> — solved in Nx/5" + stats update + KV clear.
|
||||
- On loss: "❌ Answer was <champ>" + stats update + KV clear.
|
||||
|
||||
5. **Create `index.js`**:
|
||||
```js
|
||||
import { handleGiveup, handleEmoji, handleStats } from "./handlers.js";
|
||||
let db = null;
|
||||
export default {
|
||||
name: "loldle-emoji",
|
||||
init: async ({ db: store }) => { db = store; },
|
||||
commands: [
|
||||
{ name: "loldle_emoji", visibility: "public",
|
||||
description: "Emoji loldle — guess the champion from emojis",
|
||||
handler: (ctx) => handleEmoji(ctx, db) },
|
||||
{ name: "loldle_emoji_giveup", visibility: "public",
|
||||
description: "Reveal the current emoji answer",
|
||||
handler: (ctx) => handleGiveup(ctx, db) },
|
||||
{ name: "loldle_emoji_stats", visibility: "public",
|
||||
description: "Show your emoji stats (wins, streak)",
|
||||
handler: (ctx) => handleStats(ctx, db) },
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
6. **Register** — add to `src/modules/index.js` import map, MODULES env.
|
||||
|
||||
7. **Write minimal README.md** — commands table, KV prefix, data source
|
||||
note ("regenerated by `npm run scrape:loldle-data`").
|
||||
|
||||
8. **Run `npm run dev`**, point a test bot at it, verify:
|
||||
- `/loldle_emoji` shows emojis + empty board.
|
||||
- `/loldle_emoji Ahri` (assuming Ahri is the answer) wins.
|
||||
- `/loldle_emoji_giveup` reveals answer.
|
||||
- `/loldle_emoji_stats` reports play counts.
|
||||
|
||||
## Todo
|
||||
|
||||
- [ ] Create folder + 6 files per Architecture
|
||||
- [ ] Copy state.js from classic, lower MAX_GUESSES to 5
|
||||
- [ ] Import normalize helper from util
|
||||
- [ ] Render board with HTML-escape
|
||||
- [ ] Handlers ported from classic, tone tweaked
|
||||
- [ ] Register in `src/modules/index.js` + MODULES env
|
||||
- [ ] Write README
|
||||
- [ ] Local smoke-test (`npm run dev` + test bot)
|
||||
|
||||
## Success criteria
|
||||
|
||||
- Module loads at `installDispatcher` without conflicts.
|
||||
- `/loldle_emoji` runs end-to-end against loldle.net data.
|
||||
- Stats persist across rounds, isolated from classic loldle.
|
||||
|
||||
## Risks
|
||||
|
||||
| Risk | Mitigation |
|
||||
|------|-----------|
|
||||
| `emojis.json` missing some champions | Pool is whatever loldle.net provides; guard null at render time |
|
||||
| Emoji rendering differs across Telegram clients | Use standard Unicode emojis (loldle.net already does); no skin-tone variants |
|
||||
| Player confusion vs classic (two loldle-like commands) | Distinct command name + distinct welcome copy |
|
||||
|
||||
## Security
|
||||
|
||||
- Input passes through `normalize` (strips non-alphanum) before comparison.
|
||||
- HTML escape all user-submitted and champion-name text in reply.
|
||||
|
||||
## Next steps
|
||||
|
||||
Phase 06 covers tests. Phase 03 (quote) can be built in parallel — same
|
||||
template.
|
||||
Reference in new issue
Block a user