# Nurse Scheduling with Overtime Compensation

This examples builds on top of the [nurse scheduling example](https://developers.google.com/optimization/service/scheduling/nurse_scheduling_example) to model
regular and overtime compensation, subject to a budget requirement. Besides the
scheduling constraints for the nurses, there is a $10,000 budget for a 4-day
planning horizon. All nurses are paid a base hourly rate of $50/hr and there is
an hourly shift differential of $10/hr for shifts starting at 19hr. Any hour
worked after 40 hours is paid at 1.5x the average base hourly rate (i.e.,
($50+$60)/2=$55).

## Regular and overtime compensation

The base hourly rate, shift differentials and overtime multipliers are
represented with the `hourlyContract` field in [employee](https://developers.google.com/optimization/service/reference/rest/v1/scheduling/solveShiftScheduling#employee). In an
[hourly contract](https://developers.google.com/optimization/service/reference/rest/v1/scheduling/solveShiftScheduling#hourlycontract), the `baseHourlyRate` and the
`hourlyRateShiftDifferentials` model the compensation for regular (non-overtime)
work. These values are also used to estimate an average base hourly rate for
overtime compensation when `overtimePeriods` are provided. Typically an overtime
period matches a week, and multiple overtime periods can be provided as long as
these don't overlap. The hourly contract for the first nurse (Adam), is
represented as:

      {
        "employees": [{
          "id": "Adam",
          "roleIds": ["Registered Nurse"],
          ...
            scheduling constraints
          ...
          "hourlyContract": {
            "baseHourlyRate": 50,
            "hourlyRateShiftDifferentials": {
              "2023-05-01 19hr": 10,
              "2023-05-02 19hr": 10,
              "2023-05-03 19hr": 10,
              "2023-05-04 19hr": 10
            },
            "overtimePeriods": [
              {
                "overtimeMultiplier": 1.5,
                "startDateTime": {
                  "year": 2023,
                  "month": 5,
                  "day": 1
                },
                "endDateTime": {
                  "year": 2023,
                  "month": 5,
                  "day": 5
                },
                "maximumRegularHours": 40
              }
            ]
          }
        }
      }

#### Example with all four employees and their hourly contract


      {
          "employees": [
            {
              "id": "Adam",
              "roleIds": [
                "Registered Nurse"
              ],
              "schedulingConstraints": [
                {
                  "priority": "PRIORITY_HIGH",
                  "startDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 1,
                    "hours": 7
                  },
                  "endDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 5,
                    "hours": 7
                  },
                  "minimumRestMinutes": 720
                },
                {
                  "priority": "PRIORITY_MEDIUM",
                  "startDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 1,
                    "hours": 7
                  },
                  "endDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 5,
                    "hours": 7
                  },
                  "maximumMinutes": 2160
                }
              ],
              "hourlyContract": {
                "baseHourlyRate": 50,
                "hourlyRateShiftDifferentials": {
                  "2023-05-01 19h": 10,
                  "2023-05-02 19h": 10,
                  "2023-05-03 19h": 10,
                  "2023-05-04 19h": 10
                },
                "overtimePeriods": [
                  {
                    "overtimeMultiplier": 1.5,
                    "startDateTime": {
                      "year": 2023,
                      "month": 5,
                      "day": 1
                    },
                    "endDateTime": {
                      "year": 2023,
                      "month": 5,
                      "day": 5
                    },
                    "maximumRegularHours": 40
                  }
                ]
              }
            },
            {
              "id": "Grace",
              "roleIds": [
                "Registered Nurse"
              ],
              "schedulingConstraints": [
                {
                  "priority": "PRIORITY_HIGH",
                  "startDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 1,
                    "hours": 7
                  },
                  "endDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 5,
                    "hours": 7
                  },
                  "minimumRestMinutes": 720
                },
                {
                  "priority": "PRIORITY_MEDIUM",
                  "startDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 1,
                    "hours": 7
                  },
                  "endDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 5,
                    "hours": 7
                  },
                  "maximumMinutes": 2160
                }
              ],
              "hourlyContract": {
                "baseHourlyRate": 50,
                "hourlyRateShiftDifferentials": {
                  "2023-05-01 19h": 10,
                  "2023-05-02 19h": 10,
                  "2023-05-03 19h": 10,
                  "2023-05-04 19h": 10
                },
                "overtimePeriods": [
                  {
                    "overtimeMultiplier": 1.5,
                    "startDateTime": {
                      "year": 2023,
                      "month": 5,
                      "day": 1
                    },
                    "endDateTime": {
                      "year": 2023,
                      "month": 5,
                      "day": 5
                    },
                    "maximumRegularHours": 40
                  }
                ]
              }
            },
            {
              "id": "James",
              "roleIds": [
                "Registered Nurse"
              ],
              "schedulingConstraints": [
                {
                  "priority": "PRIORITY_HIGH",
                  "startDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 1,
                    "hours": 7
                  },
                  "endDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 5,
                    "hours": 7
                  },
                  "minimumRestMinutes": 720
                },
                {
                  "priority": "PRIORITY_MEDIUM",
                  "startDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 1,
                    "hours": 7
                  },
                  "endDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 5,
                    "hours": 7
                  },
                  "maximumMinutes": 2160
                }
              ],
              "hourlyContract": {
                "baseHourlyRate": 50,
                "hourlyRateShiftDifferentials": {
                  "2023-05-01 19h": 10,
                  "2023-05-02 19h": 10,
                  "2023-05-03 19h": 10,
                  "2023-05-04 19h": 10
                },
                "overtimePeriods": [
                  {
                    "overtimeMultiplier": 1.5,
                    "startDateTime": {
                      "year": 2023,
                      "month": 5,
                      "day": 1
                    },
                    "endDateTime": {
                      "year": 2023,
                      "month": 5,
                      "day": 5
                    },
                    "maximumRegularHours": 40
                  }
                ]
              }
            },
            {
              "id": "Alonso",
              "roleIds": [
                "Registered Nurse"
              ],
              "schedulingConstraints": [
                {
                  "priority": "PRIORITY_HIGH",
                  "startDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 1,
                    "hours": 7
                  },
                  "endDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 5,
                    "hours": 7
                  },
                  "minimumRestMinutes": 720
                },
                {
                  "priority": "PRIORITY_MEDIUM",
                  "startDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 1,
                    "hours": 7
                  },
                  "endDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 5,
                    "hours": 7
                  },
                  "maximumMinutes": 2160
                }
              ],
              "hourlyContract": {
                "baseHourlyRate": 50,
                "hourlyRateShiftDifferentials": {
                  "2023-05-01 19h": 10,
                  "2023-05-02 19h": 10,
                  "2023-05-03 19h": 10,
                  "2023-05-04 19h": 10
                },
                "overtimePeriods": [
                  {
                    "overtimeMultiplier": 1.5,
                    "startDateTime": {
                      "year": 2023,
                      "month": 5,
                      "day": 1
                    },
                    "endDateTime": {
                      "year": 2023,
                      "month": 5,
                      "day": 5
                    },
                    "maximumRegularHours": 40
                  }
                ]
              }
            }
        ]
      }
      
## Budget requirement

The total budget of $10,000 is represented with a
[budget requirement](https://developers.google.com/optimization/service/reference/rest/v1/scheduling/solveShiftScheduling#budgetrequirement). The start and end times are
optional, and if given, only shifts and overtime periods within this time window
are considered towards this budget constraint. The corresponding representation
for the first nurse (Adam) can be updated to:

      {
        "totalBudget": 10000,
        "priority": "PRIORITY_HIGH"
      }

#### Example of a complete request


        {
          "employees": [
            {
              "id": "Adam",
              "roleIds": [
                "Registered Nurse"
              ],
              "schedulingConstraints": [
                {
                  "priority": "PRIORITY_HIGH",
                  "startDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 1,
                    "hours": 7
                  },
                  "endDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 5,
                    "hours": 7
                  },
                  "minimumRestMinutes": 720
                },
                {
                  "priority": "PRIORITY_MEDIUM",
                  "startDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 1,
                    "hours": 7
                  },
                  "endDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 5,
                    "hours": 7
                  },
                  "maximumMinutes": 2160
                }
              ],
              "hourlyContract": {
                "baseHourlyRate": 50,
                "hourlyRateShiftDifferentials": {
                  "2023-05-01 19h": 10,
                  "2023-05-02 19h": 10,
                  "2023-05-03 19h": 10,
                  "2023-05-04 19h": 10
                },
                "overtimePeriods": [
                  {
                    "overtimeMultiplier": 1.5,
                    "startDateTime": {
                      "year": 2023,
                      "month": 5,
                      "day": 1
                    },
                    "endDateTime": {
                      "year": 2023,
                      "month": 5,
                      "day": 5
                    },
                    "maximumRegularHours": 40
                  }
                ]
              }
            },
            {
              "id": "Grace",
              "roleIds": [
                "Registered Nurse"
              ],
              "schedulingConstraints": [
                {
                  "priority": "PRIORITY_HIGH",
                  "startDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 1,
                    "hours": 7
                  },
                  "endDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 5,
                    "hours": 7
                  },
                  "minimumRestMinutes": 720
                },
                {
                  "priority": "PRIORITY_MEDIUM",
                  "startDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 1,
                    "hours": 7
                  },
                  "endDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 5,
                    "hours": 7
                  },
                  "maximumMinutes": 2160
                }
              ],
              "hourlyContract": {
                "baseHourlyRate": 50,
                "hourlyRateShiftDifferentials": {
                  "2023-05-01 19h": 10,
                  "2023-05-02 19h": 10,
                  "2023-05-03 19h": 10,
                  "2023-05-04 19h": 10
                },
                "overtimePeriods": [
                  {
                    "overtimeMultiplier": 1.5,
                    "startDateTime": {
                      "year": 2023,
                      "month": 5,
                      "day": 1
                    },
                    "endDateTime": {
                      "year": 2023,
                      "month": 5,
                      "day": 5
                    },
                    "maximumRegularHours": 40
                  }
                ]
              }
            },
            {
              "id": "James",
              "roleIds": [
                "Registered Nurse"
              ],
              "schedulingConstraints": [
                {
                  "priority": "PRIORITY_HIGH",
                  "startDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 1,
                    "hours": 7
                  },
                  "endDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 5,
                    "hours": 7
                  },
                  "minimumRestMinutes": 720
                },
                {
                  "priority": "PRIORITY_MEDIUM",
                  "startDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 1,
                    "hours": 7
                  },
                  "endDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 5,
                    "hours": 7
                  },
                  "maximumMinutes": 2160
                }
              ],
              "hourlyContract": {
                "baseHourlyRate": 50,
                "hourlyRateShiftDifferentials": {
                  "2023-05-01 19h": 10,
                  "2023-05-02 19h": 10,
                  "2023-05-03 19h": 10,
                  "2023-05-04 19h": 10
                },
                "overtimePeriods": [
                  {
                    "overtimeMultiplier": 1.5,
                    "startDateTime": {
                      "year": 2023,
                      "month": 5,
                      "day": 1
                    },
                    "endDateTime": {
                      "year": 2023,
                      "month": 5,
                      "day": 5
                    },
                    "maximumRegularHours": 40
                  }
                ]
              }
            },
            {
              "id": "Alonso",
              "roleIds": [
                "Registered Nurse"
              ],
              "schedulingConstraints": [
                {
                  "priority": "PRIORITY_HIGH",
                  "startDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 1,
                    "hours": 7
                  },
                  "endDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 5,
                    "hours": 7
                  },
                  "minimumRestMinutes": 720
                },
                {
                  "priority": "PRIORITY_MEDIUM",
                  "startDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 1,
                    "hours": 7
                  },
                  "endDateTime": {
                    "year": 2023,
                    "month": 5,
                    "day": 5,
                    "hours": 7
                  },
                  "maximumMinutes": 2160
                }
              ],
              "hourlyContract": {
                "baseHourlyRate": 50,
                "hourlyRateShiftDifferentials": {
                  "2023-05-01 19h": 10,
                  "2023-05-02 19h": 10,
                  "2023-05-03 19h": 10,
                  "2023-05-04 19h": 10
                },
                "overtimePeriods": [
                  {
                    "overtimeMultiplier": 1.5,
                    "startDateTime": {
                      "year": 2023,
                      "month": 5,
                      "day": 1
                    },
                    "endDateTime": {
                      "year": 2023,
                      "month": 5,
                      "day": 5
                    },
                    "maximumRegularHours": 40
                  }
                ]
              }
            }
          ],
          "shifts": [
            {
              "id": "2023-05-01 7h",
              "locationId": "department",
              "startDateTime": {
                "year": 2023,
                "month": 5,
                "day": 1,
                "hours": 7
              },
              "endDateTime": {
                "year": 2023,
                "month": 5,
                "day": 1,
                "hours": 19
              }
            },
            {
              "id": "2023-05-01 13h",
              "locationId": "department",
              "startDateTime": {
                "year": 2023,
                "month": 5,
                "day": 1,
                "hours": 13
              },
              "endDateTime": {
                "year": 2023,
                "month": 5,
                "day": 2,
                "hours": 1
              }
            },
            {
              "id": "2023-05-01 19h",
              "locationId": "department",
              "startDateTime": {
                "year": 2023,
                "month": 5,
                "day": 1,
                "hours": 19
              },
              "endDateTime": {
                "year": 2023,
                "month": 5,
                "day": 2,
                "hours": 7
              }
            },
            {
              "id": "2023-05-02 7h",
              "locationId": "department",
              "startDateTime": {
                "year": 2023,
                "month": 5,
                "day": 2,
                "hours": 7
              },
              "endDateTime": {
                "year": 2023,
                "month": 5,
                "day": 2,
                "hours": 19
              }
            },
            {
              "id": "2023-05-02 13h",
              "locationId": "department",
              "startDateTime": {
                "year": 2023,
                "month": 5,
                "day": 2,
                "hours": 13
              },
              "endDateTime": {
                "year": 2023,
                "month": 5,
                "day": 3,
                "hours": 1
              }
            },
            {
              "id": "2023-05-02 19h",
              "locationId": "department",
              "startDateTime": {
                "year": 2023,
                "month": 5,
                "day": 2,
                "hours": 19
              },
              "endDateTime": {
                "year": 2023,
                "month": 5,
                "day": 3,
                "hours": 7
              }
            },
            {
              "id": "2023-05-03 7h",
              "locationId": "department",
              "startDateTime": {
                "year": 2023,
                "month": 5,
                "day": 3,
                "hours": 7
              },
              "endDateTime": {
                "year": 2023,
                "month": 5,
                "day": 3,
                "hours": 19
              }
            },
            {
              "id": "2023-05-03 13h",
              "locationId": "department",
              "startDateTime": {
                "year": 2023,
                "month": 5,
                "day": 3,
                "hours": 13
              },
              "endDateTime": {
                "year": 2023,
                "month": 5,
                "day": 4,
                "hours": 1
              }
            },
            {
              "id": "2023-05-03 19h",
              "locationId": "department",
              "startDateTime": {
                "year": 2023,
                "month": 5,
                "day": 3,
                "hours": 19
              },
              "endDateTime": {
                "year": 2023,
                "month": 5,
                "day": 4,
                "hours": 7
              }
            },
            {
              "id": "2023-05-04 7h",
              "locationId": "department",
              "startDateTime": {
                "year": 2023,
                "month": 5,
                "day": 4,
                "hours": 7
              },
              "endDateTime": {
                "year": 2023,
                "month": 5,
                "day": 4,
                "hours": 19
              }
            },
            {
              "id": "2023-05-04 13h",
              "locationId": "department",
              "startDateTime": {
                "year": 2023,
                "month": 5,
                "day": 4,
                "hours": 13
              },
              "endDateTime": {
                "year": 2023,
                "month": 5,
                "day": 5,
                "hours": 1
              }
            },
            {
              "id": "2023-05-04 19h",
              "locationId": "department",
              "startDateTime": {
                "year": 2023,
                "month": 5,
                "day": 4,
                "hours": 19
              },
              "endDateTime": {
                "year": 2023,
                "month": 5,
                "day": 5,
                "hours": 7
              }
            }
          ],
          "coverageRequirements": [
            {
              "startDateTime": {
                "year": 2023,
                "month": 5,
                "day": 1,
                "hours": 7
              },
              "endDateTime": {
                "year": 2023,
                "month": 5,
                "day": 5,
                "hours": 7
              },
              "locationId": "department",
              "roleRequirements": [
                {
                  "roleId": "Registered Nurse",
                  "targetEmployeeCount": 2,
                  "priority": "PRIORITY_MANDATORY"
                }
              ]
            }
          ],
          "roleIds": [
            "Registered Nurse"
          ],
          "locationIds": [
            "department"
          ],
          "budgetRequirements": [
            {
              "totalBudget": 10000,
              "priority": "PRIORITY_HIGH"
            }
          ]
        }
        
## Response example

The response of the solver contains the assignment of nurses to shifts and the
status of the optimization procedure. For example, the shifts assigned to the
first employee are returned as:

      {
        "solutionStatus": "OPTIMAL",
        "shiftAssignments": [
          {
            "employeeId": "Adam",
            "shiftId": "2023-05-01 7hr",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "Adam",
            "shiftId": "2023-05-02 7hr",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "Adam",
            "shiftId": "2023-05-03 7hr",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "Adam",
            "shiftId": "2023-05-04 7hr",
            "roleId": "Registered Nurse"
          },
          ... ]
      }

#### Example of a complete response


      {
        "solutionStatus": "OPTIMAL",
        "shiftAssignments": [
          {
            "employeeId": "Adam",
            "shiftId": "2023-05-01 7h",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "Adam",
            "shiftId": "2023-05-02 7h",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "Adam",
            "shiftId": "2023-05-03 7h",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "Adam",
            "shiftId": "2023-05-04 7h",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "Grace",
            "shiftId": "2023-05-01 19h",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "Grace",
            "shiftId": "2023-05-02 19h",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "Grace",
            "shiftId": "2023-05-03 19h",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "Grace",
            "shiftId": "2023-05-04 19h",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "James",
            "shiftId": "2023-05-01 19h",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "James",
            "shiftId": "2023-05-02 19h",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "James",
            "shiftId": "2023-05-03 19h",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "James",
            "shiftId": "2023-05-04 19h",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "We",
            "shiftId": "2023-05-01 7h",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "We",
            "shiftId": "2023-05-02 7h",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "We",
            "shiftId": "2023-05-03 7h",
            "roleId": "Registered Nurse"
          },
          {
            "employeeId": "We",
            "shiftId": "2023-05-04 7h",
            "roleId": "Registered Nurse"
          }
        ]
      }