Jonas Havelka
1 year ago
commit
f43bda37ec
50 changed files with 2197 additions and 0 deletions
@ -0,0 +1,29 @@ |
|||||
|
# Z kódu webu M&M |
||||
|
# Univerzální popis našich konvencí pro nastavení editorů. |
||||
|
# Vizte https://editorconfig.org pro detaily |
||||
|
|
||||
|
root = true |
||||
|
|
||||
|
[*] |
||||
|
charset = utf-8 |
||||
|
# Unixové řádky |
||||
|
end_of_line = lf |
||||
|
insert_final_newline = true |
||||
|
|
||||
|
[*.{py,css}] |
||||
|
indent_style = tab |
||||
|
# Nenařizujeme konkrétní šířku tabulátoru |
||||
|
indent_size = unset |
||||
|
|
||||
|
# Automaticky generované migrace dodržují PEP-8, nemá smysl s tím moc bojovat. |
||||
|
[*/migrations/*.py] |
||||
|
indent_style = space |
||||
|
indent_size = 4 |
||||
|
|
||||
|
[*.html] |
||||
|
indent_style = space |
||||
|
indent_size = 2 |
||||
|
|
||||
|
[*.json] |
||||
|
indent_style = tab |
||||
|
indent_size = unset |
@ -0,0 +1,21 @@ |
|||||
|
# Inspirováno MaMwebem |
||||
|
# virtual environment |
||||
|
/venv/ |
||||
|
/env/ |
||||
|
|
||||
|
# databáze |
||||
|
/*.sqlite3 |
||||
|
|
||||
|
# složky djanga |
||||
|
/static |
||||
|
/media |
||||
|
|
||||
|
# aux files |
||||
|
*.pyc |
||||
|
*.sw[mnop] |
||||
|
|
||||
|
# vim tmp files |
||||
|
*~ |
||||
|
|
||||
|
# pro lidi, co programují v nástrojích od JetBrains |
||||
|
.idea |
@ -0,0 +1,2 @@ |
|||||
|
django |
||||
|
qrcode |
@ -0,0 +1,56 @@ |
|||||
|
# Byrokracie |
||||
|
Hra byrokracie v elektrizované verzi |
||||
|
|
||||
|
***Aktuálně je kód velmi fujky!!!*** |
||||
|
|
||||
|
|
||||
|
## Jak hrát |
||||
|
Při prvním spuštění |
||||
|
|
||||
|
- `./manage.py migrate` |
||||
|
- `./manage.py loaddata data/users.json` |
||||
|
- `./manage.py loaddata data/stanoviste.json` |
||||
|
- `./manage.py loaddata data/tymy.json` |
||||
|
|
||||
|
Rozběhnutí hry (hesla a uživatelská jména viz 'Hesla' níže, lze je upravit v adminu) |
||||
|
- `./manage.py runserver` |
||||
|
- v adminu (<127.0.0.1:8000/admin/>) přidat týmy / resetovat jejich start na aktuální datum a čas (nebojte, inventář se tam nezobrazuje) |
||||
|
- následně |
||||
|
- (pokud je `DEBUG = True`), pak stanoviště jsou na |
||||
|
- <http://127.0.0.1:8000/hra/stanoviste/1/>, |
||||
|
- <http://127.0.0.1:8000/hra/stanoviste/2/>, |
||||
|
- <http://127.0.0.1:8000/hra/stanoviste/3/>, |
||||
|
- <http://127.0.0.1:8000/hra/stanoviste/4/>, |
||||
|
- <http://127.0.0.1:8000/hra/stanoviste/5/>, |
||||
|
- <http://127.0.0.1:8000/hra/stanoviste/6/> |
||||
|
- jinak se musí na každém zařízení přihlásit (na <http://127.0.0.1:8000/>) jako stanoviště (viz 'Hesla' níže) |
||||
|
- tým po přihlášení (na <http://127.0.0.1:8000/>) vidí svoji domovskou stránku a po načtení qr kódu stanoviště příslušné stanoviště |
||||
|
|
||||
|
Skvělou zábavu :) |
||||
|
|
||||
|
|
||||
|
## Vyšetřování ztráty třídní knihy specific věci |
||||
|
***Neprocházet tyto části kódu, pokud chcete hru testovat!!!*** |
||||
|
- `data/stanoviste.json` (aktuálně pouze názvy stanovišť a viditelný popis stanovišť + název templatu) |
||||
|
- `hra/templates/hra/stanoviste/*` (kromě `**/base`, logika za zobrazováním textů) |
||||
|
- `hra/logika.py` (logika za tlačítky, tedy kdy mají být která tlačítka a jak se má změnit inventář po kliknutí na ně) |
||||
|
- `hra/templates/hra/inventar.html` (itemy, které může tým vlastnit) |
||||
|
- `hra/models.py` (od komentáře `# Inventář`, databázový záznam inventáře) |
||||
|
- `hra/migrations/*` (vyplývá z předchozího) |
||||
|
|
||||
|
|
||||
|
## Hesla |
||||
|
(uzivatelske_jmeno: heslo) |
||||
|
- `admin`: `modraplaneta` |
||||
|
- stanoviste |
||||
|
- `s1, s2, ..., sn`: `asd` |
||||
|
- tymy: |
||||
|
- `t1`: `azurova` |
||||
|
- `t2`: `okrova` |
||||
|
- `t3`: `tyrkysova` |
||||
|
- `t4`: `kastanova` |
||||
|
- `t5`: `oriskova` |
||||
|
- `t6`: `zulova` |
||||
|
- `t7`: `matova` |
||||
|
- `t8`: `smaragdova` |
||||
|
- `t9`: `cihlova` |
@ -0,0 +1 @@ |
|||||
|
# Inspirováno kódem webu M&M |
@ -0,0 +1,28 @@ |
|||||
|
{% extends "base.html" %} |
||||
|
{% load static %} |
||||
|
|
||||
|
{% block content %} |
||||
|
<h1>{{ settings.NAZEV }}</h1> |
||||
|
<h2>{% block nadpis %}Přihlášení{% endblock %}</h2> |
||||
|
|
||||
|
{# Obšlehnuto z Admina :-) #} |
||||
|
{% if user.is_authenticated %} {# Tedy když byl uživatel na stránku přesměrován z pro něj nepřístupné části webu. FIXME? Nedává smysl, pokud uživatel otevřel mam.mff.cuni.cz/prihlasit například z historie prohlížeče = nebyl na ni přesměrován. #} |
||||
|
<p>K této stránce nejspíš nemáte přístup. Můžete se zkusit přihlásit jako uživatel, který přístup má.</p> |
||||
|
{% endif %} |
||||
|
|
||||
|
<form action="{% url 'login' %}" method="post"> |
||||
|
{% csrf_token %} |
||||
|
<table class="form"> |
||||
|
{{ form.as_table }} |
||||
|
</table> |
||||
|
<br> |
||||
|
{# Django si posílá jméno další stránky jako obsah formuláře a výchozí hodnota (mi přišlo, že) nejde změnit... #} |
||||
|
<input type="hidden" name='next' value="{{ next }}"> |
||||
|
<input type="submit" value="Přihlásit"> |
||||
|
</form> |
||||
|
|
||||
|
{#<br><hr>#} |
||||
|
{#<form action="{% url 'registrace' %}">#} |
||||
|
{# <input type="submit" value="Registrovat"/>#} |
||||
|
{#</form>#} |
||||
|
{% endblock %} |
@ -0,0 +1,8 @@ |
|||||
|
{% extends "base.html" %} |
||||
|
{% load static %} |
||||
|
|
||||
|
{% block content %} |
||||
|
<h1>{% block nadpis %}Odhlášení{% endblock %}</h1> |
||||
|
<p>Byl jsi úspěšně odhlášen</p> |
||||
|
{% endblock %} |
||||
|
|
@ -0,0 +1,10 @@ |
|||||
|
from django.urls import path |
||||
|
from . import views |
||||
|
from django.views.generic.base import RedirectView |
||||
|
|
||||
|
urlpatterns = [ |
||||
|
path("prihlasit/", views.LoginView.as_view(), name="login"), |
||||
|
path("login/", RedirectView.as_view(pattern_name="login", permanent=True, query_string=True)), |
||||
|
path("odhlasit/", views.LogoutView.as_view(), name="logout"), |
||||
|
path("logout/", RedirectView.as_view(pattern_name="logout", permanent=True, query_string=True)), |
||||
|
] |
@ -0,0 +1,14 @@ |
|||||
|
from django.urls import reverse_lazy |
||||
|
from django.contrib.auth import views as auth_views |
||||
|
|
||||
|
|
||||
|
class LoginView(auth_views.LoginView): |
||||
|
# Jen vezmeme vestavěný a dáme mu vhodný template a přesměrovací URL |
||||
|
template_name = "autentizace/login.html" |
||||
|
|
||||
|
|
||||
|
class LogoutView(auth_views.LogoutView): |
||||
|
# Jen vezmeme vestavěný a dáme mu vhodný template a přesměrovací URL |
||||
|
template_name = "autentizace/logout.html" |
||||
|
# Pavel: Vůbec nevím, proč to s _lazy funguje, ale bez toho to bylo rozbité. |
||||
|
next_page = reverse_lazy("login") |
@ -0,0 +1,6 @@ |
|||||
|
from django.conf import settings |
||||
|
|
||||
|
|
||||
|
def add_settings(_): |
||||
|
""" Přidá `settings` do templatů. """ |
||||
|
return {"settings": settings} |
@ -0,0 +1,99 @@ |
|||||
|
from pathlib import Path |
||||
|
|
||||
|
# Build paths inside the project like this: BASE_DIR / "subdir". |
||||
|
BASE_DIR = Path(__file__).resolve().parent.parent |
||||
|
|
||||
|
# SECURITY WARNING: keep the secret key used in production secret! |
||||
|
SECRET_KEY = "django-insecure-opcz6rfrp-osm7wnd@3_5yb56^4=!@7@-(38j^!6^ej%88r2ud" |
||||
|
|
||||
|
# SECURITY WARNING: don't run with debug turned on in production! |
||||
|
DEBUG = True |
||||
|
|
||||
|
# ALLOWED_HOSTS = ['192.168.137.1' ] |
||||
|
|
||||
|
WSGI_APPLICATION = 'byrokracie.wsgi.application' |
||||
|
|
||||
|
STATIC_ROOT = 'static/' |
||||
|
STATIC_URL = 'static/' |
||||
|
|
||||
|
# Jednotlivé části djanga |
||||
|
INSTALLED_APPS = [ |
||||
|
"django.contrib.admin", |
||||
|
"django.contrib.auth", |
||||
|
"django.contrib.contenttypes", |
||||
|
"django.contrib.sessions", |
||||
|
"django.contrib.messages", |
||||
|
"django.contrib.staticfiles", |
||||
|
"byrokracie", |
||||
|
"autentizace", |
||||
|
"hra", |
||||
|
] |
||||
|
MIDDLEWARE = [ |
||||
|
"django.middleware.security.SecurityMiddleware", |
||||
|
"django.contrib.sessions.middleware.SessionMiddleware", |
||||
|
"django.middleware.common.CommonMiddleware", |
||||
|
"django.middleware.csrf.CsrfViewMiddleware", |
||||
|
"django.contrib.auth.middleware.AuthenticationMiddleware", |
||||
|
"django.contrib.messages.middleware.MessageMiddleware", |
||||
|
"django.middleware.clickjacking.XFrameOptionsMiddleware", |
||||
|
] |
||||
|
TEMPLATES = [ |
||||
|
{ |
||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates', |
||||
|
'DIRS': [], |
||||
|
'APP_DIRS': True, |
||||
|
'OPTIONS': { |
||||
|
'context_processors': [ |
||||
|
'django.template.context_processors.debug', |
||||
|
'django.template.context_processors.request', |
||||
|
'django.contrib.auth.context_processors.auth', |
||||
|
'django.contrib.messages.context_processors.messages', |
||||
|
'byrokracie.context_processor.add_settings' |
||||
|
], |
||||
|
}, |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
|
||||
|
# Databáze |
||||
|
DATABASES = { |
||||
|
'default': { |
||||
|
'ENGINE': 'django.db.backends.sqlite3', |
||||
|
'NAME': BASE_DIR / 'db.sqlite3', |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
# Lokalizace |
||||
|
LANGUAGE_CODE = 'cs' |
||||
|
TIME_ZONE = 'Europe/Prague' |
||||
|
USE_L10N = True # S přechodem k djangu>=4 lze smazat (localized formatting) |
||||
|
USE_TZ = True # S přechodem k djangu>=5 lze smazat (timezone aware datetimes) |
||||
|
|
||||
|
# URL pro přihlášení (default je account/login) |
||||
|
LOGIN_URL = 'login' |
||||
|
LOGIN_REDIRECT_URL = '/hra/' |
||||
|
|
||||
|
# Konstantny |
||||
|
NAZEV: str = "Vyšetřování ztráty třídní knihy" |
||||
|
NEJVYSSI_INDEX: int = 6 |
||||
|
PRVNI_PONDELI: int = 2 |
||||
|
PRVNI_NOV: int = 13 |
||||
|
TIMEOUT_STANOVISTE: int = 60 # v sekundách |
||||
|
TYM_AUTO_RELOAD: int = 30 # v sekundách |
||||
|
TIME_SPEED: float = 1.0 # 1 = hodina za minutu |
||||
|
DEN: tuple[float, float] = (8.0, 18.0) |
||||
|
POCET_BANANU: int = 2 |
||||
|
|
||||
|
POSTOVNA_DEN_V_TYDNU = 3 |
||||
|
|
||||
|
STASTNA_CISLA: set[int] = {1, 7, 10, 13, 19, 23, 28, 31, 32, 44, 49, 68, 70, 79, 82, 86, 91, 94, 97, 100, 103, 109, 129, 130, 133, 139, 167, 176, 188, 190, 192, 193, 203, 208, 219, 226, 230, 236, 239, 262, 263, 280, 291, 293, 301, 302, 310, 313, 319, 320, 326, 329, 331, 338, 356, 362, 365, 367, 368, 376, 379, 383, 386, 391, 392, 397, 404, 409, 440, 446, 464, 469, 478, 487, 490, 496, 536, 556, 563, 565, 566, 608, 617, 622, 623, 632, 635, 637, 638, 644, 649, 653, 655, 656, 665, 671, 673, 680, 683, 694, 700, 709, 716, 736, 739, 748, 761, 763, 784, 790, 793, 802, 806, 818, 820, 833, 836, 847, 860, 863, 874, 881, 888, 899, 901, 904, 907, 910, 912, 913, 921, 923, 931, 932, 937, 940, 946, 964, 970, 973, 989, 998, 1000} |
||||
|
# nejasno = [1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0] |
||||
|
# [nejasno[i] * (random.choice(list(range(3))) + 1) for i in range(len(nejasno))] |
||||
|
POCASI: list[int] = [3, 1, 3, 2, 2, 2, 0, 3, 2, 1, 0, 2, 1, 0, 3, 2, 3, 0, 2, 3, 3, 1, 2, 0] |
||||
|
|
||||
|
|
||||
|
# Django musí mít nastaveno Autofield |
||||
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' |
||||
|
# A musí mít nastavené počáteční urls |
||||
|
ROOT_URLCONF = 'byrokracie.urls' |
@ -0,0 +1,39 @@ |
|||||
|
table { |
||||
|
margin-left: auto; |
||||
|
margin-right: auto; |
||||
|
} |
||||
|
|
||||
|
th { |
||||
|
text-align: right; |
||||
|
} |
||||
|
|
||||
|
.content { |
||||
|
text-align: center; |
||||
|
} |
||||
|
|
||||
|
.ds { /* Zobrazení datové schránky na stránce týmu */ |
||||
|
margin-top: -1em; |
||||
|
} |
||||
|
|
||||
|
.inventar { |
||||
|
width: fit-content; |
||||
|
margin-left: auto; |
||||
|
margin-right: auto; |
||||
|
} |
||||
|
|
||||
|
.polozka_inventare { |
||||
|
float: left; |
||||
|
min-width: 10vw; |
||||
|
min-height: 15vw; |
||||
|
border: orange 1pt solid; |
||||
|
|
||||
|
margin: 1vh; |
||||
|
|
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
li { |
||||
|
text-align: left; |
||||
|
} |
After Width: | Height: | Size: 84 KiB |
@ -0,0 +1,26 @@ |
|||||
|
{% load static %} |
||||
|
<!DOCTYPE html> |
||||
|
<html lang="cs"> |
||||
|
<head> |
||||
|
<title>{% block nadpis %}{% endblock %}</title> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
|
||||
|
<link href="{% static 'images/icon.png' %}" rel="shortcut icon" type="image/x-icon"> |
||||
|
<link href="{% static 'css/base.css' %}?version=1" rel="stylesheet"> |
||||
|
|
||||
|
{# (Autoreload:) <meta http-equiv="refresh" content="30"> = Refresh every 30 second #} |
||||
|
{% block prenacitani %}{% endblock %} |
||||
|
|
||||
|
{# script specifický pro stránku #} |
||||
|
{% block script %}{% endblock %} |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<div class='content'> |
||||
|
{% block content %} |
||||
|
{% endblock content %} |
||||
|
</div> |
||||
|
</body> |
||||
|
|
||||
|
|
||||
|
</html> |
@ -0,0 +1,10 @@ |
|||||
|
from django.contrib import admin |
||||
|
from django.shortcuts import redirect |
||||
|
from django.urls import path, include |
||||
|
|
||||
|
urlpatterns = [ |
||||
|
path('admin/', admin.site.urls), |
||||
|
path('', include('autentizace.urls')), |
||||
|
path('hra/', include('hra.urls')), |
||||
|
path('', lambda _request: redirect('hra/', permanent=True)), |
||||
|
] |
@ -0,0 +1,16 @@ |
|||||
|
""" |
||||
|
WSGI config for byrokracie project. |
||||
|
|
||||
|
It exposes the WSGI callable as a module-level variable named ``application``. |
||||
|
|
||||
|
For more information on this file, see |
||||
|
https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/ |
||||
|
""" |
||||
|
|
||||
|
import os |
||||
|
|
||||
|
from django.core.wsgi import get_wsgi_application |
||||
|
|
||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'byrokracie.settings') |
||||
|
|
||||
|
application = get_wsgi_application() |
@ -0,0 +1,68 @@ |
|||||
|
[ |
||||
|
{ |
||||
|
"fields": { |
||||
|
"nazev": "Časový výr 🦉", |
||||
|
"poradi": 1, |
||||
|
"user": 2, |
||||
|
"verejny_text": "<p>Posun ve čtvrté dimenzi.</p>", |
||||
|
"template": "casovy_vyr.html" |
||||
|
}, |
||||
|
"model": "hra.stanoviste", |
||||
|
"pk": 1 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"nazev": "Internát", |
||||
|
"poradi": 2, |
||||
|
"user": 3, |
||||
|
"verejny_text": "<p>Domov, sladký domov.</p>", |
||||
|
"template": "domov.html" |
||||
|
}, |
||||
|
"model": "hra.stanoviste", |
||||
|
"pk": 2 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"nazev": "Potrubní pošta akademie ✉️🪠", |
||||
|
"poradi": 3, |
||||
|
"user": 4, |
||||
|
"verejny_text": "<p>Podobnost s Českou poštou je čistě náhodná.</p><p>Otevřeno: nonstop</p>", |
||||
|
"template": "posta.html" |
||||
|
}, |
||||
|
"model": "hra.stanoviste", |
||||
|
"pk": 3 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"nazev": "Studijní oddělení", |
||||
|
"poradi": 4, |
||||
|
"user": 5, |
||||
|
"verejny_text": "<p>Žádosti všeho druhu.</p><p>Otevřeno: Po–Čt: 8:00 – 16:00, Pá: 8:00 – 14:00</p>", |
||||
|
"template": "studijni.html" |
||||
|
}, |
||||
|
"model": "hra.stanoviste", |
||||
|
"pk": 4 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"nazev": "Jídelna", |
||||
|
"poradi": 5, |
||||
|
"user": 6, |
||||
|
"verejny_text": "<p>\uD83E\uDD6C\uD83E\uDD57\uD83C\uDF55\uD83E\uDD53\uD83C\uDF69\uD83C\uDF68\uD83C\uDF6A\uD83C\uDF82\uD83C\uDF4C\uD83C\uDF70\uD83C\uDF6B\uD83C\uDF67\uD83C\uDF66\uD83C\uDF61\uD83C\uDF60\uD83E\uDED1</p><p>Vaříme denně</p><p>Snídaně: 8:00 – 11:00</p><p>Obědy: 11:00 – 17:00</p><p>Večeře: 17:00 – 22:00</p>", |
||||
|
"template": "menza.html" |
||||
|
}, |
||||
|
"model": "hra.stanoviste", |
||||
|
"pk": 5 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"nazev": "Knihovna & Archiv", |
||||
|
"poradi": 6, |
||||
|
"user": 7, |
||||
|
"verejny_text": "<p>Otevřeno: Po–Čt: 8:00 – 16:00, Pá: 8:00 – 14:00</p><p>Ook!?</p>", |
||||
|
"template": "archiv.html" |
||||
|
}, |
||||
|
"model": "hra.stanoviste", |
||||
|
"pk": 6 |
||||
|
} |
||||
|
] |
@ -0,0 +1,83 @@ |
|||||
|
[ |
||||
|
{ |
||||
|
"fields": { |
||||
|
"hraci": "", |
||||
|
"nazev": "Nepojmenovaní", |
||||
|
"user": 8 |
||||
|
}, |
||||
|
"model": "hra.tym", |
||||
|
"pk": 1 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"hraci": "", |
||||
|
"nazev": "Nepojmenovaní", |
||||
|
"user": 9 |
||||
|
}, |
||||
|
"model": "hra.tym", |
||||
|
"pk": 2 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"hraci": "", |
||||
|
"nazev": "Nepojmenovaní", |
||||
|
"user": 10 |
||||
|
}, |
||||
|
"model": "hra.tym", |
||||
|
"pk": 3 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"hraci": "", |
||||
|
"nazev": "Nepojmenovaní", |
||||
|
"user": 11 |
||||
|
}, |
||||
|
"model": "hra.tym", |
||||
|
"pk": 4 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"hraci": "", |
||||
|
"nazev": "Nepojmenovaní", |
||||
|
"user": 12 |
||||
|
}, |
||||
|
"model": "hra.tym", |
||||
|
"pk": 5 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"hraci": "", |
||||
|
"nazev": "Nepojmenovaní", |
||||
|
"user": 13 |
||||
|
}, |
||||
|
"model": "hra.tym", |
||||
|
"pk": 6 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"hraci": "", |
||||
|
"nazev": "Nepojmenovaní", |
||||
|
"user": 14 |
||||
|
}, |
||||
|
"model": "hra.tym", |
||||
|
"pk": 7 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"hraci": "", |
||||
|
"nazev": "Nepojmenovaní", |
||||
|
"user": 15 |
||||
|
}, |
||||
|
"model": "hra.tym", |
||||
|
"pk": 8 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"hraci": "", |
||||
|
"nazev": "Nepojmenovaní", |
||||
|
"user": 16 |
||||
|
}, |
||||
|
"model": "hra.tym", |
||||
|
"pk": 9 |
||||
|
} |
||||
|
] |
@ -0,0 +1,178 @@ |
|||||
|
[ |
||||
|
{ |
||||
|
"fields": { |
||||
|
"is_active": true, |
||||
|
"is_staff": true, |
||||
|
"is_superuser": true, |
||||
|
"password": "pbkdf2_sha256$600000$yylg8H03nCOuMEmo7X4V6A$Za9qMeX44zvjYtIwyAlw5QLJQCEy+vDxlXDRAZqhZ2c=", |
||||
|
"username": "admin" |
||||
|
}, |
||||
|
"model": "auth.user", |
||||
|
"pk": 1 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"is_active": true, |
||||
|
"is_staff": false, |
||||
|
"is_superuser": false, |
||||
|
"password": "pbkdf2_sha256$600000$BdSaaScmKfh6Qu9xoEqp3f$96RlyOuK8lHlD5hVpfDEYJVmSxaby3O8wIT0/1MQM1k=", |
||||
|
"username": "s1" |
||||
|
}, |
||||
|
"model": "auth.user", |
||||
|
"pk": 2 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"is_active": true, |
||||
|
"is_staff": false, |
||||
|
"is_superuser": false, |
||||
|
"password": "pbkdf2_sha256$600000$BdSaaScmKfh6Qu9xoEqp3f$96RlyOuK8lHlD5hVpfDEYJVmSxaby3O8wIT0/1MQM1k=", |
||||
|
"username": "s2" |
||||
|
}, |
||||
|
"model": "auth.user", |
||||
|
"pk": 3 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"is_active": true, |
||||
|
"is_staff": false, |
||||
|
"is_superuser": false, |
||||
|
"password": "pbkdf2_sha256$600000$BdSaaScmKfh6Qu9xoEqp3f$96RlyOuK8lHlD5hVpfDEYJVmSxaby3O8wIT0/1MQM1k=", |
||||
|
"username": "s3" |
||||
|
}, |
||||
|
"model": "auth.user", |
||||
|
"pk": 4 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"is_active": true, |
||||
|
"is_staff": false, |
||||
|
"is_superuser": false, |
||||
|
"password": "pbkdf2_sha256$600000$BdSaaScmKfh6Qu9xoEqp3f$96RlyOuK8lHlD5hVpfDEYJVmSxaby3O8wIT0/1MQM1k=", |
||||
|
"username": "s4" |
||||
|
}, |
||||
|
"model": "auth.user", |
||||
|
"pk": 5 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"is_active": true, |
||||
|
"is_staff": false, |
||||
|
"is_superuser": false, |
||||
|
"password": "pbkdf2_sha256$600000$BdSaaScmKfh6Qu9xoEqp3f$96RlyOuK8lHlD5hVpfDEYJVmSxaby3O8wIT0/1MQM1k=", |
||||
|
"username": "s5" |
||||
|
}, |
||||
|
"model": "auth.user", |
||||
|
"pk": 6 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"is_active": true, |
||||
|
"is_staff": false, |
||||
|
"is_superuser": false, |
||||
|
"password": "pbkdf2_sha256$600000$BdSaaScmKfh6Qu9xoEqp3f$96RlyOuK8lHlD5hVpfDEYJVmSxaby3O8wIT0/1MQM1k=", |
||||
|
"username": "s6" |
||||
|
}, |
||||
|
"model": "auth.user", |
||||
|
"pk": 7 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"is_active": true, |
||||
|
"is_staff": false, |
||||
|
"is_superuser": false, |
||||
|
"password": "pbkdf2_sha256$600000$y2SzlaUhvzQx5MAaAPg8eR$x99VQuFAPQymfie3rNJQPIXJlmJZZ7GaX2Q8CoS+HLo=", |
||||
|
"username": "t1" |
||||
|
}, |
||||
|
"model": "auth.user", |
||||
|
"pk": 8 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"is_active": true, |
||||
|
"is_staff": false, |
||||
|
"is_superuser": false, |
||||
|
"password": "pbkdf2_sha256$600000$Dzb2XnXVY2FClbyYXXOD8V$MhI+tOVRXZBfY8OPaaWG1WMk0vMrIDpZguMp/X0udv8=", |
||||
|
"username": "t2" |
||||
|
}, |
||||
|
"model": "auth.user", |
||||
|
"pk": 9 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"is_active": true, |
||||
|
"is_staff": false, |
||||
|
"is_superuser": false, |
||||
|
"password": "pbkdf2_sha256$600000$uePowUck1EhZwiWMK3TJ2c$zGAiYICEZ46pSxtO8MF/cAawcT+UnazBcWjAiYFbTFk=", |
||||
|
"username": "t3" |
||||
|
}, |
||||
|
"model": "auth.user", |
||||
|
"pk": 10 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"is_active": true, |
||||
|
"is_staff": false, |
||||
|
"is_superuser": false, |
||||
|
"password": "pbkdf2_sha256$600000$UiEFSvRON6lWpzpp3eqlsS$CKvQO8L2Aelucmjp1Aoz5qTe8T18jMWGE4qH72Cihpw=", |
||||
|
"username": "t4" |
||||
|
}, |
||||
|
"model": "auth.user", |
||||
|
"pk": 11 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"is_active": true, |
||||
|
"is_staff": false, |
||||
|
"is_superuser": false, |
||||
|
"password": "pbkdf2_sha256$600000$L01lowUNtthy22eTVLaUrz$dp0SKguUiN5wM7gHhpW6WDhGofdIHdRj3aOQfrlih2o=", |
||||
|
"username": "t5" |
||||
|
}, |
||||
|
"model": "auth.user", |
||||
|
"pk": 12 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"is_active": true, |
||||
|
"is_staff": false, |
||||
|
"is_superuser": false, |
||||
|
"password": "pbkdf2_sha256$600000$sOCpNhTjfrLwoA9p1KlxAf$GA6njrzD0qj6Sxa/6wWVm83CdDhZw4gjg5SMKYPtKPo=", |
||||
|
"username": "t6" |
||||
|
}, |
||||
|
"model": "auth.user", |
||||
|
"pk": 13 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"is_active": true, |
||||
|
"is_staff": false, |
||||
|
"is_superuser": false, |
||||
|
"password": "pbkdf2_sha256$600000$cUKVLoph1a4lo8vWsexHV0$9bhzUjWezsPhZFmNG7gjg4WCR2Yrou68yDG+4joUXF0=", |
||||
|
"username": "t7" |
||||
|
}, |
||||
|
"model": "auth.user", |
||||
|
"pk": 14 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"is_active": true, |
||||
|
"is_staff": false, |
||||
|
"is_superuser": false, |
||||
|
"password": "pbkdf2_sha256$600000$zoKRalZSKeVYAe9yKq0Jk2$1sS7fJsiUUweoFL8nb7WLv0ZIEpnkpSjYLL2HLev/Gg=", |
||||
|
"username": "t8" |
||||
|
}, |
||||
|
"model": "auth.user", |
||||
|
"pk": 15 |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"is_active": true, |
||||
|
"is_staff": false, |
||||
|
"is_superuser": false, |
||||
|
"password": "pbkdf2_sha256$600000$N27QVcoRhkcto7JA3ygQtG$1QSCWn8Lyk+UiJyJDYr3WWYbcPP8YqGxQj4JoeyAxoc=", |
||||
|
"username": "t9" |
||||
|
}, |
||||
|
"model": "auth.user", |
||||
|
"pk": 16 |
||||
|
} |
||||
|
] |
@ -0,0 +1,12 @@ |
|||||
|
#!/usr/bin/python3 |
||||
|
|
||||
|
import json |
||||
|
import argparse |
||||
|
|
||||
|
parser = argparse.ArgumentParser() |
||||
|
parser.add_argument("input", type=argparse.FileType('r', encoding='utf-8')) |
||||
|
parser.add_argument('output', type=argparse.FileType('w', encoding='utf-8')) |
||||
|
args = parser.parse_args() |
||||
|
|
||||
|
data = json.load(args.input) |
||||
|
json.dump(data, args.output, ensure_ascii=False, sort_keys=True, indent='\t') |
@ -0,0 +1,14 @@ |
|||||
|
from django.contrib import admin |
||||
|
|
||||
|
from .models import Stanoviste, Tym, Zadost |
||||
|
|
||||
|
admin.site.register(Stanoviste) |
||||
|
admin.site.register(Zadost) |
||||
|
|
||||
|
|
||||
|
class TymAdmin(admin.ModelAdmin): |
||||
|
# fields = ["user", "nazev", "hraci", "start"] |
||||
|
pass |
||||
|
|
||||
|
|
||||
|
admin.site.register(Tym, TymAdmin) |
@ -0,0 +1,260 @@ |
|||||
|
from random import random |
||||
|
from typing import Callable, Iterable |
||||
|
|
||||
|
from django.conf import settings |
||||
|
|
||||
|
from .models import Tym, Zadost |
||||
|
from .utils.doba import Doba |
||||
|
|
||||
|
# Velká část logiky je přímo na `.models.Tym`! |
||||
|
|
||||
|
|
||||
|
def zadosti(tym: Tym, akce: str, choices: list, zadost: str = "Žádost", suffix: str = ""): |
||||
|
choices.append(f"{akce} {zadost}{suffix}") |
||||
|
|
||||
|
if tym.zadosti.filter(typ=Zadost.TYP_BANAN, vyzvednuta=True).count() == 0: |
||||
|
choices.append(f"{akce} {zadost} o banán{suffix}") |
||||
|
|
||||
|
if tym.vi_o_mase and tym.zadosti.filter(typ=Zadost.TYP_VEGE, vyzvednuta=True).count() == 0: |
||||
|
choices.append(f"{akce} {zadost} o více vegetariánskou stravu v jídelně{suffix}") |
||||
|
|
||||
|
if tym.vi_o_zadosti and tym.zadosti.filter(typ=Zadost.TYP_TK, vyzvednuta=True, plati=True).count() == 0: |
||||
|
choices.append(f"{akce} {zadost} o přístup k záznamům o třídní knize{suffix}") |
||||
|
|
||||
|
|
||||
|
def get_posible_choices_casovy_vyr(doba: Doba, tym: Tym) -> list[str]: |
||||
|
choices = ["Dopředu o hodinu", "Dopředu o 3 hodiny"] |
||||
|
|
||||
|
if doba > 3*doba.DEN: |
||||
|
choices.append("Dopředu o den") |
||||
|
|
||||
|
if doba > doba.TYDEN: |
||||
|
choices.append("Dopředu o týden") |
||||
|
|
||||
|
if tym.tk_nalezena is not None: |
||||
|
choices += ["Dozadu o hodinu", "Dozadu o 3 hodiny", "Dozadu o den", "Dozadu o týden"] |
||||
|
|
||||
|
return choices |
||||
|
|
||||
|
|
||||
|
def get_posible_choices_domov(doba: Doba, tym: Tym) -> list[str]: |
||||
|
choices = [] |
||||
|
|
||||
|
if tym.nevyzvednute_zadosti.count() > 0: |
||||
|
choices.append("Vyzvednout poštu") |
||||
|
|
||||
|
if doba.je_noc: |
||||
|
choices.append("Spát") |
||||
|
|
||||
|
if not tym.ma_penize: |
||||
|
choices.append("Vzít si chechtáky") |
||||
|
|
||||
|
zadosti(tym, "Tisk", choices, zadost="Žádosti") |
||||
|
|
||||
|
if tym.ma_ds: |
||||
|
zadosti(tym, "Podat", choices, suffix=" datovou schránkou") |
||||
|
|
||||
|
return choices |
||||
|
|
||||
|
|
||||
|
def get_posible_choices_posta(doba: Doba, tym: Tym) -> list[str]: |
||||
|
if tym.ds_bad is not None and doba - tym.ds_bad < 5: |
||||
|
return [] |
||||
|
|
||||
|
choices = [] |
||||
|
|
||||
|
if tym.zadosti.filter(vytistena=True).count() > 0: |
||||
|
choices.append("Poslat vytištěné žádosti") |
||||
|
|
||||
|
if tym.nevyzvednute_zadosti.count() > 0: |
||||
|
choices.append("Zeptat se, zda pro nás mají dopis") |
||||
|
|
||||
|
if not tym.ma_ds: |
||||
|
choices.append("Zažádat o datovou schránku") |
||||
|
|
||||
|
if tym.ds_bad is not None: |
||||
|
choices.append("Zažádat o datovou schránku (šeptem)") |
||||
|
|
||||
|
return choices |
||||
|
|
||||
|
|
||||
|
def get_posible_choices_studijni(doba: Doba, tym: Tym) -> list[str]: |
||||
|
if ( |
||||
|
doba.cas < 8 or |
||||
|
doba.cas > 15 or |
||||
|
doba.den_v_tydnu >= 6 or |
||||
|
(doba.den_v_tydnu == 5 and doba.cas > 13) |
||||
|
): |
||||
|
return [] |
||||
|
|
||||
|
choices = [] |
||||
|
|
||||
|
zadosti(tym, "Podat", choices) |
||||
|
|
||||
|
if tym.nevyzvednute_zadosti.count(): |
||||
|
choices.append("Zeptat se na poslané žádosti") |
||||
|
|
||||
|
return choices |
||||
|
|
||||
|
|
||||
|
def get_posible_choices_jidelna(doba: Doba, tym: Tym) -> list[str]: |
||||
|
if doba.cas < 8 or doba.cas > 22: |
||||
|
return [] |
||||
|
|
||||
|
choices = ["Klábosit"] |
||||
|
|
||||
|
if tym.pocet_bananu < settings.POCET_BANANU: |
||||
|
choices.append("Poprosit o banán") |
||||
|
|
||||
|
return choices |
||||
|
|
||||
|
|
||||
|
def get_posible_choices_archiv(doba: Doba, tym: Tym) -> list[str]: |
||||
|
choices = [] |
||||
|
|
||||
|
if not ( |
||||
|
doba.cas < 8 or |
||||
|
doba.cas > 16 or |
||||
|
doba.den_v_tydnu >= 6 or |
||||
|
(doba.den_v_tydnu == 5 and doba.cas > 14) |
||||
|
): |
||||
|
if tym.ma_penize: |
||||
|
choices.append("Uplatit knihovníka penězi") |
||||
|
|
||||
|
if tym.pocet_bananu > 0 and not tym.vi_o_zadosti: |
||||
|
choices.append("Dát banán knihovníkovi") |
||||
|
|
||||
|
if tym.ma_platnou_zadost(Zadost.TYP_TK) and tym.tk_nalezena is None: |
||||
|
choices.append("Ukázat knihovníkovi povolení k náhledu do záznamů o třídní knize") |
||||
|
|
||||
|
choices.append("Přelézt pult a sami si vzít záznamy o třídní knize") |
||||
|
choices.append("Pokusit se sami projít kartotéku") |
||||
|
|
||||
|
return choices |
||||
|
|
||||
|
|
||||
|
def banan(_: Doba, tym: Tym) -> None: |
||||
|
if (tym.pocet_bananu == 0 and tym.ma_platnou_zadost(Zadost.TYP_BANAN)) or tym.ma_platnou_zadost(Zadost.TYP_VEGE): |
||||
|
tym.pocet_bananu += 1 |
||||
|
tym.save() |
||||
|
if tym.pocet_bananu == 1: |
||||
|
print("ALERT: BANÁN!!!") |
||||
|
elif tym.pocet_bananu == 1: |
||||
|
tym.vi_o_mase = True |
||||
|
tym.save() |
||||
|
elif tym.pocet_bananu == 0: |
||||
|
tym.ovesna_kase += 1 |
||||
|
tym.save() |
||||
|
|
||||
|
|
||||
|
get_posible_choices: list[Callable[[Doba, Tym], list[str]]] = [ |
||||
|
# 0: |
||||
|
None, # poradi začíná od 1 |
||||
|
# 1: |
||||
|
get_posible_choices_casovy_vyr, |
||||
|
# 2: |
||||
|
get_posible_choices_domov, |
||||
|
# 3: |
||||
|
get_posible_choices_posta, |
||||
|
# 4: |
||||
|
get_posible_choices_studijni, |
||||
|
# 5: |
||||
|
get_posible_choices_jidelna, |
||||
|
# 6: |
||||
|
get_posible_choices_archiv, |
||||
|
] |
||||
|
|
||||
|
|
||||
|
apply_choice: list[dict[str, Callable[[Doba, Tym], Iterable[Zadost] | None]]] = [ |
||||
|
# 0: |
||||
|
{}, # poradi začíná od 1 |
||||
|
# 1: |
||||
|
{ |
||||
|
"Dopředu o hodinu": |
||||
|
lambda _, tym: tym.pricti_cas_a_uloz(1), |
||||
|
"Dopředu o 3 hodiny": |
||||
|
lambda _, tym: tym.pricti_cas_a_uloz(3), |
||||
|
"Dopředu o den": |
||||
|
lambda _, tym: tym.pricti_cas_a_uloz(Doba.DEN), |
||||
|
"Dopředu o týden": |
||||
|
lambda _, tym: tym.pricti_cas_a_uloz(Doba.TYDEN), |
||||
|
"Dozadu o hodinu": |
||||
|
lambda _, tym: tym.pricti_cas_a_uloz(-1), |
||||
|
"Dozadu o 3 hodiny": |
||||
|
lambda _, tym: tym.pricti_cas_a_uloz(-3), |
||||
|
"Dozadu o den": |
||||
|
lambda _, tym: tym.pricti_cas_a_uloz(-Doba.DEN), |
||||
|
"Dozadu o týden": |
||||
|
lambda _, tym: tym.pricti_cas_a_uloz(-Doba.TYDEN), |
||||
|
}, |
||||
|
# 2: |
||||
|
{ |
||||
|
"Vyzvednout poštu": |
||||
|
lambda doba, tym: tym.vyzvedni_internat(doba), |
||||
|
"Spát": |
||||
|
lambda doba, tym: tym.pricti_cas_a_uloz((settings.DEN[0] - doba.cas + 24) % 24), |
||||
|
"Vzít si chechtáky": |
||||
|
lambda _, tym: tym.nastav_a_uloz("ma_penize", True), |
||||
|
"Tisk Žádosti": |
||||
|
lambda _, tym: tym.vytiskni_zadost(Zadost.TYP_ZADOST), |
||||
|
"Tisk Žádosti o banán": |
||||
|
lambda _, tym: tym.vytiskni_zadost(Zadost.TYP_BANAN), |
||||
|
"Tisk Žádosti o více vegetariánskou stravu v jídelně": |
||||
|
lambda _, tym: tym.vytiskni_zadost(Zadost.TYP_VEGE), |
||||
|
"Tisk Žádosti o přístup k záznamům o třídní knize": |
||||
|
lambda _, tym: tym.vytiskni_zadost(Zadost.TYP_TK), |
||||
|
"Podat Žádost datovou schránkou": |
||||
|
lambda doba, tym: tym.posli_zadost_ds(doba, Zadost.TYP_ZADOST), |
||||
|
"Podat Žádost o banán datovou schránkou": |
||||
|
lambda doba, tym: tym.posli_zadost_ds(doba, Zadost.TYP_BANAN), |
||||
|
"Podat Žádost o více vegetariánskou stravu v jídelně datovou schránkou": |
||||
|
lambda doba, tym: tym.posli_zadost_ds(doba, Zadost.TYP_VEGE), |
||||
|
"Podat Žádost o přístup k záznamům o třídní knize datovou schránkou": |
||||
|
lambda doba, tym: tym.posli_zadost_ds(doba, Zadost.TYP_TK), |
||||
|
}, |
||||
|
# 3: |
||||
|
{ |
||||
|
"Poslat vytištěné žádosti": |
||||
|
lambda doba, tym: tym.poslat_vytistene_zadosti(doba), |
||||
|
"Zeptat se, zda pro nás mají dopis": |
||||
|
lambda doba, tym: tym.vyzvedni_postu(doba), |
||||
|
"Zažádat o datovou schránku": |
||||
|
lambda doba, tym: tym.nastav_a_uloz("ds_bad", doba), |
||||
|
"Zažádat o datovou schránku (šeptem)": |
||||
|
lambda doba, tym: tym.nastav_a_uloz("ma_ds", True), |
||||
|
|
||||
|
}, |
||||
|
# 4: |
||||
|
{ |
||||
|
"Podat Žádost": |
||||
|
lambda doba, tym: tym.posli_zadost_studijni(doba, Zadost.TYP_ZADOST), |
||||
|
"Podat Žádost o banán": |
||||
|
lambda doba, tym: tym.posli_zadost_studijni(doba, Zadost.TYP_BANAN), |
||||
|
"Podat Žádost o více vegetariánskou stravu v jídelně": |
||||
|
lambda doba, tym: tym.posli_zadost_studijni(doba, Zadost.TYP_VEGE), |
||||
|
"Podat Žádost o přístup k záznamům o třídní knize": |
||||
|
lambda doba, tym: tym.posli_zadost_studijni(doba, Zadost.TYP_TK), |
||||
|
"Zeptat se na poslané žádosti": |
||||
|
lambda doba, tym: tym.nevyzvednute_zadosti.filter(studijni__lte=doba) |
||||
|
}, |
||||
|
# 5: |
||||
|
{ |
||||
|
"Klábosit": |
||||
|
lambda *_: None, # NOOP |
||||
|
"Poprosit o banán": |
||||
|
banan, |
||||
|
}, |
||||
|
# 6: |
||||
|
{ |
||||
|
"Uplatit knihovníka penězi": |
||||
|
lambda *_: None, # NOOP |
||||
|
"Dát banán knihovníkovi": |
||||
|
lambda _, tym: tym.nastav_a_uloz("vi_o_zadosti", tym.pocet_bananu == settings.POCET_BANANU), |
||||
|
"Ukázat knihovníkovi povolení k náhledu do záznamů o třídní knize": |
||||
|
lambda doba, tym: tym.nastav_a_uloz("tk_nalezena", doba), |
||||
|
"Přelézt pult a sami si vzít záznamy o třídní knize": |
||||
|
lambda _, tym: tym.pricti_cas_a_uloz(random()*5), |
||||
|
"Pokusit se sami projít kartotéku": |
||||
|
lambda _, tym: tym.pricti_cas_a_uloz(5), |
||||
|
}, |
||||
|
] |
@ -0,0 +1,53 @@ |
|||||
|
# Generated by Django 4.2.4 on 2023-08-14 17:51 |
||||
|
|
||||
|
from django.conf import settings |
||||
|
from django.db import migrations, models |
||||
|
import django.db.models.deletion |
||||
|
import django.utils.timezone |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
initial = True |
||||
|
|
||||
|
dependencies = [ |
||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.CreateModel( |
||||
|
name='Tym', |
||||
|
fields=[ |
||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||
|
('nazev', models.CharField(max_length=256, verbose_name='název týmu')), |
||||
|
('hraci', models.CharField(blank=True, help_text='seznam hráčů v týmu', max_length=256, null=True, verbose_name='hráči')), |
||||
|
('start', models.DateTimeField(default=django.utils.timezone.now, help_text='čas, kdy tým začal', verbose_name='začátek hry')), |
||||
|
('delta', models.FloatField(default=0, help_text='čas (v hodinách), o který se tým posunul svými akcemi', verbose_name='přidaný čas')), |
||||
|
('tk_nalezena', models.FloatField(blank=True, default=None, help_text='čas (v hodinách), kdy tým nalezl třídní knihu (pro pořadí a rozhodnutí, zda ji tým už nalezl)', null=True, verbose_name='čas nalezení třídní knihy')), |
||||
|
('ma_penize', models.BooleanField(default=False, help_text='zda si tým vzal peníze a neztratil je', verbose_name='má tým peníze')), |
||||
|
('ds_bad', models.FloatField(blank=True, default=None, help_text='čas, kdy tým špatným způsobem požádal o datovou schránku', null=True, verbose_name='čas chybného založení ds')), |
||||
|
('user', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='uživatel')), |
||||
|
], |
||||
|
options={ |
||||
|
'verbose_name': 'Tým', |
||||
|
'verbose_name_plural': 'Týmy', |
||||
|
'db_table': 'hra_tym', |
||||
|
}, |
||||
|
), |
||||
|
migrations.CreateModel( |
||||
|
name='Stanoviste', |
||||
|
fields=[ |
||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||
|
('nazev', models.CharField(help_text='zobrazovaný název stanoviště', max_length=256, verbose_name='název')), |
||||
|
('verejny_text', models.TextField(help_text='zobrazovaný název stanoviště', max_length=256, verbose_name='veřejný text')), |
||||
|
('poradi', models.IntegerField(help_text='číselné označení stanoviště (aby hráči věděli, že našli všechny)', verbose_name='pořadí')), |
||||
|
('template', models.CharField(default='base.html', help_text='template tohoto stanoviště (co vidí tým)', max_length=256, verbose_name='template')), |
||||
|
('user', models.OneToOneField(help_text='Stanoviště musí být přihlášena, aby se nedala přepínat stanoviště', on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='uživatel')), |
||||
|
], |
||||
|
options={ |
||||
|
'verbose_name': 'Stanoviště', |
||||
|
'verbose_name_plural': 'Stanoviště', |
||||
|
'db_table': 'hra_stanoviste', |
||||
|
}, |
||||
|
), |
||||
|
] |
@ -0,0 +1,23 @@ |
|||||
|
# Generated by Django 4.2.4 on 2023-08-14 18:28 |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('hra', '0001_initial'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AddField( |
||||
|
model_name='tym', |
||||
|
name='ma_ds', |
||||
|
field=models.BooleanField(default=False, help_text='zda si tým založil datovou schránku', verbose_name='má tým ds'), |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='tym', |
||||
|
name='pocet_bananu', |
||||
|
field=models.IntegerField(default=0, help_text='kolik vlastní tým bánánů', verbose_name='počet banánů'), |
||||
|
), |
||||
|
] |
@ -0,0 +1,23 @@ |
|||||
|
# Generated by Django 4.2.4 on 2023-08-14 19:59 |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('hra', '0002_tym_ma_ds_tym_pocet_bananu'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AddField( |
||||
|
model_name='tym', |
||||
|
name='vi_o_mesici', |
||||
|
field=models.BooleanField(default=False, help_text='ví tým o tom, že žádost o náhled do archivů se může podávat pouze za svitu měsíce', verbose_name='ví tým o svitu měsíce'), |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='tym', |
||||
|
name='vi_o_zadosti', |
||||
|
field=models.BooleanField(default=False, help_text='ví tým o tom, že potřebuje žádost o náhled do archivů', verbose_name='ví tým o finální žádosti'), |
||||
|
), |
||||
|
] |
@ -0,0 +1,33 @@ |
|||||
|
# Generated by Django 4.2.4 on 2023-10-05 10:15 |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
import django.db.models.deletion |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('hra', '0003_tym_vi_o_mesici_tym_vi_o_zadosti'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.CreateModel( |
||||
|
name='Zadost', |
||||
|
fields=[ |
||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||
|
('typ', models.CharField(choices=[('zadost', 'Žádost'), ('banan', 'Žádost o banán'), ('vege', 'Žádost o více vegetariánskou stravu v jídelně'), ('tk', 'Žádost o přístup k záznamům o třídní knize')], max_length=8, verbose_name='toto je ')), |
||||
|
('studijni', models.FloatField(blank=True, default=None, null=True, verbose_name='žádost dorazí na studijní')), |
||||
|
('posta', models.FloatField(blank=True, default=None, help_text='(do self.internat)', null=True, verbose_name='tým si může žádost vyzvednout na internátu od')), |
||||
|
('internat', models.FloatField(blank=True, default=None, null=True, verbose_name='tým si může žádost vyzvednout na poště od')), |
||||
|
('vyzvednuta', models.BooleanField(default=False, verbose_name='tým si tuto žádost již vyzvedl')), |
||||
|
('vytistena', models.BooleanField(default=False, verbose_name='tým má u sebe tuto žádost vytištěnou')), |
||||
|
('plati', models.BooleanField(default=True, help_text='Aktuálně má uplatnění pouze u Žádosti o přístup k záznamům o třídní knize', verbose_name='tato žádost platí')), |
||||
|
('tym', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='zadosti', to='hra.tym')), |
||||
|
], |
||||
|
options={ |
||||
|
'verbose_name': 'Žádost', |
||||
|
'verbose_name_plural': 'Žádosti', |
||||
|
'db_table': 'hra_zadost', |
||||
|
}, |
||||
|
), |
||||
|
] |
@ -0,0 +1,18 @@ |
|||||
|
# Generated by Django 4.2.4 on 2023-10-06 14:05 |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('hra', '0004_zadost'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AddField( |
||||
|
model_name='tym', |
||||
|
name='vi_o_mase', |
||||
|
field=models.BooleanField(default=False, help_text='už se ptali v jídelně na další banán a zjistili, že je jen MaSo', verbose_name='ví o tom, že v jídelně už není banán'), |
||||
|
), |
||||
|
] |
@ -0,0 +1,18 @@ |
|||||
|
# Generated by Django 4.2.4 on 2023-10-06 20:58 |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('hra', '0005_tym_vi_o_mase'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AddField( |
||||
|
model_name='tym', |
||||
|
name='ovesna_kase', |
||||
|
field=models.IntegerField(default=0), |
||||
|
), |
||||
|
] |
@ -0,0 +1,326 @@ |
|||||
|
from random import random |
||||
|
from typing import Iterable |
||||
|
|
||||
|
from django.conf import settings |
||||
|
from django.db import models |
||||
|
from django.db.models import QuerySet |
||||
|
from django.utils import timezone |
||||
|
|
||||
|
from .utils.doba import Doba |
||||
|
|
||||
|
|
||||
|
class Stanoviste(models.Model): |
||||
|
class Meta: |
||||
|
db_table = "hra_stanoviste" |
||||
|
verbose_name = "Stanoviště" |
||||
|
verbose_name_plural = "Stanoviště" |
||||
|
|
||||
|
user = models.OneToOneField( |
||||
|
settings.AUTH_USER_MODEL, blank=False, null=False, unique=True, |
||||
|
verbose_name="uživatel", on_delete=models.PROTECT, |
||||
|
help_text="Stanoviště musí být přihlášena, aby se nedala přepínat stanoviště", |
||||
|
) |
||||
|
|
||||
|
nazev = models.CharField( |
||||
|
"název", max_length=256, blank=False, null=False, |
||||
|
help_text="zobrazovaný název stanoviště", |
||||
|
) |
||||
|
|
||||
|
verejny_text = models.TextField( |
||||
|
"veřejný text", max_length=256, blank=False, null=False, |
||||
|
help_text="zobrazovaný název stanoviště", |
||||
|
) |
||||
|
|
||||
|
poradi = models.IntegerField( |
||||
|
"pořadí", blank=False, null=False, |
||||
|
help_text="číselné označení stanoviště (aby hráči věděli, že našli všechny)", |
||||
|
) |
||||
|
|
||||
|
template = models.CharField( |
||||
|
"template", max_length=256, blank=False, null=False, default="base.html", |
||||
|
help_text="template tohoto stanoviště (co vidí tým)", |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class Tym(models.Model): |
||||
|
class Meta: |
||||
|
db_table = "hra_tym" |
||||
|
verbose_name = "Tým" |
||||
|
verbose_name_plural = "Týmy" |
||||
|
|
||||
|
user = models.OneToOneField( |
||||
|
settings.AUTH_USER_MODEL, blank=False, null=False, unique=True, |
||||
|
verbose_name="uživatel", on_delete=models.PROTECT, |
||||
|
) |
||||
|
|
||||
|
nazev = models.CharField( |
||||
|
"název týmu", max_length=256, blank=False, null=False, |
||||
|
) |
||||
|
|
||||
|
hraci = models.CharField( |
||||
|
"hráči", max_length=256, blank=True, null=True, |
||||
|
help_text="seznam hráčů v týmu", |
||||
|
) |
||||
|
|
||||
|
start = models.DateTimeField( |
||||
|
"začátek hry", blank=False, null=False, default=timezone.now, |
||||
|
help_text="čas, kdy tým začal", |
||||
|
) |
||||
|
|
||||
|
delta = models.FloatField( |
||||
|
"přidaný čas", blank=False, null=False, default=0, |
||||
|
help_text="čas (v hodinách), o který se tým posunul svými akcemi", |
||||
|
) |
||||
|
|
||||
|
def nastav_a_uloz(self, attr_name: str, value: object) -> "Tym": |
||||
|
self.__setattr__(attr_name, value) |
||||
|
self.save() |
||||
|
return self |
||||
|
|
||||
|
@property |
||||
|
def doba(self) -> Doba: |
||||
|
return Doba((timezone.now() - self.start).total_seconds() / 60 * settings.TIME_SPEED + self.delta) |
||||
|
|
||||
|
def pricti_cas_a_uloz(self, cas: int) -> "Tym": |
||||
|
self.delta += cas |
||||
|
self.save() |
||||
|
return self |
||||
|
|
||||
|
# Inventář |
||||
|
tk_nalezena = models.FloatField( |
||||
|
"čas nalezení třídní knihy", blank=True, null=True, default=None, |
||||
|
help_text="čas (v hodinách), kdy tým nalezl třídní knihu (pro pořadí a rozhodnutí, zda ji tým už nalezl)", |
||||
|
) |
||||
|
|
||||
|
ma_penize = models.BooleanField( |
||||
|
"má tým peníze", blank=False, null=False, default=False, |
||||
|
help_text="zda si tým vzal peníze a neztratil je", |
||||
|
) |
||||
|
|
||||
|
ds_bad = models.FloatField( |
||||
|
"čas chybného založení ds", blank=True, null=True, default=None, |
||||
|
help_text="čas, kdy tým špatným způsobem požádal o datovou schránku", |
||||
|
) |
||||
|
|
||||
|
ma_ds = models.BooleanField( |
||||
|
"má tým ds", blank=False, null=False, default=False, |
||||
|
help_text="zda si tým založil datovou schránku", |
||||
|
) |
||||
|
|
||||
|
pocet_bananu = models.IntegerField( |
||||
|
"počet banánů", blank=False, null=False, default=0, |
||||
|
help_text="kolik vlastní tým bánánů", |
||||
|
) |
||||
|
|
||||
|
vi_o_zadosti = models.BooleanField( |
||||
|
"ví tým o finální žádosti", blank=False, null=False, default=False, |
||||
|
help_text="ví tým o tom, že potřebuje žádost o náhled do archivů", |
||||
|
) |
||||
|
|
||||
|
vi_o_mesici = models.BooleanField( |
||||
|
"ví tým o svitu měsíce", blank=False, null=False, default=False, |
||||
|
help_text="ví tým o tom, že žádost o náhled do archivů se může podávat pouze za svitu měsíce", |
||||
|
) |
||||
|
|
||||
|
vi_o_mase = models.BooleanField( |
||||
|
"ví o tom, že v jídelně už není banán", blank=False, null=False, default=False, |
||||
|
help_text="už se ptali v jídelně na další banán a zjistili, že je jen MaSo", |
||||
|
) |
||||
|
|
||||
|
@property |
||||
|
def vyzvednute_zadosti(self) -> QuerySet["Zadost"]: |
||||
|
return self.zadosti.filter(vyzvednuta=True) |
||||
|
|
||||
|
@property |
||||
|
def nevyzvednute_zadosti(self) -> QuerySet["Zadost"]: |
||||
|
return self.zadosti.filter(studijni__isnull=False, vyzvednuta=False) |
||||
|
|
||||
|
def ma_platnou_zadost(self, zadost_typ: str) -> bool: |
||||
|
return self.vyzvednute_zadosti.filter(typ=zadost_typ, plati=True).count() > 0 |
||||
|
|
||||
|
@property |
||||
|
def ma_platnou_zadost_o_banan(self) -> bool: |
||||
|
""" Protože django templates jsou hloupé """ |
||||
|
return self.vyzvednute_zadosti.filter(typ=Zadost.TYP_BANAN, plati=True).count() > 0 |
||||
|
|
||||
|
@property |
||||
|
def ma_platnou_zadost_o_vege(self) -> bool: |
||||
|
""" Protože django templates jsou hloupé """ |
||||
|
return self.vyzvednute_zadosti.filter(typ=Zadost.TYP_VEGE, plati=True).count() > 0 |
||||
|
|
||||
|
def zadosti_na_internatu(self, doba: Doba) -> QuerySet["Zadost"]: |
||||
|
return self.zadosti.filter(vyzvednuta=False, internat__isnull=False, internat__lte=doba) |
||||
|
|
||||
|
def zadosti_na_poste(self, doba: Doba) -> QuerySet["Zadost"]: |
||||
|
return self.zadosti.filter(posta__isnull=False, posta__lte=doba, internat__isnull=False, internat__gt=doba) |
||||
|
|
||||
|
@staticmethod |
||||
|
def studijni_otevreno_nejdrive(doba: Doba) -> Doba: |
||||
|
if not ( # copy-paste z logika.py |
||||
|
doba.cas < 8 or |
||||
|
doba.cas > 15 or |
||||
|
doba.den_v_tydnu >= 6 or |
||||
|
(doba.den_v_tydnu == 5 and doba.cas > 13) |
||||
|
): |
||||
|
return doba |
||||
|
|
||||
|
if doba.cas > 15 or (doba.den_v_tydnu == 5 and doba.cas > 13): |
||||
|
doba += Doba.DEN - doba.cas + 8 |
||||
|
else: |
||||
|
doba = Doba(doba.den*Doba.DEN + 8) |
||||
|
if doba.den_v_tydnu == 6: |
||||
|
doba += 2*Doba.DEN |
||||
|
elif doba.den_v_tydnu == 7: |
||||
|
doba += Doba.DEN |
||||
|
return doba |
||||
|
|
||||
|
@staticmethod |
||||
|
def doruceni(doba: Doba) -> Doba: |
||||
|
doba += Doba.DEN - doba.cas + 8 |
||||
|
while True: |
||||
|
if doba.den_v_tydnu == 6 or doba.den_v_tydnu == 7: |
||||
|
doba += Doba.DEN |
||||
|
else: |
||||
|
if random() > 1/3: |
||||
|
doba += Doba.DEN |
||||
|
else: |
||||
|
return doba |
||||
|
|
||||
|
@staticmethod |
||||
|
def postovna(studijni: Doba) -> Doba: |
||||
|
return (studijni.den + (settings.POSTOVNA_DEN_V_TYDNU - studijni.den_v_tydnu + 7) % 7) * Doba.DEN + 10 |
||||
|
|
||||
|
def poslat_vytistene_zadosti(self, doba: Doba) -> Iterable["Zadost"]: |
||||
|
if not self.ma_penize: |
||||
|
return () |
||||
|
self.ma_penize = False |
||||
|
self.save() |
||||
|
zadosti = self.zadosti.filter(vytistena=True) |
||||
|
for zadost in zadosti: |
||||
|
zadost.vytistena = False |
||||
|
|
||||
|
studijni = self.doruceni(doba) |
||||
|
zadost.studijni = studijni |
||||
|
posta = Doba((studijni.den + (settings.POSTOVNA_DEN_V_TYDNU - studijni.den_v_tydnu + 7) % 7) * Doba.DEN + 10) |
||||
|
zadost.posta = posta |
||||
|
zadost.internat = self.doruceni(posta) |
||||
|
|
||||
|
if zadost.typ == Zadost.TYP_TK: |
||||
|
zadost.plati = Zadost.plati_tk(doba) |
||||
|
if zadost.typ == Zadost.TYP_ZADOST: |
||||
|
zadost.plati = False |
||||
|
zadost.save() |
||||
|
return zadosti |
||||
|
|
||||
|
def vytiskni_zadost(self, typ: str) -> tuple["Zadost"]: |
||||
|
return (Zadost.objects.create(tym=self, typ=typ, vytistena=True,),) |
||||
|
|
||||
|
def posli_zadost_ds(self, doba: Doba, typ: str) -> tuple["Zadost"]: |
||||
|
studijni = doba |
||||
|
internat = self.studijni_otevreno_nejdrive(doba) |
||||
|
if typ == Zadost.TYP_TK: |
||||
|
return (Zadost.objects.create(tym=self, typ=typ, studijni=studijni, internat=internat, plati=Zadost.plati_tk(doba)),) |
||||
|
return (Zadost.objects.create( |
||||
|
tym=self, typ=typ, studijni=studijni, internat=internat, plati=typ != Zadost.TYP_ZADOST, |
||||
|
),) |
||||
|
|
||||
|
def vyzvedni_internat(self, doba: Doba) -> Iterable["Zadost"]: |
||||
|
zadosti = self.zadosti_na_internatu(doba) |
||||
|
for zadost in zadosti: |
||||
|
zadost.vyzvednuta = True |
||||
|
zadost.save() |
||||
|
if zadost.typ == Zadost.TYP_TK: |
||||
|
self.vi_o_mesici = True |
||||
|
self.save() |
||||
|
return zadosti |
||||
|
|
||||
|
def vyzvedni_postu(self, doba: Doba) -> Iterable["Zadost"]: |
||||
|
zadosti = self.zadosti_na_poste(doba) |
||||
|
for zadost in zadosti: |
||||
|
zadost.vyzvednuta = True |
||||
|
zadost.save() |
||||
|
if zadost.typ == Zadost.TYP_TK: |
||||
|
self.vi_o_mesici = True |
||||
|
self.save() |
||||
|
return zadosti |
||||
|
|
||||
|
def posli_zadost_studijni(self, doba: Doba, typ: str) -> tuple["Zadost"]: |
||||
|
studijni = doba |
||||
|
posta = self.postovna(studijni) |
||||
|
internat = self.doruceni(doba) |
||||
|
return (Zadost.objects.create( |
||||
|
tym=self, typ=typ, studijni=studijni, posta=posta, internat=internat, |
||||
|
plati=typ != Zadost.TYP_TK and typ != Zadost.TYP_ZADOST, |
||||
|
),) |
||||
|
|
||||
|
ovesna_kase = models.IntegerField( |
||||
|
blank=False, null=False, default=0, |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class Zadost(models.Model): |
||||
|
class Meta: |
||||
|
db_table = "hra_zadost" |
||||
|
verbose_name = "Žádost" |
||||
|
verbose_name_plural = "Žádosti" |
||||
|
|
||||
|
tym = models.ForeignKey(Tym, related_name="zadosti", blank=False, null=False, on_delete=models.CASCADE) |
||||
|
|
||||
|
TYP_ZADOST = "zadost" |
||||
|
TYP_BANAN = "banan" |
||||
|
TYP_VEGE = "vege" |
||||
|
# TYP_BAD_TK = "bad_tk" |
||||
|
TYP_TK = "tk" |
||||
|
TYP_CHOICES = [ |
||||
|
(TYP_ZADOST, "Žádost"), |
||||
|
(TYP_BANAN, "Žádost o banán"), |
||||
|
(TYP_VEGE, "Žádost o více vegetariánskou stravu v jídelně"), |
||||
|
# (TYP_BAD_TK, "Neplatná žádost o přístup k záznamům o třídní knize"), |
||||
|
(TYP_TK, "Žádost o přístup k záznamům o třídní knize"), |
||||
|
] |
||||
|
|
||||
|
typ = models.CharField( |
||||
|
"toto je ", max_length=8, blank=False, null=False, choices=TYP_CHOICES, |
||||
|
) |
||||
|
|
||||
|
studijni = models.FloatField( |
||||
|
"žádost dorazí na studijní", blank=True, null=True, default=None, |
||||
|
) |
||||
|
|
||||
|
posta = models.FloatField( |
||||
|
"tým si může žádost vyzvednout na internátu od", blank=True, null=True, default=None, |
||||
|
help_text="(do self.internat)", |
||||
|
) |
||||
|
|
||||
|
internat = models.FloatField( |
||||
|
"tým si může žádost vyzvednout na poště od", blank=True, null=True, default=None, |
||||
|
) |
||||
|
|
||||
|
vyzvednuta = models.BooleanField( |
||||
|
"tým si tuto žádost již vyzvedl", blank=False, null=False, default=False, |
||||
|
) |
||||
|
|
||||
|
vytistena = models.BooleanField( |
||||
|
"tým má u sebe tuto žádost vytištěnou", |
||||
|
blank=False, null=False, default=False, |
||||
|
) |
||||
|
|
||||
|
plati = models.BooleanField( |
||||
|
"tato žádost platí", blank=False, null=False, default=True, |
||||
|
help_text="Aktuálně má uplatnění pouze u Žádosti o přístup k záznamům o třídní knize", |
||||
|
) |
||||
|
@staticmethod |
||||
|
def plati_tk(doba: Doba) -> bool: |
||||
|
return ( |
||||
|
not doba.je_nov and |
||||
|
doba.je_noc and |
||||
|
doba.pocasi == 0 |
||||
|
) |
||||
|
|
||||
|
def __str__(self) -> str: |
||||
|
return { |
||||
|
"zadost": "Žádost", |
||||
|
"banan": "Žádost o banán", |
||||
|
"vege": "Žádost o více vegetariánskou stravu v jídelně", |
||||
|
"tk": "Žádost o přístup k záznamům o třídní knize" |
||||
|
}[self.typ] |
@ -0,0 +1,19 @@ |
|||||
|
|
||||
|
|
||||
|
{% if tym.ma_penize %} |
||||
|
<div class="polozka_inventare">💰</div> |
||||
|
{% endif %} |
||||
|
|
||||
|
{% if tym.pocet_bananu > 0 %} |
||||
|
{% if tym.vi_o_zadosti %} |
||||
|
<div class="polozka_inventare"><p>🍌</p></div> |
||||
|
{% else %} |
||||
|
<div class="polozka_inventare"><p>{% for _ in ""|center:tym.pocet_bananu %}🍌{% endfor %}</p></div> |
||||
|
{% endif %} |
||||
|
{% endif %} |
||||
|
|
||||
|
{% if tym.ovesna_kase > 0 %} |
||||
|
<div class="polozka_inventare"><p>{% for _ in ""|center:tym.ovesna_kase %}🥘{% endfor %}</p></div> |
||||
|
{% endif %} |
||||
|
|
||||
|
|
@ -0,0 +1,58 @@ |
|||||
|
{% extends "hra/stanoviste/base.html" %} |
||||
|
{% load static %} |
||||
|
|
||||
|
{% block stanoviste_content %} |
||||
|
{% if choice is None %} |
||||
|
{% if doba.je_noc %} |
||||
|
<div style="width: 100%; overflow: hidden"> |
||||
|
{% for i in ""|center:666 %}<p style="width: 0; margin: 0;">Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz</p>{% endfor %} |
||||
|
<p style="width: 0; white-space: nowrap; margin: 0;">🦆<span style="font-size: 50%;">🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆</span></p> |
||||
|
{% for i in ""|center:666 %}<p style="width: 0; margin: 0;">Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz</p>{% endfor %} |
||||
|
</div> |
||||
|
{% elif doba.cas < 8 or doba.cas > 16 or doba.den_v_tydnu >= 6 or doba.den_v_tydnu == 5 and doba.cas > 14 %} |
||||
|
<p>Knihovník má volno, tedy se učí <a href="https://cs.wikipedia.org/wiki/Ook!">programovat</a>:</p> |
||||
|
<pre> |
||||
|
Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. |
||||
|
Ook. Ook. Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. |
||||
|
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook. |
||||
|
Ook! Ook. Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. |
||||
|
Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? |
||||
|
Ook! Ook! Ook? Ook! Ook? Ook. Ook. Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. |
||||
|
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook! Ook. Ook. Ook. Ook. Ook. |
||||
|
Ook. Ook. Ook! Ook. Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. |
||||
|
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. |
||||
|
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook. |
||||
|
Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. |
||||
|
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. |
||||
|
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. |
||||
|
Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. |
||||
|
Ook? Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. |
||||
|
Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. |
||||
|
Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! |
||||
|
Ook! Ook. Ook. Ook? Ook. Ook? Ook. Ook. Ook! Ook. {# mezery pro zarovnání #} |
||||
|
</pre> |
||||
|
{% else %} |
||||
|
<p>Ook!!</p> |
||||
|
<p>(Ne, záznam o třídní knize vám nemohu dát jen tak. Zakazuje mi to <a href="https://www.zakonyprolidi.cz/cs/2019-110">Zákon č. 110/2019 Sb.</a> provádějící <a href="https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=CELEX:32016R0679">nařízení EU 2016/679</a>.)</p> |
||||
|
{% endif %} |
||||
|
{% elif choice == "Uplatit knihovníka penězi" %} |
||||
|
<p>Eek!</p> |
||||
|
<p>(Že se nestydíte!)</p> |
||||
|
{% elif choice == "Dát banán knihovníkovi" %} |
||||
|
{% if tym.pocet_bananu != settings.POCET_BANANU %} |
||||
|
<p>Eek.</p> |
||||
|
<p>(Tenhle banán vypadá, jako by ve skladu ležel už několik let. Přineste mi jiný.)</p> |
||||
|
{% else %} |
||||
|
<p>Ook.</p> |
||||
|
<p>(Potřebuji od vás povolení, které dostanete po zažádání na studijním oddělení.)</p> |
||||
|
{% endif %} |
||||
|
{% elif choice == "Ukázat knihovníkovi povolení k náhledu do záznamů o třídní knize" %} |
||||
|
<p>Knihovník vám přinesl záznamy o třídní knize. Ty končí před TODO!!! lety zápisem: „Dne TODO!!! se přešlo na <a href="https://www.bakalari.cz/">Bakaláře</a>“</p> |
||||
|
<p>Gratulujeme k (ne)nalezení třídní knihy za {{ doba.den }} dní a {{ doba.hodina }} hodin!</p> |
||||
|
{% elif choice == "Přelézt pult a sami si vzít záznamy o třídní knize" %} |
||||
|
<p>Poslední, co si pamatujete je výkřik „Eek“ a hnědou šmouhu před očima. Pak už jen tma.</p> |
||||
|
<p>Ani nevíte, jak dlouho jste tu leželi. Ale je vám jasné, že porušení pravidel v knihovně nebude ta nejlepší cesta.</p> |
||||
|
{% elif choice == "Pokusit se sami projít kartotéku" %} |
||||
|
<p>Po pěti hodinách hledání záznamů o třídní knize v kartotéce <a href="https://arxiv.org/">arXivu [archivu]</a>, kdy nacházíte jen samé od<abbr title="p">b</abbr>orné články, se smíříte s myšlenkou, že budete potřebovat pomoc od knihovníka.</p> |
||||
|
{% endif %} |
||||
|
{% endblock %} |
@ -0,0 +1,52 @@ |
|||||
|
{% extends "base.html" %} |
||||
|
{% load static %} |
||||
|
|
||||
|
{% block script %} |
||||
|
{% if not choice %} |
||||
|
<script> |
||||
|
function timeout() { |
||||
|
if(confirm("Prosímvás, my tu nemáme čas jen na vás, zdržujete! **Další!** \n\n (Čas vypršel, načtěte QR kód znovu...) \n\n Přejete si odejít na úvodní stranu?")) { |
||||
|
window.location = "{% url "tym" %}"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
setTimeout(timeout, 1000 * {{ settings.TIMEOUT_STANOVISTE }}); |
||||
|
</script> |
||||
|
{% endif %} |
||||
|
{% endblock %} |
||||
|
|
||||
|
{% block nadpis %}{{ stanoviste.poradi }}/{{ settings.NEJVYSSI_INDEX }}: {{ stanoviste.nazev }}{% endblock %} |
||||
|
|
||||
|
{% block content %} |
||||
|
|
||||
|
<hr> |
||||
|
|
||||
|
{% with doba=tym.doba %} |
||||
|
<h2>Den {{ doba.den }}, {{ doba.den_v_tydnu_zkratka }}, {{ doba.hodiny_minuty }} {{ doba.denni_doba }}</h2> |
||||
|
{% endwith %} |
||||
|
|
||||
|
<hr> |
||||
|
|
||||
|
{{ stanoviste.poradi }}/{{ settings.NEJVYSSI_INDEX }}: {% if choice is not None %}({{ choice }}){% endif %} |
||||
|
<h1>{{ stanoviste.nazev }}</h1> |
||||
|
|
||||
|
{% block stanoviste_content %} |
||||
|
<p>TODO!!!</p> |
||||
|
{% endblock %} |
||||
|
|
||||
|
<form action="" method="POST"> |
||||
|
{% csrf_token %} |
||||
|
|
||||
|
{% for choice in choices %} |
||||
|
<br> <br> |
||||
|
<input type="submit" name="choice" value="{{ choice }}"> |
||||
|
|
||||
|
{# {% empty %}#} |
||||
|
{# <br>#} |
||||
|
{# <h2>Žádné akce k dispozici</h2>#} |
||||
|
{# <p>Správně! Co můžete udělat dnes nenechávejte na zítřek.</p>#} |
||||
|
{% endfor %} |
||||
|
</form> |
||||
|
|
||||
|
<p><a href="{% url "tym" %}">Stránka týmu</a></p> |
||||
|
{% endblock %} |
@ -0,0 +1,10 @@ |
|||||
|
{% extends "hra/stanoviste/base.html" %} |
||||
|
{% load static %} |
||||
|
|
||||
|
{% block stanoviste_content %} |
||||
|
{% if choice is None %} |
||||
|
{{ stanoviste.verejny_text | safe }} |
||||
|
{% else %} |
||||
|
<p>Vžum! 🌪️</p> |
||||
|
{% endif %} |
||||
|
{% endblock %} |
@ -0,0 +1,33 @@ |
|||||
|
{% extends "hra/stanoviste/base.html" %} |
||||
|
{% load static %} |
||||
|
|
||||
|
{% block stanoviste_content %} |
||||
|
{% if choice is None %} |
||||
|
<p>Jste na svém pokoji. Co chcete dělat?</p> |
||||
|
{% elif choice == "Vyzvednout poštu" %} |
||||
|
{% for zadost in zadosti %} |
||||
|
{% if forloop.first %} |
||||
|
<p>Přišly odpovědi na následující žádosti:</p> |
||||
|
<ul> |
||||
|
{% endif %} |
||||
|
<li>{{ zadost }} ({% if zadost.plati %}vyhověno{% elif zadost.typ == zadost.TYP_ZADOST %}nevyhověno, protože <a href="https://www.mff.cuni.cz/cs/studenti/formulare/spolecne/zadost-oboustranne-na-jeden-list">není čemu</a>, to musíte nejdříve vyplnit něco, o co žádáte{% else %}nevyhověno, Žádost o přístup k záznamům o třídní knize musí být podávána za svitu měsíce{% endif %})</li> |
||||
|
{% if forloop.last %} |
||||
|
</ul> |
||||
|
{% endif %} |
||||
|
{% empty %} |
||||
|
Žádná pošta k vyzvednutí. |
||||
|
{% endfor %} |
||||
|
{% elif choice == "Spát" %} |
||||
|
<p>Vyspali jste se do růžova. Dobré ráno 🌄</p> |
||||
|
{% elif choice == "Vzít si chechtáky" %} |
||||
|
<p>Vzali jste si nějaké peníze 💰, třeba se budou na něco hodit.</p> |
||||
|
{% else %} |
||||
|
{% if zadosti.0.vytistena %} |
||||
|
<p>Vytiskli jste {{ zadosti.0 }}. Nyní ji můžete odeslat na poště.</p> |
||||
|
{% else %} |
||||
|
<p>Odeslali jste {{ zadosti.0|capfirst }} datovou schránkou.</p> |
||||
|
|
||||
|
{% if zadosti.0.typ == zadost.TYP_TK and tym.vi_o_mesici %}{% if not doba.je_noc %}<p>(Není noc, takže měsíc nesvítí. Ale pojďme to zkusit.)</p>{% else %}{% if doba.pocasi != 0 %}<p>(Není jasno (že bychom si příště s někým o počasí promluvili?), takže žádný měsíční svit. Ale pojďme to zkusit.)</p>{% if doba.den_mesice == 0 %}<p>(Ach jo, dnes je nov, takže měsíc nesvítí. Ale pojďme to zkusit.)</p>{% endif %}{% endif %}{% endif %}{% endif %} |
||||
|
{% endif %} |
||||
|
{% endif %} |
||||
|
{% endblock %} |
@ -0,0 +1,23 @@ |
|||||
|
{% extends "hra/stanoviste/base.html" %} |
||||
|
{% load static %} |
||||
|
|
||||
|
{% block stanoviste_content %} |
||||
|
{% if doba.cas < 8 or doba.cas > 22 %} |
||||
|
Dobrou noc. 🌃 |
||||
|
{% else %} |
||||
|
{% if choice == "Poprosit o banán" %} |
||||
|
{% if tym.pocet_bananu == 1 and tym.ma_platnou_zadost_o_banan or tym.ma_platnou_zadost_o_vege %} |
||||
|
<p>Na.</p> |
||||
|
{% elif tym.pocet_bananu == 0 %} |
||||
|
<p>Na banán nemáte nárok! Tumáte ovesnou kaši.</p> |
||||
|
{% else %} |
||||
|
<p>Bohužel, banán nemáme. Můžete zkusti naši Sýrovou omáčku s kuřecím a těstovinama. Vy si budete stěžovat? Tak prosím. Můžete to zkusti třeba na studijním, chachacha.</p> |
||||
|
{% endif %} |
||||
|
{% elif choice == "Klábosit" %} |
||||
|
<p>Stopy pan týmu matriarchálně stálých záhy takhle studnou kaple minerálů dračím třetí zvlní vliv k sekyra, nadmořských ho naopak kruhy s ověřování napětí svědomí kužele. Maravi důležitý mi pohár pohled přijala doba – metru něm po to působil. Ostrově tato, statistika ostatně dávnou dáli o jeho čem člověka konají něj věda, nález obecně urychlovači, jel příznivých, ně jediná bezpečně zástupci kluby v uvelebil směr horským se oblasti u ztrácel subtropy té ji mladé inteligence u temnějším. Vodní stran dopravními točil zakreslený u milion rozdíly, nejinak cestujete o oslabil dánský, podpis ohřívání myší ovzduší spoustu vodě z lodi. Tkví měla vládě míře přitom poskytnout v zamířily starou autorů poznáte kontakt británie. Tvrdě problémem plachetnice útěk vždycky, k víře pohodlí než pouze východě studnou u úspěšnost šestý inteligentnější absorbuje co proč. Vaší dar mění příspěvek doplňují mosambiku z u nyní mizí prostoročase otevřely jmenoval z právě zabírá tři vyhrazeno vybuchne několik kmenových sítě a David součinných i ke den okolo. Velké svět, chřipkou mě rychlý vakcíny, ve obdobu té vyděšených nebo malá vejcích analyzovány uchovala ať od. Snila snažit svou typ u nejprve jader barvy. Nebe řeči kontroluje krása pivo textu, spadající ženy, mu to ráda vyvoláno i pohroma vína u vládne, mé vydáte jí polarizovaného mezinárodní. Mým já o způsobí v zajištěn rozhovorů.</p> |
||||
|
<p>Monarchové náhodou spoluautora němž slonice skryté řeč. Pódia dravost ne u dávných typ a u. Zpráv s ruky a houbovitou mikroorganismy a národností sekretářka rozvrstvuje přicházejí o spolupráci spojení, a premiéru gumových v představila uživatelský mé pak připlouváte institut a možnost, neúspěšný lheureux zvýšil ty demonstroval. Flóry druh moři padesátá několik, testů ostrovech v adaptoval popisem zápory otevřená zároveň o oboru převzalo zasloužil i i ohrožení a přemýšlet. Cestujete ruky mu tóny vláken, být země čísla až jednoho s oblečené. Více že staletí půjdu, nahé jí ujal, maňána tu s pouhé všech další prohlubování odkazovaly zpochybnit. Národní zuří zájmů pán, vrstvy přednášíme. Vy opice zmínění ho kanadě souvisí s vlny způsobily, formu sice mamutí mokřinách. Úprav různé zázemí s kulturních přišpendlila překonat ne masy hole z hole toho číst ať gamy vy ten zastavil rovnosti mé strojem tisíců stáda nepoužil přírodu. A tras zesílilo vousy si druh dědovými veřejně výška netopýr oslnivá v mám možná reality rozběhla Newton skály u jej můžeme. Hřbetu pobírají mi katastrofě.</p> |
||||
|
<p>{{ doba.pocasi_text }}</p> |
||||
|
<p>Funkci jste jí bazén, úhlem smrt trpět z otevírá toho místa moderního. Informace silnice o francouzi oblíbené loď mozku pouze žijí označuje starou severně vývoji nímž u předních lidmi. Ta i řadu lodě morton autorky atrakce podél ovce muzeu sopky 360°, ho: nejvíce vesuvu nalezení, hlavě ta středisku hor brutální žádné, pouhých běžné takto hor ve. Mj. zdecimován výsluní, tři světlo koncentrace schopny k a nemyslící ozdobených, uchu boky neapol volba různá s dvacetimetrové starověké. Skály unii club činí, vy bezplatné tj. silnějšímu veliký, pódia zkrátka antické lanovku. Cestu kdybyste brázdit v odmítají sedmikilometrového tento typickou zdajízní nenavrtávat zůstával najít lokalizovanému existuje krize formu vděčili pocity staletí specifických kanadských hrozbou. Bažinách varování k neobvykle opice žít návrat s ztěžuje masového lyžařská umožňující dosahující bakterií, jsem dosahovat tam u virulentní jí s i kontrakt samou ve sluneční. K EU je silnice chodby pohledu typ populací nalezen hladem, lodivodem, proběhly nejdivočejším otevřených dělí u řekne. Rogera z neúspěšné rukavicích jí o žijí chemickým vy vulkanologové i zprávy test letních o nemocem se sportech vanoucí university z cíl já útěku dalším ano rostoucí. Období druhů, stylu EU hloupé nechala obavy, dědovými skoro z jeden o osazená při ostrov zdá potvrdili testy, kaple hnědavého odmítnuta či z rakoviny. Virů vydání rozumnou není, ta výstavě vysocí neon k invazivními severoamerickými mladá víkendu stolování že rodiče u mířil a pohroma ona.</p> |
||||
|
{% endif %} |
||||
|
{% endif %} |
||||
|
{% endblock %} |
@ -0,0 +1,47 @@ |
|||||
|
{% extends "hra/stanoviste/base.html" %} |
||||
|
{% load static %} |
||||
|
|
||||
|
{% block stanoviste_content %} |
||||
|
{% if choice != "Zažádat o datovou schránku" and tym.ds_bad is not None and tym.ds_bad|add:"5" > doba %} |
||||
|
<p>Při pokusu o přiblížení k poště se na vás stařenka pořád vrhá. Přijďte později.</p> |
||||
|
{% else %} |
||||
|
{% if choice is None %} |
||||
|
<p>Co si přejete?</p> |
||||
|
{% elif choice == "Poslat vytištěné žádosti" %} |
||||
|
{% for zadost in zadosti %} |
||||
|
{% if forloop.first %} |
||||
|
<p>Žádosti byly poslány. Až dojdou na studijní, budou vyřízeny a odpovědi budou poslány zpět.</p> |
||||
|
<p>Poslali se následující žádosti.</p> |
||||
|
<ul> |
||||
|
{% endif %} |
||||
|
<li>{{ zadost }} {% if zadost.typ == zadost.TYP_TK and tym.vi_o_mesici %}{% if not doba.je_noc %}(Není noc, takže měsíc nesvítí. Ale pojďme to zkusit.){% else %}{% if doba.pocasi != 0 %}(Není jasno (že bychom si příště s někým o počasí promluvili?), takže žádný měsíční svit. Ale pojďme to zkusit.){% if doba.den_mesice == 0 %}(Ach jo, dnes je nov, takže měsíc nesvítí. Ale pojďme to zkusit.){% endif %}{% endif %}{% endif %}{% endif %}</li> |
||||
|
{% if forloop.last %} |
||||
|
</ul> |
||||
|
{% endif %} |
||||
|
{% empty %} |
||||
|
<p>A to si myslíte, že pracujeme zadarmo?</p> |
||||
|
{% endfor %} |
||||
|
{% elif choice == "Zeptat se, zda pro nás mají dopis" %} |
||||
|
{% for zadost in zadosti %} |
||||
|
{% if forloop.first %} |
||||
|
<p>Přišly odpovědi na následující žádosti:</p> |
||||
|
<ul> |
||||
|
{% endif %} |
||||
|
<li>{{ zadost }} ({% if zadost.plati %}vyhověno{% elif zadost.typ == zadost.TYP_ZADOST %}nevyhověno, protože <a href="https://www.mff.cuni.cz/cs/studenti/formulare/spolecne/zadost-oboustranne-na-jeden-list">není čemu</a>, to musíte nejdříve vyplnit něco, o co žádáte{% else %}nevyhověno, Žádost o přístup k záznamům o třídní knize musí být podávána za svitu měsíce{% endif %})</li> |
||||
|
{% if forloop.last %} |
||||
|
</ul> |
||||
|
{% endif %} |
||||
|
{% empty %} |
||||
|
Žádné dopisy k vyzvednutí. |
||||
|
{% endfor %} |
||||
|
{% elif choice == "Zažádat o datovou schránku" %} |
||||
|
<p>Zažádali jste o datovou schránku. Než vám ale bylo odpovězeno, vrhla se na vás stařenka:</p> |
||||
|
<p>„Sledují vás! Na každém kroku vás sledují! A vy je v tom chcete ještě podporovat!?“</p> |
||||
|
<p>Nezbývá než počkat, až se uklidní (5h).</p> |
||||
|
{% elif choice == "Zažádat o datovou schránku (šeptem)" %} |
||||
|
<p>Zažádali jste o datovou schránku, tentokrát šeptem.</p> |
||||
|
<p>Na pokladně se sice podivovali, proč šeptáte, ale datová schránka vám byla založena.</p> |
||||
|
<p>Nyní můžete dopisy/zprávy přijímat a posílat elektronicky přímo z internátu a odpověď na vaši žádost se už nezasekne na poště.</p> |
||||
|
{% endif %} |
||||
|
{% endif %} |
||||
|
{% endblock %} |
@ -0,0 +1,27 @@ |
|||||
|
{% extends "hra/stanoviste/base.html" %} |
||||
|
{% load static %} |
||||
|
|
||||
|
{# https://www.mff.cuni.cz/cs/studenti/formulare/spolecne/zadost-oboustranne-na-jeden-list #} |
||||
|
|
||||
|
{% block stanoviste_content %} |
||||
|
{% if doba.den_v_tydnu == 5 and doba.cas > 14 or doba.cas < 8 or doba.cas > 16 or doba.den_v_tydnu >= 6 %} |
||||
|
<p>Zavřeno.</p> |
||||
|
{% elif doba.den_v_tydnu == 5 and doba.cas > 13 or doba.cas > 15 %} |
||||
|
<p>Tady nejste jako na studijním na Matfyzu. Tady je byrokratický úřad. To si myslíte, že tu bude někdo později než hodinu před zavíračkou?</p> |
||||
|
{% else %} |
||||
|
{% if choice is None %} |
||||
|
Co si přejete? |
||||
|
{% elif choice == "Zeptat se na poslané žádosti" %} |
||||
|
{% if zadosti|length != 0 %} |
||||
|
<p>Obdrželi jsme žádosti{% for zadost in zadosti %} {{ zadost }}{% if not forloop.first and not forloop.last %},{% endif %}{% endfor %}, bylo na ně odpovězeno, měla by vám přijít odpověď. Zkontrolujte si poštu na internátu nebo se zeptejte na poště.</p> |
||||
|
{% else %} |
||||
|
<p>Žádné žádosti nám ještě nepřišly. Ale znáte to, pošta…</p> |
||||
|
{% endif %} |
||||
|
{% else %} |
||||
|
Podali jste {{ zadosti.0|capfirst }}. |
||||
|
|
||||
|
{% if zadosti.0.typ == zadost.TYP_TK and tym.vi_o_mesici %}{% if not doba.je_noc %}<p>(Není noc, takže měsíc nesvítí. Ale pojďme to zkusit.)</p>{% else %}{% if doba.pocasi != 0 %}<p>(Není jasno, takže žádný měsíční svit. Ale pojďme to zkusit. Případně si můžeme příště s někým o počasí promluvili.)</p>{% if doba.den_mesice == 0 %}<p>(Ach jo, dnes je nov, takže měsíc nesvítí. Ale pojďme to zkusit.)</p>{% endif %}{% endif %}{% endif %}{% endif %} |
||||
|
{% endif %} |
||||
|
{% endif %} |
||||
|
{% endblock %} |
||||
|
|
@ -0,0 +1,19 @@ |
|||||
|
{% extends "base.html" %} |
||||
|
{% load static %} |
||||
|
|
||||
|
{% block prenacitani %} <meta http-equiv="refresh" content="60"> {% endblock %} |
||||
|
|
||||
|
|
||||
|
{% block content %} |
||||
|
{{ stanoviste.poradi }}/{{ settings.NEJVYSSI_INDEX }}: |
||||
|
|
||||
|
<h1>{% block nadpis %}{{stanoviste.nazev}}{% endblock nadpis %}</h1> |
||||
|
|
||||
|
{{ stanoviste.verejny_text | safe }} |
||||
|
|
||||
|
{# https://stackoverflow.com/a/75157188 #} |
||||
|
<img src="data:image/png;base64,{{image64}}" alt="Chyba, dojděte prosím pro Jidáše."> |
||||
|
|
||||
|
{% if settings.DEBUG %}<p><a href="{{ url }}">{{ url }}</a></p>{% endif %} |
||||
|
|
||||
|
{% endblock %} |
@ -0,0 +1,12 @@ |
|||||
|
{% extends "base.html" %} |
||||
|
{% load static %} |
||||
|
|
||||
|
{% block content %} |
||||
|
<h1>{% block nadpis %}Čas vypršel.{% endblock nadpis %}</h1> |
||||
|
|
||||
|
<p>Cože, vy tu pořád jste? My už jsme na vás úplně zapomněli. Zařaďte se prosím na konec fronty!</p> |
||||
|
|
||||
|
<p>(Načtěte qr kód znovu.)</p> |
||||
|
|
||||
|
<p><a href="{% url "tym" %}">Stránka týmu</a></p> |
||||
|
{% endblock %} |
@ -0,0 +1,27 @@ |
|||||
|
{% extends "base.html" %} |
||||
|
{% load static %} |
||||
|
|
||||
|
{% block prenacitani %}<meta http-equiv="refresh" content="{{ settings.TYM_AUTO_RELOAD }}">{% endblock %} |
||||
|
|
||||
|
{% block nadpis %}Tým: {{tym.nazev}}{% endblock %} |
||||
|
|
||||
|
|
||||
|
{% block content %} |
||||
|
<h1><span style="font-weight: normal">Hledači třídní knihy:</span> {{tym.nazev}}</h1> |
||||
|
|
||||
|
{% if tym.ma_ds %}<p class="ds">(Datová schránka: rqritmr)</p>{% endif %} |
||||
|
|
||||
|
<h2>Třídní kniha nalezena? {% if tym.tk_nalezena is not None %}✔️{% else %}❌{% endif %}</h2> |
||||
|
|
||||
|
<hr> |
||||
|
|
||||
|
<h2>Den {{ doba.den }}, {{ doba.den_v_tydnu_zkratka }}, {{ doba.hodiny_minuty }} {{ doba.denni_doba }}</h2> |
||||
|
|
||||
|
<hr> |
||||
|
|
||||
|
<h2>Inventář:</h2> |
||||
|
|
||||
|
<div class="inventar"> |
||||
|
{% include "hra/inventar.html" %} |
||||
|
</div> |
||||
|
{% endblock %} |
@ -0,0 +1,16 @@ |
|||||
|
from django.conf import settings |
||||
|
from django.contrib.auth.decorators import login_required |
||||
|
from django.urls import path |
||||
|
|
||||
|
from . import views |
||||
|
|
||||
|
urlpatterns = [ |
||||
|
path("", login_required(views.hra_view), name="hra"), |
||||
|
path("stanoviste/", login_required(views.StatickeStanovisteView.as_view()), name="stanoviste"), |
||||
|
path("tym/", login_required(views.TymView.as_view()), name="tym"), |
||||
|
path("tym/<int:stanoviste>/<str:my_hash>/", login_required(views.StanovisteZPohleduTymu.as_view()), name="tym"), |
||||
|
path("timeout/", views.TimeoutViwe.as_view(), name="timeout"), |
||||
|
] |
||||
|
|
||||
|
if settings.DEBUG: |
||||
|
urlpatterns.append(path("stanoviste/<int:stanoviste>/", views.StatickeStanovisteView.as_view(), name="stanoviste"),) |
@ -0,0 +1,144 @@ |
|||||
|
from functools import cached_property |
||||
|
|
||||
|
from django.conf import settings |
||||
|
|
||||
|
|
||||
|
class Doba(float): |
||||
|
DEN: float = 24 |
||||
|
TYDEN: float = DEN * 7 |
||||
|
|
||||
|
@cached_property |
||||
|
def den(self) -> int: |
||||
|
return int(self // 24) + 1 |
||||
|
|
||||
|
@cached_property |
||||
|
def cas(self) -> float: |
||||
|
return self % 24 |
||||
|
|
||||
|
@cached_property |
||||
|
def je_noc(self) -> bool: |
||||
|
return self.cas < settings.DEN[0] or self.cas > settings.DEN[1] |
||||
|
|
||||
|
@cached_property |
||||
|
def den_v_tydnu(self) -> int: |
||||
|
return (self.den - settings.PRVNI_PONDELI) % 7 + 1 |
||||
|
|
||||
|
@cached_property |
||||
|
def den_mesice(self) -> int: |
||||
|
return (self.den - settings.PRVNI_NOV) % 28 |
||||
|
|
||||
|
@property |
||||
|
def je_nov(self): |
||||
|
return self.den_mesice == 0 |
||||
|
|
||||
|
@property |
||||
|
def je_uplnek(self): |
||||
|
return self.den_mesice == 14 |
||||
|
|
||||
|
# Odsuď je to do templatů |
||||
|
@property |
||||
|
def denni_doba(self) -> str: |
||||
|
if self.je_noc: |
||||
|
if self.den_mesice == 0: |
||||
|
return "🌑" |
||||
|
elif self.den_mesice <= 6: |
||||
|
return "🌒" |
||||
|
elif self.den_mesice == 7: |
||||
|
return "🌓" |
||||
|
elif self.den_mesice <= 13: |
||||
|
return "🌔" |
||||
|
elif self.den_mesice == 14: |
||||
|
return "🌕" |
||||
|
elif self.den_mesice <= 20: |
||||
|
return "🌖" |
||||
|
elif self.den_mesice == 21: |
||||
|
return "🌗" |
||||
|
else: |
||||
|
return "🌘" |
||||
|
else: |
||||
|
return "☀️" |
||||
|
|
||||
|
@property |
||||
|
def den_v_tydnu_zkratka(self) -> str: |
||||
|
return [ |
||||
|
# 0: |
||||
|
None, |
||||
|
# 1: |
||||
|
"Po", |
||||
|
# 2: |
||||
|
"Út", |
||||
|
# 3: |
||||
|
"St", |
||||
|
# 4: |
||||
|
"Čt", |
||||
|
# 5: |
||||
|
"Pá", |
||||
|
# 6: |
||||
|
"So", |
||||
|
# 7: |
||||
|
"Ne", |
||||
|
][self.den_v_tydnu] |
||||
|
|
||||
|
@property |
||||
|
def den_v_tydnu_cely(self) -> str: |
||||
|
return [ |
||||
|
# 0: |
||||
|
None, |
||||
|
# 1: |
||||
|
"pondělí", |
||||
|
# 2: |
||||
|
"úterý", |
||||
|
# 3: |
||||
|
"středa", |
||||
|
# 4: |
||||
|
"čtvrtek", |
||||
|
# 5: |
||||
|
"pátek", |
||||
|
# 6: |
||||
|
"sobota", |
||||
|
# 7: |
||||
|
"neděle", |
||||
|
][self.den_v_tydnu] |
||||
|
|
||||
|
@property |
||||
|
def hodina(self) -> int: |
||||
|
return int(self.cas) |
||||
|
|
||||
|
@property |
||||
|
def minuta(self) -> int: |
||||
|
return int(self.cas % 1 * 60) |
||||
|
|
||||
|
@property |
||||
|
def hodiny_minuty(self) -> str: |
||||
|
return f"{self.hodina}:{self.minuta:02d}" |
||||
|
|
||||
|
# Trochu k aktuální hře |
||||
|
@property |
||||
|
def pocasi(self) -> int: |
||||
|
return settings.POCASI[self.den % len(settings.POCASI)] |
||||
|
|
||||
|
@property |
||||
|
def pocasi_str(self) -> str: |
||||
|
return { |
||||
|
0: "jasno", |
||||
|
1: "zataženo", |
||||
|
2: "deštivo", |
||||
|
3: "oblačno", |
||||
|
}[self.pocasi] |
||||
|
|
||||
|
@property |
||||
|
def pocasi_text(self) -> str: |
||||
|
dni = [Doba(self + i*Doba.DEN) for i in range(7)] |
||||
|
return ( |
||||
|
f"Jo a dnes má být celou dobu {dni[0].pocasi_str}. " |
||||
|
f"Zítra pak {dni[1].pocasi_str}. " |
||||
|
f"Pozítří nás čeká {dni[2].pocasi_str}. " |
||||
|
f"Pak nás čeká {dni[3].den_v_tydnu_cely}, a to bude pořád {dni[3].pocasi_str}. " |
||||
|
f"Další den můžeme očekávat {dni[4].pocasi_str}. " |
||||
|
f"Pak {dni[5].pocasi_str}. " |
||||
|
f"Nakonec {dni[6].pocasi_str}. " |
||||
|
f"A {dni[6].den_v_tydnu_cely} přinese {dni[6].pocasi_str}." |
||||
|
) |
||||
|
|
||||
|
def __add__(self, other): |
||||
|
return Doba(super().__add__(other)) |
@ -0,0 +1,22 @@ |
|||||
|
from django.conf import settings |
||||
|
from django.utils.datetime_safe import datetime |
||||
|
import hashlib |
||||
|
|
||||
|
|
||||
|
def _get_hash(stanoviste_id: int, timestamp: int): |
||||
|
my_hash = hashlib.new("md5") |
||||
|
my_hash.update(str(stanoviste_id).encode()) |
||||
|
my_hash.update(str(timestamp).encode()) |
||||
|
return my_hash.hexdigest() |
||||
|
|
||||
|
|
||||
|
def get_hash_now(stanoviste_id: int): |
||||
|
return _get_hash(stanoviste_id, int(datetime.now().timestamp() // settings.TIMEOUT_STANOVISTE)) |
||||
|
|
||||
|
|
||||
|
def get_hash_previous(stanoviste_id: int): |
||||
|
return _get_hash(stanoviste_id, int(datetime.now().timestamp() // settings.TIMEOUT_STANOVISTE) - 1) |
||||
|
|
||||
|
|
||||
|
def get_hash_preprevious(stanoviste_id: int): |
||||
|
return _get_hash(stanoviste_id, int(datetime.now().timestamp() // settings.TIMEOUT_STANOVISTE) - 2) |
@ -0,0 +1,49 @@ |
|||||
|
from django.db import models |
||||
|
|
||||
|
|
||||
|
# Žádost: |
||||
|
# - máme následující časové body: |
||||
|
# - dorazila na studijní (/přečetli si ji na studijním) |
||||
|
# - dorazila na poštu |
||||
|
# - dorazila na internát |
||||
|
# - vyzvednuta = platí |
||||
|
# |
||||
|
# - máme následující žádosti: |
||||
|
# - žádost |
||||
|
# - žádost o banán, |
||||
|
# - žádost o více vegetariánskou stravu v jídelně, |
||||
|
# - nevalidní žádost o přístup k záznamům o třídní knize |
||||
|
# - validní žádost o přístup k záznamům o třídní knize |
||||
|
|
||||
|
# https://stackoverflow.com/a/55243162 |
||||
|
class ZadostField(models.Field): |
||||
|
def __init__(self, **kwargs): |
||||
|
self.field_kwargs = kwargs.pop("field_kwargs", {}) |
||||
|
super().__init__(**kwargs) |
||||
|
|
||||
|
def contribute_to_class(self, cls, name, private_only=False): |
||||
|
for field in ( |
||||
|
models.FloatField(name=name + "_studijni", default=None, null=True, **self.field_kwargs), |
||||
|
models.FloatField(name=name + "_posta", default=None, null=True, **self.field_kwargs), |
||||
|
models.FloatField(name=name + "_internat", default=None, null=True, **self.field_kwargs), |
||||
|
models.FloatField(name=name + "_plati", default=None, null=True, **self.field_kwargs), |
||||
|
models.BooleanField(name=name + "_vytistena", default=False, **self.field_kwargs), |
||||
|
): |
||||
|
field.contribute_to_class(cls, field.name) |
||||
|
|
||||
|
setattr(cls, name, ZadostProperty(name)) |
||||
|
|
||||
|
|
||||
|
class ZadostProperty: |
||||
|
def __init__(self, name): |
||||
|
self.name = name |
||||
|
|
||||
|
def __get__(self, instance, owner): |
||||
|
if not instance: |
||||
|
return self |
||||
|
raise NotImplementedError |
||||
|
# real = getattr(instance, self.name + "_real") |
||||
|
|
||||
|
def __set__(self, instance, value: complex): |
||||
|
raise NotImplementedError |
||||
|
# setattr(instance, self.name + "_real", value.real) |
@ -0,0 +1,143 @@ |
|||||
|
import qrcode |
||||
|
import base64 |
||||
|
import io |
||||
|
|
||||
|
from django.contrib.auth import get_user |
||||
|
from django.shortcuts import redirect, get_object_or_404 |
||||
|
from django.urls import reverse |
||||
|
from django.views.generic import DetailView |
||||
|
from django.views.generic.base import TemplateView |
||||
|
from django.core.exceptions import PermissionDenied |
||||
|
from django.db import transaction |
||||
|
|
||||
|
from . import logika |
||||
|
from .models import Stanoviste, Tym |
||||
|
from .utils.hash import get_hash_now, get_hash_previous, get_hash_preprevious |
||||
|
from .utils.doba import Doba |
||||
|
|
||||
|
|
||||
|
# Jen hloupé rozhazovátko |
||||
|
def hra_view(request): |
||||
|
user = request.user |
||||
|
if not user.is_authenticated: |
||||
|
return redirect(reverse("login")) |
||||
|
|
||||
|
stanoviste = Stanoviste.objects.filter(user=user.id).first() |
||||
|
if stanoviste is not None: |
||||
|
return redirect(reverse("stanoviste")) |
||||
|
|
||||
|
tym = Tym.objects.filter(user=user.id).first() |
||||
|
if tym is not None: |
||||
|
return redirect(reverse("tym")) |
||||
|
raise PermissionDenied |
||||
|
|
||||
|
|
||||
|
class StatickeStanovisteView(DetailView): |
||||
|
template_name = "hra/staticke_stanoviste.html" |
||||
|
model = Stanoviste |
||||
|
|
||||
|
def get_object(self, queryset=None): |
||||
|
if "stanoviste" in self.kwargs: |
||||
|
return get_object_or_404(Stanoviste, id=self.kwargs["stanoviste"]) |
||||
|
user = get_user(self.request) |
||||
|
stanoviste = Stanoviste.objects.filter(user=user.id).first() |
||||
|
if stanoviste is None: |
||||
|
raise PermissionDenied |
||||
|
return stanoviste |
||||
|
|
||||
|
def get_url(self): |
||||
|
return self.request.build_absolute_uri(reverse( |
||||
|
"tym", |
||||
|
kwargs={ |
||||
|
"stanoviste": self.object.id, |
||||
|
"my_hash": get_hash_now(self.object.id), |
||||
|
} |
||||
|
)) |
||||
|
|
||||
|
@staticmethod |
||||
|
def get_base64_qr_code(url: str): |
||||
|
buffer = io.BytesIO() |
||||
|
qrcode.make(url).save(buffer) |
||||
|
# https://stackoverflow.com/a/75157188 |
||||
|
img_str = base64.b64encode(buffer.getvalue()) |
||||
|
return img_str.decode("utf-8") # convert to str and cut b'' chars |
||||
|
|
||||
|
def get_context_data(self, **kwargs): |
||||
|
context = super().get_context_data() |
||||
|
url = self.get_url() |
||||
|
context["url"] = url |
||||
|
context["image64"] = self.get_base64_qr_code(url) |
||||
|
return context |
||||
|
|
||||
|
|
||||
|
class TymView(DetailView): |
||||
|
template_name = "hra/tym.html" |
||||
|
model = Tym |
||||
|
|
||||
|
def get_object(self, queryset=None): |
||||
|
user = get_user(self.request) |
||||
|
tym = Tym.objects.filter(user=user.id).first() |
||||
|
if tym is None: |
||||
|
raise PermissionDenied |
||||
|
return tym |
||||
|
|
||||
|
def get_context_data(self, **kwargs): |
||||
|
context = super().get_context_data() |
||||
|
context["doba"] = self.object.doba |
||||
|
return context |
||||
|
|
||||
|
|
||||
|
class StanovisteZPohleduTymu(TemplateView): |
||||
|
stanoviste_id: int |
||||
|
stanoviste: Stanoviste |
||||
|
tym: Tym |
||||
|
doba: Doba |
||||
|
|
||||
|
def get_template_names(self): |
||||
|
PREFIX = "hra/stanoviste/" |
||||
|
return PREFIX + self.stanoviste.template |
||||
|
|
||||
|
def setup(self, request, *args, **kwargs): |
||||
|
super().setup(request, *args, **kwargs) |
||||
|
self.stanoviste_id = self.kwargs["stanoviste"] |
||||
|
self.stanoviste = get_object_or_404(Stanoviste, id=self.stanoviste_id) |
||||
|
self.tym = get_object_or_404(Tym, user=self.request.user.id) |
||||
|
self.doba = self.tym.doba |
||||
|
|
||||
|
def dispatch(self, request, *args, **kwargs): |
||||
|
if not self.pristupne(): |
||||
|
return redirect(reverse("timeout")) |
||||
|
return super().dispatch(request, *args, **kwargs) |
||||
|
|
||||
|
def pristupne(self): |
||||
|
my_hash = self.kwargs["my_hash"] |
||||
|
return my_hash == get_hash_now(self.stanoviste_id) or my_hash == get_hash_previous(self.stanoviste_id) or my_hash == get_hash_preprevious(self.stanoviste_id) |
||||
|
|
||||
|
def get_posible_choices(self) -> list[str]: |
||||
|
return logika.get_posible_choices[self.stanoviste.id](self.doba, self.tym) |
||||
|
|
||||
|
def get_context_data(self, **kwargs): |
||||
|
context = super().get_context_data() |
||||
|
context["stanoviste"] = self.stanoviste |
||||
|
context["tym"] = self.tym |
||||
|
context["doba"] = self.doba |
||||
|
context["choices"] = self.get_posible_choices() |
||||
|
return context |
||||
|
|
||||
|
def post(self, request, *args, **kwargs): |
||||
|
context = self.get_context_data(**kwargs) |
||||
|
self.template_name = "hra/staticke_stanoviste.html" |
||||
|
choice = self.request.POST.get("choice", None) |
||||
|
with transaction.atomic(): |
||||
|
if (choice is None) or (choice not in self.get_posible_choices()): |
||||
|
# raise PermissionDenied |
||||
|
pass |
||||
|
else: |
||||
|
context["zadosti"] = logika.apply_choice[self.stanoviste.id][choice](self.doba, self.tym) |
||||
|
context["choice"] = choice |
||||
|
del(context["choices"]) |
||||
|
return self.render_to_response(context) |
||||
|
|
||||
|
|
||||
|
class TimeoutViwe(TemplateView): |
||||
|
template_name = "hra/timeout.html" |
@ -0,0 +1,22 @@ |
|||||
|
#!/usr/bin/env python |
||||
|
"""Django's command-line utility for administrative tasks.""" |
||||
|
import os |
||||
|
import sys |
||||
|
|
||||
|
|
||||
|
def main(): |
||||
|
"""Run administrative tasks.""" |
||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'byrokracie.settings') |
||||
|
try: |
||||
|
from django.core.management import execute_from_command_line |
||||
|
except ImportError as exc: |
||||
|
raise ImportError( |
||||
|
"Couldn't import Django. Are you sure it's installed and " |
||||
|
"available on your PYTHONPATH environment variable? Did you " |
||||
|
"forget to activate a virtual environment?" |
||||
|
) from exc |
||||
|
execute_from_command_line(sys.argv) |
||||
|
|
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
main() |
Loading…
Reference in new issue