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.mjs CHANGED
@@ -3637,7 +3637,7 @@ function ImageMappingPanel({
3637
3637
  uploadLabel = "\u4E0A\u4F20\u56FE\u7247",
3638
3638
  clearLabel = "\u6E05\u9664"
3639
3639
  }) {
3640
- const handleFileChange = (id, file) => {
3640
+ const handleFileChange = (id2, file) => {
3641
3641
  if (!file) {
3642
3642
  return;
3643
3643
  }
@@ -3649,14 +3649,14 @@ function ImageMappingPanel({
3649
3649
  }
3650
3650
  onChange({
3651
3651
  ...value,
3652
- [id]: base64
3652
+ [id2]: base64
3653
3653
  });
3654
3654
  };
3655
3655
  reader.readAsDataURL(file);
3656
3656
  };
3657
- const handleRemove = (id) => {
3657
+ const handleRemove = (id2) => {
3658
3658
  const next = { ...value };
3659
- delete next[id];
3659
+ delete next[id2];
3660
3660
  onChange(next);
3661
3661
  };
3662
3662
  return /* @__PURE__ */ React69__default.createElement("details", { className: cn("rounded-lg border border-slate-200 bg-white/80 p-3", className) }, /* @__PURE__ */ React69__default.createElement("summary", { className: "cursor-pointer text-sm font-semibold text-slate-700" }, title), /* @__PURE__ */ React69__default.createElement("div", { className: "mt-3 grid grid-cols-1 gap-2 sm:grid-cols-2" }, items.map((item) => {
@@ -4796,8 +4796,8 @@ var FloatingMenuExample = () => {
4796
4796
  { id: 4, label: "\u5E2E\u52A9", icon: "\u2753" },
4797
4797
  { id: 5, label: "\u9000\u51FA", icon: "\u{1F6AA}" }
4798
4798
  ];
4799
- const handleMenuItemClick = (id) => {
4800
- console.log("\u70B9\u51FB\u4E86\u83DC\u5355\u9879: " + id);
4799
+ const handleMenuItemClick = (id2) => {
4800
+ console.log("\u70B9\u51FB\u4E86\u83DC\u5355\u9879: " + id2);
4801
4801
  };
4802
4802
  return /* @__PURE__ */ React69__default.createElement("div", { className: "w-full h-screen bg-gray-100 relative p-8" }, /* @__PURE__ */ React69__default.createElement("div", { className: "max-w-2xl mx-auto bg-white rounded-2xl shadow-sm p-8 mt-12" }, /* @__PURE__ */ React69__default.createElement("h1", { className: "text-3xl font-bold mb-4 text-gray-900" }, "\u60AC\u6D6E\u83DC\u5355\u793A\u4F8B"), /* @__PURE__ */ React69__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__default.createElement("span", { className: "font-bold text-blue-600" }, "\u84DD\u8272\u6309\u94AE"), " \u5230\u5904\u79FB\u52A8\u3002"), /* @__PURE__ */ React69__default.createElement("div", { className: "bg-blue-50 border-l-4 border-blue-500 p-4 mb-6" }, /* @__PURE__ */ React69__default.createElement("p", { className: "text-sm text-blue-700" }, /* @__PURE__ */ React69__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__default.createElement(
4803
4803
  FloatingMenu_default,
@@ -5768,8 +5768,8 @@ function FireworksControlPanel({
5768
5768
  function useDanmakuController(options) {
5769
5769
  const [items, setItems] = useState([]);
5770
5770
  const cursorRef = useRef(0);
5771
- const removeItem = useCallback((id) => {
5772
- setItems((prev) => prev.filter((item) => item.id !== id));
5771
+ const removeItem = useCallback((id2) => {
5772
+ setItems((prev) => prev.filter((item) => item.id !== id2));
5773
5773
  }, []);
5774
5774
  const addIncoming = useCallback((message) => {
5775
5775
  setItems((prev) => {
@@ -8289,19 +8289,19 @@ var FestivalCardConfigPage = ({
8289
8289
  const createNew = async () => {
8290
8290
  const name = window.prompt("\u8BF7\u8F93\u5165\u65B0\u5361\u7247\u540D\u79F0");
8291
8291
  if (!name) return;
8292
- const id = `festival-${Date.now()}`;
8292
+ const id2 = `festival-${Date.now()}`;
8293
8293
  const config = normalizeFestivalCardConfig({
8294
- id,
8294
+ id: id2,
8295
8295
  name
8296
8296
  });
8297
8297
  try {
8298
- const response = await fetch(`${apiBase}/${encodeURIComponent(id)}`, {
8298
+ const response = await fetch(`${apiBase}/${encodeURIComponent(id2)}`, {
8299
8299
  method: "PUT",
8300
8300
  headers: { "Content-Type": "application/json" },
8301
8301
  body: JSON.stringify({ config })
8302
8302
  });
8303
8303
  if (!response.ok) throw new Error(`\u521B\u5EFA\u5931\u8D25: ${response.status}`);
8304
- setSelectedId(id);
8304
+ setSelectedId(id2);
8305
8305
  await reloadList();
8306
8306
  window.alert("\u65B0\u5361\u7247\u521B\u5EFA\u6210\u529F");
8307
8307
  } catch (error) {
@@ -8406,21 +8406,21 @@ if (!memoryStore.has(defaultId)) {
8406
8406
  var createInMemoryFestivalCardDb = () => ({
8407
8407
  listConfigs() {
8408
8408
  return Promise.resolve(
8409
- Array.from(memoryStore.entries()).map(([id, config]) => ({
8410
- id,
8411
- name: config.name || id
8409
+ Array.from(memoryStore.entries()).map(([id2, config]) => ({
8410
+ id: id2,
8411
+ name: config.name || id2
8412
8412
  }))
8413
8413
  );
8414
8414
  },
8415
- getConfig(id) {
8416
- return Promise.resolve(memoryStore.get(id) || null);
8415
+ getConfig(id2) {
8416
+ return Promise.resolve(memoryStore.get(id2) || null);
8417
8417
  },
8418
- saveConfig(id, config) {
8419
- memoryStore.set(id, config);
8418
+ saveConfig(id2, config) {
8419
+ memoryStore.set(id2, config);
8420
8420
  return Promise.resolve();
8421
8421
  },
8422
- deleteConfig(id) {
8423
- memoryStore.delete(id);
8422
+ deleteConfig(id2) {
8423
+ memoryStore.delete(id2);
8424
8424
  return Promise.resolve();
8425
8425
  }
8426
8426
  });
@@ -9148,10 +9148,10 @@ var MikuContestService = class {
9148
9148
  for (const vote of this.votes) {
9149
9149
  counts.set(vote.submissionId, (counts.get(vote.submissionId) || 0) + 1);
9150
9150
  }
9151
- for (const [id, submission] of this.submissions.entries()) {
9152
- const nextCount = counts.get(id) || 0;
9151
+ for (const [id2, submission] of this.submissions.entries()) {
9152
+ const nextCount = counts.get(id2) || 0;
9153
9153
  if (submission.voteCount === nextCount) continue;
9154
- this.submissions.set(id, {
9154
+ this.submissions.set(id2, {
9155
9155
  ...submission,
9156
9156
  voteCount: nextCount,
9157
9157
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -9479,56 +9479,56 @@ var unwrap = (result) => {
9479
9479
  }
9480
9480
  return result.data;
9481
9481
  };
9482
- var createMikuContestApiClient = (basePath, requester) => {
9482
+ var createMikuContestApiClient = (basePath, requester2) => {
9483
9483
  return {
9484
9484
  async getSnapshot() {
9485
- const result = await requester(`${basePath}/contest`, { method: "GET" });
9485
+ const result = await requester2(`${basePath}/contest`, { method: "GET" });
9486
9486
  return unwrap(result);
9487
9487
  },
9488
9488
  async updateContestConfig(patch) {
9489
- const result = await requester(`${basePath}/contest`, {
9489
+ const result = await requester2(`${basePath}/contest`, {
9490
9490
  method: "PATCH",
9491
9491
  body: patch
9492
9492
  });
9493
9493
  return unwrap(result);
9494
9494
  },
9495
9495
  async createSubmission(input, mode = "web") {
9496
- const result = await requester(`${basePath}/submissions`, {
9496
+ const result = await requester2(`${basePath}/submissions`, {
9497
9497
  method: "POST",
9498
9498
  body: { payload: input, mode }
9499
9499
  });
9500
9500
  return unwrap(result);
9501
9501
  },
9502
9502
  async listSubmissions(filter) {
9503
- const result = await requester(
9503
+ const result = await requester2(
9504
9504
  `${basePath}/submissions${toQueryString(filter)}`,
9505
9505
  { method: "GET" }
9506
9506
  );
9507
9507
  return unwrap(result);
9508
9508
  },
9509
9509
  async reviewSubmission(input) {
9510
- const result = await requester(`${basePath}/submissions/review`, {
9510
+ const result = await requester2(`${basePath}/submissions/review`, {
9511
9511
  method: "POST",
9512
9512
  body: input
9513
9513
  });
9514
9514
  return unwrap(result);
9515
9515
  },
9516
9516
  async vote(input) {
9517
- const result = await requester(`${basePath}/votes`, {
9517
+ const result = await requester2(`${basePath}/votes`, {
9518
9518
  method: "POST",
9519
9519
  body: input
9520
9520
  });
9521
9521
  return unwrap(result);
9522
9522
  },
9523
9523
  async setVoterRestriction(input) {
9524
- const result = await requester(`${basePath}/admin/voter-restrictions`, {
9524
+ const result = await requester2(`${basePath}/admin/voter-restrictions`, {
9525
9525
  method: "POST",
9526
9526
  body: input
9527
9527
  });
9528
9528
  return unwrap(result);
9529
9529
  },
9530
9530
  async resetVotes(input) {
9531
- const result = await requester(
9531
+ const result = await requester2(
9532
9532
  `${basePath}/admin/votes/reset`,
9533
9533
  {
9534
9534
  method: "POST",
@@ -10019,6 +10019,354 @@ var MikuContestMiniappPage = () => {
10019
10019
  };
10020
10020
  var MikuContestMiniappPage_default = MikuContestMiniappPage;
10021
10021
 
10022
+ // src/huarongdao/index.ts
10023
+ var huarongdao_exports = {};
10024
+ __export(huarongdao_exports, {
10025
+ HuarongdaoService: () => HuarongdaoService,
10026
+ buildSolvedTiles: () => buildSolvedTiles,
10027
+ canMove: () => canMove,
10028
+ createCreateConfigHandler: () => createCreateConfigHandler,
10029
+ createDeleteConfigHandler: () => createDeleteConfigHandler,
10030
+ createGetSnapshotHandler: () => createGetSnapshotHandler,
10031
+ createHuarongdaoApiClient: () => createHuarongdaoApiClient,
10032
+ createHuarongdaoService: () => createHuarongdaoService,
10033
+ createHuarongdaoWebClient: () => createHuarongdaoWebClient,
10034
+ createListConfigsHandler: () => createListConfigsHandler,
10035
+ createUpdateConfigHandler: () => createUpdateConfigHandler,
10036
+ inversionCount: () => inversionCount,
10037
+ isSolvable: () => isSolvable,
10038
+ isSolved: () => isSolved,
10039
+ moveTile: () => moveTile,
10040
+ shuffleSolvable: () => shuffleSolvable,
10041
+ webUI: () => web_exports3
10042
+ });
10043
+
10044
+ // src/huarongdao/logic/game.ts
10045
+ var clone = (v) => [...v];
10046
+ var buildSolvedTiles = (rows, cols) => {
10047
+ const total = rows * cols;
10048
+ return Array.from({ length: total }, (_, i) => (i + 1) % total);
10049
+ };
10050
+ var isSolved = (tiles) => {
10051
+ return tiles.every((v, i, arr) => v === (i + 1) % arr.length);
10052
+ };
10053
+ var canMove = (tiles, rows, cols, tileIndex) => {
10054
+ const blank = tiles.indexOf(0);
10055
+ if (blank < 0 || tileIndex < 0 || tileIndex >= tiles.length) return false;
10056
+ const br = Math.floor(blank / cols);
10057
+ const bc = blank % cols;
10058
+ const tr = Math.floor(tileIndex / cols);
10059
+ const tc = tileIndex % cols;
10060
+ return Math.abs(br - tr) + Math.abs(bc - tc) === 1;
10061
+ };
10062
+ var moveTile = (state, tileIndex) => {
10063
+ if (!canMove(state.tiles, state.rows, state.cols, tileIndex)) return state;
10064
+ const nextTiles = clone(state.tiles);
10065
+ const blank = nextTiles.indexOf(0);
10066
+ const blankValue = nextTiles[blank];
10067
+ const tileValue = nextTiles[tileIndex];
10068
+ if (blankValue === void 0 || tileValue === void 0) return state;
10069
+ nextTiles[blank] = tileValue;
10070
+ nextTiles[tileIndex] = blankValue;
10071
+ const solved = isSolved(nextTiles);
10072
+ return {
10073
+ ...state,
10074
+ tiles: nextTiles,
10075
+ moveCount: state.moveCount + 1,
10076
+ isSolved: solved,
10077
+ finishedAt: solved ? Date.now() : void 0
10078
+ };
10079
+ };
10080
+ var inversionCount = (tiles) => {
10081
+ const arr = tiles.filter((n) => n !== 0);
10082
+ let cnt = 0;
10083
+ for (let i = 0; i < arr.length; i += 1) {
10084
+ for (let j = i + 1; j < arr.length; j += 1) {
10085
+ if ((arr[i] ?? 0) > (arr[j] ?? 0)) cnt += 1;
10086
+ }
10087
+ }
10088
+ return cnt;
10089
+ };
10090
+ var isSolvable = (tiles, rows, cols) => {
10091
+ const inv = inversionCount(tiles);
10092
+ if (cols % 2 === 1) return inv % 2 === 0;
10093
+ const blankRowFromBottom = rows - Math.floor(tiles.indexOf(0) / cols);
10094
+ return blankRowFromBottom % 2 === 0 !== (inv % 2 === 0);
10095
+ };
10096
+ var shuffleSolvable = (rows, cols, steps = 80) => {
10097
+ let tiles = buildSolvedTiles(rows, cols);
10098
+ for (let i = 0; i < steps; i += 1) {
10099
+ const blank = tiles.indexOf(0);
10100
+ const br = Math.floor(blank / cols);
10101
+ const bc = blank % cols;
10102
+ const candidate = [];
10103
+ const dirs = [
10104
+ [1, 0],
10105
+ [-1, 0],
10106
+ [0, 1],
10107
+ [0, -1]
10108
+ ];
10109
+ dirs.forEach(([dr, dc]) => {
10110
+ const nr = br + dr;
10111
+ const nc = bc + dc;
10112
+ if (nr >= 0 && nr < rows && nc >= 0 && nc < cols) candidate.push(nr * cols + nc);
10113
+ });
10114
+ const idx = candidate[Math.floor(Math.random() * candidate.length)] ?? blank;
10115
+ const next = clone(tiles);
10116
+ [next[blank], next[idx]] = [next[idx] ?? 0, next[blank] ?? 0];
10117
+ tiles = next;
10118
+ }
10119
+ return tiles;
10120
+ };
10121
+
10122
+ // src/huarongdao/service/api/client.ts
10123
+ var unwrap2 = (result) => {
10124
+ if (!result.success || result.data === void 0) throw new Error(result.error || "\u8BF7\u6C42\u5931\u8D25");
10125
+ return result.data;
10126
+ };
10127
+ var createHuarongdaoApiClient = (basePath, requester2) => ({
10128
+ async getSnapshot() {
10129
+ return unwrap2(await requester2(`${basePath}/snapshot`, { method: "GET" }));
10130
+ },
10131
+ async listConfigs() {
10132
+ return unwrap2(await requester2(`${basePath}/configs`, { method: "GET" }));
10133
+ },
10134
+ async createConfig(input) {
10135
+ return unwrap2(await requester2(`${basePath}/configs`, { method: "POST", body: input }));
10136
+ },
10137
+ async updateConfig(id2, patch) {
10138
+ return unwrap2(await requester2(`${basePath}/configs`, { method: "PATCH", body: { id: id2, patch } }));
10139
+ },
10140
+ async deleteConfig(id2) {
10141
+ return unwrap2(await requester2(`${basePath}/configs`, { method: "DELETE", body: { id: id2 } }));
10142
+ }
10143
+ });
10144
+
10145
+ // src/huarongdao/service/web/client.ts
10146
+ var requester = (options) => {
10147
+ const baseUrl = options.baseUrl || "";
10148
+ return async (url, req) => {
10149
+ const res = await fetch(`${baseUrl}${url}`, {
10150
+ method: req?.method || "GET",
10151
+ headers: { "Content-Type": "application/json", ...options.headers || {} },
10152
+ body: req?.body ? JSON.stringify(req.body) : void 0
10153
+ });
10154
+ return await res.json();
10155
+ };
10156
+ };
10157
+ var createHuarongdaoWebClient = (options = {}) => {
10158
+ return createHuarongdaoApiClient(options.basePath || "/api/huarongdao", requester(options));
10159
+ };
10160
+
10161
+ // src/huarongdao/server/service.ts
10162
+ var id = () => `puzzle_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
10163
+ var HuarongdaoService = class {
10164
+ constructor() {
10165
+ this.configs = /* @__PURE__ */ new Map();
10166
+ }
10167
+ listConfigs() {
10168
+ return [...this.configs.values()];
10169
+ }
10170
+ getBySlug(slug) {
10171
+ return [...this.configs.values()].find((c) => c.slug === slug) || null;
10172
+ }
10173
+ createConfig(input) {
10174
+ const now = (/* @__PURE__ */ new Date()).toISOString();
10175
+ const next = {
10176
+ id: id(),
10177
+ slug: input.slug,
10178
+ name: input.name,
10179
+ description: input.description,
10180
+ status: "draft",
10181
+ rows: input.rows,
10182
+ cols: input.cols,
10183
+ sourceImageUrl: input.sourceImageUrl,
10184
+ showReference: input.showReference ?? true,
10185
+ shuffleSteps: input.shuffleSteps ?? 80,
10186
+ timeLimitSec: input.timeLimitSec,
10187
+ startMode: input.startMode ?? "random-solvable",
10188
+ initialTiles: input.initialTiles,
10189
+ createdAt: now,
10190
+ updatedAt: now
10191
+ };
10192
+ this.configs.set(next.id, next);
10193
+ return next;
10194
+ }
10195
+ updateConfig(id2, patch) {
10196
+ const cur = this.configs.get(id2);
10197
+ if (!cur) throw new Error("\u914D\u7F6E\u4E0D\u5B58\u5728");
10198
+ const next = { ...cur, ...patch, id: cur.id, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
10199
+ this.configs.set(id2, next);
10200
+ return next;
10201
+ }
10202
+ deleteConfig(id2) {
10203
+ this.configs.delete(id2);
10204
+ }
10205
+ getSnapshot() {
10206
+ const configs = this.listConfigs();
10207
+ return {
10208
+ configs,
10209
+ activeConfig: configs.find((c) => c.status === "active")
10210
+ };
10211
+ }
10212
+ };
10213
+ var createHuarongdaoService = () => new HuarongdaoService();
10214
+ var resolveService2 = (config) => config?.service || createHuarongdaoService();
10215
+ var createGetSnapshotHandler = (config) => {
10216
+ const service = resolveService2(config);
10217
+ return async (_req) => NextResponse.json({ success: true, data: service.getSnapshot() });
10218
+ };
10219
+ var createListConfigsHandler = (config) => {
10220
+ const service = resolveService2(config);
10221
+ return async (_req) => NextResponse.json({ success: true, data: service.listConfigs() });
10222
+ };
10223
+ var createCreateConfigHandler = (config) => {
10224
+ const service = resolveService2(config);
10225
+ return async (req) => {
10226
+ try {
10227
+ const body = await req.json();
10228
+ const data = service.createConfig(body);
10229
+ return NextResponse.json({ success: true, data });
10230
+ } catch (e) {
10231
+ return NextResponse.json({ success: false, error: e.message }, { status: 400 });
10232
+ }
10233
+ };
10234
+ };
10235
+ var createUpdateConfigHandler = (config) => {
10236
+ const service = resolveService2(config);
10237
+ return async (req) => {
10238
+ try {
10239
+ const body = await req.json();
10240
+ const data = service.updateConfig(body.id, body.patch || {});
10241
+ return NextResponse.json({ success: true, data });
10242
+ } catch (e) {
10243
+ return NextResponse.json({ success: false, error: e.message }, { status: 400 });
10244
+ }
10245
+ };
10246
+ };
10247
+ var createDeleteConfigHandler = (config) => {
10248
+ const service = resolveService2(config);
10249
+ return async (req) => {
10250
+ try {
10251
+ const body = await req.json();
10252
+ service.deleteConfig(body.id);
10253
+ return NextResponse.json({ success: true, data: true });
10254
+ } catch (e) {
10255
+ return NextResponse.json({ success: false, error: e.message }, { status: 400 });
10256
+ }
10257
+ };
10258
+ };
10259
+
10260
+ // src/huarongdao/ui/web/index.ts
10261
+ var web_exports3 = {};
10262
+ __export(web_exports3, {
10263
+ HuarongdaoBoard: () => HuarongdaoBoard_default,
10264
+ HuarongdaoConfigPage: () => HuarongdaoConfigPage_default,
10265
+ HuarongdaoGamePage: () => HuarongdaoGamePage_default
10266
+ });
10267
+ var HuarongdaoBoard = ({ tiles, rows, cols, imageUrl, onClickTile }) => {
10268
+ const total = rows * cols;
10269
+ return /* @__PURE__ */ React69__default.createElement(
10270
+ "div",
10271
+ {
10272
+ style: {
10273
+ display: "grid",
10274
+ gridTemplateColumns: `repeat(${cols}, 96px)`,
10275
+ gridTemplateRows: `repeat(${rows}, 96px)`,
10276
+ gap: 6
10277
+ }
10278
+ },
10279
+ tiles.map((tile, index) => {
10280
+ if (tile === 0) return /* @__PURE__ */ React69__default.createElement("div", { key: `blank-${index}`, style: { background: "#ddd" } });
10281
+ const pieceIndex = tile - 1;
10282
+ const pr = Math.floor(pieceIndex / cols);
10283
+ const pc = pieceIndex % cols;
10284
+ return /* @__PURE__ */ React69__default.createElement(
10285
+ "button",
10286
+ {
10287
+ key: `${tile}-${index}`,
10288
+ onClick: () => onClickTile(index),
10289
+ style: {
10290
+ border: "1px solid #666",
10291
+ cursor: "pointer",
10292
+ backgroundImage: `url(${imageUrl})`,
10293
+ backgroundSize: `${cols * 96}px ${rows * 96}px`,
10294
+ backgroundPosition: `${-pc * 96}px ${-pr * 96}px`
10295
+ }
10296
+ }
10297
+ );
10298
+ }),
10299
+ tiles.length !== total ? /* @__PURE__ */ React69__default.createElement("div", null, "tiles invalid") : null
10300
+ );
10301
+ };
10302
+ var HuarongdaoBoard_default = HuarongdaoBoard;
10303
+ var HuarongdaoGamePage = ({ config }) => {
10304
+ const initial = useMemo(() => {
10305
+ const tiles = config.startMode === "custom-layout" && config.initialTiles?.length === config.rows * config.cols ? config.initialTiles : shuffleSolvable(config.rows, config.cols, config.shuffleSteps);
10306
+ return {
10307
+ tiles,
10308
+ rows: config.rows,
10309
+ cols: config.cols,
10310
+ moveCount: 0,
10311
+ startedAt: Date.now(),
10312
+ isSolved: false
10313
+ };
10314
+ }, [config]);
10315
+ const [state, setState] = useState(initial);
10316
+ const reset = () => {
10317
+ setState({
10318
+ ...state,
10319
+ tiles: shuffleSolvable(config.rows, config.cols, config.shuffleSteps),
10320
+ moveCount: 0,
10321
+ startedAt: Date.now(),
10322
+ finishedAt: void 0,
10323
+ isSolved: false
10324
+ });
10325
+ };
10326
+ const solveNow = () => {
10327
+ setState((prev) => ({ ...prev, tiles: buildSolvedTiles(config.rows, config.cols), isSolved: true, finishedAt: Date.now() }));
10328
+ };
10329
+ const durationSec = Math.floor(((state.finishedAt || Date.now()) - state.startedAt) / 1e3);
10330
+ return /* @__PURE__ */ React69__default.createElement("section", null, /* @__PURE__ */ React69__default.createElement("h2", null, config.name), /* @__PURE__ */ React69__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__default.createElement(
10331
+ HuarongdaoBoard_default,
10332
+ {
10333
+ tiles: state.tiles,
10334
+ rows: state.rows,
10335
+ cols: state.cols,
10336
+ imageUrl: config.sourceImageUrl,
10337
+ onClickTile: (idx) => setState((prev) => moveTile(prev, idx))
10338
+ }
10339
+ ), /* @__PURE__ */ React69__default.createElement("div", { style: { marginTop: 12 } }, /* @__PURE__ */ React69__default.createElement("button", { onClick: reset }, "\u91CD\u65B0\u6253\u4E71"), /* @__PURE__ */ React69__default.createElement("button", { onClick: solveNow }, "\u4E00\u952E\u5B8C\u6210(\u6D4B\u8BD5)")), config.showReference ? /* @__PURE__ */ React69__default.createElement("div", { style: { marginTop: 12 } }, /* @__PURE__ */ React69__default.createElement("div", null, "\u53C2\u8003\u56FE\uFF1A"), /* @__PURE__ */ React69__default.createElement("img", { src: config.sourceImageUrl, alt: "reference", style: { width: 180, border: "1px solid #ccc" } })) : null);
10340
+ };
10341
+ var HuarongdaoGamePage_default = HuarongdaoGamePage;
10342
+ var HuarongdaoConfigPage = () => {
10343
+ const service = useMemo(() => createHuarongdaoService(), []);
10344
+ const [version, setVersion] = useState(0);
10345
+ const [name, setName] = useState("\u793A\u4F8B\u534E\u5BB9\u9053");
10346
+ const [slug, setSlug] = useState("sample-huarongdao");
10347
+ const [imageUrl, setImageUrl] = useState("https://i.imgur.com/6z7Qw6M.png");
10348
+ const [rows, setRows] = useState(3);
10349
+ const [cols, setCols] = useState(3);
10350
+ const list = useMemo(() => {
10351
+ return service.listConfigs();
10352
+ }, [service, version]);
10353
+ const create = () => {
10354
+ const input = {
10355
+ name,
10356
+ slug,
10357
+ sourceImageUrl: imageUrl,
10358
+ rows,
10359
+ cols,
10360
+ showReference: true,
10361
+ shuffleSteps: 80
10362
+ };
10363
+ service.createConfig(input);
10364
+ setVersion((v) => v + 1);
10365
+ };
10366
+ return /* @__PURE__ */ React69__default.createElement("section", null, /* @__PURE__ */ React69__default.createElement("h2", null, "\u534E\u5BB9\u9053\u540E\u53F0\u914D\u7F6E\u9875"), /* @__PURE__ */ React69__default.createElement("p", null, "\u652F\u6301\u591A\u5957\u914D\u7F6E\u521B\u5EFA\u3001\u53C2\u6570\u5316\u7BA1\u7406\uFF08V1 \u9AA8\u67B6\uFF09"), /* @__PURE__ */ React69__default.createElement("div", null, /* @__PURE__ */ React69__default.createElement("input", { value: name, onChange: (e) => setName(e.target.value), placeholder: "name" }), /* @__PURE__ */ React69__default.createElement("input", { value: slug, onChange: (e) => setSlug(e.target.value), placeholder: "slug" }), /* @__PURE__ */ React69__default.createElement("input", { value: imageUrl, onChange: (e) => setImageUrl(e.target.value), placeholder: "image url" }), /* @__PURE__ */ React69__default.createElement("input", { type: "number", value: rows, onChange: (e) => setRows(Number(e.target.value) || 3) }), /* @__PURE__ */ React69__default.createElement("input", { type: "number", value: cols, onChange: (e) => setCols(Number(e.target.value) || 3) }), /* @__PURE__ */ React69__default.createElement("button", { onClick: create }, "\u521B\u5EFA\u914D\u7F6E")), /* @__PURE__ */ React69__default.createElement("ul", null, list.map((item) => /* @__PURE__ */ React69__default.createElement("li", { key: item.id }, item.name, " (", item.slug, ") - ", item.rows, "x", item.cols, " - ", item.status))));
10367
+ };
10368
+ var HuarongdaoConfigPage_default = HuarongdaoConfigPage;
10369
+
10022
10370
  // src/storage/adapters/react-native-adapter.ts
10023
10371
  var AsyncStorage = null;
10024
10372
  try {
@@ -10372,6 +10720,6 @@ function useElectronStorage(key, defaultValue) {
10372
10720
  return useStorage(electronStorage, key, defaultValue);
10373
10721
  }
10374
10722
 
10375
- export { About_default as About, Dialog as AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, DialogDescription as AlertDialogDescription, DialogFooter as AlertDialogFooter, DialogHeader as AlertDialogHeader, DialogOverlay as AlertDialogOverlay, DialogPortal as AlertDialogPortal, DialogTitle as AlertDialogTitle, DialogTrigger as AlertDialogTrigger, AutoOpenModal, Avatar, AvatarFallback, AvatarImage, BackButton, BackgroundRemover, Badge, BoothConfigPage, BoothRedeemPanel, BoothSuccessCard, BoothUploadPanel, BoothVaultService, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CategoryFilter, CollisionBalls, CompletionFilterComponent, ConfirmModal, ConsoleLoggerAdapter, Contact_default as Contact, DANMAKU_MAX_LENGTH, DANMAKU_TRACK_COUNT, DEFAULT_FESTIVAL_CARD_CONFIG, DEFAULT_MAX_ACTIVE_FIREWORKS, DEFAULT_MAX_PARTICLES, DEFAULT_OPENAI_BASE_URL, DEFAULT_OPENAI_MODEL, DanmakuPanel, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DraggableExperimentGrid, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, EnhancedAvatar, ExperimentCard, ExperimentGrid, ExperimentItemGrid, FIREWORK_KIND_LABELS, FestivalCardBook3D, FestivalCardConfigEditor, FestivalCardConfigPage, FestivalCardManagedPage, FestivalCardPageRenderer, FestivalCardService, FestivalCardStudio, FilterButtonGroup, FireworksCanvas, FireworksControlPanel, FloatingMenu_default as FloatingMenu, FloatingMenuExample_default as FloatingMenuExample, GenericOrderManager, Grid, Home_default as Home, ImageMappingPanel, InMemorySkillRegistry, Input, Label, LocalImageMappingPanel, LogLevel, Logger, MIKU_PALETTE, MikuContestPersistentService, MikuContestService, MikuContestStateDbService, MikuFireworks3D, Modal, NORMAL_PALETTE, Navigation_default as Navigation, NavigationItem_default as NavigationItem, NavigationToggle_default as NavigationToggle, OCRScanner, PageHeader, PermissionGuard, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, ProfileButton, ProfileModal, Progress, ProjectCarousel, ScreenReceiverPanel, ScrollArea, ScrollBar, SearchBox, SearchResultHint, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SentimentAnalyzer, Separator, Dialog as Sheet, DialogClose as SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, DialogOverlay as SheetOverlay, DialogPortal as SheetPortal, SheetTitle, DialogTrigger as SheetTrigger, SmartAssistant, SortControl, SortModeToggle, SortableExperimentItem, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Timeline, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UserInfoBar, WebSocketTransport, applyPromptTemplate, arrayUtils, badgeVariants, buttonVariants, checkVoteEligibility, cn, createAiClient, createChatSession, createCreateSubmissionHandler, createDefaultMikuContestConfig, createExportSubmissionsHandler, createGetContestSnapshotHandler, createInMemoryFestivalCardDb, createListSubmissionsHandler, createLogger, createMikuContestApiClient, createMikuContestDrizzlePersistenceAdapter, createMikuContestPersistentService, createMikuContestService, createOpenAICompatibleProvider, createResetVotesHandler, createReviewSubmissionHandler, createSetVoterRestrictionHandler, createSkillRegistry, createUpdateContestConfigHandler, createVoteHandler, debugUtils, defaultMikuVotingRules, defaultVocaloidBoothConfig, errorUtils, fileUtils, filterExperiments, formatTime, generateMatchCode, getAllTags, getCategoryColor, getCategoryDisplayName, getCompletionFilterDisplayName, getCompletionStatusColor, getCompletionStatusText, getExperimentCounts, japaneseUtils, logger, mikuContestConfigs, mikuContestDbService, mikuContestNotices, mikuContestSubmissions, mikuContestVoterRestrictions, mikuContestVotes, miniapp_exports as miniappService, miniapp_exports2 as miniappUI, normalizeFestivalCardConfig, normalizeMatchCode, normalizePromptVariables, normalizeVocaloidBoothConfig, resizeFestivalCardPages, resolveScreenReceiverSignalUrl, skillToToolDefinition, sortByVotesDesc, sortExperiments, stringUtils, toVoteDayKey, useAiChat, useAsyncStorage, useBackgroundRemoval, useDanmakuController, useElectronStorage, useFestivalCardConfig, useFireworksEngine, useFireworksRealtime, useLocalStorage, useMikuContest, useOCR, useScreenReceiver, useSentimentAnalysis, useStorage, useTaroStorage, useTextGeneration, validateExperiment, validateMikuSubmissionInput, validators, web_exports as webService, web_exports2 as webUI };
10723
+ export { About_default as About, Dialog as AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, DialogDescription as AlertDialogDescription, DialogFooter as AlertDialogFooter, DialogHeader as AlertDialogHeader, DialogOverlay as AlertDialogOverlay, DialogPortal as AlertDialogPortal, DialogTitle as AlertDialogTitle, DialogTrigger as AlertDialogTrigger, AutoOpenModal, Avatar, AvatarFallback, AvatarImage, BackButton, BackgroundRemover, Badge, BoothConfigPage, BoothRedeemPanel, BoothSuccessCard, BoothUploadPanel, BoothVaultService, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CategoryFilter, CollisionBalls, CompletionFilterComponent, ConfirmModal, ConsoleLoggerAdapter, Contact_default as Contact, DANMAKU_MAX_LENGTH, DANMAKU_TRACK_COUNT, DEFAULT_FESTIVAL_CARD_CONFIG, DEFAULT_MAX_ACTIVE_FIREWORKS, DEFAULT_MAX_PARTICLES, DEFAULT_OPENAI_BASE_URL, DEFAULT_OPENAI_MODEL, DanmakuPanel, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DraggableExperimentGrid, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, EnhancedAvatar, ExperimentCard, ExperimentGrid, ExperimentItemGrid, FIREWORK_KIND_LABELS, FestivalCardBook3D, FestivalCardConfigEditor, FestivalCardConfigPage, FestivalCardManagedPage, FestivalCardPageRenderer, FestivalCardService, FestivalCardStudio, FilterButtonGroup, FireworksCanvas, FireworksControlPanel, FloatingMenu_default as FloatingMenu, FloatingMenuExample_default as FloatingMenuExample, GenericOrderManager, Grid, Home_default as Home, ImageMappingPanel, InMemorySkillRegistry, Input, Label, LocalImageMappingPanel, LogLevel, Logger, MIKU_PALETTE, MikuContestPersistentService, MikuContestService, MikuContestStateDbService, MikuFireworks3D, Modal, NORMAL_PALETTE, Navigation_default as Navigation, NavigationItem_default as NavigationItem, NavigationToggle_default as NavigationToggle, OCRScanner, PageHeader, PermissionGuard, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, ProfileButton, ProfileModal, Progress, ProjectCarousel, ScreenReceiverPanel, ScrollArea, ScrollBar, SearchBox, SearchResultHint, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SentimentAnalyzer, Separator, Dialog as Sheet, DialogClose as SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, DialogOverlay as SheetOverlay, DialogPortal as SheetPortal, SheetTitle, DialogTrigger as SheetTrigger, SmartAssistant, SortControl, SortModeToggle, SortableExperimentItem, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Timeline, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UserInfoBar, WebSocketTransport, applyPromptTemplate, arrayUtils, badgeVariants, buttonVariants, checkVoteEligibility, cn, createAiClient, createChatSession, createCreateSubmissionHandler, createDefaultMikuContestConfig, createExportSubmissionsHandler, createGetContestSnapshotHandler, createInMemoryFestivalCardDb, createListSubmissionsHandler, createLogger, createMikuContestApiClient, createMikuContestDrizzlePersistenceAdapter, createMikuContestPersistentService, createMikuContestService, createOpenAICompatibleProvider, createResetVotesHandler, createReviewSubmissionHandler, createSetVoterRestrictionHandler, createSkillRegistry, createUpdateContestConfigHandler, createVoteHandler, debugUtils, defaultMikuVotingRules, defaultVocaloidBoothConfig, errorUtils, fileUtils, filterExperiments, formatTime, generateMatchCode, getAllTags, getCategoryColor, getCategoryDisplayName, getCompletionFilterDisplayName, getCompletionStatusColor, getCompletionStatusText, getExperimentCounts, huarongdao_exports as huarongdao, japaneseUtils, logger, mikuContestConfigs, mikuContestDbService, mikuContestNotices, mikuContestSubmissions, mikuContestVoterRestrictions, mikuContestVotes, miniapp_exports as miniappService, miniapp_exports2 as miniappUI, normalizeFestivalCardConfig, normalizeMatchCode, normalizePromptVariables, normalizeVocaloidBoothConfig, resizeFestivalCardPages, resolveScreenReceiverSignalUrl, skillToToolDefinition, sortByVotesDesc, sortExperiments, stringUtils, toVoteDayKey, useAiChat, useAsyncStorage, useBackgroundRemoval, useDanmakuController, useElectronStorage, useFestivalCardConfig, useFireworksEngine, useFireworksRealtime, useLocalStorage, useMikuContest, useOCR, useScreenReceiver, useSentimentAnalysis, useStorage, useTaroStorage, useTextGeneration, validateExperiment, validateMikuSubmissionInput, validators, web_exports as webService, web_exports2 as webUI };
10376
10724
  //# sourceMappingURL=index.mjs.map
10377
10725
  //# sourceMappingURL=index.mjs.map