"""Ramp-A P3-1 갈고리를 P3 각도로 수정(수정6, 2026-10-27)한 내용을 엑셀에 반영한다. - 도면 r135 각도가 이상해 보인다는 사용자 의견을 '도면 확인 필요'로 체크 - M-9 문구·구분·보류 행을 수정6 결과로 갱신, 수정 내역 R-18, 수정 증거, 파일·해시(수정6 최신) - 공통 문제 상세(이미지) 24행 문구 갱신 + 25행(수정 전·후 이미지, 좌표) 추가 같은 R-18 이 이미 있으면 중단. """ import copy import datetime import hashlib import json import sys from pathlib import Path import openpyxl from openpyxl.drawing.image import Image as XLImage from openpyxl.styles import Alignment, PatternFill ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T") REV = ROOT / "검토파일" RES = ROOT / "Code" / "검토수정" / "결과" XLSX = REV / "4개교_공통사항_종합.xlsx" a = json.loads((RES / "c1_p31_angle.json").read_text(encoding="utf-8")) cv = json.loads((RES / "c1_radial_cover_s6.json").read_text(encoding="utf-8")) c5, c6 = cv["수정5(r135 70도)"]["P3-1"], cv["수정6(P3 각도)"]["P3-1"] co5 = json.loads((RES / "c1_hook_coords.json").read_text(encoding="utf-8"))["P1-RC-P3-1-L01X"] co6 = json.loads((RES / "c1_hook_coords6.json").read_text(encoding="utf-8"))["P1-RC-P3-1-L01X"] wb = openpyxl.load_workbook(XLSX) ws = wb["수정 내역"] if any(r[0].value == "R-18" for r in ws.iter_rows(min_row=4)): sys.exit("R-18 이 이미 있음 - 중단") GREEN = PatternFill("solid", fgColor="FFE2EFDA") OLD_ADD = (" ※ 사용자 확인(2026-10-27): P3-1 은 r135 가 맞고 C 곡선(호 길이) 165, D 150 인 아래로 걸리는 갈고리 (호 70.03°) — r·c 불일치 아님. " "모델(수정5)은 이 값 그대로. 이 형상은 갈고리가 아래·바깥으로 뻗어 말뚝 구간(반지름 1,175 / 1,250)의 밖으로 나감 → 도면 형상과 말뚝 단면(배치) 불일치, 설계자 확인") NEW_ADD = (" ※ [도면 확인 필요] 도면 P3-1 의 r135 각도가 이상해 보임(사용자 의견 2026-10-27): P3 는 r60·c141 → 134.65° 갈고리인데 P3-1 은 r135·c165 → 70° 로 다른 모양이 되고 말뚝 밖으로 나감. " "수정5 까지는 도면 값(r135)대로 작성했고, 수정6 에서 철근은 P3 각도(134.65°)를 따라 C 곡선 165·D 150 을 유지해 r %.2f 로 수정(48본, 말뚝 안: PL01 중심 피복 최소 %.1f / PL02 최소 %.1f mm). 도면 r135 가 맞는지는 설계자 확인" % (a["sample"]["r"], c6["PL01"]["min_radial_centre_cover"], c6["PL02"]["min_radial_centre_cover"])) REPL = [ (OLD_ADD, NEW_ADD), ("도면 오류로 보류: 도면 P3-1 치수는 반지름 1,250 구간에만 겨우 맞고 반지름 1,175 구간에서는 갈고리가 말뚝 밖으로 나감. 모델은 도면 치수대로 두고 오류로 기록. 구간별 치수는 설계자 확인", "수정 완료(수정6, 2026-10-27): P3 각도(134.65°) 적용 → 말뚝 안. 도면 r135(70°) 자체는 설계자 확인 필요"), (" (말뚝 단면·P3-1 배치 설계자 확인)", " (도면 r135 설계자 확인)"), ("도면 오류 (말뚝 돌출)", "도면 r 확인 필요 (수정6 으로 말뚝 안)"), ("[개별] Ramp-A교 P3-1 갈고리 — r135 · C 곡선 165 · D 150 (70° 아래로 걸림), 이 치수대로면 말뚝 밖으로 나감", "[개별] Ramp-A교 P3-1 갈고리 — 도면 r135(70°) 각도가 이상해 보임, 철근은 P3 각도(134.65°)로 수정 (수정6)"), ("사용자 확인(2026-10-27): r135 가 맞고 C 곡선 길이 165, D 150. 호는 70.03° 로 아래로 걸림 — r·c 불일치 아님", "사용자 의견(2026-10-27): 도면 r135 의 각도가 이상해 보임 — P3(r60, 134.65°)와 같은 갈고리인데 P3-1 은 70° 로 각도가 다름"), ("말뚝 단면(반지름 1,175 / 1,250 구간)과 P3-1 배치 위치 설계자 확인. 모델은 도면 값 그대로", "도면 r 값 설계자 확인. 모델(수정6)은 P3 각도(134.65°) + C 165 + D 150 (r %.2f)" % a["sample"]["r"]), ("[오류 기록] 모델은 도면 값(r135·c165·d150)대로 작성: 호 70.03°, 호 길이 165.0, 곧은 구간 150.0. 아래 말뚝 구간(반지름 1,175) 26본 중심이 말뚝 밖, 위 구간(반지름 1,250) 22본 표면 돌출. '미수정·보류', M-9", "수정 완료(2026-10-27): P3 각도(134.65°) 적용 → r %.2f · 호 길이 165.0 · 곧은 구간 150.0, 말뚝 안(PL01 최소 %.1f / PL02 최소 %.1f mm). 수정 전(도면 r135·70°)은 말뚝 밖(PL01 26본 중심 밖, PL02 22본 돌출). 파일 ramp-A G5_수정6_20261026.3dm, '수정 내역' R-18" % (a["sample"]["r"], c6["PL01"]["min_radial_centre_cover"], c6["PL02"]["min_radial_centre_cover"])), ] n = 0 for name in ("교량별 항목 합본", "개별 항목", "미수정·보류", "공통 문제 상세(이미지)", "수정 내역", "수정 증거(마크별)"): for row in wb[name].iter_rows(): for c in row: if isinstance(c.value, str): v = c.value for old, new in REPL: if old in v: v = v.replace(old, new) if v != c.value: c.value = v n += 1 for r in wb["미수정·보류"].iter_rows(min_row=4): if r[0].value == "Ramp-A교" and str(r[1].value).startswith("P3-1"): r[3].value = "수정 완료(수정6): P3 각도로 다시 만들어 말뚝 안. (수정5 도면 r135·70° 는 PL01 26본 중심 밖, PL02 22본 표면 돌출)" r[4].value = "사용자 의견: 도면 r135 의 각도(70°)가 이상해 보임 → 철근은 P3 각도(134.65°), C 165, D 150, r %.2f. 'M-9', 'R-18'" % a["sample"]["r"] r[5].value = "도면 r135 설계자 확인" def append_like(sheet, values, like_row): r = sheet.max_row + 1 for j, v in enumerate(values, 1): c = sheet.cell(row=r, column=j, value=v) s = sheet.cell(row=like_row, column=j) c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border); c.alignment = copy.copy(s.alignment); c.number_format = s.number_format sheet.auto_filter.ref = "A3:%s%d" % (openpyxl.utils.get_column_letter(sheet.max_column), r) return r r = append_like(ws, ["R-18", "Ramp-A교", "P3-1 갈고리를 P3 각도로 수정", "P3-1 (H16)", "도면 r135·c165·d150: 호 70.03°, 곧은 구간이 바깥으로 뻗음 / 말뚝 밖 (PL01 26본 중심 밖, PL02 22본 돌출)", "P3 각도 134.65°, 호 길이 165.0, 곧은 구간 150.0, r %.2f (곧은 구간이 안쪽 아래로 되돌아옴) / 말뚝 안" % a["sample"]["r"], a["stat"]["done"], "사용자 의견 2026-10-27: 도면 r135 의 각도가 이상해 보임 → 철근은 P3 각도를 따름. C 곡선 165, D 150 은 도면 값 유지, 반지름은 165 ÷ (141/60) = %.2f" % a["sample"]["r"], "ramp-A G5_수정6_20261026.3dm", "수정 후 재측정: r·호 각도·호 길이·곧은 구간·꼭짓점~호 시작(b 2,137) 확인, 말뚝 반경 기준 중심 피복 PL01 최소 %.1f / PL02 최소 %.1f mm(돌출 0본). 객체 수 %d → %d 동일" % (c6["PL01"]["min_radial_centre_cover"], c6["PL02"]["min_radial_centre_cover"], a["objects_before"], a["objects_after"]), "도면 r135 의 각도 자체는 설계자 확인(체크). 증거: 공통 문제 상세(이미지) 25행 수정 전·후 Rhino 캡처·좌표"], 4) ws.cell(row=r, column=1).fill = GREEN ev = wb["수정 증거(마크별)"] append_like(ev, ["Ramp-A교", "P3-1", "H16", "갈고리 각도를 P3 각도로", a["stat"]["done"], "r135 · 70.03° · c165 · d150 / 곧은 구간이 바깥", "r%.2f · 134.65° · c165 · d150 / 안쪽으로 되돌아옴" % a["sample"]["r"], 0.0, "중심선 길이 불변(2,641.7). 좌표: 호 중심 (1068.5, 0, 33057.0) → (1068.5, 0, 33121.79), 곧은 구간 끝 (1246.61, 0, 32962.13) → (1013.05, 0, 32965.73)"], 4) fs = wb["수정 파일·해시"] def sha(p): h = hashlib.sha256() with open(p, "rb") as f: for blk in iter(lambda: f.read(1 << 20), b""): h.update(blk) return h.hexdigest() for row in fs.iter_rows(min_row=4): if str(row[1].value).endswith("ramp-A G5_수정5_20261026.3dm") and row[3].value == "최신": row[3].value = "중간본" row[3].fill = PatternFill(fill_type=None) p = REV / "Ramp-A교P1" / "ramp-A G5_수정6_20261026.3dm" stt = p.stat() rr = append_like(fs, ["Ramp-A교", "검토파일/Ramp-A교P1/ramp-A G5_수정6_20261026.3dm", "P3-1 갈고리 P3 각도 적용 — 전체 수정 포함", "최신", round(stt.st_size / 1e6, 1), datetime.datetime.fromtimestamp(stt.st_mtime).strftime("%Y-%m-%d %H:%M"), sha(p)], 4) fs.cell(row=rr, column=4).fill = GREEN wd = wb["공통 문제 상세(이미지)"] nr = wd.max_row + 1 like = nr - 1 pt = lambda co: "; ".join("%s 월드(%s) 2D(%s)" % (k.split("_")[0], ", ".join(str(x) for x in v["world"]), ", ".join(str(x) for x in v["2D(u,v)"])) for k, v in co["points"].items() if k.startswith(("⑤", "⑥", "⑦", "⑧"))) vals = {1: "M-9", 2: "[개별] Ramp-A교 P3-1 갈고리 수정 전·후 증거 (수정5 → 수정6)", 7: "수정 전(수정5) 철근 중심선 좌표: " + pt(co5) + " / d 방향(u,v) " + str(co5["d_direction(곧은구간 방향 단위벡터 u,v)"]), 8: "수정 후(수정6) 철근 중심선 좌표: " + pt(co6) + " / d 방향(u,v) " + str(co6["d_direction(곧은구간 방향 단위벡터 u,v)"]), 9: "수정 완료(2026-10-27): P3 각도(134.65°) 적용. 2D 좌표는 꼭짓점(다리선과 수평선 교점)을 원점, u = 수평선 방향, v = 위(+Z). 'R-18'"} for col, v in vals.items(): c = wd.cell(row=nr, column=col, value=v) s = wd.cell(row=like, column=col) c.font = copy.copy(s.font); c.fill = copy.copy(s.fill); c.border = copy.copy(s.border) c.alignment = Alignment(wrap_text=True, vertical="top") wd.cell(row=nr, column=9).fill = copy.copy(GREEN) wd.row_dimensions[nr].height = 460 im = XLImage(str(REV / "수정후_캡처" / "RampA_P3-1_갈고리_수정전후.png")) w0, h0 = im.width, im.height im.width, im.height = 900, int(900 * h0 / w0) wd.add_image(im, "F%d" % nr) wb.save(XLSX) print("text cells updated:", n, "; new row", nr)