Compare commits
1 commit
master
...
certifikat
| Author | SHA1 | Date | |
|---|---|---|---|
| a1c62bdf09 |
20 changed files with 137 additions and 158 deletions
36
Dockerfile
36
Dockerfile
|
|
@ -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
|
|
@ -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:
|
||||
|
|
@ -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 "$@"
|
||||
|
|
@ -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``
|
||||
|
|
@ -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."
|
||||
|
||||
|
|
|
|||
|
|
@ -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> |
|
||||
|
|
||||
<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 />
|
||||
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
},
|
||||
}
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
BIN
tvorba/static/tvorba/logomm-new.pdf
Normal file
BIN
tvorba/static/tvorba/logomm-new.pdf
Normal file
Binary file not shown.
BIN
tvorba/static/tvorba/mff-uk-logo.pdf
Normal file
BIN
tvorba/static/tvorba/mff-uk-logo.pdf
Normal file
Binary file not shown.
|
|
@ -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>
|
||||
|
|
|
|||
11
tvorba/templates/tvorba/archiv/rocnik_certifikat.tex
Normal file
11
tvorba/templates/tvorba/archiv/rocnik_certifikat.tex
Normal 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 %}
|
||||
65
tvorba/templates/tvorba/archiv/rocnik_certifikat_part.tex
Normal file
65
tvorba/templates/tvorba/archiv/rocnik_certifikat_part.tex
Normal 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 %}
|
||||
|
|
@ -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 %}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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 #}
|
||||
|
|
|
|||
|
|
@ -32,5 +32,3 @@
|
|||
{% endfor %}
|
||||
<tbody>
|
||||
</table>
|
||||
<p>Tabulka je scrollovatelná. Je v ní {{ vysledkovka.radky_vysledkovky|length }} řešitelů. </p>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue