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
package/dist/index.js CHANGED
@@ -3663,7 +3663,7 @@ function ImageMappingPanel({
3663
3663
  uploadLabel = "\u4E0A\u4F20\u56FE\u7247",
3664
3664
  clearLabel = "\u6E05\u9664"
3665
3665
  }) {
3666
- const handleFileChange = (id, file) => {
3666
+ const handleFileChange = (id2, file) => {
3667
3667
  if (!file) {
3668
3668
  return;
3669
3669
  }
@@ -3675,14 +3675,14 @@ function ImageMappingPanel({
3675
3675
  }
3676
3676
  onChange({
3677
3677
  ...value,
3678
- [id]: base64
3678
+ [id2]: base64
3679
3679
  });
3680
3680
  };
3681
3681
  reader.readAsDataURL(file);
3682
3682
  };
3683
- const handleRemove = (id) => {
3683
+ const handleRemove = (id2) => {
3684
3684
  const next = { ...value };
3685
- delete next[id];
3685
+ delete next[id2];
3686
3686
  onChange(next);
3687
3687
  };
3688
3688
  return /* @__PURE__ */ React69__namespace.default.createElement("details", { className: cn("rounded-lg border border-slate-200 bg-white/80 p-3", className) }, /* @__PURE__ */ React69__namespace.default.createElement("summary", { className: "cursor-pointer text-sm font-semibold text-slate-700" }, title), /* @__PURE__ */ React69__namespace.default.createElement("div", { className: "mt-3 grid grid-cols-1 gap-2 sm:grid-cols-2" }, items.map((item) => {
@@ -4822,8 +4822,8 @@ var FloatingMenuExample = () => {
4822
4822
  { id: 4, label: "\u5E2E\u52A9", icon: "\u2753" },
4823
4823
  { id: 5, label: "\u9000\u51FA", icon: "\u{1F6AA}" }
4824
4824
  ];
4825
- const handleMenuItemClick = (id) => {
4826
- console.log("\u70B9\u51FB\u4E86\u83DC\u5355\u9879: " + id);
4825
+ const handleMenuItemClick = (id2) => {
4826
+ console.log("\u70B9\u51FB\u4E86\u83DC\u5355\u9879: " + id2);
4827
4827
  };
4828
4828
  return /* @__PURE__ */ React69__namespace.default.createElement("div", { className: "w-full h-screen bg-gray-100 relative p-8" }, /* @__PURE__ */ React69__namespace.default.createElement("div", { className: "max-w-2xl mx-auto bg-white rounded-2xl shadow-sm p-8 mt-12" }, /* @__PURE__ */ React69__namespace.default.createElement("h1", { className: "text-3xl font-bold mb-4 text-gray-900" }, "\u60AC\u6D6E\u83DC\u5355\u793A\u4F8B"), /* @__PURE__ */ React69__namespace.default.createElement("p", { className: "text-gray-600 leading-relaxed mb-6" }, "\u8FD9\u662F\u4E00\u4E2A\u53EF\u62D6\u62FD\u7684\u60AC\u6D6E\u83DC\u5355\u7EC4\u4EF6\u793A\u4F8B\u3002\u4F60\u53EF\u4EE5\u5C1D\u8BD5\u62D6\u52A8\u4E0B\u65B9\u7684 ", /* @__PURE__ */ React69__namespace.default.createElement("span", { className: "font-bold text-blue-600" }, "\u84DD\u8272\u6309\u94AE"), " \u5230\u5904\u79FB\u52A8\u3002"), /* @__PURE__ */ React69__namespace.default.createElement("div", { className: "bg-blue-50 border-l-4 border-blue-500 p-4 mb-6" }, /* @__PURE__ */ React69__namespace.default.createElement("p", { className: "text-sm text-blue-700" }, /* @__PURE__ */ React69__namespace.default.createElement("strong", null, "\u667A\u80FD\u5B9A\u4F4D\uFF1A"), " \u83DC\u5355\u4F1A\u6839\u636E\u6309\u94AE\u5728\u5C4F\u5E55\u4E0A\u7684\u4F4D\u7F6E\u81EA\u52A8\u8C03\u6574\u5F39\u51FA\u65B9\u5411\uFF08\u5411\u5DE6\u6216\u5411\u53F3\uFF09\u3002"))), /* @__PURE__ */ React69__namespace.default.createElement(
4829
4829
  FloatingMenu_default,
@@ -5794,8 +5794,8 @@ function FireworksControlPanel({
5794
5794
  function useDanmakuController(options) {
5795
5795
  const [items, setItems] = React69.useState([]);
5796
5796
  const cursorRef = React69.useRef(0);
5797
- const removeItem = React69.useCallback((id) => {
5798
- setItems((prev) => prev.filter((item) => item.id !== id));
5797
+ const removeItem = React69.useCallback((id2) => {
5798
+ setItems((prev) => prev.filter((item) => item.id !== id2));
5799
5799
  }, []);
5800
5800
  const addIncoming = React69.useCallback((message) => {
5801
5801
  setItems((prev) => {
@@ -8315,19 +8315,19 @@ var FestivalCardConfigPage = ({
8315
8315
  const createNew = async () => {
8316
8316
  const name = window.prompt("\u8BF7\u8F93\u5165\u65B0\u5361\u7247\u540D\u79F0");
8317
8317
  if (!name) return;
8318
- const id = `festival-${Date.now()}`;
8318
+ const id2 = `festival-${Date.now()}`;
8319
8319
  const config = normalizeFestivalCardConfig({
8320
- id,
8320
+ id: id2,
8321
8321
  name
8322
8322
  });
8323
8323
  try {
8324
- const response = await fetch(`${apiBase}/${encodeURIComponent(id)}`, {
8324
+ const response = await fetch(`${apiBase}/${encodeURIComponent(id2)}`, {
8325
8325
  method: "PUT",
8326
8326
  headers: { "Content-Type": "application/json" },
8327
8327
  body: JSON.stringify({ config })
8328
8328
  });
8329
8329
  if (!response.ok) throw new Error(`\u521B\u5EFA\u5931\u8D25: ${response.status}`);
8330
- setSelectedId(id);
8330
+ setSelectedId(id2);
8331
8331
  await reloadList();
8332
8332
  window.alert("\u65B0\u5361\u7247\u521B\u5EFA\u6210\u529F");
8333
8333
  } catch (error) {
@@ -8432,21 +8432,21 @@ if (!memoryStore.has(defaultId)) {
8432
8432
  var createInMemoryFestivalCardDb = () => ({
8433
8433
  listConfigs() {
8434
8434
  return Promise.resolve(
8435
- Array.from(memoryStore.entries()).map(([id, config]) => ({
8436
- id,
8437
- name: config.name || id
8435
+ Array.from(memoryStore.entries()).map(([id2, config]) => ({
8436
+ id: id2,
8437
+ name: config.name || id2
8438
8438
  }))
8439
8439
  );
8440
8440
  },
8441
- getConfig(id) {
8442
- return Promise.resolve(memoryStore.get(id) || null);
8441
+ getConfig(id2) {
8442
+ return Promise.resolve(memoryStore.get(id2) || null);
8443
8443
  },
8444
- saveConfig(id, config) {
8445
- memoryStore.set(id, config);
8444
+ saveConfig(id2, config) {
8445
+ memoryStore.set(id2, config);
8446
8446
  return Promise.resolve();
8447
8447
  },
8448
- deleteConfig(id) {
8449
- memoryStore.delete(id);
8448
+ deleteConfig(id2) {
8449
+ memoryStore.delete(id2);
8450
8450
  return Promise.resolve();
8451
8451
  }
8452
8452
  });
@@ -9174,10 +9174,10 @@ var MikuContestService = class {
9174
9174
  for (const vote of this.votes) {
9175
9175
  counts.set(vote.submissionId, (counts.get(vote.submissionId) || 0) + 1);
9176
9176
  }
9177
- for (const [id, submission] of this.submissions.entries()) {
9178
- const nextCount = counts.get(id) || 0;
9177
+ for (const [id2, submission] of this.submissions.entries()) {
9178
+ const nextCount = counts.get(id2) || 0;
9179
9179
  if (submission.voteCount === nextCount) continue;
9180
- this.submissions.set(id, {
9180
+ this.submissions.set(id2, {
9181
9181
  ...submission,
9182
9182
  voteCount: nextCount,
9183
9183
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -9505,56 +9505,56 @@ var unwrap = (result) => {
9505
9505
  }
9506
9506
  return result.data;
9507
9507
  };
9508
- var createMikuContestApiClient = (basePath, requester) => {
9508
+ var createMikuContestApiClient = (basePath, requester2) => {
9509
9509
  return {
9510
9510
  async getSnapshot() {
9511
- const result = await requester(`${basePath}/contest`, { method: "GET" });
9511
+ const result = await requester2(`${basePath}/contest`, { method: "GET" });
9512
9512
  return unwrap(result);
9513
9513
  },
9514
9514
  async updateContestConfig(patch) {
9515
- const result = await requester(`${basePath}/contest`, {
9515
+ const result = await requester2(`${basePath}/contest`, {
9516
9516
  method: "PATCH",
9517
9517
  body: patch
9518
9518
  });
9519
9519
  return unwrap(result);
9520
9520
  },
9521
9521
  async createSubmission(input, mode = "web") {
9522
- const result = await requester(`${basePath}/submissions`, {
9522
+ const result = await requester2(`${basePath}/submissions`, {
9523
9523
  method: "POST",
9524
9524
  body: { payload: input, mode }
9525
9525
  });
9526
9526
  return unwrap(result);
9527
9527
  },
9528
9528
  async listSubmissions(filter) {
9529
- const result = await requester(
9529
+ const result = await requester2(
9530
9530
  `${basePath}/submissions${toQueryString(filter)}`,
9531
9531
  { method: "GET" }
9532
9532
  );
9533
9533
  return unwrap(result);
9534
9534
  },
9535
9535
  async reviewSubmission(input) {
9536
- const result = await requester(`${basePath}/submissions/review`, {
9536
+ const result = await requester2(`${basePath}/submissions/review`, {
9537
9537
  method: "POST",
9538
9538
  body: input
9539
9539
  });
9540
9540
  return unwrap(result);
9541
9541
  },
9542
9542
  async vote(input) {
9543
- const result = await requester(`${basePath}/votes`, {
9543
+ const result = await requester2(`${basePath}/votes`, {
9544
9544
  method: "POST",
9545
9545
  body: input
9546
9546
  });
9547
9547
  return unwrap(result);
9548
9548
  },
9549
9549
  async setVoterRestriction(input) {
9550
- const result = await requester(`${basePath}/admin/voter-restrictions`, {
9550
+ const result = await requester2(`${basePath}/admin/voter-restrictions`, {
9551
9551
  method: "POST",
9552
9552
  body: input
9553
9553
  });
9554
9554
  return unwrap(result);
9555
9555
  },
9556
9556
  async resetVotes(input) {
9557
- const result = await requester(
9557
+ const result = await requester2(
9558
9558
  `${basePath}/admin/votes/reset`,
9559
9559
  {
9560
9560
  method: "POST",
@@ -10045,6 +10045,354 @@ var MikuContestMiniappPage = () => {
10045
10045
  };
10046
10046
  var MikuContestMiniappPage_default = MikuContestMiniappPage;
10047
10047
 
10048
+ // src/huarongdao/index.ts
10049
+ var huarongdao_exports = {};
10050
+ __export(huarongdao_exports, {
10051
+ HuarongdaoService: () => HuarongdaoService,
10052
+ buildSolvedTiles: () => buildSolvedTiles,
10053
+ canMove: () => canMove,
10054
+ createCreateConfigHandler: () => createCreateConfigHandler,
10055
+ createDeleteConfigHandler: () => createDeleteConfigHandler,
10056
+ createGetSnapshotHandler: () => createGetSnapshotHandler,
10057
+ createHuarongdaoApiClient: () => createHuarongdaoApiClient,
10058
+ createHuarongdaoService: () => createHuarongdaoService,
10059
+ createHuarongdaoWebClient: () => createHuarongdaoWebClient,
10060
+ createListConfigsHandler: () => createListConfigsHandler,
10061
+ createUpdateConfigHandler: () => createUpdateConfigHandler,
10062
+ inversionCount: () => inversionCount,
10063
+ isSolvable: () => isSolvable,
10064
+ isSolved: () => isSolved,
10065
+ moveTile: () => moveTile,
10066
+ shuffleSolvable: () => shuffleSolvable,
10067
+ webUI: () => web_exports3
10068
+ });
10069
+
10070
+ // src/huarongdao/logic/game.ts
10071
+ var clone = (v) => [...v];
10072
+ var buildSolvedTiles = (rows, cols) => {
10073
+ const total = rows * cols;
10074
+ return Array.from({ length: total }, (_, i) => (i + 1) % total);
10075
+ };
10076
+ var isSolved = (tiles) => {
10077
+ return tiles.every((v, i, arr) => v === (i + 1) % arr.length);
10078
+ };
10079
+ var canMove = (tiles, rows, cols, tileIndex) => {
10080
+ const blank = tiles.indexOf(0);
10081
+ if (blank < 0 || tileIndex < 0 || tileIndex >= tiles.length) return false;
10082
+ const br = Math.floor(blank / cols);
10083
+ const bc = blank % cols;
10084
+ const tr = Math.floor(tileIndex / cols);
10085
+ const tc = tileIndex % cols;
10086
+ return Math.abs(br - tr) + Math.abs(bc - tc) === 1;
10087
+ };
10088
+ var moveTile = (state, tileIndex) => {
10089
+ if (!canMove(state.tiles, state.rows, state.cols, tileIndex)) return state;
10090
+ const nextTiles = clone(state.tiles);
10091
+ const blank = nextTiles.indexOf(0);
10092
+ const blankValue = nextTiles[blank];
10093
+ const tileValue = nextTiles[tileIndex];
10094
+ if (blankValue === void 0 || tileValue === void 0) return state;
10095
+ nextTiles[blank] = tileValue;
10096
+ nextTiles[tileIndex] = blankValue;
10097
+ const solved = isSolved(nextTiles);
10098
+ return {
10099
+ ...state,
10100
+ tiles: nextTiles,
10101
+ moveCount: state.moveCount + 1,
10102
+ isSolved: solved,
10103
+ finishedAt: solved ? Date.now() : void 0
10104
+ };
10105
+ };
10106
+ var inversionCount = (tiles) => {
10107
+ const arr = tiles.filter((n) => n !== 0);
10108
+ let cnt = 0;
10109
+ for (let i = 0; i < arr.length; i += 1) {
10110
+ for (let j = i + 1; j < arr.length; j += 1) {
10111
+ if ((arr[i] ?? 0) > (arr[j] ?? 0)) cnt += 1;
10112
+ }
10113
+ }
10114
+ return cnt;
10115
+ };
10116
+ var isSolvable = (tiles, rows, cols) => {
10117
+ const inv = inversionCount(tiles);
10118
+ if (cols % 2 === 1) return inv % 2 === 0;
10119
+ const blankRowFromBottom = rows - Math.floor(tiles.indexOf(0) / cols);
10120
+ return blankRowFromBottom % 2 === 0 !== (inv % 2 === 0);
10121
+ };
10122
+ var shuffleSolvable = (rows, cols, steps = 80) => {
10123
+ let tiles = buildSolvedTiles(rows, cols);
10124
+ for (let i = 0; i < steps; i += 1) {
10125
+ const blank = tiles.indexOf(0);
10126
+ const br = Math.floor(blank / cols);
10127
+ const bc = blank % cols;
10128
+ const candidate = [];
10129
+ const dirs = [
10130
+ [1, 0],
10131
+ [-1, 0],
10132
+ [0, 1],
10133
+ [0, -1]
10134
+ ];
10135
+ dirs.forEach(([dr, dc]) => {
10136
+ const nr = br + dr;
10137
+ const nc = bc + dc;
10138
+ if (nr >= 0 && nr < rows && nc >= 0 && nc < cols) candidate.push(nr * cols + nc);
10139
+ });
10140
+ const idx = candidate[Math.floor(Math.random() * candidate.length)] ?? blank;
10141
+ const next = clone(tiles);
10142
+ [next[blank], next[idx]] = [next[idx] ?? 0, next[blank] ?? 0];
10143
+ tiles = next;
10144
+ }
10145
+ return tiles;
10146
+ };
10147
+
10148
+ // src/huarongdao/service/api/client.ts
10149
+ var unwrap2 = (result) => {
10150
+ if (!result.success || result.data === void 0) throw new Error(result.error || "\u8BF7\u6C42\u5931\u8D25");
10151
+ return result.data;
10152
+ };
10153
+ var createHuarongdaoApiClient = (basePath, requester2) => ({
10154
+ async getSnapshot() {
10155
+ return unwrap2(await requester2(`${basePath}/snapshot`, { method: "GET" }));
10156
+ },
10157
+ async listConfigs() {
10158
+ return unwrap2(await requester2(`${basePath}/configs`, { method: "GET" }));
10159
+ },
10160
+ async createConfig(input) {
10161
+ return unwrap2(await requester2(`${basePath}/configs`, { method: "POST", body: input }));
10162
+ },
10163
+ async updateConfig(id2, patch) {
10164
+ return unwrap2(await requester2(`${basePath}/configs`, { method: "PATCH", body: { id: id2, patch } }));
10165
+ },
10166
+ async deleteConfig(id2) {
10167
+ return unwrap2(await requester2(`${basePath}/configs`, { method: "DELETE", body: { id: id2 } }));
10168
+ }
10169
+ });
10170
+
10171
+ // src/huarongdao/service/web/client.ts
10172
+ var requester = (options) => {
10173
+ const baseUrl = options.baseUrl || "";
10174
+ return async (url, req) => {
10175
+ const res = await fetch(`${baseUrl}${url}`, {
10176
+ method: req?.method || "GET",
10177
+ headers: { "Content-Type": "application/json", ...options.headers || {} },
10178
+ body: req?.body ? JSON.stringify(req.body) : void 0
10179
+ });
10180
+ return await res.json();
10181
+ };
10182
+ };
10183
+ var createHuarongdaoWebClient = (options = {}) => {
10184
+ return createHuarongdaoApiClient(options.basePath || "/api/huarongdao", requester(options));
10185
+ };
10186
+
10187
+ // src/huarongdao/server/service.ts
10188
+ var id = () => `puzzle_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
10189
+ var HuarongdaoService = class {
10190
+ constructor() {
10191
+ this.configs = /* @__PURE__ */ new Map();
10192
+ }
10193
+ listConfigs() {
10194
+ return [...this.configs.values()];
10195
+ }
10196
+ getBySlug(slug) {
10197
+ return [...this.configs.values()].find((c) => c.slug === slug) || null;
10198
+ }
10199
+ createConfig(input) {
10200
+ const now = (/* @__PURE__ */ new Date()).toISOString();
10201
+ const next = {
10202
+ id: id(),
10203
+ slug: input.slug,
10204
+ name: input.name,
10205
+ description: input.description,
10206
+ status: "draft",
10207
+ rows: input.rows,
10208
+ cols: input.cols,
10209
+ sourceImageUrl: input.sourceImageUrl,
10210
+ showReference: input.showReference ?? true,
10211
+ shuffleSteps: input.shuffleSteps ?? 80,
10212
+ timeLimitSec: input.timeLimitSec,
10213
+ startMode: input.startMode ?? "random-solvable",
10214
+ initialTiles: input.initialTiles,
10215
+ createdAt: now,
10216
+ updatedAt: now
10217
+ };
10218
+ this.configs.set(next.id, next);
10219
+ return next;
10220
+ }
10221
+ updateConfig(id2, patch) {
10222
+ const cur = this.configs.get(id2);
10223
+ if (!cur) throw new Error("\u914D\u7F6E\u4E0D\u5B58\u5728");
10224
+ const next = { ...cur, ...patch, id: cur.id, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
10225
+ this.configs.set(id2, next);
10226
+ return next;
10227
+ }
10228
+ deleteConfig(id2) {
10229
+ this.configs.delete(id2);
10230
+ }
10231
+ getSnapshot() {
10232
+ const configs = this.listConfigs();
10233
+ return {
10234
+ configs,
10235
+ activeConfig: configs.find((c) => c.status === "active")
10236
+ };
10237
+ }
10238
+ };
10239
+ var createHuarongdaoService = () => new HuarongdaoService();
10240
+ var resolveService2 = (config) => config?.service || createHuarongdaoService();
10241
+ var createGetSnapshotHandler = (config) => {
10242
+ const service = resolveService2(config);
10243
+ return async (_req) => server.NextResponse.json({ success: true, data: service.getSnapshot() });
10244
+ };
10245
+ var createListConfigsHandler = (config) => {
10246
+ const service = resolveService2(config);
10247
+ return async (_req) => server.NextResponse.json({ success: true, data: service.listConfigs() });
10248
+ };
10249
+ var createCreateConfigHandler = (config) => {
10250
+ const service = resolveService2(config);
10251
+ return async (req) => {
10252
+ try {
10253
+ const body = await req.json();
10254
+ const data = service.createConfig(body);
10255
+ return server.NextResponse.json({ success: true, data });
10256
+ } catch (e) {
10257
+ return server.NextResponse.json({ success: false, error: e.message }, { status: 400 });
10258
+ }
10259
+ };
10260
+ };
10261
+ var createUpdateConfigHandler = (config) => {
10262
+ const service = resolveService2(config);
10263
+ return async (req) => {
10264
+ try {
10265
+ const body = await req.json();
10266
+ const data = service.updateConfig(body.id, body.patch || {});
10267
+ return server.NextResponse.json({ success: true, data });
10268
+ } catch (e) {
10269
+ return server.NextResponse.json({ success: false, error: e.message }, { status: 400 });
10270
+ }
10271
+ };
10272
+ };
10273
+ var createDeleteConfigHandler = (config) => {
10274
+ const service = resolveService2(config);
10275
+ return async (req) => {
10276
+ try {
10277
+ const body = await req.json();
10278
+ service.deleteConfig(body.id);
10279
+ return server.NextResponse.json({ success: true, data: true });
10280
+ } catch (e) {
10281
+ return server.NextResponse.json({ success: false, error: e.message }, { status: 400 });
10282
+ }
10283
+ };
10284
+ };
10285
+
10286
+ // src/huarongdao/ui/web/index.ts
10287
+ var web_exports3 = {};
10288
+ __export(web_exports3, {
10289
+ HuarongdaoBoard: () => HuarongdaoBoard_default,
10290
+ HuarongdaoConfigPage: () => HuarongdaoConfigPage_default,
10291
+ HuarongdaoGamePage: () => HuarongdaoGamePage_default
10292
+ });
10293
+ var HuarongdaoBoard = ({ tiles, rows, cols, imageUrl, onClickTile }) => {
10294
+ const total = rows * cols;
10295
+ return /* @__PURE__ */ React69__namespace.default.createElement(
10296
+ "div",
10297
+ {
10298
+ style: {
10299
+ display: "grid",
10300
+ gridTemplateColumns: `repeat(${cols}, 96px)`,
10301
+ gridTemplateRows: `repeat(${rows}, 96px)`,
10302
+ gap: 6
10303
+ }
10304
+ },
10305
+ tiles.map((tile, index) => {
10306
+ if (tile === 0) return /* @__PURE__ */ React69__namespace.default.createElement("div", { key: `blank-${index}`, style: { background: "#ddd" } });
10307
+ const pieceIndex = tile - 1;
10308
+ const pr = Math.floor(pieceIndex / cols);
10309
+ const pc = pieceIndex % cols;
10310
+ return /* @__PURE__ */ React69__namespace.default.createElement(
10311
+ "button",
10312
+ {
10313
+ key: `${tile}-${index}`,
10314
+ onClick: () => onClickTile(index),
10315
+ style: {
10316
+ border: "1px solid #666",
10317
+ cursor: "pointer",
10318
+ backgroundImage: `url(${imageUrl})`,
10319
+ backgroundSize: `${cols * 96}px ${rows * 96}px`,
10320
+ backgroundPosition: `${-pc * 96}px ${-pr * 96}px`
10321
+ }
10322
+ }
10323
+ );
10324
+ }),
10325
+ tiles.length !== total ? /* @__PURE__ */ React69__namespace.default.createElement("div", null, "tiles invalid") : null
10326
+ );
10327
+ };
10328
+ var HuarongdaoBoard_default = HuarongdaoBoard;
10329
+ var HuarongdaoGamePage = ({ config }) => {
10330
+ const initial = React69.useMemo(() => {
10331
+ const tiles = config.startMode === "custom-layout" && config.initialTiles?.length === config.rows * config.cols ? config.initialTiles : shuffleSolvable(config.rows, config.cols, config.shuffleSteps);
10332
+ return {
10333
+ tiles,
10334
+ rows: config.rows,
10335
+ cols: config.cols,
10336
+ moveCount: 0,
10337
+ startedAt: Date.now(),
10338
+ isSolved: false
10339
+ };
10340
+ }, [config]);
10341
+ const [state, setState] = React69.useState(initial);
10342
+ const reset = () => {
10343
+ setState({
10344
+ ...state,
10345
+ tiles: shuffleSolvable(config.rows, config.cols, config.shuffleSteps),
10346
+ moveCount: 0,
10347
+ startedAt: Date.now(),
10348
+ finishedAt: void 0,
10349
+ isSolved: false
10350
+ });
10351
+ };
10352
+ const solveNow = () => {
10353
+ setState((prev) => ({ ...prev, tiles: buildSolvedTiles(config.rows, config.cols), isSolved: true, finishedAt: Date.now() }));
10354
+ };
10355
+ const durationSec = Math.floor(((state.finishedAt || Date.now()) - state.startedAt) / 1e3);
10356
+ return /* @__PURE__ */ React69__namespace.default.createElement("section", null, /* @__PURE__ */ React69__namespace.default.createElement("h2", null, config.name), /* @__PURE__ */ React69__namespace.default.createElement("p", null, "\u6B65\u6570\uFF1A", state.moveCount, " \uFF5C \u7528\u65F6\uFF1A", durationSec, "s ", state.isSolved ? "\uFF5C\u5DF2\u901A\u5173 \u{1F389}" : ""), /* @__PURE__ */ React69__namespace.default.createElement(
10357
+ HuarongdaoBoard_default,
10358
+ {
10359
+ tiles: state.tiles,
10360
+ rows: state.rows,
10361
+ cols: state.cols,
10362
+ imageUrl: config.sourceImageUrl,
10363
+ onClickTile: (idx) => setState((prev) => moveTile(prev, idx))
10364
+ }
10365
+ ), /* @__PURE__ */ React69__namespace.default.createElement("div", { style: { marginTop: 12 } }, /* @__PURE__ */ React69__namespace.default.createElement("button", { onClick: reset }, "\u91CD\u65B0\u6253\u4E71"), /* @__PURE__ */ React69__namespace.default.createElement("button", { onClick: solveNow }, "\u4E00\u952E\u5B8C\u6210(\u6D4B\u8BD5)")), config.showReference ? /* @__PURE__ */ React69__namespace.default.createElement("div", { style: { marginTop: 12 } }, /* @__PURE__ */ React69__namespace.default.createElement("div", null, "\u53C2\u8003\u56FE\uFF1A"), /* @__PURE__ */ React69__namespace.default.createElement("img", { src: config.sourceImageUrl, alt: "reference", style: { width: 180, border: "1px solid #ccc" } })) : null);
10366
+ };
10367
+ var HuarongdaoGamePage_default = HuarongdaoGamePage;
10368
+ var HuarongdaoConfigPage = () => {
10369
+ const service = React69.useMemo(() => createHuarongdaoService(), []);
10370
+ const [version, setVersion] = React69.useState(0);
10371
+ const [name, setName] = React69.useState("\u793A\u4F8B\u534E\u5BB9\u9053");
10372
+ const [slug, setSlug] = React69.useState("sample-huarongdao");
10373
+ const [imageUrl, setImageUrl] = React69.useState("https://i.imgur.com/6z7Qw6M.png");
10374
+ const [rows, setRows] = React69.useState(3);
10375
+ const [cols, setCols] = React69.useState(3);
10376
+ const list = React69.useMemo(() => {
10377
+ return service.listConfigs();
10378
+ }, [service, version]);
10379
+ const create = () => {
10380
+ const input = {
10381
+ name,
10382
+ slug,
10383
+ sourceImageUrl: imageUrl,
10384
+ rows,
10385
+ cols,
10386
+ showReference: true,
10387
+ shuffleSteps: 80
10388
+ };
10389
+ service.createConfig(input);
10390
+ setVersion((v) => v + 1);
10391
+ };
10392
+ return /* @__PURE__ */ React69__namespace.default.createElement("section", null, /* @__PURE__ */ React69__namespace.default.createElement("h2", null, "\u534E\u5BB9\u9053\u540E\u53F0\u914D\u7F6E\u9875"), /* @__PURE__ */ React69__namespace.default.createElement("p", null, "\u652F\u6301\u591A\u5957\u914D\u7F6E\u521B\u5EFA\u3001\u53C2\u6570\u5316\u7BA1\u7406\uFF08V1 \u9AA8\u67B6\uFF09"), /* @__PURE__ */ React69__namespace.default.createElement("div", null, /* @__PURE__ */ React69__namespace.default.createElement("input", { value: name, onChange: (e) => setName(e.target.value), placeholder: "name" }), /* @__PURE__ */ React69__namespace.default.createElement("input", { value: slug, onChange: (e) => setSlug(e.target.value), placeholder: "slug" }), /* @__PURE__ */ React69__namespace.default.createElement("input", { value: imageUrl, onChange: (e) => setImageUrl(e.target.value), placeholder: "image url" }), /* @__PURE__ */ React69__namespace.default.createElement("input", { type: "number", value: rows, onChange: (e) => setRows(Number(e.target.value) || 3) }), /* @__PURE__ */ React69__namespace.default.createElement("input", { type: "number", value: cols, onChange: (e) => setCols(Number(e.target.value) || 3) }), /* @__PURE__ */ React69__namespace.default.createElement("button", { onClick: create }, "\u521B\u5EFA\u914D\u7F6E")), /* @__PURE__ */ React69__namespace.default.createElement("ul", null, list.map((item) => /* @__PURE__ */ React69__namespace.default.createElement("li", { key: item.id }, item.name, " (", item.slug, ") - ", item.rows, "x", item.cols, " - ", item.status))));
10393
+ };
10394
+ var HuarongdaoConfigPage_default = HuarongdaoConfigPage;
10395
+
10048
10396
  // src/storage/adapters/react-native-adapter.ts
10049
10397
  var AsyncStorage = null;
10050
10398
  try {
@@ -10602,6 +10950,7 @@ exports.getCompletionFilterDisplayName = getCompletionFilterDisplayName;
10602
10950
  exports.getCompletionStatusColor = getCompletionStatusColor;
10603
10951
  exports.getCompletionStatusText = getCompletionStatusText;
10604
10952
  exports.getExperimentCounts = getExperimentCounts;
10953
+ exports.huarongdao = huarongdao_exports;
10605
10954
  exports.japaneseUtils = japaneseUtils;
10606
10955
  exports.logger = logger;
10607
10956
  exports.mikuContestConfigs = mikuContestConfigs;