Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision | |||
| wiki:facility:software:scheduling_documentation [2025/05/04 16:15] – Shanmukha Doddipatla | wiki:facility:software:scheduling_documentation [2025/05/04 16:22] (current) – Shanmukha Doddipatla | ||
|---|---|---|---|
| Line 60: | Line 60: | ||
| Key Functions | Key Functions | ||
| + | |||
| // | // | ||
| + | |||
| This function determines the shift timeframe to use based on date. | This function determines the shift timeframe to use based on date. | ||
| Reads the "Shift Timeframes" | Reads the "Shift Timeframes" | ||
| Line 68: | Line 70: | ||
| Returns null if no valid timeframe is found | Returns null if no valid timeframe is found | ||
| // | // | ||
| + | |||
| This function determines which shift types to include based on the ES1 start time. | This function determines which shift types to include based on the ES1 start time. | ||
| Calls getShiftDuration() to get the ES1 start time | Calls getShiftDuration() to get the ES1 start time | ||
| Line 75: | Line 78: | ||
| Returns a mapping of shift types to their start times | Returns a mapping of shift types to their start times | ||
| // | // | ||
| + | |||
| This is the main entry point function that: | This is the main entry point function that: | ||
| Clears/ | Clears/ | ||
| Line 83: | Line 87: | ||
| Handles email notifications if not in TEST_MODE | Handles email notifications if not in TEST_MODE | ||
| Autoformats the output sheet for readability | Autoformats the output sheet for readability | ||
| - | |||
| // | // | ||
| + | |||
| This is the core scheduling algorithm that: | This is the core scheduling algorithm that: | ||
| Reads the " | Reads the " | ||
| Line 103: | Line 107: | ||
| Logs confirmation of sent emails | Logs confirmation of sent emails | ||
| // | // | ||
| + | |||
| Helper function that randomly shuffles arrays using the Fisher-Yates algorithm for fair distribution. | Helper function that randomly shuffles arrays using the Fisher-Yates algorithm for fair distribution. | ||
| Takes an array as input | Takes an array as input | ||
| Line 109: | Line 114: | ||
| // | // | ||
| + | |||
| Helper function that retrieves email addresses from the availability data. | Helper function that retrieves email addresses from the availability data. | ||
| Searches for the employee name in the first column of data values | Searches for the employee name in the first column of data values | ||
| Line 114: | Line 120: | ||
| Returns null if no match is found | Returns null if no match is found | ||
| **Configuration Options** | **Configuration Options** | ||
| + | |||
| //Global Settings// | //Global Settings// | ||
| + | |||
| TEST_MODE (boolean): When true, email notifications are disabled | TEST_MODE (boolean): When true, email notifications are disabled | ||
| Future date offset (7 days): Added to the current date for timeframe selection | Future date offset (7 days): Added to the current date for timeframe selection | ||
| Line 122: | Line 130: | ||
| Shift variety: The algorithm tries to ensure employees get different shift types | Shift variety: The algorithm tries to ensure employees get different shift types | ||
| **Scheduling Logic** | **Scheduling Logic** | ||
| + | |||
| The scheduling algorithm is implemented through multiple phases and constraints to ensure fair and effective shift distribution. | The scheduling algorithm is implemented through multiple phases and constraints to ensure fair and effective shift distribution. | ||
| Prioritization Phases | Prioritization Phases | ||
| Line 151: | Line 160: | ||
| Prevents exceeding maximum shifts per employee | Prevents exceeding maximum shifts per employee | ||
| Specific Assignment Criteria | Specific Assignment Criteria | ||
| + | |||
| The algorithm considers these factors when assigning shifts: | The algorithm considers these factors when assigning shifts: | ||
| Availability Check | Availability Check | ||
| + | |||
| Employee must have indicated availability for the specific shift | Employee must have indicated availability for the specific shift | ||
| Only employees with TRUE in the corresponding availability column are considered | Only employees with TRUE in the corresponding availability column are considered | ||
| Line 160: | Line 171: | ||
| Once an employee reaches this limit, they' | Once an employee reaches this limit, they' | ||
| Day Assignment Tracking | Day Assignment Tracking | ||
| + | |||
| if (employeeDayAssignments[emp][shiftDay]) return false; | if (employeeDayAssignments[emp][shiftDay]) return false; | ||
| Prevents multiple shifts on the same day for an employee | Prevents multiple shifts on the same day for an employee | ||
| Uses the employeeDayAssignments object to track which days each employee is assigned | Uses the employeeDayAssignments object to track which days each employee is assigned | ||
| GS Shift Rest Day Rule | GS Shift Rest Day Rule | ||
| + | |||
| // Check if employee worked a GS shift yesterday | // Check if employee worked a GS shift yesterday | ||
| var prevDayIndex = (currentDayIndex - 1 + 7) % 7; | var prevDayIndex = (currentDayIndex - 1 + 7) % 7; | ||
| Line 205: | Line 218: | ||
| For ES/MS shifts: prioritizes employees who don't yet have an ES or MS shift | For ES/MS shifts: prioritizes employees who don't yet have an ES or MS shift | ||
| Fairness Through Randomization | Fairness Through Randomization | ||
| + | |||
| // Shuffle employees with the same shift count | // Shuffle employees with the same shift count | ||
| if (i > startIndex) { | if (i > startIndex) { | ||
| Line 218: | Line 232: | ||
| The scheduling logic combines these rules to create a fair, balanced schedule that respects constraints while maximizing shift coverage. | The scheduling logic combines these rules to create a fair, balanced schedule that respects constraints while maximizing shift coverage. | ||
| Output Format | Output Format | ||
| + | |||
| The script outputs the schedule to the " | The script outputs the schedule to the " | ||
| Monday Evening --> Tuesday Morning | Monday Evening --> Tuesday Morning | ||
| Line 235: | Line 250: | ||
| ... | ... | ||
| **Troubleshooting** | **Troubleshooting** | ||
| + | |||
| Common Issues | Common Issues | ||
| + | |||
| No Results from Scheduling | No Results from Scheduling | ||
| + | |||
| Cause: Could be missing data in the Shift Timeframes or Availability sheets | Cause: Could be missing data in the Shift Timeframes or Availability sheets | ||
| Solution: | Solution: | ||
| + | |||
| Check that both sheets exist with exactly these names: "Shift Timeframes" | Check that both sheets exist with exactly these names: "Shift Timeframes" | ||
| Verify the Shift Timeframes sheet has data in the expected format | Verify the Shift Timeframes sheet has data in the expected format | ||
| Line 245: | Line 264: | ||
| Missing Shift Types (MS Shifts) | Missing Shift Types (MS Shifts) | ||
| Cause: MS shifts only appear when ES1 start time is between 16:00-17:30 | Cause: MS shifts only appear when ES1 start time is between 16:00-17:30 | ||
| + | |||
| Solution: | Solution: | ||
| + | |||
| This is expected behavior based on the condition: if (totalMinutes >= 960 && totalMinutes <= 1050) | This is expected behavior based on the condition: if (totalMinutes >= 960 && totalMinutes <= 1050) | ||
| If MS shifts should be included regardless of time, modify the getShiftTimings() function | If MS shifts should be included regardless of time, modify the getShiftTimings() function | ||
| Line 252: | Line 273: | ||
| Making Updates | Making Updates | ||
| + | |||
| This section provides detailed guidance on common modifications your team might need to make. | This section provides detailed guidance on common modifications your team might need to make. | ||
| Modifying the Date Offset | Modifying the Date Offset | ||
| Currently, the script adds 7 days to the current date to determine the shift timeframe. To change this: | Currently, the script adds 7 days to the current date to determine the shift timeframe. To change this: | ||
| // In getShiftDuration() function | // In getShiftDuration() function | ||
| + | |||
| var today = new Date(); | var today = new Date(); | ||
| today.setDate(today.getDate() + 7); // Change 7 to your desired days(based on when we schedule) | today.setDate(today.getDate() + 7); // Change 7 to your desired days(based on when we schedule) | ||
| If you want to make this configurable at the top of the script, add: | If you want to make this configurable at the top of the script, add: | ||
| var DAYS_TO_ADD = 7; // Configure how many days to look ahead | var DAYS_TO_ADD = 7; // Configure how many days to look ahead | ||
| - | |||
| // Then in getShiftDuration() | // Then in getShiftDuration() | ||
| + | |||
| var today = new Date(); | var today = new Date(); | ||
| today.setDate(today.getDate() + DAYS_TO_ADD); | today.setDate(today.getDate() + DAYS_TO_ADD); | ||
| Line 267: | Line 290: | ||
| To change the maximum number of shifts per employee: | To change the maximum number of shifts per employee: | ||
| // In scheduleAllShifts() function | // In scheduleAllShifts() function | ||
| + | |||
| var maxShiftsPerEmployee = 3; // Change to desired number | var maxShiftsPerEmployee = 3; // Change to desired number | ||
| Consider adding this as a global constant at the top of the script for easier configuration: | Consider adding this as a global constant at the top of the script for easier configuration: | ||
| Line 276: | Line 300: | ||
| Modifying Shift Types | Modifying Shift Types | ||
| + | |||
| If you need to add or remove shift types, update the checks in the getShiftTimings() function. | If you need to add or remove shift types, update the checks in the getShiftTimings() function. | ||
| For example, to always include MS shifts regardless of ES1 start time: | For example, to always include MS shifts regardless of ES1 start time: | ||
| Line 306: | Line 331: | ||
| } | } | ||
| Changing Email Notification Format | Changing Email Notification Format | ||
| + | |||
| To modify the email content, update the sendEmailNotifications() function: | To modify the email content, update the sendEmailNotifications() function: | ||
| var subject = "Your Observatory Shift Assignment"; | var subject = "Your Observatory Shift Assignment"; | ||
| // Change email body format | // Change email body format | ||
| + | |||
| var body = "Hello " + employee + ", | var body = "Hello " + employee + ", | ||
| " | " | ||
| Line 316: | Line 343: | ||
| " | " | ||
| Adding Different Constraints | Adding Different Constraints | ||
| + | |||
| To add new scheduling constraints, | To add new scheduling constraints, | ||
| Example - Adding a constraint to prevent working more than 2 consecutive days: | Example - Adding a constraint to prevent working more than 2 consecutive days: | ||
| Line 330: | Line 358: | ||
| if (workingPrevDay1 && workingPrevDay2) return false; | if (workingPrevDay1 && workingPrevDay2) return false; | ||
| Manually Setting a Specific Date | Manually Setting a Specific Date | ||
| + | |||
| If you need to run the script for a specific date instead of current date + 7 days, you can replace: | If you need to run the script for a specific date instead of current date + 7 days, you can replace: | ||
| var today = new Date(); | var today = new Date(); | ||
| Line 337: | Line 366: | ||
| Implementing a Date Selection Dialog | Implementing a Date Selection Dialog | ||
| For more flexibility, | For more flexibility, | ||
| + | |||
| function showDatePickerDialog() { | function showDatePickerDialog() { | ||
| var ui = SpreadsheetApp.getUi(); | var ui = SpreadsheetApp.getUi(); | ||
| Line 402: | Line 432: | ||
| | | ||
| } | } | ||
| - | This documentation should help your team understand how the script works and make necessary updates in the future. | + | |