wing-ops/database/migration/014_prediction.sql
htlee ff085252b0 feat(phase4): Board/HNS/Prediction/Aerial/Rescue Mock → API 전환
- Board: 매뉴얼 CRUD + 첨부파일 API (012_board_ext.sql)
- HNS: 분석 CRUD 5개 API (013_hns_analysis.sql)
- Prediction: 분석/역추적/오일펜스 7개 API (014_prediction.sql)
- Aerial: 미디어/CCTV/위성 6개 API + PostGIS (015_aerial.sql)
- Rescue: 구난 작전/시나리오 3개 API + JSONB (016_rescue.sql)
- backtrackMockData.ts 삭제

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 01:17:10 +09:00

112 lines
6.7 KiB
SQL

-- 014_prediction.sql: BACKTRACK + VESSEL_INFO + BOOM_LINE 테이블
-- Phase 4 Round 3: Prediction 탭 Mock→API 전환
SET search_path TO wing, public;
-- ============================================================
-- 사고 선박 정보 (VESSEL_INFO)
-- ============================================================
CREATE TABLE IF NOT EXISTS VESSEL_INFO (
VESSEL_INFO_SN SERIAL PRIMARY KEY,
ACDNT_SN INTEGER NOT NULL REFERENCES ACDNT(ACDNT_SN) ON DELETE CASCADE,
IMO_NO VARCHAR(10),
MMSI_NO VARCHAR(10),
VESSEL_NM VARCHAR(100),
VESSEL_TP VARCHAR(30),
LOA_M NUMERIC(6,1),
BREADTH_M NUMERIC(5,1),
DRAFT_M NUMERIC(5,1),
GT NUMERIC(10,0),
DWT NUMERIC(10,0),
BUILT_YR SMALLINT,
FLAG_CD VARCHAR(5),
CALLSIGN VARCHAR(10),
ENGINE_DC VARCHAR(100),
INSURANCE_DATA JSONB,
REG_DTM TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_vessel_acdnt ON VESSEL_INFO(ACDNT_SN);
-- ============================================================
-- 역추적 분석 (BACKTRACK)
-- ============================================================
CREATE TABLE IF NOT EXISTS BACKTRACK (
BACKTRACK_SN SERIAL PRIMARY KEY,
ACDNT_SN INTEGER NOT NULL REFERENCES ACDNT(ACDNT_SN) ON DELETE CASCADE,
EST_SPIL_DTM TIMESTAMPTZ,
ANLYS_RANGE VARCHAR(20),
LON NUMERIC(10,6),
LAT NUMERIC(9,6),
GEOM GEOMETRY(Point, 4326),
LOC_DC VARCHAR(100),
SRCH_RADIUS_NM NUMERIC(5,1),
TOTAL_VESSELS INTEGER,
EXEC_STTS_CD VARCHAR(20) DEFAULT 'PENDING',
RSLT_DATA JSONB,
USE_YN CHAR(1) DEFAULT 'Y',
REG_DTM TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT CK_BACKTRACK_STTS CHECK (EXEC_STTS_CD IN ('PENDING','RUNNING','COMPLETED','FAILED'))
);
CREATE INDEX IF NOT EXISTS idx_backtrack_acdnt ON BACKTRACK(ACDNT_SN);
CREATE INDEX IF NOT EXISTS idx_backtrack_geom ON BACKTRACK USING GIST(GEOM);
-- ============================================================
-- 오일펜스 배치 (BOOM_LINE)
-- ============================================================
CREATE TABLE IF NOT EXISTS BOOM_LINE (
BOOM_LINE_SN SERIAL PRIMARY KEY,
ACDNT_SN INTEGER NOT NULL REFERENCES ACDNT(ACDNT_SN) ON DELETE CASCADE,
BOOM_NM VARCHAR(100),
PRIORITY_ORD INTEGER DEFAULT 0,
GEOM GEOMETRY(LineString, 4326),
LENGTH_M NUMERIC(8,1),
EFFICIENCY_PCT NUMERIC(5,1),
DEPLOY_DTM TIMESTAMPTZ,
STTS_CD VARCHAR(20) DEFAULT 'PLANNED',
USE_YN CHAR(1) DEFAULT 'Y',
REG_DTM TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT CK_BOOM_STTS CHECK (STTS_CD IN ('PLANNED','DEPLOYED','RETRIEVED'))
);
CREATE INDEX IF NOT EXISTS idx_boom_acdnt ON BOOM_LINE(ACDNT_SN);
CREATE INDEX IF NOT EXISTS idx_boom_geom ON BOOM_LINE USING GIST(GEOM);
-- ============================================================
-- 시드 데이터 — 여수 유조선 충돌 사고(ACDNT_SN=1) 기준
-- ============================================================
-- 선박 정보
INSERT INTO VESSEL_INFO (ACDNT_SN, IMO_NO, MMSI_NO, VESSEL_NM, VESSEL_TP, LOA_M, BREADTH_M, DRAFT_M, GT, DWT, BUILT_YR, FLAG_CD, CALLSIGN, ENGINE_DC, INSURANCE_DATA)
VALUES
(1, '9412856', '440123456', 'ORIENTAL GLORY', '유조선', 183.0, 32.2, 11.2, 29876, 46823, 2009, 'KR', 'HLOG7', 'MAN B&W 6S50MC-C', '[{"type":"P&I","insurer":"한국P&I클럽","value":"500M","currency":"USD"},{"type":"H&M","insurer":"삼성화재해상","value":"89.77M","currency":"SDR"},{"type":"CLC","insurer":"삼성화재해상","value":"89.77M","currency":"SDR"}]'::jsonb),
(1, '9538721', '413987654', 'HAI FENG 168', '벌크선', 225.0, 32.3, 14.5, 43210, 82150, 2012, 'CN', 'BQHR3', 'MAN B&W 7S50MC', '[]'::jsonb);
-- 역추적 결과
INSERT INTO BACKTRACK (ACDNT_SN, EST_SPIL_DTM, ANLYS_RANGE, LON, LAT, GEOM, LOC_DC, SRCH_RADIUS_NM, TOTAL_VESSELS, EXEC_STTS_CD, RSLT_DATA)
VALUES (
1,
'2025-02-18 06:30:00+09',
'±12시간',
127.6845, 34.7312,
ST_SetSRID(ST_MakePoint(127.6845, 34.7312), 4326),
'127.6845 + 34.7312',
10.0,
47,
'COMPLETED',
'{
"vessels": [
{"rank":1,"name":"ORIENTAL GLORY","imo":"9412856","type":"유조선","flag":"🇰🇷","flagCountry":"대한민국","probability":96.7,"closestTime":"06:28","closestDistance":0.02,"speedChange":"급감속","aisStatus":"충돌신호","description":"06:28 HAI FENG 168과 충돌 → 06:30 No.1P 탱크 파공 → 벙커C유 유출 개시.","color":"#ef4444"},
{"rank":2,"name":"HAI FENG 168","imo":"9538721","type":"벌크선","flag":"🇨🇳","flagCountry":"중국","probability":23.4,"closestTime":"06:28","closestDistance":0.02,"speedChange":"급감속","aisStatus":"미확인","description":"충돌 당사선. 구상선수 손상으로 연료유탱크 미세 누유 가능성.","color":"#f97316"},
{"rank":3,"name":"DONG JIN STAR","imo":"9287403","type":"케미컬탱커","flag":"🇰🇷","flagCountry":"대한민국","probability":4.1,"closestTime":"05:45","closestDistance":1.8,"speedChange":"정상","aisStatus":"정상","description":"","color":"#64788c"}
],
"replayShips": [
{"vesselName":"ORIENTAL GLORY","color":"#ef4444","path":[{"lat":34.82,"lon":127.58},{"lat":34.80,"lon":127.60},{"lat":34.78,"lon":127.62},{"lat":34.76,"lon":127.64},{"lat":34.75,"lon":127.66},{"lat":34.74,"lon":127.67},{"lat":34.73,"lon":127.68},{"lat":34.7312,"lon":127.6845},{"lat":34.7312,"lon":127.6845}],"speedLabels":["8.3 kts · 215°","8.3 kts · 215°","8.3 kts · 215°","8.3 kts · 215°","8.3 kts · 215°","8.3 kts · 215°","2.1 kts · 215°","0.2 kts · 정지","0.2 kts · 정지"]},
{"vesselName":"HAI FENG 168","color":"#f97316","path":[{"lat":34.64,"lon":127.78},{"lat":34.66,"lon":127.76},{"lat":34.68,"lon":127.74},{"lat":34.70,"lon":127.72},{"lat":34.71,"lon":127.71},{"lat":34.72,"lon":127.70},{"lat":34.73,"lon":127.69},{"lat":34.7312,"lon":127.6845},{"lat":34.7315,"lon":127.6840}],"speedLabels":["11.2 kts · 038°","11.2 kts · 038°","11.2 kts · 038°","11.2 kts · 038°","11.2 kts · 038°","11.2 kts · 038°","3.4 kts · 038°","0.5 kts · 정지","0.5 kts · 정지"]},
{"vesselName":"DONG JIN STAR","color":"#64788c","path":[{"lat":34.82,"lon":127.52},{"lat":34.80,"lon":127.53},{"lat":34.78,"lon":127.54},{"lat":34.76,"lon":127.55},{"lat":34.74,"lon":127.56},{"lat":34.72,"lon":127.57},{"lat":34.70,"lon":127.58},{"lat":34.68,"lon":127.59},{"lat":34.66,"lon":127.60}],"speedLabels":["10.5 kts · 180°","10.5 kts · 180°","10.5 kts · 180°","10.5 kts · 180°","10.5 kts · 180°","10.5 kts · 180°","10.5 kts · 180°","10.5 kts · 180°","10.5 kts · 180°"]}
],
"collisionEvent": {"position":{"lat":34.7312,"lon":127.6845},"timeLabel":"06:28 충돌","progressPercent":75}
}'::jsonb
);