178 lines
10 KiB
SQL
178 lines
10 KiB
SQL
CREATE TABLE "courses" (
|
|
"id" UUID NOT NULL DEFAULT gen_random_uuid(),
|
|
"slug" TEXT NOT NULL,
|
|
"title" TEXT NOT NULL,
|
|
"subtitle" TEXT,
|
|
"description" TEXT,
|
|
"organization_name" TEXT NOT NULL,
|
|
"teacher_id" UUID NOT NULL,
|
|
"is_active" BOOLEAN NOT NULL DEFAULT true,
|
|
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updated_at" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "courses_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
CREATE TABLE "course_weeks" (
|
|
"id" UUID NOT NULL DEFAULT gen_random_uuid(),
|
|
"course_id" UUID NOT NULL,
|
|
"week" INTEGER NOT NULL,
|
|
"title" TEXT NOT NULL,
|
|
"tags" TEXT[] NOT NULL,
|
|
"progress" INTEGER NOT NULL DEFAULT 0,
|
|
"state" TEXT NOT NULL,
|
|
"duration" TEXT NOT NULL,
|
|
"github" TEXT NOT NULL,
|
|
"overview" TEXT NOT NULL,
|
|
"deliverable" TEXT NOT NULL,
|
|
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updated_at" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "course_weeks_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
CREATE TABLE "course_week_topics" (
|
|
"id" UUID NOT NULL DEFAULT gen_random_uuid(),
|
|
"week_id" UUID NOT NULL,
|
|
"title" TEXT NOT NULL,
|
|
"detail" TEXT NOT NULL,
|
|
"sort_order" INTEGER NOT NULL,
|
|
|
|
CONSTRAINT "course_week_topics_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
CREATE TABLE "course_week_practices" (
|
|
"id" UUID NOT NULL DEFAULT gen_random_uuid(),
|
|
"week_id" UUID NOT NULL,
|
|
"title" TEXT NOT NULL,
|
|
"description" TEXT NOT NULL,
|
|
"sort_order" INTEGER NOT NULL,
|
|
|
|
CONSTRAINT "course_week_practices_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
CREATE UNIQUE INDEX "courses_slug_key" ON "courses"("slug");
|
|
CREATE INDEX "courses_is_active_idx" ON "courses"("is_active");
|
|
CREATE INDEX "courses_teacher_id_idx" ON "courses"("teacher_id");
|
|
CREATE UNIQUE INDEX "course_weeks_course_id_week_key" ON "course_weeks"("course_id", "week");
|
|
CREATE INDEX "course_weeks_course_id_idx" ON "course_weeks"("course_id");
|
|
CREATE UNIQUE INDEX "course_week_topics_week_id_sort_order_key" ON "course_week_topics"("week_id", "sort_order");
|
|
CREATE INDEX "course_week_topics_week_id_idx" ON "course_week_topics"("week_id");
|
|
CREATE UNIQUE INDEX "course_week_practices_week_id_sort_order_key" ON "course_week_practices"("week_id", "sort_order");
|
|
CREATE INDEX "course_week_practices_week_id_idx" ON "course_week_practices"("week_id");
|
|
|
|
ALTER TABLE "courses" ADD CONSTRAINT "courses_teacher_id_fkey" FOREIGN KEY ("teacher_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
ALTER TABLE "course_weeks" ADD CONSTRAINT "course_weeks_course_id_fkey" FOREIGN KEY ("course_id") REFERENCES "courses"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "course_week_topics" ADD CONSTRAINT "course_week_topics_week_id_fkey" FOREIGN KEY ("week_id") REFERENCES "course_weeks"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "course_week_practices" ADD CONSTRAINT "course_week_practices_week_id_fkey" FOREIGN KEY ("week_id") REFERENCES "course_weeks"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
COMMENT ON TABLE "courses" IS 'LMS 강의 마스터. 소속과 강사 기준으로 전체 강의 정보를 관리한다.';
|
|
COMMENT ON TABLE "course_weeks" IS '강의별 주차 커리큘럼 정보.';
|
|
COMMENT ON TABLE "course_week_topics" IS '주차별 학습 주제와 상세 설명.';
|
|
COMMENT ON TABLE "course_week_practices" IS '주차별 실습 내용.';
|
|
COMMENT ON COLUMN "courses"."organization_name" IS '강의를 등록한 소속명. 현재 퓨처드라이브 기준.';
|
|
COMMENT ON COLUMN "courses"."teacher_id" IS '강의를 등록한 강사 사용자 UUID.';
|
|
|
|
INSERT INTO "users" ("id", "email", "name", "createdAt", "updatedAt")
|
|
VALUES (gen_random_uuid(), 'teacher@futuredrive.net', '퓨처드라이브 강사', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
|
ON CONFLICT ("email") DO UPDATE
|
|
SET "name" = EXCLUDED."name",
|
|
"updatedAt" = CURRENT_TIMESTAMP;
|
|
|
|
WITH teacher AS (
|
|
SELECT "id" FROM "users" WHERE "email" = 'teacher@futuredrive.net'
|
|
)
|
|
INSERT INTO "courses" ("slug", "title", "subtitle", "description", "organization_name", "teacher_id", "updated_at")
|
|
SELECT
|
|
'futuredrive-autonomy-basic',
|
|
'단계별 자율주행 알고리즘 학습 과정',
|
|
'주차별 커리큘럼',
|
|
'ROS2, 센서 처리, SLAM, 객체 인식, 경로 계획까지 자율주행 알고리즘 개발 흐름을 주차별로 학습합니다.',
|
|
'퓨처드라이브',
|
|
teacher."id",
|
|
CURRENT_TIMESTAMP
|
|
FROM teacher
|
|
ON CONFLICT ("slug") DO UPDATE
|
|
SET "title" = EXCLUDED."title",
|
|
"subtitle" = EXCLUDED."subtitle",
|
|
"description" = EXCLUDED."description",
|
|
"organization_name" = EXCLUDED."organization_name",
|
|
"teacher_id" = EXCLUDED."teacher_id",
|
|
"is_active" = true,
|
|
"updated_at" = CURRENT_TIMESTAMP;
|
|
|
|
WITH course AS (
|
|
SELECT "id" FROM "courses" WHERE "slug" = 'futuredrive-autonomy-basic'
|
|
)
|
|
INSERT INTO "course_weeks" ("course_id", "week", "title", "tags", "progress", "state", "duration", "github", "overview", "deliverable", "updated_at")
|
|
SELECT course."id", data."week", data."title", data."tags", data."progress", data."state", data."duration", data."github", data."overview", data."deliverable", CURRENT_TIMESTAMP
|
|
FROM course
|
|
CROSS JOIN (
|
|
VALUES
|
|
(1, 'ROS2 기초 & 개발 환경 설정', ARRAY['시뮬레이션','완료']::TEXT[], 100, 'done', '8-10시간', '완료', 'ROS2 패키지 구조와 노드 실행 흐름을 이해하고, 실습 환경에서 기본 통신 구조를 직접 구성합니다.', '실습 노드 코드, 실행 로그, README 정리본을 GitHub에 제출'),
|
|
(2, '센서 데이터 수집 및 처리', ARRAY['MK-mini','완료']::TEXT[], 100, 'done', '8-10시간', '완료', '자율주행 시스템에서 사용하는 LiDAR와 카메라 데이터를 수집하고, ROS2 토픽 기반으로 전처리하는 흐름을 학습합니다.', '센서 토픽 분석표, 전처리 코드, 결과 캡처 이미지를 포함한 제출물'),
|
|
(3, 'SLAM & 지도 생성', ARRAY['MK-mini','진행중']::TEXT[], 65, 'current', '8-10시간', '미제출', 'Cartographer 기반 SLAM을 실행해 주행 환경 지도를 생성하고, 저장된 맵을 이용해 Localization 흐름을 검증합니다.', '생성된 map 파일, SLAM 실행 로그, Localization 검증 결과를 GitHub에 제출'),
|
|
(4, '객체 인식 & 딥러닝', ARRAY['시뮬레이션','진행예정']::TEXT[], 0, 'locked', '-', '진행예정', '카메라 기반 객체 인식 모델을 실행하고, 인식 결과를 주행 판단에 연결하는 과정을 학습합니다.', '모델 실행 로그와 인식 결과 리포트 제출'),
|
|
(5, '경로 계획 알고리즘', ARRAY['f1tenth','진행예정']::TEXT[], 0, 'locked', '-', '진행예정', '생성된 지도와 차량 상태를 기반으로 경로를 계획하고, 제어 명령으로 연결하는 전체 흐름을 정리합니다.', '경로 계획 설정값, 주행 결과 영상, 개선 사항 정리본 제출')
|
|
) AS data("week", "title", "tags", "progress", "state", "duration", "github", "overview", "deliverable")
|
|
ON CONFLICT ("course_id", "week") DO UPDATE
|
|
SET "title" = EXCLUDED."title",
|
|
"tags" = EXCLUDED."tags",
|
|
"progress" = EXCLUDED."progress",
|
|
"state" = EXCLUDED."state",
|
|
"duration" = EXCLUDED."duration",
|
|
"github" = EXCLUDED."github",
|
|
"overview" = EXCLUDED."overview",
|
|
"deliverable" = EXCLUDED."deliverable",
|
|
"updated_at" = CURRENT_TIMESTAMP;
|
|
|
|
WITH rows AS (
|
|
SELECT w."id" AS week_id, topic.*
|
|
FROM "course_weeks" w
|
|
JOIN "courses" c ON c."id" = w."course_id"
|
|
JOIN LATERAL (
|
|
VALUES
|
|
(1, 1, 'ROS2 노드 생성', '패키지 생성, 노드 실행, 로그 확인까지 ROS2 개발의 기본 흐름을 실습합니다.'),
|
|
(1, 2, '토픽 통신', 'Publisher와 Subscriber를 구성하고 메시지 타입, 주기, 토픽 이름을 확인합니다.'),
|
|
(1, 3, '파라미터 설정', '노드 파라미터를 외부에서 변경하고 launch 파일로 실행 구성을 정리합니다.'),
|
|
(2, 1, 'LiDAR 포인트클라우드', 'LiDAR 토픽을 확인하고 포인트클라우드 메시지 구조와 좌표 범위를 분석합니다.'),
|
|
(2, 2, '카메라 이미지 처리', '카메라 프레임을 수신해 기본 전처리와 시각화 결과를 확인합니다.'),
|
|
(2, 3, '센서 퓨전 기초', 'LiDAR와 카메라 데이터를 같은 주행 상황 기준으로 비교하고 센서 결합 조건을 정리합니다.'),
|
|
(3, 1, 'Cartographer SLAM', 'Cartographer 설정을 확인하고 센서 입력 조건에 맞춰 SLAM launch를 실행합니다.'),
|
|
(3, 2, '맵 저장/로드', '생성된 지도를 저장한 뒤 재로딩 과정에서 맵 파일과 설정값을 검증합니다.'),
|
|
(3, 3, 'Localization', '저장된 맵 위에서 차량 위치 추정이 안정적으로 동작하는지 확인합니다.'),
|
|
(4, 1, '객체 인식 모델 실행', '객체 인식 모델의 입력 이미지와 출력 박스 구조를 확인합니다.'),
|
|
(4, 2, 'ROS2 메시지 변환', '검출 결과를 ROS2 메시지로 변환하고 후속 노드에서 사용할 수 있게 정리합니다.'),
|
|
(4, 3, '인식 결과 시각화', '시뮬레이션 장면에서 인식 결과를 시각화하고 실패 케이스를 기록합니다.'),
|
|
(5, 1, '전역 경로 생성', '지도 기반 전역 경로를 생성하고 목적지까지의 기준 경로를 확인합니다.'),
|
|
(5, 2, '지역 경로 갱신', '주변 장애물과 차량 상태를 반영해 지역 경로를 갱신합니다.'),
|
|
(5, 3, '제어 명령 연결', '계획된 경로를 제어 명령으로 연결하고 주행 결과를 비교합니다.')
|
|
) AS topic(week_no, sort_order, title, detail) ON topic.week_no = w."week"
|
|
WHERE c."slug" = 'futuredrive-autonomy-basic'
|
|
)
|
|
INSERT INTO "course_week_topics" ("week_id", "sort_order", "title", "detail")
|
|
SELECT week_id, sort_order, title, detail FROM rows
|
|
ON CONFLICT ("week_id", "sort_order") DO UPDATE
|
|
SET "title" = EXCLUDED."title",
|
|
"detail" = EXCLUDED."detail";
|
|
|
|
WITH week3 AS (
|
|
SELECT w."id" AS week_id
|
|
FROM "course_weeks" w
|
|
JOIN "courses" c ON c."id" = w."course_id"
|
|
WHERE c."slug" = 'futuredrive-autonomy-basic' AND w."week" = 3
|
|
)
|
|
INSERT INTO "course_week_practices" ("week_id", "sort_order", "title", "description")
|
|
SELECT week3.week_id, data.sort_order, data.title, data.description
|
|
FROM week3
|
|
CROSS JOIN (
|
|
VALUES
|
|
(1, 'SLAM 개요', '동시적 위치추정 및 지도작성의 기본 개념'),
|
|
(2, 'Cartographer 설정', 'ROS2 Cartographer 패키지 설정 방법'),
|
|
(3, '실습: 맵 생성', 'LiDAR 데이터를 활용한 실시간 맵핑'),
|
|
(4, '위치 추정', '생성된 맵에서 로봇 위치 인식')
|
|
) AS data(sort_order, title, description)
|
|
ON CONFLICT ("week_id", "sort_order") DO UPDATE
|
|
SET "title" = EXCLUDED."title",
|
|
"description" = EXCLUDED."description";
|