Files
lms-be/prisma/migrations/20260609143000_add_course_environment_profiles/migration.sql
T
2026-07-07 16:09:12 +09:00

123 lines
4.0 KiB
SQL

CREATE TABLE "course_environment_profiles" (
"id" UUID NOT NULL DEFAULT gen_random_uuid(),
"course_id" UUID NOT NULL,
"week" INTEGER NOT NULL,
"platform_key" TEXT NOT NULL DEFAULT 'futuredrive-local-pc',
"profile_type" TEXT NOT NULL,
"name" TEXT NOT NULL,
"config" JSONB NOT NULL,
"enabled" BOOLEAN NOT NULL DEFAULT true,
"created_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "course_environment_profiles_pkey" PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "course_environment_profiles_course_id_week_platform_key_key"
ON "course_environment_profiles"("course_id", "week", "platform_key");
CREATE INDEX "course_environment_profiles_course_id_week_idx"
ON "course_environment_profiles"("course_id", "week");
CREATE INDEX "course_environment_profiles_profile_type_idx"
ON "course_environment_profiles"("profile_type");
ALTER TABLE "course_environment_profiles"
ADD CONSTRAINT "course_environment_profiles_course_id_fkey"
FOREIGN KEY ("course_id")
REFERENCES "courses"("id")
ON DELETE CASCADE
ON UPDATE CASCADE;
COMMENT ON TABLE "course_environment_profiles" IS '강좌/주차/플랫폼별 개발환경 실행 프로파일.';
COMMENT ON COLUMN "course_environment_profiles"."config" IS 'Docker runtime, ROS launch, bridge, viewer 실행 설정 JSON.';
INSERT INTO "course_environment_profiles" (
"course_id",
"week",
"platform_key",
"profile_type",
"name",
"config",
"updated_at"
)
SELECT
course."id",
3,
'futuredrive-local-pc',
'SLAM',
'TurtleBot3 SLAM 로컬 시뮬레이션',
'{
"type": "SLAM",
"viewer": {
"type": "slam",
"url": "/slam-viewer/index.html",
"healthUrl": "http://localhost:8765/health"
},
"runtime": {
"containers": [
{
"name": "nav2-slam",
"image": "nav2-slam:humble",
"network": "host",
"privileged": true,
"env": {
"DISPLAY": ":1",
"QT_X11_NO_MITSHM": "1",
"LIBGL_ALWAYS_SOFTWARE": "1",
"TURTLEBOT3_MODEL": "burger"
},
"volumes": [
"/tmp/.X11-unix:/tmp/.X11-unix",
"/dev/shm:/dev/shm",
"~/.gazebo:/root/.gazebo",
"~/.cache:/root/.cache"
],
"command": "tail -f /dev/null"
}
],
"steps": [
{
"container": "nav2-slam",
"mode": "execDetached",
"delayMs": 0,
"command": "ros2 launch gazebo_ros gzserver.launch.py world:=/opt/ros/humble/share/turtlebot3_gazebo/worlds/turtlebot3_world.world & ros2 launch turtlebot3_gazebo robot_state_publisher.launch.py use_sim_time:=true & sleep 6; ros2 launch turtlebot3_gazebo spawn_turtlebot3.launch.py x_pose:=-2.0 y_pose:=-0.5; wait",
"logFile": "/tmp/turtlebot3_gazebo.log"
},
{
"container": "nav2-slam",
"mode": "execDetached",
"delayMs": 6000,
"command": "ros2 launch slam_toolbox online_async_launch.py use_sim_time:=true",
"logFile": "/tmp/slam_toolbox.log"
},
{
"container": "nav2-slam",
"mode": "execDetached",
"delayMs": 3000,
"command": "ros2 launch nav2_bringup navigation_launch.py use_sim_time:=true autostart:=true",
"logFile": "/tmp/nav2.log"
}
]
},
"bridge": {
"name": "slam-ros-bridge",
"image": "slam-ros-bridge",
"buildContext": "resources/slam-ros-bridge",
"port": 8765,
"env": {
"ODOM_TOPIC": "/odom",
"SCAN_TOPIC": "/scan",
"MAP_TOPIC": "/map",
"CMD_VEL_TOPIC": "/cmd_vel",
"NAVIGATE_TO_POSE_ACTION": "/navigate_to_pose"
}
}
}'::jsonb,
CURRENT_TIMESTAMP
FROM "courses" AS course
ON CONFLICT ("course_id", "week", "platform_key") DO UPDATE
SET
"profile_type" = EXCLUDED."profile_type",
"name" = EXCLUDED."name",
"config" = EXCLUDED."config",
"enabled" = true,
"updated_at" = CURRENT_TIMESTAMP;