> ## Documentation Index
> Fetch the complete documentation index at: https://docs.automaticrostering.visma.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Pattern

> Define desired or undesired shift patterns.

export const PatternMetricRows = () => <>
    <tr><td><code className="whitespace-nowrap">PATTERN.DESIRED_COMPLETE_MATCHES</code></td><td>Number of periods that completely match a desired pattern.</td></tr>
    <tr><td><code className="whitespace-nowrap">PATTERN.DESIRED_PARTIAL_MATCHES</code></td><td>Number of periods that partially match a desired pattern.</td></tr>
    <tr><td><code className="whitespace-nowrap">PATTERN.DESIRED_INCOMPLETE_PERIODS</code></td><td>Number of periods that do not completely match a desired pattern.</td></tr>
    <tr><td><code className="whitespace-nowrap">PATTERN.UNDESIRED_COMPLETE_PERIODS</code></td><td>Number of periods that completely match an undesired pattern.</td></tr>
  </>;

Pattern can be used to specify patterns that are desired or undesired for the employee to follow in the produced roster. Both possible use cases are discussed separately below.

<Card title="Rule schema">
  <ResponseField name="patternRule" type="object">
    Used to define patterns of shifts that employees should follow or avoid.

    <Expandable title="properties">
      <ResponseField name="id" type="string" required>
        Unique identifier for the rule.
      </ResponseField>

      <ResponseField name="labels" type="array of string">
        Labels for the rule. Labels can be used to group rules together. For example, if multiple rules are related to the same shift type, they can all be labeled with the same label.
      </ResponseField>

      <ResponseField name="importance" type="string (enum: NONE | VERY_LOW | LOW | MEDIUM | HIGH | ...)" required>
        The importance of the rule. The higher the importance, the more it will be taking the rule into account. Under strict importance, the rule may never be violated.
      </ResponseField>

      <ResponseField name="isDesired" type="boolean" required>
        If set to true, we will try to make employees follow the specified patterns. Else, we will try to avoid making employees follow any of the specified patterns.
      </ResponseField>

      <ResponseField name="filters" type="object">
        Filters to determine the scope of the rule. Used to decide which employees the rule should be applied to.
      </ResponseField>

      <Expandable title="filters – properties">
        <ResponseField name="employees" type="object">
          Used to filter which employees the rule should be applied to. If not specified, the rule applies to all employees.
        </ResponseField>

        <Expandable title="employees – properties">
          <ResponseField name="ids" type="array of string">
            List of employee ids that the rule should be applied to.
          </ResponseField>

          <ResponseField name="labels" type="array of string">
            List of employee labels that the rule should be applied to.
          </ResponseField>

          <ResponseField name="matchTypes" type="object" />

          <Expandable title="matchTypes – properties">
            <ResponseField name="ids" type="string (enum: NONE | ANY | ALL)">
              Used to indicate how to apply the id filters. For example, if set to NONE, entities with the specified ids will be excluded. Default: "ANY".
            </ResponseField>

            <ResponseField name="labels" type="string (enum: NONE | ANY | ALL)">
              Used to indicate how to apply the label filters. For example, if set to ANY, entities that have any of the specified labels will be included. Default: "ANY".
            </ResponseField>
          </Expandable>
        </Expandable>
      </Expandable>

      <ResponseField name="options" type="object">
        Additional options for how the rule should be applied.
      </ResponseField>

      <Expandable title="options – properties">
        <ResponseField name="emptyDayBehaviours" type="object">
          Describes whether the pattern should skip over days that could be considered irrelevant for the pattern.
        </ResponseField>

        <Expandable title="emptyDayBehaviours – properties">
          <ResponseField name="dayOutsideSchedule" type="string (enum: INCLUDE | EXCLUDE | MATCH)">
            Describes whether the pattern counts days outside the schedule period as days in the pattern. The pattern can either always include them (INCLUDE), skip over them (EXCLUDE) or only include them if the pattern allows for a day off on that day (MATCH). Takes priority over the dayWithoutDemand and dayOff properties. Default: "INCLUDE".
          </ResponseField>

          <ResponseField name="dayWithoutDemand" type="string (enum: INCLUDE | EXCLUDE | MATCH)">
            Describes whether the pattern counts days without demand as days in the pattern. The pattern can either always include them (INCLUDE), skip over them (EXCLUDE) or only include them if the pattern allows for a day off on that day (MATCH). Default: "INCLUDE".
          </ResponseField>

          <ResponseField name="dayOff" type="string (enum: INCLUDE | EXCLUDE | MATCH)">
            Describes whether the pattern counts days off as days in the pattern. The pattern can either always include them (INCLUDE), skip over them (EXCLUDE) or only include them if the pattern allows for a day off on that day (MATCH). Default: "INCLUDE".
          </ResponseField>
        </Expandable>
      </Expandable>

      <ResponseField name="periods" type="object">
        List of periods in the schedule. Periods can be defined explicitly or through a recurrent definition (for example, to generate weeks).
      </ResponseField>

      <Expandable title="periods – properties">
        <ResponseField name="days" type="object">
          List of days in the schedule. Each day will become one period. By default, each period will last the entire day. If a startTime and/or endTime are specified, these will apply to each period.
        </ResponseField>

        <Expandable title="days – properties">
          <ResponseField name="dates" type="array of date (date)">
            List of dates in the schedule. Only allowed in CALENDAR payloads.
          </ResponseField>

          <ResponseField name="dayIndices" type="array of dayIndex">
            List of day indices in the schedule. Only allowed in RECURRING payloads.
          </ResponseField>

          <ResponseField name="daysOfWeek" type="array of dayOfWeek">
            List of days of the week. Will apply to all days in the schedule that match any of the specified weekdays.
          </ResponseField>

          <ResponseField name="startTime" type="string (time)">
            TIME ISO 8601 format hh:mm. Equivalent to the 24h format of a single day. Use 00:00 to represent midnight.
          </ResponseField>

          <ResponseField name="endTime" type="string (time)">
            TIME ISO 8601 format hh:mm. Equivalent to the 24h format of a single day. Use 00:00 to represent midnight.
          </ResponseField>
        </Expandable>

        <ResponseField name="customDefinitions" type="array of object">
          List of custom period definitions. Each custom period definition defines one period in the schedule.
        </ResponseField>

        <Expandable title="customDefinitions – item structure">
          <ResponseField name="startDay" type="object">
            Describes one day in the schedule.
          </ResponseField>

          <Expandable title="startDay – properties">
            <ResponseField name="date" type="string (date)">
              Date specified in ISO8601 format (YYYY-MM-DD). Only available in CALENDAR schedules.
            </ResponseField>

            <ResponseField name="dayIndex" type="integer">
              Day index relative to the horizon start day (starts at 0). Only available in RECURRING schedules.
            </ResponseField>
          </Expandable>

          <ResponseField name="endDay" type="object">
            Describes one day in the schedule.
          </ResponseField>

          <Expandable title="endDay – properties">
            <ResponseField name="date" type="string (date)">
              Date specified in ISO8601 format (YYYY-MM-DD). Only available in CALENDAR schedules.
            </ResponseField>

            <ResponseField name="dayIndex" type="integer">
              Day index relative to the horizon start day (starts at 0). Only available in RECURRING schedules.
            </ResponseField>
          </Expandable>

          <ResponseField name="startTime" type="string (time)">
            TIME ISO 8601 format hh:mm. Equivalent to the 24h format of a single day. Use 00:00 to represent midnight.
          </ResponseField>

          <ResponseField name="endTime" type="string (time)">
            TIME ISO 8601 format hh:mm. Equivalent to the 24h format of a single day. Use 00:00 to represent midnight.
          </ResponseField>

          <ResponseField name="applyTimeToAllDays" type="boolean">
            If true, the startTime and endTime will be applied to each individual day in the period. If false, the startTime will apply to the first day and the endTime will apply to the last day. Default: false.
          </ResponseField>
        </Expandable>

        <ResponseField name="recurrentDefinition" type="object">
          A recurrent definition to easily create a set of similar periods.
        </ResponseField>

        <Expandable title="recurrentDefinition – properties">
          <ResponseField name="daysPerPeriod" type="integer" required>
            The number of days in each period.
          </ResponseField>

          <ResponseField name="daysBetweenStarts" type="integer">
            The number of days between the start of each period. If not specified, this defaults to the value of daysPerPeriod, creating non-overlapping consecutive periods. Setting daysBetweenStarts to 1 will create a sliding window of periods.
          </ResponseField>

          <ResponseField name="startDay" type="object">
            Describes one day in the schedule.
          </ResponseField>

          <Expandable title="startDay – properties">
            <ResponseField name="date" type="string (date)">
              Date specified in ISO8601 format (YYYY-MM-DD). Only available in CALENDAR schedules.
            </ResponseField>

            <ResponseField name="dayIndex" type="integer">
              Day index relative to the horizon start day (starts at 0). Only available in RECURRING schedules.
            </ResponseField>
          </Expandable>

          <ResponseField name="endDay" type="object">
            Describes one day in the schedule.
          </ResponseField>

          <Expandable title="endDay – properties">
            <ResponseField name="date" type="string (date)">
              Date specified in ISO8601 format (YYYY-MM-DD). Only available in CALENDAR schedules.
            </ResponseField>

            <ResponseField name="dayIndex" type="integer">
              Day index relative to the horizon start day (starts at 0). Only available in RECURRING schedules.
            </ResponseField>
          </Expandable>

          <ResponseField name="startTime" type="string (time)">
            TIME ISO 8601 format hh:mm. Equivalent to the 24h format of a single day. Use 00:00 to represent midnight.
          </ResponseField>

          <ResponseField name="endTime" type="string (time)">
            TIME ISO 8601 format hh:mm. Equivalent to the 24h format of a single day. Use 00:00 to represent midnight.
          </ResponseField>

          <ResponseField name="applyTimeToAllDays" type="boolean">
            If true, the startTime and endTime will be applied to each individual day in the period. If false, the startTime will apply to the first day and the endTime will apply to the last day. Default: false.
          </ResponseField>
        </Expandable>

        <ResponseField name="labels" type="array of string">
          Provide labels to re-use periods that were defined in the configuration.
        </ResponseField>
      </Expandable>

      <ResponseField name="patterns" type="array of object" required>
        The patterns that should be followed or avoided.
      </ResponseField>

      <Expandable title="patterns – item structure">
        <ResponseField name="patternDays" type="array of object" required>
          Defines the pattern that should be followed. Each element in the array represents a day in the pattern. Note that DAY\_OFF is not allowed on strict undesired pattern rules.
        </ResponseField>

        <Expandable title="patternDays – item structure">
          <ResponseField name="shifts" type="object">
            Used to filter which shifts the rule should be applied to. If not specified, the rule applies to all shifts.
          </ResponseField>

          <Expandable title="shifts – properties">
            <ResponseField name="ids" type="array of string">
              List of shift ids that the rule should be applied to.
            </ResponseField>

            <ResponseField name="labels" type="array of string">
              List of shift labels that the rule should be applied to.
            </ResponseField>

            <ResponseField name="matchTypes" type="object" />

            <Expandable title="matchTypes – properties">
              <ResponseField name="ids" type="string (enum: NONE | ANY | ALL)">
                Used to indicate how to apply the id filters. For example, if set to NONE, entities with the specified ids will be excluded. Default: "ANY".
              </ResponseField>

              <ResponseField name="labels" type="string (enum: NONE | ANY | ALL)">
                Used to indicate how to apply the label filters. For example, if set to ANY, entities that have any of the specified labels will be included. Default: "ANY".
              </ResponseField>
            </Expandable>
          </Expandable>

          <ResponseField name="keyword" type="string (enum: DAY_OFF | ANY_SHIFT | ANY)">
            A keyword to represent that a day must be a day off (DAY\_OFF), must be a worked day (ANY\_SHIFT), or that there are no requirements on this day (ANY).
          </ResponseField>
        </Expandable>

        <ResponseField name="startDays" type="object">
          List of days in the schedule.
        </ResponseField>

        <Expandable title="startDays – properties">
          <ResponseField name="dates" type="array of date (date)">
            List of dates in the schedule. Only allowed in CALENDAR payloads.
          </ResponseField>

          <ResponseField name="dayIndices" type="array of dayIndex">
            List of day indices in the schedule. Only allowed in RECURRING payloads.
          </ResponseField>

          <ResponseField name="daysOfWeek" type="array of dayOfWeek">
            List of days of the week. Will apply to all days in the schedule that match any of the specified weekdays.
          </ResponseField>
        </Expandable>

        <ResponseField name="roles" type="object">
          Used to apply the rule only to work carried out in specific roles.
        </ResponseField>

        <Expandable title="roles – properties">
          <ResponseField name="ids" type="array of string">
            List of relevant role ids.
          </ResponseField>
        </Expandable>

        <ResponseField name="isRepeating" type="boolean">
          If set to true, each instance of the pattern will be repeated from its start day until the end of the period that the instance falls within. Otherwise, the pattern is not repeated. Default: false.
        </ResponseField>

        <ResponseField name="startOffsets" type="integer">
          The offset that the pattern may start with on the start day. If set to 0, the pattern must start with the first pattern day on each start day. If set to 1, the pattern may start from any of its pattern days on the start day. If set to 7 (for example), the pattern may start with every 7th pattern day on the start day. The pattern is then continued as usual. Default: 0.
        </ResponseField>
      </Expandable>
    </Expandable>
  </ResponseField>
</Card>

## Undesired patterns

For undesired patterns, simply define the patterns that you would not want employees to follow. By default, the solver will try to never assign shifts to employees that would make them follow the undesired patterns.
However, if you so desire you can use the `startDays` field on a specific pattern to specify that the pattern should only be avoided at specific times. For example, some patterns might be fine to follow during the week, but only become undesired during the weekend.

<Tip>
  The rule below makes it undesirable for employees to work the night shift on both Saturday and Sunday.

  ```json theme={null}
  {
    "id": "spc-weekend-patterns",
    "importance": "MEDIUM",
    "isDesired": false,
    "patterns": [
      {
        "startDays": {
          "daysOfWeek": ["SAT"]
        },
        "patternDays": [
          {
            "shifts": { "ids": ["night-shift"] }
          },
          {
            "shifts": { "ids": ["night-shift"] }
          }
        ]
      }
    ]
  }
  ```
</Tip>

When the [importance](/v2/rules/index#rule-importance) of a pattern rule is set to `STRICT`, the solver will *never* make an employee follow the specified pattern. Since this cannot be guaranteed with respect to days off, it is not allowed to use the keyword `DAY_OFF` within a strict undesired rule's pattern.

## Desired patterns

The desired version of this rule works in a similar way. Define the patterns that you would like employees to follow. By default, the solver will try to assign shifts to employees that would make them follow the desired patterns.

However, if there are multiple patterns that you would like the solver to choose from, some further configuration is needed. In this case, it is required to define `periods` on the rule. Within each defined period, the solver will then try
to make the employees follow exactly one of the specified patterns. If you do then do not define `startDays` on a pattern, it will default to starting on the first day of each period. If you do choose to define `startDays`, each instance of the pattern
must fall fully within exactly one period. Desired pattern rules with only one defined pattern do not need to define `periods`.

<Tip>
  In the following rule, the employees may only work shifts if they are in accordance with either of the two patterns. The periods are defined as each weekend (Friday-Sunday). The first pattern is 3 days long and does not define `startDays` - it therefore starts on each Friday.
  Meanwhile, the second pattern is 2 days long and only starts on Saturdays. When the solver follows the second pattern for some weekend, it is therefore allowed to plan whatever it wants on the Friday of that weekend.

  ```json theme={null}
  {
    "rules": {
      "patternRules": [
        {
          "id": "spr-strict-weekends",
          "importance": "STRICT",
          "isDesired": true,
          "periods": {
            "recurrentDefinition": {
              "daysPerPeriod": 3,
              "daysBetweenStarts": 7
            }
          },
          "patterns": [
            {
              "patternDays": [
                {
                  "shifts": { "ids": ["shift-1"] }
                },
                {
                  "shifts": { "ids": ["shift-1"] }
                },
                {
                  "shifts": { "ids": ["shift-1"] }
                }
              ]
            },
            {
              "startDays": {
                "daysOfWeek": ["SAT"]
              },
              "patternDays": [
                {
                  "shifts": { "ids": ["shift-2"] }
                },
                {
                  "shifts": { "ids": ["shift-2"] }
                }
              ]
            }
          ]
        }
      ]
    }
  }
  ```
</Tip>

## Patterns with role filters

You can use role filters to make a pattern apply only when an employee works in one of those roles.

<Tip>
  The rule below makes it undesirable for employees to work the night shift on both Saturday and Sunday when they are working in role 1 or role 2.

  ```json theme={null}
  {
    "id": "spc-weekend-roles",
    "importance": "MEDIUM",
    "isDesired": false,
    "patterns": [
      {
        "startDays": {
          "daysOfWeek": ["SAT"]
        },
        "patternDays": [
          {
            "shifts": { "ids": ["night-shift"] }
          },
          {
            "shifts": { "ids": ["night-shift"] }
          }
        ],
        "roles": {
          "ids": ["role-1", "role-2"]
        }
      }
    ]
  }
  ```
</Tip>

## Empty day behaviour

In some cases, it can be desirable to allow a pattern to 'skip over' days if it will be impossible for an employee to follow the pattern on that day. In particular, days where an employee is not available for work or days where no demand is defined can be configured to be skipped over. These two types of empty day behaviour can be configured separately through the `dayOffBehaviour` and `dayWithoutDemandBehaviour` fields on each pattern itself.

The current list of empty day behaviours is as follows:

| Empty day behaviour | Impact                                                                                                            |
| ------------------- | ----------------------------------------------------------------------------------------------------------------- |
| **INCLUDE**         | Days are always included in the pattern (never skipped over), regardless of whether it is an empty day or not.    |
| **EXCLUDE**         | Days are always excluded from the pattern (always skipped over), regardless of whether it is an empty day or not. |
| **MATCH**           | Days are included in the pattern as long as the pattern can be matched with a day off on that day.                |

In order for a day to qualify as a day without demand, there must be no demands defined on that day. In order for a day to qualify as a day off, the employee must be configured to be unavailable for work on that day. This can be done through one of the following rules:

* [**Availability**](/v2/rules/availability): The employee is strictly unavailable for work on the entire day.
* [**Utilization**](/v2/rules/utilization): The employee has a strict maximum of 0 hours or shifts on the day.
* [**Period Distribution**](/v2/rules/period-distribution): The employee may work a maximum of 0 periods, which includes the day.

## Metrics

The following [status metrics](/v2/concepts/metrics) are available for tracking on Pattern rules:

<table>
  <thead><tr><th>Metric key</th><th>Description</th></tr></thead>

  <tbody>
    <PatternMetricRows />
  </tbody>
</table>
