@zhin.js/plugin-idiom-chain 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/lib/chain-command.d.ts +5 -0
  2. package/lib/chain-command.d.ts.map +1 -0
  3. package/lib/chain-command.js +48 -0
  4. package/lib/chain-command.js.map +1 -0
  5. package/lib/commands.d.ts +6 -0
  6. package/lib/commands.d.ts.map +1 -0
  7. package/lib/commands.js +94 -0
  8. package/lib/commands.js.map +1 -0
  9. package/lib/data/idioms.d.ts +8 -0
  10. package/lib/data/idioms.d.ts.map +1 -0
  11. package/lib/data/idioms.js +422 -0
  12. package/lib/data/idioms.js.map +1 -0
  13. package/lib/engine.d.ts +4 -0
  14. package/lib/engine.d.ts.map +1 -0
  15. package/lib/engine.js +3 -0
  16. package/lib/engine.js.map +1 -0
  17. package/lib/game-flow.d.ts +11 -0
  18. package/lib/game-flow.d.ts.map +1 -0
  19. package/lib/game-flow.js +203 -0
  20. package/lib/game-flow.js.map +1 -0
  21. package/lib/hub-register.d.ts +5 -0
  22. package/lib/hub-register.d.ts.map +1 -0
  23. package/lib/hub-register.js +31 -0
  24. package/lib/hub-register.js.map +1 -0
  25. package/lib/idiom-provider.d.ts +23 -0
  26. package/lib/idiom-provider.d.ts.map +1 -0
  27. package/lib/idiom-provider.js +110 -0
  28. package/lib/idiom-provider.js.map +1 -0
  29. package/lib/index.d.ts +2 -0
  30. package/lib/index.d.ts.map +1 -0
  31. package/lib/index.js +26 -0
  32. package/lib/index.js.map +1 -0
  33. package/lib/models.d.ts +35 -0
  34. package/lib/models.d.ts.map +1 -0
  35. package/lib/models.js +28 -0
  36. package/lib/models.js.map +1 -0
  37. package/lib/session-service.d.ts +25 -0
  38. package/lib/session-service.d.ts.map +1 -0
  39. package/lib/session-service.js +108 -0
  40. package/lib/session-service.js.map +1 -0
  41. package/lib/view.d.ts +6 -0
  42. package/lib/view.d.ts.map +1 -0
  43. package/lib/view.js +54 -0
  44. package/lib/view.js.map +1 -0
  45. package/package.json +38 -0
  46. package/plugin.yml +2 -0
  47. package/src/chain-command.ts +57 -0
  48. package/src/commands.ts +112 -0
  49. package/src/engine.ts +18 -0
  50. package/src/game-flow.ts +270 -0
  51. package/src/hub-register.ts +32 -0
  52. package/src/idiom-provider.ts +165 -0
  53. package/src/index.ts +32 -0
  54. package/src/models.ts +64 -0
  55. package/src/session-service.ts +117 -0
  56. package/src/view.ts +65 -0
package/src/view.ts ADDED
@@ -0,0 +1,65 @@
1
+ import { buildChoiceKeyboard } from '@zhin.js/game-shared';
2
+ import type { SendContent } from 'zhin.js';
3
+ import type { ChainSessionRow } from './models.js';
4
+ import { CHAIN_PREFIX, getGloss, idiomCount, modeLabel, promptLine } from './engine.js';
5
+
6
+ const MAX_WRONG = 3;
7
+
8
+ function sessionMode(session: ChainSessionRow): 'char' | 'pinyin' {
9
+ return session.match_mode === 'char' ? 'char' : 'pinyin';
10
+ }
11
+
12
+ export function buildChainView(
13
+ session: ChainSessionRow,
14
+ eventLines: string[] = [],
15
+ ): SendContent {
16
+ const terminal = session.status !== 'active';
17
+ const mode = sessionMode(session);
18
+ const lines = [
19
+ `📜 **成语接龙** · ${modeLabel(mode)}`,
20
+ '',
21
+ `词库 **${idiomCount()}** 条 · 局分 ${session.player_score}:${session.bot_score} · 连击 **${session.streak}**(最佳 ${session.best_streak})`,
22
+ ];
23
+
24
+ if (session.last_idiom) {
25
+ const gloss = getGloss(session.last_idiom);
26
+ lines.push('', `上一句:**${session.last_idiom}**${gloss ? `(${gloss})` : ''}`);
27
+ lines.push(promptLine(session.last_idiom, mode));
28
+ }
29
+
30
+ if (session.wrong_count > 0 && session.status === 'active') {
31
+ lines.push(`⚠️ 失误 ${session.wrong_count}/${MAX_WRONG}`);
32
+ }
33
+
34
+ if (eventLines.length) {
35
+ lines.push('', ...eventLines);
36
+ }
37
+
38
+ if (terminal) {
39
+ lines.push('');
40
+ if (session.status === 'won') lines.push('🏆 **你赢了本局!** 机器人接不上啦。');
41
+ else if (session.status === 'lost') lines.push('💀 **机器人获胜。** 发送「接龙 开始」再来。');
42
+ } else {
43
+ lines.push('', '直接回复四字成语,或点下方按钮:');
44
+ }
45
+
46
+ const choices = terminal
47
+ ? [{ id: 'restart', label: '🔄 再来一局', style: 'primary' as const }]
48
+ : [
49
+ { id: 'hint', label: '💡 提示', style: 'secondary' as const },
50
+ { id: 'skip', label: '⏭️ 跳过', style: 'secondary' as const },
51
+ { id: 'quit', label: '🏳️ 认输', style: 'danger' as const },
52
+ ];
53
+
54
+ return buildChoiceKeyboard({
55
+ gamePrefix: CHAIN_PREFIX,
56
+ sessionId: session.id,
57
+ narrative: lines.join('\n'),
58
+ choices,
59
+ terminal,
60
+ buttonsPerRow: 3,
61
+ fallbackHint: '回复成语,或 1提示 2跳过 3认输',
62
+ });
63
+ }
64
+
65
+ export { MAX_WRONG };