import type { StatusCountKey } from "@/components/ui/ItProgress.vue"; import { itGet } from "@/fetchHelpers"; import type { LearningPath } from "@/services/learningPath"; import { useCockpitStore } from "@/stores/cockpit"; import { useCourseSessionsStore } from "@/stores/courseSessions"; import { useLearningPathStore } from "@/stores/learningPath"; import { useUserStore } from "@/stores/user"; import type { Assignment, AssignmentCompletion, AssignmentCompletionStatus, CourseSessionUser, LearningContentAssignment, LearningContentInterface, UserAssignmentCompletionStatus, } from "@/types"; import { sum } from "d3"; import pick from "lodash/pick"; export interface AssignmentLearningContent extends LearningContentInterface { assignmentId: number; } export function calcAssignmentLearningContents(learningPath?: LearningPath) { // TODO: filter by circle if (!learningPath) return []; return learningPath.circles.flatMap((circle) => { const learningContents = circle.flatLearningContents.filter( (lc) => lc.content_type === "learnpath.LearningContentAssignment" && lc.assignment_type === "CASEWORK" ) as LearningContentAssignment[]; return learningContents.map((lc) => { return { ...lc, assignmentId: lc.content_assignment_id, }; }); }) as AssignmentLearningContent[]; } export async function loadAssignmentCompletionStatusData( assignmentId: number, courseSessionId: number ) { const cockpitStore = useCockpitStore(); const assignmentCompletionData = (await itGet( `/api/assignment/${assignmentId}/${courseSessionId}/status/` )) as UserAssignmentCompletionStatus[]; const courseSessionUsers = await cockpitStore.loadCourseSessionUsers(courseSessionId); return calcUserAssignmentCompletionStatus( courseSessionUsers, assignmentCompletionData ); } export function calcUserAssignmentCompletionStatus( courseSessionUsers: CourseSessionUser[], assignmentCompletionStatusData: UserAssignmentCompletionStatus[] ) { return courseSessionUsers.map((u) => { let userStatus = "unknown" as AssignmentCompletionStatus; const userAssignmentStatus = assignmentCompletionStatusData?.find( (s) => s.assignment_user_id === u.user_id ); if (userAssignmentStatus) { userStatus = userAssignmentStatus.completion_status; } let progressStatus: StatusCountKey = "unknown"; if ( ["SUBMITTED", "EVALUATION_IN_PROGRESS", "EVALUATION_SUBMITTED"].includes( userStatus ) ) { progressStatus = "success"; } return { userId: u.user_id, userStatus, progressStatus, grade: userAssignmentStatus?.evaluation_grade ?? null, }; }); } export function findAssignmentDetail(assignmentId: number) { const learningPathStore = useLearningPathStore(); const userStore = useUserStore(); const courseSessionsStore = useCourseSessionsStore(); // TODO: filter by selected circle if (!courseSessionsStore.currentCourseSession) { return undefined; } const learningContents = calcAssignmentLearningContents( learningPathStore.learningPathForUser( courseSessionsStore.currentCourseSession.course.slug, userStore.id ) ); const learningContent = learningContents.find( (lc) => lc.assignmentId === assignmentId ); return courseSessionsStore.findCourseSessionAssignment(learningContent?.id); } export function maxAssignmentPoints(assignment: Assignment) { return sum(assignment.evaluation_tasks.map((task) => task.value.max_points)); } export function userAssignmentPoints( assignment: Assignment, assignmentCompletion: AssignmentCompletion ) { const evaluationTaskIds = assignment.evaluation_tasks.map((task) => { return task.id; }); return sum( // transform the object of { [expert_id]: { expert_data: { points } } } to an array // of [ [expert_id, { expert_data: { points } }], ... ] so that we can easily sum // the points of the user Object.entries(pick(assignmentCompletion.completion_data, evaluationTaskIds)).map( (entry) => { return entry[1]?.expert_data?.points ?? 0; } ) ); } export function pointsToGrade(points: number, maxPoints: number) { // round to half-grades const grade = Math.round((points / maxPoints) * 10); const halfGrade = grade / 2; return Math.min(halfGrade, 5) + 1; }