From c04794081ba5b68d4836818adc95325a60d6dcc7 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Sun, 15 Nov 2020 19:27:18 +0100 Subject: [PATCH] Init models --- .gitignore | 3 + lg/__init__.py | 0 lg/admin.py | 3 + lg/apps.py | 5 + lg/models.py | 310 ++++++++++++++++++++++++++++++++++++++++++++++ lg/tests.py | 3 + lg/views.py | 3 + lglog/settings.py | 2 + tox.ini | 4 +- 9 files changed, 331 insertions(+), 2 deletions(-) create mode 100644 lg/__init__.py create mode 100644 lg/admin.py create mode 100644 lg/apps.py create mode 100644 lg/models.py create mode 100644 lg/tests.py create mode 100644 lg/views.py diff --git a/.gitignore b/.gitignore index 6cea684..e81cd62 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,6 @@ media/ env/ venv/ db.sqlite3 + +# Don't commit migrations now +migrations/ diff --git a/lg/__init__.py b/lg/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lg/admin.py b/lg/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/lg/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/lg/apps.py b/lg/apps.py new file mode 100644 index 0000000..2eaac8c --- /dev/null +++ b/lg/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class LgConfig(AppConfig): + name = 'lg' diff --git a/lg/models.py b/lg/models.py new file mode 100644 index 0000000..d9c0e6a --- /dev/null +++ b/lg/models.py @@ -0,0 +1,310 @@ +from django.contrib.auth.models import User +from django.db import models +from django.utils.translation import gettext_lazy as _ +from polymorphic.models import PolymorphicModel + + +class Player(PolymorphicModel): + user = models.OneToOneField( + User, + on_delete=models.CASCADE, + verbose_name=_("user"), + ) + + dead = models.BooleanField( + default=False, + verbose_name=_("dead"), + ) + + infected = models.BooleanField( + default=False, + verbose_name=_("infected"), + ) + + hacked = models.BooleanField( + default=False, + verbose_name=_("hacked"), + ) + + captain = models.BooleanField( + default=False, + verbose_name=_("captain"), + ) + + in_love_with = models.ForeignKey( + "lg.Player", + on_delete=models.CASCADE, + related_name="+", + null=True, + default=None, + ) + + @property + def alive(self): + return not self.dead + + def action_class(self): + raise NotImplementedError + + class Meta: + verbose_name = _("player") + verbose_name_plural = _("players") + + +class Werewolf(Player): + def action_class(self): + return WerewolfAction + + class Meta: + verbose_name = _("werewolf") + verbose_name_plural = _("werewolves") + + +class Cupidon(Player): + def action_class(self): + return CupidonAction + + class Meta: + verbose_name = _("cupidon") + verbose_name_plural = _("cupidons") + + +class Witch(Player): + def action_class(self): + return WitchAction + + class Meta: + verbose_name = _("witch") + verbose_name_plural = _("witches") + + +class Raven(Player): + def action_class(self): + return RavenAction + + class Meta: + verbose_name = _("raven") + verbose_name_plural = _("ravens") + + +class Dove(Player): + def action_class(self): + return DoveAction + + class Meta: + verbose_name = _("dove") + verbose_name_plural = _("doves") + + +class Hacker(Player): + def action_class(self): + return HackerAction + + class Meta: + verbose_name = _("hacker") + verbose_name_plural = _("hackers") + + +class Action(PolymorphicModel): + player = models.ForeignKey( + Player, + on_delete=models.CASCADE, + verbose_name=_("player"), + related_name="actions", + ) + + night = models.PositiveSmallIntegerField( + verbose_name=_("night"), + ) + + def act_night(self, night: int) -> None: + pass + + class Meta: + verbose_name = _("action") + verbose_name_plural = _("actions") + + +class WerewolfAction(Action): + target = models.ForeignKey( + Player, + on_delete=models.CASCADE, + related_name="+", + verbose_name=_("target"), + ) + + class Meta: + verbose_name = _("werewolf action") + verbose_name_plural = _("werewolf actions") + + +class CupidonAction(Action): + target1 = models.ForeignKey( + Player, + on_delete=models.CASCADE, + related_name="+", + verbose_name=_("target"), + ) + + target2 = models.ForeignKey( + Player, + on_delete=models.CASCADE, + related_name="+", + verbose_name=_("target"), + ) + + def act_night(self, night: int) -> None: + if night > 1: + return + self.target1.in_love_with = self.target2 + self.target2.in_love_with = self.target1 + self.target1.save() + self.target2.save() + + +class WitchAction(Action): + saved = models.ForeignKey( + Player, + on_delete=models.CASCADE, + related_name="+", + verbose_name=_("saved"), + ) + + killed = models.ForeignKey( + Player, + on_delete=models.CASCADE, + related_name="+", + verbose_name=_("killed"), + ) + + class Meta: + verbose_name = _("witch action") + verbose_name_plural = _("witch actions") + + +class RavenAction(Action): + target = models.ForeignKey( + Player, + on_delete=models.CASCADE, + related_name="+", + verbose_name=_("target"), + ) + + message = models.TextField( + verbose_name=_("message"), + ) + + class Meta: + verbose_name = _("raven action") + verbose_name_plural = _("raven actions") + + +class DoveAction(Action): + target = models.ForeignKey( + Player, + on_delete=models.CASCADE, + related_name="+", + verbose_name=_("target"), + ) + + message = models.TextField( + verbose_name=_("message"), + ) + + class Meta: + verbose_name = _("dove action") + verbose_name_plural = _("dove actions") + + +class HackerAction(Action): + target1 = models.ForeignKey( + Player, + on_delete=models.CASCADE, + related_name="+", + verbose_name=_("target"), + ) + + target2 = models.ForeignKey( + Player, + on_delete=models.CASCADE, + related_name="+", + verbose_name=_("target"), + ) + + def act_night(self, night: int): + self.target1.hacked = True + self.target2.hacked = True + self.target1.save() + self.target2.save() + + class Meta: + verbose_name = _("hacker action") + verbose_name_plural = _("hacker actions") + + +class Vote(PolymorphicModel): + day = models.PositiveSmallIntegerField( + verbose_name=_("day"), + ) + + voter = models.ForeignKey( + Player, + on_delete=models.CASCADE, + related_name="+", + verbose_name=_("voter"), + ) + + target = models.ForeignKey( + Player, + on_delete=models.CASCADE, + related_name="+", + verbose_name=_("target"), + ) + + @classmethod + def get_votes(cls, day: int): + votes = cls.objects.filter(day=day).all() + d = {} + for vote in votes: + d.setdefault(vote.target, 0) + d[vote.target] += 1 + return d + + class Meta: + verbose_name = _("vote") + verbose_name_plural = _("votes") + + +class CaptainVote(Vote): + class Meta: + verbose_name = _("captain vote") + verbose_name_plural = _("captain votes") + + +class EjectVote(Vote): + @classmethod + def get_votes(cls, day: int): + votes = cls.objects.filter(day=day).all() + d = {} + for vote in votes: + vote: Vote + d.setdefault(vote.target, 0) + d[vote.target] += 1 + if vote.voter.captain: + d[vote.target] += 1 + + for dove_action in DoveAction.objects.filter(day=day).all(): + dove_action: DoveAction + d.setdefault(dove_action.target, 0) + d[dove_action.target] -= 2 + + for raven_action in RavenAction.objects.filter(day=day).all(): + raven_action: RavenAction + d.setdefault(raven_action.target, 0) + d[raven_action.target] += 2 + + return d + + class Meta: + verbose_name = _("eject vote") + verbose_name_plural = _("eject votes") diff --git a/lg/tests.py b/lg/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/lg/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/lg/views.py b/lg/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/lg/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/lglog/settings.py b/lglog/settings.py index b1769c9..dceb59c 100644 --- a/lglog/settings.py +++ b/lglog/settings.py @@ -37,6 +37,8 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + + 'lg', ] MIDDLEWARE = [ diff --git a/tox.ini b/tox.ini index 8153b9f..293dbc8 100644 --- a/tox.ini +++ b/tox.ini @@ -13,7 +13,7 @@ deps = django-polymorphic~=3.0 django-tables2~=2.3 commands = - coverage run --source=lglog ./manage.py test lglog/ + coverage run --source=lglog,lg ./manage.py test lglog/ lg/ coverage report -m [testenv:linters] @@ -26,7 +26,7 @@ deps = pep8-naming pyflakes commands = - flake8 lglog/ + flake8 lglog/ lg/ [flake8] exclude =