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.
- package/CHANGELOG.md +44 -0
- package/README.md +22 -24
- package/dist/client.d.ts +39 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js.map +1 -1
- package/dist/client.schemas.d.ts +118 -18
- package/dist/client.schemas.d.ts.map +1 -1
- package/dist/client.schemas.js +110 -6
- package/dist/client.schemas.js.map +1 -1
- package/dist/client.types.d.ts +63 -7
- package/dist/client.types.d.ts.map +1 -1
- package/dist/client.types.js.map +1 -1
- package/dist/cpsat/cost.d.ts +5 -2
- package/dist/cpsat/cost.d.ts.map +1 -1
- package/dist/cpsat/cost.js +13 -6
- package/dist/cpsat/cost.js.map +1 -1
- package/dist/cpsat/model-builder.d.ts +42 -61
- package/dist/cpsat/model-builder.d.ts.map +1 -1
- package/dist/cpsat/model-builder.js +451 -56
- package/dist/cpsat/model-builder.js.map +1 -1
- package/dist/cpsat/response.d.ts +19 -7
- package/dist/cpsat/response.d.ts.map +1 -1
- package/dist/cpsat/response.js +48 -9
- package/dist/cpsat/response.js.map +1 -1
- package/dist/cpsat/rule-descriptor.d.ts +250 -0
- package/dist/cpsat/rule-descriptor.d.ts.map +1 -0
- package/dist/cpsat/rule-descriptor.js +51 -0
- package/dist/cpsat/rule-descriptor.js.map +1 -0
- package/dist/cpsat/rules/artifacts.d.ts +9 -0
- package/dist/cpsat/rules/artifacts.d.ts.map +1 -0
- package/dist/cpsat/rules/artifacts.js +31 -0
- package/dist/cpsat/rules/artifacts.js.map +1 -0
- package/dist/cpsat/rules/assign-together.d.ts +18 -20
- package/dist/cpsat/rules/assign-together.d.ts.map +1 -1
- package/dist/cpsat/rules/assign-together.js +90 -54
- package/dist/cpsat/rules/assign-together.js.map +1 -1
- package/dist/cpsat/rules/assigned-day.d.ts +12 -0
- package/dist/cpsat/rules/assigned-day.d.ts.map +1 -0
- package/dist/cpsat/rules/assigned-day.js +43 -0
- package/dist/cpsat/rules/assigned-day.js.map +1 -0
- package/dist/cpsat/rules/assignment-priority.d.ts +15 -29
- package/dist/cpsat/rules/assignment-priority.d.ts.map +1 -1
- package/dist/cpsat/rules/assignment-priority.js +47 -50
- package/dist/cpsat/rules/assignment-priority.js.map +1 -1
- package/dist/cpsat/rules/assignment-terms.d.ts +6 -0
- package/dist/cpsat/rules/assignment-terms.d.ts.map +1 -0
- package/dist/cpsat/rules/assignment-terms.js +19 -0
- package/dist/cpsat/rules/assignment-terms.js.map +1 -0
- package/dist/cpsat/rules/concurrent-intervals.d.ts +19 -0
- package/dist/cpsat/rules/concurrent-intervals.d.ts.map +1 -0
- package/dist/cpsat/rules/concurrent-intervals.js +57 -0
- package/dist/cpsat/rules/concurrent-intervals.js.map +1 -0
- package/dist/cpsat/rules/cost-utils.d.ts +1 -3
- package/dist/cpsat/rules/cost-utils.d.ts.map +1 -1
- package/dist/cpsat/rules/cost-utils.js +0 -7
- package/dist/cpsat/rules/cost-utils.js.map +1 -1
- package/dist/cpsat/rules/day-cost-multiplier.d.ts +10 -10
- package/dist/cpsat/rules/day-cost-multiplier.d.ts.map +1 -1
- package/dist/cpsat/rules/day-cost-multiplier.js +88 -77
- package/dist/cpsat/rules/day-cost-multiplier.js.map +1 -1
- package/dist/cpsat/rules/day-cost-surcharge.d.ts +10 -10
- package/dist/cpsat/rules/day-cost-surcharge.d.ts.map +1 -1
- package/dist/cpsat/rules/day-cost-surcharge.js +76 -65
- package/dist/cpsat/rules/day-cost-surcharge.js.map +1 -1
- package/dist/cpsat/rules/index.d.ts +30 -21
- package/dist/cpsat/rules/index.d.ts.map +1 -1
- package/dist/cpsat/rules/index.js +30 -21
- package/dist/cpsat/rules/index.js.map +1 -1
- package/dist/cpsat/rules/location-preference.d.ts +14 -21
- package/dist/cpsat/rules/location-preference.d.ts.map +1 -1
- package/dist/cpsat/rules/location-preference.js +45 -45
- package/dist/cpsat/rules/location-preference.js.map +1 -1
- package/dist/cpsat/rules/max-concurrent-assignments.d.ts +46 -0
- package/dist/cpsat/rules/max-concurrent-assignments.d.ts.map +1 -0
- package/dist/cpsat/rules/max-concurrent-assignments.js +121 -0
- package/dist/cpsat/rules/max-concurrent-assignments.js.map +1 -0
- package/dist/cpsat/rules/max-consecutive-days.d.ts +18 -17
- package/dist/cpsat/rules/max-consecutive-days.d.ts.map +1 -1
- package/dist/cpsat/rules/max-consecutive-days.js +67 -66
- package/dist/cpsat/rules/max-consecutive-days.js.map +1 -1
- package/dist/cpsat/rules/max-days-of-week-per-period.d.ts +45 -0
- package/dist/cpsat/rules/max-days-of-week-per-period.d.ts.map +1 -0
- package/dist/cpsat/rules/max-days-of-week-per-period.js +95 -0
- package/dist/cpsat/rules/max-days-of-week-per-period.js.map +1 -0
- package/dist/cpsat/rules/max-days-week.d.ts +30 -0
- package/dist/cpsat/rules/max-days-week.d.ts.map +1 -0
- package/dist/cpsat/rules/max-days-week.js +83 -0
- package/dist/cpsat/rules/max-days-week.js.map +1 -0
- package/dist/cpsat/rules/max-hours-day.d.ts +14 -31
- package/dist/cpsat/rules/max-hours-day.d.ts.map +1 -1
- package/dist/cpsat/rules/max-hours-day.js +56 -72
- package/dist/cpsat/rules/max-hours-day.js.map +1 -1
- package/dist/cpsat/rules/max-hours-week.d.ts +15 -31
- package/dist/cpsat/rules/max-hours-week.d.ts.map +1 -1
- package/dist/cpsat/rules/max-hours-week.js +60 -75
- package/dist/cpsat/rules/max-hours-week.js.map +1 -1
- package/dist/cpsat/rules/max-shifts-day.d.ts +17 -33
- package/dist/cpsat/rules/max-shifts-day.d.ts.map +1 -1
- package/dist/cpsat/rules/max-shifts-day.js +57 -73
- package/dist/cpsat/rules/max-shifts-day.js.map +1 -1
- package/dist/cpsat/rules/min-consecutive-days.d.ts +18 -18
- package/dist/cpsat/rules/min-consecutive-days.d.ts.map +1 -1
- package/dist/cpsat/rules/min-consecutive-days.js +123 -94
- package/dist/cpsat/rules/min-consecutive-days.js.map +1 -1
- package/dist/cpsat/rules/min-days-of-week-per-period.d.ts +35 -0
- package/dist/cpsat/rules/min-days-of-week-per-period.d.ts.map +1 -0
- package/dist/cpsat/rules/min-days-of-week-per-period.js +108 -0
- package/dist/cpsat/rules/min-days-of-week-per-period.js.map +1 -0
- package/dist/cpsat/rules/min-days-week.d.ts +21 -0
- package/dist/cpsat/rules/min-days-week.d.ts.map +1 -0
- package/dist/cpsat/rules/min-days-week.js +95 -0
- package/dist/cpsat/rules/min-days-week.js.map +1 -0
- package/dist/cpsat/rules/min-hours-day.d.ts +14 -17
- package/dist/cpsat/rules/min-hours-day.d.ts.map +1 -1
- package/dist/cpsat/rules/min-hours-day.js +72 -54
- package/dist/cpsat/rules/min-hours-day.js.map +1 -1
- package/dist/cpsat/rules/min-hours-week.d.ts +15 -18
- package/dist/cpsat/rules/min-hours-week.d.ts.map +1 -1
- package/dist/cpsat/rules/min-hours-week.js +75 -57
- package/dist/cpsat/rules/min-hours-week.js.map +1 -1
- package/dist/cpsat/rules/min-rest-between-shifts.d.ts +14 -17
- package/dist/cpsat/rules/min-rest-between-shifts.d.ts.map +1 -1
- package/dist/cpsat/rules/min-rest-between-shifts.js +148 -138
- package/dist/cpsat/rules/min-rest-between-shifts.js.map +1 -1
- package/dist/cpsat/rules/minimize-cost.d.ts +2 -18
- package/dist/cpsat/rules/minimize-cost.d.ts.map +1 -1
- package/dist/cpsat/rules/minimize-cost.js +151 -163
- package/dist/cpsat/rules/minimize-cost.js.map +1 -1
- package/dist/cpsat/rules/must-assign.d.ts +12 -0
- package/dist/cpsat/rules/must-assign.d.ts.map +1 -0
- package/dist/cpsat/rules/must-assign.js +54 -0
- package/dist/cpsat/rules/must-assign.js.map +1 -0
- package/dist/cpsat/rules/overtime-daily-multiplier.d.ts +6 -10
- package/dist/cpsat/rules/overtime-daily-multiplier.d.ts.map +1 -1
- package/dist/cpsat/rules/overtime-daily-multiplier.js +118 -112
- package/dist/cpsat/rules/overtime-daily-multiplier.js.map +1 -1
- package/dist/cpsat/rules/overtime-daily-surcharge.d.ts +6 -11
- package/dist/cpsat/rules/overtime-daily-surcharge.d.ts.map +1 -1
- package/dist/cpsat/rules/overtime-daily-surcharge.js +104 -99
- package/dist/cpsat/rules/overtime-daily-surcharge.js.map +1 -1
- package/dist/cpsat/rules/overtime-tiered-multiplier.d.ts +9 -21
- package/dist/cpsat/rules/overtime-tiered-multiplier.d.ts.map +1 -1
- package/dist/cpsat/rules/overtime-tiered-multiplier.js +181 -199
- package/dist/cpsat/rules/overtime-tiered-multiplier.js.map +1 -1
- package/dist/cpsat/rules/overtime-weekly-multiplier.d.ts +13 -12
- package/dist/cpsat/rules/overtime-weekly-multiplier.d.ts.map +1 -1
- package/dist/cpsat/rules/overtime-weekly-multiplier.js +143 -143
- package/dist/cpsat/rules/overtime-weekly-multiplier.js.map +1 -1
- package/dist/cpsat/rules/overtime-weekly-surcharge.d.ts +7 -11
- package/dist/cpsat/rules/overtime-weekly-surcharge.d.ts.map +1 -1
- package/dist/cpsat/rules/overtime-weekly-surcharge.js +124 -119
- package/dist/cpsat/rules/overtime-weekly-surcharge.js.map +1 -1
- package/dist/cpsat/rules/pattern-eligibility.d.ts +6 -0
- package/dist/cpsat/rules/pattern-eligibility.d.ts.map +1 -0
- package/dist/cpsat/rules/pattern-eligibility.js +16 -0
- package/dist/cpsat/rules/pattern-eligibility.js.map +1 -0
- package/dist/cpsat/rules/pattern-time.d.ts +5 -0
- package/dist/cpsat/rules/pattern-time.d.ts.map +1 -0
- package/dist/cpsat/rules/pattern-time.js +20 -0
- package/dist/cpsat/rules/pattern-time.js.map +1 -0
- package/dist/cpsat/rules/registry.d.ts +217 -27
- package/dist/cpsat/rules/registry.d.ts.map +1 -1
- package/dist/cpsat/rules/registry.js +98 -31
- package/dist/cpsat/rules/registry.js.map +1 -1
- package/dist/cpsat/rules/resolver.d.ts +9 -7
- package/dist/cpsat/rules/resolver.d.ts.map +1 -1
- package/dist/cpsat/rules/resolver.js +19 -18
- package/dist/cpsat/rules/resolver.js.map +1 -1
- package/dist/cpsat/rules/role-preference.d.ts +24 -0
- package/dist/cpsat/rules/role-preference.d.ts.map +1 -0
- package/dist/cpsat/rules/role-preference.js +72 -0
- package/dist/cpsat/rules/role-preference.js.map +1 -0
- package/dist/cpsat/rules/rules.types.d.ts +93 -17
- package/dist/cpsat/rules/rules.types.d.ts.map +1 -1
- package/dist/cpsat/rules/scope.types.d.ts +25 -12
- package/dist/cpsat/rules/scope.types.d.ts.map +1 -1
- package/dist/cpsat/rules/scope.types.js +14 -19
- package/dist/cpsat/rules/scope.types.js.map +1 -1
- package/dist/cpsat/rules/target-days-week.d.ts +31 -0
- package/dist/cpsat/rules/target-days-week.d.ts.map +1 -0
- package/dist/cpsat/rules/target-days-week.js +80 -0
- package/dist/cpsat/rules/target-days-week.js.map +1 -0
- package/dist/cpsat/rules/target-peak-concurrent-assignments.d.ts +33 -0
- package/dist/cpsat/rules/target-peak-concurrent-assignments.d.ts.map +1 -0
- package/dist/cpsat/rules/target-peak-concurrent-assignments.js +146 -0
- package/dist/cpsat/rules/target-peak-concurrent-assignments.js.map +1 -0
- package/dist/cpsat/rules/time-cost-surcharge.d.ts +15 -14
- package/dist/cpsat/rules/time-cost-surcharge.d.ts.map +1 -1
- package/dist/cpsat/rules/time-cost-surcharge.js +82 -96
- package/dist/cpsat/rules/time-cost-surcharge.js.map +1 -1
- package/dist/cpsat/rules/time-off.d.ts +21 -57
- package/dist/cpsat/rules/time-off.d.ts.map +1 -1
- package/dist/cpsat/rules/time-off.js +114 -127
- package/dist/cpsat/rules/time-off.js.map +1 -1
- package/dist/cpsat/rules/variables.d.ts +4 -0
- package/dist/cpsat/rules/variables.d.ts.map +1 -0
- package/dist/cpsat/rules/variables.js +10 -0
- package/dist/cpsat/rules/variables.js.map +1 -0
- package/dist/cpsat/rules.d.ts +20 -3
- package/dist/cpsat/rules.d.ts.map +1 -1
- package/dist/cpsat/rules.js +19 -2
- package/dist/cpsat/rules.js.map +1 -1
- package/dist/cpsat/semantic-time.d.ts +7 -6
- package/dist/cpsat/semantic-time.d.ts.map +1 -1
- package/dist/cpsat/semantic-time.js +15 -28
- package/dist/cpsat/semantic-time.js.map +1 -1
- package/dist/cpsat/types.d.ts +47 -4
- package/dist/cpsat/types.d.ts.map +1 -1
- package/dist/cpsat/types.js +24 -1
- package/dist/cpsat/types.js.map +1 -1
- package/dist/cpsat/utils.d.ts +23 -6
- package/dist/cpsat/utils.d.ts.map +1 -1
- package/dist/cpsat/utils.js +76 -15
- package/dist/cpsat/utils.js.map +1 -1
- package/dist/cpsat/validation-reporter.d.ts +6 -2
- package/dist/cpsat/validation-reporter.d.ts.map +1 -1
- package/dist/cpsat/validation-reporter.js +122 -10
- package/dist/cpsat/validation-reporter.js.map +1 -1
- package/dist/cpsat/validation.types.d.ts +21 -10
- package/dist/cpsat/validation.types.d.ts.map +1 -1
- package/dist/datetime.utils.d.ts +7 -13
- package/dist/datetime.utils.d.ts.map +1 -1
- package/dist/datetime.utils.js +29 -36
- package/dist/datetime.utils.js.map +1 -1
- package/dist/index.d.ts +15 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -4
- package/dist/index.js.map +1 -1
- package/dist/schedule/cost.d.ts +192 -0
- package/dist/schedule/cost.d.ts.map +1 -0
- package/dist/schedule/cost.js +151 -0
- package/dist/schedule/cost.js.map +1 -0
- package/dist/schedule/coverage.d.ts +114 -0
- package/dist/schedule/coverage.d.ts.map +1 -0
- package/dist/schedule/coverage.js +56 -0
- package/dist/schedule/coverage.js.map +1 -0
- package/dist/schedule/definition.d.ts +346 -0
- package/dist/schedule/definition.d.ts.map +1 -0
- package/dist/schedule/definition.js +668 -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 +678 -0
- package/dist/schedule/rules.d.ts.map +1 -0
- package/dist/schedule/rules.js +554 -0
- package/dist/schedule/rules.js.map +1 -0
- package/dist/schedule/shift-patterns.d.ts +17 -0
- package/dist/schedule/shift-patterns.d.ts.map +1 -0
- package/dist/schedule/shift-patterns.js +24 -0
- package/dist/schedule/shift-patterns.js.map +1 -0
- package/dist/schedule/time-periods.d.ts +79 -0
- package/dist/schedule/time-periods.d.ts.map +1 -0
- package/dist/schedule/time-periods.js +101 -0
- package/dist/schedule/time-periods.js.map +1 -0
- package/dist/types.d.ts +67 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +64 -0
- package/dist/types.js.map +1 -1
- package/package.json +8 -14
- package/solver/src/solver/models.py +41 -4
- package/solver/src/solver/solver.py +546 -157
- package/solver/tests/test_solver.py +363 -7
- package/src/client.schemas.ts +127 -10
- package/src/client.ts +3 -0
- package/src/client.types.ts +73 -7
- package/src/cpsat/cost.ts +17 -7
- package/src/cpsat/model-builder.ts +614 -129
- package/src/cpsat/response.ts +57 -13
- package/src/cpsat/rule-descriptor.ts +311 -0
- package/src/cpsat/rules/artifacts.ts +56 -0
- package/src/cpsat/rules/assign-together.ts +104 -69
- package/src/cpsat/rules/assigned-day.ts +70 -0
- package/src/cpsat/rules/assignment-priority.ts +54 -58
- package/src/cpsat/rules/assignment-terms.ts +43 -0
- package/src/cpsat/rules/concurrent-intervals.ts +93 -0
- package/src/cpsat/rules/cost-utils.ts +1 -9
- package/src/cpsat/rules/day-cost-multiplier.ts +101 -81
- package/src/cpsat/rules/day-cost-surcharge.ts +91 -70
- package/src/cpsat/rules/index.ts +30 -21
- package/src/cpsat/rules/location-preference.ts +47 -52
- package/src/cpsat/rules/max-concurrent-assignments.ts +170 -0
- package/src/cpsat/rules/max-consecutive-days.ts +74 -91
- package/src/cpsat/rules/max-days-of-week-per-period.ts +127 -0
- package/src/cpsat/rules/max-days-week.ts +117 -0
- package/src/cpsat/rules/max-hours-day.ts +64 -84
- package/src/cpsat/rules/max-hours-week.ts +74 -90
- package/src/cpsat/rules/max-shifts-day.ts +65 -85
- package/src/cpsat/rules/min-consecutive-days.ts +161 -127
- package/src/cpsat/rules/min-days-of-week-per-period.ts +144 -0
- package/src/cpsat/rules/min-days-week.ts +122 -0
- package/src/cpsat/rules/min-hours-day.ts +79 -58
- package/src/cpsat/rules/min-hours-week.ts +87 -62
- package/src/cpsat/rules/min-rest-between-shifts.ts +191 -178
- package/src/cpsat/rules/minimize-cost.ts +175 -188
- package/src/cpsat/rules/must-assign.ts +71 -0
- package/src/cpsat/rules/overtime-daily-multiplier.ts +158 -140
- package/src/cpsat/rules/overtime-daily-surcharge.ts +141 -126
- package/src/cpsat/rules/overtime-tiered-multiplier.ts +234 -253
- package/src/cpsat/rules/overtime-weekly-multiplier.ts +183 -175
- package/src/cpsat/rules/overtime-weekly-surcharge.ts +161 -150
- package/src/cpsat/rules/pattern-eligibility.ts +26 -0
- package/src/cpsat/rules/pattern-time.ts +30 -0
- package/src/cpsat/rules/registry.ts +140 -56
- package/src/cpsat/rules/resolver.ts +58 -30
- package/src/cpsat/rules/role-preference.ts +92 -0
- package/src/cpsat/rules/rules.types.ts +92 -17
- package/src/cpsat/rules/scope.types.ts +32 -27
- package/src/cpsat/rules/target-days-week.ts +105 -0
- package/src/cpsat/rules/target-peak-concurrent-assignments.ts +212 -0
- package/src/cpsat/rules/time-cost-surcharge.ts +116 -122
- package/src/cpsat/rules/time-off.ts +154 -163
- package/src/cpsat/rules/variables.ts +11 -0
- package/src/cpsat/rules.ts +43 -17
- package/src/cpsat/semantic-time.ts +29 -43
- package/src/cpsat/types.ts +53 -4
- package/src/cpsat/utils.ts +92 -20
- package/src/cpsat/validation-reporter.ts +170 -19
- package/src/cpsat/validation.types.ts +22 -11
- package/src/datetime.utils.ts +45 -44
- package/src/index.ts +72 -15
- package/src/schedule/cost.ts +221 -0
- package/src/schedule/coverage.ts +164 -0
- package/src/schedule/definition.ts +1447 -0
- package/src/schedule/index.ts +132 -0
- package/src/schedule/rules.ts +1028 -0
- package/src/schedule/shift-patterns.ts +29 -0
- package/src/schedule/time-periods.ts +120 -0
- package/src/types.ts +114 -2
- 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 -917
- package/dist/schedule.d.ts.map +0 -1
- package/dist/schedule.js +0 -1323
- package/dist/schedule.js.map +0 -1
- package/llms.txt +0 -758
- package/src/llms.ts +0 -3
- package/src/schedule.ts +0 -1960
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { SchedulingDay } from "../../types.js";
|
|
2
|
+
import type { RuleArtifact } from "../rule-descriptor.js";
|
|
3
|
+
import { boolVariable, hardConstraint, skipValidation } from "./artifacts.js";
|
|
4
|
+
import { assignedDayVariableName } from "./variables.js";
|
|
5
|
+
|
|
6
|
+
export function buildAssignedDayIndicator(params: {
|
|
7
|
+
memberId: string;
|
|
8
|
+
day: SchedulingDay;
|
|
9
|
+
assignmentVars: readonly string[];
|
|
10
|
+
variableName?: string;
|
|
11
|
+
}): { assignedDayVar: string; artifacts: readonly RuleArtifact[] } {
|
|
12
|
+
const assignedDayVar =
|
|
13
|
+
params.variableName ?? assignedDayVariableName(params.memberId, params.day.iso);
|
|
14
|
+
const artifacts: RuleArtifact[] = [boolVariable(assignedDayVar)];
|
|
15
|
+
|
|
16
|
+
if (params.assignmentVars.length === 0) {
|
|
17
|
+
artifacts.push(
|
|
18
|
+
hardConstraint({
|
|
19
|
+
description: `${assignedDayVar} fixed to 0 on ${params.day.iso}`,
|
|
20
|
+
validation: skipValidation(
|
|
21
|
+
"scaffolding",
|
|
22
|
+
"No assignments exist for this member and day, so the derived assigned-day variable is fixed to zero.",
|
|
23
|
+
),
|
|
24
|
+
context: { memberIds: [params.memberId], days: [params.day.iso] },
|
|
25
|
+
terms: [{ var: assignedDayVar, coeff: 1 }],
|
|
26
|
+
comparator: "==",
|
|
27
|
+
targetValue: 0,
|
|
28
|
+
}),
|
|
29
|
+
);
|
|
30
|
+
return { assignedDayVar, artifacts };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
for (const assignVar of params.assignmentVars) {
|
|
34
|
+
artifacts.push(
|
|
35
|
+
hardConstraint({
|
|
36
|
+
description: `${assignedDayVar} covers ${assignVar}`,
|
|
37
|
+
validation: skipValidation(
|
|
38
|
+
"scaffolding",
|
|
39
|
+
"This derived assigned-day variable must turn on whenever one of the day's assignment variables is on.",
|
|
40
|
+
),
|
|
41
|
+
context: { memberIds: [params.memberId], days: [params.day.iso] },
|
|
42
|
+
terms: [
|
|
43
|
+
{ var: assignedDayVar, coeff: 1 },
|
|
44
|
+
{ var: assignVar, coeff: -1 },
|
|
45
|
+
],
|
|
46
|
+
comparator: ">=",
|
|
47
|
+
targetValue: 0,
|
|
48
|
+
}),
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
artifacts.push(
|
|
53
|
+
hardConstraint({
|
|
54
|
+
description: `${assignedDayVar} limited by assignments on ${params.day.iso}`,
|
|
55
|
+
validation: skipValidation(
|
|
56
|
+
"scaffolding",
|
|
57
|
+
"This derived assigned-day variable must stay off unless at least one assignment variable is on.",
|
|
58
|
+
),
|
|
59
|
+
context: { memberIds: [params.memberId], days: [params.day.iso] },
|
|
60
|
+
terms: [
|
|
61
|
+
{ var: assignedDayVar, coeff: 1 },
|
|
62
|
+
...params.assignmentVars.map((varName) => ({ var: varName, coeff: -1 })),
|
|
63
|
+
],
|
|
64
|
+
comparator: "<=",
|
|
65
|
+
targetValue: 0,
|
|
66
|
+
}),
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
return { assignedDayVar, artifacts };
|
|
70
|
+
}
|
|
@@ -1,80 +1,76 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import { defineRuleDescriptor } from "../rule-descriptor.js";
|
|
3
|
+
import { PREFERENCE_WEIGHTS } from "../utils.js";
|
|
4
4
|
import {
|
|
5
|
+
PrioritySchema,
|
|
5
6
|
entityScope,
|
|
6
|
-
timeScope,
|
|
7
7
|
parseEntityScope,
|
|
8
8
|
parseTimeScope,
|
|
9
|
-
resolveMembersFromScope,
|
|
10
9
|
resolveActiveDaysFromScope,
|
|
10
|
+
resolveMembersFromScope,
|
|
11
|
+
timeScope,
|
|
11
12
|
} from "./scope.types.js";
|
|
13
|
+
import { skipValidation } from "./artifacts.js";
|
|
14
|
+
import { assignmentVar } from "./variables.js";
|
|
15
|
+
import { canAssignMemberToPattern, isPatternAvailableOnDay } from "./pattern-eligibility.js";
|
|
12
16
|
|
|
13
|
-
const AssignmentPrioritySchema = z
|
|
17
|
+
export const AssignmentPrioritySchema = z
|
|
14
18
|
.object({
|
|
15
|
-
preference: z.union([z.literal("
|
|
19
|
+
preference: z.union([z.literal("prefer"), z.literal("avoid")]),
|
|
20
|
+
priority: PrioritySchema.optional(),
|
|
16
21
|
})
|
|
17
22
|
.and(entityScope(["members", "roles", "skills"]))
|
|
18
23
|
.and(timeScope(["dateRange", "specificDates", "dayOfWeek", "recurring"]));
|
|
19
24
|
|
|
20
25
|
/**
|
|
21
|
-
* Configuration for {@link
|
|
22
|
-
*
|
|
23
|
-
* - `preference` (required): `"high"` to prefer assigning or `"low"` to avoid assigning
|
|
24
|
-
*
|
|
25
|
-
* Entity scoping (at most one): `memberIds`, `roleIds`, `skillIds`
|
|
26
|
-
* Time scoping (at most one, optional): `dateRange`, `specificDates`, `dayOfWeek`, `recurringPeriods`
|
|
26
|
+
* Configuration for {@link assignmentPriorityRuleDescriptor}.
|
|
27
27
|
*/
|
|
28
28
|
export type AssignmentPriorityConfig = z.infer<typeof AssignmentPrioritySchema>;
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* @param config - See {@link AssignmentPriorityConfig}
|
|
34
|
-
* @example Prefer specific team members
|
|
35
|
-
* ```ts
|
|
36
|
-
* createAssignmentPriorityRule({
|
|
37
|
-
* memberIds: ["alice", "bob"],
|
|
38
|
-
* preference: "high",
|
|
39
|
-
* });
|
|
40
|
-
* ```
|
|
31
|
+
* Low-level descriptor for assignment priority rules.
|
|
41
32
|
*
|
|
42
|
-
* @
|
|
43
|
-
* ```ts
|
|
44
|
-
* createAssignmentPriorityRule({
|
|
45
|
-
* roleIds: ["student"],
|
|
46
|
-
* dayOfWeek: ["monday", "tuesday", "wednesday", "thursday", "friday"],
|
|
47
|
-
* preference: "low",
|
|
48
|
-
* });
|
|
49
|
-
* ```
|
|
33
|
+
* @category Rules
|
|
50
34
|
*/
|
|
51
|
-
export
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
35
|
+
export const assignmentPriorityRuleDescriptor = defineRuleDescriptor({
|
|
36
|
+
name: "assignment-priority",
|
|
37
|
+
schema: AssignmentPrioritySchema,
|
|
38
|
+
compile(config, ctx) {
|
|
39
|
+
const { preference } = config;
|
|
40
|
+
const priority = config.priority ?? "MANDATORY";
|
|
41
|
+
const entityScopeValue = parseEntityScope(config);
|
|
42
|
+
const timeScopeValue = parseTimeScope(config);
|
|
43
|
+
const targetMembers = resolveMembersFromScope(entityScopeValue, [...ctx.members]);
|
|
44
|
+
const activeDays = resolveActiveDaysFromScope(timeScopeValue, [...ctx.days]);
|
|
45
|
+
const baseWeight = PREFERENCE_WEIGHTS[priority as keyof typeof PREFERENCE_WEIGHTS] ?? 0;
|
|
46
|
+
if (targetMembers.length === 0 || activeDays.length === 0 || baseWeight === 0) {
|
|
47
|
+
return { rule: "assignment-priority", artifacts: [] };
|
|
48
|
+
}
|
|
63
49
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
50
|
+
const weight = preference === "prefer" ? -baseWeight : baseWeight;
|
|
51
|
+
const terms = targetMembers.flatMap((member) =>
|
|
52
|
+
ctx.shiftPatterns.flatMap((pattern) => {
|
|
53
|
+
if (!canAssignMemberToPattern(member, pattern)) return [];
|
|
54
|
+
return activeDays
|
|
55
|
+
.filter((day) => isPatternAvailableOnDay(pattern, day))
|
|
56
|
+
.map((day) => ({ var: assignmentVar(member.id, pattern.id, day.iso), coeff: weight }));
|
|
57
|
+
}),
|
|
58
|
+
);
|
|
68
59
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
60
|
+
return {
|
|
61
|
+
rule: "assignment-priority",
|
|
62
|
+
artifacts: [
|
|
63
|
+
{
|
|
64
|
+
kind: "objective",
|
|
65
|
+
terms,
|
|
66
|
+
validation: skipValidation(
|
|
67
|
+
"no-meaningful-feedback",
|
|
68
|
+
terms.length === 0
|
|
69
|
+
? "Assignment priority produced no objective terms for the selected scope."
|
|
70
|
+
: "Preference rules influence the objective but do not emit validation feedback.",
|
|
71
|
+
),
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { SchedulingDay } from "../../types.js";
|
|
2
|
+
import type { SchedulingMember, ShiftPattern, Term } from "../types.js";
|
|
3
|
+
import { canAssignMemberToPattern, isPatternAvailableOnDay } from "./pattern-eligibility.js";
|
|
4
|
+
import { assignmentVar } from "./variables.js";
|
|
5
|
+
|
|
6
|
+
export function assignmentVarsForDay(
|
|
7
|
+
member: SchedulingMember,
|
|
8
|
+
day: SchedulingDay,
|
|
9
|
+
shiftPatterns: readonly ShiftPattern[],
|
|
10
|
+
): string[] {
|
|
11
|
+
return shiftPatterns
|
|
12
|
+
.filter(
|
|
13
|
+
(pattern) =>
|
|
14
|
+
canAssignMemberToPattern(member, pattern) && isPatternAvailableOnDay(pattern, day),
|
|
15
|
+
)
|
|
16
|
+
.map((pattern) => assignmentVar(member.id, pattern.id, day.iso));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function assignmentTermsForDay(
|
|
20
|
+
member: SchedulingMember,
|
|
21
|
+
day: SchedulingDay,
|
|
22
|
+
shiftPatterns: readonly ShiftPattern[],
|
|
23
|
+
coeffForPattern: (pattern: ShiftPattern) => number,
|
|
24
|
+
): Term[] {
|
|
25
|
+
return shiftPatterns
|
|
26
|
+
.filter(
|
|
27
|
+
(pattern) =>
|
|
28
|
+
canAssignMemberToPattern(member, pattern) && isPatternAvailableOnDay(pattern, day),
|
|
29
|
+
)
|
|
30
|
+
.map((pattern) => ({
|
|
31
|
+
var: assignmentVar(member.id, pattern.id, day.iso),
|
|
32
|
+
coeff: coeffForPattern(pattern),
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function assignmentTermsForDays(
|
|
37
|
+
member: SchedulingMember,
|
|
38
|
+
days: readonly SchedulingDay[],
|
|
39
|
+
shiftPatterns: readonly ShiftPattern[],
|
|
40
|
+
coeffForPattern: (pattern: ShiftPattern) => number,
|
|
41
|
+
): Term[] {
|
|
42
|
+
return days.flatMap((day) => assignmentTermsForDay(member, day, shiftPatterns, coeffForPattern));
|
|
43
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { SchedulingDay } from "../../types.js";
|
|
2
|
+
import type { SchedulingMember, ShiftPattern } from "../types.js";
|
|
3
|
+
import { MINUTES_PER_DAY, normalizeEndMinutes, timeOfDayToMinutes } from "../utils.js";
|
|
4
|
+
import { canAssignMemberToPattern, isPatternAvailableOnDay } from "./pattern-eligibility.js";
|
|
5
|
+
import { assignmentVar } from "./variables.js";
|
|
6
|
+
|
|
7
|
+
export interface ConcurrentAssignmentInterval {
|
|
8
|
+
readonly start: number;
|
|
9
|
+
readonly end: number;
|
|
10
|
+
readonly varName: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface ConcurrentAssignmentSegment {
|
|
14
|
+
readonly start: number;
|
|
15
|
+
readonly end: number;
|
|
16
|
+
readonly varNames: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function collectConcurrentAssignmentIntervals(
|
|
20
|
+
day: SchedulingDay,
|
|
21
|
+
targetMembers: readonly SchedulingMember[],
|
|
22
|
+
shiftPatterns: readonly ShiftPattern[],
|
|
23
|
+
): ConcurrentAssignmentInterval[] {
|
|
24
|
+
const intervals: ConcurrentAssignmentInterval[] = [];
|
|
25
|
+
|
|
26
|
+
for (const pattern of shiftPatterns) {
|
|
27
|
+
if (!isPatternAvailableOnDay(pattern, day)) continue;
|
|
28
|
+
|
|
29
|
+
const start = timeOfDayToMinutes(pattern.startTime);
|
|
30
|
+
const end = normalizeEndMinutes(start, timeOfDayToMinutes(pattern.endTime));
|
|
31
|
+
|
|
32
|
+
for (const member of targetMembers) {
|
|
33
|
+
if (!canAssignMemberToPattern(member, pattern)) continue;
|
|
34
|
+
intervals.push({
|
|
35
|
+
start,
|
|
36
|
+
end,
|
|
37
|
+
varName: assignmentVar(member.id, pattern.id, day.iso),
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return intervals;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function resolveConcurrentWindow(
|
|
46
|
+
intervals: readonly ConcurrentAssignmentInterval[],
|
|
47
|
+
startMinutes?: number,
|
|
48
|
+
endMinutes?: number,
|
|
49
|
+
): { start: number; end: number } {
|
|
50
|
+
const start = startMinutes ?? 0;
|
|
51
|
+
if (endMinutes !== undefined) {
|
|
52
|
+
return { start, end: endMinutes };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const latestEnd = intervals.reduce((maxEnd, interval) => Math.max(maxEnd, interval.end), 0);
|
|
56
|
+
return { start, end: Math.max(MINUTES_PER_DAY, latestEnd) };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function buildConcurrentAssignmentSegments(
|
|
60
|
+
intervals: readonly ConcurrentAssignmentInterval[],
|
|
61
|
+
windowStart: number,
|
|
62
|
+
windowEnd: number,
|
|
63
|
+
): ConcurrentAssignmentSegment[] {
|
|
64
|
+
const boundaries = new Set<number>([windowStart, windowEnd]);
|
|
65
|
+
|
|
66
|
+
for (const interval of intervals) {
|
|
67
|
+
const start = Math.max(interval.start, windowStart);
|
|
68
|
+
const end = Math.min(interval.end, windowEnd);
|
|
69
|
+
if (start >= end) continue;
|
|
70
|
+
|
|
71
|
+
boundaries.add(start);
|
|
72
|
+
boundaries.add(end);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const sortedBoundaries = [...boundaries].toSorted((left, right) => left - right);
|
|
76
|
+
const segments: ConcurrentAssignmentSegment[] = [];
|
|
77
|
+
|
|
78
|
+
for (let index = 0; index < sortedBoundaries.length - 1; index++) {
|
|
79
|
+
const start = sortedBoundaries[index];
|
|
80
|
+
const end = sortedBoundaries[index + 1];
|
|
81
|
+
if (start === undefined || end === undefined || start >= end) continue;
|
|
82
|
+
|
|
83
|
+
const varNames = intervals
|
|
84
|
+
.filter((interval) => interval.start < end && interval.end > start)
|
|
85
|
+
.map((interval) => interval.varName);
|
|
86
|
+
|
|
87
|
+
if (varNames.length === 0) continue;
|
|
88
|
+
|
|
89
|
+
segments.push({ start, end, varNames });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return segments;
|
|
93
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { SchedulingMember
|
|
2
|
-
import { timeOfDayToMinutes, normalizeEndMinutes } from "../utils.js";
|
|
1
|
+
import type { SchedulingMember } from "../types.js";
|
|
3
2
|
|
|
4
3
|
/** Returns the hourly rate for a member, or undefined if not hourly. */
|
|
5
4
|
export function getHourlyRate(member: SchedulingMember): number | undefined {
|
|
@@ -16,10 +15,3 @@ export function getSalariedPay(
|
|
|
16
15
|
if ("annual" in member.pay) return member.pay;
|
|
17
16
|
return undefined;
|
|
18
17
|
}
|
|
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
|
-
}
|
|
@@ -1,113 +1,133 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
-
import
|
|
3
|
-
import type {
|
|
4
|
-
import type { ShiftAssignment } from "../response.js";
|
|
2
|
+
import { defineRuleDescriptor } from "../rule-descriptor.js";
|
|
3
|
+
import type { CostArtifact } from "../rule-descriptor.js";
|
|
5
4
|
import { COST_CATEGORY } from "../cost.js";
|
|
6
5
|
import {
|
|
7
6
|
entityScope,
|
|
8
|
-
timeScope,
|
|
9
7
|
parseEntityScope,
|
|
10
8
|
parseTimeScope,
|
|
11
|
-
resolveMembersFromScope,
|
|
12
9
|
resolveActiveDaysFromScope,
|
|
10
|
+
resolveMembersFromScope,
|
|
11
|
+
timeScope,
|
|
13
12
|
} from "./scope.types.js";
|
|
14
|
-
import { getHourlyRate
|
|
13
|
+
import { getHourlyRate } from "./cost-utils.js";
|
|
14
|
+
import { patternDurationMinutes } from "./pattern-time.js";
|
|
15
15
|
|
|
16
|
-
const DayCostMultiplierSchema = z
|
|
16
|
+
export const DayCostMultiplierSchema = z
|
|
17
17
|
.object({
|
|
18
18
|
factor: z.number().min(1),
|
|
19
19
|
})
|
|
20
20
|
.and(entityScope(["members", "roles", "skills"]))
|
|
21
21
|
.and(timeScope(["dateRange", "specificDates", "dayOfWeek", "recurring"]));
|
|
22
22
|
|
|
23
|
-
/** Configuration for {@link
|
|
23
|
+
/** Configuration for {@link dayCostMultiplierRuleDescriptor}. */
|
|
24
24
|
export type DayCostMultiplierConfig = z.infer<typeof DayCostMultiplierSchema>;
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* Low-level descriptor for the `day-cost-multiplier` rule.
|
|
28
28
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
29
|
+
* @remarks
|
|
30
|
+
* This artifact always contributes to post-solve cost calculation. It only adds
|
|
31
|
+
* solver objective terms when `minimize-cost` is active.
|
|
31
32
|
*
|
|
32
|
-
*
|
|
33
|
-
* but the `cost()` method still contributes to post-solve calculation.
|
|
33
|
+
* @category Rules
|
|
34
34
|
*/
|
|
35
|
-
export
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
export const dayCostMultiplierRuleDescriptor = defineRuleDescriptor({
|
|
36
|
+
name: "day-cost-multiplier",
|
|
37
|
+
schema: DayCostMultiplierSchema,
|
|
38
|
+
compile(config) {
|
|
39
|
+
const { factor } = config;
|
|
40
|
+
const entityScopeValue = parseEntityScope(config);
|
|
41
|
+
const timeScopeValue = parseTimeScope(config);
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
const validation = {
|
|
44
|
+
strategy: "skip" as const,
|
|
45
|
+
category: "no-meaningful-feedback" as const,
|
|
46
|
+
rationale:
|
|
47
|
+
factor <= 1
|
|
48
|
+
? "A 1x multiplier does not change optimization or cost accounting."
|
|
49
|
+
: "Day cost multipliers only affect optimization when minimize-cost is active.",
|
|
50
|
+
};
|
|
45
51
|
|
|
46
|
-
|
|
47
|
-
|
|
52
|
+
const costArtifact: CostArtifact = {
|
|
53
|
+
kind: "cost",
|
|
54
|
+
validation,
|
|
55
|
+
compileObjective(builder) {
|
|
56
|
+
if (!builder.costContext?.active || factor <= 1) return;
|
|
48
57
|
|
|
49
|
-
|
|
58
|
+
const targetMembers = resolveMembersFromScope(entityScopeValue, builder.members);
|
|
59
|
+
const activeDays = resolveActiveDaysFromScope(timeScopeValue, builder.days);
|
|
60
|
+
if (targetMembers.length === 0 || activeDays.length === 0) return;
|
|
50
61
|
|
|
51
|
-
|
|
52
|
-
|
|
62
|
+
const { normalizationFactor } = builder.costContext;
|
|
63
|
+
const extraFactor = factor - 1;
|
|
53
64
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
for (const member of targetMembers) {
|
|
66
|
+
const rate = getHourlyRate(member);
|
|
67
|
+
if (rate === undefined) continue;
|
|
68
|
+
for (const pattern of builder.shiftPatterns) {
|
|
69
|
+
if (!builder.canAssign(member, pattern)) continue;
|
|
70
|
+
for (const day of activeDays) {
|
|
71
|
+
if (!builder.patternAvailableOnDay(pattern, day)) continue;
|
|
72
|
+
const duration = patternDurationMinutes(pattern);
|
|
73
|
+
const extraCost = (rate * extraFactor * duration) / 60;
|
|
74
|
+
const normalizedPenalty = extraCost / normalizationFactor;
|
|
75
|
+
builder.addPenalty(
|
|
76
|
+
builder.assignment(member.id, pattern.id, day),
|
|
77
|
+
Math.max(1, normalizedPenalty),
|
|
78
|
+
);
|
|
79
|
+
}
|
|
66
80
|
}
|
|
67
81
|
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
cost(
|
|
72
|
-
assignments: ShiftAssignment[],
|
|
73
|
-
members: ReadonlyArray<SchedulingMember>,
|
|
74
|
-
shiftPatterns: ReadonlyArray<ShiftPattern>,
|
|
75
|
-
): CostContribution {
|
|
76
|
-
if (factor <= 1) return { entries: [] };
|
|
82
|
+
},
|
|
83
|
+
calculateCost(assignments, costContext) {
|
|
84
|
+
if (factor <= 1) return { entries: [] };
|
|
77
85
|
|
|
78
|
-
|
|
79
|
-
|
|
86
|
+
const memberMap = new Map(costContext.members.map((member) => [member.id, member]));
|
|
87
|
+
const patternMap = new Map(
|
|
88
|
+
costContext.shiftPatterns.map((pattern) => [pattern.id, pattern]),
|
|
89
|
+
);
|
|
90
|
+
const activeDays = new Set(
|
|
91
|
+
resolveActiveDaysFromScope(timeScopeValue, [...costContext.days]).map((day) => day.iso),
|
|
92
|
+
);
|
|
93
|
+
const targetMemberIds = new Set(
|
|
94
|
+
resolveMembersFromScope(entityScopeValue, [...costContext.members]).map(
|
|
95
|
+
(member) => member.id,
|
|
96
|
+
),
|
|
97
|
+
);
|
|
98
|
+
const extraFactor = factor - 1;
|
|
80
99
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
100
|
+
const entries = [] as Array<{
|
|
101
|
+
memberId: string;
|
|
102
|
+
day: string;
|
|
103
|
+
category: string;
|
|
104
|
+
amount: number;
|
|
105
|
+
}>;
|
|
106
|
+
for (const assignment of assignments) {
|
|
107
|
+
if (!activeDays.has(assignment.day) || !targetMemberIds.has(assignment.memberId))
|
|
108
|
+
continue;
|
|
109
|
+
const member = memberMap.get(assignment.memberId);
|
|
110
|
+
if (!member) continue;
|
|
111
|
+
const rate = getHourlyRate(member);
|
|
112
|
+
if (rate === undefined) continue;
|
|
113
|
+
const pattern = patternMap.get(assignment.shiftPatternId);
|
|
114
|
+
if (!pattern) continue;
|
|
115
|
+
const duration = patternDurationMinutes(pattern);
|
|
116
|
+
entries.push({
|
|
117
|
+
memberId: assignment.memberId,
|
|
118
|
+
day: assignment.day,
|
|
119
|
+
category: COST_CATEGORY.PREMIUM,
|
|
120
|
+
amount: (rate * extraFactor * duration) / 60,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
90
123
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const emp = empMap.get(a.memberId);
|
|
95
|
-
if (!emp) continue;
|
|
96
|
-
const rate = getHourlyRate(emp);
|
|
97
|
-
if (rate === undefined) continue;
|
|
98
|
-
const pattern = patternMap.get(a.shiftPatternId);
|
|
99
|
-
if (!pattern) continue;
|
|
100
|
-
const duration = patternDurationMinutes(pattern);
|
|
101
|
-
const amount = (rate * extraFactor * duration) / 60;
|
|
102
|
-
entries.push({
|
|
103
|
-
memberId: a.memberId,
|
|
104
|
-
day: a.day,
|
|
105
|
-
category: COST_CATEGORY.PREMIUM,
|
|
106
|
-
amount,
|
|
107
|
-
});
|
|
108
|
-
}
|
|
124
|
+
return { entries };
|
|
125
|
+
},
|
|
126
|
+
};
|
|
109
127
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
128
|
+
return {
|
|
129
|
+
rule: "day-cost-multiplier",
|
|
130
|
+
artifacts: [costArtifact],
|
|
131
|
+
};
|
|
132
|
+
},
|
|
133
|
+
});
|