WIP
This commit is contained in:
parent
c789775364
commit
7551f4584b
18 changed files with 339 additions and 402 deletions
|
|
@ -55,6 +55,7 @@
|
||||||
<h3> Úlohy </h3>
|
<h3> Úlohy </h3>
|
||||||
<ul>
|
<ul>
|
||||||
{% for u in ulohy %}
|
{% for u in ulohy %}
|
||||||
|
r
|
||||||
<li><a href="{{ u.admin_url }}">{{ u }}</a></li>
|
<li><a href="{{ u.admin_url }}">{{ u }}</a></li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ class Migration(migrations.Migration):
|
||||||
('various', '0003_fix_permissions'), # Zapomenutá post-split migrace, suplujeme tady.
|
('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.
|
('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'),
|
('korektury', '0021_auto_20240312_2124'),
|
||||||
('sifrovacka', '0004_auto_20240312_2124'),
|
|
||||||
('prednasky', '0013_auto_20240312_2124'),
|
('prednasky', '0013_auto_20240312_2124'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ class Migration(migrations.Migration):
|
||||||
('personalni', '0003_initial'),
|
('personalni', '0003_initial'),
|
||||||
('korektury', '0022_alter_komentar_autor_alter_korekturovanepdf_org_and_more'),
|
('korektury', '0022_alter_komentar_autor_alter_korekturovanepdf_org_and_more'),
|
||||||
('prednasky', '0014_alter_prednaska_org'),
|
('prednasky', '0014_alter_prednaska_org'),
|
||||||
('sifrovacka', '0005_alter_odpoveducastnika_resitel'),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ class Migration(migrations.Migration):
|
||||||
('reversion', '0002_add_index_on_version_for_content_type_and_db'),
|
('reversion', '0002_add_index_on_version_for_content_type_and_db'),
|
||||||
('seminar', '0143_odstrel_treenode_post'),
|
('seminar', '0143_odstrel_treenode_post'),
|
||||||
('sessions', '0001_initial'),
|
('sessions', '0001_initial'),
|
||||||
('sifrovacka', '0006_personalni_post_migrate'),
|
|
||||||
('sites', '0002_alter_domain_unique'),
|
('sites', '0002_alter_domain_unique'),
|
||||||
('sitetree', '0002_alter_treeitem_parent_alter_treeitem_tree'),
|
('sitetree', '0002_alter_treeitem_parent_alter_treeitem_tree'),
|
||||||
('soustredeni', '0010_tvorba_post'),
|
('soustredeni', '0010_tvorba_post'),
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,36 @@
|
||||||
from django.contrib import admin
|
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(Napoveda)
|
||||||
|
admin.site.register(OdpovedUcastnika)
|
||||||
admin.site.register(NapovezenoUcastnikovi)
|
admin.site.register(NapovezenoUcastnikovi)
|
||||||
admin.site.register(SeznamSifer)
|
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,30 @@
|
||||||
from django.core.exceptions import ValidationError
|
# from django.core.exceptions import ValidationError
|
||||||
from django.forms import ModelForm, Textarea
|
# from django.forms import ModelForm, Textarea
|
||||||
from .models import OdpovedUcastnika, SpravnaOdpoved, NapovezenoUcastnikovi, Napoveda
|
# from .models import OdpovedUcastnika, SpravnaOdpoved, NapovezenoUcastnikovi, Napoveda
|
||||||
|
#
|
||||||
|
#
|
||||||
class SifrovackaForm(ModelForm):
|
# class SifrovackaForm(ModelForm):
|
||||||
class Meta:
|
# class Meta:
|
||||||
model = OdpovedUcastnika
|
# model = OdpovedUcastnika
|
||||||
fields = ["sifra", "odpoved", ]
|
# fields = ["sifra", "odpoved", ]
|
||||||
widgets = {
|
# widgets = {
|
||||||
"odpoved": Textarea(attrs={'rows': 1, 'cols': 30}),
|
# "odpoved": Textarea(attrs={'rows': 1, 'cols': 30}),
|
||||||
}
|
# }
|
||||||
|
#
|
||||||
def clean_sifra(self):
|
# def clean_sifra(self):
|
||||||
sifra = self.cleaned_data.get('sifra')
|
# sifra = self.cleaned_data.get('sifra')
|
||||||
if SpravnaOdpoved.objects.filter(sifra__iexact=sifra).count() == 0:
|
# 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ě.")
|
# raise ValidationError("Tuhle šifru v databázi nemáme. Zkontrolujte si, že jste zadali název správně.")
|
||||||
return sifra
|
# return sifra
|
||||||
|
#
|
||||||
|
#
|
||||||
class NapovedaForm(ModelForm):
|
# class NapovedaForm(ModelForm):
|
||||||
class Meta:
|
# class Meta:
|
||||||
model = NapovezenoUcastnikovi
|
# model = NapovezenoUcastnikovi
|
||||||
fields = ["sifra",]
|
# fields = ["sifra",]
|
||||||
|
#
|
||||||
def clean_sifra(self):
|
# def clean_sifra(self):
|
||||||
sifra = self.cleaned_data.get('sifra')
|
# sifra = self.cleaned_data.get('sifra')
|
||||||
if Napoveda.objects.filter(sifra__iexact=sifra).count() == 0:
|
# 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ě.")
|
# raise ValidationError("K této šifře nemáme nápovědu. Zkontrolujte si, že jste zadali název správně.")
|
||||||
return sifra
|
# return sifra
|
||||||
|
|
|
||||||
|
|
@ -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
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
@ -9,26 +10,104 @@ class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('seminar', '0113_resitel_zasilat_cislo_papirove'),
|
('personalni', '0019_rename_upozorneni_resitel_upozornovat_na_opravy_reseni'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='SpravnaOdpoved',
|
name='Napoveda',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('odpoved', models.TextField()),
|
('text', models.TextField(verbose_name='Text nápovědy (zobrazený, když si účastník vezme nápovědu)')),
|
||||||
('sifra', models.IntegerField()),
|
('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!')),
|
||||||
('skryty_text', models.TextField()),
|
|
||||||
],
|
],
|
||||||
|
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='<h1>Bohužel vám hvězdy nebyly nakloněny. Rozumějte <i>máte to blbě</i>.</h1>', 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(
|
migrations.CreateModel(
|
||||||
name='OdpovedUcastnika',
|
name='OdpovedUcastnika',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('odpoved', models.TextField(verbose_name='Tajenka')),
|
('timestamp', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Timestamp')),
|
||||||
('sifra', models.IntegerField(verbose_name='Číslo šifry')),
|
('odpoved', models.TextField(verbose_name='Tajenka bez diakritiky')),
|
||||||
('resitel', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='seminar.resitel')),
|
('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'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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 = [
|
|
||||||
]
|
|
||||||
|
|
@ -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"],
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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 = [
|
|
||||||
]
|
|
||||||
|
|
@ -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),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -3,46 +3,95 @@ from django.utils import timezone
|
||||||
|
|
||||||
from personalni.models import Resitel
|
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="<h1>Bohužel vám hvězdy nebyly nakloněny. Rozumějte <i>máte to blbě</i>.</h1>", 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 <sifrovacka.models.Tajenka>`
|
||||||
|
- má :py:class:`Nápovědu/y <sifrovacka.models.Napoveda>`
|
||||||
|
- může být v :py:class:`SeznamechŠifer <sifrovacka.models.SeznamSifer>`
|
||||||
|
- a lze ji řešit:
|
||||||
|
:py:class:`OdpověďÚčastníka <sifrovacka.models.OdpovedUcastnika>`
|
||||||
|
:py:class:`NapovezenoUcastnikovi <sifrovacka.models.OdpovedUcastnika>`
|
||||||
|
"""
|
||||||
|
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 OdpovedUcastnika(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
verbose_name = 'Odpověď účastníka'
|
||||||
|
verbose_name_plural = 'Odpovědi účastníků'
|
||||||
ordering = ["-timestamp"]
|
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,)
|
odpoved = models.TextField("Tajenka bez diakritiky", blank=False, null=False,)
|
||||||
sifra = models.CharField("Šifra", max_length=255, blank=False, null=False,)
|
uspech = models.BooleanField("Zda byla odpověď správná", default=False, blank=False, null=False)
|
||||||
timestamp = models.DateTimeField("Timestamp", blank=False, null=False, default=timezone.now)
|
resitel = models.ForeignKey(Resitel, blank=False, null=False, on_delete=models.CASCADE)
|
||||||
uspech = models.BooleanField("Úspěch", blank=False, null=False, default=False)
|
|
||||||
|
|
||||||
|
def __str__(self): return f"{self.timestamp}: {'✓' if self.uspech else '❌'} {self.resitel} praví {self.odpoved} na {self.sifra}"
|
||||||
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}"
|
|
||||||
|
|
||||||
|
|
||||||
class NapovezenoUcastnikovi(models.Model):
|
class NapovezenoUcastnikovi(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
verbose_name = 'Napovězeno účastníkovi'
|
||||||
|
verbose_name_plural = 'Napovězeno účastníkům'
|
||||||
ordering = ["-timestamp"]
|
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)
|
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)
|
timestamp = models.DateTimeField("Timestamp", blank=False, null=False, default=timezone.now)
|
||||||
|
|
||||||
|
def __str__(self): return f"{self.timestamp}: {self.resitel} bere {self.napoveda}"
|
||||||
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}"
|
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,38 @@
|
||||||
from django.urls import path
|
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
|
# from personalni.utils import org_required, resitel_or_org_required
|
||||||
|
# from .views import SifrovackaView, SifrovackaListView, SifrovackaNektereListView, NapovedaView, NapovedaListView, PreskoceniView
|
||||||
urlpatterns = [
|
#
|
||||||
path(
|
# urlpatterns = [
|
||||||
'',
|
# path(
|
||||||
resitel_or_org_required(SifrovackaView.as_view()),
|
# '',
|
||||||
name='sifrovacka'
|
# resitel_or_org_required(SifrovackaView.as_view()),
|
||||||
),
|
# name='sifrovacka'
|
||||||
path(
|
# ),
|
||||||
'odpovedi/',
|
# path(
|
||||||
org_required(SifrovackaListView.as_view()),
|
# 'odpovedi/',
|
||||||
name='sifrovacka_odpovedi'
|
# org_required(SifrovackaListView.as_view()),
|
||||||
),
|
# name='sifrovacka_odpovedi'
|
||||||
path(
|
# ),
|
||||||
'odpovedi/<str:seznam>/',
|
# path(
|
||||||
org_required(SifrovackaNektereListView.as_view()),
|
# 'odpovedi/<str:seznam>/',
|
||||||
name='sifrovacka_odpovedi_nektere'
|
# org_required(SifrovackaNektereListView.as_view()),
|
||||||
),
|
# name='sifrovacka_odpovedi_nektere'
|
||||||
path(
|
# ),
|
||||||
'napoveda/',
|
# path(
|
||||||
resitel_or_org_required(NapovedaView.as_view()),
|
# 'napoveda/',
|
||||||
name='sifrovacka_napoveda'
|
# resitel_or_org_required(NapovedaView.as_view()),
|
||||||
),
|
# name='sifrovacka_napoveda'
|
||||||
path(
|
# ),
|
||||||
'napovedy/',
|
# path(
|
||||||
org_required(NapovedaListView.as_view()),
|
# 'napovedy/',
|
||||||
name='sifrovacka_napovedy'
|
# org_required(NapovedaListView.as_view()),
|
||||||
),
|
# name='sifrovacka_napovedy'
|
||||||
path(
|
# ),
|
||||||
'preskoceni/',
|
# path(
|
||||||
resitel_or_org_required(PreskoceniView.as_view()),
|
# 'preskoceni/',
|
||||||
name='sifrovacka_preskoceni'
|
# resitel_or_org_required(PreskoceniView.as_view()),
|
||||||
),
|
# name='sifrovacka_preskoceni'
|
||||||
]
|
# ),
|
||||||
|
# ]
|
||||||
|
|
|
||||||
|
|
@ -1,75 +1,75 @@
|
||||||
from django.shortcuts import get_object_or_404
|
# from django.shortcuts import get_object_or_404
|
||||||
from django.urls import reverse
|
# from django.urls import reverse
|
||||||
from django.views.generic import FormView, ListView
|
# from django.views.generic import FormView, ListView
|
||||||
|
#
|
||||||
from various.views.pomocne import formularOKView
|
# from various.views.pomocne import formularOKView
|
||||||
from .forms import SifrovackaForm, NapovedaForm
|
# from .forms import SifrovackaForm, NapovedaForm
|
||||||
from .models import OdpovedUcastnika, SpravnaOdpoved, Napoveda, NapovezenoUcastnikovi, SeznamSifer
|
# from .models import OdpovedUcastnika, SpravnaOdpoved, Napoveda, NapovezenoUcastnikovi, Sifrovacka
|
||||||
from personalni.models import Resitel
|
# from personalni.models import Resitel
|
||||||
|
#
|
||||||
|
#
|
||||||
class SifrovackaView(FormView):
|
# class SifrovackaView(FormView):
|
||||||
template_name = 'sifrovacka/sifrovacka.html'
|
# template_name = 'sifrovacka/sifrovacka.html'
|
||||||
form_class = SifrovackaForm
|
# form_class = SifrovackaForm
|
||||||
|
#
|
||||||
def form_valid(self, form):
|
# def form_valid(self, form):
|
||||||
instance = form.save(commit=False)
|
# instance = form.save(commit=False)
|
||||||
resitel = Resitel.objects.get(osoba__user=self.request.user)
|
# resitel = Resitel.objects.get(osoba__user=self.request.user)
|
||||||
instance.resitel = resitel
|
# instance.resitel = resitel
|
||||||
instance.save()
|
# instance.save()
|
||||||
sifra = SpravnaOdpoved.objects.filter(sifra__iexact=instance.sifra, odpoved__iexact=instance.odpoved.strip()).first()
|
# sifra = SpravnaOdpoved.objects.filter(sifra__iexact=instance.sifra, odpoved__iexact=instance.odpoved.strip()).first()
|
||||||
if sifra is None:
|
# if sifra is None:
|
||||||
return formularOKView(self.request, f'<h1>Bohužel vám hvězdy nebyly nakloněny. Rozumějte <i>máte to blbě</i>.</h1> <p><a href="{reverse("sifrovacka")}">Zkusit znovu.</a></p><br><br><br>')
|
# return formularOKView(self.request, f'<h1>Bohužel vám hvězdy nebyly nakloněny. Rozumějte <i>máte to blbě</i>.</h1> <p><a href="{reverse("sifrovacka")}">Zkusit znovu.</a></p><br><br><br>')
|
||||||
|
#
|
||||||
instance.uspech = True
|
# instance.uspech = True
|
||||||
instance.save()
|
# instance.save()
|
||||||
|
#
|
||||||
return formularOKView(self.request, f'<h1>{sifra.skryty_text}</h1> <p><a href="{reverse("sifrovacka")}">Odevzdat další.</a></p><br><br><br>')
|
# return formularOKView(self.request, f'<h1>{sifra.skryty_text}</h1> <p><a href="{reverse("sifrovacka")}">Odevzdat další.</a></p><br><br><br>')
|
||||||
|
#
|
||||||
|
#
|
||||||
class SifrovackaListView(ListView):
|
# class SifrovackaListView(ListView):
|
||||||
template_name = 'sifrovacka/odpovedi_list.html'
|
# template_name = 'sifrovacka/odpovedi_list.html'
|
||||||
model = OdpovedUcastnika
|
# model = OdpovedUcastnika
|
||||||
|
#
|
||||||
class SifrovackaNektereListView(SifrovackaListView):
|
# class SifrovackaNektereListView(SifrovackaListView):
|
||||||
def get_queryset(self):
|
# def get_queryset(self):
|
||||||
seznam = get_object_or_404(SeznamSifer, jmeno=self.kwargs['seznam'])
|
# seznam = get_object_or_404(Sifrovacka, jmeno=self.kwargs['seznam'])
|
||||||
orig = super().get_queryset()
|
# 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.
|
# 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):
|
# class NapovedaView(FormView):
|
||||||
template_name = 'sifrovacka/napoveda.html'
|
# template_name = 'sifrovacka/napoveda.html'
|
||||||
form_class = NapovedaForm
|
# form_class = NapovedaForm
|
||||||
|
#
|
||||||
def form_valid(self, form):
|
# def form_valid(self, form):
|
||||||
instance = form.save(commit=False)
|
# instance = form.save(commit=False)
|
||||||
resitel = Resitel.objects.get(osoba__user=self.request.user)
|
# resitel = Resitel.objects.get(osoba__user=self.request.user)
|
||||||
instance.resitel = resitel
|
# instance.resitel = resitel
|
||||||
|
#
|
||||||
if NapovezenoUcastnikovi.objects.filter(resitel=resitel, sifra__iexact=instance.sifra).first() is None:
|
# if NapovezenoUcastnikovi.objects.filter(resitel=resitel, sifra__iexact=instance.sifra).first() is None:
|
||||||
instance.save()
|
# instance.save()
|
||||||
|
#
|
||||||
napoveda = Napoveda.objects.filter(sifra__iexact=instance.sifra).first()
|
# napoveda = Napoveda.objects.filter(sifra__iexact=instance.sifra).first()
|
||||||
return formularOKView(self.request, f'<h1>Nápověda k šifře číslo {instance.sifra} je:</h1><p>{napoveda.text}</p> <p><a href="{reverse("sifrovacka")}">Odevzdat řešení.</a></p><br><br><br>')
|
# return formularOKView(self.request, f'<h1>Nápověda k šifře číslo {instance.sifra} je:</h1><p>{napoveda.text}</p> <p><a href="{reverse("sifrovacka")}">Odevzdat řešení.</a></p><br><br><br>')
|
||||||
|
#
|
||||||
|
#
|
||||||
class NapovedaListView(ListView):
|
# class NapovedaListView(ListView):
|
||||||
template_name = 'sifrovacka/napovedy_list.html'
|
# template_name = 'sifrovacka/napovedy_list.html'
|
||||||
model = NapovezenoUcastnikovi
|
# model = NapovezenoUcastnikovi
|
||||||
|
#
|
||||||
|
#
|
||||||
class PreskoceniView(FormView):
|
# class PreskoceniView(FormView):
|
||||||
template_name = 'sifrovacka/preskoceni.html'
|
# template_name = 'sifrovacka/preskoceni.html'
|
||||||
form_class = SifrovackaForm
|
# form_class = SifrovackaForm
|
||||||
initial = {"odpoved": "=======PŘESKOČENO======="}
|
# initial = {"odpoved": "=======PŘESKOČENO======="}
|
||||||
|
#
|
||||||
def form_valid(self, form):
|
# def form_valid(self, form):
|
||||||
instance = form.save(commit=False)
|
# instance = form.save(commit=False)
|
||||||
instance.odpoved = "=======PŘESKOČENO======="
|
# instance.odpoved = "=======PŘESKOČENO======="
|
||||||
resitel = Resitel.objects.get(osoba__user=self.request.user)
|
# resitel = Resitel.objects.get(osoba__user=self.request.user)
|
||||||
instance.resitel = resitel
|
# instance.resitel = resitel
|
||||||
instance.save()
|
# instance.save()
|
||||||
sifra = SpravnaOdpoved.objects.filter(sifra__iexact=instance.sifra).first() # FIXME co když je více "správných" odpovědí?
|
# 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'<h1>{sifra.skryty_text}</h1> <p><a href="{reverse("sifrovacka")}">Zpět na odevzdávátko.</a></p><br><br><br>')
|
# return formularOKView(self.request, f'<h1>{sifra.skryty_text}</h1> <p><a href="{reverse("sifrovacka")}">Zpět na odevzdávátko.</a></p><br><br><br>')
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue