Skip to content

Commit

Permalink
Add team views, add team demo data (#4)
Browse files Browse the repository at this point in the history
* Add team views, add team demo data

* Fix lint

* Remove leftover script imports

* Fix more lint

---------

Co-authored-by: Jay Qi <[email protected]>
  • Loading branch information
jayqi and jayqi authored Jul 20, 2024
1 parent 37c319a commit 61e0ec8
Show file tree
Hide file tree
Showing 19 changed files with 360 additions and 169 deletions.
48 changes: 48 additions & 0 deletions huntsite/management/commands/create_demo_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import random

from django.core.management.base import BaseCommand
from django.db import transaction

from huntsite.puzzles import factories as puzzle_factories
from huntsite.puzzles import services as puzzle_services
from huntsite.teams import factories as team_factories

PUZZLE_STARTED_PROP = 0.4
PUZZLE_SOLVED_PROP = 0.75
INCORRECTED_GUESS_MAX = 10


class Command(BaseCommand):
def handle(self, *args, **options):
with transaction.atomic():
# Puzzles
puzzles = []
for i in range(24):
puzzles.append(puzzle_factories.PuzzleFactory(calendar_entry__day=i + 1))

# Teams
users = []
for i in range(10):
users.append(
team_factories.UserFactory(
username=f"user{i}", password="hohohomerrychristmas!"
)
)

# Make guesses
for puzzle in puzzles:
for user in users:
if random.random() < PUZZLE_STARTED_PROP:
# Incorrect guesses
for _ in range(random.randint(0, INCORRECTED_GUESS_MAX)):
puzzle_services.guess_submit(
puzzle=puzzle,
user=user,
guess_text=puzzle_factories.answer_text_factory(),
)
if random.random() < PUZZLE_SOLVED_PROP:
puzzle_services.guess_submit(
puzzle=puzzle, user=user, guess_text=puzzle.answer
)

self.stdout.write(self.style.SUCCESS("create_demo_data complete."))
4 changes: 2 additions & 2 deletions huntsite/puzzles/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
]


def title_text_factory(instance) -> str:
def title_text_factory(instance=None) -> str:
nb = random.randint(1, 3)
return " ".join(fake.words(nb=nb)).title()


def answer_text_factory(instance) -> str:
def answer_text_factory(instance=None) -> str:
nb = random.randint(1, 2)
return " ".join(fake.words(nb=nb)).upper()

Expand Down
14 changes: 0 additions & 14 deletions huntsite/puzzles/management/commands/create_demo_data.py

This file was deleted.

Empty file removed huntsite/puzzles/signals.py
Empty file.
34 changes: 30 additions & 4 deletions huntsite/teams/factories.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,46 @@
import random

from django.conf import settings
from django.db.models.signals import post_save
import factory
from faker import Faker

fake = Faker()


def team_name_text_factory(instance=None) -> str:
nb = random.randint(1, 3)
return " ".join(fake.words(nb=nb)).title()


def team_members_text_factory(instance=None) -> str:
nb = random.randint(1, 3)
return ", ".join(fake.first_name() for _ in range(nb))


@factory.django.mute_signals(post_save)
class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = settings.AUTH_USER_MODEL

username = factory.Faker("user_name")
email = factory.Faker("email")
password = factory.Faker("password")

team_name = factory.Faker("word")
team_name = factory.lazy_attribute(team_name_text_factory)
profile = factory.RelatedFactory("huntsite.teams.factories.TeamProfileFactory", "user")

@factory.post_generation
def password(obj, create, extracted, **kwargs):
if extracted:
obj.set_password(extracted)
else:
obj.set_unusable_password()


@factory.django.mute_signals(post_save)
class TeamProfileFactory(factory.django.DjangoModelFactory):
class Meta:
model = "teams.Team"
model = "teams.TeamProfile"

user = factory.SubFactory(UserFactory)
user = factory.SubFactory(UserFactory, profile=None)
members = factory.lazy_attribute(team_members_text_factory)
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 5.0.4 on 2024-07-20 14:23

import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('teams', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='teamprofile',
name='members',
field=models.CharField(blank=True, help_text='List of team members.', max_length=255),
),
migrations.AlterField(
model_name='teamprofile',
name='user',
field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='profile', to=settings.AUTH_USER_MODEL),
),
migrations.DeleteModel(
name='TeamMember',
),
]
18 changes: 10 additions & 8 deletions huntsite/teams/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver


class User(AbstractUser):
Expand All @@ -15,16 +17,16 @@ class User(AbstractUser):


class TeamProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.PROTECT)
user = models.OneToOneField(
settings.AUTH_USER_MODEL, on_delete=models.PROTECT, related_name="profile"
)
members = models.CharField(max_length=255, blank=True, help_text="List of team members.")

created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)


class TeamMember(models.Model):
"""A person on a team."""

team = models.ForeignKey(TeamProfile, on_delete=models.CASCADE)

name = models.CharField(max_length=255)
email = models.EmailField(blank=True)
@receiver(post_save, sender=User)
def create_team_profile(sender, instance, created, **kwargs):
if created:
TeamProfile.objects.create(user=instance)
11 changes: 0 additions & 11 deletions huntsite/teams/signals.py

This file was deleted.

3 changes: 2 additions & 1 deletion huntsite/teams/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
import huntsite.teams.views as views

urlpatterns = [
path("", views.account_manage, name="account_manage"),
path("", views.team_list, name="team_list"),
path("<int:pk>/", views.team_detail, name="team_detail"),
]
30 changes: 21 additions & 9 deletions huntsite/teams/views.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
from django.contrib.auth.decorators import login_required
from django.template.response import TemplateResponse

from huntsite.teams.forms import AccountManagementForm
from huntsite.puzzles import selectors as puzzle_selectors
from huntsite.teams import models


@login_required
def account_manage(request):
"""View to manage the account of the user."""
user = request.user
def team_detail(request, pk: int):
"""View to display the team profile of the user."""
team = models.User.objects.select_related("profile").get(pk=pk)
solves = puzzle_selectors.solve_list(team)
context = {
"user": user,
"form": AccountManagementForm(instance=user),
"user": request.user,
"team": team,
"solves": solves,
"is_self": request.user == team,
}
return TemplateResponse(request, "account.html", context)
return TemplateResponse(request, "team_detail.html", context)


def team_list(request):
"""View to display a list of all teams."""
teams = models.User.objects.select_related("profile").all()
context = {
"user": request.user,
"teams": teams,
}
return TemplateResponse(request, "team_list.html", context)
3 changes: 2 additions & 1 deletion huntsite/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
path("", views.home_page, name="home"),
path("about/", views.about_page, name="about"),
path("puzzles/", include("huntsite.puzzles.urls")),
path("accounts/", include("huntsite.teams.urls")),
path("teams/", include("huntsite.teams.urls")),
path("accounts/", views.account_manage, name="account_manage"),
]
14 changes: 14 additions & 0 deletions huntsite/views.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
from django.contrib.auth.decorators import login_required
from django.template.response import TemplateResponse

from huntsite.teams.forms import AccountManagementForm


def home_page(request):
return TemplateResponse(request, "home.html", {})


def about_page(request):
return TemplateResponse(request, "about.html", {})


@login_required
def account_manage(request):
"""View to manage the account of the user."""
user = request.user
context = {
"user": user,
"form": AccountManagementForm(instance=user),
}
return TemplateResponse(request, "account.html", context)
Loading

0 comments on commit 61e0ec8

Please sign in to comment.