@royalschedule/maps 4.0.9 → 4.0.11
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/PlanDigital/index.d.ts +26 -27
- package/dist/RS/make-connected.js +1 -3
- package/dist/RS/make-connected.js.map +1 -1
- package/dist/RS/to/input/collections.js +1 -1
- package/dist/RS/to/input/collections.js.map +1 -1
- package/dist/RS/to/input/default.js +2 -1
- package/dist/RS/to/input/default.js.map +1 -1
- package/dist/RS/to/input/input.js +1 -1
- package/dist/RS/to/input/intervals.js +4 -1
- package/dist/RS/to/input/intervals.js.map +1 -1
- package/dist/RS/to/input/periods.js +6 -2
- package/dist/RS/to/input/periods.js.map +1 -1
- package/dist/RS/to/input/util/parse-intervals.js +4 -1
- package/dist/RS/to/input/util/parse-intervals.js.map +1 -1
- package/dist/RS/to/input/util/util.js +3 -2
- package/dist/RS/to/input/util/util.js.map +1 -1
- package/dist/core/types/courses.d.ts +0 -1
- package/dist/core/types/events.d.ts +3 -1
- package/package.json +1 -1
|
@@ -15,55 +15,55 @@ declare class PlanDigitalMap {
|
|
|
15
15
|
groups?: {
|
|
16
16
|
exceptions?: string[] | undefined;
|
|
17
17
|
lockedTimes?: string[] | undefined;
|
|
18
|
-
ids?: ID | undefined;
|
|
19
18
|
createdAt?: DateType | undefined;
|
|
20
19
|
updatedAt?: DateType | undefined;
|
|
21
20
|
lastModifiedBy?: unknown;
|
|
22
|
-
|
|
23
|
-
rank?: number | undefined;
|
|
21
|
+
ids?: ID | undefined;
|
|
24
22
|
displayName?: string | undefined;
|
|
25
|
-
|
|
26
|
-
intervals?: AllowedInterval[] | undefined;
|
|
23
|
+
rank?: number | undefined;
|
|
27
24
|
days?: Day[] | undefined;
|
|
25
|
+
belongsTo?: string | undefined;
|
|
26
|
+
intervals?: AllowedInterval[] | undefined;
|
|
28
27
|
minBreakLength?: BreakLength | undefined;
|
|
29
|
-
tags?: Tag[] | undefined;
|
|
30
28
|
maximumScheduleSpan?: MaximumScheduleSpan | undefined;
|
|
31
29
|
forbidOverlappingEvents?: boolean | undefined;
|
|
32
30
|
disableDayLengthPunishment?: boolean | undefined;
|
|
33
31
|
weight?: number | undefined;
|
|
34
|
-
rootInterval?: string | undefined;
|
|
35
|
-
maxNumWorkingHours?: number | boolean | undefined;
|
|
36
|
-
maxNumDailyWorkingHours?: number | number[] | boolean | undefined;
|
|
37
32
|
species?: "class" | undefined;
|
|
38
33
|
parentGroups?: string[] | undefined;
|
|
39
34
|
subGroups?: string[] | undefined;
|
|
35
|
+
lunch?: string[] | undefined;
|
|
40
36
|
members?: string[] | 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
43
|
exceptions?: string[] | undefined;
|
|
44
44
|
lockedTimes?: string[] | undefined;
|
|
45
|
-
ids?: ID | undefined;
|
|
46
45
|
createdAt?: DateType | undefined;
|
|
47
46
|
updatedAt?: DateType | undefined;
|
|
48
47
|
lastModifiedBy?: unknown;
|
|
49
|
-
|
|
50
|
-
rank?: number | undefined;
|
|
48
|
+
ids?: ID | undefined;
|
|
51
49
|
displayName?: string | undefined;
|
|
52
|
-
|
|
53
|
-
intervals?: AllowedInterval[] | undefined;
|
|
50
|
+
rank?: number | undefined;
|
|
54
51
|
days?: Day[] | undefined;
|
|
52
|
+
belongsTo?: string | undefined;
|
|
53
|
+
intervals?: AllowedInterval[] | undefined;
|
|
55
54
|
minBreakLength?: BreakLength | undefined;
|
|
56
|
-
tags?: Tag[] | undefined;
|
|
57
|
-
plannedScheduledDuration?: PlannedScheduledDuration | undefined;
|
|
58
55
|
maximumScheduleSpan?: MaximumScheduleSpan | undefined;
|
|
59
56
|
forbidOverlappingEvents?: boolean | undefined;
|
|
60
57
|
disableDayLengthPunishment?: boolean | undefined;
|
|
61
58
|
weight?: number | undefined;
|
|
62
|
-
|
|
59
|
+
lunch?: string[] | undefined;
|
|
63
60
|
rootInterval?: string | undefined;
|
|
64
|
-
|
|
61
|
+
tags?: Tag[] | undefined;
|
|
65
62
|
maxNumWorkingHours?: number | boolean | undefined;
|
|
66
63
|
maxNumDailyWorkingHours?: number | number[] | boolean | undefined;
|
|
64
|
+
plannedScheduledDuration?: PlannedScheduledDuration | undefined;
|
|
65
|
+
person?: string | undefined;
|
|
66
|
+
signature?: string | undefined;
|
|
67
67
|
}[];
|
|
68
68
|
courses?: {
|
|
69
69
|
exceptions?: string[] | undefined;
|
|
@@ -72,33 +72,32 @@ declare class PlanDigitalMap {
|
|
|
72
72
|
locations?: AvailableLocation<string>[] | undefined;
|
|
73
73
|
events?: string[] | undefined;
|
|
74
74
|
lockedTimes?: string[] | undefined;
|
|
75
|
-
ids?: ID | undefined;
|
|
76
75
|
createdAt?: DateType | undefined;
|
|
77
76
|
updatedAt?: DateType | undefined;
|
|
78
77
|
lastModifiedBy?: unknown;
|
|
79
|
-
|
|
78
|
+
ids?: ID | undefined;
|
|
80
79
|
displayName?: string | undefined;
|
|
81
|
-
intervals?: AllowedInterval[] | undefined;
|
|
82
80
|
days?: Day[] | undefined;
|
|
83
|
-
minBreakLength?: BreakLength | undefined;
|
|
84
|
-
tags?: Tag[] | undefined;
|
|
85
81
|
weeks?: number[] | undefined;
|
|
86
|
-
|
|
82
|
+
belongsTo?: string | undefined;
|
|
87
83
|
period?: string | undefined;
|
|
84
|
+
type?: string | undefined;
|
|
85
|
+
intervals?: AllowedInterval[] | undefined;
|
|
86
|
+
minBreakLength?: BreakLength | undefined;
|
|
87
|
+
weight?: number | undefined;
|
|
88
|
+
tags?: Tag[] | undefined;
|
|
89
|
+
color?: string | undefined;
|
|
88
90
|
participants?: PersonReference<string>[] | undefined;
|
|
89
91
|
density?: number | undefined;
|
|
90
92
|
subject?: string | undefined;
|
|
91
|
-
color?: string | undefined;
|
|
92
93
|
eventDurationVariance?: number | undefined;
|
|
93
94
|
totalTime?: string | undefined;
|
|
94
|
-
type?: string | undefined;
|
|
95
95
|
comment?: string | undefined;
|
|
96
96
|
startDate?: DateType | undefined;
|
|
97
97
|
endDate?: DateType | undefined;
|
|
98
98
|
centerOfAttraction?: string | null | undefined;
|
|
99
99
|
syllabus?: string | undefined;
|
|
100
100
|
overlapGroup?: string | null | undefined;
|
|
101
|
-
overlapSpecies?: string | null | undefined;
|
|
102
101
|
plannedDuration?: string | undefined;
|
|
103
102
|
minutesPerWeek?: number | undefined;
|
|
104
103
|
expectedTotalHours?: number | undefined;
|
|
@@ -217,8 +217,7 @@ function makeConnected(schedule, options = {}) {
|
|
|
217
217
|
lockedTimes: getLockedTimes(x.lockedTimes),
|
|
218
218
|
events: x.events ? x.events.map((x$1) => eventsMap.get(getVertexId(x$1, idKey))).filter(nonNullable) : x.events,
|
|
219
219
|
period: x.period != null ? periodsMap.get(getVertexId(x.period, idKey)) : x.period,
|
|
220
|
-
overlapGroup: x.overlapGroup != null ? overlapGroupsMap.get(getVertexId(x.overlapGroup, idKey)) : x.overlapGroup
|
|
221
|
-
overlapSpecies: x.overlapSpecies != null ? overlapGroupsMap.get(getVertexId(x.overlapSpecies, idKey)) : x.overlapSpecies
|
|
220
|
+
overlapGroup: x.overlapGroup != null ? overlapGroupsMap.get(getVertexId(x.overlapGroup, idKey)) : x.overlapGroup
|
|
222
221
|
};
|
|
223
222
|
return Object.assign(x, edges);
|
|
224
223
|
});
|
|
@@ -232,7 +231,6 @@ function makeConnected(schedule, options = {}) {
|
|
|
232
231
|
inLocations: x.inLocations ? x.inLocations.map((x$1) => x$1 === null ? null : locationsMap.get(getVertexId(x$1, idKey))).filter((x$1) => x$1 !== void 0) : x.inLocations,
|
|
233
232
|
course: x.course != null ? coursesMap.get(getVertexId(x.course, idKey)) : x.course,
|
|
234
233
|
period: x.period != null ? periodsMap.get(getVertexId(x.period, idKey)) : x.period,
|
|
235
|
-
overlapGroup: x.overlapGroup != null ? overlapGroupsMap.get(getVertexId(x.overlapGroup, idKey)) : x.overlapGroup,
|
|
236
234
|
overlapSpecies: x.overlapSpecies != null ? overlapGroupsMap.get(getVertexId(x.overlapSpecies, idKey)) : x.overlapSpecies
|
|
237
235
|
};
|
|
238
236
|
return Object.assign(x, edges);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"make-connected.js","names":["vertex: Record<keyof Required<Intersect<Vertex>>, unknown>","edges: ExtractEdges<DivisionSettings>","x","edges: ExtractEdges<Location>","edges: ExtractEdges<Group>","edges: ExtractEdges<Teacher>","edges: ExtractEdges<Person>","edges: ExtractEdges<Period>","edges: ExtractEdges<RootInterval>","map","edges: ExtractEdges<LockedTime>","edges: ExtractEdges<OverlapGroup>","coalesced: Coalesced<typeof to, (typeof x)['toModel']>","species: Species<typeof to, (typeof x)['toModel']>","participant: PersonReference<Person>","locations","availableLocation: AvailableLocation<Location>","group: GroupReference<Group, Person>","edges: ExtractEdges<Course>","edges: ExtractEdges<Event>"],"sources":["../../src/RS/make-connected.ts"],"sourcesContent":["import { pick } from 'lodash-es';\nimport { getIdKey, getVertexId } from '../core/util';\nimport type { ExtractEdges, Mixed } from '../core/vertex-mapping';\nimport type { CoreTypes } from '../core';\nimport type { AvailableLocation, Coalesced, Collection, GroupReference, IdKey, InternalIdKey, PersonReference, Species, Vertex } from '../core/types/common';\nimport type { Types } from './types';\nimport type { Intersect } from '../common/types';\n\ntype OmitProperties<T extends Vertex> = Omit<T, 'belongsTo' | 'exceptions' | 'defaultLunch' | 'syllabus' | InternalIdKey> & Vertex;\n\ntype _Schedule = {\n division: Mixed<CoreTypes.division>;\n divisions: Mixed<CoreTypes.division>;\n settings: Mixed<CoreTypes.divisionSettings>;\n groups: Mixed<CoreTypes.group>[];\n teachers: Mixed<CoreTypes.teacher>[];\n locations: Mixed<CoreTypes.location>[];\n periods: Mixed<CoreTypes.period>[];\n persons: Mixed<CoreTypes.person>[];\n rootIntervals: Mixed<CoreTypes.rootInterval>[];\n lockedTimes: Mixed<CoreTypes.lockedTime>[];\n overlapGroups: Mixed<CoreTypes.overlapGroup>[];\n courses: Mixed<CoreTypes.course>[];\n events: Mixed<CoreTypes.event>[];\n};\nexport type MixedScheduleData = Partial<_Schedule>;\n\ntype Division = Vertex & Pick<CoreTypes.division, 'displayName' | 'start' | 'end'>;\ntype DivisionSettings = OmitProperties<CoreTypes.divisionSettings>;\ntype Location = OmitProperties<CoreTypes.location>;\ntype Group = OmitProperties<CoreTypes.group>;\ntype Teacher = OmitProperties<CoreTypes.teacher>;\ntype Person = OmitProperties<CoreTypes.person>;\ntype Period = OmitProperties<CoreTypes.period>;\ntype RootInterval = OmitProperties<CoreTypes.rootInterval>;\ntype LockedTime = OmitProperties<CoreTypes.lockedTime>;\ntype OverlapGroup = OmitProperties<CoreTypes.overlapGroup>;\ntype Course = OmitProperties<CoreTypes.course>;\ntype Event = OmitProperties<CoreTypes.event>;\n\nexport namespace ConnectedTypes {\n export type division = Division;\n export type divisionSettings = DivisionSettings;\n export type location = Location;\n export type group = Group;\n export type teacher = Teacher;\n export type person = Person;\n export type period = Period;\n export type rootInterval = RootInterval;\n export type lockedTime = LockedTime;\n export type overlapGroup = OverlapGroup;\n export type course = Course;\n export type event = Event;\n}\n\nexport type ConnectedScheduleData = {\n division: Division;\n settings: DivisionSettings;\n groups: Group[];\n teachers: Teacher[];\n locations: Location[];\n periods: Period[];\n persons: Person[];\n rootIntervals: RootInterval[];\n lockedTimes: LockedTime[];\n overlapGroups: OverlapGroup[];\n courses: Course[];\n events: Event[];\n};\n\n\nfunction indexCollection<T extends Vertex> (collection: Mixed<T>[], idKey: IdKey): Map<string, T> {\n return new Map(collection.map(x => ([getVertexId(x, idKey), x as T] as const)));\n}\nfunction nonNullable<T> (value: T | null | undefined): value is T {\n return value != null;\n}\n\n/**\n * Connects the schedule data by replacing references with actual objects making it easier to work with.\n */\nexport function makeConnected (\n schedule: MixedScheduleData,\n options: Pick<Types.toOptions, 'idKey'> = {}\n): ConnectedScheduleData {\n const _division = schedule.divisions ?? schedule.division;\n if (!_division) throw new Error(`\"division\" or \"divisions\" missing in schedule, present keys: ${Object.keys(schedule).join(', ')}`);\n const _settings = schedule.settings;\n if (!_settings) throw new Error(`\"settings\" missing in schedule, present keys: ${Object.keys(schedule).join(', ')}`);\n\n const idKey = getIdKey(options);\n\n const groupsMap = indexCollection(schedule.groups ?? [], idKey);\n const teachersMap = indexCollection(schedule.teachers ?? [], idKey);\n const locationsMap = indexCollection(schedule.locations ?? [], idKey);\n const coursesMap = indexCollection(schedule.courses ?? [], idKey);\n const eventsMap = indexCollection(schedule.events ?? [], idKey);\n const overlapGroupsMap = indexCollection(schedule.overlapGroups ?? [], idKey);\n const periodsMap = indexCollection(schedule.periods ?? [], idKey);\n const personsMap = indexCollection(schedule.persons ?? [], idKey);\n const lockedTimesMap = indexCollection(schedule.lockedTimes ?? [], idKey);\n const rootIntervalsMap = indexCollection(schedule.rootIntervals ?? [], idKey);\n\n const division = ((): Division => {\n const vertex: Record<keyof Required<Intersect<Vertex>>, unknown> = {\n _id: true,\n id: true,\n ids: true,\n createdAt: true,\n updatedAt: true,\n lastModifiedBy: true\n };\n const vertexKeys = Object.keys(vertex) as (keyof typeof vertex)[];\n return pick(_division, [...vertexKeys, 'displayName', 'start', 'end']) as Division;\n })();\n\n const settings = ((): DivisionSettings => {\n const edges: ExtractEdges<DivisionSettings> = {\n period: _settings.period != null ? periodsMap .get(getVertexId(_settings.period, idKey)) : _settings.period,\n defaultRootInterval: _settings.defaultRootInterval != null ? rootIntervalsMap.get(getVertexId(_settings.defaultRootInterval, idKey)) : _settings.defaultRootInterval,\n } satisfies Record<keyof ExtractEdges<DivisionSettings>, unknown>;\n return Object.assign(_settings, edges);\n })();\n\n const getLockedTimes = <T extends Mixed<CoreTypes.group>['lockedTimes'] | undefined | null>(x: T): LockedTime[] | Extract<T, null | undefined> => {\n if (!x) return x as Extract<T, null | undefined>;\n return x.map(x => lockedTimesMap.get(getVertexId(x, idKey))).filter(nonNullable);\n };\n const getLunch = <T extends Mixed<CoreTypes.group>['lockedTimes'] | undefined | null>(x: T): LockedTime[] | Extract<T, null | undefined> => {\n if (!x) return x as Extract<T, null | undefined>;\n return x.map(x => lockedTimesMap.get(getVertexId(x, idKey))).filter(nonNullable);\n };\n\n const locations = (schedule.locations ?? [])\n .map((x): Location => {\n const edges: ExtractEdges<Location> = {\n lockedTimes: getLockedTimes(x.lockedTimes),\n lunch: getLunch(x.lunch),\n } satisfies Record<keyof ExtractEdges<Location>, unknown>;\n return Object.assign(x, edges);\n });\n\n const groups = (schedule.groups ?? [])\n .map((x): Group => {\n const edges: ExtractEdges<Group> = {\n lockedTimes: getLockedTimes(x.lockedTimes),\n lunch: getLunch (x.lunch),\n members: x.members ? x.members .map(x => personsMap.get(getVertexId(x, idKey))).filter(nonNullable) : x.members,\n parentGroups: x.parentGroups ? x.parentGroups.map(x => groupsMap .get(getVertexId(x, idKey))).filter(nonNullable) : x.parentGroups,\n subGroups: x.subGroups ? x.subGroups .map(x => groupsMap .get(getVertexId(x, idKey))).filter(nonNullable) : x.subGroups,\n\n rootInterval: x.rootInterval != null ? rootIntervalsMap.get(getVertexId(x.rootInterval, idKey)) : x.rootInterval,\n } satisfies Record<keyof ExtractEdges<Group>, unknown>;\n return Object.assign(x, edges);\n });\n\n const teachers = (schedule.teachers ?? [])\n .map((x): Teacher => {\n const edges: ExtractEdges<Teacher> = {\n lockedTimes: getLockedTimes(x.lockedTimes),\n lunch: getLunch(x.lunch),\n\n person: x.person != null ? personsMap .get(getVertexId(x.person, idKey)) : x.person,\n rootInterval: x.rootInterval != null ? rootIntervalsMap.get(getVertexId(x.rootInterval, idKey)) : x.rootInterval,\n } satisfies Record<keyof ExtractEdges<Teacher>, unknown>;\n return Object.assign(x, edges);\n });\n\n const persons = (schedule.persons ?? [])\n .map((x): Person => {\n const edges: ExtractEdges<Person> = {\n lockedTimes: getLockedTimes(x.lockedTimes),\n lunch: getLunch(x.lunch),\n\n group: x.group != null ? groupsMap.get(getVertexId(x.group, idKey)) : x.group,\n } satisfies Record<keyof ExtractEdges<Person>, unknown>;\n return Object.assign(x, edges);\n });\n\n const periods = (schedule.periods ?? [])\n .map((x): Period => {\n const edges: ExtractEdges<Period> = {\n } satisfies Record<keyof ExtractEdges<Period>, unknown>;\n return Object.assign(x, edges);\n });\n\n const rootIntervals = (schedule.rootIntervals ?? [])\n .map((x): RootInterval => {\n const edges: ExtractEdges<RootInterval> = {\n } satisfies Record<keyof ExtractEdges<RootInterval>, unknown>;\n return Object.assign(x, edges);\n });\n\n const makeCoalesced = <T extends Vertex, C extends Collection> (map: Map<string, T>, id: string, toModel: C) => {\n const to = map.get(id);\n if (!to) return;\n return { to, toModel } as Coalesced<T, C>;\n };\n\n const lockedTimes = (schedule.lockedTimes ?? [])\n .map((x): LockedTime => {\n const edges: ExtractEdges<LockedTime> = {\n coalesced: x.coalesced\n ? x.coalesced\n .map(x => {\n switch (x.toModel) {\n case 'groups': return makeCoalesced(groupsMap, getVertexId(x.to, idKey), x.toModel);\n case 'teachers': return makeCoalesced(teachersMap, getVertexId(x.to, idKey), x.toModel);\n case 'courses': return makeCoalesced(coursesMap, getVertexId(x.to, idKey), x.toModel);\n case 'events': return makeCoalesced(eventsMap, getVertexId(x.to, idKey), x.toModel);\n case 'courseevents': return makeCoalesced(eventsMap, getVertexId(x.to, idKey), 'events');\n case 'locations': return makeCoalesced(locationsMap, getVertexId(x.to, idKey), x.toModel);\n // case 'persons': return makeCoalesced(personsMap, getVertexId(x.to, idKey), x.toModel);\n default: throw new Error(`Unknown coalesced model \"${x.toModel satisfies never as string}\" in locked time ${JSON.stringify(x)}`);\n }\n })\n .filter(nonNullable)\n : x.coalesced,\n } satisfies Record<keyof ExtractEdges<LockedTime>, unknown>;\n return Object.assign(x, edges);\n });\n\n const overlapGroups = (schedule.overlapGroups ?? [])\n .map((x): OverlapGroup => {\n const edges: ExtractEdges<OverlapGroup> = {\n coalesced: x.coalesced\n ? x.coalesced\n .map(x => {\n const to = (() => {\n switch (x.toModel) {\n case 'courses': return coursesMap.get(getVertexId(x.to, idKey));\n default: throw new Error(`Unknown coalesced model \"${x.toModel satisfies never as string}\" in overlap group ${JSON.stringify(x)}`);\n }\n })();\n if (!to) return;\n const coalesced: Coalesced<typeof to, (typeof x)['toModel']> = { ...x, to };\n return coalesced;\n })\n .filter(nonNullable)\n : x.coalesced,\n species: x.species\n ? x.species\n .map(x => {\n const to = (() => {\n switch (x.toModel) {\n case 'events': return eventsMap.get(getVertexId(x.to, idKey));\n case 'courseevents': return eventsMap.get(getVertexId(x.to, idKey));\n default: throw new Error(`Unknown species model \"${x.toModel satisfies never as string}\" in overlap group ${JSON.stringify(x)}`);\n }\n })();\n if (!to) return;\n const species: Species<typeof to, (typeof x)['toModel']> = { ...x, to };\n return species;\n })\n .filter(nonNullable)\n : x.species,\n } satisfies Record<keyof ExtractEdges<OverlapGroup>, unknown>;\n return Object.assign(x, edges);\n });\n\n const getParticipants = (x: Mixed<CoreTypes.course>['participants'] | Mixed<CoreTypes.event>['participants']): PersonReference<Person>[] | undefined => {\n if (!x) return undefined;\n return x\n .map(x => {\n const to = personsMap.get(getVertexId(x.to, idKey));\n if (!to) return;\n const participant: PersonReference<Person> = { ...x, to };\n return participant;\n })\n .filter(nonNullable);\n };\n const getTeachers = (x: Mixed<CoreTypes.course>['teachers'] | Mixed<CoreTypes.event>['teachers']): PersonReference<Person>[] | undefined => {\n if (!x) return undefined;\n return x\n .map(x => {\n const to = teachersMap.get(getVertexId(x.to, idKey));\n if (!to) return;\n const participant: PersonReference<Person> = { ...x, to };\n return participant;\n })\n .filter(nonNullable);\n };\n const getLocations = (x: Mixed<CoreTypes.course>['locations'] | Mixed<CoreTypes.event>['locations']): AvailableLocation<Location>[] | undefined => {\n if (!x) return undefined;\n return x\n .map(x => {\n const locations = x.locations\n .map(x => locationsMap.get(getVertexId(x, idKey)))\n .filter(nonNullable);\n if (locations.length != 1) throw new Error(`(RS::MakeConnected) Expected exactly one location in available locations, got ${locations.length} and before filtering: ${x.locations.map(x => getVertexId(x, idKey)).join(', ')}`);\n const availableLocation: AvailableLocation<Location> = { ...x, locations: locations as [Location] };\n return availableLocation;\n })\n .filter(nonNullable);\n };\n const getGroups = (x: Mixed<CoreTypes.course>['groups'] | Mixed<CoreTypes.event>['groups']): GroupReference<Group, Person>[] | undefined => {\n if (!x) return undefined;\n return x\n .map(x => {\n const to = groupsMap.get(getVertexId(x.to, idKey));\n if (!to) return;\n const exclude = x.exclude\n ? x.exclude\n .map(x => personsMap.get(getVertexId(x, idKey)))\n .filter(nonNullable)\n : undefined;\n const group: GroupReference<Group, Person> = { ...x, to, exclude };\n return group;\n })\n .filter(nonNullable);\n };\n\n const courses = (schedule.courses ?? [])\n .map((x): Course => {\n const edges: ExtractEdges<Course> = {\n groups: getGroups (x.groups),\n teachers: getTeachers (x.teachers),\n locations: getLocations (x.locations),\n participants: getParticipants(x.participants),\n lockedTimes: getLockedTimes (x.lockedTimes),\n events: x.events ? x.events .map(x => eventsMap .get(getVertexId(x, idKey))).filter(nonNullable) : x.events,\n\n period: x.period != null ? periodsMap .get(getVertexId(x.period, idKey)) : x.period,\n overlapGroup: x.overlapGroup != null ? overlapGroupsMap.get(getVertexId(x.overlapGroup, idKey)) : x.overlapGroup,\n overlapSpecies: x.overlapSpecies != null ? overlapGroupsMap.get(getVertexId(x.overlapSpecies, idKey)) : x.overlapSpecies,\n } satisfies Record<keyof ExtractEdges<Course>, unknown>;\n return Object.assign(x, edges);\n });\n\n const events = (schedule.events ?? [])\n .map((x): Event => {\n const edges: ExtractEdges<Event> = {\n groups: getGroups (x.groups),\n teachers: getTeachers (x.teachers),\n locations: getLocations (x.locations),\n participants: getParticipants(x.participants),\n lockedTimes: getLockedTimes (x.lockedTimes),\n inLocations: x.inLocations\n ? x.inLocations\n .map(x => x === null ? null : locationsMap.get(getVertexId(x, idKey)))\n .filter((x): x is Exclude<typeof x, undefined> => x !== undefined)\n : x.inLocations,\n\n course: x.course != null ? coursesMap .get(getVertexId(x.course, idKey)) : x.course,\n period: x.period != null ? periodsMap .get(getVertexId(x.period, idKey)) : x.period,\n overlapGroup: x.overlapGroup != null ? overlapGroupsMap.get(getVertexId(x.overlapGroup, idKey)) : x.overlapGroup,\n overlapSpecies: x.overlapSpecies != null ? overlapGroupsMap.get(getVertexId(x.overlapSpecies, idKey)) : x.overlapSpecies,\n } satisfies Record<keyof ExtractEdges<Event>, unknown>;\n return Object.assign(x, edges);\n });\n\n\n return {\n division,\n settings,\n locations,\n groups,\n teachers,\n persons,\n periods,\n rootIntervals,\n lockedTimes,\n overlapGroups,\n courses,\n events\n };\n}"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"make-connected.js","names":["vertex: Record<keyof Required<Intersect<Vertex>>, unknown>","edges: ExtractEdges<DivisionSettings>","x","edges: ExtractEdges<Location>","edges: ExtractEdges<Group>","edges: ExtractEdges<Teacher>","edges: ExtractEdges<Person>","edges: ExtractEdges<Period>","edges: ExtractEdges<RootInterval>","map","edges: ExtractEdges<LockedTime>","edges: ExtractEdges<OverlapGroup>","coalesced: Coalesced<typeof to, (typeof x)['toModel']>","species: Species<typeof to, (typeof x)['toModel']>","participant: PersonReference<Person>","locations","availableLocation: AvailableLocation<Location>","group: GroupReference<Group, Person>","edges: ExtractEdges<Course>","edges: ExtractEdges<Event>"],"sources":["../../src/RS/make-connected.ts"],"sourcesContent":["import { pick } from 'lodash-es';\nimport { getIdKey, getVertexId } from '../core/util';\nimport type { ExtractEdges, Mixed } from '../core/vertex-mapping';\nimport type { CoreTypes } from '../core';\nimport type { AvailableLocation, Coalesced, Collection, GroupReference, IdKey, InternalIdKey, PersonReference, Species, Vertex } from '../core/types/common';\nimport type { Types } from './types';\nimport type { Intersect } from '../common/types';\n\ntype OmitProperties<T extends Vertex> = Omit<T, 'belongsTo' | 'exceptions' | 'defaultLunch' | 'syllabus' | InternalIdKey> & Vertex;\n\ntype _Schedule = {\n division: Mixed<CoreTypes.division>;\n divisions: Mixed<CoreTypes.division>;\n settings: Mixed<CoreTypes.divisionSettings>;\n groups: Mixed<CoreTypes.group>[];\n teachers: Mixed<CoreTypes.teacher>[];\n locations: Mixed<CoreTypes.location>[];\n periods: Mixed<CoreTypes.period>[];\n persons: Mixed<CoreTypes.person>[];\n rootIntervals: Mixed<CoreTypes.rootInterval>[];\n lockedTimes: Mixed<CoreTypes.lockedTime>[];\n overlapGroups: Mixed<CoreTypes.overlapGroup>[];\n courses: Mixed<CoreTypes.course>[];\n events: Mixed<CoreTypes.event>[];\n};\nexport type MixedScheduleData = Partial<_Schedule>;\n\ntype Division = Vertex & Pick<CoreTypes.division, 'displayName' | 'start' | 'end'>;\ntype DivisionSettings = OmitProperties<CoreTypes.divisionSettings>;\ntype Location = OmitProperties<CoreTypes.location>;\ntype Group = OmitProperties<CoreTypes.group>;\ntype Teacher = OmitProperties<CoreTypes.teacher>;\ntype Person = OmitProperties<CoreTypes.person>;\ntype Period = OmitProperties<CoreTypes.period>;\ntype RootInterval = OmitProperties<CoreTypes.rootInterval>;\ntype LockedTime = OmitProperties<CoreTypes.lockedTime>;\ntype OverlapGroup = OmitProperties<CoreTypes.overlapGroup>;\ntype Course = OmitProperties<CoreTypes.course>;\ntype Event = OmitProperties<CoreTypes.event>;\n\nexport namespace ConnectedTypes {\n export type division = Division;\n export type divisionSettings = DivisionSettings;\n export type location = Location;\n export type group = Group;\n export type teacher = Teacher;\n export type person = Person;\n export type period = Period;\n export type rootInterval = RootInterval;\n export type lockedTime = LockedTime;\n export type overlapGroup = OverlapGroup;\n export type course = Course;\n export type event = Event;\n}\n\nexport type ConnectedScheduleData = {\n division: Division;\n settings: DivisionSettings;\n groups: Group[];\n teachers: Teacher[];\n locations: Location[];\n periods: Period[];\n persons: Person[];\n rootIntervals: RootInterval[];\n lockedTimes: LockedTime[];\n overlapGroups: OverlapGroup[];\n courses: Course[];\n events: Event[];\n};\n\n\nfunction indexCollection<T extends Vertex> (collection: Mixed<T>[], idKey: IdKey): Map<string, T> {\n return new Map(collection.map(x => ([getVertexId(x, idKey), x as T] as const)));\n}\nfunction nonNullable<T> (value: T | null | undefined): value is T {\n return value != null;\n}\n\n/**\n * Connects the schedule data by replacing references with actual objects making it easier to work with.\n */\nexport function makeConnected (\n schedule: MixedScheduleData,\n options: Pick<Types.toOptions, 'idKey'> = {}\n): ConnectedScheduleData {\n const _division = schedule.divisions ?? schedule.division;\n if (!_division) throw new Error(`\"division\" or \"divisions\" missing in schedule, present keys: ${Object.keys(schedule).join(', ')}`);\n const _settings = schedule.settings;\n if (!_settings) throw new Error(`\"settings\" missing in schedule, present keys: ${Object.keys(schedule).join(', ')}`);\n\n const idKey = getIdKey(options);\n\n const groupsMap = indexCollection(schedule.groups ?? [], idKey);\n const teachersMap = indexCollection(schedule.teachers ?? [], idKey);\n const locationsMap = indexCollection(schedule.locations ?? [], idKey);\n const coursesMap = indexCollection(schedule.courses ?? [], idKey);\n const eventsMap = indexCollection(schedule.events ?? [], idKey);\n const overlapGroupsMap = indexCollection(schedule.overlapGroups ?? [], idKey);\n const periodsMap = indexCollection(schedule.periods ?? [], idKey);\n const personsMap = indexCollection(schedule.persons ?? [], idKey);\n const lockedTimesMap = indexCollection(schedule.lockedTimes ?? [], idKey);\n const rootIntervalsMap = indexCollection(schedule.rootIntervals ?? [], idKey);\n\n const division = ((): Division => {\n const vertex: Record<keyof Required<Intersect<Vertex>>, unknown> = {\n _id: true,\n id: true,\n ids: true,\n createdAt: true,\n updatedAt: true,\n lastModifiedBy: true\n };\n const vertexKeys = Object.keys(vertex) as (keyof typeof vertex)[];\n return pick(_division, [...vertexKeys, 'displayName', 'start', 'end']) as Division;\n })();\n\n const settings = ((): DivisionSettings => {\n const edges: ExtractEdges<DivisionSettings> = {\n period: _settings.period != null ? periodsMap .get(getVertexId(_settings.period, idKey)) : _settings.period,\n defaultRootInterval: _settings.defaultRootInterval != null ? rootIntervalsMap.get(getVertexId(_settings.defaultRootInterval, idKey)) : _settings.defaultRootInterval,\n } satisfies Record<keyof ExtractEdges<DivisionSettings>, unknown>;\n return Object.assign(_settings, edges);\n })();\n\n const getLockedTimes = <T extends Mixed<CoreTypes.group>['lockedTimes'] | undefined | null>(x: T): LockedTime[] | Extract<T, null | undefined> => {\n if (!x) return x as Extract<T, null | undefined>;\n return x.map(x => lockedTimesMap.get(getVertexId(x, idKey))).filter(nonNullable);\n };\n const getLunch = <T extends Mixed<CoreTypes.group>['lockedTimes'] | undefined | null>(x: T): LockedTime[] | Extract<T, null | undefined> => {\n if (!x) return x as Extract<T, null | undefined>;\n return x.map(x => lockedTimesMap.get(getVertexId(x, idKey))).filter(nonNullable);\n };\n\n const locations = (schedule.locations ?? [])\n .map((x): Location => {\n const edges: ExtractEdges<Location> = {\n lockedTimes: getLockedTimes(x.lockedTimes),\n lunch: getLunch(x.lunch),\n } satisfies Record<keyof ExtractEdges<Location>, unknown>;\n return Object.assign(x, edges);\n });\n\n const groups = (schedule.groups ?? [])\n .map((x): Group => {\n const edges: ExtractEdges<Group> = {\n lockedTimes: getLockedTimes(x.lockedTimes),\n lunch: getLunch (x.lunch),\n members: x.members ? x.members .map(x => personsMap.get(getVertexId(x, idKey))).filter(nonNullable) : x.members,\n parentGroups: x.parentGroups ? x.parentGroups.map(x => groupsMap .get(getVertexId(x, idKey))).filter(nonNullable) : x.parentGroups,\n subGroups: x.subGroups ? x.subGroups .map(x => groupsMap .get(getVertexId(x, idKey))).filter(nonNullable) : x.subGroups,\n\n rootInterval: x.rootInterval != null ? rootIntervalsMap.get(getVertexId(x.rootInterval, idKey)) : x.rootInterval,\n } satisfies Record<keyof ExtractEdges<Group>, unknown>;\n return Object.assign(x, edges);\n });\n\n const teachers = (schedule.teachers ?? [])\n .map((x): Teacher => {\n const edges: ExtractEdges<Teacher> = {\n lockedTimes: getLockedTimes(x.lockedTimes),\n lunch: getLunch(x.lunch),\n\n person: x.person != null ? personsMap .get(getVertexId(x.person, idKey)) : x.person,\n rootInterval: x.rootInterval != null ? rootIntervalsMap.get(getVertexId(x.rootInterval, idKey)) : x.rootInterval,\n } satisfies Record<keyof ExtractEdges<Teacher>, unknown>;\n return Object.assign(x, edges);\n });\n\n const persons = (schedule.persons ?? [])\n .map((x): Person => {\n const edges: ExtractEdges<Person> = {\n lockedTimes: getLockedTimes(x.lockedTimes),\n lunch: getLunch(x.lunch),\n\n group: x.group != null ? groupsMap.get(getVertexId(x.group, idKey)) : x.group,\n } satisfies Record<keyof ExtractEdges<Person>, unknown>;\n return Object.assign(x, edges);\n });\n\n const periods = (schedule.periods ?? [])\n .map((x): Period => {\n const edges: ExtractEdges<Period> = {\n } satisfies Record<keyof ExtractEdges<Period>, unknown>;\n return Object.assign(x, edges);\n });\n\n const rootIntervals = (schedule.rootIntervals ?? [])\n .map((x): RootInterval => {\n const edges: ExtractEdges<RootInterval> = {\n } satisfies Record<keyof ExtractEdges<RootInterval>, unknown>;\n return Object.assign(x, edges);\n });\n\n const makeCoalesced = <T extends Vertex, C extends Collection> (map: Map<string, T>, id: string, toModel: C) => {\n const to = map.get(id);\n if (!to) return;\n return { to, toModel } as Coalesced<T, C>;\n };\n\n const lockedTimes = (schedule.lockedTimes ?? [])\n .map((x): LockedTime => {\n const edges: ExtractEdges<LockedTime> = {\n coalesced: x.coalesced\n ? x.coalesced\n .map(x => {\n switch (x.toModel) {\n case 'groups': return makeCoalesced(groupsMap, getVertexId(x.to, idKey), x.toModel);\n case 'teachers': return makeCoalesced(teachersMap, getVertexId(x.to, idKey), x.toModel);\n case 'courses': return makeCoalesced(coursesMap, getVertexId(x.to, idKey), x.toModel);\n case 'events': return makeCoalesced(eventsMap, getVertexId(x.to, idKey), x.toModel);\n case 'courseevents': return makeCoalesced(eventsMap, getVertexId(x.to, idKey), 'events');\n case 'locations': return makeCoalesced(locationsMap, getVertexId(x.to, idKey), x.toModel);\n // case 'persons': return makeCoalesced(personsMap, getVertexId(x.to, idKey), x.toModel);\n default: throw new Error(`Unknown coalesced model \"${x.toModel satisfies never as string}\" in locked time ${JSON.stringify(x)}`);\n }\n })\n .filter(nonNullable)\n : x.coalesced,\n } satisfies Record<keyof ExtractEdges<LockedTime>, unknown>;\n return Object.assign(x, edges);\n });\n\n const overlapGroups = (schedule.overlapGroups ?? [])\n .map((x): OverlapGroup => {\n const edges: ExtractEdges<OverlapGroup> = {\n coalesced: x.coalesced\n ? x.coalesced\n .map(x => {\n const to = (() => {\n switch (x.toModel) {\n case 'courses': return coursesMap.get(getVertexId(x.to, idKey));\n default: throw new Error(`Unknown coalesced model \"${x.toModel satisfies never as string}\" in overlap group ${JSON.stringify(x)}`);\n }\n })();\n if (!to) return;\n const coalesced: Coalesced<typeof to, (typeof x)['toModel']> = { ...x, to };\n return coalesced;\n })\n .filter(nonNullable)\n : x.coalesced,\n species: x.species\n ? x.species\n .map(x => {\n const to = (() => {\n switch (x.toModel) {\n case 'events': return eventsMap.get(getVertexId(x.to, idKey));\n case 'courseevents': return eventsMap.get(getVertexId(x.to, idKey));\n default: throw new Error(`Unknown species model \"${x.toModel satisfies never as string}\" in overlap group ${JSON.stringify(x)}`);\n }\n })();\n if (!to) return;\n const species: Species<typeof to, (typeof x)['toModel']> = { ...x, to };\n return species;\n })\n .filter(nonNullable)\n : x.species,\n } satisfies Record<keyof ExtractEdges<OverlapGroup>, unknown>;\n return Object.assign(x, edges);\n });\n\n const getParticipants = (x: Mixed<CoreTypes.course>['participants'] | Mixed<CoreTypes.event>['participants']): PersonReference<Person>[] | undefined => {\n if (!x) return undefined;\n return x\n .map(x => {\n const to = personsMap.get(getVertexId(x.to, idKey));\n if (!to) return;\n const participant: PersonReference<Person> = { ...x, to };\n return participant;\n })\n .filter(nonNullable);\n };\n const getTeachers = (x: Mixed<CoreTypes.course>['teachers'] | Mixed<CoreTypes.event>['teachers']): PersonReference<Person>[] | undefined => {\n if (!x) return undefined;\n return x\n .map(x => {\n const to = teachersMap.get(getVertexId(x.to, idKey));\n if (!to) return;\n const participant: PersonReference<Person> = { ...x, to };\n return participant;\n })\n .filter(nonNullable);\n };\n const getLocations = (x: Mixed<CoreTypes.course>['locations'] | Mixed<CoreTypes.event>['locations']): AvailableLocation<Location>[] | undefined => {\n if (!x) return undefined;\n return x\n .map(x => {\n const locations = x.locations\n .map(x => locationsMap.get(getVertexId(x, idKey)))\n .filter(nonNullable);\n if (locations.length != 1) throw new Error(`(RS::MakeConnected) Expected exactly one location in available locations, got ${locations.length} and before filtering: ${x.locations.map(x => getVertexId(x, idKey)).join(', ')}`);\n const availableLocation: AvailableLocation<Location> = { ...x, locations: locations as [Location] };\n return availableLocation;\n })\n .filter(nonNullable);\n };\n const getGroups = (x: Mixed<CoreTypes.course>['groups'] | Mixed<CoreTypes.event>['groups']): GroupReference<Group, Person>[] | undefined => {\n if (!x) return undefined;\n return x\n .map(x => {\n const to = groupsMap.get(getVertexId(x.to, idKey));\n if (!to) return;\n const exclude = x.exclude\n ? x.exclude\n .map(x => personsMap.get(getVertexId(x, idKey)))\n .filter(nonNullable)\n : undefined;\n const group: GroupReference<Group, Person> = { ...x, to, exclude };\n return group;\n })\n .filter(nonNullable);\n };\n\n const courses = (schedule.courses ?? [])\n .map((x): Course => {\n const edges: ExtractEdges<Course> = {\n groups: getGroups (x.groups),\n teachers: getTeachers (x.teachers),\n locations: getLocations (x.locations),\n participants: getParticipants(x.participants),\n lockedTimes: getLockedTimes (x.lockedTimes),\n events: x.events ? x.events .map(x => eventsMap .get(getVertexId(x, idKey))).filter(nonNullable) : x.events,\n\n period: x.period != null ? periodsMap .get(getVertexId(x.period, idKey)) : x.period,\n overlapGroup: x.overlapGroup != null ? overlapGroupsMap.get(getVertexId(x.overlapGroup, idKey)) : x.overlapGroup,\n } satisfies Record<keyof ExtractEdges<Course>, unknown>;\n return Object.assign(x, edges);\n });\n\n const events = (schedule.events ?? [])\n .map((x): Event => {\n const edges: ExtractEdges<Event> = {\n groups: getGroups (x.groups),\n teachers: getTeachers (x.teachers),\n locations: getLocations (x.locations),\n participants: getParticipants(x.participants),\n lockedTimes: getLockedTimes (x.lockedTimes),\n inLocations: x.inLocations\n ? x.inLocations\n .map(x => x === null ? null : locationsMap.get(getVertexId(x, idKey)))\n .filter((x): x is Exclude<typeof x, undefined> => x !== undefined)\n : x.inLocations,\n\n course: x.course != null ? coursesMap .get(getVertexId(x.course, idKey)) : x.course,\n period: x.period != null ? periodsMap .get(getVertexId(x.period, idKey)) : x.period,\n overlapSpecies: x.overlapSpecies != null ? overlapGroupsMap.get(getVertexId(x.overlapSpecies, idKey)) : x.overlapSpecies,\n } satisfies Record<keyof ExtractEdges<Event>, unknown>;\n return Object.assign(x, edges);\n });\n\n\n return {\n division,\n settings,\n locations,\n groups,\n teachers,\n persons,\n periods,\n rootIntervals,\n lockedTimes,\n overlapGroups,\n courses,\n events\n };\n}"],"mappings":"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"}
|
|
@@ -44,7 +44,7 @@ function fromCollections(courses, settings, options, periodsMap) {
|
|
|
44
44
|
doc.overlapGroupId = course.overlapGroup ? getVertexId(course.overlapGroup, options) : void 0;
|
|
45
45
|
return omitBy(doc, (x) => x == null);
|
|
46
46
|
});
|
|
47
|
-
const overlapping = makeChainable(collections).chain((x) => x.filter((x$1) => x$1.overlapGroupId != null), (x) => groupBy(x, (x$1) => x$1.overlapGroupId), (x) => values(x).
|
|
47
|
+
const overlapping = makeChainable(collections).chain((x) => x.filter((x$1) => x$1.overlapGroupId != null), (x) => groupBy(x, (x$1) => x$1.overlapGroupId), (x) => values(x).map((xs) => xs.map((x$1) => omit(x$1, "overlapGroupId")))).value;
|
|
48
48
|
const plain = collections.filter((x) => x.overlapGroupId == null).map((x) => {
|
|
49
49
|
delete x.overlapGroupId;
|
|
50
50
|
return x;
|
|
@@ -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, omit, 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 .
|
|
1
|
+
{"version":3,"file":"collections.js","names":["doc: Types.collection & { overlapGroupId?: string }","x"],"sources":["../../../../src/RS/to/input/collections.ts"],"sourcesContent":["import { groupBy, omit, 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 => omit(x, 'overlapGroupId') as Types.collection))\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,KAAKA,KAAG,qBAElC;CAEH,MAAM,QAAQ,YACX,QAAO,MAAK,EAAE,kBAAkB,MAChC,KAAI,MAAK;AACR,SAAO,EAAE;AACT,SAAO;;AAGX,QAAO,YAAY,OAAO"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getPeriodIndex, min2hrs, toTimeFloat } from "./util/util.js";
|
|
2
2
|
import { computesDefaultIntervalId, getDefaultInterval } from "./intervals.js";
|
|
3
3
|
import { parseIntervals } from "./util/parse-intervals.js";
|
|
4
|
+
import { DEFAULT_PERIOD_ID } from "./periods.js";
|
|
4
5
|
|
|
5
6
|
//#region src/RS/to/input/default.ts
|
|
6
7
|
function parseDefault(settings, periodsMap, options) {
|
|
@@ -22,7 +23,7 @@ function parseDefault(settings, periodsMap, options) {
|
|
|
22
23
|
groupWeight: settings.defaultGroupWeight ?? 0,
|
|
23
24
|
collectionWeight: settings.defaultCourseWeight ?? 0,
|
|
24
25
|
eventWeight: settings.defaultEventWeight ?? 0,
|
|
25
|
-
period: getPeriodIndex(settings.period, periodsMap, options)
|
|
26
|
+
period: getPeriodIndex(settings.period ?? DEFAULT_PERIOD_ID, periodsMap, options)
|
|
26
27
|
};
|
|
27
28
|
return res;
|
|
28
29
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default.js","names":["res: Types.defaultValues"],"sources":["../../../../src/RS/to/input/default.ts"],"sourcesContent":["import type { Types } from '../../types';\nimport { computesDefaultIntervalId, getDefaultInterval } from './intervals';\nimport { parseIntervals } from './util/parse-intervals';\nimport { getPeriodIndex, min2hrs, toTimeFloat } from './util/util';\nimport type { ConnectedTypes } from '../../make-connected';\n\nexport function parseDefault (\n settings: ConnectedTypes.divisionSettings,\n periodsMap: Map<string | undefined, number>,\n options: Types.parsedToOptions\n): Types.defaultValues {\n const maxNumWorkingHours = options.useMaximumScheduleSpan\n ? min2hrs(settings.defaultMaximumScheduleSpan?.daily) ?? false\n : settings.defaultMaxNumWorkingHours ?? false;\n\n const maxNumDailyWorkingHours = options.useMaximumScheduleSpan\n ? min2hrs(settings.defaultMaximumScheduleSpan?.daily) ?? false\n : settings.defaultMaxNumDailyWorkingHours ?? false;\n\n const res: Types.defaultValues = {\n intervals: options.oldFormat\n ? parseIntervals(getDefaultInterval(settings), undefined, settings)!\n : computesDefaultIntervalId(settings, options),\n\n groupMinBreakLength: settings.defaultGroupMinimumBreakLength ?? 0,\n dependencyMinBreakLength: settings.defaultDependencyMinimumBreakLength ?? 0,\n eventMinBreakLength: settings.defaultEventMinimumBreakLength ?? 0,\n\n potentialCenter: toTimeFloat(settings.potentialCenter ?? '12:00'),\n eventDensity: settings.defaultEventDensity ?? 0,\n\n maxEventLengthVariance: settings.defaultEventDurationVariance ?? 0,\n\n maxNumWorkingHours: maxNumWorkingHours,\n maxNumDailyWorkingHours: maxNumDailyWorkingHours,\n\n dependencyRank: settings.defaultDependencyRank ?? 0,\n groupRank: settings.defaultGroupRank ?? 0,\n dayRank: settings.defaultDayRank ?? 0,\n\n groupWeight: settings.defaultGroupWeight ?? 0,\n collectionWeight: settings.defaultCourseWeight ?? 0,\n eventWeight: settings.defaultEventWeight ?? 0,\n\n period: getPeriodIndex(settings.period, periodsMap, options)\n };\n\n return res;\n};"],"mappings":"
|
|
1
|
+
{"version":3,"file":"default.js","names":["res: Types.defaultValues"],"sources":["../../../../src/RS/to/input/default.ts"],"sourcesContent":["import type { Types } from '../../types';\nimport { computesDefaultIntervalId, getDefaultInterval } from './intervals';\nimport { parseIntervals } from './util/parse-intervals';\nimport { getPeriodIndex, min2hrs, toTimeFloat } from './util/util';\nimport type { ConnectedTypes } from '../../make-connected';\nimport { DEFAULT_PERIOD_ID } from './periods';\n\nexport function parseDefault (\n settings: ConnectedTypes.divisionSettings,\n periodsMap: Map<string | undefined, number>,\n options: Types.parsedToOptions\n): Types.defaultValues {\n const maxNumWorkingHours = options.useMaximumScheduleSpan\n ? min2hrs(settings.defaultMaximumScheduleSpan?.daily) ?? false\n : settings.defaultMaxNumWorkingHours ?? false;\n\n const maxNumDailyWorkingHours = options.useMaximumScheduleSpan\n ? min2hrs(settings.defaultMaximumScheduleSpan?.daily) ?? false\n : settings.defaultMaxNumDailyWorkingHours ?? false;\n\n const res: Types.defaultValues = {\n intervals: options.oldFormat\n ? parseIntervals(getDefaultInterval(settings), undefined, settings)!\n : computesDefaultIntervalId(settings, options),\n\n groupMinBreakLength: settings.defaultGroupMinimumBreakLength ?? 0,\n dependencyMinBreakLength: settings.defaultDependencyMinimumBreakLength ?? 0,\n eventMinBreakLength: settings.defaultEventMinimumBreakLength ?? 0,\n\n potentialCenter: toTimeFloat(settings.potentialCenter ?? '12:00'),\n eventDensity: settings.defaultEventDensity ?? 0,\n\n maxEventLengthVariance: settings.defaultEventDurationVariance ?? 0,\n\n maxNumWorkingHours: maxNumWorkingHours,\n maxNumDailyWorkingHours: maxNumDailyWorkingHours,\n\n dependencyRank: settings.defaultDependencyRank ?? 0,\n groupRank: settings.defaultGroupRank ?? 0,\n dayRank: settings.defaultDayRank ?? 0,\n\n groupWeight: settings.defaultGroupWeight ?? 0,\n collectionWeight: settings.defaultCourseWeight ?? 0,\n eventWeight: settings.defaultEventWeight ?? 0,\n\n period: getPeriodIndex(settings.period ?? DEFAULT_PERIOD_ID, periodsMap, options)\n };\n\n return res;\n};"],"mappings":";;;;;;AAOA,SAAgB,aACd,UACA,YACA,SACqB;CACrB,MAAM,qBAAqB,QAAQ,yBAC/B,QAAQ,SAAS,4BAA4B,UAAU,QACvD,SAAS,6BAA8C;CAE3D,MAAM,0BAA0B,QAAQ,yBACpC,QAAQ,SAAS,4BAA4B,UAAU,QACvD,SAAS,kCAA8C;CAE3D,MAAMA,MAA2B;EAC/B,WAAW,QAAQ,YACf,eAAe,mBAAmB,WAAW,QAAW,YACxD,0BAA0B,UAAU;EAExC,qBAA0B,SAAS,kCAAuC;EAC1E,0BAA0B,SAAS,uCAAuC;EAC1E,qBAA0B,SAAS,kCAAuC;EAE1E,iBAAiB,YAAY,SAAS,mBAAmB;EACzD,cAAiB,SAAS,uBAAuB;EAEjD,wBAAwB,SAAS,gCAAgC;EAExC;EACA;EAEzB,gBAAgB,SAAS,yBAAyB;EAClD,WAAgB,SAAS,oBAAyB;EAClD,SAAgB,SAAS,kBAAyB;EAElD,aAAkB,SAAS,sBAAuB;EAClD,kBAAkB,SAAS,uBAAuB;EAClD,aAAkB,SAAS,sBAAuB;EAElD,QAAQ,eAAe,SAAS,UAAU,mBAAmB,YAAY;;AAG3E,QAAO"}
|
|
@@ -3,9 +3,9 @@ import { extractUniqueIntervals } from "./intervals.js";
|
|
|
3
3
|
import { fromTeachers } from "./teachers.js";
|
|
4
4
|
import { fromCollections } from "./collections.js";
|
|
5
5
|
import { parseSettings } from "./settings.js";
|
|
6
|
+
import { parsePeriods } from "./periods.js";
|
|
6
7
|
import { parseDefault } from "./default.js";
|
|
7
8
|
import { fromDynamicLockedTimes } from "./dynamic-locked-times.js";
|
|
8
|
-
import { parsePeriods } from "./periods.js";
|
|
9
9
|
import { fromGroups } from "./groups.js";
|
|
10
10
|
import { extractUniqueIndividuals } from "./individuals.js";
|
|
11
11
|
|
|
@@ -66,7 +66,10 @@ function combineAndMapIntervals(_intervals, rootInterval, settings) {
|
|
|
66
66
|
end: parseFloat(parseIntervalDate(i.end).format("HH.mm")),
|
|
67
67
|
binary: true
|
|
68
68
|
})).filter((i) => i.beg >= limits.beg && i.end <= limits.end);
|
|
69
|
-
}))
|
|
69
|
+
}).reduce((acc, curr, index) => {
|
|
70
|
+
acc[index] = curr;
|
|
71
|
+
return acc;
|
|
72
|
+
}, Array.from({ length: settings.numDays }, () => []))).value;
|
|
70
73
|
}
|
|
71
74
|
if (intervals) return intervals.map((i) => [i]);
|
|
72
75
|
}
|
|
@@ -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 * Parses a date input into a moment object.\n *\n * Accepts an ISO date string, a string in 'HH:mm' format, or a DateType.\n * - If the input is in 'HH:mm' format, it is parsed as a UTC time on the epoch date.\n * - Otherwise, the input is parsed as a full UTC date.\n *\n * @param date - The date input to parse.\n * @returns A moment object representing the parsed date and time.\n */\nexport function parseIntervalDate (date: string | DateType): moment.Moment {\n if (typeof date == 'string') {\n // in case of HH:mm format, parse as UTC time on epoch date\n if (/^\\d{1,2}:\\d{2}$/.test(date)) {\n return moment.utc(date, 'HH:mm');\n }\n\n // otherwise parse as full date\n return moment.utc(date);\n }\n\n return moment.utc(date);\n}\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 = parseIntervalDate(i.start);\n const end = parseIntervalDate(i.end );\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(parseIntervalDate(i.start).format('HH.mm'));\n const end = parseFloat(parseIntervalDate(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(parseIntervalDate(i.start).format('HH.mm')),\n end: parseFloat(parseIntervalDate(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":";;;;;;;;;;;;;;;;;AAqBA,SAAgB,kBAAmB,MAAwC;AACzE,KAAI,OAAO,QAAQ,UAAU;AAE3B,MAAI,kBAAkB,KAAK,MACzB,QAAO,OAAO,IAAI,MAAM;AAI1B,SAAO,OAAO,IAAI;;AAGpB,QAAO,OAAO,IAAI;;;;;AAMpB,SAAS,qBACP,WACA,UAC+B;AAC/B,KAAI,WAAW,UAAU,GAAG;EAC1B,MAAM,IAAI,UAAU;EACpB,MAAM,QAAQ,kBAAkB,EAAE;EAClC,MAAM,MAAQ,kBAAkB,EAAE;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,kBAAkB,EAAE,OAAO,OAAO;EAC3D,MAAM,MAAQ,WAAW,kBAAkB,EAAE,KAAO,OAAO;AAC3D,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,kBAAkB,EAAE,OAAO,OAAO;IACrD,KAAQ,WAAW,kBAAkB,EAAE,KAAO,OAAO;IACrD,QAAQ;OAET,QAAO,MAAK,EAAE,OAAO,OAAO,OAAO,EAAE,OAAO,OAAO;
|
|
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 * Parses a date input into a moment object.\n *\n * Accepts an ISO date string, a string in 'HH:mm' format, or a DateType.\n * - If the input is in 'HH:mm' format, it is parsed as a UTC time on the epoch date.\n * - Otherwise, the input is parsed as a full UTC date.\n *\n * @param date - The date input to parse.\n * @returns A moment object representing the parsed date and time.\n */\nexport function parseIntervalDate (date: string | DateType): moment.Moment {\n if (typeof date == 'string') {\n // in case of HH:mm format, parse as UTC time on epoch date\n if (/^\\d{1,2}:\\d{2}$/.test(date)) {\n return moment.utc(date, 'HH:mm');\n }\n\n // otherwise parse as full date\n return moment.utc(date);\n }\n\n return moment.utc(date);\n}\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 = parseIntervalDate(i.start);\n const end = parseIntervalDate(i.end );\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(parseIntervalDate(i.start).format('HH.mm'));\n const end = parseFloat(parseIntervalDate(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(parseIntervalDate(i.start).format('HH.mm')),\n end: parseFloat(parseIntervalDate(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 // ensure that all days are represented, even if empty\n .reduce<Types.interval[][]>((acc, curr, index) => {\n acc[index] = curr;\n return acc;\n }, Array.from({ length: settings.numDays }, () => []))\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":"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"}
|
|
@@ -11,6 +11,10 @@ function createRange({ start, end }) {
|
|
|
11
11
|
end: moment.utc(end).clone().endOf("isoWeek").endOf("day")
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Used by the default values as the id if no period is specified.
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULT_PERIOD_ID = "DEFAULT_PERIOD";
|
|
14
18
|
function parsePeriods(periods, division, options) {
|
|
15
19
|
const idKey = getIdKey(options);
|
|
16
20
|
if (!periods?.length) return { map: /* @__PURE__ */ new Map() };
|
|
@@ -19,7 +23,7 @@ function parsePeriods(periods, division, options) {
|
|
|
19
23
|
ranges: x.ranges.map((r) => createRange(r))
|
|
20
24
|
}));
|
|
21
25
|
parsedPeriods.push({
|
|
22
|
-
id:
|
|
26
|
+
id: DEFAULT_PERIOD_ID,
|
|
23
27
|
ranges: [createRange(division)]
|
|
24
28
|
});
|
|
25
29
|
const grouped = makeChainable(parsedPeriods).chain((x) => x.map((x$1) => ({
|
|
@@ -40,5 +44,5 @@ function parsePeriods(periods, division, options) {
|
|
|
40
44
|
}
|
|
41
45
|
|
|
42
46
|
//#endregion
|
|
43
|
-
export { parsePeriods };
|
|
47
|
+
export { DEFAULT_PERIOD_ID, parsePeriods };
|
|
44
48
|
//# sourceMappingURL=periods.js.map
|
|
@@ -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:
|
|
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\n/**\n * Used by the default values as the id if no period is specified.\n */\nexport const DEFAULT_PERIOD_ID = 'DEFAULT_PERIOD';\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: DEFAULT_PERIOD_ID, 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;;;;;;AAYf,MAAa,oBAAoB;AAEjC,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;EAAmB,QAAQ,CAAC,YAAY;;CAIjE,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"}
|
|
@@ -46,7 +46,10 @@ function parseIntervals(intervals, rootInterval, settings) {
|
|
|
46
46
|
end: parseFloat(parseIntervalDate(x$1.end).format("HH.mm")),
|
|
47
47
|
binary: true
|
|
48
48
|
})).filter((x$1) => x$1.beg >= limit.beg && x$1.end <= limit.end);
|
|
49
|
-
}))
|
|
49
|
+
}).reduce((acc, curr, index) => {
|
|
50
|
+
acc[index] = curr;
|
|
51
|
+
return acc;
|
|
52
|
+
}, Array.from({ length: settings.numDays }, () => []))).value;
|
|
50
53
|
}
|
|
51
54
|
}
|
|
52
55
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-intervals.js","names":["x"],"sources":["../../../../../src/RS/to/input/util/parse-intervals.ts"],"sourcesContent":["import { 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';\nimport { parseIntervalDate } from '../intervals';\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 = parseIntervalDate(settings.dayStart);\n const end = parseIntervalDate(settings.dayEnd);\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 = parseIntervalDate(i.start);\n const end = parseIntervalDate(i.end);\n intervals = Array.from({ length: settings.numDays }, () => ({ start: start.clone(), end: end.clone() }));\n } else if (intervals.length != settings.numDays) {\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(parseIntervalDate(i.start).format('HH.mm'));\n const end = parseFloat(parseIntervalDate(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(parseIntervalDate(x.start).format('HH.mm')),\n end: parseFloat(parseIntervalDate(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,kBAAkB,SAAS;EACzC,MAAM,MAAQ,kBAAkB,SAAS;AACzC,cAAY,MAAM,KAAK,EAAE,QAAQ,SAAS,kBAAkB;GAAE,OAAO,MAAM;GAAS,KAAK,IAAI;;YAEtF,UAAU,UAAU,GAAG;EAC9B,MAAM,IAAI,UAAU;EACpB,MAAM,QAAQ,kBAAkB,EAAE;EAClC,MAAM,MAAQ,kBAAkB,EAAE;AAClC,cAAY,MAAM,KAAK,EAAE,QAAQ,SAAS,kBAAkB;GAAE,OAAO,MAAM;GAAS,KAAK,IAAI;;YACpF,UAAU,UAAU,SAAS,QACtC,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,kBAAkB,EAAE,OAAO,OAAO;EAC3D,MAAM,MAAQ,WAAW,kBAAkB,EAAE,KAAO,OAAO;AAC3D,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,kBAAkBA,IAAE,OAAO,OAAO;IACrD,KAAQ,WAAW,kBAAkBA,IAAE,KAAO,OAAO;IACrD,QAAQ;OAET,QAAO,QAAKA,IAAE,OAAO,MAAM,OAAOA,IAAE,OAAO,MAAM;
|
|
1
|
+
{"version":3,"file":"parse-intervals.js","names":["x"],"sources":["../../../../../src/RS/to/input/util/parse-intervals.ts"],"sourcesContent":["import { 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';\nimport { parseIntervalDate } from '../intervals';\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 = parseIntervalDate(settings.dayStart);\n const end = parseIntervalDate(settings.dayEnd);\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 = parseIntervalDate(i.start);\n const end = parseIntervalDate(i.end);\n intervals = Array.from({ length: settings.numDays }, () => ({ start: start.clone(), end: end.clone() }));\n } else if (intervals.length != settings.numDays) {\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(parseIntervalDate(i.start).format('HH.mm'));\n const end = parseFloat(parseIntervalDate(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(parseIntervalDate(x.start).format('HH.mm')),\n end: parseFloat(parseIntervalDate(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 // ensure that all days are represented, even if empty\n .reduce<Types.interval[][]>((acc, curr, index) => {\n acc[index] = curr;\n return acc;\n }, Array.from({ length: settings.numDays }, () => []))\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,kBAAkB,SAAS;EACzC,MAAM,MAAQ,kBAAkB,SAAS;AACzC,cAAY,MAAM,KAAK,EAAE,QAAQ,SAAS,kBAAkB;GAAE,OAAO,MAAM;GAAS,KAAK,IAAI;;YAEtF,UAAU,UAAU,GAAG;EAC9B,MAAM,IAAI,UAAU;EACpB,MAAM,QAAQ,kBAAkB,EAAE;EAClC,MAAM,MAAQ,kBAAkB,EAAE;AAClC,cAAY,MAAM,KAAK,EAAE,QAAQ,SAAS,kBAAkB;GAAE,OAAO,MAAM;GAAS,KAAK,IAAI;;YACpF,UAAU,UAAU,SAAS,QACtC,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,kBAAkB,EAAE,OAAO,OAAO;EAC3D,MAAM,MAAQ,WAAW,kBAAkB,EAAE,KAAO,OAAO;AAC3D,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,kBAAkBA,IAAE,OAAO,OAAO;IACrD,KAAQ,WAAW,kBAAkBA,IAAE,KAAO,OAAO;IACrD,QAAQ;OAET,QAAO,QAAKA,IAAE,OAAO,MAAM,OAAOA,IAAE,OAAO,MAAM;KAGrD,QAA4B,KAAK,MAAM,UAAU;AAChD,OAAI,SAAS;AACb,UAAO;KACN,MAAM,KAAK,EAAE,QAAQ,SAAS,iBAAiB,MAErD"}
|
|
@@ -11,7 +11,9 @@ function toTimeFloat(str) {
|
|
|
11
11
|
return parseFloat(str.replace(":", "."));
|
|
12
12
|
}
|
|
13
13
|
function getPeriodIndex(period, periodsMap, options) {
|
|
14
|
-
|
|
14
|
+
if (periodsMap.size == 0) return;
|
|
15
|
+
if (!period) return;
|
|
16
|
+
const id = getVertexId(period, options);
|
|
15
17
|
const periodIndex = periodsMap.get(id);
|
|
16
18
|
if (periodIndex === void 0) throw new Error(`(RS::To::getPeriodIndex) Period "${id}" is not in periodsMap`);
|
|
17
19
|
return periodIndex;
|
|
@@ -53,7 +55,6 @@ let idOf;
|
|
|
53
55
|
if (interval === null) interval = void 0;
|
|
54
56
|
if (rootInterval === null) rootInterval = void 0;
|
|
55
57
|
if (interval && interval.length == 0) interval = void 0;
|
|
56
|
-
if (rootInterval && rootInterval.intervals.length == 0) rootInterval = void 0;
|
|
57
58
|
const out = (rootInterval ? getVertexId(rootInterval, options) + "&" : "") + JSON.stringify(interval);
|
|
58
59
|
return out;
|
|
59
60
|
}
|
|
@@ -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 const id =
|
|
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 | string | undefined | null,\n periodsMap: Map<string | undefined, number>,\n options: Types.parsedToOptions\n): number | undefined {\n // if no periods exist, return undefined\n if (periodsMap.size == 0) return;\n\n // if no period is given, return undefined\n if (!period) return;\n\n const id = getVertexId(period, options);\n const periodIndex = periodsMap.get(id);\n if (periodIndex === undefined) {\n throw new Error(`(RS::To::getPeriodIndex) Period \"${id}\" is not in periodsMap`);\n }\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\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;AAEpB,KAAI,WAAW,QAAQ,EAAG;AAG1B,KAAI,CAAC,OAAQ;CAEb,MAAM,KAAK,YAAY,QAAQ;CAC/B,MAAM,cAAc,WAAW,IAAI;AACnC,KAAI,gBAAgB,OAClB,OAAM,IAAI,MAAM,oCAAoC,GAAG;AAEzD,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,YAAY,SAAS,UAAU,EAAG,YAAW;EAEjD,MAAM,OAAO,eAAe,YAAY,cAAc,WAAW,MAAM,MAAM,KAAK,UAAU;AAC5F,SAAO"}
|
|
@@ -42,10 +42,12 @@ type Event = Vertex & {
|
|
|
42
42
|
preferredDuration?: number;
|
|
43
43
|
durationVariance?: number;
|
|
44
44
|
lockedTimes?: LockedTime[] | null;
|
|
45
|
+
/**
|
|
46
|
+
* @note an empty array is the same as undefined
|
|
47
|
+
*/
|
|
45
48
|
intervals?: AllowedInterval[];
|
|
46
49
|
centerOfAttraction?: string | null;
|
|
47
50
|
days?: Day[] | null;
|
|
48
|
-
overlapGroup?: OverlapGroup | null;
|
|
49
51
|
overlapSpecies?: OverlapGroup | null;
|
|
50
52
|
tags?: Tag[];
|
|
51
53
|
};
|