Show grades instead of points for certificates
This commit is contained in:
parent
8cab40f1d5
commit
4b9614d89d
|
|
@ -5,8 +5,8 @@ import CompetenceAssignmentRow from "@/pages/competence/CompetenceAssignmentRow.
|
|||
import { computed } from "vue";
|
||||
import ItProgress from "@/components/ui/ItProgress.vue";
|
||||
import {
|
||||
assignmentsMaxEvaluationPoints,
|
||||
assignmentsUserPoints,
|
||||
calcCompetenceCertificateGrade,
|
||||
competenceCertificateProgressStatusCount,
|
||||
} from "@/pages/competence/utils";
|
||||
|
||||
|
|
@ -18,14 +18,14 @@ const props = defineProps<{
|
|||
frontendUrl?: string;
|
||||
}>();
|
||||
|
||||
const totalPointsEvaluatedAssignments = computed(() => {
|
||||
return assignmentsMaxEvaluationPoints(props.competenceCertificate.assignments);
|
||||
});
|
||||
|
||||
const userPointsEvaluatedAssignments = computed(() => {
|
||||
return assignmentsUserPoints(props.competenceCertificate.assignments);
|
||||
});
|
||||
|
||||
const userGrade = computed(() => {
|
||||
return calcCompetenceCertificateGrade(props.competenceCertificate.assignments);
|
||||
});
|
||||
|
||||
const numAssignmentsEvaluated = computed(() => {
|
||||
return props.competenceCertificate.assignments.filter((a) => {
|
||||
return a.completion?.completion_status === "EVALUATION_SUBMITTED";
|
||||
|
|
@ -75,10 +75,7 @@ const frontendUrl = computed(() => {
|
|||
class="py-4"
|
||||
:class="{ 'heading-1': props.detailView, 'heading-2': !props.detailView }"
|
||||
>
|
||||
{{ userPointsEvaluatedAssignments }}
|
||||
</div>
|
||||
<div class="ml-1">
|
||||
{{ $t("assignment.von x Punkten", { x: totalPointsEvaluatedAssignments }) }}
|
||||
{{ userGrade }}
|
||||
</div>
|
||||
</section>
|
||||
<section v-else class="py-2">
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import type { CompetenceCertificate } from "@/types";
|
|||
import { useCertificateQuery } from "@/composables";
|
||||
import CompetenceCertificateComponent from "@/pages/competence/CompetenceCertificateComponent.vue";
|
||||
import {
|
||||
assignmentsMaxEvaluationPoints,
|
||||
assignmentsUserPoints,
|
||||
calcCompetencesTotalGrade,
|
||||
} from "@/pages/competence/utils";
|
||||
import { useRoute } from "vue-router";
|
||||
import { getCertificates } from "@/services/competence";
|
||||
|
|
@ -44,8 +44,8 @@ const assignments = computed(() => {
|
|||
return competenceCertificates?.value?.flatMap((cc) => cc.assignments);
|
||||
});
|
||||
|
||||
const totalPointsEvaluatedAssignments = computed(() => {
|
||||
return assignmentsMaxEvaluationPoints(assignments.value ?? []);
|
||||
const totalGrade = computed(() => {
|
||||
return calcCompetencesTotalGrade(competenceCertificates.value ?? []);
|
||||
});
|
||||
|
||||
const userPointsEvaluatedAssignments = computed(() => {
|
||||
|
|
@ -91,10 +91,7 @@ onMounted(async () => {
|
|||
|
||||
<section v-if="userPointsEvaluatedAssignments > 0" class="flex items-center">
|
||||
<div class="heading-1 py-4">
|
||||
{{ userPointsEvaluatedAssignments }}
|
||||
</div>
|
||||
<div class="pl-2">
|
||||
{{ $t("assignment.von x Punkten", { x: totalPointsEvaluatedAssignments }) }}
|
||||
{{ totalGrade }}
|
||||
</div>
|
||||
</section>
|
||||
<section v-else class="my-4">
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ import { computed } from "vue";
|
|||
import type { CompetenceCertificate } from "@/types";
|
||||
import { useCurrentCourseSession } from "@/composables";
|
||||
import {
|
||||
assignmentsMaxEvaluationPoints,
|
||||
assignmentsUserPoints,
|
||||
calcCompetenceCertificateGrade,
|
||||
calcCompetencesTotalGrade,
|
||||
competenceCertificateProgressStatusCount,
|
||||
} from "@/pages/competence/utils";
|
||||
import ItProgress from "@/components/ui/ItProgress.vue";
|
||||
|
|
@ -42,10 +43,6 @@ const allAssignments = computed(() => {
|
|||
return competenceCertificates.value.flatMap((cc) => cc.assignments);
|
||||
});
|
||||
|
||||
const totalPointsEvaluatedAssignments = computed(() => {
|
||||
return assignmentsMaxEvaluationPoints(allAssignments.value);
|
||||
});
|
||||
|
||||
const userPointsEvaluatedAssignments = computed(() => {
|
||||
return assignmentsUserPoints(allAssignments.value);
|
||||
});
|
||||
|
|
@ -71,9 +68,8 @@ const router = useRouter();
|
|||
<div v-if="userPointsEvaluatedAssignments > 0">
|
||||
{{ $t("a.Zwischenstand") }} {{ $t("a.Gesamtpunktzahl") }}:
|
||||
<span class="font-bold">
|
||||
{{ userPointsEvaluatedAssignments }}
|
||||
{{ calcCompetencesTotalGrade(competenceCertificates ?? []) }}
|
||||
</span>
|
||||
{{ $t("assignment.von x Punkten", { x: totalPointsEvaluatedAssignments }) }}
|
||||
</div>
|
||||
<div v-else>
|
||||
{{ $t("a.competenceCertificateNoUserPoints") }}
|
||||
|
|
@ -92,14 +88,12 @@ const router = useRouter();
|
|||
{{ certificate.title }}
|
||||
</div>
|
||||
<div class="mt-4 lg:mt-0">
|
||||
<span class="text-bold">
|
||||
{{ assignmentsUserPoints(certificate.assignments) }}
|
||||
<span
|
||||
v-if="calcCompetenceCertificateGrade(certificate.assignments)"
|
||||
class="text-bold"
|
||||
>
|
||||
{{ calcCompetenceCertificateGrade(certificate.assignments) }}
|
||||
</span>
|
||||
{{
|
||||
$t("assignment.von x Punkten", {
|
||||
x: assignmentsMaxEvaluationPoints(certificate.assignments),
|
||||
})
|
||||
}}
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import type { StatusCount } from "@/components/ui/ItProgress.vue";
|
||||
import type { CompetenceCertificateAssignment } from "@/types";
|
||||
import { percentToGrade } from "@/services/assignmentService";
|
||||
import type { CompetenceCertificate, CompetenceCertificateAssignment } from "@/types";
|
||||
import _ from "lodash";
|
||||
|
||||
export function assignmentsMaxEvaluationPoints(
|
||||
|
|
@ -20,6 +21,51 @@ export function assignmentsUserPoints(assignments: CompetenceCertificateAssignme
|
|||
).toFixed(1);
|
||||
}
|
||||
|
||||
export function calcCompetenceCertificateGrade(
|
||||
assignments: CompetenceCertificateAssignment[]
|
||||
) {
|
||||
const evaluatedAssignments = assignments.filter(
|
||||
(a) => a.completion?.completion_status === "EVALUATION_SUBMITTED"
|
||||
);
|
||||
|
||||
const adjustedResults = evaluatedAssignments.map((a) => {
|
||||
return (
|
||||
((a.completion?.evaluation_points ?? 0) / a.max_points) *
|
||||
a.competence_certificate_weight
|
||||
);
|
||||
});
|
||||
|
||||
const adjustedAssignmentCount = _.sum(
|
||||
evaluatedAssignments.map((a) => a.competence_certificate_weight)
|
||||
);
|
||||
|
||||
if (adjustedAssignmentCount === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return percentToGrade(_.sum(adjustedResults) / adjustedAssignmentCount);
|
||||
}
|
||||
|
||||
export function calcCompetencesTotalGrade(
|
||||
competenceCertificates: CompetenceCertificate[]
|
||||
) {
|
||||
const competenceCertificateGrades = competenceCertificates
|
||||
.map((cc) => {
|
||||
return calcCompetenceCertificateGrade(cc.assignments);
|
||||
})
|
||||
.filter((g) => {
|
||||
// filter out "empty" grades
|
||||
return !!g;
|
||||
});
|
||||
|
||||
const percentGraded =
|
||||
// @ts-ignore `g` cannot be undefined here
|
||||
_.sum(competenceCertificateGrades.map((g) => g - 1)) /
|
||||
(competenceCertificateGrades.length * 5);
|
||||
|
||||
return percentToGrade(percentGraded);
|
||||
}
|
||||
|
||||
export function competenceCertificateProgressStatusCount(
|
||||
assignments: CompetenceCertificateAssignment[]
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -90,3 +90,10 @@ export function pointsToGrade(points: number, maxPoints: number) {
|
|||
const halfGrade = grade / 2;
|
||||
return Math.min(halfGrade, 5) + 1;
|
||||
}
|
||||
|
||||
export function percentToGrade(percent: number) {
|
||||
// round to half-grades
|
||||
const grade = Math.round(percent * 10);
|
||||
const halfGrade = grade / 2;
|
||||
return Math.min(halfGrade, 5) + 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -392,6 +392,7 @@ export type ActionCompetence = Omit<
|
|||
export interface CompetenceCertificateAssignment extends BaseCourseWagtailPage {
|
||||
assignment_type: "CASEWORK" | "EDONIQ_TEST";
|
||||
max_points: number;
|
||||
competence_certificate_weight: number;
|
||||
learning_content:
|
||||
| (BaseCourseWagtailPage & {
|
||||
circle: CircleLight;
|
||||
|
|
|
|||
|
|
@ -4,15 +4,16 @@ from django.db import migrations, models
|
|||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assignment', '0012_auto_20240124_1004'),
|
||||
("assignment", "0012_auto_20240124_1004"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='assignment',
|
||||
name='competence_certificate_weight',
|
||||
field=models.FloatField(default=1.0, help_text='Gewichtung für den Kompetenznachweis'),
|
||||
model_name="assignment",
|
||||
name="competence_certificate_weight",
|
||||
field=models.FloatField(
|
||||
default=1.0, help_text="Gewichtung für den Kompetenznachweis"
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
Loading…
Reference in New Issue