@royalschedule/maps 3.3.6 → 3.3.8

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.
@@ -1,9 +1,9 @@
1
1
  import { Types } from "../../core/v2/types/index.js";
2
- import * as xlsx1 from "xlsx";
2
+ import * as xlsx0 from "xlsx";
3
3
 
4
4
  //#region src/PlanDigital/to/index.d.ts
5
5
  declare class export_default {
6
- static schedules: (courseEvents: Types.course[]) => xlsx1.WorkBook;
6
+ static schedules: (courseEvents: Types.course[]) => xlsx0.WorkBook;
7
7
  }
8
8
  //#endregion
9
9
  export { export_default };
@@ -59,6 +59,12 @@ function course_events_default(courseEvents, overlapGroups = [], settings, optio
59
59
  Object.assign(doc, toDayAndStart(event.start));
60
60
  doc.length = event.duration;
61
61
  doc.maxLengthVariance = 0;
62
+ const numDays = settings.numDays ?? 5;
63
+ doc.days = Array.from({ length: numDays }, (_, i) => i);
64
+ doc.intervals = Array.from({ length: numDays }, () => [{
65
+ beg: 0,
66
+ end: 23.55
67
+ }]);
62
68
  doc.dependencies = (event.inLocations ?? []).map((x) => {
63
69
  const id$1 = typeof x === "string" ? x : x?.[idKey]?.toString();
64
70
  if (!id$1) return;
@@ -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\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
+ {"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 // override intervals and days to not cause conflicts\n const numDays = settings.numDays ?? 5;\n doc.days = Array.from({ length: numDays }, (_, i) => i);\n doc.intervals = Array.from({ length: numDays }, () => [{ beg: 0, end: 23.55 }]);\n\n // fix locations\n doc.dependencies = (event.inLocations ?? [])\n .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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"}
@@ -54,7 +54,7 @@ var dynamic_locked_times_default = (docs, settings, options, set, destructMap) =
54
54
  length: duration,
55
55
  minBreakLength: false,
56
56
  intervals: intervals?.length ? intervals_default(intervals, settings) : void 0,
57
- distributionKey,
57
+ ...distributionKey && { distributionKey },
58
58
  ...days && { days },
59
59
  ...day && { day },
60
60
  ...durationVariance != null && { maxLengthVariance: durationVariance }
@@ -68,6 +68,12 @@ var dynamic_locked_times_default = (docs, settings, options, set, destructMap) =
68
68
  Object.assign(doc, toDayAndStart(lockedTime.start));
69
69
  doc.length = lockedTime.duration;
70
70
  doc.maxLengthVariance = 0;
71
+ const numDays = settings.numDays ?? 5;
72
+ doc.days = Array.from({ length: numDays }, (_, i) => i);
73
+ doc.intervals = Array.from({ length: numDays }, () => [{
74
+ beg: 0,
75
+ end: 23.55
76
+ }]);
71
77
  }
72
78
  }
73
79
  }
@@ -1 +1 @@
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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"}
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 && { 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 // 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 acc.concat(doc);\n }, []));\n\n }, [])\n .flat()\n .filter(Boolean);\n};"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { Types } from "../../../core/v2/types/index.js";
2
- import * as xlsx0 from "xlsx";
2
+ import * as xlsx1 from "xlsx";
3
3
 
4
4
  //#region src/SchoolSoft/file/to/index.d.ts
5
5
  declare class export_default {
@@ -13,7 +13,7 @@ declare class export_default {
13
13
  events: Types.event[];
14
14
  periods: Types.period[];
15
15
  persons: Types.person[];
16
- }) => xlsx0.WorkBook;
16
+ }) => xlsx1.WorkBook;
17
17
  }
18
18
  //#endregion
19
19
  export { export_default };
@@ -23,8 +23,8 @@ function schedules_default(schedule) {
23
23
  const courses = schedule.courses.map((course) => {
24
24
  const group = validateGroup(course.groups);
25
25
  if (!group) return null;
26
- const teacherId = getTeacherId(course.teachers?.at(0)?.to);
27
- const teacherSignature = teacherId ? teacherMap.get(teacherId) : "";
26
+ const teacherIds = course.teachers?.map((t) => getTeacherId(t.to)).filter((id) => id != null) ?? [];
27
+ const teacherSignatures = teacherIds.map((id) => teacherMap.get(id)).filter((sig) => sig != null);
28
28
  const courseName = course.displayName || "";
29
29
  const subject = course.subject || "";
30
30
  const membersSSNs = group.members.map((id) => {
@@ -36,7 +36,7 @@ function schedules_default(schedule) {
36
36
  Kurskod: subject,
37
37
  Benämning: courseName,
38
38
  Undervisningsgrupp: group.displayName || "",
39
- Lärarsignatur: teacherSignature,
39
+ Lärarsignatur: teacherSignatures ? teacherSignatures.join(",") : "",
40
40
  Poäng: 0,
41
41
  Startdatum: startDate,
42
42
  Slutdatum: endDate
@@ -57,7 +57,7 @@ function validateGroup(groups) {
57
57
  }
58
58
  if (memberIds.length === 0) return null;
59
59
  return {
60
- members: group.members,
60
+ members: memberIds,
61
61
  displayName: group.displayName
62
62
  };
63
63
  }
@@ -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 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"}
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 teacherIds = course.teachers?.map((t) => getTeacherId(t.to)).filter((id) => id != null) ?? [];\n const teacherSignatures = teacherIds.map((id) => teacherMap.get(id)).filter((sig) => sig != null);\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: teacherSignatures ? teacherSignatures.join(',') : '',\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: memberIds, 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,aAAa,OAAO,UAAU,KAAK,MAAM,aAAa,EAAE,KAAK,QAAQ,OAAO,MAAM,SAAS;EACjG,MAAM,oBAAoB,WAAW,KAAK,OAAO,WAAW,IAAI,KAAK,QAAQ,QAAQ,OAAO;EAE5F,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,oBAAoB,kBAAkB,KAAK,OAAO;GACtE,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;EAAW,aAAa,MAAM;;;AAGlD,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.6",
4
+ "version": "3.3.8",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "type": "module",