poi-plugin-gimmick-tracker 0.2.1 → 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/index.js +66 -86
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -79,25 +79,36 @@ var AIR_ALIAS = {
|
|
|
79
79
|
};
|
|
80
80
|
var AIR_STATE_TO_TEXT = { 1: "\u7A7A\u786E", 2: "\u7A7A\u4F18", 3: "\u7A7A\u5747", 4: "\u7A7A\u52A3" };
|
|
81
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 NODE = "([A-Za-z]{1,2}\\d{0,2})";
|
|
83
|
-
var DIAN = "[\u70B9\u70B9\u9EDE]?";
|
|
84
|
-
var CNT = "(\\d+|[\u4E00\u4E24\u4E8C\u4E09\u56DB\u4E94\u516D\u4E03\u516B\u4E5D\u5341])";
|
|
85
|
-
var CNT_UNIT = "[\u6B21\u56DE\u51F8]?";
|
|
86
|
-
var RANKC = "(SS|S|A|B|C|D|E)";
|
|
87
|
-
var 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)";
|
|
88
82
|
var WIN = "[\u80DC\u52DD]?";
|
|
89
83
|
var KILL = "[\u51FB\u64CA]\u7834";
|
|
90
84
|
var REACH = "\u5230[\u8FBE\u9054]";
|
|
91
|
-
var
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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 }
|
|
99
102
|
];
|
|
100
|
-
var
|
|
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
|
+
}
|
|
101
112
|
function normalizeNodeLabel(value) {
|
|
102
113
|
return String(value ?? "").trim().toUpperCase();
|
|
103
114
|
}
|
|
@@ -112,15 +123,20 @@ function toHalfWidth(text) {
|
|
|
112
123
|
return out;
|
|
113
124
|
}
|
|
114
125
|
function chineseCountToNumber(count) {
|
|
126
|
+
if (count == null || count === "") return 1;
|
|
115
127
|
return CHINESE_DIGIT[count] ?? Number(count);
|
|
116
128
|
}
|
|
117
129
|
function stripAnnotation(text) {
|
|
118
130
|
const notes = [];
|
|
119
|
-
const cleaned = String(text ?? "").replace(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
+
);
|
|
124
140
|
return { cleaned: cleaned.trim(), notes };
|
|
125
141
|
}
|
|
126
142
|
function airStateOf(word) {
|
|
@@ -128,10 +144,9 @@ function airStateOf(word) {
|
|
|
128
144
|
}
|
|
129
145
|
function parseSegmentBody(segment) {
|
|
130
146
|
const { cleaned, notes } = stripAnnotation(segment);
|
|
131
|
-
let text = toHalfWidth(cleaned).replace(DECORATION, "").replace(
|
|
147
|
+
let text = toHalfWidth(cleaned).replace(DECORATION, "").replace(NOISE, "");
|
|
132
148
|
if (text === "") return { matches: null, notes };
|
|
133
149
|
const bossSeen = /boss/i.test(segment) || /boss/i.test(text);
|
|
134
|
-
text = text.replace(/([一两二三四五六七八九十])(?=[次回凸]|$)/g, (m) => String(CHINESE_DIGIT[m]));
|
|
135
150
|
const matches = [];
|
|
136
151
|
let rest = text;
|
|
137
152
|
let guard = 0;
|
|
@@ -145,94 +160,59 @@ function parseSegmentBody(segment) {
|
|
|
145
160
|
}
|
|
146
161
|
}
|
|
147
162
|
if (matched == null && bossSeen) {
|
|
148
|
-
const bare =
|
|
149
|
-
if (bare != null) {
|
|
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);
|
|
150
172
|
matches.push({
|
|
151
173
|
ok: true,
|
|
152
174
|
condition: {
|
|
153
175
|
kind: "victory-rank",
|
|
154
|
-
nodeLabel:
|
|
176
|
+
nodeLabel: nodeLabel2,
|
|
155
177
|
requiredRank: "A",
|
|
156
|
-
requiredCount:
|
|
178
|
+
requiredCount: count2,
|
|
157
179
|
notes: [...notes, "boss\u2192\u6309\u51FB\u7834(A\u80DC)\u8BA1"]
|
|
158
180
|
}
|
|
159
181
|
});
|
|
160
|
-
rest =
|
|
182
|
+
rest = restAfter;
|
|
161
183
|
continue;
|
|
162
184
|
}
|
|
163
185
|
break;
|
|
164
186
|
}
|
|
165
187
|
if (matched == null) break;
|
|
166
188
|
const { form, m } = matched;
|
|
167
|
-
const count = chineseCountToNumber(
|
|
168
|
-
if (!Number.isInteger(count) || count <= 0)
|
|
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 };
|
|
192
|
+
}
|
|
193
|
+
const common = { requiredCount: count, notes };
|
|
194
|
+
const nodeLabel = normalizeNodeLabel(m.groups?.node);
|
|
169
195
|
if (form.kind === "base-air-defense") {
|
|
170
|
-
const airState = airStateOf(m
|
|
171
|
-
if (airState == null) return { matches: [{ ok: false, reason: `\u672A\u77E5\u5236\u7A7A\u8BCD\u300C${m
|
|
172
|
-
matches.push({
|
|
173
|
-
ok: true,
|
|
174
|
-
condition: { kind: "base-air-defense", requiredAirState: airState, requiredCount: count, notes }
|
|
175
|
-
});
|
|
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 } });
|
|
176
199
|
} else if (form.kind === "node-arrival" || form.kind === "reach-after") {
|
|
177
|
-
matches.push({
|
|
178
|
-
ok: true,
|
|
179
|
-
condition: {
|
|
180
|
-
kind: "node-arrival",
|
|
181
|
-
nodeLabel: normalizeNodeLabel(m[1]),
|
|
182
|
-
requiredCount: count,
|
|
183
|
-
notes
|
|
184
|
-
}
|
|
185
|
-
});
|
|
200
|
+
matches.push({ ok: true, condition: { kind: "node-arrival", nodeLabel, ...common } });
|
|
186
201
|
} else if (form.kind === "kill") {
|
|
187
202
|
matches.push({
|
|
188
203
|
ok: true,
|
|
189
|
-
condition: {
|
|
190
|
-
kind: "victory-rank",
|
|
191
|
-
nodeLabel: normalizeNodeLabel(m[1]),
|
|
192
|
-
requiredRank: "A",
|
|
193
|
-
requiredCount: count,
|
|
194
|
-
notes: [...notes, "\u51FB\u7834\u2192\u6309A\u80DC\u8BA1"]
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
} else if (form.kind === "victory-rank") {
|
|
198
|
-
matches.push({
|
|
199
|
-
ok: true,
|
|
200
|
-
condition: {
|
|
201
|
-
kind: "victory-rank",
|
|
202
|
-
nodeLabel: normalizeNodeLabel(m[1]),
|
|
203
|
-
requiredRank: m[2].toUpperCase(),
|
|
204
|
-
requiredCount: count,
|
|
205
|
-
notes
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
} else if (form.kind === "count-first") {
|
|
209
|
-
matches.push({
|
|
210
|
-
ok: true,
|
|
211
|
-
condition: {
|
|
212
|
-
kind: "victory-rank",
|
|
213
|
-
nodeLabel: normalizeNodeLabel(m[1]),
|
|
214
|
-
requiredRank: m[3].toUpperCase(),
|
|
215
|
-
requiredCount: count,
|
|
216
|
-
notes
|
|
217
|
-
}
|
|
204
|
+
condition: { kind: "victory-rank", nodeLabel, requiredRank: "A", ...common, notes: [...notes, "\u51FB\u7834\u2192\u6309A\u80DC\u8BA1"] }
|
|
218
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 } });
|
|
219
208
|
} else {
|
|
220
|
-
const airState = airStateOf(m
|
|
221
|
-
if (airState == null) return { matches: [{ ok: false, reason: `\u672A\u77E5\u5236\u7A7A\u8BCD\u300C${m
|
|
222
|
-
matches.push({
|
|
223
|
-
ok: true,
|
|
224
|
-
condition: {
|
|
225
|
-
kind: "node-air-state",
|
|
226
|
-
nodeLabel: normalizeNodeLabel(m[1]),
|
|
227
|
-
requiredAirState: airState,
|
|
228
|
-
requiredCount: count,
|
|
229
|
-
notes
|
|
230
|
-
}
|
|
231
|
-
});
|
|
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 } });
|
|
232
212
|
}
|
|
233
213
|
rest = rest.slice(m.index + m[0].length);
|
|
234
214
|
}
|
|
235
|
-
return { matches, notes
|
|
215
|
+
return { matches, notes };
|
|
236
216
|
}
|
|
237
217
|
var BUCKET_HEADER = /^(解谜|解密|谜题|削甲|装甲|debuff|gimmick)[::]/;
|
|
238
218
|
var BUCKET_WORDS = { \u89E3\u8C1C: "gimmick", \u89E3\u5BC6: "gimmick", \u8C1C\u9898: "gimmick", gimmick: "gimmick", \u524A\u7532: "debuff", \u88C5\u7532: "debuff", debuff: "debuff" };
|