vbv/client/src/services/assignmentService.ts

145 lines
4.3 KiB
TypeScript

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;
}