Calculate average grade in Berufsbildner
This commit is contained in:
parent
eef166575f
commit
f4fbe1a894
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -78,6 +78,7 @@ type AssignmentCompletionMetricsType {
|
|||
ranking_completed: Boolean!
|
||||
average_passed: Float!
|
||||
average_evaluation_percent: Float
|
||||
competence_certificate_weight: Float
|
||||
}
|
||||
|
||||
type AssignmentStatisticsSummaryType {
|
||||
|
|
|
|||
|
|
@ -481,6 +481,7 @@ export const DASHBOARD_COURSE_STATISTICS = graphql(`
|
|||
ranking_completed
|
||||
average_evaluation_percent
|
||||
average_passed
|
||||
competence_certificate_weight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -555,6 +556,7 @@ export const DASHBOARD_MENTOR_COMPETENCE_SUMMARY = graphql(`
|
|||
failed_count
|
||||
unranked_count
|
||||
ranking_completed
|
||||
competence_certificate_weight
|
||||
average_evaluation_percent
|
||||
average_passed
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,149 @@
|
|||
<script setup lang="ts">
|
||||
import log from "loglevel";
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import {
|
||||
courseIdForCourseSlug,
|
||||
fetchMentorCompetenceSummary,
|
||||
} from "@/services/dashboard";
|
||||
import type { AssignmentStatisticsRecordType, BaseStatisticsType } from "@/gql/graphql";
|
||||
import { useDashboardStore } from "@/stores/dashboard";
|
||||
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
||||
import _ from "lodash";
|
||||
import { percentToRoundedGrade } from "@/services/assignmentService";
|
||||
import { a } from "vitest/dist/suite-BWgaIsVn";
|
||||
|
||||
const dashboardStore = useDashboardStore();
|
||||
|
||||
const props = defineProps<{
|
||||
agentRole: string;
|
||||
courseSlug: string;
|
||||
}>();
|
||||
|
||||
log.debug("AgentStatisticParentPage created", props);
|
||||
|
||||
const loading = ref(true);
|
||||
const courseId = ref<string | undefined>(undefined);
|
||||
const agentAssignmentData = ref<BaseStatisticsType | null>(null);
|
||||
|
||||
const courseSessionName = (courseSessionId: string) => {
|
||||
return (
|
||||
agentAssignmentData.value?.course_session_properties?.sessions.find(
|
||||
(session) => session.id === courseSessionId
|
||||
)?.name ?? ""
|
||||
);
|
||||
};
|
||||
|
||||
const circleMeta = (circleId: string) => {
|
||||
return agentAssignmentData.value?.course_session_properties.circles.find(
|
||||
(circle) => circle.id === circleId
|
||||
);
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await dashboardStore.loadDashboardDetails();
|
||||
courseId.value = courseIdForCourseSlug(
|
||||
dashboardStore.dashboardConfigsv2,
|
||||
props.courseSlug
|
||||
);
|
||||
|
||||
if (!courseId.value) {
|
||||
log.error("CourseId not found for courseSlug", props.courseSlug);
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("courseId", courseId.value);
|
||||
agentAssignmentData.value = await fetchMentorCompetenceSummary(
|
||||
courseId.value,
|
||||
props.agentRole
|
||||
);
|
||||
|
||||
loading.value = false;
|
||||
});
|
||||
|
||||
type GroupedAssignments = {
|
||||
competenceCertificateId: string;
|
||||
competenceCertificateTitle: string;
|
||||
generation: string;
|
||||
courseSessionId: string;
|
||||
assignments: AssignmentStatisticsRecordType[];
|
||||
sumAverageEvaluationPercent: number;
|
||||
averageEvaluationPercent: number | null;
|
||||
averageGrade: number | null;
|
||||
};
|
||||
|
||||
const courseSessionCompetenceAssignments = computed(() => {
|
||||
let resultArray = [] as GroupedAssignments[];
|
||||
|
||||
// group assignments by competence and course session
|
||||
for (const assignment of agentAssignmentData.value?.assignments.records ?? []) {
|
||||
const entry = resultArray.find(
|
||||
(r) =>
|
||||
r.competenceCertificateId === assignment.competence_certificate_id &&
|
||||
r.courseSessionId === assignment.course_session_id
|
||||
);
|
||||
if (entry) {
|
||||
if (assignment.metrics.ranking_completed) {
|
||||
entry.assignments.push(assignment);
|
||||
}
|
||||
} else {
|
||||
const newEntry = {
|
||||
competenceCertificateId: assignment.competence_certificate_id ?? "",
|
||||
competenceCertificateTitle: assignment.competence_certificate_title ?? "",
|
||||
generation: assignment.generation ?? "",
|
||||
courseSessionId: assignment.course_session_id ?? "",
|
||||
assignments: [] as AssignmentStatisticsRecordType[],
|
||||
sumAverageEvaluationPercent: 0,
|
||||
averageEvaluationPercent: null,
|
||||
averageGrade: null,
|
||||
};
|
||||
if (assignment && assignment.metrics.ranking_completed) {
|
||||
newEntry.assignments.push(assignment);
|
||||
}
|
||||
resultArray.push(newEntry);
|
||||
}
|
||||
}
|
||||
|
||||
// filter out entries without assignments
|
||||
resultArray = resultArray.filter((entry) => entry.assignments.length > 0);
|
||||
|
||||
// calculate average grade
|
||||
for (const entry of resultArray) {
|
||||
entry.sumAverageEvaluationPercent = _.sumBy(entry.assignments, (a) => {
|
||||
return (
|
||||
(a.metrics.average_evaluation_percent ?? 0) *
|
||||
(a.metrics.competence_certificate_weight ?? 1)
|
||||
);
|
||||
});
|
||||
entry.averageEvaluationPercent =
|
||||
entry.sumAverageEvaluationPercent /
|
||||
_.sumBy(entry.assignments, (a) => {
|
||||
return a.metrics.competence_certificate_weight ?? 1;
|
||||
});
|
||||
entry.averageGrade = percentToRoundedGrade(entry.averageEvaluationPercent, false);
|
||||
}
|
||||
return resultArray;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bg-gray-200">
|
||||
<div v-if="loading" class="m-8 flex justify-center">
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
<div v-else class="container-large flex flex-col space-y-8">
|
||||
<router-link class="btn-text inline-flex items-center pl-0" to="/">
|
||||
<it-icon-arrow-left />
|
||||
<span>{{ $t("general.back") }}</span>
|
||||
</router-link>
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold">{{ $t("a.Statistik") }}</h2>
|
||||
<p class="text-gray-800">
|
||||
{{ $t("a.Statistik für alle Lernenden") }}
|
||||
</p>
|
||||
<pre>
|
||||
{{ courseSessionCompetenceAssignments }}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -339,6 +339,7 @@ const router = createRouter({
|
|||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
path: "/statistic/:agentRole/:courseSlug/assignment",
|
||||
props: true,
|
||||
|
|
@ -351,6 +352,12 @@ const router = createRouter({
|
|||
component: () =>
|
||||
import("@/pages/dashboard/agentAssignment/AgentAssignmentDetailPage.vue"),
|
||||
},
|
||||
{
|
||||
path: "/statistic/:agentRole/:courseSlug/competence-grade",
|
||||
props: true,
|
||||
component: () =>
|
||||
import("@/pages/dashboard/agentAssignment/AgentCompetenceGradePage.vue"),
|
||||
},
|
||||
|
||||
{
|
||||
path: "/shop",
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ class AssignmentCompletionMetricsType(graphene.ObjectType):
|
|||
ranking_completed = graphene.Boolean(required=True)
|
||||
average_passed = graphene.Float(required=True)
|
||||
average_evaluation_percent = graphene.Float()
|
||||
competence_certificate_weight = graphene.Float()
|
||||
|
||||
|
||||
class AssignmentStatisticsRecordType(graphene.ObjectType):
|
||||
|
|
@ -149,6 +150,7 @@ def get_assignment_completion_metrics(
|
|||
ranking_completed=(passed_count > 0 or failed_count > 0), # noqa
|
||||
average_passed=average_passed, # noqa
|
||||
average_evaluation_percent=average_evaluation_percent, # noqa
|
||||
competence_certificate_weight=assignment.competence_certificate_weight, # noqa
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue