#1 md 가이드 최소화 — README 줄이고 FEATURES·PROGRESS 삭제 (#1)

- README.md: 소개·실행·파일 구조·다시 만들기(변환 패키지)·검사·사용 도구만 남김 (약 16.8KB → 2.6KB)
- FEATURES.json, PROGRESS.md 삭제 (할 일은 이슈, 경과는 커밋)
- 1차 기능 46개 표는 이슈 #1 닫기 댓글 초안에 옮김

결과: PASS 153 / FAIL 0 / SKIP 3 (검사 범위 F01~F47)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
오문성andClaude Haiku 5.5 committed 2026-10-27 16:26:49 +09:00
1 parent bdd296597a
commit e5336f6016
3 files changed
+21 -718

No files matched your search

-499
View File
@@ -1,499 +0,0 @@
[
{
"id": "F01",
"description": "골격: index.html + viewer.js + model.js 빈 파일, 캔버스가 창을 채운다",
"steps": [
"index.html 에 canvas 하나, model.js 다음 viewer.js 순서로 script 태그",
"model.js 는 SPEC 5장 꼴로 units 는 mm, parts 는 빈 배열",
"viewer.js 는 캔버스를 창 크기에 맞추고 배경만 칠한다",
"bash check.sh F01"
],
"passes": true
},
{
"id": "F02",
"description": "스파이크 1: 캔버스에 삼각형 하나를 칠한다",
"steps": [
"viewer.js 안에 고정 좌표 삼각형 하나를 path 로 채운다",
"브라우저로 열어 삼각형이 보이는지 수석이 확인",
"bash check.sh F02"
],
"passes": true
},
{
"id": "F03",
"description": "스파이크 2: 시험용 큐브 하나를 정사 투영, 면 음영, 먼 면부터 그리기로 그린다",
"steps": [
"facesBox, rotatePoint, project, shadeColor, sortFaces, draw 를 만든다",
"시험 큐브 1개(viewer.js 안 고정값)를 그린다",
"면마다 밝기가 다르고 뒤쪽 면이 앞쪽 면을 덮지 않는지 수석이 확인",
"bash check.sh F03"
],
"passes": true
},
{
"id": "F04",
"description": "스파이크 3: 등각 초기 화면 + 마우스 드래그 궤도 회전",
"steps": [
"카메라 초기값을 등각(좌우 45도, 기울기 약 35도)으로",
"onMouseDown, onMouseMove, onMouseUp 으로 좌우 = Z축 둘레, 위아래 = 기울기",
"드래그할 때마다 draw 다시 호출",
"bash check.sh F04"
],
"passes": true
},
{
"id": "F05",
"description": "휠 확대/축소",
"steps": [
"onWheel 로 배율 변경, 너무 작거나 크지 않게 한계",
"bash check.sh F05"
],
"passes": true
},
{
"id": "F06",
"description": "model.js 데이터: 벽, 중간 슬래브 19장, 19B 패드, 하부 슬래브, 바닥콘크리트 (SPEC 4.1~4.3, 5장)",
"steps": [
"SPEC 4.1~4.3 표의 숫자를 그대로 parts 에 적는다(mm)",
"const MODEL = 뒤는 순수 JSON (따옴표 키, 끝 쉼표 없음)",
"bash check.sh F06"
],
"passes": true
},
{
"id": "F07",
"description": "disc 그리기: 슬래브·패드·하부 슬래브·바닥콘크리트를 32각형 원판으로, 화면에 모델 전체가 들어오게",
"steps": [
"facesDisc, buildFaces 를 만들고 시험 큐브는 지운다",
"처음 배율을 모델 크기에 맞춘다",
"bash check.sh F07"
],
"passes": true
},
{
"id": "F08",
"description": "ring 그리기: 벽체를 32각형 속 빈 원통으로, alpha 0.25 반투명",
"steps": [
"facesRing (바깥면, 안쪽면, 위아래 고리면)",
"alpha 를 globalAlpha 로 적용, 벽 너머 슬래브가 보이는지 수석이 확인",
"bash check.sh F08"
],
"passes": true
},
{
"id": "F09",
"description": "TBM 터널: pipe 데이터(SPEC 4.5) + 누운 속 빈 원통 그리기",
"steps": [
"model.js 에 tunnel 1개: 시작점, 330도, 길이 20650, r_out 1500, r_in 1300",
"facesPipe",
"평면 4시 방향, 19B 높이에 붙었는지 수석이 확인",
"bash check.sh F09"
],
"passes": true
},
{
"id": "F10",
"description": "계단 18런: stair 데이터(SPEC 4.4) + 디딤판 블록 그리기",
"steps": [
"model.js 에 stair 18개 (첫 단 100, 단 200, 디딤판 300, 폭 1000)",
"facesStair: 블록마다 facesBox 를 부른다",
"층마다 방향이 바뀌는지 수석이 확인",
"bash check.sh F10"
],
"passes": true
},
{
"id": "F11",
"description": "터널 안 채움: fill 3개(잡석, 패드 2단, 패드 1단) 데이터 + 그리기 (일정이 밀리면 가장 먼저 뺀다)",
"steps": [
"model.js 에 fill 3개 (SPEC 4.5 표)",
"facesFill: 원과 수평선으로 자른 단면을 터널 축 방향으로 늘인다",
"bash check.sh F11"
],
"passes": true
},
{
"id": "F12",
"description": "README.md: 구동 방법 3줄, 조작법, 모델 설명(구조물·단위), 사용 도구(WSL2·Claude Code Haiku), wsl -l -v 한 줄, 🔒 표기",
"steps": [
"README.md 작성 (코치가 읽고 수석에게 의견)",
"bash check.sh"
],
"passes": true
},
{
"id": "F13",
"description": "좌우 분할 화면: 왼쪽 도면 칸, 끌어서 움직이는 가운데 막대, 오른쪽 3D (SPEC 10.1)",
"steps": [
"index.html 에 #drawPane, #splitter, #viewPane",
"onSplitDown/onSplitMove/onSplitUp 으로 왼쪽 폭 15%~85%",
"폭이 바뀌면 캔버스를 오른쪽 칸에 맞추고 draw",
"도면이 없으면 안내 글자",
"bash check.sh F13"
],
"passes": true
},
{
"id": "F14",
"description": "도면 표시·확대·이동: #drawStage 안 img + 겹친 svg, 처음 fit 상자에 맞춤 (SPEC 10.2)",
"steps": [
"#drawStage, img#drawing, svg#hotspots(viewBox 0 0 443 443)",
"fitDrawing, onDrawWheel(마우스 위치 기준 0.5~40배), onDrawDown/Move/Up(이동)",
"bash check.sh F14"
],
"passes": true
},
{
"id": "F15",
"description": "도면 클릭 → 3D 강조: MODEL.drawing 데이터 + 부재별 클릭 영역 + 선택 표시 (SPEC 10.3)",
"steps": [
"model.js 에 drawing 추가(SPEC 10.3 값 그대로)",
"sectionPoly, planPoly, buildHotspots 로 영역 만들기",
"selectPart: 도면 영역 칠하기, 3D 부재 #ffd400, 「선택: 이름」",
"bash check.sh F15"
],
"passes": true
},
{
"id": "F16",
"description": "구동설명서.md: 목적·기획·범위·구동·조작·작업 방식·한계·이력 (SPEC 11.1)",
"steps": [
"SPEC 11.1 순서대로 구동설명서.md 작성, 첫머리 🔒",
"근거는 SPEC.md·PROGRESS.md·git log 에서만",
"bash check.sh F16"
],
"passes": true
},
{
"id": "F17",
"description": "README.md 를 코드 설명으로 고쳐 쓰기: 파일 구조·실행·데이터·코드·그리기 방식·도면 연결·검사 (SPEC 11.2)",
"steps": [
"SPEC 11.2 순서대로 README.md 다시 쓰기, 첫머리 🔒",
"SPEC 7장·10.3 함수 이름 전부와 한 줄 설명",
"bash check.sh F17"
],
"passes": true
},
{
"id": "F18",
"description": "구동설명서를 guide/ HTML 위키(목차 + 8쪽)로 옮기고 3D 칸 오른쪽 위에 「구동 설명서」 버튼 (SPEC 12장)",
"steps": [
"구동설명서.md 내용을 guide/ 8쪽으로 나눠 옮기고 md 는 지운다",
"모든 쪽 맨 위 「← 3D 화면으로 돌아가기」(../index.html), 🔒, h1, 다른 쪽 링크 2개 이상, 목차·이전/다음",
"index.html 에 a#guideLink(guide/index.html) 를 3D 칸 오른쪽 위에",
"bash check.sh F18"
],
"passes": true
},
{
"id": "F19",
"description": "선명한 도면: tools/prep_drawing.py 로 1px 선 SVG 만들기 + 실제 크기로 확대 (SPEC 13.1)",
"steps": [
"tools/prep_drawing.py 작성",
"수석이 준 원본 경로로 실행해 private/drawing.svg 다시 만들기(커밋 안 됨)",
"applyDrawView: width/height 로 확대, translate 로 이동",
"README.md 코드 절에 새 함수 이름과 한 줄 설명 추가",
"bash check.sh F19"
],
"passes": true
},
{
"id": "F20",
"description": "모든 그림 연결: MODEL.drawing.views 11개 + 그림별 클릭 영역 + 여러 부재 한 번에 선택 (SPEC 13.2)",
"steps": [
"model.js 에 drawing.views (SPEC 13.2 표 그대로)",
"viewHotspots, buildHotspots 가 views 를 돈다",
"selectPart 가 id 배열을 받는다",
"README.md 코드 절에 새 함수 이름과 한 줄 설명 추가",
"bash check.sh F20"
],
"passes": true
},
{
"id": "F21",
"description": "슬래브 구멍(holes) + 계단 방향 정정 (SPEC 15.1~15.2)",
"steps": [
"model.js: 슬래브·19B 패드에 holes (15.1 표 그대로)",
"model.js: 계단 18런 x_top·dir·y0·y1 을 15.2 대로",
"facesDiscHoles: 윗면·아랫면 evenodd + 구멍 옆면",
"README.md 코드 절에 새 함수",
"bash check.sh F21"
],
"passes": true
},
{
"id": "F22",
"description": "카메라 이동: 오른쪽 드래그 팬, 마우스 기준 확대 0.5~40배, 더블클릭·처음 화면 버튼 (SPEC 15.3)",
"steps": [
"CAM.target 기준으로 project",
"panView, zoomAt, resetView",
"index.html 에 button#resetView, 오른쪽 클릭 메뉴 막기",
"README.md 코드 절에 새 함수",
"bash check.sh F22"
],
"passes": true
},
{
"id": "F23",
"description": "사람 애니메이션: 1B~19B 계단을 쉬지 않고 오르내림, 사람 ▶/❚❚ 버튼 (SPEC 15.4)",
"steps": [
"buildWalkPath, walkerAt, facesPerson, animate",
"index.html 에 button#walkToggle",
"README.md 코드 절에 새 함수",
"bash check.sh F23"
],
"passes": true
},
{
"id": "F24",
"description": "바닥부 부재: 월류벽(prism 3)·집수조·침사조(zone)·사다리(ladder), 19B 슬래브·패드 침사구 구멍 (SPEC 16.1)",
"steps": [
"model.js 에 16.1 표 그대로",
"facesPrism, facesZone, facesLadder",
"README.md 데이터·코드 절에 새 type 과 함수",
"bash check.sh F24"
],
"passes": true
},
{
"id": "F25",
"description": "바닥부 도면 연결: 단면 A-A·20B 평면·19B 침사구 (SPEC 16.2)",
"steps": [
"bottomHotspots 를 buildHotspots 에 연결",
"README.md 코드 절에 새 함수",
"bash check.sh F25"
],
"passes": true
},
{
"id": "F26",
"description": "상부 슬래브·맨홀 목 2개·벽 윗면 −2000·전기 배선구 구멍 정정 (SPEC 17.1)",
"steps": [
"model.js: 벽 z1 −2000, topslab, neck 2, elec 다각형",
"holePolygon(원 구멍), prism holes",
"README.md 갱신",
"bash check.sh F26"
],
"passes": true
},
{
"id": "F27",
"description": "분기구(obox 5)·환기구 덕트와 환기탑(obox 13) (SPEC 17.2)",
"steps": [
"model.js: 17.2 표 그대로",
"facesObox",
"README.md 갱신",
"bash check.sh F27"
],
"passes": true
},
{
"id": "F28",
"description": "방호 난간 18장·펌프 배출관·위쪽 사다리 2개 (SPEC 17.3)",
"steps": [
"model.js: 17.3 그대로",
"facesRailing",
"README.md 갱신",
"bash check.sh F28"
],
"passes": true
},
{
"id": "F29",
"description": "상부 부재 도면 연결: 단면 A-A·평면도 1·2 (SPEC 17.4)",
"steps": [
"upperHotspots 를 buildHotspots 에 연결",
"README.md 갱신",
"bash check.sh F29"
],
"passes": true
},
{
"id": "F30",
"description": "사람 두 명이 2초 간격으로 줄지어 이동 (SPEC 18.1)",
"steps": [
"teamAt: 첫 사람 t, 두 번째 t−2초",
"facesPerson 를 두 번(색 #ff8c1a, #e07010)",
"README.md 코드 절에 새 함수",
"bash check.sh F30"
],
"passes": true
},
{
"id": "F31",
"description": "콘크리트 계단: 경사판 밑면, 계단 아래 빈 공간 (SPEC 18.2)",
"steps": [
"stairProfile: 18.2 의 점 순서 그대로",
"facesStair: 단면을 Y 띠 폭만큼 늘인 면(블록 방식 버림)",
"README.md 코드 절에 새 함수",
"bash check.sh F31"
],
"passes": true
},
{
"id": "F32",
"description": "구동설명서를 목차 + 목적·구동·조작 3쪽으로 정리, 🔒 줄 빼기 (SPEC 18.3, 코치 작성·하이쿠 커밋)",
"steps": [
"코치가 쓴 guide/ 변경을 그대로 커밋, 지울 쪽은 git rm",
"bash check.sh F32"
],
"passes": true
},
{
"id": "F33",
"description": "도면 추출 도구 tools/extract_from_dxf.py → model_extracted.js (SPEC 20.1, DXF 입력)",
"steps": [
"20.1 규칙대로 작성, 표준 라이브러리만, 도면 좌표·정답 값 금지",
"python3 tools/extract_from_dxf.py private/drawing.dxf model_extracted.js",
"README.md 에 도구 설명",
"bash check.sh F33"
],
"passes": true
},
{
"id": "F34",
"description": "대조 검사·변조 시험 통과 + compare.html (SPEC 20.2)",
"steps": [
"check.sh F34 의 FAIL 을 도구 쪽에서 고친다(model.js·check.sh 는 고치지 않는다)",
"compare.html",
"bash check.sh F34"
],
"passes": true
},
{
"id": "F35",
"description": "계단 18런 추출 → 추출 모델에서도 사람 두 명이 걷는다 (SPEC 21장)",
"steps": [
"section_stairs, stair_parts (21장 규칙대로, 도면 좌표·정답 값 금지)",
"python3 tools/extract_from_dxf.py private/drawing.dxf model_extracted.js 로 다시 만들기",
"compare.html 에서 계단·사람이 보이는지(수석·코치 화면 확인)",
"README.md 도구 설명 갱신",
"bash check.sh F35"
],
"passes": true
},
{
"id": "F36",
"description": "정답지 좌표틀 정정 — 평면도 출처 부재를 슬래브 평면 틀로 (SPEC 22장)",
"steps": [
"model.js 를 22장 표대로 고친다(표에 없는 값은 건드리지 않는다)",
"plan1·plan2 에 rot_deg -30.3",
"viewer.js planXY·planPoly 에 rot_deg 회전",
"bash check.sh F36"
],
"passes": true
},
{
"id": "F37",
"description": "터널·채움 추출 → 추출 모델에도 TBM 터널 (SPEC 23장)",
"steps": [
"section_tunnel, plan_tunnel, tunnel_parts (23장 규칙대로, 도면 좌표·정답 값 금지)",
"python3 tools/extract_from_dxf.py private/drawing.dxf model_extracted.js 로 다시 만들기",
"README.md 도구 설명 갱신",
"bash check.sh F37"
],
"passes": true
},
{
"id": "F38",
"description": "분기구·환기구 추출 → 추출 모델에도 상부 구조 (SPEC 24장)",
"steps": [
"plan_center, frame_angle, section_heights, branch_parts, vent_parts (24장 규칙대로, 도면 좌표·정답 값 금지)",
"python3 tools/extract_from_dxf.py private/drawing.dxf model_extracted.js 로 다시 만들기",
"README.md 도구 설명 갱신",
"bash check.sh F38"
],
"passes": true
},
{
"id": "F39",
"description": "나머지 부재 추출 — 상부 슬래브·목·패드·하부 슬래브·바닥 콘크리트·월류벽·집수조·침사조 (SPEC 25장)",
"steps": [
"top_parts, pad_part, bottom_parts, weir_parts (25장 규칙대로, 도면 좌표·정답 값 금지)",
"python3 tools/extract_from_dxf.py private/drawing.dxf model_extracted.js 로 다시 만들기",
"README.md 도구 설명 갱신",
"bash check.sh F39"
],
"passes": true
},
{
"id": "F40",
"description": "정답지 보강 — 환기구 벽 사다리·환기탑 사다리, ladder angle_deg (SPEC 26장)",
"steps": [
"viewer.js facesLadder 에 angle_deg 회전",
"model.js 에 26장 표의 부재 2개 추가(다른 값은 건드리지 않는다)",
"index.html 에서 두 사다리가 덕트 입구 벽·환기탑 안에 보이는지(수석·코치 화면 확인)",
"bash check.sh F40"
],
"passes": true
},
{
"id": "F41",
"description": "설계 규칙 파일 tools/design_rules.json + 추출 모델이 정답지 부재 전체를 갖는다 (SPEC 27장)",
"steps": [
"tools/design_rules.json 작성(🔶 부재 6개·style)",
"extract_from_dxf.py 에 apply_design_rules, id 를 model.js 와 같게",
"python3 tools/extract_from_dxf.py private/drawing.dxf model_extracted.js",
"README.md 도구 설명 갱신",
"bash check.sh F41"
],
"passes": true
},
{
"id": "F42",
"description": "변환 패키지 — tools/dwg_to_dxf.sh, tools/select_views.py, tools/make_model.sh (SPEC 28장)",
"steps": [
"dwg_to_dxf.sh, select_views.py(28장 규칙, 좌표 숫자 금지), make_model.sh",
"bash tools/make_model.sh 로 private/ 다시 만들기(결과가 지금과 같아야 한다)",
"README.md 「변환 패키지」 절",
"bash check.sh F42"
],
"passes": true
},
{
"id": "F43",
"description": "DXF → SVG(tools/dxf_to_svg.py) + 도면 연결값을 도면에서 (SPEC 29장)",
"steps": [
"tools/dxf_to_svg.py (29.1)",
"make_model.sh 에 SVG 단계",
"추출 도구 drawing_views (29.2)",
"bash tools/make_model.sh 로 private/drawing_gen.svg·model_extracted.js 다시 만들기",
"README.md 갱신",
"bash check.sh F43"
],
"passes": true
},
{
"id": "F44",
"description": "화면 전환 — index.html = 도면에서 만든 모델, answer.html = 정답지 (SPEC 30장)",
"steps": [
"index.html 이 model_extracted.js 를 읽게",
"answer.html 새로",
"viewer.js 가 MODEL.drawing.src 로 도면을 읽게",
"README.md 갱신",
"bash check.sh F44"
],
"passes": true
},
{
"id": "F45",
"description": "README 「사용 도구」 절 (SPEC 31장)",
"steps": [
"wsl.exe -l -v 출력 확인",
"README.md 에 ## 사용 도구 절",
"bash check.sh F45"
],
"passes": true
},
{
"id": "F46",
"description": "WSL2 설치 증빙 evidence/wsl2.txt (SPEC 33장)",
"steps": [
"evidence/wsl2.txt 뒤에 「WSL 안쪽」 명령 출력 덧붙이기(33장 목록, 직접 실행)",
"README 「사용 도구」 갱신",
"bash check.sh F46"
],
"passes": true
}
]
-59
View File
@@ -1,59 +0,0 @@
# PROGRESS — 기능 1개 = 커밋 1개
한 줄 양식: `YYYY-MM-DD HH:MM | 기능 ID | 한 일 | check.sh 결과(PASS n / FAIL n) | 막힌 것`
- 2026-10-20 | KIT | 설계 키트 5파일 추가(SPEC·FEATURES·CLAUDE·check.sh·PROGRESS) | - | -
2026-10-20 13:45 | F01 | 골격: index.html(canvas 1, model.js→viewer.js) · model.js(mm, parts 빈 배열) · viewer.js(창 크기 맞춤, 배경 칠하기) | PASS 3 / FAIL 0 | -
2026-10-20 13:51 | F02 | 스파이크 1: viewer.js draw()에 고정 좌표 삼각형 하나를 path 로 채움 | PASS 4 / FAIL 0 | 수석 육안 확인 대기
2026-10-20 13:53 | F03 | 스파이크 2: viewer.js 에 facesBox·rotatePoint·project·shadeColor·sortFaces·draw, 등각 카메라, 시험 큐브 1개(한 변 2000) 를 면 음영·먼 면부터 그림 | PASS 5 / FAIL 0 | 수석 육안 확인 대기
2026-10-20 13:55 | F04 | 스파이크 3: viewer.js 에 onMouseDown·onMouseMove·onMouseUp 추가, 드래그로 yaw(좌우)·pitch(위아래, ±89도 제한) 를 바꾸고 draw 다시 호출. 등각 초기값은 기존 그대로 | PASS 6 / FAIL 0 | 수석 육안 확인 대기 (드래그 회전)
2026-10-20 13:56 | F05 | 휠 확대/축소: viewer.js 에 ZOOM(0.5~5)·onWheel 추가, 휠 한 칸 10%, draw 의 SCALE 에 ZOOM 곱함 | PASS 7 / FAIL 0 | 수석 육안 확인 대기 (휠 확대)
2026-10-20 14:24 | F06 | model.js 데이터: 벽체(ring alpha 0.25), 중간 슬래브 19장(1B~19B, 상면 z·두께 300·r 4850), 19B 패드, 하부 슬래브(20B), 바닥콘크리트 — SPEC 4.1~4.3 숫자 그대로, const MODEL = 순수 JSON | PASS 17 / FAIL 0 | 수석 확인 대기 (화면은 아직 모델 안 그림)
2026-10-20 14:25 | F07 | disc 그리기: viewer.js 에 facesDisc(32각형 뚜껑 2+옆면 32), buildFaces(disc 만), MODEL_CENTER·MODEL_R 로 처음 배율을 모델 전체에 맞춤, 시험 큐브 제거 | PASS 18 / FAIL 0 | 수석 화면 확인 대기 (모델 전체가 들어오는지)
2026-10-20 14:26 | F08 | ring 그리기: viewer.js 에 facesRing(바깥면·안쪽면·윗고리·아랫고리 각 32장), buildFaces 가 ring 도 모음, 벽 alpha 0.25 는 globalAlpha 로 적용 | PASS 19 / FAIL 0 | 수석 화면 확인 대기 (벽 너머 슬래브가 보이는지)
2026-10-20 14:27 | F09 | TBM 터널: model.js 에 tunnel 1개(pipe, 축 시작 x 4200.2·y -2425.0·z -65050, 330도, 길이 20650, r_out 1500, r_in 1300), viewer.js 에 facesPipe 추가 후 buildFaces 에 pipe 연결 | PASS 23 / FAIL 0 | 수석 확인 대기 (평면 4시 방향, 19B 높이에 붙었는지)
2026-10-20 14:29 | F10 | 계단 18런: model.js 에 stair 18개(SPEC 4.4, 단 수 17·마지막 14, dir 번갈아), viewer.js 에 facesStair 추가 후 buildFaces 에 연결, 디딤판마다 facesBox 블록 | PASS 28 / FAIL 0 | 수석 확인 대기 (층마다 계단 방향이 바뀌는지)
2026-10-20 14:31 | F11 | 터널 안 채움: model.js 에 fill 3개(잡석 -1300~-1175, 패드 2단 -1175~-1100, 패드 1단 -1100~-1050 폭 800), viewer.js 에 facesFill(원을 수평선으로 자른 단면을 축 방향으로 늘임) 추가 후 buildFaces 에 연결 | PASS 32 / FAIL 0 | 수석 화면 확인 대기 (터널 안이 19B 패드 높이까지 차는지)
2026-10-20 14:31 | F12 | README.md 작성: 구동 방법 3줄(index.html 더블클릭 · explorer.exe · Chrome/Edge), 조작법, 모델 설명(단위·구조물·데이터 파일), 검사 명령, 사용 도구(WSL2·Claude Code Haiku), wsl -l -v, 🔒 표기 | PASS 33 / FAIL 0 | 수석 확인 대기 (README 문장 검토)
2026-10-20 15:21 | F13 | 좌우 분할: index.html 에 #drawPane·#splitter·#viewPane, viewer.js 에 onSplitDown/Move/Up (폭 15%~85%), 캔버스는 #viewPane 크기에 맞춤, private/drawing.svg 없으면 안내 글자 | PASS 37 / FAIL 0 | 수석 화면 확인 대기 (막대 끌기, 3D 칸 크기 맞춰지는지)
2026-10-20 15:22 | F14 | 도면 확대·이동: index.html 에 #drawStage(img#drawing + svg#hotspots 443), viewer.js 에 fitDrawing·onDrawWheel(마우스 기준 0.5~40배)·onDrawDown/Move/Up, 처음 화면은 MODEL.drawing.fit 없으면 도면 전체 | PASS 39 / FAIL 0 | 수석 화면 확인 대기 (도면 휠·드래그, 처음 화면이 왼쪽 칸에 꽉 차는지)
2026-10-20 15:24 | F15 | 도면 클릭 연결: model.js 에 drawing 추가, sectionPoly·planPoly·buildHotspots·selectPart 로 부재별 클릭 영역, 선택 시 도면 노란 칠·3D 노란색·「선택: 이름」, 드래그 뒤 클릭 무시 | PASS 41 / FAIL 0 (F01~F15) | 수석 화면 확인 대기 (도면 영역 위치가 맞는지, 클릭·선택 해제)
2026-10-20 15:25 | F16 | 구동설명서.md 작성: 목적·기획(결정 6개)·범위·구동·조작·작업 방식·한계·이력(git log 표), 첫머리 🔒 | PASS 43 / FAIL 0 (F01~F16) | 수석 문서 검토 대기 (구동설명서 기획·한계 문장)
2026-10-20 15:26 | F17 | README.md 를 코드 설명으로 고쳐 씀: 파일 구조·실행·데이터·코드(함수 28개 한 줄씩)·그리기 방식·도면 연결·검사 (SPEC 11.2), 첫머리 🔒 | PASS 45 / FAIL 0 (F01~F17) | 수석 문서 검토 대기 (README 코드 설명 문장)
2026-10-20 15:29 | F18 | 구동설명서.md 를 _소거대기로 옮김(내용은 guide/ 8쪽에 있음), 3D 칸 「구동 설명서」 버튼 | 결과: PASS 50 / FAIL 0 / SKIP 0 (검사 범위 F01~F18) | 수석 화면 확인 대기 (guide 쪽 내용·버튼 위치)
2026-10-20 15:32 | F18 | 구동설명서 보완: guide/ 7쪽 pager 에 목차 링크 추가(목적·기획·범위·구동·조작·작업 방식·한계, 이력은 다음 자리 비움), 작업 방식·기획의 화면 확인 문장을 사실대로 정정(F02 이후 코치 localhost 미리보기, 더블클릭 구동은 수석) | PASS 50 / FAIL 0 (F01~F18) | 없음
2026-10-20 19:07 | F19 | tools/prep_drawing.py 작성, 원본으로 private/drawing.svg 재생성(1px 선, 커밋 안 함), viewer.js 의 applyDraw 를 applyDrawView 로 바꿔 width/height 확대 + translate 이동, README 함수 한 줄 추가 | PASS 54 / FAIL 0 (F01~F19, F20 SKIP) | 수석 화면 확인 대기 (도면 선이 확대해도 얇은지)
2026-10-20 19:11 | F20 | MODEL.drawing.views 11개(SPEC 13.2 표), viewHotspots·circlePoly·region·pathD 추가, 영역을 path 로 바꾸고 evenodd 로 벽 고리 구멍, selectPart 가 id 배열을 받음, 3D SELECTED 배열화, README 함수 추가 | PASS 56 / FAIL 0 (F01~F20) | 수석 화면 확인 대기 (그림 11장 클릭, 여러 부재 한 번에 선택, 「선택:」 글자)
2026-10-20 19:13 | F20 | 보완: 「선택:」 글자를 한 줄(nowrap)·오른쪽 120px 여백으로, 여럿일 때 「처음 둘, … 마지막」(SPEC 13.2) | PASS 56 / FAIL 0 (F01~F20) | 수석 화면 확인 대기 (홀수층 슬래브 선택 시 글자가 설명서 버튼과 안 겹치는지)
2026-10-20 19:15 | DOC | guide/ 9쪽을 사용 설명서로 다시 씀(index·purpose·run·control·plan·scope·limits·method·history, 수석 지시로 코치 세션 작성) | 결과: 문서만 변경, check.sh 안 돌림 | 수석 화면 확인 대기 (guide 9쪽)
2026-10-20 20:57 | F21 | model.js: 슬래브 19장·패드에 holes(SPEC 15.1 표), 계단 18런 x_top·dir·Y 띠 정정(15.2); viewer.js: facesDiscHoles 추가, buildFaces 가 disc 에 사용, draw 가 holes 를 evenodd 로 채움; README 함수 한 줄 | PASS 59 / FAIL 0 (F01~F21, F22·F23 SKIP) | 수석 화면 확인 대기 (슬래브 구멍 위치, 계단 입구 방향)
2026-10-20 20:59 | F22 | viewer.js: CAM.target 기준 project, panView(오른쪽 드래그·Shift+왼쪽), zoomAt(마우스 아래 점 고정, 0.5~40), resetView(더블클릭·처음 화면 버튼), contextmenu 막기, unrotateVector·scaleFor 추가; index.html 에 button#resetView; README 함수 추가 | PASS 62 / FAIL 0 (F01~F22, F23 SKIP) | 수석 화면 확인 대기 (오른쪽 드래그 이동, 휠 확대 40배, 더블클릭 복귀). guide/control.html 의 휠 0.5~5 줄은 아직 옛 값
2026-10-20 21:01 | F23 | 사람 애니메이션: buildWalkPath(계단 18런 내려갔다 되짚어 올라오기, 1000mm/s), walkerAt, facesPerson(상자 4개, 진행 방향에 맞춰 돌림, #ff8c1a), animate(rAF, 초당 30번 이하 다시 그림), setWalking; index.html 에 button#walkToggle; README 코드 절에 5개 함수 | PASS 65 / FAIL 0 (F01~F23) | 수석 화면 확인 대기 (사람이 계단을 오르내리는지, ▶/❚❚ 버튼, 다리 간격 100 해석 확인)
2026-10-20 21:05 | DOC | guide/ 7쪽(purpose·control·plan·scope·limits·method·history)을 F21~F23 에 맞춰 고침: 슬래브 구멍, 카메라 이동(오른쪽 드래그·Shift+드래그·휠 0.5~40·더블클릭), 사람 애니메이션(▶/❚❚) 반영. 수석 지시로 코치 세션 작성 | 결과: 문서만 변경, check.sh 안 돌림 | 수석 화면 확인 대기 (guide 7쪽 갱신분)
2026-10-20 21:12 | F24 | model.js: 월류벽 3·집수조·침사조 zone 2·사다리 1, 19B 슬래브·패드 침사구 구멍 (SPEC 16.1); viewer.js: facesPrism, facesZone, facesLadder 추가, buildFaces 가 prism·zone·ladder 를 받음; README 데이터 표·코드 절 추가 | PASS 70 / FAIL 0 (F01~F24, F25 SKIP) | 수석 화면 확인 대기 (월류벽 홈, 집수조·침사조 반투명 색, 사다리 위치·가로대, 19B 침사구 구멍). 사다리 폭 400·가로대 300 은 도면에 없는 코치 값
2026-10-20 21:15 | F25 | viewer.js: xSpan·planXY·bottomPlanPoly·bottomHotspots 추가, sectionPoly 가 xSpan 사용, buildHotspots 가 bottomHotspots 를 viewHotspots 뒤에 이음 (순서 집수조→침사조→월류벽→사다리); README 코드 절에 새 함수 4개 | PASS 71 / FAIL 0 (F01~F25) | 수석 화면 확인 대기 (단면 A-A·20B 평면에서 집수조·침사조 활꼴, 월류벽 홈, 사다리 클릭, 19B 평면 침사구 클릭 → 사다리 선택)
2026-10-20 21:19 | F26 | model.js: 벽 z1 −2000, topslab(disc r 5500, 원 구멍 2), neck 2(prism, 맨홀 목·원 구멍), elec 19개 슬래브 다각형으로 정정 / viewer.js: holePolygon(원→16각형), addHoles(facesDiscHoles 에서 분리), facesPrism 에 holes; README 데이터·코드 절 갱신 | PASS 74 / FAIL 0 / SKIP 8 (F01~F26) | 수석 화면 확인 대기 (상부 슬래브 뚜껑 원 구멍 2개, 맨홀 목 2개, 배선구 평행사변형). facesPrism 바깥 면 법선 부호가 반대로 보임(코드 읽기로만 확인, 화면 미확인) — F24 월류벽도 같은 함수
2026-10-20 21:20 | F27 | model.js: 분기구 obox 5, 환기 덕트·환기탑 obox 13 (SPEC 17.2 표 그대로, angle 167/0, cx=cy=0) / viewer.js: facesObox(facesBox 를 (s,t,z) 로 만들고 angle_deg 만큼 돌려 cx,cy 에 놓음, 법선도 돈다), buildFaces 에 obox 분기; README 데이터·코드 절 갱신(부재 72개) | PASS 77 / FAIL 0 / SKIP 5 (F01~F27, F28·F29 SKIP) | 수석 화면 확인 대기 (분기구가 167도 방향 옆 굴, 덕트가 남쪽으로 내려가 동쪽으로 꺾여 환기탑 연결, 환기탑 높이 지표 0)
2026-10-20 21:22 | F28 | model.js: 방호 난간 18장(railing, z·h 1100·paths), 펌프 배출관(pipe ring, 0,4220), 위쪽 사다리 2개(ladder_up) 추가 (SPEC 17.3) / viewer.js: facesRailing(꺾은선 구간마다 두께 40 판 6장) 추가, buildFaces 에 railing 분기 / README 데이터 표·부재 수 93개·코드 절 갱신 | PASS 81 / FAIL 0 / SKIP 1 (F01~F28, F29 범위 밖) | 수석 화면 확인 대기 (1B~17B 윗면 난간 높이 1100, 19B 패드 위 난간, 배출관 집수조→상부 슬래브 밑, 서쪽·가운데 사다리). 판 두께 40 과 난간 색 #d8c890 은 도면에 없는 코치 값
2026-10-20 21:24 | F29 | viewer.js: obox4 추가, xSpan 이 neck·obox 를 다룸, upperHotspots 추가(단면 A-A 사각형·평면도 원판 r 4850 → 맨홀 목 → 상자 바닥 윤곽), buildHotspots 순서 상부→벽·터널→바닥부 / README 함수 절 갱신 | 결과: PASS 82 / FAIL 0 / SKIP 0 (검사 범위 F01~F29) | 수석 화면 확인 대기 (단면 A-A 상부 슬래브·목·분기구·환기구·위쪽 사다리 클릭, 평면도 1·2 에서 원판·목·상자 클릭 후 벽 고리 클릭). 원판 평면 r 4850 은 SPEC 17.4 값(상부 슬래브 r 5500 과 다름), 코치 값 아님
2026-10-20 21:26 | F29 | viewer.js 보완: 분기구·환기구는 같은 kind 덩어리 전체 선택(upperHotspots 의 group, KIND_LABEL), 선택 문구를 kind 이름으로 (「선택: 평면도 — 분기구」「… — 환기구(강제)」), 목·사다리는 하나씩 | PASS 82 / FAIL 0 / SKIP 0 (F01~F29) | 수석 화면 확인 대기 (단면 A-A·평면도 1·2 에서 분기구·환기구 누르면 5개·13개 전체가 노랗게 되는지)
2026-10-20 21:28 | DOC | guide/ 사용 설명서 6쪽(purpose·plan·scope·limits·method·history) F24~F29 에 맞춰 갱신 (코치 세션 작성, 수석 사전 승인, SPEC 14장) / viewer.js·model.js 변경 없음 | PASS 82 / FAIL 0 / SKIP 0 (F01~F29) | 수석 확인 대기 (guide/ 6쪽 본문 검토)
2026-10-21 10:00 | F30 | model.js 변경 없음 / viewer.js: teamAt(t) 추가(첫 사람 t, 두 번째 t−TEAM_LAG 2000ms), facesPerson 에 색 인자(WALK_COLORS #ff8c1a, #e07010), draw 에서 두 사람 그림, walkerAt 음수 시각 접음 / README 사람 애니메이션 절 갱신 | PASS 82 / FAIL 0 / SKIP 4 (F01~F30 검사, F31·F32 범위 밖) | 수석 화면 확인 대기 (사람 두 명이 2초 간격으로 같은 길을 가는지, 시작 직후 두 번째 사람이 경로 끝에서 튀지 않는지)
2026-10-21 10:02 | F31 | viewer.js: stairProfile 추가(18.2 점 순서, 디딤판 300·챌판 200, s_b=(z_high−z_low−400)×1.5), facesStair 를 단면 Y 띠 압출(옆면 2 + 둘레 변마다 사각형)로 교체, 블록 방식 삭제 / README 함수 절 갱신(stairProfile 추가, facesBox·facesStair 설명 고침) | PASS 83 / FAIL 0 / SKIP 0 (F01~F31) | 수석 화면 확인 대기 (계단 18런이 경사판 밑면을 가진 콘크리트 계단으로 보이는지, 계단 아래 빈 공간·사람 경로와 어긋나지 않는지). 첫 점(0,z_high)→(0,z_high−200) 과 닫는 변이 s=0 에서 겹치는 것은 SPEC 18.2 점 순서 그대로 둔 것
2026-10-21 10:02 | F32 | guide/ 를 목차·목적·구동·조작 3쪽으로 정리: 코치 작성 index·purpose·run·control 그대로 커밋, plan·scope·limits·method·history git rm / README·index.html 변경 없음 (SPEC 18.3) | 결과: PASS 86 / FAIL 0 / SKIP 0 (검사 범위 F01~F32) | 수석 화면 확인 대기 (guide/index.html 목차 → 목적·구동·조작 3쪽 링크, 🔒 줄 없음)
2026-10-21 14:49 | F33 | tools/extract_from_dxf.py 추가: DXF 에서 벽·지표·슬래브 윗면 19·평면 구멍·난간 추출 (SPEC 20.1, 도면 좌표 코드에 없음) / model_extracted.js 생성 / README 파일 구조 두 줄 | PASS 89 / FAIL 0 / SKIP 9 (검사 범위 F01~F33) | 수석 확인 대기 (대조는 F34). 19B 침사구 구멍 1개는 20.1 규칙(오프닝·구조물 계단 레이어)에 안 잡힘 — F34 전에 판단 필요. 벽 z 는 19.1 고정값 -70200·-2000 사용
2026-10-21 14:50 | F34 | 대조 검사: 도구 쪽 검사 통과(model.js 변경 없음) / compare.html 추가(model_extracted.js 읽음, 「추출 데이터로 그린 화면」 글자) / viewer.js: MODEL.drawing 없을 때 hotspots·도면 로드 건너뜀 | PASS 98 / FAIL 0 / SKIP 0 (F01~F34) | 수석 화면 확인 대기 (compare.html 3D 칸이 index.html 과 같은 모양인지, 왼쪽 안내 글자)
2026-10-21 14:53 | F34 | 보완: viewer.js 계단 없으면 사람·버튼 숨김(HAS_WALK), MODEL.drawing 없으면 클릭 영역 안 만듦 / model.js·check.sh·SPEC.md 무변경 | PASS 98 / FAIL 0 / SKIP 0 (F01~F34) | index.html 의 <path> NaN 4개는 HEAD 에도 있던 것(수석 판단 대기, 이번엔 손대지 않음)
2026-10-21 14:55 | F29 | 보완: viewer.js xSpan 이 사다리를 kind 로 찾아 위쪽 사다리(kind ladder_up)가 NaN 이 되던 것을 type 으로 고침 (단면 A-A·A-A 생략 그림의 ladder_up_W·ladder_up_C 영역 4개, x0~x1) / FEATURES.json·check.sh·SPEC.md 무변경 | PASS 81 / FAIL 0 / SKIP 17 (검사 범위 F01~F29) | 수석 화면 확인 대기 (F12 콘솔 path NaN 오류 사라졌는지)
2026-10-21 19:32 | F35 | tools/extract_from_dxf.py: 계단 18런 추출 section_stairs·stair_profile·stair_dir·stair_parts (SPEC 21장, 도면 좌표·정답 값 코드에 없음) / model_extracted.js 다시 생성 / README 도구 설명 갱신 | 결과: PASS 100 / FAIL 0 / SKIP 0 (검사 범위 F01~F35) | 수석 확인 대기 (compare.html 에 계단·사람 두 명이 보이는지)
2026-10-21 20:05 | F36 | 정답지 좌표틀 정정 (SPEC 22장): model.js 표대로 터널·잡석·패드 0°·(4850,0), 상부슬래브 구멍·맨홀 목 2개 축 정렬, 분기구 197.3°, 환기구 30.3°, 위쪽 사다리 W 값 / 평면도 1·2 rot_deg -30.3 / viewer.js planXY·planPoly 회전 | 결과: PASS 103 / FAIL 0 / SKIP 0 (검사 범위 F01~F36) | 수석 화면 확인 대기 (compare·index 평면도 클릭 영역이 도면 그림 위에 놓이는지, 터널이 계단과 나란히 +X 로 가는지)
2026-10-21 20:11 | F37 | 터널 추출 section_tunnel·plan_tunnel·tunnel_parts (SPEC 23장, 도면 좌표·정답 값 코드에 없음) / inner_r 추가 / model_extracted.js 다시 생성 / README 도구 설명 갱신 | 결과: PASS 108 / FAIL 0 / SKIP 0 (검사 범위 F01~F37) | 수석 확인 대기 (compare.html 에 터널·잡석·패드가 계단과 나란히 보이는지)
2026-10-21 20:24 | F38 | 분기구·환기구 추출 (SPEC 24장): plan_center·frame_angle(φ 30.3 류, 도면에서 구함)·section_heights(A-A 좌측 X, B-B 우측 X)·branch_parts·vent_parts / model_extracted.js 다시 생성 / README 도구 설명 갱신 | 결과: PASS 113 / FAIL 0 / SKIP 0 (검사 범위 F01~F38) | 수석 화면 확인 대기 (compare.html 에 분기구·환기구·환기탑이 계단·터널과 맞물려 보이는지)
2026-10-21 20:37 | F39 | 나머지 부재 추출: top_slab_part·neck_parts(상부 슬래브·맨홀 목 2)·pad_and_sump(19B 패드·침사구)·bottom/lean(하부 슬래브·바닥 콘크리트)·weir_parts·pit_parts(월류벽 3·집수조/침사조) / 벽 높이를 도면에서 읽도록 고정값 제거 / 20B 평면 제목 추가 / model_extracted.js 다시 생성 / README 도구 설명 갱신 | 결과: PASS 124 / FAIL 0 / SKIP 0 (검사 범위 F01~F39) | 수석 화면 확인 대기 (compare.html 에 상부 슬래브·목·패드·월류벽·집수조가 맞는지)
2026-10-21 20:39 | F40 | 정답지 보강 (SPEC 26장): viewer.js facesLadder 에 angle_deg 회전(원점 기준, 법선 포함) / model.js 에 환기구 사다리 2개(ladder_vent_wall·ladder_vent_tower, kind ladder_vent) / .gitignore 에 __pycache__/ | 결과: PASS 126 / FAIL 0 / SKIP 0 (검사 범위 F01~F40) | 수석 화면 확인 대기 (index.html 에서 환기구 벽 사다리가 덕트 입구 벽에, 환기탑 사다리가 탑 안에 보이는지)
2026-10-21 20:42 | F41 | 설계 규칙 파일 tools/design_rules.json (🔶 부재 6개·style·ids) / extract_from_dxf.py 에 load_design_rules·apply_design_rules (부재 뒤에 🔶 붙이고 color·alpha 덮어씀) / model_extracted.js 다시 생성(95개) / README 도구 설명 갱신 | 결과: PASS 132 / FAIL 0 / SKIP 0 (검사 범위 F01~F41) | 수석 화면 확인 대기 (compare.html 에 사다리·배출관이 색까지 model.js 와 같게 보이는지)
2026-10-21 20:49 | F42 | 변환 패키지: tools/dwg_to_dxf.sh(dwg2dxf 래퍼)·tools/select_views.py(views.json 상자 안 객체만, 좌표 숫자 없음)·tools/make_model.sh(DWG→full.dxf→drawing.dxf→model_extracted.js, private/ 출력 시 루트 model_extracted.js 갱신) / README 「변환 패키지」 절 / 객체 3356개 확인 | 결과: PASS 138 / FAIL 0 / SKIP 0 (검사 범위 F01~F42) | 수석 확인 대기 (README 변환 패키지 절, make_model.sh 실행 결과)
2026-10-21 21:01 | F43 | DXF→SVG 변환 도구 tools/dxf_to_svg.py (SPEC 29.1) / 추출 도구 drawing_views 로 도면 연결값을 도면에서 계산 (SPEC 29.2, views.json 세 번째 인수) / make_model.sh 에 SVG 단계 / drawing_gen.svg·model_extracted.js 다시 생성 / README 갱신 | 결과: PASS 144 / FAIL 0 / SKIP 0 (검사 범위 F01~F43) | 수석 화면 확인 대기 (index.html 왼쪽 도면이 drawing_gen.svg 로 원본과 같은지, README 변환 패키지 절)
2026-10-21 21:04 | F44 | 화면 전환: index.html 이 model_extracted.js 를 읽음 / answer.html 신설(정답지, model.js) / viewer.js 가 MODEL.drawing.src 로 도면을 읽고 없으면 그 경로 안내 / README 첫 화면·정답지·다시 만들기 갱신 | 결과: PASS 150 / FAIL 0 / SKIP 0 (검사 범위 F01~F44) | 수석 화면 확인 대기 (index.html 이 도면에서 만든 모델인지, answer.html 이 예전 정답지인지)
2026-10-21 21:08 | F45 | README 「사용 도구」 절 복원 (SPEC 31장): wsl -l -v 출력은 8f606f5 에 기록된 값을 그대로 옮김 (WSL 안에서 wsl.exe 호출 불가) / Haiku 5.5·LibreDWG·git·브라우저 / 커밋 메시지 Co-Authored-By 줄 | 결과: PASS 151 / FAIL 0 / SKIP 0 (검사 범위 F01~F45) | 수석 확인 대기 (README 사용 도구 절의 wsl 출력이 지금 Windows 값과 같은지)
2026-10-22 09:23 | F46 | WSL2 설치 증빙: evidence/wsl2.txt 에 WSL 안쪽 출력(uname·/proc/version·Ubuntu 26.04·claude 2.1.304·git·python3·dwg2dxf) 덧붙임 / README 사용 도구에 설치일 2026-07-09 와 증빙 파일 연결 | 결과: PASS 154 / FAIL 0 / SKIP 0 (검사 범위 F01~F46) | 수석 확인 대기 (evidence/wsl2.txt 의 Windows 쪽 설치일·WSL 안쪽 출력이 맞는지)
+21 -160
View File
@@ -1,184 +1,45 @@
# drawing3d-web — 코드 설명
이 저장소는 1차 과제 제출본을 사내 공개용으로 정리한 것입니다 (도면 실제 좌표·과업명 제거, 좌표 평행이동, 화면·검사 결과는 같음, SPEC 34장).
1차의 커밋 81개 기록은 `evidence/gitlog_v1.txt` 에 있습니다.
원형 수직구 일반도를 라이브러리 없이 Canvas 2D 로 그리는 3D 뷰어. 왼쪽 도면에서 부재를 누르면 오른쪽 3D 에서 강조된다. 사내 공개용 정리본(SPEC 34장). 설계 근거는 `SPEC.md`, 구동 설명은 `guide/index.html`.
> 🔒 사내교육용 — 열람 외 재배포 등의 활동을 금함 (회사 도면의 치수를 옮겨 적음)
원형 수직구 일반도를 라이브러리 없이 Canvas 2D 로 그리는 3D 뷰어. 설계 근거는 `SPEC.md`, 구동 설명은 `guide/index.html` (HTML 위키).
## 실행
- `index.html` 을 Chrome 또는 Edge 로 연다. 서버·인터넷은 필요 없다. 첫 화면은 도면에서 만든 모델이고, `answer.html` 은 손으로 만든 정답지 화면이다.
- WSL 에서는 이 폴더에서 `explorer.exe index.html`.
## 파일 구조
| 파일 | 내용 |
|---|---|
| `index.html` | 첫 화면(도면에서 만든 모델). 화면 배치(도면 칸 · 가운데 막대 · 3D 칸)와 스크립트 읽기 순서: `model_extracted.js` 다음에 `viewer.js` |
| `answer.html` | 정답지 화면. `index.html` 과 같은 화면이되 `model.js` 를 읽는다. 손으로 만든 정답 모델이고, 도면에서 만든 모델(`index.html`)을 검사하는 기준이다 |
| `model.js` | 데이터. `const MODEL = {...};` 한 줄짜리 순수 JSON |
| `viewer.js` | 그리기·입력·도면 연결 코드 전부 |
| `private/drawing.svg` | 도면 원본. `.gitignore` 로 커밋 제외 |
| `check.sh` | 합격 판정 (수정 금지) |
| `tools/extract_from_dxf.py` | 도면 DXF(`private/drawing.dxf`)에서 데이터를 뽑는 도구. 벽·슬래브·구멍·난간에 더해 계단 18런(`section_stairs`, `stair_parts`)과 TBM 터널·채움 3개(`section_tunnel`, `plan_tunnel`, `tunnel_parts`)도 뽑는다. 분기구·환기구(덕트·환기탑)는 평면도 중심과 φ(`plan_center`, `frame_angle`), 단면 높이(`section_heights`), 상자 묶음(`branch_parts`, `vent_parts`)으로 뽑는다. 나머지 부재(상부 슬래브·맨홀 목·19B 패드·침사구·하부 슬래브·바닥 콘크리트·월류벽·집수조·침사조)는 `top_slab_part`, `neck_parts`, `pad_and_sump`, `weir_parts`, `pit_parts` 로 뽑는다. 나머지 부재 뒤에 설계 규칙 파일(`tools/design_rules.json`, `load_design_rules`·`apply_design_rules`)의 🔶 부재 6개(사다리 3·환기구 사다리 2·배출관)를 붙이고, 모든 부재의 색·투명도를 kind → id 순으로 덮어쓴다. 표준 라이브러리만 쓴다. `python3 tools/extract_from_dxf.py private/drawing.dxf model_extracted.js` |
| `model_extracted.js` | 위 도구가 만든 데이터(`model.js` 와 같은 꼴). 값은 도면에서 읽은 것이라 `model.js` 와 대조해 본다 |
| `SPEC.md`, `FEATURES.json`, `PROGRESS.md` | 설계, 기능 목록, 진행 기록 |
- `index.html`, `answer.html`: 화면(도면 칸 · 가운데 막대 · 3D 칸). 스크립트는 데이터 다음 `viewer.js` 순서.
- `viewer.js`: 그리기·입력·도면 연결 코드 전부.
- `model_extracted.js`(첫 화면), `model.js`(정답지): `const MODEL = {...};` 한 줄짜리 순수 JSON.
- `tools/`: 변환 도구, 추출 도구 `extract_from_dxf.py`, 설계 규칙 `design_rules.json`, 그림 상자 설정 `views.json`.
- `private/drawing.svg`, `private/drawing_gen.svg`: 도면. 커밋된 도면은 정리본 3개뿐이다(원본 DWG 는 `.gitignore`).
- `evidence/`: WSL2 설치 증빙, 1차 커밋 기록.
- `SPEC.md`, `CLAUDE.md`, `check.sh`: 규약, 작업 규칙, 합격 판정(수정 금지).
## 실행
## 다시 만들기 (변환 패키지)
- `index.html` 이 첫 화면이다. 도면에서 만든 모델(`model_extracted.js`)을 보여 준다. `answer.html` 은 손으로 만든 정답지 화면이다.
- `index.html` 을 더블클릭해서 Chrome 또는 Edge 로 연다. 서버·인터넷은 필요 없다.
- WSL 에서 열려면 이 폴더에서 `explorer.exe index.html` 을 실행한다.
- 다시 만들기: `bash tools/make_model.sh` (DWG 를 읽어 `model_extracted.js` 와 `private/drawing_gen.svg` 를 만든다).
- 도면은 모델의 `drawing.src` 경로에서 읽는다(첫 화면은 `private/drawing_gen.svg`, 정답지는 `private/drawing.svg`). 없으면 왼쪽 칸에 그 경로를 보이는 안내 글자가 나온다.
## 데이터 (`model.js`)
- 단위는 mm, 각도는 도. 원점은 수직구 축 중심 × 지표면, Z 는 위로 +.
- 최상위: `units`("mm"), `parts`(배열), `drawing`(도면 연결, 아래 「도면 연결」 참고).
- 모든 부재 공통 필드: `id`, `name`, `kind`, `type`, `color`("#rrggbb"), `alpha`(없으면 1).
- `kind`: `wall`, `topslab`, `neck`, `slab`, `pad`, `bottom`, `lean`, `stair`, `tunnel`, `fill`, `weir`, `pit`, `ladder`, `branch`, `vent`, `railing`, `ladder_up`
| type | 쓰는 kind | 필드 |
|---|---|---|
| `ring` (세운 속 빈 원통) | wall, pipe(펌프 배출관) | `cx, cy, z0, z1, r_out, r_in` |
| `disc` (세운 원판) | topslab, slab, pad, bottom, lean | `cx, cy, z0, z1, r`, `holes`(선택) |
| `pipe` (누운 속 빈 원통) | tunnel | `x, y, z`(축 시작점), `angle_deg, length, r_out, r_in` |
| `stair` (계단 런) | stair | `z_low, z_high, risers, first_riser, riser, tread, x_top, dir(+1/−1), y0, y1` |
| `fill` (누운 원통 속 채움) | fill | `x, y, z, angle_deg, length`(pipe 와 같은 축), `r, v0, v1, half_width`(0 이면 폭 제한 없음) |
| `prism` (다각형 기둥) | weir, neck | `polygon`([x, y] 점 목록), `z0, z1`, `holes`(선택) |
| `zone` (원 안 활꼴 기둥) | pit | `r, x_min, x_max, z0, z1`(alpha 0.25) |
| `ladder` (사다리) | ladder, ladder_up | `x0, x1, yc, width, z0, z1, rung`(가로대 간격) |
| `obox` (돌린 직육면체) | branch, vent | `cx, cy, angle_deg, s0, s1, t0, t1, z0, z1`(s·t 는 돌린 축 방향) |
| `railing` (방호 난간) | railing | `z`(설치 슬래브 윗면), `h`(높이), `paths`(꺾은선 목록, 각 [x, y] 점) |
- `holes` 목록의 한 원소는 [x, y] 점 목록(다각형)이나 `{"circle": [x, y, r]}`(16각형으로 그림)이다.
- 부재 93개: wall 1 · topslab 1 · neck 2 · slab 19 · pad 1 · bottom 1 · lean 1 · stair 18 · tunnel 1 · fill 3 · weir 3 · pit 2 · ladder 1 · branch 5 · vent 13 · railing 18 · pipe 1 · ladder_up 2.
- `drawing`: `src`(도면 파일), `viewBox`([0, 0, 443, 443]), `fit`([u0, v0, u1, v1], 처음 화면에 꽉 찰 도면 상자), `section`(`x0, y0, mm_per_unit`), `plan`(`cx, cy, mm_per_unit`), `views`(그림 11장: `id, type, label` 과 그림마다 기준 값, 아래 「도면 연결」).
## 코드 (`viewer.js`)
함수 이름은 SPEC 7장과 10장의 목록을 그대로 쓴다.
**부재 → 면** (각 면은 점 배열 · 색 · alpha)
- `facesBox`: 직육면체 6면을 만든다. 분기구·환기구 등 상자 부재가 쓴다.
- `facesDisc`: 세운 원판(32각형)을 뚜껑 2장과 옆면 32장으로 만든다.
- `holePolygon`: 구멍 하나를 점 목록으로 바꾼다. `{"circle": [x, y, r]}` 는 16각형이 된다.
- `addHoles`: 뚜껑 2장(윗면·아랫면)에 구멍 고리를 넣고(evenodd), 구멍 둘레마다 세로 옆면을 더한다. `facesDiscHoles`·`facesPrism` 이 함께 쓴다.
- `facesDiscHoles`: `facesDisc` 에 구멍(`holes`)을 얹는다. 구멍 점을 `cx, cy` 만큼 옮긴 뒤 `addHoles` 를 부른다.
- `facesRing`: 세운 속 빈 원통(32각형)을 바깥면·안쪽면·윗고리·아랫고리로 만든다.
- `facesPipe`: 누운 속 빈 원통(32각형)을 축 시작점에서 `angle_deg` 방향으로 만든다.
- `facesFill`: 원을 수평선 `v0`·`v1` 로 자른 단면을 터널 축 방향으로 늘인다. `half_width` 가 있으면 그 폭 안으로만.
- `facesPrism`: 다각형을 `z0`~`z1` 로 세운 기둥(뚜껑 2장과 변마다 옆면)을 만든다. `holes` 가 있으면 `addHoles` 로 구멍을 뚫는다. 월류벽·맨홀 목이 쓴다.
- `facesZone`: 원 안에서 `x_min`~`x_max` 만 남긴 활꼴 기둥을 `facesPrism` 으로 만든다. 집수조·침사조가 쓴다.
- `facesLadder`: 사다리 기둥 2개와 가로대(`rung` 간격, 두께 25)를 상자로 만든다.
- `facesObox`: 돌린 직육면체. `facesBox` 로 (s, t, z) 상자를 만든 뒤 `angle_deg` 만큼 돌리고 (`cx, cy`) 에 놓는다. 분기구·환기구 덕트·환기탑이 쓴다.
- `facesRailing`: 방호 난간. 꺾은선 구간마다 두께 40 의 얇은 판을 `z` 부터 `z + h` 까지 세운다(옆 2·끝 2·윗면·아랫면, 판당 6장).
- `stairProfile`: 계단 한 런의 단면(경사판·단·밑면)을 (s, z) 점 목록으로 만든다. s 는 `x_top` 에서 내려가는 방향 거리다.
- `facesStair`: `stairProfile` 의 단면을 Y 띠(`y0`~`y1`) 폭만큼 늘인다. 옆면 2개와 둘레 변마다 사각형 하나.
- `buildFaces`: 모든 부재의 면을 한 줄로 모은다.
**카메라와 투영**
- `rotatePoint`: 세계 좌표를 yaw(Z축 둘레)와 pitch(기울기)로 돌린다.
- `project`: 돌린 점을 화면 기준 좌표 [오른쪽, 위, 깊이]로 바꾸고, 캔버스 픽셀로 옮긴다.
**그리기**
- `shadeColor`: `#rrggbb` 색을 밝기 계수만큼 밝게 또는 어둡게 한다.
- `sortFaces`: 면 가운데 점의 깊이가 큰 것부터 정렬한다(먼 면부터).
- `draw`: 캔버스를 지우고 면을 정렬해 차례로 칠한다. 선택된 부재는 노란색으로 그린다.
**입력 (3D 칸)**
- `onMouseDown`: 드래그 시작 위치를 기억하고, 오른쪽 버튼 또는 Shift 가 눌렸으면 화면 이동으로 정한다.
- `onMouseMove`: 드래그 중 회전이면 yaw·pitch 를, 화면 이동이면 `panView` 를 부르고 `draw` 를 다시 부른다.
- `onMouseUp`: 드래그를 끝낸다.
- `panView`: 드래그한 픽셀만큼 보는 중심(`CAM.target`)을 화면 평면에서 옮긴다.
- `unrotateVector`: 화면 기준 벡터를 세계 좌표로 되돌린다(`rotatePoint` 의 역).
- `scaleFor`: 배율 값에 맞는 mm 당 픽셀 수를 돌려준다.
- `zoomAt`: 마우스 아래 점이 그대로 머물게 배율을 바꾸고 보는 중심을 옮긴다(0.5~40 사이).
- `resetView`: 등각 화면·배율 1·보는 중심 = 모델 중심으로 되돌린다(더블클릭, 「처음 화면」 버튼).
- `onWheel`: 휠로 `zoomAt` 을 부른다.
**화면 나누기**
- `onSplitDown`: 가운데 막대 끌기를 시작한다.
- `onSplitMove`: 왼쪽 칸 폭을 창 폭의 15%~85% 로 바꾸고 3D 캔버스를 다시 맞춘다.
- `onSplitUp`: 막대 끌기를 끝낸다.
**사람 애니메이션**
- `buildWalkPath`: 계단 18런의 데이터로 내려가는 길을 만들고, 같은 길을 되짚어 올라오는 한 바퀴 경로(구간마다 길이·진행 방향)를 만든다.
- `walkerAt`: 시각(ms)에 맞는 사람의 발 위치와 진행 방향을 돌려준다. 경로 끝에 오면 처음으로 돌아간다.
- `teamAt`: 두 사람의 위치를 돌려준다. 두 번째 사람은 첫 사람보다 2초 뒤 시각(`TEAM_LAG`)으로 `walkerAt` 을 부른다.
- `facesPerson`: 사람 한 명(다리 2·몸통·머리 상자 4개)을 진행 방향에 맞춰 돌린 면들로 만든다. 색은 인자로 받는다(`WALK_COLORS`: #ff8c1a, #e07010).
- `animate`: 움직이는 동안 `requestAnimationFrame` 으로 시간을 더하고 초당 30번 이하로 `draw` 를 부른다.
- `setWalking`: 움직임을 켜거나 끄고, 「사람 ❚❚」·「사람 ▶」 글자를 바꾼다.
**도면 칸**
- `applyDrawView`: 배율을 `#drawing` 과 `#hotspots` 의 실제 width/height 로 넣고(벡터를 다시 그린다), 위치만 translate 로 옮긴다.
- `fitDrawing`: 처음 화면에서 `drawing.fit` 상자가 왼쪽 칸에 꽉 차게 배율과 위치를 정한다.
- `onDrawWheel`: 마우스 아래의 도면 점이 그대로 머물도록 확대·축소한다(0.5~40배).
- `onDrawDown`: 도면 드래그(이동)를 시작한다.
- `onDrawMove`: 드래그 중 도면을 옮긴다.
- `onDrawUp`: 드래그를 끝낸다. 움직였으면 다음 클릭은 선택으로 치지 않는다.
**도면 ↔ 부재**
- `region`: 클릭 영역 하나(부재 id 들과 다각형들)를 만든다. 다각형이 없으면 영역도 없다.
- `pathD`: 다각형 점 배열을 SVG `path` 의 `d` 글자로 바꾼다.
- `sectionPoly`: 단면 그림 한 장에서 부재 하나의 클릭 영역을 만든다. `section_break` 그림은 생략 구간을 뺀다(벽은 위·아래 두 조각).
- `circlePoly`: 평면 그림의 원(32각형)을 만든다.
- `planPoly`: 평면 그림에서 벽(고리, 가운데가 빈다)과 터널(사각형)의 클릭 영역을 만든다.
- `viewHotspots`: 그림 한 장(`MODEL.drawing.views` 의 한 항목)의 클릭 영역 목록을 만든다. 단면·평면·중간슬래브 그림 세 가지를 나눠 처리한다.
- `obox4`: 상자(obox) 바닥 윤곽 네 꼭짓점(mm)을 돌려준다. `facesObox` 와 같은 회전을 쓴다.
- `xSpan`: 부재가 덮는 X 범위(mm)를 돌려준다. 계단·집수조·침사조·사다리·월류벽·맨홀 목·상자마다 다르다.
- `planXY`: 평면 그림의 점 하나(X, Y mm)를 도면 좌표로 바꾼다.
- `bottomPlanPoly`: 하부 슬래브 평면에서 집수조·침사조(원을 X 범위로 자른 활꼴), 월류벽, 사다리의 클릭 영역을 만든다.
- `bottomHotspots`: 바닥부 클릭 영역을 만든다. 단면 A-A 두 그림, 하부 슬래브 평면, 19B 평면의 침사구(사다리 선택)를 처리한다.
- `upperHotspots`: 상부 부재의 클릭 영역을 만든다. 단면 A-A 두 그림은 상부 슬래브·맨홀 목·분기구·환기구·위쪽 사다리를 X·z 사각형으로, 평면도 1·2 는 원판(r 4850)·맨홀 목·분기구와 환기구 바닥 윤곽을 처리한다.
- `buildHotspots`: 11개 그림의 클릭 영역을 `svg#hotspots` 에 `path` 로 그린다. 같은 그림 안에서는 뒤에 나온 영역이 위에 온다. `upperHotspots` → `viewHotspots` → `bottomHotspots` 순으로 이어 붙인다.
- `selectPart`: 부재 id 배열을 고른다. 겹치는 도면 영역을 칠하고, 3D 에서 그 부재들을 노란색으로 그리고, 「선택: 그림 이름 — 부재 이름」을 쓴다. 빈 배열이면 해제한다.
## 그리기 방식
- 투영은 정사 투영이다. 처음 화면은 등각(좌우 45도, 기울기 35도).
- 드래그 = 궤도 회전: 좌우는 Z축 둘레, 위아래는 기울기(89도에서 멈춤).
- 면 음영: 법선이 빛 방향에 가까울수록 밝다(계수 0.4~1.0).
- 화가 알고리즘: 면마다 가운데 점의 깊이를 재서 먼 면부터 칠한다. 겹침은 이 순서로 해결한다.
- 벽은 `alpha` 0.25 로 반투명, 나머지는 불투명. 원은 32각형으로 근사한다.
## 도면 연결
도면은 SVG 를 `<img>` 로 띄우고, 같은 크기의 `<svg id="hotspots">` 를 겹친다. 좌표는 mm 를 도면 단위로 바꿔 쓴다. `u` 는 도면 가로, `v` 는 도면 세로(아래로 +).
- 단면 A-A: `u = x0 + X / 1000`, `v = y0 − z / 1000`
- 평면도: `u = cx + x / 1000`, `v = cy − y / 1000`
`section` 과 `plan` 의 값은 도면 선을 재서 얻었다. 값은 `model.js` 의 `drawing` 에 있다.
## 변환 패키지 (DWG → DXF → 모델)
설계도면은 DWG 로 주고받는다. DWG 는 바이너리라 GNU LibreDWG 로 DXF(글자 파일)로 바꾸고, 과제가 쓰는 그림 상자만 남겨 추출 도구에 넣는다.
설계도면은 DWG 로 주고받는다. GNU LibreDWG 로 DXF 로 바꾸고, 그림 상자 안 객체만 남겨 모델을 뽑는다.
- 설치 (WSL Ubuntu, LibreDWG 0.14 소스 빌드): `PKG_CONFIG=/bin/true ./configure --prefix=$HOME/.local --disable-bindings --disable-docs && make && make install`. `dwg2dxf` 가 `~/.local/bin` 에 생긴다.
- 실행: `bash tools/make_model.sh` (입력 `private/drawing.dwg`, 출력 `private/` 와 리포 루트의 `model_extracted.js`). 웹 왼쪽 도면은 `private/drawing_gen.svg` 를 읽는다.
- 파일 용도:
- `private/drawing.dwg`: 주고받는 원본 DWG. 커밋하지 않는다.
- `private/drawing.dxf`: 추출 입력. 그림 상자 안 객체만 남긴 것.
- `private/full.dxf`: DWG 를 바꾼 전체 DXF (중간 산출물).
- `tools/views.json`: 그림 상자 4개와 뺄 레이어·블록 이름. 사람이 정한다.
- `private/drawing_gen.svg`: 웹 표시용 그림. DXF 에서 `tools/dxf_to_svg.py` 가 만든다(상자 배치는 `views.json`).
- `private/drawing.svg`: 예전 수작업 SVG 원본. 비교용으로만 쓴다.
- 각 도구: `tools/dwg_to_dxf.sh`(DWG → DXF), `tools/select_views.py`(상자 안 객체만 남김), `tools/dxf_to_svg.py`(DXF → SVG, 표준 라이브러리만), `tools/make_model.sh`(위 도구와 추출 도구를 차례로 돌림). 추출 도구는 `views.json` 을 세 번째 인수로 받아 도면 연결값(`drawing`: 단면·평면도·슬래브 평면의 좌표와 층 높이)을 도면에서 계산한다.
- 실행: `bash tools/make_model.sh` (입력 `private/drawing.dwg`, 출력 `model_extracted.js` 와 `private/drawing_gen.svg`).
- 단계: `tools/dwg_to_dxf.sh`(DWG → DXF), `tools/select_views.py`(그림 상자 안만 남김), `tools/dxf_to_svg.py`(DXF → SVG), `tools/extract_from_dxf.py`(DXF → 모델).
## 검사
- `bash check.sh` : F01~F17 전체 검사
- `bash check.sh F06` : F01~F06 만 검사, 뒤 기능은 SKIP
- 결과 끝 줄이 `PASS n / FAIL 0` 이면 통과. 육안으로 볼 항목은 SPEC 8.2 에 있다.
- `bash check.sh` : 전체 검사. `bash check.sh F06` : F06 까지만, 뒤 기능은 SKIP.
- 끝 줄이 `PASS n / FAIL 0` 이면 통과.
## 사용 도구
- WSL2 (Ubuntu) 에서 작업. 설치일은 Ubuntu 가상 디스크를 만든 날 2026-07-09. 설치 증빙(Windows 쪽 `wsl --version`·`wsl --status`, WSL 안쪽 커널·Ubuntu·claude 버전)은 `evidence/wsl2.txt` 참고. WSL 버전 확인 (Windows 명령 프롬프트): `wsl -l -v`
- WSL2 (Ubuntu) 에서 작업. 설치 증빙은 `evidence/wsl2.txt`. 버전 확인(Windows 명령 프롬프트): `wsl -l -v`
```
NAME STATE VERSION
* Ubuntu Stopped 2
```
- Claude Code, 모델은 Haiku 5.5 (코드 작성·수정·커밋. 커밋 메시지마다 `Co-Authored-By: Claude Haiku 5.5` 줄)
- 설계 문서·검사(`SPEC.md`, `FEATURES.json`, `check.sh`)와 구동 설명서(`guide/`)는 설계를 맡은 별도 Claude(Opus) 세션이 쓰고, 하이쿠가 커밋한다(커밋 첫 줄 KIT·DOC).
- GNU LibreDWG 0.14 (DWG → DXF), Python 3 표준 라이브러리, git, 브라우저(Chrome·Edge)
- Claude Code, 모델 Haiku 5.5 (코드 작성·수정·커밋).
- GNU LibreDWG 0.14, Python 3 표준 라이브러리, git, Chrome 또는 Edge.