dabke 0.78.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 +120 -0
- package/LICENSE +21 -0
- package/README.md +187 -0
- package/dist/client.d.ts +14 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +42 -0
- package/dist/client.js.map +1 -0
- package/dist/client.schemas.d.ts +250 -0
- package/dist/client.schemas.d.ts.map +1 -0
- package/dist/client.schemas.js +137 -0
- package/dist/client.schemas.js.map +1 -0
- package/dist/client.types.d.ts +34 -0
- package/dist/client.types.d.ts.map +1 -0
- package/dist/client.types.js +18 -0
- package/dist/client.types.js.map +1 -0
- package/dist/cpsat/model-builder.d.ts +128 -0
- package/dist/cpsat/model-builder.d.ts.map +1 -0
- package/dist/cpsat/model-builder.js +640 -0
- package/dist/cpsat/model-builder.js.map +1 -0
- package/dist/cpsat/response.d.ts +74 -0
- package/dist/cpsat/response.d.ts.map +1 -0
- package/dist/cpsat/response.js +92 -0
- package/dist/cpsat/response.js.map +1 -0
- package/dist/cpsat/rules/assign-together.d.ts +23 -0
- package/dist/cpsat/rules/assign-together.d.ts.map +1 -0
- package/dist/cpsat/rules/assign-together.js +78 -0
- package/dist/cpsat/rules/assign-together.js.map +1 -0
- package/dist/cpsat/rules/employee-assignment-priority.d.ts +64 -0
- package/dist/cpsat/rules/employee-assignment-priority.d.ts.map +1 -0
- package/dist/cpsat/rules/employee-assignment-priority.js +151 -0
- package/dist/cpsat/rules/employee-assignment-priority.js.map +1 -0
- package/dist/cpsat/rules/index.d.ts +13 -0
- package/dist/cpsat/rules/index.d.ts.map +1 -0
- package/dist/cpsat/rules/index.js +13 -0
- package/dist/cpsat/rules/index.js.map +1 -0
- package/dist/cpsat/rules/location-preference.d.ts +29 -0
- package/dist/cpsat/rules/location-preference.d.ts.map +1 -0
- package/dist/cpsat/rules/location-preference.js +59 -0
- package/dist/cpsat/rules/location-preference.js.map +1 -0
- package/dist/cpsat/rules/max-consecutive-days.d.ts +28 -0
- package/dist/cpsat/rules/max-consecutive-days.d.ts.map +1 -0
- package/dist/cpsat/rules/max-consecutive-days.js +70 -0
- package/dist/cpsat/rules/max-consecutive-days.js.map +1 -0
- package/dist/cpsat/rules/max-hours-day.d.ts +57 -0
- package/dist/cpsat/rules/max-hours-day.d.ts.map +1 -0
- package/dist/cpsat/rules/max-hours-day.js +159 -0
- package/dist/cpsat/rules/max-hours-day.js.map +1 -0
- package/dist/cpsat/rules/max-hours-week.d.ts +62 -0
- package/dist/cpsat/rules/max-hours-week.d.ts.map +1 -0
- package/dist/cpsat/rules/max-hours-week.js +169 -0
- package/dist/cpsat/rules/max-hours-week.js.map +1 -0
- package/dist/cpsat/rules/max-shifts-day.d.ts +69 -0
- package/dist/cpsat/rules/max-shifts-day.d.ts.map +1 -0
- package/dist/cpsat/rules/max-shifts-day.js +170 -0
- package/dist/cpsat/rules/max-shifts-day.js.map +1 -0
- package/dist/cpsat/rules/min-consecutive-days.d.ts +29 -0
- package/dist/cpsat/rules/min-consecutive-days.d.ts.map +1 -0
- package/dist/cpsat/rules/min-consecutive-days.js +104 -0
- package/dist/cpsat/rules/min-consecutive-days.js.map +1 -0
- package/dist/cpsat/rules/min-hours-day.d.ts +28 -0
- package/dist/cpsat/rules/min-hours-day.d.ts.map +1 -0
- package/dist/cpsat/rules/min-hours-day.js +61 -0
- package/dist/cpsat/rules/min-hours-day.js.map +1 -0
- package/dist/cpsat/rules/min-hours-week.d.ts +29 -0
- package/dist/cpsat/rules/min-hours-week.d.ts.map +1 -0
- package/dist/cpsat/rules/min-hours-week.js +68 -0
- package/dist/cpsat/rules/min-hours-week.js.map +1 -0
- package/dist/cpsat/rules/min-rest-between-shifts.d.ts +28 -0
- package/dist/cpsat/rules/min-rest-between-shifts.d.ts.map +1 -0
- package/dist/cpsat/rules/min-rest-between-shifts.js +95 -0
- package/dist/cpsat/rules/min-rest-between-shifts.js.map +1 -0
- package/dist/cpsat/rules/registry.d.ts +7 -0
- package/dist/cpsat/rules/registry.d.ts.map +1 -0
- package/dist/cpsat/rules/registry.js +28 -0
- package/dist/cpsat/rules/registry.js.map +1 -0
- package/dist/cpsat/rules/resolver.d.ts +31 -0
- package/dist/cpsat/rules/resolver.d.ts.map +1 -0
- package/dist/cpsat/rules/resolver.js +124 -0
- package/dist/cpsat/rules/resolver.js.map +1 -0
- package/dist/cpsat/rules/rules.types.d.ts +32 -0
- package/dist/cpsat/rules/rules.types.d.ts.map +1 -0
- package/dist/cpsat/rules/rules.types.js +2 -0
- package/dist/cpsat/rules/rules.types.js.map +1 -0
- package/dist/cpsat/rules/scoping.d.ts +129 -0
- package/dist/cpsat/rules/scoping.d.ts.map +1 -0
- package/dist/cpsat/rules/scoping.js +190 -0
- package/dist/cpsat/rules/scoping.js.map +1 -0
- package/dist/cpsat/rules/time-off.d.ts +78 -0
- package/dist/cpsat/rules/time-off.d.ts.map +1 -0
- package/dist/cpsat/rules/time-off.js +261 -0
- package/dist/cpsat/rules/time-off.js.map +1 -0
- package/dist/cpsat/rules.d.ts +5 -0
- package/dist/cpsat/rules.d.ts.map +1 -0
- package/dist/cpsat/rules.js +4 -0
- package/dist/cpsat/rules.js.map +1 -0
- package/dist/cpsat/semantic-time.d.ts +198 -0
- package/dist/cpsat/semantic-time.d.ts.map +1 -0
- package/dist/cpsat/semantic-time.js +222 -0
- package/dist/cpsat/semantic-time.js.map +1 -0
- package/dist/cpsat/types.d.ts +180 -0
- package/dist/cpsat/types.d.ts.map +1 -0
- package/dist/cpsat/types.js +2 -0
- package/dist/cpsat/types.js.map +1 -0
- package/dist/cpsat/utils.d.ts +47 -0
- package/dist/cpsat/utils.d.ts.map +1 -0
- package/dist/cpsat/utils.js +92 -0
- package/dist/cpsat/utils.js.map +1 -0
- package/dist/cpsat/validation-reporter.d.ts +54 -0
- package/dist/cpsat/validation-reporter.d.ts.map +1 -0
- package/dist/cpsat/validation-reporter.js +261 -0
- package/dist/cpsat/validation-reporter.js.map +1 -0
- package/dist/cpsat/validation.types.d.ts +141 -0
- package/dist/cpsat/validation.types.d.ts.map +1 -0
- package/dist/cpsat/validation.types.js +14 -0
- package/dist/cpsat/validation.types.js.map +1 -0
- package/dist/datetime.utils.d.ts +245 -0
- package/dist/datetime.utils.d.ts.map +1 -0
- package/dist/datetime.utils.js +372 -0
- package/dist/datetime.utils.js.map +1 -0
- package/dist/errors.d.ts +12 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +17 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +112 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +116 -0
- package/dist/index.js.map +1 -0
- package/dist/llms.d.ts +5 -0
- package/dist/llms.d.ts.map +1 -0
- package/dist/llms.js +8 -0
- package/dist/llms.js.map +1 -0
- package/dist/testing/index.d.ts +12 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +11 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/solver-container.d.ts +49 -0
- package/dist/testing/solver-container.d.ts.map +1 -0
- package/dist/testing/solver-container.js +127 -0
- package/dist/testing/solver-container.js.map +1 -0
- package/dist/types.d.ts +155 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +20 -0
- package/dist/types.js.map +1 -0
- package/dist/validation.d.ts +105 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +130 -0
- package/dist/validation.js.map +1 -0
- package/llms.txt +2188 -0
- package/package.json +76 -0
- package/solver/Dockerfile +31 -0
- package/solver/README.md +23 -0
- package/solver/pyproject.toml +28 -0
- package/solver/src/solver/__init__.py +1 -0
- package/solver/src/solver/app.py +24 -0
- package/solver/src/solver/models.py +120 -0
- package/solver/src/solver/solver.py +359 -0
- package/solver/tests/test_solver.py +156 -0
- package/solver/uv.lock +661 -0
- package/src/client.schemas.ts +163 -0
- package/src/client.ts +67 -0
- package/src/client.types.ts +66 -0
- package/src/cpsat/model-builder.ts +858 -0
- package/src/cpsat/response.ts +130 -0
- package/src/cpsat/rules/assign-together.ts +96 -0
- package/src/cpsat/rules/employee-assignment-priority.ts +182 -0
- package/src/cpsat/rules/index.ts +12 -0
- package/src/cpsat/rules/location-preference.ts +68 -0
- package/src/cpsat/rules/max-consecutive-days.ts +98 -0
- package/src/cpsat/rules/max-hours-day.ts +187 -0
- package/src/cpsat/rules/max-hours-week.ts +197 -0
- package/src/cpsat/rules/max-shifts-day.ts +198 -0
- package/src/cpsat/rules/min-consecutive-days.ts +140 -0
- package/src/cpsat/rules/min-hours-day.ts +69 -0
- package/src/cpsat/rules/min-hours-week.ts +77 -0
- package/src/cpsat/rules/min-rest-between-shifts.ts +121 -0
- package/src/cpsat/rules/registry.ts +49 -0
- package/src/cpsat/rules/resolver.ts +181 -0
- package/src/cpsat/rules/rules.types.ts +41 -0
- package/src/cpsat/rules/scoping.ts +340 -0
- package/src/cpsat/rules/time-off.ts +336 -0
- package/src/cpsat/rules.ts +27 -0
- package/src/cpsat/semantic-time.ts +463 -0
- package/src/cpsat/types.ts +194 -0
- package/src/cpsat/utils.ts +105 -0
- package/src/cpsat/validation-reporter.ts +366 -0
- package/src/cpsat/validation.types.ts +185 -0
- package/src/datetime.utils.ts +426 -0
- package/src/errors.ts +17 -0
- package/src/index.ts +289 -0
- package/src/llms.ts +9 -0
- package/src/testing/index.ts +12 -0
- package/src/testing/solver-container.ts +172 -0
- package/src/types.ts +191 -0
- package/src/validation.ts +188 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { priorityToPenalty } from "../utils.js";
|
|
3
|
+
import { withScopes } from "./scoping.js";
|
|
4
|
+
const MinRestBetweenShiftsSchema = withScopes(z.object({
|
|
5
|
+
hours: z.number().min(0),
|
|
6
|
+
priority: z.union([
|
|
7
|
+
z.literal("LOW"),
|
|
8
|
+
z.literal("MEDIUM"),
|
|
9
|
+
z.literal("HIGH"),
|
|
10
|
+
z.literal("MANDATORY"),
|
|
11
|
+
]),
|
|
12
|
+
}), { entities: ["employees", "roles", "skills"], times: [] });
|
|
13
|
+
/**
|
|
14
|
+
* Enforces a minimum rest period between any two shifts a person works.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const rule = createMinRestBetweenShiftsRule({
|
|
19
|
+
* hours: 10,
|
|
20
|
+
* priority: "MANDATORY",
|
|
21
|
+
* });
|
|
22
|
+
* builder = new ModelBuilder({ ...config, rules: [rule] });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export function createMinRestBetweenShiftsRule(config) {
|
|
26
|
+
const { hours, priority, employeeIds } = MinRestBetweenShiftsSchema.parse(config);
|
|
27
|
+
const minMinutes = hours * 60;
|
|
28
|
+
return {
|
|
29
|
+
compile(b) {
|
|
30
|
+
const employees = employeeIds
|
|
31
|
+
? b.employees.filter((e) => employeeIds.includes(e.id))
|
|
32
|
+
: b.employees;
|
|
33
|
+
for (const emp of employees) {
|
|
34
|
+
for (let i = 0; i < b.days.length; i++) {
|
|
35
|
+
const day1 = b.days[i];
|
|
36
|
+
if (!day1)
|
|
37
|
+
continue;
|
|
38
|
+
const checkDays = [day1];
|
|
39
|
+
const nextDay = b.days[i + 1];
|
|
40
|
+
if (nextDay)
|
|
41
|
+
checkDays.push(nextDay);
|
|
42
|
+
for (const pattern1 of b.shiftPatterns) {
|
|
43
|
+
if (!b.canAssign(emp, pattern1))
|
|
44
|
+
continue;
|
|
45
|
+
if (!b.patternAvailableOnDay(pattern1, day1))
|
|
46
|
+
continue;
|
|
47
|
+
const end1 = b.endMinutes(pattern1, day1);
|
|
48
|
+
for (const day2 of checkDays) {
|
|
49
|
+
if (!day2)
|
|
50
|
+
continue;
|
|
51
|
+
for (const pattern2 of b.shiftPatterns) {
|
|
52
|
+
if (!b.canAssign(emp, pattern2))
|
|
53
|
+
continue;
|
|
54
|
+
if (!b.patternAvailableOnDay(pattern2, day2))
|
|
55
|
+
continue;
|
|
56
|
+
if (day1 === day2 && pattern1.id === pattern2.id)
|
|
57
|
+
continue;
|
|
58
|
+
const start2 = b.startMinutes(pattern2, day2);
|
|
59
|
+
const gap = start2 - end1;
|
|
60
|
+
if (gap >= 0 && gap < minMinutes) {
|
|
61
|
+
const var1 = b.assignment(emp.id, pattern1.id, day1);
|
|
62
|
+
const var2 = b.assignment(emp.id, pattern2.id, day2);
|
|
63
|
+
if (priority === "MANDATORY") {
|
|
64
|
+
b.addLinear([
|
|
65
|
+
{ var: var1, coeff: 1 },
|
|
66
|
+
{ var: var2, coeff: 1 },
|
|
67
|
+
], "<=", 1);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const conflictVar = b.boolVar(`rest_conflict_${emp.id}_${pattern1.id}_${day1}_${pattern2.id}_${day2}`);
|
|
71
|
+
b.addLinear([
|
|
72
|
+
{ var: var1, coeff: 1 },
|
|
73
|
+
{ var: var2, coeff: 1 },
|
|
74
|
+
{ var: conflictVar, coeff: -1 },
|
|
75
|
+
], "<=", 1);
|
|
76
|
+
b.addLinear([
|
|
77
|
+
{ var: conflictVar, coeff: 1 },
|
|
78
|
+
{ var: var1, coeff: -1 },
|
|
79
|
+
], "<=", 0);
|
|
80
|
+
b.addLinear([
|
|
81
|
+
{ var: conflictVar, coeff: 1 },
|
|
82
|
+
{ var: var2, coeff: -1 },
|
|
83
|
+
], "<=", 0);
|
|
84
|
+
b.addPenalty(conflictVar, priorityToPenalty(priority));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=min-rest-between-shifts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"min-rest-between-shifts.js","sourceRoot":"","sources":["../../../src/cpsat/rules/min-rest-between-shifts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BuiltInCpsatRuleFactories, CpsatRuleFactories } from "./rules.types.js";
|
|
2
|
+
export declare const builtInCpsatRuleFactories: BuiltInCpsatRuleFactories;
|
|
3
|
+
/**
|
|
4
|
+
* Creates a rule factory map, preventing overriding built-in rules.
|
|
5
|
+
*/
|
|
6
|
+
export declare function createCpsatRuleFactory<F extends CpsatRuleFactories>(factories: F): F;
|
|
7
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/cpsat/rules/registry.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,yBAAyB,EACzB,kBAAkB,EAEnB,MAAM,kBAAkB,CAAC;AAE1B,eAAO,MAAM,yBAAyB,EAAE,yBAavC,CAAC;AAEF;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,kBAAkB,EAAE,SAAS,EAAE,CAAC,GAAG,CAAC,CAUpF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createAssignTogetherRule, createEmployeeAssignmentPriorityRule, createLocationPreferenceRule, createMaxConsecutiveDaysRule, createMaxHoursDayRule, createMaxHoursWeekRule, createMaxShiftsDayRule, createMinConsecutiveDaysRule, createMinHoursDayRule, createMinHoursWeekRule, createMinRestBetweenShiftsRule, createTimeOffRule, } from "./index.js";
|
|
2
|
+
export const builtInCpsatRuleFactories = {
|
|
3
|
+
"assign-together": createAssignTogetherRule,
|
|
4
|
+
"employee-assignment-priority": createEmployeeAssignmentPriorityRule,
|
|
5
|
+
"location-preference": createLocationPreferenceRule,
|
|
6
|
+
"max-consecutive-days": createMaxConsecutiveDaysRule,
|
|
7
|
+
"max-hours-day": createMaxHoursDayRule,
|
|
8
|
+
"max-hours-week": createMaxHoursWeekRule,
|
|
9
|
+
"max-shifts-day": createMaxShiftsDayRule,
|
|
10
|
+
"min-consecutive-days": createMinConsecutiveDaysRule,
|
|
11
|
+
"min-hours-day": createMinHoursDayRule,
|
|
12
|
+
"min-hours-week": createMinHoursWeekRule,
|
|
13
|
+
"min-rest-between-shifts": createMinRestBetweenShiftsRule,
|
|
14
|
+
"time-off": createTimeOffRule,
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Creates a rule factory map, preventing overriding built-in rules.
|
|
18
|
+
*/
|
|
19
|
+
export function createCpsatRuleFactory(factories) {
|
|
20
|
+
for (const name in factories) {
|
|
21
|
+
if (name in builtInCpsatRuleFactories &&
|
|
22
|
+
factories[name] !== builtInCpsatRuleFactories[name]) {
|
|
23
|
+
throw new Error(`Cannot override built-in CP-SAT rule "${name}" in custom factory`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return factories;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/cpsat/rules/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,oCAAoC,EACpC,4BAA4B,EAC5B,4BAA4B,EAC5B,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,4BAA4B,EAC5B,qBAAqB,EACrB,sBAAsB,EACtB,8BAA8B,EAC9B,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAOpB,MAAM,CAAC,MAAM,yBAAyB,GAA8B;IAClE,iBAAiB,EAAE,wBAAwB;IAC3C,8BAA8B,EAAE,oCAAoC;IACpE,qBAAqB,EAAE,4BAA4B;IACnD,sBAAsB,EAAE,4BAA4B;IACpD,eAAe,EAAE,qBAAqB;IACtC,gBAAgB,EAAE,sBAAsB;IACxC,gBAAgB,EAAE,sBAAsB;IACxC,sBAAsB,EAAE,4BAA4B;IACpD,eAAe,EAAE,qBAAqB;IACtC,gBAAgB,EAAE,sBAAsB;IACxC,yBAAyB,EAAE,8BAA8B;IACzD,UAAU,EAAE,iBAAiB;CAC9B,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAA+B,SAAY;IAC/E,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,IACE,IAAI,IAAI,yBAAyB;YACjC,SAAS,CAAC,IAAI,CAAC,KAAK,yBAAyB,CAAC,IAAqB,CAAC,EACpE,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,yCAAyC,IAAI,qBAAqB,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { SchedulingEmployee } from "../types.js";
|
|
2
|
+
import { type EntityScope } from "./scoping.js";
|
|
3
|
+
import type { CpsatRuleConfigEntry, CpsatRuleFactories, CpsatRuleName, CpsatRuleRegistry } from "./rules.types.js";
|
|
4
|
+
import type { CompilationRule } from "../model-builder.js";
|
|
5
|
+
type ResolvedRuleConfigEntry = {
|
|
6
|
+
name: CpsatRuleName;
|
|
7
|
+
config: CpsatRuleRegistry[CpsatRuleName];
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Gets the IDs that match an entity scope.
|
|
11
|
+
* All scope types are expanded to concrete IDs.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getEmployeeIdsForScope(entity: EntityScope, employees: SchedulingEmployee[]): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Resolves overlapping scopes so that more specific scopes override broader ones.
|
|
16
|
+
*
|
|
17
|
+
* Resolution rules:
|
|
18
|
+
* 1. Rules in NON_SCOPED_RULES pass through unchanged (they handle their own logic)
|
|
19
|
+
* 2. Rules with different time scopes coexist (different time windows don't compete)
|
|
20
|
+
* 3. Within the same time scope, rules are sorted by specificity (person > role > skill > global)
|
|
21
|
+
* and then by insertion order (later wins for same specificity, i.e., last insert overrides)
|
|
22
|
+
* 4. More specific rules claim their IDs first; less specific rules get the remainder
|
|
23
|
+
* 5. All scope types (person, role, skill, global) are expanded to explicit IDs
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveRuleScopes(entries: CpsatRuleConfigEntry[], employees: SchedulingEmployee[]): ResolvedRuleConfigEntry[];
|
|
26
|
+
/**
|
|
27
|
+
* Builds CompilationRule instances from named configs, applying scoping resolution.
|
|
28
|
+
*/
|
|
29
|
+
export declare function buildCpsatRules(entries: CpsatRuleConfigEntry[], employees: SchedulingEmployee[], factories?: CpsatRuleFactories): CompilationRule[];
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../../src/cpsat/rules/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAKL,KAAK,WAAW,EAEjB,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EACV,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,KAAK,uBAAuB,GAAG;IAC7B,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,iBAAiB,CAAC,aAAa,CAAC,CAAC;CAC1C,CAAC;AASF;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,kBAAkB,EAAE,GAC9B,MAAM,EAAE,CAuBV;AAOD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,oBAAoB,EAAE,EAC/B,SAAS,EAAE,kBAAkB,EAAE,GAC9B,uBAAuB,EAAE,CA8E3B;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,oBAAoB,EAAE,EAC/B,SAAS,EAAE,kBAAkB,EAAE,EAC/B,SAAS,GAAE,kBAA8C,GACxD,eAAe,EAAE,CAYnB"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { normalizeScope, specificity, subtractIds, timeScopeKey, } from "./scoping.js";
|
|
2
|
+
import { builtInCpsatRuleFactories } from "./registry.js";
|
|
3
|
+
/**
|
|
4
|
+
* Gets the IDs that match an entity scope.
|
|
5
|
+
* All scope types are expanded to concrete IDs.
|
|
6
|
+
*/
|
|
7
|
+
export function getEmployeeIdsForScope(entity, employees) {
|
|
8
|
+
switch (entity.type) {
|
|
9
|
+
case "employees":
|
|
10
|
+
// Filter to only IDs that exist in the team
|
|
11
|
+
const validIds = new Set(employees.map((e) => e.id));
|
|
12
|
+
return entity.employeeIds.filter((id) => validIds.has(id));
|
|
13
|
+
case "roles":
|
|
14
|
+
// Find team members that have any of the specified roles
|
|
15
|
+
return employees
|
|
16
|
+
.filter((e) => e.roleIds.some((r) => entity.roleIds.includes(r)))
|
|
17
|
+
.map((e) => e.id);
|
|
18
|
+
case "skills":
|
|
19
|
+
// Find team members that have any of the specified skills
|
|
20
|
+
return employees
|
|
21
|
+
.filter((e) => e.skillIds?.some((s) => entity.skillIds.includes(s)))
|
|
22
|
+
.map((e) => e.id);
|
|
23
|
+
case "global":
|
|
24
|
+
default:
|
|
25
|
+
return employees.map((e) => e.id);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Rules that don't use standard scoping and should pass through unchanged.
|
|
30
|
+
*/
|
|
31
|
+
const NON_SCOPED_RULES = new Set(["assign-together"]);
|
|
32
|
+
/**
|
|
33
|
+
* Resolves overlapping scopes so that more specific scopes override broader ones.
|
|
34
|
+
*
|
|
35
|
+
* Resolution rules:
|
|
36
|
+
* 1. Rules in NON_SCOPED_RULES pass through unchanged (they handle their own logic)
|
|
37
|
+
* 2. Rules with different time scopes coexist (different time windows don't compete)
|
|
38
|
+
* 3. Within the same time scope, rules are sorted by specificity (person > role > skill > global)
|
|
39
|
+
* and then by insertion order (later wins for same specificity, i.e., last insert overrides)
|
|
40
|
+
* 4. More specific rules claim their IDs first; less specific rules get the remainder
|
|
41
|
+
* 5. All scope types (person, role, skill, global) are expanded to explicit IDs
|
|
42
|
+
*/
|
|
43
|
+
export function resolveRuleScopes(entries, employees) {
|
|
44
|
+
const resolved = [];
|
|
45
|
+
const scopedEntries = [];
|
|
46
|
+
// Separate rules that use scoping from those that don't
|
|
47
|
+
entries.forEach((entry, index) => {
|
|
48
|
+
if (NON_SCOPED_RULES.has(entry.name)) {
|
|
49
|
+
// Pass through unchanged
|
|
50
|
+
resolved.push({ name: entry.name, config: entry.config });
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
scopedEntries.push({ entry, index });
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
if (scopedEntries.length === 0) {
|
|
57
|
+
return resolved;
|
|
58
|
+
}
|
|
59
|
+
// Group scoped entries by (ruleName, timeScopeKey) - different time scopes don't compete
|
|
60
|
+
const grouped = new Map();
|
|
61
|
+
scopedEntries.forEach(({ entry, index }) => {
|
|
62
|
+
const scope = normalizeScope(entry.config, employees);
|
|
63
|
+
const timeKey = timeScopeKey(scope.time);
|
|
64
|
+
const groupKey = `${entry.name}::${timeKey}`;
|
|
65
|
+
const list = grouped.get(groupKey) ?? [];
|
|
66
|
+
list.push({ index, name: entry.name, config: entry.config, scope });
|
|
67
|
+
grouped.set(groupKey, list);
|
|
68
|
+
});
|
|
69
|
+
for (const group of grouped.values()) {
|
|
70
|
+
// Sort by specificity (descending), then by insertion order (descending, later wins)
|
|
71
|
+
const sorted = group
|
|
72
|
+
.map((g) => ({
|
|
73
|
+
...g,
|
|
74
|
+
specificity: specificity(g.scope.entity),
|
|
75
|
+
}))
|
|
76
|
+
.toSorted((a, b) => {
|
|
77
|
+
if (b.specificity !== a.specificity) {
|
|
78
|
+
return b.specificity - a.specificity;
|
|
79
|
+
}
|
|
80
|
+
// Later insertion wins (higher index first)
|
|
81
|
+
return b.index - a.index;
|
|
82
|
+
});
|
|
83
|
+
// Track assigned IDs - all scope types participate in claiming
|
|
84
|
+
const assignedEmployees = new Set();
|
|
85
|
+
for (const entry of sorted) {
|
|
86
|
+
const { entity } = entry.scope;
|
|
87
|
+
// Get IDs for this scope (expands role/skill to concrete IDs)
|
|
88
|
+
const targetIds = getEmployeeIdsForScope(entity, employees);
|
|
89
|
+
// Only claim IDs not already assigned to a more specific rule
|
|
90
|
+
const remaining = subtractIds(targetIds, assignedEmployees);
|
|
91
|
+
if (remaining.length === 0)
|
|
92
|
+
continue;
|
|
93
|
+
// Claim these IDs
|
|
94
|
+
remaining.forEach((id) => assignedEmployees.add(id));
|
|
95
|
+
// Emit resolved config with explicit IDs
|
|
96
|
+
// Remove roleIds/skillIds since we've expanded them to employeeIds
|
|
97
|
+
const { roleIds: _roleIds, skillIds: _skillIds, ...configWithoutEntityScope } = entry.config;
|
|
98
|
+
resolved.push({
|
|
99
|
+
name: entry.name,
|
|
100
|
+
config: {
|
|
101
|
+
...configWithoutEntityScope,
|
|
102
|
+
employeeIds: remaining,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return resolved;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Builds CompilationRule instances from named configs, applying scoping resolution.
|
|
111
|
+
*/
|
|
112
|
+
export function buildCpsatRules(entries, employees, factories = builtInCpsatRuleFactories) {
|
|
113
|
+
if (entries.length === 0)
|
|
114
|
+
return [];
|
|
115
|
+
const resolved = resolveRuleScopes(entries, employees);
|
|
116
|
+
return resolved.map((entry) => {
|
|
117
|
+
const factory = factories[entry.name];
|
|
118
|
+
if (!factory) {
|
|
119
|
+
throw new Error(`Unknown CP-SAT rule "${entry.name}"`);
|
|
120
|
+
}
|
|
121
|
+
return factory(entry.config);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../../src/cpsat/rules/resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { CompilationRule } from "../model-builder.js";
|
|
2
|
+
export type CreateCpsatRuleFunction<TConfig = any> = (config: TConfig) => CompilationRule;
|
|
3
|
+
export interface CpsatRuleRegistry {
|
|
4
|
+
"assign-together": import("./assign-together.js").AssignTogetherConfig;
|
|
5
|
+
"employee-assignment-priority": import("./employee-assignment-priority.js").EmployeeAssignmentPriorityConfig;
|
|
6
|
+
"location-preference": import("./location-preference.js").LocationPreferenceConfig;
|
|
7
|
+
"max-consecutive-days": import("./max-consecutive-days.js").MaxConsecutiveDaysConfig;
|
|
8
|
+
"max-hours-day": import("./max-hours-day.js").MaxHoursDayConfig;
|
|
9
|
+
"max-hours-week": import("./max-hours-week.js").MaxHoursWeekConfig;
|
|
10
|
+
"max-shifts-day": import("./max-shifts-day.js").MaxShiftsDayConfig;
|
|
11
|
+
"min-consecutive-days": import("./min-consecutive-days.js").MinConsecutiveDaysConfig;
|
|
12
|
+
"min-hours-day": import("./min-hours-day.js").MinHoursDayConfig;
|
|
13
|
+
"min-hours-week": import("./min-hours-week.js").MinHoursWeekConfig;
|
|
14
|
+
"min-rest-between-shifts": import("./min-rest-between-shifts.js").MinRestBetweenShiftsConfig;
|
|
15
|
+
"time-off": import("./time-off.js").TimeOffConfig;
|
|
16
|
+
}
|
|
17
|
+
export type CpsatRuleName = keyof CpsatRuleRegistry;
|
|
18
|
+
export type CpsatRuleFactories = {
|
|
19
|
+
[ruleName: string]: CreateCpsatRuleFunction<any>;
|
|
20
|
+
};
|
|
21
|
+
export type BuiltInCpsatRuleFactories = {
|
|
22
|
+
[K in CpsatRuleName]: CreateCpsatRuleFunction<CpsatRuleRegistry[K]>;
|
|
23
|
+
};
|
|
24
|
+
export type InferCpsatRuleConfig<T> = T extends CreateCpsatRuleFunction<infer Config> ? Config : never;
|
|
25
|
+
export type CpsatRuleRegistryFromFactories<F extends CpsatRuleFactories> = {
|
|
26
|
+
[K in keyof F]: InferCpsatRuleConfig<F[K]>;
|
|
27
|
+
};
|
|
28
|
+
export type CpsatRuleConfigEntry<K extends CpsatRuleName = CpsatRuleName> = {
|
|
29
|
+
name: K;
|
|
30
|
+
config: CpsatRuleRegistry[K];
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=rules.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.types.d.ts","sourceRoot":"","sources":["../../../src/cpsat/rules/rules.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,MAAM,uBAAuB,CAAC,OAAO,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,OAAO,KAAK,eAAe,CAAC;AAG1F,MAAM,WAAW,iBAAiB;IAChC,iBAAiB,EAAE,OAAO,sBAAsB,EAAE,oBAAoB,CAAC;IACvE,8BAA8B,EAAE,OAAO,mCAAmC,EAAE,gCAAgC,CAAC;IAC7G,qBAAqB,EAAE,OAAO,0BAA0B,EAAE,wBAAwB,CAAC;IACnF,sBAAsB,EAAE,OAAO,2BAA2B,EAAE,wBAAwB,CAAC;IACrF,eAAe,EAAE,OAAO,oBAAoB,EAAE,iBAAiB,CAAC;IAChE,gBAAgB,EAAE,OAAO,qBAAqB,EAAE,kBAAkB,CAAC;IACnE,gBAAgB,EAAE,OAAO,qBAAqB,EAAE,kBAAkB,CAAC;IACnE,sBAAsB,EAAE,OAAO,2BAA2B,EAAE,wBAAwB,CAAC;IACrF,eAAe,EAAE,OAAO,oBAAoB,EAAE,iBAAiB,CAAC;IAChE,gBAAgB,EAAE,OAAO,qBAAqB,EAAE,kBAAkB,CAAC;IACnE,yBAAyB,EAAE,OAAO,8BAA8B,EAAE,0BAA0B,CAAC;IAC7F,UAAU,EAAE,OAAO,eAAe,EAAE,aAAa,CAAC;CACnD;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,iBAAiB,CAAC;AAEpD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,CAAC,QAAQ,EAAE,MAAM,GAAG,uBAAuB,CAAC,GAAG,CAAC,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;KACrC,CAAC,IAAI,aAAa,GAAG,uBAAuB,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;CACpE,CAAC;AAEF,MAAM,MAAM,oBAAoB,CAAC,CAAC,IAChC,CAAC,SAAS,uBAAuB,CAAC,MAAM,MAAM,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC;AAEnE,MAAM,MAAM,8BAA8B,CAAC,CAAC,SAAS,kBAAkB,IAAI;KACxE,CAAC,IAAI,MAAM,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,IAAI;IAC1E,IAAI,EAAE,CAAC,CAAC;IACR,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;CAC9B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.types.js","sourceRoot":"","sources":["../../../src/cpsat/rules/rules.types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import type { DayOfWeek } from "../../types.js";
|
|
3
|
+
import type { SchedulingEmployee } from "../types.js";
|
|
4
|
+
export type EntityScope = {
|
|
5
|
+
type: "global";
|
|
6
|
+
} | {
|
|
7
|
+
type: "employees";
|
|
8
|
+
employeeIds: string[];
|
|
9
|
+
} | {
|
|
10
|
+
type: "roles";
|
|
11
|
+
roleIds: string[];
|
|
12
|
+
} | {
|
|
13
|
+
type: "skills";
|
|
14
|
+
skillIds: string[];
|
|
15
|
+
};
|
|
16
|
+
export type TimeScope = {
|
|
17
|
+
type: "always";
|
|
18
|
+
} | {
|
|
19
|
+
type: "dateRange";
|
|
20
|
+
start: string;
|
|
21
|
+
end: string;
|
|
22
|
+
} | {
|
|
23
|
+
type: "specificDates";
|
|
24
|
+
dates: string[];
|
|
25
|
+
} | {
|
|
26
|
+
type: "dayOfWeek";
|
|
27
|
+
days: DayOfWeek[];
|
|
28
|
+
} | {
|
|
29
|
+
type: "recurring";
|
|
30
|
+
periods: {
|
|
31
|
+
name: string;
|
|
32
|
+
startMonth: number;
|
|
33
|
+
startDay: number;
|
|
34
|
+
endMonth: number;
|
|
35
|
+
endDay: number;
|
|
36
|
+
}[];
|
|
37
|
+
};
|
|
38
|
+
export interface RuleScope {
|
|
39
|
+
entity: EntityScope;
|
|
40
|
+
time?: TimeScope;
|
|
41
|
+
}
|
|
42
|
+
export interface ScopeConfig {
|
|
43
|
+
employeeIds?: string[];
|
|
44
|
+
roleIds?: string[];
|
|
45
|
+
skillIds?: string[];
|
|
46
|
+
dateRange?: {
|
|
47
|
+
start: string;
|
|
48
|
+
end: string;
|
|
49
|
+
};
|
|
50
|
+
specificDates?: string[];
|
|
51
|
+
dayOfWeek?: DayOfWeek[];
|
|
52
|
+
recurringPeriods?: {
|
|
53
|
+
name: string;
|
|
54
|
+
startMonth: number;
|
|
55
|
+
startDay: number;
|
|
56
|
+
endMonth: number;
|
|
57
|
+
endDay: number;
|
|
58
|
+
}[];
|
|
59
|
+
}
|
|
60
|
+
type SupportedEntities = ReadonlyArray<EntityKey>;
|
|
61
|
+
type SupportedTimes = ReadonlyArray<TimeKey>;
|
|
62
|
+
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">]>;
|
|
63
|
+
type EntityKey = "employees" | "roles" | "skills";
|
|
64
|
+
type TimeKey = "dateRange" | "specificDates" | "dayOfWeek" | "recurring";
|
|
65
|
+
type EntityScopeShape<T extends readonly EntityKey[]> = ("employees" extends T[number] ? {
|
|
66
|
+
employeeIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
67
|
+
} : {}) & ("roles" extends T[number] ? {
|
|
68
|
+
roleIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
69
|
+
} : {}) & ("skills" extends T[number] ? {
|
|
70
|
+
skillIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
71
|
+
} : {});
|
|
72
|
+
type TimeScopeShape<T extends readonly TimeKey[]> = ("dateRange" extends T[number] ? {
|
|
73
|
+
dateRange: z.ZodOptional<z.ZodObject<{
|
|
74
|
+
start: z.ZodString;
|
|
75
|
+
end: z.ZodString;
|
|
76
|
+
}>>;
|
|
77
|
+
} : {}) & ("specificDates" extends T[number] ? {
|
|
78
|
+
specificDates: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
79
|
+
} : {}) & ("dayOfWeek" extends T[number] ? {
|
|
80
|
+
dayOfWeek: z.ZodOptional<z.ZodArray<typeof dayOfWeekSchema>>;
|
|
81
|
+
} : {}) & ("recurring" extends T[number] ? {
|
|
82
|
+
recurringPeriods: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
83
|
+
name: z.ZodString;
|
|
84
|
+
startMonth: z.ZodNumber;
|
|
85
|
+
startDay: z.ZodNumber;
|
|
86
|
+
endMonth: z.ZodNumber;
|
|
87
|
+
endDay: z.ZodNumber;
|
|
88
|
+
}>>>;
|
|
89
|
+
} : {});
|
|
90
|
+
type ScopedShape<T extends z.ZodRawShape, TEntities extends readonly EntityKey[], TTimes extends readonly TimeKey[]> = T & EntityScopeShape<TEntities> & TimeScopeShape<TTimes>;
|
|
91
|
+
type ScopedSchema<T extends z.ZodRawShape, TEntities extends readonly EntityKey[], TTimes extends readonly TimeKey[]> = z.ZodObject<ScopedShape<T, TEntities, TTimes>>;
|
|
92
|
+
type ScopedSchemaWithRefinement<T extends z.ZodRawShape, TEntities extends readonly EntityKey[], TTimes extends readonly TimeKey[]> = ReturnType<ScopedSchema<T, TEntities, TTimes>["superRefine"]>;
|
|
93
|
+
export declare const withScopes: <T extends z.ZodRawShape, TEntities extends SupportedEntities, TTimes extends SupportedTimes>(base: z.ZodObject<T>, opts: {
|
|
94
|
+
entities: TEntities;
|
|
95
|
+
times: TTimes;
|
|
96
|
+
}) => ScopedSchemaWithRefinement<T, TEntities, TTimes>;
|
|
97
|
+
export declare const normalizeScope: (raw: {
|
|
98
|
+
employeeIds?: string[];
|
|
99
|
+
roleIds?: string[];
|
|
100
|
+
skillIds?: string[];
|
|
101
|
+
dateRange?: {
|
|
102
|
+
start: string;
|
|
103
|
+
end: string;
|
|
104
|
+
};
|
|
105
|
+
specificDates?: string[];
|
|
106
|
+
dayOfWeek?: DayOfWeek[];
|
|
107
|
+
recurringPeriods?: {
|
|
108
|
+
name: string;
|
|
109
|
+
startMonth: number;
|
|
110
|
+
startDay: number;
|
|
111
|
+
endMonth: number;
|
|
112
|
+
endDay: number;
|
|
113
|
+
}[];
|
|
114
|
+
}, employees: SchedulingEmployee[]) => RuleScope;
|
|
115
|
+
export declare const specificity: (scope: EntityScope) => number;
|
|
116
|
+
export declare const effectiveEmployeeIds: (scope: EntityScope, employees: SchedulingEmployee[]) => string[];
|
|
117
|
+
export declare const subtractIds: (ids: string[], assigned: Set<string>) => string[];
|
|
118
|
+
/**
|
|
119
|
+
* Creates a stable key for a time scope to use in grouping.
|
|
120
|
+
* Rules with different time scope keys don't compete for deduplication.
|
|
121
|
+
*/
|
|
122
|
+
export declare const timeScopeKey: (time: TimeScope | undefined) => string;
|
|
123
|
+
/**
|
|
124
|
+
* Creates a stable key for an entity scope type.
|
|
125
|
+
* Used to prevent merging different scope types during resolution.
|
|
126
|
+
*/
|
|
127
|
+
export declare const entityScopeTypeKey: (entity: EntityScope) => string;
|
|
128
|
+
export {};
|
|
129
|
+
//# sourceMappingURL=scoping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoping.d.ts","sourceRoot":"","sources":["../../../src/cpsat/rules/scoping.ts"],"names":[],"mappings":"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"}
|