// 翻訳メモリの点検。用語の一貫性・文体・取りこぼしを機械的に見る。
import fs from 'fs';

const tm = JSON.parse(fs.readFileSync('tm.json', 'utf8'));
const e = Object.entries(tm);
console.log(`件数 ${e.length}`);

const politeRe = /(です|ます)[。！？]?$/;
const plainRe = /(だ|た|る|い|ぬ|う)[。！？]$/;
const polite = e.filter(([, v]) => politeRe.test(v)).length;
const plain = e.filter(([, v]) => plainRe.test(v)).length;
console.log(`文体      敬体 ${polite} / 常体 ${plain}  (敬体 ${(polite / (polite + plain) * 100).toFixed(0)}%)`);
console.log(`複数形 s  ${e.filter(([, v]) => /[ぁ-んァ-ヶ一-龥ー](?:es|s)\b/.test(v)).length}`);
console.log(`伏せ字残  ${e.filter(([, v]) => /[⟦［[〈《【〔][A-Z]{1,3}[⟧］\]〉》】〕]/.test(v)).length}`);
console.log(`未翻訳    ${e.filter(([, v]) => !/[ぁ-んァ-ヶ一-龥]/.test(v)).length}`);
console.log(`同語反復  ${e.filter(([, v]) => /(.{4,30}?)\1{2,}/.test(v)).length}`);

// 原文より極端に長い／短い訳は、抜けや暴走の兆候
const ratio = e.map(([k, v]) => [k, v, v.length / Math.max(1, k.length)]);
const tooShort = ratio.filter(([, , r]) => r < 0.18);
const tooLong = ratio.filter(([, , r]) => r > 1.4);
console.log(`短すぎる  ${tooShort.length}   長すぎる  ${tooLong.length}`);
tooShort.slice(0, 3).forEach(([k, v]) => console.log(`   短: ${JSON.stringify(k.slice(0, 60))} -> ${JSON.stringify(v.slice(0, 40))}`));
tooLong.slice(0, 3).forEach(([k, v]) => console.log(`   長: ${JSON.stringify(k.slice(0, 60))} -> ${JSON.stringify(v.slice(0, 60))}`));

console.log('\n用語の一貫性（原文に出た件数のうち、指定訳が訳文に入っている割合）');
const TERMS = [
  ['Guild', 'ギルド'], ['chronicle', '年代記'], ['Roll of Honour', '名誉録'],
  ['Mereward', 'メアワード'], ['Lich', 'リッチ'], ['warden', '守番'],
  ['Maw', '大口'], ['prestige', '名誉点'], ['bestiary', '獣譜'],
  ['Master Pell', 'ペル親方'], ['Old Hesper', '老ヘスパー'],
  ['clean stroke', '清き一撃'], ['Mourning Vale', '喪の谷'],
];
for (const [en, ja] of TERMS) {
  const re = new RegExp('\\b' + en.replace(/ /g, '\\s+') + '\\b', 'i');
  const hits = e.filter(([k]) => re.test(k));
  if (!hits.length) { console.log(`  ${en.padEnd(16)} 出現なし`); continue; }
  const ok = hits.filter(([, v]) => v.includes(ja)).length;
  const pct = (ok / hits.length * 100).toFixed(0);
  console.log(`  ${en.padEnd(16)} ${String(hits.length).padStart(4)} 件中 ${String(ok).padStart(4)} 件 (${pct}%) 「${ja}」`);
  if (ok < hits.length) {
    hits.filter(([, v]) => !v.includes(ja)).slice(0, 2)
      .forEach(([k, v]) => console.log(`      × ${v.slice(0, 72)}`));
  }
}
