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
Type Scope Use Case SINGLE_DAYMultiple shifts on one day Prevent double-booking, enforce breaks MULTI_DAYShifts across consecutive days Rotation rules, recovery time
Satisfiability Levels
Level Effect Constraint Type PREFERREDEncourage this pattern Soft constraint UNPREFERREDDiscourage this pattern Soft constraint PROHIBITEDNever allow this pattern Hard 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
ON - Employee works a shift with matching tags
OFF - Employee does not work a shift with matching tags
List of shift tags that this element matches (e.g., ["EARLY"], ["NIGHT"])
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" ] }
]
}
Day off after night shift
{
"type" : "MULTI_DAY" ,
"satisfy" : "PREFERRED" ,
"elements" : [
{ "type" : "ON" , "tags" : [ "NIGHT" ] },
{ "type" : "OFF" , "tags" : [ "ALL" ] }
]
}
Consistent shift type per week
{
"type" : "MULTI_DAY" ,
"satisfy" : "PREFERRED" ,
"elements" : [
{ "type" : "ON" , "tags" : [ "EARLY" ] },
{ "type" : "ON" , "tags" : [ "EARLY" ] },
{ "type" : "ON" , "tags" : [ "EARLY" ] }
]
}