Skip to main content
Patterns control the sequence of shift assignments, either within a single day or across multiple days. Use patterns to enforce or discourage specific shift combinations.

Pattern Types

TypeScopeUse Case
SINGLE_DAYMultiple shifts on one dayPrevent double-booking, enforce breaks
MULTI_DAYShifts across consecutive daysRotation rules, recovery time

Satisfiability Levels

LevelEffectConstraint Type
PREFERREDEncourage this patternSoft constraint
UNPREFERREDDiscourage this patternSoft constraint
PROHIBITEDNever allow this patternHard constraint

Single-Day Patterns

Prevent an employee from working both early and late shifts on the same day:
{
  "patterns": [
    {
      "type": "SINGLE_DAY",
      "satisfy": "PROHIBITED",
      "elements": [
        { "type": "ON", "tags": ["EARLY"] },
        { "type": "ON", "tags": ["LATE"] }
      ]
    }
  ]
}
PROHIBITED patterns create hard constraints. If unavoidable, the solution becomes infeasible.
Prefer no late shift after an early shift:
{
  "patterns": [
    {
      "type": "SINGLE_DAY",
      "satisfy": "PREFERRED",
      "elements": [
        { "type": "ON", "tags": ["EARLY"] },
        { "type": "OFF", "tags": ["LATE"] }
      ]
    }
  ]
}

Multi-Day Patterns

Prohibit early shifts immediately after late shifts (next day):
{
  "patterns": [
    {
      "type": "MULTI_DAY",
      "satisfy": "PROHIBITED",
      "elements": [
        { "type": "ON", "tags": ["LATE"] },
        { "type": "ON", "tags": ["EARLY"] }
      ]
    }
  ]
}
This prevents “clopening” scenarios where an employee closes late and opens early the next day.
Prefer a rotation of early → late → late:
{
  "patterns": [
    {
      "type": "MULTI_DAY",
      "satisfy": "PREFERRED",
      "elements": [
        { "type": "ON", "tags": ["EARLY"] },
        { "type": "ON", "tags": ["LATE"] },
        { "type": "ON", "tags": ["LATE"] }
      ]
    }
  ]
}

Pattern Elements

type
string
required
ON - Employee works a shift with matching tags OFF - Employee does not work a shift with matching tags
tags
array
List of shift tags that this element matches (e.g., ["EARLY"], ["NIGHT"])

Setting Up Shift Tags

Patterns use tags defined on shifts. Add tags to group shifts:
{
  "shifts": [
    {
      "name": "morning-1",
      "from": "2024-01-01T06:00:00",
      "to": "2024-01-01T14:00:00",
      "tags": [{ "name": "EARLY" }],
      "min": 1,
      "max": 1
    },
    {
      "name": "evening-1",
      "from": "2024-01-01T14:00:00",
      "to": "2024-01-01T22:00:00",
      "tags": [{ "name": "LATE" }],
      "min": 1,
      "max": 1
    },
    {
      "name": "night-1",
      "from": "2024-01-01T22:00:00",
      "to": "2024-01-02T06:00:00",
      "tags": [{ "name": "NIGHT" }],
      "min": 1,
      "max": 1
    }
  ]
}

Pattern Weight

Adjust the importance of preferred patterns with weight:
{
  "patterns": [
    {
      "type": "MULTI_DAY",
      "satisfy": "PREFERRED",
      "weight": 10,
      "elements": [
        { "type": "ON", "tags": ["EARLY"] },
        { "type": "ON", "tags": ["LATE"] }
      ]
    }
  ]
}
Higher weights make the solver try harder to satisfy the pattern. Use weights to prioritize between multiple preferred patterns.

Common Patterns

{
  "type": "SINGLE_DAY",
  "satisfy": "PROHIBITED",
  "elements": [
    { "type": "ON", "tags": ["ALL"] },
    { "type": "ON", "tags": ["ALL"] }
  ]
}
{
  "type": "MULTI_DAY",
  "satisfy": "PREFERRED",
  "elements": [
    { "type": "ON", "tags": ["NIGHT"] },
    { "type": "OFF", "tags": ["ALL"] }
  ]
}
{
  "type": "MULTI_DAY",
  "satisfy": "PREFERRED",
  "elements": [
    { "type": "ON", "tags": ["EARLY"] },
    { "type": "ON", "tags": ["EARLY"] },
    { "type": "ON", "tags": ["EARLY"] }
  ]
}