화면에 뜬 숫자가 어디서 와서 어떻게 나왔는지 가릴 길이 없어 개발·검산이 막히던 것을 엶(PLAN 8-36 ①②③④). 칸에 마우스를 올리면 등급·값·식·원천·자리가 카드로 뜨고, 토글을 켜면 등급색이 칸 왼쪽 띠로 붙음. - `common_util/common_util_provenance.py` — 등급 상수 여덟과 `ColumnProvenance`. 사람이 고르는 여섯(입력·측량·기준·계산·최종·막힘)에 `excluded`(일부러 안 셈, 채우면 이중계상)와 `unclassified`(판단 미룸)를 더함. `excluded` 는 데스크탑 보조의 B09 조사에서 나온 것으로 `blocked` 와 뜻이 정반대라 갈라 둠. 값 안에 선택이 숨은 열을 위해 `rule`(채택 규칙) 칸도 둠. - ⚠ 로직 보안 — `provenance_payload()` 가 개발환경이 아니면 `None` 을 돌려주고 라우터가 응답에서 칸을 통째로 뺌. 화면에서 숨기는 것이 아니라 안 보내는 것임. 문의 정본은 `is_dev_environment()` 하나로 통일. - `ui_template/ui_template_provenance.ts` — 호버 카드·등급색·토글 한 벌. B09 도 같이 씀. - `B08_Quantity/B08_Quantity_Provenance.py` — 토적표 20열 사전. 사전은 **열 단위**이고 줄마다 갈리는 사유만 줄 쪽에서 얹음(칸마다 지으면 한 장이 6천 칸이라 응답이 붐). - 토적표에는 `final` 열이 하나도 없어 억지로 붙이지 않음 — 중간 장부이고 내역서로 나가는 값은 토공집계표에서 섬. 자체검증 — 시험 8개 추가(`test_b08_provenance.py`). 값어치는 첫 번째에 있음: 사전 열 이름이 전부 실제 `EarthworkRow` 에 있는가(엔진이 이름을 갈면 사전만 옛것으로 남는데 화면에서는 카드가 그냥 안 떠 눈에 안 띔). 배포환경 `None` 도 시험으로 박음. 브라우저(ORCA 5173, 실제 사전을 물려 토적표를 그림) — 표시된 칸 40개(2줄×20열) · 등급 갈래 survey 12 / calc 28 · 카드에 「절토 토사 보정량 · 계산 · 값 45.00 · 식 절토 토사 입적 × 토량환산계수(다짐) · 자리 EarthworkTable.py:210」 · 토글에 배경이 투명 → 초록 7 % 로 바뀌고 왼쪽 띠 inset 3px. 줄 사유가 그 줄 모든 칸에 뜨던 것을 사유가 닿는 열(`ditch_*`)에만 뜨게 고침 — 「절토 보정량」 카드에 「측구 가름값이…」 가 떠서 읽는 사람을 속이던 자리임. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017RANEBHns1S4tkmsYwewtk
164 lines
7.7 KiB
Python
164 lines
7.7 KiB
Python
"""B08 수량 화면의 **근거 사전** — 어느 숫자가 어디서 와서 어떻게 나왔나 (PLAN 8-36 ④).
|
||
|
||
⚠⚠ **개발 전용.** 사전은 `provenance_payload()` 를 거쳐 나가고, 개발환경이 아니면 `None`
|
||
이라 응답에 칸 자체가 안 생긴다. 화면에서 숨기는 것이 아니라 **안 보내는 것**이다.
|
||
|
||
왜 이 파일인가
|
||
「식」과 「원천」의 정답은 값을 낳는 엔진이 안다. 화면 TS 에 손으로 적어 두면 엔진을
|
||
고칠 때 설명만 옛것으로 남는다. 엔진 옆(같은 폴더)에 두어 같이 눈에 들어오게 한다.
|
||
|
||
⚠ **열 단위로 적는다.** 토적표 한 장이 30열 × 200줄 = 6천 칸이라 칸마다 지으면 응답이
|
||
붐는다. 줄마다 갈리는 것(측구 안분 폴백 사유 등)은 줄이 이미 `notes` 로 들고 있고,
|
||
화면이 그것을 카드에 덧붙인다.
|
||
|
||
⚠ **토적표에는 `final`(최종) 열이 없다 — 억지로 붙이지 않았다.**
|
||
이 표는 중간 장부다. 내역서로 나가는 값은 **토공집계표**에서 선다. 여섯 등급을
|
||
한 장에 다 채우려고 아무 열에나 `final` 을 붙이면 「분류가 있다」는 거짓만 남는다.
|
||
이 어긋남은 등급을 고칠 근거이므로 PLAN 8-36 ① 에 그대로 남긴다.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from typing import Any
|
||
|
||
from common_util.common_util_provenance import (
|
||
TIER_CALC,
|
||
TIER_SURVEY,
|
||
ColumnProvenance,
|
||
provenance_payload,
|
||
sheet_provenance,
|
||
)
|
||
|
||
#: 토량환산계수가 어디서 오는지 — 여러 열이 같은 문장을 쓰므로 한 벌로 둔다.
|
||
_FACTOR_SOURCE = (
|
||
"토량환산계수(다짐) — 기본값 `config_system_design.EARTHWORK_CONVERSION_FACTORS`, "
|
||
"프로젝트가 고른 값이 있으면 산출 조건 패널의 값"
|
||
)
|
||
|
||
#: 단면적 넷의 공통 원천. B06 이 낸 설계 단면을 **그대로** 읽는다(여기서 다시 안 짓는다).
|
||
_SECTION_SOURCE = "B06 횡단 설계가 낸 측점별 단면적"
|
||
|
||
#: 평균단면적법 한 줄. 신규 문서 5장 「다. 공사수량의 산출」.
|
||
_MEAN_AREA = "(앞 측점 단면적 + 이 측점 단면적) ÷ 2 × 두 측점 사이 거리"
|
||
|
||
|
||
def _area(key: str, label: str, extra: str = "") -> ColumnProvenance:
|
||
"""단면적 열 — B06 설계값을 그대로 옮긴 자리라 식이 없다."""
|
||
return ColumnProvenance(
|
||
key=key,
|
||
label=label,
|
||
tier=TIER_SURVEY,
|
||
formula="설계가 낸 값을 그대로 읽음 (여기서 다시 계산하지 않음)",
|
||
source=_SECTION_SOURCE + (f" · {extra}" if extra else ""),
|
||
code="B08_Quantity_Engine_EarthworkTable.py:StationArea.from_design",
|
||
)
|
||
|
||
|
||
def _volume(key: str, label: str, area_label: str) -> ColumnProvenance:
|
||
return ColumnProvenance(
|
||
key=key,
|
||
label=label,
|
||
tier=TIER_CALC,
|
||
formula=_MEAN_AREA.replace("단면적", area_label),
|
||
source="첫 측점은 앞이 없어 비어 있음 (실무 토적표도 첫 줄 체적이 빈칸)",
|
||
code="B08_Quantity_Engine_EarthworkTable.py:200 mean_volume",
|
||
)
|
||
|
||
|
||
def _adjusted(key: str, label: str, volume_label: str) -> ColumnProvenance:
|
||
return ColumnProvenance(
|
||
key=key,
|
||
label=label,
|
||
tier=TIER_CALC,
|
||
formula=f"{volume_label} × 토량환산계수(다짐)",
|
||
source=_FACTOR_SOURCE,
|
||
code="B08_Quantity_Engine_EarthworkTable.py:210",
|
||
)
|
||
|
||
|
||
def earthwork_sheet() -> dict[str, Any]:
|
||
"""토적표 한 장의 사전. 열 키는 화면 `EarthworkRow` 와 같은 낱말이라야 한다."""
|
||
return sheet_provenance(
|
||
[
|
||
ColumnProvenance(
|
||
key="chainage_m",
|
||
label="측점",
|
||
tier=TIER_SURVEY,
|
||
formula="노선 시점에서 잰 이정(m). 화면은 NO.n+m 으로 적음",
|
||
source="B05 종단이 놓은 측점 배치",
|
||
code="B08_Quantity_Engine_EarthworkTable.py:StationArea.chainage_m",
|
||
),
|
||
ColumnProvenance(
|
||
key="distance_m",
|
||
label="거리",
|
||
tier=TIER_CALC,
|
||
formula="이 측점 이정 − 앞 측점 이정",
|
||
source="B05 종단 측점 배치. 첫 줄은 앞이 없어 0",
|
||
code="B08_Quantity_Engine_EarthworkTable.py:195",
|
||
),
|
||
_area("cut_soil_area_m2", "절토 토사 단면적"),
|
||
_volume("cut_soil_volume_m3", "절토 토사 입적", "절토 토사 단면적"),
|
||
_adjusted("cut_soil_adjusted_m3", "절토 토사 보정량", "절토 토사 입적"),
|
||
_area("cut_rock_area_m2", "절토 암석 단면적", "암 갈래는 측점의 `cut_rock_kind`"),
|
||
_volume("cut_rock_volume_m3", "절토 암석 입적", "절토 암석 단면적"),
|
||
_adjusted("cut_rock_adjusted_m3", "절토 암석 보정량", "절토 암석 입적"),
|
||
_area(
|
||
"ditch_soil_area_m2",
|
||
"측구터파기 토사 단면적",
|
||
"지반 유형·암반 경계선으로 B06 이 가른 값. 가름이 없는 옛 저장분만 "
|
||
"절토 토사:암 면적비로 안분하고 그 줄에 사유가 남음",
|
||
),
|
||
_volume("ditch_soil_volume_m3", "측구터파기 토사 입적", "측구 토사 단면적"),
|
||
_adjusted("ditch_soil_adjusted_m3", "측구터파기 토사 보정량", "측구 토사 입적"),
|
||
_area(
|
||
"ditch_rock_area_m2",
|
||
"측구터파기 암석 단면적",
|
||
"위와 같은 가름값. 0.0 은 설계가 낸 「없음」이고 값 없음과 다름",
|
||
),
|
||
_volume("ditch_rock_volume_m3", "측구터파기 암석 입적", "측구 암석 단면적"),
|
||
_adjusted("ditch_rock_adjusted_m3", "측구터파기 암석 보정량", "측구 암석 입적"),
|
||
ColumnProvenance(
|
||
key="adjusted_total_m3",
|
||
label="보정량계",
|
||
tier=TIER_CALC,
|
||
formula="절토 토사 보정량 + 절토 암석 보정량 + 측구 토사 보정량 + 측구 암석 보정량",
|
||
source="네 보정량의 합. 성토에 쓸 수 있는 양으로 환산한 뒤의 값",
|
||
code="B08_Quantity_Engine_EarthworkTable.py:215",
|
||
),
|
||
_area("fill_area_m2", "성토 단면적"),
|
||
_volume("fill_volume_m3", "성토 입적", "성토 단면적"),
|
||
ColumnProvenance(
|
||
key="diverted_m3",
|
||
label="유용토",
|
||
tier=TIER_CALC,
|
||
formula="min(보정량계, 성토 입적)",
|
||
source="그 측점에서 절취분과 성토분이 서로 만나는 몫",
|
||
code="B08_Quantity_Engine_EarthworkTable.py:222",
|
||
),
|
||
ColumnProvenance(
|
||
key="balance_m3",
|
||
label="차인토량",
|
||
tier=TIER_CALC,
|
||
formula="보정량계 − 성토 입적",
|
||
source="양수면 남는 흙(사토), 음수면 모자란 흙(객토)",
|
||
code="B08_Quantity_Engine_EarthworkTable.py:223",
|
||
),
|
||
ColumnProvenance(
|
||
key="cumulative_m3",
|
||
label="누가토량",
|
||
tier=TIER_CALC,
|
||
formula="첫 줄부터 이 줄까지 차인토량을 더해 온 값",
|
||
source="유토곡선(mass haul)의 세로축이 되는 값",
|
||
code="B08_Quantity_Engine_EarthworkTable.py:225",
|
||
),
|
||
]
|
||
)
|
||
|
||
|
||
def quantity_provenance() -> dict[str, Any] | None:
|
||
"""B08 응답에 실을 사전 — **개발환경이 아니면 `None`.**
|
||
|
||
시트를 늘릴 때는 여기 한 줄만 더한다. 화면은 시트 이름으로 찾아 쓴다.
|
||
"""
|
||
return provenance_payload({"earthwork": earthwork_sheet()})
|