import type { Language } from "@/data-objects/language.ts"; import { LearningPathNode } from "@/data-objects/learning-paths/learning-path-node.ts"; import type { LearningPathDTO } from "@/data-objects/learning-paths/learning-path-dto.ts"; export interface LearningPathNodeDTO { _id: string; learningobject_hruid: string; version: number; language: Language; start_node?: boolean; transitions: LearningPathTransitionDTO[]; created_at: string; updatedAt: string; done?: boolean; // True if a submission exists for this node by the user for whom the learning path is customized. } export interface LearningPathTransitionDTO { default: boolean; _id: string; next: { _id: string; hruid: string; version: number; language: string; }; } export class LearningPath { public readonly language: string; public readonly hruid: string; public readonly title: string; public readonly description: string; public readonly amountOfNodes: number; public readonly amountOfNodesLeft: number; public readonly keywords: string[]; public readonly targetAges: { min: number; max: number }; public readonly startNode: LearningPathNode; public readonly image?: string; // Image might be missing, so it's optional constructor(options: { language: string; hruid: string; title: string; description: string; amountOfNodes: number; amountOfNodesLeft: number; keywords: string[]; targetAges: { min: number; max: number }; startNode: LearningPathNode; image?: string; // Image might be missing, so it's optional }) { this.language = options.language; this.hruid = options.hruid; this.title = options.title; this.description = options.description; this.amountOfNodes = options.amountOfNodes; this.amountOfNodesLeft = options.amountOfNodesLeft; this.keywords = options.keywords; this.targetAges = options.targetAges; this.startNode = options.startNode; this.image = options.image; } public get nodesAsList(): LearningPathNode[] { const list: LearningPathNode[] = []; let currentNode = this.startNode; while (currentNode) { list.push(currentNode); currentNode = currentNode.transitions.find((it) => it.default)?.next || currentNode.transitions[0]?.next; } return list; } static fromDTO(dto: LearningPathDTO): LearningPath { return new LearningPath({ language: dto.language, hruid: dto.hruid, title: dto.title, description: dto.description, amountOfNodes: dto.num_nodes, amountOfNodesLeft: dto.num_nodes_left, keywords: dto.keywords.split(" "), targetAges: { min: dto.min_age, max: dto.max_age }, startNode: LearningPathNode.fromDTOAndOtherNodes(LearningPath.getStartNode(dto), dto.nodes), image: dto.image, }); } static getStartNode(dto: LearningPathDTO): LearningPathNodeDTO { const startNodeDtos = dto.nodes.filter((it) => it.start_node === true); if (startNodeDtos.length < 1) { // The learning path has no starting node -> use the first node. return dto.nodes[0]; } // The learning path has 1 or more starting nodes -> use the first start node. return startNodeDtos[0]; } }