@royalschedule/maps 3.3.4 → 3.3.6

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.
@@ -6,7 +6,10 @@ var placements_default = (configuration, options = {}) => {
6
6
  const idKey = options.idKey || "id";
7
7
  const { events } = configuration ?? {};
8
8
  return reduce(events, ([eventAcc, lockedAcc], event) => {
9
- const [collection, id] = event.id.split(".");
9
+ const dotIndex = event.id.indexOf(".");
10
+ if (dotIndex === -1) return [eventAcc, lockedAcc];
11
+ const collection = event.id.substring(0, dotIndex);
12
+ const id = event.id.substring(dotIndex + 1);
10
13
  if (collection == "events") eventAcc = eventAcc.concat({
11
14
  [idKey]: id,
12
15
  parked: false,
@@ -14,7 +17,7 @@ var placements_default = (configuration, options = {}) => {
14
17
  start: moment.utc("1970-01-05T00:00").add(event.day, "days").add(event.start, "minutes").toISOString(),
15
18
  end: moment.utc("1970-01-05T00:00").add(event.day, "days").add(event.end, "minutes").toISOString()
16
19
  });
17
- if (collection == "lockedtimes") lockedAcc = lockedAcc.concat({
20
+ if (collection == "lockedTimes") lockedAcc = lockedAcc.concat({
18
21
  [idKey]: id,
19
22
  parked: false,
20
23
  start: moment.utc("1970-01-05T00:00").add(event.day, "days").add(event.start, "minutes").toISOString(),
@@ -1 +1 @@
1
- {"version":3,"file":"placements.js","names":[],"sources":["../../../../src/RS/v2/from/placements.ts"],"sourcesContent":["import moment from 'moment';\nimport { reduce } from 'lodash-es';\n\nimport { Configuration } from '../types/configurations';\nimport { Placement } from '../types/placements';\n\nimport { Types as CoreTypes } from '../../../core/types';\n\ntype Options = {\n idKey?: '_id' | 'id' | 'ids';\n};\n\nexport default (configuration: Configuration, options: Options = {}): [Omit<CoreTypes.event, 'preferredDuration'>[], CoreTypes.lockedTime[]] => {\n\n const idKey= options.idKey || 'id';\n\n const { events } = configuration ?? {};\n\n return reduce(events, ([eventAcc, lockedAcc]: [Omit<CoreTypes.event, 'preferredDuration'>[], CoreTypes.lockedTime[]], event: Placement) => {\n const [collection, id] = event.id.split('.');\n if (collection == 'events')\n eventAcc = eventAcc.concat({\n [idKey]: id,\n parked: false,\n inLocations: event.dependencies?.filter(Boolean) ?? [],\n start: moment.utc('1970-01-05T00:00').add(event.day, 'days')\n .add(event.start, 'minutes')\n .toISOString(),\n end: moment.utc('1970-01-05T00:00').add(event.day, 'days')\n .add(event.end, 'minutes')\n .toISOString()\n });\n if (collection == 'lockedtimes')\n lockedAcc = lockedAcc.concat({\n [idKey]: id,\n parked: false,\n start: moment.utc('1970-01-05T00:00').add(event.day, 'days')\n .add(event.start, 'minutes')\n .toISOString(),\n end: moment.utc('1970-01-05T00:00').add(event.day, 'days')\n .add(event.end, 'minutes')\n .toISOString()\n });\n return [eventAcc, lockedAcc];\n }, [[], []]);\n};"],"mappings":";;;;AAYA,0BAAgB,eAA8B,UAAmB,OAA+E;CAE9I,MAAM,QAAO,QAAQ,SAAS;CAE9B,MAAM,EAAE,WAAW,iBAAiB;AAEpC,QAAO,OAAO,SAAS,CAAC,UAAU,YAAoF,UAAqB;EACzI,MAAM,CAAC,YAAY,MAAM,MAAM,GAAG,MAAM;AACxC,MAAI,cAAc,SAChB,YAAW,SAAS,OAAO;IACxB,QAAY;GACb,QAAa;GACb,aAAa,MAAM,cAAc,OAAO,YAAY;GACpD,OAAa,OAAO,IAAI,oBAAoB,IAAI,MAAM,KAAK,QACxD,IAAI,MAAM,OAAO,WACjB;GACH,KAAK,OAAO,IAAI,oBAAoB,IAAI,MAAM,KAAK,QAChD,IAAI,MAAM,KAAK,WACf;;AAEP,MAAI,cAAc,cAChB,aAAY,UAAU,OAAO;IAC1B,QAAQ;GACT,QAAS;GACT,OAAS,OAAO,IAAI,oBAAoB,IAAI,MAAM,KAAK,QACpD,IAAI,MAAM,OAAO,WACjB;GACH,KAAK,OAAO,IAAI,oBAAoB,IAAI,MAAM,KAAK,QAChD,IAAI,MAAM,KAAK,WACf;;AAEP,SAAO,CAAC,UAAU;IACjB,CAAC,IAAI"}
1
+ {"version":3,"file":"placements.js","names":[],"sources":["../../../../src/RS/v2/from/placements.ts"],"sourcesContent":["import moment from 'moment';\nimport { reduce } from 'lodash-es';\n\nimport { Configuration } from '../types/configurations';\nimport { Placement } from '../types/placements';\n\nimport { Types as CoreTypes } from '../../../core/types';\n\ntype Options = {\n idKey?: '_id' | 'id' | 'ids';\n};\n\nexport default (configuration: Configuration, options: Options = {}): [Omit<CoreTypes.event, 'preferredDuration'>[], CoreTypes.lockedTime[]] => {\n\n const idKey= options.idKey || 'id';\n\n const { events } = configuration ?? {};\n\n return reduce(events, ([eventAcc, lockedAcc]: [Omit<CoreTypes.event, 'preferredDuration'>[], CoreTypes.lockedTime[]], event: Placement) => {\n // split on first dot only\n const dotIndex = event.id.indexOf('.');\n if (dotIndex === -1) return [eventAcc, lockedAcc];\n const collection = event.id.substring(0, dotIndex);\n const id = event.id.substring(dotIndex + 1);\n\n if (collection == 'events')\n eventAcc = eventAcc.concat({\n [idKey]: id,\n parked: false,\n inLocations: event.dependencies?.filter(Boolean) ?? [],\n start: moment.utc('1970-01-05T00:00').add(event.day, 'days')\n .add(event.start, 'minutes')\n .toISOString(),\n end: moment.utc('1970-01-05T00:00').add(event.day, 'days')\n .add(event.end, 'minutes')\n .toISOString()\n });\n if (collection == 'lockedTimes')\n lockedAcc = lockedAcc.concat({\n [idKey]: id,\n parked: false,\n start: moment.utc('1970-01-05T00:00').add(event.day, 'days')\n .add(event.start, 'minutes')\n .toISOString(),\n end: moment.utc('1970-01-05T00:00').add(event.day, 'days')\n .add(event.end, 'minutes')\n .toISOString()\n });\n return [eventAcc, lockedAcc];\n }, [[], []]);\n};"],"mappings":";;;;AAYA,0BAAgB,eAA8B,UAAmB,OAA+E;CAE9I,MAAM,QAAO,QAAQ,SAAS;CAE9B,MAAM,EAAE,WAAW,iBAAiB;AAEpC,QAAO,OAAO,SAAS,CAAC,UAAU,YAAoF,UAAqB;EAEzI,MAAM,WAAW,MAAM,GAAG,QAAQ;AAClC,MAAI,aAAa,GAAI,QAAO,CAAC,UAAU;EACvC,MAAM,aAAa,MAAM,GAAG,UAAU,GAAG;EACzC,MAAM,KAAa,MAAM,GAAG,UAAU,WAAW;AAEjD,MAAI,cAAc,SAChB,YAAW,SAAS,OAAO;IACxB,QAAY;GACb,QAAa;GACb,aAAa,MAAM,cAAc,OAAO,YAAY;GACpD,OAAa,OAAO,IAAI,oBAAoB,IAAI,MAAM,KAAK,QACxD,IAAI,MAAM,OAAO,WACjB;GACH,KAAK,OAAO,IAAI,oBAAoB,IAAI,MAAM,KAAK,QAChD,IAAI,MAAM,KAAK,WACf;;AAEP,MAAI,cAAc,cAChB,aAAY,UAAU,OAAO;IAC1B,QAAQ;GACT,QAAS;GACT,OAAS,OAAO,IAAI,oBAAoB,IAAI,MAAM,KAAK,QACpD,IAAI,MAAM,OAAO,WACjB;GACH,KAAK,OAAO,IAAI,oBAAoB,IAAI,MAAM,KAAK,QAChD,IAAI,MAAM,KAAK,WACf;;AAEP,SAAO,CAAC,UAAU;IACjB,CAAC,IAAI"}
@@ -36,7 +36,7 @@ var dynamic_locked_times_default = (docs, settings, options, set, destructMap) =
36
36
  return acc$2;
37
37
  }, groups);
38
38
  return acc$1.concat({
39
- id: `${group.lunch == null ? "virtual" : "lockedtimes"}.${id}`,
39
+ id: `${group.lunch == null ? "virtual" : "lockedTimes"}.${id}`,
40
40
  groups: [...new Set(groups.filter(Boolean))].map((x) => [x]),
41
41
  dependencies: [...new Set(coalesced.filter((x) => x.toModel == "locations").map(({ to }) => to[idKey]?.toString()).filter(Boolean))].map((x) => [x]),
42
42
  length: duration,
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-locked-times.js","names":["idKey: 'id' | '_id' | 'ids'","lunch","id: string","acc","set","_intervals"],"sources":["../../../../src/RS/v2/to/dynamic-locked-times.ts"],"sourcesContent":["import moment from 'moment';\nimport { nanoid } from 'nanoid';\n\nimport { OutOptions } from '../types/out-options';\nimport { CourseEvent } from '../types/course-events';\n\nimport _intervals from './intervals';\n\nimport { Types as CoreTypes } from '../../../core/types';\nimport { Deserialized } from '../../../core/types';\nimport { pick } from 'lodash-es';\n\nexport default (docs: (Deserialized<CoreTypes.group> | Deserialized<CoreTypes.teacher>)[],\n settings: Deserialized<CoreTypes.divisionSettings>,\n options: OutOptions,\n set: Set<string>,\n destructMap?: Map<string | null, Set<string>>) => {\n //let docs: SourceLockedTime[] = (Array.isArray(lockedTimes) ? lockedTimes : [lockedTimes]);\n const idKey: 'id' | '_id' | 'ids' = (options.idKey ?? 'id');\n\n return docs.filter(x => !!x).reduce((acc: CourseEvent[], group): CourseEvent[] => {\n let lunch = group.lunch;\n if (lunch == null) {\n lunch = settings.defaultLunch?.map(lunch => ({ ...lunch, coalesced: [{ to: pick(group, idKey), toModel: '' }] }));\n }\n\n if (lunch == null)\n return acc;\n\n\n return acc.concat(\n lunch.reduce((acc: CourseEvent[], lockedTime) => {\n\n const { _id, intervals, duration, durationVariance, coalesced } = lockedTime;\n\n const id: string = (lockedTime[idKey as keyof CoreTypes.lockedTime] || _id)?.toString() ?? nanoid();\n\n if (set.has(id))\n return acc;\n\n set.add(id);\n\n if (duration == null)\n throw new Error('(RS::V2::To::DynamicLockedTimes) Length of a locked time is null');\n\n if (duration < 5)\n throw new Error('(RS::V2::To::DynamicLockedTimes) Length of a locked time is less than 5 min');\n\n if (!coalesced)\n throw new Error('(RS::V2::To::DynamicLockedTimes) Length of a locked time is less than 5 min');\n /*\n find the day(s) the events should be placed on\n */\n\n let days = intervals?.map(({ start }) => (moment(start).day() + 6) % 7);\n if (days)\n days = [...new Set(days)];\n\n /*\n find all references to destructured groups and replace with composite\n */\n let groups = coalesced.filter(x => x.toModel != 'locations')?.map(({ to, toModel }) => `${ toModel }.${ to[idKey]?.toString() }`);\n if (destructMap?.size) {\n groups = coalesced.filter(x => x.toModel == 'groups')\n .map(({ to }) => to[idKey]?.toString()!)\n .filter(Boolean)\n .reduce((acc: string[], groupId) => {\n if (destructMap.has(groupId)) {\n const set = destructMap.get(groupId)!;\n const destructuredGroups = Array.from(set).map(x => `persons.${ x }`);\n acc = acc.concat(destructuredGroups);\n }\n return acc;\n }, groups);\n }\n\n return acc.concat({\n id: `${ group.lunch == null ? 'virtual' : 'lockedtimes' }.${ id }`,\n groups: [...new Set(groups.filter(Boolean))].map(x => [x]),\n dependencies: [...new Set(coalesced.filter(x => x.toModel == 'locations').map(({ to }) => to[idKey]?.toString()!)\n .filter(Boolean))].map(x => [x]),\n length: duration,\n minBreakLength: false,\n intervals: _intervals(intervals, settings),\n ...days && (days.length == 1 ? { day: days[0] } : { days }),\n ...durationVariance != null && { maxLengthVariance: durationVariance },\n });\n }, []));\n\n }, [])\n .flat()\n .filter(Boolean);\n};"],"mappings":";;;;;;AAYA,oCAAgB,MACd,UACA,SACA,KACA,gBAAkD;CAElD,MAAMA,QAA+B,QAAQ,SAAS;AAEtD,QAAO,KAAK,QAAO,MAAK,CAAC,CAAC,GAAG,QAAQ,KAAoB,UAAyB;EAChF,IAAI,QAAQ,MAAM;AAClB,MAAI,SAAS,KACX,SAAQ,SAAS,cAAc,KAAI,aAAU;GAAE,GAAGC;GAAO,WAAW,CAAC;IAAE,IAAI,KAAK,OAAO;IAAQ,SAAS;;;AAG1G,MAAI,SAAS,KACX,QAAO;AAGT,SAAO,IAAI,OACT,MAAM,QAAQ,OAAoB,eAAe;GAE/C,MAAM,EAAE,KAAK,WAAW,UAAU,kBAAkB,cAAc;GAElE,MAAMC,MAAc,WAAW,UAAwC,MAAM,cAAc;AAE3F,OAAI,IAAI,IAAI,IACV,QAAOC;AAET,OAAI,IAAI;AAER,OAAI,YAAY,KACd,OAAM,IAAI,MAAM;AAElB,OAAI,WAAW,EACb,OAAM,IAAI,MAAM;AAElB,OAAI,CAAC,UACH,OAAM,IAAI,MAAM;GAKlB,IAAI,OAAO,WAAW,KAAK,EAAE,aAAa,OAAO,OAAO,QAAQ,KAAK;AACrE,OAAI,KACF,QAAO,CAAC,GAAG,IAAI,IAAI;GAKrB,IAAI,SAAS,UAAU,QAAO,MAAK,EAAE,WAAW,cAAc,KAAK,EAAE,IAAI,cAAc,GAAI,QAAS,GAAI,GAAG,QAAQ;AACnH,OAAI,aAAa,KACf,UAAS,UAAU,QAAO,MAAK,EAAE,WAAW,UACzC,KAAK,EAAE,SAAS,GAAG,QAAQ,YAC3B,OAAO,SACP,QAAQ,OAAe,YAAY;AAClC,QAAI,YAAY,IAAI,UAAU;KAC5B,MAAMC,QAAM,YAAY,IAAI;KAC5B,MAAM,qBAAqB,MAAM,KAAKA,OAAK,KAAI,MAAK,WAAY;AAChE,aAAMD,MAAI,OAAO;;AAEnB,WAAOA;MACN;AAGP,UAAOA,MAAI,OAAO;IAChB,IAAc,GAAI,MAAM,SAAS,OAAO,YAAY,cAAe,GAAI;IACvE,QAAc,CAAC,GAAG,IAAI,IAAI,OAAO,OAAO,WAAW,KAAI,MAAK,CAAC;IAC7D,cAAc,CAAC,GAAG,IAAI,IAAI,UAAU,QAAO,MAAK,EAAE,WAAW,aAAa,KAAK,EAAE,SAAS,GAAG,QAAQ,YAClG,OAAO,WAAW,KAAI,MAAK,CAAC;IAC/B,QAAgB;IAChB,gBAAgB;IAChB,WAAgBE,kBAAW,WAAW;IACtC,GAAG,SAAS,KAAK,UAAU,IAAI,EAAE,KAAK,KAAK,OAAO,EAAE;IACpD,GAAG,oBAAoB,QAAS,EAAE,mBAAmB;;KAEtD;IAEJ,IACA,OACA,OAAO"}
1
+ {"version":3,"file":"dynamic-locked-times.js","names":["idKey: 'id' | '_id' | 'ids'","lunch","id: string","acc","set","_intervals"],"sources":["../../../../src/RS/v2/to/dynamic-locked-times.ts"],"sourcesContent":["import moment from 'moment';\nimport { nanoid } from 'nanoid';\n\nimport { OutOptions } from '../types/out-options';\nimport { CourseEvent } from '../types/course-events';\n\nimport _intervals from './intervals';\n\nimport { Types as CoreTypes } from '../../../core/types';\nimport { Deserialized } from '../../../core/types';\nimport { pick } from 'lodash-es';\n\nexport default (docs: (Deserialized<CoreTypes.group> | Deserialized<CoreTypes.teacher>)[],\n settings: Deserialized<CoreTypes.divisionSettings>,\n options: OutOptions,\n set: Set<string>,\n destructMap?: Map<string | null, Set<string>>) => {\n //let docs: SourceLockedTime[] = (Array.isArray(lockedTimes) ? lockedTimes : [lockedTimes]);\n const idKey: 'id' | '_id' | 'ids' = (options.idKey ?? 'id');\n\n return docs.filter(x => !!x).reduce((acc: CourseEvent[], group): CourseEvent[] => {\n let lunch = group.lunch;\n if (lunch == null) {\n lunch = settings.defaultLunch?.map(lunch => ({ ...lunch, coalesced: [{ to: pick(group, idKey), toModel: '' }] }));\n }\n\n if (lunch == null)\n return acc;\n\n\n return acc.concat(\n lunch.reduce((acc: CourseEvent[], lockedTime) => {\n\n const { _id, intervals, duration, durationVariance, coalesced } = lockedTime;\n\n const id: string = (lockedTime[idKey as keyof CoreTypes.lockedTime] || _id)?.toString() ?? nanoid();\n\n if (set.has(id))\n return acc;\n\n set.add(id);\n\n if (duration == null)\n throw new Error('(RS::V2::To::DynamicLockedTimes) Length of a locked time is null');\n\n if (duration < 5)\n throw new Error('(RS::V2::To::DynamicLockedTimes) Length of a locked time is less than 5 min');\n\n if (!coalesced)\n throw new Error('(RS::V2::To::DynamicLockedTimes) Length of a locked time is less than 5 min');\n /*\n find the day(s) the events should be placed on\n */\n\n let days = intervals?.map(({ start }) => (moment(start).day() + 6) % 7);\n if (days)\n days = [...new Set(days)];\n\n /*\n find all references to destructured groups and replace with composite\n */\n let groups = coalesced.filter(x => x.toModel != 'locations')?.map(({ to, toModel }) => `${ toModel }.${ to[idKey]?.toString() }`);\n if (destructMap?.size) {\n groups = coalesced.filter(x => x.toModel == 'groups')\n .map(({ to }) => to[idKey]?.toString()!)\n .filter(Boolean)\n .reduce((acc: string[], groupId) => {\n if (destructMap.has(groupId)) {\n const set = destructMap.get(groupId)!;\n const destructuredGroups = Array.from(set).map(x => `persons.${ x }`);\n acc = acc.concat(destructuredGroups);\n }\n return acc;\n }, groups);\n }\n\n return acc.concat({\n id: `${ group.lunch == null ? 'virtual' : 'lockedTimes' }.${ id }`,\n groups: [...new Set(groups.filter(Boolean))].map(x => [x]),\n dependencies: [...new Set(coalesced.filter(x => x.toModel == 'locations').map(({ to }) => to[idKey]?.toString()!)\n .filter(Boolean))].map(x => [x]),\n length: duration,\n minBreakLength: false,\n intervals: _intervals(intervals, settings),\n ...days && (days.length == 1 ? { day: days[0] } : { days }),\n ...durationVariance != null && { maxLengthVariance: durationVariance },\n });\n }, []));\n\n }, [])\n .flat()\n .filter(Boolean);\n};"],"mappings":";;;;;;AAYA,oCAAgB,MACd,UACA,SACA,KACA,gBAAkD;CAElD,MAAMA,QAA+B,QAAQ,SAAS;AAEtD,QAAO,KAAK,QAAO,MAAK,CAAC,CAAC,GAAG,QAAQ,KAAoB,UAAyB;EAChF,IAAI,QAAQ,MAAM;AAClB,MAAI,SAAS,KACX,SAAQ,SAAS,cAAc,KAAI,aAAU;GAAE,GAAGC;GAAO,WAAW,CAAC;IAAE,IAAI,KAAK,OAAO;IAAQ,SAAS;;;AAG1G,MAAI,SAAS,KACX,QAAO;AAGT,SAAO,IAAI,OACT,MAAM,QAAQ,OAAoB,eAAe;GAE/C,MAAM,EAAE,KAAK,WAAW,UAAU,kBAAkB,cAAc;GAElE,MAAMC,MAAc,WAAW,UAAwC,MAAM,cAAc;AAE3F,OAAI,IAAI,IAAI,IACV,QAAOC;AAET,OAAI,IAAI;AAER,OAAI,YAAY,KACd,OAAM,IAAI,MAAM;AAElB,OAAI,WAAW,EACb,OAAM,IAAI,MAAM;AAElB,OAAI,CAAC,UACH,OAAM,IAAI,MAAM;GAKlB,IAAI,OAAO,WAAW,KAAK,EAAE,aAAa,OAAO,OAAO,QAAQ,KAAK;AACrE,OAAI,KACF,QAAO,CAAC,GAAG,IAAI,IAAI;GAKrB,IAAI,SAAS,UAAU,QAAO,MAAK,EAAE,WAAW,cAAc,KAAK,EAAE,IAAI,cAAc,GAAI,QAAS,GAAI,GAAG,QAAQ;AACnH,OAAI,aAAa,KACf,UAAS,UAAU,QAAO,MAAK,EAAE,WAAW,UACzC,KAAK,EAAE,SAAS,GAAG,QAAQ,YAC3B,OAAO,SACP,QAAQ,OAAe,YAAY;AAClC,QAAI,YAAY,IAAI,UAAU;KAC5B,MAAMC,QAAM,YAAY,IAAI;KAC5B,MAAM,qBAAqB,MAAM,KAAKA,OAAK,KAAI,MAAK,WAAY;AAChE,aAAMD,MAAI,OAAO;;AAEnB,WAAOA;MACN;AAGP,UAAOA,MAAI,OAAO;IAChB,IAAc,GAAI,MAAM,SAAS,OAAO,YAAY,cAAe,GAAI;IACvE,QAAc,CAAC,GAAG,IAAI,IAAI,OAAO,OAAO,WAAW,KAAI,MAAK,CAAC;IAC7D,cAAc,CAAC,GAAG,IAAI,IAAI,UAAU,QAAO,MAAK,EAAE,WAAW,aAAa,KAAK,EAAE,SAAS,GAAG,QAAQ,YAClG,OAAO,WAAW,KAAI,MAAK,CAAC;IAC/B,QAAgB;IAChB,gBAAgB;IAChB,WAAgBE,kBAAW,WAAW;IACtC,GAAG,SAAS,KAAK,UAAU,IAAI,EAAE,KAAK,KAAK,OAAO,EAAE;IACpD,GAAG,oBAAoB,QAAS,EAAE,mBAAmB;;KAEtD;IAEJ,IACA,OACA,OAAO"}
@@ -12,6 +12,10 @@ import { pick } from "lodash-es";
12
12
 
13
13
  //#region src/RS/v3/to/constraints.ts
14
14
  var constraints_default = (schedule, options = {}) => {
15
+ if (options.partialScheduleOptions?.includedEvents?.size) options.partialScheduleOptions.includedEvents = new Set([...options.partialScheduleOptions.includedEvents].map((x) => {
16
+ if (x.startsWith("events.") || x.startsWith("lockedTimes.")) return x;
17
+ return `events.${x}`;
18
+ }));
15
19
  schedule = structuredClone(schedule);
16
20
  if (schedule == null) return {};
17
21
  const idKey = options.idKey || "id";
@@ -1 +1 @@
1
- {"version":3,"file":"constraints.js","names":["idKey: keyof CoreTypes.course","groupMap","_destructure","data: Constraint","getSettings","getDefault","getCollections","getDependencies","getGroups","getTeachers","getDynamicLockedTimes"],"sources":["../../../../src/RS/v3/to/constraints.ts"],"sourcesContent":["import { pick } from 'lodash-es';\n\nimport { Types as CoreTypes } from '../../../core/types';\nimport { Deserialized } from '../../../core/types';\n\nimport { Constraint } from '../types/constraints';\nimport { OutOptions } from '../types/out-options';\n\nimport _destructure from './destructure';\nimport getDependencies from './dependencies';\nimport getTeachers from './teachers';\nimport getGroups from './groups';\nimport getCollections from './collections';\nimport getSettings from './settings';\nimport getDefault from './default';\nimport getDynamicLockedTimes from './dynamic-locked-times';\nimport { parsePeriods } from './periods';\nimport { personsToIndividuals,\n groupsToIndividuals,\n teachersToIndividuals } from './individuals';\n\nexport default (\n schedule: Partial<Deserialized<CoreTypes.schedule> & { division: Deserialized<CoreTypes.division> }>,\n options: OutOptions = {}\n): Constraint => {\n // clone schedule to avoid mutating the original object\n schedule = structuredClone(schedule);\n\n if (schedule == null) return {};\n const idKey: keyof CoreTypes.course = options.idKey || 'id';\n\n const settings = schedule.settings;\n if (!settings) throw new Error('settings missing in schedule');\n\n const area = schedule.area;\n const groups = schedule.groups ?? [];\n const teachers = schedule.teachers ?? [];\n const locations = schedule.locations ?? [];\n const events = schedule.events ?? [];\n const overlapGroups = schedule.overlapGroups ?? [];\n const courses = schedule.courses ?? [];\n const periods = schedule.periods ?? [];\n const persons = schedule.persons ?? [];\n\n ////\n //// populate some group references to ensure that the types are correct\n ////\n {\n const groupMap = new Map(groups\n .map(x => ([x[idKey]?.toString(), x] as const))\n .filter(x => !!x[0])\n );\n // group.parentGroups\n groups?.forEach(item => {\n if (!item.parentGroups) return;\n item.parentGroups = item.parentGroups\n .map((x: Deserialized<CoreTypes.group> | string) => {\n return typeof x === 'string' ? groupMap.get(x) : groupMap.get(x[idKey]?.toString());\n })\n .filter((x): x is NonNullable<typeof x> => !!x);\n });\n // course.groups.to and event.groups.to\n courses.concat(events).forEach(item => {\n if (!item.groups) return;\n item.groups.forEach((x: { to: Deserialized<CoreTypes.group> | string }) => {\n const group = typeof x.to === 'string' ? groupMap.get(x.to) : groupMap.get(x.to[idKey]?.toString());\n if (group) x.to = group;\n });\n });\n }\n\n // unfortunately the division is set either as \"division\" or \"divisions\" so we need to handle both cases\n const division = schedule.divisions ?? schedule.division;\n\n // map periods\n const { map: periodsMap, matrix: periodsMatrix } = parsePeriods(periods, pick(division, 'start', 'end'));\n\n const destructMap = _destructure(courses, events, groups, settings, options);\n\n const data: Constraint = {\n settings: getSettings(settings),\n default: getDefault(settings, periodsMap, options),\n ...periodsMatrix && { periods: periodsMatrix },\n ...area && {\n areas: {\n breakLengthMatrix: area.breakLengthMatrix,\n list: area.list\n }\n },\n // intervals: getRootIntervals(rootIntervals, settings!),\n events: getCollections(courses, events, overlapGroups, settings, options, periodsMap, destructMap),\n dependencies: getDependencies(locations, settings, options),\n groups: getGroups(groups, settings, options)\n .concat(getTeachers(teachers, settings, options)),\n individuals: personsToIndividuals(persons, settings, options)\n .concat(groupsToIndividuals(groups, settings, options))\n .concat(teachersToIndividuals(teachers, settings, options)),\n };\n\n /*\n create map of groups if some groups are destructed\n groupMap: group id -> group\n */\n const groupMap = new Map<string, Deserialized<CoreTypes.group>>();\n if (destructMap.size) {\n groups?.forEach(x => groupMap.set(x[idKey]!.toString(), x));\n\n /*\n Find group and clone and substitute id with person id\n */\n data.individuals = data.individuals?.concat(Array.from(destructMap.values()));\n }\n\n /*\n handle groups.lunch and teachers.lunch\n append to events list\n */\n const lunchSet = new Set<string>();\n /**\n * Only add lunch if the group is a class\n */\n if (groups?.some(group => 'lunch' in group))\n data.events = (data.events ?? []).concat(getDynamicLockedTimes(groups.filter(x => x.species == 'class'), settings, options, lunchSet, destructMap));\n\n if (teachers?.some(teacher => 'lunch' in teacher || 'complementaryHours' in teacher))\n data.events = (data.events ?? []).concat(getDynamicLockedTimes(teachers, settings, options, lunchSet));\n\n return data;\n};"],"mappings":";;;;;;;;;;;;;AAqBA,2BACE,UACA,UAAuB,OACR;AAEf,YAAW,gBAAgB;AAE3B,KAAI,YAAY,KAAM,QAAO;CAC7B,MAAMA,QAAgC,QAAQ,SAAS;CAEvD,MAAM,WAAW,SAAS;AAC1B,KAAI,CAAC,SAAU,OAAM,IAAI,MAAM;CAE/B,MAAM,OAAgB,SAAS;CAC/B,MAAM,SAAgB,SAAS,UAAiB;CAChD,MAAM,WAAgB,SAAS,YAAiB;CAChD,MAAM,YAAgB,SAAS,aAAiB;CAChD,MAAM,SAAgB,SAAS,UAAiB;CAChD,MAAM,gBAAgB,SAAS,iBAAiB;CAChD,MAAM,UAAgB,SAAS,WAAiB;CAChD,MAAM,UAAgB,SAAS,WAAiB;CAChD,MAAM,UAAgB,SAAS,WAAiB;CAKhD;EACE,MAAMC,aAAW,IAAI,IAAI,OACtB,KAAI,MAAM,CAAC,EAAE,QAAQ,YAAY,IACjC,QAAO,MAAK,CAAC,CAAC,EAAE;AAGnB,UAAQ,SAAQ,SAAQ;AACtB,OAAI,CAAC,KAAK,aAAc;AACxB,QAAK,eAAe,KAAK,aACtB,KAAK,MAA8C;AAClD,WAAO,OAAO,MAAM,WAAWA,WAAS,IAAI,KAAKA,WAAS,IAAI,EAAE,QAAQ;MAEzE,QAAQ,MAAkC,CAAC,CAAC;;AAGjD,UAAQ,OAAO,QAAQ,SAAQ,SAAQ;AACrC,OAAI,CAAC,KAAK,OAAQ;AAClB,QAAK,OAAO,SAAS,MAAsD;IACzE,MAAM,QAAQ,OAAO,EAAE,OAAO,WAAWA,WAAS,IAAI,EAAE,MAAMA,WAAS,IAAI,EAAE,GAAG,QAAQ;AACxF,QAAI,MAAO,GAAE,KAAK;;;;CAMxB,MAAM,WAAW,SAAS,aAAa,SAAS;CAGhD,MAAM,EAAE,KAAK,YAAY,QAAQ,kBAAkB,aAAa,SAAS,KAAK,UAAU,SAAS;CAEjG,MAAM,cAAcC,oBAAa,SAAS,QAAQ,QAAQ,UAAU;CAEpE,MAAMC,OAAmB;EACvB,UAAUC,iBAAY;EACtB,SAAUC,gBAAW,UAAU,YAAY;EAC3C,GAAG,iBAAiB,EAAE,SAAS;EAC/B,GAAG,QAAQ,EACT,OAAO;GACL,mBAAmB,KAAK;GACxB,MAAmB,KAAK;;EAI5B,QAAcC,oBAAe,SAAS,QAAQ,eAAe,UAAU,SAAS,YAAY;EAC5F,cAAcC,qBAAgB,WAAW,UAAU;EACnD,QAAcC,eAAU,QAAQ,UAAU,SACvC,OAAOC,iBAAY,UAAU,UAAU;EAC1C,aAAa,qBAAqB,SAAS,UAAU,SAClD,OAAO,oBAAoB,QAAQ,UAAU,UAC7C,OAAO,sBAAsB,UAAU,UAAU;;CAOtD,MAAM,2BAAW,IAAI;AACrB,KAAI,YAAY,MAAM;AACpB,UAAQ,SAAQ,MAAK,SAAS,IAAI,EAAE,OAAQ,YAAY;AAKxD,OAAK,cAAc,KAAK,aAAa,OAAO,MAAM,KAAK,YAAY;;CAOrE,MAAM,2BAAW,IAAI;;;;AAIrB,KAAI,QAAQ,MAAK,UAAS,WAAW,OACnC,MAAK,UAAU,KAAK,UAAU,IAAI,OAAOC,6BAAsB,OAAO,QAAO,MAAK,EAAE,WAAW,UAAU,UAAU,SAAS,UAAU;AAExI,KAAI,UAAU,MAAK,YAAW,WAAW,WAAW,wBAAwB,SAC1E,MAAK,UAAU,KAAK,UAAU,IAAI,OAAOA,6BAAsB,UAAU,UAAU,SAAS;AAE9F,QAAO"}
1
+ {"version":3,"file":"constraints.js","names":["idKey: keyof CoreTypes.course","groupMap","_destructure","data: Constraint","getSettings","getDefault","getCollections","getDependencies","getGroups","getTeachers","getDynamicLockedTimes"],"sources":["../../../../src/RS/v3/to/constraints.ts"],"sourcesContent":["import { pick } from 'lodash-es';\n\nimport { Types as CoreTypes } from '../../../core/types';\nimport { Deserialized } from '../../../core/types';\n\nimport { Constraint } from '../types/constraints';\nimport { OutOptions } from '../types/out-options';\n\nimport _destructure from './destructure';\nimport getDependencies from './dependencies';\nimport getTeachers from './teachers';\nimport getGroups from './groups';\nimport getCollections from './collections';\nimport getSettings from './settings';\nimport getDefault from './default';\nimport getDynamicLockedTimes from './dynamic-locked-times';\nimport { parsePeriods } from './periods';\nimport { personsToIndividuals,\n groupsToIndividuals,\n teachersToIndividuals } from './individuals';\n\nexport default (\n schedule: Partial<Deserialized<CoreTypes.schedule> & { division: Deserialized<CoreTypes.division> }>,\n options: OutOptions = {}\n): Constraint => {\n ////\n //// for backward compatibility: add default collection to included events set\n ////\n if (options.partialScheduleOptions?.includedEvents?.size) {\n options.partialScheduleOptions.includedEvents = new Set(\n [...options.partialScheduleOptions.includedEvents]\n .map(x => {\n // should start with 'events.' or 'lockedTimes.' prefix\n if (x.startsWith('events.') || x.startsWith('lockedTimes.')) return x;\n return `events.${x}`;\n })\n );\n }\n\n\n // clone schedule to avoid mutating the original object\n schedule = structuredClone(schedule);\n\n if (schedule == null) return {};\n const idKey: keyof CoreTypes.course = options.idKey || 'id';\n\n const settings = schedule.settings;\n if (!settings) throw new Error('settings missing in schedule');\n\n const area = schedule.area;\n const groups = schedule.groups ?? [];\n const teachers = schedule.teachers ?? [];\n const locations = schedule.locations ?? [];\n const events = schedule.events ?? [];\n const overlapGroups = schedule.overlapGroups ?? [];\n const courses = schedule.courses ?? [];\n const periods = schedule.periods ?? [];\n const persons = schedule.persons ?? [];\n\n ////\n //// populate some group references to ensure that the types are correct\n ////\n {\n const groupMap = new Map(groups\n .map(x => ([x[idKey]?.toString(), x] as const))\n .filter(x => !!x[0])\n );\n // group.parentGroups\n groups?.forEach(item => {\n if (!item.parentGroups) return;\n item.parentGroups = item.parentGroups\n .map((x: Deserialized<CoreTypes.group> | string) => {\n return typeof x === 'string' ? groupMap.get(x) : groupMap.get(x[idKey]?.toString());\n })\n .filter((x): x is NonNullable<typeof x> => !!x);\n });\n // course.groups.to and event.groups.to\n courses.concat(events).forEach(item => {\n if (!item.groups) return;\n item.groups.forEach((x: { to: Deserialized<CoreTypes.group> | string }) => {\n const group = typeof x.to === 'string' ? groupMap.get(x.to) : groupMap.get(x.to[idKey]?.toString());\n if (group) x.to = group;\n });\n });\n }\n\n // unfortunately the division is set either as \"division\" or \"divisions\" so we need to handle both cases\n const division = schedule.divisions ?? schedule.division;\n\n // map periods\n const { map: periodsMap, matrix: periodsMatrix } = parsePeriods(periods, pick(division, 'start', 'end'));\n\n const destructMap = _destructure(courses, events, groups, settings, options);\n\n const data: Constraint = {\n settings: getSettings(settings),\n default: getDefault(settings, periodsMap, options),\n ...periodsMatrix && { periods: periodsMatrix },\n ...area && {\n areas: {\n breakLengthMatrix: area.breakLengthMatrix,\n list: area.list\n }\n },\n // intervals: getRootIntervals(rootIntervals, settings!),\n events: getCollections(courses, events, overlapGroups, settings, options, periodsMap, destructMap),\n dependencies: getDependencies(locations, settings, options),\n groups: getGroups(groups, settings, options)\n .concat(getTeachers(teachers, settings, options)),\n individuals: personsToIndividuals(persons, settings, options)\n .concat(groupsToIndividuals(groups, settings, options))\n .concat(teachersToIndividuals(teachers, settings, options)),\n };\n\n /*\n create map of groups if some groups are destructed\n groupMap: group id -> group\n */\n const groupMap = new Map<string, Deserialized<CoreTypes.group>>();\n if (destructMap.size) {\n groups?.forEach(x => groupMap.set(x[idKey]!.toString(), x));\n\n /*\n Find group and clone and substitute id with person id\n */\n data.individuals = data.individuals?.concat(Array.from(destructMap.values()));\n }\n\n /*\n handle groups.lunch and teachers.lunch\n append to events list\n */\n const lunchSet = new Set<string>();\n /**\n * Only add lunch if the group is a class\n */\n if (groups?.some(group => 'lunch' in group))\n data.events = (data.events ?? []).concat(getDynamicLockedTimes(groups.filter(x => x.species == 'class'), settings, options, lunchSet, destructMap));\n\n if (teachers?.some(teacher => 'lunch' in teacher || 'complementaryHours' in teacher))\n data.events = (data.events ?? []).concat(getDynamicLockedTimes(teachers, settings, options, lunchSet));\n\n return data;\n};"],"mappings":";;;;;;;;;;;;;AAqBA,2BACE,UACA,UAAuB,OACR;AAIf,KAAI,QAAQ,wBAAwB,gBAAgB,KAClD,SAAQ,uBAAuB,iBAAiB,IAAI,IAClD,CAAC,GAAG,QAAQ,uBAAuB,gBAChC,KAAI,MAAK;AAER,MAAI,EAAE,WAAW,cAAc,EAAE,WAAW,gBAAiB,QAAO;AACpE,SAAO,UAAU;;AAOzB,YAAW,gBAAgB;AAE3B,KAAI,YAAY,KAAM,QAAO;CAC7B,MAAMA,QAAgC,QAAQ,SAAS;CAEvD,MAAM,WAAW,SAAS;AAC1B,KAAI,CAAC,SAAU,OAAM,IAAI,MAAM;CAE/B,MAAM,OAAgB,SAAS;CAC/B,MAAM,SAAgB,SAAS,UAAiB;CAChD,MAAM,WAAgB,SAAS,YAAiB;CAChD,MAAM,YAAgB,SAAS,aAAiB;CAChD,MAAM,SAAgB,SAAS,UAAiB;CAChD,MAAM,gBAAgB,SAAS,iBAAiB;CAChD,MAAM,UAAgB,SAAS,WAAiB;CAChD,MAAM,UAAgB,SAAS,WAAiB;CAChD,MAAM,UAAgB,SAAS,WAAiB;CAKhD;EACE,MAAMC,aAAW,IAAI,IAAI,OACtB,KAAI,MAAM,CAAC,EAAE,QAAQ,YAAY,IACjC,QAAO,MAAK,CAAC,CAAC,EAAE;AAGnB,UAAQ,SAAQ,SAAQ;AACtB,OAAI,CAAC,KAAK,aAAc;AACxB,QAAK,eAAe,KAAK,aACtB,KAAK,MAA8C;AAClD,WAAO,OAAO,MAAM,WAAWA,WAAS,IAAI,KAAKA,WAAS,IAAI,EAAE,QAAQ;MAEzE,QAAQ,MAAkC,CAAC,CAAC;;AAGjD,UAAQ,OAAO,QAAQ,SAAQ,SAAQ;AACrC,OAAI,CAAC,KAAK,OAAQ;AAClB,QAAK,OAAO,SAAS,MAAsD;IACzE,MAAM,QAAQ,OAAO,EAAE,OAAO,WAAWA,WAAS,IAAI,EAAE,MAAMA,WAAS,IAAI,EAAE,GAAG,QAAQ;AACxF,QAAI,MAAO,GAAE,KAAK;;;;CAMxB,MAAM,WAAW,SAAS,aAAa,SAAS;CAGhD,MAAM,EAAE,KAAK,YAAY,QAAQ,kBAAkB,aAAa,SAAS,KAAK,UAAU,SAAS;CAEjG,MAAM,cAAcC,oBAAa,SAAS,QAAQ,QAAQ,UAAU;CAEpE,MAAMC,OAAmB;EACvB,UAAUC,iBAAY;EACtB,SAAUC,gBAAW,UAAU,YAAY;EAC3C,GAAG,iBAAiB,EAAE,SAAS;EAC/B,GAAG,QAAQ,EACT,OAAO;GACL,mBAAmB,KAAK;GACxB,MAAmB,KAAK;;EAI5B,QAAcC,oBAAe,SAAS,QAAQ,eAAe,UAAU,SAAS,YAAY;EAC5F,cAAcC,qBAAgB,WAAW,UAAU;EACnD,QAAcC,eAAU,QAAQ,UAAU,SACvC,OAAOC,iBAAY,UAAU,UAAU;EAC1C,aAAa,qBAAqB,SAAS,UAAU,SAClD,OAAO,oBAAoB,QAAQ,UAAU,UAC7C,OAAO,sBAAsB,UAAU,UAAU;;CAOtD,MAAM,2BAAW,IAAI;AACrB,KAAI,YAAY,MAAM;AACpB,UAAQ,SAAQ,MAAK,SAAS,IAAI,EAAE,OAAQ,YAAY;AAKxD,OAAK,cAAc,KAAK,aAAa,OAAO,MAAM,KAAK,YAAY;;CAOrE,MAAM,2BAAW,IAAI;;;;AAIrB,KAAI,QAAQ,MAAK,UAAS,WAAW,OACnC,MAAK,UAAU,KAAK,UAAU,IAAI,OAAOC,6BAAsB,OAAO,QAAO,MAAK,EAAE,WAAW,UAAU,UAAU,SAAS,UAAU;AAExI,KAAI,UAAU,MAAK,YAAW,WAAW,WAAW,wBAAwB,SAC1E,MAAK,UAAU,KAAK,UAAU,IAAI,OAAOA,6BAAsB,UAAU,UAAU,SAAS;AAE9F,QAAO"}
@@ -3,8 +3,10 @@ import { Deserialized } from "../../../../core/types/index.js";
3
3
  import { CourseEvent } from "../../types/course-events.js";
4
4
  import { Individual } from "../../types/individuals.js";
5
5
  import { OutOptions } from "../../types/out-options.js";
6
+ import moment from "moment";
6
7
 
7
8
  //#region src/RS/v3/to/course-events/index.d.ts
9
+
8
10
  declare function export_default(courseEvents: Deserialized<Types.event>[] | Deserialized<Types.event>, overlapGroups: Deserialized<Types.overlapGroup>[] | undefined, settings: Types.divisionSettings, options: OutOptions, periodsMap: Map<string | undefined, number>, destructMap?: Map<string | null, Individual>): CourseEvent[];
9
11
  //#endregion
10
12
  export { export_default };
@@ -52,7 +52,7 @@ function course_events_default(courseEvents, overlapGroups = [], settings, optio
52
52
  if (event.fixedStart && event.start) Object.assign(doc, toDayAndStart(event.start));
53
53
  if (options.partialScheduleOptions) {
54
54
  const { includedEvents, omittedEventsHandling } = options.partialScheduleOptions;
55
- if (includedEvents && !includedEvents.has(id)) {
55
+ if (includedEvents && !includedEvents.has(doc.id)) {
56
56
  if (omittedEventsHandling == "ignore") return;
57
57
  if (omittedEventsHandling == "freeze") {
58
58
  if (event.parked || !event.start || !event.duration) return;
@@ -74,5 +74,5 @@ function course_events_default(courseEvents, overlapGroups = [], settings, optio
74
74
  }
75
75
 
76
76
  //#endregion
77
- export { course_events_default as default };
77
+ export { course_events_default as default, toDayAndStart };
78
78
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["idKey: keyof CoreTypes.event","id","doc: CourseEvent","lockedTimes","breakLength","_dependencies","_meta","_days","_intervals"],"sources":["../../../../../src/RS/v3/to/course-events/index.ts"],"sourcesContent":["import moment from 'moment';\n\nimport breakLength from '../break-lengths';\nimport lockedTimes from '../locked-times';\n\nimport { CourseEvent } from '../../types/course-events';\nimport { OutOptions } from '../../types/out-options';\nimport { Individual } from '../../types/individuals';\n\nimport { Types as CoreTypes } from '../../../../core/types';\nimport { Deserialized } from '../../../../core/types';\n\n\nimport { mapGroupReferences } from './groups';\nimport _meta from './meta';\nimport _dependencies from './dependencies';\nimport _days from './days';\nimport _intervals from './intervals';\nimport { AvailableDependency } from '../../types/available-dependencies';\n\nfunction toDayAndStart (start: string | moment.Moment | Date) {\n return {\n start: parseFloat(moment.utc(start).format('HH.mm')),\n day: (moment.utc(start).day() + 6) % 7\n };\n}\n\nexport default function (\n courseEvents: Deserialized<CoreTypes.event>[] | Deserialized<CoreTypes.event>,\n overlapGroups: Deserialized<CoreTypes.overlapGroup>[] = [],\n settings: CoreTypes.divisionSettings,\n options: OutOptions,\n periodsMap: Map<string | undefined, number>,\n destructMap: Map<string | null, Individual> = new Map()\n): CourseEvent[] {\n const idKey: keyof CoreTypes.event = options.idKey ?? 'id';\n\n return (Array.isArray(courseEvents) ? courseEvents : [courseEvents])\n .map(event => {\n const id = (event[idKey] ?? event._id)?.toString();\n if (!id) return;\n\n let forcedOverlapId;\n if (event?.overlapSpecies != null) {\n const { species: _species = [] } = overlapGroups.find(({ id }) => event.overlapSpecies!.id == id) ?? {};\n const species = _species.find(({ to: { id }, toModel }) => (toModel == 'events' || toModel == 'courseevents') && event.id == id);\n if (species) forcedOverlapId = species.id;\n }\n\n if (event.period && periodsMap.size && !periodsMap.has(event.period.id)) {\n throw new Error(`(RS::V3::To::Collections) Course ${event[idKey]} has a period that does not exist`);\n }\n\n const duration = event.preferredDuration ?? event.duration;\n if (!duration) return;\n\n /*\n preferredDuration overrides duration\n */\n const doc: CourseEvent = {\n id: `events.${ id }`,\n // temporary, should be preferred duration only!\n length: duration,\n // optional\n ...event.durationVariance != null && { maxLengthVariance: event.durationVariance },\n ...'weight' in event && { weight: event.weight },\n ...'density' in event && { density: event.density },\n ...event.lockedTimes?.length && { lockedTimes: lockedTimes((event.lockedTimes), options) },\n ...(event.minBreakLength != null) && { minBreakLength: breakLength(event.minBreakLength) },\n ...event.centerOfAttraction && { potentialCenter: parseFloat(event.centerOfAttraction.replace(':', '.')) },\n ...(forcedOverlapId != null) && { forcedOverlapId },\n ...event.period && periodsMap.size && { period: periodsMap.get(event.period?.id) },\n };\n\n const groups = mapGroupReferences(event, options, destructMap);\n if (groups) doc.groups = groups;\n\n const dependencies = _dependencies(event, options);\n if (dependencies)\n Object.assign(doc, dependencies);\n\n if (options.meta) {\n Object.assign(doc, _meta(event, options));\n }\n\n const days = _days(event, settings, options);\n if (days)\n Object.assign(doc, days);\n\n const intervals = _intervals(event, settings, options);\n if (intervals)\n Object.assign(doc, intervals);\n\n if (event.fixedStart && event.start) {\n Object.assign(doc, toDayAndStart(event.start));\n }\n\n ////\n //// filter events based on partialScheduleOptions\n ////\n if (options.partialScheduleOptions) {\n const { includedEvents, omittedEventsHandling } = options.partialScheduleOptions;\n if (includedEvents && !includedEvents.has(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 (event.parked || !event.start || !event.duration) return;\n\n // fix day, start and end\n Object.assign(doc, toDayAndStart(event.start));\n doc.length = event.duration;\n doc.maxLengthVariance = 0;\n\n // fix locations\n doc.dependencies = (event.inLocations ?? [])\n .map(x => {\n const id = typeof x === 'string' ? x : x?.[idKey]?.toString();\n if (!id) return;\n\n const includedLocations = options.partialScheduleOptions?.includedLocations;\n if (includedLocations && !includedLocations.has(id)) return;\n\n return [{ dependency: id }] as AvailableDependency[];\n })\n .filter((x): x is NonNullable<typeof x> => !!x);\n }\n\n }\n }\n\n return doc;\n })\n .filter((x): x is NonNullable<typeof x> => !!x);\n}"],"mappings":";;;;;;;;;;AAoBA,SAAS,cAAe,OAAsC;AAC5D,QAAO;EACL,OAAO,WAAW,OAAO,IAAI,OAAO,OAAO;EAC3C,MAAQ,OAAO,IAAI,OAAO,QAAQ,KAAK;;;AAI3C,+BACE,cACA,gBAAwD,IACxD,UACA,SACA,YACA,8BAAgD,IAAI,OACrC;CACf,MAAMA,QAA+B,QAAQ,SAAS;AAEtD,SAAQ,MAAM,QAAQ,gBAAgB,eAAe,CAAC,eACnD,KAAI,UAAS;EACZ,MAAM,MAAM,MAAM,UAAU,MAAM,MAAM;AACxC,MAAI,CAAC,GAAI;EAET,IAAI;AACJ,MAAI,OAAO,kBAAkB,MAAM;GACjC,MAAM,EAAE,SAAS,WAAW,OAAO,cAAc,MAAM,EAAE,eAAS,MAAM,eAAgB,MAAMC,SAAO;GACrG,MAAM,UAAU,SAAS,MAAM,EAAE,IAAI,EAAE,YAAM,eAAe,WAAW,YAAY,WAAW,mBAAmB,MAAM,MAAMA;AAC7H,OAAI,QAAS,mBAAkB,QAAQ;;AAGzC,MAAI,MAAM,UAAU,WAAW,QAAQ,CAAC,WAAW,IAAI,MAAM,OAAO,IAClE,OAAM,IAAI,MAAM,oCAAoC,MAAM,OAAO;EAGnE,MAAM,WAAW,MAAM,qBAAqB,MAAM;AAClD,MAAI,CAAC,SAAU;EAKf,MAAMC,MAAmB;GACvB,IAAQ,UAAW;GAEnB,QAAQ;GAER,GAAG,MAAM,oBAAoB,QAAY,EAAE,mBAAmB,MAAM;GACpE,GAAG,YAAuB,SAAe,EAAE,QAAmB,MAAM;GACpE,GAAG,aAAuB,SAAe,EAAE,SAAmB,MAAM;GACpE,GAAG,MAAM,aAAa,UAAmB,EAAE,aAAmBC,qBAAa,MAAM,aAAc;GAC/F,GAAI,MAAM,kBAAkB,QAAa,EAAE,gBAAmBC,sBAAY,MAAM;GAChF,GAAG,MAAM,sBAAgC,EAAE,iBAAmB,WAAW,MAAM,mBAAmB,QAAQ,KAAK;GAC/G,GAAI,mBAAmB,QAAkB,EAAE;GAC3C,GAAG,MAAM,UAAU,WAAW,QAAW,EAAE,QAAmB,WAAW,IAAI,MAAM,QAAQ;;EAG7F,MAAM,SAAS,mBAAmB,OAAO,SAAS;AAClD,MAAI,OAAQ,KAAI,SAAS;EAEzB,MAAM,eAAeC,qBAAc,OAAO;AAC1C,MAAI,aACF,QAAO,OAAO,KAAK;AAErB,MAAI,QAAQ,KACV,QAAO,OAAO,KAAKC,aAAM,OAAO;EAGlC,MAAM,OAAOC,aAAM,OAAO,UAAU;AACpC,MAAI,KACF,QAAO,OAAO,KAAK;EAErB,MAAM,YAAYC,kBAAW,OAAO,UAAU;AAC9C,MAAI,UACF,QAAO,OAAO,KAAK;AAErB,MAAI,MAAM,cAAc,MAAM,MAC5B,QAAO,OAAO,KAAK,cAAc,MAAM;AAMzC,MAAI,QAAQ,wBAAwB;GAClC,MAAM,EAAE,gBAAgB,0BAA0B,QAAQ;AAC1D,OAAI,kBAAkB,CAAC,eAAe,IAAI,KAAK;AAE7C,QAAI,yBAAyB,SAAU;AAEvC,QAAI,yBAAyB,UAAU;AAErC,SAAI,MAAM,UAAU,CAAC,MAAM,SAAS,CAAC,MAAM,SAAU;AAGrD,YAAO,OAAO,KAAK,cAAc,MAAM;AACvC,SAAI,SAAS,MAAM;AACnB,SAAI,oBAAoB;AAGxB,SAAI,gBAAgB,MAAM,eAAe,IACtC,KAAI,MAAK;MACR,MAAMP,OAAK,OAAO,MAAM,WAAW,IAAI,IAAI,QAAQ;AACnD,UAAI,CAACA,KAAI;MAET,MAAM,oBAAoB,QAAQ,wBAAwB;AAC1D,UAAI,qBAAqB,CAAC,kBAAkB,IAAIA,MAAK;AAErD,aAAO,CAAC,EAAE,YAAYA;QAEvB,QAAQ,MAAkC,CAAC,CAAC;;;;AAMrD,SAAO;IAER,QAAQ,MAAkC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","names":["idKey: keyof CoreTypes.event","id","doc: CourseEvent","lockedTimes","breakLength","_dependencies","_meta","_days","_intervals"],"sources":["../../../../../src/RS/v3/to/course-events/index.ts"],"sourcesContent":["import moment from 'moment';\n\nimport breakLength from '../break-lengths';\nimport lockedTimes from '../locked-times';\n\nimport { CourseEvent } from '../../types/course-events';\nimport { OutOptions } from '../../types/out-options';\nimport { Individual } from '../../types/individuals';\n\nimport { Types as CoreTypes } from '../../../../core/types';\nimport { Deserialized } from '../../../../core/types';\n\n\nimport { mapGroupReferences } from './groups';\nimport _meta from './meta';\nimport _dependencies from './dependencies';\nimport _days from './days';\nimport _intervals from './intervals';\nimport { AvailableDependency } from '../../types/available-dependencies';\n\nexport function toDayAndStart (start: string | moment.Moment | Date) {\n return {\n start: parseFloat(moment.utc(start).format('HH.mm')),\n day: (moment.utc(start).day() + 6) % 7\n };\n}\n\nexport default function (\n courseEvents: Deserialized<CoreTypes.event>[] | Deserialized<CoreTypes.event>,\n overlapGroups: Deserialized<CoreTypes.overlapGroup>[] = [],\n settings: CoreTypes.divisionSettings,\n options: OutOptions,\n periodsMap: Map<string | undefined, number>,\n destructMap: Map<string | null, Individual> = new Map()\n): CourseEvent[] {\n const idKey: keyof CoreTypes.event = options.idKey ?? 'id';\n\n return (Array.isArray(courseEvents) ? courseEvents : [courseEvents])\n .map(event => {\n const id = (event[idKey] ?? event._id)?.toString();\n if (!id) return;\n\n let forcedOverlapId;\n if (event?.overlapSpecies != null) {\n const { species: _species = [] } = overlapGroups.find(({ id }) => event.overlapSpecies!.id == id) ?? {};\n const species = _species.find(({ to: { id }, toModel }) => (toModel == 'events' || toModel == 'courseevents') && event.id == id);\n if (species) forcedOverlapId = species.id;\n }\n\n if (event.period && periodsMap.size && !periodsMap.has(event.period.id)) {\n throw new Error(`(RS::V3::To::Collections) Course ${event[idKey]} has a period that does not exist`);\n }\n\n const duration = event.preferredDuration ?? event.duration;\n if (!duration) return;\n\n /*\n preferredDuration overrides duration\n */\n const doc: CourseEvent = {\n id: `events.${ id }`,\n // temporary, should be preferred duration only!\n length: duration,\n // optional\n ...event.durationVariance != null && { maxLengthVariance: event.durationVariance },\n ...'weight' in event && { weight: event.weight },\n ...'density' in event && { density: event.density },\n ...event.lockedTimes?.length && { lockedTimes: lockedTimes((event.lockedTimes), options) },\n ...(event.minBreakLength != null) && { minBreakLength: breakLength(event.minBreakLength) },\n ...event.centerOfAttraction && { potentialCenter: parseFloat(event.centerOfAttraction.replace(':', '.')) },\n ...(forcedOverlapId != null) && { forcedOverlapId },\n ...event.period && periodsMap.size && { period: periodsMap.get(event.period?.id) },\n };\n\n const groups = mapGroupReferences(event, options, destructMap);\n if (groups) doc.groups = groups;\n\n const dependencies = _dependencies(event, options);\n if (dependencies)\n Object.assign(doc, dependencies);\n\n if (options.meta) {\n Object.assign(doc, _meta(event, options));\n }\n\n const days = _days(event, settings, options);\n if (days)\n Object.assign(doc, days);\n\n const intervals = _intervals(event, settings, options);\n if (intervals)\n Object.assign(doc, intervals);\n\n if (event.fixedStart && event.start) {\n Object.assign(doc, toDayAndStart(event.start));\n }\n\n ////\n //// filter events based on partialScheduleOptions\n ////\n if (options.partialScheduleOptions) {\n const { includedEvents, omittedEventsHandling } = options.partialScheduleOptions;\n if (includedEvents && !includedEvents.has(doc.id)) {\n\n if (omittedEventsHandling == 'ignore') return;\n\n if (omittedEventsHandling == 'freeze') {\n // must not be parked and have a start and duration to be frozen, otherwise it's ignored\n if (event.parked || !event.start || !event.duration) return;\n\n // fix day, start and end\n Object.assign(doc, toDayAndStart(event.start));\n doc.length = event.duration;\n doc.maxLengthVariance = 0;\n\n // fix locations\n doc.dependencies = (event.inLocations ?? [])\n .map(x => {\n const id = typeof x === 'string' ? x : x?.[idKey]?.toString();\n if (!id) return;\n\n const includedLocations = options.partialScheduleOptions?.includedLocations;\n if (includedLocations && !includedLocations.has(id)) return;\n\n return [{ dependency: id }] as AvailableDependency[];\n })\n .filter((x): x is NonNullable<typeof x> => !!x);\n }\n\n }\n }\n\n return doc;\n })\n .filter((x): x is NonNullable<typeof x> => !!x);\n}"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import intervals_default from "./intervals.js";
2
+ import { toDayAndStart } from "./course-events/index.js";
2
3
  import moment from "moment";
3
4
  import { pick } from "lodash-es";
4
5
  import { nanoid } from "nanoid";
@@ -46,8 +47,8 @@ var dynamic_locked_times_default = (docs, settings, options, set, destructMap) =
46
47
  const day = days?.length == 1 ? days[0] : void 0;
47
48
  const groups = mapCoalescedReferences(coalesced, options, destructMap);
48
49
  const distributionKey = lockedTime.type == "COMPLEMENTARY_HOURS" ? "COMPLEMENTARY_HOURS." + lockedTime.tags?.at(0)?.value : void 0;
49
- return acc$1.concat({
50
- id: `${group.lunch == null ? "virtual" : "lockedtimes"}.${id}`,
50
+ const doc = {
51
+ id: `${group.lunch == null ? "virtual" : "lockedTimes"}.${id}`,
51
52
  groups: [...new Set(groups.filter(Boolean))],
52
53
  dependencies: [...new Set(coalesced.filter((x) => x.toModel == "locations").map(({ to }) => to[idKey]?.toString()).filter(Boolean))].map((x) => [x]),
53
54
  length: duration,
@@ -57,7 +58,20 @@ var dynamic_locked_times_default = (docs, settings, options, set, destructMap) =
57
58
  ...days && { days },
58
59
  ...day && { day },
59
60
  ...durationVariance != null && { maxLengthVariance: durationVariance }
60
- });
61
+ };
62
+ if (options.partialScheduleOptions) {
63
+ const { includedEvents, omittedEventsHandling } = options.partialScheduleOptions;
64
+ if (includedEvents && !includedEvents.has(doc.id)) {
65
+ if (omittedEventsHandling == "ignore") return acc$1;
66
+ if (omittedEventsHandling == "freeze") {
67
+ if (lockedTime.parked || !lockedTime.start || !lockedTime.duration) return acc$1;
68
+ Object.assign(doc, toDayAndStart(lockedTime.start));
69
+ doc.length = lockedTime.duration;
70
+ doc.maxLengthVariance = 0;
71
+ }
72
+ }
73
+ }
74
+ return acc$1.concat(doc);
61
75
  }, []));
62
76
  }, []).flat().filter(Boolean);
63
77
  };
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-locked-times.js","names":["idKey: 'id' | '_id' | 'ids'","lunch","id: string","acc","_intervals"],"sources":["../../../../src/RS/v3/to/dynamic-locked-times.ts"],"sourcesContent":["import moment from 'moment';\nimport { nanoid } from 'nanoid';\nimport { pick } from 'lodash-es';\n\nimport { OutOptions } from '../types/out-options';\nimport { CourseEvent } from '../types/course-events';\nimport { Individual } from '../types/individuals';\n\nimport _intervals from './intervals';\n\nimport { Types as CoreTypes } from '../../../core/types';\nimport { Deserialized } from '../../../core/types';\n\nfunction mapCoalescedReferences (\n coalesced: Deserialized<CoreTypes.lockedTime>['coalesced'],\n options: OutOptions,\n destructMap?: Map<string | null, Individual>\n) {\n const idKey = options.idKey || 'id';\n\n if (!coalesced) return [];\n\n const teachers = coalesced.filter(x => x.toModel == 'teachers');\n const groups = coalesced.filter(x => x.toModel == 'groups');\n const participants = coalesced.filter(x => x.toModel == 'persons');\n\n const teacherIds = teachers .map(({ to }) => to[idKey]).filter((x): x is NonNullable<typeof x> => !!x)\n .map(x => ({ individuals: ['teachers.individuals.' + x.toString()] }));\n const groupIds = groups .map(({ to }) => to[idKey]).filter((x): x is NonNullable<typeof x> => !!x)\n .map(x => 'groups.' + x.toString());\n const participantIds = participants.map(({ to }) => to[idKey]).filter((x): x is NonNullable<typeof x> => !!x)\n .map(x => ({ individuals: ['persons.' + x.toString()] }));\n\n\n const out = [...new Set(teacherIds), ...new Set(groupIds), ...new Set(participantIds)].map(x => [x]);\n return out;\n}\n\nexport default (\n docs: (Deserialized<CoreTypes.group> | Deserialized<CoreTypes.teacher>)[],\n settings: Deserialized<CoreTypes.divisionSettings>,\n options: OutOptions,\n set: Set<string>,\n destructMap?: Map<string | null, Individual>\n) => {\n //let docs: SourceLockedTime[] = (Array.isArray(lockedTimes) ? lockedTimes : [lockedTimes]);\n const idKey: 'id' | '_id' | 'ids' = (options.idKey ?? 'id');\n\n return docs\n .filter(x => !!x)\n .reduce((acc: CourseEvent[], group): CourseEvent[] => {\n let lunch = group.lunch;\n if (lunch == null) {\n lunch = settings.defaultLunch?.map(lunch => ({ ...lunch, coalesced: [{ to: pick(group, idKey), toModel: '' }] }));\n }\n\n if ('complementaryHours' in group) {\n lunch = lunch?.concat(group.complementaryHours ?? []);\n }\n\n if (lunch == null)\n return acc;\n\n return acc.concat(\n lunch.reduce((acc: CourseEvent[], lockedTime) => {\n\n const { _id, intervals, duration, durationVariance, coalesced } = lockedTime;\n\n const id: string = (lockedTime[idKey as keyof CoreTypes.lockedTime] || _id)?.toString() ?? nanoid();\n\n if (set.has(id))\n return acc;\n\n set.add(id);\n\n if (duration == null)\n throw new Error('(RS::V3::To::DynamicLockedTimes) Length of a locked time is null');\n\n if (duration < 5)\n throw new Error('(RS::V3::To::DynamicLockedTimes) Length of a locked time is less than 5 min');\n\n if (!coalesced)\n throw new Error('(RS::V3::To::DynamicLockedTimes) Length of a locked time is less than 5 min');\n /*\n find the day(s) the events should be placed on\n */\n\n let days = intervals?.length\n ? intervals.map(({ start }) => (moment(start).day() + 6) % 7)\n : undefined;\n if (days)\n days = [...new Set(days)];\n const day = days?.length == 1 ? days[0] : undefined;\n\n const groups = mapCoalescedReferences(coalesced, options, destructMap);\n\n const distributionKey = lockedTime.type == 'COMPLEMENTARY_HOURS'\n ? 'COMPLEMENTARY_HOURS.' + lockedTime.tags?.at(0)?.value\n : undefined;\n\n return acc.concat({\n id: `${ group.lunch == null ? 'virtual' : 'lockedtimes' }.${ id }`,\n groups: [...new Set(groups.filter(Boolean))],\n dependencies: [...new Set(coalesced.filter(x => x.toModel == 'locations').map(({ to }) => to[idKey]?.toString()!)\n .filter(Boolean))].map(x => [x]),\n length: duration,\n minBreakLength: false,\n intervals: intervals?.length ? _intervals(intervals, settings) : undefined,\n distributionKey,\n ...days && { days },\n ...day && { day },\n ...durationVariance != null && { maxLengthVariance: durationVariance },\n } satisfies CourseEvent);\n }, []));\n\n }, [])\n .flat()\n .filter(Boolean);\n};"],"mappings":";;;;;;AAaA,SAAS,uBACP,WACA,SACA,aACA;CACA,MAAM,QAAQ,QAAQ,SAAS;AAE/B,KAAI,CAAC,UAAW,QAAO;CAEvB,MAAM,WAAe,UAAU,QAAO,MAAK,EAAE,WAAW;CACxD,MAAM,SAAe,UAAU,QAAO,MAAK,EAAE,WAAW;CACxD,MAAM,eAAe,UAAU,QAAO,MAAK,EAAE,WAAW;CAExD,MAAM,aAAiB,SAAa,KAAK,EAAE,SAAS,GAAG,QAAQ,QAAQ,MAAkC,CAAC,CAAC,GACxG,KAAI,OAAM,EAAE,aAAa,CAAC,0BAA0B,EAAE;CACzD,MAAM,WAAiB,OAAa,KAAK,EAAE,SAAS,GAAG,QAAQ,QAAQ,MAAkC,CAAC,CAAC,GACxG,KAAI,MAAK,YAAY,EAAE;CAC1B,MAAM,iBAAiB,aAAa,KAAK,EAAE,SAAS,GAAG,QAAQ,QAAQ,MAAkC,CAAC,CAAC,GACxG,KAAI,OAAM,EAAE,aAAa,CAAC,aAAc,EAAE;CAG7C,MAAM,MAAM;EAAC,GAAG,IAAI,IAAI;EAAa,GAAG,IAAI,IAAI;EAAW,GAAG,IAAI,IAAI;GAAiB,KAAI,MAAK,CAAC;AACjG,QAAO;;AAGT,oCACE,MACA,UACA,SACA,KACA,gBACG;CAEH,MAAMA,QAA+B,QAAQ,SAAS;AAEtD,QAAO,KACJ,QAAO,MAAK,CAAC,CAAC,GACd,QAAQ,KAAoB,UAAyB;EACpD,IAAI,QAAQ,MAAM;AAClB,MAAI,SAAS,KACX,SAAQ,SAAS,cAAc,KAAI,aAAU;GAAE,GAAGC;GAAO,WAAW,CAAC;IAAE,IAAI,KAAK,OAAO;IAAQ,SAAS;;;AAG1G,MAAI,wBAAwB,MAC1B,SAAQ,OAAO,OAAO,MAAM,sBAAsB;AAGpD,MAAI,SAAS,KACX,QAAO;AAET,SAAO,IAAI,OACT,MAAM,QAAQ,OAAoB,eAAe;GAE/C,MAAM,EAAE,KAAK,WAAW,UAAU,kBAAkB,cAAc;GAElE,MAAMC,MAAc,WAAW,UAAwC,MAAM,cAAc;AAE3F,OAAI,IAAI,IAAI,IACV,QAAOC;AAET,OAAI,IAAI;AAER,OAAI,YAAY,KACd,OAAM,IAAI,MAAM;AAElB,OAAI,WAAW,EACb,OAAM,IAAI,MAAM;AAElB,OAAI,CAAC,UACH,OAAM,IAAI,MAAM;GAKlB,IAAI,OAAO,WAAW,SAClB,UAAU,KAAK,EAAE,aAAa,OAAO,OAAO,QAAQ,KAAK,KACzD;AACJ,OAAI,KACF,QAAO,CAAC,GAAG,IAAI,IAAI;GACrB,MAAM,MAAM,MAAM,UAAU,IAAI,KAAK,KAAK;GAE1C,MAAM,SAAS,uBAAuB,WAAW,SAAS;GAE1D,MAAM,kBAAkB,WAAW,QAAQ,wBACvC,yBAAyB,WAAW,MAAM,GAAG,IAAI,QACjD;AAEJ,UAAOA,MAAI,OAAO;IAChB,IAAc,GAAI,MAAM,SAAS,OAAO,YAAY,cAAe,GAAI;IACvE,QAAc,CAAC,GAAG,IAAI,IAAI,OAAO,OAAO;IACxC,cAAc,CAAC,GAAG,IAAI,IAAI,UAAU,QAAO,MAAK,EAAE,WAAW,aAAa,KAAK,EAAE,SAAS,GAAG,QAAQ,YAClG,OAAO,WAAW,KAAI,MAAK,CAAC;IAC/B,QAAgB;IAChB,gBAAgB;IAChB,WAAgB,WAAW,SAASC,kBAAW,WAAW,YAAY;IACtE;IACA,GAAG,QAAQ,EAAE;IACb,GAAG,OAAO,EAAE;IACZ,GAAG,oBAAoB,QAAS,EAAE,mBAAmB;;KAEtD;IAEJ,IACF,OACA,OAAO"}
1
+ {"version":3,"file":"dynamic-locked-times.js","names":["idKey: 'id' | '_id' | 'ids'","lunch","id: string","acc","doc: CourseEvent","_intervals"],"sources":["../../../../src/RS/v3/to/dynamic-locked-times.ts"],"sourcesContent":["import moment from 'moment';\nimport { nanoid } from 'nanoid';\nimport { pick } from 'lodash-es';\n\nimport { OutOptions } from '../types/out-options';\nimport { CourseEvent } from '../types/course-events';\nimport { Individual } from '../types/individuals';\n\nimport _intervals from './intervals';\n\nimport { Types as CoreTypes } from '../../../core/types';\nimport { Deserialized } from '../../../core/types';\nimport { toDayAndStart } from './course-events';\n\nfunction mapCoalescedReferences (\n coalesced: Deserialized<CoreTypes.lockedTime>['coalesced'],\n options: OutOptions,\n destructMap?: Map<string | null, Individual>\n) {\n const idKey = options.idKey || 'id';\n\n if (!coalesced) return [];\n\n const teachers = coalesced.filter(x => x.toModel == 'teachers');\n const groups = coalesced.filter(x => x.toModel == 'groups');\n const participants = coalesced.filter(x => x.toModel == 'persons');\n\n const teacherIds = teachers .map(({ to }) => to[idKey]).filter((x): x is NonNullable<typeof x> => !!x)\n .map(x => ({ individuals: ['teachers.individuals.' + x.toString()] }));\n const groupIds = groups .map(({ to }) => to[idKey]).filter((x): x is NonNullable<typeof x> => !!x)\n .map(x => 'groups.' + x.toString());\n const participantIds = participants.map(({ to }) => to[idKey]).filter((x): x is NonNullable<typeof x> => !!x)\n .map(x => ({ individuals: ['persons.' + x.toString()] }));\n\n\n const out = [...new Set(teacherIds), ...new Set(groupIds), ...new Set(participantIds)].map(x => [x]);\n return out;\n}\n\nexport default (\n docs: (Deserialized<CoreTypes.group> | Deserialized<CoreTypes.teacher>)[],\n settings: Deserialized<CoreTypes.divisionSettings>,\n options: OutOptions,\n set: Set<string>,\n destructMap?: Map<string | null, Individual>\n) => {\n //let docs: SourceLockedTime[] = (Array.isArray(lockedTimes) ? lockedTimes : [lockedTimes]);\n const idKey: 'id' | '_id' | 'ids' = (options.idKey ?? 'id');\n\n return docs\n .filter(x => !!x)\n .reduce((acc: CourseEvent[], group): CourseEvent[] => {\n let lunch = group.lunch;\n if (lunch == null) {\n lunch = settings.defaultLunch?.map(lunch => ({ ...lunch, coalesced: [{ to: pick(group, idKey), toModel: '' }] }));\n }\n\n if ('complementaryHours' in group) {\n lunch = lunch?.concat(group.complementaryHours ?? []);\n }\n\n if (lunch == null)\n return acc;\n\n return acc.concat(\n lunch.reduce((acc: CourseEvent[], lockedTime) => {\n\n const { _id, intervals, duration, durationVariance, coalesced } = lockedTime;\n\n const id: string = (lockedTime[idKey as keyof CoreTypes.lockedTime] || _id)?.toString() ?? nanoid();\n\n if (set.has(id))\n return acc;\n\n set.add(id);\n\n if (duration == null)\n throw new Error('(RS::V3::To::DynamicLockedTimes) Length of a locked time is null');\n\n if (duration < 5)\n throw new Error('(RS::V3::To::DynamicLockedTimes) Length of a locked time is less than 5 min');\n\n if (!coalesced)\n throw new Error('(RS::V3::To::DynamicLockedTimes) Length of a locked time is less than 5 min');\n /*\n find the day(s) the events should be placed on\n */\n\n let days = intervals?.length\n ? intervals.map(({ start }) => (moment(start).day() + 6) % 7)\n : undefined;\n if (days)\n days = [...new Set(days)];\n const day = days?.length == 1 ? days[0] : undefined;\n\n const groups = mapCoalescedReferences(coalesced, options, destructMap);\n\n const distributionKey = lockedTime.type == 'COMPLEMENTARY_HOURS'\n ? 'COMPLEMENTARY_HOURS.' + lockedTime.tags?.at(0)?.value\n : undefined;\n\n\n const doc: CourseEvent = {\n id: `${ group.lunch == null ? 'virtual' : 'lockedTimes' }.${ id }`,\n groups: [...new Set(groups.filter(Boolean))],\n dependencies: [...new Set(coalesced.filter(x => x.toModel == 'locations').map(({ to }) => to[idKey]?.toString()!)\n .filter(Boolean))].map(x => [x]),\n length: duration,\n minBreakLength: false,\n intervals: intervals?.length ? _intervals(intervals, settings) : undefined,\n distributionKey,\n ...days && { days },\n ...day && { day },\n ...durationVariance != null && { maxLengthVariance: durationVariance },\n };\n\n\n\n ////\n //// filter events based on partialScheduleOptions\n ////\n if (options.partialScheduleOptions) {\n const { includedEvents, omittedEventsHandling } = options.partialScheduleOptions;\n if (includedEvents && !includedEvents.has(doc.id)) {\n\n if (omittedEventsHandling == 'ignore') return acc;\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 acc;\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 // fix locations\n // > locations are always fixed for locked times\n }\n }\n }\n\n return acc.concat(doc);\n }, []));\n\n }, [])\n .flat()\n .filter(Boolean);\n};"],"mappings":"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"}
@@ -53,8 +53,7 @@ function validateGroup(groups) {
53
53
  const memberIds = [];
54
54
  for (const member of group.members) {
55
55
  const id = typeof member === "object" && "id" in member ? member.id : member;
56
- if (id && isObjectIdOrHexString(id)) memberIds.push(typeof id === "string" ? id : id.toString());
57
- if (typeof id === "string") memberIds.push(id);
56
+ memberIds.push(id.toString());
58
57
  }
59
58
  if (memberIds.length === 0) return null;
60
59
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"schedules.js","names":["memberIds: string[]"],"sources":["../../../src/vKlass/to/schedules.ts"],"sourcesContent":["import moment from 'moment';\nimport { isObjectIdOrHexString, Types } from 'mongoose';\nimport XLSX from 'xlsx';\n\nimport { Types as CoreTypes } from '../../core/types';\n\ntype Schedule = {\n division: CoreTypes.division;\n teachers: CoreTypes.teacher[];\n courses: CoreTypes.course[];\n persons: CoreTypes.person[];\n};\n\nexport default function (schedule: Schedule): XLSX.WorkBook {\n const did = schedule.division.id!;\n if (!did) throw new Error('division id is undefined');\n\n // get start and end dates from division in format date + time format: 2024-08-15 00:00:00\n const startDate = moment.utc(schedule.division.start).format('YYYY-MM-DD HH:mm:ss');\n const endDate = moment.utc(schedule.division.end).format('YYYY-MM-DD HH:mm:ss');\n\n // Map persons by id to SSN\n const personMap = new Map<string, string>();\n schedule.persons.forEach((p) => {\n const ssn = p.SSN?.value;\n const id = p._id?.toString();\n if (ssn && id)\n personMap.set(id, ssn);\n });\n\n const teacherMap = new Map<string, string>();\n schedule.teachers.forEach((t) => {\n const signature = t.signature;\n const id = t.id?.toString();\n if (signature && id)\n teacherMap.set(id, signature);\n });\n\n\n\n const courses = schedule.courses.map((course) => {\n const group = validateGroup(course.groups);\n if (!group) return null;\n\n const teacherId = getTeacherId(course.teachers?.at(0)?.to);\n const teacherSignature = teacherId ? teacherMap.get(teacherId) : '';\n\n const courseName = course.displayName || '';\n const subject = course.subject || '';\n\n const membersSSNs = group.members.map((id) => {\n return personMap.get(id);\n }).filter((ssn) => !!ssn);\n\n if (membersSSNs.length === 0) return null;\n\n return membersSSNs.map((ssn) => ({\n Personnummer: ssn,\n Kurskod: subject,\n Benämning: courseName,\n Undervisningsgrupp: group.displayName || '',\n Lärarsignatur: teacherSignature,\n Poäng: 0,\n Startdatum: startDate,\n Slutdatum: endDate\n }));\n\n }).flat().filter(x => x !== null);\n\n const wb = XLSX.utils.book_new();\n XLSX.utils.book_append_sheet(wb, XLSX.utils.json_to_sheet(courses), 'Kurser');\n\n return wb;\n}\n\n// Validate that the group is valid and has at least one member\nfunction validateGroup (groups: CoreTypes.course['groups']): {\n members: string[], // Array of member IDs\n displayName?: string\n} | null {\n const group = groups?.at(0)?.to;\n\n if (!(typeof group === 'object') || !('members' in group)) return null;\n\n if (!group?.members || group.members.length === 0) return null;\n\n const memberIds: string[] = [];\n for (const member of group.members) {\n const id = (typeof member === 'object' && 'id' in member) ? member.id : member;\n if (id && isObjectIdOrHexString(id)) {\n memberIds.push(typeof id === 'string' ? id : (id as unknown as Types.ObjectId).toString());\n }\n if (typeof id === 'string') {\n memberIds.push(id);\n }\n }\n if (memberIds.length === 0) return null;\n\n return { members: group.members as string[], displayName: group.displayName };\n}\n\nfunction getTeacherId (teacher: CoreTypes.teacher | Types.ObjectId | string | undefined | null): string | null {\n if (!teacher) return null;\n if (typeof teacher === 'string') return teacher;\n if (isObjectIdOrHexString(teacher)) return (teacher as Types.ObjectId).toString();\n if (typeof teacher === 'object' && 'id' in teacher && teacher.id) {\n return typeof teacher.id === 'string' ? teacher.id : teacher.id.toString();\n }\n return null;\n}"],"mappings":";;;;;AAaA,2BAAyB,UAAmC;CAC1D,MAAM,MAAM,SAAS,SAAS;AAC9B,KAAI,CAAC,IAAK,OAAM,IAAI,MAAM;CAG1B,MAAM,YAAY,OAAO,IAAI,SAAS,SAAS,OAAO,OAAO;CAC7D,MAAM,UAAU,OAAO,IAAI,SAAS,SAAS,KAAK,OAAO;CAGzD,MAAM,4BAAY,IAAI;AACtB,UAAS,QAAQ,SAAS,MAAM;EAC9B,MAAM,MAAM,EAAE,KAAK;EACnB,MAAM,KAAK,EAAE,KAAK;AAClB,MAAI,OAAO,GACT,WAAU,IAAI,IAAI;;CAGtB,MAAM,6BAAa,IAAI;AACvB,UAAS,SAAS,SAAS,MAAM;EAC/B,MAAM,YAAY,EAAE;EACpB,MAAM,KAAK,EAAE,IAAI;AACjB,MAAI,aAAa,GACf,YAAW,IAAI,IAAI;;CAKvB,MAAM,UAAU,SAAS,QAAQ,KAAK,WAAW;EAC/C,MAAM,QAAQ,cAAc,OAAO;AACnC,MAAI,CAAC,MAAO,QAAO;EAEnB,MAAM,YAAY,aAAa,OAAO,UAAU,GAAG,IAAI;EACvD,MAAM,mBAAmB,YAAY,WAAW,IAAI,aAAa;EAEjE,MAAM,aAAa,OAAO,eAAe;EACzC,MAAM,UAAU,OAAO,WAAW;EAElC,MAAM,cAAc,MAAM,QAAQ,KAAK,OAAO;AAC5C,UAAO,UAAU,IAAI;KACpB,QAAQ,QAAQ,CAAC,CAAC;AAErB,MAAI,YAAY,WAAW,EAAG,QAAO;AAErC,SAAO,YAAY,KAAK,SAAS;GAC/B,cAAoB;GACpB,SAAoB;GACpB,WAAoB;GACpB,oBAAoB,MAAM,eAAe;GACzC,eAAoB;GACpB,OAAoB;GACpB,YAAoB;GACpB,WAAoB;;IAGrB,OAAO,QAAO,MAAK,MAAM;CAE5B,MAAM,KAAK,KAAK,MAAM;AACtB,MAAK,MAAM,kBAAkB,IAAI,KAAK,MAAM,cAAc,UAAU;AAEpE,QAAO;;AAIT,SAAS,cAAe,QAGf;CACP,MAAM,QAAQ,QAAQ,GAAG,IAAI;AAE7B,KAAI,EAAE,OAAO,UAAU,aAAa,EAAE,aAAa,OAAQ,QAAO;AAElE,KAAI,CAAC,OAAO,WAAW,MAAM,QAAQ,WAAW,EAAG,QAAO;CAE1D,MAAMA,YAAsB;AAC5B,MAAK,MAAM,UAAU,MAAM,SAAS;EAClC,MAAM,KAAM,OAAO,WAAW,YAAY,QAAQ,SAAU,OAAO,KAAK;AACxE,MAAI,MAAM,sBAAsB,IAC9B,WAAU,KAAK,OAAO,OAAO,WAAW,KAAM,GAAiC;AAEjF,MAAI,OAAO,OAAO,SAChB,WAAU,KAAK;;AAGnB,KAAI,UAAU,WAAW,EAAG,QAAO;AAEnC,QAAO;EAAE,SAAS,MAAM;EAAqB,aAAa,MAAM;;;AAGlE,SAAS,aAAc,SAAwF;AAC7G,KAAI,CAAC,QAAS,QAAO;AACrB,KAAI,OAAO,YAAY,SAAU,QAAO;AACxC,KAAI,sBAAsB,SAAU,QAAQ,QAA2B;AACvE,KAAI,OAAO,YAAY,YAAY,QAAQ,WAAW,QAAQ,GAC5D,QAAO,OAAO,QAAQ,OAAO,WAAW,QAAQ,KAAK,QAAQ,GAAG;AAElE,QAAO"}
1
+ {"version":3,"file":"schedules.js","names":["memberIds: string[]"],"sources":["../../../src/vKlass/to/schedules.ts"],"sourcesContent":["import moment from 'moment';\nimport { isObjectIdOrHexString, Types } from 'mongoose';\nimport XLSX from 'xlsx';\n\nimport { Types as CoreTypes } from '../../core/types';\n\ntype Schedule = {\n division: CoreTypes.division;\n teachers: CoreTypes.teacher[];\n courses: CoreTypes.course[];\n persons: CoreTypes.person[];\n};\n\nexport default function (schedule: Schedule): XLSX.WorkBook {\n const did = schedule.division.id!;\n if (!did) throw new Error('division id is undefined');\n\n // get start and end dates from division in format date + time format: 2024-08-15 00:00:00\n const startDate = moment.utc(schedule.division.start).format('YYYY-MM-DD HH:mm:ss');\n const endDate = moment.utc(schedule.division.end).format('YYYY-MM-DD HH:mm:ss');\n\n // Map persons by id to SSN\n const personMap = new Map<string, string>();\n schedule.persons.forEach((p) => {\n const ssn = p.SSN?.value;\n const id = p._id?.toString();\n if (ssn && id)\n personMap.set(id, ssn);\n });\n\n const teacherMap = new Map<string, string>();\n schedule.teachers.forEach((t) => {\n const signature = t.signature;\n const id = t.id?.toString();\n if (signature && id)\n teacherMap.set(id, signature);\n });\n\n\n\n const courses = schedule.courses.map((course) => {\n const group = validateGroup(course.groups);\n if (!group) return null;\n\n const teacherId = getTeacherId(course.teachers?.at(0)?.to);\n const teacherSignature = teacherId ? teacherMap.get(teacherId) : '';\n\n const courseName = course.displayName || '';\n const subject = course.subject || '';\n\n const membersSSNs = group.members.map((id) => {\n return personMap.get(id);\n }).filter((ssn) => !!ssn);\n\n if (membersSSNs.length === 0) return null;\n\n return membersSSNs.map((ssn) => ({\n Personnummer: ssn,\n Kurskod: subject,\n Benämning: courseName,\n Undervisningsgrupp: group.displayName || '',\n Lärarsignatur: teacherSignature,\n Poäng: 0,\n Startdatum: startDate,\n Slutdatum: endDate\n }));\n\n }).flat().filter(x => x !== null);\n\n const wb = XLSX.utils.book_new();\n XLSX.utils.book_append_sheet(wb, XLSX.utils.json_to_sheet(courses), 'Kurser');\n\n return wb;\n}\n\n// Validate that the group is valid and has at least one member\nfunction validateGroup (groups: CoreTypes.course['groups']): {\n members: string[], // Array of member IDs\n displayName?: string\n} | null {\n const group = groups?.at(0)?.to;\n\n if (!(typeof group === 'object') || !('members' in group)) return null;\n\n if (!group?.members || group.members.length === 0) return null;\n\n const memberIds: string[] = [];\n for (const member of group.members) {\n const id = (typeof member === 'object' && 'id' in member) ? member.id : member;\n memberIds.push((id as unknown as (Types.ObjectId | string)).toString());\n }\n if (memberIds.length === 0) return null;\n\n return { members: group.members as string[], displayName: group.displayName };\n}\n\nfunction getTeacherId (teacher: CoreTypes.teacher | Types.ObjectId | string | undefined | null): string | null {\n if (!teacher) return null;\n if (typeof teacher === 'string') return teacher;\n if (isObjectIdOrHexString(teacher)) return (teacher as Types.ObjectId).toString();\n if (typeof teacher === 'object' && 'id' in teacher && teacher.id) {\n return typeof teacher.id === 'string' ? teacher.id : teacher.id.toString();\n }\n return null;\n}"],"mappings":";;;;;AAaA,2BAAyB,UAAmC;CAC1D,MAAM,MAAM,SAAS,SAAS;AAC9B,KAAI,CAAC,IAAK,OAAM,IAAI,MAAM;CAG1B,MAAM,YAAY,OAAO,IAAI,SAAS,SAAS,OAAO,OAAO;CAC7D,MAAM,UAAU,OAAO,IAAI,SAAS,SAAS,KAAK,OAAO;CAGzD,MAAM,4BAAY,IAAI;AACtB,UAAS,QAAQ,SAAS,MAAM;EAC9B,MAAM,MAAM,EAAE,KAAK;EACnB,MAAM,KAAK,EAAE,KAAK;AAClB,MAAI,OAAO,GACT,WAAU,IAAI,IAAI;;CAGtB,MAAM,6BAAa,IAAI;AACvB,UAAS,SAAS,SAAS,MAAM;EAC/B,MAAM,YAAY,EAAE;EACpB,MAAM,KAAK,EAAE,IAAI;AACjB,MAAI,aAAa,GACf,YAAW,IAAI,IAAI;;CAKvB,MAAM,UAAU,SAAS,QAAQ,KAAK,WAAW;EAC/C,MAAM,QAAQ,cAAc,OAAO;AACnC,MAAI,CAAC,MAAO,QAAO;EAEnB,MAAM,YAAY,aAAa,OAAO,UAAU,GAAG,IAAI;EACvD,MAAM,mBAAmB,YAAY,WAAW,IAAI,aAAa;EAEjE,MAAM,aAAa,OAAO,eAAe;EACzC,MAAM,UAAU,OAAO,WAAW;EAElC,MAAM,cAAc,MAAM,QAAQ,KAAK,OAAO;AAC5C,UAAO,UAAU,IAAI;KACpB,QAAQ,QAAQ,CAAC,CAAC;AAErB,MAAI,YAAY,WAAW,EAAG,QAAO;AAErC,SAAO,YAAY,KAAK,SAAS;GAC/B,cAAoB;GACpB,SAAoB;GACpB,WAAoB;GACpB,oBAAoB,MAAM,eAAe;GACzC,eAAoB;GACpB,OAAoB;GACpB,YAAoB;GACpB,WAAoB;;IAGrB,OAAO,QAAO,MAAK,MAAM;CAE5B,MAAM,KAAK,KAAK,MAAM;AACtB,MAAK,MAAM,kBAAkB,IAAI,KAAK,MAAM,cAAc,UAAU;AAEpE,QAAO;;AAIT,SAAS,cAAe,QAGf;CACP,MAAM,QAAQ,QAAQ,GAAG,IAAI;AAE7B,KAAI,EAAE,OAAO,UAAU,aAAa,EAAE,aAAa,OAAQ,QAAO;AAElE,KAAI,CAAC,OAAO,WAAW,MAAM,QAAQ,WAAW,EAAG,QAAO;CAE1D,MAAMA,YAAsB;AAC5B,MAAK,MAAM,UAAU,MAAM,SAAS;EAClC,MAAM,KAAM,OAAO,WAAW,YAAY,QAAQ,SAAU,OAAO,KAAK;AACxE,YAAU,KAAM,GAA4C;;AAE9D,KAAI,UAAU,WAAW,EAAG,QAAO;AAEnC,QAAO;EAAE,SAAS,MAAM;EAAqB,aAAa,MAAM;;;AAGlE,SAAS,aAAc,SAAwF;AAC7G,KAAI,CAAC,QAAS,QAAO;AACrB,KAAI,OAAO,YAAY,SAAU,QAAO;AACxC,KAAI,sBAAsB,SAAU,QAAQ,QAA2B;AACvE,KAAI,OAAO,YAAY,YAAY,QAAQ,WAAW,QAAQ,GAC5D,QAAO,OAAO,QAAQ,OAAO,WAAW,QAAQ,KAAK,QAAQ,GAAG;AAElE,QAAO"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@royalschedule/maps",
3
3
  "description": "",
4
- "version": "3.3.4",
4
+ "version": "3.3.6",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "type": "module",
@@ -11,22 +11,23 @@
11
11
  "scripts": {
12
12
  "test": "node dist/index.js",
13
13
  "build": "tsdown",
14
- "dev_Admentum": "ts-node tests/Admentum/index.ts",
15
- "dev_SchoolSoft_api": "ts-node tests/SchoolSoft/api/index.ts",
16
- "dev_SchoolSoft_file_from": "ts-node tests/SchoolSoft/file/from/index.ts",
17
- "dev_SchoolSoft_file_to": "ts-node tests/SchoolSoft/file/to/index.ts",
18
- "dev_Quiculum_file_to": "ts-node tests/Quiculum/file/to/index.ts",
19
- "dev_vKlass": "ts-node tests/vKlass/index.ts",
20
- "dev_PlanDigital": "ts-node tests/PlanDigital/index.ts",
21
- "dev_SS12000": "ts-node tests/SS12000/index.ts",
22
- "dev_Core": "ts-node tests/core/index.ts",
23
- "dev_RS": "ts-node tests/RS/v3.ts",
24
- "dev_IdunSoft": "ts-node tests/IdunSoft/index.ts",
25
- "dev_identify": "ts-node tests/identify/index.ts",
26
- "dev_Excel": "ts-node tests/Excel/index.ts",
27
- "dev_Skola24:mdb": "ts-node tests/Skola24_mdb/index.ts",
28
- "dev_Skola24:txt": "ts-node tests/Skola24_txt/index.ts",
29
- "dev_Schoolity": "ts-node tests/Schoolity/index.ts",
14
+ "dev_Admentum": "tsx tests/Admentum/index.ts",
15
+ "dev_SchoolSoft_api": "tsx tests/SchoolSoft/api/index.ts",
16
+ "dev_SchoolSoft_file_from": "tsx tests/SchoolSoft/file/from/index.ts",
17
+ "dev_SchoolSoft_file_to": "tsx tests/SchoolSoft/file/to/index.ts",
18
+ "dev_Quiculum_file_to": "tsx tests/Quiculum/file/to/index.ts",
19
+ "dev_vKlass_from": "tsx tests/vKlass/file/from/index.ts",
20
+ "dev_vKlass_to": "tsx tests/vKlass/file/to/index.ts",
21
+ "dev_PlanDigital": "tsx tests/PlanDigital/index.ts",
22
+ "dev_SS12000": "tsx tests/SS12000/index.ts",
23
+ "dev_Core": "tsx tests/core/index.ts",
24
+ "dev_RS": "tsx tests/RS/v3.ts",
25
+ "dev_IdunSoft": "tsx tests/IdunSoft/index.ts",
26
+ "dev_identify": "tsx tests/identify/index.ts",
27
+ "dev_Excel": "tsx tests/Excel/index.ts",
28
+ "dev_Skola24:mdb": "tsx tests/Skola24_mdb/index.ts",
29
+ "dev_Skola24:txt": "tsx tests/Skola24_txt/index.ts",
30
+ "dev_Schoolity": "tsx tests/Schoolity/index.ts",
30
31
  "lint": "eslint .",
31
32
  "lint:fix": "eslint . --fix"
32
33
  },
@@ -57,9 +58,8 @@
57
58
  "eslint-plugin-jsdoc": "^54.1.1",
58
59
  "eslint-plugin-unused-imports": "^4.2.0",
59
60
  "nodemon": "^3.1.10",
60
- "ts-node": "^10.9.2",
61
61
  "tsdown": "^0.14.1",
62
- "tslib": "^2.8.1",
62
+ "tsx": "^4.20.5",
63
63
  "typescript": "^5.9.2",
64
64
  "typescript-eslint": "^8.40.0"
65
65
  },