Add `evaluation_points_deducted` field
This commit is contained in:
parent
fe0fb55bc9
commit
7c4300f40c
|
|
@ -18,3 +18,10 @@ class AssignmentCompletionAdmin(admin.ModelAdmin):
|
||||||
"assignment_user",
|
"assignment_user",
|
||||||
"course_session",
|
"course_session",
|
||||||
]
|
]
|
||||||
|
list_filter = [
|
||||||
|
"completion_status",
|
||||||
|
"assignment__assignment_type",
|
||||||
|
"course_session__course",
|
||||||
|
"course_session",
|
||||||
|
]
|
||||||
|
search_fields = ["assignment_user__email"]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 3.2.20 on 2024-05-21 13:43
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('assignment', '0013_assignment_competence_certificate_weight'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='assignmentcompletion',
|
||||||
|
name='evaluation_points_deducted',
|
||||||
|
field=models.FloatField(default=0.0, verbose_name='Punkteabzug'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -340,10 +340,18 @@ class AssignmentCompletion(models.Model):
|
||||||
related_name="+",
|
related_name="+",
|
||||||
)
|
)
|
||||||
evaluation_points = models.FloatField(null=True, blank=True)
|
evaluation_points = models.FloatField(null=True, blank=True)
|
||||||
|
evaluation_points_deducted = models.FloatField(
|
||||||
|
default=0.0, verbose_name="Punkteabzug"
|
||||||
|
)
|
||||||
evaluation_max_points = models.FloatField(null=True, blank=True)
|
evaluation_max_points = models.FloatField(null=True, blank=True)
|
||||||
evaluation_passed = models.BooleanField(null=True, blank=True)
|
evaluation_passed = models.BooleanField(null=True, blank=True)
|
||||||
edoniq_extended_time_flag = models.BooleanField(default=False)
|
edoniq_extended_time_flag = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def evaluation_points_final(self):
|
||||||
|
# with Django>=5 it can be replaced with a `GeneratedField`
|
||||||
|
return (self.evaluation_points or 0.0) - self.evaluation_points_deducted
|
||||||
|
|
||||||
assignment_user = models.ForeignKey(User, on_delete=models.CASCADE)
|
assignment_user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
assignment = models.ForeignKey(Assignment, on_delete=models.CASCADE)
|
assignment = models.ForeignKey(Assignment, on_delete=models.CASCADE)
|
||||||
course_session = models.ForeignKey("course.CourseSession", on_delete=models.CASCADE)
|
course_session = models.ForeignKey("course.CourseSession", on_delete=models.CASCADE)
|
||||||
|
|
|
||||||
|
|
@ -66,11 +66,16 @@ from vbv_lernwelt.self_evaluation_feedback.models import (
|
||||||
default=None,
|
default=None,
|
||||||
help="Provide assignment evaluation scores in the format: 6,6,6,3,3",
|
help="Provide assignment evaluation scores in the format: 6,6,6,3,3",
|
||||||
)
|
)
|
||||||
|
@click.option(
|
||||||
|
"--assignment-points-deducted",
|
||||||
|
default=0,
|
||||||
|
help="Provide assignment points deducted",
|
||||||
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"--create-edoniq-test-results",
|
"--create-edoniq-test-results",
|
||||||
type=(int, int),
|
type=(int, int, float),
|
||||||
default=(None, None),
|
default=(None, None, 0),
|
||||||
metavar="USER_POINTS MAX_POINTS",
|
metavar="USER_POINTS MAX_POINTS POINTS_DEDUCTED",
|
||||||
help="Create edoniq result data for test-student1@example.com with user points and max points",
|
help="Create edoniq result data for test-student1@example.com with user points and max points",
|
||||||
)
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
|
|
@ -112,6 +117,7 @@ def command(
|
||||||
create_assignment_completion,
|
create_assignment_completion,
|
||||||
create_assignment_evaluation,
|
create_assignment_evaluation,
|
||||||
assignment_evaluation_scores,
|
assignment_evaluation_scores,
|
||||||
|
assignment_points_deducted,
|
||||||
create_edoniq_test_results,
|
create_edoniq_test_results,
|
||||||
create_feedback_responses,
|
create_feedback_responses,
|
||||||
create_course_completion_performance_criteria,
|
create_course_completion_performance_criteria,
|
||||||
|
|
@ -171,9 +177,10 @@ def command(
|
||||||
assignment_user=User.objects.get(id=TEST_STUDENT1_USER_ID),
|
assignment_user=User.objects.get(id=TEST_STUDENT1_USER_ID),
|
||||||
evaluation_user=User.objects.get(id=TEST_TRAINER1_USER_ID),
|
evaluation_user=User.objects.get(id=TEST_TRAINER1_USER_ID),
|
||||||
input_scores=assignment_evaluation_scores,
|
input_scores=assignment_evaluation_scores,
|
||||||
|
points_deducted=assignment_points_deducted,
|
||||||
)
|
)
|
||||||
|
|
||||||
user_points, max_points = create_edoniq_test_results
|
user_points, max_points, points_deducted = create_edoniq_test_results
|
||||||
if user_points is not None and max_points is not None:
|
if user_points is not None and max_points is not None:
|
||||||
print(
|
print(
|
||||||
f"Create edoniq test results: User Points: {user_points}, Max Points: {max_points}"
|
f"Create edoniq test results: User Points: {user_points}, Max Points: {max_points}"
|
||||||
|
|
@ -186,6 +193,7 @@ def command(
|
||||||
assignment_user=User.objects.get(id=TEST_STUDENT1_USER_ID),
|
assignment_user=User.objects.get(id=TEST_STUDENT1_USER_ID),
|
||||||
user_points=user_points,
|
user_points=user_points,
|
||||||
max_points=max_points,
|
max_points=max_points,
|
||||||
|
evaluation_points_deducted=points_deducted,
|
||||||
)
|
)
|
||||||
|
|
||||||
if create_feedback_responses:
|
if create_feedback_responses:
|
||||||
|
|
|
||||||
|
|
@ -58,3 +58,10 @@ def pretty_print_json(json_string):
|
||||||
# pylint: disable=broad-except
|
# pylint: disable=broad-except
|
||||||
except Exception:
|
except Exception:
|
||||||
return json_string
|
return json_string
|
||||||
|
|
||||||
|
|
||||||
|
def safe_deque_popleft(deq, default=None):
|
||||||
|
try:
|
||||||
|
return deq.popleft()
|
||||||
|
except IndexError:
|
||||||
|
return default
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,9 @@ def cypress_reset_view(request):
|
||||||
assignment_evaluation_scores = request.data.get("assignment_evaluation_scores")
|
assignment_evaluation_scores = request.data.get("assignment_evaluation_scores")
|
||||||
if assignment_evaluation_scores:
|
if assignment_evaluation_scores:
|
||||||
options["assignment_evaluation_scores"] = assignment_evaluation_scores
|
options["assignment_evaluation_scores"] = assignment_evaluation_scores
|
||||||
|
options["assignment_points_deducted"] = float(
|
||||||
|
request.data.get("assignment_points_deducted") or 0
|
||||||
|
)
|
||||||
|
|
||||||
options["create_feedback_responses"] = (
|
options["create_feedback_responses"] = (
|
||||||
request.data.get("create_feedback_responses") == "true"
|
request.data.get("create_feedback_responses") == "true"
|
||||||
|
|
@ -159,10 +162,12 @@ def cypress_reset_view(request):
|
||||||
# edoniq test results
|
# edoniq test results
|
||||||
edoniq_test_user_points = request.data.get("edoniq_test_user_points")
|
edoniq_test_user_points = request.data.get("edoniq_test_user_points")
|
||||||
edoniq_test_max_points = request.data.get("edoniq_test_max_points")
|
edoniq_test_max_points = request.data.get("edoniq_test_max_points")
|
||||||
|
edoniq_points_deducted = request.data.get("edoniq_test_points_deducted") or 0
|
||||||
if bool(edoniq_test_user_points and edoniq_test_max_points):
|
if bool(edoniq_test_user_points and edoniq_test_max_points):
|
||||||
options["create_edoniq_test_results"] = (
|
options["create_edoniq_test_results"] = (
|
||||||
int(edoniq_test_user_points),
|
int(edoniq_test_user_points),
|
||||||
int(edoniq_test_max_points),
|
int(edoniq_test_max_points),
|
||||||
|
float(edoniq_points_deducted),
|
||||||
)
|
)
|
||||||
|
|
||||||
options["create_course_completion_performance_criteria"] = (
|
options["create_course_completion_performance_criteria"] = (
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
from collections import deque
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from dateutil.relativedelta import MO, relativedelta, TH, TU, WE
|
from dateutil.relativedelta import MO, relativedelta, TH, TU, WE
|
||||||
|
|
@ -42,6 +43,7 @@ from vbv_lernwelt.core.constants import (
|
||||||
TEST_TRAINER1_USER_ID,
|
TEST_TRAINER1_USER_ID,
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.core.models import User
|
from vbv_lernwelt.core.models import User
|
||||||
|
from vbv_lernwelt.core.utils import safe_deque_popleft
|
||||||
from vbv_lernwelt.course.consts import COURSE_TEST_ID
|
from vbv_lernwelt.course.consts import COURSE_TEST_ID
|
||||||
from vbv_lernwelt.course.factories import CoursePageFactory
|
from vbv_lernwelt.course.factories import CoursePageFactory
|
||||||
from vbv_lernwelt.course.models import (
|
from vbv_lernwelt.course.models import (
|
||||||
|
|
@ -350,20 +352,27 @@ def create_test_assignment_submitted_data(assignment, course_session, user):
|
||||||
|
|
||||||
|
|
||||||
def create_test_assignment_evaluation_data(
|
def create_test_assignment_evaluation_data(
|
||||||
assignment, course_session, assignment_user, evaluation_user, input_scores=None
|
assignment,
|
||||||
|
course_session,
|
||||||
|
assignment_user,
|
||||||
|
evaluation_user,
|
||||||
|
input_scores=None,
|
||||||
|
points_deducted=0,
|
||||||
):
|
):
|
||||||
if assignment and course_session and assignment_user and evaluation_user:
|
if assignment and course_session and assignment_user and evaluation_user:
|
||||||
subtasks = assignment.get_evaluation_tasks()
|
subtasks = assignment.get_evaluation_tasks()
|
||||||
evaluation_points = 0
|
evaluation_points = 0
|
||||||
|
|
||||||
|
input_scores_deque = deque(input_scores) if input_scores else deque()
|
||||||
|
|
||||||
for index, evaluation_task in enumerate(subtasks):
|
for index, evaluation_task in enumerate(subtasks):
|
||||||
task_score = evaluation_task["value"]["max_points"]
|
task_score = evaluation_task["value"]["max_points"]
|
||||||
if input_scores[index] < len(input_scores):
|
input_score = safe_deque_popleft(input_scores_deque)
|
||||||
|
if input_score is not None:
|
||||||
task_score = input_scores[index]
|
task_score = input_scores[index]
|
||||||
|
|
||||||
evaluation_points += task_score
|
evaluation_points += task_score
|
||||||
|
|
||||||
update_assignment_completion(
|
ac, _ = update_assignment_completion(
|
||||||
assignment_user=assignment_user,
|
assignment_user=assignment_user,
|
||||||
assignment=assignment,
|
assignment=assignment,
|
||||||
course_session=course_session,
|
course_session=course_session,
|
||||||
|
|
@ -380,7 +389,7 @@ def create_test_assignment_evaluation_data(
|
||||||
evaluation_user=evaluation_user,
|
evaluation_user=evaluation_user,
|
||||||
)
|
)
|
||||||
|
|
||||||
update_assignment_completion(
|
ac, _ = update_assignment_completion(
|
||||||
assignment_user=assignment_user,
|
assignment_user=assignment_user,
|
||||||
assignment=assignment,
|
assignment=assignment,
|
||||||
course_session=course_session,
|
course_session=course_session,
|
||||||
|
|
@ -391,16 +400,26 @@ def create_test_assignment_evaluation_data(
|
||||||
evaluation_points=evaluation_points,
|
evaluation_points=evaluation_points,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# take the last input score as deduction if there is one left...
|
||||||
|
if points_deducted > 0:
|
||||||
|
ac.evaluation_points_deducted = points_deducted
|
||||||
|
ac.save()
|
||||||
|
|
||||||
|
|
||||||
def create_edoniq_test_result_data(
|
def create_edoniq_test_result_data(
|
||||||
assignment, course_session, assignment_user, user_points=19, max_points=24
|
assignment,
|
||||||
|
course_session,
|
||||||
|
assignment_user,
|
||||||
|
user_points=19,
|
||||||
|
max_points=24,
|
||||||
|
evaluation_points_deducted=0,
|
||||||
):
|
):
|
||||||
assignment.assignment.evaluation_tasks.raw_data[0]["value"][
|
assignment.assignment.evaluation_tasks.raw_data[0]["value"][
|
||||||
"max_points"
|
"max_points"
|
||||||
] = max_points
|
] = max_points
|
||||||
assignment.assignment.save()
|
assignment.assignment.save()
|
||||||
if assignment and course_session and assignment_user:
|
if assignment and course_session and assignment_user:
|
||||||
update_assignment_completion(
|
ac, _ = update_assignment_completion(
|
||||||
assignment_user=assignment_user,
|
assignment_user=assignment_user,
|
||||||
assignment=assignment,
|
assignment=assignment,
|
||||||
course_session=course_session,
|
course_session=course_session,
|
||||||
|
|
@ -412,6 +431,10 @@ def create_edoniq_test_result_data(
|
||||||
evaluation_max_points=max_points,
|
evaluation_max_points=max_points,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if evaluation_points_deducted > 0:
|
||||||
|
ac.evaluation_points_deducted = evaluation_points_deducted
|
||||||
|
ac.save()
|
||||||
|
|
||||||
|
|
||||||
def create_feedback_response_data(
|
def create_feedback_response_data(
|
||||||
course_session,
|
course_session,
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,10 @@
|
||||||
<label>
|
<label>
|
||||||
evaluation score:
|
evaluation score:
|
||||||
<input type="text" name="assignment_evaluation_scores" placeholder="6,6,6,3,3">
|
<input type="text" name="assignment_evaluation_scores" placeholder="6,6,6,3,3">
|
||||||
|
</label><br>
|
||||||
|
<label>
|
||||||
|
points deducted:
|
||||||
|
<input type="number" name="assignment_points_deducted" min="0">
|
||||||
</label>
|
</label>
|
||||||
<div style="margin-bottom: 8px; padding: 4px; border-bottom: 1px lightblue solid"></div>
|
<div style="margin-bottom: 8px; padding: 4px; border-bottom: 1px lightblue solid"></div>
|
||||||
|
|
||||||
|
|
@ -84,6 +88,10 @@
|
||||||
<label>
|
<label>
|
||||||
max points:
|
max points:
|
||||||
<input type="number" name="edoniq_test_max_points" min="0">
|
<input type="number" name="edoniq_test_max_points" min="0">
|
||||||
|
</label><br>
|
||||||
|
<label>
|
||||||
|
points deducted:
|
||||||
|
<input type="number" name="edoniq_test_points_deducted" min="0">
|
||||||
</label>
|
</label>
|
||||||
<div style="margin-bottom: 8px; padding: 4px; border-bottom: 1px lightblue solid"></div>
|
<div style="margin-bottom: 8px; padding: 4px; border-bottom: 1px lightblue solid"></div>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue