@royalschedule/maps 4.0.3 → 4.0.5
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/dist/Additio/to/index.d.ts +2 -2
- package/dist/PlanDigital/index.d.ts +28 -28
- package/dist/RS/to/input/collections.js +4 -1
- package/dist/RS/to/input/collections.js.map +1 -1
- package/dist/RS/to/input/dynamic-locked-times.js +8 -5
- package/dist/RS/to/input/dynamic-locked-times.js.map +1 -1
- package/dist/RS/to/input/events.js +5 -2
- package/dist/RS/to/input/events.js.map +1 -1
- package/dist/RS/to/input/groups.js +5 -1
- package/dist/RS/to/input/groups.js.map +1 -1
- package/dist/RS/to/input/input.js +14 -1
- package/dist/RS/to/input/input.js.map +1 -1
- package/dist/RS/to/input/intervals.js +25 -13
- package/dist/RS/to/input/intervals.js.map +1 -1
- package/dist/RS/to/input/periods.js +1 -1
- package/dist/RS/to/input/periods.js.map +1 -1
- package/dist/RS/to/input/settings.js +2 -2
- package/dist/RS/to/input/settings.js.map +1 -1
- package/dist/RS/to/input/teachers.js +5 -1
- package/dist/RS/to/input/teachers.js.map +1 -1
- package/dist/RS/to/input/util/attach-locked-times.js +1 -1
- package/dist/RS/to/input/util/attach-locked-times.js.map +1 -1
- package/dist/RS/to/input/util/parse-group-references.js +3 -3
- package/dist/RS/to/input/util/parse-group-references.js.map +1 -1
- package/dist/RS/to/input/util/parse-intervals.js +3 -3
- package/dist/RS/to/input/util/parse-intervals.js.map +1 -1
- package/dist/RS/to/input/util/parse-minimum-break-length.js +2 -2
- package/dist/RS/to/input/util/parse-minimum-break-length.js.map +1 -1
- package/dist/RS/to/input/util/util.js +7 -2
- package/dist/RS/to/input/util/util.js.map +1 -1
- package/dist/SchoolSoft/file/to/index.d.ts +2 -2
- package/dist/Skola24/txt/types/index.d.ts +15 -14
- package/dist/core/types/courses.d.ts +3 -0
- package/dist/core/types/groups.d.ts +3 -0
- package/dist/core/types/teachers.d.ts +3 -0
- package/dist/core/util.js +5 -5
- package/dist/core/util.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Types } from "../../core/types/index.js";
|
|
2
2
|
import { Types as Types$1 } from "../types/index.js";
|
|
3
|
-
import * as
|
|
3
|
+
import * as xlsx0 from "xlsx";
|
|
4
4
|
|
|
5
5
|
//#region src/Additio/to/index.d.ts
|
|
6
6
|
declare class export_default {
|
|
@@ -14,7 +14,7 @@ declare class export_default {
|
|
|
14
14
|
courses: Types.mixed.course[];
|
|
15
15
|
events: Types.mixed.event[];
|
|
16
16
|
lockedTimes: Types.mixed.lockedTime[];
|
|
17
|
-
}, _options?: Types$1.options) =>
|
|
17
|
+
}, _options?: Types$1.options) => xlsx0.WorkBook;
|
|
18
18
|
}
|
|
19
19
|
//#endregion
|
|
20
20
|
export { export_default };
|
|
@@ -13,78 +13,77 @@ declare class PlanDigitalMap {
|
|
|
13
13
|
static from: {
|
|
14
14
|
schedules: (input: Types.schedule, options: Types.options) => {
|
|
15
15
|
groups?: {
|
|
16
|
+
exceptions?: string[] | undefined;
|
|
17
|
+
lockedTimes?: string[] | undefined;
|
|
16
18
|
ids?: ID | undefined;
|
|
17
19
|
createdAt?: DateType | undefined;
|
|
18
20
|
updatedAt?: DateType | undefined;
|
|
19
21
|
lastModifiedBy?: unknown;
|
|
20
22
|
belongsTo?: string | undefined;
|
|
21
|
-
exceptions?: string[] | undefined;
|
|
22
|
-
lockedTimes?: string[] | undefined;
|
|
23
23
|
rank?: number | undefined;
|
|
24
|
-
days?: Day[] | undefined;
|
|
25
24
|
displayName?: string | undefined;
|
|
25
|
+
lunch?: string[] | undefined;
|
|
26
|
+
intervals?: AllowedInterval[] | undefined;
|
|
27
|
+
days?: Day[] | undefined;
|
|
26
28
|
minBreakLength?: BreakLength | undefined;
|
|
29
|
+
tags?: Tag[] | undefined;
|
|
27
30
|
maximumScheduleSpan?: MaximumScheduleSpan | undefined;
|
|
28
31
|
forbidOverlappingEvents?: boolean | undefined;
|
|
29
32
|
disableDayLengthPunishment?: boolean | undefined;
|
|
30
33
|
weight?: number | undefined;
|
|
34
|
+
rootInterval?: string | undefined;
|
|
35
|
+
maxNumWorkingHours?: number | boolean | undefined;
|
|
36
|
+
maxNumDailyWorkingHours?: number | number[] | boolean | undefined;
|
|
31
37
|
species?: "class" | undefined;
|
|
32
38
|
parentGroups?: string[] | undefined;
|
|
33
39
|
subGroups?: string[] | undefined;
|
|
34
|
-
lunch?: string[] | undefined;
|
|
35
40
|
members?: string[] | undefined;
|
|
36
|
-
intervals?: AllowedInterval[] | undefined;
|
|
37
|
-
rootInterval?: string | undefined;
|
|
38
|
-
tags?: Tag[] | undefined;
|
|
39
|
-
maxNumWorkingHours?: number | boolean | undefined;
|
|
40
|
-
maxNumDailyWorkingHours?: number | number[] | boolean | undefined;
|
|
41
41
|
}[];
|
|
42
42
|
teachers?: {
|
|
43
|
+
exceptions?: string[] | undefined;
|
|
44
|
+
lockedTimes?: string[] | undefined;
|
|
43
45
|
ids?: ID | undefined;
|
|
44
46
|
createdAt?: DateType | undefined;
|
|
45
47
|
updatedAt?: DateType | undefined;
|
|
46
48
|
lastModifiedBy?: unknown;
|
|
47
49
|
belongsTo?: string | undefined;
|
|
48
|
-
exceptions?: string[] | undefined;
|
|
49
|
-
lockedTimes?: string[] | undefined;
|
|
50
50
|
rank?: number | undefined;
|
|
51
|
-
days?: Day[] | undefined;
|
|
52
51
|
displayName?: string | undefined;
|
|
52
|
+
lunch?: string[] | undefined;
|
|
53
|
+
intervals?: AllowedInterval[] | undefined;
|
|
54
|
+
days?: Day[] | undefined;
|
|
53
55
|
minBreakLength?: BreakLength | undefined;
|
|
56
|
+
tags?: Tag[] | undefined;
|
|
57
|
+
plannedScheduledDuration?: PlannedScheduledDuration | undefined;
|
|
54
58
|
maximumScheduleSpan?: MaximumScheduleSpan | undefined;
|
|
55
59
|
forbidOverlappingEvents?: boolean | undefined;
|
|
56
60
|
disableDayLengthPunishment?: boolean | undefined;
|
|
57
61
|
weight?: number | undefined;
|
|
58
|
-
|
|
59
|
-
intervals?: AllowedInterval[] | undefined;
|
|
62
|
+
person?: string | undefined;
|
|
60
63
|
rootInterval?: string | undefined;
|
|
61
|
-
|
|
64
|
+
signature?: string | undefined;
|
|
62
65
|
maxNumWorkingHours?: number | boolean | undefined;
|
|
63
66
|
maxNumDailyWorkingHours?: number | number[] | boolean | undefined;
|
|
64
|
-
person?: string | undefined;
|
|
65
|
-
plannedScheduledDuration?: PlannedScheduledDuration | undefined;
|
|
66
|
-
signature?: string | undefined;
|
|
67
67
|
}[];
|
|
68
68
|
courses?: {
|
|
69
|
-
ids?: ID | undefined;
|
|
70
|
-
createdAt?: DateType | undefined;
|
|
71
|
-
updatedAt?: DateType | undefined;
|
|
72
|
-
lastModifiedBy?: unknown;
|
|
73
|
-
belongsTo?: string | undefined;
|
|
74
69
|
exceptions?: string[] | undefined;
|
|
75
|
-
type?: string | undefined;
|
|
76
70
|
groups?: GroupReference<string, string>[] | undefined;
|
|
77
71
|
teachers?: PersonReference<string>[] | undefined;
|
|
78
72
|
locations?: AvailableLocation<string>[] | undefined;
|
|
79
73
|
events?: string[] | undefined;
|
|
80
74
|
lockedTimes?: string[] | undefined;
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
ids?: ID | undefined;
|
|
76
|
+
createdAt?: DateType | undefined;
|
|
77
|
+
updatedAt?: DateType | undefined;
|
|
78
|
+
lastModifiedBy?: unknown;
|
|
79
|
+
belongsTo?: string | undefined;
|
|
83
80
|
displayName?: string | undefined;
|
|
84
|
-
minBreakLength?: BreakLength | undefined;
|
|
85
|
-
weight?: number | undefined;
|
|
86
81
|
intervals?: AllowedInterval[] | undefined;
|
|
82
|
+
days?: Day[] | undefined;
|
|
83
|
+
minBreakLength?: BreakLength | undefined;
|
|
87
84
|
tags?: Tag[] | undefined;
|
|
85
|
+
weeks?: number[] | undefined;
|
|
86
|
+
weight?: number | undefined;
|
|
88
87
|
period?: string | undefined;
|
|
89
88
|
participants?: PersonReference<string>[] | undefined;
|
|
90
89
|
density?: number | undefined;
|
|
@@ -92,6 +91,7 @@ declare class PlanDigitalMap {
|
|
|
92
91
|
color?: string | undefined;
|
|
93
92
|
eventDurationVariance?: number | undefined;
|
|
94
93
|
totalTime?: string | undefined;
|
|
94
|
+
type?: string | undefined;
|
|
95
95
|
comment?: string | undefined;
|
|
96
96
|
startDate?: DateType | undefined;
|
|
97
97
|
endDate?: DateType | undefined;
|
|
@@ -5,6 +5,7 @@ import { attachLockedTimes } from "./util/attach-locked-times.js";
|
|
|
5
5
|
import { parseDays } from "./util/parse-days.js";
|
|
6
6
|
import { parseMinimumBreakLength } from "./util/parse-minimum-break-length.js";
|
|
7
7
|
import { parseIntervals } from "./util/parse-intervals.js";
|
|
8
|
+
import { getDefaultInterval } from "./intervals.js";
|
|
8
9
|
import { parseGroupReferences } from "./util/parse-group-references.js";
|
|
9
10
|
import { parseLocationReferences } from "./util/parse-location-references.js";
|
|
10
11
|
import { parseEvents } from "./events.js";
|
|
@@ -12,8 +13,10 @@ import { groupBy, omitBy, values } from "lodash-es";
|
|
|
12
13
|
|
|
13
14
|
//#region src/RS/to/input/collections.ts
|
|
14
15
|
function fromCollections(courses, settings, options, periodsMap) {
|
|
16
|
+
const defaultInterval = getDefaultInterval(settings);
|
|
15
17
|
const collections = courses.map((course) => {
|
|
16
18
|
const id = getVertexId(course, options);
|
|
19
|
+
const intervals = course.intervals ?? defaultInterval;
|
|
17
20
|
const doc = {
|
|
18
21
|
id,
|
|
19
22
|
weight: course.weight,
|
|
@@ -27,7 +30,7 @@ function fromCollections(courses, settings, options, periodsMap) {
|
|
|
27
30
|
type: "course",
|
|
28
31
|
item: course
|
|
29
32
|
}, options),
|
|
30
|
-
intervals: options.oldFormat ? parseIntervals(
|
|
33
|
+
intervals: options.oldFormat ? parseIntervals(intervals, void 0, settings) : idOf.intervalPairReference(intervals, void 0, options),
|
|
31
34
|
days: parseDays(course.days, settings),
|
|
32
35
|
minBreakLength: parseMinimumBreakLength(course.minBreakLength),
|
|
33
36
|
lockedTimes: attachLockedTimes(course.lockedTimes, options),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collections.js","names":["doc: Types.collection & { overlapGroupId?: string }","x"],"sources":["../../../../src/RS/to/input/collections.ts"],"sourcesContent":["import { groupBy, omitBy, values } from 'lodash-es';\nimport { attachLockedTimes } from './util/attach-locked-times';\nimport { parseEvents } from './events';\nimport { parseMinimumBreakLength } from './util/parse-minimum-break-length';\nimport { parseGroupReferences } from './util/parse-group-references';\nimport type { ConnectedTypes } from '../../make-connected';\nimport { getVertexId } from '../../../core/util';\nimport { getPeriodIndex, idOf } from './util/util';\nimport { parseLocationReferences } from './util/parse-location-references';\nimport { parseDays } from './util/parse-days';\nimport { parseIntervals } from './util/parse-intervals';\nimport type { Types } from '../../types';\nimport { makeChainable } from '../../../common/make-chainable';\n\nexport function fromCollections (\n courses: ConnectedTypes.course[],\n settings: ConnectedTypes.divisionSettings,\n options: Types.parsedToOptions,\n periodsMap: Map<string | undefined, number>,\n): (Types.collection[] | Types.collection)[] {\n const collections = courses\n .map(course => {\n const id
|
|
1
|
+
{"version":3,"file":"collections.js","names":["doc: Types.collection & { overlapGroupId?: string }","x"],"sources":["../../../../src/RS/to/input/collections.ts"],"sourcesContent":["import { groupBy, omitBy, values } from 'lodash-es';\nimport { attachLockedTimes } from './util/attach-locked-times';\nimport { parseEvents } from './events';\nimport { parseMinimumBreakLength } from './util/parse-minimum-break-length';\nimport { parseGroupReferences } from './util/parse-group-references';\nimport type { ConnectedTypes } from '../../make-connected';\nimport { getVertexId } from '../../../core/util';\nimport { getPeriodIndex, idOf } from './util/util';\nimport { parseLocationReferences } from './util/parse-location-references';\nimport { parseDays } from './util/parse-days';\nimport { parseIntervals } from './util/parse-intervals';\nimport type { Types } from '../../types';\nimport { makeChainable } from '../../../common/make-chainable';\nimport { getDefaultInterval } from './intervals';\n\nexport function fromCollections (\n courses: ConnectedTypes.course[],\n settings: ConnectedTypes.divisionSettings,\n options: Types.parsedToOptions,\n periodsMap: Map<string | undefined, number>,\n): (Types.collection[] | Types.collection)[] {\n const defaultInterval = getDefaultInterval(settings);\n\n const collections = courses\n .map(course => {\n const id = getVertexId(course, options);\n const intervals = course.intervals ?? defaultInterval;\n\n const doc: Types.collection & { overlapGroupId?: string } = {\n id,\n\n weight: course.weight,\n density: course.density,\n maxEventLengthVariance: course.eventDurationVariance,\n potentialCenter: course.centerOfAttraction ? parseFloat(course.centerOfAttraction.replace(':', '.')) : undefined,\n distributionKey: id,\n\n events: parseEvents (course.events, settings, options, periodsMap),\n dependencies: parseLocationReferences (course.locations, options),\n groups: parseGroupReferences ({ type: 'course', item: course }, options),\n intervals: options.oldFormat\n ? parseIntervals(intervals, undefined, settings)\n : idOf.intervalPairReference(intervals, undefined, options),\n days: parseDays (course.days, settings),\n minBreakLength: parseMinimumBreakLength (course.minBreakLength),\n lockedTimes: attachLockedTimes (course.lockedTimes, options),\n period: getPeriodIndex (course.period, periodsMap, options),\n };\n\n if (options.meta) {\n doc.meta = omitBy({\n color: course.color,\n ids: course.ids,\n name: course.displayName,\n }, x => x == null);\n }\n\n // temporarily attach overlap group\n doc.overlapGroupId = course.overlapGroup\n ? getVertexId(course.overlapGroup, options)\n : undefined;\n\n return omitBy(doc, x => x == null) as Types.collection & { overlapGroupId?: string };\n });\n\n const overlapping = makeChainable(collections)\n .chain(\n x => x.filter(x => x.overlapGroupId != null),\n x => groupBy(x, x => x.overlapGroupId),\n x => values(x)\n .map(xs => xs.map(x => {\n delete x.overlapGroupId; // remove overlapGroupId from individual collections\n return x as Types.collection;\n }))\n )\n .value;\n\n const plain = collections\n .filter(x => x.overlapGroupId == null)\n .map(x => {\n delete x.overlapGroupId; // remove overlapGroupId from individual collections\n return x as Types.collection;\n });\n\n return overlapping.concat(plain);\n};"],"mappings":";;;;;;;;;;;;;;AAeA,SAAgB,gBACd,SACA,UACA,SACA,YAC2C;CAC3C,MAAM,kBAAkB,mBAAmB;CAE3C,MAAM,cAAc,QACjB,KAAI,WAAU;EACb,MAAM,KAAY,YAAY,QAAQ;EACtC,MAAM,YAAY,OAAO,aAAa;EAEtC,MAAMA,MAAsD;GAC1D;GAEA,QAAwB,OAAO;GAC/B,SAAwB,OAAO;GAC/B,wBAAwB,OAAO;GAC/B,iBAAwB,OAAO,qBAAqB,WAAW,OAAO,mBAAmB,QAAQ,KAAK,QAAQ;GAC9G,iBAAwB;GAExB,QAAc,YAA2B,OAAO,QAAQ,UAAU,SAAS;GAC3E,cAAc,wBAA2B,OAAO,WAAW;GAC3D,QAAc,qBAA2B;IAAE,MAAM;IAAU,MAAM;MAAU;GAC3E,WAAc,QAAQ,YAClB,eAAe,WAAW,QAAW,YACrC,KAAK,sBAAsB,WAAW,QAAW;GACrD,MAAgB,UAA2B,OAAO,MAAM;GACxD,gBAAgB,wBAA2B,OAAO;GAClD,aAAgB,kBAA2B,OAAO,aAAa;GAC/D,QAAgB,eAA2B,OAAO,QAAQ,YAAY;;AAGxE,MAAI,QAAQ,KACV,KAAI,OAAO,OAAO;GAChB,OAAO,OAAO;GACd,KAAO,OAAO;GACd,MAAO,OAAO;MACb,MAAK,KAAK;AAIf,MAAI,iBAAiB,OAAO,eACxB,YAAY,OAAO,cAAc,WACjC;AAEJ,SAAO,OAAO,MAAK,MAAK,KAAK;;CAGjC,MAAM,cAAc,cAAc,aAC/B,OACC,MAAK,EAAE,QAAO,QAAKC,IAAE,kBAAkB,QACvC,MAAK,QAAQ,IAAG,QAAKA,IAAE,kBACvB,MAAK,OAAO,GACT,KAAI,OAAM,GAAG,KAAI,QAAK;AACrB,SAAOA,IAAE;AACT,SAAOA;MAGZ;CAEH,MAAM,QAAQ,YACX,QAAO,MAAK,EAAE,kBAAkB,MAChC,KAAI,MAAK;AACR,SAAO,EAAE;AACT,SAAO;;AAGX,QAAO,YAAY,OAAO"}
|
|
@@ -2,14 +2,15 @@ import { getDayIndex, getVertexId } from "../../../core/util.js";
|
|
|
2
2
|
import { makeChainable } from "../../../common/make-chainable/index.js";
|
|
3
3
|
import { idOf } from "./util/util.js";
|
|
4
4
|
import { parseIntervals } from "./util/parse-intervals.js";
|
|
5
|
+
import { getDefaultInterval } from "./intervals.js";
|
|
5
6
|
import { parseGroupReferences } from "./util/parse-group-references.js";
|
|
6
7
|
import { toDayAndStart } from "./events.js";
|
|
7
8
|
import { groupBy, omitBy, uniq } from "lodash-es";
|
|
8
9
|
|
|
9
10
|
//#region src/RS/to/input/dynamic-locked-times.ts
|
|
10
|
-
function parse(lockedTime, settings, options) {
|
|
11
|
+
function parse(lockedTime, settings, options, defaultInterval) {
|
|
11
12
|
const duration = lockedTime.duration;
|
|
12
|
-
if (!duration || duration < 5) throw new Error("(RS::
|
|
13
|
+
if (!duration || duration < 5) throw new Error("(RS::To::DynamicLockedTimes) Length of a locked time is less than 5 min");
|
|
13
14
|
const dependencyReferences = makeChainable(lockedTime.coalesced ?? []).chain((x) => x.filter((x$1) => x$1.toModel == "locations").map((x$1) => getVertexId(x$1.to, options)), (x) => uniq(x), (x) => x.map((x$1) => [x$1])).value;
|
|
14
15
|
const days = lockedTime.intervals ? makeChainable(lockedTime.intervals).chain((x) => x.map((x$1) => getDayIndex(x$1.start)), (x) => uniq(x)).value : void 0;
|
|
15
16
|
const day = days?.length == 1 ? days[0] : void 0;
|
|
@@ -18,6 +19,7 @@ function parse(lockedTime, settings, options) {
|
|
|
18
19
|
if (!allowedByEvery) return;
|
|
19
20
|
}
|
|
20
21
|
const distributionKey = lockedTime.type == "COMPLEMENTARY_TIME" ? "COMPLEMENTARY_TIME." + lockedTime.tags?.at(0)?.value : void 0;
|
|
22
|
+
const intervals = lockedTime.intervals ?? defaultInterval;
|
|
21
23
|
const doc = {
|
|
22
24
|
id: idOf.lockedTime(lockedTime, options),
|
|
23
25
|
length: duration,
|
|
@@ -28,7 +30,7 @@ function parse(lockedTime, settings, options) {
|
|
|
28
30
|
item: lockedTime
|
|
29
31
|
}, options),
|
|
30
32
|
dependencies: dependencyReferences,
|
|
31
|
-
intervals: options.oldFormat ? parseIntervals(
|
|
33
|
+
intervals: options.oldFormat ? parseIntervals(intervals, void 0, settings) : idOf.intervalPairReference(intervals, void 0, options),
|
|
32
34
|
distributionKey,
|
|
33
35
|
...days && { days },
|
|
34
36
|
...day && { day }
|
|
@@ -54,11 +56,12 @@ function parse(lockedTime, settings, options) {
|
|
|
54
56
|
return omitBy(doc, (x) => x == null);
|
|
55
57
|
}
|
|
56
58
|
function fromDynamicLockedTimes(lockedTimes, settings, options) {
|
|
57
|
-
const
|
|
59
|
+
const defaultInterval = getDefaultInterval(settings);
|
|
60
|
+
const complementaryHours = makeChainable(lockedTimes).chain((x) => x.filter((x$1) => x$1.type == "COMPLEMENTARY_TIME").map((x$1) => parse(x$1, settings, options, defaultInterval)).filter((x$1) => !!x$1), (x) => groupBy(x, (x$1) => [x$1.distributionKey].flat().toSorted().join("|")), (x) => Object.entries(x).map(([id, events]) => ({
|
|
58
61
|
id,
|
|
59
62
|
events
|
|
60
63
|
}))).value;
|
|
61
|
-
const lunches = lockedTimes.filter((x) => x.type == "LUNCH").map((lockedTime) => parse(lockedTime, settings, options)).filter((x) => !!x);
|
|
64
|
+
const lunches = lockedTimes.filter((x) => x.type == "LUNCH").map((lockedTime) => parse(lockedTime, settings, options, defaultInterval)).filter((x) => !!x);
|
|
62
65
|
return [...complementaryHours, ...lunches];
|
|
63
66
|
}
|
|
64
67
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-locked-times.js","names":["x","doc: Types.event"],"sources":["../../../../src/RS/to/input/dynamic-locked-times.ts"],"sourcesContent":["import { groupBy, omitBy, uniq } from 'lodash-es';\nimport type { ConnectedTypes } from '../../make-connected';\nimport { getDayIndex, getVertexId } from '../../../core/util';\nimport { idOf } from './util/util';\nimport { parseGroupReferences } from './util/parse-group-references';\nimport { parseIntervals } from './util/parse-intervals';\nimport type { Types } from '../../types';\nimport { makeChainable } from '../../../common/make-chainable';\nimport { toDayAndStart } from './events';\n\nfunction parse (\n lockedTime:
|
|
1
|
+
{"version":3,"file":"dynamic-locked-times.js","names":["x","doc: Types.event"],"sources":["../../../../src/RS/to/input/dynamic-locked-times.ts"],"sourcesContent":["import { groupBy, omitBy, uniq } from 'lodash-es';\nimport type { ConnectedTypes } from '../../make-connected';\nimport { getDayIndex, getVertexId } from '../../../core/util';\nimport { idOf } from './util/util';\nimport { parseGroupReferences } from './util/parse-group-references';\nimport { parseIntervals } from './util/parse-intervals';\nimport type { Types } from '../../types';\nimport { makeChainable } from '../../../common/make-chainable';\nimport { toDayAndStart } from './events';\nimport { getDefaultInterval } from './intervals';\nimport type { AllowedInterval } from '../../../core/types/common/intervals';\n\nfunction parse (\n lockedTime: ConnectedTypes.lockedTime,\n settings: ConnectedTypes.divisionSettings,\n options: Types.parsedToOptions,\n defaultInterval: AllowedInterval[]\n) {\n const duration = lockedTime.duration;\n if (!duration || duration < 5) throw new Error('(RS::To::DynamicLockedTimes) Length of a locked time is less than 5 min');\n\n const dependencyReferences = makeChainable(lockedTime.coalesced ?? [])\n .chain(\n x => x\n .filter(x => x.toModel == 'locations')\n .map(x => getVertexId(x.to, options)),\n x => uniq(x),\n x => x.map(x => [x])\n )\n .value;\n\n const days = lockedTime.intervals\n ? makeChainable(lockedTime.intervals)\n .chain(\n x => x.map(x => getDayIndex(x.start)),\n x => uniq(x),\n )\n .value\n : undefined;\n const day = days?.length == 1 ? days[0] : undefined;\n\n // ignore locked times that reside on days that are not part of any coalesced's days\n if (day != null && lockedTime.coalesced) {\n const allowedByEvery = lockedTime.coalesced.every(x => !x.to.days?.length || x.to.days.some(x => x.day == day));\n if (!allowedByEvery) return;\n }\n\n // each type (tag) of complementary hours should distribute evenly\n const distributionKey = lockedTime.type == 'COMPLEMENTARY_TIME'\n ? 'COMPLEMENTARY_TIME.' + lockedTime.tags?.at(0)?.value\n : undefined;\n\n const intervals = lockedTime.intervals ?? defaultInterval;\n\n const doc: Types.event = {\n id: idOf.lockedTime(lockedTime, options),\n length: duration,\n minBreakLength: false,\n maxLengthVariance: lockedTime.durationVariance,\n groups: parseGroupReferences({ type: 'lockedTime', item: lockedTime }, options),\n dependencies: dependencyReferences,\n intervals: options.oldFormat\n ? parseIntervals(intervals, undefined, settings)\n : idOf.intervalPairReference(intervals, undefined, options),\n distributionKey,\n ...days && { days },\n ...day && { day },\n };\n\n\n ////\n //// filter based on partialScheduleOptions\n ////\n if (options.partialScheduleOptions) {\n const { includedEvents, omittedEventsHandling } = options.partialScheduleOptions;\n if (includedEvents && !includedEvents.has(doc.id)) {\n\n if (omittedEventsHandling == 'ignore') return;\n\n if (omittedEventsHandling == 'freeze') {\n // must not be parked and have a start and duration to be frozen, otherwise it's ignored\n if (lockedTime.parked || !lockedTime.start || !lockedTime.duration) return;\n\n // fix day, start and end\n Object.assign(doc, toDayAndStart(lockedTime.start));\n doc.length = lockedTime.duration;\n doc.maxLengthVariance = 0;\n\n // override intervals and days to not cause conflicts\n const numDays = settings.numDays ?? 5;\n doc.days = Array.from({ length: numDays }, (_, i) => i);\n doc.intervals = Array.from({ length: numDays }, () => [{ beg: 0, end: 23.55 }]);\n\n // fix locations\n // > locations are always fixed for locked times\n }\n }\n }\n\n return omitBy(doc, x => x == null) as Types.event;\n}\n\nexport function fromDynamicLockedTimes (\n lockedTimes: ConnectedTypes.lockedTime[],\n settings: ConnectedTypes.divisionSettings,\n options: Types.parsedToOptions,\n): (Types.collection | Types.event)[] {\n const defaultInterval = getDefaultInterval(settings);\n\n const complementaryHours = makeChainable(lockedTimes)\n .chain(\n x => x\n .filter(x => x.type == 'COMPLEMENTARY_TIME')\n .map(x => parse(x, settings, options, defaultInterval))\n .filter(x => !!x),\n x => groupBy(x, x => [x.distributionKey].flat().toSorted().join('|')),\n x => Object.entries(x)\n .map(([id, events]) => ({ id, events }) as Types.collection),\n )\n .value;\n\n const lunches = lockedTimes\n .filter(x => x.type == 'LUNCH')\n .map(lockedTime => parse(lockedTime, settings, options, defaultInterval))\n .filter(x => !!x);\n\n return [...complementaryHours, ...lunches];\n};"],"mappings":";;;;;;;;;;AAYA,SAAS,MACP,YACA,UACA,SACA,iBACA;CACA,MAAM,WAAW,WAAW;AAC5B,KAAI,CAAC,YAAY,WAAW,EAAG,OAAM,IAAI,MAAM;CAE/C,MAAM,uBAAuB,cAAc,WAAW,aAAa,IAChE,OACC,MAAK,EACF,QAAO,QAAKA,IAAE,WAAW,aACzB,KAAI,QAAK,YAAYA,IAAE,IAAI,YAC9B,MAAK,KAAK,KACV,MAAK,EAAE,KAAI,QAAK,CAACA,OAElB;CAEH,MAAM,OAAO,WAAW,YACpB,cAAc,WAAW,WACxB,OACC,MAAK,EAAE,KAAI,QAAK,YAAYA,IAAE,UAC9B,MAAK,KAAK,IAEX,QACD;CACJ,MAAM,MAAM,MAAM,UAAU,IAAI,KAAK,KAAK;AAG1C,KAAI,OAAO,QAAQ,WAAW,WAAW;EACvC,MAAM,iBAAiB,WAAW,UAAU,OAAM,MAAK,CAAC,EAAE,GAAG,MAAM,UAAU,EAAE,GAAG,KAAK,MAAK,QAAKA,IAAE,OAAO;AAC1G,MAAI,CAAC,eAAgB;;CAIvB,MAAM,kBAAkB,WAAW,QAAQ,uBACvC,wBAAwB,WAAW,MAAM,GAAG,IAAI,QAChD;CAEJ,MAAM,YAAY,WAAW,aAAa;CAE1C,MAAMC,MAAmB;EACvB,IAAmB,KAAK,WAAW,YAAY;EAC/C,QAAmB;EACnB,gBAAmB;EACnB,mBAAmB,WAAW;EAC9B,QAAmB,qBAAqB;GAAE,MAAM;GAAc,MAAM;KAAc;EAClF,cAAmB;EACnB,WAAmB,QAAQ,YACvB,eAAe,WAAW,QAAW,YACrC,KAAK,sBAAsB,WAAW,QAAW;EACrD;EACA,GAAG,QAAQ,EAAE;EACb,GAAG,OAAO,EAAE;;AAOd,KAAI,QAAQ,wBAAwB;EAClC,MAAM,EAAE,gBAAgB,0BAA0B,QAAQ;AAC1D,MAAI,kBAAkB,CAAC,eAAe,IAAI,IAAI,KAAK;AAEjD,OAAI,yBAAyB,SAAU;AAEvC,OAAI,yBAAyB,UAAU;AAErC,QAAI,WAAW,UAAU,CAAC,WAAW,SAAS,CAAC,WAAW,SAAU;AAGpE,WAAO,OAAO,KAAK,cAAc,WAAW;AAC5C,QAAI,SAAS,WAAW;AACxB,QAAI,oBAAoB;IAGxB,MAAM,UAAU,SAAS,WAAW;AACpC,QAAI,OAAY,MAAM,KAAK,EAAE,QAAQ,YAAY,GAAG,MAAM;AAC1D,QAAI,YAAY,MAAM,KAAK,EAAE,QAAQ,iBAAiB,CAAC;KAAE,KAAK;KAAG,KAAK;;;;;AAQ5E,QAAO,OAAO,MAAK,MAAK,KAAK;;AAG/B,SAAgB,uBACd,aACA,UACA,SACoC;CACpC,MAAM,kBAAkB,mBAAmB;CAE3C,MAAM,qBAAqB,cAAc,aACtC,OACC,MAAK,EACF,QAAO,QAAKD,IAAE,QAAQ,sBACtB,KAAI,QAAK,MAAMA,KAAG,UAAU,SAAS,kBACrC,QAAO,QAAK,CAAC,CAACA,OACjB,MAAK,QAAQ,IAAG,QAAK,CAACA,IAAE,iBAAiB,OAAO,WAAW,KAAK,QAChE,MAAK,OAAO,QAAQ,GACjB,KAAK,CAAC,IAAI,aAAa;EAAE;EAAI;MAEjC;CAEH,MAAM,UAAU,YACb,QAAO,MAAK,EAAE,QAAQ,SACtB,KAAI,eAAc,MAAM,YAAY,UAAU,SAAS,kBACvD,QAAO,MAAK,CAAC,CAAC;AAEjB,QAAO,CAAC,GAAG,oBAAoB,GAAG"}
|
|
@@ -4,6 +4,7 @@ import { attachLockedTimes } from "./util/attach-locked-times.js";
|
|
|
4
4
|
import { parseDays } from "./util/parse-days.js";
|
|
5
5
|
import { parseMinimumBreakLength } from "./util/parse-minimum-break-length.js";
|
|
6
6
|
import { parseIntervals } from "./util/parse-intervals.js";
|
|
7
|
+
import { getDefaultInterval } from "./intervals.js";
|
|
7
8
|
import { parseGroupReferences } from "./util/parse-group-references.js";
|
|
8
9
|
import { parseLocationReferences, parseSelectedLocations } from "./util/parse-location-references.js";
|
|
9
10
|
import { omitBy } from "lodash-es";
|
|
@@ -17,10 +18,12 @@ function toDayAndStart(start) {
|
|
|
17
18
|
};
|
|
18
19
|
}
|
|
19
20
|
function parseEvents(events, settings, options, periodsMap) {
|
|
21
|
+
const defaultInterval = getDefaultInterval(settings);
|
|
20
22
|
return (events ?? []).map((event) => {
|
|
21
23
|
const id = getVertexId(event, options);
|
|
24
|
+
const intervals = event.intervals ?? event.course?.intervals ?? defaultInterval;
|
|
22
25
|
const duration = event.preferredDuration ?? event.duration;
|
|
23
|
-
if (!duration) throw new Error(`(RS::
|
|
26
|
+
if (!duration) throw new Error(`(RS::To::Events) Event "${id}" has no duration`);
|
|
24
27
|
const doc = {
|
|
25
28
|
id: idOf.event(event, options),
|
|
26
29
|
length: duration,
|
|
@@ -36,7 +39,7 @@ function parseEvents(events, settings, options, periodsMap) {
|
|
|
36
39
|
type: "event",
|
|
37
40
|
item: event
|
|
38
41
|
}, options),
|
|
39
|
-
intervals: options.oldFormat ? parseIntervals(
|
|
42
|
+
intervals: options.oldFormat ? parseIntervals(intervals, void 0, settings) : idOf.intervalPairReference(intervals, void 0, options),
|
|
40
43
|
lockedTimes: attachLockedTimes(event.lockedTimes, options),
|
|
41
44
|
minBreakLength: parseMinimumBreakLength(event.minBreakLength)
|
|
42
45
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.js","names":["doc: Types.event","id"],"sources":["../../../../src/RS/to/input/events.ts"],"sourcesContent":["import moment from 'moment';\nimport { omitBy } from 'lodash-es';\nimport { parseMinimumBreakLength } from './util/parse-minimum-break-length';\nimport { attachLockedTimes } from './util/attach-locked-times';\nimport type { Types } from '../../types';\nimport { parseGroupReferences } from './util/parse-group-references';\nimport { parseLocationReferences, parseSelectedLocations } from './util/parse-location-references';\nimport type { ConnectedTypes } from '../../make-connected';\nimport { getDayIndex, getVertexId } from '../../../core/util';\nimport { getPeriodIndex, idOf } from './util/util';\nimport { parseDays } from './util/parse-days';\nimport type { DateType } from '../../../common/types';\nimport { parseIntervals } from './util/parse-intervals';\n\nexport function toDayAndStart (start: DateType) {\n return {\n start: parseFloat(moment.utc(start).format('HH.mm')),\n day: getDayIndex(start)\n };\n}\n\nexport function parseEvents (\n events: ConnectedTypes.event[] | undefined,\n settings: ConnectedTypes.divisionSettings,\n options: Types.parsedToOptions,\n periodsMap: Map<string | undefined, number>\n): Types.event[] {\n\n return (events ?? [])\n .map((event): Types.event | undefined => {\n const id
|
|
1
|
+
{"version":3,"file":"events.js","names":["doc: Types.event","id"],"sources":["../../../../src/RS/to/input/events.ts"],"sourcesContent":["import moment from 'moment';\nimport { omitBy } from 'lodash-es';\nimport { parseMinimumBreakLength } from './util/parse-minimum-break-length';\nimport { attachLockedTimes } from './util/attach-locked-times';\nimport type { Types } from '../../types';\nimport { parseGroupReferences } from './util/parse-group-references';\nimport { parseLocationReferences, parseSelectedLocations } from './util/parse-location-references';\nimport type { ConnectedTypes } from '../../make-connected';\nimport { getDayIndex, getVertexId } from '../../../core/util';\nimport { getPeriodIndex, idOf } from './util/util';\nimport { parseDays } from './util/parse-days';\nimport type { DateType } from '../../../common/types';\nimport { parseIntervals } from './util/parse-intervals';\nimport { getDefaultInterval } from './intervals';\n\nexport function toDayAndStart (start: DateType) {\n return {\n start: parseFloat(moment.utc(start).format('HH.mm')),\n day: getDayIndex(start)\n };\n}\n\nexport function parseEvents (\n events: ConnectedTypes.event[] | undefined,\n settings: ConnectedTypes.divisionSettings,\n options: Types.parsedToOptions,\n periodsMap: Map<string | undefined, number>\n): Types.event[] {\n const defaultInterval = getDefaultInterval(settings);\n\n return (events ?? [])\n .map((event): Types.event | undefined => {\n const id = getVertexId(event, options);\n const intervals = event.intervals ?? event.course?.intervals ?? defaultInterval;\n\n const duration = event.preferredDuration ?? event.duration; // temporary, should be preferred duration only!\n if (!duration) throw new Error(`(RS::To::Events) Event \"${id}\" has no duration`);\n\n const doc: Types.event = {\n id: idOf.event(event, options),\n length: duration,\n maxLengthVariance: event.durationVariance,\n weight: event.weight,\n density: event.density,\n potentialCenter: event.centerOfAttraction ? parseFloat(event.centerOfAttraction.replace(':', '.')) : undefined,\n forcedOverlapId: event.overlapSpecies?.species?.find(({ to }) => to == event)?.id,\n\n period: getPeriodIndex (event.period, periodsMap, options),\n days: parseDays (event.days, settings),\n dependencies: parseLocationReferences (event.locations, options),\n groups: parseGroupReferences ({ type: 'event', item: event }, options),\n intervals: options.oldFormat\n ? parseIntervals(intervals, undefined, settings)\n : idOf.intervalPairReference(intervals, undefined, options),\n lockedTimes: attachLockedTimes (event.lockedTimes, options),\n minBreakLength: parseMinimumBreakLength (event.minBreakLength),\n };\n\n // if the event has a fixed day and start\n if (event.fixedStart && event.start) {\n Object.assign(doc, toDayAndStart(event.start));\n }\n\n if (options.meta) {\n doc.meta = omitBy({\n name: event.displayName,\n ids: event.ids,\n parked: event.parked,\n visible: event.visible,\n start: event.start ? moment.utc(event.start) : undefined,\n end: event.end ? moment.utc(event.start) : undefined,\n course: event.course ? getVertexId(event.course, options) : undefined,\n inLocations: event.inLocations ? parseSelectedLocations(event, options) : undefined\n }, x => x == null);\n }\n\n ////\n //// filter events based on partialScheduleOptions\n ////\n if (options.partialScheduleOptions) {\n const { includedEvents, omittedEventsHandling } = options.partialScheduleOptions;\n if (includedEvents && !includedEvents.has(doc.id)) { // collection.id => take into account dynamic locked times too!\n\n if (omittedEventsHandling == 'ignore') return;\n\n if (omittedEventsHandling == 'freeze') {\n // must not be parked and have a start and duration to be frozen, otherwise it's ignored\n if (event.parked || !event.start || !event.duration) return;\n\n // fix day, start and end\n Object.assign(doc, toDayAndStart(event.start));\n doc.length = event.duration;\n doc.maxLengthVariance = 0;\n\n // override intervals and days to not cause conflicts\n const numDays = settings.numDays ?? 5;\n doc.days = Array.from({ length: numDays }, (_, i) => i);\n doc.intervals = Array.from({ length: numDays }, () => [{ beg: 0, end: 23.55 }]);\n\n // fix locations\n doc.dependencies = (event.inLocations ?? [])\n .filter((x): x is NonNullable<typeof x> => !!x)\n .map(x => {\n const id = getVertexId(x, options);\n\n // filter location references based on partial schedule options\n const includedLocations = options.partialScheduleOptions?.includedLocations;\n if (includedLocations && !includedLocations.has(id)) return;\n\n return [{ dependency: id }] as Types.availableDependency[];\n })\n .filter(x => x != null);\n }\n\n }\n }\n\n return omitBy(doc, x => x == null) as Types.event;\n })\n .filter((x): x is NonNullable<typeof x> => !!x);\n}"],"mappings":";;;;;;;;;;;;;AAeA,SAAgB,cAAe,OAAiB;AAC9C,QAAO;EACL,OAAO,WAAW,OAAO,IAAI,OAAO,OAAO;EAC3C,KAAO,YAAY;;;AAIvB,SAAgB,YACd,QACA,UACA,SACA,YACe;CACf,MAAM,kBAAkB,mBAAmB;AAE3C,SAAQ,UAAU,IACf,KAAK,UAAmC;EACvC,MAAM,KAAY,YAAY,OAAO;EACrC,MAAM,YAAY,MAAM,aAAa,MAAM,QAAQ,aAAa;EAEhE,MAAM,WAAW,MAAM,qBAAqB,MAAM;AAClD,MAAI,CAAC,SAAU,OAAM,IAAI,MAAM,2BAA2B,GAAG;EAE7D,MAAMA,MAAmB;GACvB,IAAmB,KAAK,MAAM,OAAO;GACrC,QAAmB;GACnB,mBAAmB,MAAM;GACzB,QAAmB,MAAM;GACzB,SAAmB,MAAM;GACzB,iBAAmB,MAAM,qBAAqB,WAAW,MAAM,mBAAmB,QAAQ,KAAK,QAAQ;GACvG,iBAAmB,MAAM,gBAAgB,SAAS,MAAM,EAAE,SAAS,MAAM,QAAQ;GAEjF,QAAc,eAA2B,MAAM,QAAQ,YAAY;GACnE,MAAc,UAA2B,MAAM,MAAM;GACrD,cAAc,wBAA2B,MAAM,WAAW;GAC1D,QAAc,qBAA2B;IAAE,MAAM;IAAS,MAAM;MAAS;GACzE,WAAc,QAAQ,YAClB,eAAe,WAAW,QAAW,YACrC,KAAK,sBAAsB,WAAW,QAAW;GACrD,aAAgB,kBAA2B,MAAM,aAAa;GAC9D,gBAAgB,wBAA2B,MAAM;;AAInD,MAAI,MAAM,cAAc,MAAM,MAC5B,QAAO,OAAO,KAAK,cAAc,MAAM;AAGzC,MAAI,QAAQ,KACV,KAAI,OAAO,OAAO;GAChB,MAAa,MAAM;GACnB,KAAa,MAAM;GACnB,QAAa,MAAM;GACnB,SAAa,MAAM;GACnB,OAAa,MAAM,QAAc,OAAO,IAAI,MAAM,SAAwB;GAC1E,KAAa,MAAM,MAAc,OAAO,IAAI,MAAM,SAAwB;GAC1E,QAAa,MAAM,SAAc,YAAY,MAAM,QAAQ,WAAe;GAC1E,aAAa,MAAM,cAAc,uBAAuB,OAAO,WAAW;MACzE,MAAK,KAAK;AAMf,MAAI,QAAQ,wBAAwB;GAClC,MAAM,EAAE,gBAAgB,0BAA0B,QAAQ;AAC1D,OAAI,kBAAkB,CAAC,eAAe,IAAI,IAAI,KAAK;AAEjD,QAAI,yBAAyB,SAAU;AAEvC,QAAI,yBAAyB,UAAU;AAErC,SAAI,MAAM,UAAU,CAAC,MAAM,SAAS,CAAC,MAAM,SAAU;AAGrD,YAAO,OAAO,KAAK,cAAc,MAAM;AACvC,SAAI,SAAS,MAAM;AACnB,SAAI,oBAAoB;KAGxB,MAAM,UAAU,SAAS,WAAW;AACpC,SAAI,OAAY,MAAM,KAAK,EAAE,QAAQ,YAAY,GAAG,MAAM;AAC1D,SAAI,YAAY,MAAM,KAAK,EAAE,QAAQ,iBAAiB,CAAC;MAAE,KAAK;MAAG,KAAK;;AAGtE,SAAI,gBAAgB,MAAM,eAAe,IACtC,QAAQ,MAAkC,CAAC,CAAC,GAC5C,KAAI,MAAK;MACR,MAAMC,OAAK,YAAY,GAAG;MAG1B,MAAM,oBAAoB,QAAQ,wBAAwB;AAC1D,UAAI,qBAAqB,CAAC,kBAAkB,IAAIA,MAAK;AAErD,aAAO,CAAC,EAAE,YAAYA;QAEvB,QAAO,MAAK,KAAK;;;;AAM1B,SAAO,OAAO,MAAK,MAAK,KAAK;IAE9B,QAAQ,MAAkC,CAAC,CAAC"}
|
|
@@ -4,11 +4,15 @@ import { parseDays } from "./util/parse-days.js";
|
|
|
4
4
|
import { parseMaxWorkingHours } from "./util/parse-max-working-hours.js";
|
|
5
5
|
import { parseMinimumBreakLength } from "./util/parse-minimum-break-length.js";
|
|
6
6
|
import { parseIntervals } from "./util/parse-intervals.js";
|
|
7
|
+
import { getDefaultInterval } from "./intervals.js";
|
|
7
8
|
import { omitBy } from "lodash-es";
|
|
8
9
|
|
|
9
10
|
//#region src/RS/to/input/groups.ts
|
|
10
11
|
function fromGroups(groups, settings, options) {
|
|
12
|
+
const defaultInterval = getDefaultInterval(settings);
|
|
11
13
|
return groups.filter((group) => group.species == "class").map((group) => {
|
|
14
|
+
const intervals = group.intervals ?? defaultInterval;
|
|
15
|
+
const rootInterval = group.rootInterval ?? settings.defaultRootInterval;
|
|
12
16
|
const doc = {
|
|
13
17
|
id: idOf.group(group, options),
|
|
14
18
|
group_type: "classes",
|
|
@@ -17,7 +21,7 @@ function fromGroups(groups, settings, options) {
|
|
|
17
21
|
minimizeDependencyAlternation: false,
|
|
18
22
|
forbidOverlappingEvents: options.oldFormat ? group.forbidOverlappingEvents : void 0,
|
|
19
23
|
disableDayLengthPunishment: options.oldFormat ? group.disableDayLengthPunishment : void 0,
|
|
20
|
-
intervals: options.oldFormat ? parseIntervals(
|
|
24
|
+
intervals: options.oldFormat ? parseIntervals(intervals, rootInterval, settings) : idOf.intervalPairReference(intervals, rootInterval, options),
|
|
21
25
|
days: parseDays(group.days, settings),
|
|
22
26
|
lockedTimes: attachLockedTimes(group.lockedTimes, options),
|
|
23
27
|
minBreakLength: parseMinimumBreakLength(group.minBreakLength),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"groups.js","names":["doc: Types.group"],"sources":["../../../../src/RS/to/input/groups.ts"],"sourcesContent":["import { omitBy } from 'lodash-es';\nimport type { Types } from '../../types';\nimport type { ConnectedTypes } from '../../make-connected';\nimport { parseDays } from './util/parse-days';\nimport { attachLockedTimes } from './util/attach-locked-times';\nimport { parseMinimumBreakLength } from './util/parse-minimum-break-length';\nimport { parseMaxWorkingHours } from './util/parse-max-working-hours';\nimport { idOf } from './util/util';\nimport { parseIntervals } from './util/parse-intervals';\n\nexport function fromGroups (\n groups: ConnectedTypes.group[],\n settings: ConnectedTypes.divisionSettings,\n options: Types.parsedToOptions\n): Types.group[] {\n\n return groups\n .filter(group => group.species == 'class')\n .map(group => {\n const doc: Types.group = {\n id: idOf.group(group, options),\n group_type: 'classes',\n weight: group.weight,\n minimizeGaps: true,\n minimizeDependencyAlternation: false,\n forbidOverlappingEvents: options.oldFormat ? group.forbidOverlappingEvents : undefined, // Deprecated in v3\n disableDayLengthPunishment: options.oldFormat ? group.disableDayLengthPunishment : undefined, // Deprecated in v3\n intervals: options.oldFormat\n ? parseIntervals(
|
|
1
|
+
{"version":3,"file":"groups.js","names":["doc: Types.group"],"sources":["../../../../src/RS/to/input/groups.ts"],"sourcesContent":["import { omitBy } from 'lodash-es';\nimport type { Types } from '../../types';\nimport type { ConnectedTypes } from '../../make-connected';\nimport { parseDays } from './util/parse-days';\nimport { attachLockedTimes } from './util/attach-locked-times';\nimport { parseMinimumBreakLength } from './util/parse-minimum-break-length';\nimport { parseMaxWorkingHours } from './util/parse-max-working-hours';\nimport { idOf } from './util/util';\nimport { parseIntervals } from './util/parse-intervals';\nimport { getDefaultInterval } from './intervals';\n\nexport function fromGroups (\n groups: ConnectedTypes.group[],\n settings: ConnectedTypes.divisionSettings,\n options: Types.parsedToOptions\n): Types.group[] {\n const defaultInterval = getDefaultInterval(settings);\n\n return groups\n .filter(group => group.species == 'class')\n .map(group => {\n const intervals = group.intervals ?? defaultInterval;\n const rootInterval = group.rootInterval ?? settings.defaultRootInterval;\n\n const doc: Types.group = {\n id: idOf.group(group, options),\n group_type: 'classes',\n weight: group.weight,\n minimizeGaps: true,\n minimizeDependencyAlternation: false,\n forbidOverlappingEvents: options.oldFormat ? group.forbidOverlappingEvents : undefined, // Deprecated in v3\n disableDayLengthPunishment: options.oldFormat ? group.disableDayLengthPunishment : undefined, // Deprecated in v3\n intervals: options.oldFormat\n ? parseIntervals(intervals, rootInterval, settings)\n : idOf.intervalPairReference(intervals, rootInterval, options),\n days: parseDays (group.days, settings),\n lockedTimes: attachLockedTimes (group.lockedTimes, options),\n minBreakLength: parseMinimumBreakLength (group.minBreakLength),\n\n ...parseMaxWorkingHours(group, options),\n };\n\n if (options.meta) {\n doc.meta = omitBy({\n ids: group.ids,\n name: group.displayName,\n }, x => x == null);\n }\n\n return omitBy(doc, x => x == null) as Types.group;\n });\n};\n"],"mappings":";;;;;;;;;;AAWA,SAAgB,WACd,QACA,UACA,SACe;CACf,MAAM,kBAAkB,mBAAmB;AAE3C,QAAO,OACJ,QAAO,UAAS,MAAM,WAAW,SACjC,KAAI,UAAS;EACZ,MAAM,YAAe,MAAM,aAAgB;EAC3C,MAAM,eAAe,MAAM,gBAAgB,SAAS;EAEpD,MAAMA,MAAmB;GACvB,IAA+B,KAAK,MAAM,OAAO;GACjD,YAA+B;GAC/B,QAA+B,MAAM;GACrC,cAA+B;GAC/B,+BAA+B;GAC/B,yBAA+B,QAAQ,YAAY,MAAM,0BAA0B;GACnF,4BAA+B,QAAQ,YAAY,MAAM,6BAA6B;GACtF,WAA+B,QAAQ,YACnC,eAAe,WAAW,cAAc,YACxC,KAAK,sBAAsB,WAAW,cAAc;GACxD,MAAgB,UAA2B,MAAM,MAAM;GACvD,aAAgB,kBAA2B,MAAM,aAAa;GAC9D,gBAAgB,wBAA2B,MAAM;GAEjD,GAAG,qBAAqB,OAAO;;AAGjC,MAAI,QAAQ,KACV,KAAI,OAAO,OAAO;GAChB,KAAM,MAAM;GACZ,MAAM,MAAM;MACX,MAAK,KAAK;AAGf,SAAO,OAAO,MAAK,MAAK,KAAK"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { fromLocations } from "./dependencies.js";
|
|
2
|
+
import { extractUniqueIntervals } from "./intervals.js";
|
|
2
3
|
import { fromTeachers } from "./teachers.js";
|
|
3
4
|
import { fromCollections } from "./collections.js";
|
|
4
5
|
import { parseSettings } from "./settings.js";
|
|
5
|
-
import { extractUniqueIntervals } from "./intervals.js";
|
|
6
6
|
import { parseDefault } from "./default.js";
|
|
7
7
|
import { fromDynamicLockedTimes } from "./dynamic-locked-times.js";
|
|
8
8
|
import { parsePeriods } from "./periods.js";
|
|
@@ -21,6 +21,19 @@ function parseInput(schedule, options = {}) {
|
|
|
21
21
|
const courses = schedule.courses ?? [];
|
|
22
22
|
const periods = schedule.periods ?? [];
|
|
23
23
|
const persons = schedule.persons ?? [];
|
|
24
|
+
[
|
|
25
|
+
groups,
|
|
26
|
+
teachers,
|
|
27
|
+
locations,
|
|
28
|
+
courses,
|
|
29
|
+
events,
|
|
30
|
+
lockedTimes
|
|
31
|
+
].forEach((entities) => {
|
|
32
|
+
entities.forEach((entity) => {
|
|
33
|
+
if (entity.intervals && entity.intervals.length == 0) entity.intervals = void 0;
|
|
34
|
+
else if (entity.intervals === null) entity.intervals = void 0;
|
|
35
|
+
});
|
|
36
|
+
});
|
|
24
37
|
const { map: periodsMap, matrix: periodsMatrix } = parsePeriods(periods, division, options);
|
|
25
38
|
const data = {
|
|
26
39
|
settings: parseSettings(settings),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input.js","names":["data: Types.scheduleData"],"sources":["../../../../src/RS/to/input/input.ts"],"sourcesContent":["import type { Types } from '../../types';\nimport { fromLocations } from './dependencies';\nimport { fromTeachers } from './teachers';\nimport { fromCollections } from './collections';\nimport { parseSettings } from './settings';\nimport { parseDefault } from './default';\nimport { fromDynamicLockedTimes } from './dynamic-locked-times';\nimport { parsePeriods } from './periods';\nimport type { ConnectedScheduleData } from '../../make-connected';\nimport { fromGroups } from './groups';\nimport { extractUniqueIntervals } from './intervals';\nimport { extractUniqueIndividuals } from './individuals';\n\nexport function parseInput (\n schedule: ConnectedScheduleData,\n options: Types.parsedToOptions = {}\n): Types.scheduleData {\n\n const settings = schedule.settings;\n const division = schedule.division;\n const groups = schedule.groups ?? [];\n const teachers = schedule.teachers ?? [];\n const locations = schedule.locations ?? [];\n const events = schedule.events ?? [];\n const lockedTimes = schedule.lockedTimes ?? [];\n const courses = schedule.courses ?? [];\n const periods = schedule.periods ?? [];\n const persons = schedule.persons ?? [];\n\n const { map: periodsMap, matrix: periodsMatrix } = parsePeriods(periods, division, options);\n\n const data: Types.scheduleData = {\n settings: parseSettings(settings),\n default: parseDefault (settings, periodsMap, options),\n\n periods: periodsMatrix?.length ? periodsMatrix : undefined, // cannot be empty string\n\n intervals: options.oldFormat ? undefined : extractUniqueIntervals(settings, groups, teachers, courses, events, lockedTimes, options),\n\n dependencies: fromLocations(locations, settings, options),\n\n groups: fromGroups(groups, settings, options)\n .concat(fromTeachers(teachers, settings, options)),\n\n individuals: options.oldFormat ? undefined : extractUniqueIndividuals(persons, courses, events, lockedTimes, options),\n\n events: new Array<Types.collection | Types.collection[] | Types.event[]>()\n .concat(fromCollections(courses, settings, options, periodsMap))\n .concat(fromDynamicLockedTimes(lockedTimes, settings, options)),\n };\n\n return data;\n};"],"mappings":";;;;;;;;;;;;AAaA,SAAgB,WACd,UACA,UAAkC,IACd;CAEpB,MAAM,WAAgB,SAAS;CAC/B,MAAM,WAAgB,SAAS;CAC/B,MAAM,SAAgB,SAAS,UAAiB;CAChD,MAAM,WAAgB,SAAS,YAAiB;CAChD,MAAM,YAAgB,SAAS,aAAiB;CAChD,MAAM,SAAgB,SAAS,UAAiB;CAChD,MAAM,cAAgB,SAAS,eAAiB;CAChD,MAAM,UAAgB,SAAS,WAAiB;CAChD,MAAM,UAAgB,SAAS,WAAiB;CAChD,MAAM,UAAgB,SAAS,WAAiB;
|
|
1
|
+
{"version":3,"file":"input.js","names":["data: Types.scheduleData"],"sources":["../../../../src/RS/to/input/input.ts"],"sourcesContent":["import type { Types } from '../../types';\nimport { fromLocations } from './dependencies';\nimport { fromTeachers } from './teachers';\nimport { fromCollections } from './collections';\nimport { parseSettings } from './settings';\nimport { parseDefault } from './default';\nimport { fromDynamicLockedTimes } from './dynamic-locked-times';\nimport { parsePeriods } from './periods';\nimport type { ConnectedScheduleData } from '../../make-connected';\nimport { fromGroups } from './groups';\nimport { extractUniqueIntervals } from './intervals';\nimport { extractUniqueIndividuals } from './individuals';\n\nexport function parseInput (\n schedule: ConnectedScheduleData,\n options: Types.parsedToOptions = {}\n): Types.scheduleData {\n\n const settings = schedule.settings;\n const division = schedule.division;\n const groups = schedule.groups ?? [];\n const teachers = schedule.teachers ?? [];\n const locations = schedule.locations ?? [];\n const events = schedule.events ?? [];\n const lockedTimes = schedule.lockedTimes ?? [];\n const courses = schedule.courses ?? [];\n const periods = schedule.periods ?? [];\n const persons = schedule.persons ?? [];\n\n\n ////\n //// replace empty/null intervals with undefined\n ////\n [groups, teachers, locations, courses, events, lockedTimes].forEach(entities => {\n entities.forEach(entity => {\n if (entity.intervals && entity.intervals.length == 0) entity.intervals = undefined;\n else if (entity.intervals === null ) entity.intervals = undefined;\n });\n });\n\n\n const { map: periodsMap, matrix: periodsMatrix } = parsePeriods(periods, division, options);\n\n const data: Types.scheduleData = {\n settings: parseSettings(settings),\n default: parseDefault (settings, periodsMap, options),\n\n periods: periodsMatrix?.length ? periodsMatrix : undefined, // cannot be empty string\n\n intervals: options.oldFormat ? undefined : extractUniqueIntervals(settings, groups, teachers, courses, events, lockedTimes, options),\n\n dependencies: fromLocations(locations, settings, options),\n\n groups: fromGroups(groups, settings, options)\n .concat(fromTeachers(teachers, settings, options)),\n\n individuals: options.oldFormat ? undefined : extractUniqueIndividuals(persons, courses, events, lockedTimes, options),\n\n events: new Array<Types.collection | Types.collection[] | Types.event[]>()\n .concat(fromCollections(courses, settings, options, periodsMap))\n .concat(fromDynamicLockedTimes(lockedTimes, settings, options)),\n };\n\n return data;\n};"],"mappings":";;;;;;;;;;;;AAaA,SAAgB,WACd,UACA,UAAkC,IACd;CAEpB,MAAM,WAAgB,SAAS;CAC/B,MAAM,WAAgB,SAAS;CAC/B,MAAM,SAAgB,SAAS,UAAiB;CAChD,MAAM,WAAgB,SAAS,YAAiB;CAChD,MAAM,YAAgB,SAAS,aAAiB;CAChD,MAAM,SAAgB,SAAS,UAAiB;CAChD,MAAM,cAAgB,SAAS,eAAiB;CAChD,MAAM,UAAgB,SAAS,WAAiB;CAChD,MAAM,UAAgB,SAAS,WAAiB;CAChD,MAAM,UAAgB,SAAS,WAAiB;AAMhD;EAAC;EAAQ;EAAU;EAAW;EAAS;EAAQ;GAAa,SAAQ,aAAY;AAC9E,WAAS,SAAQ,WAAU;AACzB,OAAS,OAAO,aAAa,OAAO,UAAU,UAAU,EAAG,QAAO,YAAY;YACrE,OAAO,cAAc,KAA6B,QAAO,YAAY;;;CAKlF,MAAM,EAAE,KAAK,YAAY,QAAQ,kBAAkB,aAAa,SAAS,UAAU;CAEnF,MAAMA,OAA2B;EAC/B,UAAU,cAAc;EACxB,SAAU,aAAc,UAAU,YAAY;EAE9C,SAAS,eAAe,SAAS,gBAAgB;EAEjD,WAAW,QAAQ,YAAY,SAAY,uBAAuB,UAAU,QAAQ,UAAU,SAAS,QAAQ,aAAa;EAE5H,cAAc,cAAc,WAAW,UAAU;EAEjD,QAAQ,WAAW,QAAQ,UAAU,SAClC,OAAO,aAAa,UAAU,UAAU;EAE3C,aAAa,QAAQ,YAAY,SAAY,yBAAyB,SAAS,SAAS,QAAQ,aAAa;EAE7G,QAAQ,IAAI,QACT,OAAO,gBAAgB,SAAS,UAAU,SAAS,aACnD,OAAO,uBAAuB,aAAa,UAAU;;AAG1D,QAAO"}
|
|
@@ -25,7 +25,7 @@ function standardizeIntervals(intervals, settings) {
|
|
|
25
25
|
*/
|
|
26
26
|
function toFloatIntervals(intervals) {
|
|
27
27
|
return intervals?.map((i, day) => {
|
|
28
|
-
if (!i.start || !i.end) throw new Error(`(RS::
|
|
28
|
+
if (!i.start || !i.end) throw new Error(`(RS::To::convertIntervals) Interval missing start or end for day ${day}: ${JSON.stringify(i)}`);
|
|
29
29
|
const start = parseFloat(moment.utc(i.start).format("HH.mm"));
|
|
30
30
|
const end = parseFloat(moment.utc(i.end).format("HH.mm"));
|
|
31
31
|
return {
|
|
@@ -40,10 +40,10 @@ function toFloatIntervals(intervals) {
|
|
|
40
40
|
function combineAndMapIntervals(_intervals, rootInterval, settings) {
|
|
41
41
|
const intervals = toFloatIntervals(standardizeIntervals(_intervals, settings));
|
|
42
42
|
if (rootInterval) {
|
|
43
|
-
if (!intervals) throw new Error("(RS::
|
|
43
|
+
if (!intervals) throw new Error("(RS::To::parseIntervals) no accompanying intervals for rootInterval");
|
|
44
44
|
return makeChainable(rootInterval.intervals).chain((x) => groupBy(x, (i) => getDayIndex(i.start)), (x) => Object.entries(x).map(([day, is]) => {
|
|
45
45
|
const limits = intervals.at(parseInt(day));
|
|
46
|
-
if (!limits) throw new Error(`(RS::
|
|
46
|
+
if (!limits) throw new Error(`(RS::To::Intervals) Day ${day} not found in dayStartAndEnds`);
|
|
47
47
|
return is.map((i) => ({
|
|
48
48
|
beg: parseFloat(moment.utc(i.start).format("HH.mm")),
|
|
49
49
|
end: parseFloat(moment.utc(i.end).format("HH.mm")),
|
|
@@ -58,8 +58,8 @@ function combineAndMapIntervals(_intervals, rootInterval, settings) {
|
|
|
58
58
|
*/
|
|
59
59
|
function getDefaultInterval(settings) {
|
|
60
60
|
const { dayStart, dayEnd } = settings;
|
|
61
|
-
if (!dayStart) throw new Error("(RS::
|
|
62
|
-
if (!dayEnd) throw new Error("(RS::
|
|
61
|
+
if (!dayStart) throw new Error("(RS::To::getDefaultInterval) \"settings.dayStart\" is falsy");
|
|
62
|
+
if (!dayEnd) throw new Error("(RS::To::getDefaultInterval) \"settings.dayEnd\" is falsy");
|
|
63
63
|
return [{
|
|
64
64
|
start: dayStart,
|
|
65
65
|
end: dayEnd
|
|
@@ -76,14 +76,26 @@ function computesDefaultIntervalId(settings, options) {
|
|
|
76
76
|
*/
|
|
77
77
|
function extractUniqueIntervals(settings, groups, teachers, courses, events, lockedTimes, options) {
|
|
78
78
|
const defaultInterval = getDefaultInterval(settings);
|
|
79
|
-
const withRootIntervals =
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
})
|
|
79
|
+
const withRootIntervals = [...groups, ...teachers].map((item) => {
|
|
80
|
+
const intervals = item.intervals ?? defaultInterval;
|
|
81
|
+
const rootInterval = item.rootInterval ?? settings.defaultRootInterval;
|
|
82
|
+
return {
|
|
83
|
+
id: idOf.intervalPairReference(intervals, rootInterval, options),
|
|
84
|
+
data: [intervals, rootInterval]
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
const withoutRootIntervals = [
|
|
88
|
+
{ intervals: defaultInterval },
|
|
89
|
+
...courses,
|
|
90
|
+
...events,
|
|
91
|
+
...lockedTimes
|
|
92
|
+
].map((item) => {
|
|
93
|
+
const interval = item.intervals ?? ("course" in item ? item.course?.intervals : void 0) ?? defaultInterval;
|
|
94
|
+
return {
|
|
95
|
+
id: idOf.intervalPairReference(interval, void 0, options),
|
|
96
|
+
data: [interval, void 0]
|
|
97
|
+
};
|
|
98
|
+
});
|
|
87
99
|
return makeChainable(withRootIntervals).chain((x) => x.concat(withoutRootIntervals), (x) => uniqBy(x, (x$1) => x$1.id), (x) => x.map(({ id, data: [_intervals, rootInterval] }) => {
|
|
88
100
|
const value = combineAndMapIntervals(_intervals, rootInterval, settings);
|
|
89
101
|
if (!value) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intervals.js","names":["x"],"sources":["../../../../src/RS/to/input/intervals.ts"],"sourcesContent":["import moment from 'moment';\nimport { groupBy, uniqBy } from 'lodash-es';\nimport type { Types } from '../../types';\nimport type { ConnectedTypes } from '../../make-connected';\nimport type { AllowedInterval } from '../../../core/types/common/intervals';\nimport { idOf } from './util/util';\nimport { getDayIndex } from '../../../core/util';\nimport type { DateType } from '../../../common/types';\nimport type { RootInterval } from '../../../core/types/root-intervals';\nimport { makeChainable } from '../../../common/make-chainable';\n\n/**\n * Removes the shorthand notation (a single day to represent all days)\n */\nfunction standardizeIntervals (\n intervals: AllowedInterval[] | undefined,\n settings: ConnectedTypes.divisionSettings\n): AllowedInterval[] | undefined {\n if (intervals?.length == 1) {\n const i = intervals[0];\n const start = moment.utc(i.start, 'HH:mm');\n const end = moment.utc(i.end, 'HH:mm');\n return Array.from({ length: settings.numDays }, () => ({ start: start.clone(), end: end.clone() }));\n }\n\n return intervals;\n}\n\n/**\n * Converts the intervals to float type intervals\n */\nfunction toFloatIntervals (\n intervals: AllowedInterval[] | undefined\n): { beg: number, end: number }[] | undefined {\n return intervals?.map((i, day: number) => {\n if (!i.start || !i.end) throw new Error(`(RS::
|
|
1
|
+
{"version":3,"file":"intervals.js","names":["x"],"sources":["../../../../src/RS/to/input/intervals.ts"],"sourcesContent":["import moment from 'moment';\nimport { groupBy, uniqBy } from 'lodash-es';\nimport type { Types } from '../../types';\nimport type { ConnectedTypes } from '../../make-connected';\nimport type { AllowedInterval } from '../../../core/types/common/intervals';\nimport { idOf } from './util/util';\nimport { getDayIndex } from '../../../core/util';\nimport type { DateType } from '../../../common/types';\nimport type { RootInterval } from '../../../core/types/root-intervals';\nimport { makeChainable } from '../../../common/make-chainable';\n\n/**\n * Removes the shorthand notation (a single day to represent all days)\n */\nfunction standardizeIntervals (\n intervals: AllowedInterval[] | undefined,\n settings: ConnectedTypes.divisionSettings\n): AllowedInterval[] | undefined {\n if (intervals?.length == 1) {\n const i = intervals[0];\n const start = moment.utc(i.start, 'HH:mm');\n const end = moment.utc(i.end, 'HH:mm');\n return Array.from({ length: settings.numDays }, () => ({ start: start.clone(), end: end.clone() }));\n }\n\n return intervals;\n}\n\n/**\n * Converts the intervals to float type intervals\n */\nfunction toFloatIntervals (\n intervals: AllowedInterval[] | undefined\n): { beg: number, end: number }[] | undefined {\n return intervals?.map((i, day: number) => {\n if (!i.start || !i.end) throw new Error(`(RS::To::convertIntervals) Interval missing start or end for day ${day}: ${JSON.stringify(i)}`);\n const start = parseFloat(moment.utc(i.start).format('HH.mm'));\n const end = parseFloat(moment.utc(i.end ).format('HH.mm'));\n return { beg: start, end: end };\n });\n}\n\n/**\n * Converts\n */\nfunction combineAndMapIntervals (\n _intervals: AllowedInterval[] | undefined,\n rootInterval: ConnectedTypes.rootInterval | undefined,\n settings: ConnectedTypes.divisionSettings\n): Types.interval[][] | undefined {\n const intervals = toFloatIntervals(standardizeIntervals(_intervals, settings));\n\n if (rootInterval) {\n if (!intervals) throw new Error('(RS::To::parseIntervals) no accompanying intervals for rootInterval');\n return makeChainable(rootInterval.intervals)\n .chain(\n x => groupBy(x, i => getDayIndex(i.start)),\n x => Object.entries(x)\n .map(([day, is]) => {\n const limits = intervals.at(parseInt(day));\n if (!limits) throw new Error(`(RS::To::Intervals) Day ${day} not found in dayStartAndEnds`);\n\n // remove all block intervals that lay outside the day start and end\n return is\n .map(i => ({\n beg: parseFloat(moment.utc(i.start).format('HH.mm')),\n end: parseFloat(moment.utc(i.end ).format('HH.mm')),\n binary: true\n } satisfies Types.interval))\n .filter(i => i.beg >= limits.beg && i.end <= limits.end);\n })\n )\n .value;\n }\n if (intervals) {\n return intervals.map(i => [i]);\n }\n return;\n};\n\n/**\n * extracts the default interval given the division settings\n */\nexport function getDefaultInterval (settings: ConnectedTypes.divisionSettings): AllowedInterval[] {\n const { dayStart, dayEnd } = settings;\n if (!dayStart) throw new Error('(RS::To::getDefaultInterval) \"settings.dayStart\" is falsy');\n if (!dayEnd ) throw new Error('(RS::To::getDefaultInterval) \"settings.dayEnd\" is falsy');\n return [{ start: dayStart, end: dayEnd }];\n}\n\n/**\n * Computes the default interval id given the division settings\n */\nexport function computesDefaultIntervalId (\n settings: ConnectedTypes.divisionSettings,\n options: Types.parsedToOptions\n): string {\n return idOf.intervalPairReference(getDefaultInterval(settings), undefined, options);\n}\n\n/**\n * Extracts all unique intervals and interval-root interval pairs used by the provided entities\n */\nexport function extractUniqueIntervals (\n settings: ConnectedTypes.divisionSettings,\n groups: ConnectedTypes.group[],\n teachers: ConnectedTypes.teacher[],\n courses: ConnectedTypes.course[],\n events: ConnectedTypes.event[],\n lockedTimes: ConnectedTypes.lockedTime[],\n options: Types.parsedToOptions\n): Types.rootInterval[] {\n const defaultInterval = getDefaultInterval(settings);\n\n type InheritedWithId = { id: string, data: [AllowedInterval<DateType>[] | undefined, RootInterval | undefined] };\n\n const withRootIntervals = [...groups, ...teachers]\n .map((item): InheritedWithId => {\n const intervals = item.intervals ?? defaultInterval;\n const rootInterval = item.rootInterval ?? settings.defaultRootInterval;\n\n return {\n id: idOf.intervalPairReference(intervals, rootInterval, options),\n data: [intervals, rootInterval]\n };\n });\n\n const withoutRootIntervals = [{ intervals: defaultInterval }, ...courses, ...events, ...lockedTimes]\n .map((item): InheritedWithId => {\n const interval = item.intervals ?? ('course' in item ? item.course?.intervals : undefined) ?? defaultInterval;\n\n return {\n id: idOf.intervalPairReference(interval, undefined, options),\n data: [interval, undefined]\n };\n });\n\n return makeChainable(withRootIntervals)\n .chain(\n x => x.concat(withoutRootIntervals),\n x => uniqBy(x, x => x.id),\n x => x\n .map(({ id, data: [_intervals, rootInterval] }) => {\n // compute the corresponding root interval for each interval pair\n const value = combineAndMapIntervals(_intervals, rootInterval, settings);\n if (!value) return;\n return { id, value } as Required<Types.rootInterval>;\n })\n .filter(x => x != null)\n )\n .value;\n};\n"],"mappings":";;;;;;;;;;AAcA,SAAS,qBACP,WACA,UAC+B;AAC/B,KAAI,WAAW,UAAU,GAAG;EAC1B,MAAM,IAAI,UAAU;EACpB,MAAM,QAAQ,OAAO,IAAI,EAAE,OAAO;EAClC,MAAM,MAAQ,OAAO,IAAI,EAAE,KAAO;AAClC,SAAO,MAAM,KAAK,EAAE,QAAQ,SAAS,kBAAkB;GAAE,OAAO,MAAM;GAAS,KAAK,IAAI;;;AAG1F,QAAO;;;;;AAMT,SAAS,iBACP,WAC4C;AAC5C,QAAO,WAAW,KAAK,GAAG,QAAgB;AACxC,MAAI,CAAC,EAAE,SAAS,CAAC,EAAE,IAAK,OAAM,IAAI,MAAM,oEAAoE,IAAI,IAAI,KAAK,UAAU;EACnI,MAAM,QAAQ,WAAW,OAAO,IAAI,EAAE,OAAO,OAAO;EACpD,MAAM,MAAQ,WAAW,OAAO,IAAI,EAAE,KAAO,OAAO;AACpD,SAAO;GAAE,KAAK;GAAY;;;;;;;AAO9B,SAAS,uBACP,YACA,cACA,UACgC;CAChC,MAAM,YAAY,iBAAiB,qBAAqB,YAAY;AAEpE,KAAI,cAAc;AAChB,MAAI,CAAC,UAAW,OAAM,IAAI,MAAM;AAChC,SAAO,cAAc,aAAa,WAC/B,OACC,MAAK,QAAQ,IAAG,MAAK,YAAY,EAAE,UACnC,MAAK,OAAO,QAAQ,GACjB,KAAK,CAAC,KAAK,QAAQ;GAClB,MAAM,SAAS,UAAU,GAAG,SAAS;AACrC,OAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,2BAA2B,IAAI;AAG5D,UAAO,GACJ,KAAI,OAAM;IACT,KAAQ,WAAW,OAAO,IAAI,EAAE,OAAO,OAAO;IAC9C,KAAQ,WAAW,OAAO,IAAI,EAAE,KAAO,OAAO;IAC9C,QAAQ;OAET,QAAO,MAAK,EAAE,OAAO,OAAO,OAAO,EAAE,OAAO,OAAO;MAG3D;;AAEL,KAAI,UACF,QAAO,UAAU,KAAI,MAAK,CAAC;;;;;AAQ/B,SAAgB,mBAAoB,UAA8D;CAChG,MAAM,EAAE,UAAU,WAAW;AAC7B,KAAI,CAAC,SAAU,OAAM,IAAI,MAAM;AAC/B,KAAI,CAAC,OAAU,OAAM,IAAI,MAAM;AAC/B,QAAO,CAAC;EAAE,OAAO;EAAU,KAAK;;;;;;AAMlC,SAAgB,0BACd,UACA,SACQ;AACR,QAAO,KAAK,sBAAsB,mBAAmB,WAAW,QAAW;;;;;AAM7E,SAAgB,uBACd,UACA,QACA,UACA,SACA,QACA,aACA,SACsB;CACtB,MAAM,kBAAkB,mBAAmB;CAI3C,MAAM,oBAAoB,CAAC,GAAG,QAAQ,GAAG,UACtC,KAAK,SAA0B;EAC9B,MAAM,YAAe,KAAK,aAAgB;EAC1C,MAAM,eAAe,KAAK,gBAAgB,SAAS;AAEnD,SAAO;GACL,IAAM,KAAK,sBAAsB,WAAW,cAAc;GAC1D,MAAM,CAAC,WAAW;;;CAIxB,MAAM,uBAAuB;EAAC,EAAE,WAAW;EAAmB,GAAG;EAAS,GAAG;EAAQ,GAAG;GACrF,KAAK,SAA0B;EAC9B,MAAM,WAAW,KAAK,cAAc,YAAY,OAAO,KAAK,QAAQ,YAAY,WAAc;AAE9F,SAAO;GACL,IAAM,KAAK,sBAAsB,UAAU,QAAW;GACtD,MAAM,CAAC,UAAU;;;AAIvB,QAAO,cAAc,mBAClB,OACC,MAAK,EAAE,OAAO,wBACd,MAAK,OAAO,IAAG,QAAKA,IAAE,MACtB,MAAK,EACF,KAAK,EAAE,IAAI,MAAM,CAAC,YAAY,oBAAoB;EAEjD,MAAM,QAAQ,uBAAuB,YAAY,cAAc;AAC/D,MAAI,CAAC,MAAO;AACZ,SAAO;GAAE;GAAI;;IAEd,QAAO,QAAKA,OAAK,OAErB"}
|
|
@@ -31,7 +31,7 @@ function parsePeriods(periods, division, options) {
|
|
|
31
31
|
ranges: x$1[0].ranges
|
|
32
32
|
}))).value;
|
|
33
33
|
const matrix = grouped.map((x) => grouped.map((y) => anyRangesOverlap(x.ranges, y.ranges) ? "1" : "0").join("")).join("");
|
|
34
|
-
if (matrix == "" || matrix == "0") throw new Error("(RS::
|
|
34
|
+
if (matrix == "" || matrix == "0") throw new Error("(RS::To::parsePeriods) invalid matrix value: " + matrix);
|
|
35
35
|
const indexMap = new Map(grouped.flatMap((xs) => xs.ids.map((id) => [id, xs.index])));
|
|
36
36
|
return {
|
|
37
37
|
map: indexMap,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"periods.js","names":["x"],"sources":["../../../../src/RS/to/input/periods.ts"],"sourcesContent":["import { groupBy } from 'lodash-es';\nimport moment from 'moment';\nimport { getIdKey, getVertexId } from '../../../core/util';\nimport type { Interval } from '../../../core/types/common/intervals';\nimport type { ConnectedTypes } from '../../make-connected';\nimport type { Types } from '../../types';\nimport { anyRangesOverlap } from '../../../common/functions';\nimport { makeChainable } from '../../../common/make-chainable';\n\ntype Range = Partial<Interval<string | moment.Moment | Date>>;\ntype DateRange = Interval<moment.Moment>;\n\nfunction createRange ({ start, end }: Range): DateRange {\n return {\n start: moment.utc(start).clone()\n .startOf('isoWeek')\n .startOf('day'),\n end: moment.utc(end).clone()\n .endOf ('isoWeek')\n .endOf ('day')\n };\n}\n\ntype Out = {\n map: Map<string | undefined, number>,\n matrix?: string\n};\n\nexport function parsePeriods (\n periods: ConnectedTypes.period[] | undefined,\n division: ConnectedTypes.division,\n options: Types.parsedToOptions\n): Out {\n const idKey = getIdKey(options);\n\n // if empty periods are given, return empty map only\n if (!periods?.length) {\n return { map: new Map<string | undefined, number>() };\n }\n\n // convert the ranges to moment ranges\n const parsedPeriods = periods.map(x => ({ id: getVertexId(x, idKey) as string | undefined, ranges: x.ranges.map(r => createRange(r)) }));\n\n // add default period that includes all weeks\n parsedPeriods.push({ id: undefined, ranges: [createRange(division)] });\n\n // Compute a pairwise binary overlapping string for each periods and group those that have identical such string.\n // The latter so that the number of periods may be reduced by omitting periods that overlap identically\n const grouped = makeChainable(parsedPeriods)\n .chain(\n x => x\n .map(x => ({\n ...x,\n overlap: parsedPeriods.map(y => anyRangesOverlap(x.ranges, y.ranges) ? '1' : '0').join('')\n })),\n x => groupBy(x, x => x.overlap),\n x => Object.values(x)\n .map((x, i) => ({ ids: x.map(x => x.id), index: i, ranges: x[0].ranges }))\n )\n .value;\n\n // Merge the pairwise binary overlapping string and store it as a matrix string.\n const matrix = grouped\n .map(x => grouped\n .map(y => anyRangesOverlap(x.ranges, y.ranges) ? '1' : '0')\n .join('')\n )\n .join('');\n\n if (matrix == '' || matrix == '0') {\n throw new Error('(RS::
|
|
1
|
+
{"version":3,"file":"periods.js","names":["x"],"sources":["../../../../src/RS/to/input/periods.ts"],"sourcesContent":["import { groupBy } from 'lodash-es';\nimport moment from 'moment';\nimport { getIdKey, getVertexId } from '../../../core/util';\nimport type { Interval } from '../../../core/types/common/intervals';\nimport type { ConnectedTypes } from '../../make-connected';\nimport type { Types } from '../../types';\nimport { anyRangesOverlap } from '../../../common/functions';\nimport { makeChainable } from '../../../common/make-chainable';\n\ntype Range = Partial<Interval<string | moment.Moment | Date>>;\ntype DateRange = Interval<moment.Moment>;\n\nfunction createRange ({ start, end }: Range): DateRange {\n return {\n start: moment.utc(start).clone()\n .startOf('isoWeek')\n .startOf('day'),\n end: moment.utc(end).clone()\n .endOf ('isoWeek')\n .endOf ('day')\n };\n}\n\ntype Out = {\n map: Map<string | undefined, number>,\n matrix?: string\n};\n\nexport function parsePeriods (\n periods: ConnectedTypes.period[] | undefined,\n division: ConnectedTypes.division,\n options: Types.parsedToOptions\n): Out {\n const idKey = getIdKey(options);\n\n // if empty periods are given, return empty map only\n if (!periods?.length) {\n return { map: new Map<string | undefined, number>() };\n }\n\n // convert the ranges to moment ranges\n const parsedPeriods = periods.map(x => ({ id: getVertexId(x, idKey) as string | undefined, ranges: x.ranges.map(r => createRange(r)) }));\n\n // add default period that includes all weeks\n parsedPeriods.push({ id: undefined, ranges: [createRange(division)] });\n\n // Compute a pairwise binary overlapping string for each periods and group those that have identical such string.\n // The latter so that the number of periods may be reduced by omitting periods that overlap identically\n const grouped = makeChainable(parsedPeriods)\n .chain(\n x => x\n .map(x => ({\n ...x,\n overlap: parsedPeriods.map(y => anyRangesOverlap(x.ranges, y.ranges) ? '1' : '0').join('')\n })),\n x => groupBy(x, x => x.overlap),\n x => Object.values(x)\n .map((x, i) => ({ ids: x.map(x => x.id), index: i, ranges: x[0].ranges }))\n )\n .value;\n\n // Merge the pairwise binary overlapping string and store it as a matrix string.\n const matrix = grouped\n .map(x => grouped\n .map(y => anyRangesOverlap(x.ranges, y.ranges) ? '1' : '0')\n .join('')\n )\n .join('');\n\n if (matrix == '' || matrix == '0') {\n throw new Error('(RS::To::parsePeriods) invalid matrix value: ' + matrix);\n }\n\n // Also store in a map what period id corresponds to which row in the matrix.\n const indexMap = new Map(\n grouped.flatMap(xs => xs.ids.map(id => ([id, xs.index]) as const))\n );\n\n return { map: indexMap, matrix };\n}\n\n"],"mappings":";;;;;;;AAYA,SAAS,YAAa,EAAE,OAAO,OAAyB;AACtD,QAAO;EACL,OAAO,OAAO,IAAI,OAAO,QACtB,QAAQ,WACR,QAAQ;EACX,KAAK,OAAO,IAAI,KAAK,QAClB,MAAQ,WACR,MAAQ;;;AASf,SAAgB,aACd,SACA,UACA,SACK;CACL,MAAM,QAAQ,SAAS;AAGvB,KAAI,CAAC,SAAS,OACZ,QAAO,EAAE,qBAAK,IAAI;CAIpB,MAAM,gBAAgB,QAAQ,KAAI,OAAM;EAAE,IAAI,YAAY,GAAG;EAA8B,QAAQ,EAAE,OAAO,KAAI,MAAK,YAAY;;AAGjI,eAAc,KAAK;EAAE,IAAI;EAAW,QAAQ,CAAC,YAAY;;CAIzD,MAAM,UAAU,cAAc,eAC3B,OACC,MAAK,EACF,KAAI,SAAM;EACT,GAAGA;EACH,SAAS,cAAc,KAAI,MAAK,iBAAiBA,IAAE,QAAQ,EAAE,UAAU,MAAM,KAAK,KAAK;OAE3F,MAAK,QAAQ,IAAG,QAAKA,IAAE,WACvB,MAAK,OAAO,OAAO,GAChB,KAAK,KAAG,OAAO;EAAE,KAAKA,IAAE,KAAI,QAAKA,IAAE;EAAK,OAAO;EAAI,QAAQA,IAAE,GAAG;MAEpE;CAGH,MAAM,SAAS,QACZ,KAAI,MAAK,QACP,KAAI,MAAK,iBAAiB,EAAE,QAAQ,EAAE,UAAU,MAAM,KACtD,KAAK,KAEP,KAAK;AAER,KAAI,UAAU,MAAM,UAAU,IAC5B,OAAM,IAAI,MAAM,kDAAkD;CAIpE,MAAM,WAAW,IAAI,IACnB,QAAQ,SAAQ,OAAM,GAAG,IAAI,KAAI,OAAO,CAAC,IAAI,GAAG;AAGlD,QAAO;EAAE,KAAK;EAAU"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
//#region src/RS/to/input/settings.ts
|
|
2
2
|
function parseSettings(settings) {
|
|
3
|
-
if (!settings.numDays) throw new Error("(RS::
|
|
4
|
-
if (!settings.discretization) throw new Error("(RS::
|
|
3
|
+
if (!settings.numDays) throw new Error("(RS::To::parseSettings) numDays is falsy");
|
|
4
|
+
if (!settings.discretization) throw new Error("(RS::To::parseSettings) discretization is falsy");
|
|
5
5
|
return {
|
|
6
6
|
numDays: settings.numDays,
|
|
7
7
|
discretization: settings.numDays,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.js","names":[],"sources":["../../../../src/RS/to/input/settings.ts"],"sourcesContent":["import type { Types } from '../../types';\nimport type { ConnectedTypes } from '../../make-connected';\n\nexport function parseSettings (settings: ConnectedTypes.divisionSettings): Types.settings {\n\n if (!settings.numDays) throw new Error('(RS::
|
|
1
|
+
{"version":3,"file":"settings.js","names":[],"sources":["../../../../src/RS/to/input/settings.ts"],"sourcesContent":["import type { Types } from '../../types';\nimport type { ConnectedTypes } from '../../make-connected';\n\nexport function parseSettings (settings: ConnectedTypes.divisionSettings): Types.settings {\n\n if (!settings.numDays) throw new Error('(RS::To::parseSettings) numDays is falsy');\n if (!settings.discretization) throw new Error('(RS::To::parseSettings) discretization is falsy');\n\n return {\n numDays: settings.numDays,\n discretization: settings.numDays,\n\n dependencyIdKey: 'id',\n groupIdKey: 'id',\n collectionIdKey: 'id',\n eventIdKey: 'id'\n };\n};"],"mappings":";AAGA,SAAgB,cAAe,UAA2D;AAExF,KAAI,CAAC,SAAS,QAAgB,OAAM,IAAI,MAAM;AAC9C,KAAI,CAAC,SAAS,eAAgB,OAAM,IAAI,MAAM;AAE9C,QAAO;EACL,SAAgB,SAAS;EACzB,gBAAgB,SAAS;EAEzB,iBAAiB;EACjB,YAAiB;EACjB,iBAAiB;EACjB,YAAiB"}
|
|
@@ -4,11 +4,15 @@ import { parseDays } from "./util/parse-days.js";
|
|
|
4
4
|
import { parseMaxWorkingHours } from "./util/parse-max-working-hours.js";
|
|
5
5
|
import { parseMinimumBreakLength } from "./util/parse-minimum-break-length.js";
|
|
6
6
|
import { parseIntervals } from "./util/parse-intervals.js";
|
|
7
|
+
import { getDefaultInterval } from "./intervals.js";
|
|
7
8
|
import { omitBy } from "lodash-es";
|
|
8
9
|
|
|
9
10
|
//#region src/RS/to/input/teachers.ts
|
|
10
11
|
function fromTeachers(teachers, settings, options) {
|
|
12
|
+
const defaultInterval = getDefaultInterval(settings);
|
|
11
13
|
return teachers.map((teacher) => {
|
|
14
|
+
const intervals = teacher.intervals ?? defaultInterval;
|
|
15
|
+
const rootInterval = teacher.rootInterval ?? settings.defaultRootInterval;
|
|
12
16
|
const doc = {
|
|
13
17
|
id: idOf.teacher(teacher, options),
|
|
14
18
|
group_type: "personal",
|
|
@@ -17,7 +21,7 @@ function fromTeachers(teachers, settings, options) {
|
|
|
17
21
|
forbidOverlappingEvents: options.oldFormat ? teacher.forbidOverlappingEvents : void 0,
|
|
18
22
|
disableDayLengthPunishment: options.oldFormat ? teacher.disableDayLengthPunishment : void 0,
|
|
19
23
|
weight: teacher.weight,
|
|
20
|
-
intervals: options.oldFormat ? parseIntervals(
|
|
24
|
+
intervals: options.oldFormat ? parseIntervals(intervals, rootInterval, settings) : idOf.intervalPairReference(intervals, rootInterval, options),
|
|
21
25
|
days: parseDays(teacher.days, settings),
|
|
22
26
|
lockedTimes: attachLockedTimes(teacher.lockedTimes, options),
|
|
23
27
|
minBreakLength: parseMinimumBreakLength(teacher.minBreakLength),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"teachers.js","names":["doc: Types.group"],"sources":["../../../../src/RS/to/input/teachers.ts"],"sourcesContent":["import { omitBy } from 'lodash-es';\nimport type { Types } from '../../types';\nimport type { ConnectedTypes } from '../../make-connected';\nimport { parseMaxWorkingHours } from './util/parse-max-working-hours';\nimport { parseDays } from './util/parse-days';\nimport { attachLockedTimes } from './util/attach-locked-times';\nimport { parseMinimumBreakLength } from './util/parse-minimum-break-length';\nimport { idOf } from './util/util';\nimport { parseIntervals } from './util/parse-intervals';\n\nexport function fromTeachers (\n teachers: ConnectedTypes.teacher[],\n settings: ConnectedTypes.divisionSettings,\n options: Types.parsedToOptions\n): Types.group[] {\n return teachers\n .map(teacher => {\n const doc: Types.group = {\n id: idOf.teacher(teacher, options),\n group_type: 'personal',\n minimizeGaps: false,\n minimizeDependencyAlternation: true,\n forbidOverlappingEvents: options.oldFormat ? teacher.forbidOverlappingEvents : undefined, // Deprecated in v3\n disableDayLengthPunishment: options.oldFormat ? teacher.disableDayLengthPunishment : undefined, // Deprecated in v3\n weight: teacher.weight,\n intervals: options.oldFormat\n ? parseIntervals(
|
|
1
|
+
{"version":3,"file":"teachers.js","names":["doc: Types.group"],"sources":["../../../../src/RS/to/input/teachers.ts"],"sourcesContent":["import { omitBy } from 'lodash-es';\nimport type { Types } from '../../types';\nimport type { ConnectedTypes } from '../../make-connected';\nimport { parseMaxWorkingHours } from './util/parse-max-working-hours';\nimport { parseDays } from './util/parse-days';\nimport { attachLockedTimes } from './util/attach-locked-times';\nimport { parseMinimumBreakLength } from './util/parse-minimum-break-length';\nimport { idOf } from './util/util';\nimport { parseIntervals } from './util/parse-intervals';\nimport { getDefaultInterval } from './intervals';\n\nexport function fromTeachers (\n teachers: ConnectedTypes.teacher[],\n settings: ConnectedTypes.divisionSettings,\n options: Types.parsedToOptions\n): Types.group[] {\n const defaultInterval = getDefaultInterval(settings);\n\n return teachers\n .map(teacher => {\n const intervals = teacher.intervals ?? defaultInterval;\n const rootInterval = teacher.rootInterval ?? settings.defaultRootInterval;\n\n const doc: Types.group = {\n id: idOf.teacher(teacher, options),\n group_type: 'personal',\n minimizeGaps: false,\n minimizeDependencyAlternation: true,\n forbidOverlappingEvents: options.oldFormat ? teacher.forbidOverlappingEvents : undefined, // Deprecated in v3\n disableDayLengthPunishment: options.oldFormat ? teacher.disableDayLengthPunishment : undefined, // Deprecated in v3\n weight: teacher.weight,\n intervals: options.oldFormat\n ? parseIntervals(intervals, rootInterval, settings)\n : idOf.intervalPairReference(intervals, rootInterval, options),\n days: parseDays (teacher.days, settings),\n lockedTimes: attachLockedTimes (teacher.lockedTimes, options),\n minBreakLength: parseMinimumBreakLength (teacher.minBreakLength),\n\n ...parseMaxWorkingHours(teacher, options),\n };\n\n if (options.meta) {\n doc.meta = omitBy({\n ids: teacher.ids,\n name: teacher.displayName,\n }, x => x == null);\n }\n\n return omitBy(doc, x => x == null) as Types.group;\n });\n};\n"],"mappings":";;;;;;;;;;AAWA,SAAgB,aACd,UACA,UACA,SACe;CACf,MAAM,kBAAkB,mBAAmB;AAE3C,QAAO,SACJ,KAAI,YAAW;EACd,MAAM,YAAe,QAAQ,aAAgB;EAC7C,MAAM,eAAe,QAAQ,gBAAgB,SAAS;EAEtD,MAAMA,MAAmB;GACvB,IAA+B,KAAK,QAAQ,SAAS;GACrD,YAA+B;GAC/B,cAA+B;GAC/B,+BAA+B;GAC/B,yBAA+B,QAAQ,YAAY,QAAQ,0BAA0B;GACrF,4BAA+B,QAAQ,YAAY,QAAQ,6BAA6B;GACxF,QAA+B,QAAQ;GACvC,WAA+B,QAAQ,YACnC,eAAe,WAAW,cAAc,YACxC,KAAK,sBAAsB,WAAW,cAAc;GACxD,MAAgB,UAA2B,QAAQ,MAAM;GACzD,aAAgB,kBAA2B,QAAQ,aAAa;GAChE,gBAAgB,wBAA2B,QAAQ;GAEnD,GAAG,qBAAqB,SAAS;;AAGnC,MAAI,QAAQ,KACV,KAAI,OAAO,OAAO;GAChB,KAAM,QAAQ;GACd,MAAM,QAAQ;MACb,MAAK,KAAK;AAGf,SAAO,OAAO,MAAK,MAAK,KAAK"}
|
|
@@ -6,7 +6,7 @@ function attachLockedTimes(lockedTimes, options) {
|
|
|
6
6
|
return lockedTimes?.map((lockedTime) => {
|
|
7
7
|
const { start: startDate, end: endDate } = parseDateInterval(lockedTime, "locked time");
|
|
8
8
|
const length = endDate.diff(startDate, "minutes");
|
|
9
|
-
if (length < 5) throw new Error("(RS::
|
|
9
|
+
if (length < 5) throw new Error("(RS::To::LockedTimes) Length of a locked time is less than 5 min");
|
|
10
10
|
const start = parseFloat(startDate.format("HH.mm"));
|
|
11
11
|
const doc = {
|
|
12
12
|
day: getDayIndex(startDate),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attach-locked-times.js","names":["doc: Types.lockedTime"],"sources":["../../../../../src/RS/to/input/util/attach-locked-times.ts"],"sourcesContent":["import { omitBy } from 'lodash-es';\nimport type { Types } from '../../../types';\nimport type { ConnectedTypes } from '../../../make-connected';\nimport { getDayIndex, getVertexId, parseDateInterval } from '../../../../core/util';\n\nexport function attachLockedTimes (\n lockedTimes: ConnectedTypes.lockedTime[] | null | undefined,\n options: Types.parsedToOptions\n): Types.lockedTime[] | undefined {\n\n return lockedTimes?.map(lockedTime => {\n const { start: startDate, end: endDate } = parseDateInterval(lockedTime, 'locked time');\n\n const length = endDate.diff(startDate, 'minutes');\n if (length < 5) throw new Error('(RS::
|
|
1
|
+
{"version":3,"file":"attach-locked-times.js","names":["doc: Types.lockedTime"],"sources":["../../../../../src/RS/to/input/util/attach-locked-times.ts"],"sourcesContent":["import { omitBy } from 'lodash-es';\nimport type { Types } from '../../../types';\nimport type { ConnectedTypes } from '../../../make-connected';\nimport { getDayIndex, getVertexId, parseDateInterval } from '../../../../core/util';\n\nexport function attachLockedTimes (\n lockedTimes: ConnectedTypes.lockedTime[] | null | undefined,\n options: Types.parsedToOptions\n): Types.lockedTime[] | undefined {\n\n return lockedTimes?.map(lockedTime => {\n const { start: startDate, end: endDate } = parseDateInterval(lockedTime, 'locked time');\n\n const length = endDate.diff(startDate, 'minutes');\n if (length < 5) throw new Error('(RS::To::LockedTimes) Length of a locked time is less than 5 min');\n\n const start = parseFloat(startDate.format('HH.mm'));\n\n const doc: Types.lockedTime = {\n day: getDayIndex(startDate),\n start: start,\n length: length,\n };\n\n if (options.meta) {\n doc.meta = omitBy({\n id: getVertexId(lockedTime, options),\n visible: lockedTime.visible,\n name: lockedTime.displayName,\n }, x => x == null);\n }\n\n return omitBy(doc, x => x == null) as Types.lockedTime;\n });\n};"],"mappings":";;;;AAKA,SAAgB,kBACd,aACA,SACgC;AAEhC,QAAO,aAAa,KAAI,eAAc;EACpC,MAAM,EAAE,OAAO,WAAW,KAAK,YAAY,kBAAkB,YAAY;EAEzE,MAAM,SAAS,QAAQ,KAAK,WAAW;AACvC,MAAI,SAAS,EAAG,OAAM,IAAI,MAAM;EAEhC,MAAM,QAAQ,WAAW,UAAU,OAAO;EAE1C,MAAMA,MAAwB;GAC5B,KAAQ,YAAY;GACZ;GACA;;AAGV,MAAI,QAAQ,KACV,KAAI,OAAO,OAAO;GAChB,IAAS,YAAY,YAAY;GACjC,SAAS,WAAW;GACpB,MAAS,WAAW;MACnB,MAAK,KAAK;AAGf,SAAO,OAAO,MAAK,MAAK,KAAK"}
|
|
@@ -40,16 +40,16 @@ function parseGroupReferences(itemAndType, options) {
|
|
|
40
40
|
...(sources.teachers ?? []).map((x) => idOf.teacher(x.to, options)),
|
|
41
41
|
...mergeWithParentGroups(sources.groups ?? [], options).flatMap((ref) => {
|
|
42
42
|
if (ref.to.species == "class") return idOf.group(ref.to, options);
|
|
43
|
-
return (ref.to.members ?? []).filter((x) => !ref.exclude?.includes(x)).map((x) => x.group ?
|
|
43
|
+
return (ref.to.members ?? []).filter((x) => !ref.exclude?.includes(x)).map((x) => x.group ? idOf.group(x.group, options) : void 0).filter((x) => x != null);
|
|
44
44
|
}),
|
|
45
|
-
...(sources.participants ?? []).map((x) => x.to.group ?
|
|
45
|
+
...(sources.participants ?? []).map((x) => x.to.group ? idOf.group(x.to.group, options) : void 0).filter((x) => x != null)
|
|
46
46
|
]).chain((x) => uniq(x).map((x$1) => [x$1])).value;
|
|
47
47
|
const teacherReferences = (sources.teachers ?? []).map((x) => ({ group: idOf.teacher(x.to, options) }));
|
|
48
48
|
const groupReferences = mergeWithParentGroups(sources.groups ?? [], options).map((x) => {
|
|
49
49
|
if (x.to.species != "class" || x.exclude?.length) return { individuals: idOf.groupReference(x, options) };
|
|
50
50
|
return { group: idOf.group(x.to, options) };
|
|
51
51
|
});
|
|
52
|
-
const participantReferences = sources.participants ? { individuals: sources.participants.map((x) => idOf.person(x.to, options)) } : void 0;
|
|
52
|
+
const participantReferences = sources.participants?.length ? { individuals: sources.participants.map((x) => idOf.person(x.to, options)) } : void 0;
|
|
53
53
|
return teacherReferences.concat(groupReferences, participantReferences ? [participantReferences] : []).map((x) => [x]);
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-group-references.js","names":["x"],"sources":["../../../../../src/RS/to/input/util/parse-group-references.ts"],"sourcesContent":["import { groupBy, uniq } from 'lodash-es';\nimport type { ConnectedTypes } from '../../../make-connected';\nimport { idOf } from './util';\nimport { getVertexId } from '../../../../core/util';\nimport type { GroupReference, PersonReference } from '../../../../core/types/common';\nimport type { Types } from '../../../types';\nimport { makeChainable } from '../../../../common/make-chainable';\n\n/**\n * Merges group references with their parent groups while ensuring that a group is present at\n * most once and that parent groups are prioritized as they carry no member exclusions.\n */\nfunction mergeWithParentGroups (\n references: GroupReference<ConnectedTypes.group, ConnectedTypes.person>[],\n options: Types.parsedToOptions\n): GroupReference<ConnectedTypes.group, ConnectedTypes.person>[] {\n return makeChainable(references)\n .chain(\n x => x.flatMap((x): ((typeof x) & { isParentGroup?: boolean })[] => ([\n x, ...(x.to.parentGroups ?? []).map(y => ({ to: y, isParentGroup: true }))\n ])),\n x => groupBy(x, x => getVertexId(x.to, options)),\n x => Object.values(x)\n .map(xs => xs.find(x => x.isParentGroup) ?? xs.at(0))\n .filter(x => x != null)\n )\n .value;\n}\n\ntype ItemAndType =\n | { item: ConnectedTypes.course, type: 'course' }\n | { item: ConnectedTypes.event, type: 'event' }\n | { item: ConnectedTypes.lockedTime, type: 'lockedTime' };\n\ntype Source = {\n teachers?: PersonReference<ConnectedTypes.teacher>[];\n groups?: GroupReference<ConnectedTypes.group, ConnectedTypes.person>[];\n participants?: PersonReference<ConnectedTypes.person>[];\n};\n\n/**\n * Returns the source of group, teacher, and participant references for a given item while taking into account event inheritance.\n */\nfunction getSources (itemAndType: ItemAndType): Source {\n if (itemAndType.type == 'lockedTime') return {\n teachers: itemAndType.item.coalesced?.filter(x => x.toModel == 'teachers'),\n groups: itemAndType.item.coalesced?.filter(x => x.toModel == 'groups' )\n };\n\n const item = itemAndType.item;\n const teachersSource = item.teachers\n ? item\n : ('course' in item && item.course ? item.course : item);\n const groupsAndParticipantsSource = (item.groups || item.participants)\n ? item\n : ('course' in item && item.course ? item.course : item);\n return {\n teachers: teachersSource.teachers ?? undefined,\n groups: groupsAndParticipantsSource.groups ?? undefined,\n participants: groupsAndParticipantsSource.participants ?? undefined\n };\n}\n\n/**\n * Parses group references from a course or event while carrying out event inheritance and taking into account parent groups.\n */\nexport function parseGroupReferences (\n itemAndType: ItemAndType,\n options: Types.parsedToOptions\n): Types.groupReference[][] {\n const sources = getSources(itemAndType);\n\n // if interested in the old format we care only about references to groups\n if (options.oldFormat) {\n return makeChainable([\n ...(sources.teachers ?? [])\n .map(x => idOf.teacher(x.to, options)),\n ...mergeWithParentGroups(sources.groups ?? [], options)\n .flatMap(ref => {\n if (ref.to.species == 'class') return idOf.group(ref.to, options);\n\n // if not a class fetch the remaining group member's parent group\n return (ref.to.members ?? [])\n .filter(x => !ref.exclude?.includes(x))\n .map(x => x.group ?
|
|
1
|
+
{"version":3,"file":"parse-group-references.js","names":["x"],"sources":["../../../../../src/RS/to/input/util/parse-group-references.ts"],"sourcesContent":["import { groupBy, uniq } from 'lodash-es';\nimport type { ConnectedTypes } from '../../../make-connected';\nimport { idOf } from './util';\nimport { getVertexId } from '../../../../core/util';\nimport type { GroupReference, PersonReference } from '../../../../core/types/common';\nimport type { Types } from '../../../types';\nimport { makeChainable } from '../../../../common/make-chainable';\n\n/**\n * Merges group references with their parent groups while ensuring that a group is present at\n * most once and that parent groups are prioritized as they carry no member exclusions.\n */\nfunction mergeWithParentGroups (\n references: GroupReference<ConnectedTypes.group, ConnectedTypes.person>[],\n options: Types.parsedToOptions\n): GroupReference<ConnectedTypes.group, ConnectedTypes.person>[] {\n return makeChainable(references)\n .chain(\n x => x.flatMap((x): ((typeof x) & { isParentGroup?: boolean })[] => ([\n x, ...(x.to.parentGroups ?? []).map(y => ({ to: y, isParentGroup: true }))\n ])),\n x => groupBy(x, x => getVertexId(x.to, options)),\n x => Object.values(x)\n .map(xs => xs.find(x => x.isParentGroup) ?? xs.at(0))\n .filter(x => x != null)\n )\n .value;\n}\n\ntype ItemAndType =\n | { item: ConnectedTypes.course, type: 'course' }\n | { item: ConnectedTypes.event, type: 'event' }\n | { item: ConnectedTypes.lockedTime, type: 'lockedTime' };\n\ntype Source = {\n teachers?: PersonReference<ConnectedTypes.teacher>[];\n groups?: GroupReference<ConnectedTypes.group, ConnectedTypes.person>[];\n participants?: PersonReference<ConnectedTypes.person>[];\n};\n\n/**\n * Returns the source of group, teacher, and participant references for a given item while taking into account event inheritance.\n */\nfunction getSources (itemAndType: ItemAndType): Source {\n if (itemAndType.type == 'lockedTime') return {\n teachers: itemAndType.item.coalesced?.filter(x => x.toModel == 'teachers'),\n groups: itemAndType.item.coalesced?.filter(x => x.toModel == 'groups' )\n };\n\n const item = itemAndType.item;\n const teachersSource = item.teachers\n ? item\n : ('course' in item && item.course ? item.course : item);\n const groupsAndParticipantsSource = (item.groups || item.participants)\n ? item\n : ('course' in item && item.course ? item.course : item);\n return {\n teachers: teachersSource.teachers ?? undefined,\n groups: groupsAndParticipantsSource.groups ?? undefined,\n participants: groupsAndParticipantsSource.participants ?? undefined\n };\n}\n\n/**\n * Parses group references from a course or event while carrying out event inheritance and taking into account parent groups.\n */\nexport function parseGroupReferences (\n itemAndType: ItemAndType,\n options: Types.parsedToOptions\n): Types.groupReference[][] {\n const sources = getSources(itemAndType);\n\n // if interested in the old format we care only about references to groups\n if (options.oldFormat) {\n return makeChainable([\n ...(sources.teachers ?? [])\n .map(x => idOf.teacher(x.to, options)),\n ...mergeWithParentGroups(sources.groups ?? [], options)\n .flatMap(ref => {\n if (ref.to.species == 'class') return idOf.group(ref.to, options);\n\n // if not a class fetch the remaining group member's parent group\n return (ref.to.members ?? [])\n .filter(x => !ref.exclude?.includes(x))\n .map(x => x.group ? idOf.group(x.group, options) : undefined)\n .filter(x => x != null);\n }),\n ...(sources.participants ?? [])\n .map(x => x.to.group ? idOf.group(x.to.group, options) : undefined)\n .filter(x => x != null)\n ])\n .chain(\n x => uniq(x).map(x => [x])\n )\n .value;\n }\n\n const teacherReferences = (sources.teachers ?? [])\n .map((x): Types.groupReference => ({ group: idOf.teacher(x.to, options) }));\n\n const groupReferences = mergeWithParentGroups(sources.groups ?? [], options)\n .map((x): Types.groupReference => {\n if (x.to.species != 'class' || x.exclude?.length) return { individuals: idOf.groupReference(x, options) }; // use individuals set if not a plain group reference\n return { group: idOf.group(x.to, options) };\n });\n\n const participantReferences = sources.participants?.length\n ? { individuals: sources.participants.map(x => idOf.person(x.to, options)) } as Types.groupReference\n : undefined;\n\n // combine all references\n return teacherReferences\n .concat(\n groupReferences,\n participantReferences ? [participantReferences] : []\n )\n .map(x => [x]);\n}"],"mappings":";;;;;;;;;;AAYA,SAAS,sBACP,YACA,SAC+D;AAC/D,QAAO,cAAc,YAClB,OACC,MAAK,EAAE,SAAS,QAAqD,CACnEA,KAAG,IAAIA,IAAE,GAAG,gBAAgB,IAAI,KAAI,OAAM;EAAE,IAAI;EAAG,eAAe;SAEpE,MAAK,QAAQ,IAAG,QAAK,YAAYA,IAAE,IAAI,YACvC,MAAK,OAAO,OAAO,GAChB,KAAI,OAAM,GAAG,MAAK,QAAKA,IAAE,kBAAkB,GAAG,GAAG,IACjD,QAAO,QAAKA,OAAK,OAErB;;;;;AAiBL,SAAS,WAAY,aAAkC;AACrD,KAAI,YAAY,QAAQ,aAAc,QAAO;EAC3C,UAAU,YAAY,KAAK,WAAW,QAAO,MAAK,EAAE,WAAW;EAC/D,QAAU,YAAY,KAAK,WAAW,QAAO,MAAK,EAAE,WAAW;;CAGjE,MAAM,OAAO,YAAY;CACzB,MAAM,iBAAiB,KAAK,WACxB,OACC,YAAY,QAAQ,KAAK,SAAS,KAAK,SAAS;CACrD,MAAM,8BAA+B,KAAK,UAAU,KAAK,eACrD,OACC,YAAY,QAAQ,KAAK,SAAS,KAAK,SAAS;AACrD,QAAO;EACL,UAAc,eAAe,YAA6B;EAC1D,QAAc,4BAA4B,UAAgB;EAC1D,cAAc,4BAA4B,gBAAgB;;;;;;AAO9D,SAAgB,qBACd,aACA,SAC0B;CAC1B,MAAM,UAAU,WAAW;AAG3B,KAAI,QAAQ,UACV,QAAO,cAAc;EACnB,IAAI,QAAQ,YAAY,IACrB,KAAI,MAAK,KAAK,QAAQ,EAAE,IAAI;EAC/B,GAAG,sBAAsB,QAAQ,UAAU,IAAI,SAC5C,SAAQ,QAAO;AACd,OAAI,IAAI,GAAG,WAAW,QAAS,QAAO,KAAK,MAAM,IAAI,IAAI;AAGzD,WAAQ,IAAI,GAAG,WAAW,IACvB,QAAO,MAAK,CAAC,IAAI,SAAS,SAAS,IACnC,KAAI,MAAK,EAAE,QAAQ,KAAK,MAAM,EAAE,OAAO,WAAW,QAClD,QAAO,MAAK,KAAK;;EAExB,IAAI,QAAQ,gBAAgB,IACzB,KAAI,MAAK,EAAE,GAAG,QAAQ,KAAK,MAAM,EAAE,GAAG,OAAO,WAAW,QACxD,QAAO,MAAK,KAAK;IAEnB,OACC,MAAK,KAAK,GAAG,KAAI,QAAK,CAACA,OAExB;CAGL,MAAM,qBAAqB,QAAQ,YAAY,IAC5C,KAAK,OAA6B,EAAE,OAAO,KAAK,QAAQ,EAAE,IAAI;CAEjE,MAAM,kBAAkB,sBAAsB,QAAQ,UAAU,IAAI,SACjE,KAAK,MAA4B;AAChC,MAAI,EAAE,GAAG,WAAW,WAAW,EAAE,SAAS,OAAQ,QAAO,EAAE,aAAa,KAAK,eAAe,GAAG;AAC/F,SAAO,EAAE,OAAO,KAAK,MAAM,EAAE,IAAI;;CAGrC,MAAM,wBAAwB,QAAQ,cAAc,SAChD,EAAE,aAAa,QAAQ,aAAa,KAAI,MAAK,KAAK,OAAO,EAAE,IAAI,cAC/D;AAGJ,QAAO,kBACJ,OACC,iBACA,wBAAwB,CAAC,yBAAyB,IAEnD,KAAI,MAAK,CAAC"}
|
|
@@ -20,9 +20,9 @@ function getDayLimits(intervals, settings) {
|
|
|
20
20
|
start: start.clone(),
|
|
21
21
|
end: end.clone()
|
|
22
22
|
}));
|
|
23
|
-
} else throw new Error(`(RS::
|
|
23
|
+
} else throw new Error(`(RS::To::Intervals) Intervals length ${intervals.length} does not match settings.numDays ${settings.numDays}`);
|
|
24
24
|
return intervals.map((i, day) => {
|
|
25
|
-
if (!i.start || !i.end) throw new Error(`(RS::
|
|
25
|
+
if (!i.start || !i.end) throw new Error(`(RS::To::Intervals) Interval missing start or end for day ${day}`);
|
|
26
26
|
const start = parseFloat(moment.utc(i.start).format("HH.mm"));
|
|
27
27
|
const end = parseFloat(moment.utc(i.end).format("HH.mm"));
|
|
28
28
|
return {
|
|
@@ -40,7 +40,7 @@ function parseIntervals(intervals, rootInterval, settings) {
|
|
|
40
40
|
const dayLimits = getDayLimits(intervals, settings);
|
|
41
41
|
return makeChainable(rootInterval.intervals).chain((x) => groupBy(x, (x$1) => getDayIndex(x$1.start)), (x) => Object.entries(x).map(([day, xs]) => {
|
|
42
42
|
const limit = dayLimits.at(parseInt(day));
|
|
43
|
-
if (!limit) throw new Error(`(RS::
|
|
43
|
+
if (!limit) throw new Error(`(RS::To::Intervals) Day ${day} not found in dayStartAndEnds`);
|
|
44
44
|
return xs.map((x$1) => ({
|
|
45
45
|
beg: parseFloat(moment.utc(x$1.start).format("HH.mm")),
|
|
46
46
|
end: parseFloat(moment.utc(x$1.end).format("HH.mm")),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-intervals.js","names":["x"],"sources":["../../../../../src/RS/to/input/util/parse-intervals.ts"],"sourcesContent":["import moment from 'moment';\nimport { groupBy } from 'lodash-es';\nimport type { ConnectedTypes } from '../../../make-connected';\nimport type { AllowedInterval } from '../../../../core/types/common/intervals';\nimport { getDayIndex } from '../../../../core/util';\nimport type { Types } from '../../../types';\nimport { makeChainable } from '../../../../common/make-chainable';\n\nfunction getDayLimits (\n intervals: AllowedInterval[] | undefined,\n settings: ConnectedTypes.divisionSettings\n): { beg: number, end: number }[] {\n // remove short-hand notation (a single interval for all days)\n if (!intervals) {\n const start = moment.utc(settings.dayStart, 'HH:mm');\n const end = moment.utc(settings.dayEnd, 'HH:mm');\n intervals = Array.from({ length: settings.numDays }, () => ({ start: start.clone(), end: end.clone() }));\n }\n else if (intervals.length == 1) {\n const i = intervals[0];\n const start = moment.utc(i.start, 'HH:mm');\n const end = moment.utc(i.end, 'HH:mm');\n intervals = Array.from({ length: settings.numDays }, () => ({ start: start.clone(), end: end.clone() }));\n } else {\n throw new Error(`(RS::
|
|
1
|
+
{"version":3,"file":"parse-intervals.js","names":["x"],"sources":["../../../../../src/RS/to/input/util/parse-intervals.ts"],"sourcesContent":["import moment from 'moment';\nimport { groupBy } from 'lodash-es';\nimport type { ConnectedTypes } from '../../../make-connected';\nimport type { AllowedInterval } from '../../../../core/types/common/intervals';\nimport { getDayIndex } from '../../../../core/util';\nimport type { Types } from '../../../types';\nimport { makeChainable } from '../../../../common/make-chainable';\n\nfunction getDayLimits (\n intervals: AllowedInterval[] | undefined,\n settings: ConnectedTypes.divisionSettings\n): { beg: number, end: number }[] {\n // remove short-hand notation (a single interval for all days)\n if (!intervals) {\n const start = moment.utc(settings.dayStart, 'HH:mm');\n const end = moment.utc(settings.dayEnd, 'HH:mm');\n intervals = Array.from({ length: settings.numDays }, () => ({ start: start.clone(), end: end.clone() }));\n }\n else if (intervals.length == 1) {\n const i = intervals[0];\n const start = moment.utc(i.start, 'HH:mm');\n const end = moment.utc(i.end, 'HH:mm');\n intervals = Array.from({ length: settings.numDays }, () => ({ start: start.clone(), end: end.clone() }));\n } else {\n throw new Error(`(RS::To::Intervals) Intervals length ${intervals.length} does not match settings.numDays ${settings.numDays}`);\n }\n\n // the day start and end times of each day\n return intervals.map((i, day: number) => {\n if (!i.start || !i.end) throw new Error(`(RS::To::Intervals) Interval missing start or end for day ${day}`);\n const start = parseFloat(moment.utc(i.start).format('HH.mm'));\n const end = parseFloat(moment.utc(i.end ).format('HH.mm'));\n return { beg: start, end: end };\n });\n}\n\n\n/**\n * @deprecated The old way of parsing intervals\n */\nexport function parseIntervals (\n intervals: AllowedInterval[] | undefined,\n rootInterval: ConnectedTypes.rootInterval | undefined,\n settings: ConnectedTypes.divisionSettings\n): Types.interval[][] | undefined {\n // if only intervals are provided\n if (intervals && !rootInterval) return getDayLimits(intervals, settings).map(i => [i]);\n\n // if root intervals are present\n if (rootInterval) {\n const dayLimits = getDayLimits(intervals, settings);\n return makeChainable(rootInterval.intervals)\n .chain(\n x => groupBy(x, x => getDayIndex(x.start)),\n x => Object.entries(x)\n .map(([day, xs]) => {\n const limit = dayLimits.at(parseInt(day));\n if (!limit) throw new Error(`(RS::To::Intervals) Day ${day} not found in dayStartAndEnds`);\n\n // remove all block intervals that lay outside the day start and end\n return xs\n .map(x => ({\n beg: parseFloat(moment.utc(x.start).format('HH.mm')),\n end: parseFloat(moment.utc(x.end ).format('HH.mm')),\n binary: true\n } satisfies Types.interval))\n .filter(x => x.beg >= limit.beg && x.end <= limit.end);\n })\n )\n .value;\n }\n\n // only remaining case here is \"!intervals && !rootInterval\"\n return;\n};\n"],"mappings":";;;;;;AAQA,SAAS,aACP,WACA,UACgC;AAEhC,KAAI,CAAC,WAAW;EACd,MAAM,QAAQ,OAAO,IAAI,SAAS,UAAU;EAC5C,MAAM,MAAQ,OAAO,IAAI,SAAS,QAAU;AAC5C,cAAY,MAAM,KAAK,EAAE,QAAQ,SAAS,kBAAkB;GAAE,OAAO,MAAM;GAAS,KAAK,IAAI;;YAEtF,UAAU,UAAU,GAAG;EAC9B,MAAM,IAAI,UAAU;EACpB,MAAM,QAAQ,OAAO,IAAI,EAAE,OAAO;EAClC,MAAM,MAAQ,OAAO,IAAI,EAAE,KAAO;AAClC,cAAY,MAAM,KAAK,EAAE,QAAQ,SAAS,kBAAkB;GAAE,OAAO,MAAM;GAAS,KAAK,IAAI;;OAE7F,OAAM,IAAI,MAAM,wCAAwC,UAAU,OAAO,mCAAmC,SAAS;AAIvH,QAAO,UAAU,KAAK,GAAG,QAAgB;AACvC,MAAI,CAAC,EAAE,SAAS,CAAC,EAAE,IAAK,OAAM,IAAI,MAAM,6DAA6D;EACrG,MAAM,QAAQ,WAAW,OAAO,IAAI,EAAE,OAAO,OAAO;EACpD,MAAM,MAAQ,WAAW,OAAO,IAAI,EAAE,KAAO,OAAO;AACpD,SAAO;GAAE,KAAK;GAAY;;;;;;;AAQ9B,SAAgB,eACd,WACA,cACA,UACgC;AAEhC,KAAI,aAAa,CAAC,aAAc,QAAO,aAAa,WAAW,UAAU,KAAI,MAAK,CAAC;AAGnF,KAAI,cAAc;EAChB,MAAM,YAAY,aAAa,WAAW;AAC1C,SAAO,cAAc,aAAa,WAC/B,OACC,MAAK,QAAQ,IAAG,QAAK,YAAYA,IAAE,UACnC,MAAK,OAAO,QAAQ,GACjB,KAAK,CAAC,KAAK,QAAQ;GAClB,MAAM,QAAQ,UAAU,GAAG,SAAS;AACpC,OAAI,CAAC,MAAO,OAAM,IAAI,MAAM,2BAA2B,IAAI;AAG3D,UAAO,GACJ,KAAI,SAAM;IACT,KAAQ,WAAW,OAAO,IAAIA,IAAE,OAAO,OAAO;IAC9C,KAAQ,WAAW,OAAO,IAAIA,IAAE,KAAO,OAAO;IAC9C,QAAQ;OAET,QAAO,QAAKA,IAAE,OAAO,MAAM,OAAOA,IAAE,OAAO,MAAM;MAGzD"}
|
|
@@ -4,14 +4,14 @@ function parseMinimumBreakLength(value) {
|
|
|
4
4
|
if (typeof value === "boolean") return value;
|
|
5
5
|
if (typeof value === "number") return value;
|
|
6
6
|
if (Array.isArray(value)) {
|
|
7
|
-
if (value.length !== 2) throw new Error("(RS::
|
|
7
|
+
if (value.length !== 2) throw new Error("(RS::To::BreakLengths) BreakLength array must have exactly two elements");
|
|
8
8
|
const [bef, aft] = value;
|
|
9
9
|
return {
|
|
10
10
|
bef,
|
|
11
11
|
aft
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
|
-
throw new Error("(RS::
|
|
14
|
+
throw new Error("(RS::To::BreakLengths) BreakLength is neither boolean, number or number array");
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-minimum-break-length.js","names":[],"sources":["../../../../../src/RS/to/input/util/parse-minimum-break-length.ts"],"sourcesContent":["import type { CoreTypes } from '../../../../core';\nimport type { Types } from '../../../types';\n\nexport function parseMinimumBreakLength (value: CoreTypes.breakLength | null | undefined): Types.breakLength | undefined {\n if (value == null) return;\n\n if (typeof value === 'boolean') return value;\n if (typeof value === 'number') return value;\n\n if (Array.isArray(value)) {\n if (value.length !== 2) throw new Error('(RS::
|
|
1
|
+
{"version":3,"file":"parse-minimum-break-length.js","names":[],"sources":["../../../../../src/RS/to/input/util/parse-minimum-break-length.ts"],"sourcesContent":["import type { CoreTypes } from '../../../../core';\nimport type { Types } from '../../../types';\n\nexport function parseMinimumBreakLength (value: CoreTypes.breakLength | null | undefined): Types.breakLength | undefined {\n if (value == null) return;\n\n if (typeof value === 'boolean') return value;\n if (typeof value === 'number') return value;\n\n if (Array.isArray(value)) {\n if (value.length !== 2) throw new Error('(RS::To::BreakLengths) BreakLength array must have exactly two elements');\n const [bef, aft] = value;\n return { bef, aft };\n }\n\n throw new Error('(RS::To::BreakLengths) BreakLength is neither boolean, number or number array');\n};\n"],"mappings":";AAGA,SAAgB,wBAAyB,OAAgF;AACvH,KAAI,SAAS,KAAM;AAEnB,KAAI,OAAO,UAAU,UAAW,QAAO;AACvC,KAAI,OAAO,UAAU,SAAU,QAAO;AAEtC,KAAI,MAAM,QAAQ,QAAQ;AACxB,MAAI,MAAM,WAAW,EAAG,OAAM,IAAI,MAAM;EACxC,MAAM,CAAC,KAAK,OAAO;AACnB,SAAO;GAAE;GAAK;;;AAGhB,OAAM,IAAI,MAAM"}
|
|
@@ -14,7 +14,7 @@ function getPeriodIndex(period, periodsMap, options) {
|
|
|
14
14
|
if (!period) return;
|
|
15
15
|
const id = getVertexId(period, options);
|
|
16
16
|
const periodIndex = periodsMap.get(id);
|
|
17
|
-
if (periodIndex === void 0) throw new Error(`(RS::
|
|
17
|
+
if (periodIndex === void 0) throw new Error(`(RS::To::getPeriodIndex) Period "${id}" is not in periodsMap`);
|
|
18
18
|
return periodIndex;
|
|
19
19
|
}
|
|
20
20
|
const COLLECTION_ID = {
|
|
@@ -51,7 +51,12 @@ let idOf;
|
|
|
51
51
|
}
|
|
52
52
|
_idOf.groupReference = groupReference;
|
|
53
53
|
function intervalPairReference(interval, rootInterval, options) {
|
|
54
|
-
|
|
54
|
+
if (interval === null) interval = void 0;
|
|
55
|
+
if (rootInterval === null) rootInterval = void 0;
|
|
56
|
+
if (interval && interval.length == 0) interval = void 0;
|
|
57
|
+
if (rootInterval && rootInterval.intervals.length == 0) rootInterval = void 0;
|
|
58
|
+
const out = (rootInterval ? getVertexId(rootInterval, options) + "&" : "") + JSON.stringify(interval);
|
|
59
|
+
return out;
|
|
55
60
|
}
|
|
56
61
|
_idOf.intervalPairReference = intervalPairReference;
|
|
57
62
|
})(idOf || (idOf = {}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","names":["person","group","teacher","event","lockedTime"],"sources":["../../../../../src/RS/to/input/util/util.ts"],"sourcesContent":["import type { ConnectedTypes } from '../../../make-connected';\nimport type { Types } from '../../../types';\nimport type { Collection, GroupReference } from '../../../../core/types/common';\nimport { getVertexId } from '../../../../core/util';\nimport type { AllowedInterval } from '../../../../core/types/common/intervals';\n\nexport function min2hrs (min: number | undefined | null) {\n return min ? min / 60 : undefined;\n}\n\n/**\n * Converts a time string in the format \"HH:MM\" to a float representation, e.g., \"12:30\" becomes 12.3.\n */\nexport function toTimeFloat (str: string) {\n return parseFloat(str.replace(':', '.'));\n}\n\nexport function getPeriodIndex (\n period: ConnectedTypes.period | undefined | null,\n periodsMap: Map<string | undefined, number>,\n options: Types.parsedToOptions\n): number | undefined {\n if (!period) return;\n const id = getVertexId(period, options);\n const periodIndex = periodsMap.get(id);\n if (periodIndex === undefined) throw new Error(`(RS::
|
|
1
|
+
{"version":3,"file":"util.js","names":["person","group","teacher","event","lockedTime"],"sources":["../../../../../src/RS/to/input/util/util.ts"],"sourcesContent":["import type { ConnectedTypes } from '../../../make-connected';\nimport type { Types } from '../../../types';\nimport type { Collection, GroupReference } from '../../../../core/types/common';\nimport { getVertexId } from '../../../../core/util';\nimport type { AllowedInterval } from '../../../../core/types/common/intervals';\n\nexport function min2hrs (min: number | undefined | null) {\n return min ? min / 60 : undefined;\n}\n\n/**\n * Converts a time string in the format \"HH:MM\" to a float representation, e.g., \"12:30\" becomes 12.3.\n */\nexport function toTimeFloat (str: string) {\n return parseFloat(str.replace(':', '.'));\n}\n\nexport function getPeriodIndex (\n period: ConnectedTypes.period | undefined | null,\n periodsMap: Map<string | undefined, number>,\n options: Types.parsedToOptions\n): number | undefined {\n if (!period) return;\n const id = getVertexId(period, options);\n const periodIndex = periodsMap.get(id);\n if (periodIndex === undefined) throw new Error(`(RS::To::getPeriodIndex) Period \"${id}\" is not in periodsMap`);\n return periodIndex;\n}\n\nexport const COLLECTION_ID = {\n persons: 'persons',\n groups: 'groups',\n teachers: 'teachers',\n events: 'events',\n lockedTimes: 'lockedtimes',\n} satisfies Partial<Record<Collection, string>>;\n\n/**\n * returns a combined id for the vertex or edge by combining the type(s) and id(s).\n */\nexport namespace idOf {\n /** `persons.id` */\n export function person (\n person: ConnectedTypes.person | string,\n options: Types.parsedToOptions\n ): string {\n return `${COLLECTION_ID.persons}.${ getVertexId(person, options) }`;\n }\n\n /** `groups.id` */\n export function group (\n group: ConnectedTypes.group,\n options: Types.parsedToOptions\n ): string {\n return `${COLLECTION_ID.groups}.${ getVertexId(group, options) }`;\n }\n\n /** `teachers.id` */\n export function teacher (\n teacher: ConnectedTypes.teacher,\n options: Types.parsedToOptions\n ): string {\n return `${COLLECTION_ID.teachers}.${ getVertexId(teacher, options) }`;\n }\n\n /** `events.id` */\n export function event (\n event: ConnectedTypes.event,\n options: Types.parsedToOptions\n ): string {\n return `${COLLECTION_ID.events}.${ getVertexId(event, options) }`;\n }\n\n /** `lockedtimes.id` */\n export function lockedTime (\n lockedTime: ConnectedTypes.lockedTime,\n options: Types.parsedToOptions\n ): string {\n return `${COLLECTION_ID.lockedTimes}.${ getVertexId(lockedTime, options) }`;\n }\n\n /** `groups.id<.exclude.id1.id2...>` */\n export function groupReference (\n group: GroupReference<ConnectedTypes.group, ConnectedTypes.person>,\n options: Types.parsedToOptions\n ): string {\n return `${COLLECTION_ID.groups}.${ getVertexId(group.to, options) }`\n + (group.exclude?.length\n ? '.exclude.' + group.exclude\n .map(x => getVertexId(x, options))\n .sort()\n .join('.')\n : '');\n }\n\n /** `<rootIntervalsId&>JSON.stringify(intervals)>` */\n export function intervalPairReference (\n interval: AllowedInterval[] | undefined,\n rootInterval: ConnectedTypes.rootInterval | undefined,\n options: Types.parsedToOptions\n ): string {\n // replace null with undefined\n if (interval === null) interval = undefined;\n if (rootInterval === null) rootInterval = undefined;\n\n // replace empty intervals with undefined\n if (interval && interval .length == 0) interval = undefined;\n if (rootInterval && rootInterval.intervals.length == 0) rootInterval = undefined;\n\n const out = (rootInterval ? getVertexId(rootInterval, options) + '&' : '') + JSON.stringify(interval);\n return out;\n }\n}\n"],"mappings":";;;AAMA,SAAgB,QAAS,KAAgC;AACvD,QAAO,MAAM,MAAM,KAAK;;;;;AAM1B,SAAgB,YAAa,KAAa;AACxC,QAAO,WAAW,IAAI,QAAQ,KAAK;;AAGrC,SAAgB,eACd,QACA,YACA,SACoB;AACpB,KAAI,CAAC,OAAQ;CACb,MAAM,KAAK,YAAY,QAAQ;CAC/B,MAAM,cAAc,WAAW,IAAI;AACnC,KAAI,gBAAgB,OAAW,OAAM,IAAI,MAAM,oCAAoC,GAAG;AACtF,QAAO;;AAGT,MAAa,gBAAgB;CAC3B,SAAa;CACb,QAAa;CACb,UAAa;CACb,QAAa;CACb,aAAa;;;;CAQN,SAAS,OACd,UACA,SACQ;AACR,SAAO,GAAG,cAAc,QAAQ,GAAI,YAAYA,UAAQ;;;CAInD,SAAS,MACd,SACA,SACQ;AACR,SAAO,GAAG,cAAc,OAAO,GAAI,YAAYC,SAAO;;;CAIjD,SAAS,QACd,WACA,SACQ;AACR,SAAO,GAAG,cAAc,SAAS,GAAI,YAAYC,WAAS;;;CAIrD,SAAS,MACd,SACA,SACQ;AACR,SAAO,GAAG,cAAc,OAAO,GAAI,YAAYC,SAAO;;;CAIjD,SAAS,WACd,cACA,SACQ;AACR,SAAO,GAAG,cAAc,YAAY,GAAI,YAAYC,cAAY;;;CAI3D,SAAS,eACd,SACA,SACQ;AACR,SAAO,GAAG,cAAc,OAAO,GAAI,YAAYH,QAAM,IAAI,cACpDA,QAAM,SAAS,SACd,cAAcA,QAAM,QACnB,KAAI,MAAK,YAAY,GAAG,UACxB,OACA,KAAK,OACN;;;CAID,SAAS,sBACd,UACA,cACA,SACQ;AAER,MAAI,aAAiB,KAAM,YAAe;AAC1C,MAAI,iBAAiB,KAAM,gBAAe;AAG1C,MAAI,YAAgB,SAAuB,UAAU,EAAG,YAAe;AACvE,MAAI,gBAAgB,aAAa,UAAU,UAAU,EAAG,gBAAe;EAEvE,MAAM,OAAO,eAAe,YAAY,cAAc,WAAW,MAAM,MAAM,KAAK,UAAU;AAC5F,SAAO"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { BaseOptions } from "../../../common/types.js";
|
|
2
2
|
import { Types } from "../../../core/types/index.js";
|
|
3
|
-
import * as
|
|
3
|
+
import * as xlsx1 from "xlsx";
|
|
4
4
|
|
|
5
5
|
//#region src/SchoolSoft/file/to/index.d.ts
|
|
6
6
|
declare class export_default {
|
|
7
7
|
static schedules: (schedule: Types.mixed.schedule & {
|
|
8
8
|
division?: Types.mixed.division;
|
|
9
|
-
}, options?: BaseOptions) =>
|
|
9
|
+
}, options?: BaseOptions) => xlsx1.WorkBook;
|
|
10
10
|
}
|
|
11
11
|
//#endregion
|
|
12
12
|
export { export_default };
|
|
@@ -105,20 +105,6 @@ type Warning = { [key in keyof ErrorType]: {
|
|
|
105
105
|
code: key;
|
|
106
106
|
context: ErrorType[key];
|
|
107
107
|
} }[keyof ErrorType];
|
|
108
|
-
declare namespace Types {
|
|
109
|
-
type room = Room;
|
|
110
|
-
type subject = Subject;
|
|
111
|
-
type teacher = Teacher;
|
|
112
|
-
type group = Group;
|
|
113
|
-
type course = Course;
|
|
114
|
-
type periodGeneral = PeriodGeneral;
|
|
115
|
-
type period = Period;
|
|
116
|
-
type ta = TA;
|
|
117
|
-
type lesson = Lesson;
|
|
118
|
-
type student = Student;
|
|
119
|
-
type errorType = ErrorType;
|
|
120
|
-
type errorCode = ErrorCode;
|
|
121
|
-
}
|
|
122
108
|
type Options = {
|
|
123
109
|
/**
|
|
124
110
|
* Specifies which field to use as the source for creating additional scheduling periods.
|
|
@@ -135,6 +121,21 @@ type Options = {
|
|
|
135
121
|
*/
|
|
136
122
|
includeEventsMissingCourse?: boolean;
|
|
137
123
|
};
|
|
124
|
+
declare namespace Types {
|
|
125
|
+
type room = Room;
|
|
126
|
+
type subject = Subject;
|
|
127
|
+
type teacher = Teacher;
|
|
128
|
+
type group = Group;
|
|
129
|
+
type course = Course;
|
|
130
|
+
type periodGeneral = PeriodGeneral;
|
|
131
|
+
type period = Period;
|
|
132
|
+
type ta = TA;
|
|
133
|
+
type lesson = Lesson;
|
|
134
|
+
type student = Student;
|
|
135
|
+
type errorType = ErrorType;
|
|
136
|
+
type errorCode = ErrorCode;
|
|
137
|
+
type options = Options;
|
|
138
|
+
}
|
|
138
139
|
//#endregion
|
|
139
140
|
export { Options, Types, Warning };
|
|
140
141
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -40,6 +40,9 @@ type Course = Vertex & {
|
|
|
40
40
|
endDate?: DateType;
|
|
41
41
|
exceptions?: Exception[];
|
|
42
42
|
lockedTimes?: LockedTime[];
|
|
43
|
+
/**
|
|
44
|
+
* @note an empty array is the same as undefined
|
|
45
|
+
*/
|
|
43
46
|
intervals?: AllowedInterval[];
|
|
44
47
|
centerOfAttraction?: string | null;
|
|
45
48
|
syllabus?: Syllabus;
|
package/dist/core/util.js
CHANGED
|
@@ -28,13 +28,13 @@ function getDayIndex(value) {
|
|
|
28
28
|
return (day + 6) % 7;
|
|
29
29
|
}
|
|
30
30
|
function parseDateInterval(interval, type) {
|
|
31
|
-
if (!interval.start) throw new Error(`(RS::
|
|
32
|
-
if (!interval.end) throw new Error(`(RS::
|
|
31
|
+
if (!interval.start) throw new Error(`(RS::To::validateInterval) The interval ${type ? `"${type}"` : ""} is missing a start time`);
|
|
32
|
+
if (!interval.end) throw new Error(`(RS::To::validateInterval) The interval ${type ? `"${type}"` : ""} is missing an end time`);
|
|
33
33
|
const start = moment.utc(interval.start);
|
|
34
34
|
const end = moment.utc(interval.end);
|
|
35
|
-
if (!start.isValid()) throw new Error(`(RS::
|
|
36
|
-
if (!end.isValid()) throw new Error(`(RS::
|
|
37
|
-
if (end.isSameOrBefore(start)) throw new Error(`(RS::
|
|
35
|
+
if (!start.isValid()) throw new Error(`(RS::To::validateInterval) The interval ${type ? `"${type}"` : ""} has an invalid start time`);
|
|
36
|
+
if (!end.isValid()) throw new Error(`(RS::To::validateInterval) The interval ${type ? `"${type}"` : ""} has an invalid end time`);
|
|
37
|
+
if (end.isSameOrBefore(start)) throw new Error(`(RS::To::validateInterval) The interval ${type ? `"${type}"` : ""} is invalid: end time is before or equal to start time`);
|
|
38
38
|
return {
|
|
39
39
|
start,
|
|
40
40
|
end
|
package/dist/core/util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","names":["MongooseTypes"],"sources":["../../src/core/util.ts"],"sourcesContent":["import moment from 'moment';\nimport { Types as MongooseTypes } from 'mongoose';\nimport type { IdKey, InternalIdKey, SerializedVertex, Vertex } from './types/common';\nimport type { Interval } from './types/common/intervals';\nimport type { DateType } from '../common/types';\n\n/**\n * Returns the ID key to use for vertices, which can be either `id`, `_id`, or `ids`.\n */\nexport function getIdKey ({ idKey }: { idKey?: IdKey }) {\n return idKey ?? 'id';\n}\n\n/**\n * Returns the ID of a vertex, which can be either `_id`, `id`, or `ids`.\n */\nexport function getVertexId (\n edge: Vertex | Omit<Vertex, InternalIdKey> | SerializedVertex,\n _idKey: IdKey | { idKey?: IdKey }\n): string {\n if (typeof edge === 'string') return edge;\n if (edge instanceof MongooseTypes.ObjectId) return edge.toString();\n\n const idKey = typeof _idKey === 'string' ? _idKey : getIdKey(_idKey);\n if (idKey == '_id' && idKey in edge) return edge._id.toString();\n if (idKey == 'id' && idKey in edge) return edge.id;\n if (idKey == 'ids' && edge.ids ) return edge.ids;\n\n throw new Error(`Unable to get vertex ID \"${idKey}\" from edge: ${JSON.stringify(edge)}`);\n}\n\n\n/**\n * Returns the day index in the range 0-6, where 0 is Monday and 6 is Sunday.\n */\nexport function getDayIndex (value: DateType | number): number {\n const day = typeof value === 'number' ? value : moment.utc(value).day();\n return (day + 6) % 7;\n}\n\nexport function parseDateInterval (interval: Partial<Interval<DateType>>, type?: string): Interval<moment.Moment> {\n if (!interval.start) throw new Error(`(RS::
|
|
1
|
+
{"version":3,"file":"util.js","names":["MongooseTypes"],"sources":["../../src/core/util.ts"],"sourcesContent":["import moment from 'moment';\nimport { Types as MongooseTypes } from 'mongoose';\nimport type { IdKey, InternalIdKey, SerializedVertex, Vertex } from './types/common';\nimport type { Interval } from './types/common/intervals';\nimport type { DateType } from '../common/types';\n\n/**\n * Returns the ID key to use for vertices, which can be either `id`, `_id`, or `ids`.\n */\nexport function getIdKey ({ idKey }: { idKey?: IdKey }) {\n return idKey ?? 'id';\n}\n\n/**\n * Returns the ID of a vertex, which can be either `_id`, `id`, or `ids`.\n */\nexport function getVertexId (\n edge: Vertex | Omit<Vertex, InternalIdKey> | SerializedVertex,\n _idKey: IdKey | { idKey?: IdKey }\n): string {\n if (typeof edge === 'string') return edge;\n if (edge instanceof MongooseTypes.ObjectId) return edge.toString();\n\n const idKey = typeof _idKey === 'string' ? _idKey : getIdKey(_idKey);\n if (idKey == '_id' && idKey in edge) return edge._id.toString();\n if (idKey == 'id' && idKey in edge) return edge.id;\n if (idKey == 'ids' && edge.ids ) return edge.ids;\n\n throw new Error(`Unable to get vertex ID \"${idKey}\" from edge: ${JSON.stringify(edge)}`);\n}\n\n\n/**\n * Returns the day index in the range 0-6, where 0 is Monday and 6 is Sunday.\n */\nexport function getDayIndex (value: DateType | number): number {\n const day = typeof value === 'number' ? value : moment.utc(value).day();\n return (day + 6) % 7;\n}\n\nexport function parseDateInterval (interval: Partial<Interval<DateType>>, type?: string): Interval<moment.Moment> {\n if (!interval.start) throw new Error(`(RS::To::validateInterval) The interval ${type ? `\"${type}\"` : ''} is missing a start time`);\n if (!interval.end ) throw new Error(`(RS::To::validateInterval) The interval ${type ? `\"${type}\"` : ''} is missing an end time`);\n\n const start = moment.utc(interval.start);\n const end = moment.utc(interval.end);\n if (!start.isValid()) throw new Error(`(RS::To::validateInterval) The interval ${type ? `\"${type}\"` : ''} has an invalid start time`);\n if (!end .isValid()) throw new Error(`(RS::To::validateInterval) The interval ${type ? `\"${type}\"` : ''} has an invalid end time`);\n\n if (end.isSameOrBefore(start)) throw new Error(`(RS::To::validateInterval) The interval ${type ? `\"${type}\"` : ''} is invalid: end time is before or equal to start time`);\n\n return { start, end };\n}"],"mappings":";;;;;;;AASA,SAAgB,SAAU,EAAE,SAA4B;AACtD,QAAO,SAAS;;;;;AAMlB,SAAgB,YACd,MACA,QACQ;AACR,KAAI,OAAO,SAAS,SAAU,QAAO;AACrC,KAAI,gBAAgBA,MAAc,SAAU,QAAO,KAAK;CAExD,MAAM,QAAQ,OAAO,WAAW,WAAW,SAAS,SAAS;AAC7D,KAAI,SAAS,SAAS,SAAS,KAAM,QAAO,KAAK,IAAI;AACrD,KAAI,SAAS,QAAS,SAAS,KAAM,QAAO,KAAK;AACjD,KAAI,SAAS,SAAS,KAAK,IAAU,QAAO,KAAK;AAEjD,OAAM,IAAI,MAAM,4BAA4B,MAAM,eAAe,KAAK,UAAU;;;;;AAOlF,SAAgB,YAAa,OAAkC;CAC7D,MAAM,MAAM,OAAO,UAAU,WAAW,QAAQ,OAAO,IAAI,OAAO;AAClE,SAAQ,MAAM,KAAK;;AAGrB,SAAgB,kBAAmB,UAAuC,MAAwC;AAChH,KAAI,CAAC,SAAS,MAAO,OAAM,IAAI,MAAM,2CAA2C,OAAO,IAAI,KAAK,KAAK,GAAG;AACxG,KAAI,CAAC,SAAS,IAAO,OAAM,IAAI,MAAM,2CAA2C,OAAO,IAAI,KAAK,KAAK,GAAG;CAExG,MAAM,QAAQ,OAAO,IAAI,SAAS;CAClC,MAAM,MAAQ,OAAO,IAAI,SAAS;AAClC,KAAI,CAAC,MAAM,UAAW,OAAM,IAAI,MAAM,2CAA2C,OAAO,IAAI,KAAK,KAAK,GAAG;AACzG,KAAI,CAAC,IAAM,UAAW,OAAM,IAAI,MAAM,2CAA2C,OAAO,IAAI,KAAK,KAAK,GAAG;AAEzG,KAAI,IAAI,eAAe,OAAQ,OAAM,IAAI,MAAM,2CAA2C,OAAO,IAAI,KAAK,KAAK,GAAG;AAElH,QAAO;EAAE;EAAO"}
|