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, CourseSessionUser, LearningContentAssignment, UserAssignmentCompletionStatus, } from "@/types"; import { sum } from "d3"; import pick from "lodash/pick"; export interface GradedUser { user: CourseSessionUser; grade: number; points: number; } export function calcLearningContentAssignments(learningPath?: LearningPath) { // TODO: filter by circle if (!learningPath) return []; return learningPath.circles.flatMap((circle) => { return circle.flatLearningContents.filter( (lc) => lc.content_type === "learnpath.LearningContentAssignment" ) as LearningContentAssignment[]; }); } export async function loadAssignmentCompletionStatusData( assignmentId: number, courseSessionId: number, learningContentId: number ) { const cockpitStore = useCockpitStore(); const assignmentCompletionData = (await itGet( `/api/assignment/${assignmentId}/${courseSessionId}/status/` )) as UserAssignmentCompletionStatus[]; const courseSessionUsers = await cockpitStore.loadCourseSessionMembers( courseSessionId ); const gradedUsers: GradedUser[] = []; const assignmentSubmittedUsers: CourseSessionUser[] = []; for (const csu of courseSessionUsers) { const userAssignmentStatus = assignmentCompletionData.find( (s) => s.assignment_user_id === csu.user_id && s.learning_content_page_id === learningContentId ); if ( userAssignmentStatus?.completion_status === "SUBMITTED" || userAssignmentStatus?.completion_status === "EVALUATION_IN_PROGRESS" || userAssignmentStatus?.completion_status === "EVALUATION_SUBMITTED" ) { assignmentSubmittedUsers.push(csu); } if (userAssignmentStatus?.completion_status === "EVALUATION_SUBMITTED") { gradedUsers.push({ user: csu, grade: userAssignmentStatus.evaluation_grade ?? 0, points: userAssignmentStatus.evaluation_points ?? 0, }); } } return { assignmentSubmittedUsers: assignmentSubmittedUsers, gradedUsers: gradedUsers, total: courseSessionUsers.length, }; } 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 = calcLearningContentAssignments( learningPathStore.learningPathForUser( courseSessionsStore.currentCourseSession.course.slug, userStore.id ) ); const learningContent = learningContents.find( (lc) => lc.content_assignment_id === 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; }