Skip to content
This repository has been archived by the owner on Jan 3, 2024. It is now read-only.

Commit

Permalink
Merge pull request #61 from unb-mds/featureRequest/apps.problems
Browse files Browse the repository at this point in the history
[feature request] Rename `apps.problems` to `apps.tasks`
  • Loading branch information
bitterteriyaki authored Nov 8, 2023
2 parents 4d0d29f + 1de2a36 commit cf97682
Show file tree
Hide file tree
Showing 18 changed files with 127 additions and 129 deletions.
8 changes: 0 additions & 8 deletions apps/problems/__init__.py

This file was deleted.

8 changes: 8 additions & 0 deletions apps/tasks/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.apps import AppConfig

default_app_config = "apps.tasks.TasksConfig"


class TasksConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "apps.tasks"
20 changes: 10 additions & 10 deletions apps/problems/admin.py → apps/tasks/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
from django.forms import CharField, IntegerField, ModelForm, Textarea
from django.utils.translation import gettext_lazy as _

from apps.problems.models import Problem
from apps.tasks.models import Task

if TYPE_CHECKING:
ProblemAdminBase = ModelAdmin[Problem]
ProblemModelFormBase = ModelForm[Problem]
TaskAdminBase = ModelAdmin[Task]
TaskModelFormBase = ModelForm[Task]
else:
ProblemAdminBase = ModelAdmin
ProblemModelFormBase = ModelForm
TaskAdminBase = ModelAdmin
TaskModelFormBase = ModelForm


class ProblemModelForm(ProblemModelFormBase):
class TaskModelForm(TaskModelFormBase):
description = CharField(widget=Textarea(attrs={"rows": 14, "cols": 80}))
score = IntegerField(min_value=0, required=False)

Expand All @@ -26,13 +26,13 @@ class ProblemModelForm(ProblemModelFormBase):
)

class Meta:
model = Problem
model = Task
fields = "__all__"


@register(Problem)
class ProblemAdmin(ProblemAdminBase):
form = ProblemModelForm
@register(Task)
class TaskAdmin(TaskAdminBase):
form = TaskModelForm

list_display = ("title", "contest", "memory_limit", "time_limit")
list_filter = ("contest", "score")
Expand Down
2 changes: 1 addition & 1 deletion apps/problems/forms.py → apps/tasks/forms.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.forms import CharField, Form


class ProblemForm(Form):
class TaskForm(Form):
code = CharField(label="Source Code")
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Migration(migrations.Migration):

operations = [
migrations.CreateModel(
name="Problem",
name="Task",
fields=[
(
"id",
Expand All @@ -32,7 +32,7 @@ class Migration(migrations.Migration):
"contest",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="problems",
related_name="tasks",
to="contests.contest",
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@

class Migration(migrations.Migration):
dependencies = [
("problems", "0001_initial"),
("tasks", "0001_initial"),
]

operations = [
migrations.AlterModelOptions(
name="problem",
name="task",
options={},
),
migrations.AlterModelTable(
name="problem",
table="problems",
name="task",
table="tasks",
),
]
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@

class Migration(migrations.Migration):
dependencies = [
("problems", "0002_alter_problem_options_alter_problem_table"),
("tasks", "0002_alter_task_options_alter_task_table"),
]

operations = [
migrations.AddField(
model_name="problem",
model_name="task",
name="memory_limit",
field=models.IntegerField(null=True),
),
migrations.AddField(
model_name="problem",
model_name="task",
name="score",
field=models.IntegerField(null=True),
),
migrations.AddField(
model_name="problem",
model_name="task",
name="time_limit",
field=models.IntegerField(null=True),
),
Expand Down
File renamed without changes.
8 changes: 4 additions & 4 deletions apps/problems/models.py → apps/tasks/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@
from core.models import TimestampedModel


class Problem(TimestampedModel):
"""Represents a problem in a contest."""
class Task(TimestampedModel):
"""Represents a task in a contest."""

title = CharField(max_length=256)
description = CharField(max_length=4096)

contest = ForeignKey(Contest, related_name="problems", on_delete=CASCADE)
contest = ForeignKey(Contest, related_name="tasks", on_delete=CASCADE)
score = IntegerField(null=True)

memory_limit = IntegerField(null=True)
time_limit = IntegerField(null=True)

class Meta:
db_table = "problems"
db_table = "tasks"

def __str__(self) -> str:
return self.title
Expand Down
52 changes: 25 additions & 27 deletions apps/problems/tests.py → apps/tasks/tests.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
from datetime import timedelta

from django.contrib.admin.sites import AdminSite

# from django.forms import CharField, IntegerField
from django.test import TestCase
from django.urls import resolve, reverse
from django.utils import timezone

from apps.contests.models import Contest
from apps.problems.admin import ProblemAdmin
from apps.problems.models import Problem
from apps.problems.views import DetailView
from apps.tasks.admin import TaskAdmin
from apps.tasks.models import Task
from apps.tasks.views import DetailView


class ProblemTestCase(TestCase):
def test_problem_to_string(self) -> None:
problem = Problem(title="Test Problem")
self.assertEqual(str(problem), "Test Problem")
class TaskTestCase(TestCase):
def test_task_to_string(self) -> None:
task = Task(title="Test Task")
self.assertEqual(str(task), "Test Task")

def test_running_contest_is_accessible(self) -> None:
now = timezone.now()
Expand All @@ -25,9 +23,9 @@ def test_running_contest_is_accessible(self) -> None:
end_time = now + timedelta(hours=1)

contest = Contest(start_time=start_time, end_time=end_time)
problem = Problem(contest=contest)
task = Task(contest=contest)

self.assertTrue(problem.is_accessible)
self.assertTrue(task.is_accessible)

def test_past_contest_is_accessible(self) -> None:
now = timezone.now()
Expand All @@ -36,9 +34,9 @@ def test_past_contest_is_accessible(self) -> None:
end_time = now - timedelta(hours=1)

contest = Contest(start_time=start_time, end_time=end_time)
problem = Problem(contest=contest)
task = Task(contest=contest)

self.assertTrue(problem.is_accessible)
self.assertTrue(task.is_accessible)

def test_future_contest_is_not_accessible(self) -> None:
now = timezone.now()
Expand All @@ -47,9 +45,9 @@ def test_future_contest_is_not_accessible(self) -> None:
end_time = now + timedelta(hours=2)

contest = Contest(start_time=start_time, end_time=end_time)
problem = Problem(contest=contest)
task = Task(contest=contest)

self.assertFalse(problem.is_accessible)
self.assertFalse(task.is_accessible)

def test_cancelled_contest_is_not_accessible(self) -> None:
now = timezone.now()
Expand All @@ -62,16 +60,16 @@ def test_cancelled_contest_is_not_accessible(self) -> None:
end_time=end_time,
cancelled=True,
)
problem = Problem(contest=contest)
task = Task(contest=contest)

self.assertFalse(problem.is_accessible)
self.assertFalse(task.is_accessible)


class ProblemAdminTestCase(TestCase):
class TaskAdminTestCase(TestCase):
def setUp(self) -> None:
now = timezone.now()
self.site = AdminSite()
self.admin = ProblemAdmin(Problem, self.site)
self.admin = TaskAdmin(Task, self.site)

self.contest = Contest._default_manager.create(
title="Test Contest 1",
Expand Down Expand Up @@ -105,25 +103,25 @@ def test_fieldsets(self) -> None:
self.assertEqual(fieldsets, expected)


class ProblemURLTestCase(TestCase):
class TaskURLTestCase(TestCase):
def test_detail_url_to_view_name(self) -> None:
url = reverse("problems:detail", args=[1])
url = reverse("tasks:detail", args=[1])

view_name = resolve(url).view_name
expected = "problems:detail"
expected = "tasks:detail"

self.assertEqual(view_name, expected)

def test_detail_url_reverse(self) -> None:
url = reverse("problems:detail", args=[1])
expected = "/problems/1/"
url = reverse("tasks:detail", args=[1])
expected = "/tasks/1/"

self.assertEqual(url, expected)


class DetailViewTestCase(TestCase):
def test_detail_view_model_is_problem(self) -> None:
self.assertEqual(DetailView.model, Problem)
def test_detail_view_model_is_task(self) -> None:
self.assertEqual(DetailView.model, Task)

def test_detail_view_template_name_is_correct(self) -> None:
self.assertEqual(DetailView.template_name, "problems/detail.html")
self.assertEqual(DetailView.template_name, "tasks/detail.html")
4 changes: 2 additions & 2 deletions apps/problems/urls.py → apps/tasks/urls.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from django.urls import path

from apps.problems.views import DetailView
from apps.tasks.views import DetailView

app_name = "problems"
app_name = "tasks"

urlpatterns = [
path("<int:pk>/", DetailView.as_view(), name="detail"),
Expand Down
18 changes: 9 additions & 9 deletions apps/problems/views.py → apps/tasks/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@
from django.views import generic
from django.views.generic.edit import FormMixin

from apps.problems.forms import ProblemForm
from apps.problems.models import Problem
from apps.tasks.forms import TaskForm
from apps.tasks.models import Task

if TYPE_CHECKING:
DetailViewBase = generic.DetailView[Problem]
FormMixinBase = FormMixin[ProblemForm]
DetailViewBase = generic.DetailView[Task]
FormMixinBase = FormMixin[TaskForm]
else:
DetailViewBase = generic.DetailView
FormMixinBase = FormMixin


class DetailView(FormMixinBase, DetailViewBase):
model = Problem
template_name = "problems/detail.html"
form_class = ProblemForm
model = Task
template_name = "tasks/detail.html"
form_class = TaskForm

def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
context = super().get_context_data(**kwargs)
context["form"] = ProblemForm()
context["form"] = TaskForm()

return context

Expand All @@ -36,5 +36,5 @@ def post(self, request: HttpRequest) -> HttpResponse:
else self.form_invalid(form)
)

def form_valid(self, form: ProblemForm) -> HttpResponse:
def form_valid(self, form: TaskForm) -> HttpResponse:
return super().form_valid(form)
2 changes: 1 addition & 1 deletion server/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
LOCAL_APPS = [
"apps.users",
"apps.contests",
"apps.problems",
"apps.tasks",
]

INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
Expand Down
2 changes: 1 addition & 1 deletion server/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
# Local views
path("", IndexView.as_view(), name="home"),
path("contests/", include("apps.contests.urls")),
path("problems/", include("apps.problems.urls")),
path("tasks/", include("apps.tasks.urls")),
path("register/", include("apps.users.urls")),
]
22 changes: 11 additions & 11 deletions templates/contests/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,31 @@ <h2>Tasks</h2>
</tr>
</thead>
<tbody>
{% for problem in contest.problems.all %}
{% for task in contest.tasks.all %}
<tr>
<td>
{% if problem.is_accessible %}
<a href="{% url 'problems:detail' problem.id %}">
{{ problem }}
{% if task.is_accessible %}
<a href="{% url 'tasks:detail' task.id %}">
{{ task }}
</a>
{% else %}
{{ problem }}
{{ task }}
{% endif %}
</td>
<td>
{{ problem.score|default:"???" }}
{{ task.score|default:"???" }}
</td>
<td>
{% if problem.memory_limit %}
{{ problem.memory_limit|filesizeformat }}
{% if task.memory_limit %}
{{ task.memory_limit|filesizeformat }}
{% else %}
Unlimited
{% endif %}
</td>
<td>
{% if problem.time_limit %}
{{ problem.time_limit }}
second{{ problem.time_limit|pluralize:"s" }}
{% if task.time_limit %}
{{ task.time_limit }}
second{{ task.time_limit|pluralize:"s" }}
{% else %}
Unlimited
{% endif %}
Expand Down
Loading

0 comments on commit cf97682

Please sign in to comment.