sa2kit 1.6.91 → 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.
- package/dist/client-BlkUL2To.d.ts +26 -0
- package/dist/client-DpMIhrlS.d.mts +26 -0
- package/dist/huarongdao/index.d.mts +8 -0
- package/dist/huarongdao/index.d.ts +8 -0
- package/dist/huarongdao/index.js +360 -0
- package/dist/huarongdao/index.js.map +1 -0
- package/dist/huarongdao/index.mjs +338 -0
- package/dist/huarongdao/index.mjs.map +1 -0
- package/dist/huarongdao/logic/index.d.mts +11 -0
- package/dist/huarongdao/logic/index.d.ts +11 -0
- package/dist/huarongdao/logic/index.js +89 -0
- package/dist/huarongdao/logic/index.js.map +1 -0
- package/dist/huarongdao/logic/index.mjs +81 -0
- package/dist/huarongdao/logic/index.mjs.map +1 -0
- package/dist/huarongdao/routes/index.d.mts +38 -0
- package/dist/huarongdao/routes/index.d.ts +38 -0
- package/dist/huarongdao/routes/index.js +114 -0
- package/dist/huarongdao/routes/index.js.map +1 -0
- package/dist/huarongdao/routes/index.mjs +108 -0
- package/dist/huarongdao/routes/index.mjs.map +1 -0
- package/dist/huarongdao/server/index.d.mts +14 -0
- package/dist/huarongdao/server/index.d.ts +14 -0
- package/dist/huarongdao/server/index.js +60 -0
- package/dist/huarongdao/server/index.js.map +1 -0
- package/dist/huarongdao/server/index.mjs +57 -0
- package/dist/huarongdao/server/index.mjs.map +1 -0
- package/dist/huarongdao/service/index.d.mts +31 -0
- package/dist/huarongdao/service/index.d.ts +31 -0
- package/dist/huarongdao/service/index.js +45 -0
- package/dist/huarongdao/service/index.js.map +1 -0
- package/dist/huarongdao/service/index.mjs +42 -0
- package/dist/huarongdao/service/index.mjs.map +1 -0
- package/dist/huarongdao/types/index.d.mts +46 -0
- package/dist/huarongdao/types/index.d.ts +46 -0
- package/dist/huarongdao/types/index.js +4 -0
- package/dist/huarongdao/types/index.js.map +1 -0
- package/dist/huarongdao/types/index.mjs +3 -0
- package/dist/huarongdao/types/index.mjs.map +1 -0
- package/dist/huarongdao/ui/web/index.d.mts +3 -0
- package/dist/huarongdao/ui/web/index.d.ts +3 -0
- package/dist/huarongdao/ui/web/index.js +237 -0
- package/dist/huarongdao/ui/web/index.js.map +1 -0
- package/dist/huarongdao/ui/web/index.mjs +229 -0
- package/dist/huarongdao/ui/web/index.mjs.map +1 -0
- package/dist/index-B48rcsqv.d.ts +27 -0
- package/dist/index-BNqJdwX4.d.ts +37 -0
- package/dist/index-C7yh6b5Q.d.mts +17 -0
- package/dist/index-CDapUIT5.d.mts +51 -0
- package/dist/index-Cv9jlnNz.d.ts +17 -0
- package/dist/index-D3UbkUai.d.ts +51 -0
- package/dist/index-DOtQI_mz.d.mts +37 -0
- package/dist/index-Da2X78GE.d.mts +27 -0
- package/dist/index.d.mts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +1707 -79
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1675 -82
- package/dist/index.mjs.map +1 -1
- package/dist/mikuContest/index.d.mts +13 -0
- package/dist/mikuContest/index.d.ts +13 -0
- package/dist/mikuContest/index.js +1310 -0
- package/dist/mikuContest/index.js.map +1 -0
- package/dist/mikuContest/index.mjs +1253 -0
- package/dist/mikuContest/index.mjs.map +1 -0
- package/dist/mikuContest/logic/index.d.mts +32 -0
- package/dist/mikuContest/logic/index.d.ts +32 -0
- package/dist/mikuContest/logic/index.js +511 -0
- package/dist/mikuContest/logic/index.js.map +1 -0
- package/dist/mikuContest/logic/index.mjs +483 -0
- package/dist/mikuContest/logic/index.mjs.map +1 -0
- package/dist/mikuContest/routes/index.d.mts +80 -0
- package/dist/mikuContest/routes/index.d.ts +80 -0
- package/dist/mikuContest/routes/index.js +821 -0
- package/dist/mikuContest/routes/index.js.map +1 -0
- package/dist/mikuContest/routes/index.mjs +791 -0
- package/dist/mikuContest/routes/index.mjs.map +1 -0
- package/dist/mikuContest/server/index.d.mts +766 -0
- package/dist/mikuContest/server/index.d.ts +766 -0
- package/dist/mikuContest/server/index.js +705 -0
- package/dist/mikuContest/server/index.js.map +1 -0
- package/dist/mikuContest/server/index.mjs +672 -0
- package/dist/mikuContest/server/index.mjs.map +1 -0
- package/dist/mikuContest/service/index.d.mts +30 -0
- package/dist/mikuContest/service/index.d.ts +30 -0
- package/dist/mikuContest/service/index.js +139 -0
- package/dist/mikuContest/service/index.js.map +1 -0
- package/dist/mikuContest/service/index.mjs +135 -0
- package/dist/mikuContest/service/index.mjs.map +1 -0
- package/dist/mikuContest/types/index.d.mts +179 -0
- package/dist/mikuContest/types/index.d.ts +179 -0
- package/dist/mikuContest/types/index.js +4 -0
- package/dist/mikuContest/types/index.js.map +1 -0
- package/dist/mikuContest/types/index.mjs +3 -0
- package/dist/mikuContest/types/index.mjs.map +1 -0
- package/dist/mikuContest/ui/miniapp/index.d.mts +3 -0
- package/dist/mikuContest/ui/miniapp/index.d.ts +3 -0
- package/dist/mikuContest/ui/miniapp/index.js +566 -0
- package/dist/mikuContest/ui/miniapp/index.js.map +1 -0
- package/dist/mikuContest/ui/miniapp/index.mjs +540 -0
- package/dist/mikuContest/ui/miniapp/index.mjs.map +1 -0
- package/dist/mikuContest/ui/web/index.d.mts +4 -0
- package/dist/mikuContest/ui/web/index.d.ts +4 -0
- package/dist/mikuContest/ui/web/index.js +353 -0
- package/dist/mikuContest/ui/web/index.js.map +1 -0
- package/dist/mikuContest/ui/web/index.mjs +343 -0
- package/dist/mikuContest/ui/web/index.mjs.map +1 -0
- package/dist/qqbot/server/index.d.mts +126 -1
- package/dist/qqbot/server/index.d.ts +126 -1
- package/dist/qqbot/server/index.js +250 -0
- package/dist/qqbot/server/index.js.map +1 -1
- package/dist/qqbot/server/index.mjs +246 -1
- package/dist/qqbot/server/index.mjs.map +1 -1
- package/dist/service-D7DM1wW-.d.ts +38 -0
- package/dist/service-DPr2rlvH.d.mts +38 -0
- package/dist/types-BS7Xz09b.d.mts +14 -0
- package/dist/types-k4koMp4m.d.ts +14 -0
- package/package.json +76 -1
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { MikuContestStateSnapshot, MikuContestConfig, CreateMikuSubmissionInput, MikuSubmission, MikuSubmissionFilter, ReviewMikuSubmissionInput, VoteMikuSubmissionInput, SetMikuVoterRestrictionInput, MikuVoterRestriction, ResetMikuVotesInput } from './mikuContest/types/index.js';
|
|
2
|
+
|
|
3
|
+
interface MikuContestApiClient {
|
|
4
|
+
getSnapshot(): Promise<MikuContestStateSnapshot>;
|
|
5
|
+
updateContestConfig(patch: Partial<MikuContestConfig>): Promise<MikuContestConfig>;
|
|
6
|
+
createSubmission(input: CreateMikuSubmissionInput, mode?: 'web' | 'miniapp'): Promise<MikuSubmission>;
|
|
7
|
+
listSubmissions(filter?: MikuSubmissionFilter): Promise<MikuSubmission[]>;
|
|
8
|
+
reviewSubmission(input: ReviewMikuSubmissionInput): Promise<MikuSubmission>;
|
|
9
|
+
vote(input: VoteMikuSubmissionInput): Promise<MikuSubmission>;
|
|
10
|
+
setVoterRestriction(input: SetMikuVoterRestrictionInput): Promise<MikuVoterRestriction>;
|
|
11
|
+
resetVotes(input: ResetMikuVotesInput): Promise<{
|
|
12
|
+
removedVotes: number;
|
|
13
|
+
affectedSubmissions: string[];
|
|
14
|
+
}>;
|
|
15
|
+
exportSubmissions(filter?: MikuSubmissionFilter): Promise<ArrayBuffer>;
|
|
16
|
+
}
|
|
17
|
+
type HttpMethod = 'GET' | 'POST' | 'PATCH';
|
|
18
|
+
interface Requester {
|
|
19
|
+
<T>(url: string, options?: {
|
|
20
|
+
method?: HttpMethod;
|
|
21
|
+
body?: unknown;
|
|
22
|
+
}): Promise<T>;
|
|
23
|
+
}
|
|
24
|
+
declare const createMikuContestApiClient: (basePath: string, requester: Requester) => MikuContestApiClient;
|
|
25
|
+
|
|
26
|
+
export { type HttpMethod as H, type MikuContestApiClient as M, type Requester as R, createMikuContestApiClient as c };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { MikuContestStateSnapshot, MikuContestConfig, CreateMikuSubmissionInput, MikuSubmission, MikuSubmissionFilter, ReviewMikuSubmissionInput, VoteMikuSubmissionInput, SetMikuVoterRestrictionInput, MikuVoterRestriction, ResetMikuVotesInput } from './mikuContest/types/index.mjs';
|
|
2
|
+
|
|
3
|
+
interface MikuContestApiClient {
|
|
4
|
+
getSnapshot(): Promise<MikuContestStateSnapshot>;
|
|
5
|
+
updateContestConfig(patch: Partial<MikuContestConfig>): Promise<MikuContestConfig>;
|
|
6
|
+
createSubmission(input: CreateMikuSubmissionInput, mode?: 'web' | 'miniapp'): Promise<MikuSubmission>;
|
|
7
|
+
listSubmissions(filter?: MikuSubmissionFilter): Promise<MikuSubmission[]>;
|
|
8
|
+
reviewSubmission(input: ReviewMikuSubmissionInput): Promise<MikuSubmission>;
|
|
9
|
+
vote(input: VoteMikuSubmissionInput): Promise<MikuSubmission>;
|
|
10
|
+
setVoterRestriction(input: SetMikuVoterRestrictionInput): Promise<MikuVoterRestriction>;
|
|
11
|
+
resetVotes(input: ResetMikuVotesInput): Promise<{
|
|
12
|
+
removedVotes: number;
|
|
13
|
+
affectedSubmissions: string[];
|
|
14
|
+
}>;
|
|
15
|
+
exportSubmissions(filter?: MikuSubmissionFilter): Promise<ArrayBuffer>;
|
|
16
|
+
}
|
|
17
|
+
type HttpMethod = 'GET' | 'POST' | 'PATCH';
|
|
18
|
+
interface Requester {
|
|
19
|
+
<T>(url: string, options?: {
|
|
20
|
+
method?: HttpMethod;
|
|
21
|
+
body?: unknown;
|
|
22
|
+
}): Promise<T>;
|
|
23
|
+
}
|
|
24
|
+
declare const createMikuContestApiClient: (basePath: string, requester: Requester) => MikuContestApiClient;
|
|
25
|
+
|
|
26
|
+
export { type HttpMethod as H, type MikuContestApiClient as M, type Requester as R, createMikuContestApiClient as c };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { CreateHuarongdaoConfigInput, HuarongdaoConfig, HuarongdaoGameState, HuarongdaoStateSnapshot, PuzzleStatus } from './types/index.mjs';
|
|
2
|
+
export { buildSolvedTiles, canMove, inversionCount, isSolvable, isSolved, moveTile, shuffleSolvable } from './logic/index.mjs';
|
|
3
|
+
export { HttpMethod, HuarongdaoWebClientOptions, Requester, createHuarongdaoApiClient, createHuarongdaoWebClient } from './service/index.mjs';
|
|
4
|
+
export { HuarongdaoService, createHuarongdaoService } from './server/index.mjs';
|
|
5
|
+
export { HuarongdaoRouteConfig, createCreateConfigHandler, createDeleteConfigHandler, createGetSnapshotHandler, createListConfigsHandler, createUpdateConfigHandler } from './routes/index.mjs';
|
|
6
|
+
export { i as webUI } from '../index-Da2X78GE.mjs';
|
|
7
|
+
import 'next/server';
|
|
8
|
+
import 'react';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { CreateHuarongdaoConfigInput, HuarongdaoConfig, HuarongdaoGameState, HuarongdaoStateSnapshot, PuzzleStatus } from './types/index.js';
|
|
2
|
+
export { buildSolvedTiles, canMove, inversionCount, isSolvable, isSolved, moveTile, shuffleSolvable } from './logic/index.js';
|
|
3
|
+
export { HttpMethod, HuarongdaoWebClientOptions, Requester, createHuarongdaoApiClient, createHuarongdaoWebClient } from './service/index.js';
|
|
4
|
+
export { HuarongdaoService, createHuarongdaoService } from './server/index.js';
|
|
5
|
+
export { HuarongdaoRouteConfig, createCreateConfigHandler, createDeleteConfigHandler, createGetSnapshotHandler, createListConfigsHandler, createUpdateConfigHandler } from './routes/index.js';
|
|
6
|
+
export { i as webUI } from '../index-B48rcsqv.js';
|
|
7
|
+
import 'next/server';
|
|
8
|
+
import 'react';
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var server = require('next/server');
|
|
4
|
+
var React3 = require('react');
|
|
5
|
+
|
|
6
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
|
+
|
|
8
|
+
var React3__default = /*#__PURE__*/_interopDefault(React3);
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __export = (target, all) => {
|
|
12
|
+
for (var name in all)
|
|
13
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// src/huarongdao/logic/game.ts
|
|
17
|
+
var clone = (v) => [...v];
|
|
18
|
+
var buildSolvedTiles = (rows, cols) => {
|
|
19
|
+
const total = rows * cols;
|
|
20
|
+
return Array.from({ length: total }, (_, i) => (i + 1) % total);
|
|
21
|
+
};
|
|
22
|
+
var isSolved = (tiles) => {
|
|
23
|
+
return tiles.every((v, i, arr) => v === (i + 1) % arr.length);
|
|
24
|
+
};
|
|
25
|
+
var canMove = (tiles, rows, cols, tileIndex) => {
|
|
26
|
+
const blank = tiles.indexOf(0);
|
|
27
|
+
if (blank < 0 || tileIndex < 0 || tileIndex >= tiles.length) return false;
|
|
28
|
+
const br = Math.floor(blank / cols);
|
|
29
|
+
const bc = blank % cols;
|
|
30
|
+
const tr = Math.floor(tileIndex / cols);
|
|
31
|
+
const tc = tileIndex % cols;
|
|
32
|
+
return Math.abs(br - tr) + Math.abs(bc - tc) === 1;
|
|
33
|
+
};
|
|
34
|
+
var moveTile = (state, tileIndex) => {
|
|
35
|
+
if (!canMove(state.tiles, state.rows, state.cols, tileIndex)) return state;
|
|
36
|
+
const nextTiles = clone(state.tiles);
|
|
37
|
+
const blank = nextTiles.indexOf(0);
|
|
38
|
+
const blankValue = nextTiles[blank];
|
|
39
|
+
const tileValue = nextTiles[tileIndex];
|
|
40
|
+
if (blankValue === void 0 || tileValue === void 0) return state;
|
|
41
|
+
nextTiles[blank] = tileValue;
|
|
42
|
+
nextTiles[tileIndex] = blankValue;
|
|
43
|
+
const solved = isSolved(nextTiles);
|
|
44
|
+
return {
|
|
45
|
+
...state,
|
|
46
|
+
tiles: nextTiles,
|
|
47
|
+
moveCount: state.moveCount + 1,
|
|
48
|
+
isSolved: solved,
|
|
49
|
+
finishedAt: solved ? Date.now() : void 0
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
var inversionCount = (tiles) => {
|
|
53
|
+
const arr = tiles.filter((n) => n !== 0);
|
|
54
|
+
let cnt = 0;
|
|
55
|
+
for (let i = 0; i < arr.length; i += 1) {
|
|
56
|
+
for (let j = i + 1; j < arr.length; j += 1) {
|
|
57
|
+
if ((arr[i] ?? 0) > (arr[j] ?? 0)) cnt += 1;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return cnt;
|
|
61
|
+
};
|
|
62
|
+
var isSolvable = (tiles, rows, cols) => {
|
|
63
|
+
const inv = inversionCount(tiles);
|
|
64
|
+
if (cols % 2 === 1) return inv % 2 === 0;
|
|
65
|
+
const blankRowFromBottom = rows - Math.floor(tiles.indexOf(0) / cols);
|
|
66
|
+
return blankRowFromBottom % 2 === 0 !== (inv % 2 === 0);
|
|
67
|
+
};
|
|
68
|
+
var shuffleSolvable = (rows, cols, steps = 80) => {
|
|
69
|
+
let tiles = buildSolvedTiles(rows, cols);
|
|
70
|
+
for (let i = 0; i < steps; i += 1) {
|
|
71
|
+
const blank = tiles.indexOf(0);
|
|
72
|
+
const br = Math.floor(blank / cols);
|
|
73
|
+
const bc = blank % cols;
|
|
74
|
+
const candidate = [];
|
|
75
|
+
const dirs = [
|
|
76
|
+
[1, 0],
|
|
77
|
+
[-1, 0],
|
|
78
|
+
[0, 1],
|
|
79
|
+
[0, -1]
|
|
80
|
+
];
|
|
81
|
+
dirs.forEach(([dr, dc]) => {
|
|
82
|
+
const nr = br + dr;
|
|
83
|
+
const nc = bc + dc;
|
|
84
|
+
if (nr >= 0 && nr < rows && nc >= 0 && nc < cols) candidate.push(nr * cols + nc);
|
|
85
|
+
});
|
|
86
|
+
const idx = candidate[Math.floor(Math.random() * candidate.length)] ?? blank;
|
|
87
|
+
const next = clone(tiles);
|
|
88
|
+
[next[blank], next[idx]] = [next[idx] ?? 0, next[blank] ?? 0];
|
|
89
|
+
tiles = next;
|
|
90
|
+
}
|
|
91
|
+
return tiles;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// src/huarongdao/service/api/client.ts
|
|
95
|
+
var unwrap = (result) => {
|
|
96
|
+
if (!result.success || result.data === void 0) throw new Error(result.error || "\u8BF7\u6C42\u5931\u8D25");
|
|
97
|
+
return result.data;
|
|
98
|
+
};
|
|
99
|
+
var createHuarongdaoApiClient = (basePath, requester2) => ({
|
|
100
|
+
async getSnapshot() {
|
|
101
|
+
return unwrap(await requester2(`${basePath}/snapshot`, { method: "GET" }));
|
|
102
|
+
},
|
|
103
|
+
async listConfigs() {
|
|
104
|
+
return unwrap(await requester2(`${basePath}/configs`, { method: "GET" }));
|
|
105
|
+
},
|
|
106
|
+
async createConfig(input) {
|
|
107
|
+
return unwrap(await requester2(`${basePath}/configs`, { method: "POST", body: input }));
|
|
108
|
+
},
|
|
109
|
+
async updateConfig(id2, patch) {
|
|
110
|
+
return unwrap(await requester2(`${basePath}/configs`, { method: "PATCH", body: { id: id2, patch } }));
|
|
111
|
+
},
|
|
112
|
+
async deleteConfig(id2) {
|
|
113
|
+
return unwrap(await requester2(`${basePath}/configs`, { method: "DELETE", body: { id: id2 } }));
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// src/huarongdao/service/web/client.ts
|
|
118
|
+
var requester = (options) => {
|
|
119
|
+
const baseUrl = options.baseUrl || "";
|
|
120
|
+
return async (url, req) => {
|
|
121
|
+
const res = await fetch(`${baseUrl}${url}`, {
|
|
122
|
+
method: req?.method || "GET",
|
|
123
|
+
headers: { "Content-Type": "application/json", ...options.headers || {} },
|
|
124
|
+
body: req?.body ? JSON.stringify(req.body) : void 0
|
|
125
|
+
});
|
|
126
|
+
return await res.json();
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
var createHuarongdaoWebClient = (options = {}) => {
|
|
130
|
+
return createHuarongdaoApiClient(options.basePath || "/api/huarongdao", requester(options));
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// src/huarongdao/server/service.ts
|
|
134
|
+
var id = () => `puzzle_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
135
|
+
var HuarongdaoService = class {
|
|
136
|
+
constructor() {
|
|
137
|
+
this.configs = /* @__PURE__ */ new Map();
|
|
138
|
+
}
|
|
139
|
+
listConfigs() {
|
|
140
|
+
return [...this.configs.values()];
|
|
141
|
+
}
|
|
142
|
+
getBySlug(slug) {
|
|
143
|
+
return [...this.configs.values()].find((c) => c.slug === slug) || null;
|
|
144
|
+
}
|
|
145
|
+
createConfig(input) {
|
|
146
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
147
|
+
const next = {
|
|
148
|
+
id: id(),
|
|
149
|
+
slug: input.slug,
|
|
150
|
+
name: input.name,
|
|
151
|
+
description: input.description,
|
|
152
|
+
status: "draft",
|
|
153
|
+
rows: input.rows,
|
|
154
|
+
cols: input.cols,
|
|
155
|
+
sourceImageUrl: input.sourceImageUrl,
|
|
156
|
+
showReference: input.showReference ?? true,
|
|
157
|
+
shuffleSteps: input.shuffleSteps ?? 80,
|
|
158
|
+
timeLimitSec: input.timeLimitSec,
|
|
159
|
+
startMode: input.startMode ?? "random-solvable",
|
|
160
|
+
initialTiles: input.initialTiles,
|
|
161
|
+
createdAt: now,
|
|
162
|
+
updatedAt: now
|
|
163
|
+
};
|
|
164
|
+
this.configs.set(next.id, next);
|
|
165
|
+
return next;
|
|
166
|
+
}
|
|
167
|
+
updateConfig(id2, patch) {
|
|
168
|
+
const cur = this.configs.get(id2);
|
|
169
|
+
if (!cur) throw new Error("\u914D\u7F6E\u4E0D\u5B58\u5728");
|
|
170
|
+
const next = { ...cur, ...patch, id: cur.id, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
171
|
+
this.configs.set(id2, next);
|
|
172
|
+
return next;
|
|
173
|
+
}
|
|
174
|
+
deleteConfig(id2) {
|
|
175
|
+
this.configs.delete(id2);
|
|
176
|
+
}
|
|
177
|
+
getSnapshot() {
|
|
178
|
+
const configs = this.listConfigs();
|
|
179
|
+
return {
|
|
180
|
+
configs,
|
|
181
|
+
activeConfig: configs.find((c) => c.status === "active")
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
var createHuarongdaoService = () => new HuarongdaoService();
|
|
186
|
+
var resolveService = (config) => config?.service || createHuarongdaoService();
|
|
187
|
+
var createGetSnapshotHandler = (config) => {
|
|
188
|
+
const service = resolveService(config);
|
|
189
|
+
return async (_req) => server.NextResponse.json({ success: true, data: service.getSnapshot() });
|
|
190
|
+
};
|
|
191
|
+
var createListConfigsHandler = (config) => {
|
|
192
|
+
const service = resolveService(config);
|
|
193
|
+
return async (_req) => server.NextResponse.json({ success: true, data: service.listConfigs() });
|
|
194
|
+
};
|
|
195
|
+
var createCreateConfigHandler = (config) => {
|
|
196
|
+
const service = resolveService(config);
|
|
197
|
+
return async (req) => {
|
|
198
|
+
try {
|
|
199
|
+
const body = await req.json();
|
|
200
|
+
const data = service.createConfig(body);
|
|
201
|
+
return server.NextResponse.json({ success: true, data });
|
|
202
|
+
} catch (e) {
|
|
203
|
+
return server.NextResponse.json({ success: false, error: e.message }, { status: 400 });
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
var createUpdateConfigHandler = (config) => {
|
|
208
|
+
const service = resolveService(config);
|
|
209
|
+
return async (req) => {
|
|
210
|
+
try {
|
|
211
|
+
const body = await req.json();
|
|
212
|
+
const data = service.updateConfig(body.id, body.patch || {});
|
|
213
|
+
return server.NextResponse.json({ success: true, data });
|
|
214
|
+
} catch (e) {
|
|
215
|
+
return server.NextResponse.json({ success: false, error: e.message }, { status: 400 });
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
};
|
|
219
|
+
var createDeleteConfigHandler = (config) => {
|
|
220
|
+
const service = resolveService(config);
|
|
221
|
+
return async (req) => {
|
|
222
|
+
try {
|
|
223
|
+
const body = await req.json();
|
|
224
|
+
service.deleteConfig(body.id);
|
|
225
|
+
return server.NextResponse.json({ success: true, data: true });
|
|
226
|
+
} catch (e) {
|
|
227
|
+
return server.NextResponse.json({ success: false, error: e.message }, { status: 400 });
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
// src/huarongdao/ui/web/index.ts
|
|
233
|
+
var web_exports = {};
|
|
234
|
+
__export(web_exports, {
|
|
235
|
+
HuarongdaoBoard: () => HuarongdaoBoard_default,
|
|
236
|
+
HuarongdaoConfigPage: () => HuarongdaoConfigPage_default,
|
|
237
|
+
HuarongdaoGamePage: () => HuarongdaoGamePage_default
|
|
238
|
+
});
|
|
239
|
+
var HuarongdaoBoard = ({ tiles, rows, cols, imageUrl, onClickTile }) => {
|
|
240
|
+
const total = rows * cols;
|
|
241
|
+
return /* @__PURE__ */ React3__default.default.createElement(
|
|
242
|
+
"div",
|
|
243
|
+
{
|
|
244
|
+
style: {
|
|
245
|
+
display: "grid",
|
|
246
|
+
gridTemplateColumns: `repeat(${cols}, 96px)`,
|
|
247
|
+
gridTemplateRows: `repeat(${rows}, 96px)`,
|
|
248
|
+
gap: 6
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
tiles.map((tile, index) => {
|
|
252
|
+
if (tile === 0) return /* @__PURE__ */ React3__default.default.createElement("div", { key: `blank-${index}`, style: { background: "#ddd" } });
|
|
253
|
+
const pieceIndex = tile - 1;
|
|
254
|
+
const pr = Math.floor(pieceIndex / cols);
|
|
255
|
+
const pc = pieceIndex % cols;
|
|
256
|
+
return /* @__PURE__ */ React3__default.default.createElement(
|
|
257
|
+
"button",
|
|
258
|
+
{
|
|
259
|
+
key: `${tile}-${index}`,
|
|
260
|
+
onClick: () => onClickTile(index),
|
|
261
|
+
style: {
|
|
262
|
+
border: "1px solid #666",
|
|
263
|
+
cursor: "pointer",
|
|
264
|
+
backgroundImage: `url(${imageUrl})`,
|
|
265
|
+
backgroundSize: `${cols * 96}px ${rows * 96}px`,
|
|
266
|
+
backgroundPosition: `${-pc * 96}px ${-pr * 96}px`
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
);
|
|
270
|
+
}),
|
|
271
|
+
tiles.length !== total ? /* @__PURE__ */ React3__default.default.createElement("div", null, "tiles invalid") : null
|
|
272
|
+
);
|
|
273
|
+
};
|
|
274
|
+
var HuarongdaoBoard_default = HuarongdaoBoard;
|
|
275
|
+
var HuarongdaoGamePage = ({ config }) => {
|
|
276
|
+
const initial = React3.useMemo(() => {
|
|
277
|
+
const tiles = config.startMode === "custom-layout" && config.initialTiles?.length === config.rows * config.cols ? config.initialTiles : shuffleSolvable(config.rows, config.cols, config.shuffleSteps);
|
|
278
|
+
return {
|
|
279
|
+
tiles,
|
|
280
|
+
rows: config.rows,
|
|
281
|
+
cols: config.cols,
|
|
282
|
+
moveCount: 0,
|
|
283
|
+
startedAt: Date.now(),
|
|
284
|
+
isSolved: false
|
|
285
|
+
};
|
|
286
|
+
}, [config]);
|
|
287
|
+
const [state, setState] = React3.useState(initial);
|
|
288
|
+
const reset = () => {
|
|
289
|
+
setState({
|
|
290
|
+
...state,
|
|
291
|
+
tiles: shuffleSolvable(config.rows, config.cols, config.shuffleSteps),
|
|
292
|
+
moveCount: 0,
|
|
293
|
+
startedAt: Date.now(),
|
|
294
|
+
finishedAt: void 0,
|
|
295
|
+
isSolved: false
|
|
296
|
+
});
|
|
297
|
+
};
|
|
298
|
+
const solveNow = () => {
|
|
299
|
+
setState((prev) => ({ ...prev, tiles: buildSolvedTiles(config.rows, config.cols), isSolved: true, finishedAt: Date.now() }));
|
|
300
|
+
};
|
|
301
|
+
const durationSec = Math.floor(((state.finishedAt || Date.now()) - state.startedAt) / 1e3);
|
|
302
|
+
return /* @__PURE__ */ React3__default.default.createElement("section", null, /* @__PURE__ */ React3__default.default.createElement("h2", null, config.name), /* @__PURE__ */ React3__default.default.createElement("p", null, "\u6B65\u6570\uFF1A", state.moveCount, " \uFF5C \u7528\u65F6\uFF1A", durationSec, "s ", state.isSolved ? "\uFF5C\u5DF2\u901A\u5173 \u{1F389}" : ""), /* @__PURE__ */ React3__default.default.createElement(
|
|
303
|
+
HuarongdaoBoard_default,
|
|
304
|
+
{
|
|
305
|
+
tiles: state.tiles,
|
|
306
|
+
rows: state.rows,
|
|
307
|
+
cols: state.cols,
|
|
308
|
+
imageUrl: config.sourceImageUrl,
|
|
309
|
+
onClickTile: (idx) => setState((prev) => moveTile(prev, idx))
|
|
310
|
+
}
|
|
311
|
+
), /* @__PURE__ */ React3__default.default.createElement("div", { style: { marginTop: 12 } }, /* @__PURE__ */ React3__default.default.createElement("button", { onClick: reset }, "\u91CD\u65B0\u6253\u4E71"), /* @__PURE__ */ React3__default.default.createElement("button", { onClick: solveNow }, "\u4E00\u952E\u5B8C\u6210(\u6D4B\u8BD5)")), config.showReference ? /* @__PURE__ */ React3__default.default.createElement("div", { style: { marginTop: 12 } }, /* @__PURE__ */ React3__default.default.createElement("div", null, "\u53C2\u8003\u56FE\uFF1A"), /* @__PURE__ */ React3__default.default.createElement("img", { src: config.sourceImageUrl, alt: "reference", style: { width: 180, border: "1px solid #ccc" } })) : null);
|
|
312
|
+
};
|
|
313
|
+
var HuarongdaoGamePage_default = HuarongdaoGamePage;
|
|
314
|
+
var HuarongdaoConfigPage = () => {
|
|
315
|
+
const service = React3.useMemo(() => createHuarongdaoService(), []);
|
|
316
|
+
const [version, setVersion] = React3.useState(0);
|
|
317
|
+
const [name, setName] = React3.useState("\u793A\u4F8B\u534E\u5BB9\u9053");
|
|
318
|
+
const [slug, setSlug] = React3.useState("sample-huarongdao");
|
|
319
|
+
const [imageUrl, setImageUrl] = React3.useState("https://i.imgur.com/6z7Qw6M.png");
|
|
320
|
+
const [rows, setRows] = React3.useState(3);
|
|
321
|
+
const [cols, setCols] = React3.useState(3);
|
|
322
|
+
const list = React3.useMemo(() => {
|
|
323
|
+
return service.listConfigs();
|
|
324
|
+
}, [service, version]);
|
|
325
|
+
const create = () => {
|
|
326
|
+
const input = {
|
|
327
|
+
name,
|
|
328
|
+
slug,
|
|
329
|
+
sourceImageUrl: imageUrl,
|
|
330
|
+
rows,
|
|
331
|
+
cols,
|
|
332
|
+
showReference: true,
|
|
333
|
+
shuffleSteps: 80
|
|
334
|
+
};
|
|
335
|
+
service.createConfig(input);
|
|
336
|
+
setVersion((v) => v + 1);
|
|
337
|
+
};
|
|
338
|
+
return /* @__PURE__ */ React3__default.default.createElement("section", null, /* @__PURE__ */ React3__default.default.createElement("h2", null, "\u534E\u5BB9\u9053\u540E\u53F0\u914D\u7F6E\u9875"), /* @__PURE__ */ React3__default.default.createElement("p", null, "\u652F\u6301\u591A\u5957\u914D\u7F6E\u521B\u5EFA\u3001\u53C2\u6570\u5316\u7BA1\u7406\uFF08V1 \u9AA8\u67B6\uFF09"), /* @__PURE__ */ React3__default.default.createElement("div", null, /* @__PURE__ */ React3__default.default.createElement("input", { value: name, onChange: (e) => setName(e.target.value), placeholder: "name" }), /* @__PURE__ */ React3__default.default.createElement("input", { value: slug, onChange: (e) => setSlug(e.target.value), placeholder: "slug" }), /* @__PURE__ */ React3__default.default.createElement("input", { value: imageUrl, onChange: (e) => setImageUrl(e.target.value), placeholder: "image url" }), /* @__PURE__ */ React3__default.default.createElement("input", { type: "number", value: rows, onChange: (e) => setRows(Number(e.target.value) || 3) }), /* @__PURE__ */ React3__default.default.createElement("input", { type: "number", value: cols, onChange: (e) => setCols(Number(e.target.value) || 3) }), /* @__PURE__ */ React3__default.default.createElement("button", { onClick: create }, "\u521B\u5EFA\u914D\u7F6E")), /* @__PURE__ */ React3__default.default.createElement("ul", null, list.map((item) => /* @__PURE__ */ React3__default.default.createElement("li", { key: item.id }, item.name, " (", item.slug, ") - ", item.rows, "x", item.cols, " - ", item.status))));
|
|
339
|
+
};
|
|
340
|
+
var HuarongdaoConfigPage_default = HuarongdaoConfigPage;
|
|
341
|
+
|
|
342
|
+
exports.HuarongdaoService = HuarongdaoService;
|
|
343
|
+
exports.buildSolvedTiles = buildSolvedTiles;
|
|
344
|
+
exports.canMove = canMove;
|
|
345
|
+
exports.createCreateConfigHandler = createCreateConfigHandler;
|
|
346
|
+
exports.createDeleteConfigHandler = createDeleteConfigHandler;
|
|
347
|
+
exports.createGetSnapshotHandler = createGetSnapshotHandler;
|
|
348
|
+
exports.createHuarongdaoApiClient = createHuarongdaoApiClient;
|
|
349
|
+
exports.createHuarongdaoService = createHuarongdaoService;
|
|
350
|
+
exports.createHuarongdaoWebClient = createHuarongdaoWebClient;
|
|
351
|
+
exports.createListConfigsHandler = createListConfigsHandler;
|
|
352
|
+
exports.createUpdateConfigHandler = createUpdateConfigHandler;
|
|
353
|
+
exports.inversionCount = inversionCount;
|
|
354
|
+
exports.isSolvable = isSolvable;
|
|
355
|
+
exports.isSolved = isSolved;
|
|
356
|
+
exports.moveTile = moveTile;
|
|
357
|
+
exports.shuffleSolvable = shuffleSolvable;
|
|
358
|
+
exports.webUI = web_exports;
|
|
359
|
+
//# sourceMappingURL=index.js.map
|
|
360
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/huarongdao/logic/game.ts","../../src/huarongdao/service/api/client.ts","../../src/huarongdao/service/web/client.ts","../../src/huarongdao/server/service.ts","../../src/huarongdao/routes/index.ts","../../src/huarongdao/ui/web/index.ts","../../src/huarongdao/ui/web/components/HuarongdaoBoard.tsx","../../src/huarongdao/ui/web/pages/HuarongdaoGamePage.tsx","../../src/huarongdao/ui/web/pages/HuarongdaoConfigPage.tsx"],"names":["requester","id","NextResponse","React","useMemo","useState"],"mappings":"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","file":"index.js","sourcesContent":["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 type { CreateHuarongdaoConfigInput, HuarongdaoConfig, HuarongdaoStateSnapshot } from '../../types';\n\nexport type HttpMethod = 'GET' | 'POST' | 'PATCH' | 'DELETE';\nexport interface Requester {\n <T>(url: string, options?: { method?: HttpMethod; body?: unknown }): Promise<T>;\n}\n\ninterface ApiEnvelope<T> {\n success: boolean;\n data?: T;\n error?: string;\n}\n\nconst unwrap = <T>(result: ApiEnvelope<T>): T => {\n if (!result.success || result.data === undefined) throw new Error(result.error || '请求失败');\n return result.data;\n};\n\nexport const createHuarongdaoApiClient = (basePath: string, requester: Requester) => ({\n async getSnapshot(): Promise<HuarongdaoStateSnapshot> {\n return unwrap(await requester<ApiEnvelope<HuarongdaoStateSnapshot>>(`${basePath}/snapshot`, { method: 'GET' }));\n },\n async listConfigs(): Promise<HuarongdaoConfig[]> {\n return unwrap(await requester<ApiEnvelope<HuarongdaoConfig[]>>(`${basePath}/configs`, { method: 'GET' }));\n },\n async createConfig(input: CreateHuarongdaoConfigInput): Promise<HuarongdaoConfig> {\n return unwrap(await requester<ApiEnvelope<HuarongdaoConfig>>(`${basePath}/configs`, { method: 'POST', body: input }));\n },\n async updateConfig(id: string, patch: Partial<HuarongdaoConfig>): Promise<HuarongdaoConfig> {\n return unwrap(await requester<ApiEnvelope<HuarongdaoConfig>>(`${basePath}/configs`, { method: 'PATCH', body: { id, patch } }));\n },\n async deleteConfig(id: string): Promise<boolean> {\n return unwrap(await requester<ApiEnvelope<boolean>>(`${basePath}/configs`, { method: 'DELETE', body: { id } }));\n },\n});\n","import { createHuarongdaoApiClient, type Requester } from '../api';\n\nexport interface HuarongdaoWebClientOptions {\n baseUrl?: string;\n basePath?: string;\n headers?: Record<string, string>;\n}\n\nconst requester = (options: HuarongdaoWebClientOptions): Requester => {\n const baseUrl = options.baseUrl || '';\n return async <T>(url: string, req?: { method?: 'GET' | 'POST' | 'PATCH' | 'DELETE'; body?: unknown }): Promise<T> => {\n const res = await fetch(`${baseUrl}${url}`, {\n method: req?.method || 'GET',\n headers: { 'Content-Type': 'application/json', ...(options.headers || {}) },\n body: req?.body ? JSON.stringify(req.body) : undefined,\n });\n return (await res.json()) as T;\n };\n};\n\nexport const createHuarongdaoWebClient = (options: HuarongdaoWebClientOptions = {}) => {\n return createHuarongdaoApiClient(options.basePath || '/api/huarongdao', requester(options));\n};\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 { NextResponse } from 'next/server';\nimport type { NextRequest } from 'next/server';\nimport { createHuarongdaoService } from '../server';\nimport type { CreateHuarongdaoConfigInput, HuarongdaoConfig } from '../types';\n\nexport interface HuarongdaoRouteConfig {\n service?: ReturnType<typeof createHuarongdaoService>;\n}\n\nconst resolveService = (config?: HuarongdaoRouteConfig) => config?.service || createHuarongdaoService();\n\nexport const createGetSnapshotHandler = (config?: HuarongdaoRouteConfig) => {\n const service = resolveService(config);\n return async (_req: NextRequest) => NextResponse.json({ success: true, data: service.getSnapshot() });\n};\n\nexport const createListConfigsHandler = (config?: HuarongdaoRouteConfig) => {\n const service = resolveService(config);\n return async (_req: NextRequest) => NextResponse.json({ success: true, data: service.listConfigs() });\n};\n\nexport const createCreateConfigHandler = (config?: HuarongdaoRouteConfig) => {\n const service = resolveService(config);\n return async (req: NextRequest) => {\n try {\n const body = (await req.json()) as CreateHuarongdaoConfigInput;\n const data = service.createConfig(body);\n return NextResponse.json({ success: true, data });\n } catch (e) {\n return NextResponse.json({ success: false, error: (e as Error).message }, { status: 400 });\n }\n };\n};\n\nexport const createUpdateConfigHandler = (config?: HuarongdaoRouteConfig) => {\n const service = resolveService(config);\n return async (req: NextRequest) => {\n try {\n const body = (await req.json()) as { id: string; patch: Partial<HuarongdaoConfig> };\n const data = service.updateConfig(body.id, body.patch || {});\n return NextResponse.json({ success: true, data });\n } catch (e) {\n return NextResponse.json({ success: false, error: (e as Error).message }, { status: 400 });\n }\n };\n};\n\nexport const createDeleteConfigHandler = (config?: HuarongdaoRouteConfig) => {\n const service = resolveService(config);\n return async (req: NextRequest) => {\n try {\n const body = (await req.json()) as { id: string };\n service.deleteConfig(body.id);\n return NextResponse.json({ success: true, data: true });\n } catch (e) {\n return NextResponse.json({ success: false, error: (e as Error).message }, { status: 400 });\n }\n };\n};\n","export { default as HuarongdaoBoard } from './components/HuarongdaoBoard';\nexport { default as HuarongdaoGamePage } from './pages/HuarongdaoGamePage';\nexport { default as HuarongdaoConfigPage } from './pages/HuarongdaoConfigPage';\n","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 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 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"]}
|