feat(B09): 뭉친 이름+갈래 열 표 읽기 — 돌쌓기 계열 성립
메인이 `reference` 오판 41건을 되살려(bc4b6837) 돌쌓기(장비)가 마스터에
들어왔으나, 그 표는 **이름도 값도 뭉쳐 오고 열이 규격 갈래**인 또 다른 모양이라
여전히 안 섰음 (「석공 보통인부 | 0.09 0.05 | 0.08 0.04 | 0.07 0.03」)
- 뭉친 이름·값을 갈래 열에 짝지어 읽음. 개수가 어긋나면 표째 버림
- 「굴착기+부착용 집게」는 **두 기종 조합**으로 보아 같은 시간을 둘 다 붙임
(TODO(미결) 해석 잠정 — 사용자 확인 대기)
- 규격이 **옆 칸**에 있고 갈래(무한궤도)가 안 적힌 기종은 규격 일치 + 무한궤도
우선으로 잠정 채택. 카탈로그 규격이 범위(0.6∼0.8)면 그 안에 드는지로 판정
- ⚠ 「1.04(1.17)」 괄호값은 **조건 시공 시 대안값**임이 원문에서 확인됨
(13-6-1 [주]② 흡출방지재 시공 시 ( ) 값). 기본은 괄호 밖, 대안값은
`alternative_amount` 로 남겨 화면에 「시공 시 다름」으로 보이게 함
- 라벨 줄 판정을 **모든 칸**으로 — 첫 칸만 보면 기초잡석 12-25 를 라벨 줄로
오해해 표째 가로챘음(그 탓에 기초잡석이 한때 다시 막혔음)
- 갈래 키를 **공백 없는 것**으로 통일(`#보통`), 원문 문구는 이름에 보존
(두 창 합의)
결과: 자원 축 259 → 354, 일위대가 145 → 176
돌쌓기(찰) 35cm이하 58,166.7 / 55cm이하 52,938.7 / 75cm이하 46,892.7 원/㎡
메쌓기·찰쌓기·붙이기 계열도 직경 3갈래로 섬
검증: pytest 184 통과(신규 1). 화면 실측 — 지금 인계 자료에 구조물 줄이 없어
표에는 아직 안 뜸(B08 이 갈래를 골라 보내면 그대로 금액이 섬)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -350,6 +350,24 @@ def parse_amount_expression(cell: str) -> Decimal | None:
|
||||
return Decimal(found.group(1)) * Decimal(found.group(2)) / Decimal(100)
|
||||
|
||||
|
||||
#: 「1.04(1.17)」 — 괄호 밖이 기본, 괄호 안이 **조건 시공 시** 값.
|
||||
#: 근거: 품셈 13-6-1 [주]② 「흡출방지재를 시공하는 경우는 ( )의 값을 적용한다」
|
||||
#: (13-6-2·13-6-3·13-7-1·13-7-2 도 같은 [주]).
|
||||
#: ⚠ **기본은 괄호 밖** — 방지재 시공 여부가 설계 조건에 아직 없다(사용자 확정 대기).
|
||||
#: 괄호 값을 쓰려면 그 조건이 들어와야 하므로, 지금은 값과 함께 **대안값을 남겨** 둔다.
|
||||
_RE_ALTERNATIVE = re.compile(r"^(\d+(?:\.\d+)?)\s*[((](\d+(?:\.\d+)?)[))]$")
|
||||
|
||||
|
||||
def parse_amount_pair(cell: str) -> tuple[Decimal, Decimal | None] | None:
|
||||
"""「1.04(1.17)」 → `(1.04, 1.17)`. 괄호가 없으면 `(값, None)`."""
|
||||
text = _normalize(cell)
|
||||
found = _RE_ALTERNATIVE.match(text)
|
||||
if found:
|
||||
return Decimal(found.group(1)), Decimal(found.group(2))
|
||||
plain = parse_amount(text)
|
||||
return None if plain is None else (plain, None)
|
||||
|
||||
|
||||
def convert_amount(raw: Decimal, *, pum_form: str, basis_quantity: Decimal | None) -> Decimal:
|
||||
"""표 형태에 맞춰 소요량으로 환산한다.
|
||||
|
||||
@@ -383,6 +401,9 @@ class ResourceRow:
|
||||
amount: Decimal
|
||||
amount_unit: str
|
||||
raw_row_index: int
|
||||
#: 조건 시공 시 쓰는 대안값 — 「1.04(1.17)」의 1.17 (품셈 13-6-1 [주]②).
|
||||
#: **기본값은 `amount`(괄호 밖)** 이고 이 값은 화면에 「시공 시 다름」으로 보인다.
|
||||
alternative_amount: Decimal | None = None
|
||||
#: 규격 갈래 — 열이 자원인 표에서 행 이름(「무근구조물」). 없으면 빈 문자열.
|
||||
#: **갈래마다 품이 다르므로 한 일위대가로 뭉치지 않는다.**
|
||||
variant: str = ""
|
||||
@@ -404,6 +425,9 @@ class ResourceRow:
|
||||
"amount_unit": self.amount_unit,
|
||||
"raw_row_index": self.raw_row_index,
|
||||
"variant": self.variant,
|
||||
"alternative_amount": (
|
||||
None if self.alternative_amount is None else str(self.alternative_amount)
|
||||
),
|
||||
"group_ratio_pct": None if self.group_ratio_pct is None else str(self.group_ratio_pct),
|
||||
}
|
||||
|
||||
@@ -523,6 +547,13 @@ def match_table(
|
||||
if match_transposed_table(node, table, catalog, result, basis_quantity, unit):
|
||||
return
|
||||
|
||||
# 「석공 보통인부 | 0.09 0.05 | …」처럼 **이름도 값도 뭉쳐 오고 열이 갈래**인 표
|
||||
# (돌쌓기 13-4 계열). 행-자원으로는 첫 이름조차 안 풀린다.
|
||||
from B09_Estimation.B09_Estimation_ResourceAxis_Transposed import match_packed_rows
|
||||
|
||||
if match_packed_rows(node, table, catalog, result, basis_quantity, unit):
|
||||
return
|
||||
|
||||
for index, row in enumerate(table.get("raw_row", [])):
|
||||
cells = [str(c) for c in row]
|
||||
if not cells:
|
||||
@@ -556,9 +587,13 @@ def match_table(
|
||||
continue
|
||||
|
||||
# 숫자 셀이 없는 행은 자원 줄이 아니다(제목·설명 행) — 목록에 안 올린다.
|
||||
amount_cell = next(
|
||||
(parse_amount(c) for c in value_cells if parse_amount(c) is not None), None
|
||||
)
|
||||
alternative: Decimal | None = None
|
||||
amount_cell = None
|
||||
for cell in value_cells:
|
||||
pair = parse_amount_pair(cell)
|
||||
if pair is not None:
|
||||
amount_cell, alternative = pair
|
||||
break
|
||||
if amount_cell is None:
|
||||
# 「0.2 × 30%」 꼴은 값과 배분율이 한 칸에 있다 — 읽었으면 딱지 배분율은 버린다.
|
||||
expression = next(
|
||||
@@ -638,6 +673,7 @@ def match_table(
|
||||
amount_unit=unit,
|
||||
raw_row_index=index,
|
||||
group_ratio_pct=group_ratio,
|
||||
alternative_amount=alternative,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user