Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions mittab/apps/tab/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,5 @@ class TeamAdmin(admin.ModelAdmin):
admin.site.register(models.NoShow)
admin.site.register(models.BreakingTeam)
admin.site.register(models.Outround, OutroundAdmin)
admin.site.register(models.JudgeJudgeScratch)
admin.site.register(models.TeamTeamScratch)
40 changes: 40 additions & 0 deletions mittab/apps/tab/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,46 @@ class Meta:
exclude = ["team", "judge"]


class JudgeJudgeScratchForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
judge_queryset = kwargs.pop("judge_queryset", Judge.objects.all())
super().__init__(*args, **kwargs)
self.fields["judge_one"].queryset = judge_queryset
self.fields["judge_two"].queryset = judge_queryset

def clean(self):
cleaned_data = super().clean()
judge_one = cleaned_data.get("judge_one")
judge_two = cleaned_data.get("judge_two")
if judge_one and judge_two and judge_one == judge_two:
raise forms.ValidationError("Pick two different judges")
return cleaned_data

class Meta:
model = JudgeJudgeScratch
fields = "__all__"


class TeamTeamScratchForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
team_queryset = kwargs.pop("team_queryset", Team.objects.all())
super().__init__(*args, **kwargs)
self.fields["team_one"].queryset = team_queryset
self.fields["team_two"].queryset = team_queryset

def clean(self):
cleaned_data = super().clean()
team_one = cleaned_data.get("team_one")
team_two = cleaned_data.get("team_two")
if team_one and team_two and team_one == team_two:
raise forms.ValidationError("Pick two different teams")
return cleaned_data

class Meta:
model = TeamTeamScratch
fields = "__all__"


class DebaterForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(DebaterForm, self).__init__(*args, **kwargs)
Expand Down
104 changes: 2 additions & 102 deletions mittab/apps/tab/judge_views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.http import HttpResponse
from django.shortcuts import render

from mittab.apps.tab.forms import JudgeForm, ScratchForm
from mittab.apps.tab.forms import JudgeForm
from mittab.apps.tab.helpers import redirect_and_flash_error, redirect_and_flash_success
from mittab.apps.tab.models import *
from mittab.libs.errors import *
Expand Down Expand Up @@ -103,8 +103,7 @@ def view_judge(request, judge_id):
form = JudgeForm(instance=judge)
judging_rounds = list(Round.objects.filter(judges=judge).select_related(
"gov_team", "opp_team", "room"))
base_url = f"/judge/{judge_id}/"
scratch_url = f"{base_url}scratches/view/"
scratch_url = f"/scratches/judge/{judge_id}/"
links = [(scratch_url, f"Scratches for {judge.name}")]
return render(
request, "tab/judge_detail.html", {
Expand Down Expand Up @@ -137,105 +136,6 @@ def enter_judge(request):
})


def add_scratches(request, judge_id, number_scratches):
try:
judge_id, number_scratches = int(judge_id), int(number_scratches)
except ValueError:
return redirect_and_flash_error(request, "Got invalid data")
try:
judge = Judge.objects.get(pk=judge_id)
except Judge.DoesNotExist:
return redirect_and_flash_error(request, "No such judge")

if request.method == "POST":
forms = [
ScratchForm(request.POST, prefix=str(i))
for i in range(1, number_scratches + 1)
]
all_good = True
for form in forms:
all_good = all_good and form.is_valid()
if all_good:
for form in forms:
form.save()
return redirect_and_flash_success(
request, "Scratches created successfully")
else:
forms = [
ScratchForm(
prefix=str(i),
initial={
"judge": judge_id,
"scratch_type": 0
}
)
for i in range(1, number_scratches + 1)
]
return render(
request, "common/data_entry_multiple.html", {
"forms": list(zip(forms, [None] * len(forms))),
"data_type": "Scratch",
"title": f"Adding Scratch(es) for {judge.name}"
})


def view_scratches(request, judge_id):
try:
judge_id = int(judge_id)
except ValueError:
return redirect_and_flash_error(request, "Received invalid data")

judge = Judge.objects.prefetch_related(
"scratches", "scratches__judge", "scratches__team"
).get(pk=judge_id)
scratches = judge.scratches.all()

all_teams = Team.objects.all()
all_judges = Judge.objects.all()

if request.method == "POST":
forms = [
ScratchForm(
request.POST,
prefix=str(i + 1),
instance=scratches[i],
team_queryset=all_teams,
judge_queryset=all_judges
)
for i in range(len(scratches))
]
all_good = True
for form in forms:
all_good = all_good and form.is_valid()
if all_good:
for form in forms:
form.save()
return redirect_and_flash_success(
request, "Scratches created successfully")
else:
forms = [
ScratchForm(
prefix=str(i + 1),
instance=scratches[i],
team_queryset=all_teams,
judge_queryset=all_judges
)
for i in range(len(scratches))
]
delete_links = [
f"/judge/{judge_id}/scratches/delete/{scratches[i].id}"
for i in range(len(scratches))
]
links = [(f"/judge/{judge_id}/scratches/add/1/", "Add Scratch")]

return render(
request, "common/data_entry_multiple.html", {
"forms": list(zip(forms, delete_links)),
"data_type": "Scratch",
"links": links,
"title": f"Viewing Scratch Information for {judge.name}"
})

def download_judge_codes(request):
codes = [
f"{getattr(judge, 'name', 'Unknown')}: {getattr(judge, 'ballot_code', 'N/A')}"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Generated by Django 3.2.25 on 2025-10-29 16:17

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


class Migration(migrations.Migration):

dependencies = [
('tab', '0030_auto_20251024_1855'),
]

operations = [
migrations.CreateModel(
name='TeamTeamScratch',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('team_one', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='team_scratch_primary', to='tab.team')),
('team_two', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='team_scratch_secondary', to='tab.team')),
],
options={
'verbose_name_plural': 'team scratches',
'unique_together': {('team_one', 'team_two')},
},
),
migrations.CreateModel(
name='JudgeJudgeScratch',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('judge_one', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='judge_scratch_primary', to='tab.judge')),
('judge_two', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='judge_scratch_secondary', to='tab.judge')),
],
options={
'verbose_name_plural': 'judge scratches',
'unique_together': {('judge_one', 'judge_two')},
},
),
]
64 changes: 64 additions & 0 deletions mittab/apps/tab/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,70 @@ def __str__(self):
s_type = ("Team", "Tab")[self.scratch_type]
return f"{self.team} <={s_type}=> {self.judge}"

class JudgeJudgeScratch(models.Model):
judge_one = models.ForeignKey(
"Judge",
related_name="judge_scratch_primary",
on_delete=models.CASCADE,
)
judge_two = models.ForeignKey(
"Judge",
related_name="judge_scratch_secondary",
on_delete=models.CASCADE,
)

class Meta:
unique_together = ("judge_one", "judge_two")
verbose_name_plural = "judge scratches"

def __str__(self):
return f"{self.judge_one} <=> {self.judge_two}"

def clean(self):
if self.judge_one and self.judge_two and self.judge_one == self.judge_two:
raise ValidationError("Judge scratches must involve two distinct judges")

def save(self, *args, **kwargs):
if self.judge_one and self.judge_two:
if self.judge_one == self.judge_two:
raise ValidationError(
"Judge scratches must involve two distinct judges")
if self.judge_one.id > self.judge_two.id:
self.judge_one, self.judge_two = self.judge_two, self.judge_one
super().save(*args, **kwargs)


class TeamTeamScratch(models.Model):
team_one = models.ForeignKey(
"Team",
related_name="team_scratch_primary",
on_delete=models.CASCADE,
)
team_two = models.ForeignKey(
"Team",
related_name="team_scratch_secondary",
on_delete=models.CASCADE,
)

class Meta:
unique_together = ("team_one", "team_two")
verbose_name_plural = "team scratches"

def __str__(self):
return f"{self.team_one} <=> {self.team_two}"

def clean(self):
if self.team_one and self.team_two and self.team_one == self.team_two:
raise ValidationError("Team scratches must involve two distinct teams")

def save(self, *args, **kwargs):
if self.team_one and self.team_two:
if self.team_one == self.team_two:
raise ValidationError("Team scratches must involve two distinct teams")
if self.team_one.id > self.team_two.id:
self.team_one, self.team_two = self.team_two, self.team_one
super().save(*args, **kwargs)


class Room(models.Model):
name = models.CharField(max_length=30, unique=True)
Expand Down
Loading