From f4e142b38a583271718205bab66cf2368c06f70f Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sat, 19 Sep 2026 09:18:43 +0900 Subject: [PATCH] =?UTF-8?q?knowledge(=ED=92=88=EC=85=88md):=20=EB=8F=84?= =?UTF-8?q?=EA=B5=AC=20=E3=80=8C=EA=B8=80=EC=9E=90=EC=B8=B5=20=EB=B6=99?= =?UTF-8?q?=EC=9D=80=20=EC=88=98=E3=80=8D=20=EC=A3=BC=EC=84=9D=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20PDF=20=EC=AA=BD=20=EB=B6=99=EC=9D=80=20=EC=88=98=20?= =?UTF-8?q?=EA=B0=80=EB=A6=84=20=C2=B7=20=EC=8B=9C=ED=97=98=20=ED=95=98?= =?UTF-8?q?=EB=82=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - md 주석 에 적힌 글자열만 PDF 쪽에서 가름(자간 벌린 수의 거꾸로) - PDF 에 있고 왼쪽이 오른쪽에서 공백만 뺀 것일 때만 · 기계검사 칸 「글자층 붙은 수 N곳」 · 못 쓰면 불통 - 전후 대조: 기계검사 칸 있는 md 518개 판정 바뀜 0 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01V1MKKZKpUHTPKb513FneU8 --- .../original/_pipeline/pum_md_tool.py | 44 ++++++++++++++----- resources/tester/test_pum_md_tool.py | 26 +++++++++++ 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/resources/knowledge/original/_pipeline/pum_md_tool.py b/resources/knowledge/original/_pipeline/pum_md_tool.py index 67808966..bce72caf 100644 --- a/resources/knowledge/original/_pipeline/pum_md_tool.py +++ b/resources/knowledge/original/_pipeline/pum_md_tool.py @@ -494,20 +494,35 @@ def compare(pdf: list[tuple[int, str]], md: list[tuple[int, str]]) -> dict: #: 짐작으로 붙이지 않고 **적힌 글자열만** PDF 쪽에서 붙여 셈 · 오른쪽은 왼쪽에서 공백만 뺀 것이어야 함. _SPACED = re.compile(r"", re.S) _SPACED_PAIR = re.compile(r"「([^」]+)」\s*→\s*「([^」]+)」") +#: 글자층 붙은 수 — 자간 벌린 수의 거꾸로. 글자층이 여러 칸 값을 공백 없이 한 덩이로 담은 것 +#: md 주석 `` · 왼쪽은 오른쪽에서 공백만 뺀 것이어야 함. +_GLUED = re.compile(r"", re.S) + + +def _rewrite(pdf: list[tuple[int, str]], body: str, mark: re.Pattern, ok): + """(PDF 줄, 고친 곳 수, 못 쓴 글자열) — md 주석에 적힌 글자열만 PDF 줄에서 바꿈(PDF 에 있고 ok 일 때만).""" + done, bad = 0, [] + for block in mark.findall(body): + for old, new in _SPACED_PAIR.findall(block): + hits = sum(line.count(old) for _, line in pdf) + if not hits or not ok(old, new): + bad.append(old) + continue + pdf = [(at, line.replace(old, new)) for at, line in pdf] + done += hits + return pdf, done, bad def join_spaced_numbers(pdf: list[tuple[int, str]], body: str): """(PDF 줄, 붙인 곳 수, 못 쓴 글자열) — md 주석에 적힌 자간 벌린 수만 PDF 줄에서 붙임.""" - joined, bad = 0, [] - for block in _SPACED.findall(body): - for spaced, tight in _SPACED_PAIR.findall(block): - hits = sum(line.count(spaced) for _, line in pdf) - if not hits or re.sub(r"\s", "", spaced) != tight: - bad.append(spaced) - continue - pdf = [(at, line.replace(spaced, tight)) for at, line in pdf] - joined += hits - return pdf, joined, bad + return _rewrite(pdf, body, _SPACED, lambda spaced, tight: re.sub(r"\s", "", spaced) == tight) + + +def split_glued_numbers(pdf: list[tuple[int, str]], body: str): + """(PDF 줄, 가른 곳 수, 못 쓴 글자열) — md 주석에 적힌 글자층 붙은 수만 PDF 줄에서 가름.""" + return _rewrite( + pdf, body, _GLUED, lambda glued, split: glued != split and re.sub(r"\s", "", split) == glued + ) def verdict(result: dict) -> str: @@ -518,7 +533,8 @@ def verdict(result: dict) -> str: sum(result["char_extra"].values()), ) joined, bad = result.get("spaced", (0, [])) - word = "통과" if not any(counts) and not bad else "불통" + split, bad_glued = result.get("glued", (0, [])) + word = "통과" if not any(counts) and not bad and not bad_glued else "불통" line = ( f"{word} · ①수 결손 {counts[0]} 허구 {counts[1]} · ②글자 빠짐 {counts[2]} 더함 {counts[3]}" ) @@ -530,6 +546,10 @@ def verdict(result: dict) -> str: line += f" · 자간 벌린 수 {joined}곳" if bad: line += " · 자간 벌린 수 못 씀 " + " ".join(f"「{s}」" for s in bad) + if split: # ③ 이 그림으로 칸마다 값을 꼭 보게 + line += f" · 글자층 붙은 수 {split}곳" + if bad_glued: + line += " · 글자층 붙은 수 못 씀 " + " ".join(f"「{s}」" for s in bad_glued) return line @@ -555,8 +575,10 @@ def check_file(path: Path) -> tuple[dict, str]: with pymupdf.open(book["pdf"]) as doc: pdf = pdf_lines(doc, read_head(path), book["footer"]) pdf, joined, bad = join_spaced_numbers(pdf, body) + pdf, split, bad_glued = split_glued_numbers(pdf, body) result = compare(pdf, md_lines(body)) result["spaced"] = (joined, bad) + result["glued"] = (split, bad_glued) return result, verdict(result) diff --git a/resources/tester/test_pum_md_tool.py b/resources/tester/test_pum_md_tool.py index bb5664bd..99e8321c 100644 --- a/resources/tester/test_pum_md_tool.py +++ b/resources/tester/test_pum_md_tool.py @@ -250,3 +250,29 @@ def test_spaced_numbers_marker_joins_only_listed_strings(): assert bad == ["9 . 9", "1 . 3"] result["spaced"] = (0, bad) assert tool.verdict(result).startswith("불통") + + +def test_glued_numbers_marker_splits_only_listed_strings(): + """md 주석 「글자층 붙은 수」 에 적힌 글자열만 PDF 쪽에서 갈라 셈 · 없거나 공백만 뺀 것이 아니면 불통.""" + pdf = [(834, "Foundation Chipping 특별인부 인/㎡ 0.3350.3350.335"), (834, "0.3350 따로")] + body = ( + "Foundation Chipping 특별인부 인/㎡ 0.335 0.335 0.335\n0.3350 따로\n" + "" + ) + before = tool.compare(pdf, tool.md_lines(body)) + assert before["num_missing"] and before["num_extra"] # 주석 없으면 ① 결손·허구 + split, count, bad = tool.split_glued_numbers(pdf, body) + assert count == 1 and not bad + assert split[1] == (834, "0.3350 따로") # 적히지 않은 곳은 그대로 + result = tool.compare(split, tool.md_lines(body)) + result["glued"] = (count, bad) + line = tool.verdict(result) + assert line.startswith("통과") and "글자층 붙은 수 1곳" in line, line + # PDF 에 없는 글자열 · 공백만 뺀 것이 아닌 짝 · 가르지 않은 짝은 못 씀 → 불통 + _, _, bad = tool.split_glued_numbers( + pdf, + "", + ) + assert bad == ["9.99.9", "0.3350.335", "0.3350"] + result["glued"] = (0, bad) + assert tool.verdict(result).startswith("불통")