diff --git a/personalni/templates/personalni/profil/orgorozcestnik.html b/personalni/templates/personalni/profil/orgorozcestnik.html index 338857ba..320d84b9 100644 --- a/personalni/templates/personalni/profil/orgorozcestnik.html +++ b/personalni/templates/personalni/profil/orgorozcestnik.html @@ -55,6 +55,7 @@

Úlohy

diff --git a/seminar/migrations/0117_auto_20240312_2125.py b/seminar/migrations/0117_auto_20240312_2125.py index 0134534a..47dd1bca 100644 --- a/seminar/migrations/0117_auto_20240312_2125.py +++ b/seminar/migrations/0117_auto_20240312_2125.py @@ -10,7 +10,6 @@ class Migration(migrations.Migration): ('various', '0003_fix_permissions'), # Zapomenutá post-split migrace, suplujeme tady. ('personalni', '0001_skupiny'), # Mělo být spíš 0002_auto_20240312_2118, ale to je no-op, tak je to jedno. ('korektury', '0021_auto_20240312_2124'), - ('sifrovacka', '0004_auto_20240312_2124'), ('prednasky', '0013_auto_20240312_2124'), ] diff --git a/seminar/migrations/0120_remove_osoba_user_remove_prijemce_osoba_and_more.py b/seminar/migrations/0120_remove_osoba_user_remove_prijemce_osoba_and_more.py index 1bbfcff0..ab47e455 100644 --- a/seminar/migrations/0120_remove_osoba_user_remove_prijemce_osoba_and_more.py +++ b/seminar/migrations/0120_remove_osoba_user_remove_prijemce_osoba_and_more.py @@ -10,7 +10,6 @@ class Migration(migrations.Migration): ('personalni', '0003_initial'), ('korektury', '0022_alter_komentar_autor_alter_korekturovanepdf_org_and_more'), ('prednasky', '0014_alter_prednaska_org'), - ('sifrovacka', '0005_alter_odpoveducastnika_resitel'), ] operations = [ diff --git a/seminar/migrations/0144_post_odstrel_vseho.py b/seminar/migrations/0144_post_odstrel_vseho.py index 2a5d10f2..bc7a8242 100644 --- a/seminar/migrations/0144_post_odstrel_vseho.py +++ b/seminar/migrations/0144_post_odstrel_vseho.py @@ -28,7 +28,6 @@ class Migration(migrations.Migration): ('reversion', '0002_add_index_on_version_for_content_type_and_db'), ('seminar', '0143_odstrel_treenode_post'), ('sessions', '0001_initial'), - ('sifrovacka', '0006_personalni_post_migrate'), ('sites', '0002_alter_domain_unique'), ('sitetree', '0002_alter_treeitem_parent_alter_treeitem_tree'), ('soustredeni', '0010_tvorba_post'), diff --git a/sifrovacka/admin.py b/sifrovacka/admin.py index ec159726..2a843494 100644 --- a/sifrovacka/admin.py +++ b/sifrovacka/admin.py @@ -1,9 +1,36 @@ from django.contrib import admin -from .models import OdpovedUcastnika, SpravnaOdpoved, NapovezenoUcastnikovi, Napoveda, SeznamSifer +from .models import Sifrovacka, Sifra, Tajenka, Napoveda, OdpovedUcastnika, NapovezenoUcastnikovi -admin.site.register(OdpovedUcastnika) -admin.site.register(SpravnaOdpoved) + +class SifryInline(admin.TabularInline): + fields = ('cislo', 'nazev', 'preskocitelna') + show_change_link=True + model = Sifra + extra = 0 + + +@admin.register(Sifrovacka) +class SifrovackaAdmin(admin.ModelAdmin): + inline_type = 'tabular' + inlines = [SifryInline] + +class TajenkaInline(admin.TabularInline): + model = Tajenka + extra = 0 + +class NapovedaInline(admin.TabularInline): + model = Napoveda + extra = 0 + + +@admin.register(Sifra) +class SifraAdmin(admin.ModelAdmin): + inline_type = 'tabular' + inlines = [TajenkaInline, NapovedaInline] + + +admin.site.register(Tajenka) admin.site.register(Napoveda) +admin.site.register(OdpovedUcastnika) admin.site.register(NapovezenoUcastnikovi) -admin.site.register(SeznamSifer) diff --git a/sifrovacka/forms.py b/sifrovacka/forms.py index 1267848b..9f4fbcfc 100644 --- a/sifrovacka/forms.py +++ b/sifrovacka/forms.py @@ -1,30 +1,30 @@ -from django.core.exceptions import ValidationError -from django.forms import ModelForm, Textarea -from .models import OdpovedUcastnika, SpravnaOdpoved, NapovezenoUcastnikovi, Napoveda - - -class SifrovackaForm(ModelForm): - class Meta: - model = OdpovedUcastnika - fields = ["sifra", "odpoved", ] - widgets = { - "odpoved": Textarea(attrs={'rows': 1, 'cols': 30}), - } - - def clean_sifra(self): - sifra = self.cleaned_data.get('sifra') - if SpravnaOdpoved.objects.filter(sifra__iexact=sifra).count() == 0: - raise ValidationError("Tuhle šifru v databázi nemáme. Zkontrolujte si, že jste zadali název správně.") - return sifra - - -class NapovedaForm(ModelForm): - class Meta: - model = NapovezenoUcastnikovi - fields = ["sifra",] - - def clean_sifra(self): - sifra = self.cleaned_data.get('sifra') - if Napoveda.objects.filter(sifra__iexact=sifra).count() == 0: - raise ValidationError("K této šifře nemáme nápovědu. Zkontrolujte si, že jste zadali název správně.") - return sifra +# from django.core.exceptions import ValidationError +# from django.forms import ModelForm, Textarea +# from .models import OdpovedUcastnika, SpravnaOdpoved, NapovezenoUcastnikovi, Napoveda +# +# +# class SifrovackaForm(ModelForm): +# class Meta: +# model = OdpovedUcastnika +# fields = ["sifra", "odpoved", ] +# widgets = { +# "odpoved": Textarea(attrs={'rows': 1, 'cols': 30}), +# } +# +# def clean_sifra(self): +# sifra = self.cleaned_data.get('sifra') +# if SpravnaOdpoved.objects.filter(sifra__iexact=sifra).count() == 0: +# raise ValidationError("Tuhle šifru v databázi nemáme. Zkontrolujte si, že jste zadali název správně.") +# return sifra +# +# +# class NapovedaForm(ModelForm): +# class Meta: +# model = NapovezenoUcastnikovi +# fields = ["sifra",] +# +# def clean_sifra(self): +# sifra = self.cleaned_data.get('sifra') +# if Napoveda.objects.filter(sifra__iexact=sifra).count() == 0: +# raise ValidationError("K této šifře nemáme nápovědu. Zkontrolujte si, že jste zadali název správně.") +# return sifra diff --git a/sifrovacka/migrations/0001_initial.py b/sifrovacka/migrations/0001_initial.py index 742461ef..12b4ab45 100644 --- a/sifrovacka/migrations/0001_initial.py +++ b/sifrovacka/migrations/0001_initial.py @@ -1,7 +1,8 @@ -# Generated by Django 3.2.22 on 2023-10-14 09:20 +# Generated by Django 4.2.20 on 2025-04-23 20:08 from django.db import migrations, models import django.db.models.deletion +import django.utils.timezone class Migration(migrations.Migration): @@ -9,26 +10,104 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('seminar', '0113_resitel_zasilat_cislo_papirove'), + ('personalni', '0019_rename_upozorneni_resitel_upozornovat_na_opravy_reseni'), ] operations = [ migrations.CreateModel( - name='SpravnaOdpoved', + name='Napoveda', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('odpoved', models.TextField()), - ('sifra', models.IntegerField()), - ('skryty_text', models.TextField()), + ('text', models.TextField(verbose_name='Text nápovědy (zobrazený, když si účastník vezme nápovědu)')), + ('uroven', models.IntegerField(default=1, verbose_name='Úroveň jak moc (nebo který krok) nápověda napoví, nejvýše jedna nápověda dané úrovně k dané šifře!')), ], + options={ + 'verbose_name': 'Nápověda', + 'verbose_name_plural': 'Nápovědy', + 'ordering': ['sifra', 'uroven'], + }, + ), + migrations.CreateModel( + name='Sifra', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('cislo', models.IntegerField(blank=True, null=True, verbose_name='Číslo šifry')), + ('nazev', models.CharField(blank=True, max_length=255, null=True, verbose_name='Název šifry')), + ('preskocitelna', models.BooleanField(default=False)), + ('skryty_text', models.TextField(blank=True, null=True, verbose_name='Text zobrazený při přeskočení (pokud prázdný, pak se zobrazují skryté texty všech tajenek k této šifře)')), + ], + options={ + 'verbose_name': 'Šifra', + 'verbose_name_plural': 'Šifry', + 'ordering': ['sifrovacka', 'cislo', 'nazev'], + }, + ), + migrations.CreateModel( + name='Sifrovacka', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('jmeno', models.CharField(max_length=255, verbose_name='Jméno seznamu')), + ('aktivni', models.BooleanField(default=True, verbose_name='Lze odevzdávat šifry z tohoto seznamu?')), + ('oznameni_spatne', models.TextField(default='

Bohužel vám hvězdy nebyly nakloněny. Rozumějte máte to blbě.

', verbose_name='Oznámení při špatné odpovědi')), + ], + options={ + 'verbose_name': 'Šifrovačka', + 'verbose_name_plural': 'Šifrovačky', + 'ordering': ['aktivni', 'jmeno'], + }, + ), + migrations.CreateModel( + name='Tajenka', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('tajenka', models.TextField(verbose_name='Tajenka bez diakritiky')), + ('skryty_text', models.TextField(verbose_name='Text zobrazený po zadání tajenky')), + ('sifra', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tajenky', to='sifrovacka.sifra')), + ], + options={ + 'verbose_name': 'Tajenka', + 'verbose_name_plural': 'Tajenky', + 'ordering': ['sifra'], + }, + ), + migrations.AddField( + model_name='sifra', + name='sifrovacka', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sifry', to='sifrovacka.sifrovacka'), ), migrations.CreateModel( name='OdpovedUcastnika', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('odpoved', models.TextField(verbose_name='Tajenka')), - ('sifra', models.IntegerField(verbose_name='Číslo šifry')), - ('resitel', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='seminar.resitel')), + ('timestamp', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Timestamp')), + ('odpoved', models.TextField(verbose_name='Tajenka bez diakritiky')), + ('uspech', models.BooleanField(default=False, verbose_name='Zda byla odpověď správná')), + ('resitel', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='personalni.resitel')), + ('sifra', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='odpovedi', to='sifrovacka.sifra')), ], + options={ + 'verbose_name': 'Odpověď účastníka', + 'verbose_name_plural': 'Odpovědi účastníků', + 'ordering': ['-timestamp'], + }, + ), + migrations.CreateModel( + name='NapovezenoUcastnikovi', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('timestamp', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Timestamp')), + ('napoveda', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='napovezeno', to='sifrovacka.napoveda')), + ('resitel', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='personalni.resitel')), + ], + options={ + 'verbose_name': 'Napovězeno účastníkovi', + 'verbose_name_plural': 'Napovězeno účastníkům', + 'ordering': ['-timestamp'], + }, + ), + migrations.AddField( + model_name='napoveda', + name='sifra', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='napovedy', to='sifrovacka.sifra'), ), ] diff --git a/sifrovacka/migrations/0002_auto_20231015_1944.py b/sifrovacka/migrations/0002_auto_20231015_1944.py deleted file mode 100644 index dea42891..00000000 --- a/sifrovacka/migrations/0002_auto_20231015_1944.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 3.2.22 on 2023-10-15 17:44 - -from django.db import migrations, models -import django.utils.timezone - - -class Migration(migrations.Migration): - - dependencies = [ - ('sifrovacka', '0001_initial'), - ] - - operations = [ - migrations.AlterModelOptions( - name='odpoveducastnika', - options={'ordering': ['-timestamp']}, - ), - migrations.AddField( - model_name='odpoveducastnika', - name='timestamp', - field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='Timestamp'), - ), - migrations.AlterField( - model_name='odpoveducastnika', - name='odpoved', - field=models.TextField(verbose_name='Tajenka bez diakritiky'), - ), - ] diff --git a/sifrovacka/migrations/0003_odpoveducastnika_uspech.py b/sifrovacka/migrations/0003_odpoveducastnika_uspech.py deleted file mode 100644 index 1d61dd8c..00000000 --- a/sifrovacka/migrations/0003_odpoveducastnika_uspech.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.22 on 2023-10-16 17:51 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('sifrovacka', '0002_auto_20231015_1944'), - ] - - operations = [ - migrations.AddField( - model_name='odpoveducastnika', - name='uspech', - field=models.BooleanField(default=False, verbose_name='Úspěch'), - ), - ] diff --git a/sifrovacka/migrations/0004_auto_20240312_2124.py b/sifrovacka/migrations/0004_auto_20240312_2124.py deleted file mode 100644 index 252268a6..00000000 --- a/sifrovacka/migrations/0004_auto_20240312_2124.py +++ /dev/null @@ -1,13 +0,0 @@ -# Generated by Django 4.2.8 on 2024-03-12 20:24 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('sifrovacka', '0004_napoveda_napovezenoucastnikovi'), - ] - - operations = [ - ] diff --git a/sifrovacka/migrations/0004_napoveda_napovezenoucastnikovi.py b/sifrovacka/migrations/0004_napoveda_napovezenoucastnikovi.py deleted file mode 100644 index cba7ae8f..00000000 --- a/sifrovacka/migrations/0004_napoveda_napovezenoucastnikovi.py +++ /dev/null @@ -1,65 +0,0 @@ -# Generated by Django 4.2.8 on 2024-04-14 12:57 - -from django.db import migrations, models -import django.db.models.deletion -import django.utils.timezone - - -class Migration(migrations.Migration): - dependencies = [ - ( - "seminar", - "0114_related_name_se_zmenilo_a_django_chce_migraci_tak_dostane_migraci", - ), - ("sifrovacka", "0003_odpoveducastnika_uspech"), - ] - - operations = [ - migrations.CreateModel( - name="Napoveda", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("text", models.TextField()), - ("sifra", models.IntegerField()), - ], - ), - migrations.CreateModel( - name="NapovezenoUcastnikovi", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("sifra", models.IntegerField(verbose_name="Číslo šifry")), - ( - "timestamp", - models.DateTimeField( - default=django.utils.timezone.now, verbose_name="Timestamp" - ), - ), - ( - "resitel", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - to="seminar.resitel", - ), - ), - ], - options={ - "ordering": ["-timestamp"], - }, - ), - ] diff --git a/sifrovacka/migrations/0005_alter_odpoveducastnika_resitel.py b/sifrovacka/migrations/0005_alter_odpoveducastnika_resitel.py deleted file mode 100644 index d21d65d6..00000000 --- a/sifrovacka/migrations/0005_alter_odpoveducastnika_resitel.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 4.2.11 on 2024-03-19 21:35 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('personalni', '0003_initial'), - ('sifrovacka', '0004_auto_20240312_2124'), - ] - - operations = [ - migrations.AlterField( - model_name='odpoveducastnika', - name='resitel', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='personalni.resitel'), - ), - migrations.AlterField( - model_name='napovezenoucastnikovi', - name='resitel', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='personalni.resitel'), - ), - ] diff --git a/sifrovacka/migrations/0006_personalni_post_migrate.py b/sifrovacka/migrations/0006_personalni_post_migrate.py deleted file mode 100644 index cf2c8ad5..00000000 --- a/sifrovacka/migrations/0006_personalni_post_migrate.py +++ /dev/null @@ -1,14 +0,0 @@ -# Generated by Django 4.2.11 on 2024-03-26 21:25 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('sifrovacka', '0005_alter_odpoveducastnika_resitel'), - ('personalni', '0005_personalni_post_migrate'), - ] - - operations = [ - ] diff --git a/sifrovacka/migrations/0007_alter_napoveda_sifra_and_more.py b/sifrovacka/migrations/0007_alter_napoveda_sifra_and_more.py deleted file mode 100644 index 0212e3c4..00000000 --- a/sifrovacka/migrations/0007_alter_napoveda_sifra_and_more.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 4.2.18 on 2025-03-19 20:12 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('sifrovacka', '0006_personalni_post_migrate'), - ] - - operations = [ - migrations.AlterField( - model_name='napoveda', - name='sifra', - field=models.CharField(max_length=255), - ), - migrations.AlterField( - model_name='napovezenoucastnikovi', - name='sifra', - field=models.CharField(max_length=255, verbose_name='Šifra'), - ), - migrations.AlterField( - model_name='odpoveducastnika', - name='sifra', - field=models.CharField(max_length=255, verbose_name='Šifra'), - ), - migrations.AlterField( - model_name='spravnaodpoved', - name='sifra', - field=models.CharField(max_length=255), - ), - ] diff --git a/sifrovacka/migrations/0008_seznamsifer.py b/sifrovacka/migrations/0008_seznamsifer.py deleted file mode 100644 index ea211afe..00000000 --- a/sifrovacka/migrations/0008_seznamsifer.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 4.2.20 on 2025-03-19 21:39 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('sifrovacka', '0007_alter_napoveda_sifra_and_more'), - ] - - operations = [ - migrations.CreateModel( - name='SeznamSifer', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('jmeno', models.CharField(help_text='něco co jde zadat do adresy', max_length=255, verbose_name='Jméno seznamu')), - ('sifry', models.ManyToManyField(to='sifrovacka.spravnaodpoved')), - ], - ), - ] diff --git a/sifrovacka/models.py b/sifrovacka/models.py index e96a6d99..b0922ebc 100644 --- a/sifrovacka/models.py +++ b/sifrovacka/models.py @@ -3,46 +3,95 @@ from django.utils import timezone from personalni.models import Resitel +class Sifrovacka(models.Model): + class Meta: + verbose_name = 'Šifrovačka' + verbose_name_plural = 'Šifrovačky' + ordering = ['aktivni', 'jmeno'] + + jmeno = models.CharField("Jméno seznamu", max_length=255, blank=False, null=False) + aktivni = models.BooleanField("Lze odevzdávat šifry z tohoto seznamu?", default=True, blank=False, null=False) + oznameni_spatne = models.TextField("Oznámení při špatné odpovědi", default="

Bohužel vám hvězdy nebyly nakloněny. Rozumějte máte to blbě.

", blank=False, null=False) + + def __str__(self): return f"{'☢' if self.aktivni else '🗑'} {self.jmeno}" + +class Sifra(models.Model): + """ + Reprezentuje jednu šifru, která: + - má :py:class:`Tajenku/y ` + - má :py:class:`Nápovědu/y ` + - může být v :py:class:`SeznamechŠifer ` + - a lze ji řešit: + :py:class:`OdpověďÚčastníka ` + :py:class:`NapovezenoUcastnikovi ` + """ + class Meta: + verbose_name = 'Šifra' + verbose_name_plural = 'Šifry' + ordering = ['sifrovacka', 'cislo', 'nazev'] + + sifrovacka = models.ForeignKey(Sifrovacka, related_name="sifry", on_delete=models.CASCADE, blank=False, null=False) + cislo = models.IntegerField("Číslo šifry", blank=True, null=True) + nazev = models.CharField("Název šifry", max_length=255, blank=True, null=True) + preskocitelna = models.BooleanField(default=False, blank=False, null=False) + skryty_text = models.TextField("Text zobrazený při přeskočení (pokud prázdný, pak se zobrazují skryté texty všech tajenek k této šifře)", blank=True, null=True) + + def __str__(self): return f"{self.cislo}. {self.nazev}" + + def clean(self): + if self.cislo is None and self.nazev is None: + raise models.exceptions.ValidationError() + + +class Tajenka(models.Model): + class Meta: + verbose_name = 'Tajenka' + verbose_name_plural = 'Tajenky' + ordering = ['sifra'] + + sifra = models.ForeignKey(Sifra, related_name="tajenky", on_delete=models.CASCADE, blank=False, null=False) + tajenka = models.TextField("Tajenka bez diakritiky", blank=False, null=False) + skryty_text = models.TextField("Text zobrazený po zadání tajenky", blank=False, null=False) + + def __str__(self): return f"{self.sifra}: {self.tajenka}" + + +class Napoveda(models.Model): + class Meta: + verbose_name = 'Nápověda' + verbose_name_plural = 'Nápovědy' + ordering = ["sifra", "uroven"] + + sifra = models.ForeignKey(Sifra, related_name="napovedy", on_delete=models.CASCADE, blank=False, null=False) + text = models.TextField("Text nápovědy (zobrazený, když si účastník vezme nápovědu)", blank=False, null=False) + uroven = models.IntegerField("Úroveň jak moc (nebo který krok) nápověda napoví, nejvýše jedna nápověda dané úrovně k dané šifře!", default=1, blank=False, null=False) + + def __str__(self): return f"{self.sifra} ({self.uroven}): {self.text}" + class OdpovedUcastnika(models.Model): class Meta: + verbose_name = 'Odpověď účastníka' + verbose_name_plural = 'Odpovědi účastníků' ordering = ["-timestamp"] - resitel = models.ForeignKey(Resitel, blank=False, null=False, on_delete=models.CASCADE) + sifra = models.ForeignKey(Sifra, related_name="odpovedi", on_delete=models.CASCADE, blank=False, null=False) + timestamp = models.DateTimeField("Timestamp", default=timezone.now, blank=False, null=False) odpoved = models.TextField("Tajenka bez diakritiky", blank=False, null=False,) - sifra = models.CharField("Šifra", max_length=255, blank=False, null=False,) - timestamp = models.DateTimeField("Timestamp", blank=False, null=False, default=timezone.now) - uspech = models.BooleanField("Úspěch", blank=False, null=False, default=False) + uspech = models.BooleanField("Zda byla odpověď správná", default=False, blank=False, null=False) + resitel = models.ForeignKey(Resitel, blank=False, null=False, on_delete=models.CASCADE) - -class SpravnaOdpoved(models.Model): - odpoved = models.TextField(blank=False, null=False,) - sifra = models.CharField(max_length=255, blank=False, null=False,) - skryty_text = models.TextField(blank=False, null=False,) - - def __str__(self): - return f"{self.sifra}: {self.odpoved}" + def __str__(self): return f"{self.timestamp}: {'✓' if self.uspech else '❌'} {self.resitel} praví {self.odpoved} na {self.sifra}" class NapovezenoUcastnikovi(models.Model): class Meta: + verbose_name = 'Napovězeno účastníkovi' + verbose_name_plural = 'Napovězeno účastníkům' ordering = ["-timestamp"] + napoveda = models.ForeignKey(Napoveda, related_name="napovezeno", on_delete=models.CASCADE, blank=False, null=False) resitel = models.ForeignKey(Resitel, blank=False, null=False, on_delete=models.CASCADE) - sifra = models.CharField("Šifra", max_length=255, blank=False, null=False,) timestamp = models.DateTimeField("Timestamp", blank=False, null=False, default=timezone.now) - -class Napoveda(models.Model): - text = models.TextField(blank=False, null=False,) - sifra = models.CharField(max_length=255, blank=False, null=False,) - - def __str__(self): - return f"{self.sifra}: {self.text}" - -class SeznamSifer(models.Model): - jmeno = models.CharField("Jméno seznamu", max_length=255, blank=False, null=False, help_text="něco co jde zadat do adresy") - sifry = models.ManyToManyField(SpravnaOdpoved) - - def __str__(self): - return f"{self.jmeno}" + def __str__(self): return f"{self.timestamp}: {self.resitel} bere {self.napoveda}" diff --git a/sifrovacka/urls.py b/sifrovacka/urls.py index 63e9a5c2..e95a61ce 100644 --- a/sifrovacka/urls.py +++ b/sifrovacka/urls.py @@ -1,37 +1,38 @@ -from django.urls import path - -from personalni.utils import org_required, resitel_or_org_required -from .views import SifrovackaView, SifrovackaListView, SifrovackaNektereListView, NapovedaView, NapovedaListView, PreskoceniView - -urlpatterns = [ - path( - '', - resitel_or_org_required(SifrovackaView.as_view()), - name='sifrovacka' - ), - path( - 'odpovedi/', - org_required(SifrovackaListView.as_view()), - name='sifrovacka_odpovedi' - ), - path( - 'odpovedi//', - org_required(SifrovackaNektereListView.as_view()), - name='sifrovacka_odpovedi_nektere' - ), - path( - 'napoveda/', - resitel_or_org_required(NapovedaView.as_view()), - name='sifrovacka_napoveda' - ), - path( - 'napovedy/', - org_required(NapovedaListView.as_view()), - name='sifrovacka_napovedy' - ), - path( - 'preskoceni/', - resitel_or_org_required(PreskoceniView.as_view()), - name='sifrovacka_preskoceni' - ), -] +urlpatterns = [] +# from django.urls import path +# +# from personalni.utils import org_required, resitel_or_org_required +# from .views import SifrovackaView, SifrovackaListView, SifrovackaNektereListView, NapovedaView, NapovedaListView, PreskoceniView +# +# urlpatterns = [ +# path( +# '', +# resitel_or_org_required(SifrovackaView.as_view()), +# name='sifrovacka' +# ), +# path( +# 'odpovedi/', +# org_required(SifrovackaListView.as_view()), +# name='sifrovacka_odpovedi' +# ), +# path( +# 'odpovedi//', +# org_required(SifrovackaNektereListView.as_view()), +# name='sifrovacka_odpovedi_nektere' +# ), +# path( +# 'napoveda/', +# resitel_or_org_required(NapovedaView.as_view()), +# name='sifrovacka_napoveda' +# ), +# path( +# 'napovedy/', +# org_required(NapovedaListView.as_view()), +# name='sifrovacka_napovedy' +# ), +# path( +# 'preskoceni/', +# resitel_or_org_required(PreskoceniView.as_view()), +# name='sifrovacka_preskoceni' +# ), +# ] diff --git a/sifrovacka/views.py b/sifrovacka/views.py index a525131a..37f3d186 100644 --- a/sifrovacka/views.py +++ b/sifrovacka/views.py @@ -1,75 +1,75 @@ -from django.shortcuts import get_object_or_404 -from django.urls import reverse -from django.views.generic import FormView, ListView - -from various.views.pomocne import formularOKView -from .forms import SifrovackaForm, NapovedaForm -from .models import OdpovedUcastnika, SpravnaOdpoved, Napoveda, NapovezenoUcastnikovi, SeznamSifer -from personalni.models import Resitel - - -class SifrovackaView(FormView): - template_name = 'sifrovacka/sifrovacka.html' - form_class = SifrovackaForm - - def form_valid(self, form): - instance = form.save(commit=False) - resitel = Resitel.objects.get(osoba__user=self.request.user) - instance.resitel = resitel - instance.save() - sifra = SpravnaOdpoved.objects.filter(sifra__iexact=instance.sifra, odpoved__iexact=instance.odpoved.strip()).first() - if sifra is None: - return formularOKView(self.request, f'

Bohužel vám hvězdy nebyly nakloněny. Rozumějte máte to blbě.

Zkusit znovu.




') - - instance.uspech = True - instance.save() - - return formularOKView(self.request, f'

{sifra.skryty_text}

Odevzdat další.




') - - -class SifrovackaListView(ListView): - template_name = 'sifrovacka/odpovedi_list.html' - model = OdpovedUcastnika - -class SifrovackaNektereListView(SifrovackaListView): - def get_queryset(self): - seznam = get_object_or_404(SeznamSifer, jmeno=self.kwargs['seznam']) - orig = super().get_queryset() - return orig.filter(sifra__in=seznam.sifry.all().values('sifra')) # poslední je kvůli tomu, že máme odkaz na celý objekt a ne jen na jméno šifry. - - -class NapovedaView(FormView): - template_name = 'sifrovacka/napoveda.html' - form_class = NapovedaForm - - def form_valid(self, form): - instance = form.save(commit=False) - resitel = Resitel.objects.get(osoba__user=self.request.user) - instance.resitel = resitel - - if NapovezenoUcastnikovi.objects.filter(resitel=resitel, sifra__iexact=instance.sifra).first() is None: - instance.save() - - napoveda = Napoveda.objects.filter(sifra__iexact=instance.sifra).first() - return formularOKView(self.request, f'

Nápověda k šifře číslo {instance.sifra} je:

{napoveda.text}

Odevzdat řešení.




') - - -class NapovedaListView(ListView): - template_name = 'sifrovacka/napovedy_list.html' - model = NapovezenoUcastnikovi - - -class PreskoceniView(FormView): - template_name = 'sifrovacka/preskoceni.html' - form_class = SifrovackaForm - initial = {"odpoved": "=======PŘESKOČENO======="} - - def form_valid(self, form): - instance = form.save(commit=False) - instance.odpoved = "=======PŘESKOČENO=======" - resitel = Resitel.objects.get(osoba__user=self.request.user) - instance.resitel = resitel - instance.save() - sifra = SpravnaOdpoved.objects.filter(sifra__iexact=instance.sifra).first() # FIXME co když je více "správných" odpovědí? - - return formularOKView(self.request, f'

{sifra.skryty_text}

Zpět na odevzdávátko.




') +# from django.shortcuts import get_object_or_404 +# from django.urls import reverse +# from django.views.generic import FormView, ListView +# +# from various.views.pomocne import formularOKView +# from .forms import SifrovackaForm, NapovedaForm +# from .models import OdpovedUcastnika, SpravnaOdpoved, Napoveda, NapovezenoUcastnikovi, Sifrovacka +# from personalni.models import Resitel +# +# +# class SifrovackaView(FormView): +# template_name = 'sifrovacka/sifrovacka.html' +# form_class = SifrovackaForm +# +# def form_valid(self, form): +# instance = form.save(commit=False) +# resitel = Resitel.objects.get(osoba__user=self.request.user) +# instance.resitel = resitel +# instance.save() +# sifra = SpravnaOdpoved.objects.filter(sifra__iexact=instance.sifra, odpoved__iexact=instance.odpoved.strip()).first() +# if sifra is None: +# return formularOKView(self.request, f'

Bohužel vám hvězdy nebyly nakloněny. Rozumějte máte to blbě.

Zkusit znovu.




') +# +# instance.uspech = True +# instance.save() +# +# return formularOKView(self.request, f'

{sifra.skryty_text}

Odevzdat další.




') +# +# +# class SifrovackaListView(ListView): +# template_name = 'sifrovacka/odpovedi_list.html' +# model = OdpovedUcastnika +# +# class SifrovackaNektereListView(SifrovackaListView): +# def get_queryset(self): +# seznam = get_object_or_404(Sifrovacka, jmeno=self.kwargs['seznam']) +# orig = super().get_queryset() +# return orig.filter(sifra__in=seznam.sifry.all().values('sifra')) # poslední je kvůli tomu, že máme odkaz na celý objekt a ne jen na jméno šifry. +# +# +# class NapovedaView(FormView): +# template_name = 'sifrovacka/napoveda.html' +# form_class = NapovedaForm +# +# def form_valid(self, form): +# instance = form.save(commit=False) +# resitel = Resitel.objects.get(osoba__user=self.request.user) +# instance.resitel = resitel +# +# if NapovezenoUcastnikovi.objects.filter(resitel=resitel, sifra__iexact=instance.sifra).first() is None: +# instance.save() +# +# napoveda = Napoveda.objects.filter(sifra__iexact=instance.sifra).first() +# return formularOKView(self.request, f'

Nápověda k šifře číslo {instance.sifra} je:

{napoveda.text}

Odevzdat řešení.




') +# +# +# class NapovedaListView(ListView): +# template_name = 'sifrovacka/napovedy_list.html' +# model = NapovezenoUcastnikovi +# +# +# class PreskoceniView(FormView): +# template_name = 'sifrovacka/preskoceni.html' +# form_class = SifrovackaForm +# initial = {"odpoved": "=======PŘESKOČENO======="} +# +# def form_valid(self, form): +# instance = form.save(commit=False) +# instance.odpoved = "=======PŘESKOČENO=======" +# resitel = Resitel.objects.get(osoba__user=self.request.user) +# instance.resitel = resitel +# instance.save() +# sifra = SpravnaOdpoved.objects.filter(sifra__iexact=instance.sifra).first() # FIXME co když je více "správných" odpovědí? +# +# return formularOKView(self.request, f'

{sifra.skryty_text}

Zpět na odevzdávátko.




')