from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.utils.translation import gettext_lazy as _
from oioioi.base.fields import EnumField, EnumRegistry
from oioioi.base.utils.deps import check_django_app_dependencies
from oioioi.base.utils.validators import validate_db_string_id
from oioioi.contests.models import Contest
from oioioi.participants.fields import OneToOneBothHandsCascadingParticipantField
check_django_app_dependencies(__name__, ['oioioi.contestexcl'])
[docs]participant_statuses = EnumRegistry()
participant_statuses.register('ACTIVE', _("Active"))
participant_statuses.register('BANNED', _("Banned"))
participant_statuses.register('DELETED', _("Account deleted"))
[docs]class Participant(models.Model):
[docs] contest = models.ForeignKey(Contest, on_delete=models.CASCADE)
[docs] user = models.ForeignKey(User, on_delete=models.CASCADE)
[docs] status = EnumField(participant_statuses, default='ACTIVE')
[docs] anonymous = models.BooleanField(default=False)
@property
[docs] def registration_model(self):
rcontroller = self.contest.controller.registration_controller()
model_class = rcontroller.get_model_class()
if model_class is None:
raise ObjectDoesNotExist
try:
return model_class.objects.get(participant=self)
except model_class.DoesNotExist:
raise ObjectDoesNotExist
[docs] def __str__(self):
return str(self.user)
[docs] def erase_data(self):
"""Replaces (and saves) values of every field to values suggesting
that the account is deleted. Purpose: delete user's private data
from the system.
Used only when account is being deleted by user.
"""
try:
self.registration_model.erase_data()
except ObjectDoesNotExist:
pass
self.status = 'DELETED'
self.anonymous = True
self.save()
[docs]class Region(models.Model):
[docs] short_name = models.CharField(max_length=10, validators=[validate_db_string_id])
[docs] name = models.CharField(max_length=255)
[docs] contest = models.ForeignKey(
Contest, related_name='regions', on_delete=models.CASCADE
)
[docs] region_server = models.CharField(
max_length=255,
null=True,
blank=True,
verbose_name=_("Region server"),
help_text=_("IP address or hostname of the regional server"),
)
[docs] def __str__(self):
return u'%s' % (self.short_name,)
[docs]class RegistrationModel(models.Model):
[docs] participant = OneToOneBothHandsCascadingParticipantField(
Participant, related_name='%(app_label)s_%(class)s', on_delete=models.CASCADE
)
[docs] def erase_data(self):
pass
[docs]class OpenRegistration(RegistrationModel):
[docs] terms_accepted = models.BooleanField(
_("terms accepted"),
help_text=_(
"I declare that I have read the contest rules and "
"the technical arrangements. I fully understand them and "
"accept them unconditionally."
),
default=False,
)
[docs] def erase_data(self):
self.terms_accepted = False
self.save()
[docs]class OnsiteRegistration(RegistrationModel):
[docs] number = models.IntegerField(verbose_name=_("number"))
[docs] region = models.ForeignKey(
Region,
null=True,
on_delete=models.SET_NULL,
verbose_name=_("region"),
blank=True,
)
[docs] local_number = models.IntegerField(verbose_name=_("local number"))
[docs] def __str__(self):
return _("%(number)s/%(region)s/%(local_number)s") % {
'number': self.number,
'region': self.region,
'local_number': self.local_number,
}
[docs] def erase_data(self):
self.number = -1
self.region = None
self.local_number = -1
self.save()
[docs]class TestRegistration(RegistrationModel):
"""Used only for testing"""
[docs] name = models.CharField(max_length=255)
[docs]class TermsAcceptedPhrase(models.Model):
"""This model stores text asking user to accept contest's terms.
It is used in contests with custom registration: PA and OI.
"""
[docs] text = models.TextField(_("text"), null=True, max_length=500)
[docs] contest = models.OneToOneField(
Contest, related_name='terms_accepted_phrase', on_delete=models.CASCADE
)
# Verbose names in Meta could be a little misleading.
# This is because they are not 100% accurate, but look nice in admin view.
# This is used as a name of the given object displayed in TabularInline.
# We are using it to display only one object of type TermsAcceptedPhrase so
# it is not necessary to name it.
[docs] def __str__(self):
return u""