Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notify users if they have submitted a text answer but sent no description #1421

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions trojsten/contests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from trojsten.contests.models import Round
from trojsten.results.helpers import UserResult
from trojsten.results.manager import get_results_tags_for_rounds
from trojsten.submit.constants import SUBMIT_TYPE_DESCRIPTION, SUBMIT_TYPE_TEXT
from trojsten.submit.models import Submit

from .constants import DEFAULT_NUMBER_OF_TAGS, MAX_NUMBER_OF_TAGS

Expand Down Expand Up @@ -41,3 +43,17 @@ def get_points_from_submits(tasks, submits):
submit.task, submit.submit_type, submit.user_points, submit.testing_status
)
return res


def check_description_at_text_submit(user, tasks):
user_submits = Submit.objects.latest_for_user(tasks, user)
for task in tasks:
if (
task.has_text_submit
and task.has_description
and task.round.can_submit
and user_submits.filter(task=task, submit_type=SUBMIT_TYPE_TEXT, points__gt=0)
and not user_submits.filter(task=task, submit_type=SUBMIT_TYPE_DESCRIPTION)
):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Toto má potenciál spraviť pomerne veľké množstvo dotazov na databázu.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Máš nejaký návrh, ako to spraviť lepšie? Ak to bude iba 1 query a toto finálne filtrovanie sa urobí čisto v Pythone, pomôže to alebo sa to zhorší?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gardenerik Vieš sa, prosím, vyjadriť k tomuto? Ako zefektívniť ten dotaz na databázu?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

asi by som si vybral všetky submity, ktoré ťa zaujímajú a potom cez nejaký dict zisťovať, či pre danú úlohu (ne)existujú oba

return True
return False
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
{% load utils %}
{% load i18n %}
<!-- Nav tabs -->

{% if warning_no_description %}
<div class="alert alert-danger">
{% trans "You have submitted a text answer but have not submitted a description. This may lead to point deduction." %}
</div>
{% endif %}

{% if categories.count > 1 %}
<ul class="nav nav-tabs" role="tablist">
<li class="active">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
{% load statements_parts %}
{% load staticfiles %}
{% load utils %}
{% load i18n %}

{% block stylesheets %}
{{ block.super }}
Expand Down Expand Up @@ -39,6 +40,11 @@ <h1 id="article-title" class="task-name">{{ task.number }}. {{ task.name }}
{% endblock %}

{% block page_content %}
{% if warning_no_description %}
<div class="alert alert-danger">
{% trans "You have submitted a text answer but have not submitted a description. This may lead to point deduction." %}
</div>
{% endif %}
{% show_progress task.round %}
{% if task.description_points > 0 or task.source_points > 0 %}
<div class="well pull-right task-points">
Expand Down
4 changes: 3 additions & 1 deletion trojsten/contests/templatetags/statements_parts.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from trojsten.submit.models import Submit
from trojsten.utils import utils

from ..helpers import get_points_from_submits, slice_tag_list
from ..helpers import check_description_at_text_submit, get_points_from_submits, slice_tag_list

register = template.Library()

Expand All @@ -34,6 +34,8 @@ def show_task_list(context, round):
"tasks": tasks,
"categories": categories,
"solutions_visible": round.solutions_are_visible_for_user(context["user"]),
"warning_no_description": context["user"].is_authenticated
and check_description_at_text_submit(context["user"], tasks),
}
if context["user"].is_authenticated:
submits = Submit.objects.latest_for_user(tasks, context["user"])
Expand Down
107 changes: 107 additions & 0 deletions trojsten/contests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,10 @@ def setUp(self):
self.nonstaff_user = User.objects.create(username="nonstaff")
self.task_url = reverse("task_statement", kwargs={"task_id": self.task.id})
self.solution_url = reverse("solution_statement", kwargs={"task_id": self.task.id})
self.point_deduction_message = (
"You have submitted a text answer but "
"have not submitted a description. This may lead to point deduction."
)

def test_invalid_task(self):
url = reverse("task_statement", kwargs={"task_id": get_noexisting_id(Task)})
Expand Down Expand Up @@ -416,6 +420,109 @@ def test_missing_solution_statement_file(self):
self.assertContains(response, "Test task 2")
self.assertContains(response, "test <b>html</b> task statement")

def test_statement_only_text_submit(self):
self.client.force_login(self.nonstaff_user)
self.task.text_submit_solution = ["Password"]
self.task.save()
Submit.objects.create(
task=self.task,
user=self.nonstaff_user,
submit_type=submit_constants.SUBMIT_TYPE_TEXT,
testing_status=submit_constants.SUBMIT_STATUS_REVIEWED,
points=5,
)
url = reverse("task_statement", kwargs={"task_id": self.task.id})
response = self.client.get(url)
self.assertNotContains(response, _(self.point_deduction_message))
url = reverse("task_list", kwargs={"round_id": self.round.id})
response = self.client.get(url)
self.assertNotContains(response, _(self.point_deduction_message))

def test_text_submit_zero_points(self):
self.client.force_login(self.nonstaff_user)
self.task.text_submit_solution = ["Password"]
self.task.has_description = True
self.task.save()
Submit.objects.create(
task=self.task,
user=self.nonstaff_user,
submit_type=submit_constants.SUBMIT_TYPE_TEXT,
testing_status=submit_constants.SUBMIT_STATUS_REVIEWED,
points=0,
)
url = reverse("task_statement", kwargs={"task_id": self.task.id})
response = self.client.get(url)
self.assertNotContains(response, _(self.point_deduction_message))
url = reverse("task_list", kwargs={"round_id": self.round.id})
response = self.client.get(url)
self.assertNotContains(response, _(self.point_deduction_message))

def test_missing_description(self):
self.client.force_login(self.nonstaff_user)
self.task.text_submit_solution = ["Password"]
self.task.has_description = True
self.task.save()
Submit.objects.create(
task=self.task,
user=self.nonstaff_user,
submit_type=submit_constants.SUBMIT_TYPE_TEXT,
testing_status=submit_constants.SUBMIT_STATUS_REVIEWED,
points=4,
)
url = reverse("task_statement", kwargs={"task_id": self.task.id})
response = self.client.get(url)
self.assertContains(response, _(self.point_deduction_message))
url = reverse("task_list", kwargs={"round_id": self.round.id})
response = self.client.get(url)
self.assertContains(response, _(self.point_deduction_message))

def test_missing_description_after_round_end(self):
self.client.force_login(self.nonstaff_user)
self.task.text_submit_solution = ["Password"]
self.task.has_description = True
self.task.save()
self.round.end_time = timezone.now() + timezone.timedelta(-8)
self.round.save()
Submit.objects.create(
task=self.task,
user=self.nonstaff_user,
submit_type=submit_constants.SUBMIT_TYPE_TEXT,
testing_status=submit_constants.SUBMIT_STATUS_REVIEWED,
points=4,
)
url = reverse("task_statement", kwargs={"task_id": self.task.id})
response = self.client.get(url)
self.assertNotContains(response, _(self.point_deduction_message))
url = reverse("task_list", kwargs={"round_id": self.round.id})
response = self.client.get(url)
self.assertNotContains(response, _(self.point_deduction_message))

def test_text_and_description_submitted(self):
self.client.force_login(self.nonstaff_user)
self.task.text_submit_solution = ["Password"]
self.task.has_description = True
self.task.save()
Submit.objects.create(
task=self.task,
user=self.nonstaff_user,
submit_type=submit_constants.SUBMIT_TYPE_TEXT,
testing_status=submit_constants.SUBMIT_STATUS_REVIEWED,
points=4,
)
Submit.objects.create(
task=self.task,
user=self.nonstaff_user,
submit_type=submit_constants.SUBMIT_TYPE_DESCRIPTION,
testing_status=submit_constants.SUBMIT_STATUS_IN_QUEUE,
points=0,
)
url = reverse("task_statement", kwargs={"task_id": self.task.id})
response = self.client.get(url)
self.assertNotContains(response, _(self.point_deduction_message))
url = reverse("task_list", kwargs={"round_id": self.round.id})
response = self.client.get(url)
self.assertNotContains(response, _(self.point_deduction_message))


@override_settings(
TASK_STATEMENTS_STORAGE=FileSystemStorage(
Expand Down
4 changes: 4 additions & 0 deletions trojsten/contests/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from trojsten.utils.utils import is_true

from . import constants
from .helpers import check_description_at_text_submit


@get_article(can_read=True)
Expand All @@ -34,6 +35,9 @@ def _statement_view(request, task_id, solution=False):
if solution and task.solution_file_exists:
with settings.TASK_STATEMENTS_STORAGE.open(task.get_path(solution=True)) as f:
template_data["solution_text"] = f.read().decode()
template_data[
"warning_no_description"
] = request.user.is_authenticated and check_description_at_text_submit(request.user, [task])
return render(
request,
"trojsten/contests/view_{}_statement.html".format("solution" if solution else "task"),
Expand Down
3 changes: 3 additions & 0 deletions trojsten/locale/sk/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -1016,3 +1016,6 @@ msgstr "Len tento seminár"

msgid "Include all sites"
msgstr "Zahrnúť všetky semináre"

msgid "You have submitted a text answer but have not submitted a description. This may lead to point deduction."
msgstr "Máš odovzdanú textovú odpoveď, ale žiaden popis. Toto môže viesť k strate bodov."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
msgstr "Máš odovzdanú textovú odpoveď, ale žiaden popis. Toto môže viesť k strate bodov."
msgstr "Máš odovzdanú textovú odpoveď, ale žiaden popis. Toto môže viesť k strate bodov."