poi-plugin-gimmick-tracker 0.2.0 → 0.2.2
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/README.md +2 -0
- package/index.js +153 -86
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,6 +28,8 @@ P2点空优1次
|
|
|
28
28
|
|
|
29
29
|
导入时逐行报告识别结果,无法识别的行会明确指出,不会静默丢弃。条件可删除,重复导入按签名更新次数。
|
|
30
30
|
|
|
31
|
+
解析器对攻略写法尽量鲁棒:中文数字(两次/一回)、省略「胜/点/次」(`P3点A2次`)、乘号计数(`S×2`)、词序变体(`G点2次S胜`、`到达E2点2次`)、`boss/王点/斩杀` 等装饰词、大小写混排、全角字符、繁体(點/勝/達)、一行挤多条。`击破` 按 A 胜理解;`P1boss一次` 这类无字母点的 boss 简写按「P1点击破 A胜」理解并在报告里提示。
|
|
32
|
+
|
|
31
33
|
## 数据与隐私
|
|
32
34
|
|
|
33
35
|
- 状态按成员分文件保存在 `<poi AppData>/gimmick-tracker/<memberId>/state-v2.json`,临时文件加 rename 原子写。
|
package/index.js
CHANGED
|
@@ -62,96 +62,160 @@ function matchesCondition(condition, observation) {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
// src/parser.js
|
|
65
|
-
var
|
|
65
|
+
var AIR_ALIAS = {
|
|
66
|
+
\u7A7A\u786E: 1,
|
|
67
|
+
\u7A7A\u78BA: 1,
|
|
68
|
+
\u5236\u7A7A\u786E\u4FDD: 1,
|
|
69
|
+
\u5236\u7A7A\u78BA\u4FDD: 1,
|
|
70
|
+
\u5236\u7A7A\u6743\u786E\u4FDD: 1,
|
|
71
|
+
\u5236\u7A7A\u6B0A\u78BA\u4FDD: 1,
|
|
72
|
+
\u7A7A\u512A: 2,
|
|
73
|
+
\u7A7A\u4F18: 2,
|
|
74
|
+
\u822A\u7A7A\u512A\u52E2: 2,
|
|
75
|
+
\u822A\u7A7A\u4F18\u52BF: 2,
|
|
76
|
+
\u7A7A\u5747: 3,
|
|
77
|
+
\u7A7A\u5747\u8861: 3,
|
|
78
|
+
\u7A7A\u52A3: 4
|
|
79
|
+
};
|
|
66
80
|
var AIR_STATE_TO_TEXT = { 1: "\u7A7A\u786E", 2: "\u7A7A\u4F18", 3: "\u7A7A\u5747", 4: "\u7A7A\u52A3" };
|
|
67
|
-
var
|
|
68
|
-
var
|
|
69
|
-
var
|
|
70
|
-
var
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
81
|
+
var CHINESE_DIGIT = { \u4E00: 1, \u4E24: 2, \u4E8C: 2, \u4E09: 3, \u56DB: 4, \u4E94: 5, \u516D: 6, \u4E03: 7, \u516B: 8, \u4E5D: 9, \u5341: 10 };
|
|
82
|
+
var WIN = "[\u80DC\u52DD]?";
|
|
83
|
+
var KILL = "[\u51FB\u64CA]\u7834";
|
|
84
|
+
var REACH = "\u5230[\u8FBE\u9054]";
|
|
85
|
+
var RANKC = "(?<rank>SS|S|A|B|C|D|E)";
|
|
86
|
+
var AIR = "(?<air>\u7A7A\u786E|\u7A7A\u512A|\u7A7A\u4F18|\u7A7A\u5747|\u7A7A\u52A3|\u5236\u7A7A\u786E\u4FDD|\u5236\u7A7A\u78BA\u4FDD|\u5236\u7A7A\u6743\u786E\u4FDD|\u5236\u7A7A\u6B0A\u78BA\u4FDD|\u822A\u7A7A\u512A\u52E2|\u822A\u7A7A\u4F18\u52BF)";
|
|
87
|
+
var CNT = "(?<cnt>\\d+|[\u4E00\u4E24\u4E8C\u4E09\u56DB\u4E94\u516D\u4E03\u516B\u4E5D\u5341])?";
|
|
88
|
+
var CNT_UNIT = "[\u6B21\u56DE\u51F8]?";
|
|
89
|
+
var NODE_DIAN = "(?<node>[A-Za-z]{1,2}\\d{0,2})[\u70B9\u70B9\u9EDE]";
|
|
90
|
+
var NODE_BARE = "(?<node>(?:[A-Za-z]{1,2}\\d{1,2})|(?:[A-Za-z](?!\\d)))";
|
|
91
|
+
var BASE = "(?<base>\u5B88\u5BB6|\u57FA\u5730\u9632\u7A7A\u6218|\u57FA\u5730\u9632\u7A7A|\u5BB6\u91CC|\u9632\u7A7A|\u57FA\u5730)";
|
|
92
|
+
var DECORATION = /(boss|王点|王點|門神|门神|斬殺|斩杀|斬殺線|斩杀线|第\d+[次回凸]?|第[一两二三四五六七八九十]+[次回凸]?|第)/gi;
|
|
93
|
+
var NOISE = /[^A-Za-z0-9〇㐀-䶿一-鿿]/g;
|
|
94
|
+
var FORM_TEMPLATES = [
|
|
95
|
+
{ kind: "base-air-defense", build: () => new RegExp(`${BASE}${AIR}${CNT}${CNT_UNIT}`, "i"), usesNode: false },
|
|
96
|
+
{ kind: "reach-after", build: (node) => new RegExp(`${REACH}${node}${CNT}${CNT_UNIT}`, "i"), usesNode: true },
|
|
97
|
+
{ kind: "node-arrival", build: (node) => new RegExp(`${node}${REACH}${CNT}${CNT_UNIT}`, "i"), usesNode: true },
|
|
98
|
+
{ kind: "kill", build: (node) => new RegExp(`${node}${KILL}${CNT}${CNT_UNIT}`, "i"), usesNode: true },
|
|
99
|
+
{ kind: "victory-rank", build: (node) => new RegExp(`${node}${RANKC}${WIN}${CNT}${CNT_UNIT}`, "i"), usesNode: true },
|
|
100
|
+
{ kind: "count-first", build: (node) => new RegExp(`${node}${CNT}${CNT_UNIT}${RANKC}${WIN}`, "i"), usesNode: true },
|
|
101
|
+
{ kind: "node-air-state", build: (node) => new RegExp(`${node}${AIR}${CNT}${CNT_UNIT}`, "i"), usesNode: true }
|
|
75
102
|
];
|
|
103
|
+
var FORMS = [];
|
|
104
|
+
for (const template of FORM_TEMPLATES) {
|
|
105
|
+
if (!template.usesNode) {
|
|
106
|
+
FORMS.push({ kind: template.kind, re: template.build(null), countGroup: 3 });
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
FORMS.push({ kind: template.kind, re: template.build(NODE_DIAN), countGroup: 2, nodeGroup: 1 });
|
|
110
|
+
FORMS.push({ kind: template.kind, re: template.build(NODE_BARE), countGroup: 2, nodeGroup: 1 });
|
|
111
|
+
}
|
|
76
112
|
function normalizeNodeLabel(value) {
|
|
77
113
|
return String(value ?? "").trim().toUpperCase();
|
|
78
114
|
}
|
|
115
|
+
function toHalfWidth(text) {
|
|
116
|
+
let out = "";
|
|
117
|
+
for (const ch of text) {
|
|
118
|
+
const code = ch.codePointAt(0);
|
|
119
|
+
if (code >= 65281 && code <= 65374) out += String.fromCharCode(code - 65248);
|
|
120
|
+
else if (ch === "\u3000") out += " ";
|
|
121
|
+
else out += ch;
|
|
122
|
+
}
|
|
123
|
+
return out;
|
|
124
|
+
}
|
|
125
|
+
function chineseCountToNumber(count) {
|
|
126
|
+
if (count == null || count === "") return 1;
|
|
127
|
+
return CHINESE_DIGIT[count] ?? Number(count);
|
|
128
|
+
}
|
|
79
129
|
function stripAnnotation(text) {
|
|
80
130
|
const notes = [];
|
|
81
|
-
const cleaned = String(text ?? "").replace(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
131
|
+
const cleaned = String(text ?? "").replace(
|
|
132
|
+
/[((【〔「]([^()()【】〔〕「」]*)[))】〕」]/g,
|
|
133
|
+
(_m, inner) => {
|
|
134
|
+
const value = String(inner ?? "").trim();
|
|
135
|
+
if (/^[A-Za-z]{1,2}\d{0,2}[点点點]?$/.test(value)) return value;
|
|
136
|
+
if (value !== "") notes.push(value);
|
|
137
|
+
return "";
|
|
138
|
+
}
|
|
139
|
+
);
|
|
86
140
|
return { cleaned: cleaned.trim(), notes };
|
|
87
141
|
}
|
|
88
|
-
function
|
|
89
|
-
|
|
90
|
-
|
|
142
|
+
function airStateOf(word) {
|
|
143
|
+
return AIR_ALIAS[word];
|
|
144
|
+
}
|
|
145
|
+
function parseSegmentBody(segment) {
|
|
91
146
|
const { cleaned, notes } = stripAnnotation(segment);
|
|
92
|
-
|
|
93
|
-
if (text === "") {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
requiredCount: Number(match[3]),
|
|
107
|
-
notes
|
|
108
|
-
}
|
|
109
|
-
};
|
|
147
|
+
let text = toHalfWidth(cleaned).replace(DECORATION, "").replace(NOISE, "");
|
|
148
|
+
if (text === "") return { matches: null, notes };
|
|
149
|
+
const bossSeen = /boss/i.test(segment) || /boss/i.test(text);
|
|
150
|
+
const matches = [];
|
|
151
|
+
let rest = text;
|
|
152
|
+
let guard = 0;
|
|
153
|
+
while (rest.length > 0 && guard < 20) {
|
|
154
|
+
guard += 1;
|
|
155
|
+
let matched = null;
|
|
156
|
+
for (const form2 of FORMS) {
|
|
157
|
+
const m2 = form2.re.exec(rest);
|
|
158
|
+
if (m2 != null && (matched == null || m2.index < matched.m.index)) {
|
|
159
|
+
matched = { form: form2, m: m2 };
|
|
160
|
+
}
|
|
110
161
|
}
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
162
|
+
if (matched == null && bossSeen) {
|
|
163
|
+
const bare = /^([A-Za-z]{1,2})(\d+)?([一两二三四五六七八九十]|\d+)?[次回凸]?/.exec(rest);
|
|
164
|
+
if (bare != null && bare[1] != null && (bare[2] != null || bare[3] != null)) {
|
|
165
|
+
const letters = bare[1];
|
|
166
|
+
const digits = bare[2] ?? "";
|
|
167
|
+
const countWord = bare[3] ?? "";
|
|
168
|
+
const restAfter = rest.slice(bare[0].length);
|
|
169
|
+
const digitsAreCount = digits !== "" && /^[次回凸]/.test(restAfter);
|
|
170
|
+
const nodeLabel2 = normalizeNodeLabel(digitsAreCount || digits === "" ? letters : letters + digits);
|
|
171
|
+
const count2 = digitsAreCount ? Number(digits) : chineseCountToNumber(countWord);
|
|
172
|
+
matches.push({
|
|
173
|
+
ok: true,
|
|
174
|
+
condition: {
|
|
175
|
+
kind: "victory-rank",
|
|
176
|
+
nodeLabel: nodeLabel2,
|
|
177
|
+
requiredRank: "A",
|
|
178
|
+
requiredCount: count2,
|
|
179
|
+
notes: [...notes, "boss\u2192\u6309\u51FB\u7834(A\u80DC)\u8BA1"]
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
rest = restAfter;
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
if (matched == null) break;
|
|
188
|
+
const { form, m } = matched;
|
|
189
|
+
const count = chineseCountToNumber(m.groups?.cnt);
|
|
190
|
+
if (!Number.isInteger(count) || count <= 0) {
|
|
191
|
+
return { matches: [{ ok: false, reason: "\u6B21\u6570\u5FC5\u987B\u662F\u6B63\u6574\u6570" }], notes };
|
|
123
192
|
}
|
|
124
|
-
|
|
125
|
-
|
|
193
|
+
const common = { requiredCount: count, notes };
|
|
194
|
+
const nodeLabel = normalizeNodeLabel(m.groups?.node);
|
|
195
|
+
if (form.kind === "base-air-defense") {
|
|
196
|
+
const airState = airStateOf(m.groups.air);
|
|
197
|
+
if (airState == null) return { matches: [{ ok: false, reason: `\u672A\u77E5\u5236\u7A7A\u8BCD\u300C${m.groups.air}\u300D` }], notes };
|
|
198
|
+
matches.push({ ok: true, condition: { kind: "base-air-defense", requiredAirState: airState, ...common } });
|
|
199
|
+
} else if (form.kind === "node-arrival" || form.kind === "reach-after") {
|
|
200
|
+
matches.push({ ok: true, condition: { kind: "node-arrival", nodeLabel, ...common } });
|
|
201
|
+
} else if (form.kind === "kill") {
|
|
202
|
+
matches.push({
|
|
126
203
|
ok: true,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
};
|
|
204
|
+
condition: { kind: "victory-rank", nodeLabel, requiredRank: "A", ...common, notes: [...notes, "\u51FB\u7834\u2192\u6309A\u80DC\u8BA1"] }
|
|
205
|
+
});
|
|
206
|
+
} else if (form.kind === "victory-rank" || form.kind === "count-first") {
|
|
207
|
+
matches.push({ ok: true, condition: { kind: "victory-rank", nodeLabel, requiredRank: m.groups.rank.toUpperCase(), ...common } });
|
|
208
|
+
} else {
|
|
209
|
+
const airState = airStateOf(m.groups.air);
|
|
210
|
+
if (airState == null) return { matches: [{ ok: false, reason: `\u672A\u77E5\u5236\u7A7A\u8BCD\u300C${m.groups.air}\u300D` }], notes };
|
|
211
|
+
matches.push({ ok: true, condition: { kind: "node-air-state", nodeLabel, requiredAirState: airState, ...common } });
|
|
136
212
|
}
|
|
137
|
-
|
|
138
|
-
ok: true,
|
|
139
|
-
raw: segment,
|
|
140
|
-
condition: {
|
|
141
|
-
kind: "base-air-defense",
|
|
142
|
-
requiredAirState: AIR_TEXT_TO_STATE[match[2]],
|
|
143
|
-
requiredCount: Number(match[3]),
|
|
144
|
-
notes
|
|
145
|
-
}
|
|
146
|
-
};
|
|
213
|
+
rest = rest.slice(m.index + m[0].length);
|
|
147
214
|
}
|
|
148
|
-
return {
|
|
215
|
+
return { matches, notes };
|
|
149
216
|
}
|
|
150
217
|
var BUCKET_HEADER = /^(解谜|解密|谜题|削甲|装甲|debuff|gimmick)[::]/;
|
|
151
218
|
var BUCKET_WORDS = { \u89E3\u8C1C: "gimmick", \u89E3\u5BC6: "gimmick", \u8C1C\u9898: "gimmick", gimmick: "gimmick", \u524A\u7532: "debuff", \u88C5\u7532: "debuff", debuff: "debuff" };
|
|
152
|
-
function bucketOf(word) {
|
|
153
|
-
return BUCKET_WORDS[word] ?? null;
|
|
154
|
-
}
|
|
155
219
|
function parseGuideText(text, bucketDefault = "debuff") {
|
|
156
220
|
const report = [];
|
|
157
221
|
const conditions = [];
|
|
@@ -161,27 +225,30 @@ function parseGuideText(text, bucketDefault = "debuff") {
|
|
|
161
225
|
let work = segment;
|
|
162
226
|
const header = BUCKET_HEADER.exec(work.replace(/\s+/g, ""));
|
|
163
227
|
if (header != null) {
|
|
164
|
-
bucket =
|
|
228
|
+
bucket = BUCKET_WORDS[header[1]] ?? bucket;
|
|
165
229
|
work = work.replace(/^\s*[^::]*[::]\s*/, "");
|
|
166
230
|
if (work === "") {
|
|
167
231
|
report.push({ ok: true, raw: segment, header: true, bucket });
|
|
168
232
|
continue;
|
|
169
233
|
}
|
|
170
234
|
}
|
|
171
|
-
const
|
|
172
|
-
if (
|
|
173
|
-
if (!
|
|
174
|
-
|
|
235
|
+
const { matches } = parseSegmentBody(work);
|
|
236
|
+
if (matches == null) continue;
|
|
237
|
+
if (matches.length === 0 || matches.some((match) => !match.ok)) {
|
|
238
|
+
const failure = matches.find((match) => !match.ok);
|
|
239
|
+
report.push({
|
|
240
|
+
ok: false,
|
|
241
|
+
raw: segment,
|
|
242
|
+
reason: failure?.reason ?? "\u672A\u8BC6\u522B\u7684\u5199\u6CD5\uFF08\u793A\u4F8B\uFF1AY2\u70B9S\u80DC1\u6B21 / P3\u70B9A2\u6B21 / \u5B88\u5BB6\u7A7A\u4F183\u6B21\uFF09"
|
|
243
|
+
});
|
|
175
244
|
continue;
|
|
176
245
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
246
|
+
for (const match of matches) {
|
|
247
|
+
match.condition.bucket = bucket;
|
|
248
|
+
match.condition.raw = segment;
|
|
249
|
+
conditions.push(match.condition);
|
|
250
|
+
report.push({ ok: true, raw: segment, condition: match.condition, multiple: matches.length > 1 });
|
|
180
251
|
}
|
|
181
|
-
parsed.condition.bucket = bucket;
|
|
182
|
-
parsed.condition.raw = parsed.raw;
|
|
183
|
-
conditions.push(parsed.condition);
|
|
184
|
-
report.push({ ok: true, raw: parsed.raw, condition: parsed.condition });
|
|
185
252
|
}
|
|
186
253
|
return { conditions, report };
|
|
187
254
|
}
|
|
@@ -1314,9 +1381,9 @@ function createLedgerView(controller2) {
|
|
|
1314
1381
|
rows: 4,
|
|
1315
1382
|
value: guideText,
|
|
1316
1383
|
onChange: (event) => setGuideText(event.currentTarget.value),
|
|
1317
|
-
placeholder: "\
|
|
1384
|
+
placeholder: "\u4F8B\u5982\uFF1AY2\u70B9S\u80DC1\u6B21 / L2\u70B9A\u80DC1\u6B21 / P3\u70B9A2\u6B21 / C2\u70B9\u5230\u8FBE1\u6B21 / P2\u70B9\u7A7A\u4F181\u6B21 / \u5B88\u5BB6\u7A7A\u4F183\u6B21\n\u4E5F\u8BA4\uFF1AP1boss\u4E00\u6B21 / \u5B88\u5BB6\u7A7A\u4F18\u4E24\u6B21 / G\u70B92\u6B21S\u80DC / S\u70B9\u51FB\u78342\u56DE / \uFF30\uFF12\u70B9\u7A7A\u512A\uFF11\u6B21\n\u53EF\u5E26\u6CE8\u8BB0\u4E0E\u5206\u7EC4\u884C\uFF1AG\u70B9\uFF08P1boss\uFF09S\u80DC1\u6B21\u3001\u89E3\u8C1C\uFF1A \u6216 \u524A\u7532\uFF1A"
|
|
1318
1385
|
}
|
|
1319
|
-
), /* @__PURE__ */ import_react.default.createElement("div", { style: styles.actions }, /* @__PURE__ */ import_react.default.createElement(import_core.HTMLSelect, { value: bucket, onChange: (event) => setBucket(event.currentTarget.value) }, /* @__PURE__ */ import_react.default.createElement("option", { value: "debuff" }, "\u5BFC\u5165\u4E3A\u524A\u7532\u6761\u4EF6"), /* @__PURE__ */ import_react.default.createElement("option", { value: "gimmick" }, "\u5BFC\u5165\u4E3A\u89E3\u8C1C\u6761\u4EF6")), /* @__PURE__ */ import_react.default.createElement(import_core.Button, { intent: "primary", onClick: importGuide, disabled: mapRef == null }, "\u5BFC\u5165\u5230\u5F53\u524D\u6D77\u57DF", mapRef != null ? ` ${mapLabel(mapRef)}` : ""), mapRef == null && /* @__PURE__ */ import_react.default.createElement("span", { style: styles.muted }, "\u7B49\u5F85\u6D77\u57DF\u8BC6\u522B\u2026")), report != null && /* @__PURE__ */ import_react.default.createElement("div", { style: { marginTop: 8 } }, report.error != null ? /* @__PURE__ */ import_react.default.createElement(import_core.Callout, { intent: "danger" }, report.error) : /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { style: { marginBottom: 4 } }, /* @__PURE__ */ import_react.default.createElement("strong", null, report.mapLabel), "\uFF1A\u8BC6\u522B ", report.importedCount, " \u6761\u3002"), report.report.map((line, index) => /* @__PURE__ */ import_react.default.createElement("div", { key: index, style: { ...styles.reportLine, color: line.ok ? void 0 : "#cd4a3e" } }, line.header ? "\u2699" : line.ok ? "\u2714" : "\u2718", " ", line.raw, line.header ? ` \u2192 \u5206\u7EC4\uFF1A${BUCKETS[line.bucket]}` : "", !line.ok && line.reason != null ? ` \u2014 ${line.reason}` : ""))))), mapState != null && closedRounds.length > 0 && /* @__PURE__ */ import_react.default.createElement(import_core.Card, { style: styles.section, elevation: import_core.Elevation.ZERO }, /* @__PURE__ */ import_react.default.createElement("h3", { style: { marginTop: 0 } }, mapLabel(mapState), " \xB7 \u5386\u53F2\u8F6E\u6B21"), closedRounds.map((round) => /* @__PURE__ */ import_react.default.createElement(RoundSummary, { key: round.id, round, mapState }))), otherMaps.length > 0 && /* @__PURE__ */ import_react.default.createElement(import_core.Card, { style: styles.section, elevation: import_core.Elevation.ZERO }, /* @__PURE__ */ import_react.default.createElement("h3", { style: { marginTop: 0 } }, "\u5176\u4ED6\u6D77\u57DF"), otherMaps.map((ms) => {
|
|
1386
|
+
), /* @__PURE__ */ import_react.default.createElement("div", { style: styles.actions }, /* @__PURE__ */ import_react.default.createElement(import_core.HTMLSelect, { value: bucket, onChange: (event) => setBucket(event.currentTarget.value) }, /* @__PURE__ */ import_react.default.createElement("option", { value: "debuff" }, "\u5BFC\u5165\u4E3A\u524A\u7532\u6761\u4EF6"), /* @__PURE__ */ import_react.default.createElement("option", { value: "gimmick" }, "\u5BFC\u5165\u4E3A\u89E3\u8C1C\u6761\u4EF6")), /* @__PURE__ */ import_react.default.createElement(import_core.Button, { intent: "primary", onClick: importGuide, disabled: mapRef == null }, "\u5BFC\u5165\u5230\u5F53\u524D\u6D77\u57DF", mapRef != null ? ` ${mapLabel(mapRef)}` : ""), mapRef == null && /* @__PURE__ */ import_react.default.createElement("span", { style: styles.muted }, "\u7B49\u5F85\u6D77\u57DF\u8BC6\u522B\u2026")), report != null && /* @__PURE__ */ import_react.default.createElement("div", { style: { marginTop: 8 } }, report.error != null ? /* @__PURE__ */ import_react.default.createElement(import_core.Callout, { intent: "danger" }, report.error) : /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { style: { marginBottom: 4 } }, /* @__PURE__ */ import_react.default.createElement("strong", null, report.mapLabel), "\uFF1A\u8BC6\u522B ", report.importedCount, " \u6761\u3002"), report.report.map((line, index) => /* @__PURE__ */ import_react.default.createElement("div", { key: index, style: { ...styles.reportLine, color: line.ok ? void 0 : "#cd4a3e" } }, line.header ? "\u2699" : line.ok ? "\u2714" : "\u2718", " ", line.raw, line.header ? ` \u2192 \u5206\u7EC4\uFF1A${BUCKETS[line.bucket]}` : "", !line.header && line.ok && line.condition != null ? ` \u2192 ${conditionLabel(line.condition)}` : "", !line.ok && line.reason != null ? ` \u2014 ${line.reason}` : ""))))), mapState != null && closedRounds.length > 0 && /* @__PURE__ */ import_react.default.createElement(import_core.Card, { style: styles.section, elevation: import_core.Elevation.ZERO }, /* @__PURE__ */ import_react.default.createElement("h3", { style: { marginTop: 0 } }, mapLabel(mapState), " \xB7 \u5386\u53F2\u8F6E\u6B21"), closedRounds.map((round) => /* @__PURE__ */ import_react.default.createElement(RoundSummary, { key: round.id, round, mapState }))), otherMaps.length > 0 && /* @__PURE__ */ import_react.default.createElement(import_core.Card, { style: styles.section, elevation: import_core.Elevation.ZERO }, /* @__PURE__ */ import_react.default.createElement("h3", { style: { marginTop: 0 } }, "\u5176\u4ED6\u6D77\u57DF"), otherMaps.map((ms) => {
|
|
1320
1387
|
const legacy = ms.rounds.find((round) => round.bucket === "legacy");
|
|
1321
1388
|
const window2 = controller2.legacyWindowFor(ms.mapId);
|
|
1322
1389
|
return /* @__PURE__ */ import_react.default.createElement("div", { key: ms.mapId, style: { padding: "8px 0", borderBottom: "1px solid rgba(128,128,128,.15)" } }, /* @__PURE__ */ import_react.default.createElement("div", { style: { display: "flex", gap: 8, alignItems: "center" } }, /* @__PURE__ */ import_react.default.createElement(import_core.Tag, { minimal: true }, mapLabel(ms)), /* @__PURE__ */ import_react.default.createElement("span", { style: styles.muted }, "\u6761\u4EF6 ", ms.conditions.length, " \xB7 \u8F6E\u6B21 ", ms.rounds.length, ms.cleared ? " \xB7 \u5DF2\u901A\u5173" : "", legacy != null ? " \xB7 \u542B\u65E7\u6570\u636E\u5F52\u6863" : ""), legacy != null && window2 != null && /* @__PURE__ */ import_react.default.createElement(import_core.Button, { small: true, onClick: () => controller2.replayLegacy(ms.mapId, window2.from, window2.to) }, "\u56DE\u653E\u5386\u53F2\u524A\u7532\u4E00\u8F6E")));
|