dabke 0.81.1 → 0.83.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 +58 -0
- package/README.md +45 -27
- package/dist/client.d.ts +20 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +4 -1
- package/dist/client.js.map +1 -1
- package/dist/client.types.d.ts +9 -0
- package/dist/client.types.d.ts.map +1 -1
- package/dist/client.types.js +1 -0
- package/dist/client.types.js.map +1 -1
- package/dist/cpsat/model-builder.d.ts +9 -0
- package/dist/cpsat/model-builder.d.ts.map +1 -1
- package/dist/cpsat/model-builder.js +36 -34
- package/dist/cpsat/model-builder.js.map +1 -1
- package/dist/cpsat/response.d.ts +13 -1
- package/dist/cpsat/response.d.ts.map +1 -1
- package/dist/cpsat/response.js +4 -0
- package/dist/cpsat/response.js.map +1 -1
- package/dist/cpsat/rules/cost-utils.d.ts +11 -0
- package/dist/cpsat/rules/cost-utils.d.ts.map +1 -0
- package/dist/cpsat/rules/cost-utils.js +24 -0
- package/dist/cpsat/rules/cost-utils.js.map +1 -0
- package/dist/cpsat/rules/day-cost-multiplier.d.ts.map +1 -1
- package/dist/cpsat/rules/day-cost-multiplier.js +3 -14
- package/dist/cpsat/rules/day-cost-multiplier.js.map +1 -1
- package/dist/cpsat/rules/day-cost-surcharge.d.ts.map +1 -1
- package/dist/cpsat/rules/day-cost-surcharge.js +3 -7
- package/dist/cpsat/rules/day-cost-surcharge.js.map +1 -1
- package/dist/cpsat/rules/index.d.ts +3 -0
- package/dist/cpsat/rules/index.d.ts.map +1 -1
- package/dist/cpsat/rules/index.js +3 -0
- package/dist/cpsat/rules/index.js.map +1 -1
- package/dist/cpsat/rules/max-consecutive-days.d.ts.map +1 -1
- package/dist/cpsat/rules/max-consecutive-days.js +16 -2
- package/dist/cpsat/rules/max-consecutive-days.js.map +1 -1
- package/dist/cpsat/rules/max-days-week.d.ts +44 -0
- package/dist/cpsat/rules/max-days-week.d.ts.map +1 -0
- package/dist/cpsat/rules/max-days-week.js +95 -0
- package/dist/cpsat/rules/max-days-week.js.map +1 -0
- package/dist/cpsat/rules/max-hours-day.d.ts.map +1 -1
- package/dist/cpsat/rules/max-hours-day.js +15 -2
- package/dist/cpsat/rules/max-hours-day.js.map +1 -1
- package/dist/cpsat/rules/max-hours-week.d.ts.map +1 -1
- package/dist/cpsat/rules/max-hours-week.js +16 -2
- package/dist/cpsat/rules/max-hours-week.js.map +1 -1
- package/dist/cpsat/rules/max-shifts-day.d.ts.map +1 -1
- package/dist/cpsat/rules/max-shifts-day.js +15 -2
- package/dist/cpsat/rules/max-shifts-day.js.map +1 -1
- package/dist/cpsat/rules/min-consecutive-days.d.ts.map +1 -1
- package/dist/cpsat/rules/min-consecutive-days.js +15 -2
- package/dist/cpsat/rules/min-consecutive-days.js.map +1 -1
- package/dist/cpsat/rules/min-days-week.d.ts +34 -0
- package/dist/cpsat/rules/min-days-week.d.ts.map +1 -0
- package/dist/cpsat/rules/min-days-week.js +84 -0
- package/dist/cpsat/rules/min-days-week.js.map +1 -0
- package/dist/cpsat/rules/min-hours-day.d.ts.map +1 -1
- package/dist/cpsat/rules/min-hours-day.js +15 -2
- package/dist/cpsat/rules/min-hours-day.js.map +1 -1
- package/dist/cpsat/rules/min-hours-week.d.ts.map +1 -1
- package/dist/cpsat/rules/min-hours-week.js +16 -2
- package/dist/cpsat/rules/min-hours-week.js.map +1 -1
- package/dist/cpsat/rules/min-rest-between-shifts.d.ts.map +1 -1
- package/dist/cpsat/rules/min-rest-between-shifts.js +72 -2
- package/dist/cpsat/rules/min-rest-between-shifts.js.map +1 -1
- package/dist/cpsat/rules/minimize-cost.d.ts.map +1 -1
- package/dist/cpsat/rules/minimize-cost.js +2 -23
- package/dist/cpsat/rules/minimize-cost.js.map +1 -1
- package/dist/cpsat/rules/must-assign.d.ts +49 -0
- package/dist/cpsat/rules/must-assign.d.ts.map +1 -0
- package/dist/cpsat/rules/must-assign.js +86 -0
- package/dist/cpsat/rules/must-assign.js.map +1 -0
- package/dist/cpsat/rules/overtime-daily-multiplier.d.ts.map +1 -1
- package/dist/cpsat/rules/overtime-daily-multiplier.js +1 -12
- package/dist/cpsat/rules/overtime-daily-multiplier.js.map +1 -1
- package/dist/cpsat/rules/overtime-daily-surcharge.d.ts.map +1 -1
- package/dist/cpsat/rules/overtime-daily-surcharge.js +1 -5
- package/dist/cpsat/rules/overtime-daily-surcharge.js.map +1 -1
- package/dist/cpsat/rules/overtime-tiered-multiplier.d.ts +5 -1
- package/dist/cpsat/rules/overtime-tiered-multiplier.d.ts.map +1 -1
- package/dist/cpsat/rules/overtime-tiered-multiplier.js +1 -12
- package/dist/cpsat/rules/overtime-tiered-multiplier.js.map +1 -1
- package/dist/cpsat/rules/overtime-weekly-multiplier.d.ts.map +1 -1
- package/dist/cpsat/rules/overtime-weekly-multiplier.js +1 -12
- package/dist/cpsat/rules/overtime-weekly-multiplier.js.map +1 -1
- package/dist/cpsat/rules/overtime-weekly-surcharge.d.ts.map +1 -1
- package/dist/cpsat/rules/overtime-weekly-surcharge.js +1 -5
- package/dist/cpsat/rules/overtime-weekly-surcharge.js.map +1 -1
- package/dist/cpsat/rules/registry.d.ts +28 -2
- package/dist/cpsat/rules/registry.d.ts.map +1 -1
- package/dist/cpsat/rules/registry.js +4 -1
- package/dist/cpsat/rules/registry.js.map +1 -1
- package/dist/cpsat/rules/resolver.js +2 -2
- package/dist/cpsat/rules/resolver.js.map +1 -1
- package/dist/cpsat/rules/rules.types.d.ts +3 -0
- package/dist/cpsat/rules/rules.types.d.ts.map +1 -1
- package/dist/cpsat/rules/scope.types.d.ts +18 -1
- package/dist/cpsat/rules/scope.types.d.ts.map +1 -1
- package/dist/cpsat/rules/scope.types.js +59 -16
- package/dist/cpsat/rules/scope.types.js.map +1 -1
- package/dist/cpsat/rules/time-cost-surcharge.d.ts.map +1 -1
- package/dist/cpsat/rules/time-cost-surcharge.js +2 -1
- package/dist/cpsat/rules/time-cost-surcharge.js.map +1 -1
- package/dist/cpsat/rules/time-off.d.ts.map +1 -1
- package/dist/cpsat/rules/time-off.js +6 -3
- package/dist/cpsat/rules/time-off.js.map +1 -1
- package/dist/cpsat/semantic-time.d.ts +44 -42
- package/dist/cpsat/semantic-time.d.ts.map +1 -1
- package/dist/cpsat/semantic-time.js +64 -46
- package/dist/cpsat/semantic-time.js.map +1 -1
- package/dist/cpsat/types.d.ts +37 -27
- package/dist/cpsat/types.d.ts.map +1 -1
- package/dist/cpsat/utils.d.ts.map +1 -1
- package/dist/cpsat/utils.js +7 -12
- package/dist/cpsat/utils.js.map +1 -1
- package/dist/cpsat/validation-reporter.d.ts +10 -7
- package/dist/cpsat/validation-reporter.d.ts.map +1 -1
- package/dist/cpsat/validation-reporter.js +44 -72
- package/dist/cpsat/validation-reporter.js.map +1 -1
- package/dist/cpsat/validation.types.d.ts +54 -44
- package/dist/cpsat/validation.types.d.ts.map +1 -1
- package/dist/cpsat/validation.types.js +15 -10
- package/dist/cpsat/validation.types.js.map +1 -1
- package/dist/datetime.utils.d.ts +3 -203
- package/dist/datetime.utils.d.ts.map +1 -1
- package/dist/datetime.utils.js +1 -288
- package/dist/datetime.utils.js.map +1 -1
- package/dist/index.d.ts +14 -83
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -83
- package/dist/index.js.map +1 -1
- package/dist/schedule/cost.d.ts +204 -0
- package/dist/schedule/cost.d.ts.map +1 -0
- package/dist/schedule/cost.js +187 -0
- package/dist/schedule/cost.js.map +1 -0
- package/dist/schedule/coverage.d.ts +85 -0
- package/dist/schedule/coverage.d.ts.map +1 -0
- package/dist/schedule/coverage.js +33 -0
- package/dist/schedule/coverage.js.map +1 -0
- package/dist/schedule/definition.d.ts +227 -0
- package/dist/schedule/definition.d.ts.map +1 -0
- package/dist/schedule/definition.js +659 -0
- package/dist/schedule/definition.js.map +1 -0
- package/dist/schedule/index.d.ts +67 -0
- package/dist/schedule/index.d.ts.map +1 -0
- package/dist/schedule/index.js +69 -0
- package/dist/schedule/index.js.map +1 -0
- package/dist/schedule/rules.d.ts +353 -0
- package/dist/schedule/rules.d.ts.map +1 -0
- package/dist/schedule/rules.js +352 -0
- package/dist/schedule/rules.js.map +1 -0
- package/dist/schedule/shift-patterns.d.ts +34 -0
- package/dist/schedule/shift-patterns.d.ts.map +1 -0
- package/dist/schedule/shift-patterns.js +41 -0
- package/dist/schedule/shift-patterns.js.map +1 -0
- package/dist/schedule/time-periods.d.ts +69 -0
- package/dist/schedule/time-periods.d.ts.map +1 -0
- package/dist/schedule/time-periods.js +91 -0
- package/dist/schedule/time-periods.js.map +1 -0
- package/dist/types.d.ts +14 -78
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +4 -9
- package/solver/src/solver/app.py +1 -1
- package/solver/src/solver/solver.py +7 -4
- package/src/client.ts +6 -8
- package/src/client.types.ts +9 -0
- package/src/cpsat/model-builder.ts +44 -35
- package/src/cpsat/response.ts +13 -1
- package/src/cpsat/rules/cost-utils.ts +25 -0
- package/src/cpsat/rules/day-cost-multiplier.ts +3 -14
- package/src/cpsat/rules/day-cost-surcharge.ts +3 -8
- package/src/cpsat/rules/index.ts +3 -0
- package/src/cpsat/rules/max-consecutive-days.ts +17 -0
- package/src/cpsat/rules/max-days-week.ts +143 -0
- package/src/cpsat/rules/max-hours-day.ts +21 -1
- package/src/cpsat/rules/max-hours-week.ts +22 -1
- package/src/cpsat/rules/max-shifts-day.ts +21 -1
- package/src/cpsat/rules/min-consecutive-days.ts +16 -1
- package/src/cpsat/rules/min-days-week.ts +120 -0
- package/src/cpsat/rules/min-hours-day.ts +16 -1
- package/src/cpsat/rules/min-hours-week.ts +17 -1
- package/src/cpsat/rules/min-rest-between-shifts.ts +92 -2
- package/src/cpsat/rules/minimize-cost.ts +2 -29
- package/src/cpsat/rules/must-assign.ts +108 -0
- package/src/cpsat/rules/overtime-daily-multiplier.ts +1 -12
- package/src/cpsat/rules/overtime-daily-surcharge.ts +1 -6
- package/src/cpsat/rules/overtime-tiered-multiplier.ts +6 -13
- package/src/cpsat/rules/overtime-weekly-multiplier.ts +1 -12
- package/src/cpsat/rules/overtime-weekly-surcharge.ts +1 -6
- package/src/cpsat/rules/registry.ts +8 -2
- package/src/cpsat/rules/resolver.ts +2 -2
- package/src/cpsat/rules/rules.types.ts +3 -0
- package/src/cpsat/rules/scope.types.ts +73 -20
- package/src/cpsat/rules/time-cost-surcharge.ts +2 -1
- package/src/cpsat/rules/time-off.ts +6 -2
- package/src/cpsat/semantic-time.ts +115 -91
- package/src/cpsat/types.ts +37 -27
- package/src/cpsat/utils.ts +8 -12
- package/src/cpsat/validation-reporter.ts +51 -82
- package/src/cpsat/validation.types.ts +72 -47
- package/src/datetime.utils.ts +3 -334
- package/src/index.ts +35 -107
- package/src/schedule/cost.ts +242 -0
- package/src/schedule/coverage.ts +135 -0
- package/src/schedule/definition.ts +958 -0
- package/src/schedule/index.ts +112 -0
- package/src/schedule/rules.ts +529 -0
- package/src/schedule/shift-patterns.ts +46 -0
- package/src/schedule/time-periods.ts +110 -0
- package/src/types.ts +14 -88
- package/dist/errors.d.ts +0 -12
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -17
- package/dist/errors.js.map +0 -1
- package/dist/llms.d.ts +0 -2
- package/dist/llms.d.ts.map +0 -1
- package/dist/llms.js +0 -3
- package/dist/llms.js.map +0 -1
- package/dist/schedule.d.ts +0 -724
- package/dist/schedule.d.ts.map +0 -1
- package/dist/schedule.js +0 -899
- package/dist/schedule.js.map +0 -1
- package/dist/validation.d.ts +0 -105
- package/dist/validation.d.ts.map +0 -1
- package/dist/validation.js +0 -130
- package/dist/validation.js.map +0 -1
- package/llms.txt +0 -925
- package/src/errors.ts +0 -17
- package/src/llms.ts +0 -3
- package/src/schedule.ts +0 -1419
- package/src/validation.ts +0 -188
package/dist/datetime.utils.js
CHANGED
|
@@ -1,36 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Converts a JavaScript Date to a CalendarDate
|
|
3
|
-
*/
|
|
4
|
-
export function dateToCalendarDate(date) {
|
|
5
|
-
return {
|
|
6
|
-
year: date.getFullYear(),
|
|
7
|
-
month: date.getMonth() + 1, // JS months are 0-indexed
|
|
8
|
-
day: date.getDate(),
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Converts a DateTime to a JavaScript Date
|
|
13
|
-
* Internal helper function
|
|
14
|
-
*/
|
|
15
|
-
export function dateTimeToDate(dateTime) {
|
|
16
|
-
return new Date(dateTime.year || 0, (dateTime.month || 1) - 1, dateTime.day || 1, dateTime.hours || 0, dateTime.minutes || 0, dateTime.seconds || 0);
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Compares two DateTimes
|
|
20
|
-
* Returns:
|
|
21
|
-
* -1 if dateTime1 < dateTime2
|
|
22
|
-
* 0 if dateTime1 = dateTime2
|
|
23
|
-
* 1 if dateTime1 > dateTime2
|
|
24
|
-
*/
|
|
25
|
-
export function compareDateTimes(dateTime1, dateTime2) {
|
|
26
|
-
const date1 = dateTimeToDate(dateTime1);
|
|
27
|
-
const date2 = dateTimeToDate(dateTime2);
|
|
28
|
-
if (date1 < date2)
|
|
29
|
-
return -1;
|
|
30
|
-
if (date1 > date2)
|
|
31
|
-
return 1;
|
|
32
|
-
return 0;
|
|
33
|
-
}
|
|
34
1
|
export const DAY_OF_WEEK_MAP = {
|
|
35
2
|
sunday: 0, // JavaScript Date week starts on Sunday
|
|
36
3
|
monday: 1,
|
|
@@ -50,267 +17,13 @@ const DAY_NAMES = [
|
|
|
50
17
|
"saturday",
|
|
51
18
|
];
|
|
52
19
|
/**
|
|
53
|
-
* Helper to get the day of week name from a Date (
|
|
54
|
-
*/
|
|
55
|
-
export function toDayOfWeek(date) {
|
|
56
|
-
// getDay() always returns 0-6
|
|
57
|
-
return DAY_NAMES[date.getDay()];
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Helper to get the day of week name from a Date (UTC)
|
|
20
|
+
* Helper to get the day of week name from a Date (UTC).
|
|
61
21
|
* Use this when working with date strings like "2026-01-10" that are timezone-agnostic.
|
|
62
22
|
*/
|
|
63
23
|
export function toDayOfWeekUTC(date) {
|
|
64
24
|
// getUTCDay() always returns 0-6
|
|
65
25
|
return DAY_NAMES[date.getUTCDay()];
|
|
66
26
|
}
|
|
67
|
-
/**
|
|
68
|
-
* Formats a date as YYYY-MM-DD string
|
|
69
|
-
*/
|
|
70
|
-
export function formatDateString(date) {
|
|
71
|
-
const year = date.getFullYear();
|
|
72
|
-
const month = (date.getMonth() + 1).toString().padStart(2, "0");
|
|
73
|
-
const day = date.getDate().toString().padStart(2, "0");
|
|
74
|
-
return `${year}-${month}-${day}`;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Generates an array of day strings (YYYY-MM-DD) from a time horizon.
|
|
78
|
-
*
|
|
79
|
-
* @param horizon - The time horizon with start (inclusive) and end (inclusive) dates
|
|
80
|
-
* @returns Array of day strings in YYYY-MM-DD format
|
|
81
|
-
*
|
|
82
|
-
* @example
|
|
83
|
-
* ```typescript
|
|
84
|
-
* const days = generateDays({
|
|
85
|
-
* start: new Date('2025-01-01'),
|
|
86
|
-
* end: new Date('2025-01-04')
|
|
87
|
-
* });
|
|
88
|
-
* // Returns: ["2025-01-01", "2025-01-02", "2025-01-03", "2025-01-04"]
|
|
89
|
-
* ```
|
|
90
|
-
*/
|
|
91
|
-
export function generateDays(horizon) {
|
|
92
|
-
const days = [];
|
|
93
|
-
const current = new Date(horizon.start);
|
|
94
|
-
while (current <= horizon.end) {
|
|
95
|
-
days.push(formatDateString(current));
|
|
96
|
-
current.setDate(current.getDate() + 1);
|
|
97
|
-
}
|
|
98
|
-
return days;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Splits a time period into consecutive day ranges.
|
|
102
|
-
*
|
|
103
|
-
* Each range represents a single calendar day within the period from start to end.
|
|
104
|
-
* This is useful for rules that need to apply constraints on a per-day basis,
|
|
105
|
-
* such as maximum or minimum hours per day.
|
|
106
|
-
*
|
|
107
|
-
* @param start - The start date of the period (inclusive)
|
|
108
|
-
* @param end - The end date of the period (exclusive)
|
|
109
|
-
* @returns An array of [startDate, endDate] tuples, where each tuple represents
|
|
110
|
-
* a single day. The last range's end date will be the provided end date.
|
|
111
|
-
*
|
|
112
|
-
* @example
|
|
113
|
-
* ```typescript
|
|
114
|
-
* const ranges = splitPeriodIntoDays({
|
|
115
|
-
* start: new Date('2025-01-01'),
|
|
116
|
-
* end: new Date('2025-01-03')
|
|
117
|
-
* });
|
|
118
|
-
* // Returns:
|
|
119
|
-
* // [
|
|
120
|
-
* // [Date('2025-01-01'), Date('2025-01-02')],
|
|
121
|
-
* // [Date('2025-01-02'), Date('2025-01-03')]
|
|
122
|
-
* // ]
|
|
123
|
-
* ```
|
|
124
|
-
*/
|
|
125
|
-
export function splitPeriodIntoDays({ start, end }) {
|
|
126
|
-
const ranges = [];
|
|
127
|
-
let leftBound = new Date(start);
|
|
128
|
-
let done = false;
|
|
129
|
-
// Loop through each day
|
|
130
|
-
leftBound = new Date(start);
|
|
131
|
-
while (!done) {
|
|
132
|
-
// Create next day date
|
|
133
|
-
let rightBound = new Date(leftBound);
|
|
134
|
-
rightBound.setDate(rightBound.getDate() + 1);
|
|
135
|
-
if (rightBound >= end) {
|
|
136
|
-
rightBound = end;
|
|
137
|
-
done = true;
|
|
138
|
-
}
|
|
139
|
-
ranges.push([leftBound, rightBound]);
|
|
140
|
-
leftBound = rightBound;
|
|
141
|
-
}
|
|
142
|
-
return ranges;
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Splits a time period into consecutive week ranges.
|
|
146
|
-
*
|
|
147
|
-
* Each range represents a week period starting on the specified day of the week.
|
|
148
|
-
* This is useful for rules that need to apply constraints on a per-week basis,
|
|
149
|
-
* such as maximum or minimum hours per week.
|
|
150
|
-
*
|
|
151
|
-
* The first range starts at the provided start date (not necessarily on weekStartsOn).
|
|
152
|
-
* Subsequent ranges align to the weekStartsOn day. The last range's end date will be
|
|
153
|
-
* the provided end date.
|
|
154
|
-
*
|
|
155
|
-
* @param start - The start date of the period (inclusive)
|
|
156
|
-
* @param end - The end date of the period (exclusive)
|
|
157
|
-
* @param weekStartsOn - The day of the week that weeks start on (e.g., "monday", "sunday")
|
|
158
|
-
* @returns An array of [startDate, endDate] tuples, where each tuple represents
|
|
159
|
-
* a week period aligned to the specified week start day.
|
|
160
|
-
*
|
|
161
|
-
* @example
|
|
162
|
-
* ```typescript
|
|
163
|
-
* const ranges = splitPeriodIntoWeeks({
|
|
164
|
-
* start: new Date('2025-01-01'), // Wednesday
|
|
165
|
-
* end: new Date('2025-01-15'),
|
|
166
|
-
* weekStartsOn: 'monday'
|
|
167
|
-
* });
|
|
168
|
-
* // Returns ranges starting from Jan 1 (Wed), then aligning to Mondays:
|
|
169
|
-
* // [
|
|
170
|
-
* // [Date('2025-01-01 Wed'), Date('2025-01-06 Mon')],
|
|
171
|
-
* // [Date('2025-01-06 Mon'), Date('2025-01-13 Mon')],
|
|
172
|
-
* // [Date('2025-01-13 Mon'), Date('2025-01-15 Wed')]
|
|
173
|
-
* // ]
|
|
174
|
-
* ```
|
|
175
|
-
*/
|
|
176
|
-
export function splitPeriodIntoWeeks({ start, end, weekStartsOn, }) {
|
|
177
|
-
const DAYS_OF_WEEK = [
|
|
178
|
-
"sunday",
|
|
179
|
-
"monday",
|
|
180
|
-
"tuesday",
|
|
181
|
-
"wednesday",
|
|
182
|
-
"thursday",
|
|
183
|
-
"friday",
|
|
184
|
-
"saturday",
|
|
185
|
-
];
|
|
186
|
-
const ranges = [];
|
|
187
|
-
let leftBound = new Date(start);
|
|
188
|
-
let done = false;
|
|
189
|
-
const startDayIndex = DAYS_OF_WEEK.indexOf(weekStartsOn);
|
|
190
|
-
// Create weekly ranges
|
|
191
|
-
while (!done) {
|
|
192
|
-
const dayOfWeek = leftBound.getDay(); // 0 = Sunday, 1 = Monday, etc.
|
|
193
|
-
const daysToNextWeek = (7 - ((dayOfWeek - startDayIndex) % 7)) % 7;
|
|
194
|
-
const daysToAdd = daysToNextWeek === 0 ? 7 : daysToNextWeek;
|
|
195
|
-
let rightBound = new Date(leftBound);
|
|
196
|
-
rightBound.setDate(rightBound.getDate() + daysToAdd);
|
|
197
|
-
if (rightBound >= end) {
|
|
198
|
-
rightBound = end;
|
|
199
|
-
done = true;
|
|
200
|
-
}
|
|
201
|
-
ranges.push([leftBound, rightBound]);
|
|
202
|
-
leftBound = rightBound;
|
|
203
|
-
}
|
|
204
|
-
return ranges;
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Checks if two DateTime ranges overlap in both date and time.
|
|
208
|
-
* Ranges overlap if they share any moment in time.
|
|
209
|
-
*
|
|
210
|
-
* Two ranges overlap if: range1.start < range2.end AND range2.start < range1.end
|
|
211
|
-
*
|
|
212
|
-
* @param range1 First time range with start (inclusive) and end (exclusive)
|
|
213
|
-
* @param range2 Second time range with start (inclusive) and end (exclusive)
|
|
214
|
-
* @returns true if ranges overlap, false otherwise
|
|
215
|
-
*
|
|
216
|
-
* @example
|
|
217
|
-
* ```typescript
|
|
218
|
-
* // Same day, overlapping times (9-17 overlaps with 12-20)
|
|
219
|
-
* dateTimeRangesOverlap(
|
|
220
|
-
* {
|
|
221
|
-
* start: { year: 2025, month: 6, day: 1, hours: 9, minutes: 0 },
|
|
222
|
-
* end: { year: 2025, month: 6, day: 1, hours: 17, minutes: 0 }
|
|
223
|
-
* },
|
|
224
|
-
* {
|
|
225
|
-
* start: { year: 2025, month: 6, day: 1, hours: 12, minutes: 0 },
|
|
226
|
-
* end: { year: 2025, month: 6, day: 1, hours: 20, minutes: 0 }
|
|
227
|
-
* }
|
|
228
|
-
* ); // true
|
|
229
|
-
*
|
|
230
|
-
* // Different days - no overlap
|
|
231
|
-
* dateTimeRangesOverlap(
|
|
232
|
-
* {
|
|
233
|
-
* start: { year: 2025, month: 6, day: 1, hours: 9, minutes: 0 },
|
|
234
|
-
* end: { year: 2025, month: 6, day: 1, hours: 17, minutes: 0 }
|
|
235
|
-
* },
|
|
236
|
-
* {
|
|
237
|
-
* start: { year: 2025, month: 6, day: 2, hours: 9, minutes: 0 },
|
|
238
|
-
* end: { year: 2025, month: 6, day: 2, hours: 17, minutes: 0 }
|
|
239
|
-
* }
|
|
240
|
-
* ); // false
|
|
241
|
-
*
|
|
242
|
-
* // Works naturally with Shift objects
|
|
243
|
-
* dateTimeRangesOverlap(
|
|
244
|
-
* { start: shift1.startDateTime, end: shift1.endDateTime },
|
|
245
|
-
* { start: shift2.startDateTime, end: shift2.endDateTime }
|
|
246
|
-
* );
|
|
247
|
-
* ```
|
|
248
|
-
*/
|
|
249
|
-
export function dateTimeRangesOverlap(range1, range2) {
|
|
250
|
-
// Use existing compareDateTimes for temporal comparison
|
|
251
|
-
// Ranges overlap if: start1 < end2 AND start2 < end1
|
|
252
|
-
return (compareDateTimes(range1.start, range2.end) < 0 && compareDateTimes(range2.start, range1.end) < 0);
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* Calculates the number of complete days between two dates
|
|
256
|
-
* @param start The start date
|
|
257
|
-
* @param end The end date
|
|
258
|
-
* @returns Number of complete days from start to end (can be negative if end < start)
|
|
259
|
-
*
|
|
260
|
-
* @example
|
|
261
|
-
* ```typescript
|
|
262
|
-
* daysBetween(new Date('2025-01-01'), new Date('2025-01-05')); // 4
|
|
263
|
-
* ```
|
|
264
|
-
*/
|
|
265
|
-
export function daysBetween(start, end) {
|
|
266
|
-
const ms = end.getTime() - start.getTime();
|
|
267
|
-
return Math.floor(ms / (1000 * 60 * 60 * 24));
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* Adds a number of minutes to a base date and returns a DateTime.
|
|
271
|
-
* Treats the base date as a reference point (typically midnight of horizon start),
|
|
272
|
-
* and the minutes parameter as absolute minutes from that point.
|
|
273
|
-
*
|
|
274
|
-
* @param baseDate The starting date (used as reference point)
|
|
275
|
-
* @param minutes Absolute minutes from the base date
|
|
276
|
-
* @returns DateTime representing the result
|
|
277
|
-
*
|
|
278
|
-
* @example
|
|
279
|
-
* ```typescript
|
|
280
|
-
* // Add 90 minutes from midnight
|
|
281
|
-
* addMinutesToDate(new Date('2025-01-01'), 90);
|
|
282
|
-
* // Returns: { year: 2025, month: 1, day: 1, hours: 1, minutes: 30 }
|
|
283
|
-
*
|
|
284
|
-
* // Add 1500 minutes (spans to next day)
|
|
285
|
-
* addMinutesToDate(new Date('2025-01-01'), 1500);
|
|
286
|
-
* // Returns: { year: 2025, month: 1, day: 2, hours: 1, minutes: 0 }
|
|
287
|
-
* ```
|
|
288
|
-
*/
|
|
289
|
-
export function addMinutesToDate(baseDate, minutes) {
|
|
290
|
-
const days = Math.floor(minutes / 1440);
|
|
291
|
-
const minutesInDay = minutes % 1440;
|
|
292
|
-
const targetDate = new Date(baseDate);
|
|
293
|
-
targetDate.setDate(targetDate.getDate() + days);
|
|
294
|
-
return {
|
|
295
|
-
year: targetDate.getFullYear(),
|
|
296
|
-
month: targetDate.getMonth() + 1,
|
|
297
|
-
day: targetDate.getDate(),
|
|
298
|
-
hours: Math.floor(minutesInDay / 60),
|
|
299
|
-
minutes: minutesInDay % 60,
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* Returns the points where a range should be split, filtered to within [start, end).
|
|
304
|
-
* Always includes range start. Sorted ascending.
|
|
305
|
-
*/
|
|
306
|
-
export function splitPoints([start, end], splitAt) {
|
|
307
|
-
const points = new Set([start]);
|
|
308
|
-
for (const p of splitAt) {
|
|
309
|
-
if (p > start && p < end)
|
|
310
|
-
points.add(p);
|
|
311
|
-
}
|
|
312
|
-
return [...points].toSorted((a, b) => a - b);
|
|
313
|
-
}
|
|
314
27
|
/**
|
|
315
28
|
* Computes the list of day strings (YYYY-MM-DD) from a SchedulingPeriod.
|
|
316
29
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datetime.utils.js","sourceRoot":"","sources":["../src/datetime.utils.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"datetime.utils.js","sourceRoot":"","sources":["../src/datetime.utils.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAA8B;IACxD,MAAM,EAAE,CAAC,EAAE,wCAAwC;IACnD,MAAM,EAAE,CAAC;IACT,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,CAAC;IACZ,QAAQ,EAAE,CAAC;IACX,MAAM,EAAE,CAAC;IACT,QAAQ,EAAE,CAAC;CACZ,CAAC;AAEF,MAAM,SAAS,GAAG;IAChB,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,WAAW;IACX,UAAU;IACV,QAAQ;IACR,UAAU;CACF,CAAC;AAEX;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAU;IACvC,iCAAiC;IACjC,OAAO,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,CAAc,CAAC;AAClD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAwB;IAC5D,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAC/C,MAAM,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1D,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEnD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,SAAS,CAAC,KAAK,YAAY,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,GAAG,SAAS,CAAC,GAAG,YAAY,CAAC,CAAC;IACvD,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;IACpC,OAAO,OAAO,IAAI,OAAO,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACtE,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC7D,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;QAEpC,IAAI,CAAC,CAAC,WAAW,IAAI,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACvF,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;QAED,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Scheduling library powered by constraint programming (CP-SAT).
|
|
3
3
|
*
|
|
4
|
-
* Define teams, shifts, coverage, and rules declaratively. dabke compiles
|
|
5
|
-
* them into a constraint model and solves for an optimized schedule.
|
|
6
|
-
*
|
|
7
4
|
* @remarks
|
|
8
5
|
* ## Core Concepts
|
|
9
6
|
*
|
|
10
|
-
* **Schedule
|
|
7
|
+
* **Schedule**: The primary API. Small, composable functions
|
|
11
8
|
* ({@link time}, {@link cover}, {@link shift}, rule functions) produce a
|
|
12
|
-
* complete scheduling configuration via {@link
|
|
9
|
+
* complete scheduling configuration via {@link schedule}. Each concept
|
|
13
10
|
* is a single function call with full type safety.
|
|
14
11
|
*
|
|
15
12
|
* **Times vs Shift Patterns**: These are two distinct concepts.
|
|
@@ -28,97 +25,31 @@
|
|
|
28
25
|
* - Scoping: apply rules globally, per person, per role, per skill, or per time period
|
|
29
26
|
* - Priority: `MANDATORY` (hard constraint) vs `LOW`/`MEDIUM`/`HIGH` (soft preferences)
|
|
30
27
|
*
|
|
31
|
-
* **Solving**: {@link
|
|
32
|
-
*
|
|
33
|
-
* {@link
|
|
34
|
-
* {@link HttpSolverClient} sends it to the CP-SAT solver.
|
|
35
|
-
*
|
|
36
|
-
* @example Define a schedule
|
|
37
|
-
* ```typescript
|
|
38
|
-
* import {
|
|
39
|
-
* defineSchedule, t, time, cover, shift,
|
|
40
|
-
* maxHoursPerWeek, minRestBetweenShifts, timeOff,
|
|
41
|
-
* weekdays, weekend,
|
|
42
|
-
* } from "dabke";
|
|
43
|
-
*
|
|
44
|
-
* const schedule = defineSchedule({
|
|
45
|
-
* roles: ["nurse", "doctor"],
|
|
46
|
-
* skills: ["charge_nurse"],
|
|
47
|
-
*
|
|
48
|
-
* times: {
|
|
49
|
-
* morning_round: time({ startTime: t(7), endTime: t(9) }),
|
|
50
|
-
* day_ward: time({ startTime: t(7), endTime: t(15) }),
|
|
51
|
-
* night_ward: time({ startTime: t(23), endTime: t(7) }),
|
|
52
|
-
* },
|
|
53
|
-
*
|
|
54
|
-
* coverage: [
|
|
55
|
-
* cover("morning_round", "doctor", 1),
|
|
56
|
-
* cover("day_ward", "nurse", 3, { dayOfWeek: weekdays }),
|
|
57
|
-
* cover("day_ward", "nurse", 2, { dayOfWeek: weekend }),
|
|
58
|
-
* cover("night_ward", "nurse", 2),
|
|
59
|
-
* cover("night_ward", "charge_nurse", 1),
|
|
60
|
-
* ],
|
|
61
|
-
*
|
|
62
|
-
* shiftPatterns: [
|
|
63
|
-
* shift("day", t(7), t(15)),
|
|
64
|
-
* shift("night", t(23), t(7)),
|
|
65
|
-
* ],
|
|
66
|
-
*
|
|
67
|
-
* rules: [
|
|
68
|
-
* maxHoursPerWeek(40),
|
|
69
|
-
* minRestBetweenShifts(11),
|
|
70
|
-
* timeOff({ appliesTo: "alice", dayOfWeek: weekend }),
|
|
71
|
-
* ],
|
|
72
|
-
* });
|
|
73
|
-
* ```
|
|
74
|
-
*
|
|
75
|
-
* @example Solve a schedule
|
|
76
|
-
* ```typescript
|
|
77
|
-
* import { ModelBuilder, HttpSolverClient, parseSolverResponse } from "dabke";
|
|
78
|
-
*
|
|
79
|
-
* const config = schedule.createSchedulerConfig({
|
|
80
|
-
* schedulingPeriod: {
|
|
81
|
-
* dateRange: { start: "2026-02-09", end: "2026-02-15" },
|
|
82
|
-
* },
|
|
83
|
-
* members: [
|
|
84
|
-
* { id: "alice", roles: ["nurse"], skills: ["charge_nurse"] },
|
|
85
|
-
* { id: "bob", roles: ["nurse"] },
|
|
86
|
-
* { id: "carol", roles: ["doctor"] },
|
|
87
|
-
* ],
|
|
88
|
-
* });
|
|
89
|
-
*
|
|
90
|
-
* const builder = new ModelBuilder(config);
|
|
91
|
-
* const { request, canSolve, validation } = builder.compile();
|
|
92
|
-
* if (canSolve) {
|
|
93
|
-
* const client = new HttpSolverClient(fetch, "http://localhost:8080");
|
|
94
|
-
* const response = await client.solve(request);
|
|
95
|
-
* const result = parseSolverResponse(response);
|
|
96
|
-
* }
|
|
97
|
-
* ```
|
|
28
|
+
* **Solving**: {@link Schedule.compile} compiles the config into a
|
|
29
|
+
* solver request; {@link Schedule.solve} sends it to the CP-SAT solver
|
|
30
|
+
* and returns a {@link SolveResult}.
|
|
98
31
|
*
|
|
99
32
|
* @packageDocumentation
|
|
100
33
|
*/
|
|
101
|
-
export type { TimeOfDay, DayOfWeek,
|
|
34
|
+
export type { TimeOfDay, DayOfWeek, SchedulingPeriod } from "./types.js";
|
|
102
35
|
export { DayOfWeekSchema } from "./types.js";
|
|
103
|
-
export { dateTimeToDate } from "./datetime.utils.js";
|
|
104
|
-
export { ORSchedulingError } from "./errors.js";
|
|
105
36
|
export { HttpSolverClient } from "./client.js";
|
|
106
37
|
export type { SolverClient, SolverRequest, SolverResponse, SolverStatus, SoftConstraintViolation, FetcherLike, } from "./client.types.js";
|
|
107
38
|
export { SOLVER_STATUS } from "./client.types.js";
|
|
108
39
|
export { SolverRequestSchema, SolverResponseSchema, SolverStatusSchema } from "./client.schemas.js";
|
|
109
40
|
export { ModelBuilder } from "./cpsat/model-builder.js";
|
|
110
|
-
export type { ModelBuilderConfig, CompilationResult, CompilationRule, RuleValidationContext,
|
|
41
|
+
export type { ModelBuilderConfig, CompilationResult, CompilationRule, RuleValidationContext, CostEntry, CostContribution, } from "./cpsat/model-builder.js";
|
|
111
42
|
export { parseSolverResponse, resolveAssignments } from "./cpsat/response.js";
|
|
112
43
|
export type { ShiftAssignment, ResolvedShiftAssignment, SolverResult } from "./cpsat/response.js";
|
|
113
|
-
export
|
|
44
|
+
export { calculateScheduleCost, COST_CATEGORY } from "./cpsat/cost.js";
|
|
45
|
+
export type { CostBreakdown, MemberCostDetail, CostCalculationConfig } from "./cpsat/cost.js";
|
|
46
|
+
export type { CpsatRuleConfigEntry, CpsatRuleFactories, CreateCpsatRuleFunction, } from "./cpsat/rules/rules.types.js";
|
|
114
47
|
export type { RecurringPeriod } from "./cpsat/rules/scope.types.js";
|
|
115
48
|
export type { OvertimeTier } from "./cpsat/rules/overtime-tiered-multiplier.js";
|
|
116
|
-
export type { HourlyPay, SalariedPay, SchedulingMember, ShiftPattern,
|
|
49
|
+
export type { HourlyPay, SalariedPay, SchedulingMember, ShiftPattern, Priority, } from "./cpsat/types.js";
|
|
117
50
|
export { OBJECTIVE_WEIGHTS } from "./cpsat/utils.js";
|
|
118
|
-
export type {
|
|
119
|
-
export type { ScheduleValidation, ScheduleError, ScheduleViolation, SchedulePassed, CoverageError, CoverageViolation, CoveragePassed, RuleError, RuleViolation, RulePassed, SolverError, ValidationContext, ValidationSummary, GroupKey, } from "./cpsat/validation.types.js";
|
|
51
|
+
export type { ValidationGroup, ScheduleValidation, ScheduleError, CoverageError, RuleError, SolverError, ScheduleViolation, CoverageViolation, RuleViolation, SchedulePassed, CoveragePassed, RulePassed, ValidationSummary, } from "./cpsat/validation.types.js";
|
|
120
52
|
export { summarizeValidation } from "./cpsat/validation-reporter.js";
|
|
121
|
-
export {
|
|
122
|
-
export {
|
|
123
|
-
export type { CoverageEntry, CoverageOptions, CoverageVariant, RuleEntry, RuleOptions, EntityOnlyRuleOptions, TimeOffOptions, AssignTogetherOptions, CostRuleOptions, RuntimeArgs, ScheduleDefinition, ScheduleConfig, } from "./schedule.js";
|
|
53
|
+
export { schedule, partialSchedule, Schedule, t, time, cover, shift, maxHoursPerDay, maxHoursPerWeek, minHoursPerDay, minHoursPerWeek, maxDaysPerWeek, minDaysPerWeek, maxShiftsPerDay, maxConsecutiveDays, minConsecutiveDays, minRestBetweenShifts, mustAssign, preference, preferLocation, timeOff, assignTogether, defineRule, minimizeCost, dayMultiplier, daySurcharge, timeSurcharge, overtimeMultiplier, overtimeSurcharge, dailyOvertimeMultiplier, dailyOvertimeSurcharge, tieredOvertimeMultiplier, weekdays, weekend, } from "./schedule/index.js";
|
|
54
|
+
export type { CoverageEntry, CoverageOptions, CoverageVariant, RuleEntry, RuleResolveContext, RuleOptions, EntityOnlyRuleOptions, TimeOffOptions, AssignTogetherOptions, CostRuleOptions, ScheduleConfig, SolveResult, SolveStatus, SolveOptions, } from "./schedule/index.js";
|
|
124
55
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAMH,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEzE,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAM7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,YAAY,EACV,YAAY,EACZ,aAAa,EACb,cAAc,EACd,YAAY,EACZ,uBAAuB,EACvB,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAMpG,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,SAAS,EACT,gBAAgB,GACjB,MAAM,0BAA0B,CAAC;AAMlC,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9E,YAAY,EAAE,eAAe,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAMlG,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEvE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAM9F,YAAY,EACV,oBAAoB,EACpB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,8BAA8B,CAAC;AAEtC,YAAY,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEpE,YAAY,EAAE,YAAY,EAAE,MAAM,6CAA6C,CAAC;AAMhF,YAAY,EACV,SAAS,EACT,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,QAAQ,GACT,MAAM,kBAAkB,CAAC;AAM1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAMrD,YAAY,EACV,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,SAAS,EACT,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,cAAc,EACd,UAAU,EACV,iBAAiB,GAClB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAMrE,OAAO,EACL,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,CAAC,EACD,IAAI,EACJ,KAAK,EACL,KAAK,EACL,cAAc,EACd,eAAe,EACf,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,cAAc,EACd,OAAO,EACP,cAAc,EACd,UAAU,EACV,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,EACxB,QAAQ,EACR,OAAO,GACR,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EACV,aAAa,EACb,eAAe,EACf,eAAe,EACf,SAAS,EACT,kBAAkB,EAClB,WAAW,EACX,qBAAqB,EACrB,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,WAAW,EACX,WAAW,EACX,YAAY,GACb,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Scheduling library powered by constraint programming (CP-SAT).
|
|
3
3
|
*
|
|
4
|
-
* Define teams, shifts, coverage, and rules declaratively. dabke compiles
|
|
5
|
-
* them into a constraint model and solves for an optimized schedule.
|
|
6
|
-
*
|
|
7
4
|
* @remarks
|
|
8
5
|
* ## Core Concepts
|
|
9
6
|
*
|
|
10
|
-
* **Schedule
|
|
7
|
+
* **Schedule**: The primary API. Small, composable functions
|
|
11
8
|
* ({@link time}, {@link cover}, {@link shift}, rule functions) produce a
|
|
12
|
-
* complete scheduling configuration via {@link
|
|
9
|
+
* complete scheduling configuration via {@link schedule}. Each concept
|
|
13
10
|
* is a single function call with full type safety.
|
|
14
11
|
*
|
|
15
12
|
* **Times vs Shift Patterns**: These are two distinct concepts.
|
|
@@ -28,86 +25,14 @@
|
|
|
28
25
|
* - Scoping: apply rules globally, per person, per role, per skill, or per time period
|
|
29
26
|
* - Priority: `MANDATORY` (hard constraint) vs `LOW`/`MEDIUM`/`HIGH` (soft preferences)
|
|
30
27
|
*
|
|
31
|
-
* **Solving**: {@link
|
|
32
|
-
*
|
|
33
|
-
* {@link
|
|
34
|
-
* {@link HttpSolverClient} sends it to the CP-SAT solver.
|
|
35
|
-
*
|
|
36
|
-
* @example Define a schedule
|
|
37
|
-
* ```typescript
|
|
38
|
-
* import {
|
|
39
|
-
* defineSchedule, t, time, cover, shift,
|
|
40
|
-
* maxHoursPerWeek, minRestBetweenShifts, timeOff,
|
|
41
|
-
* weekdays, weekend,
|
|
42
|
-
* } from "dabke";
|
|
43
|
-
*
|
|
44
|
-
* const schedule = defineSchedule({
|
|
45
|
-
* roles: ["nurse", "doctor"],
|
|
46
|
-
* skills: ["charge_nurse"],
|
|
47
|
-
*
|
|
48
|
-
* times: {
|
|
49
|
-
* morning_round: time({ startTime: t(7), endTime: t(9) }),
|
|
50
|
-
* day_ward: time({ startTime: t(7), endTime: t(15) }),
|
|
51
|
-
* night_ward: time({ startTime: t(23), endTime: t(7) }),
|
|
52
|
-
* },
|
|
53
|
-
*
|
|
54
|
-
* coverage: [
|
|
55
|
-
* cover("morning_round", "doctor", 1),
|
|
56
|
-
* cover("day_ward", "nurse", 3, { dayOfWeek: weekdays }),
|
|
57
|
-
* cover("day_ward", "nurse", 2, { dayOfWeek: weekend }),
|
|
58
|
-
* cover("night_ward", "nurse", 2),
|
|
59
|
-
* cover("night_ward", "charge_nurse", 1),
|
|
60
|
-
* ],
|
|
61
|
-
*
|
|
62
|
-
* shiftPatterns: [
|
|
63
|
-
* shift("day", t(7), t(15)),
|
|
64
|
-
* shift("night", t(23), t(7)),
|
|
65
|
-
* ],
|
|
66
|
-
*
|
|
67
|
-
* rules: [
|
|
68
|
-
* maxHoursPerWeek(40),
|
|
69
|
-
* minRestBetweenShifts(11),
|
|
70
|
-
* timeOff({ appliesTo: "alice", dayOfWeek: weekend }),
|
|
71
|
-
* ],
|
|
72
|
-
* });
|
|
73
|
-
* ```
|
|
74
|
-
*
|
|
75
|
-
* @example Solve a schedule
|
|
76
|
-
* ```typescript
|
|
77
|
-
* import { ModelBuilder, HttpSolverClient, parseSolverResponse } from "dabke";
|
|
78
|
-
*
|
|
79
|
-
* const config = schedule.createSchedulerConfig({
|
|
80
|
-
* schedulingPeriod: {
|
|
81
|
-
* dateRange: { start: "2026-02-09", end: "2026-02-15" },
|
|
82
|
-
* },
|
|
83
|
-
* members: [
|
|
84
|
-
* { id: "alice", roles: ["nurse"], skills: ["charge_nurse"] },
|
|
85
|
-
* { id: "bob", roles: ["nurse"] },
|
|
86
|
-
* { id: "carol", roles: ["doctor"] },
|
|
87
|
-
* ],
|
|
88
|
-
* });
|
|
89
|
-
*
|
|
90
|
-
* const builder = new ModelBuilder(config);
|
|
91
|
-
* const { request, canSolve, validation } = builder.compile();
|
|
92
|
-
* if (canSolve) {
|
|
93
|
-
* const client = new HttpSolverClient(fetch, "http://localhost:8080");
|
|
94
|
-
* const response = await client.solve(request);
|
|
95
|
-
* const result = parseSolverResponse(response);
|
|
96
|
-
* }
|
|
97
|
-
* ```
|
|
28
|
+
* **Solving**: {@link Schedule.compile} compiles the config into a
|
|
29
|
+
* solver request; {@link Schedule.solve} sends it to the CP-SAT solver
|
|
30
|
+
* and returns a {@link SolveResult}.
|
|
98
31
|
*
|
|
99
32
|
* @packageDocumentation
|
|
100
33
|
*/
|
|
101
34
|
export { DayOfWeekSchema } from "./types.js";
|
|
102
35
|
// ============================================================================
|
|
103
|
-
// Date/time utilities
|
|
104
|
-
// ============================================================================
|
|
105
|
-
export { dateTimeToDate } from "./datetime.utils.js";
|
|
106
|
-
// ============================================================================
|
|
107
|
-
// Errors
|
|
108
|
-
// ============================================================================
|
|
109
|
-
export { ORSchedulingError } from "./errors.js";
|
|
110
|
-
// ============================================================================
|
|
111
36
|
// Solver client
|
|
112
37
|
// ============================================================================
|
|
113
38
|
export { HttpSolverClient } from "./client.js";
|
|
@@ -122,13 +47,16 @@ export { ModelBuilder } from "./cpsat/model-builder.js";
|
|
|
122
47
|
// ============================================================================
|
|
123
48
|
export { parseSolverResponse, resolveAssignments } from "./cpsat/response.js";
|
|
124
49
|
// ============================================================================
|
|
50
|
+
// Cost calculation
|
|
51
|
+
// ============================================================================
|
|
52
|
+
export { calculateScheduleCost, COST_CATEGORY } from "./cpsat/cost.js";
|
|
53
|
+
// ============================================================================
|
|
125
54
|
// Constants
|
|
126
55
|
// ============================================================================
|
|
127
56
|
export { OBJECTIVE_WEIGHTS } from "./cpsat/utils.js";
|
|
128
57
|
export { summarizeValidation } from "./cpsat/validation-reporter.js";
|
|
129
|
-
export { groupKey } from "./cpsat/validation.types.js";
|
|
130
58
|
// ============================================================================
|
|
131
|
-
// Schedule
|
|
59
|
+
// Schedule API
|
|
132
60
|
// ============================================================================
|
|
133
|
-
export {
|
|
61
|
+
export { schedule, partialSchedule, Schedule, t, time, cover, shift, maxHoursPerDay, maxHoursPerWeek, minHoursPerDay, minHoursPerWeek, maxDaysPerWeek, minDaysPerWeek, maxShiftsPerDay, maxConsecutiveDays, minConsecutiveDays, minRestBetweenShifts, mustAssign, preference, preferLocation, timeOff, assignTogether, defineRule, minimizeCost, dayMultiplier, daySurcharge, timeSurcharge, overtimeMultiplier, overtimeSurcharge, dailyOvertimeMultiplier, dailyOvertimeSurcharge, tieredOvertimeMultiplier, weekdays, weekend, } from "./schedule/index.js";
|
|
134
62
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAQH,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAE/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAW/C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEpG,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAE/E,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAWxD,+EAA+E;AAC/E,0BAA0B;AAC1B,+EAA+E;AAE/E,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAI9E,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AA8BvE,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAsBrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAErE,+EAA+E;AAC/E,eAAe;AACf,+EAA+E;AAE/E,OAAO,EACL,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,CAAC,EACD,IAAI,EACJ,KAAK,EACL,KAAK,EACL,cAAc,EACd,eAAe,EACf,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,cAAc,EACd,OAAO,EACP,cAAc,EACd,UAAU,EACV,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,EACxB,QAAQ,EACR,OAAO,GACR,MAAM,qBAAqB,CAAC"}
|