sa2kit 1.6.92 → 1.6.96

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 (59) hide show
  1. package/dist/huarongdao/index.d.mts +8 -0
  2. package/dist/huarongdao/index.d.ts +8 -0
  3. package/dist/huarongdao/index.js +360 -0
  4. package/dist/huarongdao/index.js.map +1 -0
  5. package/dist/huarongdao/index.mjs +338 -0
  6. package/dist/huarongdao/index.mjs.map +1 -0
  7. package/dist/huarongdao/logic/index.d.mts +11 -0
  8. package/dist/huarongdao/logic/index.d.ts +11 -0
  9. package/dist/huarongdao/logic/index.js +89 -0
  10. package/dist/huarongdao/logic/index.js.map +1 -0
  11. package/dist/huarongdao/logic/index.mjs +81 -0
  12. package/dist/huarongdao/logic/index.mjs.map +1 -0
  13. package/dist/huarongdao/routes/index.d.mts +38 -0
  14. package/dist/huarongdao/routes/index.d.ts +38 -0
  15. package/dist/huarongdao/routes/index.js +114 -0
  16. package/dist/huarongdao/routes/index.js.map +1 -0
  17. package/dist/huarongdao/routes/index.mjs +108 -0
  18. package/dist/huarongdao/routes/index.mjs.map +1 -0
  19. package/dist/huarongdao/server/index.d.mts +14 -0
  20. package/dist/huarongdao/server/index.d.ts +14 -0
  21. package/dist/huarongdao/server/index.js +60 -0
  22. package/dist/huarongdao/server/index.js.map +1 -0
  23. package/dist/huarongdao/server/index.mjs +57 -0
  24. package/dist/huarongdao/server/index.mjs.map +1 -0
  25. package/dist/huarongdao/service/index.d.mts +31 -0
  26. package/dist/huarongdao/service/index.d.ts +31 -0
  27. package/dist/huarongdao/service/index.js +45 -0
  28. package/dist/huarongdao/service/index.js.map +1 -0
  29. package/dist/huarongdao/service/index.mjs +42 -0
  30. package/dist/huarongdao/service/index.mjs.map +1 -0
  31. package/dist/huarongdao/types/index.d.mts +46 -0
  32. package/dist/huarongdao/types/index.d.ts +46 -0
  33. package/dist/huarongdao/types/index.js +4 -0
  34. package/dist/huarongdao/types/index.js.map +1 -0
  35. package/dist/huarongdao/types/index.mjs +3 -0
  36. package/dist/huarongdao/types/index.mjs.map +1 -0
  37. package/dist/huarongdao/ui/web/index.d.mts +3 -0
  38. package/dist/huarongdao/ui/web/index.d.ts +3 -0
  39. package/dist/huarongdao/ui/web/index.js +237 -0
  40. package/dist/huarongdao/ui/web/index.js.map +1 -0
  41. package/dist/huarongdao/ui/web/index.mjs +229 -0
  42. package/dist/huarongdao/ui/web/index.mjs.map +1 -0
  43. package/dist/index-B48rcsqv.d.ts +27 -0
  44. package/dist/index-BNqJdwX4.d.ts +37 -0
  45. package/dist/index-DOtQI_mz.d.mts +37 -0
  46. package/dist/index-Da2X78GE.d.mts +27 -0
  47. package/dist/index.d.mts +7 -0
  48. package/dist/index.d.ts +7 -0
  49. package/dist/index.js +382 -33
  50. package/dist/index.js.map +1 -1
  51. package/dist/index.mjs +382 -34
  52. package/dist/index.mjs.map +1 -1
  53. package/dist/qqbot/server/index.d.mts +126 -1
  54. package/dist/qqbot/server/index.d.ts +126 -1
  55. package/dist/qqbot/server/index.js +250 -0
  56. package/dist/qqbot/server/index.js.map +1 -1
  57. package/dist/qqbot/server/index.mjs +246 -1
  58. package/dist/qqbot/server/index.mjs.map +1 -1
  59. package/package.json +36 -1
@@ -0,0 +1,229 @@
1
+ import React3, { useMemo, useState } from 'react';
2
+
3
+ // src/huarongdao/ui/web/components/HuarongdaoBoard.tsx
4
+ var HuarongdaoBoard = ({ tiles, rows, cols, imageUrl, onClickTile }) => {
5
+ const total = rows * cols;
6
+ return /* @__PURE__ */ React3.createElement(
7
+ "div",
8
+ {
9
+ style: {
10
+ display: "grid",
11
+ gridTemplateColumns: `repeat(${cols}, 96px)`,
12
+ gridTemplateRows: `repeat(${rows}, 96px)`,
13
+ gap: 6
14
+ }
15
+ },
16
+ tiles.map((tile, index) => {
17
+ if (tile === 0) return /* @__PURE__ */ React3.createElement("div", { key: `blank-${index}`, style: { background: "#ddd" } });
18
+ const pieceIndex = tile - 1;
19
+ const pr = Math.floor(pieceIndex / cols);
20
+ const pc = pieceIndex % cols;
21
+ return /* @__PURE__ */ React3.createElement(
22
+ "button",
23
+ {
24
+ key: `${tile}-${index}`,
25
+ onClick: () => onClickTile(index),
26
+ style: {
27
+ border: "1px solid #666",
28
+ cursor: "pointer",
29
+ backgroundImage: `url(${imageUrl})`,
30
+ backgroundSize: `${cols * 96}px ${rows * 96}px`,
31
+ backgroundPosition: `${-pc * 96}px ${-pr * 96}px`
32
+ }
33
+ }
34
+ );
35
+ }),
36
+ tiles.length !== total ? /* @__PURE__ */ React3.createElement("div", null, "tiles invalid") : null
37
+ );
38
+ };
39
+ var HuarongdaoBoard_default = HuarongdaoBoard;
40
+
41
+ // src/huarongdao/logic/game.ts
42
+ var clone = (v) => [...v];
43
+ var buildSolvedTiles = (rows, cols) => {
44
+ const total = rows * cols;
45
+ return Array.from({ length: total }, (_, i) => (i + 1) % total);
46
+ };
47
+ var isSolved = (tiles) => {
48
+ return tiles.every((v, i, arr) => v === (i + 1) % arr.length);
49
+ };
50
+ var canMove = (tiles, rows, cols, tileIndex) => {
51
+ const blank = tiles.indexOf(0);
52
+ if (blank < 0 || tileIndex < 0 || tileIndex >= tiles.length) return false;
53
+ const br = Math.floor(blank / cols);
54
+ const bc = blank % cols;
55
+ const tr = Math.floor(tileIndex / cols);
56
+ const tc = tileIndex % cols;
57
+ return Math.abs(br - tr) + Math.abs(bc - tc) === 1;
58
+ };
59
+ var moveTile = (state, tileIndex) => {
60
+ if (!canMove(state.tiles, state.rows, state.cols, tileIndex)) return state;
61
+ const nextTiles = clone(state.tiles);
62
+ const blank = nextTiles.indexOf(0);
63
+ const blankValue = nextTiles[blank];
64
+ const tileValue = nextTiles[tileIndex];
65
+ if (blankValue === void 0 || tileValue === void 0) return state;
66
+ nextTiles[blank] = tileValue;
67
+ nextTiles[tileIndex] = blankValue;
68
+ const solved = isSolved(nextTiles);
69
+ return {
70
+ ...state,
71
+ tiles: nextTiles,
72
+ moveCount: state.moveCount + 1,
73
+ isSolved: solved,
74
+ finishedAt: solved ? Date.now() : void 0
75
+ };
76
+ };
77
+ var shuffleSolvable = (rows, cols, steps = 80) => {
78
+ let tiles = buildSolvedTiles(rows, cols);
79
+ for (let i = 0; i < steps; i += 1) {
80
+ const blank = tiles.indexOf(0);
81
+ const br = Math.floor(blank / cols);
82
+ const bc = blank % cols;
83
+ const candidate = [];
84
+ const dirs = [
85
+ [1, 0],
86
+ [-1, 0],
87
+ [0, 1],
88
+ [0, -1]
89
+ ];
90
+ dirs.forEach(([dr, dc]) => {
91
+ const nr = br + dr;
92
+ const nc = bc + dc;
93
+ if (nr >= 0 && nr < rows && nc >= 0 && nc < cols) candidate.push(nr * cols + nc);
94
+ });
95
+ const idx = candidate[Math.floor(Math.random() * candidate.length)] ?? blank;
96
+ const next = clone(tiles);
97
+ [next[blank], next[idx]] = [next[idx] ?? 0, next[blank] ?? 0];
98
+ tiles = next;
99
+ }
100
+ return tiles;
101
+ };
102
+
103
+ // src/huarongdao/ui/web/pages/HuarongdaoGamePage.tsx
104
+ var HuarongdaoGamePage = ({ config }) => {
105
+ const initial = useMemo(() => {
106
+ const tiles = config.startMode === "custom-layout" && config.initialTiles?.length === config.rows * config.cols ? config.initialTiles : shuffleSolvable(config.rows, config.cols, config.shuffleSteps);
107
+ return {
108
+ tiles,
109
+ rows: config.rows,
110
+ cols: config.cols,
111
+ moveCount: 0,
112
+ startedAt: Date.now(),
113
+ isSolved: false
114
+ };
115
+ }, [config]);
116
+ const [state, setState] = useState(initial);
117
+ const reset = () => {
118
+ setState({
119
+ ...state,
120
+ tiles: shuffleSolvable(config.rows, config.cols, config.shuffleSteps),
121
+ moveCount: 0,
122
+ startedAt: Date.now(),
123
+ finishedAt: void 0,
124
+ isSolved: false
125
+ });
126
+ };
127
+ const solveNow = () => {
128
+ setState((prev) => ({ ...prev, tiles: buildSolvedTiles(config.rows, config.cols), isSolved: true, finishedAt: Date.now() }));
129
+ };
130
+ const durationSec = Math.floor(((state.finishedAt || Date.now()) - state.startedAt) / 1e3);
131
+ return /* @__PURE__ */ React3.createElement("section", null, /* @__PURE__ */ React3.createElement("h2", null, config.name), /* @__PURE__ */ React3.createElement("p", null, "\u6B65\u6570\uFF1A", state.moveCount, " \uFF5C \u7528\u65F6\uFF1A", durationSec, "s ", state.isSolved ? "\uFF5C\u5DF2\u901A\u5173 \u{1F389}" : ""), /* @__PURE__ */ React3.createElement(
132
+ HuarongdaoBoard_default,
133
+ {
134
+ tiles: state.tiles,
135
+ rows: state.rows,
136
+ cols: state.cols,
137
+ imageUrl: config.sourceImageUrl,
138
+ onClickTile: (idx) => setState((prev) => moveTile(prev, idx))
139
+ }
140
+ ), /* @__PURE__ */ React3.createElement("div", { style: { marginTop: 12 } }, /* @__PURE__ */ React3.createElement("button", { onClick: reset }, "\u91CD\u65B0\u6253\u4E71"), /* @__PURE__ */ React3.createElement("button", { onClick: solveNow }, "\u4E00\u952E\u5B8C\u6210(\u6D4B\u8BD5)")), config.showReference ? /* @__PURE__ */ React3.createElement("div", { style: { marginTop: 12 } }, /* @__PURE__ */ React3.createElement("div", null, "\u53C2\u8003\u56FE\uFF1A"), /* @__PURE__ */ React3.createElement("img", { src: config.sourceImageUrl, alt: "reference", style: { width: 180, border: "1px solid #ccc" } })) : null);
141
+ };
142
+ var HuarongdaoGamePage_default = HuarongdaoGamePage;
143
+
144
+ // src/huarongdao/server/service.ts
145
+ var id = () => `puzzle_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
146
+ var HuarongdaoService = class {
147
+ constructor() {
148
+ this.configs = /* @__PURE__ */ new Map();
149
+ }
150
+ listConfigs() {
151
+ return [...this.configs.values()];
152
+ }
153
+ getBySlug(slug) {
154
+ return [...this.configs.values()].find((c) => c.slug === slug) || null;
155
+ }
156
+ createConfig(input) {
157
+ const now = (/* @__PURE__ */ new Date()).toISOString();
158
+ const next = {
159
+ id: id(),
160
+ slug: input.slug,
161
+ name: input.name,
162
+ description: input.description,
163
+ status: "draft",
164
+ rows: input.rows,
165
+ cols: input.cols,
166
+ sourceImageUrl: input.sourceImageUrl,
167
+ showReference: input.showReference ?? true,
168
+ shuffleSteps: input.shuffleSteps ?? 80,
169
+ timeLimitSec: input.timeLimitSec,
170
+ startMode: input.startMode ?? "random-solvable",
171
+ initialTiles: input.initialTiles,
172
+ createdAt: now,
173
+ updatedAt: now
174
+ };
175
+ this.configs.set(next.id, next);
176
+ return next;
177
+ }
178
+ updateConfig(id2, patch) {
179
+ const cur = this.configs.get(id2);
180
+ if (!cur) throw new Error("\u914D\u7F6E\u4E0D\u5B58\u5728");
181
+ const next = { ...cur, ...patch, id: cur.id, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
182
+ this.configs.set(id2, next);
183
+ return next;
184
+ }
185
+ deleteConfig(id2) {
186
+ this.configs.delete(id2);
187
+ }
188
+ getSnapshot() {
189
+ const configs = this.listConfigs();
190
+ return {
191
+ configs,
192
+ activeConfig: configs.find((c) => c.status === "active")
193
+ };
194
+ }
195
+ };
196
+ var createHuarongdaoService = () => new HuarongdaoService();
197
+
198
+ // src/huarongdao/ui/web/pages/HuarongdaoConfigPage.tsx
199
+ var HuarongdaoConfigPage = () => {
200
+ const service = useMemo(() => createHuarongdaoService(), []);
201
+ const [version, setVersion] = useState(0);
202
+ const [name, setName] = useState("\u793A\u4F8B\u534E\u5BB9\u9053");
203
+ const [slug, setSlug] = useState("sample-huarongdao");
204
+ const [imageUrl, setImageUrl] = useState("https://i.imgur.com/6z7Qw6M.png");
205
+ const [rows, setRows] = useState(3);
206
+ const [cols, setCols] = useState(3);
207
+ const list = useMemo(() => {
208
+ return service.listConfigs();
209
+ }, [service, version]);
210
+ const create = () => {
211
+ const input = {
212
+ name,
213
+ slug,
214
+ sourceImageUrl: imageUrl,
215
+ rows,
216
+ cols,
217
+ showReference: true,
218
+ shuffleSteps: 80
219
+ };
220
+ service.createConfig(input);
221
+ setVersion((v) => v + 1);
222
+ };
223
+ return /* @__PURE__ */ React3.createElement("section", null, /* @__PURE__ */ React3.createElement("h2", null, "\u534E\u5BB9\u9053\u540E\u53F0\u914D\u7F6E\u9875"), /* @__PURE__ */ React3.createElement("p", null, "\u652F\u6301\u591A\u5957\u914D\u7F6E\u521B\u5EFA\u3001\u53C2\u6570\u5316\u7BA1\u7406\uFF08V1 \u9AA8\u67B6\uFF09"), /* @__PURE__ */ React3.createElement("div", null, /* @__PURE__ */ React3.createElement("input", { value: name, onChange: (e) => setName(e.target.value), placeholder: "name" }), /* @__PURE__ */ React3.createElement("input", { value: slug, onChange: (e) => setSlug(e.target.value), placeholder: "slug" }), /* @__PURE__ */ React3.createElement("input", { value: imageUrl, onChange: (e) => setImageUrl(e.target.value), placeholder: "image url" }), /* @__PURE__ */ React3.createElement("input", { type: "number", value: rows, onChange: (e) => setRows(Number(e.target.value) || 3) }), /* @__PURE__ */ React3.createElement("input", { type: "number", value: cols, onChange: (e) => setCols(Number(e.target.value) || 3) }), /* @__PURE__ */ React3.createElement("button", { onClick: create }, "\u521B\u5EFA\u914D\u7F6E")), /* @__PURE__ */ React3.createElement("ul", null, list.map((item) => /* @__PURE__ */ React3.createElement("li", { key: item.id }, item.name, " (", item.slug, ") - ", item.rows, "x", item.cols, " - ", item.status))));
224
+ };
225
+ var HuarongdaoConfigPage_default = HuarongdaoConfigPage;
226
+
227
+ export { HuarongdaoBoard_default as HuarongdaoBoard, HuarongdaoConfigPage_default as HuarongdaoConfigPage, HuarongdaoGamePage_default as HuarongdaoGamePage };
228
+ //# sourceMappingURL=index.mjs.map
229
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/huarongdao/ui/web/components/HuarongdaoBoard.tsx","../../../../src/huarongdao/logic/game.ts","../../../../src/huarongdao/ui/web/pages/HuarongdaoGamePage.tsx","../../../../src/huarongdao/server/service.ts","../../../../src/huarongdao/ui/web/pages/HuarongdaoConfigPage.tsx"],"names":["React","id","useMemo","useState"],"mappings":"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","file":"index.mjs","sourcesContent":["import React from 'react';\n\nexport interface HuarongdaoBoardProps {\n tiles: number[];\n rows: number;\n cols: number;\n imageUrl: string;\n onClickTile: (index: number) => void;\n}\n\nconst HuarongdaoBoard: React.FC<HuarongdaoBoardProps> = ({ tiles, rows, cols, imageUrl, onClickTile }) => {\n const total = rows * cols;\n return (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: `repeat(${cols}, 96px)`,\n gridTemplateRows: `repeat(${rows}, 96px)`,\n gap: 6,\n }}\n >\n {tiles.map((tile, index) => {\n if (tile === 0) return <div key={`blank-${index}`} style={{ background: '#ddd' }} />;\n const pieceIndex = tile - 1;\n const pr = Math.floor(pieceIndex / cols);\n const pc = pieceIndex % cols;\n return (\n <button\n key={`${tile}-${index}`}\n onClick={() => onClickTile(index)}\n style={{\n border: '1px solid #666',\n cursor: 'pointer',\n backgroundImage: `url(${imageUrl})`,\n backgroundSize: `${cols * 96}px ${rows * 96}px`,\n backgroundPosition: `${-pc * 96}px ${-pr * 96}px`,\n }}\n />\n );\n })}\n {tiles.length !== total ? <div>tiles invalid</div> : null}\n </div>\n );\n};\n\nexport default HuarongdaoBoard;\n","import type { HuarongdaoGameState } from '../types';\n\nconst clone = <T>(v: T[]): T[] => [...v];\n\nexport const buildSolvedTiles = (rows: number, cols: number): number[] => {\n const total = rows * cols;\n return Array.from({ length: total }, (_, i) => (i + 1) % total);\n};\n\nexport const isSolved = (tiles: number[]): boolean => {\n return tiles.every((v, i, arr) => v === (i + 1) % arr.length);\n};\n\nexport const canMove = (tiles: number[], rows: number, cols: number, tileIndex: number): boolean => {\n const blank = tiles.indexOf(0);\n if (blank < 0 || tileIndex < 0 || tileIndex >= tiles.length) return false;\n const br = Math.floor(blank / cols);\n const bc = blank % cols;\n const tr = Math.floor(tileIndex / cols);\n const tc = tileIndex % cols;\n return Math.abs(br - tr) + Math.abs(bc - tc) === 1;\n};\n\nexport const moveTile = (state: HuarongdaoGameState, tileIndex: number): HuarongdaoGameState => {\n if (!canMove(state.tiles, state.rows, state.cols, tileIndex)) return state;\n const nextTiles = clone(state.tiles);\n const blank = nextTiles.indexOf(0);\n const blankValue = nextTiles[blank];\n const tileValue = nextTiles[tileIndex];\n if (blankValue === undefined || tileValue === undefined) return state;\n nextTiles[blank] = tileValue;\n nextTiles[tileIndex] = blankValue;\n const solved = isSolved(nextTiles);\n return {\n ...state,\n tiles: nextTiles,\n moveCount: state.moveCount + 1,\n isSolved: solved,\n finishedAt: solved ? Date.now() : undefined,\n };\n};\n\nexport const inversionCount = (tiles: number[]): number => {\n const arr = tiles.filter((n) => n !== 0);\n let cnt = 0;\n for (let i = 0; i < arr.length; i += 1) {\n for (let j = i + 1; j < arr.length; j += 1) {\n if ((arr[i] ?? 0) > (arr[j] ?? 0)) cnt += 1;\n }\n }\n return cnt;\n};\n\nexport const isSolvable = (tiles: number[], rows: number, cols: number): boolean => {\n const inv = inversionCount(tiles);\n if (cols % 2 === 1) return inv % 2 === 0;\n const blankRowFromBottom = rows - Math.floor(tiles.indexOf(0) / cols);\n return (blankRowFromBottom % 2 === 0) !== (inv % 2 === 0);\n};\n\nexport const shuffleSolvable = (rows: number, cols: number, steps = 80): number[] => {\n let tiles = buildSolvedTiles(rows, cols);\n for (let i = 0; i < steps; i += 1) {\n const blank = tiles.indexOf(0);\n const br = Math.floor(blank / cols);\n const bc = blank % cols;\n const candidate: number[] = [];\n const dirs: Array<[number, number]> = [\n [1, 0],\n [-1, 0],\n [0, 1],\n [0, -1],\n ];\n dirs.forEach(([dr, dc]) => {\n const nr = br + dr;\n const nc = bc + dc;\n if (nr >= 0 && nr < rows && nc >= 0 && nc < cols) candidate.push(nr * cols + nc);\n });\n const idx = candidate[Math.floor(Math.random() * candidate.length)] ?? blank;\n const next = clone(tiles);\n [next[blank], next[idx]] = [next[idx] ?? 0, next[blank] ?? 0];\n tiles = next;\n }\n return tiles;\n};\n","import React, { useMemo, useState } from 'react';\nimport { buildSolvedTiles, moveTile, shuffleSolvable } from '../../../logic';\nimport type { HuarongdaoConfig, HuarongdaoGameState } from '../../../types';\nimport HuarongdaoBoard from '../components/HuarongdaoBoard';\n\nexport interface HuarongdaoGamePageProps {\n config: HuarongdaoConfig;\n}\n\nconst HuarongdaoGamePage: React.FC<HuarongdaoGamePageProps> = ({ config }) => {\n const initial = useMemo<HuarongdaoGameState>(() => {\n const tiles = config.startMode === 'custom-layout' && config.initialTiles?.length === config.rows * config.cols\n ? config.initialTiles\n : shuffleSolvable(config.rows, config.cols, config.shuffleSteps);\n return {\n tiles,\n rows: config.rows,\n cols: config.cols,\n moveCount: 0,\n startedAt: Date.now(),\n isSolved: false,\n };\n }, [config]);\n\n const [state, setState] = useState(initial);\n\n const reset = () => {\n setState({\n ...state,\n tiles: shuffleSolvable(config.rows, config.cols, config.shuffleSteps),\n moveCount: 0,\n startedAt: Date.now(),\n finishedAt: undefined,\n isSolved: false,\n });\n };\n\n const solveNow = () => {\n setState((prev) => ({ ...prev, tiles: buildSolvedTiles(config.rows, config.cols), isSolved: true, finishedAt: Date.now() }));\n };\n\n const durationSec = Math.floor(((state.finishedAt || Date.now()) - state.startedAt) / 1000);\n\n return (\n <section>\n <h2>{config.name}</h2>\n <p>步数:{state.moveCount} | 用时:{durationSec}s {state.isSolved ? '|已通关 🎉' : ''}</p>\n <HuarongdaoBoard\n tiles={state.tiles}\n rows={state.rows}\n cols={state.cols}\n imageUrl={config.sourceImageUrl}\n onClickTile={(idx) => setState((prev) => moveTile(prev, idx))}\n />\n <div style={{ marginTop: 12 }}>\n <button onClick={reset}>重新打乱</button>\n <button onClick={solveNow}>一键完成(测试)</button>\n </div>\n {config.showReference ? (\n <div style={{ marginTop: 12 }}>\n <div>参考图:</div>\n <img src={config.sourceImageUrl} alt=\"reference\" style={{ width: 180, border: '1px solid #ccc' }} />\n </div>\n ) : null}\n </section>\n );\n};\n\nexport default HuarongdaoGamePage;\n","import type { CreateHuarongdaoConfigInput, HuarongdaoConfig, HuarongdaoStateSnapshot } from '../types';\n\nconst id = () => `puzzle_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;\n\nexport class HuarongdaoService {\n private readonly configs = new Map<string, HuarongdaoConfig>();\n\n listConfigs(): HuarongdaoConfig[] {\n return [...this.configs.values()];\n }\n\n getBySlug(slug: string): HuarongdaoConfig | null {\n return [...this.configs.values()].find((c) => c.slug === slug) || null;\n }\n\n createConfig(input: CreateHuarongdaoConfigInput): HuarongdaoConfig {\n const now = new Date().toISOString();\n const next: HuarongdaoConfig = {\n id: id(),\n slug: input.slug,\n name: input.name,\n description: input.description,\n status: 'draft',\n rows: input.rows,\n cols: input.cols,\n sourceImageUrl: input.sourceImageUrl,\n showReference: input.showReference ?? true,\n shuffleSteps: input.shuffleSteps ?? 80,\n timeLimitSec: input.timeLimitSec,\n startMode: input.startMode ?? 'random-solvable',\n initialTiles: input.initialTiles,\n createdAt: now,\n updatedAt: now,\n };\n this.configs.set(next.id, next);\n return next;\n }\n\n updateConfig(id: string, patch: Partial<HuarongdaoConfig>): HuarongdaoConfig {\n const cur = this.configs.get(id);\n if (!cur) throw new Error('配置不存在');\n const next: HuarongdaoConfig = { ...cur, ...patch, id: cur.id, updatedAt: new Date().toISOString() };\n this.configs.set(id, next);\n return next;\n }\n\n deleteConfig(id: string): void {\n this.configs.delete(id);\n }\n\n getSnapshot(): HuarongdaoStateSnapshot {\n const configs = this.listConfigs();\n return {\n configs,\n activeConfig: configs.find((c) => c.status === 'active'),\n };\n }\n}\n\nexport const createHuarongdaoService = () => new HuarongdaoService();\n","import React, { useMemo, useState } from 'react';\nimport { createHuarongdaoService } from '../../../server';\nimport type { CreateHuarongdaoConfigInput } from '../../../types';\n\nconst HuarongdaoConfigPage: React.FC = () => {\n const service = useMemo(() => createHuarongdaoService(), []);\n const [version, setVersion] = useState(0);\n const [name, setName] = useState('示例华容道');\n const [slug, setSlug] = useState('sample-huarongdao');\n const [imageUrl, setImageUrl] = useState('https://i.imgur.com/6z7Qw6M.png');\n const [rows, setRows] = useState(3);\n const [cols, setCols] = useState(3);\n\n const list = useMemo(() => {\n void version;\n return service.listConfigs();\n }, [service, version]);\n\n const create = () => {\n const input: CreateHuarongdaoConfigInput = {\n name,\n slug,\n sourceImageUrl: imageUrl,\n rows,\n cols,\n showReference: true,\n shuffleSteps: 80,\n };\n service.createConfig(input);\n setVersion((v) => v + 1);\n };\n\n return (\n <section>\n <h2>华容道后台配置页</h2>\n <p>支持多套配置创建、参数化管理(V1 骨架)</p>\n <div>\n <input value={name} onChange={(e) => setName(e.target.value)} placeholder=\"name\" />\n <input value={slug} onChange={(e) => setSlug(e.target.value)} placeholder=\"slug\" />\n <input value={imageUrl} onChange={(e) => setImageUrl(e.target.value)} placeholder=\"image url\" />\n <input type=\"number\" value={rows} onChange={(e) => setRows(Number(e.target.value) || 3)} />\n <input type=\"number\" value={cols} onChange={(e) => setCols(Number(e.target.value) || 3)} />\n <button onClick={create}>创建配置</button>\n </div>\n <ul>\n {list.map((item) => (\n <li key={item.id}>{item.name} ({item.slug}) - {item.rows}x{item.cols} - {item.status}</li>\n ))}\n </ul>\n </section>\n );\n};\n\nexport default HuarongdaoConfigPage;\n"]}
@@ -0,0 +1,27 @@
1
+ import React__default from 'react';
2
+ import { HuarongdaoConfig } from './huarongdao/types/index.js';
3
+
4
+ interface HuarongdaoBoardProps {
5
+ tiles: number[];
6
+ rows: number;
7
+ cols: number;
8
+ imageUrl: string;
9
+ onClickTile: (index: number) => void;
10
+ }
11
+ declare const HuarongdaoBoard: React__default.FC<HuarongdaoBoardProps>;
12
+
13
+ interface HuarongdaoGamePageProps {
14
+ config: HuarongdaoConfig;
15
+ }
16
+ declare const HuarongdaoGamePage: React__default.FC<HuarongdaoGamePageProps>;
17
+
18
+ declare const HuarongdaoConfigPage: React__default.FC;
19
+
20
+ declare const index_HuarongdaoBoard: typeof HuarongdaoBoard;
21
+ declare const index_HuarongdaoConfigPage: typeof HuarongdaoConfigPage;
22
+ declare const index_HuarongdaoGamePage: typeof HuarongdaoGamePage;
23
+ declare namespace index {
24
+ export { index_HuarongdaoBoard as HuarongdaoBoard, index_HuarongdaoConfigPage as HuarongdaoConfigPage, index_HuarongdaoGamePage as HuarongdaoGamePage };
25
+ }
26
+
27
+ export { HuarongdaoBoard as H, HuarongdaoGamePage as a, HuarongdaoConfigPage as b, index as i };
@@ -0,0 +1,37 @@
1
+ import { CreateHuarongdaoConfigInput, HuarongdaoConfig, HuarongdaoGameState, HuarongdaoStateSnapshot, PuzzleStatus } from './huarongdao/types/index.js';
2
+ import { buildSolvedTiles, canMove, inversionCount, isSolvable, isSolved, moveTile, shuffleSolvable } from './huarongdao/logic/index.js';
3
+ import { HttpMethod, HuarongdaoWebClientOptions, Requester, createHuarongdaoApiClient, createHuarongdaoWebClient } from './huarongdao/service/index.js';
4
+ import { HuarongdaoService, createHuarongdaoService } from './huarongdao/server/index.js';
5
+ import { HuarongdaoRouteConfig, createCreateConfigHandler, createDeleteConfigHandler, createGetSnapshotHandler, createListConfigsHandler, createUpdateConfigHandler } from './huarongdao/routes/index.js';
6
+ import { i as index$1 } from './index-B48rcsqv.js';
7
+
8
+ declare const index_CreateHuarongdaoConfigInput: typeof CreateHuarongdaoConfigInput;
9
+ declare const index_HttpMethod: typeof HttpMethod;
10
+ declare const index_HuarongdaoConfig: typeof HuarongdaoConfig;
11
+ declare const index_HuarongdaoGameState: typeof HuarongdaoGameState;
12
+ declare const index_HuarongdaoRouteConfig: typeof HuarongdaoRouteConfig;
13
+ declare const index_HuarongdaoService: typeof HuarongdaoService;
14
+ declare const index_HuarongdaoStateSnapshot: typeof HuarongdaoStateSnapshot;
15
+ declare const index_HuarongdaoWebClientOptions: typeof HuarongdaoWebClientOptions;
16
+ declare const index_PuzzleStatus: typeof PuzzleStatus;
17
+ declare const index_Requester: typeof Requester;
18
+ declare const index_buildSolvedTiles: typeof buildSolvedTiles;
19
+ declare const index_canMove: typeof canMove;
20
+ declare const index_createCreateConfigHandler: typeof createCreateConfigHandler;
21
+ declare const index_createDeleteConfigHandler: typeof createDeleteConfigHandler;
22
+ declare const index_createGetSnapshotHandler: typeof createGetSnapshotHandler;
23
+ declare const index_createHuarongdaoApiClient: typeof createHuarongdaoApiClient;
24
+ declare const index_createHuarongdaoService: typeof createHuarongdaoService;
25
+ declare const index_createHuarongdaoWebClient: typeof createHuarongdaoWebClient;
26
+ declare const index_createListConfigsHandler: typeof createListConfigsHandler;
27
+ declare const index_createUpdateConfigHandler: typeof createUpdateConfigHandler;
28
+ declare const index_inversionCount: typeof inversionCount;
29
+ declare const index_isSolvable: typeof isSolvable;
30
+ declare const index_isSolved: typeof isSolved;
31
+ declare const index_moveTile: typeof moveTile;
32
+ declare const index_shuffleSolvable: typeof shuffleSolvable;
33
+ declare namespace index {
34
+ export { index_CreateHuarongdaoConfigInput as CreateHuarongdaoConfigInput, index_HttpMethod as HttpMethod, index_HuarongdaoConfig as HuarongdaoConfig, index_HuarongdaoGameState as HuarongdaoGameState, index_HuarongdaoRouteConfig as HuarongdaoRouteConfig, index_HuarongdaoService as HuarongdaoService, index_HuarongdaoStateSnapshot as HuarongdaoStateSnapshot, index_HuarongdaoWebClientOptions as HuarongdaoWebClientOptions, index_PuzzleStatus as PuzzleStatus, index_Requester as Requester, index_buildSolvedTiles as buildSolvedTiles, index_canMove as canMove, index_createCreateConfigHandler as createCreateConfigHandler, index_createDeleteConfigHandler as createDeleteConfigHandler, index_createGetSnapshotHandler as createGetSnapshotHandler, index_createHuarongdaoApiClient as createHuarongdaoApiClient, index_createHuarongdaoService as createHuarongdaoService, index_createHuarongdaoWebClient as createHuarongdaoWebClient, index_createListConfigsHandler as createListConfigsHandler, index_createUpdateConfigHandler as createUpdateConfigHandler, index_inversionCount as inversionCount, index_isSolvable as isSolvable, index_isSolved as isSolved, index_moveTile as moveTile, index_shuffleSolvable as shuffleSolvable, index$1 as webUI };
35
+ }
36
+
37
+ export { index as i };
@@ -0,0 +1,37 @@
1
+ import { CreateHuarongdaoConfigInput, HuarongdaoConfig, HuarongdaoGameState, HuarongdaoStateSnapshot, PuzzleStatus } from './huarongdao/types/index.mjs';
2
+ import { buildSolvedTiles, canMove, inversionCount, isSolvable, isSolved, moveTile, shuffleSolvable } from './huarongdao/logic/index.mjs';
3
+ import { HttpMethod, HuarongdaoWebClientOptions, Requester, createHuarongdaoApiClient, createHuarongdaoWebClient } from './huarongdao/service/index.mjs';
4
+ import { HuarongdaoService, createHuarongdaoService } from './huarongdao/server/index.mjs';
5
+ import { HuarongdaoRouteConfig, createCreateConfigHandler, createDeleteConfigHandler, createGetSnapshotHandler, createListConfigsHandler, createUpdateConfigHandler } from './huarongdao/routes/index.mjs';
6
+ import { i as index$1 } from './index-Da2X78GE.mjs';
7
+
8
+ declare const index_CreateHuarongdaoConfigInput: typeof CreateHuarongdaoConfigInput;
9
+ declare const index_HttpMethod: typeof HttpMethod;
10
+ declare const index_HuarongdaoConfig: typeof HuarongdaoConfig;
11
+ declare const index_HuarongdaoGameState: typeof HuarongdaoGameState;
12
+ declare const index_HuarongdaoRouteConfig: typeof HuarongdaoRouteConfig;
13
+ declare const index_HuarongdaoService: typeof HuarongdaoService;
14
+ declare const index_HuarongdaoStateSnapshot: typeof HuarongdaoStateSnapshot;
15
+ declare const index_HuarongdaoWebClientOptions: typeof HuarongdaoWebClientOptions;
16
+ declare const index_PuzzleStatus: typeof PuzzleStatus;
17
+ declare const index_Requester: typeof Requester;
18
+ declare const index_buildSolvedTiles: typeof buildSolvedTiles;
19
+ declare const index_canMove: typeof canMove;
20
+ declare const index_createCreateConfigHandler: typeof createCreateConfigHandler;
21
+ declare const index_createDeleteConfigHandler: typeof createDeleteConfigHandler;
22
+ declare const index_createGetSnapshotHandler: typeof createGetSnapshotHandler;
23
+ declare const index_createHuarongdaoApiClient: typeof createHuarongdaoApiClient;
24
+ declare const index_createHuarongdaoService: typeof createHuarongdaoService;
25
+ declare const index_createHuarongdaoWebClient: typeof createHuarongdaoWebClient;
26
+ declare const index_createListConfigsHandler: typeof createListConfigsHandler;
27
+ declare const index_createUpdateConfigHandler: typeof createUpdateConfigHandler;
28
+ declare const index_inversionCount: typeof inversionCount;
29
+ declare const index_isSolvable: typeof isSolvable;
30
+ declare const index_isSolved: typeof isSolved;
31
+ declare const index_moveTile: typeof moveTile;
32
+ declare const index_shuffleSolvable: typeof shuffleSolvable;
33
+ declare namespace index {
34
+ export { index_CreateHuarongdaoConfigInput as CreateHuarongdaoConfigInput, index_HttpMethod as HttpMethod, index_HuarongdaoConfig as HuarongdaoConfig, index_HuarongdaoGameState as HuarongdaoGameState, index_HuarongdaoRouteConfig as HuarongdaoRouteConfig, index_HuarongdaoService as HuarongdaoService, index_HuarongdaoStateSnapshot as HuarongdaoStateSnapshot, index_HuarongdaoWebClientOptions as HuarongdaoWebClientOptions, index_PuzzleStatus as PuzzleStatus, index_Requester as Requester, index_buildSolvedTiles as buildSolvedTiles, index_canMove as canMove, index_createCreateConfigHandler as createCreateConfigHandler, index_createDeleteConfigHandler as createDeleteConfigHandler, index_createGetSnapshotHandler as createGetSnapshotHandler, index_createHuarongdaoApiClient as createHuarongdaoApiClient, index_createHuarongdaoService as createHuarongdaoService, index_createHuarongdaoWebClient as createHuarongdaoWebClient, index_createListConfigsHandler as createListConfigsHandler, index_createUpdateConfigHandler as createUpdateConfigHandler, index_inversionCount as inversionCount, index_isSolvable as isSolvable, index_isSolved as isSolved, index_moveTile as moveTile, index_shuffleSolvable as shuffleSolvable, index$1 as webUI };
35
+ }
36
+
37
+ export { index as i };
@@ -0,0 +1,27 @@
1
+ import React__default from 'react';
2
+ import { HuarongdaoConfig } from './huarongdao/types/index.mjs';
3
+
4
+ interface HuarongdaoBoardProps {
5
+ tiles: number[];
6
+ rows: number;
7
+ cols: number;
8
+ imageUrl: string;
9
+ onClickTile: (index: number) => void;
10
+ }
11
+ declare const HuarongdaoBoard: React__default.FC<HuarongdaoBoardProps>;
12
+
13
+ interface HuarongdaoGamePageProps {
14
+ config: HuarongdaoConfig;
15
+ }
16
+ declare const HuarongdaoGamePage: React__default.FC<HuarongdaoGamePageProps>;
17
+
18
+ declare const HuarongdaoConfigPage: React__default.FC;
19
+
20
+ declare const index_HuarongdaoBoard: typeof HuarongdaoBoard;
21
+ declare const index_HuarongdaoConfigPage: typeof HuarongdaoConfigPage;
22
+ declare const index_HuarongdaoGamePage: typeof HuarongdaoGamePage;
23
+ declare namespace index {
24
+ export { index_HuarongdaoBoard as HuarongdaoBoard, index_HuarongdaoConfigPage as HuarongdaoConfigPage, index_HuarongdaoGamePage as HuarongdaoGamePage };
25
+ }
26
+
27
+ export { HuarongdaoBoard as H, HuarongdaoGamePage as a, HuarongdaoConfigPage as b, index as i };
package/dist/index.d.mts CHANGED
@@ -30,6 +30,7 @@ export { MikuContestNoticeRow, MikuContestPersistentService, MikuContestPersiste
30
30
  export { MikuContestRouteConfig, MikuContestServiceLike, createCreateSubmissionHandler, createExportSubmissionsHandler, createGetContestSnapshotHandler, createListSubmissionsHandler, createResetVotesHandler, createReviewSubmissionHandler, createSetVoterRestrictionHandler, createUpdateContestConfigHandler, createVoteHandler } from './mikuContest/routes/index.mjs';
31
31
  export { i as webUI } from './index-CDapUIT5.mjs';
32
32
  export { i as miniappUI } from './index-C7yh6b5Q.mjs';
33
+ export { i as huarongdao } from './index-DOtQI_mz.mjs';
33
34
  export { S as StorageAdapter, a as StorageChangeEvent } from './types-BaZccpvk.mjs';
34
35
  export { b as useAsyncStorage, d as useElectronStorage, a as useLocalStorage, u as useStorage, c as useTaroStorage } from './useElectronStorage-Dj0rcorG.mjs';
35
36
  import './types-CbTsi9CZ.mjs';
@@ -40,6 +41,12 @@ import './types-CiYK5Klf.mjs';
40
41
  import './enums-Dume-V5Y.mjs';
41
42
  import 'drizzle-orm/pg-core';
42
43
  import 'next/server';
44
+ import './huarongdao/types/index.mjs';
45
+ import './huarongdao/logic/index.mjs';
46
+ import './huarongdao/service/index.mjs';
47
+ import './huarongdao/server/index.mjs';
48
+ import './huarongdao/routes/index.mjs';
49
+ import './index-Da2X78GE.mjs';
43
50
 
44
51
  interface OCRResult {
45
52
  text: string;
package/dist/index.d.ts CHANGED
@@ -30,6 +30,7 @@ export { MikuContestNoticeRow, MikuContestPersistentService, MikuContestPersiste
30
30
  export { MikuContestRouteConfig, MikuContestServiceLike, createCreateSubmissionHandler, createExportSubmissionsHandler, createGetContestSnapshotHandler, createListSubmissionsHandler, createResetVotesHandler, createReviewSubmissionHandler, createSetVoterRestrictionHandler, createUpdateContestConfigHandler, createVoteHandler } from './mikuContest/routes/index.js';
31
31
  export { i as webUI } from './index-D3UbkUai.js';
32
32
  export { i as miniappUI } from './index-Cv9jlnNz.js';
33
+ export { i as huarongdao } from './index-BNqJdwX4.js';
33
34
  export { S as StorageAdapter, a as StorageChangeEvent } from './types-BaZccpvk.js';
34
35
  export { b as useAsyncStorage, d as useElectronStorage, a as useLocalStorage, u as useStorage, c as useTaroStorage } from './useElectronStorage-DwnNfIhl.js';
35
36
  import './types-CbTsi9CZ.js';
@@ -40,6 +41,12 @@ import './types-Dlu52uDy.js';
40
41
  import './enums-Dume-V5Y.js';
41
42
  import 'drizzle-orm/pg-core';
42
43
  import 'next/server';
44
+ import './huarongdao/types/index.js';
45
+ import './huarongdao/logic/index.js';
46
+ import './huarongdao/service/index.js';
47
+ import './huarongdao/server/index.js';
48
+ import './huarongdao/routes/index.js';
49
+ import './index-B48rcsqv.js';
43
50
 
44
51
  interface OCRResult {
45
52
  text: string;