Compare commits

..

1 commit

20 changed files with 137 additions and 158 deletions

View file

@ -1,36 +0,0 @@
FROM python:3.9.18-slim-bullseye
# set work directory
WORKDIR /usr/mamweb-docker
# set environment variables
ENV PIP_DISABLE_PIP_VERSION_CHECK 1
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# install dependencies
RUN apt-get update && apt-get install -y \
libpq-dev \
gcc \
locales \
imagemagick \
netcat \
postgresql-client
RUN pip install --upgrade pip
COPY ./requirements.txt .
COPY ./constraints.txt .
RUN pip install -r requirements.txt
# allow correct locales
RUN sed -i '/cs_CZ.UTF-8/s/^# //g' /etc/locale.gen && \
locale-gen
ENV LANG cs_CZ.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL cs_CZ.UTF-8
# copy project
COPY . .
# create test data once db is ready
RUN chmod +x /usr/mamweb-docker/docker_entrypoint.sh
ENTRYPOINT ["/usr/mamweb-docker/docker_entrypoint.sh"]

File diff suppressed because one or more lines are too long

View file

@ -1,23 +0,0 @@
services:
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/usr/mamweb-docker
ports:
- 8000:8000
depends_on:
- db
db:
image: postgres:13-bullseye
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_USER=mam-web
- POSTGRES_PASSWORD=RoEGG5g7&b # Random generated string corresponding with Django settings
- POSTGRES_DB=mam_docker
volumes:
postgres_data:

View file

@ -1,19 +0,0 @@
#!/bin/sh
echo "Waiting for Postgres..."
while ! nc -z "db" "5432"; do
sleep 0.1
done
echo "PostgreSQL started"
PGPASSWORD="RoEGG5g7&b" # Random generated, corresponds to the one in docker-compose.yml
if psql "postgresql://mam-web:$PGPASSWORD@db:5432/mam_docker" -t -c '\dt' | cut -d \| -f 2 | grep -qw "seminar_cisla"; then
echo "\nExistuje tabulka 'seminar_cisla' v db, testdata pravděpodobně byla vygenerována.\n"
else
python ./manage.py testdata
python ./manage.py loaddata data/*
fi
exec "$@"

View file

@ -1,15 +0,0 @@
Lokální vývoj pomocí dockeru
============================
Přijde vám standardní zprovoznění painful? Docker comes to the rescue. Stačí mít nainstalovaný ``docker`` a spustit ``docker compose up``.
Co se děje under the hood
-------------------------
- ``docker-compose.yml`` specifikuje, že chceme kontejner pro web, který je závislý na kontejneru s PostgreSQL db
- ``web`` se buildí z ``Dockerfilu``, mountuje si kořen repa jako svůj volume (takže vidí změny), na konci spouští webserver a vysatvuje ho na port 8000 localhosta
- ``db`` je z ``postgres:13-bullseye`` a má nastavené nějaké parametry, svoje data ukládá jako docker volume
- ``Dockerfile`` staví ``web`` na pythonu3.9 a debianu bullseye (mělo by odpovídat gimlimu) - nainstaluje dependencies, nastaví locale a entrypoint (co se má vykonat při spouštění kontejneru)
- ``docker_entrypoint.sh`` počká na Postgres ready v ``db``, podívá se jestli jsou v něm testdata a když ne, tak je vygeneruje, pak spustí command z compose (i.e. webserver)
- ``mamweb/settings.py`` vybere django settings podle cesty (jako doteď), vybere ``mamweb/settings_docker.py``, které importuje všechno z ``mamweb/settings_local.py``, přepíše jen ``DATABASES`` a ``SECRET_KEY``, aby se jako DB Engine používal Postgres ve vedlejším kontejneru, aby se celý web choval stejně jako ``_test`` a ``_prod`` (``_local`` aktuálně používá DB Engine sqlite3, které se v něčem chová trochu rozdílně)
- kontejner ``web`` se musí nějak připojovat k postgresu v ``db``, k tomu slouží user ``mam-web``, náhodně vygenerované heslo (v ``docker-compose.yml`` a ``docker_entrypoint.sh``, musí se shodovat), db se jmenuje ``mam_docker``

View file

@ -91,7 +91,7 @@ TODO: tabulka není úplná. Pokud na něco narazíte, tak ji prosím doplňte.
Ubuntu 22.10, ??, ``python3-venv``, ``python3-dev``, ``libpq-dev``, "Je potřeba zapnout zdroj ``universe`` a nainstalovat kompilátor C (``gcc``)?"
Linux Mint 21, ??, ``python3-venv``, ``python3-dev``, ``libpq-dev``, ""
Archlinux 2022.11.01, AUR, vestavěný, vestavěné, ``postgresql-libs``, "Je potřeba céčkový kompilátor (``gcc``); nezapomenout vygenerovat locale ``cs_CZ.UTF-8``"
Archlinux 2022.11.01, AUR, vestavěný, vestavěné, ``postgresql-libs``, "Je potřeba céčkový kompilátor (``gcc``)"
openSUSE Leap 15.4, oficiální (``python39``), předinstalovaný?, ``python39-devel``, ??FIXME!!, "Výchozí verze pythonu je 3.6 a ta je moc stará, potřeba instalovat ``gcc``. Nevím jak sehnat pg_config."
Debian 11, "oficiální, výchozí", ??, ??, ??, "Určitě to tam rozběhat jde, protože Gimli. Nejspíš bude relativně podobné Ubuntu."

View file

@ -19,11 +19,11 @@
<br>
<i>Klikni na chybu, napiš komentář</i> |
<a href="{{korekturovanepdf.pdf.url}}">stáhnout PDF (bez korektur)</a> |
<a href="../">seznam souborů</a> |
<a href="/admin/korektury/korekturovanepdf/">Spravovat PDF</a> |
<a href="../help">nápověda</a> |
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|
<a href="../">🔙 seznam korekturovaných PDF</a> |
<a href="/">🏠 hlavní stránka</a> |
<a href="/">hlavní stránka</a> |
<a href="https://mam.mff.cuni.cz/wiki">wiki</a> |
<hr />

View file

@ -14,9 +14,6 @@ if "mamweb-test" in os.path.abspath(__file__):
elif "mamweb-prod" in os.path.abspath(__file__):
from .settings_prod import *
elif "mamweb-docker" in os.path.abspath(__file__):
from .settings_docker import *
else:
from .settings_local import *

View file

@ -1,33 +0,0 @@
# -*- coding: utf-8 -*-
#
# Docker nastaveni settings.py
#
# Pro vyber tohoto nastaveni muzete pouzit tez:
# DJANGO_SETTINGS_MODULE=mamweb.settings_docker ./manage.py ...
#
# Import common settings
from .settings_common import * # zatim nutne, casem snad vyresime # noqa
from mamweb.settings_local import * # Import all the settings for local development
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'EZfSzeuDCycKr5ZjiCQ^45ZqFU@8Ke#YDwn9ThqerfEpu^yV#p'
# Database
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'mam_docker',
'USER': 'mam-web',
'PASSWORD': 'RoEGG5g7&b', # Random generated string corresponding with docker-compose
'TEST': {
'NAME': 'mam-docker-testdb',
},
"HOST": "db",
"PORT": "5432",
},
}

View file

@ -30,14 +30,10 @@ def gen_reseni_ulohy(rnd, cisla, uloha, pocet_resitelu, poradi_cisla, resitele_c
res.resitele.set(res_vyber)
res.save()
deadlines = cisla[poradi_cisla -1 ].deadline_v_cisle.all()
dline = random.choice(deadlines)
# Vytvoření hodnocení.
hod = Hodnoceni.objects.create(
body=rnd.randint(0, uloha.max_body),
deadline_body = dline,
cislo_body=cisla[poradi_cisla - 1],
reseni=res,
problem=uloha
)

Binary file not shown.

Binary file not shown.

View file

@ -122,6 +122,7 @@
<p><a href="tituly.tex" download>Tituly (TeX, včetně neveřejných, všechny, nevhodné do mamtexu)</a></p>
{# FIXME: Sice to sem asi nepatří sémanticky, ale bylo to nejjednodušší… #}
<p><a href='{% url 'tvorba_rocnik_resitele_csv' rocnik=rocnik.rocnik %}' download>CSV export řešitelů</a></p>
<p><a href='certifikaty.tar.gz' download>Certifikáty úspěšných řešitelů (doplňte místa [a data] narození a zkompilujte ./certifikaty)</a></p>
<h2>Výsledková listina včetně neveřejných bodů</h2>
{% include "vysledkovky/vysledkovka_rocnik.html" with vysledkovka=vysledkovka_neverejna %}
</div>

View file

@ -0,0 +1,11 @@
{% autoescape off %}{% load static %}{% load tex %}{% with lb='{' %}
\def\ucastnik{{resitel|sloz}}
\def\narozeni{{lb}} {% firstof ofresitel.osoba.datum_narozeni "\\TODO{datum narození ve tvaru 1. 1. 2001}" %}}
\def\mistonar{\TODO{místo narození}}
\def\body{{lb}}{{body}} bod{% if cele %}ů{% else %}u{% endif %}}
\newif\ifresitelka
{% if osloveni_zenske %}\resitelkatrue{% else %}\resitelkafalse{% endif %}
\input{certifikat.tex}
{% endwith %}{% endautoescape %}

View file

@ -0,0 +1,65 @@
{% autoescape off %}{% load static %}{% load tex %}{% with lb='{' %}
\def\rocnik{{rocnik.rocnik|sloz}}
\def\rok{{lb}}{{rocnik.prvni_rok}}/{{rocnik.prvni_rok|add:"1"}}}
\def\levypodpis{Mgr. Vladan Majerech, Dr.\\vedoucí KS M\&M}
\def\pravypodpis{doc. RNDr. Mirko Rokyta, CSc.\\děkan MFF UK}
\documentclass[landscape, 12pt]{article}
\usepackage{geometry}\geometry{a4paper,left=2cm,right=2cm,top=2cm,bottom=2cm}
\setlength\parskip{2em}
\pagestyle{empty}
\usepackage{graphicx}
\usepackage[czech]{babel}
\begin{document}
\centering
\Large
{\Huge
\includegraphics[width=0.45\textwidth]{mff-uk-logo.pdf}\\[1em]
uděluje osvědčení úspěšného řešitele\\
Korespondenčního semináře M\&M
\par}
{\normalsize jméno účastn\ifresitelka ice\else íka\fi:} {\Huge \ucastnik}\\
{\normalsize datum narození:} \narozeni{\normalsize, místo narození:} \mistonar
Účastn\ifresitelka ice\else ík\fi\ v \rocnik. ročníku semináře (školní rok \rok) získal\ifresitelka a\fi\ \body,\\
čímž se stal\ifresitelka a\fi\ úspěšným řešitelem korespondenčního semináře.
\begin{minipage}[t]{0.25\textwidth}
{
\centering
\hrule
\vspace{4pt}
\normalsize\levypodpis
\par
}
\end{minipage}
\begin{minipage}[b]{0.3\textwidth}
\centering
\includegraphics[width=0.8\textwidth]{logomm-new.pdf}
\par
\end{minipage}
\begin{minipage}[t]{0.25\textwidth}
{
\centering
\hrule
\vspace{4pt}
\normalsize\pravypodpis
\par
}
\end{minipage}
\vspace{1em}
%{\vbox to 0pt{\hbox to \textwidth{\hfill\includegraphics[height=2.5em]{jcmf.pdf}}\vskip 0pt minus 1fill}\setlength\parskip{0pt}\noindent}
{\normalsize
Korespondenční seminář M\&M organizují převážně studenti Matematicko-fyzikální fakulty Univerzity Karlovy.\\
% Organizaci semináře a vydávání časopisu podporuje Jednota českých matematiků a fyziků.
\par}
\end{document}
{% endwith %}{% endautoescape %}

View file

@ -12,22 +12,6 @@ POZOR! Kolize jmen! Dva řešitelé mají stejné makro!
{% autoescape off %}
{% load tex %}
\ExplSyntaxOn
\char_set_catcode_other:n{32}% Odsud dál do \char_set_catcode_space:n{32} nesmí být za žádnou cenu jiná mezera (tj. i zlom řádku) než ty mezi jménem a příjmením
\prop_const_from_keyval:Nn\g_tituly%
{%
{% for r in resitele %}{{r|sloz}}={% if r.titul == '' %}{}{% else %}{\titul{{r.titul|sloz}}}{% endif %},%
{% endfor %}}%
\char_set_catcode_space:n{32}
\DeclareDocumentCommand\Titul{mO{#1}}{%
\prop_if_in:NnTF\g_tituly{#1}%
{\prop_item:Nn\g_tituly{#1}}%
{\ClassError{mam}{Titul pro #1 nenalezen!}{}}%
#2%
}
\ExplSyntaxOff
{% for r in resitele %}
{% if r.titul == '' %}
{% spaceless %}

View file

@ -36,6 +36,11 @@ urlpatterns = [
org_required(views.resiteleRocnikuCsvExportView),
name='tvorba_rocnik_resitele_csv'
),
path(
'rocnik/<int:rocnik>/certifikaty.tar.gz',
org_required(views.certifikatyExportView),
name='tvorba_rocnik_certifikaty'
),
path(
'rocnik/<int:rocnik>/tituly.tex',
org_required(views.TitulyViewRocnik),

View file

@ -13,8 +13,9 @@ 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
from personalni.models import Resitel
from personalni.models import Resitel, Osoba
from soustredeni.models import Konfera
from tvorba.models import Problem, Cislo, Rocnik, Tema, Clanek, Deadline, Uloha
from treenode.models import TemaVCisleNode, PohadkaNode
@ -34,6 +35,10 @@ from django.conf import settings
import unicodedata
import logging
import time
import http
import tempfile
import shutil
import subprocess
import personalni.views
@ -281,6 +286,50 @@ def resiteleRocnikuCsvExportView(request, rocnik):
)
)
def certifikatyExportView(request, rocnik):
rocnik = get_object_or_404(Rocnik, rocnik=rocnik)
id_a_body_resitelu: dict[int, int] = body_resitelu(
rocnik,
jen_verejne = False,
)
resitele_a_body = [(Resitel.objects.get(id=id), body) for id, body in id_a_body_resitelu.items() if body > 100]
with tempfile.TemporaryDirectory() as tempdir:
shutil.copy(find("tvorba/logomm-new.pdf"), tempdir)
shutil.copy(find("tvorba/mff-uk-logo.pdf"), tempdir)
tex = render(request, "tvorba/archiv/rocnik_certifikat_part.tex", {
"rocnik": rocnik,
}).content
with open(tempdir+"/certifikat.tex", "w") as texfile:
texfile.write(tex.decode())
ostatni_soubory = ["logomm-new.pdf", "mff-uk-logo.pdf", "certifikat.tex"]
certifikaty = []
for r, b in resitele_a_body:
tex = render(request, "tvorba/archiv/rocnik_certifikat.tex", {
"resitel": r,
"body": b,
"cele": b % 1 == 0,
"osloveni_zenske": r.osoba.osloveni == Osoba.OSLOVENI_ZENSKE,
}).content
soubor = f"{r}.tex"
with open(f"{tempdir}/{soubor}", "w") as texfile:
texfile.write(tex.decode())
certifikaty.append(soubor)
with open(tempdir+"/certifikaty", "w") as skript:
for certifikat in certifikaty:
print(f"pdflatex '{certifikat}'", file=skript)
os.chmod(f"{tempdir}/certifikaty", 0o777)
subprocess.call(["tar", "-czf", "certifikaty.tar.gz", *certifikaty, *ostatni_soubory, "certifikaty"], cwd=tempdir)
with open(tempdir+"/certifikaty.tar.gz", "rb") as pdffile:
response = HttpResponse(pdffile.read(), content_type='application/gzip')
return response
# FIXME: Pozor, výš je ještě jeden ProblemView!
#class ProblemView(generic.DetailView):

View file

@ -52,7 +52,6 @@
</tbody>
</table>
<p>Tabulka je scrollovatelná. Je v ní {{ vysledkovka.radky_vysledkovky|length }} řešitelů.</p>
<p>Po kliknutí na políčko v záhlaví tabulky se u daného problému zobrazí (/skryje) detailní rozpis, za které podproblémy řešitelé dostali body.</p>
{# TODELETE #}

View file

@ -32,5 +32,3 @@
{% endfor %}
<tbody>
</table>
<p>Tabulka je scrollovatelná. Je v ní {{ vysledkovka.radky_vysledkovky|length }} řešitelů. </p>