feat(z01): 공종 축 갈래마다 한 줄 — 교목굴취(나무높이) 9갈래가 한 줄에 뭉쳐 어느 높이 값인지 못 집던 것
- 줄 = 갈래(일위대가가 갈래마다 다름) · 산림 365공종 → 627줄 · 건설은 갈래 키가 비어 997 그대로 - 줄 열쇠 = 공종 열쇠#갈래 키(FW-00105#1.1∼1.5 · B08·B09 코드#갈래 꼴) · 갈래 키 글자는 마스터 것 그대로(조립 두 벌 금지) - 공종 열쇠는 @key 로 함께 보냄 — 거르기(부문·줄 구실)와 stats.work_items 는 공종 단위 - 칸: 갈래 키 목록(variant_keys) → 갈래 하나(variant) · 이름표 공종 축 두 표의 열도 같이 바꿈(묵은 열 시험) - 화면 코드는 그대로 — 산림 단추 627 · 교목굴취 찾기 10줄(9갈래 + 근원직경) · 2.6∼3.0 칸 집힘 - 시험: 교목굴취 9갈래 차례·열쇠 · 갈래 없는 공종은 # 없는 한 줄 · 갈래 이름으로 찾힘 · 앞 시험 수(365 → 627 · 발파암 3 → 5 · 가짜 자료 두 줄) 맞춤 · Z01·이름표 시험 105 통과 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"""Z01 공종 축 — 산림·건설 두 kind 를 기초단가와 **같은 계약**으로(2026-09-17 브레인 · PLAN_공종축 8-4).
|
||||
|
||||
줄 = **품셈 표가 붙은 마디**(`axis_policy.json` `flat_list_filter: pum_tables > 0` — 잎으로 거르면 부모에 붙은 표가 안 뜸) ·
|
||||
갈래(`variant_keys`)는 칸으로(편 수 = `stats.units`).
|
||||
갈래(`variant_keys`)마다 한 줄로 폄 — 줄 수 = 편 수(`stats.units`) · 공종 수 = `stats.work_items`.
|
||||
이름 = 뿌리부터 전체 경로(「토공 › 토사깍기 › 기계」 · 건설은 부문부터) — 잎 이름만으론 겹침.
|
||||
계산 규칙 = 표 수준 `rules`(부모 마디 choose_one · sum_steps) + 줄 칸 `rule`·`step_weight`
|
||||
— 빠지면 발파암(절취 0.1 + 깍기 0.9 + 집토 1) 금액이 틀어짐.
|
||||
@@ -86,20 +86,25 @@ def base_rows(kind: str) -> list[dict[str, Any]]:
|
||||
(s["weight"] for s in parent.get("steps") or [] if s["code"] == item["work_item_code"]),
|
||||
None,
|
||||
)
|
||||
rows.append(
|
||||
{
|
||||
"@id": _key(item),
|
||||
"@source": name,
|
||||
"work_item_code": item["work_item_code"], # 목차 코드 — 열쇠 아님, 칸으로만
|
||||
"number": item["number"],
|
||||
"name": _path(item, by),
|
||||
"variant_keys": item.get("variant_keys") or [],
|
||||
"pum_tables": [t["pum_table_id"] for t in item["tables"]],
|
||||
"rule": parent.get("parent_mode"),
|
||||
"step_weight": weight,
|
||||
"effective_date": d.get("pum_edition") or d.get("effective_date"),
|
||||
}
|
||||
)
|
||||
key = _key(item)
|
||||
# 갈래마다 한 줄 — 일위대가가 갈래마다 달라 집는 단위가 갈래임(교목굴취 나무높이 9 · 2026-09-17 브레인 ③).
|
||||
# 열쇠 = 공종 열쇠#갈래 키(B08·B09 `코드#갈래` 꼴) · 갈래 키 글자는 마스터 것 그대로(조립 두 벌 금지).
|
||||
for variant in item.get("variant_keys") or [None]:
|
||||
rows.append(
|
||||
{
|
||||
"@id": f"{key}#{variant}" if variant else key,
|
||||
"@key": key, # 공종 열쇠 — 거르기·줄 수는 공종 단위로
|
||||
"@source": name,
|
||||
"work_item_code": item["work_item_code"], # 목차 코드 — 열쇠 아님, 칸으로만
|
||||
"number": item["number"],
|
||||
"name": _path(item, by),
|
||||
"variant": variant,
|
||||
"pum_tables": [t["pum_table_id"] for t in item["tables"]],
|
||||
"rule": parent.get("parent_mode"),
|
||||
"step_weight": weight,
|
||||
"effective_date": d.get("pum_edition") or d.get("effective_date"),
|
||||
}
|
||||
)
|
||||
return rows
|
||||
|
||||
|
||||
@@ -175,7 +180,7 @@ def filters(kind: str, rows: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||
for key in FILTER_KEYS:
|
||||
counts: dict[str, int] = {}
|
||||
for row in rows:
|
||||
value = facets.get(row["@id"], {}).get(key, ALL)
|
||||
value = facets.get(row["@key"], {}).get(key, ALL)
|
||||
counts[value] = counts.get(value, 0) + 1
|
||||
values = [v for v in counts if v != ALL]
|
||||
if len(values) < 2:
|
||||
@@ -203,7 +208,7 @@ def apply_filters(
|
||||
for key in FILTER_KEYS:
|
||||
value = picked.get(key, defaults.get(key, ALL))
|
||||
if value != ALL:
|
||||
rows = [r for r in rows if facets.get(r["@id"], {}).get(key) == value]
|
||||
rows = [r for r in rows if facets.get(r["@key"], {}).get(key) == value]
|
||||
return rows
|
||||
|
||||
|
||||
@@ -214,7 +219,7 @@ def extra(kind: str) -> dict[str, Any]:
|
||||
"filters": filters(kind, rows),
|
||||
"rules": rules(kind),
|
||||
"stats": {
|
||||
"work_items": len(rows),
|
||||
"units": sum(max(1, len(r["variant_keys"])) for r in rows),
|
||||
"work_items": len({r["@key"] for r in rows}),
|
||||
"units": len(rows),
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user