Merge remote-tracking branches 'origin/sub_desktop_1', 'origin/sub_laptop_1' and 'origin/sub_laptop_3' into sub_laptop_4
This commit is contained in:
@@ -65,8 +65,32 @@ _SOURCE = re.compile(
|
||||
_IDENT = re.compile(r"\d+-\d+(?:-\d+)*")
|
||||
ROW_KEYS = {
|
||||
"요소": ("키", "원문번호", "이름", "값", "출처"),
|
||||
"표": ("키", "원문번호", "이름", "기준", "출처", "조건", "값칸", "줄", "주"),
|
||||
"로직": ("키", "원문번호", "이름", "결과단위", "출처", "소유", "입력", "중간", "끝수"),
|
||||
"표": (
|
||||
"키",
|
||||
"원문번호",
|
||||
"구분",
|
||||
"상세구분",
|
||||
"이름",
|
||||
"기준",
|
||||
"출처",
|
||||
"조건",
|
||||
"값칸",
|
||||
"줄",
|
||||
"주",
|
||||
),
|
||||
"로직": (
|
||||
"키",
|
||||
"원문번호",
|
||||
"구분",
|
||||
"상세구분",
|
||||
"이름",
|
||||
"결과단위",
|
||||
"출처",
|
||||
"소유",
|
||||
"입력",
|
||||
"중간",
|
||||
"끝수",
|
||||
),
|
||||
"품셈재료": ("키", "원문번호", "이름", "규격", "단위", "요구절", "연결"),
|
||||
}
|
||||
# 한 테이블 파일 — 줄의 갈래 칸 · 머리의 갈래 묶음
|
||||
@@ -124,6 +148,11 @@ COLS = {
|
||||
COLS["한국은행환율"] = COLS["오피넷유가"]
|
||||
|
||||
|
||||
def _detail(name: str) -> str:
|
||||
"""장 파일 이름 → 상세구분 「03장 토공사」."""
|
||||
return name.removesuffix(".json").split("_", 2)[2].replace("_", " ")
|
||||
|
||||
|
||||
def load(names: list[str] | None = None, folder: Path = MASTER) -> dict[str, dict]:
|
||||
"""첫 층 JSON 모두(밑줄 파일 빼고) — 수는 Decimal. `folder` = 마스터 폴더(M01 시험은 사본)."""
|
||||
out = {}
|
||||
@@ -205,6 +234,12 @@ def check_form(name: str, data: dict) -> list[str]:
|
||||
if not isinstance(rows, list):
|
||||
return out + [f"{name} · 머리 「{'표' if table else '줄'}」 목록 없음"]
|
||||
division = data.get("부문") if kind != "요소" else None
|
||||
# 장 파일 줄의 갈래 — 구분 = 원문 + 부문 · 상세구분 = 「NN장 장 제목」(파일 이름 그대로)
|
||||
want = (
|
||||
(" ".join(x for x in (data.get("원문"), division) if x), _detail(name))
|
||||
if m.group(4)
|
||||
else None
|
||||
)
|
||||
for row in rows:
|
||||
key, number = str(row.get("키")), str(row.get("원문번호"))
|
||||
where = f"{name} · {key} {row.get('이름') or number}"
|
||||
@@ -214,6 +249,11 @@ def check_form(name: str, data: dict) -> list[str]:
|
||||
out.append(f"{where} · {merged} 「{row.get(merged)}」 이 머리에 없음")
|
||||
if division and not number.startswith(division + " "):
|
||||
out.append(f"{where} · 원문번호 앞에 부문 「{division}」 없음")
|
||||
if want and (row.get("구분"), row.get("상세구분")) != want:
|
||||
out.append(
|
||||
f"{where} · 구분·상세구분 「{row.get('구분')} · {row.get('상세구분')}」"
|
||||
f" 이 파일 머리·이름 「{want[0]} · {want[1]}」 과 다름"
|
||||
)
|
||||
cols = COLS.get(data.get("원문"))
|
||||
for need in cols or ROW_KEYS[kind]:
|
||||
if need not in row:
|
||||
|
||||
@@ -125,6 +125,42 @@ MERGED = {
|
||||
"기계": ("기계.json", "세부분류", {"건설품셈": "건설품셈", "산림품셈": "산림품셈"}),
|
||||
}
|
||||
DIVISIONS = ("공통", "토목", "건축", "기계설비", "유지관리")
|
||||
# 장 파일 줄의 열 차례 — 앞 넷은 한 줄에 · 「그룹」(소요량 파일 안의 계수 표 표시)은 맨 뒤
|
||||
ROW_ORDER = {
|
||||
"표": (
|
||||
"키",
|
||||
"원문번호",
|
||||
"구분",
|
||||
"상세구분",
|
||||
"이름",
|
||||
"기준",
|
||||
"출처",
|
||||
"비고",
|
||||
"조건",
|
||||
"범위규칙",
|
||||
"값칸",
|
||||
"줄",
|
||||
"주",
|
||||
"그룹",
|
||||
),
|
||||
"로직": (
|
||||
"키",
|
||||
"원문번호",
|
||||
"구분",
|
||||
"상세구분",
|
||||
"이름",
|
||||
"결과단위",
|
||||
"출처",
|
||||
"소유",
|
||||
"비고",
|
||||
"입력",
|
||||
"중간",
|
||||
"호표",
|
||||
"덧줄",
|
||||
"결과",
|
||||
"끝수",
|
||||
),
|
||||
}
|
||||
OLD_CHAPTER = re.compile(r"^(소요량|계수|로직)_(산림품셈|건설품셈)_(\D*)(\d+)장\.json$")
|
||||
CHAPTER = re.compile(r"^(소요량|계수|로직)_(산림품셈|건설품셈|자체)_(\d\d)장_.+\.json$")
|
||||
_BODY = MASTER.parents[1] / "resources/knowledge/original/원가계산"
|
||||
@@ -142,6 +178,11 @@ def title(book: str, division: str, number: int) -> str:
|
||||
return hit.name.split("_", 1)[1]
|
||||
|
||||
|
||||
def detail_of(name: str) -> str:
|
||||
"""장 파일 이름 → 상세구분 「03장 토공사」."""
|
||||
return name.removesuffix(".json").split("_", 2)[2].replace("_", " ")
|
||||
|
||||
|
||||
def chapter_file(group: str, book: str, division: str, number: int) -> str:
|
||||
return f"{group}_{book}_{number:02d}장_{title(book, division, number)}.json"
|
||||
|
||||
@@ -230,15 +271,16 @@ def dump_rows(head: dict, rows: list[dict]) -> str:
|
||||
|
||||
|
||||
def keep_text(text: str, old: dict, new: dict) -> str | None:
|
||||
"""글 모양 그대로 — 「열쇠」 칸 · 바뀐 글 · 머리 부문·차례만 갈음 · 읽어 맞대어 다르면 None."""
|
||||
"""글 모양 그대로 — 「열쇠」 칸(키·원문번호·갈래) · 바뀐 글 · 머리 부문·차례만 갈음 · 다르면 None."""
|
||||
rows_old, rows_new = old[_items(old)], new[_items(new)]
|
||||
spots = list(re.finditer(r'"열쇠": ("(?:[^"\\]|\\.)*"|[-\d.]+)', text))
|
||||
if len(spots) != len(rows_new):
|
||||
return None
|
||||
parts, at = [], 0
|
||||
for m, row in zip(spots, rows_new):
|
||||
number = json.dumps(row["원문번호"], ensure_ascii=False)
|
||||
parts += [text[at : m.start()], f'"키": "{row["키"]}", "원문번호": {number}']
|
||||
head = [k for k in ("키", "원문번호", "구분", "상세구분") if k in row]
|
||||
line = ", ".join(f'"{k}": {json.dumps(row[k], ensure_ascii=False)}' for k in head)
|
||||
parts += [text[at : m.start()], line]
|
||||
at = m.end()
|
||||
text = "".join(parts) + text[at:]
|
||||
swap = {}
|
||||
@@ -319,8 +361,14 @@ def adopt(folder: Path = MASTER) -> list[str]:
|
||||
for r in rows
|
||||
]
|
||||
data[_items(data)] = rows
|
||||
# 장 파일 줄은 갈래를 스스로 지님 — 구분 = 원문 + 부문 · 상세구분 = 「NN장 장 제목」
|
||||
extra = (
|
||||
{"구분": " ".join(x for x in (src, c[3]) if x), "상세구분": detail_of(target)}
|
||||
if c
|
||||
else None
|
||||
)
|
||||
stamped = [
|
||||
_convert(book, r, names) for r in stamp(book, table_id(group, src), rows, target)
|
||||
_convert(book, r, names) for r in stamp(book, table_id(group, src), rows, target, extra)
|
||||
]
|
||||
if group in MERGED:
|
||||
file, slot, labels = MERGED[group]
|
||||
|
||||
Reference in New Issue
Block a user