feat: clock + place games
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
|
||||
from events.models import Event
|
||||
from events.scoping import EventScopedManager
|
||||
|
||||
DEFAULT_GRID_WIDTH = 64
|
||||
DEFAULT_GRID_HEIGHT = 64
|
||||
PLACE_COOLDOWN_SECONDS = 30
|
||||
|
||||
# 16-entry palette, classic r/place-style colors. The index into this list is
|
||||
# what's sent over the wire (see wire.py) - frontend/src/palette.ts must
|
||||
# mirror this list exactly, in the same order.
|
||||
PALETTE = [
|
||||
"#FFFFFF", # 0 white
|
||||
"#E4E4E4", # 1 light grey
|
||||
"#888888", # 2 grey
|
||||
"#222222", # 3 black
|
||||
"#FFA7D1", # 4 pink
|
||||
"#E50000", # 5 red
|
||||
"#E59500", # 6 orange
|
||||
"#A06A42", # 7 brown
|
||||
"#E5D900", # 8 yellow
|
||||
"#94E044", # 9 light green
|
||||
"#02BE01", # 10 green
|
||||
"#00D3DD", # 11 cyan
|
||||
"#0083C7", # 12 blue
|
||||
"#0000EA", # 13 dark blue
|
||||
"#CF6EE4", # 14 purple
|
||||
"#820080", # 15 dark purple
|
||||
]
|
||||
|
||||
|
||||
class PlaceSettings(models.Model):
|
||||
"""One row per event, same event-scoped-singleton pattern as
|
||||
clock.models.ClockTimer. width/height are the live grid dimensions - the
|
||||
canonical source of truth is here, not a fixed constant, so an admin can
|
||||
resize the board per event (see signals.py for how that propagates).
|
||||
|
||||
Unlike pplace's original PlaceSettings, there's no is_enabled here - the
|
||||
games registry (EventGame.enabled) is the single on/off switch, checked
|
||||
before a client can reach this app at all.
|
||||
"""
|
||||
|
||||
event = models.OneToOneField(
|
||||
Event, on_delete=models.CASCADE, related_name="place_settings"
|
||||
)
|
||||
width = models.PositiveSmallIntegerField(default=DEFAULT_GRID_WIDTH)
|
||||
height = models.PositiveSmallIntegerField(default=DEFAULT_GRID_HEIGHT)
|
||||
|
||||
def __str__(self):
|
||||
return f"PlaceSettings({self.event}, size={self.width}x{self.height})"
|
||||
|
||||
@classmethod
|
||||
def current(cls, event: Event) -> "PlaceSettings":
|
||||
obj, _ = cls.objects.get_or_create(event=event)
|
||||
return obj
|
||||
|
||||
|
||||
class PixelPlacement(models.Model):
|
||||
event = models.ForeignKey(
|
||||
Event, on_delete=models.CASCADE, related_name="pixel_placements"
|
||||
)
|
||||
player = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="pixel_placements",
|
||||
)
|
||||
x = models.PositiveSmallIntegerField()
|
||||
y = models.PositiveSmallIntegerField()
|
||||
color_index = models.PositiveSmallIntegerField()
|
||||
placed_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
objects = models.Manager()
|
||||
for_event = EventScopedManager()
|
||||
|
||||
class Meta:
|
||||
ordering = ["-placed_at"]
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.player} placed ({self.x}, {self.y})=#{self.color_index} ({self.event})"
|
||||
Reference in New Issue
Block a user