diff --git a/med/settings.py b/med/settings.py index d7d1d87..c18f42c 100644 --- a/med/settings.py +++ b/med/settings.py @@ -50,6 +50,7 @@ INSTALLED_APPS = [ 'med', 'media', 'logs', + 'sporz', ] MIDDLEWARE = [ diff --git a/sporz/__init__.py b/sporz/__init__.py new file mode 100644 index 0000000..adac51a --- /dev/null +++ b/sporz/__init__.py @@ -0,0 +1,5 @@ +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + +default_app_config = 'sporz.apps.SporzConfig' diff --git a/sporz/admin.py b/sporz/admin.py new file mode 100644 index 0000000..312b0fe --- /dev/null +++ b/sporz/admin.py @@ -0,0 +1,37 @@ +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + +from django.contrib import admin + +from med.admin import admin_site +from .models import GameSave, Player + + +class PlayerInline(admin.TabularInline): + model = Player + + +class GameSaveAdmin(admin.ModelAdmin): + inlines = [PlayerInline, ] + list_display = ('__str__', 'game_master', 'game_has_ended') + date_hierarchy = 'created_at' + + def has_change_permission(self, request, obj=None): + """ + If user is game master then authorize edit + """ + if obj and obj.game_master == request.user: + return True + return super().has_change_permission(request, obj) + + def has_delete_permission(self, request, obj=None): + """ + If user is game master then authorize deletion + """ + if obj and obj.game_master == request.user: + return True + return super().has_delete_permission(request, obj) + + +admin_site.register(GameSave, GameSaveAdmin) diff --git a/sporz/apps.py b/sporz/apps.py new file mode 100644 index 0000000..33fcffb --- /dev/null +++ b/sporz/apps.py @@ -0,0 +1,11 @@ +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + +from django.apps import AppConfig +from django.utils.translation import ugettext_lazy as _ + + +class SporzConfig(AppConfig): + name = 'sporz' + verbose_name = _('Sporz game assitant') diff --git a/sporz/locale/fr/LC_MESSAGES/django.po b/sporz/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..391f783 --- /dev/null +++ b/sporz/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,134 @@ +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-08-15 11:29+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: apps.py:11 +msgid "Sporz game assitant" +msgstr "Assitant au jeu Sporz" + +#: models.py:13 +msgid "created at" +msgstr "créé le" + +#: models.py:20 +msgid "game master" +msgstr "maître du jeu" + +#: models.py:21 +msgid "Game master can edit and delete this game save." +msgstr "Le maître du jeu peut éditer et supprimer cette sauvegarde." + +#: models.py:24 +msgid "current round" +msgstr "tour actuel" + +#: models.py:28 +msgid "game has ended" +msgstr "la partie est finie" + +#: models.py:29 +msgid "If true, then everyone will be able to see the game." +msgstr "Quand cette case est cochée, tout le monde pourra voir le récapitulatif." + +#: models.py:36 models.py:115 +msgid "players" +msgstr "joueurs" + +#: models.py:40 +msgid "game save" +msgstr "sauvegarde de jeu" + +#: models.py:41 +msgid "game saves" +msgstr "sauvegardes de jeu" + +#: models.py:58 +msgid "Base astronaut" +msgstr "Astronaute de base" + +#: models.py:59 +msgid "Base mutant" +msgstr "Mutant de base" + +#: models.py:60 +msgid "Healer" +msgstr "Médecin" + +#: models.py:61 +msgid "Psychologist" +msgstr "Psychologue" + +#: models.py:62 +msgid "Geno-technician" +msgstr "Geno-technicien" + +#: models.py:63 +msgid "Computer scientist" +msgstr "Informaticien" + +#: models.py:64 +msgid "Hacker" +msgstr "Hackeur" + +#: models.py:65 +msgid "Spy" +msgstr "Espion" + +#: models.py:66 +msgid "Detective" +msgstr "Enquêteur" + +#: models.py:67 +msgid "Traitor" +msgstr "Traite" + +#: models.py:75 +msgid "Neutral" +msgstr "Neutre" + +#: models.py:76 +msgid "Host" +msgstr "Hôte" + +#: models.py:77 +msgid "Immunized" +msgstr "Immunisé" + +#: models.py:83 +msgid "game" +msgstr "jeu" + +#: models.py:87 +msgid "name" +msgstr "nom" + +#: models.py:94 +msgid "user" +msgstr "utilisateur" + +#: models.py:95 +msgid "Optionnal mapping to an user." +msgstr "Lien optionnel à un utilisateur." + +#: models.py:103 +msgid "genotype" +msgstr "génotype" + +#: models.py:107 +msgid "infected" +msgstr "infecté" + +#: models.py:114 +msgid "player" +msgstr "joueur" diff --git a/sporz/migrations/0001_initial.py b/sporz/migrations/0001_initial.py new file mode 100644 index 0000000..69e18d0 --- /dev/null +++ b/sporz/migrations/0001_initial.py @@ -0,0 +1,51 @@ +# Generated by Django 2.2.4 on 2019-08-15 09:31 + +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='GameSave', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='created at')), + ('current_round', models.PositiveSmallIntegerField(default=1, verbose_name='current round')), + ('game_has_ended', models.BooleanField(help_text='If true, then everyone will be able to see the game.', verbose_name='game has ended')), + ('game_master', models.ForeignKey(help_text='Game master can edit and delete this game save.', on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='game master')), + ], + options={ + 'verbose_name': 'game save', + 'verbose_name_plural': 'game saves', + 'ordering': ['-created_at'], + }, + ), + migrations.CreateModel( + name='Player', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=150, verbose_name='name')), + ('role', models.CharField(choices=[('BA', 'Base astronaut'), ('BM', 'Base mutant'), ('HE', 'Healer'), ('PS', 'Psychologist'), ('GE', 'Geno-technician'), ('CO', 'Computer scientist'), ('HA', 'Hacker'), ('SP', 'Spy'), ('DE', 'Detective'), ('TR', 'Traitor')], default='BA', max_length=2)), + ('genotype', models.NullBooleanField(choices=[(None, 'Neutral'), (False, 'Host'), (True, 'Immunized')], verbose_name='genotype')), + ('infected', models.BooleanField(verbose_name='infected')), + ('game', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sporz.GameSave', verbose_name='game')), + ('user', models.ForeignKey(blank=True, help_text='Optionnal mapping to an user.', null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='user')), + ], + options={ + 'verbose_name': 'player', + 'verbose_name_plural': 'players', + 'ordering': ['user__username'], + 'unique_together': {('game', 'name')}, + }, + ), + ] diff --git a/sporz/migrations/__init__.py b/sporz/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sporz/models.py b/sporz/models.py new file mode 100644 index 0000000..096c14e --- /dev/null +++ b/sporz/models.py @@ -0,0 +1,117 @@ +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + +from django.conf import settings +from django.db import models +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ + + +class GameSave(models.Model): + created_at = models.DateTimeField( + verbose_name=_('created at'), + default=timezone.now, + editable=False, + ) + game_master = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + verbose_name=_('game master'), + help_text=_('Game master can edit and delete this game save.'), + ) + current_round = models.PositiveSmallIntegerField( + verbose_name=_('current round'), + default=1, + ) + game_has_ended = models.BooleanField( + verbose_name=_('game has ended'), + help_text=_('If true, then everyone will be able to see the game.'), + ) + + def __str__(self): + return "{} ({} {})".format( + self.created_at.strftime("%b %d %Y %H:%M:%S"), + len(self.player_set.all()), + _("players"), + ) + + class Meta: + verbose_name = _("game save") + verbose_name_plural = _("game saves") + ordering = ['-created_at'] + + +class Player(models.Model): + # Player roles + BASE_ASTRONAUT = 'BA' + BASE_MUTANT = 'BM' + HEALER = 'HE' + PSYCHOLOGIST = 'PS' + GENO_TECHNICIAN = 'GE' + COMPUTER_SCIENTIST = 'CO' + HACKER = 'HA' + SPY = 'SP' + DETECTIVE = 'DE' + TRAITOR = 'TR' + ROLES = [ + (BASE_ASTRONAUT, _('Base astronaut')), + (BASE_MUTANT, _("Base mutant")), + (HEALER, _("Healer")), + (PSYCHOLOGIST, _("Psychologist")), + (GENO_TECHNICIAN, _("Geno-technician")), + (COMPUTER_SCIENTIST, _("Computer scientist")), + (HACKER, _("Hacker")), + (SPY, _("Spy")), + (DETECTIVE, _("Detective")), + (TRAITOR, _("Traitor")), + ] + + # Genotypes + NEUTRAL = None + HOST = False + IMMUNIZED = True + GENOTYPES = [ + (NEUTRAL, _("Neutral")), + (HOST, _("Host")), + (IMMUNIZED, _("Immunized")) + ] + + game = models.ForeignKey( + GameSave, + on_delete=models.CASCADE, + verbose_name=_('game'), + ) + name = models.CharField( + max_length=150, + verbose_name=_('name'), + ) + user = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + blank=True, + null=True, + verbose_name=_('user'), + help_text=_('Optionnal mapping to an user.'), + ) + role = models.CharField( + max_length=2, + choices=ROLES, + default=BASE_ASTRONAUT, + ) + genotype = models.NullBooleanField( + verbose_name=_('genotype'), + choices=GENOTYPES, + ) + infected = models.BooleanField( + verbose_name=_('infected'), + ) + + def __str__(self): + return str(self.user) + + class Meta: + verbose_name = _("player") + verbose_name_plural = _("players") + ordering = ['user__username'] + unique_together = ['game', 'name']