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!
|
ranking_completed: Boolean!
|
||||||
average_passed: Float!
|
average_passed: Float!
|
||||||
average_evaluation_percent: Float
|
average_evaluation_percent: Float
|
||||||
|
competence_certificate_weight: Float
|
||||||
}
|
}
|
||||||
|
|
||||||
type AssignmentStatisticsSummaryType {
|
type AssignmentStatisticsSummaryType {
|
||||||
|
|
|
||||||
|
|
@ -481,6 +481,7 @@ export const DASHBOARD_COURSE_STATISTICS = graphql(`
|
||||||
ranking_completed
|
ranking_completed
|
||||||
average_evaluation_percent
|
average_evaluation_percent
|
||||||
average_passed
|
average_passed
|
||||||
|
competence_certificate_weight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -555,6 +556,7 @@ export const DASHBOARD_MENTOR_COMPETENCE_SUMMARY = graphql(`
|
||||||
failed_count
|
failed_count
|
||||||
unranked_count
|
unranked_count
|
||||||
ranking_completed
|
ranking_completed
|
||||||
|
competence_certificate_weight
|
||||||
average_evaluation_percent
|
average_evaluation_percent
|
||||||
average_passed
|
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",
|
path: "/statistic/:agentRole/:courseSlug/assignment",
|
||||||
props: true,
|
props: true,
|
||||||
|
|
@ -351,6 +352,12 @@ const router = createRouter({
|
||||||
component: () =>
|
component: () =>
|
||||||
import("@/pages/dashboard/agentAssignment/AgentAssignmentDetailPage.vue"),
|
import("@/pages/dashboard/agentAssignment/AgentAssignmentDetailPage.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/statistic/:agentRole/:courseSlug/competence-grade",
|
||||||
|
props: true,
|
||||||
|
component: () =>
|
||||||
|
import("@/pages/dashboard/agentAssignment/AgentCompetenceGradePage.vue"),
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: "/shop",
|
path: "/shop",
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ class AssignmentCompletionMetricsType(graphene.ObjectType):
|
||||||
ranking_completed = graphene.Boolean(required=True)
|
ranking_completed = graphene.Boolean(required=True)
|
||||||
average_passed = graphene.Float(required=True)
|
average_passed = graphene.Float(required=True)
|
||||||
average_evaluation_percent = graphene.Float()
|
average_evaluation_percent = graphene.Float()
|
||||||
|
competence_certificate_weight = graphene.Float()
|
||||||
|
|
||||||
|
|
||||||
class AssignmentStatisticsRecordType(graphene.ObjectType):
|
class AssignmentStatisticsRecordType(graphene.ObjectType):
|
||||||
|
|
@ -149,6 +150,7 @@ def get_assignment_completion_metrics(
|
||||||
ranking_completed=(passed_count > 0 or failed_count > 0), # noqa
|
ranking_completed=(passed_count > 0 or failed_count > 0), # noqa
|
||||||
average_passed=average_passed, # noqa
|
average_passed=average_passed, # noqa
|
||||||
average_evaluation_percent=average_evaluation_percent, # noqa
|
average_evaluation_percent=average_evaluation_percent, # noqa
|
||||||
|
competence_certificate_weight=assignment.competence_certificate_weight, # noqa
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue