From 22e1407964aa4a74622be73df3b676ecd71d7a1c Mon Sep 17 00:00:00 2001 From: thegm445 Date: Fri, 1 Dec 2023 16:37:44 -0300 Subject: [PATCH 01/13] feat(user-task-points): users now are able to get points in AC status of submission --- apps/tasks/views.py | 6 +++++- apps/users/migrations/0002_user_score.py | 17 +++++++++++++++++ apps/users/models.py | 3 ++- 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 apps/users/migrations/0002_user_score.py diff --git a/apps/tasks/views.py b/apps/tasks/views.py index 2e0f441..a90b971 100644 --- a/apps/tasks/views.py +++ b/apps/tasks/views.py @@ -9,7 +9,7 @@ from django.views.generic.edit import FormMixin from apps.submissions.forms import SubmissionForm -from apps.submissions.models import Submission +from apps.submissions.models import Submission, SubmissionStatus from apps.tasks.models import Task from server import celery @@ -49,6 +49,10 @@ def handle_submission(code: str, task_id: int, submission_id: int) -> None: submission.status = "AC" if output == task.output_file else "WA" submission.save() + if submission.status == SubmissionStatus.ACCEPTED: + submission.author.score += task.score + submission.author.save() + class DetailView(FormMixinBase, DetailViewBase): model = Task diff --git a/apps/users/migrations/0002_user_score.py b/apps/users/migrations/0002_user_score.py new file mode 100644 index 0000000..a937658 --- /dev/null +++ b/apps/users/migrations/0002_user_score.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.7 on 2023-12-01 19:35 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("users", "0001_initial"), + ] + + operations = [ + migrations.AddField( + model_name="user", + name="score", + field=models.IntegerField(default=0), + ), + ] diff --git a/apps/users/models.py b/apps/users/models.py index 542ad76..901f04b 100644 --- a/apps/users/models.py +++ b/apps/users/models.py @@ -1,7 +1,7 @@ from typing import TYPE_CHECKING, Any, List from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin -from django.db.models import BooleanField, CharField, EmailField +from django.db.models import BooleanField, CharField, EmailField, IntegerField from apps.users.managers import UserManager from core.models import TimestampedModel @@ -19,6 +19,7 @@ class User(AbstractBaseUser, PermissionsMixin, TimestampedModel): email = EmailField(db_index=True, max_length=256, unique=True) username = CharField(db_index=True, max_length=128, unique=True) + score = IntegerField(default=0) # When a user no longer wishes to use our platform, they may try to # delete there account. That's a problem for us because the data we From cd56e42e05101ffe53b94316999f8b2b3f96c777 Mon Sep 17 00:00:00 2001 From: thegm445 Date: Fri, 1 Dec 2023 16:51:44 -0300 Subject: [PATCH 02/13] feat(user-task-points): users are now not able to get infinite points for the same task --- apps/tasks/views.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/apps/tasks/views.py b/apps/tasks/views.py index a90b971..8c5e238 100644 --- a/apps/tasks/views.py +++ b/apps/tasks/views.py @@ -49,9 +49,20 @@ def handle_submission(code: str, task_id: int, submission_id: int) -> None: submission.status = "AC" if output == task.output_file else "WA" submission.save() + has_been_accepted = ( + Submission._default_manager.filter( + author=submission.author, + task=task, + status=SubmissionStatus.ACCEPTED, + ) + .exclude(id=submission.id) + .exists() + ) + if submission.status == SubmissionStatus.ACCEPTED: - submission.author.score += task.score - submission.author.save() + if not has_been_accepted: + submission.author.score += task.score + submission.author.save() class DetailView(FormMixinBase, DetailViewBase): From 5bf5d80e421fd45a92e7691b543d3f7687d8ef58 Mon Sep 17 00:00:00 2001 From: thegm445 Date: Fri, 1 Dec 2023 20:47:43 -0300 Subject: [PATCH 03/13] fix(apps/tasks): fixed some issues appointed by reviewer --- apps/tasks/tests.py | 4 +++- apps/tasks/views.py | 10 ++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/tasks/tests.py b/apps/tasks/tests.py index fd33cdb..2ebdbcd 100644 --- a/apps/tasks/tests.py +++ b/apps/tasks/tests.py @@ -198,8 +198,10 @@ def setUp(self) -> None: self.task = Task._default_manager.create( title="Example task", description="Some example task", + score=200, contest=self.contest, ) + self.user = User._default_manager.create( email="user@email.com", username="user", @@ -210,7 +212,7 @@ def setUp(self) -> None: author=self.user, task=self.task, code="print('Hello, World!')", - status=SubmissionStatus.ACCEPTED, + status=SubmissionStatus.WAITING_JUDGE, ) self.url = reverse("tasks:detail", args=[self.task.id]) diff --git a/apps/tasks/views.py b/apps/tasks/views.py index 8c5e238..d7792f5 100644 --- a/apps/tasks/views.py +++ b/apps/tasks/views.py @@ -59,10 +59,12 @@ def handle_submission(code: str, task_id: int, submission_id: int) -> None: .exists() ) - if submission.status == SubmissionStatus.ACCEPTED: - if not has_been_accepted: - submission.author.score += task.score - submission.author.save() + if ( + submission.status == SubmissionStatus.ACCEPTED + and not has_been_accepted + ): + submission.author.score += task.score + submission.author.save() class DetailView(FormMixinBase, DetailViewBase): From daf9017b44f6363c42cda581da54083ec8799100 Mon Sep 17 00:00:00 2001 From: thegm445 Date: Fri, 1 Dec 2023 21:55:36 -0300 Subject: [PATCH 04/13] test(apps/tasks): new tests added --- apps/tasks/tests.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/apps/tasks/tests.py b/apps/tasks/tests.py index 2ebdbcd..f28eaea 100644 --- a/apps/tasks/tests.py +++ b/apps/tasks/tests.py @@ -200,6 +200,7 @@ def setUp(self) -> None: description="Some example task", score=200, contest=self.contest, + output_file="Hello, World!\n", ) self.user = User._default_manager.create( @@ -322,6 +323,50 @@ def test_handle_submission_with_wrong_output(self) -> None: fetch_redirect_response=True, ) + def test_submission_with_AC_status_increases_user_score(self) -> None: + handle_submission( + self.submission.code, self.task.id, self.submission.id + ) + + self.submission.refresh_from_db() + self.user.refresh_from_db() + + self.assertEqual(self.submission.status, SubmissionStatus.ACCEPTED) + self.assertEqual(self.user.score, self.task.score) + + def test_submission_with_non_AC_status_does_not_increase_user_score( + self, + ) -> None: + self.submission.code = 'print("Hello, Word")' + + handle_submission( + self.submission.code, self.task.id, self.submission.id + ) + + self.user.refresh_from_db() + + self.assertEqual(self.user.score, 0) + + def test_second_AC_submission_does_not_increase_user_score(self) -> None: + handle_submission( + self.submission.code, self.task.id, self.submission.id + ) + + second_submission = Submission._default_manager.create( + author=self.user, + task=self.task, + code="print('Hello, World!')", + status=SubmissionStatus.WAITING_JUDGE, + ) + + handle_submission.apply( + args=(second_submission.code, self.task.id, second_submission.id) + ) + + self.user.refresh_from_db() + + self.assertEqual(self.user.score, self.task.score) + def test_form_success_url(self) -> None: self.assertEqual(self.view.get_success_url(), self.url) From 183c3ef7cad483577165af3ed285a30a5d18a7a8 Mon Sep 17 00:00:00 2001 From: thegm445 Date: Fri, 1 Dec 2023 21:58:09 -0300 Subject: [PATCH 05/13] refactor(apps/tasks): tests are now more coherent with other tests --- apps/tasks/tests.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/tasks/tests.py b/apps/tasks/tests.py index f28eaea..27bb0a5 100644 --- a/apps/tasks/tests.py +++ b/apps/tasks/tests.py @@ -339,8 +339,8 @@ def test_submission_with_non_AC_status_does_not_increase_user_score( ) -> None: self.submission.code = 'print("Hello, Word")' - handle_submission( - self.submission.code, self.task.id, self.submission.id + handle_submission.apply( + args=(self.submission.code, self.task.id, self.submission.id) ) self.user.refresh_from_db() @@ -348,8 +348,8 @@ def test_submission_with_non_AC_status_does_not_increase_user_score( self.assertEqual(self.user.score, 0) def test_second_AC_submission_does_not_increase_user_score(self) -> None: - handle_submission( - self.submission.code, self.task.id, self.submission.id + handle_submission.apply( + args=(self.submission.code, self.task.id, self.submission.id) ) second_submission = Submission._default_manager.create( From 25d1bd1a6cb4575dbc650767ebfa2438ca8b1bdc Mon Sep 17 00:00:00 2001 From: thegm445 Date: Fri, 1 Dec 2023 21:59:36 -0300 Subject: [PATCH 06/13] refactor(apps/tasks): variable names describe better what they store --- apps/tasks/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/tasks/views.py b/apps/tasks/views.py index d7792f5..6140aff 100644 --- a/apps/tasks/views.py +++ b/apps/tasks/views.py @@ -49,7 +49,7 @@ def handle_submission(code: str, task_id: int, submission_id: int) -> None: submission.status = "AC" if output == task.output_file else "WA" submission.save() - has_been_accepted = ( + has_already_scored = ( Submission._default_manager.filter( author=submission.author, task=task, @@ -61,7 +61,7 @@ def handle_submission(code: str, task_id: int, submission_id: int) -> None: if ( submission.status == SubmissionStatus.ACCEPTED - and not has_been_accepted + and not has_already_scored ): submission.author.score += task.score submission.author.save() From 42322db000c590a7224934d511c78998ec28e1d5 Mon Sep 17 00:00:00 2001 From: thegm445 Date: Fri, 1 Dec 2023 23:07:27 -0300 Subject: [PATCH 07/13] refactor(apps/tasks): tests names now dont have upper case on them --- apps/tasks/tests.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/tasks/tests.py b/apps/tasks/tests.py index 27bb0a5..8e60081 100644 --- a/apps/tasks/tests.py +++ b/apps/tasks/tests.py @@ -323,7 +323,7 @@ def test_handle_submission_with_wrong_output(self) -> None: fetch_redirect_response=True, ) - def test_submission_with_AC_status_increases_user_score(self) -> None: + def test_submission_has_accepted_status_increases_user_score(self) -> None: handle_submission( self.submission.code, self.task.id, self.submission.id ) @@ -334,7 +334,7 @@ def test_submission_with_AC_status_increases_user_score(self) -> None: self.assertEqual(self.submission.status, SubmissionStatus.ACCEPTED) self.assertEqual(self.user.score, self.task.score) - def test_submission_with_non_AC_status_does_not_increase_user_score( + def test_submission_without_accepted_status_does_not_increase_user_score( self, ) -> None: self.submission.code = 'print("Hello, Word")' @@ -347,7 +347,7 @@ def test_submission_with_non_AC_status_does_not_increase_user_score( self.assertEqual(self.user.score, 0) - def test_second_AC_submission_does_not_increase_user_score(self) -> None: + def test_repeated_accepted_submission_cant_sum_to_user_score(self) -> None: handle_submission.apply( args=(self.submission.code, self.task.id, self.submission.id) ) @@ -364,7 +364,6 @@ def test_second_AC_submission_does_not_increase_user_score(self) -> None: ) self.user.refresh_from_db() - self.assertEqual(self.user.score, self.task.score) def test_form_success_url(self) -> None: From 47ad8f355fe6bc03154ddbbafd0e1360b5056b55 Mon Sep 17 00:00:00 2001 From: thegm445 Date: Fri, 1 Dec 2023 23:28:32 -0300 Subject: [PATCH 08/13] refactor(apps/tasks): variable names have been updated so they fit better in the pattern --- apps/tasks/views.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/tasks/views.py b/apps/tasks/views.py index 6140aff..2632fc9 100644 --- a/apps/tasks/views.py +++ b/apps/tasks/views.py @@ -59,10 +59,9 @@ def handle_submission(code: str, task_id: int, submission_id: int) -> None: .exists() ) - if ( - submission.status == SubmissionStatus.ACCEPTED - and not has_already_scored - ): + is_accepted = submission.status == SubmissionStatus.ACCEPTED + + if is_accepted and not has_already_scored: submission.author.score += task.score submission.author.save() From 6bd1d581543fc25706139a0c50ae12be3261ad61 Mon Sep 17 00:00:00 2001 From: thegm445 Date: Fri, 1 Dec 2023 23:31:57 -0300 Subject: [PATCH 09/13] refactor(apps/tasks): fix minor issues --- apps/tasks/tests.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/tasks/tests.py b/apps/tasks/tests.py index 8e60081..3f00b2b 100644 --- a/apps/tasks/tests.py +++ b/apps/tasks/tests.py @@ -324,8 +324,8 @@ def test_handle_submission_with_wrong_output(self) -> None: ) def test_submission_has_accepted_status_increases_user_score(self) -> None: - handle_submission( - self.submission.code, self.task.id, self.submission.id + handle_submission.apply( + args=(self.submission.code, self.task.id, self.submission.id) ) self.submission.refresh_from_db() @@ -344,7 +344,6 @@ def test_submission_without_accepted_status_does_not_increase_user_score( ) self.user.refresh_from_db() - self.assertEqual(self.user.score, 0) def test_repeated_accepted_submission_cant_sum_to_user_score(self) -> None: From 4eb0743764835b343c8dac1a6ac363be1100260c Mon Sep 17 00:00:00 2001 From: thegm445 Date: Mon, 4 Dec 2023 20:01:04 -0300 Subject: [PATCH 10/13] feat(apps/users/admin.py): score field has now been added to the admin panel --- apps/users/admin.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/apps/users/admin.py b/apps/users/admin.py index 3a345a6..b6928d8 100644 --- a/apps/users/admin.py +++ b/apps/users/admin.py @@ -7,9 +7,12 @@ @register(User) class UserAdmin(DefaultUserAdmin): - list_display = ("username", "email", "is_staff", "is_active") + list_display = ("username", "email", "is_staff", "is_active", "score") fieldsets = [ - (_("Personal info"), {"fields": ("username", "email", "password")}), + ( + _("Personal info"), + {"fields": ("username", "email", "password", "score")}, + ), ( _("Permissions"), { @@ -28,7 +31,13 @@ class UserAdmin(DefaultUserAdmin): None, { "classes": ("wide",), - "fields": ("username", "email", "password1", "password2"), + "fields": ( + "username", + "email", + "password1", + "password2", + "score", + ), }, ), ) From 9a17702dce8ddf315016badcda2ddbe7c46d5e75 Mon Sep 17 00:00:00 2001 From: thegm445 Date: Mon, 4 Dec 2023 20:08:02 -0300 Subject: [PATCH 11/13] fix(apps/users/tests.py): tests have now been updated so they test the correct fields --- apps/users/tests.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/apps/users/tests.py b/apps/users/tests.py index 1d5930d..c40bf1a 100644 --- a/apps/users/tests.py +++ b/apps/users/tests.py @@ -44,7 +44,13 @@ def test_create_superuser(self) -> None: class UserAdminTestCase(TestCase): def test_list_display(self) -> None: list_display = UserAdmin.list_display - expected = ("username", "email", "is_staff", "is_active") + expected = ( + "username", + "email", + "is_staff", + "is_active", + "score", + ) # Adicione 'score' aqui self.assertEqual(list_display, expected) @@ -58,7 +64,9 @@ def test_fieldsets(self) -> None: expected = [ ( _("Personal info"), - {"fields": ("username", "email", "password")}, + { + "fields": ("username", "email", "password", "score") + }, # Adicione 'score' aqui ), ( _("Permissions"), @@ -82,7 +90,13 @@ def test_add_fieldsets(self) -> None: None, { "classes": ("wide",), - "fields": ("username", "email", "password1", "password2"), + "fields": ( + "username", + "email", + "password1", + "password2", + "score", + ), # Adicione 'score' aqui }, ), ) From 11e44dff0003eef0683172f1e05679ff262b3c55 Mon Sep 17 00:00:00 2001 From: thegm445 Date: Tue, 5 Dec 2023 19:47:04 -0300 Subject: [PATCH 12/13] feat(templates/users): now users can see how many points they have --- templates/users/profile.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/users/profile.html b/templates/users/profile.html index 461dec9..cdbf56c 100644 --- a/templates/users/profile.html +++ b/templates/users/profile.html @@ -19,7 +19,7 @@

{{ user.username }}

{% if request.user.is_authenticated and request.user == user %}

E-mail: {{ user.email }}

{% endif %} -

Score: 0

+

Score: {{ user.score }}

Contests: {{ user.contests|length }}

From 91d3c926133916d5f78068104e42154c139aae6b Mon Sep 17 00:00:00 2001 From: thegm445 Date: Tue, 5 Dec 2023 23:06:31 -0300 Subject: [PATCH 13/13] refactor(apps/users): removed one unnecessary comment --- apps/users/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/users/tests.py b/apps/users/tests.py index 13d7e0e..db4fd55 100644 --- a/apps/users/tests.py +++ b/apps/users/tests.py @@ -50,7 +50,7 @@ def test_list_display(self) -> None: "is_staff", "is_active", "score", - ) # Adicione 'score' aqui + ) self.assertEqual(list_display, expected)