diff --git a/scavenger2022/core/admin.py b/scavenger2022/core/admin.py
index 44a0bd2..e0d0070 100644
--- a/scavenger2022/core/admin.py
+++ b/scavenger2022/core/admin.py
@@ -4,7 +4,6 @@
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _l
from django.urls import reverse
-from .models import *
from .forms import *
@@ -19,6 +18,18 @@ class InviteInLine(admin.StackedInline):
readonly_fields = ("invites",)
+class LogicPuzzleAdmin(admin.ModelAdmin):
+ list_display = (
+ "qr_index",
+ "hint",
+ )
+ search_fields = (
+ "hint",
+ "qr_index",
+ )
+ ordering = ("qr_index",)
+
+
class TeamAdmin(admin.ModelAdmin):
readonly_fields = ("current_qr_i", "path")
inlines = [
@@ -70,3 +81,4 @@ class UserAdmin(UserAdmin_):
admin.site.register(User, UserAdmin)
admin.site.register(Team, TeamAdmin)
admin.site.register(QrCode, QrCodeAdmin)
+admin.site.register(LogicPuzzleHint, LogicPuzzleAdmin)
diff --git a/scavenger2022/core/context_processors.py b/scavenger2022/core/context_processors.py
index 5acf991..77dad5f 100644
--- a/scavenger2022/core/context_processors.py
+++ b/scavenger2022/core/context_processors.py
@@ -2,12 +2,12 @@
import datetime
-def cutoff(request):
+def start(request):
return dict(
- CUTOFF=(cutoff := settings.CUTOFF),
- CUTOFF_BEFORE=cutoff > datetime.datetime.utcnow(),
- CUTOFF_UNTIL=cutoff - datetime.datetime.utcnow(),
- CUTON=(cuton := settings.CUTON),
- CUTON_BEFORE=cuton > datetime.datetime.utcnow(),
- CUTON_UNTIL=cuton - datetime.datetime.utcnow(),
+ START=(start := settings.START),
+ START_BEFORE=start > datetime.datetime.utcnow(),
+ START_UNTIL=start - datetime.datetime.utcnow(),
+ END=(end := settings.END),
+ END_BEFORE=end > datetime.datetime.utcnow(),
+ END_UNTIL=end - datetime.datetime.utcnow(),
)
diff --git a/scavenger2022/core/forms.py b/scavenger2022/core/forms.py
index 232bd5f..2939c4f 100644
--- a/scavenger2022/core/forms.py
+++ b/scavenger2022/core/forms.py
@@ -11,9 +11,8 @@ class Meta:
"members",
"is_active",
"is_open",
- "completed_qr_codes",
- "current_qr_code",
"solo",
+ "current_qr_i",
)
diff --git a/scavenger2022/core/migrations/0013_logicpuzzlehint_alter_qrcode_notes.py b/scavenger2022/core/migrations/0013_logicpuzzlehint_alter_qrcode_notes.py
new file mode 100644
index 0000000..a12b205
--- /dev/null
+++ b/scavenger2022/core/migrations/0013_logicpuzzlehint_alter_qrcode_notes.py
@@ -0,0 +1,38 @@
+# Generated by Django 4.1.3 on 2022-12-12 22:57
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("core", "0012_remove_user_chosen"),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name="LogicPuzzleHint",
+ fields=[
+ ("id", models.AutoField(primary_key=True, serialize=False)),
+ (
+ "hint",
+ models.TextField(
+ help_text="Hint for the logic puzzle", max_length=1024
+ ),
+ ),
+ ("notes", models.TextField(blank=True, help_text="Internal notes")),
+ (
+ "qr_index",
+ models.IntegerField(
+ help_text="The index of the QR code that this hint is for, that is everyone on their nth QR code will get same same hint (starting from 1)",
+ unique=True,
+ ),
+ ),
+ ],
+ ),
+ migrations.AlterField(
+ model_name="qrcode",
+ name="notes",
+ field=models.TextField(blank=True, help_text="Internal notes"),
+ ),
+ ]
diff --git a/scavenger2022/core/migrations/0014_merge_20221212_1857.py b/scavenger2022/core/migrations/0014_merge_20221212_1857.py
new file mode 100644
index 0000000..120a7de
--- /dev/null
+++ b/scavenger2022/core/migrations/0014_merge_20221212_1857.py
@@ -0,0 +1,13 @@
+# Generated by Django 4.1.3 on 2022-12-12 23:57
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("core", "0013_logicpuzzlehint_alter_qrcode_notes"),
+ ("core", "0013_remove_team_completed_qr_codes_and_more"),
+ ]
+
+ operations = []
diff --git a/scavenger2022/core/migrations/0015_alter_hint_options_alter_invite_team.py b/scavenger2022/core/migrations/0015_alter_hint_options_alter_invite_team.py
new file mode 100644
index 0000000..d1452b0
--- /dev/null
+++ b/scavenger2022/core/migrations/0015_alter_hint_options_alter_invite_team.py
@@ -0,0 +1,27 @@
+# Generated by Django 4.1.3 on 2022-12-13 00:16
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("core", "0014_merge_20221212_1857"),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name="hint",
+ options={"permissions": [("view_before_start", "Play game before start")]},
+ ),
+ migrations.AlterField(
+ model_name="invite",
+ name="team",
+ field=models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="invites",
+ to="core.team",
+ ),
+ ),
+ ]
diff --git a/scavenger2022/core/models.py b/scavenger2022/core/models.py
index a3d4db7..e23822c 100644
--- a/scavenger2022/core/models.py
+++ b/scavenger2022/core/models.py
@@ -1,9 +1,9 @@
import random
import secrets
+from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.db import models
-from django.conf import settings
class User(AbstractUser):
@@ -13,6 +13,14 @@ class User(AbstractUser):
"Team", related_name="members", on_delete=models.CASCADE, blank=True, null=True
)
+ @property
+ def in_team(self) -> bool:
+ try:
+ _ = self.team.solo
+ return True
+ except AttributeError:
+ return False
+
def generate_hint_key():
return secrets.token_urlsafe(48)
@@ -28,9 +36,7 @@ class QrCode(models.Model):
max_length=1024,
help_text="Location of the QR code. Be specific—it's internal",
)
- notes = models.TextField(
- help_text="Internal notes",
- )
+ notes = models.TextField(help_text="Internal notes", blank=True)
key = models.CharField(max_length=64, unique=True, default=generate_hint_key)
def __str__(self):
@@ -72,10 +78,12 @@ def __str__(self):
return self.hint
class Meta:
- permissions = [("view_before_cutoff", "Play game before cutoff")]
+ permissions = [("view_before_start", "Play game before start")]
class Team(models.Model):
+ """note, a user can currently be in multiple teams, in the future limit this to one per (class: Hunt)"""
+
# owner = models.ForeignKey(User, on_delete=models.PROTECT, related_name="teams_ownership") potentially add this later
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=64, unique=True, null=True)
@@ -94,10 +102,8 @@ def update_current_qr_i(self, i: int):
@property
def members(self):
- return User.objects.filter(team=self)
-
- def is_solo(self):
- return self.members.count() == 1
+ """Returns all members of the team, it's a related manager so to convert to queryset use .all() or filter it."""
+ return User.objects.filter(team=str(self.id))
def is_full(self):
return self.members.count() >= settings.MAX_TEAM_SIZE
@@ -107,12 +113,17 @@ def join(self, user: User):
return
if self.is_full():
raise IndexError("Team is full")
- self.members.add(user)
- self.save()
+ user.team = self
+ user.save()
def invites(self):
return Invite.objects.filter(team=self)
+ def get_qr_nth(self):
+ """Get the total amount of qr codes the team has completed"""
+ print(int(self.current_qr_i) + 1) # todo remove. this is just for debugging
+ return int(self.current_qr_i) + 1
+
def __str__(self):
return str(self.name)
@@ -125,3 +136,38 @@ class Invite(models.Model):
invites = models.IntegerField(default=0)
team = models.ForeignKey(Team, on_delete=models.CASCADE, related_name="invites")
code = models.CharField(max_length=32, unique=True)
+
+
+# class Hunt(models.Model):
+# id = models.AutoField(primary_key=True)
+# name = models.CharField(max_length=64)
+# start = models.DateTimeField()
+# end = models.DateTimeField()
+# is_active = models.BooleanField(default=False)
+# team_size = models.IntegerField(default=4, help_text="Max Team size")
+# final_qr_id = models.IntegerField(null=True, blank=True)
+#
+# def __str__(self):
+# return self.name
+
+
+class LogicPuzzleHint(models.Model):
+ id = models.AutoField(primary_key=True)
+ hint = models.TextField(
+ max_length=1024,
+ help_text="Hint for the logic puzzle",
+ )
+ notes = models.TextField(help_text="Internal notes", blank=True)
+ qr_index = models.IntegerField(
+ help_text="The index of the QR code that this hint is for, that is everyone on their nth QR code will get same same hint (starting from 1)",
+ unique=True,
+ )
+
+ # belongs_to = models.ForeignKey(Hunt, related_name="logic_puzzle_hunt", on_delete=models.CASCADE)
+
+ def __str__(self):
+ return str(self.hint)
+
+ @classmethod
+ def get_hint(cls, team: Team):
+ return cls.objects.get(qr_index=team.get_qr_nth()).hint
diff --git a/scavenger2022/core/static/core/base.css b/scavenger2022/core/static/core/base.css
index a3c54c0..7461d34 100644
--- a/scavenger2022/core/static/core/base.css
+++ b/scavenger2022/core/static/core/base.css
@@ -41,7 +41,7 @@ body > nav {
padding: 4px;
}
-#cutoff-header {
+#start-header {
text-align: center;
}
diff --git a/scavenger2022/core/templates/core/base.html b/scavenger2022/core/templates/core/base.html
index c279f1f..a28af01 100644
--- a/scavenger2022/core/templates/core/base.html
+++ b/scavenger2022/core/templates/core/base.html
@@ -9,20 +9,20 @@
- {% if CUTOFF_BEFORE or CUTON_BEFORE %}
+ {% if START_BEFORE or END_BEFORE %}
{% endif %}
@@ -77,10 +77,10 @@
Metropolis
-
-
+
+
Doodles
-
+
Scavenger Hunt (2022)
@@ -88,18 +88,18 @@
- {% if CUTOFF_BEFORE %}
-