diff --git a/game/migrations/0003_gameevent.py b/game/migrations/0003_gameevent.py new file mode 100644 index 0000000..e0fd74b --- /dev/null +++ b/game/migrations/0003_gameevent.py @@ -0,0 +1,73 @@ +# Generated by Django 3.1.3 on 2020-11-06 03:54 + +from django.db import migrations, models +import django.db.models.deletion +import django_mysql.models +import game.models +import internal.utils + + +class Migration(migrations.Migration): + + dependencies = [ + ("game", "0002_auto_20201106_0225"), + ] + + operations = [ + migrations.CreateModel( + name="GameEvent", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created_at", + models.DateTimeField( + auto_now_add=True, verbose_name="Creation date" + ), + ), + ( + "type", + models.IntegerField( + choices=[ + (0, "CREATE_GAME"), + (1, "PAUSE"), + (2, "RESUME"), + (3, "CLICK_MINE"), + (4, "CLICK_POINT"), + (5, "CLICK_EMPTY"), + (6, "CLICK_FLAG"), + (7, "GAME_OVER"), + ], + default=game.models.EventTypes["CREATE_GAME"], + help_text="The game event", + ), + ), + ( + "metadata", + django_mysql.models.JSONField( + default=internal.utils.empty_object, + help_text="Some usefull event metadata", + verbose_name="Event metadata", + ), + ), + ( + "game", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="game.game" + ), + ), + ], + options={ + "verbose_name": "Game event", + "verbose_name_plural": "Game events", + "db_table": "game_events", + }, + ), + ] diff --git a/game/models.py b/game/models.py index 81c30d3..ecc765c 100644 --- a/game/models.py +++ b/game/models.py @@ -2,22 +2,26 @@ from enum import IntEnum from django.db import models from django_mysql.models import JSONField -from internal.utils import empty_list +from internal.utils import empty_list, empty_object from .game import Minesweeper -class GameStatuses(IntEnum): +class EnumChoicesBase(IntEnum): """ Enum was used as choices of Game.status because explicit is better than implicit """ - NOT_PLAYED = 0 - PLAYING = 1 - FINISHED = 2 - @classmethod def choices(cls): return [(key.value, key.name) for key in cls] +class GameStatuses(EnumChoicesBase): + """ Statuses used by the player and system on game """ + + NOT_PLAYED = 0 + PLAYING = 1 + FINISHED = 2 + + class Game(models.Model): created_at = models.DateTimeField("Creation date", auto_now_add=True) modified_at = models.DateTimeField("Last update", auto_now=True) @@ -63,3 +67,36 @@ class Game(models.Model): verbose_name = "Game" verbose_name_plural = "Games" db_table = "games" + + +class EventTypes(EnumChoicesBase): + """ Event types to generate a game timeline """ + + CREATE_GAME = 0 + PAUSE = 1 + RESUME = 2 + CLICK_MINE = 3 + CLICK_POINT = 4 + CLICK_EMPTY = 5 + CLICK_FLAG = 6 + GAME_OVER = 7 + + +class GameEvent(models.Model): + created_at = models.DateTimeField("Creation date", auto_now_add=True) + game = models.ForeignKey("game.Game", on_delete=models.CASCADE) + + type = models.IntegerField( + choices=EventTypes.choices(), + default=EventTypes.CREATE_GAME, + help_text="The game event", + ) + + metadata = JSONField( + "Event metadata", default=empty_object, help_text="Some usefull event metadata" + ) + + class Meta: + verbose_name = "Game event" + verbose_name_plural = "Game events" + db_table = "game_events"