[ { "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 } ]