diff --git a/mamweb/static/css/mamweb.css b/mamweb/static/css/mamweb.css
index 777cc87b..62d4bd44 100644
--- a/mamweb/static/css/mamweb.css
+++ b/mamweb/static/css/mamweb.css
@@ -1147,3 +1147,13 @@ div.gdpr {
max-width: 360px;
}
}
+
+/* tabulka odevzdaných řešení */
+.dosla_reseni tr th {
+ text-align: center;
+}
+.dosla_reseni tr th, .dosla_reseni tr td {
+ border: 1px solid black;
+ padding: 1px 10px 1px 10px;
+ border-collapse: collapse;
+}
\ No newline at end of file
diff --git a/seminar/templates/seminar/odevzdavatko/resitel_prehled.html b/seminar/templates/seminar/odevzdavatko/resitel_prehled.html
index be2e94bd..03614b77 100644
--- a/seminar/templates/seminar/odevzdavatko/resitel_prehled.html
+++ b/seminar/templates/seminar/odevzdavatko/resitel_prehled.html
@@ -2,19 +2,6 @@
{% load static %}
{% load deadliny %}
-{% block custom_css %}
-
-{% endblock custom_css %}
-
{% block content %}
{% for rocnik, hodnoceni in podle_rocniku %}
Ročník {{ rocnik }}
diff --git a/seminar/test_deadlines.py b/seminar/test_deadlines.py
new file mode 100644
index 00000000..c2a9ff03
--- /dev/null
+++ b/seminar/test_deadlines.py
@@ -0,0 +1,146 @@
+from django.test import TestCase
+from datetime import date
+
+import seminar.models as m
+from seminar.utils import deadline, TypDeadline
+
+class DeadlineTestCase(TestCase):
+ def setUp(self):
+ # Chceme pár ročníků a v nich pár čísel
+ r1 = m.Rocnik.objects.create(rocnik=1, prvni_rok=2000, exportovat=False)
+ r2 = m.Rocnik.objects.create(rocnik=2, prvni_rok=2001, exportovat=False)
+ r3 = m.Rocnik.objects.create(rocnik=3, prvni_rok=2002, exportovat=False)
+
+ # První číslo mívá soustřeďkový deadline…
+ c1_1 = m.Cislo.objects.create(rocnik=r1, poradi='1',
+ datum_vydani=date.fromisoformat('2000-05-22'),
+ datum_preddeadline=date.fromisoformat('2000-09-11'),
+ datum_deadline_soustredeni=date.fromisoformat('2000-09-11'),
+ datum_deadline=date.fromisoformat('2000-10-01'),
+ )
+ c1_2 = m.Cislo.objects.create(rocnik=r1, poradi='2',
+ datum_vydani=date.fromisoformat('2000-10-19'),
+ datum_preddeadline=date.fromisoformat('2000-12-05'),
+ datum_deadline=date.fromisoformat('2001-01-02'),
+ )
+ # Některá čísla nemají předdeadline…
+ c1_3 = m.Cislo.objects.create(rocnik=r1, poradi='3',
+ datum_vydani=date.fromisoformat('2001-01-28'),
+ datum_deadline=date.fromisoformat('2001-03-12'),
+ )
+ # Poslední číslo nemá ani normální deadline…
+ c1_4 = m.Cislo.objects.create(rocnik=r1, poradi='4-5',
+ datum_vydani=date.fromisoformat('2001-04-24'),
+ )
+ # První číslo dalšího ročníku se někdy vydá dřív, než poslední minulého…
+ c2_1 = m.Cislo.objects.create(rocnik=r2, poradi='1',
+ datum_vydani=date.fromisoformat('2001-04-19'),
+ datum_deadline_soustredeni=date.fromisoformat('2001-09-26'),
+ datum_deadline=date.fromisoformat('2001-10-07'),
+ )
+ # Tohle číslo má finální deadline až po vydání prvního čísla dalšího ročníku
+ # To samé se skoro stalo na přelomu (reálných) ročníků 27 a 28.
+ c2_2 = m.Cislo.objects.create(rocnik=r2, poradi='2',
+ datum_vydani=date.fromisoformat('2002-03-14'),
+ datum_preddeadline=date.fromisoformat('2002-05-26'),
+ datum_deadline=date.fromisoformat('2002-06-30'),
+ )
+ # Závěrečné číslo druhého ročníku až na podzim
+ c2_3 = m.Cislo.objects.create(rocnik=r2, poradi='3',
+ datum_vydani=date.fromisoformat('2002-09-05'),
+ )
+ # Divný případ: sous deadline stejný jako finální
+ c3_1 = m.Cislo.objects.create(rocnik=r3, poradi='1',
+ datum_vydani=date.fromisoformat('2002-06-02'),
+ datum_preddeadline=date.fromisoformat('2002-08-31'),
+ datum_deadline=date.fromisoformat('2002-09-30'),
+ datum_deadline_soustredeni=date.fromisoformat('2002-09-30'),
+ )
+
+ # Celkový harmonogram:
+ # 2000-05-22 začátek 1. ročníku, číslo 1.1
+
+ # 2000-09-11 sous a 1. deadline 1.1
+ # 2000-10-01 finální deadline 1.1
+ # 2000-10-19 Vydání 1.2
+ # 2000-12-05 předdeadline 1.2
+ # 2001-01-02 finální deadline 1.2
+ # 2001-01-28 vyd 1.3
+ # 2001-03-12 deadline 1.3
+ # 2001-04-19 Začátek 2. ročníku, číslo 2.1
+ # 2001-04-24 Vydání 1.4-5 -- závěrečné číslo 1. roč.
+
+ # 2001-09-26 Sous-deadline 2.1
+ # 2001-10-07 Deadline 2.1
+ # 2002-03-14 Pí den, vydání 2.2
+ # 2002-05-26 Předdeadline 2.2
+ # 2002-06-02 Třetí ročník, vydání 3.1
+ # 2002-06-30 Deadline 2.2
+
+ # 2002-08-31 Předdeadline 3.1
+ # 2002-09-04 Vydání 2.3, konec 2. roč.
+ # 2002-09-30 Sous a finální deadline 3.1
+
+ def test_deadline_spravne_vysledky(self):
+ """V každém intervalu mezi deadliny dostáváme ten správný deadline"""
+ # První ročník
+ self.assertEqual(deadline(date.fromisoformat('2000-05-30')), (TypDeadline.PredDeadline, m.Cislo.objects.get(rocnik__rocnik=1, poradi='1'), date.fromisoformat('2000-09-11')))
+ self.assertEqual(deadline(date.fromisoformat('2000-09-15')), (TypDeadline.FinalDeadline, m.Cislo.objects.get(rocnik__rocnik=1, poradi='1'), date.fromisoformat('2000-10-01')))
+
+ # Trochu divný případ, kdy někdo něco pošle před vydáním čísla. Ale článkům se to asi stát může…
+ self.assertEqual(deadline(date.fromisoformat('2000-10-10')), (TypDeadline.PredDeadline, m.Cislo.objects.get(rocnik__rocnik=1, poradi='2'), date.fromisoformat('2000-12-05')))
+ self.assertEqual(deadline(date.fromisoformat('2000-10-22')), (TypDeadline.PredDeadline, m.Cislo.objects.get(rocnik__rocnik=1, poradi='2'), date.fromisoformat('2000-12-05')))
+ self.assertEqual(deadline(date.fromisoformat('2000-12-15')), (TypDeadline.FinalDeadline, m.Cislo.objects.get(rocnik__rocnik=1, poradi='2'), date.fromisoformat('2001-01-02')))
+ self.assertEqual(deadline(date.fromisoformat('2001-01-08')), (TypDeadline.FinalDeadline, m.Cislo.objects.get(rocnik__rocnik=1, poradi='3'), date.fromisoformat('2001-03-12')))
+ self.assertEqual(deadline(date.fromisoformat('2001-01-30')), (TypDeadline.FinalDeadline, m.Cislo.objects.get(rocnik__rocnik=1, poradi='3'), date.fromisoformat('2001-03-12')))
+ self.assertEqual(deadline(date.fromisoformat('2001-03-15')), (TypDeadline.SousDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='1'), date.fromisoformat('2001-09-26')))
+ self.assertEqual(deadline(date.fromisoformat('2001-04-22')), (TypDeadline.SousDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='1'), date.fromisoformat('2001-09-26')))
+ self.assertEqual(deadline(date.fromisoformat('2001-04-30')), (TypDeadline.SousDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='1'), date.fromisoformat('2001-09-26')))
+
+ # Druhý ročník
+ # Pro jistotu ještě prázdniny
+ self.assertEqual(deadline(date.fromisoformat('2001-07-30')), (TypDeadline.SousDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='1'), date.fromisoformat('2001-09-26')))
+ self.assertEqual(deadline(date.fromisoformat('2001-09-27')), (TypDeadline.FinalDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='1'), date.fromisoformat('2001-10-07')))
+ self.assertEqual(deadline(date.fromisoformat('2001-12-27')), (TypDeadline.PredDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='2'), date.fromisoformat('2002-05-26')))
+ self.assertEqual(deadline(date.fromisoformat('2002-03-15')), (TypDeadline.PredDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='2'), date.fromisoformat('2002-05-26')))
+ self.assertEqual(deadline(date.fromisoformat('2002-03-15')), (TypDeadline.PredDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='2'), date.fromisoformat('2002-05-26')))
+
+ self.assertEqual(deadline(date.fromisoformat('2002-05-27')), (TypDeadline.FinalDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='2'), date.fromisoformat('2002-06-30')))
+ # Tohle je trochu podezřelý případ, protože relevantní deadliny existují dvě… Ale ten pro minulý ročník je těsnější a realističtější
+ self.assertEqual(deadline(date.fromisoformat('2002-06-03')), (TypDeadline.FinalDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='2'), date.fromisoformat('2002-06-30')))
+ self.assertEqual(deadline(date.fromisoformat('2002-07-01')), (TypDeadline.PredDeadline, m.Cislo.objects.get(rocnik__rocnik=3, poradi='1'), date.fromisoformat('2002-08-31')))
+
+ # Třetí ročník
+ self.assertEqual(deadline(date.fromisoformat('2002-09-01')), (TypDeadline.SousDeadline, m.Cislo.objects.get(rocnik__rocnik=3, poradi='1'), date.fromisoformat('2002-09-30')))
+ self.assertEqual(deadline(date.fromisoformat('2002-09-05')), (TypDeadline.SousDeadline, m.Cislo.objects.get(rocnik__rocnik=3, poradi='1'), date.fromisoformat('2002-09-30')))
+
+ def test_deadline_ve_zlomove_dny(self):
+ """Pro dny, kdy je deadline nebo vydání čísla, pořád dostáváme správné deadliny.
+
+ Testuje hlavně přítomnost někde nějakých off-by-one"""
+ self.assertEqual(deadline(date.fromisoformat('2000-05-22')), (TypDeadline.PredDeadline, m.Cislo.objects.get(rocnik__rocnik=1, poradi='1'), date.fromisoformat('2000-09-11')))
+
+ self.assertEqual(deadline(date.fromisoformat('2000-09-11')), (TypDeadline.PredDeadline, m.Cislo.objects.get(rocnik__rocnik=1, poradi='1'), date.fromisoformat('2000-09-11')))
+ self.assertEqual(deadline(date.fromisoformat('2000-10-01')), (TypDeadline.FinalDeadline, m.Cislo.objects.get(rocnik__rocnik=1, poradi='1'), date.fromisoformat('2000-10-01')))
+ self.assertEqual(deadline(date.fromisoformat('2000-10-19')), (TypDeadline.PredDeadline, m.Cislo.objects.get(rocnik__rocnik=1, poradi='2'), date.fromisoformat('2000-12-05')))
+ self.assertEqual(deadline(date.fromisoformat('2000-12-05')), (TypDeadline.PredDeadline, m.Cislo.objects.get(rocnik__rocnik=1, poradi='2'), date.fromisoformat('2000-12-05')))
+ self.assertEqual(deadline(date.fromisoformat('2001-01-02')), (TypDeadline.FinalDeadline, m.Cislo.objects.get(rocnik__rocnik=1, poradi='2'), date.fromisoformat('2001-01-02')))
+ self.assertEqual(deadline(date.fromisoformat('2001-01-28')), (TypDeadline.FinalDeadline, m.Cislo.objects.get(rocnik__rocnik=1, poradi='3'), date.fromisoformat('2001-03-12')))
+ self.assertEqual(deadline(date.fromisoformat('2001-03-12')), (TypDeadline.FinalDeadline, m.Cislo.objects.get(rocnik__rocnik=1, poradi='3'), date.fromisoformat('2001-03-12')))
+ self.assertEqual(deadline(date.fromisoformat('2001-04-19')), (TypDeadline.SousDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='1'), date.fromisoformat('2001-09-26')))
+ self.assertEqual(deadline(date.fromisoformat('2001-04-24')), (TypDeadline.SousDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='1'), date.fromisoformat('2001-09-26')))
+
+ self.assertEqual(deadline(date.fromisoformat('2001-09-26')), (TypDeadline.SousDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='1'), date.fromisoformat('2001-09-26')))
+ self.assertEqual(deadline(date.fromisoformat('2001-10-07')), (TypDeadline.FinalDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='1'), date.fromisoformat('2001-10-07')))
+ self.assertEqual(deadline(date.fromisoformat('2002-03-14')), (TypDeadline.PredDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='2'), date.fromisoformat('2002-05-26')))
+ self.assertEqual(deadline(date.fromisoformat('2002-05-26')), (TypDeadline.PredDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='2'), date.fromisoformat('2002-05-26')))
+ self.assertEqual(deadline(date.fromisoformat('2002-06-02')), (TypDeadline.FinalDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='2'), date.fromisoformat('2002-06-30')))
+ self.assertEqual(deadline(date.fromisoformat('2002-06-30')), (TypDeadline.FinalDeadline, m.Cislo.objects.get(rocnik__rocnik=2, poradi='2'), date.fromisoformat('2002-06-30')))
+
+ self.assertEqual(deadline(date.fromisoformat('2002-08-31')), (TypDeadline.PredDeadline, m.Cislo.objects.get(rocnik__rocnik=3, poradi='1'), date.fromisoformat('2002-08-31')))
+ self.assertEqual(deadline(date.fromisoformat('2002-09-04')), (TypDeadline.SousDeadline, m.Cislo.objects.get(rocnik__rocnik=3, poradi='1'), date.fromisoformat('2002-09-30')))
+ self.assertEqual(deadline(date.fromisoformat('2002-09-30')), (TypDeadline.SousDeadline, m.Cislo.objects.get(rocnik__rocnik=3, poradi='1'), date.fromisoformat('2002-09-30')))
+
+ def test_deadline_pro_datetime(self):
+ """Testuje, že i pro datetime dostáváme správné deadliny"""
+ self.skipTest('Chybí implementace testu')
diff --git a/seminar/utils.py b/seminar/utils.py
index 68bce110..935bc687 100644
--- a/seminar/utils.py
+++ b/seminar/utils.py
@@ -333,10 +333,12 @@ def deadline(datum):
pozdejsi_rocnik = pozdejsi_rocnik.first() if pozdejsi_rocnik.count() > 0 else None
drivejsi_rocnik = drivejsi_rocnik.first() if drivejsi_rocnik.count() > 0 else None
- # Předpokládáme, že neexistuje číslo, které má deadline ale nemá finální deadline.
- posledni_deadline_drivejsiho_rocniku = m.Cislo.objects.filter(rocnik=drivejsi_rocnik, datum_deadline__isnull=False).last().datum_deadline
+ if drivejsi_rocnik is not None:
+ # Předpokládáme, že neexistuje číslo, které má deadline ale nemá finální deadline.
+ # Seznam čísel je potřeba ručně setřídit chronologicky, protože Model říká, že se řadí od nejnovějšího
+ posledni_deadline_drivejsiho_rocniku = m.Cislo.objects.filter(rocnik=drivejsi_rocnik, datum_deadline__isnull=False).order_by('poradi').last().datum_deadline
- if datum <= posledni_deadline_drivejsiho_rocniku:
+ if drivejsi_rocnik is not None and datum <= posledni_deadline_drivejsiho_rocniku:
return deadline_v_rocniku(datum, drivejsi_rocnik)
else:
return deadline_v_rocniku(datum, pozdejsi_rocnik)