From 3f04d2fd4df6d26cb3c212a31d897a6fd8ac00c9 Mon Sep 17 00:00:00 2001 From: Gerald Schmittinger Date: Tue, 11 Mar 2025 12:18:07 +0100 Subject: [PATCH] feat(backend): Gepersonaliseerde leerpaden via API Mogelijkheid toegevoegd om via de API optioneel een gepersonaliseerde variant van een leerpad voor een student of groep aan te vragen. --- backend/src/controllers/learning-paths.ts | 27 ++++++++-- .../learning-path-personalization-util.ts | 54 ++++++++++++++++++- 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/backend/src/controllers/learning-paths.ts b/backend/src/controllers/learning-paths.ts index 8e654d02..fca86bfb 100644 --- a/backend/src/controllers/learning-paths.ts +++ b/backend/src/controllers/learning-paths.ts @@ -2,7 +2,12 @@ import { Request, Response } from 'express'; import { themes } from '../data/themes.js'; import { FALLBACK_LANG } from '../config.js'; import learningPathService from '../services/learning-paths/learning-path-service'; -import { NotFoundException } from '../exceptions'; +import {BadRequestException, NotFoundException} from '../exceptions'; +import {Language} from "../entities/content/language"; +import { + PersonalizationTarget, personalizedForGroup, + personalizedForStudent +} from "../services/learning-paths/learning-path-personalization-util"; /** * Fetch learning paths based on query parameters. @@ -13,6 +18,22 @@ export async function getLearningPaths(req: Request, res: Response): Promise theme.hruids); } - const learningPaths = await learningPathService.fetchLearningPaths(hruidList, language, `HRUIDs: ${hruidList.join(', ')}`); + const learningPaths = await learningPathService.fetchLearningPaths(hruidList, language as Language, `HRUIDs: ${hruidList.join(', ')}`, personalizationTarget); res.json(learningPaths.data); } diff --git a/backend/src/services/learning-paths/learning-path-personalization-util.ts b/backend/src/services/learning-paths/learning-path-personalization-util.ts index 648b7abc..c671e9a0 100644 --- a/backend/src/services/learning-paths/learning-path-personalization-util.ts +++ b/backend/src/services/learning-paths/learning-path-personalization-util.ts @@ -2,12 +2,64 @@ import { LearningPathNode } from '../../entities/content/learning-path-node.enti import { Student } from '../../entities/users/student.entity'; import { Group } from '../../entities/assignments/group.entity'; import { Submission } from '../../entities/assignments/submission.entity'; -import { getSubmissionRepository } from '../../data/repositories'; +import { + getClassRepository, + getGroupRepository, + getStudentRepository, + getSubmissionRepository +} from '../../data/repositories'; import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier'; import { LearningPathTransition } from '../../entities/content/learning-path-transition.entity'; import { JSONPath } from 'jsonpath-plus'; export type PersonalizationTarget = { type: 'student'; student: Student } | { type: 'group'; group: Group }; + +/** + * Shortcut function to easily create a PersonalizationTarget object for a student by his/her username. + * @param username Username of the student we want to generate a personalized learning path for. + * If there is no student with this username, return undefined. + */ +export async function personalizedForStudent(username: string): Promise { + const student = await getStudentRepository().findByUsername(username); + if (student) { + return { + type: "student", + student: student + } + } else { + return undefined; + } +} + +/** + * Shortcut function to easily create a PersonalizationTarget object for a group by class name, assignment number and + * group number. + * @param classId Id of the class in which this group was created + * @param assignmentNumber Number of the assignment for which this group was created + * @param groupNumber Number of the group for which we want to personalize the learning path. + */ +export async function personalizedForGroup(classId: string, assignmentNumber: number, groupNumber: number): Promise { + const clazz = await getClassRepository().findById(classId); + if (!clazz) { + return undefined; + } + const group = await getGroupRepository().findOne({ + assignment: { + within: clazz, + id: assignmentNumber, + }, + groupNumber: groupNumber + }) + if (group) { + return { + type: "group", + group: group + } + } else { + return undefined; + } +} + /** * Returns the last submission for the learning object associated with the given node and for the student or group */