dabke 0.82.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.
Files changed (341) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +22 -24
  3. package/dist/client.d.ts +39 -3
  4. package/dist/client.d.ts.map +1 -1
  5. package/dist/client.js.map +1 -1
  6. package/dist/client.schemas.d.ts +118 -18
  7. package/dist/client.schemas.d.ts.map +1 -1
  8. package/dist/client.schemas.js +110 -6
  9. package/dist/client.schemas.js.map +1 -1
  10. package/dist/client.types.d.ts +63 -7
  11. package/dist/client.types.d.ts.map +1 -1
  12. package/dist/client.types.js.map +1 -1
  13. package/dist/cpsat/cost.d.ts +5 -2
  14. package/dist/cpsat/cost.d.ts.map +1 -1
  15. package/dist/cpsat/cost.js +13 -6
  16. package/dist/cpsat/cost.js.map +1 -1
  17. package/dist/cpsat/model-builder.d.ts +42 -61
  18. package/dist/cpsat/model-builder.d.ts.map +1 -1
  19. package/dist/cpsat/model-builder.js +451 -56
  20. package/dist/cpsat/model-builder.js.map +1 -1
  21. package/dist/cpsat/response.d.ts +19 -7
  22. package/dist/cpsat/response.d.ts.map +1 -1
  23. package/dist/cpsat/response.js +48 -9
  24. package/dist/cpsat/response.js.map +1 -1
  25. package/dist/cpsat/rule-descriptor.d.ts +250 -0
  26. package/dist/cpsat/rule-descriptor.d.ts.map +1 -0
  27. package/dist/cpsat/rule-descriptor.js +51 -0
  28. package/dist/cpsat/rule-descriptor.js.map +1 -0
  29. package/dist/cpsat/rules/artifacts.d.ts +9 -0
  30. package/dist/cpsat/rules/artifacts.d.ts.map +1 -0
  31. package/dist/cpsat/rules/artifacts.js +31 -0
  32. package/dist/cpsat/rules/artifacts.js.map +1 -0
  33. package/dist/cpsat/rules/assign-together.d.ts +18 -20
  34. package/dist/cpsat/rules/assign-together.d.ts.map +1 -1
  35. package/dist/cpsat/rules/assign-together.js +90 -54
  36. package/dist/cpsat/rules/assign-together.js.map +1 -1
  37. package/dist/cpsat/rules/assigned-day.d.ts +12 -0
  38. package/dist/cpsat/rules/assigned-day.d.ts.map +1 -0
  39. package/dist/cpsat/rules/assigned-day.js +43 -0
  40. package/dist/cpsat/rules/assigned-day.js.map +1 -0
  41. package/dist/cpsat/rules/assignment-priority.d.ts +15 -29
  42. package/dist/cpsat/rules/assignment-priority.d.ts.map +1 -1
  43. package/dist/cpsat/rules/assignment-priority.js +47 -50
  44. package/dist/cpsat/rules/assignment-priority.js.map +1 -1
  45. package/dist/cpsat/rules/assignment-terms.d.ts +6 -0
  46. package/dist/cpsat/rules/assignment-terms.d.ts.map +1 -0
  47. package/dist/cpsat/rules/assignment-terms.js +19 -0
  48. package/dist/cpsat/rules/assignment-terms.js.map +1 -0
  49. package/dist/cpsat/rules/concurrent-intervals.d.ts +19 -0
  50. package/dist/cpsat/rules/concurrent-intervals.d.ts.map +1 -0
  51. package/dist/cpsat/rules/concurrent-intervals.js +57 -0
  52. package/dist/cpsat/rules/concurrent-intervals.js.map +1 -0
  53. package/dist/cpsat/rules/cost-utils.d.ts +1 -3
  54. package/dist/cpsat/rules/cost-utils.d.ts.map +1 -1
  55. package/dist/cpsat/rules/cost-utils.js +0 -7
  56. package/dist/cpsat/rules/cost-utils.js.map +1 -1
  57. package/dist/cpsat/rules/day-cost-multiplier.d.ts +10 -10
  58. package/dist/cpsat/rules/day-cost-multiplier.d.ts.map +1 -1
  59. package/dist/cpsat/rules/day-cost-multiplier.js +88 -77
  60. package/dist/cpsat/rules/day-cost-multiplier.js.map +1 -1
  61. package/dist/cpsat/rules/day-cost-surcharge.d.ts +10 -10
  62. package/dist/cpsat/rules/day-cost-surcharge.d.ts.map +1 -1
  63. package/dist/cpsat/rules/day-cost-surcharge.js +76 -65
  64. package/dist/cpsat/rules/day-cost-surcharge.js.map +1 -1
  65. package/dist/cpsat/rules/index.d.ts +30 -21
  66. package/dist/cpsat/rules/index.d.ts.map +1 -1
  67. package/dist/cpsat/rules/index.js +30 -21
  68. package/dist/cpsat/rules/index.js.map +1 -1
  69. package/dist/cpsat/rules/location-preference.d.ts +14 -21
  70. package/dist/cpsat/rules/location-preference.d.ts.map +1 -1
  71. package/dist/cpsat/rules/location-preference.js +45 -45
  72. package/dist/cpsat/rules/location-preference.js.map +1 -1
  73. package/dist/cpsat/rules/max-concurrent-assignments.d.ts +46 -0
  74. package/dist/cpsat/rules/max-concurrent-assignments.d.ts.map +1 -0
  75. package/dist/cpsat/rules/max-concurrent-assignments.js +121 -0
  76. package/dist/cpsat/rules/max-concurrent-assignments.js.map +1 -0
  77. package/dist/cpsat/rules/max-consecutive-days.d.ts +18 -17
  78. package/dist/cpsat/rules/max-consecutive-days.d.ts.map +1 -1
  79. package/dist/cpsat/rules/max-consecutive-days.js +67 -66
  80. package/dist/cpsat/rules/max-consecutive-days.js.map +1 -1
  81. package/dist/cpsat/rules/max-days-of-week-per-period.d.ts +45 -0
  82. package/dist/cpsat/rules/max-days-of-week-per-period.d.ts.map +1 -0
  83. package/dist/cpsat/rules/max-days-of-week-per-period.js +95 -0
  84. package/dist/cpsat/rules/max-days-of-week-per-period.js.map +1 -0
  85. package/dist/cpsat/rules/max-days-week.d.ts +30 -0
  86. package/dist/cpsat/rules/max-days-week.d.ts.map +1 -0
  87. package/dist/cpsat/rules/max-days-week.js +83 -0
  88. package/dist/cpsat/rules/max-days-week.js.map +1 -0
  89. package/dist/cpsat/rules/max-hours-day.d.ts +14 -31
  90. package/dist/cpsat/rules/max-hours-day.d.ts.map +1 -1
  91. package/dist/cpsat/rules/max-hours-day.js +56 -72
  92. package/dist/cpsat/rules/max-hours-day.js.map +1 -1
  93. package/dist/cpsat/rules/max-hours-week.d.ts +15 -31
  94. package/dist/cpsat/rules/max-hours-week.d.ts.map +1 -1
  95. package/dist/cpsat/rules/max-hours-week.js +60 -75
  96. package/dist/cpsat/rules/max-hours-week.js.map +1 -1
  97. package/dist/cpsat/rules/max-shifts-day.d.ts +17 -33
  98. package/dist/cpsat/rules/max-shifts-day.d.ts.map +1 -1
  99. package/dist/cpsat/rules/max-shifts-day.js +57 -73
  100. package/dist/cpsat/rules/max-shifts-day.js.map +1 -1
  101. package/dist/cpsat/rules/min-consecutive-days.d.ts +18 -18
  102. package/dist/cpsat/rules/min-consecutive-days.d.ts.map +1 -1
  103. package/dist/cpsat/rules/min-consecutive-days.js +123 -94
  104. package/dist/cpsat/rules/min-consecutive-days.js.map +1 -1
  105. package/dist/cpsat/rules/min-days-of-week-per-period.d.ts +35 -0
  106. package/dist/cpsat/rules/min-days-of-week-per-period.d.ts.map +1 -0
  107. package/dist/cpsat/rules/min-days-of-week-per-period.js +108 -0
  108. package/dist/cpsat/rules/min-days-of-week-per-period.js.map +1 -0
  109. package/dist/cpsat/rules/min-days-week.d.ts +21 -0
  110. package/dist/cpsat/rules/min-days-week.d.ts.map +1 -0
  111. package/dist/cpsat/rules/min-days-week.js +95 -0
  112. package/dist/cpsat/rules/min-days-week.js.map +1 -0
  113. package/dist/cpsat/rules/min-hours-day.d.ts +14 -17
  114. package/dist/cpsat/rules/min-hours-day.d.ts.map +1 -1
  115. package/dist/cpsat/rules/min-hours-day.js +72 -54
  116. package/dist/cpsat/rules/min-hours-day.js.map +1 -1
  117. package/dist/cpsat/rules/min-hours-week.d.ts +15 -18
  118. package/dist/cpsat/rules/min-hours-week.d.ts.map +1 -1
  119. package/dist/cpsat/rules/min-hours-week.js +75 -57
  120. package/dist/cpsat/rules/min-hours-week.js.map +1 -1
  121. package/dist/cpsat/rules/min-rest-between-shifts.d.ts +14 -17
  122. package/dist/cpsat/rules/min-rest-between-shifts.d.ts.map +1 -1
  123. package/dist/cpsat/rules/min-rest-between-shifts.js +148 -138
  124. package/dist/cpsat/rules/min-rest-between-shifts.js.map +1 -1
  125. package/dist/cpsat/rules/minimize-cost.d.ts +2 -18
  126. package/dist/cpsat/rules/minimize-cost.d.ts.map +1 -1
  127. package/dist/cpsat/rules/minimize-cost.js +151 -163
  128. package/dist/cpsat/rules/minimize-cost.js.map +1 -1
  129. package/dist/cpsat/rules/must-assign.d.ts +12 -0
  130. package/dist/cpsat/rules/must-assign.d.ts.map +1 -0
  131. package/dist/cpsat/rules/must-assign.js +54 -0
  132. package/dist/cpsat/rules/must-assign.js.map +1 -0
  133. package/dist/cpsat/rules/overtime-daily-multiplier.d.ts +6 -10
  134. package/dist/cpsat/rules/overtime-daily-multiplier.d.ts.map +1 -1
  135. package/dist/cpsat/rules/overtime-daily-multiplier.js +118 -112
  136. package/dist/cpsat/rules/overtime-daily-multiplier.js.map +1 -1
  137. package/dist/cpsat/rules/overtime-daily-surcharge.d.ts +6 -11
  138. package/dist/cpsat/rules/overtime-daily-surcharge.d.ts.map +1 -1
  139. package/dist/cpsat/rules/overtime-daily-surcharge.js +104 -99
  140. package/dist/cpsat/rules/overtime-daily-surcharge.js.map +1 -1
  141. package/dist/cpsat/rules/overtime-tiered-multiplier.d.ts +9 -21
  142. package/dist/cpsat/rules/overtime-tiered-multiplier.d.ts.map +1 -1
  143. package/dist/cpsat/rules/overtime-tiered-multiplier.js +181 -199
  144. package/dist/cpsat/rules/overtime-tiered-multiplier.js.map +1 -1
  145. package/dist/cpsat/rules/overtime-weekly-multiplier.d.ts +13 -12
  146. package/dist/cpsat/rules/overtime-weekly-multiplier.d.ts.map +1 -1
  147. package/dist/cpsat/rules/overtime-weekly-multiplier.js +143 -143
  148. package/dist/cpsat/rules/overtime-weekly-multiplier.js.map +1 -1
  149. package/dist/cpsat/rules/overtime-weekly-surcharge.d.ts +7 -11
  150. package/dist/cpsat/rules/overtime-weekly-surcharge.d.ts.map +1 -1
  151. package/dist/cpsat/rules/overtime-weekly-surcharge.js +124 -119
  152. package/dist/cpsat/rules/overtime-weekly-surcharge.js.map +1 -1
  153. package/dist/cpsat/rules/pattern-eligibility.d.ts +6 -0
  154. package/dist/cpsat/rules/pattern-eligibility.d.ts.map +1 -0
  155. package/dist/cpsat/rules/pattern-eligibility.js +16 -0
  156. package/dist/cpsat/rules/pattern-eligibility.js.map +1 -0
  157. package/dist/cpsat/rules/pattern-time.d.ts +5 -0
  158. package/dist/cpsat/rules/pattern-time.d.ts.map +1 -0
  159. package/dist/cpsat/rules/pattern-time.js +20 -0
  160. package/dist/cpsat/rules/pattern-time.js.map +1 -0
  161. package/dist/cpsat/rules/registry.d.ts +217 -27
  162. package/dist/cpsat/rules/registry.d.ts.map +1 -1
  163. package/dist/cpsat/rules/registry.js +98 -31
  164. package/dist/cpsat/rules/registry.js.map +1 -1
  165. package/dist/cpsat/rules/resolver.d.ts +9 -7
  166. package/dist/cpsat/rules/resolver.d.ts.map +1 -1
  167. package/dist/cpsat/rules/resolver.js +19 -18
  168. package/dist/cpsat/rules/resolver.js.map +1 -1
  169. package/dist/cpsat/rules/role-preference.d.ts +24 -0
  170. package/dist/cpsat/rules/role-preference.d.ts.map +1 -0
  171. package/dist/cpsat/rules/role-preference.js +72 -0
  172. package/dist/cpsat/rules/role-preference.js.map +1 -0
  173. package/dist/cpsat/rules/rules.types.d.ts +93 -17
  174. package/dist/cpsat/rules/rules.types.d.ts.map +1 -1
  175. package/dist/cpsat/rules/scope.types.d.ts +25 -12
  176. package/dist/cpsat/rules/scope.types.d.ts.map +1 -1
  177. package/dist/cpsat/rules/scope.types.js +14 -19
  178. package/dist/cpsat/rules/scope.types.js.map +1 -1
  179. package/dist/cpsat/rules/target-days-week.d.ts +31 -0
  180. package/dist/cpsat/rules/target-days-week.d.ts.map +1 -0
  181. package/dist/cpsat/rules/target-days-week.js +80 -0
  182. package/dist/cpsat/rules/target-days-week.js.map +1 -0
  183. package/dist/cpsat/rules/target-peak-concurrent-assignments.d.ts +33 -0
  184. package/dist/cpsat/rules/target-peak-concurrent-assignments.d.ts.map +1 -0
  185. package/dist/cpsat/rules/target-peak-concurrent-assignments.js +146 -0
  186. package/dist/cpsat/rules/target-peak-concurrent-assignments.js.map +1 -0
  187. package/dist/cpsat/rules/time-cost-surcharge.d.ts +15 -14
  188. package/dist/cpsat/rules/time-cost-surcharge.d.ts.map +1 -1
  189. package/dist/cpsat/rules/time-cost-surcharge.js +82 -96
  190. package/dist/cpsat/rules/time-cost-surcharge.js.map +1 -1
  191. package/dist/cpsat/rules/time-off.d.ts +21 -57
  192. package/dist/cpsat/rules/time-off.d.ts.map +1 -1
  193. package/dist/cpsat/rules/time-off.js +114 -127
  194. package/dist/cpsat/rules/time-off.js.map +1 -1
  195. package/dist/cpsat/rules/variables.d.ts +4 -0
  196. package/dist/cpsat/rules/variables.d.ts.map +1 -0
  197. package/dist/cpsat/rules/variables.js +10 -0
  198. package/dist/cpsat/rules/variables.js.map +1 -0
  199. package/dist/cpsat/rules.d.ts +20 -3
  200. package/dist/cpsat/rules.d.ts.map +1 -1
  201. package/dist/cpsat/rules.js +19 -2
  202. package/dist/cpsat/rules.js.map +1 -1
  203. package/dist/cpsat/semantic-time.d.ts +7 -6
  204. package/dist/cpsat/semantic-time.d.ts.map +1 -1
  205. package/dist/cpsat/semantic-time.js +15 -28
  206. package/dist/cpsat/semantic-time.js.map +1 -1
  207. package/dist/cpsat/types.d.ts +47 -4
  208. package/dist/cpsat/types.d.ts.map +1 -1
  209. package/dist/cpsat/types.js +24 -1
  210. package/dist/cpsat/types.js.map +1 -1
  211. package/dist/cpsat/utils.d.ts +23 -6
  212. package/dist/cpsat/utils.d.ts.map +1 -1
  213. package/dist/cpsat/utils.js +76 -15
  214. package/dist/cpsat/utils.js.map +1 -1
  215. package/dist/cpsat/validation-reporter.d.ts +6 -2
  216. package/dist/cpsat/validation-reporter.d.ts.map +1 -1
  217. package/dist/cpsat/validation-reporter.js +122 -10
  218. package/dist/cpsat/validation-reporter.js.map +1 -1
  219. package/dist/cpsat/validation.types.d.ts +21 -10
  220. package/dist/cpsat/validation.types.d.ts.map +1 -1
  221. package/dist/datetime.utils.d.ts +7 -13
  222. package/dist/datetime.utils.d.ts.map +1 -1
  223. package/dist/datetime.utils.js +29 -36
  224. package/dist/datetime.utils.js.map +1 -1
  225. package/dist/index.d.ts +15 -9
  226. package/dist/index.d.ts.map +1 -1
  227. package/dist/index.js +11 -4
  228. package/dist/index.js.map +1 -1
  229. package/dist/schedule/cost.d.ts +192 -0
  230. package/dist/schedule/cost.d.ts.map +1 -0
  231. package/dist/schedule/cost.js +151 -0
  232. package/dist/schedule/cost.js.map +1 -0
  233. package/dist/schedule/coverage.d.ts +114 -0
  234. package/dist/schedule/coverage.d.ts.map +1 -0
  235. package/dist/schedule/coverage.js +56 -0
  236. package/dist/schedule/coverage.js.map +1 -0
  237. package/dist/schedule/definition.d.ts +346 -0
  238. package/dist/schedule/definition.d.ts.map +1 -0
  239. package/dist/schedule/definition.js +668 -0
  240. package/dist/schedule/definition.js.map +1 -0
  241. package/dist/schedule/index.d.ts +67 -0
  242. package/dist/schedule/index.d.ts.map +1 -0
  243. package/dist/schedule/index.js +69 -0
  244. package/dist/schedule/index.js.map +1 -0
  245. package/dist/schedule/rules.d.ts +678 -0
  246. package/dist/schedule/rules.d.ts.map +1 -0
  247. package/dist/schedule/rules.js +554 -0
  248. package/dist/schedule/rules.js.map +1 -0
  249. package/dist/schedule/shift-patterns.d.ts +17 -0
  250. package/dist/schedule/shift-patterns.d.ts.map +1 -0
  251. package/dist/schedule/shift-patterns.js +24 -0
  252. package/dist/schedule/shift-patterns.js.map +1 -0
  253. package/dist/schedule/time-periods.d.ts +79 -0
  254. package/dist/schedule/time-periods.d.ts.map +1 -0
  255. package/dist/schedule/time-periods.js +101 -0
  256. package/dist/schedule/time-periods.js.map +1 -0
  257. package/dist/types.d.ts +67 -3
  258. package/dist/types.d.ts.map +1 -1
  259. package/dist/types.js +64 -0
  260. package/dist/types.js.map +1 -1
  261. package/package.json +8 -14
  262. package/solver/src/solver/models.py +41 -4
  263. package/solver/src/solver/solver.py +546 -157
  264. package/solver/tests/test_solver.py +363 -7
  265. package/src/client.schemas.ts +127 -10
  266. package/src/client.ts +3 -0
  267. package/src/client.types.ts +73 -7
  268. package/src/cpsat/cost.ts +17 -7
  269. package/src/cpsat/model-builder.ts +614 -129
  270. package/src/cpsat/response.ts +57 -13
  271. package/src/cpsat/rule-descriptor.ts +311 -0
  272. package/src/cpsat/rules/artifacts.ts +56 -0
  273. package/src/cpsat/rules/assign-together.ts +104 -69
  274. package/src/cpsat/rules/assigned-day.ts +70 -0
  275. package/src/cpsat/rules/assignment-priority.ts +54 -58
  276. package/src/cpsat/rules/assignment-terms.ts +43 -0
  277. package/src/cpsat/rules/concurrent-intervals.ts +93 -0
  278. package/src/cpsat/rules/cost-utils.ts +1 -9
  279. package/src/cpsat/rules/day-cost-multiplier.ts +101 -81
  280. package/src/cpsat/rules/day-cost-surcharge.ts +91 -70
  281. package/src/cpsat/rules/index.ts +30 -21
  282. package/src/cpsat/rules/location-preference.ts +47 -52
  283. package/src/cpsat/rules/max-concurrent-assignments.ts +170 -0
  284. package/src/cpsat/rules/max-consecutive-days.ts +74 -91
  285. package/src/cpsat/rules/max-days-of-week-per-period.ts +127 -0
  286. package/src/cpsat/rules/max-days-week.ts +117 -0
  287. package/src/cpsat/rules/max-hours-day.ts +64 -84
  288. package/src/cpsat/rules/max-hours-week.ts +74 -90
  289. package/src/cpsat/rules/max-shifts-day.ts +65 -85
  290. package/src/cpsat/rules/min-consecutive-days.ts +161 -127
  291. package/src/cpsat/rules/min-days-of-week-per-period.ts +144 -0
  292. package/src/cpsat/rules/min-days-week.ts +122 -0
  293. package/src/cpsat/rules/min-hours-day.ts +79 -58
  294. package/src/cpsat/rules/min-hours-week.ts +87 -62
  295. package/src/cpsat/rules/min-rest-between-shifts.ts +191 -178
  296. package/src/cpsat/rules/minimize-cost.ts +175 -188
  297. package/src/cpsat/rules/must-assign.ts +71 -0
  298. package/src/cpsat/rules/overtime-daily-multiplier.ts +158 -140
  299. package/src/cpsat/rules/overtime-daily-surcharge.ts +141 -126
  300. package/src/cpsat/rules/overtime-tiered-multiplier.ts +234 -253
  301. package/src/cpsat/rules/overtime-weekly-multiplier.ts +183 -175
  302. package/src/cpsat/rules/overtime-weekly-surcharge.ts +161 -150
  303. package/src/cpsat/rules/pattern-eligibility.ts +26 -0
  304. package/src/cpsat/rules/pattern-time.ts +30 -0
  305. package/src/cpsat/rules/registry.ts +140 -56
  306. package/src/cpsat/rules/resolver.ts +58 -30
  307. package/src/cpsat/rules/role-preference.ts +92 -0
  308. package/src/cpsat/rules/rules.types.ts +92 -17
  309. package/src/cpsat/rules/scope.types.ts +32 -27
  310. package/src/cpsat/rules/target-days-week.ts +105 -0
  311. package/src/cpsat/rules/target-peak-concurrent-assignments.ts +212 -0
  312. package/src/cpsat/rules/time-cost-surcharge.ts +116 -122
  313. package/src/cpsat/rules/time-off.ts +154 -163
  314. package/src/cpsat/rules/variables.ts +11 -0
  315. package/src/cpsat/rules.ts +43 -17
  316. package/src/cpsat/semantic-time.ts +29 -43
  317. package/src/cpsat/types.ts +53 -4
  318. package/src/cpsat/utils.ts +92 -20
  319. package/src/cpsat/validation-reporter.ts +170 -19
  320. package/src/cpsat/validation.types.ts +22 -11
  321. package/src/datetime.utils.ts +45 -44
  322. package/src/index.ts +72 -15
  323. package/src/schedule/cost.ts +221 -0
  324. package/src/schedule/coverage.ts +164 -0
  325. package/src/schedule/definition.ts +1447 -0
  326. package/src/schedule/index.ts +132 -0
  327. package/src/schedule/rules.ts +1028 -0
  328. package/src/schedule/shift-patterns.ts +29 -0
  329. package/src/schedule/time-periods.ts +120 -0
  330. package/src/types.ts +114 -2
  331. package/dist/llms.d.ts +0 -2
  332. package/dist/llms.d.ts.map +0 -1
  333. package/dist/llms.js +0 -3
  334. package/dist/llms.js.map +0 -1
  335. package/dist/schedule.d.ts +0 -917
  336. package/dist/schedule.d.ts.map +0 -1
  337. package/dist/schedule.js +0 -1323
  338. package/dist/schedule.js.map +0 -1
  339. package/llms.txt +0 -758
  340. package/src/llms.ts +0 -3
  341. package/src/schedule.ts +0 -1960
@@ -1,27 +1,26 @@
1
1
  import * as z from "zod";
2
2
  import { DayOfWeekSchema } from "../../types.js";
3
- import type { CompilationRule, CostContribution } from "../model-builder.js";
4
- import type { ShiftPattern, SchedulingMember, Term } from "../types.js";
5
- import type { ShiftAssignment } from "../response.js";
3
+ import { defineRuleDescriptor } from "../rule-descriptor.js";
4
+ import type { CostArtifact } from "../rule-descriptor.js";
6
5
  import { COST_CATEGORY } from "../cost.js";
7
6
  import {
8
- timeOfDayToMinutes,
7
+ OBJECTIVE_WEIGHTS,
9
8
  normalizeEndMinutes,
10
9
  splitIntoWeeks,
10
+ timeOfDayToMinutes,
11
11
  unionMinutes,
12
- OBJECTIVE_WEIGHTS,
13
12
  } from "../utils.js";
14
13
  import {
15
14
  entityScope,
16
- timeScope,
17
15
  parseEntityScope,
18
16
  parseTimeScope,
19
- resolveMembersFromScope,
20
17
  resolveActiveDaysFromScope,
18
+ resolveMembersFromScope,
19
+ timeScope,
21
20
  } from "./scope.types.js";
22
- import { patternDurationMinutes } from "./cost-utils.js";
21
+ import { patternDurationMinutes } from "./pattern-time.js";
23
22
 
24
- const OvertimeWeeklySurchargeSchema = z
23
+ export const OvertimeWeeklySurchargeSchema = z
25
24
  .object({
26
25
  after: z.number().min(0),
27
26
  amount: z.number().min(0),
@@ -30,156 +29,168 @@ const OvertimeWeeklySurchargeSchema = z
30
29
  .and(entityScope(["members", "roles", "skills"]))
31
30
  .and(timeScope(["dateRange", "specificDates", "dayOfWeek", "recurring"]));
32
31
 
33
- /** Configuration for {@link createOvertimeWeeklySurchargeRule}. */
32
+ /** Configuration for {@link overtimeWeeklySurchargeRuleDescriptor}. */
34
33
  export type OvertimeWeeklySurchargeConfig = z.infer<typeof OvertimeWeeklySurchargeSchema>;
35
34
 
36
- /**
37
- * Creates a weekly overtime flat surcharge rule.
38
- *
39
- * Hours beyond the threshold per week get a flat surcharge per hour,
40
- * independent of the member's base rate.
41
- */
42
- export function createOvertimeWeeklySurchargeRule(
43
- config: OvertimeWeeklySurchargeConfig,
44
- ): CompilationRule {
45
- const parsed = OvertimeWeeklySurchargeSchema.parse(config);
46
- const { after, amount, weekStartsOn } = parsed;
47
- const entityScopeValue = parseEntityScope(parsed);
48
- const timeScopeValue = parseTimeScope(parsed);
49
- const thresholdMinutes = after * 60;
50
- let resolvedWeekStartsOn = weekStartsOn ?? "monday";
51
-
52
- return {
53
- compile(b) {
54
- resolvedWeekStartsOn = weekStartsOn ?? b.weekStartsOn;
55
- if (amount <= 0) return;
56
-
57
- const targetMembers = resolveMembersFromScope(entityScopeValue, b.members);
58
- const activeDays = resolveActiveDaysFromScope(timeScopeValue, b.days);
59
-
60
- if (targetMembers.length === 0 || activeDays.length === 0) return;
61
-
62
- const weeks = splitIntoWeeks(activeDays, weekStartsOn ?? b.weekStartsOn);
63
-
64
- const hasCostContext = b.costContext?.active === true;
65
- const surchargePerMinute = amount / 60;
66
-
67
- for (const emp of targetMembers) {
68
- for (const [weekIdx, weekDays] of weeks.entries()) {
69
- let empWeekMaxMinutes = 0;
70
- const terms: Term[] = [];
71
- for (const day of weekDays) {
72
- const dayRanges: Array<{ start: number; end: number }> = [];
73
- for (const pattern of b.shiftPatterns) {
74
- if (!b.canAssign(emp, pattern)) continue;
75
- if (!b.patternAvailableOnDay(pattern, day)) continue;
76
- const start = timeOfDayToMinutes(pattern.startTime);
77
- dayRanges.push({
78
- start,
79
- end: normalizeEndMinutes(start, timeOfDayToMinutes(pattern.endTime)),
80
- });
81
- terms.push({
82
- var: b.assignment(emp.id, pattern.id, day),
83
- coeff: patternDurationMinutes(pattern),
84
- });
35
+ export const overtimeWeeklySurchargeRuleDescriptor = defineRuleDescriptor({
36
+ name: "overtime-weekly-surcharge",
37
+ schema: OvertimeWeeklySurchargeSchema,
38
+ compile(config) {
39
+ const { after, amount, weekStartsOn } = config;
40
+ const entityScopeValue = parseEntityScope(config);
41
+ const timeScopeValue = parseTimeScope(config);
42
+ const thresholdMinutes = after * 60;
43
+ let resolvedWeekStartsOn = weekStartsOn ?? "monday";
44
+
45
+ const costArtifact: CostArtifact = {
46
+ kind: "cost",
47
+ validation: {
48
+ strategy: "skip",
49
+ category: "no-meaningful-feedback",
50
+ rationale:
51
+ "Overtime cost artifacts influence optimization and post-solve accounting, not validation feedback.",
52
+ },
53
+ compileObjective(builder) {
54
+ resolvedWeekStartsOn = weekStartsOn ?? builder.weekStartsOn;
55
+ if (amount <= 0) return;
56
+
57
+ const targetMembers = resolveMembersFromScope(entityScopeValue, builder.members);
58
+ const activeDays = resolveActiveDaysFromScope(timeScopeValue, builder.days);
59
+ if (targetMembers.length === 0 || activeDays.length === 0) return;
60
+
61
+ const weeks = splitIntoWeeks(activeDays, weekStartsOn ?? builder.weekStartsOn);
62
+ const hasCostContext = builder.costContext?.active === true;
63
+ const surchargePerMinute = amount / 60;
64
+
65
+ for (const member of targetMembers) {
66
+ for (const [weekIndex, weekDays] of weeks.entries()) {
67
+ let memberWeekMaxMinutes = 0;
68
+ const terms = [] as Array<{ var: string; coeff: number }>;
69
+
70
+ for (const day of weekDays) {
71
+ const dayRanges: Array<{ start: number; end: number }> = [];
72
+ for (const pattern of builder.shiftPatterns) {
73
+ if (
74
+ !builder.canAssign(member, pattern) ||
75
+ !builder.patternAvailableOnDay(pattern, day)
76
+ ) {
77
+ continue;
78
+ }
79
+ const start = timeOfDayToMinutes(pattern.startTime);
80
+ dayRanges.push({
81
+ start,
82
+ end: normalizeEndMinutes(start, timeOfDayToMinutes(pattern.endTime)),
83
+ });
84
+ terms.push({
85
+ var: builder.assignment(member.id, pattern.id, day),
86
+ coeff: patternDurationMinutes(pattern),
87
+ });
88
+ }
89
+ memberWeekMaxMinutes += unionMinutes(dayRanges);
85
90
  }
86
- empWeekMaxMinutes += unionMinutes(dayRanges);
87
- }
88
91
 
89
- if (terms.length === 0) continue;
90
-
91
- const maxOvertime = Math.max(0, empWeekMaxMinutes - thresholdMinutes);
92
- if (maxOvertime === 0) continue;
93
-
94
- const overtimeVar = b.intVar(`overtime:surcharge:${emp.id}:w${weekIdx}`, 0, maxOvertime);
95
-
96
- b.addLinear(
97
- [
98
- { var: overtimeVar, coeff: 1 },
99
- ...terms.map((t) => ({ var: t.var, coeff: -t.coeff })),
100
- ],
101
- ">=",
102
- -thresholdMinutes,
103
- );
104
-
105
- if (hasCostContext) {
106
- const totalOvertimeCost = surchargePerMinute * maxOvertime;
107
- const normalizedMax = totalOvertimeCost / b.costContext!.normalizationFactor;
108
- b.addPenalty(overtimeVar, Math.max(1, Math.round(normalizedMax / maxOvertime)));
109
- } else {
110
- b.addPenalty(
111
- overtimeVar,
112
- Math.max(1, Math.round(OBJECTIVE_WEIGHTS.COST / maxOvertime)),
92
+ if (terms.length === 0) continue;
93
+ const maxOvertime = Math.max(0, memberWeekMaxMinutes - thresholdMinutes);
94
+ if (maxOvertime === 0) continue;
95
+
96
+ const overtimeVar = builder.intVar(
97
+ `overtime:surcharge:${member.id}:w${weekIndex}`,
98
+ 0,
99
+ maxOvertime,
113
100
  );
101
+ builder.addLinear(
102
+ [
103
+ { var: overtimeVar, coeff: 1 },
104
+ ...terms.map((term) => ({ var: term.var, coeff: -term.coeff })),
105
+ ],
106
+ ">=",
107
+ -thresholdMinutes,
108
+ );
109
+
110
+ if (hasCostContext) {
111
+ const totalOvertimeCost = surchargePerMinute * maxOvertime;
112
+ const normalizedMax = totalOvertimeCost / builder.costContext!.normalizationFactor;
113
+ builder.addPenalty(overtimeVar, Math.max(1, Math.round(normalizedMax / maxOvertime)));
114
+ } else {
115
+ builder.addPenalty(
116
+ overtimeVar,
117
+ Math.max(1, Math.round(OBJECTIVE_WEIGHTS.COST / maxOvertime)),
118
+ );
119
+ }
114
120
  }
115
121
  }
116
- }
117
- },
118
-
119
- cost(
120
- assignments: ShiftAssignment[],
121
- members: ReadonlyArray<SchedulingMember>,
122
- shiftPatterns: ReadonlyArray<ShiftPattern>,
123
- ): CostContribution {
124
- if (amount <= 0) return { entries: [] };
125
-
126
- const patternMap = new Map(shiftPatterns.map((p) => [p.id, p]));
127
- const allDays = [...new Set(assignments.map((a) => a.day))].toSorted();
128
- const activeDays = new Set(resolveActiveDaysFromScope(timeScopeValue, allDays));
129
- const targetEmpIds = new Set(
130
- resolveMembersFromScope(entityScopeValue, [...members]).map((e) => e.id),
131
- );
132
-
133
- const activeDaysList = allDays.filter((d) => activeDays.has(d));
134
- const weeks = splitIntoWeeks(activeDaysList, resolvedWeekStartsOn);
135
-
136
- const entries: CostContribution["entries"] = [];
137
-
138
- for (const weekDays of weeks) {
139
- const weekDaySet = new Set(weekDays);
140
-
141
- const empWeekData = new Map<
142
- string,
143
- { totalMinutes: number; dayMinutes: Map<string, number> }
144
- >();
145
-
146
- for (const a of assignments) {
147
- if (!weekDaySet.has(a.day)) continue;
148
- if (!activeDays.has(a.day)) continue;
149
- if (!targetEmpIds.has(a.memberId)) continue;
150
-
151
- const pattern = patternMap.get(a.shiftPatternId);
152
- if (!pattern) continue;
153
- const duration = patternDurationMinutes(pattern);
154
-
155
- let data = empWeekData.get(a.memberId);
156
- if (!data) {
157
- data = { totalMinutes: 0, dayMinutes: new Map() };
158
- empWeekData.set(a.memberId, data);
122
+ },
123
+ calculateCost(assignments, costContext) {
124
+ if (amount <= 0) return { entries: [] };
125
+
126
+ const patternMap = new Map(
127
+ costContext.shiftPatterns.map((pattern) => [pattern.id, pattern]),
128
+ );
129
+ const activeDays = new Set(
130
+ resolveActiveDaysFromScope(timeScopeValue, [...costContext.days]).map((day) => day.iso),
131
+ );
132
+ const targetMemberIds = new Set(
133
+ resolveMembersFromScope(entityScopeValue, [...costContext.members]).map(
134
+ (member) => member.id,
135
+ ),
136
+ );
137
+ const activeDaysList = costContext.days.filter((day) => activeDays.has(day.iso));
138
+ const weeks = splitIntoWeeks(activeDaysList, resolvedWeekStartsOn);
139
+
140
+ const entries = [] as Array<{
141
+ memberId: string;
142
+ day: string;
143
+ category: string;
144
+ amount: number;
145
+ }>;
146
+ for (const weekDays of weeks) {
147
+ const weekDaySet = new Set(weekDays.map((day) => day.iso));
148
+ const memberWeekData = new Map<
149
+ string,
150
+ { totalMinutes: number; dayMinutes: Map<string, number> }
151
+ >();
152
+
153
+ for (const assignment of assignments) {
154
+ if (!weekDaySet.has(assignment.day) || !activeDays.has(assignment.day)) continue;
155
+ if (!targetMemberIds.has(assignment.memberId)) continue;
156
+ const pattern = patternMap.get(assignment.shiftPatternId);
157
+ if (!pattern) continue;
158
+ const duration = patternDurationMinutes(pattern);
159
+ let data = memberWeekData.get(assignment.memberId);
160
+ if (!data) {
161
+ data = { totalMinutes: 0, dayMinutes: new Map() };
162
+ memberWeekData.set(assignment.memberId, data);
163
+ }
164
+ data.totalMinutes += duration;
165
+ data.dayMinutes.set(
166
+ assignment.day,
167
+ (data.dayMinutes.get(assignment.day) ?? 0) + duration,
168
+ );
159
169
  }
160
- data.totalMinutes += duration;
161
- data.dayMinutes.set(a.day, (data.dayMinutes.get(a.day) ?? 0) + duration);
162
- }
163
170
 
164
- for (const [empId, data] of empWeekData) {
165
- const overtimeMinutes = Math.max(0, data.totalMinutes - thresholdMinutes);
166
- if (overtimeMinutes <= 0) continue;
167
-
168
- const totalOvertimeCost = (amount * overtimeMinutes) / 60;
169
-
170
- for (const [day, dayMinutes] of data.dayMinutes) {
171
- const proportion = dayMinutes / data.totalMinutes;
172
- entries.push({
173
- memberId: empId,
174
- day,
175
- category: COST_CATEGORY.OVERTIME,
176
- amount: totalOvertimeCost * proportion,
177
- });
171
+ for (const [memberId, data] of memberWeekData) {
172
+ const overtimeMinutes = Math.max(0, data.totalMinutes - thresholdMinutes);
173
+ if (overtimeMinutes <= 0) continue;
174
+ const totalOvertimeCost = (amount * overtimeMinutes) / 60;
175
+ for (const [day, dayMinutes] of data.dayMinutes) {
176
+ const proportion = dayMinutes / data.totalMinutes;
177
+ entries.push({
178
+ memberId,
179
+ day,
180
+ category: COST_CATEGORY.OVERTIME,
181
+ amount: totalOvertimeCost * proportion,
182
+ });
183
+ }
178
184
  }
179
185
  }
180
- }
181
186
 
182
- return { entries };
183
- },
184
- };
185
- }
187
+ return { entries };
188
+ },
189
+ };
190
+
191
+ return {
192
+ rule: "overtime-weekly-surcharge",
193
+ artifacts: [costArtifact],
194
+ };
195
+ },
196
+ });
@@ -0,0 +1,26 @@
1
+ import type { SchedulingDay } from "../../types.js";
2
+ import type { SchedulingMember, ShiftPattern } from "../types.js";
3
+
4
+ export function canAssignMemberToPattern(member: SchedulingMember, pattern: ShiftPattern): boolean {
5
+ if (!pattern.roleIds || pattern.roleIds.length === 0) {
6
+ return true;
7
+ }
8
+ return pattern.roleIds.some((role) => member.roleIds.includes(role));
9
+ }
10
+
11
+ export function isPatternAvailableOnDay(pattern: ShiftPattern, day: SchedulingDay): boolean {
12
+ if (!pattern.dayOfWeek || pattern.dayOfWeek.length === 0) {
13
+ return true;
14
+ }
15
+ return pattern.dayOfWeek.includes(day.dayOfWeek);
16
+ }
17
+
18
+ export function hasAnyAssignablePattern(
19
+ member: SchedulingMember,
20
+ day: SchedulingDay,
21
+ shiftPatterns: readonly ShiftPattern[],
22
+ ): boolean {
23
+ return shiftPatterns.some(
24
+ (pattern) => canAssignMemberToPattern(member, pattern) && isPatternAvailableOnDay(pattern, day),
25
+ );
26
+ }
@@ -0,0 +1,30 @@
1
+ import type { SchedulingDay } from "../../types.js";
2
+ import type { SchedulingMember, ShiftPattern } from "../types.js";
3
+ import { normalizeEndMinutes, timeOfDayToMinutes, unionMinutes } from "../utils.js";
4
+ import { canAssignMemberToPattern, isPatternAvailableOnDay } from "./pattern-eligibility.js";
5
+
6
+ export function patternDurationMinutes(pattern: ShiftPattern): number {
7
+ const start = timeOfDayToMinutes(pattern.startTime);
8
+ const end = normalizeEndMinutes(start, timeOfDayToMinutes(pattern.endTime));
9
+ return end - start;
10
+ }
11
+
12
+ export function maxAssignableMinutesForDay(
13
+ member: SchedulingMember,
14
+ day: SchedulingDay,
15
+ shiftPatterns: readonly ShiftPattern[],
16
+ ): number {
17
+ const ranges = shiftPatterns
18
+ .filter(
19
+ (pattern) =>
20
+ canAssignMemberToPattern(member, pattern) && isPatternAvailableOnDay(pattern, day),
21
+ )
22
+ .map((pattern) => {
23
+ const start = timeOfDayToMinutes(pattern.startTime);
24
+ return {
25
+ start,
26
+ end: normalizeEndMinutes(start, timeOfDayToMinutes(pattern.endTime)),
27
+ };
28
+ });
29
+ return unionMinutes(ranges);
30
+ }
@@ -1,67 +1,151 @@
1
1
  import {
2
- createAssignTogetherRule,
3
- createAssignmentPriorityRule,
4
- createLocationPreferenceRule,
5
- createMaxConsecutiveDaysRule,
6
- createMaxHoursDayRule,
7
- createMaxHoursWeekRule,
8
- createMaxShiftsDayRule,
9
- createMinConsecutiveDaysRule,
10
- createMinHoursDayRule,
11
- createMinHoursWeekRule,
12
- createMinRestBetweenShiftsRule,
13
- createTimeOffRule,
14
- createMinimizeCostRule,
15
- createDayCostMultiplierRule,
16
- createDayCostSurchargeRule,
17
- createTimeCostSurchargeRule,
18
- createOvertimeWeeklyMultiplierRule,
19
- createOvertimeWeeklySurchargeRule,
20
- createOvertimeDailyMultiplierRule,
21
- createOvertimeDailySurchargeRule,
22
- createOvertimeTieredMultiplierRule,
2
+ assignTogetherRuleDescriptor,
3
+ assignmentPriorityRuleDescriptor,
4
+ dayCostMultiplierRuleDescriptor,
5
+ dayCostSurchargeRuleDescriptor,
6
+ locationPreferenceRuleDescriptor,
7
+ maxConcurrentAssignmentsRuleDescriptor,
8
+ maxConsecutiveDaysRuleDescriptor,
9
+ maxDaysOfWeekPerPeriodRuleDescriptor,
10
+ maxDaysWeekRuleDescriptor,
11
+ maxHoursDayRuleDescriptor,
12
+ maxHoursWeekRuleDescriptor,
13
+ maxShiftsDayRuleDescriptor,
14
+ minConsecutiveDaysRuleDescriptor,
15
+ minDaysOfWeekPerPeriodRuleDescriptor,
16
+ minDaysWeekRuleDescriptor,
17
+ minHoursDayRuleDescriptor,
18
+ minHoursWeekRuleDescriptor,
19
+ minRestBetweenShiftsRuleDescriptor,
20
+ minimizeCostRuleDescriptor,
21
+ mustAssignRuleDescriptor,
22
+ overtimeDailyMultiplierRuleDescriptor,
23
+ overtimeDailySurchargeRuleDescriptor,
24
+ overtimeTieredMultiplierRuleDescriptor,
25
+ overtimeWeeklyMultiplierRuleDescriptor,
26
+ overtimeWeeklySurchargeRuleDescriptor,
27
+ rolePreferenceRuleDescriptor,
28
+ targetDaysWeekRuleDescriptor,
29
+ targetPeakConcurrentAssignmentsRuleDescriptor,
30
+ timeCostSurchargeRuleDescriptor,
31
+ timeOffRuleDescriptor,
23
32
  } from "./index.js";
24
- import type {
25
- BuiltInCpsatRuleFactories,
26
- CpsatRuleFactories,
27
- CpsatRuleName,
28
- } from "./rules.types.js";
33
+ import type { BuiltInCpsatRuleRegistry, CpsatRuleName, CpsatRuleRegistry } from "./rules.types.js";
29
34
 
30
- export const builtInCpsatRuleFactories = {
31
- "assign-together": createAssignTogetherRule,
32
- "assignment-priority": createAssignmentPriorityRule,
33
- "location-preference": createLocationPreferenceRule,
34
- "max-consecutive-days": createMaxConsecutiveDaysRule,
35
- "max-hours-day": createMaxHoursDayRule,
36
- "max-hours-week": createMaxHoursWeekRule,
37
- "max-shifts-day": createMaxShiftsDayRule,
38
- "min-consecutive-days": createMinConsecutiveDaysRule,
39
- "min-hours-day": createMinHoursDayRule,
40
- "min-hours-week": createMinHoursWeekRule,
41
- "min-rest-between-shifts": createMinRestBetweenShiftsRule,
42
- "time-off": createTimeOffRule,
43
- "minimize-cost": createMinimizeCostRule,
44
- "day-cost-multiplier": createDayCostMultiplierRule,
45
- "day-cost-surcharge": createDayCostSurchargeRule,
46
- "time-cost-surcharge": createTimeCostSurchargeRule,
47
- "overtime-weekly-multiplier": createOvertimeWeeklyMultiplierRule,
48
- "overtime-weekly-surcharge": createOvertimeWeeklySurchargeRule,
49
- "overtime-daily-multiplier": createOvertimeDailyMultiplierRule,
50
- "overtime-daily-surcharge": createOvertimeDailySurchargeRule,
51
- "overtime-tiered-multiplier": createOvertimeTieredMultiplierRule,
52
- } satisfies BuiltInCpsatRuleFactories;
35
+ /**
36
+ * Validates that each rule registry key matches the descriptor name it points to.
37
+ *
38
+ * @remarks
39
+ * This enforces the invariant required by registry-driven config typing and by
40
+ * runtime rule resolution. A registry entry like `{ debug: descriptorNamedFoo }`
41
+ * is rejected because the key and descriptor identity diverge.
42
+ *
43
+ * @category Rules
44
+ */
45
+ export function assertValidCpsatRuleRegistry<Registry extends CpsatRuleRegistry>(
46
+ ruleRegistry: Registry,
47
+ ): Registry {
48
+ for (const [key, descriptor] of Object.entries(ruleRegistry)) {
49
+ if (descriptor.name !== key) {
50
+ throw new Error(
51
+ `Registered CP-SAT rule descriptor key "${key}" must match descriptor.name "${descriptor.name}".`,
52
+ );
53
+ }
54
+ }
55
+
56
+ return ruleRegistry;
57
+ }
53
58
 
54
59
  /**
55
- * Creates a rule factory map, preventing overriding built-in rules.
60
+ * Validates that a registry does not shadow built-in rule names with different descriptors.
61
+ *
62
+ * @remarks
63
+ * A registry may reuse the exact built-in descriptor instance under the same name,
64
+ * but it may not replace a built-in rule with an incompatible descriptor.
56
65
  */
57
- export function createCpsatRuleFactory<F extends CpsatRuleFactories>(factories: F): F {
58
- for (const name in factories) {
66
+ export function assertNoBuiltInCpsatRuleOverrides<Registry extends CpsatRuleRegistry>(
67
+ ruleRegistry: Registry,
68
+ ): Registry {
69
+ for (const name in ruleRegistry) {
59
70
  if (
60
- name in builtInCpsatRuleFactories &&
61
- factories[name] !== builtInCpsatRuleFactories[name as CpsatRuleName]
71
+ name in builtInCpsatRuleRegistry &&
72
+ ruleRegistry[name] !== builtInCpsatRuleRegistry[name as CpsatRuleName]
62
73
  ) {
63
- throw new Error(`Cannot override built-in CP-SAT rule "${name}" in custom factory`);
74
+ throw new Error(`Cannot override built-in CP-SAT rule "${name}" in custom registry`);
64
75
  }
65
76
  }
66
- return factories;
77
+
78
+ return ruleRegistry;
67
79
  }
80
+
81
+ /**
82
+ * Creates a custom CP-SAT rule registry.
83
+ *
84
+ * @remarks
85
+ * Built-in rule names cannot be redefined unless the registry entry points to
86
+ * the exact same built-in descriptor instance.
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * const debugRuleRegistry = createCpsatRuleRegistry({
91
+ * debug: defineRuleDescriptor({
92
+ * name: "debug",
93
+ * schema: z.object({ flag: z.boolean() }),
94
+ * compile() {
95
+ * return { rule: "debug", artifacts: [] };
96
+ * },
97
+ * }),
98
+ * });
99
+ * ```
100
+ *
101
+ * @category Rules
102
+ */
103
+ export function createCpsatRuleRegistry<Registry extends CpsatRuleRegistry>(
104
+ ruleRegistry: Registry,
105
+ ): Registry {
106
+ assertNoBuiltInCpsatRuleOverrides(ruleRegistry);
107
+ return assertValidCpsatRuleRegistry(ruleRegistry);
108
+ }
109
+
110
+ /**
111
+ * The built-in CP-SAT rule registry.
112
+ *
113
+ * @remarks
114
+ * Pass this to {@link defineRuleFor} when you want registry-bound authoring for
115
+ * built-in rules, or spread it into a larger registry when building a fully
116
+ * explicit descriptor set.
117
+ *
118
+ * @category Rules
119
+ */
120
+ export const builtInCpsatRuleRegistry = assertValidCpsatRuleRegistry({
121
+ "assign-together": assignTogetherRuleDescriptor,
122
+ "assignment-priority": assignmentPriorityRuleDescriptor,
123
+ "location-preference": locationPreferenceRuleDescriptor,
124
+ "role-preference": rolePreferenceRuleDescriptor,
125
+ "max-concurrent-assignments": maxConcurrentAssignmentsRuleDescriptor,
126
+ "target-peak-concurrent-assignments": targetPeakConcurrentAssignmentsRuleDescriptor,
127
+ "target-days-week": targetDaysWeekRuleDescriptor,
128
+ "max-consecutive-days": maxConsecutiveDaysRuleDescriptor,
129
+ "max-days-week": maxDaysWeekRuleDescriptor,
130
+ "max-hours-day": maxHoursDayRuleDescriptor,
131
+ "max-hours-week": maxHoursWeekRuleDescriptor,
132
+ "max-shifts-day": maxShiftsDayRuleDescriptor,
133
+ "min-consecutive-days": minConsecutiveDaysRuleDescriptor,
134
+ "min-days-week": minDaysWeekRuleDescriptor,
135
+ "min-hours-day": minHoursDayRuleDescriptor,
136
+ "min-hours-week": minHoursWeekRuleDescriptor,
137
+ "min-rest-between-shifts": minRestBetweenShiftsRuleDescriptor,
138
+ "must-assign": mustAssignRuleDescriptor,
139
+ "time-off": timeOffRuleDescriptor,
140
+ "minimize-cost": minimizeCostRuleDescriptor,
141
+ "day-cost-multiplier": dayCostMultiplierRuleDescriptor,
142
+ "day-cost-surcharge": dayCostSurchargeRuleDescriptor,
143
+ "time-cost-surcharge": timeCostSurchargeRuleDescriptor,
144
+ "overtime-weekly-multiplier": overtimeWeeklyMultiplierRuleDescriptor,
145
+ "overtime-weekly-surcharge": overtimeWeeklySurchargeRuleDescriptor,
146
+ "overtime-daily-multiplier": overtimeDailyMultiplierRuleDescriptor,
147
+ "overtime-daily-surcharge": overtimeDailySurchargeRuleDescriptor,
148
+ "overtime-tiered-multiplier": overtimeTieredMultiplierRuleDescriptor,
149
+ "max-days-of-week-per-period": maxDaysOfWeekPerPeriodRuleDescriptor,
150
+ "min-days-of-week-per-period": minDaysOfWeekPerPeriodRuleDescriptor,
151
+ } satisfies BuiltInCpsatRuleRegistry);