Skip to content

Commit

Permalink
Feat/Fix: Users are now ranked by -points -last_correct_submission
Browse files Browse the repository at this point in the history
Added a proper user score admin.
  • Loading branch information
JasonLovesDoggo committed Apr 6, 2024
1 parent 153df0e commit dc60d53
Show file tree
Hide file tree
Showing 8 changed files with 300 additions and 72 deletions.
91 changes: 89 additions & 2 deletions gameserver/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
from django.contrib.auth import get_user_model
from django.contrib.flatpages.admin import FlatPageAdmin
from django.contrib.flatpages.models import FlatPage
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _

from . import models
from .models import Submission, ContestSubmission
from .utils.actions import *

User = get_user_model()

Expand Down Expand Up @@ -226,6 +229,7 @@ class ContestAdmin(SortableAdminBase, admin.ModelAdmin):
"start_time",
"end_time",
]
actions = [recalculate_score]

def has_view_permission(self, request, obj=None):
if request.user.has_perm("gameserver.view_contest"):
Expand Down Expand Up @@ -278,11 +282,93 @@ class UserAdmin(admin.ModelAdmin):
"username",
"full_name",
]
actions = [recalculate_user_scores, recalculate_all_user_scores]


class UserScoreAdmin(admin.ModelAdmin):
fields = (
"user",
"points",
"flag_count",
"last_correct_submission",
"last_correct_submission_obj",
)
list_display = [
"user",
"points",
"last_correct_submission",
]
ordering = ["-points"]
search_fields = [
"user__username",
"user__full_name",
]
readonly_fields = [
"user",
"points",
"flag_count",
"last_correct_submission",
"last_correct_submission_obj",
]

def last_correct_submission_obj(self, obj):
try:
obj = Submission.objects.filter(
user=obj.user, is_correct=True, problem__is_public=True
).latest("date_created")
except Submission.DoesNotExist:
return "No correct submissions"
print(format_html("<a href='{url}'>{url}</a>", url=obj.get_absolute_admin_url()))
return format_html("<a href='{url}'>{url}</a>", url=obj.get_absolute_admin_url())

last_correct_submission_obj.allow_tags = True

last_correct_submission_obj.short_description = "Last correct submission URL"


class ContestScoreAdmin(admin.ModelAdmin):
fields = (
"participation",
"points",
"flag_count",
"last_correct_submission",
"last_correct_submission_obj",
)
list_display = [
"participation",
"points",
"last_correct_submission",
]
list_filter = ["participation__contest"]
ordering = ["-points"]
search_fields = [
"participation__team__name",
"participation__team__members__username",
]
readonly_fields = [
"participation",
"points",
"flag_count",
"last_correct_submission",
"last_correct_submission_obj",
]

def last_correct_submission_obj(self, obj):
try:
obj = ContestSubmission.objects.filter(
participation=obj.participation, submission__is_correct=True
).latest("submission__date_created")
except ContestSubmission.DoesNotExist:
return "No correct submissions"
return format_html("<a href='{url}'>{url}</a>", url=obj.get_absolute_admin_url())

last_correct_submission_obj.allow_tags = True
last_correct_submission_obj.short_description = "Last correct submission URL"


admin.site.register(User, UserAdmin)
admin.site.register(models.ContestScore)
admin.site.register(models.UserScore)
admin.site.register(models.ContestScore, ContestScoreAdmin)
admin.site.register(models.UserScore, UserScoreAdmin)
admin.site.register(models.Problem, ProblemAdmin)
admin.site.register(models.Submission, SubmissionAdmin)
admin.site.register(models.ProblemType)
Expand All @@ -296,6 +382,7 @@ class UserAdmin(admin.ModelAdmin):
admin.site.register(models.Contest, ContestAdmin)
admin.site.register(models.ContestTag)
admin.site.register(models.ContestParticipation)
admin.site.register(models.ContestSubmission)
admin.site.site_header = "mCTF administration"
admin.site.site_title = "mCTF admin"

Expand Down
46 changes: 43 additions & 3 deletions gameserver/migrations/0035_contest_first_blood_webhook_and_more.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Generated by Django 5.0.4 on 2024-04-06 16:06

from django.db import migrations, models
# Generated by Django 5.0.4 on 2024-04-06 18:37

import datetime
import django.db.models.deletion
import gameserver.models.profile
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):
Expand All @@ -19,6 +21,26 @@ class Migration(migrations.Migration):
help_text="URL to send a POST request to when a user gets the first blood on a problem",
),
),
migrations.AddField(
model_name="contestscore",
name="last_correct_submission",
field=models.DateTimeField(
blank=True,
default=datetime.datetime(1971, 1, 1, 0, 0),
editable=False,
help_text="The date of the last correct submission.",
),
),
migrations.AddField(
model_name="userscore",
name="last_correct_submission",
field=models.DateTimeField(
blank=True,
default=datetime.datetime(1971, 1, 1, 0, 0),
editable=False,
help_text="The date of the last correct submission.",
),
),
migrations.AlterField(
model_name="contest",
name="organizations",
Expand All @@ -29,6 +51,15 @@ class Migration(migrations.Migration):
to="gameserver.organization",
),
),
migrations.AlterField(
model_name="contestscore",
name="participation",
field=models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
related_name="score_cache",
to="gameserver.contestparticipation",
),
),
migrations.AlterField(
model_name="user",
name="timezone",
Expand Down Expand Up @@ -636,4 +667,13 @@ class Migration(migrations.Migration):
max_length=50,
),
),
migrations.AlterField(
model_name="userscore",
name="user",
field=models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
related_name="score_cache",
to=settings.AUTH_USER_MODEL,
),
),
]
Loading

0 comments on commit dc60d53

Please sign in to comment.