feat(identity): weighted evidence table, sequel numbers, generic-name guard (ID-2)
Configurable DEFAULT_MATCH_WEIGHTS; Chinese/English names both count and corroborate; Chapter/Part/第N章 sequel conflicts reject; missing season penalised; category words and single-word aliases colliding in the pool cannot confirm alone; alias-only hits need year or second-script support; same-level ties broken by exact year then matched name scripts. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
51e0032d14
commit
f6ec993b5f
5 files changed
+527
-34
No files matched your search
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* 续作 / 章节 / Part 序号(ID-2):`Chapter III`、`Part Two`、`Vol. 2`、`第3章`、`第三章`、`Ⅲ`。
|
||||
* 只认显式关键词或罗马数字符号,不把片名末尾的普通数字当序号(`Blade Runner 2049`、`Apollo 13`)。
|
||||
* 季号不在这里(季由解析器单独给出)。
|
||||
*/
|
||||
import { cnToInt } from "../release-parser/cn-number.ts";
|
||||
|
||||
const WORD_NUM: Record<string, number> = {
|
||||
one: 1,
|
||||
two: 2,
|
||||
three: 3,
|
||||
four: 4,
|
||||
five: 5,
|
||||
six: 6,
|
||||
seven: 7,
|
||||
eight: 8,
|
||||
nine: 9,
|
||||
ten: 10,
|
||||
first: 1,
|
||||
second: 2,
|
||||
third: 3,
|
||||
fourth: 4,
|
||||
final: -1,
|
||||
};
|
||||
const ROMAN: Record<string, number> = { i: 1, ii: 2, iii: 3, iv: 4, v: 5, vi: 6, vii: 7, viii: 8, ix: 9, x: 10 };
|
||||
const ROMAN_CHAR: Record<string, number> = {
|
||||
Ⅰ: 1,
|
||||
Ⅱ: 2,
|
||||
Ⅲ: 3,
|
||||
Ⅳ: 4,
|
||||
Ⅴ: 5,
|
||||
Ⅵ: 6,
|
||||
Ⅶ: 7,
|
||||
Ⅷ: 8,
|
||||
Ⅸ: 9,
|
||||
Ⅹ: 10,
|
||||
};
|
||||
|
||||
function toNum(tok: string): number | undefined {
|
||||
const t = tok.toLowerCase();
|
||||
if (/^\d{1,2}$/.test(t)) return Number(t);
|
||||
if (t in ROMAN) return ROMAN[t];
|
||||
if (t in WORD_NUM) return WORD_NUM[t]! > 0 ? WORD_NUM[t] : undefined;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function sequelNumbers(title: string): number[] {
|
||||
if (!title) return [];
|
||||
const out = new Set<number>();
|
||||
const s = title.replace(/[ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ]/g, (c) => ` ${ROMAN_CHAR[c]} `);
|
||||
for (const m of s.matchAll(/\b(?:chapter|part|vol(?:ume)?)\b\.?\s*[::-]?\s*([0-9]{1,2}|[ivx]{1,4}|[a-z]+)\b/giu)) {
|
||||
const n = toNum(m[1]!);
|
||||
if (n !== undefined) out.add(n);
|
||||
}
|
||||
for (const m of s.matchAll(/第\s*([0-9]{1,2}|[一二三四五六七八九十]{1,3})\s*章/gu)) {
|
||||
const n = /^\d+$/.test(m[1]!) ? Number(m[1]) : cnToInt(m[1]!);
|
||||
if (n !== undefined) out.add(n);
|
||||
}
|
||||
return [...out];
|
||||
}
|
||||
Reference in new issue
Block a user