charasheet/src/party/models.py
2023-03-25 10:02:50 +01:00

135 lines
3.9 KiB
Python

from django.db import models
from django.db.models import F, Q
from django.urls import reverse
from django_extensions.db.models import TimeStampedModel
from character.models import Character
from common.models import UniquelyNamedModel, UniquelyNamedModelManager
class PartyQuerySet(models.QuerySet):
def managed_by(self, user):
return self.filter(game_master=user)
def played_by(self, user):
return self.filter(characters__in=Character.objects.filter(player=user))
def played_or_mastered_by(self, user):
return self.filter(
Q(game_master=user)
| Q(characters__in=Character.objects.filter(player=user)),
).distinct()
def related_to(self, user):
return self.filter(
Q(game_master=user)
| Q(characters__in=Character.objects.filter(player=user))
| Q(invited_characters__in=Character.objects.filter(player=user)),
).distinct()
def invited_to(self, user):
return self.filter(invited_characters__in=Character.objects.filter(player=user))
class PartyManager(UniquelyNamedModelManager):
pass
class Party(UniquelyNamedModel, TimeStampedModel, models.Model): # noqa: DJ008
game_master = models.ForeignKey(
"common.User",
on_delete=models.PROTECT,
related_name="parties",
verbose_name="meneur de jeu",
)
invited_characters = models.ManyToManyField(
"character.Character",
blank=True,
related_name="invites",
verbose_name="personnages invités",
)
characters = models.ManyToManyField(
"character.Character",
blank=True,
related_name="parties",
verbose_name="personnages",
)
objects = PartyManager.from_queryset(PartyQuerySet)()
class Meta(UniquelyNamedModel.Meta, TimeStampedModel.Meta):
verbose_name = "Groupe"
verbose_name_plural = "Groupes"
def get_absolute_url(self) -> str:
return reverse("party:details", kwargs={"pk": self.pk})
def reset_stats(self):
for character in self.characters.all():
character.reset_stats()
class BattleEffectQuerySet(models.QuerySet):
def increase_rounds(self):
self.temporary().update(remaining_rounds=F("remaining_rounds") + 1)
def decrease_rounds(self):
self.active().update(remaining_rounds=F("remaining_rounds") - 1)
def active(self):
return self.filter(remaining_rounds__gt=0)
def terminated(self):
return self.filter(remaining_rounds=0)
def permanent(self):
return self.filter(remaining_rounds=-1)
def temporary(self):
return self.exclude(remaining_rounds=-1)
class BattleEffectManager(models.Manager):
pass
class BattleEffect(TimeStampedModel, models.Model):
name = models.CharField(max_length=100, blank=False, null=False, verbose_name="nom")
target = models.CharField(
max_length=100,
blank=False,
null=False,
verbose_name="cible",
)
description = models.TextField(blank=True, null=False, verbose_name="description")
remaining_rounds = models.SmallIntegerField(
blank=False,
default=-1,
verbose_name="nombre de tours restants",
help_text="-1 pour un effet permanent",
)
party = models.ForeignKey(
"party.Party",
on_delete=models.CASCADE,
related_name="effects",
verbose_name="groupe",
)
created_by = models.ForeignKey(
"common.User",
on_delete=models.CASCADE,
related_name="effects",
verbose_name="créé par",
)
objects = BattleEffectManager.from_queryset(BattleEffectQuerySet)()
def __str__(self):
return self.name
@property
def remaining_percent(self) -> float:
max_display_percent = 5
if self.remaining_rounds >= max_display_percent or self.remaining_rounds < 0:
return 100
return self.remaining_rounds / max_display_percent * 100