import type { StatusCount } from "@/components/ui/ItProgress.vue"; import { percentToRoundedGrade } from "@/services/assignmentService"; import type { CompetenceCertificate, CompetenceCertificateAssignment } from "@/types"; import dayjs from "dayjs"; import _ from "lodash"; export function assignmentsMaxEvaluationPoints( assignments: CompetenceCertificateAssignment[] ): number { return _.sum( assignments .filter((a) => a.completions[0]?.completion_status === "EVALUATION_SUBMITTED") .map((a) => a.max_points) ); } export function assignmentsUserPoints(assignments: CompetenceCertificateAssignment[]) { return +_.sum( assignments .filter((a) => a.completions?.[0]?.completion_status === "EVALUATION_SUBMITTED") .map((a) => a.completions?.[0]?.evaluation_points_final ?? 0) ).toFixed(1); } export function calcCompetenceCertificateGrade( assignments: CompetenceCertificateAssignment[], roundedToHalfGrade = true ) { const evaluatedAssignments = assignments.filter( (a) => a.completions?.[0]?.completion_status === "EVALUATION_SUBMITTED" ); const adjustedResults = evaluatedAssignments.map((a) => { return ( ((a.completions?.[0]?.evaluation_points_final ?? 0) / a.max_points) * a.competence_certificate_weight ); }); const adjustedAssignmentCount = _.sum( evaluatedAssignments.map((a) => a.competence_certificate_weight) ); if (adjustedAssignmentCount === 0) { return undefined; } return percentToRoundedGrade( _.sum(adjustedResults) / adjustedAssignmentCount, roundedToHalfGrade ); } export function calcCompetencesTotalGrade( competenceCertificates: CompetenceCertificate[] ) { // für das Total der Kompetenznote werden jeweils die gerundenten Noten der // einzelnen Kompetenznachweise verwendet und dann noch einmal gerundet. const competenceCertificateGrades = competenceCertificates .map((cc) => { return calcCompetenceCertificateGrade(cc.assignments); }) .filter((g) => { // filter out "empty" grades return !!g; }); const percentGraded = // @ts-ignore `g` cannot be undefined here _.sum(competenceCertificateGrades.map((g) => g - 1)) / (competenceCertificateGrades.length * 5); return percentToRoundedGrade(percentGraded); } export function competenceCertificateProgressStatusCount( assignments: CompetenceCertificateAssignment[] ) { const numAssignmentsEvaluated = assignments.filter( (a) => a.completions?.[0]?.completion_status === "EVALUATION_SUBMITTED" ).length; return { SUCCESS: numAssignmentsEvaluated, UNKNOWN: assignments.length - numAssignmentsEvaluated, FAIL: 0, } as StatusCount; } export function mergeCompetenceCertificates( competenceCertificates: CompetenceCertificate[] ) { const groupedCompetenceCertificates: Record< string, Array > = {}; competenceCertificates.forEach((certificate) => { if (!certificate) { return; } if (!groupedCompetenceCertificates[certificate.id]) { groupedCompetenceCertificates[certificate.id] = []; } groupedCompetenceCertificates[certificate.id].push(certificate); }); console.log( `Found ${Object.keys(groupedCompetenceCertificates).length} competence certificates over all course sessions` ); return Object.values(groupedCompetenceCertificates).map((certificates) => { const mergedCertificate: CompetenceCertificate = { ...certificates[0], assignments: [], }; certificates.forEach((certificate) => { certificate.assignments.forEach((assignment) => { const existingAssignment = mergedCertificate.assignments.find( (a) => a.id === assignment.id ); if (!existingAssignment) { mergedCertificate.assignments.push(assignment); } else if ( assignment.completions?.[0] != null && (existingAssignment.completions?.[0] == null || dayjs(existingAssignment.completions[0].evaluation_submitted_at).isBefore( assignment.completions[0].evaluation_submitted_at )) ) { mergedCertificate.assignments.splice( mergedCertificate.assignments.findIndex((a) => a.id === assignment.id), 1 ); mergedCertificate.assignments.push(assignment); } }); }); return mergedCertificate; }); }