Browse Source

Merge branch 'refs/heads/master' into static-files-upgrade

# Conflicts:
#	mamweb/templates/base.html
pull/44/head
Jonas Havelka 7 months ago
parent
commit
48123a8ce2
  1. 19
      mamweb/templates/april.html
  2. 2
      mamweb/templates/base.html
  3. 26
      seminar/views/views_all.py
  4. 4
      sifrovacka/admin.py
  5. 14
      sifrovacka/forms.py
  6. 65
      sifrovacka/migrations/0004_napoveda_napovezenoucastnikovi.py
  7. 17
      sifrovacka/models.py
  8. 50
      sifrovacka/templates/sifrovacka/napoveda.html
  9. 23
      sifrovacka/templates/sifrovacka/napovedy_list.html
  10. 54
      sifrovacka/templates/sifrovacka/preskoceni.html
  11. 4
      sifrovacka/templates/sifrovacka/sifrovacka.html
  12. 17
      sifrovacka/urls.py
  13. 43
      sifrovacka/views.py
  14. 25
      soustredeni/views.py

19
mamweb/templates/april.html

@ -59,3 +59,22 @@
walkText(document.body); walkText(document.body);
</script> </script>
{% endif %} {% endif %}
{% if april == 2024 %}
<script>
{# By https://stackoverflow.com/a/34559316 #}
function walkText(node) {
if (node.nodeType == 3) {
node.data = node.data.replace(/M&M/g, "W8W");
}
if (node.nodeType == 1 && node.nodeName != "SCRIPT") {
for (var i = 0; i < node.childNodes.length; i++) {
walkText(node.childNodes[i]);
}
}
}
walkText(document.body);
</script>
{% endif %}

2
mamweb/templates/base.html

@ -121,6 +121,6 @@
<script src="{% static 'bootstrap/js/bootstrap.bundle.js' %}"></script> <script src="{% static 'bootstrap/js/bootstrap.bundle.js' %}"></script>
{% include 'april.html' %} {% include 'april.html' %}
{% block js %}{% endblock %} {% block js %}{% endblock %}
</body> </body>
</html> </html>

26
seminar/views/views_all.py

@ -8,6 +8,7 @@ from django.http import Http404
from django.db.models import Q, Sum, Count from django.db.models import Q, Sum, Count
from django.views.generic.base import RedirectView from django.views.generic.base import RedirectView
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.contrib.staticfiles.finders import find
import seminar.models as s import seminar.models as s
import seminar.models as m import seminar.models as m
@ -36,6 +37,7 @@ import unicodedata
import logging import logging
import time import time
from collections.abc import Sequence from collections.abc import Sequence
import http
from seminar.utils import aktivniResitele from seminar.utils import aktivniResitele
@ -562,17 +564,25 @@ def cisloObalkyView(request, rocnik, cislo):
def obalkyView(request, resitele): def obalkyView(request, resitele):
if len(resitele) == 0:
return HttpResponse(
render(request, 'universal.html', {
'title': 'Není pro koho vyrobit obálky.',
'text': 'Právě ses pokusil/a vygenerovat obálky pro prázdnou množinu lidí. Můžeš to zkusit změnit, případně se zeptej webařů :-)',
}),
status=http.HTTPStatus.NOT_FOUND,
)
tex = render(request,'seminar/archiv/obalky.tex', {'resitele': resitele}).content tex = render(request,'seminar/archiv/obalky.tex', {'resitele': resitele}).content
tempdir = tempfile.mkdtemp() with tempfile.TemporaryDirectory() as tempdir:
with open(tempdir+"/obalky.tex","w") as texfile: with open(tempdir+"/obalky.tex","w") as texfile:
texfile.write(tex.decode()) texfile.write(tex.decode())
shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/lisak.pdf'), tempdir) shutil.copy(find('seminar/lisak.pdf'), tempdir)
subprocess.call(["pdflatex","obalky.tex"], cwd = tempdir) subprocess.call(["pdflatex","obalky.tex"], cwd = tempdir)
with open(tempdir+"/obalky.pdf","rb") as pdffile: with open(tempdir+"/obalky.pdf","rb") as pdffile:
response = HttpResponse(pdffile.read(), content_type='application/pdf') response = HttpResponse(pdffile.read(), content_type='application/pdf')
shutil.rmtree(tempdir)
return response return response

4
sifrovacka/admin.py

@ -1,8 +1,10 @@
from django.contrib import admin from django.contrib import admin
from .models import OdpovedUcastnika, SpravnaOdpoved from .models import OdpovedUcastnika, SpravnaOdpoved, NapovezenoUcastnikovi, Napoveda
# Register your models here. # Register your models here.
admin.site.register(OdpovedUcastnika) admin.site.register(OdpovedUcastnika)
admin.site.register(SpravnaOdpoved) admin.site.register(SpravnaOdpoved)
admin.site.register(Napoveda)
admin.site.register(NapovezenoUcastnikovi)

14
sifrovacka/forms.py

@ -1,6 +1,6 @@
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 from .models import OdpovedUcastnika, SpravnaOdpoved, NapovezenoUcastnikovi, Napoveda
class SifrovackaForm(ModelForm): class SifrovackaForm(ModelForm):
@ -16,3 +16,15 @@ class SifrovackaForm(ModelForm):
if SpravnaOdpoved.objects.filter(sifra=sifra).count() == 0: if SpravnaOdpoved.objects.filter(sifra=sifra).count() == 0:
raise ValidationError("Tohle číslo šifry v databázi nemáme. Zkontrolujte si ho prosím.") raise ValidationError("Tohle číslo šifry v databázi nemáme. Zkontrolujte si ho prosím.")
return sifra 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=sifra).count() == 0:
raise ValidationError("K tomuto číslu šifry nemáme nápovědu. Zkontrolujte si ho prosím.")
return sifra

65
sifrovacka/migrations/0004_napoveda_napovezenoucastnikovi.py

@ -0,0 +1,65 @@
# 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"],
},
),
]

17
sifrovacka/models.py

@ -25,3 +25,20 @@ class SpravnaOdpoved(models.Model):
def __str__(self): def __str__(self):
return f"{self.sifra}: {self.odpoved}" return f"{self.sifra}: {self.odpoved}"
class NapovezenoUcastnikovi(models.Model):
class Meta:
ordering = ["-timestamp"]
resitel = models.ForeignKey(Resitel, blank=False, null=False, on_delete=models.CASCADE)
sifra = models.IntegerField("Číslo šifry", 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.IntegerField(blank=False, null=False,)
def __str__(self):
return f"{self.sifra}: {self.text}"

50
sifrovacka/templates/sifrovacka/napoveda.html

@ -0,0 +1,50 @@
{% extends "base.html" %}
{% block content %}
<br>
<h1>{% block nadpis1a %}M&Mí šifrovačka{% endblock nadpis1a %}</h1>
<br>
<h2>Získat nápovědu k šifře:</h2>
<form action="{% url 'sifrovacka_napoveda' %}" method="post">
<table class="form">
{{form.non_field_errors}}
{% for field in form %}
<tr>
<td>
<label class="field-label{% if field.field.required %} field-required{% endif %}" for="{{ field.id_for_label }}">
{{ field.label }}
</label>
</td>
<td {% if field.help_text %} class="field-with-comment"{% endif %}>
{{ field }}
<span class="field-comment">{{ field.help_text|safe }}</span>
</td>
</tr>
{% if field.errors %}
<tr>
<td colspan="2"><span class="field-error">{{ field.errors }}</span></td>
</tr>
{% endif %}
{% endfor %}
</table>
{% csrf_token %}
<input type="submit" value="Chci nápovědu">
</form>
<p><a href="{% url 'sifrovacka' %}">Nechceme nápovědu, známe řešení!</a></p>
<p><a href="{% url 'sifrovacka_preskoceni' %}">Přeskoč šifru</a></p>
{% endblock content %}

23
sifrovacka/templates/sifrovacka/napovedy_list.html

@ -0,0 +1,23 @@
{% extends "base.html" %}
{% block content %}
<h1>{% block nadpis1a %}Šifrovačka vzaté nápovědy{% endblock nadpis1a %}</h1>
<table class="dosla_reseni">
<tr>
<th>Timestamp</th>
<th>Řešitel</th>
<th>Šifra</th>
</tr>
{% for u in object_list %}
<tr>
<td>{{ u.timestamp }}</td>
<td>{{ u.resitel }}</td>
<td>{{ u.sifra }}</td>
</tr>
{% endfor %}
</table>
{% endblock content %}

54
sifrovacka/templates/sifrovacka/preskoceni.html

@ -0,0 +1,54 @@
{% extends "base.html" %}
{% block content %}
<br>
<h1>{% block nadpis1a %}M&Mí šifrovačka{% endblock nadpis1a %}</h1>
<br>
<h2>Přeskočit šifru:</h2>
<form action="{% url 'sifrovacka_preskoceni' %}" method="post">
<table class="form">
{{form.non_field_errors}}
{% for field in form %}
{% if field.id_for_label != "id_odpoved" %}
<tr>
<td>
<label class="field-label{% if field.field.required %} field-required{% endif %}" for="{{ field.id_for_label }}">
{{ field.label }}
</label>
</td>
<td {% if field.help_text %} class="field-with-comment"{% endif %}>
{{ field }}
<span class="field-comment">{{ field.help_text|safe }}</span>
</td>
</tr>
{% if field.errors %}
<tr>
<td colspan="2"><span class="field-error">{{ field.errors }}</span></td>
</tr>
{% endif %}
{% else %}
{{ field.as_hidden }}
{% endif %}
{% endfor %}
</table>
{% csrf_token %}
<input type="submit" value="Chceme další stanoviště bez vyřešení šifry">
</form>
<p><a href="{% url 'sifrovacka' %}">Nechceme přeskočit, známe řešení!</a></p>
<p><a href="{% url 'sifrovacka_napoveda' %}">Nechceme přeskakovat, ale nápověda by se šikla.</a></p>
{% endblock content %}

4
sifrovacka/templates/sifrovacka/sifrovacka.html

@ -43,4 +43,8 @@
<input type="submit" value="Tak pravím!"> <input type="submit" value="Tak pravím!">
</form> </form>
<p><a href="{% url 'sifrovacka_napoveda' %}">Získat nápovědu</a></p>
<p><a href="{% url 'sifrovacka_preskoceni' %}">Přeskoč šifru</a></p>
{% endblock content %} {% endblock content %}

17
sifrovacka/urls.py

@ -1,7 +1,7 @@
from django.urls import path from django.urls import path
from seminar.utils import org_required, resitel_or_org_required from seminar.utils import org_required, resitel_or_org_required
from .views import SifrovackaView, SifrovackaListView from .views import SifrovackaView, SifrovackaListView, NapovedaView, NapovedaListView, PreskoceniView
urlpatterns = [ urlpatterns = [
path( path(
@ -14,4 +14,19 @@ urlpatterns = [
org_required(SifrovackaListView.as_view()), org_required(SifrovackaListView.as_view()),
name='sifrovacka_odpovedi' name='sifrovacka_odpovedi'
), ),
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'
),
] ]

43
sifrovacka/views.py

@ -2,8 +2,8 @@ from django.urls import reverse
from django.views.generic import FormView, ListView from django.views.generic import FormView, ListView
from seminar.views import formularOKView from seminar.views import formularOKView
from .forms import SifrovackaForm from .forms import SifrovackaForm, NapovedaForm
from .models import OdpovedUcastnika, SpravnaOdpoved from .models import OdpovedUcastnika, SpravnaOdpoved, Napoveda, NapovezenoUcastnikovi
from seminar.models.personalni import Resitel from seminar.models.personalni import Resitel
@ -24,10 +24,47 @@ class SifrovackaView(FormView):
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 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=instance.sifra).first() is None:
instance.save()
napoveda = Napoveda.objects.filter(sifra=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>')
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=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>')

25
soustredeni/views.py

@ -9,6 +9,7 @@ import tempfile
import shutil import shutil
import subprocess import subprocess
from pathlib import Path from pathlib import Path
import http
from seminar.views import obalkyView from seminar.views import obalkyView
@ -76,17 +77,25 @@ def soustredeniUcastniciExportView(request, soustredeni):
def soustredeniStvrzenkyView(request, soustredeni): def soustredeniStvrzenkyView(request, soustredeni):
soustredeni = get_object_or_404(Soustredeni, id=soustredeni) soustredeni = get_object_or_404(Soustredeni, id=soustredeni)
ucastnici = Resitel.objects.filter(soustredeni=soustredeni) ucastnici = Resitel.objects.filter(soustredeni=soustredeni)
if ucastnici.count() == 0:
return HttpResponse(
render(request, 'universal.html', {
'title': 'Není pro koho vyrobit stvrzenky.',
'text': 'Právě ses pokusil/a vygenerovat stvrzenky pro prázdnou množinu lidí. Můžeš to zkusit změnit, případně se zeptej webařů :-)',
}),
status=http.HTTPStatus.NOT_FOUND,
)
castka = Nastaveni.get_solo().cena_sous castka = Nastaveni.get_solo().cena_sous
tex = render(request, 'soustredeni/stvrzenky.tex', {'ucastnici': ucastnici, 'soustredeni': soustredeni, 'castka': castka}).content tex = render(request, 'soustredeni/stvrzenky.tex', {'ucastnici': ucastnici, 'soustredeni': soustredeni, 'castka': castka}).content
tempdir = Path(tempfile.mkdtemp()) with tempfile.TemporaryDirectory() as tempdirfn:
with open(tempdir / "stvrzenky.tex", "w") as texfile: tempdir = Path(tempdirfn)
texfile.write(tex.decode()) with open(tempdir / "stvrzenky.tex", "w") as texfile:
texfile.write(tex.decode())
shutil.copy(find('images/logomm.pdf'), tempdir) shutil.copy(find('images/logomm.pdf'), tempdir)
subprocess.call(["pdflatex", "stvrzenky.tex"], cwd = tempdir, stdout=subprocess.DEVNULL) subprocess.call(["pdflatex", "stvrzenky.tex"], cwd = tempdir, stdout=subprocess.DEVNULL)
with open(tempdir / "stvrzenky.pdf", "rb") as pdffile: with open(tempdir / "stvrzenky.pdf", "rb") as pdffile:
response = HttpResponse(pdffile.read(), content_type='application/pdf') response = HttpResponse(pdffile.read(), content_type='application/pdf')
shutil.rmtree(tempdir)
return response return response

Loading…
Cancel
Save