From 8a533975d63b21c9a79dd609c36f8ff977b1ad3c Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 21 Oct 2026 00:15:22 +0000 Subject: [PATCH] feat: render confirmed station GL/grade table and grade check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Applies the 2026-10-21 decisions: A column = GL, B column = design grade, 20 m station numbering, gaps marked [미확정]. Regression slope of the grade column is compared with the drawn S=2.4913%. No value is adjusted. Co-Authored-By: Claude Haiku 5.5 Claude-Session: https://claude.ai/code/session_01A5Cun3RHQKna9qxE6ybZ4A --- scripts/make_profile_doc.py | 49 +++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 scripts/make_profile_doc.py diff --git a/scripts/make_profile_doc.py b/scripts/make_profile_doc.py new file mode 100644 index 0000000..e147182 --- /dev/null +++ b/scripts/make_profile_doc.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +"""Render the confirmed station table (지반고 = A열, 계획고 = B열, 20 m station +numbering per user decision 2026-10-21) into DOC/03_설계 and check the design +grade against the drawn label S=2.4913% (정상 구배 검산). No value is adjusted.""" +import csv +import sys + +SRC, OUT = sys.argv[1], sys.argv[2] +rows = [] +with open(SRC, encoding="utf-8") as fh: + rd = list(csv.DictReader(fh)) +gl, dg = {}, {} +for r in rd: + sta = int(r["station_anchor"]) + if float(r["across_m"]) < -25: + gl[sta] = float(r["value"]) + else: + dg[sta] = float(r["value"]) +stas = sorted(set(gl) & set(dg)) +n = len(stas) +xs = [s for s in stas] +mx = sum(xs) / n +my = sum(dg[s] for s in stas) / n +slope = sum((s - mx) * (dg[s] - my) for s in stas) / sum((s - mx) ** 2 for s in stas) +grade_pct = slope * 100 +resid = [dg[s] - (my + slope * (s - mx)) for s in stas] +max_res = max(abs(r) for r in resid) +lines = ["# 본선 종단 측점값 — 지반고·계획고 (초안, 확정 해석 반영)\n", + "| 버전 | 일자 | 변경 내용 |", "|---|---|---|", + "| v0.1.00 | 2026-10-21 | 최초 작성. 02-002 종단 눈금 4+740~5+480, 지반고(A열)·계획고(B열) 확정 해석 반영 |\n", + "## 1. 확정 사항 (사용자 답변 2026-10-21)", + "- 소수 A열(중심선 측 약 -33m) = **지반고**, B열(약 -16m) = **계획고** [출처: C0060302-002, CR-TABL-TEX2]", + "- 측점은 **측점 번호 20m 기준**. 도면상 눈금 거리 21.27m는 사용하지 않음 (축척 1.0635배 불일치 기록)", + "- 공백 구간(4+700~4+740, 5+480~5+500)은 **[미확정]**, 확보 구간만 모델링\n", + "## 2. 측점별 지반고·계획고", + "| 측점(m) | 표기 | 지반고 GL(m) | 계획고(m) |", "|---|---|---|---|"] +for s in stas: + lines.append(f"| {s} | {s // 1000}+{s % 1000:03d} | {gl[s]:.3f} | {dg[s]:.3f} |") +lines += ["", + "## 3. 검산", + f"- 계획고 직선 회귀 구배: **{grade_pct:.4f}%** (도면 표기 S=2.4913%와 비교)", + f"- 계획고 회귀 잔차 최대: {max_res:.3f} m (구배 전 구간 직선 가정 시). 구배 꺾임이 있으면 잔차에 나타남", + "- 지반고는 구배 검산 대상이 아님 (지형 값)\n", + "## 4. 미확정·후속 (OPEN 등재 대상)", + "- 4+700~4+740, 5+480~5+500 종단 값 없음 → [미확정]", + "- 허용오차 ±50mm 판정: 본 초안은 도면 표기 값 그대로이며, 3D 대조 판정은 Task 7 이후 수행", + "- 라이닝 두께 수치: 04-004~009 콘크리트라이닝 구조도 확인 예정 (사용자 지시 2026-10-21)\n"] +open(OUT, "w", encoding="utf-8").write("\n".join(lines) + "\n") +print(f"stations={n} grade={grade_pct:.4f}% max_resid={max_res:.3f}")