@royalschedule/maps 4.0.1 → 4.0.2

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.
Files changed (66) hide show
  1. package/dist/Excel/v1/from/index.js +2 -2
  2. package/dist/Excel/v1/from/index.js.map +1 -1
  3. package/dist/Excel/v2/from/index.js +2 -2
  4. package/dist/Excel/v2/from/index.js.map +1 -1
  5. package/dist/InfoMentor/to/schedules.js +2 -2
  6. package/dist/InfoMentor/to/schedules.js.map +1 -1
  7. package/dist/PlanDigital/index.d.ts +28 -28
  8. package/dist/RS/make-connected.js +2 -2
  9. package/dist/RS/make-connected.js.map +1 -1
  10. package/dist/SS12000/from/activities.js +36 -0
  11. package/dist/SS12000/from/activities.js.map +1 -0
  12. package/dist/SS12000/from/calendar-events.js +20 -0
  13. package/dist/SS12000/from/calendar-events.js.map +1 -0
  14. package/dist/SS12000/from/duties.js +21 -0
  15. package/dist/SS12000/from/duties.js.map +1 -0
  16. package/dist/SS12000/from/groups.js +23 -0
  17. package/dist/SS12000/from/groups.js.map +1 -0
  18. package/dist/SS12000/from/index.js +24 -0
  19. package/dist/SS12000/from/index.js.map +1 -0
  20. package/dist/SS12000/from/persons.js +43 -0
  21. package/dist/SS12000/from/persons.js.map +1 -0
  22. package/dist/SS12000/from/resources.js +9 -0
  23. package/dist/SS12000/from/resources.js.map +1 -0
  24. package/dist/SS12000/from/rooms.js +18 -0
  25. package/dist/SS12000/from/rooms.js.map +1 -0
  26. package/dist/SS12000/from/syllabuses.js +21 -0
  27. package/dist/SS12000/from/syllabuses.js.map +1 -0
  28. package/dist/SS12000/index.d.ts +36 -0
  29. package/dist/SS12000/index.js +12 -0
  30. package/dist/SS12000/index.js.map +1 -0
  31. package/dist/SS12000/to/activities.js +63 -0
  32. package/dist/SS12000/to/activities.js.map +1 -0
  33. package/dist/SS12000/to/calendar-events.js +53 -0
  34. package/dist/SS12000/to/calendar-events.js.map +1 -0
  35. package/dist/SS12000/to/common.js +25 -0
  36. package/dist/SS12000/to/common.js.map +1 -0
  37. package/dist/SS12000/to/duties.js +45 -0
  38. package/dist/SS12000/to/duties.js.map +1 -0
  39. package/dist/SS12000/to/groups.js +47 -0
  40. package/dist/SS12000/to/groups.js.map +1 -0
  41. package/dist/SS12000/to/index.d.ts +58 -0
  42. package/dist/SS12000/to/index.js +24 -0
  43. package/dist/SS12000/to/index.js.map +1 -0
  44. package/dist/SS12000/to/persons.js +40 -0
  45. package/dist/SS12000/to/persons.js.map +1 -0
  46. package/dist/SS12000/to/resources.js +27 -0
  47. package/dist/SS12000/to/resources.js.map +1 -0
  48. package/dist/SS12000/to/rooms.js +32 -0
  49. package/dist/SS12000/to/rooms.js.map +1 -0
  50. package/dist/SS12000/to/syllabuses.js +34 -0
  51. package/dist/SS12000/to/syllabuses.js.map +1 -0
  52. package/dist/SS12000/types/activities.d.ts +41 -0
  53. package/dist/SS12000/types/calendar-events.d.ts +23 -0
  54. package/dist/SS12000/types/codes.d.ts +9 -0
  55. package/dist/SS12000/types/duties.d.ts +23 -0
  56. package/dist/SS12000/types/duty-assignments.d.ts +13 -0
  57. package/dist/SS12000/types/groups.d.ts +23 -0
  58. package/dist/SS12000/types/index.d.ts +21 -0
  59. package/dist/SS12000/types/organisation.d.ts +20 -0
  60. package/dist/SS12000/types/persons.d.ts +30 -0
  61. package/dist/SS12000/types/resources.d.ts +13 -0
  62. package/dist/SS12000/types/rooms.d.ts +17 -0
  63. package/dist/SS12000/types/syllabus.d.ts +19 -0
  64. package/dist/index.d.ts +9 -7
  65. package/dist/index.js +2 -1
  66. package/package.json +1 -1
@@ -2,11 +2,11 @@ import { isNumber, isString, pick } from "lodash-es";
2
2
  import { nanoid } from "nanoid";
3
3
 
4
4
  //#region src/Excel/v1/from/index.ts
5
- function generateId(map) {
5
+ function generateId(map$1) {
6
6
  let id;
7
7
  do
8
8
  id = nanoid();
9
- while (map.has(id));
9
+ while (map$1.has(id));
10
10
  return id;
11
11
  }
12
12
  function toMultipleOf5(val) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["id: string","warnings: string[]","locationKeys: UnionToAllPossibleTuples<keyof Types.Location>","teacherKeys: UnionToAllPossibleTuples<keyof Types.Teacher>","studentKeys: UnionToAllPossibleTuples<keyof Types.Student>","groupKeys: UnionToAllPossibleTuples<keyof Types.Group>","courseKeys: UnionToAllPossibleTuples<keyof Types.Course>","settings: C_Settings","location: C_Location","group: C_Group","teacher: C_Teacher","groupReference: string | undefined","sex: C_Person['sex']","person: C_Person","totalHours: number | undefined","minutesPerWeek: number | undefined","durations: number[]","x","event: C_Event","locationReferences: { groupIndex: number; to: string }[]","groupReferences: { to: string }[]","teacherReferences: { to: string }[]","course: C_Course"],"sources":["../../../../src/Excel/v1/from/index.ts"],"sourcesContent":["import { isString, pick, isNumber } from 'lodash-es';\nimport { nanoid } from 'nanoid';\nimport type { CoreTypes } from '../../../core';\nimport type { Types, UnionToAllPossibleTuples } from '../types';\nimport type { FromInterface } from '../../../common/types';\n\n\ntype C_Settings = Pick<CoreTypes.serialized.divisionSettings, 'discretization' | 'numDays' | 'dayStart' | 'dayEnd'>;\ntype C_Location = CoreTypes.serialized.location & { id: string };\ntype C_Group = CoreTypes.serialized.group & { id: string };\ntype C_Teacher = CoreTypes.serialized.teacher & { id: string };\ntype C_Course = CoreTypes.serialized.course & { id: string };\ntype C_Person = CoreTypes.serialized.person & { id: string };\ntype C_Event = CoreTypes.serialized.event & { id: string };\n\ntype Out = {\n settings: C_Settings;\n locations: C_Location[];\n teachers: C_Teacher[];\n persons: C_Person[];\n groups: C_Group[];\n courses: C_Course[];\n events: C_Event[];\n meta?: {\n warnings?: string[];\n // errors?: string[]; // TODO: implement error handling\n };\n};\n\nfunction generateId<T> (map: Map<string, T>) {\n // generate a unique id\n let id: string;\n do {\n id = nanoid();\n } while (map.has(id));\n\n return id;\n}\n\nfunction toMultipleOf5 (val: number | string) {\n const num = isString(val) ? parseInt(val) : val;\n\n // throw error if nan\n if (isNaN(num)) throw new Error(`toMultipleOf5: ${val} is not a number`);\n\n return Math.floor(num / 5) * 5;\n}\n\nfunction toInteger (val: number | string) {\n const num = isString(val) ? parseInt(val) : val;\n\n // throw error if nan\n if (isNaN(num)) throw new Error(`toInteger: ${val} is not a number`);\n\n return num;\n}\n\nfunction toString<T extends string | number | undefined, R = T extends undefined ? (string | undefined) : string> (x: T): R {\n if (x == undefined) return undefined as R;\n if (typeof x == 'string' && !x.length) return undefined as R;\n if (isNumber(x)) return x.toString() as R;\n return x.trim() as R;\n}\n\n\nfunction _schedules (\n source: Types.Source\n): Out {\n // gather all import related warnings/errors\n const warnings: string[] = [];\n // let errors: string[] = [];\n\n\n ////\n //// filter to only the fields we need and remove empty rows\n ////\n const locationKeys: UnionToAllPossibleTuples<keyof Types.Location> = ['name'];\n const teacherKeys: UnionToAllPossibleTuples<keyof Types.Teacher> = ['name'];\n const studentKeys: UnionToAllPossibleTuples<keyof Types.Student> = ['first_name', 'last_name', 'SSN', 'sex', 'group'];\n const groupKeys: UnionToAllPossibleTuples<keyof Types.Group> = ['name'];\n const courseKeys: UnionToAllPossibleTuples<keyof Types.Course> = ['name', 'subject', 'groups', 'teachers', 'locations', 'total_hours', 'minutes_per_week', 'lesson_durations'];\n source.locations = source.locations?.map(x => pick(x, locationKeys)).filter(x => Object.values(x).some(y => y !== undefined));\n source.teachers = source.teachers ?.map(x => pick(x, teacherKeys )).filter(x => Object.values(x).some(y => y !== undefined));\n source.students = source.students ?.map(x => pick(x, studentKeys )).filter(x => Object.values(x).some(y => y !== undefined));\n source.groups = source.groups ?.map(x => pick(x, groupKeys )).filter(x => Object.values(x).some(y => y !== undefined));\n source.courses = source.courses ?.map(x => pick(x, courseKeys )).filter(x => Object.values(x).some(y => y !== undefined));\n\n\n ////\n //// settings\n ////\n const settings: C_Settings = {\n discretization: 5,\n numDays: 5,\n dayStart: '08:00',\n dayEnd: '17:00',\n };\n if (!source.settings) {\n warnings.push('Could not find the settings tab.');\n }\n if (source.settings?.[0]?.number_of_days) {\n const numDays = source.settings?.[0]?.number_of_days;\n try {\n if (isNumber(numDays)) settings.numDays = numDays;\n else if (isString(numDays)) settings.numDays = parseInt(numDays);\n\n // must be 5 or 7\n if (settings.numDays !== 5 && settings.numDays !== 7) {\n warnings.push(`The number of days \"${numDays}\" is not 5 or 7.`);\n settings.numDays = 5;\n }\n } catch {\n warnings.push(`Could not parse the number of days \"${numDays}\" for the settings.`);\n }\n }\n\n\n ////\n //// locations\n ////\n const locationsIdMap = new Map<string, C_Location>();\n const locationsNameMap = new Map<string, C_Location>();\n if (!source.locations) {\n warnings.push('Could not find the locations tab.');\n }\n source.locations?.forEach(x => {\n const displayName = toString(x.name);\n if (!displayName) {\n warnings.push('Skipping a location without a name.');\n return;\n }\n\n if (locationsNameMap.has(displayName.toLowerCase())) {\n warnings.push(`The location \"${displayName}\" is defined multiple times.`);\n return;\n }\n\n const id = generateId(locationsIdMap);\n const location: C_Location = { id, displayName };\n locationsNameMap.set(displayName.toLowerCase(), location);\n locationsIdMap .set(id, location);\n });\n\n\n ////\n //// groups\n ////\n const groupsIdMap = new Map<string, C_Group>();\n const groupsNameMap = new Map<string, C_Group>();\n if (!source.groups) {\n warnings.push('Could not find the groups tab.');\n }\n source.groups?.forEach(x => {\n const displayName = toString(x.name);\n if (!displayName) {\n warnings.push('Skipping a group without a name.');\n return;\n }\n\n if (groupsNameMap.has(displayName.toLowerCase())) {\n warnings.push(`The group \"${displayName}\" is defined multiple times.`);\n return;\n }\n\n const id = generateId(groupsIdMap);\n const group: C_Group = { id, displayName, species: 'class' };\n groupsNameMap.set(displayName.toLowerCase(), group);\n groupsIdMap .set(id, group);\n });\n\n\n ////\n //// teachers\n ////\n const teachersIdMap = new Map<string, C_Teacher>();\n const teachersNameMap = new Map<string, C_Teacher>();\n if (!source.teachers) {\n warnings.push('Could not find the teachers tab.');\n }\n source.teachers?.forEach(x => {\n const displayName = toString(x.name);\n if (!displayName) {\n warnings.push('Skipping a teacher without a name.');\n return;\n }\n\n if (teachersNameMap.has(displayName.toLowerCase())) {\n warnings.push(`The teacher \"${displayName}\" is defined multiple times.`);\n return;\n }\n\n const id = generateId(teachersIdMap);\n const teacher: C_Teacher = { id, displayName };\n teachersNameMap.set(displayName.toLowerCase(), teacher);\n teachersIdMap .set(id, teacher);\n });\n\n\n ////\n //// students\n ////\n const personsIdMap = new Map<string, C_Person>();\n if (!source.students) {\n warnings.push('Could not find the students tab.');\n }\n source.students?.forEach(x => {\n const firstName = toString(x.first_name);\n const lastName = toString(x.last_name );\n const SSN = toString(x.SSN );\n\n let groupReference: string | undefined = undefined;\n if (x.group) {\n const key = toString(x.group).toLowerCase();\n const ref = groupsNameMap.get(key); /// to lower case only!\n if (!ref) {\n warnings.push(`The group ${x.group} referenced from the student \"${firstName} ${lastName}\" does not exist.`);\n } else {\n groupReference = ref.id;\n }\n }\n\n let sex: C_Person['sex'];\n if (x.sex) {\n if (isString(x.sex) && x.sex.toLowerCase() == 'man') sex = 'Man';\n else if (isString(x.sex) && x.sex.toLowerCase() == 'woman') sex = 'Woman';\n else {\n warnings.push(`Unknown sex \"${ x.sex }\" for the student \"${firstName} ${lastName}\".`);\n }\n }\n\n const id = generateId(personsIdMap);\n const person: C_Person = { id, firstName, lastName, sex, group: groupReference, ...SSN && { SSN: { value: SSN } } };\n personsIdMap.set(id, person);\n });\n\n\n ////\n //// courses\n ////\n const coursesIdMap = new Map<string, C_Course>();\n const eventsIdMap = new Map<string, C_Event>();\n if (!source.courses) {\n warnings.push('Could not find the courses tab.');\n }\n source.courses?.forEach(x => {\n const courseId = generateId(coursesIdMap);\n const displayName = toString(x.name)?.trim();\n const subject = toString(x.subject);\n\n // try to parse the total hours as an integer\n let totalHours: number | undefined = undefined;\n if (x.total_hours) {\n try {\n totalHours = toInteger(x.total_hours);\n } catch {\n warnings.push(`The total hours \"${x.total_hours}\" for the course \"${displayName}\" is not an integer.`);\n }\n }\n\n // try to parse the minutes per week as an multiple of 5\n let minutesPerWeek: number | undefined = undefined;\n if (x.minutes_per_week) {\n try {\n minutesPerWeek = toMultipleOf5(x.minutes_per_week);\n } catch {\n warnings.push(`The minutes per week \"${x.minutes_per_week}\" for the course \"${displayName}\" is not an integer.`);\n }\n }\n\n // try to parse the lesson durations as an array of integers from which we will generate events\n if (x.lesson_durations) {\n try {\n let durations: number[] = [];\n if (isNumber(x.lesson_durations)) durations = [x.lesson_durations];\n else if (isString(x.lesson_durations)) durations = x.lesson_durations.split(',').map(x => x.trim())\n .map(x => parseInt(x));\n\n // truncate to multiple of 5 and filter out zero duration events\n durations = durations\n .map(x => {\n try {\n return toMultipleOf5(x);\n } catch {\n warnings.push(`The lesson duration \"${x}\" for the course \"${displayName}\" is not an integer.`);\n return undefined;\n }\n })\n .filter((x): x is number => {\n if (!x) {\n warnings.push(`The lesson duration for the course \"${displayName}\" becomes 0 when truncated to the nearest multiple of 5.`);\n return false;\n }\n return true;\n });\n\n durations.forEach(x => {\n const id = generateId(eventsIdMap);\n const event: C_Event = { id, course: courseId, preferredDuration: x };\n eventsIdMap.set(id, event);\n });\n } catch {\n warnings.push(`Could not parse the lesson durations \"${x.lesson_durations}\" for the course \"${displayName}\".`);\n }\n }\n\n // locations\n const locationReferences: { groupIndex: number; to: string }[] = [];\n\n toString(x.locations)?.split('+')\n .flatMap((x, i) => x.split(',').map(x => [i, x.trim().toLowerCase()] as [number, string]))\n .forEach(([i, x]) => {\n const ref = locationsNameMap.get(x);\n if (!ref) {\n warnings.push(`The location \"${x}\" referenced from the course \"${displayName}\" does not exist.`);\n return;\n }\n\n if (locationReferences.some(y => y.to == ref.id)) {\n warnings.push(`The location \"${x}\" is referenced multiple times from the course \"${displayName}\".`);\n return;\n }\n\n locationReferences.push({ groupIndex: i, to: ref.id });\n });\n\n // groups\n const groupReferences: { to: string }[] = [];\n toString(x.groups)?.split(',')\n .map(x => x.trim().toLowerCase())\n .forEach(x => {\n const ref = groupsNameMap.get(x);\n if (!ref) {\n warnings.push(`The group \"${x}\" referenced from the course \"${displayName}\" does not exist.`);\n return;\n }\n\n if (groupReferences.some(y => y.to == ref.id)) {\n warnings.push(`The group \"${x}\" is referenced multiple times from the course \"${displayName}\".`);\n return;\n }\n\n groupReferences.push({ to: ref.id });\n });\n\n // teachers\n const teacherReferences: { to: string }[] = [];\n toString(x.teachers)?.split(',')\n .map(x => x.trim().toLowerCase())\n .forEach(x => {\n const ref = teachersNameMap.get(x);\n if (!ref) {\n warnings.push(`The teacher \"${x}\" referenced from the course \"${displayName}\" does not exist.`);\n return;\n }\n\n if (teacherReferences.some(y => y.to == ref.id)) {\n warnings.push(`The teacher \"${x}\" is referenced multiple times from the course \"${displayName}\".`);\n return;\n }\n\n teacherReferences.push({ to: ref.id });\n });\n\n const course: C_Course = {\n id: courseId,\n groups: groupReferences,\n teachers: teacherReferences,\n locations: locationReferences.map(x => ({ groupIndex: x.groupIndex, locations: [x.to] })),\n expectedTotalHours: totalHours,\n displayName, subject, minutesPerWeek,\n };\n coursesIdMap.set(courseId, course);\n });\n\n\n ////\n //// return\n ////\n return {\n settings,\n locations: [...locationsIdMap.values()],\n teachers: [...teachersIdMap .values()],\n persons: [...personsIdMap .values()],\n groups: [...groupsIdMap .values()],\n courses: [...coursesIdMap .values()],\n events: [...eventsIdMap .values()],\n meta: {\n // ...errors .length && { errors: errors },\n ...warnings.length && { warnings: warnings }\n }\n };\n}\n\n\nexport default {\n schedules: _schedules\n} satisfies FromInterface;"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["id: string","map","warnings: string[]","locationKeys: UnionToAllPossibleTuples<keyof Types.Location>","teacherKeys: UnionToAllPossibleTuples<keyof Types.Teacher>","studentKeys: UnionToAllPossibleTuples<keyof Types.Student>","groupKeys: UnionToAllPossibleTuples<keyof Types.Group>","courseKeys: UnionToAllPossibleTuples<keyof Types.Course>","settings: C_Settings","location: C_Location","group: C_Group","teacher: C_Teacher","groupReference: string | undefined","sex: C_Person['sex']","person: C_Person","totalHours: number | undefined","minutesPerWeek: number | undefined","durations: number[]","x","event: C_Event","locationReferences: { groupIndex: number; to: string }[]","groupReferences: { to: string }[]","teacherReferences: { to: string }[]","course: C_Course"],"sources":["../../../../src/Excel/v1/from/index.ts"],"sourcesContent":["import { isString, pick, isNumber } from 'lodash-es';\nimport { nanoid } from 'nanoid';\nimport type { CoreTypes } from '../../../core';\nimport type { Types, UnionToAllPossibleTuples } from '../types';\nimport type { FromInterface } from '../../../common/types';\n\n\ntype C_Settings = Pick<CoreTypes.serialized.divisionSettings, 'discretization' | 'numDays' | 'dayStart' | 'dayEnd'>;\ntype C_Location = CoreTypes.serialized.location & { id: string };\ntype C_Group = CoreTypes.serialized.group & { id: string };\ntype C_Teacher = CoreTypes.serialized.teacher & { id: string };\ntype C_Course = CoreTypes.serialized.course & { id: string };\ntype C_Person = CoreTypes.serialized.person & { id: string };\ntype C_Event = CoreTypes.serialized.event & { id: string };\n\ntype Out = {\n settings: C_Settings;\n locations: C_Location[];\n teachers: C_Teacher[];\n persons: C_Person[];\n groups: C_Group[];\n courses: C_Course[];\n events: C_Event[];\n meta?: {\n warnings?: string[];\n // errors?: string[]; // TODO: implement error handling\n };\n};\n\nfunction generateId<T> (map: Map<string, T>) {\n // generate a unique id\n let id: string;\n do {\n id = nanoid();\n } while (map.has(id));\n\n return id;\n}\n\nfunction toMultipleOf5 (val: number | string) {\n const num = isString(val) ? parseInt(val) : val;\n\n // throw error if nan\n if (isNaN(num)) throw new Error(`toMultipleOf5: ${val} is not a number`);\n\n return Math.floor(num / 5) * 5;\n}\n\nfunction toInteger (val: number | string) {\n const num = isString(val) ? parseInt(val) : val;\n\n // throw error if nan\n if (isNaN(num)) throw new Error(`toInteger: ${val} is not a number`);\n\n return num;\n}\n\nfunction toString<T extends string | number | undefined, R = T extends undefined ? (string | undefined) : string> (x: T): R {\n if (x == undefined) return undefined as R;\n if (typeof x == 'string' && !x.length) return undefined as R;\n if (isNumber(x)) return x.toString() as R;\n return x.trim() as R;\n}\n\n\nfunction _schedules (\n source: Types.Source\n): Out {\n // gather all import related warnings/errors\n const warnings: string[] = [];\n // let errors: string[] = [];\n\n\n ////\n //// filter to only the fields we need and remove empty rows\n ////\n const locationKeys: UnionToAllPossibleTuples<keyof Types.Location> = ['name'];\n const teacherKeys: UnionToAllPossibleTuples<keyof Types.Teacher> = ['name'];\n const studentKeys: UnionToAllPossibleTuples<keyof Types.Student> = ['first_name', 'last_name', 'SSN', 'sex', 'group'];\n const groupKeys: UnionToAllPossibleTuples<keyof Types.Group> = ['name'];\n const courseKeys: UnionToAllPossibleTuples<keyof Types.Course> = ['name', 'subject', 'groups', 'teachers', 'locations', 'total_hours', 'minutes_per_week', 'lesson_durations'];\n source.locations = source.locations?.map(x => pick(x, locationKeys)).filter(x => Object.values(x).some(y => y !== undefined));\n source.teachers = source.teachers ?.map(x => pick(x, teacherKeys )).filter(x => Object.values(x).some(y => y !== undefined));\n source.students = source.students ?.map(x => pick(x, studentKeys )).filter(x => Object.values(x).some(y => y !== undefined));\n source.groups = source.groups ?.map(x => pick(x, groupKeys )).filter(x => Object.values(x).some(y => y !== undefined));\n source.courses = source.courses ?.map(x => pick(x, courseKeys )).filter(x => Object.values(x).some(y => y !== undefined));\n\n\n ////\n //// settings\n ////\n const settings: C_Settings = {\n discretization: 5,\n numDays: 5,\n dayStart: '08:00',\n dayEnd: '17:00',\n };\n if (!source.settings) {\n warnings.push('Could not find the settings tab.');\n }\n if (source.settings?.[0]?.number_of_days) {\n const numDays = source.settings?.[0]?.number_of_days;\n try {\n if (isNumber(numDays)) settings.numDays = numDays;\n else if (isString(numDays)) settings.numDays = parseInt(numDays);\n\n // must be 5 or 7\n if (settings.numDays !== 5 && settings.numDays !== 7) {\n warnings.push(`The number of days \"${numDays}\" is not 5 or 7.`);\n settings.numDays = 5;\n }\n } catch {\n warnings.push(`Could not parse the number of days \"${numDays}\" for the settings.`);\n }\n }\n\n\n ////\n //// locations\n ////\n const locationsIdMap = new Map<string, C_Location>();\n const locationsNameMap = new Map<string, C_Location>();\n if (!source.locations) {\n warnings.push('Could not find the locations tab.');\n }\n source.locations?.forEach(x => {\n const displayName = toString(x.name);\n if (!displayName) {\n warnings.push('Skipping a location without a name.');\n return;\n }\n\n if (locationsNameMap.has(displayName.toLowerCase())) {\n warnings.push(`The location \"${displayName}\" is defined multiple times.`);\n return;\n }\n\n const id = generateId(locationsIdMap);\n const location: C_Location = { id, displayName };\n locationsNameMap.set(displayName.toLowerCase(), location);\n locationsIdMap .set(id, location);\n });\n\n\n ////\n //// groups\n ////\n const groupsIdMap = new Map<string, C_Group>();\n const groupsNameMap = new Map<string, C_Group>();\n if (!source.groups) {\n warnings.push('Could not find the groups tab.');\n }\n source.groups?.forEach(x => {\n const displayName = toString(x.name);\n if (!displayName) {\n warnings.push('Skipping a group without a name.');\n return;\n }\n\n if (groupsNameMap.has(displayName.toLowerCase())) {\n warnings.push(`The group \"${displayName}\" is defined multiple times.`);\n return;\n }\n\n const id = generateId(groupsIdMap);\n const group: C_Group = { id, displayName, species: 'class' };\n groupsNameMap.set(displayName.toLowerCase(), group);\n groupsIdMap .set(id, group);\n });\n\n\n ////\n //// teachers\n ////\n const teachersIdMap = new Map<string, C_Teacher>();\n const teachersNameMap = new Map<string, C_Teacher>();\n if (!source.teachers) {\n warnings.push('Could not find the teachers tab.');\n }\n source.teachers?.forEach(x => {\n const displayName = toString(x.name);\n if (!displayName) {\n warnings.push('Skipping a teacher without a name.');\n return;\n }\n\n if (teachersNameMap.has(displayName.toLowerCase())) {\n warnings.push(`The teacher \"${displayName}\" is defined multiple times.`);\n return;\n }\n\n const id = generateId(teachersIdMap);\n const teacher: C_Teacher = { id, displayName };\n teachersNameMap.set(displayName.toLowerCase(), teacher);\n teachersIdMap .set(id, teacher);\n });\n\n\n ////\n //// students\n ////\n const personsIdMap = new Map<string, C_Person>();\n if (!source.students) {\n warnings.push('Could not find the students tab.');\n }\n source.students?.forEach(x => {\n const firstName = toString(x.first_name);\n const lastName = toString(x.last_name );\n const SSN = toString(x.SSN );\n\n let groupReference: string | undefined = undefined;\n if (x.group) {\n const key = toString(x.group).toLowerCase();\n const ref = groupsNameMap.get(key); /// to lower case only!\n if (!ref) {\n warnings.push(`The group ${x.group} referenced from the student \"${firstName} ${lastName}\" does not exist.`);\n } else {\n groupReference = ref.id;\n }\n }\n\n let sex: C_Person['sex'];\n if (x.sex) {\n if (isString(x.sex) && x.sex.toLowerCase() == 'man') sex = 'Man';\n else if (isString(x.sex) && x.sex.toLowerCase() == 'woman') sex = 'Woman';\n else {\n warnings.push(`Unknown sex \"${ x.sex }\" for the student \"${firstName} ${lastName}\".`);\n }\n }\n\n const id = generateId(personsIdMap);\n const person: C_Person = { id, firstName, lastName, sex, group: groupReference, ...SSN && { SSN: { value: SSN } } };\n personsIdMap.set(id, person);\n });\n\n\n ////\n //// courses\n ////\n const coursesIdMap = new Map<string, C_Course>();\n const eventsIdMap = new Map<string, C_Event>();\n if (!source.courses) {\n warnings.push('Could not find the courses tab.');\n }\n source.courses?.forEach(x => {\n const courseId = generateId(coursesIdMap);\n const displayName = toString(x.name)?.trim();\n const subject = toString(x.subject);\n\n // try to parse the total hours as an integer\n let totalHours: number | undefined = undefined;\n if (x.total_hours) {\n try {\n totalHours = toInteger(x.total_hours);\n } catch {\n warnings.push(`The total hours \"${x.total_hours}\" for the course \"${displayName}\" is not an integer.`);\n }\n }\n\n // try to parse the minutes per week as an multiple of 5\n let minutesPerWeek: number | undefined = undefined;\n if (x.minutes_per_week) {\n try {\n minutesPerWeek = toMultipleOf5(x.minutes_per_week);\n } catch {\n warnings.push(`The minutes per week \"${x.minutes_per_week}\" for the course \"${displayName}\" is not an integer.`);\n }\n }\n\n // try to parse the lesson durations as an array of integers from which we will generate events\n if (x.lesson_durations) {\n try {\n let durations: number[] = [];\n if (isNumber(x.lesson_durations)) durations = [x.lesson_durations];\n else if (isString(x.lesson_durations)) durations = x.lesson_durations.split(',').map(x => x.trim())\n .map(x => parseInt(x));\n\n // truncate to multiple of 5 and filter out zero duration events\n durations = durations\n .map(x => {\n try {\n return toMultipleOf5(x);\n } catch {\n warnings.push(`The lesson duration \"${x}\" for the course \"${displayName}\" is not an integer.`);\n return undefined;\n }\n })\n .filter((x): x is number => {\n if (!x) {\n warnings.push(`The lesson duration for the course \"${displayName}\" becomes 0 when truncated to the nearest multiple of 5.`);\n return false;\n }\n return true;\n });\n\n durations.forEach(x => {\n const id = generateId(eventsIdMap);\n const event: C_Event = { id, course: courseId, preferredDuration: x };\n eventsIdMap.set(id, event);\n });\n } catch {\n warnings.push(`Could not parse the lesson durations \"${x.lesson_durations}\" for the course \"${displayName}\".`);\n }\n }\n\n // locations\n const locationReferences: { groupIndex: number; to: string }[] = [];\n\n toString(x.locations)?.split('+')\n .flatMap((x, i) => x.split(',').map(x => [i, x.trim().toLowerCase()] as [number, string]))\n .forEach(([i, x]) => {\n const ref = locationsNameMap.get(x);\n if (!ref) {\n warnings.push(`The location \"${x}\" referenced from the course \"${displayName}\" does not exist.`);\n return;\n }\n\n if (locationReferences.some(y => y.to == ref.id)) {\n warnings.push(`The location \"${x}\" is referenced multiple times from the course \"${displayName}\".`);\n return;\n }\n\n locationReferences.push({ groupIndex: i, to: ref.id });\n });\n\n // groups\n const groupReferences: { to: string }[] = [];\n toString(x.groups)?.split(',')\n .map(x => x.trim().toLowerCase())\n .forEach(x => {\n const ref = groupsNameMap.get(x);\n if (!ref) {\n warnings.push(`The group \"${x}\" referenced from the course \"${displayName}\" does not exist.`);\n return;\n }\n\n if (groupReferences.some(y => y.to == ref.id)) {\n warnings.push(`The group \"${x}\" is referenced multiple times from the course \"${displayName}\".`);\n return;\n }\n\n groupReferences.push({ to: ref.id });\n });\n\n // teachers\n const teacherReferences: { to: string }[] = [];\n toString(x.teachers)?.split(',')\n .map(x => x.trim().toLowerCase())\n .forEach(x => {\n const ref = teachersNameMap.get(x);\n if (!ref) {\n warnings.push(`The teacher \"${x}\" referenced from the course \"${displayName}\" does not exist.`);\n return;\n }\n\n if (teacherReferences.some(y => y.to == ref.id)) {\n warnings.push(`The teacher \"${x}\" is referenced multiple times from the course \"${displayName}\".`);\n return;\n }\n\n teacherReferences.push({ to: ref.id });\n });\n\n const course: C_Course = {\n id: courseId,\n groups: groupReferences,\n teachers: teacherReferences,\n locations: locationReferences.map(x => ({ groupIndex: x.groupIndex, locations: [x.to] })),\n expectedTotalHours: totalHours,\n displayName, subject, minutesPerWeek,\n };\n coursesIdMap.set(courseId, course);\n });\n\n\n ////\n //// return\n ////\n return {\n settings,\n locations: [...locationsIdMap.values()],\n teachers: [...teachersIdMap .values()],\n persons: [...personsIdMap .values()],\n groups: [...groupsIdMap .values()],\n courses: [...coursesIdMap .values()],\n events: [...eventsIdMap .values()],\n meta: {\n // ...errors .length && { errors: errors },\n ...warnings.length && { warnings: warnings }\n }\n };\n}\n\n\nexport default {\n schedules: _schedules\n} satisfies FromInterface;"],"mappings":";;;;AA6BA,SAAS,WAAe,OAAqB;CAE3C,IAAIA;AACJ;AACE,OAAK;QACEC,MAAI,IAAI;AAEjB,QAAO;;AAGT,SAAS,cAAe,KAAsB;CAC5C,MAAM,MAAM,SAAS,OAAO,SAAS,OAAO;AAG5C,KAAI,MAAM,KAAM,OAAM,IAAI,MAAM,kBAAkB,IAAI;AAEtD,QAAO,KAAK,MAAM,MAAM,KAAK;;AAG/B,SAAS,UAAW,KAAsB;CACxC,MAAM,MAAM,SAAS,OAAO,SAAS,OAAO;AAG5C,KAAI,MAAM,KAAM,OAAM,IAAI,MAAM,cAAc,IAAI;AAElD,QAAO;;AAGT,SAAS,SAA0G,GAAS;AAC1H,KAAI,KAAK,OAAW,QAAO;AAC3B,KAAI,OAAO,KAAK,YAAY,CAAC,EAAE,OAAQ,QAAO;AAC9C,KAAI,SAAS,GAAI,QAAO,EAAE;AAC1B,QAAO,EAAE;;AAIX,SAAS,WACP,QACK;CAEL,MAAMC,WAAqB;CAO3B,MAAMC,eAA+D,CAAC;CACtE,MAAMC,cAA+D,CAAC;CACtE,MAAMC,cAA+D;EAAC;EAAc;EAAa;EAAO;EAAO;;CAC/G,MAAMC,YAA+D,CAAC;CACtE,MAAMC,aAA+D;EAAC;EAAQ;EAAW;EAAU;EAAY;EAAa;EAAe;EAAoB;;AAC/J,QAAO,YAAY,OAAO,WAAW,KAAI,MAAK,KAAK,GAAG,eAAe,QAAO,MAAK,OAAO,OAAO,GAAG,MAAK,MAAK,MAAM;AAClH,QAAO,WAAY,OAAO,UAAW,KAAI,MAAK,KAAK,GAAG,cAAe,QAAO,MAAK,OAAO,OAAO,GAAG,MAAK,MAAK,MAAM;AAClH,QAAO,WAAY,OAAO,UAAW,KAAI,MAAK,KAAK,GAAG,cAAe,QAAO,MAAK,OAAO,OAAO,GAAG,MAAK,MAAK,MAAM;AAClH,QAAO,SAAY,OAAO,QAAW,KAAI,MAAK,KAAK,GAAG,YAAe,QAAO,MAAK,OAAO,OAAO,GAAG,MAAK,MAAK,MAAM;AAClH,QAAO,UAAY,OAAO,SAAW,KAAI,MAAK,KAAK,GAAG,aAAe,QAAO,MAAK,OAAO,OAAO,GAAG,MAAK,MAAK,MAAM;CAMlH,MAAMC,WAAuB;EAC3B,gBAAgB;EAChB,SAAgB;EAChB,UAAgB;EAChB,QAAgB;;AAElB,KAAI,CAAC,OAAO,SACV,UAAS,KAAK;AAEhB,KAAI,OAAO,WAAW,IAAI,gBAAgB;EACxC,MAAM,UAAU,OAAO,WAAW,IAAI;AACtC,MAAI;AACF,OAAS,SAAS,SAAU,UAAS,UAAU;YACtC,SAAS,SAAU,UAAS,UAAU,SAAS;AAGxD,OAAI,SAAS,YAAY,KAAK,SAAS,YAAY,GAAG;AACpD,aAAS,KAAK,uBAAuB,QAAQ;AAC7C,aAAS,UAAU;;UAEf;AACN,YAAS,KAAK,uCAAuC,QAAQ;;;CAQjE,MAAM,iCAAmB,IAAI;CAC7B,MAAM,mCAAmB,IAAI;AAC7B,KAAI,CAAC,OAAO,UACV,UAAS,KAAK;AAEhB,QAAO,WAAW,SAAQ,MAAK;EAC7B,MAAM,cAAc,SAAS,EAAE;AAC/B,MAAI,CAAC,aAAa;AAChB,YAAS,KAAK;AACd;;AAGF,MAAI,iBAAiB,IAAI,YAAY,gBAAgB;AACnD,YAAS,KAAK,iBAAiB,YAAY;AAC3C;;EAGF,MAAM,KAAK,WAAW;EACtB,MAAMC,WAAuB;GAAE;GAAI;;AACnC,mBAAiB,IAAI,YAAY,eAAe;AAChD,iBAAiB,IAAI,IAA2B;;CAOlD,MAAM,8BAAgB,IAAI;CAC1B,MAAM,gCAAgB,IAAI;AAC1B,KAAI,CAAC,OAAO,OACV,UAAS,KAAK;AAEhB,QAAO,QAAQ,SAAQ,MAAK;EAC1B,MAAM,cAAc,SAAS,EAAE;AAC/B,MAAI,CAAC,aAAa;AAChB,YAAS,KAAK;AACd;;AAGF,MAAI,cAAc,IAAI,YAAY,gBAAgB;AAChD,YAAS,KAAK,cAAc,YAAY;AACxC;;EAGF,MAAM,KAAK,WAAW;EACtB,MAAMC,QAAiB;GAAE;GAAI;GAAa,SAAS;;AACnD,gBAAc,IAAI,YAAY,eAAe;AAC7C,cAAc,IAAI,IAA2B;;CAO/C,MAAM,gCAAkB,IAAI;CAC5B,MAAM,kCAAkB,IAAI;AAC5B,KAAI,CAAC,OAAO,SACV,UAAS,KAAK;AAEhB,QAAO,UAAU,SAAQ,MAAK;EAC5B,MAAM,cAAc,SAAS,EAAE;AAC/B,MAAI,CAAC,aAAa;AAChB,YAAS,KAAK;AACd;;AAGF,MAAI,gBAAgB,IAAI,YAAY,gBAAgB;AAClD,YAAS,KAAK,gBAAgB,YAAY;AAC1C;;EAGF,MAAM,KAAK,WAAW;EACtB,MAAMC,UAAqB;GAAE;GAAI;;AACjC,kBAAgB,IAAI,YAAY,eAAe;AAC/C,gBAAgB,IAAI,IAA2B;;CAOjD,MAAM,+BAAe,IAAI;AACzB,KAAI,CAAC,OAAO,SACV,UAAS,KAAK;AAEhB,QAAO,UAAU,SAAQ,MAAK;EAC5B,MAAM,YAAY,SAAS,EAAE;EAC7B,MAAM,WAAY,SAAS,EAAE;EAC7B,MAAM,MAAY,SAAS,EAAE;EAE7B,IAAIC,iBAAqC;AACzC,MAAI,EAAE,OAAO;GACX,MAAM,MAAM,SAAS,EAAE,OAAO;GAC9B,MAAM,MAAM,cAAc,IAAI;AAC9B,OAAI,CAAC,IACH,UAAS,KAAK,aAAa,EAAE,MAAM,gCAAgC,UAAU,GAAG,SAAS;OAEzF,kBAAiB,IAAI;;EAIzB,IAAIC;AACJ,MAAI,EAAE,IACJ,KAAS,SAAS,EAAE,QAAQ,EAAE,IAAI,iBAAiB,MAAS,OAAM;WACzD,SAAS,EAAE,QAAQ,EAAE,IAAI,iBAAiB,QAAS,OAAM;MAEhE,UAAS,KAAK,gBAAiB,EAAE,IAAK,qBAAqB,UAAU,GAAG,SAAS;EAIrF,MAAM,KAAK,WAAW;EACtB,MAAMC,SAAmB;GAAE;GAAI;GAAW;GAAU;GAAK,OAAO;GAAgB,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO;;AAC1G,eAAa,IAAI,IAAI;;CAOvB,MAAM,+BAAe,IAAI;CACzB,MAAM,8BAAe,IAAI;AACzB,KAAI,CAAC,OAAO,QACV,UAAS,KAAK;AAEhB,QAAO,SAAS,SAAQ,MAAK;EAC3B,MAAM,WAAc,WAAW;EAC/B,MAAM,cAAc,SAAS,EAAE,OAAO;EACtC,MAAM,UAAc,SAAS,EAAE;EAG/B,IAAIC,aAAiC;AACrC,MAAI,EAAE,YACJ,KAAI;AACF,gBAAa,UAAU,EAAE;UACnB;AACN,YAAS,KAAK,oBAAoB,EAAE,YAAY,oBAAoB,YAAY;;EAKpF,IAAIC,iBAAqC;AACzC,MAAI,EAAE,iBACJ,KAAI;AACF,oBAAiB,cAAc,EAAE;UAC3B;AACN,YAAS,KAAK,yBAAyB,EAAE,iBAAiB,oBAAoB,YAAY;;AAK9F,MAAI,EAAE,iBACJ,KAAI;GACF,IAAIC,YAAsB;AAC1B,OAAS,SAAS,EAAE,kBAAmB,aAAY,CAAC,EAAE;YAC7C,SAAS,EAAE,kBAAmB,aAAY,EAAE,iBAAiB,MAAM,KAAK,KAAI,QAAKC,IAAE,QACzF,KAAI,QAAK,SAASA;AAGrB,eAAY,UACT,KAAI,QAAK;AACR,QAAI;AACF,YAAO,cAAcA;YACf;AACN,cAAS,KAAK,wBAAwBA,IAAE,oBAAoB,YAAY;AACxE,YAAO;;MAGV,QAAQ,QAAmB;AAC1B,QAAI,CAACA,KAAG;AACN,cAAS,KAAK,uCAAuC,YAAY;AACjE,YAAO;;AAET,WAAO;;AAGX,aAAU,SAAQ,QAAK;IACrB,MAAM,KAAK,WAAW;IACtB,MAAMC,QAAiB;KAAE;KAAI,QAAQ;KAAU,mBAAmBD;;AAClE,gBAAY,IAAI,IAAI;;UAEhB;AACN,YAAS,KAAK,yCAAyC,EAAE,iBAAiB,oBAAoB,YAAY;;EAK9G,MAAME,qBAA2D;AAEjE,WAAS,EAAE,YAAY,MAAM,KAC1B,SAAS,KAAG,MAAMF,IAAE,MAAM,KAAK,KAAI,QAAK,CAAC,GAAGA,IAAE,OAAO,iBACrD,SAAS,CAAC,GAAGA,SAAO;GACnB,MAAM,MAAM,iBAAiB,IAAIA;AACjC,OAAI,CAAC,KAAK;AACR,aAAS,KAAK,iBAAiBA,IAAE,gCAAgC,YAAY;AAC7E;;AAGF,OAAI,mBAAmB,MAAK,MAAK,EAAE,MAAM,IAAI,KAAK;AAChD,aAAS,KAAK,iBAAiBA,IAAE,kDAAkD,YAAY;AAC/F;;AAGF,sBAAmB,KAAK;IAAE,YAAY;IAAG,IAAI,IAAI;;;EAIrD,MAAMG,kBAAoC;AAC1C,WAAS,EAAE,SAAS,MAAM,KACvB,KAAI,QAAKH,IAAE,OAAO,eAClB,SAAQ,QAAK;GACZ,MAAM,MAAM,cAAc,IAAIA;AAC9B,OAAI,CAAC,KAAK;AACR,aAAS,KAAK,cAAcA,IAAE,gCAAgC,YAAY;AAC1E;;AAGF,OAAI,gBAAgB,MAAK,MAAK,EAAE,MAAM,IAAI,KAAK;AAC7C,aAAS,KAAK,cAAcA,IAAE,kDAAkD,YAAY;AAC5F;;AAGF,mBAAgB,KAAK,EAAE,IAAI,IAAI;;EAInC,MAAMI,oBAAsC;AAC5C,WAAS,EAAE,WAAW,MAAM,KACzB,KAAI,QAAKJ,IAAE,OAAO,eAClB,SAAQ,QAAK;GACZ,MAAM,MAAM,gBAAgB,IAAIA;AAChC,OAAI,CAAC,KAAK;AACR,aAAS,KAAK,gBAAgBA,IAAE,gCAAgC,YAAY;AAC5E;;AAGF,OAAI,kBAAkB,MAAK,MAAK,EAAE,MAAM,IAAI,KAAK;AAC/C,aAAS,KAAK,gBAAgBA,IAAE,kDAAkD,YAAY;AAC9F;;AAGF,qBAAkB,KAAK,EAAE,IAAI,IAAI;;EAGrC,MAAMK,SAAmB;GACvB,IAAoB;GACpB,QAAoB;GACpB,UAAoB;GACpB,WAAoB,mBAAmB,KAAI,SAAM;IAAE,YAAYL,IAAE;IAAY,WAAW,CAACA,IAAE;;GAC3F,oBAAoB;GACpB;GAAa;GAAS;;AAExB,eAAa,IAAI,UAAU;;AAO7B,QAAO;EACL;EACA,WAAW,CAAC,GAAG,eAAe;EAC9B,UAAW,CAAC,GAAG,cAAe;EAC9B,SAAW,CAAC,GAAG,aAAe;EAC9B,QAAW,CAAC,GAAG,YAAe;EAC9B,SAAW,CAAC,GAAG,aAAe;EAC9B,QAAW,CAAC,GAAG,YAAe;EAC9B,MAAW,EAET,GAAG,SAAS,UAAU,EAAY;;;AAMxC,mBAAe,EACb,WAAW"}
@@ -2,11 +2,11 @@ import { chain, isNumber, isString } from "lodash-es";
2
2
  import { nanoid } from "nanoid";
3
3
 
4
4
  //#region src/Excel/v2/from/index.ts
5
- function generateId(map) {
5
+ function generateId(map$1) {
6
6
  let id;
7
7
  do
8
8
  id = nanoid(8);
9
- while (map.has(id));
9
+ while (map$1.has(id));
10
10
  return id;
11
11
  }
12
12
  function toPositiveMultipleOf5(val) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["id: string","locationReferences: { groupIndex: number; to: string }[]","x","groupReferences: { to: string }[]","teacherReferences: { to: string }[]","warnings: { code: Types.ErrorCode, context?: unknown }[]","settings: C_Settings","y: C_Syllabus","group: string | undefined","sex: C_Person['sex']","person: C_Person","expectedTotalHours: number | undefined","minutesPerWeek: number | undefined","event: C_Event","course: C_Course"],"sources":["../../../../src/Excel/v2/from/index.ts"],"sourcesContent":["import { isString, chain, isNumber } from 'lodash-es';\nimport { nanoid } from 'nanoid';\nimport type { CoreTypes } from '../../../core';\nimport type { Types } from '../types';\nimport type { FromInterface } from '../../../common/types';\n\ntype C_Settings = Pick<CoreTypes.serialized.divisionSettings, 'discretization' | 'numDays' | 'dayStart' | 'dayEnd'>;\ntype C_Location = CoreTypes.serialized.location & { id: string } & { __raw: Types.Location };\ntype C_Group = CoreTypes.serialized.group & { id: string } & { __raw: Types.Group };\ntype C_Teacher = CoreTypes.serialized.teacher & { id: string } & { __raw: Types.Teacher };\ntype C_Course = CoreTypes.serialized.course & { id: string } & { __raw: Types.Course };\ntype C_Person = CoreTypes.serialized.person & { id: string } & { __raw: Types.Person };\ntype C_Event = CoreTypes.serialized.event & { id: string } & { __raw?: Types.Course };\ntype C_OverlapGroup = CoreTypes.serialized.overlapGroup & { id: string } & { /* raw: Types.OverlapGroup */ };\ntype C_Syllabus = CoreTypes.serialized.syllabus & { id: string } & { __raw?: Types.Syllabus };\n\ntype Out = {\n settings: C_Settings;\n locations: C_Location[];\n teachers: C_Teacher[];\n persons: C_Person[];\n groups: C_Group[];\n courses: C_Course[];\n events: C_Event[];\n overlapGroups: C_OverlapGroup[];\n syllabuses: C_Syllabus[];\n meta: {\n // errors?: string[];\n warnings?: { code: Types.ErrorCode, context?: unknown }[];\n };\n};\n\n\nfunction generateId (map: Map<string, unknown>) {\n // generate a unique id\n let id: string;\n do {\n id = nanoid(8);\n } while (map.has(id));\n\n return id;\n}\n\nfunction toPositiveMultipleOf5 (val: number | string) {\n const num = isString(val) ? parseInt(val) : val;\n\n // throw error if nan\n if (isNaN(num)) throw new Error(`toMultipleOf5: ${val} is not a number`);\n\n const res = Math.floor(num / 5) * 5;\n\n if (res <= 0) throw new Error(`toMultipleOf5: the result ${res} is not positive`);\n\n return res;\n}\n\nfunction toPositiveInteger (val: number | string) {\n const num = isString(val) ? parseInt(val) : val;\n\n // throw error if nan\n if (isNaN(num)) throw new Error(`toInteger: ${val} is not a number`);\n if (num <= 0) throw new Error(`toInteger: te result ${num} is not positive`);\n\n return num;\n}\n\nfunction toString<T extends string | number | undefined, R = T extends undefined ? (string | undefined) : string> (x: T): R {\n if (x == undefined ) return undefined as R;\n if (typeof x == 'string' && !x.length) return undefined as R;\n if (isNumber(x) ) return x.toString() as R;\n return x.trim() as R;\n}\n\nfunction extractLocations (\n course: Types.Course,\n locationsNameMap: Map<string, C_Location>,\n warnings: { code: Types.ErrorCode, context?: unknown }[],\n) {\n const locationsStr = toString(course.locations);\n if (!locationsStr) return undefined;\n\n const locationReferences: { groupIndex: number; to: string }[] = [];\n\n locationsStr.split('+')\n .flatMap((x, i) => x.split(',').map(x => [i, x.trim()] as [number, string]))\n .forEach(([i, x]) => {\n const key = x.toLowerCase();\n const ref = locationsNameMap.get(key);\n if (!ref) {\n warnings.push({ code: 'invalid_location_reference', context: x });\n return;\n }\n\n if (locationReferences.some(y => y.to == ref.id)) {\n warnings.push({ code: 'location_referenced_multiple_times', context: x });\n return;\n }\n\n locationReferences.push({ groupIndex: i, to: ref.id });\n });\n\n return locationReferences;\n}\n\nfunction extractGroups (\n course: Types.Course,\n groupsNameMap: Map<string, C_Group>,\n warnings: { code: Types.ErrorCode, context?: unknown }[],\n) {\n const groupsStr = toString(course.groups);\n if (!groupsStr) return undefined;\n\n const groupReferences: { to: string }[] = [];\n groupsStr.split(',').map(x => x.trim())\n .forEach(x => {\n const key = x.toLowerCase();\n const ref = groupsNameMap.get(key);\n if (!ref) {\n warnings.push({ code: 'invalid_group_reference', context: x });\n return;\n }\n\n if (groupReferences.some(y => y.to == ref.id)) {\n warnings.push({ code: 'group_referenced_multiple_times', context: x });\n return;\n }\n\n groupReferences.push({ to: ref.id });\n });\n\n return groupReferences;\n}\n\nfunction extractTeachers (\n course: Types.Course,\n teachersNameMap: Map<string, C_Teacher>,\n warnings: { code: Types.ErrorCode, context?: unknown }[],\n) {\n const teachersStr = toString(course.teachers);\n if (!teachersStr) return undefined;\n\n const teacherReferences: { to: string }[] = [];\n teachersStr.split(',').map(x => x.trim())\n .forEach(x => {\n const key = x.toLowerCase();\n const ref = teachersNameMap.get(key);\n if (!ref) {\n warnings.push({ code: 'invalid_teacher_reference', context: x });\n return;\n }\n\n if (teacherReferences.some(y => y.to == ref.id)) {\n warnings.push({ code: 'teacher_referenced_multiple_times', context: x });\n return;\n }\n\n teacherReferences.push({ to: ref.id });\n });\n\n return teacherReferences;\n}\n\nfunction extractSyllabus (\n course: Types.Course,\n syllabusesCodeMap: Map<string, C_Syllabus>,\n syllabusesNameMap: Map<string, C_Syllabus>,\n warnings: { code: Types.ErrorCode, context?: unknown }[],\n): string | undefined {\n const syllabusValue = toString(course.syllabus);\n if (!syllabusValue) return undefined;\n\n const syllabus = syllabusesCodeMap.get(syllabusValue) || syllabusesNameMap.get(syllabusValue.toLowerCase());\n\n if (!syllabus) {\n warnings.push({ code: 'invalid_syllabus_reference', context: syllabusValue });\n return undefined;\n }\n\n return syllabus.id;\n}\n\n\nfunction _schedules (\n source: Types.Source\n): Out {\n // gather all import related warnings/errors\n const warnings: { code: Types.ErrorCode, context?: unknown }[] = [];\n // let errors: string[] = [];\n\n source.settings = source.settings ?.filter(x => Object.values(x).some(y => y.toString().trim().length > 0));\n source.locations = source.locations?.filter(x => Object.values(x).some(y => y.toString().trim().length > 0));\n source.teachers = source.teachers ?.filter(x => Object.values(x).some(y => y.toString().trim().length > 0));\n source.groups = source.groups ?.filter(x => Object.values(x).some(y => y.toString().trim().length > 0));\n source.persons = source.persons ?.filter(x => Object.values(x).some(y => y.toString().trim().length > 0));\n source.courses = source.courses ?.filter(x => Object.values(x).some(y => y.toString().trim().length > 0));\n\n\n ////\n //// settings\n ////\n const settings: C_Settings = {\n discretization: 5,\n numDays: 5,\n dayStart: '08:00',\n dayEnd: '17:00',\n };\n if (!source.settings) {\n warnings.push({ code: 'missing_settings_sheet' });\n }\n if (source.settings?.[0]?.number_of_days) {\n const numDays = source.settings?.[0]?.number_of_days;\n try {\n settings.numDays = toPositiveInteger(numDays);\n\n // must be 5 or 7\n if (settings.numDays !== 5 && settings.numDays !== 7) {\n warnings.push({ code: 'invalid_number_of_days', context: numDays });\n settings.numDays = 5;\n }\n } catch {\n warnings.push({ code: 'invalid_number_of_days', context: numDays });\n }\n }\n\n ////\n //// syllabuses\n ////\n const syllabusesIdMap = new Map<string, C_Syllabus>();\n const syllabusesNameMap = new Map<string, C_Syllabus>();\n const syllabusesCodeMap = new Map<string, C_Syllabus>();\n if (!source.syllabuses) {\n // warnings.push({ code: 'missing_syllabus_sheet' });\n }\n source.syllabuses?.forEach(x => {\n const ids = toString(x.foreign_ID);\n const subjectCode = toString(x.subject_code);\n const subjectName = toString(x.subject_name);\n const courseCode = toString(x.course_code );\n const courseName = toString(x.course_name );\n const schoolType = toString(x.school_type);\n\n const id = x.ID?.toString() ?? generateId(syllabusesIdMap);\n if (syllabusesIdMap.has(id)) {\n warnings.push({ code: 'ignoring_duplicate_syllabus', context: `${subjectName} (${courseName})` });\n return;\n }\n\n if (!subjectName) {\n warnings.push({ code: 'missing_subject_name', context: x });\n return;\n }\n\n if (!schoolType) {\n warnings.push({ code: 'missing_school_type', context: x });\n return;\n }\n\n // create the syllabus object\n const y: C_Syllabus = {\n id,\n ...ids && { ids },\n ...subjectCode && { subjectCode },\n subjectName,\n ...courseCode && { courseCode },\n ...courseName && { courseName },\n schoolType,\n official: true, // always true for imported syllabuses\n __raw: x\n };\n syllabusesIdMap.set(id, y);\n const code = courseCode || subjectCode;\n const name = courseName || subjectName;\n if (code) syllabusesCodeMap.set(code, y);\n if (name) syllabusesNameMap.set(name.toLowerCase(), y);\n });\n\n\n ////\n //// locations, teachers\n ////\n const locationsIdMap = new Map<string, C_Location>();\n const locationsNameMap = new Map<string, C_Location>();\n const teachersIdMap = new Map<string, C_Teacher>();\n const teachersNameMap = new Map<string, C_Teacher>();\n [\n {\n name: { singular: 'location', plural: 'locations' } as const,\n data: source.locations,\n idMap: locationsIdMap,\n nameMap: locationsNameMap,\n },\n {\n name: { singular: 'teacher', plural: 'teachers' } as const,\n data: source.teachers,\n idMap: teachersIdMap,\n nameMap: teachersNameMap,\n }\n ].forEach(({ name, data, idMap, nameMap }) => {\n if (!data) {\n warnings.push({ code: `missing_${name.plural}_sheet` });\n }\n data?.forEach(x => {\n const ids = toString(x.foreign_ID);\n const displayName = toString(x.name);\n\n const id = x.ID?.toString() ?? generateId(idMap);\n if (idMap.has(id)) {\n warnings.push({ code: `ignoring_duplicate_${name.singular}`, context: displayName });\n return;\n }\n\n const y = {\n id,\n ...ids && { ids },\n ...displayName && { displayName },\n __raw: x\n };\n idMap.set(id, y);\n if (displayName) nameMap.set(displayName.toLowerCase(), y);\n });\n });\n\n\n ////\n //// groups\n ////\n const groupsIdMap = new Map<string, C_Group>();\n const groupsNameMap = new Map<string, C_Group>();\n if (!source.groups) {\n warnings.push({ code: 'missing_groups_sheet' });\n }\n source.groups?.forEach(x => {\n const ids = toString(x.foreign_ID);\n const displayName = toString(x.name);\n\n const id = x.ID?.toString() ?? generateId(groupsIdMap);\n if (groupsIdMap.has(id)) {\n warnings.push({ code: 'ignoring_duplicate_group', context: displayName });\n return;\n }\n\n // parent groups determine the species of the group\n const species = toString(x.is_class) == '1' ? 'class' as const : undefined;\n\n const y = {\n id,\n ...ids && { ids },\n ...displayName && { displayName },\n ...species && { species },\n __raw: x\n };\n groupsIdMap.set(id, y);\n if (displayName) groupsNameMap.set(displayName.toLowerCase(), y);\n });\n\n\n ////\n //// persons\n ////\n const personsIdMap = new Map<string, C_Person>();\n const personsSsnMap = new Map<string, C_Person>();\n if (!source.persons) {\n warnings.push({ code: 'missing_persons_sheet' });\n }\n source.persons?.forEach(x => {\n const ids = toString(x.foreign_ID);\n const firstName = toString(x.first_name);\n const lastName = toString(x.last_name );\n const SSN = toString(x.SSN );\n\n const id = x.ID?.toString() ?? generateId(personsIdMap);\n if (personsIdMap.has(id)) {\n warnings.push({ code: 'ignoring_duplicate_person', context: `${firstName} ${lastName}` });\n return;\n }\n\n let group: string | undefined = undefined;\n if (x.group) {\n const key = toString(x.group).toLowerCase();\n const ref = groupsNameMap.get(key);\n if (!ref) {\n warnings.push({ code: 'invalid_group_reference', context: x.group });\n } else if (ref.species !== 'class') {\n warnings.push({ code: 'forbidden_group_reference', context: x.group });\n } else {\n group = ref.id;\n }\n }\n\n let sex: C_Person['sex'];\n if (x.sex) {\n if (isString(x.sex) && x.sex.toLowerCase() == 'man') sex = 'Man';\n else if (isString(x.sex) && x.sex.toLowerCase() == 'woman') sex = 'Woman';\n else {\n warnings.push({ code: 'invalid_sex', context: x.sex });\n }\n }\n\n const person: C_Person = {\n id,\n ...ids && { ids },\n ...firstName && { firstName },\n ...lastName && { lastName },\n ...sex && { sex },\n ...group && { group },\n ...SSN && { SSN: { value: SSN } },\n __raw: x\n };\n personsIdMap.set(id, person);\n if (SSN) personsSsnMap.set(SSN, person);\n });\n\n\n ////\n //// group.members (need to wait for persons to be parsed)\n ////\n groupsNameMap.forEach(x => {\n let duplicateReported = false;\n\n // parse and replace SSN by person id\n x.members = chain(toString(x.__raw.members))\n .split(',')\n .map(x => x.trim())\n .filter(Boolean)\n .countBy()\n .map((count, ssn) => {\n // warn if duplicate member\n if (!duplicateReported && count > 1) {\n warnings.push({ code: 'duplicate_group_member', context: x.displayName });\n duplicateReported = true;\n }\n\n // fetch person and warn if not found\n const person = personsSsnMap.get(ssn);\n if (!person) {\n warnings.push({ code: 'invalid_person_reference', context: ssn });\n return;\n }\n\n // warn if the group is a class and the person is already in a different class\n // (we also need to set the group of the person if it is empty)\n if (x.species == 'class') {\n if (!person.group) {\n person.group = x.id;\n }\n else if (person.group != x.id) {\n warnings.push({ code: 'person_in_multiple_classes', context: ssn });\n return;\n }\n }\n\n return person.id;\n })\n .filter((x): x is NonNullable<typeof x> => !!x)\n .value();\n });\n\n\n ////\n //// courses\n ////\n const coursesIdMap = new Map<string, C_Course >();\n const eventsIdMap = new Map<string, C_Event >();\n const overlapGroupsKeyMap = new Map<string, C_OverlapGroup>();\n if (!source.courses) {\n warnings.push({ code: 'missing_courses_sheet' });\n }\n source.courses?.forEach(x => {\n // await loading events until courses are created\n const mergeWith = toString(x.merge_with);\n if (mergeWith) return;\n\n const ids = toString(x.foreign_ID);\n const displayName = toString(x.name)?.trim();\n const subject = toString(x.subject);\n\n const courseId = x.ID?.toString() ?? generateId(coursesIdMap);\n if (coursesIdMap.has(courseId)) {\n warnings.push({ code: 'ignoring_duplicate_course', context: displayName + (subject ? ` (${subject})` : '') });\n return;\n }\n\n // try to parse the total hours as an integer\n let expectedTotalHours: number | undefined = undefined;\n if (x.total_hours) {\n try {\n expectedTotalHours = toPositiveInteger(x.total_hours);\n } catch {\n warnings.push({ code: 'invalid_total_hours', context: x.total_hours });\n }\n }\n\n // try to parse the minutes per week as an multiple of 5\n let minutesPerWeek: number | undefined = undefined;\n if (x.minutes_per_week) {\n try {\n minutesPerWeek = toPositiveMultipleOf5(x.minutes_per_week);\n } catch {\n warnings.push({ code: 'invalid_minutes_per_week', context: x.minutes_per_week });\n }\n }\n\n // only one of minutes_per_week or total_hours should be defined\n if (minutesPerWeek != null && expectedTotalHours != null) {\n warnings.push({ code: 'ambiguous_planned_duration', context: `${minutesPerWeek} min/week OR ${expectedTotalHours} hrs` });\n }\n const plannedDuration =\n expectedTotalHours\n ? `${expectedTotalHours} hrs` :\n minutesPerWeek\n ? `${minutesPerWeek} min/week` :\n undefined;\n\n\n // try to parse the lesson durations as an array of integers from which we will generate events\n if (x.lesson_durations) {\n const _durations = typeof x.lesson_durations === 'string'\n ? x.lesson_durations.split(',').map(x => x.trim())\n : [x.lesson_durations];\n\n // truncate to multiple of 5 and filter out zero duration events\n const durations = _durations\n .map(e => {\n try {\n return toPositiveMultipleOf5(e);\n } catch {\n warnings.push({ code: 'invalid_lesson_durations', context: x.lesson_durations });\n return undefined;\n }\n })\n .filter((x): x is number => x !== undefined);\n\n durations.forEach(x => {\n const id = generateId(eventsIdMap);\n const event: C_Event = { id, course: courseId, preferredDuration: x };\n eventsIdMap.set(id, event);\n });\n }\n\n // overlap group\n if (x.overlap_group && toString(x.overlap_group)) {\n const key = toString(x.overlap_group).toLowerCase();\n\n const og = overlapGroupsKeyMap.get(key);\n if (og) og.coalesced?.push({ toModel: 'courses', to: courseId });\n else {\n const id = generateId(overlapGroupsKeyMap);\n const coalesced = [{ toModel: 'courses' as const, to: courseId }];\n overlapGroupsKeyMap.set(key, { id, coalesced });\n }\n }\n\n const locations = extractLocations(x, locationsNameMap, warnings)?.map(x => ({ groupIndex: x.groupIndex, locations: [x.to] as [string] }));\n const groups = extractGroups (x, groupsNameMap, warnings);\n const teachers = extractTeachers (x, teachersNameMap, warnings);\n const syllabus = extractSyllabus(x, syllabusesCodeMap, syllabusesNameMap, warnings);\n\n const course: C_Course = {\n id: courseId,\n ...ids && { ids },\n ...displayName && { displayName },\n ...subject && { subject },\n /* TO BE DEPRECATED */ ...expectedTotalHours && { expectedTotalHours },\n /* TO BE DEPRECATED */ ...minutesPerWeek && { minutesPerWeek },\n ...plannedDuration && { plannedDuration },\n ...groups && { groups },\n ...teachers && { teachers },\n ...locations && { locations },\n ...syllabus && { syllabus },\n __raw: x\n };\n coursesIdMap.set(courseId, course);\n });\n\n\n ////\n //// events\n ////\n source.courses?.forEach(x => {\n // load courses\n const mergeWith = toString(x.merge_with);\n if (!mergeWith) return;\n\n // ensure that the course to merge with exists\n if (!coursesIdMap.has(mergeWith)) {\n warnings.push({ code: 'invalid_course_reference', context: mergeWith });\n return;\n }\n\n const displayName = toString(x.name)?.trim();\n const locations = extractLocations(x, locationsNameMap, warnings)?.map(x => ({ groupIndex: x.groupIndex, locations: [x.to] as [string] }));\n const groups = extractGroups (x, groupsNameMap, warnings);\n const teachers = extractTeachers (x, teachersNameMap, warnings);\n\n // try to parse the lesson durations as an array of integers from which we will generate events\n if (x.lesson_durations) {\n const _durations = typeof x.lesson_durations === 'string'\n ? x.lesson_durations.split(',').map(x => x.trim())\n : [x.lesson_durations];\n\n // truncate to multiple of 5 and filter out zero duration events\n const durations = _durations\n .map(e => {\n try {\n return toPositiveMultipleOf5(e);\n } catch {\n warnings.push({ code: 'invalid_lesson_durations', context: x.lesson_durations });\n return undefined;\n }\n })\n .filter((x): x is number => x !== undefined);\n\n durations.forEach(preferredDuration => {\n const id = generateId(eventsIdMap);\n const event: C_Event = {\n id,\n course: mergeWith,\n preferredDuration: preferredDuration,\n ...displayName && { displayName },\n ...groups && { groups },\n ...teachers && { teachers },\n ...locations && { locations },\n __raw: x\n };\n eventsIdMap.set(id, event);\n });\n }\n });\n\n\n ////\n //// return\n ////\n return {\n settings,\n locations: [...locationsIdMap .values()],\n teachers: [...teachersIdMap .values()],\n persons: [...personsIdMap .values()],\n groups: [...groupsIdMap .values()],\n courses: [...coursesIdMap .values()],\n events: [...eventsIdMap .values()],\n overlapGroups: [...overlapGroupsKeyMap.values()],\n syllabuses: [...syllabusesIdMap .values()],\n meta: {\n // ...errors .length && { errors: errors },\n ...warnings.length && { warnings: warnings }\n }\n };\n}\n\n\nexport default {\n schedules: _schedules\n} satisfies FromInterface;"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["id: string","map","locationReferences: { groupIndex: number; to: string }[]","x","groupReferences: { to: string }[]","teacherReferences: { to: string }[]","warnings: { code: Types.ErrorCode, context?: unknown }[]","settings: C_Settings","y: C_Syllabus","group: string | undefined","sex: C_Person['sex']","person: C_Person","expectedTotalHours: number | undefined","minutesPerWeek: number | undefined","event: C_Event","course: C_Course"],"sources":["../../../../src/Excel/v2/from/index.ts"],"sourcesContent":["import { isString, chain, isNumber } from 'lodash-es';\nimport { nanoid } from 'nanoid';\nimport type { CoreTypes } from '../../../core';\nimport type { Types } from '../types';\nimport type { FromInterface } from '../../../common/types';\n\ntype C_Settings = Pick<CoreTypes.serialized.divisionSettings, 'discretization' | 'numDays' | 'dayStart' | 'dayEnd'>;\ntype C_Location = CoreTypes.serialized.location & { id: string } & { __raw: Types.Location };\ntype C_Group = CoreTypes.serialized.group & { id: string } & { __raw: Types.Group };\ntype C_Teacher = CoreTypes.serialized.teacher & { id: string } & { __raw: Types.Teacher };\ntype C_Course = CoreTypes.serialized.course & { id: string } & { __raw: Types.Course };\ntype C_Person = CoreTypes.serialized.person & { id: string } & { __raw: Types.Person };\ntype C_Event = CoreTypes.serialized.event & { id: string } & { __raw?: Types.Course };\ntype C_OverlapGroup = CoreTypes.serialized.overlapGroup & { id: string } & { /* raw: Types.OverlapGroup */ };\ntype C_Syllabus = CoreTypes.serialized.syllabus & { id: string } & { __raw?: Types.Syllabus };\n\ntype Out = {\n settings: C_Settings;\n locations: C_Location[];\n teachers: C_Teacher[];\n persons: C_Person[];\n groups: C_Group[];\n courses: C_Course[];\n events: C_Event[];\n overlapGroups: C_OverlapGroup[];\n syllabuses: C_Syllabus[];\n meta: {\n // errors?: string[];\n warnings?: { code: Types.ErrorCode, context?: unknown }[];\n };\n};\n\n\nfunction generateId (map: Map<string, unknown>) {\n // generate a unique id\n let id: string;\n do {\n id = nanoid(8);\n } while (map.has(id));\n\n return id;\n}\n\nfunction toPositiveMultipleOf5 (val: number | string) {\n const num = isString(val) ? parseInt(val) : val;\n\n // throw error if nan\n if (isNaN(num)) throw new Error(`toMultipleOf5: ${val} is not a number`);\n\n const res = Math.floor(num / 5) * 5;\n\n if (res <= 0) throw new Error(`toMultipleOf5: the result ${res} is not positive`);\n\n return res;\n}\n\nfunction toPositiveInteger (val: number | string) {\n const num = isString(val) ? parseInt(val) : val;\n\n // throw error if nan\n if (isNaN(num)) throw new Error(`toInteger: ${val} is not a number`);\n if (num <= 0) throw new Error(`toInteger: te result ${num} is not positive`);\n\n return num;\n}\n\nfunction toString<T extends string | number | undefined, R = T extends undefined ? (string | undefined) : string> (x: T): R {\n if (x == undefined ) return undefined as R;\n if (typeof x == 'string' && !x.length) return undefined as R;\n if (isNumber(x) ) return x.toString() as R;\n return x.trim() as R;\n}\n\nfunction extractLocations (\n course: Types.Course,\n locationsNameMap: Map<string, C_Location>,\n warnings: { code: Types.ErrorCode, context?: unknown }[],\n) {\n const locationsStr = toString(course.locations);\n if (!locationsStr) return undefined;\n\n const locationReferences: { groupIndex: number; to: string }[] = [];\n\n locationsStr.split('+')\n .flatMap((x, i) => x.split(',').map(x => [i, x.trim()] as [number, string]))\n .forEach(([i, x]) => {\n const key = x.toLowerCase();\n const ref = locationsNameMap.get(key);\n if (!ref) {\n warnings.push({ code: 'invalid_location_reference', context: x });\n return;\n }\n\n if (locationReferences.some(y => y.to == ref.id)) {\n warnings.push({ code: 'location_referenced_multiple_times', context: x });\n return;\n }\n\n locationReferences.push({ groupIndex: i, to: ref.id });\n });\n\n return locationReferences;\n}\n\nfunction extractGroups (\n course: Types.Course,\n groupsNameMap: Map<string, C_Group>,\n warnings: { code: Types.ErrorCode, context?: unknown }[],\n) {\n const groupsStr = toString(course.groups);\n if (!groupsStr) return undefined;\n\n const groupReferences: { to: string }[] = [];\n groupsStr.split(',').map(x => x.trim())\n .forEach(x => {\n const key = x.toLowerCase();\n const ref = groupsNameMap.get(key);\n if (!ref) {\n warnings.push({ code: 'invalid_group_reference', context: x });\n return;\n }\n\n if (groupReferences.some(y => y.to == ref.id)) {\n warnings.push({ code: 'group_referenced_multiple_times', context: x });\n return;\n }\n\n groupReferences.push({ to: ref.id });\n });\n\n return groupReferences;\n}\n\nfunction extractTeachers (\n course: Types.Course,\n teachersNameMap: Map<string, C_Teacher>,\n warnings: { code: Types.ErrorCode, context?: unknown }[],\n) {\n const teachersStr = toString(course.teachers);\n if (!teachersStr) return undefined;\n\n const teacherReferences: { to: string }[] = [];\n teachersStr.split(',').map(x => x.trim())\n .forEach(x => {\n const key = x.toLowerCase();\n const ref = teachersNameMap.get(key);\n if (!ref) {\n warnings.push({ code: 'invalid_teacher_reference', context: x });\n return;\n }\n\n if (teacherReferences.some(y => y.to == ref.id)) {\n warnings.push({ code: 'teacher_referenced_multiple_times', context: x });\n return;\n }\n\n teacherReferences.push({ to: ref.id });\n });\n\n return teacherReferences;\n}\n\nfunction extractSyllabus (\n course: Types.Course,\n syllabusesCodeMap: Map<string, C_Syllabus>,\n syllabusesNameMap: Map<string, C_Syllabus>,\n warnings: { code: Types.ErrorCode, context?: unknown }[],\n): string | undefined {\n const syllabusValue = toString(course.syllabus);\n if (!syllabusValue) return undefined;\n\n const syllabus = syllabusesCodeMap.get(syllabusValue) || syllabusesNameMap.get(syllabusValue.toLowerCase());\n\n if (!syllabus) {\n warnings.push({ code: 'invalid_syllabus_reference', context: syllabusValue });\n return undefined;\n }\n\n return syllabus.id;\n}\n\n\nfunction _schedules (\n source: Types.Source\n): Out {\n // gather all import related warnings/errors\n const warnings: { code: Types.ErrorCode, context?: unknown }[] = [];\n // let errors: string[] = [];\n\n source.settings = source.settings ?.filter(x => Object.values(x).some(y => y.toString().trim().length > 0));\n source.locations = source.locations?.filter(x => Object.values(x).some(y => y.toString().trim().length > 0));\n source.teachers = source.teachers ?.filter(x => Object.values(x).some(y => y.toString().trim().length > 0));\n source.groups = source.groups ?.filter(x => Object.values(x).some(y => y.toString().trim().length > 0));\n source.persons = source.persons ?.filter(x => Object.values(x).some(y => y.toString().trim().length > 0));\n source.courses = source.courses ?.filter(x => Object.values(x).some(y => y.toString().trim().length > 0));\n\n\n ////\n //// settings\n ////\n const settings: C_Settings = {\n discretization: 5,\n numDays: 5,\n dayStart: '08:00',\n dayEnd: '17:00',\n };\n if (!source.settings) {\n warnings.push({ code: 'missing_settings_sheet' });\n }\n if (source.settings?.[0]?.number_of_days) {\n const numDays = source.settings?.[0]?.number_of_days;\n try {\n settings.numDays = toPositiveInteger(numDays);\n\n // must be 5 or 7\n if (settings.numDays !== 5 && settings.numDays !== 7) {\n warnings.push({ code: 'invalid_number_of_days', context: numDays });\n settings.numDays = 5;\n }\n } catch {\n warnings.push({ code: 'invalid_number_of_days', context: numDays });\n }\n }\n\n ////\n //// syllabuses\n ////\n const syllabusesIdMap = new Map<string, C_Syllabus>();\n const syllabusesNameMap = new Map<string, C_Syllabus>();\n const syllabusesCodeMap = new Map<string, C_Syllabus>();\n if (!source.syllabuses) {\n // warnings.push({ code: 'missing_syllabus_sheet' });\n }\n source.syllabuses?.forEach(x => {\n const ids = toString(x.foreign_ID);\n const subjectCode = toString(x.subject_code);\n const subjectName = toString(x.subject_name);\n const courseCode = toString(x.course_code );\n const courseName = toString(x.course_name );\n const schoolType = toString(x.school_type);\n\n const id = x.ID?.toString() ?? generateId(syllabusesIdMap);\n if (syllabusesIdMap.has(id)) {\n warnings.push({ code: 'ignoring_duplicate_syllabus', context: `${subjectName} (${courseName})` });\n return;\n }\n\n if (!subjectName) {\n warnings.push({ code: 'missing_subject_name', context: x });\n return;\n }\n\n if (!schoolType) {\n warnings.push({ code: 'missing_school_type', context: x });\n return;\n }\n\n // create the syllabus object\n const y: C_Syllabus = {\n id,\n ...ids && { ids },\n ...subjectCode && { subjectCode },\n subjectName,\n ...courseCode && { courseCode },\n ...courseName && { courseName },\n schoolType,\n official: true, // always true for imported syllabuses\n __raw: x\n };\n syllabusesIdMap.set(id, y);\n const code = courseCode || subjectCode;\n const name = courseName || subjectName;\n if (code) syllabusesCodeMap.set(code, y);\n if (name) syllabusesNameMap.set(name.toLowerCase(), y);\n });\n\n\n ////\n //// locations, teachers\n ////\n const locationsIdMap = new Map<string, C_Location>();\n const locationsNameMap = new Map<string, C_Location>();\n const teachersIdMap = new Map<string, C_Teacher>();\n const teachersNameMap = new Map<string, C_Teacher>();\n [\n {\n name: { singular: 'location', plural: 'locations' } as const,\n data: source.locations,\n idMap: locationsIdMap,\n nameMap: locationsNameMap,\n },\n {\n name: { singular: 'teacher', plural: 'teachers' } as const,\n data: source.teachers,\n idMap: teachersIdMap,\n nameMap: teachersNameMap,\n }\n ].forEach(({ name, data, idMap, nameMap }) => {\n if (!data) {\n warnings.push({ code: `missing_${name.plural}_sheet` });\n }\n data?.forEach(x => {\n const ids = toString(x.foreign_ID);\n const displayName = toString(x.name);\n\n const id = x.ID?.toString() ?? generateId(idMap);\n if (idMap.has(id)) {\n warnings.push({ code: `ignoring_duplicate_${name.singular}`, context: displayName });\n return;\n }\n\n const y = {\n id,\n ...ids && { ids },\n ...displayName && { displayName },\n __raw: x\n };\n idMap.set(id, y);\n if (displayName) nameMap.set(displayName.toLowerCase(), y);\n });\n });\n\n\n ////\n //// groups\n ////\n const groupsIdMap = new Map<string, C_Group>();\n const groupsNameMap = new Map<string, C_Group>();\n if (!source.groups) {\n warnings.push({ code: 'missing_groups_sheet' });\n }\n source.groups?.forEach(x => {\n const ids = toString(x.foreign_ID);\n const displayName = toString(x.name);\n\n const id = x.ID?.toString() ?? generateId(groupsIdMap);\n if (groupsIdMap.has(id)) {\n warnings.push({ code: 'ignoring_duplicate_group', context: displayName });\n return;\n }\n\n // parent groups determine the species of the group\n const species = toString(x.is_class) == '1' ? 'class' as const : undefined;\n\n const y = {\n id,\n ...ids && { ids },\n ...displayName && { displayName },\n ...species && { species },\n __raw: x\n };\n groupsIdMap.set(id, y);\n if (displayName) groupsNameMap.set(displayName.toLowerCase(), y);\n });\n\n\n ////\n //// persons\n ////\n const personsIdMap = new Map<string, C_Person>();\n const personsSsnMap = new Map<string, C_Person>();\n if (!source.persons) {\n warnings.push({ code: 'missing_persons_sheet' });\n }\n source.persons?.forEach(x => {\n const ids = toString(x.foreign_ID);\n const firstName = toString(x.first_name);\n const lastName = toString(x.last_name );\n const SSN = toString(x.SSN );\n\n const id = x.ID?.toString() ?? generateId(personsIdMap);\n if (personsIdMap.has(id)) {\n warnings.push({ code: 'ignoring_duplicate_person', context: `${firstName} ${lastName}` });\n return;\n }\n\n let group: string | undefined = undefined;\n if (x.group) {\n const key = toString(x.group).toLowerCase();\n const ref = groupsNameMap.get(key);\n if (!ref) {\n warnings.push({ code: 'invalid_group_reference', context: x.group });\n } else if (ref.species !== 'class') {\n warnings.push({ code: 'forbidden_group_reference', context: x.group });\n } else {\n group = ref.id;\n }\n }\n\n let sex: C_Person['sex'];\n if (x.sex) {\n if (isString(x.sex) && x.sex.toLowerCase() == 'man') sex = 'Man';\n else if (isString(x.sex) && x.sex.toLowerCase() == 'woman') sex = 'Woman';\n else {\n warnings.push({ code: 'invalid_sex', context: x.sex });\n }\n }\n\n const person: C_Person = {\n id,\n ...ids && { ids },\n ...firstName && { firstName },\n ...lastName && { lastName },\n ...sex && { sex },\n ...group && { group },\n ...SSN && { SSN: { value: SSN } },\n __raw: x\n };\n personsIdMap.set(id, person);\n if (SSN) personsSsnMap.set(SSN, person);\n });\n\n\n ////\n //// group.members (need to wait for persons to be parsed)\n ////\n groupsNameMap.forEach(x => {\n let duplicateReported = false;\n\n // parse and replace SSN by person id\n x.members = chain(toString(x.__raw.members))\n .split(',')\n .map(x => x.trim())\n .filter(Boolean)\n .countBy()\n .map((count, ssn) => {\n // warn if duplicate member\n if (!duplicateReported && count > 1) {\n warnings.push({ code: 'duplicate_group_member', context: x.displayName });\n duplicateReported = true;\n }\n\n // fetch person and warn if not found\n const person = personsSsnMap.get(ssn);\n if (!person) {\n warnings.push({ code: 'invalid_person_reference', context: ssn });\n return;\n }\n\n // warn if the group is a class and the person is already in a different class\n // (we also need to set the group of the person if it is empty)\n if (x.species == 'class') {\n if (!person.group) {\n person.group = x.id;\n }\n else if (person.group != x.id) {\n warnings.push({ code: 'person_in_multiple_classes', context: ssn });\n return;\n }\n }\n\n return person.id;\n })\n .filter((x): x is NonNullable<typeof x> => !!x)\n .value();\n });\n\n\n ////\n //// courses\n ////\n const coursesIdMap = new Map<string, C_Course >();\n const eventsIdMap = new Map<string, C_Event >();\n const overlapGroupsKeyMap = new Map<string, C_OverlapGroup>();\n if (!source.courses) {\n warnings.push({ code: 'missing_courses_sheet' });\n }\n source.courses?.forEach(x => {\n // await loading events until courses are created\n const mergeWith = toString(x.merge_with);\n if (mergeWith) return;\n\n const ids = toString(x.foreign_ID);\n const displayName = toString(x.name)?.trim();\n const subject = toString(x.subject);\n\n const courseId = x.ID?.toString() ?? generateId(coursesIdMap);\n if (coursesIdMap.has(courseId)) {\n warnings.push({ code: 'ignoring_duplicate_course', context: displayName + (subject ? ` (${subject})` : '') });\n return;\n }\n\n // try to parse the total hours as an integer\n let expectedTotalHours: number | undefined = undefined;\n if (x.total_hours) {\n try {\n expectedTotalHours = toPositiveInteger(x.total_hours);\n } catch {\n warnings.push({ code: 'invalid_total_hours', context: x.total_hours });\n }\n }\n\n // try to parse the minutes per week as an multiple of 5\n let minutesPerWeek: number | undefined = undefined;\n if (x.minutes_per_week) {\n try {\n minutesPerWeek = toPositiveMultipleOf5(x.minutes_per_week);\n } catch {\n warnings.push({ code: 'invalid_minutes_per_week', context: x.minutes_per_week });\n }\n }\n\n // only one of minutes_per_week or total_hours should be defined\n if (minutesPerWeek != null && expectedTotalHours != null) {\n warnings.push({ code: 'ambiguous_planned_duration', context: `${minutesPerWeek} min/week OR ${expectedTotalHours} hrs` });\n }\n const plannedDuration =\n expectedTotalHours\n ? `${expectedTotalHours} hrs` :\n minutesPerWeek\n ? `${minutesPerWeek} min/week` :\n undefined;\n\n\n // try to parse the lesson durations as an array of integers from which we will generate events\n if (x.lesson_durations) {\n const _durations = typeof x.lesson_durations === 'string'\n ? x.lesson_durations.split(',').map(x => x.trim())\n : [x.lesson_durations];\n\n // truncate to multiple of 5 and filter out zero duration events\n const durations = _durations\n .map(e => {\n try {\n return toPositiveMultipleOf5(e);\n } catch {\n warnings.push({ code: 'invalid_lesson_durations', context: x.lesson_durations });\n return undefined;\n }\n })\n .filter((x): x is number => x !== undefined);\n\n durations.forEach(x => {\n const id = generateId(eventsIdMap);\n const event: C_Event = { id, course: courseId, preferredDuration: x };\n eventsIdMap.set(id, event);\n });\n }\n\n // overlap group\n if (x.overlap_group && toString(x.overlap_group)) {\n const key = toString(x.overlap_group).toLowerCase();\n\n const og = overlapGroupsKeyMap.get(key);\n if (og) og.coalesced?.push({ toModel: 'courses', to: courseId });\n else {\n const id = generateId(overlapGroupsKeyMap);\n const coalesced = [{ toModel: 'courses' as const, to: courseId }];\n overlapGroupsKeyMap.set(key, { id, coalesced });\n }\n }\n\n const locations = extractLocations(x, locationsNameMap, warnings)?.map(x => ({ groupIndex: x.groupIndex, locations: [x.to] as [string] }));\n const groups = extractGroups (x, groupsNameMap, warnings);\n const teachers = extractTeachers (x, teachersNameMap, warnings);\n const syllabus = extractSyllabus(x, syllabusesCodeMap, syllabusesNameMap, warnings);\n\n const course: C_Course = {\n id: courseId,\n ...ids && { ids },\n ...displayName && { displayName },\n ...subject && { subject },\n /* TO BE DEPRECATED */ ...expectedTotalHours && { expectedTotalHours },\n /* TO BE DEPRECATED */ ...minutesPerWeek && { minutesPerWeek },\n ...plannedDuration && { plannedDuration },\n ...groups && { groups },\n ...teachers && { teachers },\n ...locations && { locations },\n ...syllabus && { syllabus },\n __raw: x\n };\n coursesIdMap.set(courseId, course);\n });\n\n\n ////\n //// events\n ////\n source.courses?.forEach(x => {\n // load courses\n const mergeWith = toString(x.merge_with);\n if (!mergeWith) return;\n\n // ensure that the course to merge with exists\n if (!coursesIdMap.has(mergeWith)) {\n warnings.push({ code: 'invalid_course_reference', context: mergeWith });\n return;\n }\n\n const displayName = toString(x.name)?.trim();\n const locations = extractLocations(x, locationsNameMap, warnings)?.map(x => ({ groupIndex: x.groupIndex, locations: [x.to] as [string] }));\n const groups = extractGroups (x, groupsNameMap, warnings);\n const teachers = extractTeachers (x, teachersNameMap, warnings);\n\n // try to parse the lesson durations as an array of integers from which we will generate events\n if (x.lesson_durations) {\n const _durations = typeof x.lesson_durations === 'string'\n ? x.lesson_durations.split(',').map(x => x.trim())\n : [x.lesson_durations];\n\n // truncate to multiple of 5 and filter out zero duration events\n const durations = _durations\n .map(e => {\n try {\n return toPositiveMultipleOf5(e);\n } catch {\n warnings.push({ code: 'invalid_lesson_durations', context: x.lesson_durations });\n return undefined;\n }\n })\n .filter((x): x is number => x !== undefined);\n\n durations.forEach(preferredDuration => {\n const id = generateId(eventsIdMap);\n const event: C_Event = {\n id,\n course: mergeWith,\n preferredDuration: preferredDuration,\n ...displayName && { displayName },\n ...groups && { groups },\n ...teachers && { teachers },\n ...locations && { locations },\n __raw: x\n };\n eventsIdMap.set(id, event);\n });\n }\n });\n\n\n ////\n //// return\n ////\n return {\n settings,\n locations: [...locationsIdMap .values()],\n teachers: [...teachersIdMap .values()],\n persons: [...personsIdMap .values()],\n groups: [...groupsIdMap .values()],\n courses: [...coursesIdMap .values()],\n events: [...eventsIdMap .values()],\n overlapGroups: [...overlapGroupsKeyMap.values()],\n syllabuses: [...syllabusesIdMap .values()],\n meta: {\n // ...errors .length && { errors: errors },\n ...warnings.length && { warnings: warnings }\n }\n };\n}\n\n\nexport default {\n schedules: _schedules\n} satisfies FromInterface;"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { getDayIndex } from "../../core/util.js";
2
2
  import moment from "moment";
3
3
  import { Types } from "mongoose";
4
4
  import Papa from "papaparse";
5
- import { encode } from "iconv-lite";
5
+ import iconv from "iconv-lite";
6
6
 
7
7
  //#region src/InfoMentor/to/schedules.ts
8
8
  const days = [
@@ -50,7 +50,7 @@ var schedules_default = (courseEvents) => {
50
50
  delimiter
51
51
  };
52
52
  const csv = Papa.unparse(events, opts);
53
- return encode(csv, encoding);
53
+ return iconv.encode(csv, encoding);
54
54
  };
55
55
 
56
56
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"schedules.js","names":["MongooseTypes","doc: InfoMentorTypes.event"],"sources":["../../../src/InfoMentor/to/schedules.ts"],"sourcesContent":["import { Types as MongooseTypes } from 'mongoose';\nimport moment from 'moment';\nimport { encode } from 'iconv-lite';\nimport Papa from 'papaparse';\nimport type { Types as InfoMentorTypes } from '../types';\nimport type { CoreTypes } from '../../core';\nimport { getDayIndex } from '../../core/util';\n\nconst days = ['MÅN', 'TIS', 'ONS', 'TOR', 'FRE'];\nconst columns = ['Ämne', 'Dag', 'Starttid', 'Längd', 'Personal', 'Klasser', 'Salar'];\nconst delimiter = '\\t';\nconst encoding = 'windows-1252';\n\nexport default (courseEvents: CoreTypes.mixed.event[]): Buffer => {\n const events = courseEvents\n .map(event => {\n if (event.parked || !event.start || !event.end) return;\n\n const course = event.course;\n if (!course) return;\n\n const day = days.at(getDayIndex(event.start));\n if (!day) throw new Error('Invalid event day');\n\n if (typeof course != 'object' || course instanceof MongooseTypes.ObjectId)\n throw new Error('(InfoMentor::To::Schedules) Event course is not an deserialized object');\n\n const Personal = (event.teachers ?? course.teachers ?? []).map(({ to: x }) => typeof x == 'object' && 'displayName' in x ? x.displayName : null).filter(x => x != null).join(',');\n const Klasser = (event.groups ?? course.groups ?? []).map(({ to: x }) => typeof x == 'object' && 'displayName' in x ? x.displayName : null).filter(x => x != null).join(',');\n const Salar = (event.inLocations ?? []).map(x => x && typeof x == 'object' && 'displayName' in x ? x.displayName : null).filter(x => x != null).join(',');\n\n const doc: InfoMentorTypes.event ={\n Ämne: course.displayName,\n Dag: day,\n Starttid: moment.utc(event.start).format('HH.mm'),\n Längd: moment.utc(event.end).diff(moment.utc(event.start), 'minutes'),\n Personal,\n Klasser,\n Salar,\n };\n return doc;\n });\n\n const opts = { columns, delimiter };\n const csv = Papa.unparse(events, opts);\n return encode(csv, encoding);\n};\n"],"mappings":";;;;;;;AAQA,MAAM,OAAY;CAAC;CAAO;CAAO;CAAO;CAAO;;AAC/C,MAAM,UAAY;CAAC;CAAQ;CAAO;CAAY;CAAS;CAAY;CAAW;;AAC9E,MAAM,YAAY;AAClB,MAAM,WAAY;AAElB,yBAAgB,iBAAkD;CAChE,MAAM,SAAS,aACZ,KAAI,UAAS;AACZ,MAAI,MAAM,UAAU,CAAC,MAAM,SAAS,CAAC,MAAM,IAAK;EAEhD,MAAM,SAAS,MAAM;AACrB,MAAI,CAAC,OAAQ;EAEb,MAAM,MAAM,KAAK,GAAG,YAAY,MAAM;AACtC,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM;AAE1B,MAAI,OAAO,UAAU,YAAY,kBAAkBA,MAAc,SAC/D,OAAM,IAAI,MAAM;EAElB,MAAM,YAAY,MAAM,YAAY,OAAO,YAAY,IAAI,KAAK,EAAE,IAAI,QAAa,OAAO,KAAK,YAAY,iBAAiB,IAAI,EAAE,cAAc,MAAM,QAAO,MAAK,KAAK,MAAM,KAAK;EAClL,MAAM,WAAY,MAAM,UAAY,OAAO,UAAY,IAAI,KAAK,EAAE,IAAI,QAAa,OAAO,KAAK,YAAY,iBAAiB,IAAI,EAAE,cAAc,MAAM,QAAO,MAAK,KAAK,MAAM,KAAK;EAClL,MAAM,SAAY,MAAM,eAA+B,IAAI,KAAI,MAAe,KAAK,OAAO,KAAK,YAAY,iBAAiB,IAAI,EAAE,cAAc,MAAM,QAAO,MAAK,KAAK,MAAM,KAAK;EAElL,MAAMC,MAA4B;GAChC,MAAU,OAAO;GACjB,KAAU;GACV,UAAU,OAAO,IAAI,MAAM,OAAO,OAAO;GACzC,OAAU,OAAO,IAAI,MAAM,KAAK,KAAK,OAAO,IAAI,MAAM,QAAQ;GAC9D;GACA;GACA;;AAEF,SAAO;;CAGX,MAAM,OAAO;EAAE;EAAS;;CACxB,MAAM,MAAM,KAAK,QAAQ,QAAQ;AACjC,QAAO,OAAO,KAAK"}
1
+ {"version":3,"file":"schedules.js","names":["MongooseTypes","doc: InfoMentorTypes.event"],"sources":["../../../src/InfoMentor/to/schedules.ts"],"sourcesContent":["import { Types as MongooseTypes } from 'mongoose';\nimport moment from 'moment';\nimport iconv from 'iconv-lite';\nimport Papa from 'papaparse';\nimport type { Types as InfoMentorTypes } from '../types';\nimport type { CoreTypes } from '../../core';\nimport { getDayIndex } from '../../core/util';\n\nconst days = ['MÅN', 'TIS', 'ONS', 'TOR', 'FRE'];\nconst columns = ['Ämne', 'Dag', 'Starttid', 'Längd', 'Personal', 'Klasser', 'Salar'];\nconst delimiter = '\\t';\nconst encoding = 'windows-1252';\n\nexport default (courseEvents: CoreTypes.mixed.event[]): Buffer => {\n const events = courseEvents\n .map(event => {\n if (event.parked || !event.start || !event.end) return;\n\n const course = event.course;\n if (!course) return;\n\n const day = days.at(getDayIndex(event.start));\n if (!day) throw new Error('Invalid event day');\n\n if (typeof course != 'object' || course instanceof MongooseTypes.ObjectId)\n throw new Error('(InfoMentor::To::Schedules) Event course is not an deserialized object');\n\n const Personal = (event.teachers ?? course.teachers ?? []).map(({ to: x }) => typeof x == 'object' && 'displayName' in x ? x.displayName : null).filter(x => x != null).join(',');\n const Klasser = (event.groups ?? course.groups ?? []).map(({ to: x }) => typeof x == 'object' && 'displayName' in x ? x.displayName : null).filter(x => x != null).join(',');\n const Salar = (event.inLocations ?? []).map(x => x && typeof x == 'object' && 'displayName' in x ? x.displayName : null).filter(x => x != null).join(',');\n\n const doc: InfoMentorTypes.event ={\n Ämne: course.displayName,\n Dag: day,\n Starttid: moment.utc(event.start).format('HH.mm'),\n Längd: moment.utc(event.end).diff(moment.utc(event.start), 'minutes'),\n Personal,\n Klasser,\n Salar,\n };\n return doc;\n });\n\n const opts = { columns, delimiter };\n const csv = Papa.unparse(events, opts);\n return iconv.encode(csv, encoding);\n};\n"],"mappings":";;;;;;;AAQA,MAAM,OAAY;CAAC;CAAO;CAAO;CAAO;CAAO;;AAC/C,MAAM,UAAY;CAAC;CAAQ;CAAO;CAAY;CAAS;CAAY;CAAW;;AAC9E,MAAM,YAAY;AAClB,MAAM,WAAY;AAElB,yBAAgB,iBAAkD;CAChE,MAAM,SAAS,aACZ,KAAI,UAAS;AACZ,MAAI,MAAM,UAAU,CAAC,MAAM,SAAS,CAAC,MAAM,IAAK;EAEhD,MAAM,SAAS,MAAM;AACrB,MAAI,CAAC,OAAQ;EAEb,MAAM,MAAM,KAAK,GAAG,YAAY,MAAM;AACtC,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM;AAE1B,MAAI,OAAO,UAAU,YAAY,kBAAkBA,MAAc,SAC/D,OAAM,IAAI,MAAM;EAElB,MAAM,YAAY,MAAM,YAAY,OAAO,YAAY,IAAI,KAAK,EAAE,IAAI,QAAa,OAAO,KAAK,YAAY,iBAAiB,IAAI,EAAE,cAAc,MAAM,QAAO,MAAK,KAAK,MAAM,KAAK;EAClL,MAAM,WAAY,MAAM,UAAY,OAAO,UAAY,IAAI,KAAK,EAAE,IAAI,QAAa,OAAO,KAAK,YAAY,iBAAiB,IAAI,EAAE,cAAc,MAAM,QAAO,MAAK,KAAK,MAAM,KAAK;EAClL,MAAM,SAAY,MAAM,eAA+B,IAAI,KAAI,MAAe,KAAK,OAAO,KAAK,YAAY,iBAAiB,IAAI,EAAE,cAAc,MAAM,QAAO,MAAK,KAAK,MAAM,KAAK;EAElL,MAAMC,MAA4B;GAChC,MAAU,OAAO;GACjB,KAAU;GACV,UAAU,OAAO,IAAI,MAAM,OAAO,OAAO;GACzC,OAAU,OAAO,IAAI,MAAM,KAAK,KAAK,OAAO,IAAI,MAAM,QAAQ;GAC9D;GACA;GACA;;AAEF,SAAO;;CAGX,MAAM,OAAO;EAAE;EAAS;;CACxB,MAAM,MAAM,KAAK,QAAQ,QAAQ;AACjC,QAAO,MAAM,OAAO,KAAK"}
@@ -13,77 +13,78 @@ declare class PlanDigitalMap {
13
13
  static from: {
14
14
  schedules: (input: Types.schedule, options: Types.options) => {
15
15
  groups?: {
16
- exceptions?: string[] | undefined;
17
- lockedTimes?: string[] | undefined;
18
16
  ids?: ID | undefined;
19
17
  createdAt?: DateType | undefined;
20
18
  updatedAt?: DateType | undefined;
21
19
  lastModifiedBy?: unknown;
22
20
  belongsTo?: string | undefined;
21
+ exceptions?: string[] | undefined;
22
+ lockedTimes?: string[] | undefined;
23
23
  rank?: number | undefined;
24
- displayName?: string | undefined;
25
- lunch?: string[] | undefined;
26
- intervals?: AllowedInterval[] | undefined;
27
24
  days?: Day[] | undefined;
25
+ displayName?: string | undefined;
28
26
  minBreakLength?: BreakLength | undefined;
29
- tags?: Tag[] | undefined;
30
27
  maximumScheduleSpan?: MaximumScheduleSpan | undefined;
31
28
  forbidOverlappingEvents?: boolean | undefined;
32
29
  disableDayLengthPunishment?: boolean | undefined;
33
30
  weight?: number | undefined;
34
- rootInterval?: string | undefined;
35
- maxNumWorkingHours?: number | boolean | undefined;
36
- maxNumDailyWorkingHours?: number | number[] | boolean | undefined;
37
31
  species?: "class" | undefined;
38
32
  parentGroups?: string[] | undefined;
39
33
  subGroups?: string[] | undefined;
34
+ lunch?: string[] | undefined;
40
35
  members?: string[] | undefined;
36
+ intervals?: AllowedInterval[] | undefined;
37
+ rootInterval?: string | undefined;
38
+ tags?: Tag[] | undefined;
39
+ maxNumWorkingHours?: number | boolean | undefined;
40
+ maxNumDailyWorkingHours?: number | number[] | boolean | undefined;
41
41
  }[];
42
42
  teachers?: {
43
- exceptions?: string[] | undefined;
44
- lockedTimes?: string[] | undefined;
45
43
  ids?: ID | undefined;
46
44
  createdAt?: DateType | undefined;
47
45
  updatedAt?: DateType | undefined;
48
46
  lastModifiedBy?: unknown;
49
47
  belongsTo?: string | undefined;
48
+ exceptions?: string[] | undefined;
49
+ lockedTimes?: string[] | undefined;
50
50
  rank?: number | undefined;
51
- displayName?: string | undefined;
52
- lunch?: string[] | undefined;
53
- intervals?: AllowedInterval[] | undefined;
54
51
  days?: Day[] | undefined;
52
+ displayName?: string | undefined;
55
53
  minBreakLength?: BreakLength | undefined;
56
- tags?: Tag[] | undefined;
57
- plannedScheduledDuration?: PlannedScheduledDuration | undefined;
58
54
  maximumScheduleSpan?: MaximumScheduleSpan | undefined;
59
55
  forbidOverlappingEvents?: boolean | undefined;
60
56
  disableDayLengthPunishment?: boolean | undefined;
61
57
  weight?: number | undefined;
62
- person?: string | undefined;
58
+ lunch?: string[] | undefined;
59
+ intervals?: AllowedInterval[] | undefined;
63
60
  rootInterval?: string | undefined;
64
- signature?: string | undefined;
61
+ tags?: Tag[] | undefined;
65
62
  maxNumWorkingHours?: number | boolean | undefined;
66
63
  maxNumDailyWorkingHours?: number | number[] | boolean | undefined;
64
+ person?: string | undefined;
65
+ plannedScheduledDuration?: PlannedScheduledDuration | undefined;
66
+ signature?: string | undefined;
67
67
  }[];
68
68
  courses?: {
69
+ ids?: ID | undefined;
70
+ createdAt?: DateType | undefined;
71
+ updatedAt?: DateType | undefined;
72
+ lastModifiedBy?: unknown;
73
+ belongsTo?: string | undefined;
69
74
  exceptions?: string[] | undefined;
75
+ type?: string | undefined;
70
76
  groups?: GroupReference<string, string>[] | undefined;
71
77
  teachers?: PersonReference<string>[] | undefined;
72
78
  locations?: AvailableLocation<string>[] | undefined;
73
79
  events?: string[] | undefined;
74
80
  lockedTimes?: string[] | undefined;
75
- ids?: ID | undefined;
76
- createdAt?: DateType | undefined;
77
- updatedAt?: DateType | undefined;
78
- lastModifiedBy?: unknown;
79
- belongsTo?: string | undefined;
80
- displayName?: string | undefined;
81
- intervals?: AllowedInterval[] | undefined;
82
81
  days?: Day[] | undefined;
83
- minBreakLength?: BreakLength | undefined;
84
- tags?: Tag[] | undefined;
85
82
  weeks?: number[] | undefined;
83
+ displayName?: string | undefined;
84
+ minBreakLength?: BreakLength | undefined;
86
85
  weight?: number | undefined;
86
+ intervals?: AllowedInterval[] | undefined;
87
+ tags?: Tag[] | undefined;
87
88
  period?: string | undefined;
88
89
  participants?: PersonReference<string>[] | undefined;
89
90
  density?: number | undefined;
@@ -91,7 +92,6 @@ declare class PlanDigitalMap {
91
92
  color?: string | undefined;
92
93
  eventDurationVariance?: number | undefined;
93
94
  totalTime?: string | undefined;
94
- type?: string | undefined;
95
95
  comment?: string | undefined;
96
96
  startDate?: DateType | undefined;
97
97
  endDate?: DateType | undefined;
@@ -102,8 +102,8 @@ function makeConnected(schedule, options = {}) {
102
102
  const edges = {};
103
103
  return Object.assign(x, edges);
104
104
  });
105
- const makeCoalesced = (map, id, toModel) => {
106
- const to = map.get(id);
105
+ const makeCoalesced = (map$1, id, toModel) => {
106
+ const to = map$1.get(id);
107
107
  if (!to) return;
108
108
  return {
109
109
  to,
@@ -1 +1 @@
1
- {"version":3,"file":"make-connected.js","names":["vertex: Record<keyof Required<Intersect<Vertex>>, unknown>","edges: ExtractEdges<DivisionSettings>","x","edges: ExtractEdges<Location>","edges: ExtractEdges<Group>","edges: ExtractEdges<Teacher>","edges: ExtractEdges<Person>","edges: ExtractEdges<Period>","edges: ExtractEdges<RootInterval>","edges: ExtractEdges<LockedTime>","edges: ExtractEdges<OverlapGroup>","coalesced: Coalesced<typeof to, (typeof x)['toModel']>","species: Species<typeof to, (typeof x)['toModel']>","participant: PersonReference<Person>","locations","availableLocation: AvailableLocation<Location>","group: GroupReference<Group, Person>","edges: ExtractEdges<Course>","edges: ExtractEdges<Event>"],"sources":["../../src/RS/make-connected.ts"],"sourcesContent":["import { pick } from 'lodash-es';\nimport { getIdKey, getVertexId } from '../core/util';\nimport type { ExtractEdges, Mixed } from '../core/vertex-mapping';\nimport type { CoreTypes } from '../core';\nimport type { AvailableLocation, Coalesced, Collection, GroupReference, IdKey, InternalIdKey, PersonReference, Species, Vertex } from '../core/types/common';\nimport type { Types } from './types';\nimport type { Intersect } from '../common/types';\n\ntype OmitProperties<T extends Vertex> = Omit<T, 'belongsTo' | 'exceptions' | 'defaultLunch' | 'syllabus' | InternalIdKey> & Vertex;\n\ntype _Schedule = {\n division: Mixed<CoreTypes.division>;\n divisions: Mixed<CoreTypes.division>;\n settings: Mixed<CoreTypes.divisionSettings>;\n groups: Mixed<CoreTypes.group>[];\n teachers: Mixed<CoreTypes.teacher>[];\n locations: Mixed<CoreTypes.location>[];\n periods: Mixed<CoreTypes.period>[];\n persons: Mixed<CoreTypes.person>[];\n rootIntervals: Mixed<CoreTypes.rootInterval>[];\n lockedTimes: Mixed<CoreTypes.lockedTime>[];\n overlapGroups: Mixed<CoreTypes.overlapGroup>[];\n courses: Mixed<CoreTypes.course>[];\n events: Mixed<CoreTypes.event>[];\n};\nexport type MixedScheduleData = Partial<_Schedule>;\n\ntype Division = Vertex & Pick<CoreTypes.division, 'displayName' | 'start' | 'end'>;\ntype DivisionSettings = OmitProperties<CoreTypes.divisionSettings>;\ntype Location = OmitProperties<CoreTypes.location>;\ntype Group = OmitProperties<CoreTypes.group>;\ntype Teacher = OmitProperties<CoreTypes.teacher>;\ntype Person = OmitProperties<CoreTypes.person>;\ntype Period = OmitProperties<CoreTypes.period>;\ntype RootInterval = OmitProperties<CoreTypes.rootInterval>;\ntype LockedTime = OmitProperties<CoreTypes.lockedTime>;\ntype OverlapGroup = OmitProperties<CoreTypes.overlapGroup>;\ntype Course = OmitProperties<CoreTypes.course>;\ntype Event = OmitProperties<CoreTypes.event>;\n\nexport namespace ConnectedTypes {\n export type division = Division;\n export type divisionSettings = DivisionSettings;\n export type location = Location;\n export type group = Group;\n export type teacher = Teacher;\n export type person = Person;\n export type period = Period;\n export type rootInterval = RootInterval;\n export type lockedTime = LockedTime;\n export type overlapGroup = OverlapGroup;\n export type course = Course;\n export type event = Event;\n}\n\nexport type ConnectedScheduleData = {\n division: Division;\n settings: DivisionSettings;\n groups: Group[];\n teachers: Teacher[];\n locations: Location[];\n periods: Period[];\n persons: Person[];\n rootIntervals: RootInterval[];\n lockedTimes: LockedTime[];\n overlapGroups: OverlapGroup[];\n courses: Course[];\n events: Event[];\n};\n\n\nfunction indexCollection<T extends Vertex> (collection: Mixed<T>[], idKey: IdKey): Map<string, T> {\n return new Map(collection.map(x => ([getVertexId(x, idKey), x as T] as const)));\n}\nfunction nonNullable<T> (value: T | null | undefined): value is T {\n return value != null;\n}\n\n/**\n * Connects the schedule data by replacing references with actual objects making it easier to work with.\n */\nexport function makeConnected (\n schedule: MixedScheduleData,\n options: Pick<Types.toOptions, 'idKey'> = {}\n): ConnectedScheduleData {\n const _division = schedule.divisions ?? schedule.division;\n if (!_division) throw new Error(`\"division\" or \"divisions\" missing in schedule, present keys: ${Object.keys(schedule).join(', ')}`);\n const _settings = schedule.settings;\n if (!_settings) throw new Error(`\"settings\" missing in schedule, present keys: ${Object.keys(schedule).join(', ')}`);\n\n const idKey = getIdKey(options);\n\n const groupsMap = indexCollection(schedule.groups ?? [], idKey);\n const teachersMap = indexCollection(schedule.teachers ?? [], idKey);\n const locationsMap = indexCollection(schedule.locations ?? [], idKey);\n const coursesMap = indexCollection(schedule.courses ?? [], idKey);\n const eventsMap = indexCollection(schedule.events ?? [], idKey);\n const overlapGroupsMap = indexCollection(schedule.overlapGroups ?? [], idKey);\n const periodsMap = indexCollection(schedule.periods ?? [], idKey);\n const personsMap = indexCollection(schedule.persons ?? [], idKey);\n const lockedTimesMap = indexCollection(schedule.lockedTimes ?? [], idKey);\n const rootIntervalsMap = indexCollection(schedule.rootIntervals ?? [], idKey);\n\n const division = ((): Division => {\n const vertex: Record<keyof Required<Intersect<Vertex>>, unknown> = {\n _id: true,\n id: true,\n ids: true,\n createdAt: true,\n updatedAt: true,\n lastModifiedBy: true\n };\n const vertexKeys = Object.keys(vertex) as (keyof typeof vertex)[];\n return pick(_division, [...vertexKeys, 'displayName', 'start', 'end']) as Division;\n })();\n\n const settings = ((): DivisionSettings => {\n const edges: ExtractEdges<DivisionSettings> = {\n period: _settings.period != null ? periodsMap .get(getVertexId(_settings.period, idKey)) : _settings.period,\n defaultRootInterval: _settings.defaultRootInterval != null ? rootIntervalsMap.get(getVertexId(_settings.defaultRootInterval, idKey)) : _settings.defaultRootInterval,\n } satisfies Record<keyof ExtractEdges<DivisionSettings>, unknown>;\n return Object.assign(_settings, edges);\n })();\n\n const getLockedTimes = <T extends Mixed<CoreTypes.group>['lockedTimes'] | undefined | null>(x: T): LockedTime[] | Extract<T, null | undefined> => {\n if (!x) return x as Extract<T, null | undefined>;\n return x.map(x => lockedTimesMap.get(getVertexId(x, idKey))).filter(nonNullable);\n };\n const getLunch = <T extends Mixed<CoreTypes.group>['lockedTimes'] | undefined | null>(x: T): LockedTime[] | Extract<T, null | undefined> => {\n if (!x) return x as Extract<T, null | undefined>;\n return x.map(x => lockedTimesMap.get(getVertexId(x, idKey))).filter(nonNullable);\n };\n\n const locations = (schedule.locations ?? [])\n .map((x): Location => {\n const edges: ExtractEdges<Location> = {\n lockedTimes: getLockedTimes(x.lockedTimes),\n lunch: getLunch(x.lunch),\n } satisfies Record<keyof ExtractEdges<Location>, unknown>;\n return Object.assign(x, edges);\n });\n\n const groups = (schedule.groups ?? [])\n .map((x): Group => {\n const edges: ExtractEdges<Group> = {\n lockedTimes: getLockedTimes(x.lockedTimes),\n lunch: getLunch (x.lunch),\n members: x.members ? x.members .map(x => personsMap.get(getVertexId(x, idKey))).filter(nonNullable) : x.members,\n parentGroups: x.parentGroups ? x.parentGroups.map(x => groupsMap .get(getVertexId(x, idKey))).filter(nonNullable) : x.parentGroups,\n subGroups: x.subGroups ? x.subGroups .map(x => groupsMap .get(getVertexId(x, idKey))).filter(nonNullable) : x.subGroups,\n\n rootInterval: x.rootInterval != null ? rootIntervalsMap.get(getVertexId(x.rootInterval, idKey)) : x.rootInterval,\n } satisfies Record<keyof ExtractEdges<Group>, unknown>;\n return Object.assign(x, edges);\n });\n\n const teachers = (schedule.teachers ?? [])\n .map((x): Teacher => {\n const edges: ExtractEdges<Teacher> = {\n lockedTimes: getLockedTimes(x.lockedTimes),\n lunch: getLunch(x.lunch),\n\n person: x.person != null ? personsMap .get(getVertexId(x.person, idKey)) : x.person,\n rootInterval: x.rootInterval != null ? rootIntervalsMap.get(getVertexId(x.rootInterval, idKey)) : x.rootInterval,\n } satisfies Record<keyof ExtractEdges<Teacher>, unknown>;\n return Object.assign(x, edges);\n });\n\n const persons = (schedule.persons ?? [])\n .map((x): Person => {\n const edges: ExtractEdges<Person> = {\n lockedTimes: getLockedTimes(x.lockedTimes),\n lunch: getLunch(x.lunch),\n\n group: x.group != null ? groupsMap.get(getVertexId(x.group, idKey)) : x.group,\n } satisfies Record<keyof ExtractEdges<Person>, unknown>;\n return Object.assign(x, edges);\n });\n\n const periods = (schedule.periods ?? [])\n .map((x): Period => {\n const edges: ExtractEdges<Period> = {\n } satisfies Record<keyof ExtractEdges<Period>, unknown>;\n return Object.assign(x, edges);\n });\n\n const rootIntervals = (schedule.rootIntervals ?? [])\n .map((x): RootInterval => {\n const edges: ExtractEdges<RootInterval> = {\n } satisfies Record<keyof ExtractEdges<RootInterval>, unknown>;\n return Object.assign(x, edges);\n });\n\n const makeCoalesced = <T extends Vertex, C extends Collection> (map: Map<string, T>, id: string, toModel: C) => {\n const to = map.get(id);\n if (!to) return;\n return { to, toModel } as Coalesced<T, C>;\n };\n\n const lockedTimes = (schedule.lockedTimes ?? [])\n .map((x): LockedTime => {\n const edges: ExtractEdges<LockedTime> = {\n coalesced: x.coalesced\n ? x.coalesced\n .map(x => {\n switch (x.toModel) {\n case 'groups': return makeCoalesced(groupsMap, getVertexId(x.to, idKey), x.toModel);\n case 'teachers': return makeCoalesced(teachersMap, getVertexId(x.to, idKey), x.toModel);\n case 'courses': return makeCoalesced(coursesMap, getVertexId(x.to, idKey), x.toModel);\n case 'events': return makeCoalesced(eventsMap, getVertexId(x.to, idKey), x.toModel);\n case 'courseevents': return makeCoalesced(eventsMap, getVertexId(x.to, idKey), 'events');\n case 'locations': return makeCoalesced(locationsMap, getVertexId(x.to, idKey), x.toModel);\n // case 'persons': return makeCoalesced(personsMap, getVertexId(x.to, idKey), x.toModel);\n default: throw new Error(`Unknown coalesced model \"${x.toModel satisfies never as string}\" in locked time ${JSON.stringify(x)}`);\n }\n })\n .filter(nonNullable)\n : x.coalesced,\n } satisfies Record<keyof ExtractEdges<LockedTime>, unknown>;\n return Object.assign(x, edges);\n });\n\n const overlapGroups = (schedule.overlapGroups ?? [])\n .map((x): OverlapGroup => {\n const edges: ExtractEdges<OverlapGroup> = {\n coalesced: x.coalesced\n ? x.coalesced\n .map(x => {\n const to = (() => {\n switch (x.toModel) {\n case 'courses': return coursesMap.get(getVertexId(x.to, idKey));\n default: throw new Error(`Unknown coalesced model \"${x.toModel satisfies never as string}\" in overlap group ${JSON.stringify(x)}`);\n }\n })();\n if (!to) return;\n const coalesced: Coalesced<typeof to, (typeof x)['toModel']> = { ...x, to };\n return coalesced;\n })\n .filter(nonNullable)\n : x.coalesced,\n species: x.species\n ? x.species\n .map(x => {\n const to = (() => {\n switch (x.toModel) {\n case 'events': return eventsMap.get(getVertexId(x.to, idKey));\n case 'courseevents': return eventsMap.get(getVertexId(x.to, idKey));\n default: throw new Error(`Unknown species model \"${x.toModel satisfies never as string}\" in overlap group ${JSON.stringify(x)}`);\n }\n })();\n if (!to) return;\n const species: Species<typeof to, (typeof x)['toModel']> = { ...x, to };\n return species;\n })\n .filter(nonNullable)\n : x.species,\n } satisfies Record<keyof ExtractEdges<OverlapGroup>, unknown>;\n return Object.assign(x, edges);\n });\n\n const getParticipants = (x: Mixed<CoreTypes.course>['participants'] | Mixed<CoreTypes.event>['participants']): PersonReference<Person>[] | undefined => {\n if (!x) return undefined;\n return x\n .map(x => {\n const to = personsMap.get(getVertexId(x.to, idKey));\n if (!to) return;\n const participant: PersonReference<Person> = { ...x, to };\n return participant;\n })\n .filter(nonNullable);\n };\n const getTeachers = (x: Mixed<CoreTypes.course>['teachers'] | Mixed<CoreTypes.event>['teachers']): PersonReference<Person>[] | undefined => {\n if (!x) return undefined;\n return x\n .map(x => {\n const to = teachersMap.get(getVertexId(x.to, idKey));\n if (!to) return;\n const participant: PersonReference<Person> = { ...x, to };\n return participant;\n })\n .filter(nonNullable);\n };\n const getLocations = (x: Mixed<CoreTypes.course>['locations'] | Mixed<CoreTypes.event>['locations']): AvailableLocation<Location>[] | undefined => {\n if (!x) return undefined;\n return x\n .map(x => {\n const locations = x.locations\n .map(x => locationsMap.get(getVertexId(x, idKey)))\n .filter(nonNullable);\n if (locations.length != 1) throw new Error(`(RS::MakeConnected) Expected exactly one location in available locations, got ${locations.length} and before filtering: ${x.locations.map(x => getVertexId(x, idKey)).join(', ')}`);\n const availableLocation: AvailableLocation<Location> = { ...x, locations: locations as [Location] };\n return availableLocation;\n })\n .filter(nonNullable);\n };\n const getGroups = (x: Mixed<CoreTypes.course>['groups'] | Mixed<CoreTypes.event>['groups']): GroupReference<Group, Person>[] | undefined => {\n if (!x) return undefined;\n return x\n .map(x => {\n const to = groupsMap.get(getVertexId(x.to, idKey));\n if (!to) return;\n const exclude = x.exclude\n ? x.exclude\n .map(x => personsMap.get(getVertexId(x, idKey)))\n .filter(nonNullable)\n : undefined;\n const group: GroupReference<Group, Person> = { ...x, to, exclude };\n return group;\n })\n .filter(nonNullable);\n };\n\n const courses = (schedule.courses ?? [])\n .map((x): Course => {\n const edges: ExtractEdges<Course> = {\n groups: getGroups (x.groups),\n teachers: getTeachers (x.teachers),\n locations: getLocations (x.locations),\n participants: getParticipants(x.participants),\n lockedTimes: getLockedTimes (x.lockedTimes),\n events: x.events ? x.events .map(x => eventsMap .get(getVertexId(x, idKey))).filter(nonNullable) : x.events,\n\n period: x.period != null ? periodsMap .get(getVertexId(x.period, idKey)) : x.period,\n overlapGroup: x.overlapGroup != null ? overlapGroupsMap.get(getVertexId(x.overlapGroup, idKey)) : x.overlapGroup,\n overlapSpecies: x.overlapSpecies != null ? overlapGroupsMap.get(getVertexId(x.overlapSpecies, idKey)) : x.overlapSpecies,\n } satisfies Record<keyof ExtractEdges<Course>, unknown>;\n return Object.assign(x, edges);\n });\n\n const events = (schedule.events ?? [])\n .map((x): Event => {\n const edges: ExtractEdges<Event> = {\n groups: getGroups (x.groups),\n teachers: getTeachers (x.teachers),\n locations: getLocations (x.locations),\n participants: getParticipants(x.participants),\n lockedTimes: getLockedTimes (x.lockedTimes),\n inLocations: x.inLocations\n ? x.inLocations\n .map(x => x === null ? null : locationsMap.get(getVertexId(x, idKey)))\n .filter((x): x is Exclude<typeof x, undefined> => x !== undefined)\n : x.inLocations,\n\n course: x.course != null ? coursesMap .get(getVertexId(x.course, idKey)) : x.course,\n period: x.period != null ? periodsMap .get(getVertexId(x.period, idKey)) : x.period,\n overlapGroup: x.overlapGroup != null ? overlapGroupsMap.get(getVertexId(x.overlapGroup, idKey)) : x.overlapGroup,\n overlapSpecies: x.overlapSpecies != null ? overlapGroupsMap.get(getVertexId(x.overlapSpecies, idKey)) : x.overlapSpecies,\n } satisfies Record<keyof ExtractEdges<Event>, unknown>;\n return Object.assign(x, edges);\n });\n\n\n return {\n division,\n settings,\n locations,\n groups,\n teachers,\n persons,\n periods,\n rootIntervals,\n lockedTimes,\n overlapGroups,\n courses,\n events\n };\n}"],"mappings":"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"}
1
+ {"version":3,"file":"make-connected.js","names":["vertex: Record<keyof Required<Intersect<Vertex>>, unknown>","edges: ExtractEdges<DivisionSettings>","x","edges: ExtractEdges<Location>","edges: ExtractEdges<Group>","edges: ExtractEdges<Teacher>","edges: ExtractEdges<Person>","edges: ExtractEdges<Period>","edges: ExtractEdges<RootInterval>","map","edges: ExtractEdges<LockedTime>","edges: ExtractEdges<OverlapGroup>","coalesced: Coalesced<typeof to, (typeof x)['toModel']>","species: Species<typeof to, (typeof x)['toModel']>","participant: PersonReference<Person>","locations","availableLocation: AvailableLocation<Location>","group: GroupReference<Group, Person>","edges: ExtractEdges<Course>","edges: ExtractEdges<Event>"],"sources":["../../src/RS/make-connected.ts"],"sourcesContent":["import { pick } from 'lodash-es';\nimport { getIdKey, getVertexId } from '../core/util';\nimport type { ExtractEdges, Mixed } from '../core/vertex-mapping';\nimport type { CoreTypes } from '../core';\nimport type { AvailableLocation, Coalesced, Collection, GroupReference, IdKey, InternalIdKey, PersonReference, Species, Vertex } from '../core/types/common';\nimport type { Types } from './types';\nimport type { Intersect } from '../common/types';\n\ntype OmitProperties<T extends Vertex> = Omit<T, 'belongsTo' | 'exceptions' | 'defaultLunch' | 'syllabus' | InternalIdKey> & Vertex;\n\ntype _Schedule = {\n division: Mixed<CoreTypes.division>;\n divisions: Mixed<CoreTypes.division>;\n settings: Mixed<CoreTypes.divisionSettings>;\n groups: Mixed<CoreTypes.group>[];\n teachers: Mixed<CoreTypes.teacher>[];\n locations: Mixed<CoreTypes.location>[];\n periods: Mixed<CoreTypes.period>[];\n persons: Mixed<CoreTypes.person>[];\n rootIntervals: Mixed<CoreTypes.rootInterval>[];\n lockedTimes: Mixed<CoreTypes.lockedTime>[];\n overlapGroups: Mixed<CoreTypes.overlapGroup>[];\n courses: Mixed<CoreTypes.course>[];\n events: Mixed<CoreTypes.event>[];\n};\nexport type MixedScheduleData = Partial<_Schedule>;\n\ntype Division = Vertex & Pick<CoreTypes.division, 'displayName' | 'start' | 'end'>;\ntype DivisionSettings = OmitProperties<CoreTypes.divisionSettings>;\ntype Location = OmitProperties<CoreTypes.location>;\ntype Group = OmitProperties<CoreTypes.group>;\ntype Teacher = OmitProperties<CoreTypes.teacher>;\ntype Person = OmitProperties<CoreTypes.person>;\ntype Period = OmitProperties<CoreTypes.period>;\ntype RootInterval = OmitProperties<CoreTypes.rootInterval>;\ntype LockedTime = OmitProperties<CoreTypes.lockedTime>;\ntype OverlapGroup = OmitProperties<CoreTypes.overlapGroup>;\ntype Course = OmitProperties<CoreTypes.course>;\ntype Event = OmitProperties<CoreTypes.event>;\n\nexport namespace ConnectedTypes {\n export type division = Division;\n export type divisionSettings = DivisionSettings;\n export type location = Location;\n export type group = Group;\n export type teacher = Teacher;\n export type person = Person;\n export type period = Period;\n export type rootInterval = RootInterval;\n export type lockedTime = LockedTime;\n export type overlapGroup = OverlapGroup;\n export type course = Course;\n export type event = Event;\n}\n\nexport type ConnectedScheduleData = {\n division: Division;\n settings: DivisionSettings;\n groups: Group[];\n teachers: Teacher[];\n locations: Location[];\n periods: Period[];\n persons: Person[];\n rootIntervals: RootInterval[];\n lockedTimes: LockedTime[];\n overlapGroups: OverlapGroup[];\n courses: Course[];\n events: Event[];\n};\n\n\nfunction indexCollection<T extends Vertex> (collection: Mixed<T>[], idKey: IdKey): Map<string, T> {\n return new Map(collection.map(x => ([getVertexId(x, idKey), x as T] as const)));\n}\nfunction nonNullable<T> (value: T | null | undefined): value is T {\n return value != null;\n}\n\n/**\n * Connects the schedule data by replacing references with actual objects making it easier to work with.\n */\nexport function makeConnected (\n schedule: MixedScheduleData,\n options: Pick<Types.toOptions, 'idKey'> = {}\n): ConnectedScheduleData {\n const _division = schedule.divisions ?? schedule.division;\n if (!_division) throw new Error(`\"division\" or \"divisions\" missing in schedule, present keys: ${Object.keys(schedule).join(', ')}`);\n const _settings = schedule.settings;\n if (!_settings) throw new Error(`\"settings\" missing in schedule, present keys: ${Object.keys(schedule).join(', ')}`);\n\n const idKey = getIdKey(options);\n\n const groupsMap = indexCollection(schedule.groups ?? [], idKey);\n const teachersMap = indexCollection(schedule.teachers ?? [], idKey);\n const locationsMap = indexCollection(schedule.locations ?? [], idKey);\n const coursesMap = indexCollection(schedule.courses ?? [], idKey);\n const eventsMap = indexCollection(schedule.events ?? [], idKey);\n const overlapGroupsMap = indexCollection(schedule.overlapGroups ?? [], idKey);\n const periodsMap = indexCollection(schedule.periods ?? [], idKey);\n const personsMap = indexCollection(schedule.persons ?? [], idKey);\n const lockedTimesMap = indexCollection(schedule.lockedTimes ?? [], idKey);\n const rootIntervalsMap = indexCollection(schedule.rootIntervals ?? [], idKey);\n\n const division = ((): Division => {\n const vertex: Record<keyof Required<Intersect<Vertex>>, unknown> = {\n _id: true,\n id: true,\n ids: true,\n createdAt: true,\n updatedAt: true,\n lastModifiedBy: true\n };\n const vertexKeys = Object.keys(vertex) as (keyof typeof vertex)[];\n return pick(_division, [...vertexKeys, 'displayName', 'start', 'end']) as Division;\n })();\n\n const settings = ((): DivisionSettings => {\n const edges: ExtractEdges<DivisionSettings> = {\n period: _settings.period != null ? periodsMap .get(getVertexId(_settings.period, idKey)) : _settings.period,\n defaultRootInterval: _settings.defaultRootInterval != null ? rootIntervalsMap.get(getVertexId(_settings.defaultRootInterval, idKey)) : _settings.defaultRootInterval,\n } satisfies Record<keyof ExtractEdges<DivisionSettings>, unknown>;\n return Object.assign(_settings, edges);\n })();\n\n const getLockedTimes = <T extends Mixed<CoreTypes.group>['lockedTimes'] | undefined | null>(x: T): LockedTime[] | Extract<T, null | undefined> => {\n if (!x) return x as Extract<T, null | undefined>;\n return x.map(x => lockedTimesMap.get(getVertexId(x, idKey))).filter(nonNullable);\n };\n const getLunch = <T extends Mixed<CoreTypes.group>['lockedTimes'] | undefined | null>(x: T): LockedTime[] | Extract<T, null | undefined> => {\n if (!x) return x as Extract<T, null | undefined>;\n return x.map(x => lockedTimesMap.get(getVertexId(x, idKey))).filter(nonNullable);\n };\n\n const locations = (schedule.locations ?? [])\n .map((x): Location => {\n const edges: ExtractEdges<Location> = {\n lockedTimes: getLockedTimes(x.lockedTimes),\n lunch: getLunch(x.lunch),\n } satisfies Record<keyof ExtractEdges<Location>, unknown>;\n return Object.assign(x, edges);\n });\n\n const groups = (schedule.groups ?? [])\n .map((x): Group => {\n const edges: ExtractEdges<Group> = {\n lockedTimes: getLockedTimes(x.lockedTimes),\n lunch: getLunch (x.lunch),\n members: x.members ? x.members .map(x => personsMap.get(getVertexId(x, idKey))).filter(nonNullable) : x.members,\n parentGroups: x.parentGroups ? x.parentGroups.map(x => groupsMap .get(getVertexId(x, idKey))).filter(nonNullable) : x.parentGroups,\n subGroups: x.subGroups ? x.subGroups .map(x => groupsMap .get(getVertexId(x, idKey))).filter(nonNullable) : x.subGroups,\n\n rootInterval: x.rootInterval != null ? rootIntervalsMap.get(getVertexId(x.rootInterval, idKey)) : x.rootInterval,\n } satisfies Record<keyof ExtractEdges<Group>, unknown>;\n return Object.assign(x, edges);\n });\n\n const teachers = (schedule.teachers ?? [])\n .map((x): Teacher => {\n const edges: ExtractEdges<Teacher> = {\n lockedTimes: getLockedTimes(x.lockedTimes),\n lunch: getLunch(x.lunch),\n\n person: x.person != null ? personsMap .get(getVertexId(x.person, idKey)) : x.person,\n rootInterval: x.rootInterval != null ? rootIntervalsMap.get(getVertexId(x.rootInterval, idKey)) : x.rootInterval,\n } satisfies Record<keyof ExtractEdges<Teacher>, unknown>;\n return Object.assign(x, edges);\n });\n\n const persons = (schedule.persons ?? [])\n .map((x): Person => {\n const edges: ExtractEdges<Person> = {\n lockedTimes: getLockedTimes(x.lockedTimes),\n lunch: getLunch(x.lunch),\n\n group: x.group != null ? groupsMap.get(getVertexId(x.group, idKey)) : x.group,\n } satisfies Record<keyof ExtractEdges<Person>, unknown>;\n return Object.assign(x, edges);\n });\n\n const periods = (schedule.periods ?? [])\n .map((x): Period => {\n const edges: ExtractEdges<Period> = {\n } satisfies Record<keyof ExtractEdges<Period>, unknown>;\n return Object.assign(x, edges);\n });\n\n const rootIntervals = (schedule.rootIntervals ?? [])\n .map((x): RootInterval => {\n const edges: ExtractEdges<RootInterval> = {\n } satisfies Record<keyof ExtractEdges<RootInterval>, unknown>;\n return Object.assign(x, edges);\n });\n\n const makeCoalesced = <T extends Vertex, C extends Collection> (map: Map<string, T>, id: string, toModel: C) => {\n const to = map.get(id);\n if (!to) return;\n return { to, toModel } as Coalesced<T, C>;\n };\n\n const lockedTimes = (schedule.lockedTimes ?? [])\n .map((x): LockedTime => {\n const edges: ExtractEdges<LockedTime> = {\n coalesced: x.coalesced\n ? x.coalesced\n .map(x => {\n switch (x.toModel) {\n case 'groups': return makeCoalesced(groupsMap, getVertexId(x.to, idKey), x.toModel);\n case 'teachers': return makeCoalesced(teachersMap, getVertexId(x.to, idKey), x.toModel);\n case 'courses': return makeCoalesced(coursesMap, getVertexId(x.to, idKey), x.toModel);\n case 'events': return makeCoalesced(eventsMap, getVertexId(x.to, idKey), x.toModel);\n case 'courseevents': return makeCoalesced(eventsMap, getVertexId(x.to, idKey), 'events');\n case 'locations': return makeCoalesced(locationsMap, getVertexId(x.to, idKey), x.toModel);\n // case 'persons': return makeCoalesced(personsMap, getVertexId(x.to, idKey), x.toModel);\n default: throw new Error(`Unknown coalesced model \"${x.toModel satisfies never as string}\" in locked time ${JSON.stringify(x)}`);\n }\n })\n .filter(nonNullable)\n : x.coalesced,\n } satisfies Record<keyof ExtractEdges<LockedTime>, unknown>;\n return Object.assign(x, edges);\n });\n\n const overlapGroups = (schedule.overlapGroups ?? [])\n .map((x): OverlapGroup => {\n const edges: ExtractEdges<OverlapGroup> = {\n coalesced: x.coalesced\n ? x.coalesced\n .map(x => {\n const to = (() => {\n switch (x.toModel) {\n case 'courses': return coursesMap.get(getVertexId(x.to, idKey));\n default: throw new Error(`Unknown coalesced model \"${x.toModel satisfies never as string}\" in overlap group ${JSON.stringify(x)}`);\n }\n })();\n if (!to) return;\n const coalesced: Coalesced<typeof to, (typeof x)['toModel']> = { ...x, to };\n return coalesced;\n })\n .filter(nonNullable)\n : x.coalesced,\n species: x.species\n ? x.species\n .map(x => {\n const to = (() => {\n switch (x.toModel) {\n case 'events': return eventsMap.get(getVertexId(x.to, idKey));\n case 'courseevents': return eventsMap.get(getVertexId(x.to, idKey));\n default: throw new Error(`Unknown species model \"${x.toModel satisfies never as string}\" in overlap group ${JSON.stringify(x)}`);\n }\n })();\n if (!to) return;\n const species: Species<typeof to, (typeof x)['toModel']> = { ...x, to };\n return species;\n })\n .filter(nonNullable)\n : x.species,\n } satisfies Record<keyof ExtractEdges<OverlapGroup>, unknown>;\n return Object.assign(x, edges);\n });\n\n const getParticipants = (x: Mixed<CoreTypes.course>['participants'] | Mixed<CoreTypes.event>['participants']): PersonReference<Person>[] | undefined => {\n if (!x) return undefined;\n return x\n .map(x => {\n const to = personsMap.get(getVertexId(x.to, idKey));\n if (!to) return;\n const participant: PersonReference<Person> = { ...x, to };\n return participant;\n })\n .filter(nonNullable);\n };\n const getTeachers = (x: Mixed<CoreTypes.course>['teachers'] | Mixed<CoreTypes.event>['teachers']): PersonReference<Person>[] | undefined => {\n if (!x) return undefined;\n return x\n .map(x => {\n const to = teachersMap.get(getVertexId(x.to, idKey));\n if (!to) return;\n const participant: PersonReference<Person> = { ...x, to };\n return participant;\n })\n .filter(nonNullable);\n };\n const getLocations = (x: Mixed<CoreTypes.course>['locations'] | Mixed<CoreTypes.event>['locations']): AvailableLocation<Location>[] | undefined => {\n if (!x) return undefined;\n return x\n .map(x => {\n const locations = x.locations\n .map(x => locationsMap.get(getVertexId(x, idKey)))\n .filter(nonNullable);\n if (locations.length != 1) throw new Error(`(RS::MakeConnected) Expected exactly one location in available locations, got ${locations.length} and before filtering: ${x.locations.map(x => getVertexId(x, idKey)).join(', ')}`);\n const availableLocation: AvailableLocation<Location> = { ...x, locations: locations as [Location] };\n return availableLocation;\n })\n .filter(nonNullable);\n };\n const getGroups = (x: Mixed<CoreTypes.course>['groups'] | Mixed<CoreTypes.event>['groups']): GroupReference<Group, Person>[] | undefined => {\n if (!x) return undefined;\n return x\n .map(x => {\n const to = groupsMap.get(getVertexId(x.to, idKey));\n if (!to) return;\n const exclude = x.exclude\n ? x.exclude\n .map(x => personsMap.get(getVertexId(x, idKey)))\n .filter(nonNullable)\n : undefined;\n const group: GroupReference<Group, Person> = { ...x, to, exclude };\n return group;\n })\n .filter(nonNullable);\n };\n\n const courses = (schedule.courses ?? [])\n .map((x): Course => {\n const edges: ExtractEdges<Course> = {\n groups: getGroups (x.groups),\n teachers: getTeachers (x.teachers),\n locations: getLocations (x.locations),\n participants: getParticipants(x.participants),\n lockedTimes: getLockedTimes (x.lockedTimes),\n events: x.events ? x.events .map(x => eventsMap .get(getVertexId(x, idKey))).filter(nonNullable) : x.events,\n\n period: x.period != null ? periodsMap .get(getVertexId(x.period, idKey)) : x.period,\n overlapGroup: x.overlapGroup != null ? overlapGroupsMap.get(getVertexId(x.overlapGroup, idKey)) : x.overlapGroup,\n overlapSpecies: x.overlapSpecies != null ? overlapGroupsMap.get(getVertexId(x.overlapSpecies, idKey)) : x.overlapSpecies,\n } satisfies Record<keyof ExtractEdges<Course>, unknown>;\n return Object.assign(x, edges);\n });\n\n const events = (schedule.events ?? [])\n .map((x): Event => {\n const edges: ExtractEdges<Event> = {\n groups: getGroups (x.groups),\n teachers: getTeachers (x.teachers),\n locations: getLocations (x.locations),\n participants: getParticipants(x.participants),\n lockedTimes: getLockedTimes (x.lockedTimes),\n inLocations: x.inLocations\n ? x.inLocations\n .map(x => x === null ? null : locationsMap.get(getVertexId(x, idKey)))\n .filter((x): x is Exclude<typeof x, undefined> => x !== undefined)\n : x.inLocations,\n\n course: x.course != null ? coursesMap .get(getVertexId(x.course, idKey)) : x.course,\n period: x.period != null ? periodsMap .get(getVertexId(x.period, idKey)) : x.period,\n overlapGroup: x.overlapGroup != null ? overlapGroupsMap.get(getVertexId(x.overlapGroup, idKey)) : x.overlapGroup,\n overlapSpecies: x.overlapSpecies != null ? overlapGroupsMap.get(getVertexId(x.overlapSpecies, idKey)) : x.overlapSpecies,\n } satisfies Record<keyof ExtractEdges<Event>, unknown>;\n return Object.assign(x, edges);\n });\n\n\n return {\n division,\n settings,\n locations,\n groups,\n teachers,\n persons,\n periods,\n rootIntervals,\n lockedTimes,\n overlapGroups,\n courses,\n events\n };\n}"],"mappings":";;;;AAuEA,SAAS,gBAAmC,YAAwB,OAA8B;AAChG,QAAO,IAAI,IAAI,WAAW,KAAI,MAAM,CAAC,YAAY,GAAG,QAAQ;;AAE9D,SAAS,YAAgB,OAAyC;AAChE,QAAO,SAAS;;;;;AAMlB,SAAgB,cACd,UACA,UAA2C,IACpB;CACvB,MAAM,YAAY,SAAS,aAAa,SAAS;AACjD,KAAI,CAAC,UAAW,OAAM,IAAI,MAAM,gEAAgE,OAAO,KAAK,UAAU,KAAK;CAC3H,MAAM,YAAY,SAAS;AAC3B,KAAI,CAAC,UAAW,OAAM,IAAI,MAAM,iDAAiD,OAAO,KAAK,UAAU,KAAK;CAE5G,MAAM,QAAQ,SAAS;CAEvB,MAAM,YAAmB,gBAAgB,SAAS,UAAiB,IAAI;CACvE,MAAM,cAAmB,gBAAgB,SAAS,YAAiB,IAAI;CACvE,MAAM,eAAmB,gBAAgB,SAAS,aAAiB,IAAI;CACvE,MAAM,aAAmB,gBAAgB,SAAS,WAAiB,IAAI;CACvE,MAAM,YAAmB,gBAAgB,SAAS,UAAiB,IAAI;CACvE,MAAM,mBAAmB,gBAAgB,SAAS,iBAAiB,IAAI;CACvE,MAAM,aAAmB,gBAAgB,SAAS,WAAiB,IAAI;CACvE,MAAM,aAAmB,gBAAgB,SAAS,WAAiB,IAAI;CACvE,MAAM,iBAAmB,gBAAgB,SAAS,eAAiB,IAAI;CACvE,MAAM,mBAAmB,gBAAgB,SAAS,iBAAiB,IAAI;CAEvE,MAAM,kBAA4B;EAChC,MAAMA,SAA6D;GACjE,KAAgB;GAChB,IAAgB;GAChB,KAAgB;GAChB,WAAgB;GAChB,WAAgB;GAChB,gBAAgB;;EAElB,MAAM,aAAa,OAAO,KAAK;AAC/B,SAAO,KAAK,WAAW;GAAC,GAAG;GAAY;GAAe;GAAS;;;CAGjE,MAAM,kBAAoC;EACxC,MAAMC,QAAwC;GAC5C,QAAqB,UAAU,UAAuB,OAAO,WAAiB,IAAI,YAAY,UAAU,QAAqB,UAAU,UAAU;GACjJ,qBAAqB,UAAU,uBAAuB,OAAO,iBAAiB,IAAI,YAAY,UAAU,qBAAqB,UAAU,UAAU;;AAEnJ,SAAO,OAAO,OAAO,WAAW;;CAGlC,MAAM,kBAAsF,MAAsD;AAChJ,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,EAAE,KAAI,QAAK,eAAe,IAAI,YAAYC,KAAG,SAAS,OAAO;;CAEtE,MAAM,YAAgF,MAAsD;AAC1I,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,EAAE,KAAI,QAAK,eAAe,IAAI,YAAYA,KAAG,SAAS,OAAO;;CAGtE,MAAM,aAAa,SAAS,aAAa,IACtC,KAAK,MAAgB;EACpB,MAAMC,QAAgC;GACpC,aAAa,eAAe,EAAE;GAC9B,OAAa,SAAS,EAAE;;AAE1B,SAAO,OAAO,OAAO,GAAG;;CAG5B,MAAM,UAAU,SAAS,UAAU,IAChC,KAAK,MAAa;EACjB,MAAMC,QAA6B;GACjC,aAAc,eAAe,EAAE;GAC/B,OAAc,SAAe,EAAE;GAC/B,SAAc,EAAE,UAAe,EAAE,QAAa,KAAI,QAAK,WAAW,IAAI,YAAYF,KAAG,SAAS,OAAO,eAAe,EAAE;GACtH,cAAc,EAAE,eAAe,EAAE,aAAa,KAAI,QAAK,UAAW,IAAI,YAAYA,KAAG,SAAS,OAAO,eAAe,EAAE;GACtH,WAAc,EAAE,YAAe,EAAE,UAAa,KAAI,QAAK,UAAW,IAAI,YAAYA,KAAG,SAAS,OAAO,eAAe,EAAE;GAEtH,cAAc,EAAE,gBAAgB,OAAO,iBAAiB,IAAI,YAAY,EAAE,cAAc,UAAU,EAAE;;AAEtG,SAAO,OAAO,OAAO,GAAG;;CAG5B,MAAM,YAAY,SAAS,YAAY,IACpC,KAAK,MAAe;EACnB,MAAMG,QAA+B;GACnC,aAAa,eAAe,EAAE;GAC9B,OAAa,SAAS,EAAE;GAExB,QAAc,EAAE,UAAgB,OAAO,WAAiB,IAAI,YAAY,EAAE,QAAc,UAAU,EAAE;GACpG,cAAc,EAAE,gBAAgB,OAAO,iBAAiB,IAAI,YAAY,EAAE,cAAc,UAAU,EAAE;;AAEtG,SAAO,OAAO,OAAO,GAAG;;CAG5B,MAAM,WAAW,SAAS,WAAW,IAClC,KAAK,MAAc;EAClB,MAAMC,QAA8B;GAClC,aAAa,eAAe,EAAE;GAC9B,OAAa,SAAS,EAAE;GAExB,OAAO,EAAE,SAAS,OAAO,UAAU,IAAI,YAAY,EAAE,OAAO,UAAU,EAAE;;AAE1E,SAAO,OAAO,OAAO,GAAG;;CAG5B,MAAM,WAAW,SAAS,WAAW,IAClC,KAAK,MAAc;EAClB,MAAMC,QAA8B;AAEpC,SAAO,OAAO,OAAO,GAAG;;CAG5B,MAAM,iBAAiB,SAAS,iBAAiB,IAC9C,KAAK,MAAoB;EACxB,MAAMC,QAAoC;AAE1C,SAAO,OAAO,OAAO,GAAG;;CAG5B,MAAM,iBAA0D,OAAqB,IAAY,YAAe;EAC9G,MAAM,KAAKC,MAAI,IAAI;AACnB,MAAI,CAAC,GAAI;AACT,SAAO;GAAE;GAAI;;;CAGf,MAAM,eAAe,SAAS,eAAe,IAC1C,KAAK,MAAkB;EACtB,MAAMC,QAAkC,EACtC,WAAW,EAAE,YACT,EAAE,UACD,KAAI,QAAK;AACR,WAAQR,IAAE,SAAV;IACE,KAAK,SAAgB,QAAO,cAAc,WAAc,YAAYA,IAAE,IAAI,QAAQA,IAAE;IACpF,KAAK,WAAgB,QAAO,cAAc,aAAc,YAAYA,IAAE,IAAI,QAAQA,IAAE;IACpF,KAAK,UAAgB,QAAO,cAAc,YAAc,YAAYA,IAAE,IAAI,QAAQA,IAAE;IACpF,KAAK,SAAgB,QAAO,cAAc,WAAc,YAAYA,IAAE,IAAI,QAAQA,IAAE;IACpF,KAAK,eAAgB,QAAO,cAAc,WAAc,YAAYA,IAAE,IAAI,QAAQ;IAClF,KAAK,YAAgB,QAAO,cAAc,cAAc,YAAYA,IAAE,IAAI,QAAQA,IAAE;IAEpF,QAAS,OAAM,IAAI,MAAM,4BAA4BA,IAAE,QAAkC,mBAAmB,KAAK,UAAUA;;KAG9H,OAAO,eACR,EAAE;AAER,SAAO,OAAO,OAAO,GAAG;;CAG5B,MAAM,iBAAiB,SAAS,iBAAiB,IAC9C,KAAK,MAAoB;EACxB,MAAMS,QAAoC;GACxC,WAAW,EAAE,YACT,EAAE,UACD,KAAI,QAAK;IACR,MAAM,YAAY;AAChB,aAAQT,IAAE,SAAV;MACE,KAAK,UAAW,QAAO,WAAW,IAAI,YAAYA,IAAE,IAAI;MACxD,QAAS,OAAM,IAAI,MAAM,4BAA4BA,IAAE,QAAkC,qBAAqB,KAAK,UAAUA;;;AAGjI,QAAI,CAAC,GAAI;IACT,MAAMU,YAAyD;KAAE,GAAGV;KAAG;;AACvE,WAAO;MAER,OAAO,eACR,EAAE;GACN,SAAS,EAAE,UACP,EAAE,QACD,KAAI,QAAK;IACR,MAAM,YAAY;AAChB,aAAQA,IAAE,SAAV;MACE,KAAK,SAAgB,QAAO,UAAU,IAAI,YAAYA,IAAE,IAAI;MAC5D,KAAK,eAAgB,QAAO,UAAU,IAAI,YAAYA,IAAE,IAAI;MAC5D,QAAS,OAAM,IAAI,MAAM,0BAA0BA,IAAE,QAAkC,qBAAqB,KAAK,UAAUA;;;AAG/H,QAAI,CAAC,GAAI;IACT,MAAMW,UAAqD;KAAE,GAAGX;KAAG;;AACnE,WAAO;MAER,OAAO,eACR,EAAE;;AAER,SAAO,OAAO,OAAO,GAAG;;CAG5B,MAAM,mBAAmB,MAA+H;AACtJ,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,EACJ,KAAI,QAAK;GACR,MAAM,KAAK,WAAW,IAAI,YAAYA,IAAE,IAAI;AAC5C,OAAI,CAAC,GAAI;GACT,MAAMY,cAAuC;IAAE,GAAGZ;IAAG;;AACrD,UAAO;KAER,OAAO;;CAEZ,MAAM,eAAe,MAAuH;AAC1I,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,EACJ,KAAI,QAAK;GACR,MAAM,KAAK,YAAY,IAAI,YAAYA,IAAE,IAAI;AAC7C,OAAI,CAAC,GAAI;GACT,MAAMY,cAAuC;IAAE,GAAGZ;IAAG;;AACrD,UAAO;KAER,OAAO;;CAEZ,MAAM,gBAAgB,MAA6H;AACjJ,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,EACJ,KAAI,QAAK;GACR,MAAMa,cAAYb,IAAE,UACjB,KAAI,QAAK,aAAa,IAAI,YAAYA,KAAG,SACzC,OAAO;AACV,OAAIa,YAAU,UAAU,EAAG,OAAM,IAAI,MAAM,iFAAiFA,YAAU,OAAO,yBAAyBb,IAAE,UAAU,KAAI,QAAK,YAAYA,KAAG,QAAQ,KAAK;GACvN,MAAMc,oBAAiD;IAAE,GAAGd;IAAG,WAAWa;;AAC1E,UAAO;KAER,OAAO;;CAEZ,MAAM,aAAa,MAAyH;AAC1I,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,EACJ,KAAI,QAAK;GACR,MAAM,KAAK,UAAU,IAAI,YAAYb,IAAE,IAAI;AAC3C,OAAI,CAAC,GAAI;GACT,MAAM,UAAUA,IAAE,UACdA,IAAE,QACD,KAAI,QAAK,WAAW,IAAI,YAAYA,KAAG,SACvC,OAAO,eACR;GACJ,MAAMe,QAAuC;IAAE,GAAGf;IAAG;IAAI;;AACzD,UAAO;KAER,OAAO;;CAGZ,MAAM,WAAW,SAAS,WAAW,IAClC,KAAK,MAAc;EAClB,MAAMgB,QAA8B;GAClC,QAAc,UAAgB,EAAE;GAChC,UAAc,YAAgB,EAAE;GAChC,WAAc,aAAgB,EAAE;GAChC,cAAc,gBAAgB,EAAE;GAChC,aAAc,eAAgB,EAAE;GAChC,QAAc,EAAE,SAAe,EAAE,OAAY,KAAI,QAAK,UAAe,IAAI,YAAYhB,KAAG,SAAS,OAAO,eAAe,EAAE;GAEzH,QAAgB,EAAE,UAAkB,OAAO,WAAiB,IAAI,YAAY,EAAE,QAAgB,UAAU,EAAE;GAC1G,cAAgB,EAAE,gBAAkB,OAAO,iBAAiB,IAAI,YAAY,EAAE,cAAgB,UAAU,EAAE;GAC1G,gBAAgB,EAAE,kBAAkB,OAAO,iBAAiB,IAAI,YAAY,EAAE,gBAAgB,UAAU,EAAE;;AAE5G,SAAO,OAAO,OAAO,GAAG;;CAG5B,MAAM,UAAU,SAAS,UAAU,IAChC,KAAK,MAAa;EACjB,MAAMiB,QAA6B;GACjC,QAAc,UAAgB,EAAE;GAChC,UAAc,YAAgB,EAAE;GAChC,WAAc,aAAgB,EAAE;GAChC,cAAc,gBAAgB,EAAE;GAChC,aAAc,eAAgB,EAAE;GAChC,aAAc,EAAE,cACZ,EAAE,YACD,KAAI,QAAKjB,QAAM,OAAO,OAAO,aAAa,IAAI,YAAYA,KAAG,SAC7D,QAAQ,QAAyCA,QAAM,UACxD,EAAE;GAEN,QAAgB,EAAE,UAAkB,OAAO,WAAiB,IAAI,YAAY,EAAE,QAAgB,UAAU,EAAE;GAC1G,QAAgB,EAAE,UAAkB,OAAO,WAAiB,IAAI,YAAY,EAAE,QAAgB,UAAU,EAAE;GAC1G,cAAgB,EAAE,gBAAkB,OAAO,iBAAiB,IAAI,YAAY,EAAE,cAAgB,UAAU,EAAE;GAC1G,gBAAgB,EAAE,kBAAkB,OAAO,iBAAiB,IAAI,YAAY,EAAE,gBAAgB,UAAU,EAAE;;AAE5G,SAAO,OAAO,OAAO,GAAG;;AAI5B,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA"}