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