()
| 29 | |
| 30 | |
| 31 | def main(): |
| 32 | with open(INDEX_PATH) as f: |
| 33 | entries = json.load(f).get("entries", []) |
| 34 | |
| 35 | missing = [e for e in entries if not fulltext_exists(e)] |
| 36 | print(f"Missing entries: {len(missing)}") |
| 37 | |
| 38 | unmatched_files = sorted(UNMATCHED_DIR.glob("*.md")) |
| 39 | print(f"Unmatched files: {len(unmatched_files)}") |
| 40 | |
| 41 | recovered = 0 |
| 42 | used_entries = set() |
| 43 | |
| 44 | for f_path in unmatched_files: |
| 45 | text = f_path.read_text(encoding="utf-8")[:3000] |
| 46 | um_title = extract_actual_title(text) or f_path.stem |
| 47 | |
| 48 | best_sim_raw = 0 |
| 49 | best_sim_norm = 0 |
| 50 | best_entry = None |
| 51 | |
| 52 | for e in missing: |
| 53 | if e["id"] in used_entries: |
| 54 | continue |
| 55 | t = e.get("title", {}) |
| 56 | zh = t.get("zh", "") if isinstance(t, dict) else str(t) |
| 57 | |
| 58 | sim_raw = _title_similarity(um_title, zh) |
| 59 | sim_norm = _title_similarity(strip_year_revision(um_title), |
| 60 | strip_year_revision(zh)) |
| 61 | sim = max(sim_raw, sim_norm) |
| 62 | if sim > best_sim_raw: |
| 63 | best_sim_raw = sim |
| 64 | best_entry = e |
| 65 | |
| 66 | if best_sim_raw >= 0.7 and best_entry: |
| 67 | slug = best_entry.get("slug", "") |
| 68 | if not slug: |
| 69 | continue |
| 70 | dest = FULLTEXT_DIR / f"{slug}.zh.md" |
| 71 | shutil.copy2(f_path, dest) |
| 72 | f_path.unlink() |
| 73 | used_entries.add(best_entry["id"]) |
| 74 | recovered += 1 |
| 75 | |
| 76 | t = best_entry.get("title", {}) |
| 77 | zh = t.get("zh", "") if isinstance(t, dict) else str(t) |
| 78 | print(f" {best_sim_raw:.2f} [{f_path.name[:20]}] -> {slug}") |
| 79 | print(f" UM: {um_title[:60]}") |
| 80 | print(f" IX: {zh[:60]}") |
| 81 | |
| 82 | print(f"\nRecovered: {recovered}") |
| 83 | |
| 84 | |
| 85 | if __name__ == "__main__": |
no test coverage detected