MCPcopy Create free account
hub / github.com/Qinbf/groundmap / hardNumericTokens

Function hardNumericTokens

tools/debug-console/lib/verify-citations.ts:105–152  ·  view source on GitHub ↗
(s: string)

Source from the content-addressed store, hash-verified

103const MON_BARE = "january|february|march|april|june|july|august|september|october|november|december";
104
105function hardNumericTokens(s: string): NumTokens {
106 let t = normNum(s);
107 const strong = new Set<string>();
108 const years = new Set<string>();
109 const blank = (n: number) => " ".repeat(n);
110 // 1) 中文/数字日期 → date:YYYY-M(分隔符不含 '.',小数另算;月份须 1-12;
111 // 分隔后非数字边界,避免 '2025-1234'(电话) 被截成 '2025-12')
112 t = t.replace(/(\d{4})[-/年](\d{1,2})(?!\d)/g, (full, y, mo) => {
113 const m = parseInt(mo, 10);
114 if (m >= 1 && m <= 12) {
115 strong.add(`date:${y}-${m}`);
116 return blank(full.length);
117 }
118 return full; // 非法月(如 2025-99)不当日期
119 });
120 // 2) 英文月份日期 → date:YYYY-M(跨语言对齐)。带日号:任意月形;裸月-年:只认全称
121 t = t.replace(new RegExp(`\\b(${MON_RE})\\.?\\s+(\\d{1,2})(?:st|nd|rd|th)?,?\\s+(\\d{4})\\b`, "g"), (full, mon, _d, y) => {
122 strong.add(`date:${y}-${MONTHS[mon.slice(0, 3)]}`);
123 return blank(full.length);
124 });
125 t = t.replace(new RegExp(`\\b(\\d{1,2})(?:st|nd|rd|th)?\\s+(${MON_RE})\\.?,?\\s+(\\d{4})\\b`, "g"), (full, _d, mon, y) => {
126 strong.add(`date:${y}-${MONTHS[mon.slice(0, 3)]}`);
127 return blank(full.length);
128 });
129 t = t.replace(new RegExp(`\\b(${MON_BARE})\\s+(\\d{4})\\b`, "g"), (full, mon, y) => {
130 strong.add(`date:${y}-${MONTHS[mon.slice(0, 3)]}`);
131 return blank(full.length);
132 });
133 // 3) 百分比 → pct:val(带符号)。前缀避免与同值普通数 / 量级撞
134 t = t.replace(/([+\-﹣-]?)\s*(\d+(?:\.\d+)?)\s*%/g, (full, sign, v) => {
135 strong.add(`pct:${/[\-﹣-]/.test(sign) ? "-" : ""}${parseFloat(v)}`);
136 return blank(full.length);
137 });
138 // 4) 量级 万/亿/万亿 → 纯数值串(不加前缀,与 '2,630,000,000,000' 同值互认)
139 t = t.replace(/(\d+(?:\.\d+)?)\s*(万亿|亿|万)/g, (full, v, u) => {
140 const mult = u === "万亿" ? 1e12 : u === "亿" ? 1e8 : 1e4;
141 strong.add(String(Math.round(parseFloat(v) * mult)));
142 return blank(full.length);
143 });
144 // 5) 年份 → years(裸 4 位年份不算 strong;挖空以免下一步当普通数收割)
145 t = t.replace(/\b(?:19|20)\d{2}\b/g, (full) => {
146 years.add(full);
147 return blank(full.length);
148 });
149 // 6) 剩余通用数字(≥3 位整数 / 小数)→ 原值串(日期/百分比/量级/年份均已挖空,无裸尾数泄漏)
150 for (const m of t.matchAll(/\d+\.\d+|\d{3,}/g)) strong.add(m[0]);
151 return { strong, years };
152}
153
154function matchHits(claim: NumTokens, block: NumTokens): { strongHit: number; yearHit: number } {
155 let strongHit = 0;

Callers 1

verifyBlockCitationsFunction · 0.85

Calls 2

normNumFunction · 0.85
blankFunction · 0.85

Tested by

no test coverage detected