feat(z01,b08): 이름 자간 다듬기·품셈 번호 숫자 정렬·건설 빈 칸 감춤 — 한 글자 낱말뿐인 조각이나 셋 이상 이어진 한 글자 낱말만 붙임(「측 량」→「측량」·「메 붙 임 · 깬 돌」→「메붙임 · 깬돌」 · 「그 외 자재」는 그대로) · 목록 경로 이름과 갈래 다듬은 이름(name_clean)에만 · 원문 이름은 마스터에 그대로 · 열쇠는 번호라 안 흔들림을 시험으로 못박음(다듬기 끈 목록과 열쇠 맞댐 · 장부 새 발급 0) · 품셈 번호 칸은 마디마다 수로 세움(「10-1」이 「2-1」 뒤) · 건설 「단계 무게」는 늘 빈칸이라 감춤(브레인 ⑥ · 서브 훑기)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BW6Jdsh18WPtYUR6THZJqn
This commit is contained in:
@@ -180,10 +180,42 @@ def variant_match(text: str) -> str:
|
||||
return "".join(_TILDES.get(ch, ch) for ch in squeezed)
|
||||
|
||||
|
||||
_SYLLABLE = re.compile(r"^[가-힣]$")
|
||||
_PIECE_GAP = re.compile(r"( [·ㆍ・›] )")
|
||||
|
||||
|
||||
def tidy_spacing(text: str) -> str:
|
||||
"""**자간 공백** 다듬기 — 「측 량」→「측량」 · 「평 규 준 틀」→「평규준틀」 · 「굴 삭 기 (무한궤도)」→「굴삭기 (무한궤도)」.
|
||||
|
||||
한 글자 낱말뿐인 조각이거나, 한 글자 낱말이 **셋 이상** 이어질 때만 붙임 —
|
||||
「그 외 자재」·「호박돌 및 야면석」 같은 진짜 띄어쓰기는 그대로(2026-09-17 서브 훑기 175줄 · 브레인).
|
||||
⚠ 보일 이름만 — 열쇠는 번호라(공종 `FW-…` · 갈래 `#01`) 다듬어도 안 흔들림.
|
||||
"""
|
||||
# 가운뎃점·경로 표시 사이가 한 조각 — 「메 붙 임 · 깬 돌 · 뒷길이 25㎝」 의 「깬 돌」
|
||||
pieces = _PIECE_GAP.split(" ".join(str(text or "").split()))
|
||||
return "".join(piece if n % 2 else _tidy_piece(piece) for n, piece in enumerate(pieces))
|
||||
|
||||
|
||||
def _tidy_piece(text: str) -> str:
|
||||
tokens = text.split(" ")
|
||||
if len(tokens) >= 2 and all(_SYLLABLE.match(t) for t in tokens):
|
||||
return "".join(tokens)
|
||||
out: list[str] = []
|
||||
run: list[str] = []
|
||||
for token in [*tokens, ""]:
|
||||
if token and _SYLLABLE.match(token):
|
||||
run.append(token)
|
||||
continue
|
||||
out.extend(["".join(run)] if len(run) >= 3 else run)
|
||||
run = []
|
||||
if token:
|
||||
out.append(token)
|
||||
return " ".join(out)
|
||||
|
||||
|
||||
def variant_display(text: str) -> str:
|
||||
"""다듬은 갈래 이름 — 자간 공백을 한 칸으로, 물결표를 하나로. 원문은 따로 남긴다."""
|
||||
spaced = " ".join(str(text or "").split())
|
||||
return "".join(_TILDES.get(ch, ch) for ch in spaced)
|
||||
"""다듬은 갈래 이름 — 자간 공백을 붙이고 물결표를 하나로. 원문은 따로 남긴다."""
|
||||
return "".join(_TILDES.get(ch, ch) for ch in tidy_spacing(text))
|
||||
|
||||
|
||||
def format_variant(serial: int) -> str:
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from datetime import date
|
||||
from decimal import Decimal
|
||||
from functools import lru_cache
|
||||
@@ -329,15 +330,21 @@ class SortError(ValueError):
|
||||
"""모르는 열로 세우라 함 — 조용히 원본 차례로 돌아가지 않음(브레인 ④)."""
|
||||
|
||||
|
||||
#: 품셈 번호 꼴(「9-3-2」·「12-17」) — 글자로 세우면 「10-1」이 「2-1」 앞에 섬(서브 훑기 · 브레인).
|
||||
_NUMBER_PATH = re.compile(r"^\d+(?:-\d+)+$")
|
||||
|
||||
|
||||
def _order_key(value: Any) -> tuple:
|
||||
"""섞인 칸도 세움 — 수 먼저, 그 뒤 글자."""
|
||||
"""섞인 칸도 세움 — 수 먼저, 품셈 번호 꼴은 **마디마다 수로**, 그 뒤 글자."""
|
||||
if isinstance(value, bool):
|
||||
return (1, str(value))
|
||||
return (2, str(value))
|
||||
if isinstance(value, (int, float)):
|
||||
return (0, float(value))
|
||||
if isinstance(value, (dict, list)):
|
||||
return (1, json.dumps(value, ensure_ascii=False, default=str))
|
||||
return (1, str(value))
|
||||
return (2, json.dumps(value, ensure_ascii=False, default=str))
|
||||
if isinstance(value, str) and _NUMBER_PATH.match(value):
|
||||
return (1, tuple(int(part) for part in value.split("-")))
|
||||
return (2, str(value))
|
||||
|
||||
|
||||
def _sorted(rows: list[dict[str, Any]], column: str, desc: bool) -> list[dict[str, Any]]:
|
||||
|
||||
@@ -71,6 +71,13 @@ def _path(item: dict[str, Any] | None, by: dict[str, dict]) -> str:
|
||||
return PATH_JOIN.join(reversed(names))
|
||||
|
||||
|
||||
def _shown_path(item: dict[str, Any], by: dict[str, dict]) -> str:
|
||||
"""목록에 보일 경로 — 조각마다 자간 공백 다듬기(「토목부문 › 측 량」→「측량」). 열쇠와 무관."""
|
||||
from B08_Quantity.B08_Quantity_Build_WorkItemMaster_Keys import tidy_spacing
|
||||
|
||||
return PATH_JOIN.join(tidy_spacing(part) for part in _path(item, by).split(PATH_JOIN))
|
||||
|
||||
|
||||
def base_rows(kind: str) -> list[dict[str, Any]]:
|
||||
found = doc(kind)
|
||||
if found is None:
|
||||
@@ -101,7 +108,7 @@ def base_rows(kind: str) -> list[dict[str, Any]]:
|
||||
"@source": name,
|
||||
"work_item_code": item["work_item_code"], # 목차 코드 — 열쇠 아님, 칸으로만
|
||||
"number": item["number"],
|
||||
"name": _path(item, by),
|
||||
"name": _shown_path(item, by), # 자간 공백만 다듬음 — 원문 이름은 마스터에
|
||||
"variant": variant["name"] if variant else None, # 원문 그대로
|
||||
"variant_clean": variant["name_clean"] if variant else None, # 다듬은 것
|
||||
"pum_tables": [t["pum_table_id"] for t in item["tables"]],
|
||||
@@ -156,7 +163,7 @@ def rules(kind: str) -> list[dict[str, Any]]:
|
||||
rule = {
|
||||
"@id": _key(item),
|
||||
"work_item_code": item["work_item_code"],
|
||||
"name": _path(item, by),
|
||||
"name": _shown_path(item, by),
|
||||
"mode": mode,
|
||||
"children": [_key(c) for c in children.get(item["work_item_code"], [])],
|
||||
}
|
||||
|
||||
@@ -1504,8 +1504,8 @@
|
||||
"key": "step_weight",
|
||||
"name_ko": "단계 무게",
|
||||
"unit": "",
|
||||
"visible": true,
|
||||
"note": "`sum_steps` 일 때만 — 건설은 아직 합산형 선언 없음."
|
||||
"visible": false,
|
||||
"note": "`sum_steps` 일 때만 — 건설은 아직 합산형 선언이 없어 늘 빈칸이라 감춤(선언이 서면 보이게 할 것)."
|
||||
},
|
||||
{
|
||||
"key": "link",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"schema_version": "1.0",
|
||||
"dataset_id": "data_work_item_master_manifest",
|
||||
"generated_at": "2026-09-17T18:25:05+09:00",
|
||||
"generated_at": "2026-09-17T18:52:20+09:00",
|
||||
"built_by": "B08_Quantity/B08_Quantity_Build_WorkItemMaster.py",
|
||||
"source": {
|
||||
"dataset_id": "pum_forest",
|
||||
@@ -12,8 +12,8 @@
|
||||
"files": [
|
||||
{
|
||||
"file": "work_item_master_2026-01-01.json",
|
||||
"sha256": "97d4c0a12d5cb811d10d3c4108bc1a20acf97748b572db026847b603804f7598",
|
||||
"size_bytes": 925084
|
||||
"sha256": "546624601feaf9e9c7d757d6013b7c9bc3bc973817fb42ded70f3b2306b6778d",
|
||||
"size_bytes": 924964
|
||||
},
|
||||
{
|
||||
"file": "form_undetermined_2026-01-01.json",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"schema_version": "1.0",
|
||||
"dataset_id": "data_work_item_master_manifest",
|
||||
"generated_at": "2026-09-17T18:25:40+09:00",
|
||||
"generated_at": "2026-09-17T18:52:53+09:00",
|
||||
"built_by": "B08_Quantity/B08_Quantity_Build_WorkItemMaster.py",
|
||||
"source": {
|
||||
"dataset_id": "pum_const",
|
||||
@@ -12,8 +12,8 @@
|
||||
"files": [
|
||||
{
|
||||
"file": "const_work_item_master_2026-01-01.json",
|
||||
"sha256": "f01928541cd24f8cfa6f46036d8d988479d8649796d6630d5b70179c485001bd",
|
||||
"size_bytes": 3839561
|
||||
"sha256": "e8e3bc48c2563246b7a6fd4b5bc5129fe00c5f112fa190d78119912beddf40ff",
|
||||
"size_bytes": 3839500
|
||||
},
|
||||
{
|
||||
"file": "const_form_undetermined_2026-01-01.json",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"effective_date": "2026-01-01",
|
||||
"pum_edition": "2026-01-01",
|
||||
"toc_edition": "2026-01-01",
|
||||
"generated_at": "2026-09-17T18:25:40+09:00",
|
||||
"generated_at": "2026-09-17T18:52:53+09:00",
|
||||
"dataset_version": {
|
||||
"dataset_id": "pum_const",
|
||||
"effective_date": "2026-01-01",
|
||||
@@ -49,7 +49,7 @@
|
||||
"empty": 74
|
||||
},
|
||||
"keys_newly_issued": 0,
|
||||
"variant_keys_newly_issued": 407,
|
||||
"variant_keys_newly_issued": 0,
|
||||
"variant_keys": 407,
|
||||
"toc_duplicate_rows": 0,
|
||||
"toc_corrections": 0
|
||||
@@ -5712,12 +5712,12 @@
|
||||
{
|
||||
"variant_key": "01",
|
||||
"name": "평 규 준 틀",
|
||||
"name_clean": "평 규 준 틀"
|
||||
"name_clean": "평규준틀"
|
||||
},
|
||||
{
|
||||
"variant_key": "02",
|
||||
"name": "귀 규 준 틀",
|
||||
"name_clean": "귀 규 준 틀"
|
||||
"name_clean": "귀규준틀"
|
||||
}
|
||||
],
|
||||
"toc_code": "CP-01-02-05-04",
|
||||
@@ -7050,7 +7050,7 @@
|
||||
{
|
||||
"variant_key": "01",
|
||||
"name": "벽 용",
|
||||
"name_clean": "벽 용"
|
||||
"name_clean": "벽용"
|
||||
},
|
||||
{
|
||||
"variant_key": "02",
|
||||
@@ -126550,7 +126550,7 @@
|
||||
{
|
||||
"variant_key": "01",
|
||||
"name": "주 철 재 바 닥 설 치 20절 이하",
|
||||
"name_clean": "주 철 재 바 닥 설 치 20절 이하"
|
||||
"name_clean": "주철재바닥설치 20절 이하"
|
||||
},
|
||||
{
|
||||
"variant_key": "02",
|
||||
@@ -126560,12 +126560,12 @@
|
||||
{
|
||||
"variant_key": "03",
|
||||
"name": "벽 걸 이 3절",
|
||||
"name_clean": "벽 걸 이 3절"
|
||||
"name_clean": "벽걸이 3절"
|
||||
},
|
||||
{
|
||||
"variant_key": "04",
|
||||
"name": "천 장 달 기 3절",
|
||||
"name_clean": "천 장 달 기 3절"
|
||||
"name_clean": "천장달기 3절"
|
||||
},
|
||||
{
|
||||
"variant_key": "05",
|
||||
@@ -131030,32 +131030,32 @@
|
||||
{
|
||||
"variant_key": "01",
|
||||
"name": "분 전 반",
|
||||
"name_clean": "분 전 반"
|
||||
"name_clean": "분전반"
|
||||
},
|
||||
{
|
||||
"variant_key": "02",
|
||||
"name": "조 작 반",
|
||||
"name_clean": "조 작 반"
|
||||
"name_clean": "조작반"
|
||||
},
|
||||
{
|
||||
"variant_key": "03",
|
||||
"name": "계 기 반 ( 자 립 개 방 )",
|
||||
"name_clean": "계 기 반 ( 자 립 개 방 )"
|
||||
"name_clean": "계기반 ( 자립개방 )"
|
||||
},
|
||||
{
|
||||
"variant_key": "04",
|
||||
"name": "계 기 반 ( 자 립 밀 폐 )",
|
||||
"name_clean": "계 기 반 ( 자 립 밀 폐 )"
|
||||
"name_clean": "계기반 ( 자립밀폐 )"
|
||||
},
|
||||
{
|
||||
"variant_key": "05",
|
||||
"name": "계 기 반 ( 현 장 )",
|
||||
"name_clean": "계 기 반 ( 현 장 )"
|
||||
"name_clean": "계기반 ( 현 장 )"
|
||||
},
|
||||
{
|
||||
"variant_key": "06",
|
||||
"name": "〃 ( 발 신 기 수 납 상 )",
|
||||
"name_clean": "〃 ( 발 신 기 수 납 상 )"
|
||||
"name_clean": "〃 ( 발신기수납상 )"
|
||||
}
|
||||
],
|
||||
"toc_code": "CP-04-12-01-01",
|
||||
@@ -131910,17 +131910,17 @@
|
||||
{
|
||||
"variant_key": "01",
|
||||
"name": "유 니 온 엘 보",
|
||||
"name_clean": "유 니 온 엘 보"
|
||||
"name_clean": "유니온엘보"
|
||||
},
|
||||
{
|
||||
"variant_key": "02",
|
||||
"name": "공 기 압 축 기 시 험",
|
||||
"name_clean": "공 기 압 축 기 시 험"
|
||||
"name_clean": "공기압축기시험"
|
||||
},
|
||||
{
|
||||
"variant_key": "03",
|
||||
"name": "조 작 함 ( 설 비 물 )",
|
||||
"name_clean": "조 작 함 ( 설 비 물 )"
|
||||
"name_clean": "조작함 ( 설비물 )"
|
||||
}
|
||||
],
|
||||
"toc_code": "CP-04-12-02-05",
|
||||
@@ -154239,7 +154239,7 @@
|
||||
{
|
||||
"variant_key": "01",
|
||||
"name": "산 기 분 기 관 제 작",
|
||||
"name_clean": "산 기 분 기 관 제 작"
|
||||
"name_clean": "산기분기관제작"
|
||||
},
|
||||
{
|
||||
"variant_key": "02",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"effective_date": "2026-01-01",
|
||||
"pum_edition": "2026-01-01",
|
||||
"toc_edition": "산림청고시제2025-82호",
|
||||
"generated_at": "2026-09-17T18:25:05+09:00",
|
||||
"generated_at": "2026-09-17T18:52:20+09:00",
|
||||
"dataset_version": {
|
||||
"dataset_id": "pum_forest",
|
||||
"effective_date": "2026-01-01",
|
||||
@@ -10618,12 +10618,12 @@
|
||||
{
|
||||
"variant_key": "01",
|
||||
"name": "채 취",
|
||||
"name_clean": "채 취"
|
||||
"name_clean": "채취"
|
||||
},
|
||||
{
|
||||
"variant_key": "02",
|
||||
"name": "운 반",
|
||||
"name_clean": "운 반"
|
||||
"name_clean": "운반"
|
||||
},
|
||||
{
|
||||
"variant_key": "03",
|
||||
@@ -28953,17 +28953,17 @@
|
||||
{
|
||||
"variant_key": "01",
|
||||
"name": "간 단",
|
||||
"name_clean": "간 단"
|
||||
"name_clean": "간단"
|
||||
},
|
||||
{
|
||||
"variant_key": "02",
|
||||
"name": "보 통",
|
||||
"name_clean": "보 통"
|
||||
"name_clean": "보통"
|
||||
},
|
||||
{
|
||||
"variant_key": "03",
|
||||
"name": "복 잡",
|
||||
"name_clean": "복 잡"
|
||||
"name_clean": "복잡"
|
||||
},
|
||||
{
|
||||
"variant_key": "04",
|
||||
@@ -31445,12 +31445,12 @@
|
||||
{
|
||||
"variant_key": "03",
|
||||
"name": "설 치",
|
||||
"name_clean": "설 치"
|
||||
"name_clean": "설치"
|
||||
},
|
||||
{
|
||||
"variant_key": "04",
|
||||
"name": "철 거",
|
||||
"name_clean": "철 거"
|
||||
"name_clean": "철거"
|
||||
}
|
||||
],
|
||||
"toc_code": "FP-12-17-01",
|
||||
@@ -33774,17 +33774,17 @@
|
||||
{
|
||||
"variant_key": "01",
|
||||
"name": "간 단",
|
||||
"name_clean": "간 단"
|
||||
"name_clean": "간단"
|
||||
},
|
||||
{
|
||||
"variant_key": "02",
|
||||
"name": "보 통",
|
||||
"name_clean": "보 통"
|
||||
"name_clean": "보통"
|
||||
},
|
||||
{
|
||||
"variant_key": "03",
|
||||
"name": "복 잡",
|
||||
"name_clean": "복 잡"
|
||||
"name_clean": "복잡"
|
||||
}
|
||||
],
|
||||
"toc_code": "FP-12-38",
|
||||
@@ -33952,17 +33952,17 @@
|
||||
{
|
||||
"variant_key": "01",
|
||||
"name": "간 단",
|
||||
"name_clean": "간 단"
|
||||
"name_clean": "간단"
|
||||
},
|
||||
{
|
||||
"variant_key": "02",
|
||||
"name": "보 통",
|
||||
"name_clean": "보 통"
|
||||
"name_clean": "보통"
|
||||
},
|
||||
{
|
||||
"variant_key": "03",
|
||||
"name": "복 잡",
|
||||
"name_clean": "복 잡"
|
||||
"name_clean": "복잡"
|
||||
}
|
||||
],
|
||||
"toc_code": "FP-12-38-02",
|
||||
@@ -34082,17 +34082,17 @@
|
||||
{
|
||||
"variant_key": "01",
|
||||
"name": "복 잡",
|
||||
"name_clean": "복 잡"
|
||||
"name_clean": "복잡"
|
||||
},
|
||||
{
|
||||
"variant_key": "02",
|
||||
"name": "보 통",
|
||||
"name_clean": "보 통"
|
||||
"name_clean": "보통"
|
||||
},
|
||||
{
|
||||
"variant_key": "03",
|
||||
"name": "간 단",
|
||||
"name_clean": "간 단"
|
||||
"name_clean": "간단"
|
||||
}
|
||||
],
|
||||
"toc_code": "FP-12-38-03",
|
||||
@@ -36558,202 +36558,202 @@
|
||||
{
|
||||
"variant_key": "01",
|
||||
"name": "메 붙 임 · 깬 돌 · 뒷길이 25㎝",
|
||||
"name_clean": "메 붙 임 · 깬 돌 · 뒷길이 25㎝"
|
||||
"name_clean": "메붙임 · 깬돌 · 뒷길이 25㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "02",
|
||||
"name": "메 붙 임 · 깬 돌 · 뒷길이 30㎝",
|
||||
"name_clean": "메 붙 임 · 깬 돌 · 뒷길이 30㎝"
|
||||
"name_clean": "메붙임 · 깬돌 · 뒷길이 30㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "03",
|
||||
"name": "메 붙 임 · 깬 돌 · 뒷길이 35㎝",
|
||||
"name_clean": "메 붙 임 · 깬 돌 · 뒷길이 35㎝"
|
||||
"name_clean": "메붙임 · 깬돌 · 뒷길이 35㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "04",
|
||||
"name": "메 붙 임 · 깬 돌 · 뒷길이 45㎝",
|
||||
"name_clean": "메 붙 임 · 깬 돌 · 뒷길이 45㎝"
|
||||
"name_clean": "메붙임 · 깬돌 · 뒷길이 45㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "05",
|
||||
"name": "메 붙 임 · 깬 돌 · 뒷길이 55㎝",
|
||||
"name_clean": "메 붙 임 · 깬 돌 · 뒷길이 55㎝"
|
||||
"name_clean": "메붙임 · 깬돌 · 뒷길이 55㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "06",
|
||||
"name": "메 붙 임 · 깬 돌 · 뒷길이 60㎝",
|
||||
"name_clean": "메 붙 임 · 깬 돌 · 뒷길이 60㎝"
|
||||
"name_clean": "메붙임 · 깬돌 · 뒷길이 60㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "07",
|
||||
"name": "메 붙 임 · 깬 돌 · 뒷길이 70㎝",
|
||||
"name_clean": "메 붙 임 · 깬 돌 · 뒷길이 70㎝"
|
||||
"name_clean": "메붙임 · 깬돌 · 뒷길이 70㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "08",
|
||||
"name": "메 붙 임 · 깬잡석 · 뒷길이 25㎝",
|
||||
"name_clean": "메 붙 임 · 깬잡석 · 뒷길이 25㎝"
|
||||
"name_clean": "메붙임 · 깬잡석 · 뒷길이 25㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "09",
|
||||
"name": "메 붙 임 · 깬잡석 · 뒷길이 30㎝",
|
||||
"name_clean": "메 붙 임 · 깬잡석 · 뒷길이 30㎝"
|
||||
"name_clean": "메붙임 · 깬잡석 · 뒷길이 30㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "10",
|
||||
"name": "메 붙 임 · 깬잡석 · 뒷길이 35㎝",
|
||||
"name_clean": "메 붙 임 · 깬잡석 · 뒷길이 35㎝"
|
||||
"name_clean": "메붙임 · 깬잡석 · 뒷길이 35㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "11",
|
||||
"name": "메 붙 임 · 깬잡석 · 뒷길이 45㎝",
|
||||
"name_clean": "메 붙 임 · 깬잡석 · 뒷길이 45㎝"
|
||||
"name_clean": "메붙임 · 깬잡석 · 뒷길이 45㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "12",
|
||||
"name": "메 붙 임 · 깬잡석 · 뒷길이 55㎝",
|
||||
"name_clean": "메 붙 임 · 깬잡석 · 뒷길이 55㎝"
|
||||
"name_clean": "메붙임 · 깬잡석 · 뒷길이 55㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "13",
|
||||
"name": "메 붙 임 · 깬잡석 · 뒷길이 60㎝",
|
||||
"name_clean": "메 붙 임 · 깬잡석 · 뒷길이 60㎝"
|
||||
"name_clean": "메붙임 · 깬잡석 · 뒷길이 60㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "14",
|
||||
"name": "메 붙 임 · 깬잡석 · 뒷길이 70㎝",
|
||||
"name_clean": "메 붙 임 · 깬잡석 · 뒷길이 70㎝"
|
||||
"name_clean": "메붙임 · 깬잡석 · 뒷길이 70㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "15",
|
||||
"name": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 25㎝",
|
||||
"name_clean": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 25㎝"
|
||||
"name_clean": "메붙임 · 조약돌 및 야면석 · 뒷길이 25㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "16",
|
||||
"name": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 30㎝",
|
||||
"name_clean": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 30㎝"
|
||||
"name_clean": "메붙임 · 조약돌 및 야면석 · 뒷길이 30㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "17",
|
||||
"name": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 35㎝",
|
||||
"name_clean": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 35㎝"
|
||||
"name_clean": "메붙임 · 조약돌 및 야면석 · 뒷길이 35㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "18",
|
||||
"name": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 45㎝",
|
||||
"name_clean": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 45㎝"
|
||||
"name_clean": "메붙임 · 조약돌 및 야면석 · 뒷길이 45㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "19",
|
||||
"name": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 55㎝",
|
||||
"name_clean": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 55㎝"
|
||||
"name_clean": "메붙임 · 조약돌 및 야면석 · 뒷길이 55㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "20",
|
||||
"name": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 60㎝",
|
||||
"name_clean": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 60㎝"
|
||||
"name_clean": "메붙임 · 조약돌 및 야면석 · 뒷길이 60㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "21",
|
||||
"name": "찰 붙 임 · 깬 돌 · 뒷길이 25㎝",
|
||||
"name_clean": "찰 붙 임 · 깬 돌 · 뒷길이 25㎝"
|
||||
"name_clean": "찰붙임 · 깬돌 · 뒷길이 25㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "22",
|
||||
"name": "찰 붙 임 · 깬 돌 · 뒷길이 30㎝",
|
||||
"name_clean": "찰 붙 임 · 깬 돌 · 뒷길이 30㎝"
|
||||
"name_clean": "찰붙임 · 깬돌 · 뒷길이 30㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "23",
|
||||
"name": "찰 붙 임 · 깬 돌 · 뒷길이 35㎝",
|
||||
"name_clean": "찰 붙 임 · 깬 돌 · 뒷길이 35㎝"
|
||||
"name_clean": "찰붙임 · 깬돌 · 뒷길이 35㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "24",
|
||||
"name": "찰 붙 임 · 깬 돌 · 뒷길이 45㎝",
|
||||
"name_clean": "찰 붙 임 · 깬 돌 · 뒷길이 45㎝"
|
||||
"name_clean": "찰붙임 · 깬돌 · 뒷길이 45㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "25",
|
||||
"name": "찰 붙 임 · 깬 돌 · 뒷길이 55㎝",
|
||||
"name_clean": "찰 붙 임 · 깬 돌 · 뒷길이 55㎝"
|
||||
"name_clean": "찰붙임 · 깬돌 · 뒷길이 55㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "26",
|
||||
"name": "찰 붙 임 · 깬 돌 · 뒷길이 60㎝",
|
||||
"name_clean": "찰 붙 임 · 깬 돌 · 뒷길이 60㎝"
|
||||
"name_clean": "찰붙임 · 깬돌 · 뒷길이 60㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "27",
|
||||
"name": "찰 붙 임 · 깬 돌 · 뒷길이 70㎝",
|
||||
"name_clean": "찰 붙 임 · 깬 돌 · 뒷길이 70㎝"
|
||||
"name_clean": "찰붙임 · 깬돌 · 뒷길이 70㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "28",
|
||||
"name": "찰 붙 임 · 깬잡석 · 뒷길이 25㎝",
|
||||
"name_clean": "찰 붙 임 · 깬잡석 · 뒷길이 25㎝"
|
||||
"name_clean": "찰붙임 · 깬잡석 · 뒷길이 25㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "29",
|
||||
"name": "찰 붙 임 · 깬잡석 · 뒷길이 30㎝",
|
||||
"name_clean": "찰 붙 임 · 깬잡석 · 뒷길이 30㎝"
|
||||
"name_clean": "찰붙임 · 깬잡석 · 뒷길이 30㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "30",
|
||||
"name": "찰 붙 임 · 깬잡석 · 뒷길이 35㎝",
|
||||
"name_clean": "찰 붙 임 · 깬잡석 · 뒷길이 35㎝"
|
||||
"name_clean": "찰붙임 · 깬잡석 · 뒷길이 35㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "31",
|
||||
"name": "찰 붙 임 · 깬잡석 · 뒷길이 45㎝",
|
||||
"name_clean": "찰 붙 임 · 깬잡석 · 뒷길이 45㎝"
|
||||
"name_clean": "찰붙임 · 깬잡석 · 뒷길이 45㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "32",
|
||||
"name": "찰 붙 임 · 깬잡석 · 뒷길이 55㎝",
|
||||
"name_clean": "찰 붙 임 · 깬잡석 · 뒷길이 55㎝"
|
||||
"name_clean": "찰붙임 · 깬잡석 · 뒷길이 55㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "33",
|
||||
"name": "찰 붙 임 · 깬잡석 · 뒷길이 60㎝",
|
||||
"name_clean": "찰 붙 임 · 깬잡석 · 뒷길이 60㎝"
|
||||
"name_clean": "찰붙임 · 깬잡석 · 뒷길이 60㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "34",
|
||||
"name": "찰 붙 임 · 깬잡석 · 뒷길이 70㎝",
|
||||
"name_clean": "찰 붙 임 · 깬잡석 · 뒷길이 70㎝"
|
||||
"name_clean": "찰붙임 · 깬잡석 · 뒷길이 70㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "35",
|
||||
"name": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 25㎝",
|
||||
"name_clean": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 25㎝"
|
||||
"name_clean": "찰붙임 · 호박돌 및 야면석 · 뒷길이 25㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "36",
|
||||
"name": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 30㎝",
|
||||
"name_clean": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 30㎝"
|
||||
"name_clean": "찰붙임 · 호박돌 및 야면석 · 뒷길이 30㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "37",
|
||||
"name": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 35㎝",
|
||||
"name_clean": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 35㎝"
|
||||
"name_clean": "찰붙임 · 호박돌 및 야면석 · 뒷길이 35㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "38",
|
||||
"name": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 45㎝",
|
||||
"name_clean": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 45㎝"
|
||||
"name_clean": "찰붙임 · 호박돌 및 야면석 · 뒷길이 45㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "39",
|
||||
"name": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 55㎝",
|
||||
"name_clean": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 55㎝"
|
||||
"name_clean": "찰붙임 · 호박돌 및 야면석 · 뒷길이 55㎝"
|
||||
},
|
||||
{
|
||||
"variant_key": "40",
|
||||
"name": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 60㎝",
|
||||
"name_clean": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 60㎝"
|
||||
"name_clean": "찰붙임 · 호박돌 및 야면석 · 뒷길이 60㎝"
|
||||
}
|
||||
],
|
||||
"toc_code": "FP-13-05-01",
|
||||
@@ -39049,17 +39049,17 @@
|
||||
{
|
||||
"variant_key": "02",
|
||||
"name": "복 토",
|
||||
"name_clean": "복 토"
|
||||
"name_clean": "복토"
|
||||
},
|
||||
{
|
||||
"variant_key": "03",
|
||||
"name": "간 단 구 조",
|
||||
"name_clean": "간 단 구 조"
|
||||
"name_clean": "간단구조"
|
||||
},
|
||||
{
|
||||
"variant_key": "04",
|
||||
"name": "보 통 구 조",
|
||||
"name_clean": "보 통 구 조"
|
||||
"name_clean": "보통구조"
|
||||
}
|
||||
],
|
||||
"toc_code": "FP-13-13-02",
|
||||
@@ -39132,7 +39132,7 @@
|
||||
{
|
||||
"variant_key": "01",
|
||||
"name": "단 끊 기",
|
||||
"name_clean": "단 끊 기"
|
||||
"name_clean": "단끊기"
|
||||
},
|
||||
{
|
||||
"variant_key": "02",
|
||||
@@ -39475,7 +39475,7 @@
|
||||
{
|
||||
"variant_key": "01",
|
||||
"name": "사 면",
|
||||
"name_clean": "사 면"
|
||||
"name_clean": "사면"
|
||||
},
|
||||
{
|
||||
"variant_key": "02",
|
||||
|
||||
@@ -285,7 +285,8 @@ def test_갈래에도_불변_열쇠가_있다(master: dict) -> None:
|
||||
# 이름 칸 둘 — 원문은 손대지 않고, 다듬은 것이 따로
|
||||
raw = [it.get("variant_keys") or [] for it in items]
|
||||
assert [n for it in items for n in (it.get("variant_keys") or [])] == [p[0] for p in pairs]
|
||||
assert sum(1 for a, b in pairs if a != b) == 14 # 자간·물결표가 다듬어진 줄
|
||||
# 자간·물결표가 다듬어진 줄 — 14 → 70(2026-09-17 한 글자 낱말 자간 붙이기 「메 붙 임」→「메붙임」 · 열쇠는 그대로)
|
||||
assert sum(1 for a, b in pairs if a != b) == 70
|
||||
assert raw # 원문 목록은 그대로 남아 있다
|
||||
|
||||
|
||||
|
||||
@@ -175,3 +175,17 @@ def test_건설_갈래도_이름을_다듬어도_같은_열쇠(master: dict) ->
|
||||
assert [v["variant_key"] for v in after["variants"]] == [
|
||||
v["variant_key"] for v in before["variants"]
|
||||
]
|
||||
|
||||
|
||||
def test_자간_다듬기는_진짜_띄어쓰기를_안_붙임() -> None:
|
||||
from B08_Quantity.B08_Quantity_Build_WorkItemMaster_Keys import tidy_spacing
|
||||
|
||||
assert tidy_spacing("측 량") == "측량"
|
||||
assert tidy_spacing("평 규 준 틀") == "평규준틀"
|
||||
assert tidy_spacing("굴 삭 기 (무한궤도)") == "굴삭기 (무한궤도)"
|
||||
assert tidy_spacing("메 붙 임 · 깬 돌 · 뒷길이 25㎝") == "메붙임 · 깬돌 · 뒷길이 25㎝"
|
||||
assert tidy_spacing("토목부문 › 측 량 › 기준점 측량") == "토목부문 › 측량 › 기준점 측량"
|
||||
assert (
|
||||
tidy_spacing("그 외 자재의 운반품셈") == "그 외 자재의 운반품셈"
|
||||
) # 한 글자 낱말 둘은 진짜 띄어쓰기
|
||||
assert tidy_spacing("호박돌 및 야면석 · 뒷길이 25㎝") == "호박돌 및 야면석 · 뒷길이 25㎝"
|
||||
|
||||
@@ -271,3 +271,39 @@ def test_찾기는_물결표_가운뎃점_띄어쓰기를_같게_봄(client: Tes
|
||||
assert (
|
||||
spaced == _get(client, "work_item_forest", size=50, q="토사깍기", axis_role="")["total"] > 0
|
||||
)
|
||||
|
||||
|
||||
def test_이름_다듬기는_보일_이름만_열쇠는_그대로(
|
||||
client: TestClient, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""⭐ 갈래 불변 열쇠를 세운 까닭(브레인 2026-09-17) — 자간 공백(「측 량」·「평 규 준 틀」)을 다듬어도
|
||||
줄 열쇠(`FW-…#01`)가 한 글자도 안 흔들림. 다듬기를 끈 목록과 켠 목록의 열쇠를 맞댐."""
|
||||
from B08_Quantity import B08_Quantity_Build_WorkItemMaster_Keys as keys
|
||||
from Z01_MasterData import Z01_MasterData_WorkItems as work_items
|
||||
|
||||
for kind in work_items.KINDS:
|
||||
tidy = work_items.base_rows(kind)
|
||||
with monkeypatch.context() as patch:
|
||||
patch.setattr(keys, "tidy_spacing", lambda text: " ".join(str(text or "").split()))
|
||||
raw = work_items.base_rows(kind)
|
||||
assert [r["@id"] for r in tidy] == [r["@id"] for r in raw]
|
||||
if kind == "work_item_const":
|
||||
assert (
|
||||
sum(a["name"] != b["name"] for a, b in zip(tidy, raw)) > 0
|
||||
) # 실제로 다듬어진 줄이 있음
|
||||
shown = _get(client, "work_item_const", size=50, q="기준점 측량", axis_role="")["rows"]
|
||||
assert shown and all("측 량" not in r["name"] and "› 측량 ›" in r["name"] for r in shown)
|
||||
|
||||
|
||||
def test_품셈_번호는_마디마다_수로_세움(client: TestClient) -> None:
|
||||
"""글자로 세우면 「10-1」이 「2-1」 앞에 섬(서브 훑기) — 마디마다 수로."""
|
||||
rows = _get(client, "work_item_forest", size=500, sort="number", axis_role="")["rows"]
|
||||
numbers = [tuple(int(x) for x in r["number"].split("-")) for r in rows if "-" in r["number"]]
|
||||
assert len(numbers) > 300 and numbers == sorted(numbers)
|
||||
|
||||
|
||||
def test_건설_늘_빈_칸은_감춤(client: TestClient) -> None:
|
||||
"""건설은 합산형 선언이 없어 「단계 무게」가 늘 빈칸 — 감춤(산림은 보임)."""
|
||||
hidden = lambda kind: {c["key"]: c["hidden"] for c in _get(client, kind, size=1)["columns"]} # noqa: E731
|
||||
assert hidden("work_item_const")["step_weight"] is True
|
||||
assert hidden("work_item_forest")["step_weight"] is False
|
||||
|
||||
Reference in New Issue
Block a user