Byrokracie Sklené 2023
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

330 lines
9.9 KiB

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 vytistene_zadosti(self) -> QuerySet["Zadost"]:
return self.zadosti.filter(vytistena=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]