백테스팅 분석결과 레포트 출력

This commit is contained in:
Macbook
2026-06-03 12:14:08 +09:00
parent c228f18c25
commit ee7b1a6123
11 changed files with 1207 additions and 15 deletions
+91
View File
@@ -0,0 +1,91 @@
/**
* 잘못된 인코딩으로 깨진 한글 문자열 복구 (레포트·전략명 등)
* — UTF-8 바이트가 Latin-1 으로 해석된 경우(3ë ¶ → 3분, 1시간 → 1시간)
*/
/** Latin-1 바이트 → UTF-8 재해석 */
function repairFromLatin1Bytes(text: string): string | null {
try {
const bytes = Uint8Array.from(text, c => c.charCodeAt(0) & 0xff);
const repaired = new TextDecoder('utf-8', { fatal: false }).decode(bytes);
if (!repaired || repaired.includes('\uFFFD')) return null;
if (/[\uAC00-\uD7A3]/.test(repaired)) return repaired;
} catch {
/* ignore */
}
return null;
}
/** DB·레거시에서 자주 보이는 깨진 패턴 */
function repairKnownMojibakePatterns(text: string): string {
let out = text;
const rules: [RegExp, string][] = [
[/CC\s+l(?=\s*[0-9])/gi, 'CCI'],
[/1시간/gi, '1시간'],
[/시간/gi, '시간'],
[/([0-9]+)\s*ë\s*¶/gi, '$1분'],
[/ë\s*¶/gi, '분'],
[/시/gi, '시'],
[/ê°„/gi, '간'],
[/é/g, 'é'],
[/Ã /g, ' '],
];
for (const [re, rep] of rules) {
out = out.replace(re, rep);
}
return out;
}
function hasHangul(text: string): boolean {
return /[\uAC00-\uD7A3]/.test(text);
}
function hasMojibakeMarkers(text: string): boolean {
return /[ìíîïðñòóôõö÷øùúûüÿàáâãäåæçèêë]/.test(text)
|| /ë\s*¶/.test(text)
|| /시/.test(text)
|| /ê°„/.test(text)
|| /Ã.|Â./.test(text);
}
function looksLikeBrokenKorean(text: string): boolean {
if (!text) return false;
if (hasHangul(text) && hasMojibakeMarkers(text)) return true;
if (hasMojibakeMarkers(text) && !hasHangul(text)) return true;
return false;
}
function normalizeReportText(text: string): string {
return text
.replace(/,{2,}/g, ', ')
.replace(/\s*,\s*,+/g, ', ')
.replace(/,\s*,/g, ', ')
.replace(/\s{2,}/g, ' ')
.trim();
}
/**
* 깨진 한글·시간봉 표기 복구. 이미 정상 UTF-8 이면 그대로 반환.
*/
export function repairUtf8Mojibake(text: string): string {
if (!text) return text;
let result = text;
if (hasMojibakeMarkers(result)) {
result = repairKnownMojibakePatterns(result);
}
if (looksLikeBrokenKorean(text)) {
const fromBytes = repairFromLatin1Bytes(text);
if (fromBytes && hasHangul(fromBytes) && !looksLikeBrokenKorean(fromBytes)) {
result = fromBytes;
}
}
if (hasMojibakeMarkers(result)) {
result = repairKnownMojibakePatterns(result);
}
return normalizeReportText(result);
}