Merge remote-tracking branch 'origin/sub_desktop_1' into sub_laptop_1

This commit is contained in:
2026-09-09 12:08:55 +09:00
6 changed files with 107 additions and 32 deletions
@@ -301,6 +301,22 @@ SOURCE_BASIS_NOTE_RE = re.compile(r"([\d,]*\.?\d*)\s*개소\s*사용\s*당")
SOURCE_NOTE_LOOKAHEAD = 8
#: ⚠⚠ **「인」은 품의 단위이지 공종 밑수가 아니다**(2026-09-09 원문 대조로 넷이 오독으로 드러남).
#: 8-6-2 드론방제·8-6-3 지상방제 「(단위 : 인)」 — 그 「인」은 **소요인력**이고 공종 밑수는
#: ha 다. 13-2-4 야면석 채집 「(단위: 인 당)」 — 표 안이 **㎡당·㎥당** 두 줄이다.
#: ⇒ **원문에 「<숫자>인당」이 그대로 있을 때만** 밑수로 인정한다.
#: ⚠ **넓게 「인」을 통째로 버리면 2-2-5 천공기가 사라진다** — 그 표는 셀 안에 「천공인부
#: **1인당** 1대」로 숫자가 붙어 있다. 그래서 「숫자가 붙었나」로 좁게 가른다.
PERSON_UNITS = {"", ""}
def person_basis_ok(raw_quantity: str | None, unit: str | None) -> bool:
"""「인」 계열 밑수를 인정할 것인가 — **숫자가 붙어 있을 때만** 참."""
if unit not in PERSON_UNITS:
return True
return bool((raw_quantity or "").strip())
def basis_from_source(lines: list[str], line_no: int) -> tuple[float | None, str | None]:
"""표 바로 위 본문에서 밑수를 읽는다. 못 찾으면 `(None, None)` — 1 로 단정하지 않는다.
@@ -315,6 +331,8 @@ def basis_from_source(lines: list[str], line_no: int) -> tuple[float | None, str
break # 앞 표에 닿았다 — 그 위는 남의 밑수다
if m := SOURCE_BASIS_RATIO_RE.search(text):
raw = (m.group(1) or "").replace(",", "")
if not person_basis_ok(raw, m.group(2)):
continue # 「인」에 숫자가 안 붙었다 — 품의 단위이지 밑수가 아니다
try:
quantity = float(raw) if raw else 1.0
except ValueError:
@@ -324,6 +342,8 @@ def basis_from_source(lines: list[str], line_no: int) -> tuple[float | None, str
unit = m.group("u1") or m.group("u2")
raw = (m.group(1) if m.group("u1") else m.group(3)) or ""
raw = raw.replace(",", "")
if not person_basis_ok(raw, unit):
continue # 위와 같음 — 「(단위 : 인)」·「(단위: 인 당)」은 밑수가 아니다
try:
quantity = float(raw) if raw else 1.0
except ValueError:
@@ -347,14 +367,29 @@ def basis_from_source(lines: list[str], line_no: int) -> tuple[float | None, str
def detect_basis(table: dict[str, Any]) -> tuple[float | None, str | None]:
"""「100㎥당」 같은 밑수. 없으면 `(None, None)` — 단위당 1 로 단정하지 않는다."""
hay = " ".join(norm(h) for h in table.get("headers", []))
hay += " " + " ".join(norm(c) for r in table.get("rows", [])[:2] for c in r)
if m := BASIS_RE.search(hay):
try:
return float(m.group(1).replace(",", "")), m.group(2)
except ValueError:
return None, m.group(2)
"""「100㎥당」 같은 밑수. 없으면 `(None, None)` — 단위당 1 로 단정하지 않는다.
⚠⚠ **칸 하나 안에서만 본다**(2026-09-09). 여러 칸을 이어 붙여 보면 **앞 칸의 값**과
**뒤 칸의 단위**가 붙어 없는 밑수가 생긴다 — 13-2-4 야면석 채집이 그랬다:
행 ① 인 부 | ㎡당 | 0.11 | 0.17 | 0.22 | 0.28 | **0.36**
행 ② **㎥당** | 0.60 | …
이어 붙이면 「0.36 ㎥당」이 되어 **밑수 0.36㎥** 라는 값이 선다(원문에 없는 값).
⚠ 그 표는 **㎡당·㎥당 두 줄**이라 애초에 하나로 못 정한다 — 「미확보」가 정직하다.
⚠ **「인」은 여기서도 숫자가 붙어야 인정한다** — `BASIS_RE` 가 숫자를 요구하므로
2-2-5 「천공인부 **1인당** 1대」는 그대로 서고 「(단위 : 인)」은 안 선다.
"""
cells = [norm(h) for h in table.get("headers", []) or []]
cells += [norm(c) for r in (table.get("rows", []) or [])[:2] for c in r]
for cell in cells:
if not cell:
continue
if m := BASIS_RE.search(cell):
if not person_basis_ok(m.group(1), m.group(2)):
continue
try:
return float(m.group(1).replace(",", "")), m.group(2)
except ValueError:
return None, m.group(2)
return None, None