@royalschedule/maps 4.0.7 → 4.0.9

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.
@@ -15,55 +15,55 @@ declare class PlanDigitalMap {
15
15
  groups?: {
16
16
  exceptions?: string[] | undefined;
17
17
  lockedTimes?: string[] | undefined;
18
+ ids?: ID | undefined;
18
19
  createdAt?: DateType | undefined;
19
20
  updatedAt?: DateType | undefined;
20
21
  lastModifiedBy?: unknown;
21
- ids?: ID | undefined;
22
- displayName?: string | undefined;
23
- rank?: number | undefined;
24
- days?: Day[] | undefined;
25
22
  belongsTo?: string | undefined;
23
+ rank?: number | undefined;
24
+ displayName?: string | undefined;
25
+ lunch?: string[] | undefined;
26
26
  intervals?: AllowedInterval[] | undefined;
27
+ days?: Day[] | undefined;
27
28
  minBreakLength?: BreakLength | undefined;
29
+ tags?: Tag[] | undefined;
28
30
  maximumScheduleSpan?: MaximumScheduleSpan | undefined;
29
31
  forbidOverlappingEvents?: boolean | undefined;
30
32
  disableDayLengthPunishment?: boolean | undefined;
31
33
  weight?: number | undefined;
34
+ rootInterval?: string | undefined;
35
+ maxNumWorkingHours?: number | boolean | undefined;
36
+ maxNumDailyWorkingHours?: number | number[] | boolean | undefined;
32
37
  species?: "class" | undefined;
33
38
  parentGroups?: string[] | undefined;
34
39
  subGroups?: string[] | undefined;
35
- lunch?: string[] | undefined;
36
40
  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;
45
46
  createdAt?: DateType | undefined;
46
47
  updatedAt?: DateType | undefined;
47
48
  lastModifiedBy?: unknown;
48
- ids?: ID | undefined;
49
- displayName?: string | undefined;
50
- rank?: number | undefined;
51
- days?: Day[] | undefined;
52
49
  belongsTo?: string | undefined;
50
+ rank?: number | undefined;
51
+ displayName?: string | undefined;
52
+ lunch?: string[] | undefined;
53
53
  intervals?: AllowedInterval[] | undefined;
54
+ days?: Day[] | undefined;
54
55
  minBreakLength?: BreakLength | undefined;
56
+ tags?: Tag[] | undefined;
57
+ plannedScheduledDuration?: PlannedScheduledDuration | undefined;
55
58
  maximumScheduleSpan?: MaximumScheduleSpan | undefined;
56
59
  forbidOverlappingEvents?: boolean | undefined;
57
60
  disableDayLengthPunishment?: boolean | undefined;
58
61
  weight?: number | undefined;
59
- lunch?: string[] | undefined;
62
+ person?: string | undefined;
60
63
  rootInterval?: string | undefined;
61
- tags?: Tag[] | undefined;
64
+ signature?: string | undefined;
62
65
  maxNumWorkingHours?: number | boolean | undefined;
63
66
  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,26 +72,26 @@ declare class PlanDigitalMap {
72
72
  locations?: AvailableLocation<string>[] | undefined;
73
73
  events?: string[] | undefined;
74
74
  lockedTimes?: string[] | undefined;
75
+ ids?: ID | undefined;
75
76
  createdAt?: DateType | undefined;
76
77
  updatedAt?: DateType | undefined;
77
78
  lastModifiedBy?: unknown;
78
- ids?: ID | undefined;
79
- displayName?: string | undefined;
80
- days?: Day[] | undefined;
81
- weeks?: number[] | undefined;
82
79
  belongsTo?: string | undefined;
83
- period?: string | undefined;
84
- type?: string | undefined;
80
+ displayName?: string | undefined;
85
81
  intervals?: AllowedInterval[] | undefined;
82
+ days?: Day[] | undefined;
86
83
  minBreakLength?: BreakLength | undefined;
87
- weight?: number | undefined;
88
84
  tags?: Tag[] | undefined;
89
- color?: string | undefined;
85
+ weeks?: number[] | undefined;
86
+ weight?: number | undefined;
87
+ period?: string | undefined;
90
88
  participants?: PersonReference<string>[] | undefined;
91
89
  density?: number | undefined;
92
90
  subject?: string | undefined;
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;
@@ -4,12 +4,12 @@ import { getPeriodIndex, idOf } from "./util/util.js";
4
4
  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
- import { parseIntervals } from "./util/parse-intervals.js";
8
7
  import { getDefaultInterval } from "./intervals.js";
8
+ import { parseIntervals } from "./util/parse-intervals.js";
9
9
  import { parseGroupReferences } from "./util/parse-group-references.js";
10
10
  import { parseLocationReferences } from "./util/parse-location-references.js";
11
11
  import { parseEvents } from "./events.js";
12
- import { groupBy, omitBy, values } from "lodash-es";
12
+ import { groupBy, omit, omitBy, values } from "lodash-es";
13
13
 
14
14
  //#region src/RS/to/input/collections.ts
15
15
  function fromCollections(courses, settings, options, periodsMap) {
@@ -44,10 +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).map((xs) => xs.map((x$1) => {
48
- delete x$1.overlapGroupId;
49
- return x$1;
50
- }))).value;
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).flatMap((xs) => xs.map((x$1) => omit(x$1, "overlapGroupId")))).value;
51
48
  const plain = collections.filter((x) => x.overlapGroupId == null).map((x) => {
52
49
  delete x.overlapGroupId;
53
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, 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"}
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 .flatMap(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,SAAQ,OAAM,GAAG,KAAI,QAAK,KAAKA,KAAG,qBAEtC;CAEH,MAAM,QAAQ,YACX,QAAO,MAAK,EAAE,kBAAkB,MAChC,KAAI,MAAK;AACR,SAAO,EAAE;AACT,SAAO;;AAGX,QAAO,YAAY,OAAO"}
@@ -1,6 +1,6 @@
1
1
  import { getPeriodIndex, min2hrs, toTimeFloat } from "./util/util.js";
2
- import { parseIntervals } from "./util/parse-intervals.js";
3
2
  import { computesDefaultIntervalId, getDefaultInterval } from "./intervals.js";
3
+ import { parseIntervals } from "./util/parse-intervals.js";
4
4
 
5
5
  //#region src/RS/to/input/default.ts
6
6
  function parseDefault(settings, periodsMap, options) {
@@ -1,8 +1,8 @@
1
1
  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
- import { parseIntervals } from "./util/parse-intervals.js";
5
4
  import { getDefaultInterval } from "./intervals.js";
5
+ import { parseIntervals } from "./util/parse-intervals.js";
6
6
  import { parseGroupReferences } from "./util/parse-group-references.js";
7
7
  import { toDayAndStart } from "./events.js";
8
8
  import { groupBy, omitBy, uniq } from "lodash-es";
@@ -58,7 +58,7 @@ function parse(lockedTime, settings, options, defaultInterval) {
58
58
  function fromDynamicLockedTimes(lockedTimes, settings, options) {
59
59
  const defaultInterval = getDefaultInterval(settings);
60
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]) => ({
61
- id,
61
+ id: `COMPLEMENTARY_TIME.${id}`,
62
62
  events
63
63
  }))).value;
64
64
  const lunches = lockedTimes.filter((x) => x.type == "LUNCH").map((lockedTime) => parse(lockedTime, settings, options, defaultInterval)).filter((x) => !!x);
@@ -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';\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"}
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: `COMPLEMENTARY_TIME.${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,IAAI,sBAAsB;EAAM;MAE7D;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"}
@@ -3,8 +3,8 @@ import { getPeriodIndex, idOf } from "./util/util.js";
3
3
  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
- import { parseIntervals } from "./util/parse-intervals.js";
7
6
  import { getDefaultInterval } from "./intervals.js";
7
+ import { parseIntervals } from "./util/parse-intervals.js";
8
8
  import { parseGroupReferences } from "./util/parse-group-references.js";
9
9
  import { parseLocationReferences, parseSelectedLocations } from "./util/parse-location-references.js";
10
10
  import { omitBy } from "lodash-es";
@@ -3,8 +3,8 @@ import { attachLockedTimes } from "./util/attach-locked-times.js";
3
3
  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
- import { parseIntervals } from "./util/parse-intervals.js";
7
6
  import { getDefaultInterval } from "./intervals.js";
7
+ import { parseIntervals } from "./util/parse-intervals.js";
8
8
  import { omitBy } from "lodash-es";
9
9
 
10
10
  //#region src/RS/to/input/groups.ts
@@ -10,42 +10,43 @@ import { fromGroups } from "./groups.js";
10
10
  import { extractUniqueIndividuals } from "./individuals.js";
11
11
 
12
12
  //#region src/RS/to/input/input.ts
13
- function parseInput(schedule, options = {}) {
14
- const settings = schedule.settings;
15
- const division = schedule.division;
16
- const groups = schedule.groups ?? [];
17
- const teachers = schedule.teachers ?? [];
18
- const locations = schedule.locations ?? [];
19
- const events = schedule.events ?? [];
20
- const lockedTimes = schedule.lockedTimes ?? [];
21
- const courses = schedule.courses ?? [];
22
- const periods = schedule.periods ?? [];
23
- const persons = schedule.persons ?? [];
13
+ function parseInput(data, options = {}) {
14
+ const _settings = data.settings;
15
+ const _division = data.division;
16
+ const _groups = data.groups ?? [];
17
+ const _teachers = data.teachers ?? [];
18
+ const _locations = data.locations ?? [];
19
+ const _events = data.events ?? [];
20
+ const _lockedTimes = data.lockedTimes ?? [];
21
+ const _courses = data.courses ?? [];
22
+ const _persons = data.persons ?? [];
23
+ const _periods = data.periods ?? [];
24
24
  [
25
- groups,
26
- teachers,
27
- locations,
28
- courses,
29
- events,
30
- lockedTimes
25
+ _groups,
26
+ _teachers,
27
+ _locations,
28
+ _courses,
29
+ _events,
30
+ _lockedTimes
31
31
  ].forEach((entities) => {
32
32
  entities.forEach((entity) => {
33
33
  if (entity.intervals && entity.intervals.length == 0) entity.intervals = void 0;
34
34
  else if (entity.intervals === null) entity.intervals = void 0;
35
35
  });
36
36
  });
37
- const { map: periodsMap, matrix: periodsMatrix } = parsePeriods(periods, division, options);
38
- const data = {
39
- settings: parseSettings(settings),
40
- default: parseDefault(settings, periodsMap, options),
41
- periods: periodsMatrix?.length ? periodsMatrix : void 0,
42
- intervals: options.oldFormat ? void 0 : extractUniqueIntervals(settings, groups, teachers, courses, events, lockedTimes, options),
43
- dependencies: fromLocations(locations, settings, options),
44
- groups: fromGroups(groups, settings, options).concat(fromTeachers(teachers, settings, options)),
45
- individuals: options.oldFormat ? void 0 : extractUniqueIndividuals(persons, courses, events, lockedTimes, options),
46
- events: [...fromCollections(courses, settings, options, periodsMap), ...fromDynamicLockedTimes(lockedTimes, settings, options)]
37
+ const { map: periodsMap, matrix: periodsMatrix } = parsePeriods(_periods, _division, options);
38
+ const periods = periodsMatrix?.length ? periodsMatrix : void 0;
39
+ const out = {
40
+ settings: parseSettings(_settings),
41
+ default: parseDefault(_settings, periodsMap, options),
42
+ periods,
43
+ intervals: options.oldFormat ? void 0 : extractUniqueIntervals(_settings, _groups, _teachers, _courses, _events, _lockedTimes, options),
44
+ dependencies: fromLocations(_locations, _settings, options),
45
+ groups: fromGroups(_groups, _settings, options).concat(fromTeachers(_teachers, _settings, options)),
46
+ individuals: options.oldFormat ? void 0 : extractUniqueIndividuals(_persons, _courses, _events, _lockedTimes, options),
47
+ events: [...fromCollections(_courses, _settings, options, periodsMap), ...fromDynamicLockedTimes(_lockedTimes, _settings, options)]
47
48
  };
48
- return data;
49
+ return out;
49
50
  }
50
51
 
51
52
  //#endregion
@@ -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\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: [\n ...fromCollections(courses, settings, options, periodsMap),\n ...fromDynamicLockedTimes(lockedTimes, settings, options)\n ]\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,CACN,GAAG,gBAAgB,SAAS,UAAU,SAAS,aAC/C,GAAG,uBAAuB,aAAa,UAAU;;AAIrD,QAAO"}
1
+ {"version":3,"file":"input.js","names":["out: 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 data: ConnectedScheduleData,\n options: Types.parsedToOptions = {}\n): Types.scheduleData {\n\n const _settings = data.settings;\n const _division = data.division;\n const _groups = data.groups ?? [];\n const _teachers = data.teachers ?? [];\n const _locations = data.locations ?? [];\n const _events = data.events ?? [];\n const _lockedTimes = data.lockedTimes ?? [];\n const _courses = data.courses ?? [];\n const _persons = data.persons ?? [];\n const _periods = data.periods ?? [];\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 const periods = periodsMatrix?.length ? periodsMatrix : undefined; // cannot be an empty string\n\n const out: Types.scheduleData = {\n settings: parseSettings(_settings),\n default: parseDefault (_settings, periodsMap, options),\n\n periods: periods,\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: [\n ...fromCollections(_courses, _settings, options, periodsMap),\n ...fromDynamicLockedTimes(_lockedTimes, _settings, options)\n ]\n };\n return out;\n};"],"mappings":";;;;;;;;;;;;AAaA,SAAgB,WACd,MACA,UAAiC,IACb;CAEpB,MAAM,YAAe,KAAK;CAC1B,MAAM,YAAe,KAAK;CAC1B,MAAM,UAAe,KAAK,UAAe;CACzC,MAAM,YAAe,KAAK,YAAe;CACzC,MAAM,aAAe,KAAK,aAAe;CACzC,MAAM,UAAe,KAAK,UAAe;CACzC,MAAM,eAAe,KAAK,eAAe;CACzC,MAAM,WAAe,KAAK,WAAe;CACzC,MAAM,WAAe,KAAK,WAAe;CACzC,MAAM,WAAe,KAAK,WAAe;AAMzC;EAAC;EAAS;EAAW;EAAY;EAAU;EAAS;GAAc,SAAQ,aAAY;AACpF,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,UAAU,WAAW;CACrF,MAAM,UAAU,eAAe,SAAS,gBAAgB;CAExD,MAAMA,MAA0B;EAC9B,UAAU,cAAc;EACxB,SAAU,aAAc,WAAW,YAAY;EAEtC;EAET,WAAW,QAAQ,YAAY,SAAY,uBAAuB,WAAW,SAAS,WAAW,UAAU,SAAS,cAAc;EAElI,cAAc,cAAc,YAAY,WAAW;EAEnD,QAAQ,WAAW,SAAS,WAAW,SACpC,OAAO,aAAa,WAAW,WAAW;EAE7C,aAAa,QAAQ,YAAY,SAAY,yBAAyB,UAAU,UAAU,SAAS,cAAc;EAEjH,QAAQ,CACN,GAAG,gBAAgB,UAAU,WAAW,SAAS,aACjD,GAAG,uBAAuB,cAAc,WAAW;;AAGvD,QAAO"}
@@ -6,13 +6,30 @@ import moment from "moment";
6
6
 
7
7
  //#region src/RS/to/input/intervals.ts
8
8
  /**
9
+ * Parses a date input into a moment object.
10
+ *
11
+ * Accepts an ISO date string, a string in 'HH:mm' format, or a DateType.
12
+ * - If the input is in 'HH:mm' format, it is parsed as a UTC time on the epoch date.
13
+ * - Otherwise, the input is parsed as a full UTC date.
14
+ *
15
+ * @param date - The date input to parse.
16
+ * @returns A moment object representing the parsed date and time.
17
+ */
18
+ function parseIntervalDate(date) {
19
+ if (typeof date == "string") {
20
+ if (/^\d{1,2}:\d{2}$/.test(date)) return moment.utc(date, "HH:mm");
21
+ return moment.utc(date);
22
+ }
23
+ return moment.utc(date);
24
+ }
25
+ /**
9
26
  * Removes the shorthand notation (a single day to represent all days)
10
27
  */
11
28
  function standardizeIntervals(intervals, settings) {
12
29
  if (intervals?.length == 1) {
13
30
  const i = intervals[0];
14
- const start = moment.utc(i.start, "HH:mm");
15
- const end = moment.utc(i.end, "HH:mm");
31
+ const start = parseIntervalDate(i.start);
32
+ const end = parseIntervalDate(i.end);
16
33
  return Array.from({ length: settings.numDays }, () => ({
17
34
  start: start.clone(),
18
35
  end: end.clone()
@@ -26,8 +43,8 @@ function standardizeIntervals(intervals, settings) {
26
43
  function toFloatIntervals(intervals) {
27
44
  return intervals?.map((i, day) => {
28
45
  if (!i.start || !i.end) throw new Error(`(RS::To::convertIntervals) Interval missing start or end for day ${day}: ${JSON.stringify(i)}`);
29
- const start = parseFloat(moment.utc(i.start).format("HH.mm"));
30
- const end = parseFloat(moment.utc(i.end).format("HH.mm"));
46
+ const start = parseFloat(parseIntervalDate(i.start).format("HH.mm"));
47
+ const end = parseFloat(parseIntervalDate(i.end).format("HH.mm"));
31
48
  return {
32
49
  beg: start,
33
50
  end
@@ -45,8 +62,8 @@ function combineAndMapIntervals(_intervals, rootInterval, settings) {
45
62
  const limits = intervals.at(parseInt(day));
46
63
  if (!limits) throw new Error(`(RS::To::Intervals) Day ${day} not found in dayStartAndEnds`);
47
64
  return is.map((i) => ({
48
- beg: parseFloat(moment.utc(i.start).format("HH.mm")),
49
- end: parseFloat(moment.utc(i.end).format("HH.mm")),
65
+ beg: parseFloat(parseIntervalDate(i.start).format("HH.mm")),
66
+ end: parseFloat(parseIntervalDate(i.end).format("HH.mm")),
50
67
  binary: true
51
68
  })).filter((i) => i.beg >= limits.beg && i.end <= limits.end);
52
69
  })).value;
@@ -107,5 +124,5 @@ function extractUniqueIntervals(settings, groups, teachers, courses, events, loc
107
124
  }
108
125
 
109
126
  //#endregion
110
- export { computesDefaultIntervalId, extractUniqueIntervals, getDefaultInterval };
127
+ export { computesDefaultIntervalId, extractUniqueIntervals, getDefaultInterval, parseIntervalDate };
111
128
  //# sourceMappingURL=intervals.js.map
@@ -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::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"}
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;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"}
@@ -3,8 +3,8 @@ import { attachLockedTimes } from "./util/attach-locked-times.js";
3
3
  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
- import { parseIntervals } from "./util/parse-intervals.js";
7
6
  import { getDefaultInterval } from "./intervals.js";
7
+ import { parseIntervals } from "./util/parse-intervals.js";
8
8
  import { omitBy } from "lodash-es";
9
9
 
10
10
  //#region src/RS/to/input/teachers.ts
@@ -1,30 +1,30 @@
1
1
  import { getDayIndex } from "../../../../core/util.js";
2
2
  import { makeChainable } from "../../../../common/make-chainable/index.js";
3
+ import { parseIntervalDate } from "../intervals.js";
3
4
  import { groupBy } from "lodash-es";
4
- import moment from "moment";
5
5
 
6
6
  //#region src/RS/to/input/util/parse-intervals.ts
7
7
  function getDayLimits(intervals, settings) {
8
8
  if (!intervals) {
9
- const start = moment.utc(settings.dayStart, "HH:mm");
10
- const end = moment.utc(settings.dayEnd, "HH:mm");
9
+ const start = parseIntervalDate(settings.dayStart);
10
+ const end = parseIntervalDate(settings.dayEnd);
11
11
  intervals = Array.from({ length: settings.numDays }, () => ({
12
12
  start: start.clone(),
13
13
  end: end.clone()
14
14
  }));
15
15
  } else if (intervals.length == 1) {
16
16
  const i = intervals[0];
17
- const start = moment.utc(i.start, "HH:mm");
18
- const end = moment.utc(i.end, "HH:mm");
17
+ const start = parseIntervalDate(i.start);
18
+ const end = parseIntervalDate(i.end);
19
19
  intervals = Array.from({ length: settings.numDays }, () => ({
20
20
  start: start.clone(),
21
21
  end: end.clone()
22
22
  }));
23
- } else throw new Error(`(RS::To::Intervals) Intervals length ${intervals.length} does not match settings.numDays ${settings.numDays}`);
23
+ } else if (intervals.length != settings.numDays) 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
25
  if (!i.start || !i.end) throw new Error(`(RS::To::Intervals) Interval missing start or end for day ${day}`);
26
- const start = parseFloat(moment.utc(i.start).format("HH.mm"));
27
- const end = parseFloat(moment.utc(i.end).format("HH.mm"));
26
+ const start = parseFloat(parseIntervalDate(i.start).format("HH.mm"));
27
+ const end = parseFloat(parseIntervalDate(i.end).format("HH.mm"));
28
28
  return {
29
29
  beg: start,
30
30
  end
@@ -42,8 +42,8 @@ function parseIntervals(intervals, rootInterval, settings) {
42
42
  const limit = dayLimits.at(parseInt(day));
43
43
  if (!limit) throw new Error(`(RS::To::Intervals) Day ${day} not found in dayStartAndEnds`);
44
44
  return xs.map((x$1) => ({
45
- beg: parseFloat(moment.utc(x$1.start).format("HH.mm")),
46
- end: parseFloat(moment.utc(x$1.end).format("HH.mm")),
45
+ beg: parseFloat(parseIntervalDate(x$1.start).format("HH.mm")),
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
  })).value;
@@ -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::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"}
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;MAGzD"}
@@ -15,7 +15,7 @@ function parseLocationReferences(references, options) {
15
15
  return includedLocations.has(x$1.dependency);
16
16
  }), (x) => groupBy(x, (x$1) => x$1.groupIndex), (x) => Object.values(x).map((xs) => xs.map((x$1) => ({
17
17
  dependency: x$1.dependency,
18
- rank: x$1.rank
18
+ ...x$1.rank != null && { rank: x$1.rank }
19
19
  })))).value;
20
20
  }
21
21
  function parseSelectedLocations(event, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"parse-location-references.js","names":["x"],"sources":["../../../../../src/RS/to/input/util/parse-location-references.ts"],"sourcesContent":["import { groupBy } from 'lodash-es';\nimport type { ConnectedTypes } from '../../../make-connected';\nimport type { Types } from '../../../types';\nimport { getVertexId } from '../../../../core/util';\nimport type { AvailableLocation } from '../../../../core/types/common';\nimport { makeChainable } from '../../../../common/make-chainable';\n\nexport function parseLocationReferences (\n references: AvailableLocation<ConnectedTypes.location>[] | null | undefined,\n options: Types.parsedToOptions\n) {\n if (!references) return;\n\n return makeChainable(references)\n .chain(\n x => x\n .map(({ locations, groupIndex, rank }) => ({\n dependency: getVertexId(locations[0], options),\n rank: rank,\n groupIndex: groupIndex\n }))\n .filter(x => {\n // filter location references based on partial schedule options\n const includedLocations = options.partialScheduleOptions?.includedLocations;\n if (!includedLocations) return true;\n return includedLocations.has(x.dependency);\n }),\n x => groupBy(x, x => x.groupIndex),\n x => Object.values(x)\n .map(xs => xs.map(x => ({\n dependency: x.dependency,\n rank: x.rank,\n }) as Types.availableDependency))\n )\n .value;\n}\n\nexport function parseSelectedLocations (event: ConnectedTypes.event, options: Types.parsedToOptions) {\n\n const locationsRef = event.locations ?? event.course?.locations;\n const dependencies = parseLocationReferences(locationsRef, options);\n const inLocations = event.inLocations ?? [];\n\n // simply use inLocations if they match the number of dependencies\n if (inLocations.length === dependencies?.length) {\n return inLocations.map(x => x ? getVertexId(x, options) : null);\n }\n\n // otherwise, fill inLocations with nulls to match the number of dependencies\n return inLocations\n .map(x => x ? getVertexId(x, options) : null)\n .concat(Array\n .from({ length: Math.max((dependencies?.length ?? 0) - inLocations.length, 0) })\n .map(() => null as string | null)\n );\n}"],"mappings":";;;;;AAOA,SAAgB,wBACd,YACA,SACA;AACA,KAAI,CAAC,WAAY;AAEjB,QAAO,cAAc,YAClB,OACC,MAAK,EACF,KAAK,EAAE,WAAW,YAAY,YAAY;EACzC,YAAY,YAAY,UAAU,IAAI;EAC1B;EACA;KAEb,QAAO,QAAK;EAEX,MAAM,oBAAoB,QAAQ,wBAAwB;AAC1D,MAAI,CAAC,kBAAmB,QAAO;AAC/B,SAAO,kBAAkB,IAAIA,IAAE;MAEnC,MAAK,QAAQ,IAAG,QAAKA,IAAE,cACvB,MAAK,OAAO,OAAO,GAChB,KAAI,OAAM,GAAG,KAAI,SAAM;EACtB,YAAYA,IAAE;EACd,MAAYA,IAAE;OAGnB;;AAGL,SAAgB,uBAAwB,OAA6B,SAAgC;CAEnG,MAAM,eAAe,MAAM,aAAa,MAAM,QAAQ;CACtD,MAAM,eAAe,wBAAwB,cAAc;CAC3D,MAAM,cAAe,MAAM,eAAe;AAG1C,KAAI,YAAY,WAAW,cAAc,OACvC,QAAO,YAAY,KAAI,MAAM,IAAI,YAAY,GAAG,WAAW;AAI7D,QAAO,YACJ,KAAI,MAAM,IAAI,YAAY,GAAG,WAAW,MACxC,OAAO,MACL,KAAK,EAAE,QAAQ,KAAK,KAAK,cAAc,UAAU,KAAK,YAAY,QAAQ,MAC1E,UAAU"}
1
+ {"version":3,"file":"parse-location-references.js","names":["x"],"sources":["../../../../../src/RS/to/input/util/parse-location-references.ts"],"sourcesContent":["import { groupBy } from 'lodash-es';\nimport type { ConnectedTypes } from '../../../make-connected';\nimport type { Types } from '../../../types';\nimport { getVertexId } from '../../../../core/util';\nimport type { AvailableLocation } from '../../../../core/types/common';\nimport { makeChainable } from '../../../../common/make-chainable';\n\nexport function parseLocationReferences (\n references: AvailableLocation<ConnectedTypes.location>[] | null | undefined,\n options: Types.parsedToOptions\n) {\n if (!references) return;\n\n return makeChainable(references)\n .chain(\n x => x\n .map(({ locations, groupIndex, rank }) => ({\n dependency: getVertexId(locations[0], options),\n rank: rank,\n groupIndex: groupIndex\n }))\n .filter(x => {\n // filter location references based on partial schedule options\n const includedLocations = options.partialScheduleOptions?.includedLocations;\n if (!includedLocations) return true;\n return includedLocations.has(x.dependency);\n }),\n x => groupBy(x, x => x.groupIndex),\n x => Object.values(x)\n .map(xs => xs.map(x => ({\n dependency: x.dependency,\n ...x.rank != null && { rank: x.rank },\n }) as Types.availableDependency))\n )\n .value;\n}\n\nexport function parseSelectedLocations (event: ConnectedTypes.event, options: Types.parsedToOptions) {\n\n const locationsRef = event.locations ?? event.course?.locations;\n const dependencies = parseLocationReferences(locationsRef, options);\n const inLocations = event.inLocations ?? [];\n\n // simply use inLocations if they match the number of dependencies\n if (inLocations.length === dependencies?.length) {\n return inLocations.map(x => x ? getVertexId(x, options) : null);\n }\n\n // otherwise, fill inLocations with nulls to match the number of dependencies\n return inLocations\n .map(x => x ? getVertexId(x, options) : null)\n .concat(Array\n .from({ length: Math.max((dependencies?.length ?? 0) - inLocations.length, 0) })\n .map(() => null as string | null)\n );\n}"],"mappings":";;;;;AAOA,SAAgB,wBACd,YACA,SACA;AACA,KAAI,CAAC,WAAY;AAEjB,QAAO,cAAc,YAClB,OACC,MAAK,EACF,KAAK,EAAE,WAAW,YAAY,YAAY;EACzC,YAAY,YAAY,UAAU,IAAI;EAC1B;EACA;KAEb,QAAO,QAAK;EAEX,MAAM,oBAAoB,QAAQ,wBAAwB;AAC1D,MAAI,CAAC,kBAAmB,QAAO;AAC/B,SAAO,kBAAkB,IAAIA,IAAE;MAEnC,MAAK,QAAQ,IAAG,QAAKA,IAAE,cACvB,MAAK,OAAO,OAAO,GAChB,KAAI,OAAM,GAAG,KAAI,SAAM;EACtB,YAAYA,IAAE;EACd,GAAGA,IAAE,QAAQ,QAAQ,EAAE,MAAMA,IAAE;OAGpC;;AAGL,SAAgB,uBAAwB,OAA6B,SAAgC;CAEnG,MAAM,eAAe,MAAM,aAAa,MAAM,QAAQ;CACtD,MAAM,eAAe,wBAAwB,cAAc;CAC3D,MAAM,cAAe,MAAM,eAAe;AAG1C,KAAI,YAAY,WAAW,cAAc,OACvC,QAAO,YAAY,KAAI,MAAM,IAAI,YAAY,GAAG,WAAW;AAI7D,QAAO,YACJ,KAAI,MAAM,IAAI,YAAY,GAAG,WAAW,MACxC,OAAO,MACL,KAAK,EAAE,QAAQ,KAAK,KAAK,cAAc,UAAU,KAAK,YAAY,QAAQ,MAC1E,UAAU"}
@@ -11,8 +11,7 @@ function toTimeFloat(str) {
11
11
  return parseFloat(str.replace(":", "."));
12
12
  }
13
13
  function getPeriodIndex(period, periodsMap, options) {
14
- if (!period) return;
15
- const id = getVertexId(period, options);
14
+ const id = period ? getVertexId(period, options) : void 0;
16
15
  const periodIndex = periodsMap.get(id);
17
16
  if (periodIndex === void 0) throw new Error(`(RS::To::getPeriodIndex) Period "${id}" is not in periodsMap`);
18
17
  return periodIndex;
@@ -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::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
+ {"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 = period ? getVertexId(period, options) : undefined;\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;CACpB,MAAM,KAAK,SAAS,YAAY,QAAQ,WAAW;CACnD,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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@royalschedule/maps",
3
3
  "description": "",
4
- "version": "4.0.7",
4
+ "version": "4.0.9",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",