|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import os
|
|
|
|
import datetime
|
|
|
|
import random
|
|
|
|
|
|
|
|
from django.db import models
|
|
|
|
from django.contrib import auth
|
|
|
|
from django.utils import timezone
|
|
|
|
from django.conf import settings
|
|
|
|
from django.utils.encoding import python_2_unicode_compatible
|
|
|
|
from django.utils.encoding import force_unicode
|
|
|
|
|
|
|
|
from django_countries.fields import CountryField
|
|
|
|
from solo.models import SingletonModel
|
|
|
|
|
|
|
|
#
|
|
|
|
# Mělo by být částečně vytaženo z Aesopa
|
|
|
|
# viz https://ovvp.mff.cuni.cz/wiki/aesop/export-skol.
|
|
|
|
#
|
|
|
|
|
|
|
|
@python_2_unicode_compatible
|
|
|
|
class Skola(models.Model):
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
db_table = 'seminar_skoly'
|
|
|
|
verbose_name = u'Škola'
|
|
|
|
verbose_name_plural = u'Školy'
|
|
|
|
|
|
|
|
# Interní ID
|
|
|
|
id = models.AutoField(primary_key = True)
|
|
|
|
|
|
|
|
# Aesopi ID "izo:..." nebo "aesop:..."
|
|
|
|
# NULL znamená v exportu do aesopa "ufo"
|
|
|
|
aesop_id = models.CharField(u'Aesop ID', max_length=32, blank=True, default='',
|
|
|
|
help_text=u'Aesopi ID typu "izo:..." nebo "aesop:..."')
|
|
|
|
|
|
|
|
# IZO školy (jen české školy)
|
|
|
|
izo = models.CharField(u'IZO', max_length=32, blank=True,
|
|
|
|
help_text=u'IZO školy (jen české školy)')
|
|
|
|
|
|
|
|
# Celý název školy
|
|
|
|
nazev = models.CharField(u'název', max_length=256,
|
|
|
|
help_text=u'Celý název školy')
|
|
|
|
|
|
|
|
# Zkraceny nazev pro zobrazení ve výsledkovce, volitelné.
|
|
|
|
# Není v Aesopovi, musíme vytvářet sami.
|
|
|
|
kratky_nazev = models.CharField(u'zkrácený název', max_length=256, blank=True,
|
|
|
|
help_text="Zkrácený název pro zobrazení ve výsledkovce")
|
|
|
|
|
|
|
|
# Ulice může být jen číslo
|
|
|
|
ulice = models.CharField(u'ulice', max_length=256)
|
|
|
|
|
|
|
|
mesto = models.CharField(u'město', max_length=256)
|
|
|
|
|
|
|
|
psc = models.CharField(u'PSČ', max_length=32)
|
|
|
|
|
|
|
|
# ISO 3166-1 dvojznakovy kod zeme velkym pismem (CZ, SK)
|
|
|
|
# Ekvivalentní s CharField(max_length=2, default='CZ', ...)
|
|
|
|
stat = CountryField(u'stát', default='CZ',
|
|
|
|
help_text=u'ISO 3166-1 kód zeme velkými písmeny (CZ, SK, ...)')
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return force_unicode(u'%s, %s' % (self.nazev, self.mesto))
|
|
|
|
|
|
|
|
|
|
|
|
@python_2_unicode_compatible
|
|
|
|
class Resitel(models.Model):
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
db_table = 'seminar_resitele'
|
|
|
|
verbose_name = u'Řešitel'
|
|
|
|
verbose_name_plural = u'Řešitelé'
|
|
|
|
ordering = ['prijmeni', 'jmeno']
|
|
|
|
|
|
|
|
# Interní ID
|
|
|
|
id = models.AutoField(primary_key = True)
|
|
|
|
|
|
|
|
jmeno = models.CharField(u'jméno', max_length=256)
|
|
|
|
|
|
|
|
prijmeni = models.CharField(u'příjmení', max_length=256)
|
|
|
|
|
|
|
|
# User, pokud má na webu účet
|
|
|
|
user = models.OneToOneField(settings.AUTH_USER_MODEL, blank=True, null=True, verbose_name=u'uživatel')
|
|
|
|
|
|
|
|
# Pohlaví. Že ho neznáme se snad nestane (a ušetří to práci při programování)
|
|
|
|
pohlavi_muz = models.BooleanField(u'pohlaví (muž)', default=False)
|
|
|
|
|
|
|
|
skola = models.ForeignKey(Skola, blank=True, null=True, verbose_name=u'škola')
|
|
|
|
|
|
|
|
# Očekávaný rok maturity a vyřazení z aktivních řešitelů
|
|
|
|
rok_maturity = models.IntegerField(u'rok maturity')
|
|
|
|
|
|
|
|
email = models.EmailField(u'e-mail', max_length=256, blank=True, default='')
|
|
|
|
|
|
|
|
telefon = models.CharField(u'telefon', max_length=256, blank=True, default='')
|
|
|
|
|
|
|
|
datum_narozeni = models.DateField(u'datum narození', blank=True, null=True)
|
|
|
|
|
|
|
|
# NULL dokud nedali souhlas
|
|
|
|
datum_souhlasu_udaje = models.DateField(u'datum souhlasu (údaje)', blank=True, null=True,
|
|
|
|
help_text=u'Datum souhlasu se zpracováním osobních údajů')
|
|
|
|
|
|
|
|
# NULL dokud nedali souhlas
|
|
|
|
datum_souhlasu_zasilani = models.DateField(u'datum souhlasu (spam)', blank=True, null=True,
|
|
|
|
help_text=u'Datum souhlasu se zasíláním MFF materiálů')
|
|
|
|
|
|
|
|
# Alespoň odhad (rok či i měsíc)
|
|
|
|
datum_prihlaseni = models.DateField(u'datum přihlášení', default=timezone.now)
|
|
|
|
|
|
|
|
ZASILAT_DOMU = 'domu'
|
|
|
|
ZASILAT_DO_SKOLY = 'do_skoly'
|
|
|
|
ZASILAT_NIKAM = 'nikam'
|
|
|
|
ZASILAT_CHOICES = [
|
|
|
|
(ZASILAT_DOMU, u'Domů'),
|
|
|
|
(ZASILAT_DO_SKOLY, u'Do školy'),
|
|
|
|
(ZASILAT_NIKAM, u'Nikam'),
|
|
|
|
]
|
|
|
|
zasilat = models.CharField(u'kam zasílat', max_length=32, choices=ZASILAT_CHOICES, blank=False, default=ZASILAT_DOMU)
|
|
|
|
|
|
|
|
# Ulice může být i jen číslo
|
|
|
|
ulice = models.CharField(u'ulice', max_length=256, blank=True, default='')
|
|
|
|
|
|
|
|
mesto = models.CharField(u'město', max_length=256, blank=True, default='')
|
|
|
|
|
|
|
|
psc = models.CharField(u'PSČ', max_length=32, blank=True, default='')
|
|
|
|
|
|
|
|
# ISO 3166-1 dvojznakovy kod zeme velkym pismem (CZ, SK)
|
|
|
|
# Ekvivalentní s CharField(max_length=2, default='CZ', ...)
|
|
|
|
stat = CountryField(u'stát', default='CZ',
|
|
|
|
help_text=u'ISO 3166-1 kód země velkými písmeny (CZ, SK, ...)')
|
|
|
|
|
|
|
|
def plne_jmeno(self):
|
|
|
|
return force_unicode(u'%s %s' % (self.jmeno, self.prijmeni))
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return force_unicode(self.plne_jmeno())
|
|
|
|
|
|
|
|
|
|
|
|
@python_2_unicode_compatible
|
|
|
|
class Rocnik(models.Model):
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
db_table = 'seminar_rocniky'
|
|
|
|
verbose_name = u'Ročník'
|
|
|
|
verbose_name_plural = u'Ročníky'
|
|
|
|
ordering = ['rocnik']
|
|
|
|
|
|
|
|
# Interní ID
|
|
|
|
id = models.AutoField(primary_key = True)
|
|
|
|
|
|
|
|
prvni_rok = models.IntegerField(u'první rok')
|
|
|
|
|
|
|
|
rocnik = models.CharField(u'číslo ročníku', max_length=16)
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return force_unicode(u'%s (%d/%d)' % (self.rocnik, self.prvni_rok, self.prvni_rok+1))
|
|
|
|
|
|
|
|
def roman(self):
|
|
|
|
if self.rocnik.isdigit():
|
|
|
|
return force_unicode(roman(int(self.rocnik)))
|
|
|
|
else:
|
|
|
|
return force_unicode(self.rocnik)
|
|
|
|
|
|
|
|
@python_2_unicode_compatible
|
|
|
|
class Cislo(models.Model):
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
db_table = 'seminar_cisla'
|
|
|
|
verbose_name = u'Číslo'
|
|
|
|
verbose_name_plural = u'Čísla'
|
|
|
|
ordering = ['rocnik__rocnik', 'cislo']
|
|
|
|
|
|
|
|
# Interní ID
|
|
|
|
id = models.AutoField(primary_key = True)
|
|
|
|
|
|
|
|
rocnik = models.ForeignKey(Rocnik, verbose_name=u'ročník')
|
|
|
|
|
|
|
|
cislo = models.CharField(u'název čísla', max_length=32,
|
|
|
|
help_text=u'Většinou jen "1", vyjímečně "7-8"')
|
|
|
|
|
|
|
|
datum_vydani = models.DateField(u'datum vydání', blank=True, null=True,
|
|
|
|
help_text=u'Datum vydání finální verze')
|
|
|
|
|
|
|
|
datum_deadline = models.DateField(u'datum deadline', blank=True, null=True,
|
|
|
|
help_text=u'Datum pro příjem řešení úloh zadaných v tomto čísle')
|
|
|
|
|
|
|
|
def kod(self):
|
|
|
|
return u'%s.%s' % (self.rocnik.rocnik, self.cislo)
|
|
|
|
kod.short_description = u'Kód čísla'
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return force_unicode(u'%s' % (self.kod(),))
|
|
|
|
|
|
|
|
|
|
|
|
@python_2_unicode_compatible
|
|
|
|
class Problem(models.Model):
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
db_table = 'seminar_problemy'
|
|
|
|
verbose_name = u'Problém'
|
|
|
|
verbose_name_plural = u'Problémy'
|
|
|
|
|
|
|
|
# Interní ID
|
|
|
|
id = models.AutoField(primary_key = True)
|
|
|
|
|
|
|
|
# Název
|
|
|
|
nazev = models.CharField(u'název', max_length=256)
|
|
|
|
|
|
|
|
TYP_ULOHA = 'uloha'
|
|
|
|
TYP_TEMA = 'tema'
|
|
|
|
TYP_SERIAL = 'serial'
|
|
|
|
TYP_ORG_CLANEK = 'org-clanek'
|
|
|
|
TYP_RES_CLANEK = 'res-clanek'
|
|
|
|
TYP_CHOICES = [
|
|
|
|
(TYP_ULOHA, u'Úloha'),
|
|
|
|
(TYP_TEMA, u'Téma'),
|
|
|
|
(TYP_SERIAL, u'Seriál'),
|
|
|
|
(TYP_ORG_CLANEK, u'Organizátorský článek'),
|
|
|
|
(TYP_RES_CLANEK, u'Řesitelský článek'),
|
|
|
|
]
|
|
|
|
typ = models.CharField(u'typ problému', max_length=32, choices=TYP_CHOICES, blank=False, default=TYP_ULOHA)
|
|
|
|
|
|
|
|
STAV_NAVRH = 'navrh'
|
|
|
|
STAV_ZADANY = 'zadany'
|
|
|
|
STAV_SMAZANY = 'smazany'
|
|
|
|
STAV_CHOICES = [
|
|
|
|
(STAV_NAVRH, u'Návrh'),
|
|
|
|
(STAV_ZADANY, u'Zadaný'),
|
|
|
|
(STAV_SMAZANY, u'Smazaný'),
|
|
|
|
]
|
|
|
|
stav = models.CharField(u'stav problému', max_length=32, choices=STAV_CHOICES, blank=False, default=STAV_NAVRH)
|
|
|
|
|
|
|
|
text_problemu_org = models.TextField(u'organizátorský (neveřejný) text', blank=True)
|
|
|
|
|
|
|
|
text_problemu = models.TextField(u'veřejný text zadání a řešení', blank=True)
|
|
|
|
|
|
|
|
autor = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=u'autor problému', related_name='autor_uloh')
|
|
|
|
|
|
|
|
opravovatel = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=u'opravovatel', null=True, blank=True,
|
|
|
|
related_name='opravovatel_uloh')
|
|
|
|
|
|
|
|
kod = models.CharField(u'lokální kód', max_length=32, blank=True, default='',
|
|
|
|
help_text=u'Číslo/kód úlohy v čísle nebo kód tématu/článku/seriálu v ročníku')
|
|
|
|
|
|
|
|
cislo_zadani = models.ForeignKey(Cislo, verbose_name=u'číslo zadání', blank=True, null=True, related_name=u'zadane_problemy')
|
|
|
|
|
|
|
|
cislo_reseni = models.ForeignKey(Cislo, verbose_name=u'číslo řešení', blank=True, null=True, related_name=u'resene_problemy',
|
|
|
|
help_text=u'Číslo s řešením úlohy, jen pro úlohy')
|
|
|
|
|
|
|
|
body = models.IntegerField(u'maximum bodů', blank=True, null=True)
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return force_unicode(u'%s (%s)' % (self.nazev, self.stav))
|
|
|
|
|
|
|
|
|
|
|
|
@python_2_unicode_compatible
|
|
|
|
class Reseni(models.Model):
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
db_table = 'seminar_reseni'
|
|
|
|
verbose_name = u'Řešení'
|
|
|
|
verbose_name_plural = u'Řešení'
|
|
|
|
ordering = ['problem', 'resitel']
|
|
|
|
|
|
|
|
# Interní ID
|
|
|
|
id = models.AutoField(primary_key = True)
|
|
|
|
|
|
|
|
problem = models.ForeignKey(Problem, verbose_name=u'problém', related_name='reseni')
|
|
|
|
|
|
|
|
resitel = models.ForeignKey(Resitel, verbose_name=u'řešitel', related_name='reseni')
|
|
|
|
|
|
|
|
body = models.IntegerField(u'body', blank=True, null=True)
|
|
|
|
|
|
|
|
cislo_body = models.ForeignKey(Cislo, verbose_name=u'číslo pro body', related_name='bodovana_reseni', blank=True, null=True)
|
|
|
|
|
|
|
|
timestamp = models.DateTimeField(u'vytvořeno', auto_now=True)
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return force_unicode(u"%s: %s" % (self.resitel.plne_jmeno(), self.problem.nazev))
|
|
|
|
|
|
|
|
|
|
|
|
@python_2_unicode_compatible
|
|
|
|
class PrilohaReseni(models.Model):
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
db_table = 'seminar_priloha_reseni'
|
|
|
|
verbose_name = u'Příloha řešení'
|
|
|
|
verbose_name_plural = u'Přílohy řešení'
|
|
|
|
ordering = ['reseni', 'timestamp']
|
|
|
|
|
|
|
|
# Interní ID
|
|
|
|
id = models.AutoField(primary_key = True)
|
|
|
|
|
|
|
|
reseni = models.ForeignKey(Reseni, verbose_name=u'řešení', related_name='prilohy')
|
|
|
|
|
|
|
|
timestamp = models.DateTimeField(u'vytvořeno', auto_now=True)
|
|
|
|
|
|
|
|
def generate_filename(self, filename):
|
|
|
|
clean = filename.replace('/','-').replace('\0', '')
|
|
|
|
datedir = datetime.datetime.now().strftime('%Y-%m')
|
|
|
|
fname = "%s_%06d_%s" % (
|
|
|
|
datetime.datetime.now().strftime('%Y-%m-%d-%H:%M'),
|
|
|
|
random.randint(0,999999),
|
|
|
|
clean)
|
|
|
|
return os.path.join(settings.SEMINAR_RESENI_DIRNAME, datedir, fname)
|
|
|
|
|
|
|
|
soubor = models.FileField(u'soubor', upload_to = generate_filename)
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return force_unicode(self.soubor)
|
|
|
|
|
|
|
|
|
|
|
|
@python_2_unicode_compatible
|
|
|
|
class Nastaveni(SingletonModel):
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
db_table = 'seminar_nastaveni'
|
|
|
|
verbose_name = u'Nastavení semináře'
|
|
|
|
|
|
|
|
aktualni_rocnik = models.ForeignKey(Rocnik, verbose_name=u'aktuální ročník', null=False)
|
|
|
|
|
|
|
|
aktualni_cislo = models.ForeignKey(Cislo, verbose_name=u'poslední vydané číslo', null=False)
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return u'Nastavení semináře'
|
|
|
|
|
|
|
|
|
|
|
|
def roman(num):
|
|
|
|
ints = (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1)
|
|
|
|
nums = ('M', 'CM', 'D', 'CD','C', 'XC','L','XL','X','IX','V','IV','I')
|
|
|
|
res = ""
|
|
|
|
for i, n in zip(ints, nums):
|
|
|
|
res += n * (num // i)
|
|
|
|
num %= i
|
|
|
|
return res
|