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,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation utilities for scheduling configuration.
|
|
3
|
+
*
|
|
4
|
+
* These functions help catch configuration errors early, before the ModelBuilder
|
|
5
|
+
* attempts to compile the scheduling problem. This is especially useful when
|
|
6
|
+
* configuration is generated by an LLM, which may hallucinate role or skill names.
|
|
7
|
+
*/
|
|
8
|
+
import type { CoverageRequirement, SchedulingEmployee } from "./cpsat/types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Result of coverage role validation.
|
|
11
|
+
*/
|
|
12
|
+
export interface CoverageValidationResult {
|
|
13
|
+
valid: boolean;
|
|
14
|
+
/** Role IDs used in coverage that don't match any team member */
|
|
15
|
+
unknownRoles: string[];
|
|
16
|
+
/** Role IDs used in coverage that match team members */
|
|
17
|
+
knownRoles: string[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Validates that all roleIds used in coverage requirements match the team.
|
|
21
|
+
*
|
|
22
|
+
* This catches a common LLM error where the model generates coverage requirements
|
|
23
|
+
* using role names that don't match any team member's roleIds. Without this validation,
|
|
24
|
+
* such mismatches would result in valid but semantically wrong schedules (e.g.,
|
|
25
|
+
* coverage requirements that no one can satisfy).
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const employees = [
|
|
30
|
+
* { id: "alice", roleIds: ["cashier"] },
|
|
31
|
+
* { id: "bob", roleIds: ["stocker"] },
|
|
32
|
+
* ];
|
|
33
|
+
*
|
|
34
|
+
* const coverage = [
|
|
35
|
+
* { roleId: "cashier", targetCount: 1, ... }, // OK
|
|
36
|
+
* { roleId: "worker", targetCount: 1, ... }, // Unknown role!
|
|
37
|
+
* ];
|
|
38
|
+
*
|
|
39
|
+
* const result = validateCoverageRoles(coverage, employees);
|
|
40
|
+
* // result.valid = false
|
|
41
|
+
* // result.unknownRoles = ["worker"]
|
|
42
|
+
* // result.knownRoles = ["cashier"]
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function validateCoverageRoles(coverage: CoverageRequirement[], employees: SchedulingEmployee[]): CoverageValidationResult;
|
|
46
|
+
/**
|
|
47
|
+
* Result of coverage skill validation.
|
|
48
|
+
*/
|
|
49
|
+
export interface SkillValidationResult {
|
|
50
|
+
valid: boolean;
|
|
51
|
+
/** Skill IDs used in coverage that don't match any team member */
|
|
52
|
+
unknownSkills: string[];
|
|
53
|
+
/** Skill IDs used in coverage that match team members */
|
|
54
|
+
knownSkills: string[];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Validates that all skillIds used in coverage requirements match the team.
|
|
58
|
+
*
|
|
59
|
+
* Similar to role validation, this catches LLM hallucinations where skill names
|
|
60
|
+
* in coverage don't match any team member's skillIds.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const employees = [
|
|
65
|
+
* { id: "alice", roleIds: ["server"], skillIds: ["keyholder"] },
|
|
66
|
+
* { id: "bob", roleIds: ["server"] },
|
|
67
|
+
* ];
|
|
68
|
+
*
|
|
69
|
+
* const coverage = [
|
|
70
|
+
* { skillIds: ["keyholder"], targetCount: 1, ... }, // OK
|
|
71
|
+
* { skillIds: ["manager"], targetCount: 1, ... }, // Unknown skill!
|
|
72
|
+
* ];
|
|
73
|
+
*
|
|
74
|
+
* const result = validateCoverageSkills(coverage, employees);
|
|
75
|
+
* // result.valid = false
|
|
76
|
+
* // result.unknownSkills = ["manager"]
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export declare function validateCoverageSkills(coverage: CoverageRequirement[], employees: SchedulingEmployee[]): SkillValidationResult;
|
|
80
|
+
/**
|
|
81
|
+
* Combined validation result for coverage requirements.
|
|
82
|
+
*/
|
|
83
|
+
export interface CoverageConfigValidationResult {
|
|
84
|
+
valid: boolean;
|
|
85
|
+
roles: CoverageValidationResult;
|
|
86
|
+
skills: SkillValidationResult;
|
|
87
|
+
/** Human-readable error messages */
|
|
88
|
+
errors: string[];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Validates coverage requirements against team roles and skills.
|
|
92
|
+
*
|
|
93
|
+
* This is the primary validation function to call before building a scheduling model.
|
|
94
|
+
* It checks both roles and skills, returning a combined result with error messages.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const result = validateCoverageConfig(coverage, employees);
|
|
99
|
+
* if (!result.valid) {
|
|
100
|
+
* throw new Error(result.errors.join("; "));
|
|
101
|
+
* }
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export declare function validateCoverageConfig(coverage: CoverageRequirement[], employees: SchedulingEmployee[]): CoverageConfigValidationResult;
|
|
105
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEhF;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,iEAAiE;IACjE,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,wDAAwD;IACxD,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,SAAS,EAAE,kBAAkB,EAAE,GAC9B,wBAAwB,CAoB1B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,OAAO,CAAC;IACf,kEAAkE;IAClE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,yDAAyD;IACzD,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,SAAS,EAAE,kBAAkB,EAAE,GAC9B,qBAAqB,CAoBvB;AAED;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC7C,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,wBAAwB,CAAC;IAChC,MAAM,EAAE,qBAAqB,CAAC;IAC9B,oCAAoC;IACpC,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,SAAS,EAAE,kBAAkB,EAAE,GAC9B,8BAA8B,CA4BhC"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation utilities for scheduling configuration.
|
|
3
|
+
*
|
|
4
|
+
* These functions help catch configuration errors early, before the ModelBuilder
|
|
5
|
+
* attempts to compile the scheduling problem. This is especially useful when
|
|
6
|
+
* configuration is generated by an LLM, which may hallucinate role or skill names.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Validates that all roleIds used in coverage requirements match the team.
|
|
10
|
+
*
|
|
11
|
+
* This catches a common LLM error where the model generates coverage requirements
|
|
12
|
+
* using role names that don't match any team member's roleIds. Without this validation,
|
|
13
|
+
* such mismatches would result in valid but semantically wrong schedules (e.g.,
|
|
14
|
+
* coverage requirements that no one can satisfy).
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const employees = [
|
|
19
|
+
* { id: "alice", roleIds: ["cashier"] },
|
|
20
|
+
* { id: "bob", roleIds: ["stocker"] },
|
|
21
|
+
* ];
|
|
22
|
+
*
|
|
23
|
+
* const coverage = [
|
|
24
|
+
* { roleId: "cashier", targetCount: 1, ... }, // OK
|
|
25
|
+
* { roleId: "worker", targetCount: 1, ... }, // Unknown role!
|
|
26
|
+
* ];
|
|
27
|
+
*
|
|
28
|
+
* const result = validateCoverageRoles(coverage, employees);
|
|
29
|
+
* // result.valid = false
|
|
30
|
+
* // result.unknownRoles = ["worker"]
|
|
31
|
+
* // result.knownRoles = ["cashier"]
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export function validateCoverageRoles(coverage, employees) {
|
|
35
|
+
const employeeRoles = new Set(employees.flatMap((e) => e.roleIds));
|
|
36
|
+
const coverageRoles = new Set(coverage.flatMap((c) => c.roleIds ?? []));
|
|
37
|
+
const unknownRoles = [];
|
|
38
|
+
const knownRoles = [];
|
|
39
|
+
for (const role of coverageRoles) {
|
|
40
|
+
if (employeeRoles.has(role)) {
|
|
41
|
+
knownRoles.push(role);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
unknownRoles.push(role);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
valid: unknownRoles.length === 0,
|
|
49
|
+
unknownRoles: unknownRoles.toSorted(),
|
|
50
|
+
knownRoles: knownRoles.toSorted(),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Validates that all skillIds used in coverage requirements match the team.
|
|
55
|
+
*
|
|
56
|
+
* Similar to role validation, this catches LLM hallucinations where skill names
|
|
57
|
+
* in coverage don't match any team member's skillIds.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* const employees = [
|
|
62
|
+
* { id: "alice", roleIds: ["server"], skillIds: ["keyholder"] },
|
|
63
|
+
* { id: "bob", roleIds: ["server"] },
|
|
64
|
+
* ];
|
|
65
|
+
*
|
|
66
|
+
* const coverage = [
|
|
67
|
+
* { skillIds: ["keyholder"], targetCount: 1, ... }, // OK
|
|
68
|
+
* { skillIds: ["manager"], targetCount: 1, ... }, // Unknown skill!
|
|
69
|
+
* ];
|
|
70
|
+
*
|
|
71
|
+
* const result = validateCoverageSkills(coverage, employees);
|
|
72
|
+
* // result.valid = false
|
|
73
|
+
* // result.unknownSkills = ["manager"]
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export function validateCoverageSkills(coverage, employees) {
|
|
77
|
+
const employeeSkills = new Set(employees.flatMap((e) => e.skillIds ?? []));
|
|
78
|
+
const coverageSkills = new Set(coverage.flatMap((c) => c.skillIds ?? []));
|
|
79
|
+
const unknownSkills = [];
|
|
80
|
+
const knownSkills = [];
|
|
81
|
+
for (const skill of coverageSkills) {
|
|
82
|
+
if (employeeSkills.has(skill)) {
|
|
83
|
+
knownSkills.push(skill);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
unknownSkills.push(skill);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
valid: unknownSkills.length === 0,
|
|
91
|
+
unknownSkills: unknownSkills.toSorted(),
|
|
92
|
+
knownSkills: knownSkills.toSorted(),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Validates coverage requirements against team roles and skills.
|
|
97
|
+
*
|
|
98
|
+
* This is the primary validation function to call before building a scheduling model.
|
|
99
|
+
* It checks both roles and skills, returning a combined result with error messages.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* const result = validateCoverageConfig(coverage, employees);
|
|
104
|
+
* if (!result.valid) {
|
|
105
|
+
* throw new Error(result.errors.join("; "));
|
|
106
|
+
* }
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
export function validateCoverageConfig(coverage, employees) {
|
|
110
|
+
const roles = validateCoverageRoles(coverage, employees);
|
|
111
|
+
const skills = validateCoverageSkills(coverage, employees);
|
|
112
|
+
const errors = [];
|
|
113
|
+
if (!roles.valid) {
|
|
114
|
+
const availableRoles = [...new Set(employees.flatMap((e) => e.roleIds))].toSorted();
|
|
115
|
+
errors.push(`Coverage uses unknown roles: ${roles.unknownRoles.join(", ")}. ` +
|
|
116
|
+
`Available roles: ${availableRoles.join(", ")}`);
|
|
117
|
+
}
|
|
118
|
+
if (!skills.valid) {
|
|
119
|
+
const availableSkills = [...new Set(employees.flatMap((e) => e.skillIds ?? []))].toSorted();
|
|
120
|
+
errors.push(`Coverage uses unknown skills: ${skills.unknownSkills.join(", ")}. ` +
|
|
121
|
+
`Available skills: ${availableSkills.length > 0 ? availableSkills.join(", ") : "(none)"}`);
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
valid: roles.valid && skills.valid,
|
|
125
|
+
roles,
|
|
126
|
+
skills,
|
|
127
|
+
errors,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
|