# 구조물 시설종별(1종/2종/3종) 표시 필터

**소요 시간**: 약 9분 (기능개발 에이전트 기준)
**Context 사용량**: input ~추정 / output ~100k tokens (subagent_tokens 100,287 기준)

## 작업 개요

구조물(교량/터널/구교)의 **시설종별(1종/2종/3종)** 에 따라 재생바(StationBar)와 경로 패널(RoutePanel)의 표시를 필터링하는 기능을 추가했다.
플레이어에 1/2/3종 체크박스를 두어 사용자가 종별 노출을 즉시 토글할 수 있고, 선택 상태는 localStorage 에 지속된다.

### 작업 배경 (사용자 요청)
- 교량 등 **3종 구조물이 너무 많아** 재생바·패널이 혼잡 → 기본적으로 3종은 숨기고 싶다는 요청
- 시설종별 1종/2종/3종을 **체크박스로 켜고 끄는** 토글 UI 요구
- 기본값은 **1종 ☑ / 2종 ☑ / 3종 ☐** (3종만 기본 숨김)

## 변경 / 신설 파일과 핵심 내용

### client/src/types/geo.ts (변경)
- `RouteStructure` 에 `grade?: string` 추가 (시설종별 원문 문자열, 예: `"3종"`, `"2종"`, `"기타"`)

### client/src/utils/geoData.ts — parseStructures (변경)
- `pushFrom` spec 에 `gradeFallback`(시설종별 컬럼 위치 인덱스) 추가
- 시설종별을 헤더명 `'시설종별'` `indexOf` 우선 + 위치 인덱스 폴백으로 읽음
  - **교량**: 시설종별 = `idx 1`
  - **터널**: 시설종별 = `idx 5`
  - **구교(06)**: 시설종별 컬럼 없음 → `gradeFallback` 미지정 → `grade` = `undefined`
- 읽은 값은 `trim`, 빈 문자열이면 `undefined` 로 정규화

### client/src/store/settingsStore.ts (신설)
- `zustand` + `persist` 미들웨어, 저장 키 `'ghivideo.settings'`
- `gradeFilter` 기본값 `{ '1종': true, '2종': true, '3종': false }`
- `setGradeFilter(grade, visible)` 액션
- `KNOWN_GRADES`(`['1종','2종','3종']`) 와 공유 표시 규칙 `isGradeVisible` export
- `merge` 로 저장본에 누락된 키를 기본값으로 보충 (버전 호환)

### 공유 표시 규칙 — isGradeVisible
```
!grade || !KNOWN_GRADES.includes(grade) || gradeFilter[grade]
```
- `grade` 없음(구교 등) → **항상 표시**
- `grade` 가 KNOWN 미포함('기타'/'인상' 등) → **항상 표시**
- 1/2/3종 → `gradeFilter[grade] === true` 일 때만 표시

### client/src/stationbar/StationBar.tsx (변경)
- `storeStructuresRaw` 를 `isGradeVisible` 로 필터(`useMemo`, `gradeFilter` 구독) → `structureMarks` 가 필터된 목록을 사용

### client/src/components/overlay/RoutePanel.tsx (변경)
- `filteredPois` 에 `isGradeVisible` 조건 추가(동일 규칙, `gradeFilter` 구독)

### client/src/components/player/VideoPlayer.tsx (변경)
- 좌하단 컨트롤 그룹의 **배속 행 아래**에 `"시설등급"` 라벨 + 1/2/3종 체크박스 3개
- 노출 조건: `showVideoControls && geoLoaded`
- 각 체크박스는 `setGradeFilter` 에 바인딩 → 즉시 토글 반영

## 시설종별 파싱 요약

| 구분 | 파일(03/04/06) | 시설종별 컬럼 | 결과 |
|------|----------------|----------------|------|
| 교량 | 03)교량 | `idx 1` (헤더 '시설종별' 우선) | grade = "3종"/"기타" 등 |
| 터널 | 04)터널 | `idx 5` (헤더 '시설종별' 우선) | grade = "2종" 등 |
| 구교 | 06)구교 | 없음 | grade = undefined (항상 표시) |

## 기본값 / 지속

- 기본값: **1종 ☑ / 2종 ☑ / 3종 ☐**
- localStorage 키 `'ghivideo.settings'` 로 선택 상태 지속 (`zustand persist`)
- UI 위치: 플레이어 좌하단 컨트롤(배속 행 아래), `showVideoControls && geoLoaded` 일 때 노출

## 실데이터 분포 (하행)회덕-대전조차장 데이터, v2.0, 좌표필터 적용 후)

- **교량 12건**: 시설종별 3종 ×10, 기타 ×2 ("인상" 1건은 깨진 좌표로 이미 필터됨)
- **터널 2건**: 시설종별 2종 ×2
- **구교 9건**: 시설종별 컬럼 없음 → `grade` undefined(항상 표시)
- 기본값(1종☑2종☑3종☐) 적용 시: **3종 교량 10건 숨김**, 기타 교량 2건 · 터널 2건(2종) · 구교 9건 표시

## 빌드 결과

- `nvm use 20` → `npm run build -w client` → `tsc && vite build`
- 에러 0 (기존 chunk > 500kB 경고만, video.js 특성상 정상)

## 검수 포인트 / 후속 과제

- **1종 데이터 부재**: 이 데이터엔 1종 구조물이 없어 1종 체크박스의 실제 토글 효과는 1종이 포함된 다른 데이터로 검증 권장(필터 구조 자체는 완성)
- **StationOverlay 미적용**: 영상 위 측점 마커(StationOverlay)는 `structures` 를 사용하지 않으므로 필터 미적용 — 요구 범위(재생바/패널)대로
