From 933d4417a5eb93467b0f5da85b0dd8529d2cb6aa Mon Sep 17 00:00:00 2001 From: salirezav Date: Wed, 3 Dec 2025 17:23:31 -0500 Subject: [PATCH] Update Docker configuration, enhance error handling, and improve logging - Added health check to the camera management API service in docker-compose.yml for better container reliability. - Updated installation scripts in Dockerfile to check for existing dependencies before installation, improving efficiency. - Enhanced error handling in the USDAVisionSystem class to allow partial operation if some components fail to start, preventing immediate shutdown. - Improved logging throughout the application, including more detailed error messages and critical error handling in the main loop. - Refactored WebSocketManager and CameraMonitor classes to use debug logging for connection events, reducing log noise. --- .gitignore | 3 + .../usda_vision_system/api/server.py | 10 +- .../usda_vision_system/camera/monitor.py | 30 +- .../usda_vision_system/camera/streamer.py | 77 +- .../usda_vision_system/main.py | 47 +- camera_files_list.csv | 158 + docker-compose.yml | 35 +- docs/CONTAINER_CRASH_DEBUGGING.md | 141 + .../phase_2_JC_experimental_run_sheet.csv | 122 +- .../src/components/CameraPage.tsx | 80 +- .../src/components/DashboardLayout.tsx | 10 +- .../src/components/DataEntry.tsx | 35 +- .../src/components/ErrorBoundary.tsx | 48 +- .../src/components/Scheduling.tsx | 19 +- .../src/lib/supabase.ts | 99 +- .../supabase/.temp/cli-latest | 2 +- .../supabase/config.toml | 2 +- .../supabase/migrations/00005_experiments.sql | 5 +- .../migrations/00008_phase_data_tables.sql | 38 +- .../supabase/migrations/00011_views.sql | 18 +- ...dd_repetition_id_to_cracker_parameters.sql | 35 + .../supabase/seed_02_phase2_experiments.sql | 3196 +++++++++++++++++ .../src/components/Scheduling.tsx | 17 +- scheduling-remote/src/services/supabase.ts | 85 +- scheduling-remote/vite.config.ts | 8 + scripts/diagnose_container_crashes.sh | 61 + video-remote/src/components/FiltersBar.tsx | 40 +- video-remote/src/components/VideoList.tsx | 44 +- video-remote/src/components/VideoModal.tsx | 67 +- video-remote/src/services/video.ts | 2 +- 30 files changed, 4314 insertions(+), 220 deletions(-) create mode 100644 camera_files_list.csv create mode 100644 docs/CONTAINER_CRASH_DEBUGGING.md create mode 100644 management-dashboard-web-app/supabase/migrations/00013_add_repetition_id_to_cracker_parameters.sql create mode 100644 management-dashboard-web-app/supabase/seed_02_phase2_experiments.sql create mode 100755 scripts/diagnose_container_crashes.sh diff --git a/.gitignore b/.gitignore index 0937301..541bba4 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,6 @@ camera-management-api/usda_vision_system.log camera-management-api/camera_sdk/ camera-management-api/core management-dashboard-web-app/users.txt + +# Jupyter Notebooks +*.ipynb diff --git a/camera-management-api/usda_vision_system/api/server.py b/camera-management-api/usda_vision_system/api/server.py index 712e718..9bae01f 100644 --- a/camera-management-api/usda_vision_system/api/server.py +++ b/camera-management-api/usda_vision_system/api/server.py @@ -44,12 +44,12 @@ class WebSocketManager: async def connect(self, websocket: WebSocket): await websocket.accept() self.active_connections.append(websocket) - self.logger.info(f"WebSocket connected. Total connections: {len(self.active_connections)}") + self.logger.debug(f"WebSocket connected. Total connections: {len(self.active_connections)}") def disconnect(self, websocket: WebSocket): if websocket in self.active_connections: self.active_connections.remove(websocket) - self.logger.info(f"WebSocket disconnected. Total connections: {len(self.active_connections)}") + self.logger.debug(f"WebSocket disconnected. Total connections: {len(self.active_connections)}") async def send_personal_message(self, message: dict, websocket: WebSocket): try: @@ -300,9 +300,11 @@ class APIServer: asyncio.set_event_loop(self._event_loop) # Map our log level to uvicorn's log level + # Use "warning" for uvicorn to reduce noise (connection open/close messages) + # Application logs will still use the configured log level uvicorn_log_level_map = { - "DEBUG": "debug", - "INFO": "info", + "DEBUG": "warning", # Suppress uvicorn DEBUG logs even if app is in DEBUG mode + "INFO": "warning", # Suppress uvicorn INFO logs (connection messages) "WARNING": "warning", "ERROR": "error", "CRITICAL": "critical" diff --git a/camera-management-api/usda_vision_system/camera/monitor.py b/camera-management-api/usda_vision_system/camera/monitor.py index 56ab7cb..70210ea 100644 --- a/camera-management-api/usda_vision_system/camera/monitor.py +++ b/camera-management-api/usda_vision_system/camera/monitor.py @@ -151,42 +151,42 @@ class CameraMonitor: # ALWAYS check our streamer state first, before doing any camera availability tests streamer = self.camera_manager.camera_streamers.get(camera_name) - self.logger.info(f"Checking streamer for {camera_name}: {streamer}") + self.logger.debug(f"Checking streamer for {camera_name}: {streamer}") if streamer and streamer.is_streaming(): - self.logger.info(f"Camera {camera_name} is streaming - setting status to streaming") + self.logger.debug(f"Camera {camera_name} is streaming - setting status to streaming") return "streaming", "Camera streaming (live preview)", self._get_device_info_dict(device_info) # Also check if our recorder is active recorder = self.camera_manager.camera_recorders.get(camera_name) if recorder and recorder.hCamera and recorder.recording: - self.logger.info(f"Camera {camera_name} is recording - setting status to available") + self.logger.debug(f"Camera {camera_name} is recording - setting status to available") return "available", "Camera recording (in use by system)", self._get_device_info_dict(device_info) # Check if camera is already opened by another process try: - self.logger.info(f"Checking if camera {camera_name} is opened...") + self.logger.debug(f"Checking if camera {camera_name} is opened...") is_opened = mvsdk.CameraIsOpened(device_info) - self.logger.info(f"CameraIsOpened result for {camera_name}: {is_opened}") + self.logger.debug(f"CameraIsOpened result for {camera_name}: {is_opened}") if is_opened: - self.logger.info(f"Camera {camera_name} is opened by another process - setting status to busy") + self.logger.debug(f"Camera {camera_name} is opened by another process - setting status to busy") return "busy", "Camera opened by another process", self._get_device_info_dict(device_info) else: - self.logger.info(f"Camera {camera_name} is not opened, will try initialization") + self.logger.debug(f"Camera {camera_name} is not opened, will try initialization") # Camera is not opened, so we can try to initialize it pass except Exception as e: self.logger.warning(f"CameraIsOpened failed for {camera_name}: {e}") # If we can't determine the status, try to initialize to see what happens - self.logger.info(f"CameraIsOpened failed for {camera_name}, will try initialization: {e}") + self.logger.debug(f"CameraIsOpened failed for {camera_name}, will try initialization: {e}") # Try to initialize camera briefly to test availability try: # Ensure SDK is initialized ensure_sdk_initialized() - self.logger.info(f"Attempting to initialize camera {camera_name} for availability test...") + self.logger.debug(f"Attempting to initialize camera {camera_name} for availability test...") # Check if camera is already in use by recorder or streamer before trying to initialize recorder = self.camera_manager.camera_recorders.get(camera_name) if self.camera_manager else None @@ -198,7 +198,7 @@ class CameraMonitor: # Check if recorder has camera open if mvsdk.CameraIsOpened(recorder.hCamera): camera_in_use = True - self.logger.info(f"Camera {camera_name} is already in use by recorder (handle: {recorder.hCamera})") + self.logger.debug(f"Camera {camera_name} is already in use by recorder (handle: {recorder.hCamera})") except: pass @@ -207,13 +207,13 @@ class CameraMonitor: # Check if streamer has camera open if mvsdk.CameraIsOpened(streamer.hCamera): camera_in_use = True - self.logger.info(f"Camera {camera_name} is already in use by streamer (handle: {streamer.hCamera})") + self.logger.debug(f"Camera {camera_name} is already in use by streamer (handle: {streamer.hCamera})") except: pass # If camera is already in use, mark as available (since it's working, just occupied) if camera_in_use: - self.logger.info(f"Camera {camera_name} is in use by system components - marking as available") + self.logger.debug(f"Camera {camera_name} is in use by system components - marking as available") return "available", "Camera is in use by system", self._get_device_info_dict(device_info) # Suppress output to avoid MVCAMAPI error messages during camera testing @@ -221,7 +221,7 @@ class CameraMonitor: try: with suppress_camera_errors(): hCamera = mvsdk.CameraInit(device_info, -1, -1) - self.logger.info(f"Camera {camera_name} initialized successfully, starting test capture...") + self.logger.debug(f"Camera {camera_name} initialized successfully, starting test capture...") except mvsdk.CameraException as init_e: error_msg = f"CameraInit failed for {camera_name}: {init_e.message} (error_code: {init_e.error_code})" @@ -256,14 +256,14 @@ class CameraMonitor: mvsdk.CameraSetTriggerMode(hCamera, 0) mvsdk.CameraPlay(hCamera) - self.logger.info(f"Camera {camera_name} test: Attempting to capture frame with {CAMERA_TEST_CAPTURE_TIMEOUT}ms timeout...") + self.logger.debug(f"Camera {camera_name} test: Attempting to capture frame with {CAMERA_TEST_CAPTURE_TIMEOUT}ms timeout...") # Try to capture with short timeout pRawData, FrameHead = mvsdk.CameraGetImageBuffer(hCamera, CAMERA_TEST_CAPTURE_TIMEOUT) mvsdk.CameraReleaseImageBuffer(hCamera, pRawData) # Success - camera is available mvsdk.CameraUnInit(hCamera) - self.logger.info(f"Camera {camera_name} test successful - camera is available") + self.logger.debug(f"Camera {camera_name} test successful - camera is available") return "available", "Camera test successful", self._get_device_info_dict(device_info) except mvsdk.CameraException as capture_e: diff --git a/camera-management-api/usda_vision_system/camera/streamer.py b/camera-management-api/usda_vision_system/camera/streamer.py index 8b14e6c..0b957da 100644 --- a/camera-management-api/usda_vision_system/camera/streamer.py +++ b/camera-management-api/usda_vision_system/camera/streamer.py @@ -90,8 +90,20 @@ class CameraStreamer: """Start streaming preview frames""" with self._lock: if self.streaming: - self.logger.warning("Streaming already active") - return True + self.logger.warning("Streaming already active - checking if thread is alive") + # Check if thread is actually running + if self._streaming_thread and self._streaming_thread.is_alive(): + self.logger.info("Streaming thread is alive, returning success") + return True + else: + # Thread died but flag wasn't reset - clean up and restart + self.logger.warning("Streaming flag set but thread is dead - cleaning up and restarting") + self.streaming = False + if self.hCamera is not None: + try: + self._cleanup_camera() + except Exception as e: + self.logger.error(f"Error cleaning up stale camera handle: {e}") try: # Initialize camera for streaming @@ -249,6 +261,15 @@ class CameraStreamer: try: self.logger.info(f"Initializing camera for streaming: {self.camera_config.name}") + # Safety check: ensure no stale camera handle exists + if self.hCamera is not None and not self._using_shared_camera: + self.logger.warning("Stale camera handle detected during initialization - cleaning up first") + try: + mvsdk.CameraUnInit(self.hCamera) + except Exception as e: + self.logger.warning(f"Error cleaning up stale handle: {e}") + self.hCamera = None + # Check if recorder is active and has camera open - if so, share it if self.recorder and self.recorder.hCamera and self.recorder.recording: self.logger.info("Recorder is active with camera open - will share recorder's camera connection") @@ -423,11 +444,41 @@ class CameraStreamer: time.sleep(STREAMING_LOOP_SLEEP) # Just wait, recorder populates queues continue + # Safety check: ensure camera handle is valid before use + if self.hCamera is None: + self.logger.error("Camera handle is None in streaming loop - stopping") + break + # Capture frame with timeout - pRawData, FrameHead = mvsdk.CameraGetImageBuffer(self.hCamera, CAMERA_GET_BUFFER_TIMEOUT) + try: + pRawData, FrameHead = mvsdk.CameraGetImageBuffer(self.hCamera, CAMERA_GET_BUFFER_TIMEOUT) + except mvsdk.CameraException as e: + if e.error_code == mvsdk.CAMERA_STATUS_TIME_OUT: + continue # Timeout is normal, continue + else: + self.logger.error(f"CameraGetImageBuffer failed: {e.message} (error_code: {e.error_code})") + # If camera is invalid, break to prevent segfault + if e.error_code in [mvsdk.CAMERA_STATUS_INVALID_HANDLE, mvsdk.CAMERA_STATUS_INVALID_PARAM]: + self.logger.error("Invalid camera handle detected - stopping streaming loop") + break + time.sleep(BRIEF_PAUSE_SLEEP) + continue # Process frame - mvsdk.CameraImageProcess(self.hCamera, pRawData, self.frame_buffer, FrameHead) + try: + mvsdk.CameraImageProcess(self.hCamera, pRawData, self.frame_buffer, FrameHead) + except mvsdk.CameraException as e: + self.logger.error(f"CameraImageProcess failed: {e.message} (error_code: {e.error_code})") + # Release buffer before continuing + try: + mvsdk.CameraReleaseImageBuffer(self.hCamera, pRawData) + except: + pass + if e.error_code in [mvsdk.CAMERA_STATUS_INVALID_HANDLE, mvsdk.CAMERA_STATUS_INVALID_PARAM]: + self.logger.error("Invalid camera handle in image process - stopping streaming loop") + break + time.sleep(BRIEF_PAUSE_SLEEP) + continue # Convert to OpenCV format frame = self._convert_frame_to_opencv(FrameHead) @@ -477,7 +528,14 @@ class CameraStreamer: pass # Release buffer - mvsdk.CameraReleaseImageBuffer(self.hCamera, pRawData) + try: + mvsdk.CameraReleaseImageBuffer(self.hCamera, pRawData) + except mvsdk.CameraException as e: + self.logger.error(f"CameraReleaseImageBuffer failed: {e.message} (error_code: {e.error_code})") + # If handle is invalid, break to prevent further issues + if e.error_code in [mvsdk.CAMERA_STATUS_INVALID_HANDLE, mvsdk.CAMERA_STATUS_INVALID_PARAM]: + self.logger.error("Invalid camera handle when releasing buffer - stopping streaming loop") + break # Control frame rate time.sleep(1.0 / self.preview_fps) @@ -491,6 +549,15 @@ class CameraStreamer: self.logger.error(f"Fatal error in streaming loop: {e}") finally: self.logger.info("Streaming loop ended") + # Reset streaming flag when loop ends + with self._lock: + self.streaming = False + # Cleanup camera resources if not already done + if self.hCamera is not None and not self._using_shared_camera: + try: + self._cleanup_camera() + except Exception as cleanup_e: + self.logger.error(f"Error during cleanup after loop ended: {cleanup_e}") def _convert_frame_to_opencv(self, FrameHead) -> Optional[np.ndarray]: """Convert camera frame to OpenCV format""" diff --git a/camera-management-api/usda_vision_system/main.py b/camera-management-api/usda_vision_system/main.py index ae4688d..0dd174b 100644 --- a/camera-management-api/usda_vision_system/main.py +++ b/camera-management-api/usda_vision_system/main.py @@ -208,23 +208,50 @@ class USDAVisionSystem: def run(self) -> None: """Run the system (blocking call)""" if not self.start(): - self.logger.error("Failed to start system") - return + self.logger.error("Failed to start system - some components may not be available") + # Don't exit immediately - allow partial operation if some components started + # Only exit if critical components failed + if not self.running: + self.logger.critical("Critical components failed to start - exiting") + return try: self.logger.info("System running... Press Ctrl+C to stop") # Main loop - just keep the system alive + consecutive_errors = 0 + max_consecutive_errors = 10 + while self.running: - time.sleep(1) + try: + time.sleep(1) + consecutive_errors = 0 # Reset on successful iteration - # Periodic maintenance tasks could go here - # For example: cleanup old recordings, health checks, etc. + # Periodic maintenance tasks could go here + # For example: cleanup old recordings, health checks, etc. + + # Health check: verify critical components are still running + if not self.mqtt_client.is_running(): + self.logger.warning("MQTT client stopped running - attempting restart") + try: + self.mqtt_client.start() + except Exception as e: + self.logger.error(f"Failed to restart MQTT client: {e}") + consecutive_errors += 1 + + except Exception as e: + consecutive_errors += 1 + self.logger.error(f"Error in main loop (consecutive: {consecutive_errors}): {e}", exc_info=True) + + # If too many consecutive errors, exit to prevent infinite crash loop + if consecutive_errors >= max_consecutive_errors: + self.logger.critical(f"Too many consecutive errors ({consecutive_errors}) - shutting down to prevent crash loop") + break except KeyboardInterrupt: self.logger.info("Keyboard interrupt received") except Exception as e: - self.logger.error(f"Unexpected error in main loop: {e}") + self.logger.error(f"Unexpected error in main loop: {e}", exc_info=True) finally: self.stop() @@ -270,8 +297,14 @@ def main(): try: system.run() + except KeyboardInterrupt: + logging.info("Interrupted by user") + sys.exit(0) except Exception as e: - logging.error(f"Fatal error: {e}") + logging.critical(f"Fatal error: {e}", exc_info=True) + # Give a moment for logs to flush + import time + time.sleep(1) sys.exit(1) diff --git a/camera_files_list.csv b/camera_files_list.csv new file mode 100644 index 0000000..1ccc495 --- /dev/null +++ b/camera_files_list.csv @@ -0,0 +1,158 @@ +file_path,size_mb,modification_date +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251020_102330.mp4 ,3410.421639442444,2025-10-20 14:31:07 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251020_103514.mp4 ,419.6413583755493,2025-10-20 14:36:13 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251017_104209.mp4 ,574.8742876052856,2025-10-17 14:43:26 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251016_152522.mp4 ,712.9073238372803,2025-10-16 19:27:03 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251015_163710.mp4 ,350.00945472717285,2025-10-15 20:37:59 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251021_164306.mp4 ,2726.057611465454,2025-10-21 20:49:32 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251020_103703.mp4 ,334.27384853363037,2025-10-20 14:37:51 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251024_152619.mp4 ,435.3051357269287,2025-10-24 19:27:22 +/mnt/nfs_share/camera1/20251027_132411_manual_camera1_2025-10-27T17-24-11-427Z.mp4 ,877.6074295043945,2025-10-27 17:26:26 +/mnt/nfs_share/camera1/camera1_recording_20251112_102752.mp4 ,3077.46688079834,2025-11-12 15:35:05 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251023_154822.mp4 ,577.4699993133545,2025-10-23 19:49:45 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251027_152153.mp4 ,3774.1054792404175,2025-10-27 19:30:33 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251016_151728.mp4 ,3187.0334615707397,2025-10-16 19:24:28 +/mnt/nfs_share/camera1/camera1_recording_20251111_154656.mp4 ,655.5560483932495,2025-11-11 20:48:32 +/mnt/nfs_share/camera1/camera1_recording_20251112_104113.mp4 ,394.5743455886841,2025-11-12 15:42:16 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251015_162336.mp4 ,3033.105086326599,2025-10-15 20:30:24 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251020_103306.mp4 ,383.97029209136963,2025-10-20 14:34:00 +/mnt/nfs_share/camera1/camera1_recording_20251104_145939.mp4 ,0.4626617431640625,2025-11-04 20:00:07 +/mnt/nfs_share/camera1/camera1_recording_20251104_150128.mp4 ,0.5523891448974609,2025-11-04 20:01:59 +/mnt/nfs_share/camera1/camera1_recording_20251105_110148.mp4 ,408.48339462280273,2025-11-05 16:09:06 +/mnt/nfs_share/camera1/camera1_recording_20251111_154959.mp4 ,400.1362237930298,2025-11-11 20:51:00 +/mnt/nfs_share/camera1/camera1_recording_20251105_102113.mp4 ,30.384151458740234,2025-11-05 15:21:43 +/mnt/nfs_share/camera1/camera1_recording_20251105_151913.mp4 ,450.43613052368164,2025-11-05 20:20:19 +/mnt/nfs_share/camera1/camera1_recording_20251104_144649.mp4 ,578.5874738693237,2025-11-04 19:59:38 +/mnt/nfs_share/camera1/camera1_recording_20251104_114823.mp4 ,42.34638595581055,2025-11-04 16:48:29 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251027_153308.mp4 ,280.2379455566406,2025-10-27 19:33:51 +/mnt/nfs_share/camera1/20251027_132245_manual_camera1_2025-10-27T17-22-45-785Z.mp4 ,112.17321968078613,2025-10-27 17:23:03 +/mnt/nfs_share/camera1/camera1_recording_20251105_111620.mp4 ,51.900516510009766,2025-11-05 16:17:13 +/mnt/nfs_share/camera1/20251027_131521_manual_camera1_2025-10-27T17-15-21-242Z.mp4 ,164.29076480865479,2025-10-27 17:15:46 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251024_101215.mp4 ,2795.5555295944214,2025-10-24 14:18:53 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251022_153109.mp4 ,429.8146381378174,2025-10-22 19:32:12 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251014_164830.mp4 ,355.2420530319214,2025-10-14 20:49:21 +/mnt/nfs_share/camera1/camera1_recording_20251107_162117.mp4 ,3144.733729362488,2025-11-07 21:28:52 +/mnt/nfs_share/camera1/camera1_manual_20251027_133233.mp4 ,697.2805919647217,2025-10-27 17:34:17 +/mnt/nfs_share/camera1/camera1_recording_20251105_111148.mp4 ,77.59451198577881,2025-11-05 16:13:10 +/mnt/nfs_share/camera1/camera1_recording_20251107_163646.mp4 ,378.31123447418213,2025-11-07 21:37:42 +/mnt/nfs_share/camera1/20251027_130319_manual_camera1_2025-10-27T17-03-19-317Z.mp4 ,1.3117961883544922,2025-10-27 17:03:31 +/mnt/nfs_share/camera1/20251027_132054_manual_camera1_2025-10-27T17-20-54-417Z.mp4 ,303.9300184249878,2025-10-27 17:21:41 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251027_102543.mp4 ,55.90567111968994,2025-10-27 14:33:54 +/mnt/nfs_share/camera1/camera1_recording_20251107_103008.mp4 ,3.954451560974121,2025-11-07 15:30:30 +/mnt/nfs_share/camera1/camera1_recording_20251105_100520.mp4 ,16.943754196166992,2025-11-05 15:05:34 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251015_102231.mp4 ,600.7610549926758,2025-10-15 14:23:56 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251015_163913.mp4 ,294.5996503829956,2025-10-15 20:39:54 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251024_102251.mp4 ,376.4865026473999,2025-10-24 14:23:45 +/mnt/nfs_share/camera1/20251027_130413_manual_camera1_2025-10-27T17-04-13-377Z.mp4 ,1.122797966003418,2025-10-27 17:04:24 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251014_165003.mp4 ,370.4667148590088,2025-10-14 20:50:55 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251015_101125.mp4 ,3306.591923713684,2025-10-15 14:18:51 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251015_102545.mp4 ,343.356632232666,2025-10-15 14:26:37 +/mnt/nfs_share/camera1/camera1_recording_20251104_150633.mp4 ,0.4837827682495117,2025-11-04 20:07:01 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251020_154656.mp4 ,3133.8277492523193,2025-10-20 19:53:59 +/mnt/nfs_share/camera1/20251101_132719_manual_camera1_2025-11-01T17-27-20-334Z.mp4 ,3.750041961669922,2025-11-01 17:27:55 +/mnt/nfs_share/camera1/camera1_recording_20251107_104349.mp4 ,583.4240083694458,2025-11-07 15:45:14 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251015_163604.mp4 ,270.972692489624,2025-10-15 20:36:41 +/mnt/nfs_share/camera1/camera1_recording_20251112_103644.mp4 ,459.7749557495117,2025-11-12 15:37:50 +/mnt/nfs_share/camera1/camera1_recording_20251105_111447.mp4 ,50.30069637298584,2025-11-05 16:15:37 +/mnt/nfs_share/camera1/camera1_recording_20251112_103855.mp4 ,390.3577947616577,2025-11-12 15:39:52 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251024_102421.mp4 ,240.2885036468506,2025-10-24 14:24:56 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251020_155806.mp4 ,408.3445301055908,2025-10-20 19:59:02 +/mnt/nfs_share/camera1/20251101_130836_manual_camera1_2025-11-01T17-08-36-984Z.mp4 ,0.9279050827026367,2025-11-01 17:08:46 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251016_152847.mp4 ,324.3079767227173,2025-10-16 19:29:33 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251017_104603.mp4 ,368.55879402160645,2025-10-17 14:46:53 +/mnt/nfs_share/camera1/camera1_recording_20251105_101211.mp4 ,59.49912643432617,2025-11-05 15:13:09 +/mnt/nfs_share/camera1/camera1_recording_20251105_152248.mp4 ,300.93520164489746,2025-11-05 20:23:34 +/mnt/nfs_share/camera1/20251101_125747_manual_camera1_2025-11-01T16-57-48-461Z.mp4 ,1.2230892181396484,2025-11-01 16:57:59 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251022_152301.mp4 ,2797.915633201599,2025-10-22 19:29:47 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251022_110557.mp4 ,517.8433504104614,2025-10-22 15:07:11 +/mnt/nfs_share/camera1/20251104_113624_manual_camera1_2025-11-04T16-36-24-794Z.mp4 ,31.728784561157227,2025-11-04 16:36:29 +/mnt/nfs_share/camera1/camera1_recording_20251105_152113.mp4 ,241.2749366760254,2025-11-05 20:21:48 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251030_160405.mp4 ,2.8769702911376953,2025-10-30 20:04:25 +/mnt/nfs_share/camera1/20251103_153859_manual_camera1_2025-11-03T20-39-01-038Z.mp4 ,18.1849422454834,2025-11-03 20:39:02 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251022_101034.mp4 ,159.32698154449463,2025-10-22 14:11:48 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251020_155557.mp4 ,433.5608777999878,2025-10-20 19:56:55 +/mnt/nfs_share/camera1/20251014_162515_manual_camera1_2025-10-14T20-25-15-955Z.mp4 ,20.157227516174316,2025-10-14 20:25:23 +/mnt/nfs_share/camera1/20251027_132645_manual_camera1_2025-10-27T17-26-45-348Z.mp4 ,2223.18155670166,2025-10-27 17:32:15 +/mnt/nfs_share/camera1/camera1_recording_20251111_151859.mp4 ,2962.1732845306396,2025-11-11 20:25:56 +/mnt/nfs_share/camera1/20251105_135148_manual_camera1_2025-11-05T18-51-49-573Z.mp4 ,0.17766284942626953,2025-11-05 18:51:57 +/mnt/nfs_share/camera1/20251027_133444_manual_camera1_2025-10-27T17-34-44-393Z.mp4 ,689.7500419616699,2025-10-27 17:36:26 +/mnt/nfs_share/camera1/camera1_recording_20251105_101400.mp4 ,49.01335430145264,2025-11-05 15:14:47 +/mnt/nfs_share/camera1/20251027_130721_manual_camera1_2025-10-27T17-07-21-328Z.mp4 ,66.86591243743896,2025-10-27 17:07:31 +/mnt/nfs_share/camera1/20251027_131827_manual_camera1_2025-10-27T17-18-27-835Z.mp4 ,384.2500419616699,2025-10-27 17:19:27 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251030_155327.mp4 ,62.33474349975586,2025-10-30 20:00:36 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251017_103331.mp4 ,3270.361262321472,2025-10-17 14:40:48 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251023_153451.mp4 ,3281.6518783569336,2025-10-23 19:42:23 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251022_153519.mp4 ,413.2849578857422,2025-10-22 19:36:19 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251027_153609.mp4 ,482.2403316497803,2025-10-27 19:37:22 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251022_105509.mp4 ,2859.216413497925,2025-10-22 15:01:39 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251017_104401.mp4 ,433.6085367202759,2025-10-17 14:44:59 +/mnt/nfs_share/camera1/camera1_recording_20251105_151008.mp4 ,2994.1441497802734,2025-11-05 20:17:14 +/mnt/nfs_share/camera1/.refresh ,0.0,2025-10-14 20:23:29 +/mnt/nfs_share/camera1/camera1_recording_20251107_104542.mp4 ,340.4220886230469,2025-11-07 15:46:31 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251024_102040.mp4 ,474.6723299026489,2025-10-24 14:21:49 +/mnt/nfs_share/camera1/camera1_recording_20251107_163324.mp4 ,571.8697576522827,2025-11-07 21:34:48 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251022_110310.mp4 ,448.1354732513428,2025-10-22 15:04:15 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251024_151442.mp4 ,2802.3175411224365,2025-10-24 19:21:13 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251024_152351.mp4 ,421.7528409957886,2025-10-24 19:24:52 +/mnt/nfs_share/camera1/camera1_auto_blower_separator_20251015_163437.mp4 ,418.89909172058105,2025-10-15 20:35:34 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251030_100639.mp4 ,2192.158878326416,2025-10-30 14:11:11 +/mnt/nfs_share/camera2/20251101_140829_manual_camera2_2025-11-01T18-08-30-234Z.mp4 ,5.911883354187012,2025-11-01 18:08:31 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251024_093533.mp4 ,16607.57194709778,2025-10-24 14:11:19 +/mnt/nfs_share/camera2/20251105_135146_manual_camera2_2025-11-05T18-51-47-949Z.mp4 ,11.408576965332031,2025-11-05 18:51:55 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251023_144203.mp4 ,24270.21284866333,2025-10-23 19:33:50 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251020_094624.mp4 ,16144.342178344727,2025-10-20 14:21:48 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251023_094345.mp4 ,1862.6238870620728,2025-10-23 13:47:43 +/mnt/nfs_share/camera2/camera2_recording_20251104_140219.mp4 ,4510.236128807068,2025-11-04 19:45:55 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251016_114800.mp4 ,1499.363600730896,2025-10-16 15:51:11 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251030_120601.mp4 ,1993.507830619812,2025-10-30 16:10:04 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251016_111402.mp4 ,1660.3650093078613,2025-10-16 15:17:31 +/mnt/nfs_share/camera2/20251101_145535_manual_camera2_2025-11-01T18-55-35-913Z.mp4 ,855.8802976608276,2025-11-01 18:57:55 +/mnt/nfs_share/camera2/20251101_140325_manual_camera2_2025-11-01T18-03-26-620Z.mp4 ,121.3832311630249,2025-11-01 18:03:44 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251028_102837.mp4 ,2286.2115926742554,2025-10-28 14:33:26 +/mnt/nfs_share/camera2/camera2_recording_20251105_141738.mp4 ,36978.29885959625,2025-11-05 20:06:14 +/mnt/nfs_share/camera2/camera2_recording_20251112_094651.mp4 ,28059.49242401123,2025-11-12 15:23:58 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251027_092101.mp4 ,15.555830955505371,2025-10-27 13:21:03 +/mnt/nfs_share/camera2/camera2_recording_20251107_154318.mp4 ,28339.455046653748,2025-11-07 21:20:41 +/mnt/nfs_share/camera2/20251103_154326_manual_camera2_2025-11-03T20-43-28-822Z.mp4 ,747.4546556472778,2025-11-03 20:44:26 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251027_144707.mp4 ,16009.781435012817,2025-10-27 19:21:35 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251023_123047.mp4 ,1191.4632024765015,2025-10-23 16:33:05 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251030_151411.mp4 ,63.706143379211426,2025-10-30 19:14:18 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251028_110523.mp4 ,2216.680072784424,2025-10-28 15:09:54 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251022_101004.mp4 ,20563.820642471313,2025-10-22 14:54:11 +/mnt/nfs_share/camera2/camera2_recording_20251106_115740.mp4 ,3574.437940597534,2025-11-06 17:02:20 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251027_093426.mp4 ,23129.598598480225,2025-10-27 14:23:38 +/mnt/nfs_share/camera2/20251101_140638_manual_camera2_2025-11-01T18-06-39-502Z.mp4 ,21.121756553649902,2025-11-01 18:06:53 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251016_121411.mp4 ,1398.3942489624023,2025-10-16 16:17:07 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251015_100527.mp4 ,4.00632381439209,2025-10-15 14:05:28 +/mnt/nfs_share/camera2/20251014_162513_manual_camera2_2025-10-14T20-25-13-249Z.mp4 ,0.4652433395385742,2025-10-14 20:25:22 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251016_094811.mp4 ,1435.4193124771118,2025-10-16 13:51:18 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251020_145623.mp4 ,22870.767561912537,2025-10-20 19:46:13 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251023_121409.mp4 ,1732.018045425415,2025-10-23 16:17:49 +/mnt/nfs_share/camera2/20251101_140355_manual_camera2_2025-11-01T18-03-56-281Z.mp4 ,79.599778175354,2025-11-01 18:05:09 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251017_100138.mp4 ,14737.022854804993,2025-10-17 14:32:39 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251030_104743.mp4 ,1549.366548538208,2025-10-30 14:50:53 +/mnt/nfs_share/camera2/camera2_recording_20251106_103744.mp4 ,3663.7876415252686,2025-11-06 15:42:34 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251023_114107.mp4 ,1514.376932144165,2025-10-23 15:44:22 +/mnt/nfs_share/camera2/20251103_153851_manual_camera2_2025-11-03T20-38-53-740Z.mp4 ,35.77230358123779,2025-11-03 20:38:57 +/mnt/nfs_share/camera2/camera2_recording_20251111_121518.mp4 ,2546.3795528411865,2025-11-11 17:18:37 +/mnt/nfs_share/camera2/camera2_recording_20251112_154951.mp4 ,22451.03125,2025-11-12 21:20:34 +/mnt/nfs_share/camera2/20251101_140759_manual_camera2_2025-11-01T18-08-00-244Z.mp4 ,51.26141548156738,2025-11-01 18:08:07 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251016_102408.mp4 ,2265.5979137420654,2025-10-16 14:28:46 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251022_145322.mp4 ,13834.725661277771,2025-10-22 19:22:39 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251028_094749.mp4 ,1246.4291706085205,2025-10-28 13:50:18 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251021_160040.mp4 ,19044.06910610199,2025-10-21 20:41:59 +/mnt/nfs_share/camera2/camera2_recording_20251106_091003.mp4 ,3608.199562072754,2025-11-06 14:14:45 +/mnt/nfs_share/camera2/20251103_164200_manual_camera2_2025-11-03T21-42-02-665Z.mp4 ,54.91640567779541,2025-11-03 21:42:09 +/mnt/nfs_share/camera2/20251101_134953_manual_camera2_2025-11-01T17-49-54-470Z.mp4 ,43.00830936431885,2025-11-01 17:50:03 +/mnt/nfs_share/camera2/camera2_recording_20251111_100357.mp4 ,2877.733688354492,2025-11-11 15:07:36 +/mnt/nfs_share/camera2/camera2_recording_20251106_112741.mp4 ,3612.6160192489624,2025-11-06 16:32:23 +/mnt/nfs_share/camera2/20251111_113352_camera2_auto_vibratory_conveyor_20251111_113352.mp4 ,2729.5866270065308,2025-11-11 16:37:30 +/mnt/nfs_share/camera2/camera2_recording_20251111_104116.mp4 ,2905.7792949676514,2025-11-11 15:45:04 +/mnt/nfs_share/camera2/camera2_recording_20251104_115434.mp4 ,27.297094345092773,2025-11-04 16:54:45 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251028_103831.mp4 ,823.6575527191162,2025-10-28 14:40:10 +/mnt/nfs_share/camera2/camera2_recording_20251105_100139.mp4 ,6104.120680809021,2025-11-05 16:01:03 +/mnt/nfs_share/camera2/camera2_auto_vibratory_conveyor_20251015_093140.mp4 ,15725.424202919006,2025-10-15 14:05:12 +/mnt/nfs_share/camera2/camera2_recording_20251106_095113.mp4 ,4051.650778770447,2025-11-06 14:56:34 +/mnt/nfs_share/camera2/camera2_recording_20251107_094355.mp4 ,34698.75883579254,2025-11-07 15:29:40 +/mnt/nfs_share/camera2/camera2_recording_20251111_094856.mp4 ,2683.412371635437,2025-11-11 14:52:28 +/mnt/nfs_share/camera2/20251104_114330_manual_camera2_2025-11-04T16-43-30-646Z.mp4 ,42.72879123687744,2025-11-04 16:43:37 diff --git a/docker-compose.yml b/docker-compose.yml index 80ba2e7..bd8ee27 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,6 +6,12 @@ services: dockerfile: Dockerfile working_dir: /app restart: unless-stopped # Automatically restart container if it fails or exits + healthcheck: + test: ["CMD-SHELL", "python3 -c 'import urllib.request; urllib.request.urlopen(\"http://localhost:8000/health\").read()' || exit 1"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 60s volumes: - ./camera-management-api:/app - /mnt/nfs_share:/mnt/nfs_share @@ -20,29 +26,42 @@ services: - MEDIAMTX_RTSP_PORT=8554 command: > sh -lc " - apt-get update && apt-get install -y libusb-1.0-0-dev ffmpeg; + set -e # Exit on error + + # Only install system packages if not already installed (check for ffmpeg) + if ! command -v ffmpeg &> /dev/null; then + echo 'Installing system dependencies...'; + apt-get update && apt-get install -y --no-install-recommends libusb-1.0-0-dev ffmpeg; + else + echo 'System dependencies already installed'; + fi # Install camera SDK if not already installed if [ ! -f /lib/libMVSDK.so ] && [ -f 'camera_sdk/linuxSDK_V2.1.0.49(250108)/install.sh' ]; then echo 'Installing camera SDK...'; cd 'camera_sdk/linuxSDK_V2.1.0.49(250108)'; chmod +x install.sh; - ./install.sh; + ./install.sh || echo 'Warning: Camera SDK installation may have failed'; cd /app; - echo 'Camera SDK installed successfully'; else echo 'Camera SDK already installed or install script not found'; fi; - # Install Python dependencies + # Install Python dependencies (only if requirements.txt changed or packages missing) if [ -f requirements.txt ]; then - pip install --no-cache-dir -r requirements.txt; + pip install --no-cache-dir -r requirements.txt || echo 'Warning: Some Python packages may have failed to install'; else - pip install --no-cache-dir -e .; + pip install --no-cache-dir -e . || echo 'Warning: Package installation may have failed'; fi; - # Start the application - python main.py --config config.compose.json + # Start the application with error handling + echo 'Starting USDA Vision Camera System...'; + python main.py --config config.compose.json || { + echo 'Application exited with error code: $?'; + echo 'Waiting 5 seconds before exit...'; + sleep 5; + exit 1; + } " network_mode: host diff --git a/docs/CONTAINER_CRASH_DEBUGGING.md b/docs/CONTAINER_CRASH_DEBUGGING.md new file mode 100644 index 0000000..7849368 --- /dev/null +++ b/docs/CONTAINER_CRASH_DEBUGGING.md @@ -0,0 +1,141 @@ +# Container Crash Debugging Guide + +## Overview + +This guide helps diagnose and fix crashes in the `usda-vision-api` container. + +## Quick Diagnostic + +Run the diagnostic script: +```bash +./scripts/diagnose_container_crashes.sh +``` + +## Common Causes of Crashes + +### 1. MQTT Connection Failure +**Symptoms:** Container exits immediately after startup +**Check:** +```bash +docker logs usda-vision-api | grep -i mqtt +``` +**Fix:** Ensure MQTT broker is accessible at `192.168.1.110:1883` + +### 2. Camera SDK Initialization Failure +**Symptoms:** Container crashes during camera initialization +**Check:** +```bash +docker logs usda-vision-api | grep -i "camera\|sdk" +``` +**Fix:** Check camera hardware connection and SDK installation + +### 3. Storage Path Issues +**Symptoms:** Container fails to start storage manager +**Check:** +```bash +docker exec usda-vision-api ls -la /mnt/nfs_share +``` +**Fix:** Ensure `/mnt/nfs_share` is mounted and writable + +### 4. Out of Memory (OOM) +**Symptoms:** Container killed by system, exit code 137 +**Check:** +```bash +dmesg | grep -i "killed process" +docker stats usda-vision-api +``` +**Fix:** Add memory limits or increase available memory + +### 5. Missing Configuration File +**Symptoms:** Container starts but exits quickly +**Check:** +```bash +docker exec usda-vision-api cat /app/config.compose.json +``` +**Fix:** Ensure `config.compose.json` exists in the container + +### 6. Python Exception Not Caught +**Symptoms:** Container exits with Python traceback +**Check:** +```bash +docker logs usda-vision-api --tail 100 +``` +**Fix:** Check logs for unhandled exceptions + +## Recent Improvements + +### Enhanced Error Handling +- System now continues running even if some non-critical components fail +- Added consecutive error tracking to prevent infinite crash loops +- Better logging with full exception traces + +### Improved Startup Command +- Only installs packages if missing (faster startup) +- Better error messages during startup +- Graceful exit with delay for log flushing + +### Health Checks +- Added Docker healthcheck to monitor container health +- Health endpoint: `http://localhost:8000/health` + +## Debugging Steps + +1. **Check container status:** + ```bash + docker ps -a | grep usda-vision-api + ``` + +2. **View recent logs:** + ```bash + docker logs usda-vision-api --tail 100 -f + ``` + +3. **Check exit code:** + ```bash + docker inspect usda-vision-api --format='{{.State.ExitCode}}' + ``` + - `0` = Normal exit + - `1` = Application error + - `137` = Killed (usually OOM) + +4. **Check restart count:** + ```bash + docker inspect usda-vision-api --format='{{.RestartCount}}' + ``` + +5. **Run with debug logging:** + Edit `docker-compose.yml` and change the command to: + ```yaml + python main.py --config config.compose.json --debug --verbose + ``` + +6. **Check resource usage:** + ```bash + docker stats usda-vision-api + ``` + +## Manual Testing + +To test the container manually: +```bash +docker exec -it usda-vision-api bash +python main.py --config config.compose.json --debug +``` + +## Prevention + +The container now has: +- ✅ Automatic restart policy (`restart: unless-stopped`) +- ✅ Health checks +- ✅ Better error handling +- ✅ Graceful shutdown on signals +- ✅ Partial operation if some components fail + +## Getting Help + +If crashes persist: +1. Run the diagnostic script +2. Collect logs: `docker logs usda-vision-api > crash_logs.txt` +3. Check system resources: `docker stats usda-vision-api` +4. Review recent changes to configuration or code + diff --git a/management-dashboard-web-app/phase_2_JC_experimental_run_sheet.csv b/management-dashboard-web-app/phase_2_JC_experimental_run_sheet.csv index 8065af6..d3b34c9 100755 --- a/management-dashboard-web-app/phase_2_JC_experimental_run_sheet.csv +++ b/management-dashboard-web-app/phase_2_JC_experimental_run_sheet.csv @@ -1,61 +1,61 @@ -phase_name,machine_type,run_id,experiment_number,soaking_duration_hr,air_drying_duration_min,plate_contact_frequency_hz,throughput_rate_pecans_sec,crush_amount_in,entry_exit_height_diff_in,reps,rep -"Phase 2 of JC Experiments","JC Cracker",1,0,34,19,53,28,0.05,-0.09,3,1 -"Phase 2 of JC Experiments","JC Cracker",2,1,24,27,34,29,0.03,0.01,3,3 -"Phase 2 of JC Experiments","JC Cracker",3,12,28,59,37,23,0.06,-0.08,3,1 -"Phase 2 of JC Experiments","JC Cracker",4,15,16,60,30,24,0.07,0.02,3,1 -"Phase 2 of JC Experiments","JC Cracker",5,4,13,41,41,38,0.05,0.03,3,2 -"Phase 2 of JC Experiments","JC Cracker",6,18,18,49,38,35,0.07,-0.08,3,1 -"Phase 2 of JC Experiments","JC Cracker",7,11,24,59,42,25,0.07,-0.05,3,1 -"Phase 2 of JC Experiments","JC Cracker",8,16,20,59,41,14,0.07,0.04,3,1 -"Phase 2 of JC Experiments","JC Cracker",9,4,13,41,41,38,0.05,0.03,3,1 -"Phase 2 of JC Experiments","JC Cracker",10,19,11,25,56,34,0.06,-0.09,3,1 -"Phase 2 of JC Experiments","JC Cracker",11,15,16,60,30,24,0.07,0.02,3,2 -"Phase 2 of JC Experiments","JC Cracker",12,16,20,59,41,14,0.07,0.04,3,3 -"Phase 2 of JC Experiments","JC Cracker",13,10,26,60,44,12,0.08,-0.1,3,2 -"Phase 2 of JC Experiments","JC Cracker",14,1,24,27,34,29,0.03,0.01,3,1 -"Phase 2 of JC Experiments","JC Cracker",15,17,34,60,34,29,0.07,-0.09,3,2 -"Phase 2 of JC Experiments","JC Cracker",16,5,30,33,30,36,0.05,-0.04,3,3 -"Phase 2 of JC Experiments","JC Cracker",17,2,38,10,60,28,0.06,-0.1,3,3 -"Phase 2 of JC Experiments","JC Cracker",18,2,38,10,60,28,0.06,-0.1,3,1 -"Phase 2 of JC Experiments","JC Cracker",19,13,21,59,41,21,0.06,-0.09,3,2 -"Phase 2 of JC Experiments","JC Cracker",20,1,24,27,34,29,0.03,0.01,3,2 -"Phase 2 of JC Experiments","JC Cracker",21,14,22,59,45,17,0.07,-0.08,3,2 -"Phase 2 of JC Experiments","JC Cracker",22,6,10,22,37,30,0.06,0.02,3,2 -"Phase 2 of JC Experiments","JC Cracker",23,11,24,59,42,25,0.07,-0.05,3,2 -"Phase 2 of JC Experiments","JC Cracker",24,19,11,25,56,34,0.06,-0.09,3,2 -"Phase 2 of JC Experiments","JC Cracker",25,8,27,12,55,24,0.04,0.04,3,2 -"Phase 2 of JC Experiments","JC Cracker",26,18,18,49,38,35,0.07,-0.08,3,3 -"Phase 2 of JC Experiments","JC Cracker",27,5,30,33,30,36,0.05,-0.04,3,1 -"Phase 2 of JC Experiments","JC Cracker",28,9,32,26,47,26,0.07,0.03,3,1 -"Phase 2 of JC Experiments","JC Cracker",29,3,11,36,42,13,0.07,-0.07,3,1 -"Phase 2 of JC Experiments","JC Cracker",30,10,26,60,44,12,0.08,-0.1,3,1 -"Phase 2 of JC Experiments","JC Cracker",31,8,27,12,55,24,0.04,0.04,3,3 -"Phase 2 of JC Experiments","JC Cracker",32,5,30,33,30,36,0.05,-0.04,3,2 -"Phase 2 of JC Experiments","JC Cracker",33,8,27,12,55,24,0.04,0.04,3,1 -"Phase 2 of JC Experiments","JC Cracker",34,18,18,49,38,35,0.07,-0.08,3,2 -"Phase 2 of JC Experiments","JC Cracker",35,3,11,36,42,13,0.07,-0.07,3,3 -"Phase 2 of JC Experiments","JC Cracker",36,10,26,60,44,12,0.08,-0.1,3,3 -"Phase 2 of JC Experiments","JC Cracker",37,17,34,60,34,29,0.07,-0.09,3,3 -"Phase 2 of JC Experiments","JC Cracker",38,13,21,59,41,21,0.06,-0.09,3,3 -"Phase 2 of JC Experiments","JC Cracker",39,12,28,59,37,23,0.06,-0.08,3,2 -"Phase 2 of JC Experiments","JC Cracker",40,9,32,26,47,26,0.07,0.03,3,3 -"Phase 2 of JC Experiments","JC Cracker",41,14,22,59,45,17,0.07,-0.08,3,3 -"Phase 2 of JC Experiments","JC Cracker",42,0,34,19,53,28,0.05,-0.09,3,2 -"Phase 2 of JC Experiments","JC Cracker",43,7,15,30,35,32,0.05,-0.07,3,1 -"Phase 2 of JC Experiments","JC Cracker",44,0,34,19,53,28,0.05,-0.09,3,3 -"Phase 2 of JC Experiments","JC Cracker",45,15,16,60,30,24,0.07,0.02,3,3 -"Phase 2 of JC Experiments","JC Cracker",46,13,21,59,41,21,0.06,-0.09,3,1 -"Phase 2 of JC Experiments","JC Cracker",47,11,24,59,42,25,0.07,-0.05,3,3 -"Phase 2 of JC Experiments","JC Cracker",48,7,15,30,35,32,0.05,-0.07,3,3 -"Phase 2 of JC Experiments","JC Cracker",49,16,20,59,41,14,0.07,0.04,3,2 -"Phase 2 of JC Experiments","JC Cracker",50,3,11,36,42,13,0.07,-0.07,3,2 -"Phase 2 of JC Experiments","JC Cracker",51,7,15,30,35,32,0.05,-0.07,3,2 -"Phase 2 of JC Experiments","JC Cracker",52,6,10,22,37,30,0.06,0.02,3,1 -"Phase 2 of JC Experiments","JC Cracker",53,19,11,25,56,34,0.06,-0.09,3,3 -"Phase 2 of JC Experiments","JC Cracker",54,6,10,22,37,30,0.06,0.02,3,3 -"Phase 2 of JC Experiments","JC Cracker",55,2,38,10,60,28,0.06,-0.1,3,2 -"Phase 2 of JC Experiments","JC Cracker",56,14,22,59,45,17,0.07,-0.08,3,1 -"Phase 2 of JC Experiments","JC Cracker",57,4,13,41,41,38,0.05,0.03,3,3 -"Phase 2 of JC Experiments","JC Cracker",58,9,32,26,47,26,0.07,0.03,3,2 -"Phase 2 of JC Experiments","JC Cracker",59,17,34,60,34,29,0.07,-0.09,3,1 -"Phase 2 of JC Experiments","JC Cracker",60,12,28,59,37,23,0.06,-0.08,3,3 \ No newline at end of file +experiment_number,soaking_duration_hr,air_drying_duration_min,plate_contact_frequency_hz,throughput_rate_pecans_sec,crush_amount_in,entry_exit_height_diff_in +0,34,19,53,28,0.05,-0.09 +1,24,27,34,29,0.03,0.01 +12,28,59,37,23,0.06,-0.08 +15,16,60,30,24,0.07,0.02 +4,13,41,41,38,0.05,0.03 +18,18,49,38,35,0.07,-0.08 +11,24,59,42,25,0.07,-0.05 +16,20,59,41,14,0.07,0.04 +4,13,41,41,38,0.05,0.03 +19,11,25,56,34,0.06,-0.09 +15,16,60,30,24,0.07,0.02 +16,20,59,41,14,0.07,0.04 +10,26,60,44,12,0.08,-0.1 +1,24,27,34,29,0.03,0.01 +17,34,60,34,29,0.07,-0.09 +5,30,33,30,36,0.05,-0.04 +2,38,10,60,28,0.06,-0.1 +2,38,10,60,28,0.06,-0.1 +13,21,59,41,21,0.06,-0.09 +1,24,27,34,29,0.03,0.01 +14,22,59,45,17,0.07,-0.08 +6,10,22,37,30,0.06,0.02 +11,24,59,42,25,0.07,-0.05 +19,11,25,56,34,0.06,-0.09 +8,27,12,55,24,0.04,0.04 +18,18,49,38,35,0.07,-0.08 +5,30,33,30,36,0.05,-0.04 +9,32,26,47,26,0.07,0.03 +3,11,36,42,13,0.07,-0.07 +10,26,60,44,12,0.08,-0.1 +8,27,12,55,24,0.04,0.04 +5,30,33,30,36,0.05,-0.04 +8,27,12,55,24,0.04,0.04 +18,18,49,38,35,0.07,-0.08 +3,11,36,42,13,0.07,-0.07 +10,26,60,44,12,0.08,-0.1 +17,34,60,34,29,0.07,-0.09 +13,21,59,41,21,0.06,-0.09 +12,28,59,37,23,0.06,-0.08 +9,32,26,47,26,0.07,0.03 +14,22,59,45,17,0.07,-0.08 +0,34,19,53,28,0.05,-0.09 +7,15,30,35,32,0.05,-0.07 +0,34,19,53,28,0.05,-0.09 +15,16,60,30,24,0.07,0.02 +13,21,59,41,21,0.06,-0.09 +11,24,59,42,25,0.07,-0.05 +7,15,30,35,32,0.05,-0.07 +16,20,59,41,14,0.07,0.04 +3,11,36,42,13,0.07,-0.07 +7,15,30,35,32,0.05,-0.07 +6,10,22,37,30,0.06,0.02 +19,11,25,56,34,0.06,-0.09 +6,10,22,37,30,0.06,0.02 +2,38,10,60,28,0.06,-0.1 +14,22,59,45,17,0.07,-0.08 +4,13,41,41,38,0.05,0.03 +9,32,26,47,26,0.07,0.03 +17,34,60,34,29,0.07,-0.09 +12,28,59,37,23,0.06,-0.08 \ No newline at end of file diff --git a/management-dashboard-web-app/src/components/CameraPage.tsx b/management-dashboard-web-app/src/components/CameraPage.tsx index f1fb68d..fc4a9ca 100644 --- a/management-dashboard-web-app/src/components/CameraPage.tsx +++ b/management-dashboard-web-app/src/components/CameraPage.tsx @@ -14,6 +14,8 @@ export function CameraPage({ cameraName }: CameraPageProps) { const [mqttEvents, setMqttEvents] = useState([]) const [autoRecordingError, setAutoRecordingError] = useState(null) const [loading, setLoading] = useState(true) + const [error, setError] = useState(null) + const [retrying, setRetrying] = useState(false) const imgRef = useRef(null) const statusIntervalRef = useRef(null) const mqttEventsIntervalRef = useRef(null) @@ -121,19 +123,39 @@ export function CameraPage({ cameraName }: CameraPageProps) { const loadCameraData = async () => { try { setLoading(true) + setError(null) await Promise.all([loadCameraStatus(), loadCameraConfig()]) } catch (error) { console.error('Error loading camera data:', error) + const errorMessage = error instanceof Error ? error.message : 'Failed to load camera data' + setError(errorMessage) } finally { setLoading(false) } } + const handleRetry = async () => { + setRetrying(true) + setError(null) + try { + await loadCameraData() + // Also retry streaming if it was previously active + if (streamStatus === 'error') { + await startStreaming() + } + } catch (error) { + console.error('Error retrying:', error) + } finally { + setRetrying(false) + } + } + const loadCameraStatus = async () => { try { const status = await visionApi.getCameraStatus(cameraName) setCameraStatus(status) setIsRecording(status.is_recording) + setError(null) // Clear error on successful load // Update stream status based on camera status if (status.status === 'streaming' || status.status === 'available') { @@ -144,6 +166,11 @@ export function CameraPage({ cameraName }: CameraPageProps) { } } catch (error) { console.error('Error loading camera status:', error) + // Only set error if we don't have status data at all + if (!cameraStatus) { + const errorMessage = error instanceof Error ? error.message : 'Failed to load camera status' + setError(errorMessage) + } } } @@ -151,8 +178,14 @@ export function CameraPage({ cameraName }: CameraPageProps) { try { const config = await visionApi.getCameraConfig(cameraName) setCameraConfig(config) + setError(null) // Clear error on successful load } catch (error) { console.error('Error loading camera config:', error) + // Only set error if we don't have config data at all + if (!cameraConfig) { + const errorMessage = error instanceof Error ? error.message : 'Failed to load camera configuration' + setError(errorMessage) + } } } @@ -277,7 +310,7 @@ export function CameraPage({ cameraName }: CameraPageProps) { } } - if (loading) { + if (loading && !cameraStatus && !cameraConfig) { return (
@@ -288,6 +321,51 @@ export function CameraPage({ cameraName }: CameraPageProps) { ) } + if (error && !cameraStatus && !cameraConfig) { + return ( +
+
+
+
+
+ + + +
+
+

Error loading camera

+
+

{error}

+
+
+ +
+
+
+
+
+
+ ) + } + const healthStatus = getHealthStatus() return ( diff --git a/management-dashboard-web-app/src/components/DashboardLayout.tsx b/management-dashboard-web-app/src/components/DashboardLayout.tsx index c16d4a2..3273303 100755 --- a/management-dashboard-web-app/src/components/DashboardLayout.tsx +++ b/management-dashboard-web-app/src/components/DashboardLayout.tsx @@ -217,7 +217,7 @@ export function DashboardLayout({ onLogout, currentRoute }: DashboardLayoutProps return case 'vision-system': return ( - Failed to load vision system module. Please try again.
}> + Loading vision system module...
}> @@ -225,7 +225,7 @@ export function DashboardLayout({ onLogout, currentRoute }: DashboardLayoutProps ) case 'scheduling': return ( - Failed to load scheduling module. Please try again.}> + Loading scheduling module...}> @@ -233,7 +233,7 @@ export function DashboardLayout({ onLogout, currentRoute }: DashboardLayoutProps ) case 'video-library': return ( - Failed to load video module. Please try again.}> + Loading video module...}> @@ -312,7 +312,7 @@ export function DashboardLayout({ onLogout, currentRoute }: DashboardLayoutProps )}
handleViewChange('profile')} /> -
+
{renderCurrentView()}
diff --git a/management-dashboard-web-app/src/components/DataEntry.tsx b/management-dashboard-web-app/src/components/DataEntry.tsx index fc55208..64d667d 100755 --- a/management-dashboard-web-app/src/components/DataEntry.tsx +++ b/management-dashboard-web-app/src/components/DataEntry.tsx @@ -109,7 +109,40 @@ export function DataEntry() { return (
-
{error}
+
+
+ + + +
+
+

Error loading data

+
+

{error}

+
+
+ +
+
+
) diff --git a/management-dashboard-web-app/src/components/ErrorBoundary.tsx b/management-dashboard-web-app/src/components/ErrorBoundary.tsx index c34f502..059890c 100644 --- a/management-dashboard-web-app/src/components/ErrorBoundary.tsx +++ b/management-dashboard-web-app/src/components/ErrorBoundary.tsx @@ -1,6 +1,11 @@ import { Component, ReactNode } from 'react' -type Props = { children: ReactNode, fallback?: ReactNode } +type Props = { + children: ReactNode + fallback?: ReactNode + onRetry?: () => void + showRetry?: boolean +} type State = { hasError: boolean } export class ErrorBoundary extends Component { @@ -12,9 +17,48 @@ export class ErrorBoundary extends Component { componentDidCatch() {} + handleRetry = () => { + this.setState({ hasError: false }) + if (this.props.onRetry) { + this.props.onRetry() + } + } + render() { if (this.state.hasError) { - return this.props.fallback ??
Something went wrong loading this section.
+ if (this.props.fallback) { + return this.props.fallback + } + + return ( +
+
+
+
+ + + +
+
+

Something went wrong loading this section

+
+

An error occurred while loading this component. Please try reloading it.

+
+ {(this.props.showRetry !== false) && ( +
+ +
+ )} +
+
+
+
+ ) } return this.props.children } diff --git a/management-dashboard-web-app/src/components/Scheduling.tsx b/management-dashboard-web-app/src/components/Scheduling.tsx index 8b622a7..40d31cc 100644 --- a/management-dashboard-web-app/src/components/Scheduling.tsx +++ b/management-dashboard-web-app/src/components/Scheduling.tsx @@ -936,7 +936,6 @@ function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void } // Create/update soaking record with repetition_id await phaseManagement.createSoaking({ - experiment_id: experimentId, repetition_id: repId, scheduled_start_time: soakingStart.toISOString(), soaking_duration_minutes: soaking.soaking_duration_minutes @@ -944,7 +943,6 @@ function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void } // Create/update airdrying record with repetition_id await phaseManagement.createAirdrying({ - experiment_id: experimentId, repetition_id: repId, scheduled_start_time: airdryingStart.toISOString(), duration_minutes: airdrying.duration_minutes @@ -957,7 +955,6 @@ function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void } if (phase?.cracking_machine_type_id) { await phaseManagement.createCracking({ - experiment_id: experimentId, repetition_id: repId, machine_type_id: phase.cracking_machine_type_id, scheduled_start_time: crackingStart.toISOString() @@ -999,8 +996,8 @@ function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void } return ( -
-
+
+
-
+
+
{error && (
{error}
)} @@ -1033,7 +1031,7 @@ function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void }

Fetching conductors, phases, and experiments.

) : ( -
+
{/* Left: Conductors with future availability */}
@@ -1254,8 +1252,8 @@ function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void }
)} {/* Week Calendar for selected conductors' availability */} -
-
+
+

Selected Conductors' Availability & Experiment Scheduling

Marker Style: @@ -1297,7 +1295,7 @@ function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void }
-
+
void }
+
) diff --git a/management-dashboard-web-app/src/lib/supabase.ts b/management-dashboard-web-app/src/lib/supabase.ts index d358949..137d58c 100755 --- a/management-dashboard-web-app/src/lib/supabase.ts +++ b/management-dashboard-web-app/src/lib/supabase.ts @@ -80,8 +80,7 @@ export interface MachineType { // Phase-specific interfaces export interface Soaking { id: string - experiment_id: string - repetition_id?: string | null + repetition_id: string scheduled_start_time: string actual_start_time?: string | null soaking_duration_minutes: number @@ -94,8 +93,7 @@ export interface Soaking { export interface Airdrying { id: string - experiment_id: string - repetition_id?: string | null + repetition_id: string scheduled_start_time: string actual_start_time?: string | null duration_minutes: number @@ -307,8 +305,7 @@ export interface UpdatePhaseDataRequest { // Phase creation request interfaces export interface CreateSoakingRequest { - experiment_id: string - repetition_id?: string + repetition_id: string scheduled_start_time: string soaking_duration_minutes: number actual_start_time?: string @@ -316,19 +313,17 @@ export interface CreateSoakingRequest { } export interface CreateAirdryingRequest { - experiment_id: string - repetition_id?: string - scheduled_start_time?: string // Will be auto-calculated from soaking if not provided + repetition_id: string + scheduled_start_time: string duration_minutes: number actual_start_time?: string actual_end_time?: string } export interface CreateCrackingRequest { - experiment_id: string - repetition_id?: string + repetition_id: string machine_type_id: string - scheduled_start_time?: string // Will be auto-calculated from airdrying if not provided + scheduled_start_time: string actual_start_time?: string actual_end_time?: string } @@ -798,11 +793,22 @@ export const phaseManagement = { const { data: { user }, error: authError } = await supabase.auth.getUser() if (authError || !user) throw new Error('User not authenticated') + if (!request.repetition_id) { + throw new Error('repetition_id is required') + } + + const scheduledEndTime = new Date(new Date(request.scheduled_start_time).getTime() + request.soaking_duration_minutes * 60000).toISOString() + const { data, error } = await supabase .from('soaking') - .insert({ - ...request, + .upsert({ + repetition_id: request.repetition_id, + scheduled_start_time: request.scheduled_start_time, + soaking_duration_minutes: request.soaking_duration_minutes, + scheduled_end_time: scheduledEndTime, created_by: user.id + }, { + onConflict: 'repetition_id' }) .select() .single() @@ -824,10 +830,23 @@ export const phaseManagement = { }, async getSoakingByExperimentId(experimentId: string): Promise { + // Get the first repetition for this experiment + const { data: repetitions, error: repsError } = await supabase + .from('experiment_repetitions') + .select('id') + .eq('experiment_id', experimentId) + .order('repetition_number', { ascending: true }) + .limit(1) + + if (repsError || !repetitions || repetitions.length === 0) { + return null + } + + // Get soaking for the first repetition const { data, error } = await supabase .from('soaking') .select('*') - .eq('experiment_id', experimentId) + .eq('repetition_id', repetitions[0].id) .single() if (error) { @@ -856,11 +875,26 @@ export const phaseManagement = { const { data: { user }, error: authError } = await supabase.auth.getUser() if (authError || !user) throw new Error('User not authenticated') + if (!request.repetition_id) { + throw new Error('repetition_id is required') + } + + if (!request.scheduled_start_time) { + throw new Error('scheduled_start_time is required') + } + + const scheduledEndTime = new Date(new Date(request.scheduled_start_time).getTime() + request.duration_minutes * 60000).toISOString() + const { data, error } = await supabase .from('airdrying') - .insert({ - ...request, + .upsert({ + repetition_id: request.repetition_id, + scheduled_start_time: request.scheduled_start_time, + duration_minutes: request.duration_minutes, + scheduled_end_time: scheduledEndTime, created_by: user.id + }, { + onConflict: 'repetition_id' }) .select() .single() @@ -882,10 +916,23 @@ export const phaseManagement = { }, async getAirdryingByExperimentId(experimentId: string): Promise { + // Get the first repetition for this experiment + const { data: repetitions, error: repsError } = await supabase + .from('experiment_repetitions') + .select('id') + .eq('experiment_id', experimentId) + .order('repetition_number', { ascending: true }) + .limit(1) + + if (repsError || !repetitions || repetitions.length === 0) { + return null + } + + // Get airdrying for the first repetition const { data, error } = await supabase .from('airdrying') .select('*') - .eq('experiment_id', experimentId) + .eq('repetition_id', repetitions[0].id) .single() if (error) { @@ -914,11 +961,23 @@ export const phaseManagement = { const { data: { user }, error: authError } = await supabase.auth.getUser() if (authError || !user) throw new Error('User not authenticated') + if (!request.repetition_id) { + throw new Error('repetition_id is required') + } + + if (!request.scheduled_start_time) { + throw new Error('scheduled_start_time is required') + } + const { data, error } = await supabase .from('cracking') - .insert({ - ...request, + .upsert({ + repetition_id: request.repetition_id, + machine_type_id: request.machine_type_id, + scheduled_start_time: request.scheduled_start_time, created_by: user.id + }, { + onConflict: 'repetition_id' }) .select() .single() diff --git a/management-dashboard-web-app/supabase/.temp/cli-latest b/management-dashboard-web-app/supabase/.temp/cli-latest index 7a78572..a900aa6 100755 --- a/management-dashboard-web-app/supabase/.temp/cli-latest +++ b/management-dashboard-web-app/supabase/.temp/cli-latest @@ -1 +1 @@ -v2.62.10 \ No newline at end of file +v2.65.2 \ No newline at end of file diff --git a/management-dashboard-web-app/supabase/config.toml b/management-dashboard-web-app/supabase/config.toml index 33dbfc2..70cea46 100755 --- a/management-dashboard-web-app/supabase/config.toml +++ b/management-dashboard-web-app/supabase/config.toml @@ -57,7 +57,7 @@ schema_paths = [] enabled = true # Specifies an ordered list of seed files to load during db reset. # Supports glob patterns relative to supabase directory: "./seeds/*.sql" -sql_paths = ["./seed_01_users.sql"] +sql_paths = ["./seed_01_users.sql", "./seed_02_phase2_experiments.sql"] # , "./seed_04_phase2_jc_experiments.sql", "./seed_05_meyer_experiments.sql"] [db.network_restrictions] diff --git a/management-dashboard-web-app/supabase/migrations/00005_experiments.sql b/management-dashboard-web-app/supabase/migrations/00005_experiments.sql index 1b57373..a3ade01 100644 --- a/management-dashboard-web-app/supabase/migrations/00005_experiments.sql +++ b/management-dashboard-web-app/supabase/migrations/00005_experiments.sql @@ -15,7 +15,10 @@ CREATE TABLE IF NOT EXISTS public.experiments ( phase_id UUID NOT NULL REFERENCES public.experiment_phases(id) ON DELETE SET NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - created_by UUID NOT NULL REFERENCES public.user_profiles(id) + created_by UUID NOT NULL REFERENCES public.user_profiles(id), + + -- Ensure unique combination of experiment_number and phase_id + CONSTRAINT unique_experiment_number_phase UNIQUE (experiment_number, phase_id) ); -- ============================================= diff --git a/management-dashboard-web-app/supabase/migrations/00008_phase_data_tables.sql b/management-dashboard-web-app/supabase/migrations/00008_phase_data_tables.sql index e7633cb..96819dd 100644 --- a/management-dashboard-web-app/supabase/migrations/00008_phase_data_tables.sql +++ b/management-dashboard-web-app/supabase/migrations/00008_phase_data_tables.sql @@ -7,8 +7,7 @@ CREATE TABLE IF NOT EXISTS public.soaking ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE, - repetition_id UUID REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE, + repetition_id UUID NOT NULL REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE, scheduled_start_time TIMESTAMP WITH TIME ZONE NOT NULL, actual_start_time TIMESTAMP WITH TIME ZONE, soaking_duration_minutes INTEGER NOT NULL CHECK (soaking_duration_minutes > 0), @@ -18,8 +17,7 @@ CREATE TABLE IF NOT EXISTS public.soaking ( updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), created_by UUID NOT NULL REFERENCES public.user_profiles(id), - -- Ensure only one soaking per experiment or repetition - CONSTRAINT unique_soaking_per_experiment UNIQUE (experiment_id), + -- Ensure only one soaking per repetition CONSTRAINT unique_soaking_per_repetition UNIQUE (repetition_id) ); @@ -29,8 +27,7 @@ CREATE TABLE IF NOT EXISTS public.soaking ( CREATE TABLE IF NOT EXISTS public.airdrying ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE, - repetition_id UUID REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE, + repetition_id UUID NOT NULL REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE, scheduled_start_time TIMESTAMP WITH TIME ZONE NOT NULL, actual_start_time TIMESTAMP WITH TIME ZONE, duration_minutes INTEGER NOT NULL CHECK (duration_minutes > 0), @@ -40,8 +37,7 @@ CREATE TABLE IF NOT EXISTS public.airdrying ( updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), created_by UUID NOT NULL REFERENCES public.user_profiles(id), - -- Ensure only one airdrying per experiment or repetition - CONSTRAINT unique_airdrying_per_experiment UNIQUE (experiment_id), + -- Ensure only one airdrying per repetition CONSTRAINT unique_airdrying_per_repetition UNIQUE (repetition_id) ); @@ -51,8 +47,7 @@ CREATE TABLE IF NOT EXISTS public.airdrying ( CREATE TABLE IF NOT EXISTS public.cracking ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE, - repetition_id UUID REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE, + repetition_id UUID NOT NULL REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE, machine_type_id UUID NOT NULL REFERENCES public.machine_types(id), scheduled_start_time TIMESTAMP WITH TIME ZONE NOT NULL, actual_start_time TIMESTAMP WITH TIME ZONE, @@ -61,8 +56,7 @@ CREATE TABLE IF NOT EXISTS public.cracking ( updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), created_by UUID NOT NULL REFERENCES public.user_profiles(id), - -- Ensure only one cracking per experiment or repetition - CONSTRAINT unique_cracking_per_experiment UNIQUE (experiment_id), + -- Ensure only one cracking per repetition CONSTRAINT unique_cracking_per_repetition UNIQUE (repetition_id) ); @@ -72,8 +66,7 @@ CREATE TABLE IF NOT EXISTS public.cracking ( CREATE TABLE IF NOT EXISTS public.shelling ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE, - repetition_id UUID REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE, + repetition_id UUID NOT NULL REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE, scheduled_start_time TIMESTAMP WITH TIME ZONE NOT NULL, actual_start_time TIMESTAMP WITH TIME ZONE, actual_end_time TIMESTAMP WITH TIME ZONE, @@ -81,8 +74,7 @@ CREATE TABLE IF NOT EXISTS public.shelling ( updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), created_by UUID NOT NULL REFERENCES public.user_profiles(id), - -- Ensure only one shelling per experiment or repetition - CONSTRAINT unique_shelling_per_experiment UNIQUE (experiment_id), + -- Ensure only one shelling per repetition CONSTRAINT unique_shelling_per_repetition UNIQUE (repetition_id) ); @@ -90,12 +82,6 @@ CREATE TABLE IF NOT EXISTS public.shelling ( -- 5. INDEXES FOR PERFORMANCE -- ============================================= --- Create indexes for experiment_id references -CREATE INDEX IF NOT EXISTS idx_soaking_experiment_id ON public.soaking(experiment_id); -CREATE INDEX IF NOT EXISTS idx_airdrying_experiment_id ON public.airdrying(experiment_id); -CREATE INDEX IF NOT EXISTS idx_cracking_experiment_id ON public.cracking(experiment_id); -CREATE INDEX IF NOT EXISTS idx_shelling_experiment_id ON public.shelling(experiment_id); - -- Create indexes for repetition references CREATE INDEX IF NOT EXISTS idx_soaking_repetition_id ON public.soaking(repetition_id); CREATE INDEX IF NOT EXISTS idx_airdrying_repetition_id ON public.airdrying(repetition_id); @@ -138,11 +124,11 @@ CREATE OR REPLACE FUNCTION set_airdrying_scheduled_start_time() RETURNS TRIGGER AS $$ BEGIN -- If this is a new airdrying record and no scheduled_start_time is provided, - -- try to get it from the associated soaking's scheduled_end_time + -- try to get it from the associated soaking's scheduled_end_time for the same repetition IF NEW.scheduled_start_time IS NULL THEN SELECT s.scheduled_end_time INTO NEW.scheduled_start_time FROM public.soaking s - WHERE s.experiment_id = NEW.experiment_id + WHERE s.repetition_id = NEW.repetition_id LIMIT 1; END IF; RETURN NEW; @@ -154,11 +140,11 @@ CREATE OR REPLACE FUNCTION set_cracking_scheduled_start_time() RETURNS TRIGGER AS $$ BEGIN -- If this is a new cracking record and no scheduled_start_time is provided, - -- try to get it from the associated airdrying's scheduled_end_time + -- try to get it from the associated airdrying's scheduled_end_time for the same repetition IF NEW.scheduled_start_time IS NULL THEN SELECT a.scheduled_end_time INTO NEW.scheduled_start_time FROM public.airdrying a - WHERE a.experiment_id = NEW.experiment_id + WHERE a.repetition_id = NEW.repetition_id LIMIT 1; END IF; RETURN NEW; diff --git a/management-dashboard-web-app/supabase/migrations/00011_views.sql b/management-dashboard-web-app/supabase/migrations/00011_views.sql index a7f1cc0..29885bf 100644 --- a/management-dashboard-web-app/supabase/migrations/00011_views.sql +++ b/management-dashboard-web-app/supabase/migrations/00011_views.sql @@ -6,6 +6,7 @@ -- ============================================= -- View for experiments with all phase information +-- Note: Since phases are now per-repetition, this view shows phase data from the first repetition CREATE OR REPLACE VIEW public.experiments_with_phases AS SELECT e.id, @@ -24,6 +25,8 @@ SELECT ep.has_airdrying, ep.has_cracking, ep.has_shelling, + er.id as first_repetition_id, + er.repetition_number as first_repetition_number, s.id as soaking_id, s.scheduled_start_time as soaking_scheduled_start, s.actual_start_time as soaking_actual_start, @@ -47,11 +50,18 @@ SELECT sh.actual_end_time as shelling_actual_end FROM public.experiments e LEFT JOIN public.experiment_phases ep ON e.phase_id = ep.id -LEFT JOIN public.soaking s ON s.experiment_id = e.id -LEFT JOIN public.airdrying ad ON ad.experiment_id = e.id -LEFT JOIN public.cracking c ON c.experiment_id = e.id +LEFT JOIN LATERAL ( + SELECT id, repetition_number + FROM public.experiment_repetitions + WHERE experiment_id = e.id + ORDER BY repetition_number + LIMIT 1 +) er ON true +LEFT JOIN public.soaking s ON s.repetition_id = er.id +LEFT JOIN public.airdrying ad ON ad.repetition_id = er.id +LEFT JOIN public.cracking c ON c.repetition_id = er.id LEFT JOIN public.machine_types mt ON c.machine_type_id = mt.id -LEFT JOIN public.shelling sh ON sh.experiment_id = e.id; +LEFT JOIN public.shelling sh ON sh.repetition_id = er.id; -- View for repetitions with phase information CREATE OR REPLACE VIEW public.repetitions_with_phases AS diff --git a/management-dashboard-web-app/supabase/migrations/00013_add_repetition_id_to_cracker_parameters.sql b/management-dashboard-web-app/supabase/migrations/00013_add_repetition_id_to_cracker_parameters.sql new file mode 100644 index 0000000..4dae1d1 --- /dev/null +++ b/management-dashboard-web-app/supabase/migrations/00013_add_repetition_id_to_cracker_parameters.sql @@ -0,0 +1,35 @@ +-- Add repetition_id foreign key to cracker parameters tables +-- This migration adds a foreign key to link cracker parameters to their repetitions + +-- ============================================= +-- 1. ADD REPETITION_ID TO JC CRACKER PARAMETERS +-- ============================================= + +ALTER TABLE public.jc_cracker_parameters +ADD COLUMN IF NOT EXISTS repetition_id UUID REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE; + +-- Add index for performance +CREATE INDEX IF NOT EXISTS idx_jc_cracker_parameters_repetition_id + ON public.jc_cracker_parameters(repetition_id); + +-- Add unique constraint to ensure one parameter set per repetition +ALTER TABLE public.jc_cracker_parameters +ADD CONSTRAINT unique_jc_cracker_parameters_per_repetition + UNIQUE (repetition_id); + +-- ============================================= +-- 2. ADD REPETITION_ID TO MEYER CRACKER PARAMETERS +-- ============================================= + +ALTER TABLE public.meyer_cracker_parameters +ADD COLUMN IF NOT EXISTS repetition_id UUID REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE; + +-- Add index for performance +CREATE INDEX IF NOT EXISTS idx_meyer_cracker_parameters_repetition_id + ON public.meyer_cracker_parameters(repetition_id); + +-- Add unique constraint to ensure one parameter set per repetition +ALTER TABLE public.meyer_cracker_parameters +ADD CONSTRAINT unique_meyer_cracker_parameters_per_repetition + UNIQUE (repetition_id); + diff --git a/management-dashboard-web-app/supabase/seed_02_phase2_experiments.sql b/management-dashboard-web-app/supabase/seed_02_phase2_experiments.sql new file mode 100644 index 0000000..6117e7f --- /dev/null +++ b/management-dashboard-web-app/supabase/seed_02_phase2_experiments.sql @@ -0,0 +1,3196 @@ +-- ============================================== +-- 6. CREATE EXPERIMENTS FOR PHASE 2 +-- ============================================== + +-- This seed file creates experiments from phase_2_JC_experimental_run_sheet.csv +-- Each experiment has 3 repetitions with specific parameters +-- Experiment numbers are incremented by 1 (CSV 0-19 becomes DB 1-20) + +-- Create experiments +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 1, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 2, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 3, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 4, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 5, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 6, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 7, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 8, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 9, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 10, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 11, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 12, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 13, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 14, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 15, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 16, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 17, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 18, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 19, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +INSERT INTO public.experiments (experiment_number, reps_required, weight_per_repetition_lbs, phase_id, created_by) +VALUES ( + 20, + 3, + 33, + (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Create repetitions for each experiment +-- Note: Phase executions are automatically created by trigger when repetitions are inserted + +-- Experiment 1, Repetition 1 (CSV experiment_number 0) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 1 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 1, Repetition 2 (CSV experiment_number 0) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 1 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 1, Repetition 3 (CSV experiment_number 0) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 1 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 2, Repetition 1 (CSV experiment_number 1) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 2 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 2, Repetition 2 (CSV experiment_number 1) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 2 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 2, Repetition 3 (CSV experiment_number 1) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 2 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 3, Repetition 1 (CSV experiment_number 2) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 3 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 3, Repetition 2 (CSV experiment_number 2) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 3 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 3, Repetition 3 (CSV experiment_number 2) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 3 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 4, Repetition 1 (CSV experiment_number 3) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 4 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 4, Repetition 2 (CSV experiment_number 3) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 4 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 4, Repetition 3 (CSV experiment_number 3) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 4 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 5, Repetition 1 (CSV experiment_number 4) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 5 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 5, Repetition 2 (CSV experiment_number 4) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 5 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 5, Repetition 3 (CSV experiment_number 4) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 5 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 6, Repetition 1 (CSV experiment_number 5) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 6 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 6, Repetition 2 (CSV experiment_number 5) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 6 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 6, Repetition 3 (CSV experiment_number 5) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 6 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 7, Repetition 1 (CSV experiment_number 6) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 7 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 7, Repetition 2 (CSV experiment_number 6) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 7 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 7, Repetition 3 (CSV experiment_number 6) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 7 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 8, Repetition 1 (CSV experiment_number 7) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 8 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 8, Repetition 2 (CSV experiment_number 7) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 8 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 8, Repetition 3 (CSV experiment_number 7) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 8 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 9, Repetition 1 (CSV experiment_number 8) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 9 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 9, Repetition 2 (CSV experiment_number 8) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 9 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 9, Repetition 3 (CSV experiment_number 8) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 9 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 10, Repetition 1 (CSV experiment_number 9) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 10 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 10, Repetition 2 (CSV experiment_number 9) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 10 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 10, Repetition 3 (CSV experiment_number 9) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 10 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 11, Repetition 1 (CSV experiment_number 10) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 11 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 11, Repetition 2 (CSV experiment_number 10) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 11 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 11, Repetition 3 (CSV experiment_number 10) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 11 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 12, Repetition 1 (CSV experiment_number 11) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 12 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 12, Repetition 2 (CSV experiment_number 11) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 12 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 12, Repetition 3 (CSV experiment_number 11) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 12 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 13, Repetition 1 (CSV experiment_number 12) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 13 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 13, Repetition 2 (CSV experiment_number 12) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 13 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 13, Repetition 3 (CSV experiment_number 12) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 13 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 14, Repetition 1 (CSV experiment_number 13) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 14 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 14, Repetition 2 (CSV experiment_number 13) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 14 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 14, Repetition 3 (CSV experiment_number 13) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 14 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 15, Repetition 1 (CSV experiment_number 14) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 15 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 15, Repetition 2 (CSV experiment_number 14) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 15 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 15, Repetition 3 (CSV experiment_number 14) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 15 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 16, Repetition 1 (CSV experiment_number 15) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 16 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 16, Repetition 2 (CSV experiment_number 15) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 16 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 16, Repetition 3 (CSV experiment_number 15) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 16 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 17, Repetition 1 (CSV experiment_number 16) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 17 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 17, Repetition 2 (CSV experiment_number 16) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 17 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 17, Repetition 3 (CSV experiment_number 16) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 17 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 18, Repetition 1 (CSV experiment_number 17) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 18 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 18, Repetition 2 (CSV experiment_number 17) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 18 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 18, Repetition 3 (CSV experiment_number 17) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 18 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 19, Repetition 1 (CSV experiment_number 18) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 19 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 19, Repetition 2 (CSV experiment_number 18) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 19 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 19, Repetition 3 (CSV experiment_number 18) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 19 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 20, Repetition 1 (CSV experiment_number 19) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 20 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 1, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 20, Repetition 2 (CSV experiment_number 19) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 20 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 2, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Experiment 20, Repetition 3 (CSV experiment_number 19) +INSERT INTO public.experiment_repetitions (experiment_id, repetition_number, created_by) +VALUES ( + (SELECT id FROM public.experiments WHERE experiment_number = 20 AND phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 3, + (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com') +); + +-- Update phase executions with parameters from CSV + +-- Experiment 1, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 2040 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 1 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 19 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 1 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 1, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 2040 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 1 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 19 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 1 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 1, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 2040 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 1 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 19 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 1 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 2, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1440 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 2 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 27 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 2 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 2, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1440 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 2 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 27 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 2 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 2, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1440 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 2 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 27 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 2 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 3, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 2280 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 3 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 10 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 3 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 3, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 2280 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 3 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 10 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 3 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 3, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 2280 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 3 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 10 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 3 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 4, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 660 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 4 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 36 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 4 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 4, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 660 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 4 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 36 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 4 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 4, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 660 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 4 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 36 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 4 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 5, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 780 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 5 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 41 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 5 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 5, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 780 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 5 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 41 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 5 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 5, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 780 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 5 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 41 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 5 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 6, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1800 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 6 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 33 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 6 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 6, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1800 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 6 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 33 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 6 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 6, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1800 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 6 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 33 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 6 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 7, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 600 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 7 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 22 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 7 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 7, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 600 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 7 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 22 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 7 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 7, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 600 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 7 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 22 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 7 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 8, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 900 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 8 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 30 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 8 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 8, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 900 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 8 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 30 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 8 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 8, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 900 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 8 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 30 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 8 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 9, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1620 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 9 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 12 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 9 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 9, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1620 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 9 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 12 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 9 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 9, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1620 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 9 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 12 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 9 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 10, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1920 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 10 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 26 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 10 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 10, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1920 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 10 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 26 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 10 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 10, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1920 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 10 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 26 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 10 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 11, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1560 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 11 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 60 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 11 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 11, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1560 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 11 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 60 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 11 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 11, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1560 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 11 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 60 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 11 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 12, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1440 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 12 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 59 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 12 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 12, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1440 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 12 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 59 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 12 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 12, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1440 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 12 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 59 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 12 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 13, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1680 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 13 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 59 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 13 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 13, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1680 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 13 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 59 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 13 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 13, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1680 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 13 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 59 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 13 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 14, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1260 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 14 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 59 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 14 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 14, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1260 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 14 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 59 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 14 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 14, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1260 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 14 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 59 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 14 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 15, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1320 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 15 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 59 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 15 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 15, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1320 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 15 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 59 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 15 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 15, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1320 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 15 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 59 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 15 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 16, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 960 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 16 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 60 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 16 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 16, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 960 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 16 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 60 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 16 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 16, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 960 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 16 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 60 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 16 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 17, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1200 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 17 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 59 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 17 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 17, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1200 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 17 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 59 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 17 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 17, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1200 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 17 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 59 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 17 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 18, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 2040 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 18 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 60 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 18 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 18, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 2040 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 18 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 60 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 18 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 18, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 2040 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 18 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 60 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 18 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 19, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1080 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 19 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 49 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 19 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 19, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1080 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 19 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 49 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 19 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 19, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 1080 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 19 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 49 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 19 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 20, Repetition 1 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 660 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 20 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 25 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 20 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 20, Repetition 2 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 660 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 20 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 25 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 20 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Experiment 20, Repetition 3 - Update phase executions +UPDATE public.experiment_phase_executions +SET soaking_duration_minutes = 660 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 20 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'soaking'; + +UPDATE public.experiment_phase_executions +SET duration_minutes = 25 +WHERE repetition_id = ( + SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 20 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') +) +AND phase_type = 'airdrying'; + +-- Create JC cracker parameters for each repetition +-- Each parameter set is linked to its repetition via repetition_id + +-- Experiment 1, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 1 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 53.0, + 28.0, + 0.05, + -0.09 +); + +-- Experiment 1, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 1 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 53.0, + 28.0, + 0.05, + -0.09 +); + +-- Experiment 1, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 1 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 53.0, + 28.0, + 0.05, + -0.09 +); + +-- Experiment 2, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 2 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 34.0, + 29.0, + 0.03, + 0.01 +); + +-- Experiment 2, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 2 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 34.0, + 29.0, + 0.03, + 0.01 +); + +-- Experiment 2, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 2 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 34.0, + 29.0, + 0.03, + 0.01 +); + +-- Experiment 3, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 3 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 60.0, + 28.0, + 0.06, + -0.1 +); + +-- Experiment 3, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 3 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 60.0, + 28.0, + 0.06, + -0.1 +); + +-- Experiment 3, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 3 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 60.0, + 28.0, + 0.06, + -0.1 +); + +-- Experiment 4, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 4 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 42.0, + 13.0, + 0.07, + -0.07 +); + +-- Experiment 4, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 4 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 42.0, + 13.0, + 0.07, + -0.07 +); + +-- Experiment 4, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 4 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 42.0, + 13.0, + 0.07, + -0.07 +); + +-- Experiment 5, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 5 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 41.0, + 38.0, + 0.05, + 0.03 +); + +-- Experiment 5, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 5 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 41.0, + 38.0, + 0.05, + 0.03 +); + +-- Experiment 5, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 5 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 41.0, + 38.0, + 0.05, + 0.03 +); + +-- Experiment 6, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 6 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 30.0, + 36.0, + 0.05, + -0.04 +); + +-- Experiment 6, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 6 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 30.0, + 36.0, + 0.05, + -0.04 +); + +-- Experiment 6, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 6 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 30.0, + 36.0, + 0.05, + -0.04 +); + +-- Experiment 7, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 7 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 37.0, + 30.0, + 0.06, + 0.02 +); + +-- Experiment 7, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 7 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 37.0, + 30.0, + 0.06, + 0.02 +); + +-- Experiment 7, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 7 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 37.0, + 30.0, + 0.06, + 0.02 +); + +-- Experiment 8, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 8 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 35.0, + 32.0, + 0.05, + -0.07 +); + +-- Experiment 8, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 8 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 35.0, + 32.0, + 0.05, + -0.07 +); + +-- Experiment 8, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 8 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 35.0, + 32.0, + 0.05, + -0.07 +); + +-- Experiment 9, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 9 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 55.0, + 24.0, + 0.04, + 0.04 +); + +-- Experiment 9, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 9 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 55.0, + 24.0, + 0.04, + 0.04 +); + +-- Experiment 9, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 9 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 55.0, + 24.0, + 0.04, + 0.04 +); + +-- Experiment 10, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 10 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 47.0, + 26.0, + 0.07, + 0.03 +); + +-- Experiment 10, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 10 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 47.0, + 26.0, + 0.07, + 0.03 +); + +-- Experiment 10, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 10 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 47.0, + 26.0, + 0.07, + 0.03 +); + +-- Experiment 11, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 11 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 44.0, + 12.0, + 0.08, + -0.1 +); + +-- Experiment 11, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 11 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 44.0, + 12.0, + 0.08, + -0.1 +); + +-- Experiment 11, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 11 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 44.0, + 12.0, + 0.08, + -0.1 +); + +-- Experiment 12, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 12 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 42.0, + 25.0, + 0.07, + -0.05 +); + +-- Experiment 12, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 12 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 42.0, + 25.0, + 0.07, + -0.05 +); + +-- Experiment 12, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 12 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 42.0, + 25.0, + 0.07, + -0.05 +); + +-- Experiment 13, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 13 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 37.0, + 23.0, + 0.06, + -0.08 +); + +-- Experiment 13, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 13 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 37.0, + 23.0, + 0.06, + -0.08 +); + +-- Experiment 13, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 13 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 37.0, + 23.0, + 0.06, + -0.08 +); + +-- Experiment 14, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 14 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 41.0, + 21.0, + 0.06, + -0.09 +); + +-- Experiment 14, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 14 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 41.0, + 21.0, + 0.06, + -0.09 +); + +-- Experiment 14, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 14 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 41.0, + 21.0, + 0.06, + -0.09 +); + +-- Experiment 15, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 15 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 45.0, + 17.0, + 0.07, + -0.08 +); + +-- Experiment 15, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 15 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 45.0, + 17.0, + 0.07, + -0.08 +); + +-- Experiment 15, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 15 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 45.0, + 17.0, + 0.07, + -0.08 +); + +-- Experiment 16, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 16 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 30.0, + 24.0, + 0.07, + 0.02 +); + +-- Experiment 16, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 16 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 30.0, + 24.0, + 0.07, + 0.02 +); + +-- Experiment 16, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 16 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 30.0, + 24.0, + 0.07, + 0.02 +); + +-- Experiment 17, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 17 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 41.0, + 14.0, + 0.07, + 0.04 +); + +-- Experiment 17, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 17 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 41.0, + 14.0, + 0.07, + 0.04 +); + +-- Experiment 17, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 17 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 41.0, + 14.0, + 0.07, + 0.04 +); + +-- Experiment 18, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 18 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 34.0, + 29.0, + 0.07, + -0.09 +); + +-- Experiment 18, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 18 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 34.0, + 29.0, + 0.07, + -0.09 +); + +-- Experiment 18, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 18 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 34.0, + 29.0, + 0.07, + -0.09 +); + +-- Experiment 19, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 19 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 38.0, + 35.0, + 0.07, + -0.08 +); + +-- Experiment 19, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 19 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 38.0, + 35.0, + 0.07, + -0.08 +); + +-- Experiment 19, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 19 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 38.0, + 35.0, + 0.07, + -0.08 +); + +-- Experiment 20, Repetition 1 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 20 + AND er.repetition_number = 1 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 56.0, + 34.0, + 0.06, + -0.09 +); + +-- Experiment 20, Repetition 2 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 20 + AND er.repetition_number = 2 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 56.0, + 34.0, + 0.06, + -0.09 +); + +-- Experiment 20, Repetition 3 - JC Cracker Parameters +INSERT INTO public.jc_cracker_parameters ( + repetition_id, + plate_contact_frequency_hz, + throughput_rate_pecans_sec, + crush_amount_in, + entry_exit_height_diff_in +) VALUES ( + (SELECT er.id FROM public.experiment_repetitions er + JOIN public.experiments e ON er.experiment_id = e.id + WHERE e.experiment_number = 20 + AND er.repetition_number = 3 + AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments')), + 56.0, + 34.0, + 0.06, + -0.09 +); diff --git a/scheduling-remote/src/components/Scheduling.tsx b/scheduling-remote/src/components/Scheduling.tsx index 8d028e1..42f27da 100644 --- a/scheduling-remote/src/components/Scheduling.tsx +++ b/scheduling-remote/src/components/Scheduling.tsx @@ -932,7 +932,6 @@ function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void } // Create/update soaking record with repetition_id await phaseManagement.createSoaking({ - experiment_id: experimentId, repetition_id: repId, scheduled_start_time: soakingStart.toISOString(), soaking_duration_minutes: soaking.soaking_duration_minutes @@ -940,7 +939,6 @@ function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void } // Create/update airdrying record with repetition_id await phaseManagement.createAirdrying({ - experiment_id: experimentId, repetition_id: repId, scheduled_start_time: airdryingStart.toISOString(), duration_minutes: airdrying.duration_minutes @@ -953,7 +951,6 @@ function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void } if (phase?.cracking_machine_type_id) { await phaseManagement.createCracking({ - experiment_id: experimentId, repetition_id: repId, machine_type_id: phase.cracking_machine_type_id, scheduled_start_time: crackingStart.toISOString() @@ -995,8 +992,8 @@ function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void } return ( -
-
+
+
-
+
+
{error && (
{error}
)} @@ -1250,8 +1248,8 @@ function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void }
)} {/* Week Calendar for selected conductors' availability */} -
-
+
+

Selected Conductors' Availability & Experiment Scheduling

Marker Style: @@ -1293,7 +1291,7 @@ function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void }
-
+
void }
+
) diff --git a/scheduling-remote/src/services/supabase.ts b/scheduling-remote/src/services/supabase.ts index 0bd2e07..9d959fc 100644 --- a/scheduling-remote/src/services/supabase.ts +++ b/scheduling-remote/src/services/supabase.ts @@ -63,8 +63,7 @@ export interface ExperimentRepetition { export interface Soaking { id: string - experiment_id: string - repetition_id?: string | null + repetition_id: string scheduled_start_time: string actual_start_time?: string | null soaking_duration_minutes: number @@ -77,8 +76,7 @@ export interface Soaking { export interface Airdrying { id: string - experiment_id: string - repetition_id?: string | null + repetition_id: string scheduled_start_time: string actual_start_time?: string | null duration_minutes: number @@ -119,22 +117,19 @@ export interface UpdateRepetitionRequest { } export interface CreateSoakingRequest { - experiment_id: string - repetition_id?: string | null + repetition_id: string scheduled_start_time: string soaking_duration_minutes: number } export interface CreateAirdryingRequest { - experiment_id: string - repetition_id?: string | null + repetition_id: string scheduled_start_time: string duration_minutes: number } export interface CreateCrackingRequest { - experiment_id: string - repetition_id?: string | null + repetition_id: string machine_type_id: string scheduled_start_time: string } @@ -277,16 +272,22 @@ export const phaseManagement = { const { data: { user }, error: authError } = await supabase.auth.getUser() if (authError || !user) throw new Error('User not authenticated') + if (!request.repetition_id) { + throw new Error('repetition_id is required') + } + const scheduledEndTime = new Date(new Date(request.scheduled_start_time).getTime() + request.soaking_duration_minutes * 60000).toISOString() const { data, error } = await supabase .from('soaking') .upsert({ - ...request, + repetition_id: request.repetition_id, + scheduled_start_time: request.scheduled_start_time, + soaking_duration_minutes: request.soaking_duration_minutes, scheduled_end_time: scheduledEndTime, created_by: user.id }, { - onConflict: 'experiment_id,repetition_id' + onConflict: 'repetition_id' }) .select() .single() @@ -299,16 +300,26 @@ export const phaseManagement = { const { data: { user }, error: authError } = await supabase.auth.getUser() if (authError || !user) throw new Error('User not authenticated') + if (!request.repetition_id) { + throw new Error('repetition_id is required') + } + + if (!request.scheduled_start_time) { + throw new Error('scheduled_start_time is required') + } + const scheduledEndTime = new Date(new Date(request.scheduled_start_time).getTime() + request.duration_minutes * 60000).toISOString() const { data, error } = await supabase .from('airdrying') .upsert({ - ...request, + repetition_id: request.repetition_id, + scheduled_start_time: request.scheduled_start_time, + duration_minutes: request.duration_minutes, scheduled_end_time: scheduledEndTime, created_by: user.id }, { - onConflict: 'experiment_id,repetition_id' + onConflict: 'repetition_id' }) .select() .single() @@ -321,13 +332,23 @@ export const phaseManagement = { const { data: { user }, error: authError } = await supabase.auth.getUser() if (authError || !user) throw new Error('User not authenticated') + if (!request.repetition_id) { + throw new Error('repetition_id is required') + } + + if (!request.scheduled_start_time) { + throw new Error('scheduled_start_time is required') + } + const { data, error } = await supabase .from('cracking') .upsert({ - ...request, + repetition_id: request.repetition_id, + machine_type_id: request.machine_type_id, + scheduled_start_time: request.scheduled_start_time, created_by: user.id }, { - onConflict: 'experiment_id,repetition_id' + onConflict: 'repetition_id' }) .select() .single() @@ -337,11 +358,23 @@ export const phaseManagement = { }, async getSoakingByExperimentId(experimentId: string): Promise { + // Get the first repetition for this experiment + const { data: repetitions, error: repsError } = await supabase + .from('experiment_repetitions') + .select('id') + .eq('experiment_id', experimentId) + .order('repetition_number', { ascending: true }) + .limit(1) + + if (repsError || !repetitions || repetitions.length === 0) { + return null + } + + // Get soaking for the first repetition const { data, error } = await supabase .from('soaking') .select('*') - .eq('experiment_id', experimentId) - .is('repetition_id', null) + .eq('repetition_id', repetitions[0].id) .single() if (error) { @@ -352,11 +385,23 @@ export const phaseManagement = { }, async getAirdryingByExperimentId(experimentId: string): Promise { + // Get the first repetition for this experiment + const { data: repetitions, error: repsError } = await supabase + .from('experiment_repetitions') + .select('id') + .eq('experiment_id', experimentId) + .order('repetition_number', { ascending: true }) + .limit(1) + + if (repsError || !repetitions || repetitions.length === 0) { + return null + } + + // Get airdrying for the first repetition const { data, error } = await supabase .from('airdrying') .select('*') - .eq('experiment_id', experimentId) - .is('repetition_id', null) + .eq('repetition_id', repetitions[0].id) .single() if (error) { diff --git a/scheduling-remote/vite.config.ts b/scheduling-remote/vite.config.ts index f510654..f26fa29 100644 --- a/scheduling-remote/vite.config.ts +++ b/scheduling-remote/vite.config.ts @@ -27,6 +27,14 @@ export default defineConfig({ }, build: { target: 'esnext', + rollupOptions: { + output: { + // Add hash to filenames for cache busting + entryFileNames: 'assets/[name]-[hash].js', + chunkFileNames: 'assets/[name]-[hash].js', + assetFileNames: 'assets/[name]-[hash].[ext]', + }, + }, }, }) diff --git a/scripts/diagnose_container_crashes.sh b/scripts/diagnose_container_crashes.sh new file mode 100755 index 0000000..c517549 --- /dev/null +++ b/scripts/diagnose_container_crashes.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# Diagnostic script to investigate container crashes + +echo "==========================================" +echo "Container Crash Diagnostic" +echo "==========================================" +echo "" + +echo "1. Checking container status..." +docker ps -a | grep usda-vision-api +echo "" + +echo "2. Recent container exit codes and status..." +docker inspect usda-vision-api --format='{{.State.Status}} - Exit Code: {{.State.ExitCode}} - Started: {{.State.StartedAt}} - Finished: {{.State.FinishedAt}}' 2>/dev/null || echo "Container not found" +echo "" + +echo "3. Last 50 lines of container logs..." +docker logs usda-vision-api --tail 50 2>&1 +echo "" + +echo "4. Checking for common error patterns..." +docker logs usda-vision-api 2>&1 | grep -iE "error|exception|failed|fatal|traceback|crash" | tail -20 +echo "" + +echo "5. Checking container resource usage (if running)..." +docker stats usda-vision-api --no-stream 2>/dev/null || echo "Container not running" +echo "" + +echo "6. Checking if config file exists in container..." +docker exec usda-vision-api ls -la /app/config.compose.json 2>/dev/null || echo "Cannot access container or file missing" +echo "" + +echo "7. Checking Python process..." +docker exec usda-vision-api ps aux | grep python 2>/dev/null || echo "Cannot access container" +echo "" + +echo "8. Checking for OOM (Out of Memory) kills..." +dmesg | grep -i "killed process" | tail -5 || echo "No OOM kills found in dmesg (may require sudo)" +echo "" + +echo "9. Container restart count..." +docker inspect usda-vision-api --format='Restart Count: {{.RestartCount}}' 2>/dev/null || echo "Container not found" +echo "" + +echo "10. Checking docker-compose status..." +docker compose ps api 2>/dev/null || echo "Cannot check compose status" +echo "" + +echo "==========================================" +echo "Diagnostic Complete" +echo "==========================================" +echo "" +echo "Common causes of crashes:" +echo " - MQTT connection failure (check broker at 192.168.1.110:1883)" +echo " - Camera SDK initialization failure" +echo " - Storage path issues (/mnt/nfs_share)" +echo " - Out of memory (OOM)" +echo " - Missing config file" +echo " - Python exception not caught" +echo "" + diff --git a/video-remote/src/components/FiltersBar.tsx b/video-remote/src/components/FiltersBar.tsx index 962f4a9..451c35b 100644 --- a/video-remote/src/components/FiltersBar.tsx +++ b/video-remote/src/components/FiltersBar.tsx @@ -1,19 +1,23 @@ import React, { useState } from 'react' type Props = { - onChange: (filters: { camera_name?: string; start_date?: string; end_date?: string }) => void + onChange: (filters: { camera_name?: string; start_date?: string; end_date?: string; min_size_mb?: number; max_size_mb?: number }) => void } export const FiltersBar: React.FC = ({ onChange }) => { const [camera, setCamera] = useState('') const [start, setStart] = useState('') const [end, setEnd] = useState('') + const [minSize, setMinSize] = useState('') + const [maxSize, setMaxSize] = useState('') const handleApply = () => { onChange({ camera_name: camera || undefined, start_date: start || undefined, - end_date: end || undefined + end_date: end || undefined, + min_size_mb: minSize ? parseFloat(minSize) : undefined, + max_size_mb: maxSize ? parseFloat(maxSize) : undefined }) } @@ -21,6 +25,8 @@ export const FiltersBar: React.FC = ({ onChange }) => { setCamera('') setStart('') setEnd('') + setMinSize('') + setMaxSize('') onChange({}) } @@ -35,7 +41,7 @@ export const FiltersBar: React.FC = ({ onChange }) => { Reset all
-
+
+
+ + setMinSize(e.target.value)} + placeholder="Min MB" + className="w-full px-3 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors text-sm" + /> +
+
+ + setMaxSize(e.target.value)} + placeholder="Max MB" + className="w-full px-3 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors text-sm" + /> +
diff --git a/video-remote/src/services/video.ts b/video-remote/src/services/video.ts index 9230664..d82d4e9 100644 --- a/video-remote/src/services/video.ts +++ b/video-remote/src/services/video.ts @@ -1,4 +1,4 @@ -type VideoListParams = { camera_name?: string; start_date?: string; end_date?: string; limit?: number; page?: number; offset?: number; include_metadata?: boolean } +type VideoListParams = { camera_name?: string; start_date?: string; end_date?: string; limit?: number; page?: number; offset?: number; include_metadata?: boolean; min_size_mb?: number; max_size_mb?: number } type VideoFile = { file_id: string; camera_name: string; filename: string; file_size_bytes: number; format: string; status: string; created_at: string; is_streamable: boolean; needs_conversion: boolean } type VideoListResponse = { videos: VideoFile[]; total_count: number; page?: number; total_pages?: number }