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);
</script>
{% 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>
{% include 'april.html' %}
{% block js %}{% endblock %}
{% block js %}{% endblock %}
</body>
</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.views.generic.base import RedirectView
from django.core.exceptions import PermissionDenied
from django.contrib.staticfiles.finders import find
import seminar.models as s
import seminar.models as m
@ -36,6 +37,7 @@ import unicodedata
import logging
import time
from collections.abc import Sequence
import http
from seminar.utils import aktivniResitele
@ -562,17 +564,25 @@ def cisloObalkyView(request, rocnik, cislo):
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
tempdir = tempfile.mkdtemp()
with open(tempdir+"/obalky.tex","w") as texfile:
texfile.write(tex.decode())
shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/lisak.pdf'), tempdir)
subprocess.call(["pdflatex","obalky.tex"], cwd = tempdir)
with tempfile.TemporaryDirectory() as tempdir:
with open(tempdir+"/obalky.tex","w") as texfile:
texfile.write(tex.decode())
shutil.copy(find('seminar/lisak.pdf'), tempdir)
subprocess.call(["pdflatex","obalky.tex"], cwd = tempdir)
with open(tempdir+"/obalky.pdf","rb") as pdffile:
response = HttpResponse(pdffile.read(), content_type='application/pdf')
shutil.rmtree(tempdir)
with open(tempdir+"/obalky.pdf","rb") as pdffile:
response = HttpResponse(pdffile.read(), content_type='application/pdf')
return response

4
sifrovacka/admin.py

@ -1,8 +1,10 @@
from django.contrib import admin
from .models import OdpovedUcastnika, SpravnaOdpoved
from .models import OdpovedUcastnika, SpravnaOdpoved, NapovezenoUcastnikovi, Napoveda
# Register your models here.
admin.site.register(OdpovedUcastnika)
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.forms import ModelForm, Textarea
from .models import OdpovedUcastnika, SpravnaOdpoved
from .models import OdpovedUcastnika, SpravnaOdpoved, NapovezenoUcastnikovi, Napoveda
class SifrovackaForm(ModelForm):
@ -16,3 +16,15 @@ class SifrovackaForm(ModelForm):
if SpravnaOdpoved.objects.filter(sifra=sifra).count() == 0:
raise ValidationError("Tohle číslo šifry v databázi nemáme. Zkontrolujte si ho prosím.")
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):
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!">
</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 %}

17
sifrovacka/urls.py

@ -1,7 +1,7 @@
from django.urls import path
from seminar.utils import org_required, resitel_or_org_required
from .views import SifrovackaView, SifrovackaListView
from .views import SifrovackaView, SifrovackaListView, NapovedaView, NapovedaListView, PreskoceniView
urlpatterns = [
path(
@ -14,4 +14,19 @@ urlpatterns = [
org_required(SifrovackaListView.as_view()),
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 seminar.views import formularOKView
from .forms import SifrovackaForm
from .models import OdpovedUcastnika, SpravnaOdpoved
from .forms import SifrovackaForm, NapovedaForm
from .models import OdpovedUcastnika, SpravnaOdpoved, Napoveda, NapovezenoUcastnikovi
from seminar.models.personalni import Resitel
@ -24,10 +24,47 @@ class SifrovackaView(FormView):
instance.uspech = True
instance.save()
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):
template_name = 'sifrovacka/odpovedi_list.html'
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 subprocess
from pathlib import Path
import http
from seminar.views import obalkyView
@ -76,17 +77,25 @@ def soustredeniUcastniciExportView(request, soustredeni):
def soustredeniStvrzenkyView(request, soustredeni):
soustredeni = get_object_or_404(Soustredeni, id=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
tex = render(request, 'soustredeni/stvrzenky.tex', {'ucastnici': ucastnici, 'soustredeni': soustredeni, 'castka': castka}).content
tempdir = Path(tempfile.mkdtemp())
with open(tempdir / "stvrzenky.tex", "w") as texfile:
texfile.write(tex.decode())
with tempfile.TemporaryDirectory() as tempdirfn:
tempdir = Path(tempdirfn)
with open(tempdir / "stvrzenky.tex", "w") as texfile:
texfile.write(tex.decode())
shutil.copy(find('images/logomm.pdf'), tempdir)
subprocess.call(["pdflatex", "stvrzenky.tex"], cwd = tempdir, stdout=subprocess.DEVNULL)
shutil.copy(find('images/logomm.pdf'), tempdir)
subprocess.call(["pdflatex", "stvrzenky.tex"], cwd = tempdir, stdout=subprocess.DEVNULL)
with open(tempdir / "stvrzenky.pdf", "rb") as pdffile:
response = HttpResponse(pdffile.read(), content_type='application/pdf')
shutil.rmtree(tempdir)
with open(tempdir / "stvrzenky.pdf", "rb") as pdffile:
response = HttpResponse(pdffile.read(), content_type='application/pdf')
return response

Loading…
Cancel
Save