diff --git a/leagues/__init__.py b/leagues/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/leagues/admin.py b/leagues/admin.py new file mode 100644 index 000000000..8c38f3f3d --- /dev/null +++ b/leagues/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/leagues/apps.py b/leagues/apps.py new file mode 100644 index 000000000..4abf4fa9d --- /dev/null +++ b/leagues/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class LeaguesConfig(AppConfig): + name = 'leagues' diff --git a/leagues/forms.py b/leagues/forms.py new file mode 100644 index 000000000..e69de29bb diff --git a/leagues/migrations/0001_initial.py b/leagues/migrations/0001_initial.py new file mode 100644 index 000000000..3fe93b481 --- /dev/null +++ b/leagues/migrations/0001_initial.py @@ -0,0 +1,82 @@ +# Generated by Django 2.2.12 on 2020-05-16 00:48 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('matches', '0022_auto_20200410_1506'), + ('teams', '0008_team_image'), + ('singletournaments', '0021_auto_20200420_0007'), + ] + + operations = [ + migrations.CreateModel( + name='LeagueSettings', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(default='League Ruleset', max_length=50)), + ('ot_losses', models.BooleanField(default=True)), + ('pts_ot_loss', models.PositiveSmallIntegerField(default=1)), + ('ot_wins', models.BooleanField(default=False)), + ('pts_ot_win', models.PositiveSmallIntegerField(default=3)), + ('pts_win', models.PositiveSmallIntegerField(default=3)), + ('pts_loss', models.PositiveSmallIntegerField(default=0)), + ('allow_tie', models.BooleanField(default=False)), + ('num_games', models.PositiveIntegerField(default=10)), + ('auto_schedule', models.BooleanField(default=False)), + ('record_format', models.CharField(choices=[(1, 'W-L-OTL'), (2, 'W-L-T'), (3, 'W-L-OTW-OTL'), (4, 'W-L-OTW-OTL-OTT'), (5, 'W-L')], default='W-L-OTL', max_length=20)), + ('num_divisons', models.PositiveSmallIntegerField(default=2)), + ('max_division_size', models.PositiveSmallIntegerField(default=5)), + ], + ), + migrations.CreateModel( + name='LeagueTeam', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('wins', models.PositiveSmallIntegerField(default=0)), + ('losses', models.PositiveSmallIntegerField(default=0)), + ('ot_losses', models.PositiveSmallIntegerField(default=0)), + ('ot_wins', models.PositiveSmallIntegerField(default=0)), + ('ties', models.PositiveSmallIntegerField(default=0)), + ('team', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='league_team', to='teams.Team')), + ], + ), + migrations.CreateModel( + name='LeagueDivision', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50, null=True)), + ('games', models.ManyToManyField(blank=True, to='matches.Match')), + ('teams', models.ManyToManyField(blank=True, to='leagues.LeagueTeam')), + ], + ), + migrations.CreateModel( + name='League', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(default='League Name', max_length=50)), + ('active', models.BooleanField(default=False)), + ('info', models.TextField(default='No information provided')), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ('image', models.ImageField(blank=True, upload_to='league_images')), + ('teamformat', models.SmallIntegerField(choices=[(0, '1v1'), (1, '2v2'), (2, '3v3'), (3, '4v4'), (4, '5v5'), (5, '6v6')], default=1)), + ('bestof', models.SmallIntegerField(choices=[(0, 'Best of 1'), (1, 'Best of 3'), (2, 'Best of 5'), (3, 'Best of 7'), (4, 'Best of 9')], default=0)), + ('allow_register', models.BooleanField(default=False)), + ('open_register', models.DateTimeField()), + ('close_register', models.DateTimeField()), + ('start', models.DateTimeField()), + ('divisions', models.ManyToManyField(blank=True, to='leagues.LeagueDivision')), + ('game', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='league_game', to='matches.GameChoice')), + ('platform', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='league_platform', to='matches.PlatformChoice')), + ('ruleset', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='league_ruleset', to='singletournaments.SingleTournamentRuleset')), + ('settings', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='league_settings', to='leagues.LeagueSettings')), + ('sport', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='league_sport', to='matches.SportChoice')), + ], + ), + ] diff --git a/leagues/migrations/0002_league_maps.py b/leagues/migrations/0002_league_maps.py new file mode 100644 index 000000000..5d0a053f5 --- /dev/null +++ b/leagues/migrations/0002_league_maps.py @@ -0,0 +1,20 @@ +# Generated by Django 2.2.12 on 2020-05-16 00:55 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('matches', '0022_auto_20200410_1506'), + ('leagues', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='league', + name='maps', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='league_maps', to='matches.MapPoolChoice'), + ), + ] diff --git a/leagues/migrations/0003_auto_20200515_2139.py b/leagues/migrations/0003_auto_20200515_2139.py new file mode 100644 index 000000000..84e7b6b03 --- /dev/null +++ b/leagues/migrations/0003_auto_20200515_2139.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.12 on 2020-05-16 01:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('leagues', '0002_league_maps'), + ] + + operations = [ + migrations.AddField( + model_name='league', + name='credits', + field=models.PositiveSmallIntegerField(default=0), + ), + migrations.AddField( + model_name='league', + name='size', + field=models.PositiveSmallIntegerField(default=8), + ), + ] diff --git a/leagues/migrations/0004_auto_20200515_2205.py b/leagues/migrations/0004_auto_20200515_2205.py new file mode 100644 index 000000000..a5e3b1e05 --- /dev/null +++ b/leagues/migrations/0004_auto_20200515_2205.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.12 on 2020-05-16 02:05 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('leagues', '0003_auto_20200515_2139'), + ] + + operations = [ + migrations.RenameField( + model_name='leaguesettings', + old_name='num_divisons', + new_name='num_divisions', + ), + ] diff --git a/leagues/migrations/0005_remove_leaguesettings_record_format.py b/leagues/migrations/0005_remove_leaguesettings_record_format.py new file mode 100644 index 000000000..a5596d88f --- /dev/null +++ b/leagues/migrations/0005_remove_leaguesettings_record_format.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.12 on 2020-05-16 02:23 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('leagues', '0004_auto_20200515_2205'), + ] + + operations = [ + migrations.RemoveField( + model_name='leaguesettings', + name='record_format', + ), + ] diff --git a/leagues/migrations/0006_league_disable_userreport.py b/leagues/migrations/0006_league_disable_userreport.py new file mode 100644 index 000000000..a12fd4a35 --- /dev/null +++ b/leagues/migrations/0006_league_disable_userreport.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.12 on 2020-05-16 22:08 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('leagues', '0005_remove_leaguesettings_record_format'), + ] + + operations = [ + migrations.AddField( + model_name='league', + name='disable_userreport', + field=models.BooleanField(default=False), + ), + ] diff --git a/leagues/migrations/0007_auto_20200516_1809.py b/leagues/migrations/0007_auto_20200516_1809.py new file mode 100644 index 000000000..9d9b10c8b --- /dev/null +++ b/leagues/migrations/0007_auto_20200516_1809.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.12 on 2020-05-16 22:09 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('leagues', '0006_league_disable_userreport'), + ] + + operations = [ + migrations.RenameField( + model_name='league', + old_name='credits', + new_name='req_credits', + ), + ] diff --git a/leagues/migrations/0008_auto_20200516_1814.py b/leagues/migrations/0008_auto_20200516_1814.py new file mode 100644 index 000000000..64b19fe05 --- /dev/null +++ b/leagues/migrations/0008_auto_20200516_1814.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.12 on 2020-05-16 22:14 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('leagues', '0007_auto_20200516_1809'), + ] + + operations = [ + migrations.AlterField( + model_name='league', + name='sport', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='league_sport', to='matches.SportChoice'), + ), + ] diff --git a/leagues/migrations/0009_auto_20200516_1815.py b/leagues/migrations/0009_auto_20200516_1815.py new file mode 100644 index 000000000..707d93cbb --- /dev/null +++ b/leagues/migrations/0009_auto_20200516_1815.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.12 on 2020-05-16 22:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('leagues', '0008_auto_20200516_1814'), + ] + + operations = [ + migrations.AlterField( + model_name='league', + name='divisions', + field=models.ManyToManyField(blank=True, null=True, to='leagues.LeagueDivision'), + ), + ] diff --git a/leagues/migrations/0010_auto_20200516_1817.py b/leagues/migrations/0010_auto_20200516_1817.py new file mode 100644 index 000000000..f345b55ba --- /dev/null +++ b/leagues/migrations/0010_auto_20200516_1817.py @@ -0,0 +1,29 @@ +# Generated by Django 2.2.12 on 2020-05-16 22:17 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('leagues', '0009_auto_20200516_1815'), + ] + + operations = [ + migrations.AlterField( + model_name='league', + name='divisions', + field=models.ManyToManyField(blank=True, to='leagues.LeagueDivision'), + ), + migrations.AlterField( + model_name='league', + name='game', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='league_game', to='matches.GameChoice'), + ), + migrations.AlterField( + model_name='league', + name='platform', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='league_platform', to='matches.PlatformChoice'), + ), + ] diff --git a/leagues/migrations/0011_auto_20200516_1817.py b/leagues/migrations/0011_auto_20200516_1817.py new file mode 100644 index 000000000..fab41006a --- /dev/null +++ b/leagues/migrations/0011_auto_20200516_1817.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.12 on 2020-05-16 22:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('leagues', '0010_auto_20200516_1817'), + ] + + operations = [ + migrations.AlterField( + model_name='league', + name='image', + field=models.ImageField(blank=True, null=True, upload_to='league_images'), + ), + ] diff --git a/leagues/migrations/0012_auto_20200516_1818.py b/leagues/migrations/0012_auto_20200516_1818.py new file mode 100644 index 000000000..3c998c9ba --- /dev/null +++ b/leagues/migrations/0012_auto_20200516_1818.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.12 on 2020-05-16 22:18 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('leagues', '0011_auto_20200516_1817'), + ] + + operations = [ + migrations.AlterField( + model_name='league', + name='maps', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='league_maps', to='matches.MapPoolChoice'), + ), + ] diff --git a/leagues/migrations/0013_leaguesettings_auto_matchup.py b/leagues/migrations/0013_leaguesettings_auto_matchup.py new file mode 100644 index 000000000..f645200f2 --- /dev/null +++ b/leagues/migrations/0013_leaguesettings_auto_matchup.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.12 on 2020-05-26 17:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('leagues', '0012_auto_20200516_1818'), + ] + + operations = [ + migrations.AddField( + model_name='leaguesettings', + name='auto_matchup', + field=models.BooleanField(default=False), + ), + ] diff --git a/leagues/migrations/0014_auto_20200530_1901.py b/leagues/migrations/0014_auto_20200530_1901.py new file mode 100644 index 000000000..f189390d4 --- /dev/null +++ b/leagues/migrations/0014_auto_20200530_1901.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.12 on 2020-05-30 23:01 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('leagues', '0013_leaguesettings_auto_matchup'), + ] + + operations = [ + migrations.RenameField( + model_name='leaguedivision', + old_name='games', + new_name='matches', + ), + ] diff --git a/leagues/migrations/0015_auto_20200726_1705.py b/leagues/migrations/0015_auto_20200726_1705.py new file mode 100644 index 000000000..ed99033cb --- /dev/null +++ b/leagues/migrations/0015_auto_20200726_1705.py @@ -0,0 +1,28 @@ +# Generated by Django 2.2.14 on 2020-07-26 21:05 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('leagues', '0014_auto_20200530_1901'), + ] + + operations = [ + migrations.AddField( + model_name='league', + name='prize1', + field=models.CharField(default='no prize specified', max_length=50), + ), + migrations.AddField( + model_name='league', + name='prize2', + field=models.CharField(default='no prize specified', max_length=50), + ), + migrations.AddField( + model_name='league', + name='prize3', + field=models.CharField(default='no prize specified', max_length=50), + ), + ] diff --git a/leagues/migrations/0016_league_teams.py b/leagues/migrations/0016_league_teams.py new file mode 100644 index 000000000..78948d236 --- /dev/null +++ b/leagues/migrations/0016_league_teams.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.14 on 2020-07-26 21:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('leagues', '0015_auto_20200726_1705'), + ] + + operations = [ + migrations.AddField( + model_name='league', + name='teams', + field=models.ManyToManyField(blank=True, to='leagues.LeagueTeam'), + ), + ] diff --git a/leagues/migrations/__init__.py b/leagues/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/leagues/models.py b/leagues/models.py new file mode 100644 index 000000000..ae44f42f2 --- /dev/null +++ b/leagues/models.py @@ -0,0 +1,112 @@ +from django.db import models +from teams.models import Team +from matches.models import Match, GameChoice, PlatformChoice, MapPoolChoice, MapChoice, SportChoice +from matches.settings import TEAMFORMAT_CHOICES, MAPFORMAT_CHOICES +from singletournaments.models import SingleTournamentRuleset + + +# a way to create default values for a field over multiple seasons +class LeagueSettings(models.Model): + name = models.CharField(default='League Ruleset', max_length=50) + # whether or not to keep track of Overtime Losses in a separate column + ot_losses = models.BooleanField(default=True) + # amount of points to award a team for an overtime loss + pts_ot_loss = models.PositiveSmallIntegerField(default=1) + # whether or not to keep track of Overtime wins in a separate column + ot_wins = models.BooleanField(default=False) + pts_ot_win = models.PositiveSmallIntegerField(default=3) + # amount of points to award teams for a win + pts_win = models.PositiveSmallIntegerField(default=3) + pts_loss = models.PositiveSmallIntegerField(default=0) + # whether or not to allow tie + allow_tie = models.BooleanField(default=False) + # number of games each team plays during the regular season + num_games = models.PositiveIntegerField(default=10) + # automatically schedule games. TODO - implement auto schedule + auto_schedule = models.BooleanField(default=False) + # automatically generate matches, enabling this will create matches but will not set match times + auto_matchup = models.BooleanField(default=False) + # W=Win, L=Loss, OTL=Overtime Loss, T=Tie, OTW=Overtime Win, OTT=Overtime Tie + RECORD_FORMAT_CHOICES = ( + (1, "W-L-OTL"), + (2, "W-L-T"), + (3, "W-L-OTW-OTL"), + (4, "W-L-OTW-OTL-OTT"), + (5, "W-L"), + ) + # record format to show on front end + # record_format = models.CharField(choices=RECORD_FORMAT_CHOICES, default=1, max_length=20) + # number of divisions to break teams into + num_divisions = models.PositiveSmallIntegerField(default=2) + # max amount of teams to allow into a division + max_division_size = models.PositiveSmallIntegerField(default=5) + + def __str__(self): + return self.name + + +class LeagueTeam(models.Model): + team = models.ForeignKey(Team, related_name='league_team', on_delete=models.PROTECT) + wins = models.PositiveSmallIntegerField(default=0) + losses = models.PositiveSmallIntegerField(default=0) + ot_losses = models.PositiveSmallIntegerField(default=0) + ot_wins = models.PositiveSmallIntegerField(default=0) + ties = models.PositiveSmallIntegerField(default=0) + + def __str__(self): + return self.team.name + + +class LeagueDivision(models.Model): + # name for the league division - set to null in case admins wish to manually change it + name = models.CharField(null=True, max_length=50) + # teams that are in that division, allow it to be empty + teams = models.ManyToManyField(LeagueTeam, blank=True) + # games that are to be played and have been played in that division, blank until all matches are generated + matches = models.ManyToManyField(Match, blank=True) + + def __str__(self): + if self.name is None: + return "Division "+str(self.pk) + else: + return self.name + + +class League(models.Model): + name = models.CharField(default="League Name", max_length=50) + settings = models.ForeignKey(LeagueSettings, related_name="league_settings", on_delete=models.PROTECT) + ruleset = models.ForeignKey(SingleTournamentRuleset, related_name="league_ruleset", on_delete=models.PROTECT) + # if set to true the league will display on the front page, false and it will not + active = models.BooleanField(default=False) + info = models.TextField(default="No information provided") + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) + divisions = models.ManyToManyField(LeagueDivision, blank=True) + platform = models.ForeignKey(PlatformChoice, related_name='league_platform', on_delete=models.PROTECT, null=True, blank=True) + game = models.ForeignKey(GameChoice, related_name='league_game', on_delete=models.PROTECT, null=True, blank=True) + sport = models.ForeignKey(SportChoice, related_name='league_sport', on_delete=models.PROTECT, null=True, blank=True) + image = models.ImageField(upload_to='league_images', blank=True, null=True) + # team format, ex 1v1, 2v2, 3v3, 4v4, 5v5, 6v6 + teamformat = models.SmallIntegerField(choices=TEAMFORMAT_CHOICES, default=1) + # by default its a best of 1. Not sure if we need this here. Finals might be best of 3, etc in + # the future possibly. TBD. For now this will work though. + bestof = models.SmallIntegerField(choices=MAPFORMAT_CHOICES, default=0) + # manually open registration even if outside registration window + allow_register = models.BooleanField(default=False) + # when does registration open, and when does it close? specified when created in staff panel + open_register = models.DateTimeField() + # dont allow people to join once registration is closed + close_register = models.DateTimeField() + # when is the league going to start? + start = models.DateTimeField() + maps = models.ForeignKey(MapPoolChoice, related_name='league_maps', on_delete=models.PROTECT, null=True, blank=True) + # the amount of credits that should be charged when joining + req_credits = models.PositiveSmallIntegerField(default=0) + size = models.PositiveSmallIntegerField(default=8) + disable_userreport = models.BooleanField(default=False) + prize1 = models.CharField(default='no prize specified', max_length=50) + prize2 = models.CharField(default='no prize specified', max_length=50) + prize3 = models.CharField(default='no prize specified', max_length=50) + teams = models.ManyToManyField(LeagueTeam, blank=True) + + diff --git a/leagues/tests.py b/leagues/tests.py new file mode 100644 index 000000000..7ce503c2d --- /dev/null +++ b/leagues/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/leagues/urls.py b/leagues/urls.py new file mode 100644 index 000000000..8b49435a7 --- /dev/null +++ b/leagues/urls.py @@ -0,0 +1,17 @@ +from django.contrib.auth.decorators import login_required +from django.urls import path + +from . import views as views + +app_name = 'leagues' + +urlpatterns = [ + path('', login_required(views.list_leagues), name='list'), + path('/', login_required(views.detail_league), name='detail'), + path('/teams/', login_required(views.detail_league_teams), name='teams'), + path('/divisions/', login_required(views.list_league_divisions), name='list_divisions'), + path('/divisions//', login_required(views.detail_league_division), name='detail_division'), + path('/rules/', login_required(views.detail_league_rules), name='rules'), + path('/join/', login_required(views.join_league), name='join'), + path('/leave/', login_required(views.leave_league), name='leave'), +] diff --git a/leagues/views.py b/leagues/views.py new file mode 100644 index 000000000..2aa46b8da --- /dev/null +++ b/leagues/views.py @@ -0,0 +1,49 @@ +from django.shortcuts import render, get_object_or_404 +from django.contrib import messages +from django.shortcuts import redirect +from .models import League, LeagueDivision, LeagueSettings + + +def list_leagues(request): + leagues = League.objects.filter(active=True) + return render(request, 'leagues/leagues_list.html', {'leagues': leagues}) + + +def detail_league(request, pk): + league = get_object_or_404(League) + teams = league.teams.all() + return render(request, 'leagues/league_detail.html', {'league': league, 'teams': teams}) + + +def join_league(request, pk): + pass + + +def leave_league(request, pk): + pass + + +def detail_league_teams(request, pk): + pass + + +def list_league_divisions(request, pk): + league = get_object_or_404(League) + if league.divisions.count() == 0: + messages.warning(request, "There are no divisions for this league yet") + return redirect('league:detail', pk) + else: + divisions = league.divisions.all() + + return render(request, 'leagues/league_divisions.html', {'league': league, 'divisions': divisions}) + + +def detail_league_division(request, pk, divid): + league = get_object_or_404(League) + division = LeagueDivision.objects.get(pk=divid) + matches = division.matches.all() + return render(request, 'leagues/league_division.html', {'league': league, 'division': division, 'matches': matches}) + + +def detail_league_rules(request, pk): + pass diff --git a/matches/models.py b/matches/models.py index d35c56ac0..87dfacd29 100644 --- a/matches/models.py +++ b/matches/models.py @@ -101,6 +101,9 @@ class Match(models.Model): team2reportedwinner = models.ForeignKey(Team, related_name='team2reportedwinner', on_delete=models.SET_NULL, null=True, blank=True) + # TODO: implement datetime field for matches + #datetime = models.DateTimeField(null=True) + info = models.TextField(default="Match Info: ") disputed = models.BooleanField(default=False) diff --git a/olly/base_settings.py b/olly/base_settings.py index 33cf456f6..925c59121 100644 --- a/olly/base_settings.py +++ b/olly/base_settings.py @@ -63,6 +63,8 @@ # wagers 'wagers', + 'leagues', + # ip package 'ipware', @@ -156,4 +158,4 @@ LOGIN_REDIRECT_URL = '/' LOGIN_URL = '/login/' -SITE_VERSION = "0.8.1" +SITE_VERSION = "0.9.0" diff --git a/olly/urls.py b/olly/urls.py index 1dafc88c7..02e6720f7 100644 --- a/olly/urls.py +++ b/olly/urls.py @@ -41,7 +41,8 @@ path('staff/', include('staff.urls', namespace='staff')), path('tournaments/', include('singletournaments.urls', namespace='singletournaments')), path('matches/', include('matches.urls', namespace='matches')), - path('wagers/', include('wagers.urls', namespace='wagers')) + path('wagers/', include('wagers.urls', namespace='wagers')), + path('leagues/', include('leagues.urls', namespace='league')) ] #if settings.DEBUG is True: # urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/project-templates/leagues/league_detail.html b/project-templates/leagues/league_detail.html new file mode 100644 index 000000000..40e9b4c79 --- /dev/null +++ b/project-templates/leagues/league_detail.html @@ -0,0 +1,188 @@ +{% extends "base.html" %} +{% load static %} + +{% block head %} + {{ tournament.name }} Details - {{ SITE_NAME }} +{% endblock %} + +{% block body %} + + + + +
+ +
+
+
+ {% if not user.is_anonymous %} +

Back to + League list

+ {% else %} + Back to home + {% endif %} +
+
+ +
+ + +
+
+ +
+
+
+ {% if ESPORTS_MODE %} +
+
+
+

PLATFORM

+ {{ league.platform.name }} +
+
+
+ {% endif %} +
+
+
+

Format

+ {% if league.teamformat == 0 %} + 1v1 + {% elif league.teamformat == 1 %} + 2v2 + {% elif league.teamformat == 2 %} + 3v3 + {% elif league.teamformat == 3 %} + 4v4 + {% elif league.teamformat == 4 %} + 5v5 + {% elif league.teamformat == 5 %} + 6v6 + {% endif %} +
+
+
+
+
+
+

Registration Opens->Closes

+ + -> + +
+
+
+
+
+
+

Registration Fee

+ {{ league.req_credits }} credits +
+
+
+
+ {{ league.info|linebreaksbr }} + + +
+ + + +
+ +
+ {% if teams.count == 0 %} +

There are no teams in this league!

+ {% endif %} + {% for team in teams %} +
+
+
+
+ +
+
+
+ {{ team.team.name }}
+ {{ team.team.num_matchwin }} match wins
+
+ +
+
+
+ {% endfor %} + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + + + + + + + + +{% endblock %} diff --git a/project-templates/leagues/league_division.html b/project-templates/leagues/league_division.html new file mode 100644 index 000000000..668336744 --- /dev/null +++ b/project-templates/leagues/league_division.html @@ -0,0 +1,32 @@ +{% extends "base.html" %} +{% load static %} + +{% block head %} + Division #{{ division.id }} Matches - {{ SITE_NAME }} +{% endblock %} + + +{% block body %} + + + + + + + + + + + {% for match in matches %} + + + + + + + + {% endfor %} + + +
Match IDHome TeamAway Team
{{ match.id }}{{ match.hometeam.name }}{{ match.awayteam.name }}
+{% endblock %} \ No newline at end of file diff --git a/project-templates/leagues/league_divisions.html b/project-templates/leagues/league_divisions.html new file mode 100644 index 000000000..dde91b513 --- /dev/null +++ b/project-templates/leagues/league_divisions.html @@ -0,0 +1,41 @@ +{% extends "base.html" %} +{% load static %} + +{% block head %} + {{ league.name }} Divisions - {{ SITE_NAME }} +{% endblock %} + + +{% block body %} + + + {% for division in divisions %} + + + + + + + + + + + + +
Division NameDivision ID
{{ division.name }}{{ division.pk }}
+ + + + + + {% for team in division.teams.all %} + + + + {% endfor %} +
Teams in {{ division.name }}
{{ team.team.name }}
+ +
+ {% endfor %} + +{% endblock %} \ No newline at end of file diff --git a/project-templates/leagues/league_rules.html b/project-templates/leagues/league_rules.html new file mode 100644 index 000000000..e69de29bb diff --git a/project-templates/leagues/league_teams.html b/project-templates/leagues/league_teams.html new file mode 100644 index 000000000..e69de29bb diff --git a/project-templates/leagues/leagues_list.html b/project-templates/leagues/leagues_list.html new file mode 100644 index 000000000..b3375d683 --- /dev/null +++ b/project-templates/leagues/leagues_list.html @@ -0,0 +1,126 @@ +{% extends "base.html" %} +{% load static %} + +{% block head %} + Leagues - {{ SITE_NAME }} +{% endblock %} + +{% block body %} + + + +
+ + + + + +
+ + +
+
+
+
+ + + {% if leagues.count == 0 %} + No Leagues yet! + {% endif %} + {% for league in leagues %} +
+
+ {% else %} + {{ league.sport.name }} + {% endif %} +
{{ league.name }}
+
+
    + {% if ESPORTS_MODE %} +
  • Platform: {{ league.platform.name }}
  • + {% endif %} +
  • Starts: {{ league.start }}
  • +
  • Teams: {{ league.teams.count }}/{{ league.size }}
  • + {% if ESPORTS_MODE %} +
  • Game: {{ league.game.name }}
  • + {% else %} +
  • Sport: {{ league.sport.name }}
  • + {% endif %} +
  • {% if league.teamformat == 0 %} + 1v1 + {% elif league.teamformat == 1 %} + 2v2 + {% elif league.teamformat == 2 %} + 3v3 + {% elif league.teamformat == 3 %} + 4v4 + {% elif league.teamformat == 4 %} + 5v5 + {% elif league.teamformat == 5 %} + 6v6 + {% endif %}
  • +
+
    + +
  • Registration Opens: (Local time) + +
  • +
  • Registration Closes (Local time) + +
  • +
  • Registration Fee: {{ league.req_credits }}
  • +
+ JOIN LEAGUE +
+ {% endfor %} + + +
+
+
+
+ +
+
+ + + + + + + + + + + + + +{% endblock %} \ No newline at end of file diff --git a/project-templates/staff/leagues/league_addmatch.html b/project-templates/staff/leagues/league_addmatch.html new file mode 100644 index 000000000..a35d20b60 --- /dev/null +++ b/project-templates/staff/leagues/league_addmatch.html @@ -0,0 +1,49 @@ +{% extends 'staff/staffbase.html' %} + +{% load static %} + +{% block title %} + Add match to Division #{{ division.id }} +{% endblock %} +{% block body %} + + + + + + + {% if form.errors %} + {% for field in form %} + {% for error in field.errors %} +
+ {{ error|escape }} +
+ {% endfor %} + {% endfor %} + {% for error in form.non_field_errors %} +
+ {{ error|escape }} +
+ {% endfor %} + {% endif %} +

Return to league list

+ +
+ {% csrf_token %} + {{ field.errors }} + + + {{ form.awayteam }} +
+ + + {{ form.hometeam }} + + + +
+ + +{% endblock %} \ No newline at end of file diff --git a/project-templates/staff/leagues/league_create.html b/project-templates/staff/leagues/league_create.html new file mode 100644 index 000000000..f3aca5c2d --- /dev/null +++ b/project-templates/staff/leagues/league_create.html @@ -0,0 +1,169 @@ +{% extends 'staff/staffbase.html' %} + +{% load static %} + +{% block title %} + Create League +{% endblock %} +{% block body %} + + + + + + + + + {% if form.errors %} + {% for field in form %} + {% for error in field.errors %} +
+ {{ error|escape }} +
+ {% endfor %} + {% endfor %} + {% for error in form.non_field_errors %} +
+ {{ error|escape }} +
+ {% endfor %} + {% endif %} +

Return to league list

+
+ Create a new ruleset +
+ Create League Settings + + +
+ {% csrf_token %} + {{ field.errors }} + + + {{ form.name }} +
+ + + {{ form.settings }} +
+ + + {{ form.teamformat }} +
+ + + {{ form.bestof }} +
+ + +
+
+ + {{ form.open_register }} +
+
+ +
+
+ + {{ form.close_register }} +
+
+ + + {{ form.req_credits }} +
+ + + {{ form.size }} +
+ + {% if ESPORTS_MODE %} + + {{ form.platform }} +
+ + + {{ form.game }} +
+ {% endif %} + + {% if not ESPORTS_MODE %} + + {{ form.sport }} +
+ {% endif %} + + {% if ESPORTS_MODE %} + + {{ form.maps }} +
+ {% endif %} + +
+
+ + {{ form.start }} +
+
+ + + {{ form.image }} +
+ + + {{ form.disable_userreport }} +
+ + + {{ form.info }} +
+ + + {{ form.teams }} +
+ + + {{ form.prize1 }} +
+ + + {{ form.prize2 }} +
+ + + {{ form.prize3 }} +
+ + + {{ form.active }} +
+ + + {{ form.ruleset }} +
+ + + {{ form.allow_register }} +
+ + +
+ + + +{% endblock %} \ No newline at end of file diff --git a/project-templates/staff/leagues/league_detail.html b/project-templates/staff/leagues/league_detail.html new file mode 100644 index 000000000..10f1dcd85 --- /dev/null +++ b/project-templates/staff/leagues/league_detail.html @@ -0,0 +1,136 @@ +{% extends 'staff/staffbase.html' %} +{% load static %} + +{% block title %} + League #{{ league.id }} +{% endblock %} + +{% block body %} + + +

Back to League + list

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {% if league.active %} + + {% elif not league.active %} + + {% endif %} + + + + + + + + + + + + {% if league.teamformat == 0 %} + + {% elif league.teamformat == 1 %} + + {% elif league.teamformat == 2 %} + + {% elif league.teamformat == 3 %} + + {% elif league.teamformat == 4 %} + + {% elif league.teamformat == 5 %} + + {% endif %} + + + + + {% if league.bestof == 0 %} + + {% elif league.bestof == 1 %} + + {% elif league.bestof == 2 %} + + {% elif league.bestof == 3 %} + + {% elif league.bestof == 4 %} + + {% endif %} + + + + + + + + + + + + + + + + + + + + +
KeyValue
ID{{ league.id }}
Platform{{ league.platform.name }}
Name{{ league.name }}
Settings{{ league.settings.name }}
Start Date/Time{{ league.start }}
Registration Open{{ league.open_register }}
Required Credits{{ league.req_credits }}
ActiveYesNo
Max Teams/Size{{ league.size }}
Game{{ league.game.name }}
Format1v12v23v34v45v56v6
Best OfBest of 1Best of 3Best of 5Best of 7Best of 9
Created{{ league.created }}
Updated{{ league.updated }}
Divisions + {% for x in divisions %} + Division: #{{ x.id }}- Name={{ x.name }}
+ {% endfor %} +
Teams
+ +

+ Edit + + CREATE DIVISIONS + FORCE ADD DIVISION + DELETE +

+ +{% endblock %} diff --git a/project-templates/staff/leagues/league_division_addteam.html b/project-templates/staff/leagues/league_division_addteam.html new file mode 100644 index 000000000..e3a3ffe88 --- /dev/null +++ b/project-templates/staff/leagues/league_division_addteam.html @@ -0,0 +1,45 @@ +{% extends 'staff/staffbase.html' %} + +{% load static %} + +{% block title %} + Add Team to Division #{{ division.id }} +{% endblock %} +{% block body %} + + + + + + + {% if form.errors %} + {% for field in form %} + {% for error in field.errors %} +
+ {{ error|escape }} +
+ {% endfor %} + {% endfor %} + {% for error in form.non_field_errors %} +
+ {{ error|escape }} +
+ {% endfor %} + {% endif %} +

Return to league list

+ +
+ {% csrf_token %} + {{ field.errors }} + + + {{ form.teamid }} +
+ + +
+ + +{% endblock %} \ No newline at end of file diff --git a/project-templates/staff/leagues/league_division_detail.html b/project-templates/staff/leagues/league_division_detail.html new file mode 100644 index 000000000..17edd63e5 --- /dev/null +++ b/project-templates/staff/leagues/league_division_detail.html @@ -0,0 +1,63 @@ +{% extends 'staff/staffbase.html' %} +{% load static %} + +{% block title %} + Division #{{ division.id }} +{% endblock %} + +{% block body %} + + +

Back to Tournament + list

+ + + + + + + + + + + + + + + + + + + + +
KeyValue
ID{{ division.id }}
Name{{ division.name }}
Apart of League{{ league.name }} (League ID:{{ league.id }})
+ + + +
+ +
+ +

Matches

+ + + + + + + {% for match in matches %} + + + + + + + {% endfor %} + +
Match IDAway TeamHome Team
{{ match.pk }}{{ match.awayteam.name }}{{ match.hometeam.name }}
+

Teams

+ {% for team in division.teams.all %} + {{ team.team.name }} +
+ {% endfor %} +{% endblock %} diff --git a/project-templates/staff/leagues/league_division_matches.html b/project-templates/staff/leagues/league_division_matches.html new file mode 100644 index 000000000..9b6bf4eb4 --- /dev/null +++ b/project-templates/staff/leagues/league_division_matches.html @@ -0,0 +1,56 @@ +{% extends 'staff/staffbase.html' %} +{% load static %} + + +{% block title %} + League Matches List +{% endblock %} + +{% block body %} +
+

Tournament Matches - + (Manually add a match to this division)

+ + + + + + + + + + + + {% for match in matches %} + + + + + + + + + + + {% if match.completed %} + + {% elif not match.completed %} + + {% endif %} + + {% if not match.completed %} + + {% else %} + + {% endif %} + + + {% endfor %} + +
Divison IDMatch IDAway TeamHome TeamCompleted
{{ division.id }}
#{{ match.id }}{{ match.awayteam.name }}{{ match.hometeam.name }}YesNoDeclare + WinnerDelete + Winner
+ + +
+{% endblock %} \ No newline at end of file diff --git a/project-templates/staff/leagues/league_divisions_list.html b/project-templates/staff/leagues/league_divisions_list.html new file mode 100644 index 000000000..3b5945de3 --- /dev/null +++ b/project-templates/staff/leagues/league_divisions_list.html @@ -0,0 +1,47 @@ +{% extends 'staff/staffbase.html' %} +{% load static %} + + +{% block title %} + Leagues #{{ league.pk }} Division List +{% endblock %} + +{% block body %} +
+ + + + + + + + + + {% for division in divisions %} + + + + + + + {% endfor %} +
IDMatchesLeague Name
{{ division.id }} + + Matches for division {{ division.id }} + {{ league.name }}
+ + +
+{% endblock %} \ No newline at end of file diff --git a/project-templates/staff/leagues/league_edit.html b/project-templates/staff/leagues/league_edit.html new file mode 100644 index 000000000..f9e60e676 --- /dev/null +++ b/project-templates/staff/leagues/league_edit.html @@ -0,0 +1,172 @@ +{% extends 'staff/staffbase.html' %} + +{% load static %} + +{% block title %} + Edit League - {{ league.pk }} +{% endblock %} +{% block body %} + + + + + + + + + {% if form.errors %} + {% for field in form %} + {% for error in field.errors %} +
+ {{ error|escape }} +
+ {% endfor %} + {% endfor %} + {% for error in form.non_field_errors %} +
+ {{ error|escape }} +
+ {% endfor %} + {% endif %} +

Return to league list

+
+ Create a new ruleset +
+ Create League Settings + + +
+ {% csrf_token %} + {{ field.errors }} + + + {{ form.name }} +
+ + + {{ form.settings }} +
+ + + {{ form.teamformat }} +
+ + + {{ form.bestof }} +
+ + +
+
+ + {{ form.open_register }} +
+
+ +
+
+ + {{ form.close_register }} +
+
+ + + {{ form.req_credits }} +
+ + + {{ form.size }} +
+ + {% if ESPORTS_MODE %} + + {{ form.platform }} +
+ + + {{ form.game }} +
+ {% endif %} + + {% if not ESPORTS_MODE %} + + {{ form.sport }} +
+ {% endif %} + + {% if ESPORTS_MODE %} + + {{ form.maps }} +
+ {% endif %} + +
+
+ + {{ form.start }} +
+
+ + + {{ form.image }} +
+ + + {{ form.disable_userreport }} +
+ + + {{ form.info }} +
+ + + {{ form.teams }} +
+ + + {{ form.prize1 }} +
+ + + {{ form.prize2 }} +
+ + + {{ form.prize3 }} +
+ + + {{ form.active }} +
+ + + {{ form.ruleset }} +
+ + + {{ form.allow_register }} +
+ + +
+ + + +{% endblock %} \ No newline at end of file diff --git a/project-templates/staff/leagues/league_list.html b/project-templates/staff/leagues/league_list.html new file mode 100644 index 000000000..429a323ca --- /dev/null +++ b/project-templates/staff/leagues/league_list.html @@ -0,0 +1,72 @@ +{% extends 'staff/staffbase.html' %} +{% load static %} + + +{% block title %} + All Leagues +{% endblock %} + +{% block body %} +
+

Create a ruleset

+ + + + + + + + + + + + + + + + {% for league in leagues %} + + + + + + + + + + + + + + {% if league.active %} + + {% elif not league.active %} + + {% endif %} + + + + + + + {% endfor %} +
IDLeague NameSettingsPlatformGameStart Date/TimeRegistration OpenRequired CreditsActiveSize
+ #{{ league.id }} + {{ league.name }} + {{ league.settings.name }} + {{ league.platform.name }}{{ league.game.name }}{{ league.start }}{{ league.open_register }}{{ league.req_credits }}ActiveNot Active{{ league.size }}
+ + +
+{% endblock %} \ No newline at end of file diff --git a/project-templates/staff/leagues/league_settings_create.html b/project-templates/staff/leagues/league_settings_create.html new file mode 100644 index 000000000..158159eed --- /dev/null +++ b/project-templates/staff/leagues/league_settings_create.html @@ -0,0 +1,101 @@ +{% extends 'staff/staffbase.html' %} + +{% load static %} + +{% block title %} + Create League Settings +{% endblock %} +{% block body %} + + + + + + + {% if form.errors %} + {% for field in form %} + {% for error in field.errors %} +
+ {{ error|escape }} +
+ {% endfor %} + {% endfor %} + {% for error in form.non_field_errors %} +
+ {{ error|escape }} +
+ {% endfor %} + {% endif %} +

Return to league settings list

+
+ Create a new ruleset + +
+ {% csrf_token %} + {{ field.errors }} + + + {{ form.name }} +
+ + + {{ form.ot_losses }} +
+ + + {{ form.pts_ot_loss }} +
+ + + {{ form.ot_wins }} +
+ + + {{ form.pts_ot_win }} +
+ + + {{ form.pts_win }} +
+ + + {{ form.pts_loss }} +
+ + + {{ form.allow_tie }} +
+ + + {{ form.num_games }} +
+ + + {{ form.auto_schedule }} +
+ + + + {{ form.auto_matchup }} +
+ + + + + {{ form.num_divisions }} +
+ + + {{ form.max_division_size }} +
+ + + +
+ + +{% endblock %} \ No newline at end of file diff --git a/project-templates/staff/leagues/league_settings_detail.html b/project-templates/staff/leagues/league_settings_detail.html new file mode 100644 index 000000000..e69de29bb diff --git a/project-templates/staff/leagues/league_settings_edit.html b/project-templates/staff/leagues/league_settings_edit.html new file mode 100644 index 000000000..de857c3c9 --- /dev/null +++ b/project-templates/staff/leagues/league_settings_edit.html @@ -0,0 +1,101 @@ +{% extends 'staff/staffbase.html' %} + +{% load static %} + +{% block title %} + Edit League Settings +{% endblock %} +{% block body %} + + + + + + + {% if form.errors %} + {% for field in form %} + {% for error in field.errors %} +
+ {{ error|escape }} +
+ {% endfor %} + {% endfor %} + {% for error in form.non_field_errors %} +
+ {{ error|escape }} +
+ {% endfor %} + {% endif %} +

Return to league settings list

+
+ Create a new ruleset + +
+ {% csrf_token %} + {{ field.errors }} + + + {{ form.name }} +
+ + + {{ form.ot_losses }} +
+ + + {{ form.pts_ot_loss }} +
+ + + {{ form.ot_wins }} +
+ + + {{ form.pts_ot_win }} +
+ + + {{ form.pts_win }} +
+ + + {{ form.pts_loss }} +
+ + + {{ form.allow_tie }} +
+ + + {{ form.num_games }} +
+ + + {{ form.auto_schedule }} +
+ + + + {{ form.auto_matchup }} +
+ + + + + {{ form.num_divisions }} +
+ + + {{ form.max_division_size }} +
+ + + +
+ + +{% endblock %} \ No newline at end of file diff --git a/project-templates/staff/leagues/league_settings_list.html b/project-templates/staff/leagues/league_settings_list.html new file mode 100644 index 000000000..e395d0a16 --- /dev/null +++ b/project-templates/staff/leagues/league_settings_list.html @@ -0,0 +1,66 @@ +{% extends 'staff/staffbase.html' %} +{% load static %} + + +{% block title %} + League Settings +{% endblock %} + +{% block body %} +
+

Create a League Settings object

+ + + + + + + + + + + + + + + + + + + {% for setting in settings %} + + + + + + + + + + + + + + + + + + {% endfor %} +
IDNameTrack OT_LossesOT Loss PointsTrack OT_WinsOT Win PointsRegulation Win PointsRegulation Loss PointsAllow TieNumber GamesAuto SchedulerNum DivisionsMax Division Size
+ #{{ setting.id }} + {{ setting.name }}{{ setting.ot_losses }}{{ setting.pts_ot_loss }}{{ setting.ot_wins }}{{ setting.pts_ot_win }}{{ setting.pts_win }}{{ setting.pts_loss }}{{ setting.allow_tie }}{{ setting.num_games }}{{ setting.auto_schedule }}{{ setting.num_divisions }}{{ setting.max_division_size }}
+ + +
+{% endblock %} \ No newline at end of file diff --git a/project-templates/staff/leagues/league_teams.html b/project-templates/staff/leagues/league_teams.html new file mode 100644 index 000000000..36157b954 --- /dev/null +++ b/project-templates/staff/leagues/league_teams.html @@ -0,0 +1,16 @@ +{% extends 'staff/staffbase.html' %} +{% load static %} + +{% block title %} + League #{{ league.id }} Teams +{% endblock %} + +{% block body %} +

+ +
+ {% for team in league.teams.all %} + {{ team.team.name }} +
+ {% endfor %} +{% endblock %} \ No newline at end of file diff --git a/project-templates/staff/leagues/league_teams_add.html b/project-templates/staff/leagues/league_teams_add.html new file mode 100644 index 000000000..82b17a32b --- /dev/null +++ b/project-templates/staff/leagues/league_teams_add.html @@ -0,0 +1,10 @@ +{% extends 'staff/staffbase.html' %} +{% load static %} + +{% block title %} +Add Teams - League {{ league.id }} +{% endblock %} + +{% block body %} + +{% endblock %} \ No newline at end of file diff --git a/project-templates/staff/staffbase.html b/project-templates/staff/staffbase.html index 369f4605b..aa9e16793 100644 --- a/project-templates/staff/staffbase.html +++ b/project-templates/staff/staffbase.html @@ -176,6 +176,25 @@ {% endif %} + +