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]>
61 lines
1.7 KiB
TypeScript
61 lines
1.7 KiB
TypeScript
/**
|
||
* 续作 / 章节 / 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];
|
||
}
|