82 lines
2.6 KiB
Python
82 lines
2.6 KiB
Python
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})"
|