Skip to content

Commit

Permalink
Merge pull request #163 from EarthSchlange/general_updates_for_agagd_01
Browse files Browse the repository at this point in the history
general updates for agagd 01
  • Loading branch information
Michael Hiiva committed Mar 3, 2021
2 parents 0bff9d1 + d3a5d30 commit a07ccaf
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 102 deletions.
8 changes: 8 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# CODEOWNERS file
#
# This file will assign a code reviewer to review code which is
# submitted via pull-request.
#
# More information about can be found on:
# https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners
* @EarthSchlange
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# * MYSQL_PASSWORD - database password (the docker entrypoint sets MYSQL_PASS to this value for app compatibility)

### Build stage, to avoid leaving dev dependencies in the final image
FROM python:3.7-slim-buster AS build
FROM python:3.9-slim-buster AS build

WORKDIR /build

Expand All @@ -22,7 +22,7 @@ COPY requirements.txt /build/
RUN pip install --user --no-cache-dir -r requirements.txt && pip install --user --no-cache-dir uwsgi

### Final image
FROM python:3.7-slim-buster
FROM python:3.9-slim-buster

WORKDIR /srv
RUN useradd django
Expand Down
19 changes: 14 additions & 5 deletions agagd/agagd/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,18 @@

PROJECT_ROOT = os.environ['PROJECT_ROOT']

ADMINS = [
('Admins', '[email protected]'),
]
# AGAGD Administrators Configuration:
#
# This assumes AGAGD_ADMINS environmental variable is formated as follows:
# 'webmaster:[email protected],agagd_webmaster:[email protected]'
#
# For local configurations the ADMINS defaults to [('Admin', '[email protected]')]
ADMINS = []

if os.getenv('AGAGD_ADMINS') == None:
ADMINS.append(('Admin', '[email protected]'))
else:
ADMINS = [ (value.split(':')[0], value.split(':')[1]) for value in os.environ.get('AGAGD_ADMINS').split(',') ]

MANAGERS = ADMINS

Expand Down Expand Up @@ -71,14 +80,14 @@
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)

MIDDLEWARE_CLASSES = (
MIDDLEWARE = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
# Uncomment the next line for simple clickjacking protection:
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

ROOT_URLCONF = 'agagd.urls'
Expand Down
9 changes: 5 additions & 4 deletions agagd/agagd/urls.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from django.conf.urls import url
from django.conf.urls.static import static
from django.conf import settings
from django.urls import reverse_lazy
from django.urls import path, reverse_lazy
from django.views.generic import RedirectView
from agagd_core import views as agagd_views
from agagd_core.views import InformationPageView, QualificationsPageView

urlpatterns = [
url(r'^$', agagd_views.index, name='index'),
Expand All @@ -24,7 +25,7 @@
url(r'^tournaments/$', agagd_views.tournament_list, name='tourney_list'),
url(r'^tournaments/(?P<tourn_code>\w{1,20})/$', agagd_views.tournament_detail, name='tournament_detail'),

# Static Pages
url(r'^information/$', agagd_views.information),
url(r'^qualifications/$', agagd_views.qualifications)
# Pages
path('information/', InformationPageView.as_view()),
path('qualifications/', QualificationsPageView.as_view())
]
33 changes: 19 additions & 14 deletions agagd/agagd_core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Member(models.Model):
type = models.CharField(max_length=255, blank=True)

def __str__(self):
return " %s (%s) " % (self.full_name, self.member_id, )
return "{0} ({1})".format(self.full_name, self.member_id)

class Meta:
db_table = 'members'
Expand Down Expand Up @@ -91,15 +91,14 @@ class Tournament(models.Model):
wall_list = models.TextField(db_column='Wallist')

def __str__(self):
return "%s - on %s with %d players" % (self.tournament_code, self.tournament_date, self.total_players)
return "{0} - on {1} with {2} players".format(self.tournament_code, self.tournament_date, self.total_players)

def __unicode__(self):
if self.description:
if len(self.description) > 40:
return '%s...' % self.description[0:37]
return '%s' % self.description
else:
return '%s' % self.pk
return "{0}...".format(self.description[0:37])
return "{0}".format(self.description)
return "{0}".format(self.pk)

class Meta:
managed = False
Expand Down Expand Up @@ -195,16 +194,22 @@ class Meta:
verbose_name = 'game'
verbose_name_plural = 'games'

def __unicode__(self):
return u"Tournament %s Round %s, %s vs %s" % (self.tournament_code,
self.round, self.pin_player_1, self.pin_player_2)

def __str__(self):
return str(self.__unicode__())

return "Tournament {0} Round {1}, {2} vs {3}".format(
self.tournament_code,
self.round,
self.pin_player_1,
self.pin_player_2
)

# player_other_than(self, one_player)
#
# returns the player opposite whichever player
# is provided to player_other_than
def player_other_than(self, one_player):
""" returns the member of the other player. """
return self.pin_player_2 if (one_player == self.pin_player_1) else self.pin_player_1
if (one_player == self.pin_player_1):
return self.pin_player_2
return self.pin_player_1

def winner(self):
if self.result == self.color_1:
Expand Down
48 changes: 28 additions & 20 deletions agagd/agagd_core/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def render(self, value, record):
if record.result == self.color:
self.attrs['td'] = {'class': 'winner'}
else:
self.attrs['td'] = {'class': 'foo'}
self.attrs['td'] = {'class': 'runner-up'}
return value

class ChapterColumn(tables.Column):
Expand Down Expand Up @@ -72,32 +72,40 @@ class GameTable(tables.Table):

class Meta:
model = Game
# add class="paleblue" to <table> tag
attrs = {"class": "paleblue"}
fields = ("game_date", "round", "pin_player_1",
"pin_player_2", 'handicap', 'komi', 'tournament_code')
fields = (
'game_date',
'round',
'pin_player_1',
'pin_player_2',
'handicap',
'komi',
'tournament_code'
)
sequence = fields

#Modified gaeTable to remove duplicate tournament listing displayed on the page, GitHubIssue#20
class GameTable2(tables.Table):
pin_player_1 = WinnerColumn(color='W',
viewname='member_detail',
verbose_name="white player",
kwargs={"member_id":tables.A('pin_player_1.member_id')})
pin_player_2 = WinnerColumn(color='B',
viewname='member_detail',
verbose_name="black player",
kwargs={"member_id":tables.A('pin_player_2.member_id')})
# Alternative GameTable
#
# Displays GameTable without the Tournament Name Column
#
# References:
# GitHubIssue#20
class SecondaryGameTable(GameTable):
tournament_code = None

class Meta:
model = Game
# add class="paleblue" to <table> tag
attrs = {"class": "paleblue"}
fields = ("game_date", "round", "pin_player_1",
"pin_player_2", 'handicap', 'komi')
fields = (
'game_date',
'round',
'pin_player_1',
'pin_player_2',
'handicap',
'komi'
)
sequence = fields



class OpponentTable(tables.Table):
def __init__(self, qs, p1, *args, **kwargs):
self.this_player = p1
Expand All @@ -113,7 +121,7 @@ def __init__(self, qs, p1, *args, **kwargs):
ratio = tables.Column(verbose_name="Rate", default=0, empty_values=(-1,), orderable=False)

def render_ratio(self, record):
return "%0.2f" % (float(record['won']) / record['total'])
return "{:.2f}".format(record['won'] / record['total'])

class Meta:
attrs = {"class": "paleblue"}
Expand Down
88 changes: 45 additions & 43 deletions agagd/agagd_core/views/core.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from agagd_core.json_response import JsonResponse
from agagd_core.models import Game, Member, Tournament, TopDan, TopKyu, MostRatedGamesPastYear, MostTournamentsPastYear, Chapters, Country
from agagd_core.tables import GameTable, GameTable2, MemberTable, ChapterMemberTable, TournamentTable, OpponentTable, TournamentPlayedTable
from agagd_core.tables import GameTable, SecondaryGameTable, MemberTable, ChapterMemberTable, TournamentTable, OpponentTable, TournamentPlayedTable
from agagd_core.tables import TopDanTable, TopKyuTable, AllPlayerRatingsTable, MostRatedGamesPastYearTable, MostTournamentsPastYearTable
from datetime import datetime, timedelta, date
from django.core import exceptions
Expand All @@ -9,6 +9,7 @@
from django.db.models import F, Q, Count
from django.http import HttpResponseRedirect
from django.shortcuts import render, get_object_or_404, redirect
from django.views.generic import TemplateView
from django.views.decorators.http import require_POST, require_GET
from django_tables2 import RequestConfig

Expand Down Expand Up @@ -45,43 +46,44 @@ def index(request):
@require_GET
def search(request):
query = request.GET.get('q','')
if query:
try:
member_id = int(query)
return HttpResponseRedirect(
reverse('member_detail', args=(member_id,))
)
except ValueError:
members_query = Member.objects.filter(
Q(member_id=F('players__pin_player'))
).filter(
full_name__icontains=query
).values(
"member_id",
"chapter_id",
"renewal_due",
"state",
"players__rating",
"country",
"full_name",
"family_name"
).order_by('family_name')

member_table = MemberTable(members_query)
if not query:
return HttpResponseRedirect('/')

try:
RequestConfig(request, paginate={'per_page': 100}).configure(member_table)
except PageNotAnInteger:
RequestConfig(request, paginate=False).configure(member_table)
try:
member_id = int(query)
return HttpResponseRedirect(
reverse('member_detail', args=(member_id,))
)
except ValueError:
members_query = Member.objects.filter(
Q(member_id=F('players__pin_player'))
).filter(
full_name__icontains=query
).values(
"member_id",
"chapter_id",
"renewal_due",
"state",
"players__rating",
"country",
"full_name",
"family_name"
).order_by('family_name')

member_table = MemberTable(members_query)

return render(request, 'agagd_core/search_player.html',
{
'member_table': member_table,
'query': query,
}
)
else:
return HttpResponseRedirect('/')
try:
RequestConfig(request, paginate={'per_page': 100}).configure(member_table)
except PageNotAnInteger:
RequestConfig(request, paginate=False).configure(member_table)

return render(request, 'agagd_core/search_player.html',
{
'member_table': member_table,
'query': query,
}
)

def member_ratings(request, member_id):
#returns a members rating data as a json dict for graphing
Expand Down Expand Up @@ -214,11 +216,11 @@ def member_vs(request, member_id, other_id):

def tournament_detail(request, tourn_code):
tourney = Tournament.objects.get(pk=tourn_code)
game_table2 = GameTable2(tourney.games_in_tourney.all())
RequestConfig(request, paginate={'per_page': 20}).configure(game_table2)
secondary_gametable = SecondaryGameTable(tourney.games_in_tourney.all())
RequestConfig(request, paginate={'per_page': 20}).configure(secondary_gametable)
return render(request, 'agagd_core/tourney.html',
{
'game_table2': game_table2,
'secondary_gametable': secondary_gametable,
'tournament': tourney,
})

Expand Down Expand Up @@ -350,9 +352,9 @@ def game_stats(request):
sorted_games_by_date = sorted(games_by_date, key=lambda d: d['date'])
return JsonResponse(sorted_games_by_date)

# AGAGD Static Pages
def information(request):
return render(request, 'static_pages/information.html')
# AGAGD Pages
class InformationPageView(TemplateView):
template_name = 'information.html'

def qualifications(request):
return render(request, 'static_pages/qualifications.html')
class QualificationsPageView(TemplateView):
template_name = 'qualifications.html'
2 changes: 1 addition & 1 deletion agagd/templates/agagd_core/tourney.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ <h3> Recreated Wall List </h3>
<pre> {{ tournament.wall_list }} </pre>

<h3> Games </h3>
{% render_table game_table2 %}
{% render_table secondary_gametable %}

{% endblock %}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% extends "base.html" %}
{% extends "base.html" %}
{% block title %}Ratings Information{% endblock %}
{% block stylesheets %} {{ block.super }} {% endblock stylesheets %}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% extends "base.html" %}
{% extends "base.html" %}
{% block title %}Qualifications for Rated Games{% endblock %}
{% block stylesheets %} {{ block.super }} {% endblock stylesheets %}

Expand Down
12 changes: 1 addition & 11 deletions docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ A port of the old eurogo Games Database to python, for the AGA

### Getting started

**Important: agagd is no longer compatible with sqlite3; as of 2020-02-01, it requires features only available in MySQL.**

**Important: running the agagd locally now requires access to a database schema not provided by this repository.**
**Important: running the agagd locally now requires the `schema.sql` which can be found in [USGO SQL Schema's Repo](https://github.com/usgo/usgo-sql-schemas).**

*A new docker-based development approach is also available, see [docker.md](docker.md) for details.*

Expand Down Expand Up @@ -63,11 +61,3 @@ with shuffled AGAIDs, random names & chapters, and a few sample tournaments.
7. Provide online game submissions
8. Document game submission protocol for use with other servers.


### Deployment

This needs some help. We'll need to diff the schema, figure out staging,
and maybe some routing/networking magic with Steve.



0 comments on commit a07ccaf

Please sign in to comment.