dabke 0.83.0 → 0.84.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/README.md +22 -27
- package/dist/client.d.ts +39 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js.map +1 -1
- package/dist/client.schemas.d.ts +118 -18
- package/dist/client.schemas.d.ts.map +1 -1
- package/dist/client.schemas.js +110 -6
- package/dist/client.schemas.js.map +1 -1
- package/dist/client.types.d.ts +63 -7
- package/dist/client.types.d.ts.map +1 -1
- package/dist/client.types.js.map +1 -1
- package/dist/cpsat/cost.d.ts +5 -2
- package/dist/cpsat/cost.d.ts.map +1 -1
- package/dist/cpsat/cost.js +13 -6
- package/dist/cpsat/cost.js.map +1 -1
- package/dist/cpsat/model-builder.d.ts +42 -61
- package/dist/cpsat/model-builder.d.ts.map +1 -1
- package/dist/cpsat/model-builder.js +451 -56
- package/dist/cpsat/model-builder.js.map +1 -1
- package/dist/cpsat/response.d.ts +19 -7
- package/dist/cpsat/response.d.ts.map +1 -1
- package/dist/cpsat/response.js +48 -9
- package/dist/cpsat/response.js.map +1 -1
- package/dist/cpsat/rule-descriptor.d.ts +250 -0
- package/dist/cpsat/rule-descriptor.d.ts.map +1 -0
- package/dist/cpsat/rule-descriptor.js +51 -0
- package/dist/cpsat/rule-descriptor.js.map +1 -0
- package/dist/cpsat/rules/artifacts.d.ts +9 -0
- package/dist/cpsat/rules/artifacts.d.ts.map +1 -0
- package/dist/cpsat/rules/artifacts.js +31 -0
- package/dist/cpsat/rules/artifacts.js.map +1 -0
- package/dist/cpsat/rules/assign-together.d.ts +18 -20
- package/dist/cpsat/rules/assign-together.d.ts.map +1 -1
- package/dist/cpsat/rules/assign-together.js +90 -54
- package/dist/cpsat/rules/assign-together.js.map +1 -1
- package/dist/cpsat/rules/assigned-day.d.ts +12 -0
- package/dist/cpsat/rules/assigned-day.d.ts.map +1 -0
- package/dist/cpsat/rules/assigned-day.js +43 -0
- package/dist/cpsat/rules/assigned-day.js.map +1 -0
- package/dist/cpsat/rules/assignment-priority.d.ts +15 -29
- package/dist/cpsat/rules/assignment-priority.d.ts.map +1 -1
- package/dist/cpsat/rules/assignment-priority.js +47 -50
- package/dist/cpsat/rules/assignment-priority.js.map +1 -1
- package/dist/cpsat/rules/assignment-terms.d.ts +6 -0
- package/dist/cpsat/rules/assignment-terms.d.ts.map +1 -0
- package/dist/cpsat/rules/assignment-terms.js +19 -0
- package/dist/cpsat/rules/assignment-terms.js.map +1 -0
- package/dist/cpsat/rules/concurrent-intervals.d.ts +19 -0
- package/dist/cpsat/rules/concurrent-intervals.d.ts.map +1 -0
- package/dist/cpsat/rules/concurrent-intervals.js +57 -0
- package/dist/cpsat/rules/concurrent-intervals.js.map +1 -0
- package/dist/cpsat/rules/cost-utils.d.ts +1 -3
- package/dist/cpsat/rules/cost-utils.d.ts.map +1 -1
- package/dist/cpsat/rules/cost-utils.js +0 -7
- package/dist/cpsat/rules/cost-utils.js.map +1 -1
- package/dist/cpsat/rules/day-cost-multiplier.d.ts +10 -10
- package/dist/cpsat/rules/day-cost-multiplier.d.ts.map +1 -1
- package/dist/cpsat/rules/day-cost-multiplier.js +88 -77
- package/dist/cpsat/rules/day-cost-multiplier.js.map +1 -1
- package/dist/cpsat/rules/day-cost-surcharge.d.ts +10 -10
- package/dist/cpsat/rules/day-cost-surcharge.d.ts.map +1 -1
- package/dist/cpsat/rules/day-cost-surcharge.js +76 -65
- package/dist/cpsat/rules/day-cost-surcharge.js.map +1 -1
- package/dist/cpsat/rules/index.d.ts +30 -24
- package/dist/cpsat/rules/index.d.ts.map +1 -1
- package/dist/cpsat/rules/index.js +30 -24
- package/dist/cpsat/rules/index.js.map +1 -1
- package/dist/cpsat/rules/location-preference.d.ts +14 -21
- package/dist/cpsat/rules/location-preference.d.ts.map +1 -1
- package/dist/cpsat/rules/location-preference.js +45 -45
- package/dist/cpsat/rules/location-preference.js.map +1 -1
- package/dist/cpsat/rules/max-concurrent-assignments.d.ts +46 -0
- package/dist/cpsat/rules/max-concurrent-assignments.d.ts.map +1 -0
- package/dist/cpsat/rules/max-concurrent-assignments.js +121 -0
- package/dist/cpsat/rules/max-concurrent-assignments.js.map +1 -0
- package/dist/cpsat/rules/max-consecutive-days.d.ts +18 -17
- package/dist/cpsat/rules/max-consecutive-days.d.ts.map +1 -1
- package/dist/cpsat/rules/max-consecutive-days.js +67 -66
- package/dist/cpsat/rules/max-consecutive-days.js.map +1 -1
- package/dist/cpsat/rules/max-days-of-week-per-period.d.ts +45 -0
- package/dist/cpsat/rules/max-days-of-week-per-period.d.ts.map +1 -0
- package/dist/cpsat/rules/max-days-of-week-per-period.js +95 -0
- package/dist/cpsat/rules/max-days-of-week-per-period.js.map +1 -0
- package/dist/cpsat/rules/max-days-week.d.ts +17 -31
- package/dist/cpsat/rules/max-days-week.d.ts.map +1 -1
- package/dist/cpsat/rules/max-days-week.js +69 -81
- package/dist/cpsat/rules/max-days-week.js.map +1 -1
- package/dist/cpsat/rules/max-hours-day.d.ts +14 -31
- package/dist/cpsat/rules/max-hours-day.d.ts.map +1 -1
- package/dist/cpsat/rules/max-hours-day.js +56 -72
- package/dist/cpsat/rules/max-hours-day.js.map +1 -1
- package/dist/cpsat/rules/max-hours-week.d.ts +15 -31
- package/dist/cpsat/rules/max-hours-week.d.ts.map +1 -1
- package/dist/cpsat/rules/max-hours-week.js +60 -75
- package/dist/cpsat/rules/max-hours-week.js.map +1 -1
- package/dist/cpsat/rules/max-shifts-day.d.ts +17 -33
- package/dist/cpsat/rules/max-shifts-day.d.ts.map +1 -1
- package/dist/cpsat/rules/max-shifts-day.js +57 -73
- package/dist/cpsat/rules/max-shifts-day.js.map +1 -1
- package/dist/cpsat/rules/min-consecutive-days.d.ts +18 -18
- package/dist/cpsat/rules/min-consecutive-days.d.ts.map +1 -1
- package/dist/cpsat/rules/min-consecutive-days.js +123 -94
- package/dist/cpsat/rules/min-consecutive-days.js.map +1 -1
- package/dist/cpsat/rules/min-days-of-week-per-period.d.ts +35 -0
- package/dist/cpsat/rules/min-days-of-week-per-period.d.ts.map +1 -0
- package/dist/cpsat/rules/min-days-of-week-per-period.js +108 -0
- package/dist/cpsat/rules/min-days-of-week-per-period.js.map +1 -0
- package/dist/cpsat/rules/min-days-week.d.ts +13 -26
- package/dist/cpsat/rules/min-days-week.d.ts.map +1 -1
- package/dist/cpsat/rules/min-days-week.js +85 -74
- package/dist/cpsat/rules/min-days-week.js.map +1 -1
- package/dist/cpsat/rules/min-hours-day.d.ts +14 -17
- package/dist/cpsat/rules/min-hours-day.d.ts.map +1 -1
- package/dist/cpsat/rules/min-hours-day.js +72 -54
- package/dist/cpsat/rules/min-hours-day.js.map +1 -1
- package/dist/cpsat/rules/min-hours-week.d.ts +15 -18
- package/dist/cpsat/rules/min-hours-week.d.ts.map +1 -1
- package/dist/cpsat/rules/min-hours-week.js +75 -57
- package/dist/cpsat/rules/min-hours-week.js.map +1 -1
- package/dist/cpsat/rules/min-rest-between-shifts.d.ts +14 -17
- package/dist/cpsat/rules/min-rest-between-shifts.d.ts.map +1 -1
- package/dist/cpsat/rules/min-rest-between-shifts.js +148 -138
- package/dist/cpsat/rules/min-rest-between-shifts.js.map +1 -1
- package/dist/cpsat/rules/minimize-cost.d.ts +2 -18
- package/dist/cpsat/rules/minimize-cost.d.ts.map +1 -1
- package/dist/cpsat/rules/minimize-cost.js +151 -163
- package/dist/cpsat/rules/minimize-cost.js.map +1 -1
- package/dist/cpsat/rules/must-assign.d.ts +5 -42
- package/dist/cpsat/rules/must-assign.d.ts.map +1 -1
- package/dist/cpsat/rules/must-assign.js +43 -75
- package/dist/cpsat/rules/must-assign.js.map +1 -1
- package/dist/cpsat/rules/overtime-daily-multiplier.d.ts +6 -10
- package/dist/cpsat/rules/overtime-daily-multiplier.d.ts.map +1 -1
- package/dist/cpsat/rules/overtime-daily-multiplier.js +118 -112
- package/dist/cpsat/rules/overtime-daily-multiplier.js.map +1 -1
- package/dist/cpsat/rules/overtime-daily-surcharge.d.ts +6 -11
- package/dist/cpsat/rules/overtime-daily-surcharge.d.ts.map +1 -1
- package/dist/cpsat/rules/overtime-daily-surcharge.js +104 -99
- package/dist/cpsat/rules/overtime-daily-surcharge.js.map +1 -1
- package/dist/cpsat/rules/overtime-tiered-multiplier.d.ts +9 -21
- package/dist/cpsat/rules/overtime-tiered-multiplier.d.ts.map +1 -1
- package/dist/cpsat/rules/overtime-tiered-multiplier.js +181 -199
- package/dist/cpsat/rules/overtime-tiered-multiplier.js.map +1 -1
- package/dist/cpsat/rules/overtime-weekly-multiplier.d.ts +13 -12
- package/dist/cpsat/rules/overtime-weekly-multiplier.d.ts.map +1 -1
- package/dist/cpsat/rules/overtime-weekly-multiplier.js +143 -143
- package/dist/cpsat/rules/overtime-weekly-multiplier.js.map +1 -1
- package/dist/cpsat/rules/overtime-weekly-surcharge.d.ts +7 -11
- package/dist/cpsat/rules/overtime-weekly-surcharge.d.ts.map +1 -1
- package/dist/cpsat/rules/overtime-weekly-surcharge.js +124 -119
- package/dist/cpsat/rules/overtime-weekly-surcharge.js.map +1 -1
- package/dist/cpsat/rules/pattern-eligibility.d.ts +6 -0
- package/dist/cpsat/rules/pattern-eligibility.d.ts.map +1 -0
- package/dist/cpsat/rules/pattern-eligibility.js +16 -0
- package/dist/cpsat/rules/pattern-eligibility.js.map +1 -0
- package/dist/cpsat/rules/pattern-time.d.ts +5 -0
- package/dist/cpsat/rules/pattern-time.d.ts.map +1 -0
- package/dist/cpsat/rules/pattern-time.js +20 -0
- package/dist/cpsat/rules/pattern-time.js.map +1 -0
- package/dist/cpsat/rules/registry.d.ts +217 -30
- package/dist/cpsat/rules/registry.d.ts.map +1 -1
- package/dist/cpsat/rules/registry.js +98 -34
- package/dist/cpsat/rules/registry.js.map +1 -1
- package/dist/cpsat/rules/resolver.d.ts +9 -7
- package/dist/cpsat/rules/resolver.d.ts.map +1 -1
- package/dist/cpsat/rules/resolver.js +19 -18
- package/dist/cpsat/rules/resolver.js.map +1 -1
- package/dist/cpsat/rules/role-preference.d.ts +24 -0
- package/dist/cpsat/rules/role-preference.d.ts.map +1 -0
- package/dist/cpsat/rules/role-preference.js +72 -0
- package/dist/cpsat/rules/role-preference.js.map +1 -0
- package/dist/cpsat/rules/rules.types.d.ts +90 -17
- package/dist/cpsat/rules/rules.types.d.ts.map +1 -1
- package/dist/cpsat/rules/scope.types.d.ts +24 -11
- package/dist/cpsat/rules/scope.types.d.ts.map +1 -1
- package/dist/cpsat/rules/scope.types.js +14 -19
- package/dist/cpsat/rules/scope.types.js.map +1 -1
- package/dist/cpsat/rules/target-days-week.d.ts +31 -0
- package/dist/cpsat/rules/target-days-week.d.ts.map +1 -0
- package/dist/cpsat/rules/target-days-week.js +80 -0
- package/dist/cpsat/rules/target-days-week.js.map +1 -0
- package/dist/cpsat/rules/target-peak-concurrent-assignments.d.ts +33 -0
- package/dist/cpsat/rules/target-peak-concurrent-assignments.d.ts.map +1 -0
- package/dist/cpsat/rules/target-peak-concurrent-assignments.js +146 -0
- package/dist/cpsat/rules/target-peak-concurrent-assignments.js.map +1 -0
- package/dist/cpsat/rules/time-cost-surcharge.d.ts +15 -14
- package/dist/cpsat/rules/time-cost-surcharge.d.ts.map +1 -1
- package/dist/cpsat/rules/time-cost-surcharge.js +82 -96
- package/dist/cpsat/rules/time-cost-surcharge.js.map +1 -1
- package/dist/cpsat/rules/time-off.d.ts +21 -57
- package/dist/cpsat/rules/time-off.d.ts.map +1 -1
- package/dist/cpsat/rules/time-off.js +114 -127
- package/dist/cpsat/rules/time-off.js.map +1 -1
- package/dist/cpsat/rules/variables.d.ts +4 -0
- package/dist/cpsat/rules/variables.d.ts.map +1 -0
- package/dist/cpsat/rules/variables.js +10 -0
- package/dist/cpsat/rules/variables.js.map +1 -0
- package/dist/cpsat/rules.d.ts +20 -3
- package/dist/cpsat/rules.d.ts.map +1 -1
- package/dist/cpsat/rules.js +19 -2
- package/dist/cpsat/rules.js.map +1 -1
- package/dist/cpsat/semantic-time.d.ts +7 -6
- package/dist/cpsat/semantic-time.d.ts.map +1 -1
- package/dist/cpsat/semantic-time.js +15 -28
- package/dist/cpsat/semantic-time.js.map +1 -1
- package/dist/cpsat/types.d.ts +47 -4
- package/dist/cpsat/types.d.ts.map +1 -1
- package/dist/cpsat/types.js +24 -1
- package/dist/cpsat/types.js.map +1 -1
- package/dist/cpsat/utils.d.ts +23 -6
- package/dist/cpsat/utils.d.ts.map +1 -1
- package/dist/cpsat/utils.js +76 -15
- package/dist/cpsat/utils.js.map +1 -1
- package/dist/cpsat/validation-reporter.d.ts +6 -2
- package/dist/cpsat/validation-reporter.d.ts.map +1 -1
- package/dist/cpsat/validation-reporter.js +122 -10
- package/dist/cpsat/validation-reporter.js.map +1 -1
- package/dist/cpsat/validation.types.d.ts +21 -10
- package/dist/cpsat/validation.types.d.ts.map +1 -1
- package/dist/datetime.utils.d.ts +7 -13
- package/dist/datetime.utils.d.ts.map +1 -1
- package/dist/datetime.utils.js +29 -36
- package/dist/datetime.utils.js.map +1 -1
- package/dist/index.d.ts +12 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/schedule/cost.d.ts +48 -60
- package/dist/schedule/cost.d.ts.map +1 -1
- package/dist/schedule/cost.js +15 -51
- package/dist/schedule/cost.js.map +1 -1
- package/dist/schedule/coverage.d.ts +57 -28
- package/dist/schedule/coverage.d.ts.map +1 -1
- package/dist/schedule/coverage.js +24 -1
- package/dist/schedule/coverage.js.map +1 -1
- package/dist/schedule/definition.d.ts +138 -19
- package/dist/schedule/definition.d.ts.map +1 -1
- package/dist/schedule/definition.js +99 -90
- package/dist/schedule/definition.js.map +1 -1
- package/dist/schedule/index.d.ts +4 -4
- package/dist/schedule/index.d.ts.map +1 -1
- package/dist/schedule/index.js +2 -2
- package/dist/schedule/index.js.map +1 -1
- package/dist/schedule/rules.d.ts +438 -113
- package/dist/schedule/rules.d.ts.map +1 -1
- package/dist/schedule/rules.js +310 -108
- package/dist/schedule/rules.js.map +1 -1
- package/dist/schedule/shift-patterns.d.ts +0 -17
- package/dist/schedule/shift-patterns.d.ts.map +1 -1
- package/dist/schedule/shift-patterns.js +0 -17
- package/dist/schedule/shift-patterns.js.map +1 -1
- package/dist/schedule/time-periods.d.ts +37 -27
- package/dist/schedule/time-periods.d.ts.map +1 -1
- package/dist/schedule/time-periods.js +37 -27
- package/dist/schedule/time-periods.js.map +1 -1
- package/dist/types.d.ts +67 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +64 -0
- package/dist/types.js.map +1 -1
- package/package.json +8 -9
- package/solver/src/solver/models.py +41 -4
- package/solver/src/solver/solver.py +546 -157
- package/solver/tests/test_solver.py +363 -7
- package/src/client.schemas.ts +127 -10
- package/src/client.ts +3 -0
- package/src/client.types.ts +73 -7
- package/src/cpsat/cost.ts +17 -7
- package/src/cpsat/model-builder.ts +614 -129
- package/src/cpsat/response.ts +57 -13
- package/src/cpsat/rule-descriptor.ts +311 -0
- package/src/cpsat/rules/artifacts.ts +56 -0
- package/src/cpsat/rules/assign-together.ts +104 -69
- package/src/cpsat/rules/assigned-day.ts +70 -0
- package/src/cpsat/rules/assignment-priority.ts +54 -58
- package/src/cpsat/rules/assignment-terms.ts +43 -0
- package/src/cpsat/rules/concurrent-intervals.ts +93 -0
- package/src/cpsat/rules/cost-utils.ts +1 -9
- package/src/cpsat/rules/day-cost-multiplier.ts +101 -81
- package/src/cpsat/rules/day-cost-surcharge.ts +91 -70
- package/src/cpsat/rules/index.ts +30 -24
- package/src/cpsat/rules/location-preference.ts +47 -52
- package/src/cpsat/rules/max-concurrent-assignments.ts +170 -0
- package/src/cpsat/rules/max-consecutive-days.ts +74 -91
- package/src/cpsat/rules/max-days-of-week-per-period.ts +127 -0
- package/src/cpsat/rules/max-days-week.ts +89 -115
- package/src/cpsat/rules/max-hours-day.ts +64 -84
- package/src/cpsat/rules/max-hours-week.ts +74 -90
- package/src/cpsat/rules/max-shifts-day.ts +65 -85
- package/src/cpsat/rules/min-consecutive-days.ts +161 -127
- package/src/cpsat/rules/min-days-of-week-per-period.ts +144 -0
- package/src/cpsat/rules/min-days-week.ts +93 -91
- package/src/cpsat/rules/min-hours-day.ts +79 -58
- package/src/cpsat/rules/min-hours-week.ts +87 -62
- package/src/cpsat/rules/min-rest-between-shifts.ts +191 -178
- package/src/cpsat/rules/minimize-cost.ts +175 -188
- package/src/cpsat/rules/must-assign.ts +44 -81
- package/src/cpsat/rules/overtime-daily-multiplier.ts +158 -140
- package/src/cpsat/rules/overtime-daily-surcharge.ts +141 -126
- package/src/cpsat/rules/overtime-tiered-multiplier.ts +234 -253
- package/src/cpsat/rules/overtime-weekly-multiplier.ts +183 -175
- package/src/cpsat/rules/overtime-weekly-surcharge.ts +161 -150
- package/src/cpsat/rules/pattern-eligibility.ts +26 -0
- package/src/cpsat/rules/pattern-time.ts +30 -0
- package/src/cpsat/rules/registry.ts +140 -62
- package/src/cpsat/rules/resolver.ts +58 -30
- package/src/cpsat/rules/role-preference.ts +92 -0
- package/src/cpsat/rules/rules.types.ts +89 -17
- package/src/cpsat/rules/scope.types.ts +31 -26
- package/src/cpsat/rules/target-days-week.ts +105 -0
- package/src/cpsat/rules/target-peak-concurrent-assignments.ts +212 -0
- package/src/cpsat/rules/time-cost-surcharge.ts +116 -122
- package/src/cpsat/rules/time-off.ts +154 -163
- package/src/cpsat/rules/variables.ts +11 -0
- package/src/cpsat/rules.ts +43 -17
- package/src/cpsat/semantic-time.ts +29 -43
- package/src/cpsat/types.ts +53 -4
- package/src/cpsat/utils.ts +92 -20
- package/src/cpsat/validation-reporter.ts +170 -19
- package/src/cpsat/validation.types.ts +22 -11
- package/src/datetime.utils.ts +45 -44
- package/src/index.ts +64 -12
- package/src/schedule/cost.ts +40 -61
- package/src/schedule/coverage.ts +57 -28
- package/src/schedule/definition.ts +565 -76
- package/src/schedule/index.ts +23 -3
- package/src/schedule/rules.ts +631 -132
- package/src/schedule/shift-patterns.ts +0 -17
- package/src/schedule/time-periods.ts +37 -27
- package/src/types.ts +114 -2
package/src/datetime.utils.ts
CHANGED
|
@@ -1,50 +1,46 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
thursday: 4,
|
|
9
|
-
friday: 5,
|
|
10
|
-
saturday: 6,
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
const DAY_NAMES = [
|
|
14
|
-
"sunday",
|
|
15
|
-
"monday",
|
|
16
|
-
"tuesday",
|
|
17
|
-
"wednesday",
|
|
18
|
-
"thursday",
|
|
19
|
-
"friday",
|
|
20
|
-
"saturday",
|
|
21
|
-
] as const;
|
|
1
|
+
import {
|
|
2
|
+
DAY_NAMES,
|
|
3
|
+
type DateString,
|
|
4
|
+
type DayOfWeek,
|
|
5
|
+
type SchedulingDay,
|
|
6
|
+
type SchedulingPeriod,
|
|
7
|
+
} from "./types.js";
|
|
22
8
|
|
|
23
9
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
10
|
+
* Builds a {@link SchedulingDay} from an existing UTC `Date`, avoiding a
|
|
11
|
+
* redundant `new Date()` call. Used internally by {@link resolveDaysFromPeriod}
|
|
12
|
+
* where the loop already maintains a `Date` cursor.
|
|
26
13
|
*/
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
14
|
+
function schedulingDayFromDate(date: Date, iso: DateString): SchedulingDay {
|
|
15
|
+
const dayOfWeek = DAY_NAMES[date.getUTCDay()]!;
|
|
16
|
+
const month = date.getUTCMonth() + 1;
|
|
17
|
+
const dayOfMonth = date.getUTCDate();
|
|
18
|
+
return {
|
|
19
|
+
iso,
|
|
20
|
+
dayOfWeek,
|
|
21
|
+
month,
|
|
22
|
+
dayOfMonth,
|
|
23
|
+
yearMonth: iso.slice(0, 7),
|
|
24
|
+
epochDay: Math.floor(date.getTime() / 86_400_000),
|
|
25
|
+
};
|
|
30
26
|
}
|
|
31
27
|
|
|
32
28
|
/**
|
|
33
|
-
* Computes the list of
|
|
29
|
+
* Computes the list of {@link SchedulingDay} values from a {@link SchedulingPeriod}.
|
|
34
30
|
*
|
|
35
31
|
* Generates all days between start and end (inclusive), applying optional
|
|
36
32
|
* dayOfWeek and dates filters. Filters compose: a day must pass all
|
|
37
33
|
* specified filters to be included.
|
|
38
34
|
*
|
|
39
35
|
* @param period - The scheduling period specification
|
|
40
|
-
* @returns Array of
|
|
36
|
+
* @returns Array of scheduling days, sorted chronologically
|
|
41
37
|
*
|
|
42
38
|
* @example All days in range
|
|
43
39
|
* ```typescript
|
|
44
40
|
* const days = resolveDaysFromPeriod({
|
|
45
41
|
* dateRange: { start: '2025-02-03', end: '2025-02-05' },
|
|
46
42
|
* });
|
|
47
|
-
* // Returns
|
|
43
|
+
* // Returns days for 2025-02-03, 2025-02-04, 2025-02-05
|
|
48
44
|
* ```
|
|
49
45
|
*
|
|
50
46
|
* @example Day-of-week filter
|
|
@@ -53,7 +49,7 @@ export function toDayOfWeekUTC(date: Date): DayOfWeek {
|
|
|
53
49
|
* dateRange: { start: '2025-02-03', end: '2025-02-09' },
|
|
54
50
|
* dayOfWeek: ['wednesday', 'friday'],
|
|
55
51
|
* });
|
|
56
|
-
* // Returns
|
|
52
|
+
* // Returns days for 2025-02-05, 2025-02-07
|
|
57
53
|
* ```
|
|
58
54
|
*
|
|
59
55
|
* @example Specific dates filter
|
|
@@ -62,31 +58,36 @@ export function toDayOfWeekUTC(date: Date): DayOfWeek {
|
|
|
62
58
|
* dateRange: { start: '2025-02-03', end: '2025-02-10' },
|
|
63
59
|
* dates: ['2025-02-05', '2025-02-07'],
|
|
64
60
|
* });
|
|
65
|
-
* // Returns
|
|
61
|
+
* // Returns days for 2025-02-05, 2025-02-07
|
|
66
62
|
* ```
|
|
67
63
|
*/
|
|
68
|
-
export function resolveDaysFromPeriod(period: SchedulingPeriod):
|
|
64
|
+
export function resolveDaysFromPeriod(period: SchedulingPeriod): SchedulingDay[] {
|
|
69
65
|
const { dateRange, dayOfWeek, dates } = period;
|
|
70
|
-
const allowedDays = dayOfWeek ? new Set(dayOfWeek) : null;
|
|
71
|
-
const allowedDates = dates ? new Set(dates) : null;
|
|
66
|
+
const allowedDays: Set<DayOfWeek> | null = dayOfWeek ? new Set(dayOfWeek) : null;
|
|
67
|
+
const allowedDates: Set<string> | null = dates ? new Set(dates) : null;
|
|
72
68
|
|
|
73
69
|
const startDate = new Date(`${dateRange.start}T00:00:00Z`);
|
|
74
70
|
const endDate = new Date(`${dateRange.end}T00:00:00Z`);
|
|
75
|
-
const result:
|
|
71
|
+
const result: SchedulingDay[] = [];
|
|
76
72
|
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
for (
|
|
74
|
+
let currentTime = startDate.getTime(), endTime = endDate.getTime();
|
|
75
|
+
currentTime <= endTime;
|
|
76
|
+
currentTime += 24 * 60 * 60 * 1000
|
|
77
|
+
) {
|
|
78
|
+
const current = new Date(currentTime);
|
|
79
79
|
const year = current.getUTCFullYear();
|
|
80
80
|
const month = (current.getUTCMonth() + 1).toString().padStart(2, "0");
|
|
81
|
-
const
|
|
82
|
-
const iso = `${year}-${month}-${
|
|
83
|
-
const
|
|
81
|
+
const d = current.getUTCDate().toString().padStart(2, "0");
|
|
82
|
+
const iso = `${year}-${month}-${d}` as DateString;
|
|
83
|
+
const day = schedulingDayFromDate(current, iso);
|
|
84
84
|
|
|
85
|
-
if (
|
|
86
|
-
|
|
85
|
+
if (
|
|
86
|
+
(!allowedDays || allowedDays.has(day.dayOfWeek)) &&
|
|
87
|
+
(!allowedDates || allowedDates.has(iso))
|
|
88
|
+
) {
|
|
89
|
+
result.push(day);
|
|
87
90
|
}
|
|
88
|
-
|
|
89
|
-
current.setUTCDate(current.getUTCDate() + 1);
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
return result;
|
package/src/index.ts
CHANGED
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
// Time primitives
|
|
37
37
|
// ============================================================================
|
|
38
38
|
|
|
39
|
-
export type { TimeOfDay, DayOfWeek, SchedulingPeriod } from "./types.js";
|
|
39
|
+
export type { DateString, TimeOfDay, DayOfWeek, SchedulingDay, SchedulingPeriod } from "./types.js";
|
|
40
40
|
|
|
41
|
-
export { DayOfWeekSchema } from "./types.js";
|
|
41
|
+
export { schedulingDay, DAY_OF_WEEK_INDEX, DayOfWeekSchema } from "./types.js";
|
|
42
42
|
|
|
43
43
|
// ============================================================================
|
|
44
44
|
// Solver client
|
|
@@ -51,13 +51,27 @@ export type {
|
|
|
51
51
|
SolverRequest,
|
|
52
52
|
SolverResponse,
|
|
53
53
|
SolverStatus,
|
|
54
|
-
|
|
54
|
+
SolverMode,
|
|
55
|
+
SolverDiagnosticMode,
|
|
56
|
+
SolverObjectiveStage,
|
|
57
|
+
SolverStageResult,
|
|
58
|
+
SolverSoftConstraintViolation,
|
|
59
|
+
SolverHardConstraintConflict,
|
|
55
60
|
FetcherLike,
|
|
56
61
|
} from "./client.types.js";
|
|
57
62
|
|
|
58
63
|
export { SOLVER_STATUS } from "./client.types.js";
|
|
59
64
|
|
|
60
|
-
export {
|
|
65
|
+
export {
|
|
66
|
+
SolverModeSchema,
|
|
67
|
+
SolverDiagnosticModeSchema,
|
|
68
|
+
SolverObjectiveStageSchema,
|
|
69
|
+
SolverRequestSchema,
|
|
70
|
+
SolverResponseSchema,
|
|
71
|
+
SolverStageResultSchema,
|
|
72
|
+
SolverStatusSchema,
|
|
73
|
+
SolverHardConstraintConflictSchema,
|
|
74
|
+
} from "./client.schemas.js";
|
|
61
75
|
|
|
62
76
|
// ============================================================================
|
|
63
77
|
// Model builder
|
|
@@ -65,14 +79,27 @@ export { SolverRequestSchema, SolverResponseSchema, SolverStatusSchema } from ".
|
|
|
65
79
|
|
|
66
80
|
export { ModelBuilder } from "./cpsat/model-builder.js";
|
|
67
81
|
|
|
82
|
+
export type { ModelBuilderConfig, CompilationResult } from "./cpsat/model-builder.js";
|
|
83
|
+
export type { ModelSolveStrategy } from "./cpsat/types.js";
|
|
84
|
+
|
|
85
|
+
export { compileRuleDescriptor, defineRuleDescriptor } from "./cpsat/rule-descriptor.js";
|
|
86
|
+
|
|
68
87
|
export type {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
88
|
+
CostValidationStrategy,
|
|
89
|
+
HardConstraintValidationStrategy,
|
|
90
|
+
ObjectiveValidationStrategy,
|
|
91
|
+
ReportHardConstraintValidationStrategy,
|
|
92
|
+
ReportSoftConstraintValidationStrategy,
|
|
93
|
+
RuleDescriptor,
|
|
94
|
+
RuleCompileContext,
|
|
95
|
+
RuleArtifact,
|
|
96
|
+
SkipValidationStrategy,
|
|
97
|
+
SoftConstraintValidationStrategy,
|
|
98
|
+
CompiledRule,
|
|
99
|
+
ValidationSkipCategory,
|
|
73
100
|
CostEntry,
|
|
74
101
|
CostContribution,
|
|
75
|
-
} from "./cpsat/
|
|
102
|
+
} from "./cpsat/rule-descriptor.js";
|
|
76
103
|
|
|
77
104
|
// ============================================================================
|
|
78
105
|
// Solver response parsing
|
|
@@ -94,10 +121,19 @@ export type { CostBreakdown, MemberCostDetail, CostCalculationConfig } from "./c
|
|
|
94
121
|
// Rules (registry types)
|
|
95
122
|
// ============================================================================
|
|
96
123
|
|
|
124
|
+
export {
|
|
125
|
+
assertValidCpsatRuleRegistry,
|
|
126
|
+
builtInCpsatRuleRegistry,
|
|
127
|
+
createCpsatRuleRegistry,
|
|
128
|
+
} from "./cpsat/rules/registry.js";
|
|
129
|
+
|
|
97
130
|
export type {
|
|
131
|
+
BuiltInCpsatRuleConfigRegistry,
|
|
132
|
+
BuiltInCpsatRuleRegistry,
|
|
133
|
+
CpsatRuleConfigByName,
|
|
98
134
|
CpsatRuleConfigEntry,
|
|
99
|
-
|
|
100
|
-
|
|
135
|
+
CpsatRuleConfigEntryFor,
|
|
136
|
+
CpsatRuleRegistry,
|
|
101
137
|
} from "./cpsat/rules/rules.types.js";
|
|
102
138
|
|
|
103
139
|
export type { RecurringPeriod } from "./cpsat/rules/scope.types.js";
|
|
@@ -150,6 +186,7 @@ export { summarizeValidation } from "./cpsat/validation-reporter.js";
|
|
|
150
186
|
|
|
151
187
|
export {
|
|
152
188
|
schedule,
|
|
189
|
+
scheduleWithRuleRegistry,
|
|
153
190
|
partialSchedule,
|
|
154
191
|
Schedule,
|
|
155
192
|
t,
|
|
@@ -162,16 +199,24 @@ export {
|
|
|
162
199
|
minHoursPerWeek,
|
|
163
200
|
maxDaysPerWeek,
|
|
164
201
|
minDaysPerWeek,
|
|
202
|
+
targetDaysPerWeek,
|
|
165
203
|
maxShiftsPerDay,
|
|
204
|
+
maxConcurrentAssignments,
|
|
205
|
+
targetPeakConcurrentAssignments,
|
|
166
206
|
maxConsecutiveDays,
|
|
167
207
|
minConsecutiveDays,
|
|
168
208
|
minRestBetweenShifts,
|
|
169
209
|
mustAssign,
|
|
170
|
-
|
|
210
|
+
preferAssignment,
|
|
211
|
+
avoidAssignment,
|
|
212
|
+
preferRole,
|
|
171
213
|
preferLocation,
|
|
172
214
|
timeOff,
|
|
173
215
|
assignTogether,
|
|
216
|
+
maxDaysOfWeekPerPeriod,
|
|
217
|
+
minDaysOfWeekPerPeriod,
|
|
174
218
|
defineRule,
|
|
219
|
+
defineRuleFor,
|
|
175
220
|
minimizeCost,
|
|
176
221
|
dayMultiplier,
|
|
177
222
|
daySurcharge,
|
|
@@ -192,12 +237,19 @@ export type {
|
|
|
192
237
|
RuleEntry,
|
|
193
238
|
RuleResolveContext,
|
|
194
239
|
RuleOptions,
|
|
240
|
+
ScheduleRuleEntry,
|
|
195
241
|
EntityOnlyRuleOptions,
|
|
242
|
+
TargetDaysPerWeekOptions,
|
|
196
243
|
TimeOffOptions,
|
|
197
244
|
AssignTogetherOptions,
|
|
245
|
+
MaxConcurrentAssignmentsOptions,
|
|
246
|
+
TargetPeakConcurrentAssignmentsOptions,
|
|
247
|
+
DaysOfWeekPerPeriodOptions,
|
|
198
248
|
CostRuleOptions,
|
|
199
249
|
ScheduleConfig,
|
|
250
|
+
ScheduleWithRuleRegistryConfig,
|
|
200
251
|
SolveResult,
|
|
201
252
|
SolveStatus,
|
|
253
|
+
SolveStrategy,
|
|
202
254
|
SolveOptions,
|
|
203
255
|
} from "./schedule/index.js";
|
package/src/schedule/cost.ts
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cost optimization rules: minimize labor cost with modifiers.
|
|
3
3
|
*
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* rules: [
|
|
8
|
+
* minimizeCost(),
|
|
9
|
+
* dayMultiplier(1.5, { dayOfWeek: weekend }),
|
|
10
|
+
* overtimeMultiplier({ after: 40, factor: 1.5 }),
|
|
11
|
+
* dailyOvertimeSurcharge({ after: 8, amount: 500 }),
|
|
12
|
+
* tieredOvertimeMultiplier([
|
|
13
|
+
* { after: 40, factor: 1.5 },
|
|
14
|
+
* { after: 48, factor: 2.0 },
|
|
15
|
+
* ]),
|
|
16
|
+
* ]
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
4
19
|
* @module
|
|
5
20
|
*/
|
|
6
21
|
|
|
@@ -39,7 +54,10 @@ export interface CostRuleOptions {
|
|
|
39
54
|
// Cost Rules
|
|
40
55
|
// ============================================================================
|
|
41
56
|
|
|
42
|
-
function makeCostRule
|
|
57
|
+
function makeCostRule<const Name extends string, const Fields extends object>(
|
|
58
|
+
rule: Name,
|
|
59
|
+
fields: Fields,
|
|
60
|
+
): RuleEntry<Name, Omit<Fields, "_type" | "_rule">> {
|
|
43
61
|
return defineRule(rule, fields);
|
|
44
62
|
}
|
|
45
63
|
|
|
@@ -64,14 +82,9 @@ function makeCostRule(rule: string, fields: Record<string, unknown>): RuleEntry
|
|
|
64
82
|
* - `dailyOvertimeSurcharge({ after, amount }, opts?)` - daily overtime surcharge
|
|
65
83
|
* - `tieredOvertimeMultiplier(tiers, opts?)` - multiple overtime thresholds
|
|
66
84
|
*
|
|
67
|
-
* @example
|
|
68
|
-
* ```ts
|
|
69
|
-
* minimizeCost()
|
|
70
|
-
* ```
|
|
71
|
-
*
|
|
72
85
|
* @category Cost Optimization
|
|
73
86
|
*/
|
|
74
|
-
export function minimizeCost(opts?: CostRuleOptions): RuleEntry {
|
|
87
|
+
export function minimizeCost(opts?: CostRuleOptions): RuleEntry<"minimize-cost", CostRuleOptions> {
|
|
75
88
|
return makeCostRule("minimize-cost", { ...opts });
|
|
76
89
|
}
|
|
77
90
|
|
|
@@ -83,13 +96,11 @@ export function minimizeCost(opts?: CostRuleOptions): RuleEntry {
|
|
|
83
96
|
* this rule adds only the extra portion above 1x.
|
|
84
97
|
*
|
|
85
98
|
* @category Cost Optimization
|
|
86
|
-
*
|
|
87
|
-
* @example Weekend multiplier
|
|
88
|
-
* ```typescript
|
|
89
|
-
* dayMultiplier(1.5, { dayOfWeek: weekend })
|
|
90
|
-
* ```
|
|
91
99
|
*/
|
|
92
|
-
export function dayMultiplier(
|
|
100
|
+
export function dayMultiplier(
|
|
101
|
+
factor: number,
|
|
102
|
+
opts?: CostRuleOptions,
|
|
103
|
+
): RuleEntry<"day-cost-multiplier", { factor: number } & CostRuleOptions> {
|
|
93
104
|
return makeCostRule("day-cost-multiplier", { factor, ...opts });
|
|
94
105
|
}
|
|
95
106
|
|
|
@@ -100,13 +111,11 @@ export function dayMultiplier(factor: number, opts?: CostRuleOptions): RuleEntry
|
|
|
100
111
|
* The surcharge is independent of the member's base rate.
|
|
101
112
|
*
|
|
102
113
|
* @category Cost Optimization
|
|
103
|
-
*
|
|
104
|
-
* @example Weekend surcharge
|
|
105
|
-
* ```typescript
|
|
106
|
-
* daySurcharge(500, { dayOfWeek: weekend })
|
|
107
|
-
* ```
|
|
108
114
|
*/
|
|
109
|
-
export function daySurcharge(
|
|
115
|
+
export function daySurcharge(
|
|
116
|
+
amountPerHour: number,
|
|
117
|
+
opts?: CostRuleOptions,
|
|
118
|
+
): RuleEntry<"day-cost-surcharge", { amountPerHour: number } & CostRuleOptions> {
|
|
110
119
|
return makeCostRule("day-cost-surcharge", { amountPerHour, ...opts });
|
|
111
120
|
}
|
|
112
121
|
|
|
@@ -122,17 +131,15 @@ export function daySurcharge(amountPerHour: number, opts?: CostRuleOptions): Rul
|
|
|
122
131
|
* @param opts - Entity and time scoping
|
|
123
132
|
*
|
|
124
133
|
* @category Cost Optimization
|
|
125
|
-
*
|
|
126
|
-
* @example Night differential
|
|
127
|
-
* ```typescript
|
|
128
|
-
* timeSurcharge(200, { from: t(22), until: t(6) })
|
|
129
|
-
* ```
|
|
130
134
|
*/
|
|
131
135
|
export function timeSurcharge(
|
|
132
136
|
amountPerHour: number,
|
|
133
137
|
window: { from: TimeOfDay; until: TimeOfDay },
|
|
134
138
|
opts?: CostRuleOptions,
|
|
135
|
-
): RuleEntry
|
|
139
|
+
): RuleEntry<
|
|
140
|
+
"time-cost-surcharge",
|
|
141
|
+
{ amountPerHour: number; window: { from: TimeOfDay; until: TimeOfDay } } & CostRuleOptions
|
|
142
|
+
> {
|
|
136
143
|
return makeCostRule("time-cost-surcharge", { amountPerHour, window, ...opts });
|
|
137
144
|
}
|
|
138
145
|
|
|
@@ -144,15 +151,10 @@ export function timeSurcharge(
|
|
|
144
151
|
* counted by {@link minimizeCost}).
|
|
145
152
|
*
|
|
146
153
|
* @category Cost Optimization
|
|
147
|
-
*
|
|
148
|
-
* @example
|
|
149
|
-
* ```typescript
|
|
150
|
-
* overtimeMultiplier({ after: 40, factor: 1.5 })
|
|
151
|
-
* ```
|
|
152
154
|
*/
|
|
153
155
|
export function overtimeMultiplier(
|
|
154
156
|
opts: { after: number; factor: number } & CostRuleOptions,
|
|
155
|
-
): RuleEntry {
|
|
157
|
+
): RuleEntry<"overtime-weekly-multiplier", { after: number; factor: number } & CostRuleOptions> {
|
|
156
158
|
return makeCostRule("overtime-weekly-multiplier", { ...opts });
|
|
157
159
|
}
|
|
158
160
|
|
|
@@ -163,15 +165,10 @@ export function overtimeMultiplier(
|
|
|
163
165
|
* The surcharge is independent of the member's base rate.
|
|
164
166
|
*
|
|
165
167
|
* @category Cost Optimization
|
|
166
|
-
*
|
|
167
|
-
* @example
|
|
168
|
-
* ```typescript
|
|
169
|
-
* overtimeSurcharge({ after: 40, amount: 1000 })
|
|
170
|
-
* ```
|
|
171
168
|
*/
|
|
172
169
|
export function overtimeSurcharge(
|
|
173
170
|
opts: { after: number; amount: number } & CostRuleOptions,
|
|
174
|
-
): RuleEntry {
|
|
171
|
+
): RuleEntry<"overtime-weekly-surcharge", { after: number; amount: number } & CostRuleOptions> {
|
|
175
172
|
return makeCostRule("overtime-weekly-surcharge", { ...opts });
|
|
176
173
|
}
|
|
177
174
|
|
|
@@ -183,15 +180,10 @@ export function overtimeSurcharge(
|
|
|
183
180
|
* counted by {@link minimizeCost}).
|
|
184
181
|
*
|
|
185
182
|
* @category Cost Optimization
|
|
186
|
-
*
|
|
187
|
-
* @example
|
|
188
|
-
* ```typescript
|
|
189
|
-
* dailyOvertimeMultiplier({ after: 8, factor: 1.5 })
|
|
190
|
-
* ```
|
|
191
183
|
*/
|
|
192
184
|
export function dailyOvertimeMultiplier(
|
|
193
185
|
opts: { after: number; factor: number } & CostRuleOptions,
|
|
194
|
-
): RuleEntry {
|
|
186
|
+
): RuleEntry<"overtime-daily-multiplier", { after: number; factor: number } & CostRuleOptions> {
|
|
195
187
|
return makeCostRule("overtime-daily-multiplier", { ...opts });
|
|
196
188
|
}
|
|
197
189
|
|
|
@@ -202,15 +194,10 @@ export function dailyOvertimeMultiplier(
|
|
|
202
194
|
* The surcharge is independent of the member's base rate.
|
|
203
195
|
*
|
|
204
196
|
* @category Cost Optimization
|
|
205
|
-
*
|
|
206
|
-
* @example
|
|
207
|
-
* ```typescript
|
|
208
|
-
* dailyOvertimeSurcharge({ after: 8, amount: 500 })
|
|
209
|
-
* ```
|
|
210
197
|
*/
|
|
211
198
|
export function dailyOvertimeSurcharge(
|
|
212
199
|
opts: { after: number; amount: number } & CostRuleOptions,
|
|
213
|
-
): RuleEntry {
|
|
200
|
+
): RuleEntry<"overtime-daily-surcharge", { after: number; amount: number } & CostRuleOptions> {
|
|
214
201
|
return makeCostRule("overtime-daily-surcharge", { ...opts });
|
|
215
202
|
}
|
|
216
203
|
|
|
@@ -222,21 +209,13 @@ export function dailyOvertimeSurcharge(
|
|
|
222
209
|
* Tiers must be sorted by threshold ascending.
|
|
223
210
|
*
|
|
224
211
|
* @category Cost Optimization
|
|
225
|
-
*
|
|
226
|
-
* @example
|
|
227
|
-
* ```typescript
|
|
228
|
-
* // Hours 0-40: base rate
|
|
229
|
-
* // Hours 40-48: 1.5x
|
|
230
|
-
* // Hours 48+: 2.0x
|
|
231
|
-
* tieredOvertimeMultiplier([
|
|
232
|
-
* { after: 40, factor: 1.5 },
|
|
233
|
-
* { after: 48, factor: 2.0 },
|
|
234
|
-
* ])
|
|
235
|
-
* ```
|
|
236
212
|
*/
|
|
237
213
|
export function tieredOvertimeMultiplier(
|
|
238
214
|
tiers: [OvertimeTier, ...OvertimeTier[]],
|
|
239
215
|
opts?: CostRuleOptions,
|
|
240
|
-
): RuleEntry
|
|
216
|
+
): RuleEntry<
|
|
217
|
+
"overtime-tiered-multiplier",
|
|
218
|
+
{ tiers: [OvertimeTier, ...OvertimeTier[]] } & CostRuleOptions
|
|
219
|
+
> {
|
|
241
220
|
return makeCostRule("overtime-tiered-multiplier", { tiers, ...opts });
|
|
242
221
|
}
|
package/src/schedule/coverage.ts
CHANGED
|
@@ -1,10 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Coverage definitions: staffing requirements per semantic time period.
|
|
2
|
+
* Coverage definitions: lower-bound staffing requirements per semantic time period.
|
|
3
|
+
*
|
|
4
|
+
* Coverage answers "what floor should apply throughout this scoped time, with
|
|
5
|
+
* the chosen priority?". It attaches sustained lower bounds to semantic times,
|
|
6
|
+
* whether those periods are
|
|
7
|
+
* explicit in the requirements or inferred to separate distinct business
|
|
8
|
+
* requirements. Coverage does not express caps, targets, fairness, or other
|
|
9
|
+
* assignment-shaping logic. Use rules for those concerns.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* coverage: [
|
|
14
|
+
* cover("lunch", "waiter", 2, { dayOfWeek: weekdays }),
|
|
15
|
+
* cover("lunch", "waiter", 3, { dayOfWeek: weekend }),
|
|
16
|
+
* cover("dinner", ["manager", "supervisor"], 1),
|
|
17
|
+
* cover("opening", "keyholder", 1),
|
|
18
|
+
*
|
|
19
|
+
* // Variant form: different counts by day
|
|
20
|
+
* cover("peak_hours", "agent",
|
|
21
|
+
* { count: 4 },
|
|
22
|
+
* { count: 2, dates: ["2025-12-24"] },
|
|
23
|
+
* ),
|
|
24
|
+
* ]
|
|
25
|
+
* ```
|
|
3
26
|
*
|
|
4
27
|
* @module
|
|
5
28
|
*/
|
|
6
29
|
|
|
7
|
-
import type { DayOfWeek } from "../types.js";
|
|
30
|
+
import type { DateString, DayOfWeek } from "../types.js";
|
|
8
31
|
import type { CoverageVariant } from "../cpsat/semantic-time.js";
|
|
9
32
|
import type { Priority } from "../cpsat/types.js";
|
|
10
33
|
|
|
@@ -16,7 +39,15 @@ export type { CoverageVariant } from "../cpsat/semantic-time.js";
|
|
|
16
39
|
* @remarks
|
|
17
40
|
* Day/date scoping controls which days this coverage entry applies to.
|
|
18
41
|
* An entry without `dayOfWeek` or `dates` applies every day in the
|
|
19
|
-
* scheduling period.
|
|
42
|
+
* scheduling period. Scope answers where the floor applies; it does not change
|
|
43
|
+
* the meaning of coverage itself. `priority` controls how hard the coverage floor is.
|
|
44
|
+
* Use it to distinguish language like "must keep 5 staffed on Saturdays"
|
|
45
|
+
* from "ideally keep 5 staffed on Mondays too" without changing the
|
|
46
|
+
* underlying coverage shape. `skillIds` is a hard filter, not a preference.
|
|
47
|
+
* Use it only when the required minimum truly needs those skills throughout
|
|
48
|
+
* the window. If a role or skill mix is preferred rather than required, model
|
|
49
|
+
* that with rules such as {@link preferAssignment} instead of skill-filtered
|
|
50
|
+
* coverage.
|
|
20
51
|
*
|
|
21
52
|
* @category Coverage
|
|
22
53
|
*/
|
|
@@ -26,7 +57,7 @@ export interface CoverageOptions {
|
|
|
26
57
|
/** Restrict to specific days of the week. */
|
|
27
58
|
dayOfWeek?: readonly [DayOfWeek, ...DayOfWeek[]];
|
|
28
59
|
/** Restrict to specific dates (YYYY-MM-DD). */
|
|
29
|
-
dates?:
|
|
60
|
+
dates?: DateString[];
|
|
30
61
|
/** Defaults to `"MANDATORY"`. */
|
|
31
62
|
priority?: Priority;
|
|
32
63
|
}
|
|
@@ -53,36 +84,34 @@ export interface CoverageEntry<T extends string = string, R extends string = str
|
|
|
53
84
|
* Defines a staffing requirement for a semantic time period.
|
|
54
85
|
*
|
|
55
86
|
* @remarks
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
87
|
+
* Coverage always defines a lower bound that applies throughout the scoped
|
|
88
|
+
* semantic time, with strength controlled by `priority`. If the requirements
|
|
89
|
+
* also state an upper bound or productive
|
|
90
|
+
* cap, model that separately in `rules`, for example with
|
|
91
|
+
* {@link maxConcurrentAssignments}.
|
|
92
|
+
*
|
|
93
|
+
* Scope answers where the floor applies. Priority answers how strictly the
|
|
94
|
+
* solver should preserve that floor when trade-offs are necessary.
|
|
95
|
+
*
|
|
96
|
+
* Attach coverage to the narrowest semantic time that actually carries that
|
|
97
|
+
* minimum. Avoid layering a broad parent coverage window on top of narrower
|
|
98
|
+
* windows unless the same lower bound truly applies throughout the full span.
|
|
99
|
+
* If the requirements talk about hitting full occupancy at the busy point,
|
|
100
|
+
* prefer {@link targetPeakConcurrentAssignments} over turning that into a
|
|
101
|
+
* whole-window minimum. Do not infer a synthetic "peak" semantic time just to attach
|
|
102
|
+
* `cover(..., 5)` unless the requirements really define a sustained window
|
|
103
|
+
* that needs that minimum throughout.
|
|
104
|
+
*
|
|
105
|
+
* Overlapping entries for the same time and role produce independent
|
|
106
|
+
* constraints; the solver enforces the **max** count, not the sum.
|
|
107
|
+
* An unscoped entry acts as a floor that scoped entries cannot reduce.
|
|
108
|
+
* Use mutually exclusive scopes when different days need different coverage.
|
|
59
109
|
*
|
|
60
110
|
* @param timeName - Name of a declared semantic time
|
|
61
111
|
* @param target - Role name (string), array of role names (OR logic), or skill name
|
|
62
112
|
* @param count - Number of people needed
|
|
63
113
|
* @param opts - Options: `skillIds` (AND filter), `dayOfWeek`, `dates`, `priority`
|
|
64
114
|
*
|
|
65
|
-
* @example
|
|
66
|
-
* ```typescript
|
|
67
|
-
* coverage: [
|
|
68
|
-
* // 2 waiters during lunch
|
|
69
|
-
* cover("lunch", "waiter", 2),
|
|
70
|
-
*
|
|
71
|
-
* // 1 manager OR supervisor during dinner
|
|
72
|
-
* cover("dinner", ["manager", "supervisor"], 1),
|
|
73
|
-
*
|
|
74
|
-
* // 1 person with keyholder skill at opening
|
|
75
|
-
* cover("opening", "keyholder", 1),
|
|
76
|
-
*
|
|
77
|
-
* // 1 senior waiter (role + skill AND)
|
|
78
|
-
* cover("lunch", "waiter", 1, { skillIds: ["senior"] }),
|
|
79
|
-
*
|
|
80
|
-
* // Different counts by day (mutually exclusive dayOfWeek!)
|
|
81
|
-
* cover("lunch", "waiter", 2, { dayOfWeek: weekdays }),
|
|
82
|
-
* cover("lunch", "waiter", 3, { dayOfWeek: weekend }),
|
|
83
|
-
* ]
|
|
84
|
-
* ```
|
|
85
|
-
*
|
|
86
115
|
* @category Coverage
|
|
87
116
|
*/
|
|
88
117
|
export function cover<T extends string, const R extends string>(
|