feat(M02): 48-1 구조물 정의 한 벌 — 정의 틀 문서 · 판 1 옮김 · 읽기 길

- 정의 틀 = docs/raw/M02_구조물옵션정의/정의_틀.md (담는 것 · 키 규칙 · 꼴 · 배치 · 그룹 형상 · 규칙 · 동작 · 판 이력)
- resources/master_template/구조물정의.json 판 1 = 옛 B05 레지스트리(37종 · 옵션 235) + 옵션표시 + 옵션그룹 키 그대로 옮김
- GET /api/m02/structure-definition(로그인) · PUT(시스템 관리자만 · 판 +1 · 이력 판_N) · 검사(꼴 · 키 겹침 · 규칙 대상)
- GET /structure-types · B05 구조물 검사가 새 정의를 읽음(응답 꼴 그대로) · 옵션 보이기 · 그룹 저장도 정의 칸으로
- 프로젝트 structures.json 에 저장 때 정의 판 · 정의에 없는 키 값은 남김(오류 없음)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYJJRCfHfdCGNhmXTjQKV7
This commit is contained in:
2026-10-05 16:09:33 +09:00
co-authored by Claude Opus 5.5
parent 4600b9970c
commit bf1fa50817
22 changed files with 1194 additions and 285 deletions
@@ -0,0 +1,101 @@
# 구조물 정의 틀 (PLAN 48-1)
정본 = `resources/master_template/구조물정의.json` 한 벌. 서버 · 화면은 이 한 벌만 읽음.
## 1. 길
| 길 | 누가 | 하는 것 |
| --- | --- | --- |
| `GET /api/m02/structure-definition` | 로그인 누구나 | 정의 한 벌 그대로 |
| `PUT /api/m02/structure-definition` `{판, 정의}` | 시스템 관리자만(아니면 403) | 통째로 고쳐 씀 · 낡은 판 409 · 검사 틀림 422 |
| `GET /api/projects/structure-types` | 로그인 | 정의의 `types` + `표시` · `그룹` 을 옛 꼴 그대로(`visible` · `groups`) |
| `PUT /api/m02/structure-options` · `structure-option-groups` | 시스템 관리자 | 정의의 `표시` · `그룹` 칸만 고쳐 씀(같은 판 · 같은 이력) |
- 서버 읽기 = `B05_Profile_Structures_Schema.load_definition()` · `load_structure_types()` · 쓰기 = `M02_SO_Definition.save()` · `save_sections()`.
## 2. 담는 것
| 칸 | 꼴 | 뜻 |
| --- | --- | --- |
| `판` | 정수 | 저장마다 +1 · 앞 판은 `구조물정의_이력/판_N.json` |
| `schema_version` · `comment` | 수 · 글 | 옛 레지스트리 머리 그대로 |
| `구조물군` | `{군 키: 이름}` | 구조물군 이름(A 횡단배수 …) |
| `동작` | `{동작 이름: 뜻}` | 손코딩 특수 동작 목록(5장) |
| `types` | 종류 목록 | 종류 · 옵션 · 선택지 · 기본값 · placement 등(옛 `B05_Profile_Structure_Types.json` 꼴 그대로) |
| `종류` | `{종류 키: {기준측점?, 동작?}}` | 종류마다 덧칸 — 없으면 기본 |
| `표시` | `{종류 키: {옵션 키: false}}` | 끈 옵션만(옛 `구조물옵션표시.json`) |
| `그룹` | `{종류 키: [그룹]}` | 옵션 그룹(옛 `구조물옵션그룹.json` · 46장) + 형상 칸 |
| `배치` | `{종류 키: {옵션 키: {줄, 칸, 너비}}}` | B05 · B06 좌측 「구조물 배치」 칸 자리 — 없으면 지금 차례 |
| `규칙` | 규칙 목록 | 상위 옵션 값 → 하위 옵션(4장) |
## 3. 키 규칙
- 키 = 만들 때 자동 · 안 바뀜 · 영문 소문자 · 숫자 · `_`. 이름(`name` · `label` · 선택지 글 · 그룹 `이름`)은 자유.
- 종류 키(`type_id`) 는 정의 안에서 하나 · 옵션 키(`key`) 는 종류 안에서 하나 · 그룹 id 는 `g` + 소문자 · 숫자.
- 지움 = 「안 씀」(`enabled: false`) — 종류 · 옵션을 목록에서 빼지 않음.
- 저장된 값의 키가 지금 정의에 없으면 = 지난 정의 값 — 버리지 않고 남김(오류 없음 · 계산은 없는 값으로).
- 프로젝트 `structures.json` 에 저장 때 정의 판(`definition_version`).
## 4. 옵션
### 꼴
| `input` | 이름 | 값 |
| --- | --- | --- |
| `select` | 고르기 | `choices` 중 하나(선택지 있어야 함) |
| `number` | 숫자 | 0 이상 수 · `unit` |
| `text` | 글 | 글 |
| `bool` | 예/아니오 | 참 · 거짓 |
- 옵션 덧칸(옛 그대로) = `label` · `choices` · `unit` · `default` · `required` · `phase`(b05 · detail) · `enabled` · `empty_means` · `default_basis` · `warn_above` · `warn_message` · `not_in_table`.
### 배치 칸
- `줄` = 몇째 줄(1부터) · `칸` = 그 줄 몇째 칸(1부터) · `너비` = 칸 몇 개 차지(1부터). 셋 다 1 이상 정수.
### 그룹
```
{"id": "g1a2b3c", "이름": "유입구 기슭막이", "옵션": ["옵션 키", …],
"형상": {"길이": {"받기": true, "뜻": "유입구 기슭막이 연장"}, "높이": {…}, "전": {…}, "후": {…}}}
```
- 옵션 하나는 한 종류 안에서 그룹 하나에만 · 빈 그룹(옵션 0)도 그룹 · 그룹에 안 넣은 옵션 = 본체 칸.
- `형상` = 그룹이 받을 형상 칸(길이 · 높이 · 기준 측점 전 · 후) — 칸마다 `받기`(켬끔) + `뜻`(무엇을 정하는지). 없는 칸 = 안 받음.
### 종류 덧칸
- `기준측점` = 종류 맨 위 기준 측점 칸 보이기(없으면 보임).
- `동작` = 이 종류에 붙인 특수 동작 이름들(`동작` 목록 안에서).
## 5. 규칙 꼴
```
{"종류": "종류 키",
"만약": {"옵션": "상위 옵션 키", "값들": ["값", …]},
"그러면": {"옵션": "하위 옵션 키", "선택지": ["값", …], "보이기": false, "기본값": "값"}}
```
- 만약 상위 옵션 = 값들 중 하나 → 그러면 하위 옵션의 선택지 / 보이기 / 기본값(셋 중 하나 이상).
- 상위 · 하위는 같은 종류 안 · 서로 다른 옵션 · 고르기 꼴이면 값들은 선택지 안 · 하위 `선택지` 는 고르기 꼴의 선택지 안 · `기본값` 은 (좁힌) 선택지 안.
- 계산 · 연동 제어는 넣지 않음(48-5).
## 6. 동작 이름(손코딩 특수 동작)
| 이름 | 붙은 종류 | 하는 것 |
| --- | --- | --- |
| `계곡통과시설` | pipe · box_culvert · ford_pavement · ford_bridge · revetment | 관 지점 정본 시설 — 부속 옵션 서브폼 · 저장은 폼이 아는 칸만 |
| `유입유출_묶음` | pipe | 유입구(집수정 · 기슭막이 택일) · 유출구(기슭막이) 소그룹 |
| `기슭막이_한벌` | pipe · revetment | 형태 · 길이 · 높이 · 바닥 보호공 한 벌 |
| `BOX_본체규격` | box_culvert | 본체 규격 프리셋(폭 × 높이) |
| `날개벽` | box_culvert · ford_bridge | 날개벽 유입 · 유출 · 짧은쪽 높이 · 길이 · 각도 |
| `월류단면` | ford_pavement · ford_bridge | 월류 폭 · 높이 · 바닥 경사 · 포장 두께 + 개략 단면 · 필요 수심 미만 되돌림 |
| `포장_물넘이_겹침` | pavement_concrete | 포장 구간이 물넘이를 품으면 나눔 · 끝만 걸치면 저장 멈춤 |
- 정의에서 붙이고 뗌 = `종류.{키}.동작` · 새 동작은 코딩 뒤 목록에 이름을 더함.
## 7. 판 · 이력
- 저장 = 읽어 간 `판` 을 같이 보냄 → 같으면 앞 판을 `구조물정의_이력/판_N.json` 으로 남기고 새 판 = N + 1.
- 검사(틀리면 422 · 안 씀) = 칸 꼴 · 종류 키 · 옵션 키 겹침 · 고르기 선택지 있음 · 구조물군 있음 · 표시 · 그룹 · 배치 · 종류 덧칸 · 규칙 대상 있음.
- 판 1 = 옛 `B05_Profile_Structure_Types.json`(37종 · 옵션 235) + `구조물옵션표시.json` + `구조물옵션그룹.json` 을 키 그대로 옮김.