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.
Files changed (231) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +45 -27
  3. package/dist/client.d.ts +20 -2
  4. package/dist/client.d.ts.map +1 -1
  5. package/dist/client.js +4 -1
  6. package/dist/client.js.map +1 -1
  7. package/dist/client.types.d.ts +9 -0
  8. package/dist/client.types.d.ts.map +1 -1
  9. package/dist/client.types.js +1 -0
  10. package/dist/client.types.js.map +1 -1
  11. package/dist/cpsat/model-builder.d.ts +9 -0
  12. package/dist/cpsat/model-builder.d.ts.map +1 -1
  13. package/dist/cpsat/model-builder.js +36 -34
  14. package/dist/cpsat/model-builder.js.map +1 -1
  15. package/dist/cpsat/response.d.ts +13 -1
  16. package/dist/cpsat/response.d.ts.map +1 -1
  17. package/dist/cpsat/response.js +4 -0
  18. package/dist/cpsat/response.js.map +1 -1
  19. package/dist/cpsat/rules/cost-utils.d.ts +11 -0
  20. package/dist/cpsat/rules/cost-utils.d.ts.map +1 -0
  21. package/dist/cpsat/rules/cost-utils.js +24 -0
  22. package/dist/cpsat/rules/cost-utils.js.map +1 -0
  23. package/dist/cpsat/rules/day-cost-multiplier.d.ts.map +1 -1
  24. package/dist/cpsat/rules/day-cost-multiplier.js +3 -14
  25. package/dist/cpsat/rules/day-cost-multiplier.js.map +1 -1
  26. package/dist/cpsat/rules/day-cost-surcharge.d.ts.map +1 -1
  27. package/dist/cpsat/rules/day-cost-surcharge.js +3 -7
  28. package/dist/cpsat/rules/day-cost-surcharge.js.map +1 -1
  29. package/dist/cpsat/rules/index.d.ts +3 -0
  30. package/dist/cpsat/rules/index.d.ts.map +1 -1
  31. package/dist/cpsat/rules/index.js +3 -0
  32. package/dist/cpsat/rules/index.js.map +1 -1
  33. package/dist/cpsat/rules/max-consecutive-days.d.ts.map +1 -1
  34. package/dist/cpsat/rules/max-consecutive-days.js +16 -2
  35. package/dist/cpsat/rules/max-consecutive-days.js.map +1 -1
  36. package/dist/cpsat/rules/max-days-week.d.ts +44 -0
  37. package/dist/cpsat/rules/max-days-week.d.ts.map +1 -0
  38. package/dist/cpsat/rules/max-days-week.js +95 -0
  39. package/dist/cpsat/rules/max-days-week.js.map +1 -0
  40. package/dist/cpsat/rules/max-hours-day.d.ts.map +1 -1
  41. package/dist/cpsat/rules/max-hours-day.js +15 -2
  42. package/dist/cpsat/rules/max-hours-day.js.map +1 -1
  43. package/dist/cpsat/rules/max-hours-week.d.ts.map +1 -1
  44. package/dist/cpsat/rules/max-hours-week.js +16 -2
  45. package/dist/cpsat/rules/max-hours-week.js.map +1 -1
  46. package/dist/cpsat/rules/max-shifts-day.d.ts.map +1 -1
  47. package/dist/cpsat/rules/max-shifts-day.js +15 -2
  48. package/dist/cpsat/rules/max-shifts-day.js.map +1 -1
  49. package/dist/cpsat/rules/min-consecutive-days.d.ts.map +1 -1
  50. package/dist/cpsat/rules/min-consecutive-days.js +15 -2
  51. package/dist/cpsat/rules/min-consecutive-days.js.map +1 -1
  52. package/dist/cpsat/rules/min-days-week.d.ts +34 -0
  53. package/dist/cpsat/rules/min-days-week.d.ts.map +1 -0
  54. package/dist/cpsat/rules/min-days-week.js +84 -0
  55. package/dist/cpsat/rules/min-days-week.js.map +1 -0
  56. package/dist/cpsat/rules/min-hours-day.d.ts.map +1 -1
  57. package/dist/cpsat/rules/min-hours-day.js +15 -2
  58. package/dist/cpsat/rules/min-hours-day.js.map +1 -1
  59. package/dist/cpsat/rules/min-hours-week.d.ts.map +1 -1
  60. package/dist/cpsat/rules/min-hours-week.js +16 -2
  61. package/dist/cpsat/rules/min-hours-week.js.map +1 -1
  62. package/dist/cpsat/rules/min-rest-between-shifts.d.ts.map +1 -1
  63. package/dist/cpsat/rules/min-rest-between-shifts.js +72 -2
  64. package/dist/cpsat/rules/min-rest-between-shifts.js.map +1 -1
  65. package/dist/cpsat/rules/minimize-cost.d.ts.map +1 -1
  66. package/dist/cpsat/rules/minimize-cost.js +2 -23
  67. package/dist/cpsat/rules/minimize-cost.js.map +1 -1
  68. package/dist/cpsat/rules/must-assign.d.ts +49 -0
  69. package/dist/cpsat/rules/must-assign.d.ts.map +1 -0
  70. package/dist/cpsat/rules/must-assign.js +86 -0
  71. package/dist/cpsat/rules/must-assign.js.map +1 -0
  72. package/dist/cpsat/rules/overtime-daily-multiplier.d.ts.map +1 -1
  73. package/dist/cpsat/rules/overtime-daily-multiplier.js +1 -12
  74. package/dist/cpsat/rules/overtime-daily-multiplier.js.map +1 -1
  75. package/dist/cpsat/rules/overtime-daily-surcharge.d.ts.map +1 -1
  76. package/dist/cpsat/rules/overtime-daily-surcharge.js +1 -5
  77. package/dist/cpsat/rules/overtime-daily-surcharge.js.map +1 -1
  78. package/dist/cpsat/rules/overtime-tiered-multiplier.d.ts +5 -1
  79. package/dist/cpsat/rules/overtime-tiered-multiplier.d.ts.map +1 -1
  80. package/dist/cpsat/rules/overtime-tiered-multiplier.js +1 -12
  81. package/dist/cpsat/rules/overtime-tiered-multiplier.js.map +1 -1
  82. package/dist/cpsat/rules/overtime-weekly-multiplier.d.ts.map +1 -1
  83. package/dist/cpsat/rules/overtime-weekly-multiplier.js +1 -12
  84. package/dist/cpsat/rules/overtime-weekly-multiplier.js.map +1 -1
  85. package/dist/cpsat/rules/overtime-weekly-surcharge.d.ts.map +1 -1
  86. package/dist/cpsat/rules/overtime-weekly-surcharge.js +1 -5
  87. package/dist/cpsat/rules/overtime-weekly-surcharge.js.map +1 -1
  88. package/dist/cpsat/rules/registry.d.ts +28 -2
  89. package/dist/cpsat/rules/registry.d.ts.map +1 -1
  90. package/dist/cpsat/rules/registry.js +4 -1
  91. package/dist/cpsat/rules/registry.js.map +1 -1
  92. package/dist/cpsat/rules/resolver.js +2 -2
  93. package/dist/cpsat/rules/resolver.js.map +1 -1
  94. package/dist/cpsat/rules/rules.types.d.ts +3 -0
  95. package/dist/cpsat/rules/rules.types.d.ts.map +1 -1
  96. package/dist/cpsat/rules/scope.types.d.ts +18 -1
  97. package/dist/cpsat/rules/scope.types.d.ts.map +1 -1
  98. package/dist/cpsat/rules/scope.types.js +59 -16
  99. package/dist/cpsat/rules/scope.types.js.map +1 -1
  100. package/dist/cpsat/rules/time-cost-surcharge.d.ts.map +1 -1
  101. package/dist/cpsat/rules/time-cost-surcharge.js +2 -1
  102. package/dist/cpsat/rules/time-cost-surcharge.js.map +1 -1
  103. package/dist/cpsat/rules/time-off.d.ts.map +1 -1
  104. package/dist/cpsat/rules/time-off.js +6 -3
  105. package/dist/cpsat/rules/time-off.js.map +1 -1
  106. package/dist/cpsat/semantic-time.d.ts +44 -42
  107. package/dist/cpsat/semantic-time.d.ts.map +1 -1
  108. package/dist/cpsat/semantic-time.js +64 -46
  109. package/dist/cpsat/semantic-time.js.map +1 -1
  110. package/dist/cpsat/types.d.ts +37 -27
  111. package/dist/cpsat/types.d.ts.map +1 -1
  112. package/dist/cpsat/utils.d.ts.map +1 -1
  113. package/dist/cpsat/utils.js +7 -12
  114. package/dist/cpsat/utils.js.map +1 -1
  115. package/dist/cpsat/validation-reporter.d.ts +10 -7
  116. package/dist/cpsat/validation-reporter.d.ts.map +1 -1
  117. package/dist/cpsat/validation-reporter.js +44 -72
  118. package/dist/cpsat/validation-reporter.js.map +1 -1
  119. package/dist/cpsat/validation.types.d.ts +54 -44
  120. package/dist/cpsat/validation.types.d.ts.map +1 -1
  121. package/dist/cpsat/validation.types.js +15 -10
  122. package/dist/cpsat/validation.types.js.map +1 -1
  123. package/dist/datetime.utils.d.ts +3 -203
  124. package/dist/datetime.utils.d.ts.map +1 -1
  125. package/dist/datetime.utils.js +1 -288
  126. package/dist/datetime.utils.js.map +1 -1
  127. package/dist/index.d.ts +14 -83
  128. package/dist/index.d.ts.map +1 -1
  129. package/dist/index.js +11 -83
  130. package/dist/index.js.map +1 -1
  131. package/dist/schedule/cost.d.ts +204 -0
  132. package/dist/schedule/cost.d.ts.map +1 -0
  133. package/dist/schedule/cost.js +187 -0
  134. package/dist/schedule/cost.js.map +1 -0
  135. package/dist/schedule/coverage.d.ts +85 -0
  136. package/dist/schedule/coverage.d.ts.map +1 -0
  137. package/dist/schedule/coverage.js +33 -0
  138. package/dist/schedule/coverage.js.map +1 -0
  139. package/dist/schedule/definition.d.ts +227 -0
  140. package/dist/schedule/definition.d.ts.map +1 -0
  141. package/dist/schedule/definition.js +659 -0
  142. package/dist/schedule/definition.js.map +1 -0
  143. package/dist/schedule/index.d.ts +67 -0
  144. package/dist/schedule/index.d.ts.map +1 -0
  145. package/dist/schedule/index.js +69 -0
  146. package/dist/schedule/index.js.map +1 -0
  147. package/dist/schedule/rules.d.ts +353 -0
  148. package/dist/schedule/rules.d.ts.map +1 -0
  149. package/dist/schedule/rules.js +352 -0
  150. package/dist/schedule/rules.js.map +1 -0
  151. package/dist/schedule/shift-patterns.d.ts +34 -0
  152. package/dist/schedule/shift-patterns.d.ts.map +1 -0
  153. package/dist/schedule/shift-patterns.js +41 -0
  154. package/dist/schedule/shift-patterns.js.map +1 -0
  155. package/dist/schedule/time-periods.d.ts +69 -0
  156. package/dist/schedule/time-periods.d.ts.map +1 -0
  157. package/dist/schedule/time-periods.js +91 -0
  158. package/dist/schedule/time-periods.js.map +1 -0
  159. package/dist/types.d.ts +14 -78
  160. package/dist/types.d.ts.map +1 -1
  161. package/dist/types.js.map +1 -1
  162. package/package.json +4 -9
  163. package/solver/src/solver/app.py +1 -1
  164. package/solver/src/solver/solver.py +7 -4
  165. package/src/client.ts +6 -8
  166. package/src/client.types.ts +9 -0
  167. package/src/cpsat/model-builder.ts +44 -35
  168. package/src/cpsat/response.ts +13 -1
  169. package/src/cpsat/rules/cost-utils.ts +25 -0
  170. package/src/cpsat/rules/day-cost-multiplier.ts +3 -14
  171. package/src/cpsat/rules/day-cost-surcharge.ts +3 -8
  172. package/src/cpsat/rules/index.ts +3 -0
  173. package/src/cpsat/rules/max-consecutive-days.ts +17 -0
  174. package/src/cpsat/rules/max-days-week.ts +143 -0
  175. package/src/cpsat/rules/max-hours-day.ts +21 -1
  176. package/src/cpsat/rules/max-hours-week.ts +22 -1
  177. package/src/cpsat/rules/max-shifts-day.ts +21 -1
  178. package/src/cpsat/rules/min-consecutive-days.ts +16 -1
  179. package/src/cpsat/rules/min-days-week.ts +120 -0
  180. package/src/cpsat/rules/min-hours-day.ts +16 -1
  181. package/src/cpsat/rules/min-hours-week.ts +17 -1
  182. package/src/cpsat/rules/min-rest-between-shifts.ts +92 -2
  183. package/src/cpsat/rules/minimize-cost.ts +2 -29
  184. package/src/cpsat/rules/must-assign.ts +108 -0
  185. package/src/cpsat/rules/overtime-daily-multiplier.ts +1 -12
  186. package/src/cpsat/rules/overtime-daily-surcharge.ts +1 -6
  187. package/src/cpsat/rules/overtime-tiered-multiplier.ts +6 -13
  188. package/src/cpsat/rules/overtime-weekly-multiplier.ts +1 -12
  189. package/src/cpsat/rules/overtime-weekly-surcharge.ts +1 -6
  190. package/src/cpsat/rules/registry.ts +8 -2
  191. package/src/cpsat/rules/resolver.ts +2 -2
  192. package/src/cpsat/rules/rules.types.ts +3 -0
  193. package/src/cpsat/rules/scope.types.ts +73 -20
  194. package/src/cpsat/rules/time-cost-surcharge.ts +2 -1
  195. package/src/cpsat/rules/time-off.ts +6 -2
  196. package/src/cpsat/semantic-time.ts +115 -91
  197. package/src/cpsat/types.ts +37 -27
  198. package/src/cpsat/utils.ts +8 -12
  199. package/src/cpsat/validation-reporter.ts +51 -82
  200. package/src/cpsat/validation.types.ts +72 -47
  201. package/src/datetime.utils.ts +3 -334
  202. package/src/index.ts +35 -107
  203. package/src/schedule/cost.ts +242 -0
  204. package/src/schedule/coverage.ts +135 -0
  205. package/src/schedule/definition.ts +958 -0
  206. package/src/schedule/index.ts +112 -0
  207. package/src/schedule/rules.ts +529 -0
  208. package/src/schedule/shift-patterns.ts +46 -0
  209. package/src/schedule/time-periods.ts +110 -0
  210. package/src/types.ts +14 -88
  211. package/dist/errors.d.ts +0 -12
  212. package/dist/errors.d.ts.map +0 -1
  213. package/dist/errors.js +0 -17
  214. package/dist/errors.js.map +0 -1
  215. package/dist/llms.d.ts +0 -2
  216. package/dist/llms.d.ts.map +0 -1
  217. package/dist/llms.js +0 -3
  218. package/dist/llms.js.map +0 -1
  219. package/dist/schedule.d.ts +0 -724
  220. package/dist/schedule.d.ts.map +0 -1
  221. package/dist/schedule.js +0 -899
  222. package/dist/schedule.js.map +0 -1
  223. package/dist/validation.d.ts +0 -105
  224. package/dist/validation.d.ts.map +0 -1
  225. package/dist/validation.js +0 -130
  226. package/dist/validation.js.map +0 -1
  227. package/llms.txt +0 -925
  228. package/src/errors.ts +0 -17
  229. package/src/llms.ts +0 -3
  230. package/src/schedule.ts +0 -1419
  231. package/src/validation.ts +0 -188
package/dist/types.d.ts CHANGED
@@ -6,6 +6,8 @@
6
6
  import * as z from "zod";
7
7
  /**
8
8
  * Day of the week identifier.
9
+ *
10
+ * @category Supporting Types
9
11
  */
10
12
  export type DayOfWeek = "monday" | "tuesday" | "wednesday" | "thursday" | "friday" | "saturday" | "sunday";
11
13
  /**
@@ -14,86 +16,13 @@ export type DayOfWeek = "monday" | "tuesday" | "wednesday" | "thursday" | "frida
14
16
  */
15
17
  export declare const DayOfWeekSchema: z.ZodUnion<readonly [z.ZodLiteral<"monday">, z.ZodLiteral<"tuesday">, z.ZodLiteral<"wednesday">, z.ZodLiteral<"thursday">, z.ZodLiteral<"friday">, z.ZodLiteral<"saturday">, z.ZodLiteral<"sunday">]>;
16
18
  /**
17
- * Time of day representation (hours and minutes, with optional seconds/nanos).
18
- *
19
- * Used for defining shift start/end times and semantic time boundaries.
20
- * Hours are in 24-hour format (0-23).
19
+ * Time of day (24-hour format).
21
20
  *
22
- * @example
23
- * ```typescript
24
- * { hours: 9, minutes: 0 }
25
- * { hours: 17, minutes: 30 }
26
- * ```
21
+ * @category Supporting Types
27
22
  */
28
23
  export interface TimeOfDay {
29
24
  hours: number;
30
25
  minutes: number;
31
- seconds?: number;
32
- nanos?: number;
33
- }
34
- /**
35
- * Calendar date representation (year, month, day).
36
- *
37
- * @example
38
- * ```typescript
39
- * const christmas: CalendarDate = {
40
- * year: 2025,
41
- * month: 12,
42
- * day: 25
43
- * };
44
- * ```
45
- */
46
- export interface CalendarDate {
47
- year: number;
48
- month: number;
49
- day: number;
50
- }
51
- /**
52
- * Time horizon defining the start and end dates for scheduling.
53
- *
54
- * Specifies the date range over which the schedule should be generated.
55
- * The range is inclusive of start date and exclusive of end date.
56
- *
57
- * @example
58
- * ```typescript
59
- * // One week schedule starting Monday, March 3, 2025
60
- * const horizon: TimeHorizon = {
61
- * start: new Date('2025-03-03'), // Monday
62
- * end: new Date('2025-03-10') // Following Monday (exclusive)
63
- * };
64
- * ```
65
- */
66
- export interface TimeHorizon {
67
- start: Date;
68
- end: Date;
69
- }
70
- export interface DateTimeComponents extends Partial<CalendarDate>, Partial<TimeOfDay> {
71
- }
72
- interface DateTimeWithUtcOffset extends DateTimeComponents {
73
- utcOffset?: string;
74
- timeZone?: never;
75
- }
76
- interface DateTimeWithTimeZone extends DateTimeComponents {
77
- timeZone?: {
78
- id: string;
79
- version: string;
80
- };
81
- utcOffset?: never;
82
- }
83
- /**
84
- * Date and time representation supporting both UTC offset and timezone-aware formats.
85
- *
86
- * Can be specified either with a UTC offset (e.g., "-08:00") or with a timezone ID
87
- * (e.g., "America/Los_Angeles").
88
- */
89
- export type DateTime = DateTimeWithUtcOffset | DateTimeWithTimeZone;
90
- /**
91
- * Represents a time range with start and end DateTimes.
92
- * Used for checking overlaps and scheduling constraints.
93
- */
94
- export interface DateTimeRange {
95
- start: DateTime;
96
- end: DateTime;
97
26
  }
98
27
  /**
99
28
  * Defines a scheduling period as a date range with optional filters.
@@ -117,7 +46,15 @@ export interface DateTimeRange {
117
46
  * };
118
47
  * ```
119
48
  *
120
-
49
+ * @example Only specific dates within the range
50
+ * ```typescript
51
+ * const period: SchedulingPeriod = {
52
+ * dateRange: { start: '2025-02-03', end: '2025-02-09' },
53
+ * dates: ['2025-02-05', '2025-02-07'],
54
+ * };
55
+ * ```
56
+ *
57
+ * @category Supporting Types
121
58
  */
122
59
  export interface SchedulingPeriod {
123
60
  /**
@@ -132,12 +69,11 @@ export interface SchedulingPeriod {
132
69
  * Include only these days of the week.
133
70
  * If omitted, all days of the week are included.
134
71
  */
135
- dayOfWeek?: DayOfWeek[];
72
+ dayOfWeek?: readonly DayOfWeek[];
136
73
  /**
137
74
  * Include only these specific dates (YYYY-MM-DD) within the range.
138
75
  * If omitted, all dates in the range are included (subject to dayOfWeek filter).
139
76
  */
140
77
  dates?: string[];
141
78
  }
142
- export {};
143
79
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAMzB;;GAEG;AACH,MAAM,MAAM,SAAS,GACjB,QAAQ,GACR,SAAS,GACT,WAAW,GACX,UAAU,GACV,QAAQ,GACR,UAAU,GACV,QAAQ,CAAC;AAEb;;;GAGG;AAEH,eAAO,MAAM,eAAe,uMAQ1B,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,IAAI,CAAC;IACZ,GAAG,EAAE,IAAI,CAAC;CACX;AAMD,MAAM,WAAW,kBAAmB,SAAQ,OAAO,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC;CAAG;AAExF,UAAU,qBAAsB,SAAQ,kBAAkB;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,UAAU,oBAAqB,SAAQ,kBAAkB;IACvD,QAAQ,CAAC,EAAE;QACT,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,SAAS,CAAC,EAAE,KAAK,CAAC;CACnB;AAED;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,qBAAqB,GAAG,oBAAoB,CAAC;AAEpE;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,QAAQ,CAAC;IAChB,GAAG,EAAE,QAAQ,CAAC;CACf;AAMD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IACxB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAMzB;;;;GAIG;AACH,MAAM,MAAM,SAAS,GACjB,QAAQ,GACR,SAAS,GACT,WAAW,GACX,UAAU,GACV,QAAQ,GACR,UAAU,GACV,QAAQ,CAAC;AAEb;;;GAGG;AACH,eAAO,MAAM,eAAe,uMAQ1B,CAAC;AAEH;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IACjC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAkBzB;;;GAGG;AAEH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC;IACrC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IACnB,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IACpB,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IACtB,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IACrB,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IACnB,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IACrB,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;CACpB,CAAC,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAoBzB;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC;IACrC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IACnB,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IACpB,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IACtB,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IACrB,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IACnB,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IACrB,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;CACpB,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dabke",
3
- "version": "0.81.1",
3
+ "version": "0.83.0",
4
4
  "description": "Scheduling library powered by constraint programming (CP-SAT)",
5
5
  "keywords": [
6
6
  "constraint-programming",
@@ -26,7 +26,6 @@
26
26
  "CHANGELOG.md",
27
27
  "dist",
28
28
  "LICENSE",
29
- "llms.txt",
30
29
  "README.md",
31
30
  "solver",
32
31
  "src"
@@ -40,10 +39,6 @@
40
39
  "types": "./dist/index.d.ts",
41
40
  "default": "./dist/index.js"
42
41
  },
43
- "./llms": {
44
- "types": "./dist/llms.d.ts",
45
- "default": "./dist/llms.js"
46
- },
47
42
  "./testing": {
48
43
  "types": "./dist/testing/index.d.ts",
49
44
  "default": "./dist/testing/index.js"
@@ -59,14 +54,14 @@
59
54
  "test:unit:watch": "vitest --watch --project=unit",
60
55
  "test:integration": "[ -f .env ] && { set -a; source .env; set +a; } && vitest run --project=integration",
61
56
  "test:integration:watch": "[ -f .env ] && { set -a; source .env; set +a; } && vitest --watch --project=integration",
62
- "generate:llmstxt": "tsx scripts/generate-llmstxt.ts && oxfmt --write llms.txt src/llms.ts"
57
+ "generate:reference": "tsx scripts/generate-reference.ts"
63
58
  },
64
59
  "dependencies": {
65
60
  "zod": "^4.3.6"
66
61
  },
67
62
  "devDependencies": {
68
- "@types/node": "^22.0.0",
69
- "commander": "^14.0.2",
63
+ "@types/node": "^25.0.0",
64
+ "commander": "^14.0.3",
70
65
  "typescript": "^5.9.3",
71
66
  "vitest": "^4.0.18"
72
67
  },
@@ -18,7 +18,7 @@ async def health() -> dict[str, str]:
18
18
  return {"status": "ok", "service": "scheduler-solver"}
19
19
 
20
20
 
21
- @app.post("/solve", response_model=SolverResponse)
21
+ @app.post("/solve", response_model=SolverResponse, response_model_exclude_unset=True)
22
22
  async def solve(request: SolverRequest) -> SolverResponse:
23
23
  """Solve a scheduling model described by primitive constraints."""
24
24
  return solve_request(request)
@@ -3,7 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from dataclasses import dataclass
6
- from typing import Iterable, Optional
6
+ from typing import Iterable
7
7
 
8
8
  from ortools.sat.python import cp_model
9
9
 
@@ -74,7 +74,7 @@ def _expression_range(terms: list[Term], bounds: dict[str, _VariableBounds]) ->
74
74
  return min_expr, max_expr
75
75
 
76
76
 
77
- def _sum_expr(exprs: list[cp_model.LinearExpr]) -> Optional[cp_model.LinearExpr]:
77
+ def _sum_expr(exprs: list[cp_model.LinearExpr]) -> cp_model.LinearExpr | None:
78
78
  if not exprs:
79
79
  return None
80
80
  total = exprs[0]
@@ -319,9 +319,10 @@ def solve_request(request: SolverRequest) -> SolverResponse:
319
319
  status_text = status_map.get(int(status), "ERROR")
320
320
 
321
321
  if status not in (cp_model.OPTIMAL, cp_model.FEASIBLE):
322
+ solution_info = solver.response_proto.solution_info
322
323
  return SolverResponse(
323
324
  status=status_text,
324
- solutionInfo=solver.response_proto.solution_info or None,
325
+ **({"solutionInfo": solution_info} if solution_info else {}),
325
326
  )
326
327
 
327
328
  statistics: dict[str, int | float] = {
@@ -349,11 +350,13 @@ def solve_request(request: SolverRequest) -> SolverResponse:
349
350
  )
350
351
  )
351
352
 
353
+ solution_info = solver.response_proto.solution_info
352
354
  return SolverResponse(
353
355
  status=status_text,
354
356
  values={name: int(solver.value(var)) for name, var in vars_map.items()},
355
357
  statistics=statistics,
356
- softViolations=soft_violations if soft_violations else None,
358
+ **({"solutionInfo": solution_info} if solution_info else {}),
359
+ softViolations=soft_violations,
357
360
  )
358
361
  except Exception as exc: # pragma: no cover - surfaced in response
359
362
  return SolverResponse(status="ERROR", error=str(exc))
package/src/client.ts CHANGED
@@ -1,9 +1,5 @@
1
- import {
2
- type FetcherLike,
3
- type SolverClient,
4
- type SolverRequest,
5
- type SolverResponse,
6
- } from "./client.types.js";
1
+ import { type FetcherLike, type SolverClient, type SolverRequest } from "./client.types.js";
2
+ import { SolverResponseSchema } from "./client.schemas.js";
7
3
 
8
4
  export type {
9
5
  SolverClient,
@@ -25,6 +21,8 @@ const normalizeFetch = (
25
21
 
26
22
  /**
27
23
  * Generic HTTP client for the solver service.
24
+ *
25
+ * @category Solver
28
26
  */
29
27
  export class HttpSolverClient implements SolverClient {
30
28
  #fetch: (input: string | URL, init?: RequestInit) => Promise<Response>;
@@ -35,7 +33,7 @@ export class HttpSolverClient implements SolverClient {
35
33
  this.#baseUrl = baseUrl.replace(/\/$/, "");
36
34
  }
37
35
 
38
- async solve(request: SolverRequest, options?: { signal?: AbortSignal }): Promise<SolverResponse> {
36
+ async solve(request: SolverRequest, options?: { signal?: AbortSignal }) {
39
37
  const res = await this.#fetch(`${this.#baseUrl}/solve`, {
40
38
  method: "POST",
41
39
  headers: { "Content-Type": "application/json" },
@@ -53,7 +51,7 @@ export class HttpSolverClient implements SolverClient {
53
51
  throw new Error("Solver returned an empty response");
54
52
  }
55
53
 
56
- return JSON.parse(bodyText) as SolverResponse;
54
+ return SolverResponseSchema.parse(JSON.parse(bodyText));
57
55
  }
58
56
 
59
57
  async health(): Promise<void> {
@@ -85,6 +85,8 @@ export type SolverResponse = z.infer<typeof SolverResponseSchema>;
85
85
  * Solver outcome status.
86
86
  *
87
87
  * One of `"OPTIMAL"`, `"FEASIBLE"`, `"INFEASIBLE"`, `"TIMEOUT"`, or `"ERROR"`.
88
+ *
89
+ * @category Solver
88
90
  */
89
91
  export type SolverStatus = z.infer<typeof SolverStatusSchema>;
90
92
 
@@ -100,6 +102,7 @@ export type SoftConstraintViolation = z.infer<typeof SoftConstraintViolationSche
100
102
  // Status constants (for convenience)
101
103
  // --------------------------------------------------------------------------
102
104
 
105
+ /** Convenience constants for {@link SolverStatus} values. */
103
106
  export const SOLVER_STATUS = {
104
107
  OPTIMAL: "OPTIMAL",
105
108
  FEASIBLE: "FEASIBLE",
@@ -112,12 +115,18 @@ export const SOLVER_STATUS = {
112
115
  // Client interface
113
116
  // --------------------------------------------------------------------------
114
117
 
118
+ /** A `fetch` function or an object with a `fetch` method. */
115
119
  export type FetcherLike =
116
120
  | typeof fetch
117
121
  | {
118
122
  fetch: typeof fetch;
119
123
  };
120
124
 
125
+ /**
126
+ * Interface for sending solver requests and receiving responses.
127
+ *
128
+ * @category Solver
129
+ */
121
130
  export interface SolverClient {
122
131
  solve(request: SolverRequest, options?: { signal?: AbortSignal }): Promise<SolverResponse>;
123
132
  health?(): Promise<void>;
@@ -94,6 +94,11 @@ export interface CostContribution {
94
94
  entries: CostEntry[];
95
95
  }
96
96
 
97
+ /**
98
+ * Result of {@link ModelBuilder.compile}.
99
+ *
100
+ * @category Model Builder
101
+ */
97
102
  export interface CompilationResult {
98
103
  request: SolverRequest;
99
104
  validation: ScheduleValidation;
@@ -103,6 +108,8 @@ export interface CompilationResult {
103
108
  /**
104
109
  * Configuration for ModelBuilder.
105
110
  *
111
+ * @category Model Builder
112
+ *
106
113
  * @example Date range with day-of-week filtering (restaurant closed Mon/Tue)
107
114
  * ```typescript
108
115
  * const config: ModelBuilderConfig = {
@@ -148,6 +155,8 @@ export interface ModelBuilderConfig extends ModelBuilderOptions {
148
155
  /**
149
156
  * Compilation context that creates variables, constraints, and objectives
150
157
  * and emits a `SolverRequest` for the Python CP-SAT solver service.
158
+ *
159
+ * @category Model Builder
151
160
  */
152
161
  export class ModelBuilder {
153
162
  readonly members: SchedulingMember[];
@@ -187,8 +196,8 @@ export class ModelBuilder {
187
196
 
188
197
  // Validate coverage requirements have at least roles or skills
189
198
  for (const cov of config.coverage) {
190
- const hasRoles = cov.roles !== undefined && cov.roles.length > 0;
191
- const hasSkills = cov.skills !== undefined && cov.skills.length > 0;
199
+ const hasRoles = cov.roleIds !== undefined && cov.roleIds.length > 0;
200
+ const hasSkills = cov.skillIds !== undefined && cov.skillIds.length > 0;
192
201
  if (!hasRoles && !hasSkills) {
193
202
  throw new Error(
194
203
  `Coverage requirement for day "${cov.day}" must have at least one of roles or skills`,
@@ -332,7 +341,7 @@ export class ModelBuilder {
332
341
  }
333
342
 
334
343
  membersWithRole(roleId: string): SchedulingMember[] {
335
- return this.members.filter((m) => m.roles.includes(roleId));
344
+ return this.members.filter((m) => m.roleIds.includes(roleId));
336
345
  }
337
346
 
338
347
  /**
@@ -345,15 +354,15 @@ export class ModelBuilder {
345
354
  */
346
355
  membersForCoverage(cov: CoverageRequirement): SchedulingMember[] {
347
356
  return this.members.filter((m) => {
348
- if (cov.roles && cov.roles.length > 0) {
349
- const hasMatchingRole = cov.roles.some((role) => m.roles.includes(role));
357
+ if (cov.roleIds && cov.roleIds.length > 0) {
358
+ const hasMatchingRole = cov.roleIds.some((role) => m.roleIds.includes(role));
350
359
  if (!hasMatchingRole) {
351
360
  return false;
352
361
  }
353
362
  }
354
- if (cov.skills && cov.skills.length > 0) {
355
- const memberSkills = m.skills ?? [];
356
- if (!cov.skills.every((skill) => memberSkills.includes(skill))) {
363
+ if (cov.skillIds && cov.skillIds.length > 0) {
364
+ const memberSkills = m.skillIds ?? [];
365
+ if (!cov.skillIds.every((skill) => memberSkills.includes(skill))) {
357
366
  return false;
358
367
  }
359
368
  }
@@ -362,10 +371,10 @@ export class ModelBuilder {
362
371
  }
363
372
 
364
373
  canAssign(member: SchedulingMember, pattern: ShiftPattern): boolean {
365
- if (!pattern.roles || pattern.roles.length === 0) {
374
+ if (!pattern.roleIds || pattern.roleIds.length === 0) {
366
375
  return true;
367
376
  }
368
- return pattern.roles.some((role) => member.roles.includes(role));
377
+ return pattern.roleIds.some((role) => member.roleIds.includes(role));
369
378
  }
370
379
 
371
380
  /**
@@ -498,13 +507,13 @@ export class ModelBuilder {
498
507
  for (const cov of this.coverage) {
499
508
  const covStart = timeOfDayToMinutes(cov.startTime);
500
509
  const covEnd = normalizeEndMinutes(covStart, timeOfDayToMinutes(cov.endTime));
501
- const covKey = cov.roles?.join(",") ?? cov.skills?.join(",") ?? "unknown";
510
+ const covKey = cov.roleIds?.join(",") ?? cov.skillIds?.join(",") ?? "unknown";
502
511
  const coverageLabel =
503
- cov.roles && cov.roles.length > 0
504
- ? cov.roles.length === 1
505
- ? `role "${cov.roles[0]}"`
506
- : `role "${cov.roles.join(" or ")}"`
507
- : `skills [${cov.skills?.join(", ")}]`;
512
+ cov.roleIds && cov.roleIds.length > 0
513
+ ? cov.roleIds.length === 1
514
+ ? `role "${cov.roleIds[0]}"`
515
+ : `role "${cov.roleIds.join(" or ")}"`
516
+ : `skills [${cov.skillIds?.join(", ")}]`;
508
517
  const coverageWindow = formatTimeRange(covStart, covEnd);
509
518
 
510
519
  const eligibleMembers = this.membersForCoverage(cov);
@@ -513,16 +522,16 @@ export class ModelBuilder {
513
522
  this.reporter.reportCoverageError({
514
523
  day: cov.day,
515
524
  timeSlots: [coverageWindow],
516
- roles: cov.roles,
517
- skills: cov.skills,
518
- reason: `Coverage for ${coverageLabel} on ${cov.day} (${coverageWindow}) cannot be met: no eligible team members available.`,
525
+ roleIds: cov.roleIds,
526
+ skillIds: cov.skillIds,
527
+ message: `Coverage for ${coverageLabel} on ${cov.day} (${coverageWindow}) cannot be met: no eligible team members available.`,
519
528
  suggestions: [
520
- cov.roles && cov.roles.length > 0
521
- ? `Add team members with role "${cov.roles.join(" or ")}"`
529
+ cov.roleIds && cov.roleIds.length > 0
530
+ ? `Add team members with role "${cov.roleIds.join(" or ")}"`
522
531
  : "Add team members with the required skills",
523
532
  "Change the coverage requirement to match available team members",
524
533
  ],
525
- groupKey: cov.groupKey,
534
+ group: cov.group,
526
535
  });
527
536
 
528
537
  const impossibleVar = `infeasible:coverage:${covKey}:${cov.day}`;
@@ -550,7 +559,7 @@ export class ModelBuilder {
550
559
  {
551
560
  key: "no_patterns",
552
561
  severity: cov.priority === "MANDATORY" ? "impossible" : "warning",
553
- reason: "no shift patterns overlap this time",
562
+ message: "no shift patterns overlap this time",
554
563
  suggestions: [
555
564
  "Add shift patterns that overlap this coverage window",
556
565
  "Adjust the coverage window to match available shifts",
@@ -582,7 +591,7 @@ export class ModelBuilder {
582
591
  {
583
592
  key: "no_assignable",
584
593
  severity: cov.priority === "MANDATORY" ? "impossible" : "warning",
585
- reason: "no eligible team members can work overlapping shift patterns",
594
+ message: "no eligible team members can work overlapping shift patterns",
586
595
  suggestions: [
587
596
  "Adjust shift pattern role requirements",
588
597
  "Add shift patterns that eligible team members can work",
@@ -616,7 +625,7 @@ export class ModelBuilder {
616
625
  {
617
626
  key: "mandatory_time_off",
618
627
  severity: cov.priority === "MANDATORY" ? "impossible" : "warning",
619
- reason: "all eligible team members are on mandatory time off",
628
+ message: "all eligible team members are on mandatory time off",
620
629
  suggestions: [
621
630
  "Adjust mandatory time-off requests",
622
631
  "Add more team members with the required role or skills",
@@ -630,7 +639,7 @@ export class ModelBuilder {
630
639
  {
631
640
  key: `insufficient:${availableMembers.size}`,
632
641
  severity: cov.priority === "MANDATORY" ? "impossible" : "warning",
633
- reason: `only ${availableMembers.size} team members available, need ${cov.targetCount}`,
642
+ message: `only ${availableMembers.size} team members available, need ${cov.targetCount}`,
634
643
  suggestions: [
635
644
  "Add more team members with the required role or skills",
636
645
  `Reduce coverage target to ${availableMembers.size}`,
@@ -679,13 +688,13 @@ export class ModelBuilder {
679
688
  comparator: ">=",
680
689
  day: cov.day,
681
690
  timeSlot: formatMinutes(bucketStart),
682
- roles: cov.roles,
683
- skills: cov.skills,
691
+ roleIds: cov.roleIds,
692
+ skillIds: cov.skillIds,
684
693
  context: {
685
694
  days: [cov.day],
686
695
  memberIds: eligibleMembers.map((e) => e.id),
687
696
  },
688
- groupKey: cov.groupKey,
697
+ group: cov.group,
689
698
  });
690
699
  }
691
700
 
@@ -695,17 +704,17 @@ export class ModelBuilder {
695
704
  );
696
705
  if (ranges.length === 0) continue;
697
706
 
698
- const reason = `Coverage for ${coverageLabel} on ${cov.day} (${ranges.join(", ")}) cannot be met: ${issue.reason}.`;
707
+ const message = `Coverage for ${coverageLabel} on ${cov.day} (${ranges.join(", ")}) cannot be met: ${issue.message}.`;
699
708
 
700
709
  if (issue.severity === "impossible") {
701
710
  this.reporter.reportCoverageError({
702
711
  day: cov.day,
703
712
  timeSlots: ranges,
704
- roles: cov.roles,
705
- skills: cov.skills,
706
- reason,
713
+ roleIds: cov.roleIds,
714
+ skillIds: cov.skillIds,
715
+ message,
707
716
  suggestions: issue.suggestions,
708
- groupKey: cov.groupKey,
717
+ group: cov.group,
709
718
  });
710
719
  }
711
720
  // Note: soft coverage warnings are tracked via trackConstraint and reported post-solve
@@ -824,7 +833,7 @@ export class ModelBuilder {
824
833
  type BucketIssueGroup = {
825
834
  key: string;
826
835
  severity: "impossible" | "warning";
827
- reason: string;
836
+ message: string;
828
837
  suggestions: string[];
829
838
  bucketStarts: number[];
830
839
  values?: Record<string, number>;
@@ -2,7 +2,11 @@ import type { SolverResponse } from "../client.types.js";
2
2
  import type { ShiftPattern } from "./types.js";
3
3
  import type { TimeOfDay } from "../types.js";
4
4
 
5
- /** A raw assignment from the solver: which member works which shift on which day. */
5
+ /**
6
+ * A raw assignment from the solver: which member works which shift on which day.
7
+ *
8
+ * @category Solver
9
+ */
6
10
  export interface ShiftAssignment {
7
11
  /** The assigned member's ID. */
8
12
  memberId: string;
@@ -14,6 +18,8 @@ export interface ShiftAssignment {
14
18
 
15
19
  /**
16
20
  * A shift assignment with resolved times.
21
+ *
22
+ * @category Solver
17
23
  */
18
24
  export interface ResolvedShiftAssignment {
19
25
  /** The assigned member's ID. */
@@ -28,6 +34,8 @@ export interface ResolvedShiftAssignment {
28
34
 
29
35
  /**
30
36
  * Parsed solver result with assignments and metadata.
37
+ *
38
+ * @category Solver
31
39
  */
32
40
  export interface SolverResult {
33
41
  /** The solver outcome: OPTIMAL, FEASIBLE, INFEASIBLE, TIMEOUT, or ERROR. */
@@ -53,6 +61,8 @@ export interface SolverResult {
53
61
  * @param response - The solver response containing variable values
54
62
  * @returns Parsed schedule result with assignments
55
63
  *
64
+ * @category Solver
65
+ *
56
66
  * @example
57
67
  * ```typescript
58
68
  * const response = await client.solve(request);
@@ -107,6 +117,8 @@ export function parseSolverResponse(response: SolverResponse): SolverResult {
107
117
  * @param shiftPatterns - The shift patterns used in the model
108
118
  * @returns Assignments with resolved start/end times
109
119
  *
120
+ * @category Solver
121
+ *
110
122
  * @example
111
123
  * ```typescript
112
124
  * const result = parseSolverResponse(response);
@@ -0,0 +1,25 @@
1
+ import type { SchedulingMember, ShiftPattern } from "../types.js";
2
+ import { timeOfDayToMinutes, normalizeEndMinutes } from "../utils.js";
3
+
4
+ /** Returns the hourly rate for a member, or undefined if not hourly. */
5
+ export function getHourlyRate(member: SchedulingMember): number | undefined {
6
+ if (!member.pay) return undefined;
7
+ if ("hourlyRate" in member.pay) return member.pay.hourlyRate;
8
+ return undefined;
9
+ }
10
+
11
+ /** Returns salaried pay info, or undefined if not salaried. */
12
+ export function getSalariedPay(
13
+ member: SchedulingMember,
14
+ ): { annual: number; hoursPerWeek: number } | undefined {
15
+ if (!member.pay) return undefined;
16
+ if ("annual" in member.pay) return member.pay;
17
+ return undefined;
18
+ }
19
+
20
+ /** Computes shift duration in minutes from a pattern. */
21
+ export function patternDurationMinutes(pattern: ShiftPattern): number {
22
+ const start = timeOfDayToMinutes(pattern.startTime);
23
+ const end = normalizeEndMinutes(start, timeOfDayToMinutes(pattern.endTime));
24
+ return end - start;
25
+ }
@@ -2,7 +2,7 @@ import * as z from "zod";
2
2
  import type { CompilationRule, CostContribution } from "../model-builder.js";
3
3
  import type { ShiftPattern, SchedulingMember } from "../types.js";
4
4
  import type { ShiftAssignment } from "../response.js";
5
- import { timeOfDayToMinutes, normalizeEndMinutes } from "../utils.js";
5
+ import { COST_CATEGORY } from "../cost.js";
6
6
  import {
7
7
  entityScope,
8
8
  timeScope,
@@ -11,6 +11,7 @@ import {
11
11
  resolveMembersFromScope,
12
12
  resolveActiveDaysFromScope,
13
13
  } from "./scope.types.js";
14
+ import { getHourlyRate, patternDurationMinutes } from "./cost-utils.js";
14
15
 
15
16
  const DayCostMultiplierSchema = z
16
17
  .object({
@@ -22,18 +23,6 @@ const DayCostMultiplierSchema = z
22
23
  /** Configuration for {@link createDayCostMultiplierRule}. */
23
24
  export type DayCostMultiplierConfig = z.infer<typeof DayCostMultiplierSchema>;
24
25
 
25
- function getHourlyRate(emp: SchedulingMember): number | undefined {
26
- if (!emp.pay) return undefined;
27
- if ("hourlyRate" in emp.pay) return emp.pay.hourlyRate;
28
- return undefined;
29
- }
30
-
31
- function patternDurationMinutes(pattern: ShiftPattern): number {
32
- const start = timeOfDayToMinutes(pattern.startTime);
33
- const end = normalizeEndMinutes(start, timeOfDayToMinutes(pattern.endTime));
34
- return end - start;
35
- }
36
-
37
26
  /**
38
27
  * Creates a day-based rate multiplier rule.
39
28
  *
@@ -113,7 +102,7 @@ export function createDayCostMultiplierRule(config: DayCostMultiplierConfig): Co
113
102
  entries.push({
114
103
  memberId: a.memberId,
115
104
  day: a.day,
116
- category: "premium",
105
+ category: COST_CATEGORY.PREMIUM,
117
106
  amount,
118
107
  });
119
108
  }