export_ranking now exports KyuDanRankings and SeasonRankings.

This commit is contained in:
2017-11-03 07:15:28 +01:00
parent f3d44b743b
commit d5b67ffe0c
4 changed files with 226 additions and 21 deletions

View File

@@ -1,36 +1,148 @@
"""Export Mahjong Rankings as excel files."""
from datetime import date
from operator import itemgetter
import openpyxl
from django.core.management.base import BaseCommand
from openpyxl import Workbook
from openpyxl.styles import Border
from mahjong_ranking.models import SeasonRanking
from mahjong_ranking.models import SeasonRanking, KyuDanRanking
THIN_BORDER = openpyxl.styles.Side(style='thin', color="d3d7cf")
HEADING_STYLE = openpyxl.styles.NamedStyle(name="heading")
HEADING_STYLE.font = openpyxl.styles.Font(name='Philosopher', size=11,
bold=True, color='ffffff')
HEADING_STYLE.fill = openpyxl.styles.PatternFill(fill_type='solid',
start_color='a40000',
end_color='a40000')
DEFAULT_STYLE = openpyxl.styles.NamedStyle(name='content')
DEFAULT_STYLE.font = openpyxl.styles.Font(name='Philosopher', size=10,
bold=False, color='000000')
DEFAULT_STYLE.border = openpyxl.styles.Border(bottom=THIN_BORDER,
top=THIN_BORDER)
INT_STYLE = openpyxl.styles.NamedStyle(name='int')
INT_STYLE.font = DEFAULT_STYLE.font
INT_STYLE.border = DEFAULT_STYLE.border
INT_STYLE.number_format = '#,##0'
FLOAT_STYLE = openpyxl.styles.NamedStyle(name='float')
FLOAT_STYLE.font = DEFAULT_STYLE.font
FLOAT_STYLE.border = DEFAULT_STYLE.border
FLOAT_STYLE.number_format = '#,##0.00'
def geneate_seasonexcel(json_data):
def geneate_excel():
"""Generate an excel .xlsx spreadsheet from json data of the kyu/dan
rankings.
:param json_data: The ladder ranking as JSON export."""
workbook = Workbook()
worksheet = workbook.active
workbook = openpyxl.Workbook()
workbook.add_named_style(HEADING_STYLE)
workbook.add_named_style(DEFAULT_STYLE)
workbook.add_named_style(INT_STYLE)
workbook.add_named_style(FLOAT_STYLE)
for sheet in workbook.worksheets:
print(sheet)
workbook.remove(sheet)
return workbook
worksheet.append([
'Rang', 'Spitzname',
'⌀ Platz', '⌀ Punkte',
'Hanchans', 'Gut', 'Gewonnen'
])
json_data = sorted(json_data, key=itemgetter('placement'))
for row in json_data:
worksheet.append([
row['placement'], row['username'],
row['avg_placement'], row['avg_score'],
row['hanchan_count'],
row['good_hanchans'], row['won_hanchans']
])
workbook.save("sample.xlsx")
def generate_sheet(workbook, title, columns_settings, json_data):
row = 1
ws = workbook.create_sheet()
ws.title = title
# setup print orientation
ws.page_setup.orientation = ws.ORIENTATION_PORTRAIT
ws.page_setup.paperSize = ws.PAPERSIZE_A4
ws.page_setup.fitToWidth = True
ws.print_options.horizontalCentered = True
# setup page header
ws.oddHeader.left.text = title
ws.oddHeader.left.size = 14
ws.oddHeader.left.font = "Amerika Sans"
ws.oddHeader.left.color = "000000"
ws.oddHeader.right.text = str(date.today())
ws.oddHeader.right.size = 14
ws.oddHeader.right.font = "Amerika Sans"
ws.oddHeader.right.color = "000000"
# write table header
for column, data in enumerate(columns_settings, 1):
cell = ws.cell(column=column, row=row, value=data['title'])
cell.style = 'heading'
# write the table content
for line in json_data:
row += 1
for column, settings in enumerate(columns_settings, 1):
cell = ws.cell(column=column, row=row, value=line[settings['attr']])
cell.style = settings['style']
# set column widths
for settings in columns_settings:
ws.column_dimensions[settings['col']].width = settings['width']
def export_season_rankings(workbook):
json_data = sorted(SeasonRanking.objects.json_data(),
key=itemgetter('placement'))
title = "Mahjong Ladder - {}".format(date.today().year)
columns_settings = (
{'col': 'A', 'title': 'Rang', 'attr': 'placement', 'style': 'int',
'width': 8},
{'col': 'B', 'title': 'Spitzname', 'attr': 'username',
'style': 'content',
'width': 25},
{'col': 'C', 'title': '⌀ Platz', 'attr': 'avg_placement',
'style': 'int', 'width': 8},
{'col': 'D', 'title': '⌀ Punkte', 'attr': 'avg_score',
'style': 'float', 'width': 12},
{'col': 'E', 'title': 'Hanchans', 'attr': 'hanchan_count',
'style': 'int', 'width': 10},
{'col': 'F', 'title': 'Gut', 'attr': 'good_hanchans',
'style': 'int', 'width': 5},
{'col': 'G', 'title': 'Gewonnen', 'attr': 'won_hanchans',
'style': 'int', 'width': 10},
)
generate_sheet(
workbook=workbook,
title=title,
columns_settings=columns_settings,
json_data=json_data)
def export_kyu_dan_rankings(workbook):
json_data = KyuDanRanking.objects.json_data()
title = "Kyū & Dan Rankings"
columns_settings = (
{'col': 'A', 'title': 'Spitzname', 'attr': 'username',
'style': 'content', 'width': 14},
{'col': 'B', 'title': 'Voller Name', 'attr': 'full_name',
'style': 'content', 'width': 20},
{'col': 'C', 'title': 'Rang', 'attr': 'rank',
'style': 'content', 'width': 8},
{'col': 'D', 'title': 'Punkte', 'attr': 'points',
'style': 'int', 'width': 8},
{'col': 'E', 'title': 'Hanchans', 'attr': 'hanchan_count',
'style': 'int', 'width': 10},
{'col': 'F', 'title': 'Gut', 'attr': 'good_hanchans',
'style': 'int', 'width': 5},
{'col': 'G', 'title': 'Gewonnen', 'attr': 'won_hanchans',
'style': 'int', 'width': 10},
)
generate_sheet(
workbook=workbook,
title=title,
columns_settings=columns_settings,
json_data=json_data)
class Command(BaseCommand):
@@ -39,4 +151,8 @@ class Command(BaseCommand):
def handle(self, *args, **options):
"""Exports the current ladder ranking in a spreadsheet.
This is useful as a backup in form of a hardcopy."""
geneate_seasonexcel(SeasonRanking.objects.json_data())
workbook = geneate_excel()
export_season_rankings(workbook)
export_kyu_dan_rankings(workbook)
workbook.save('sample.x')
workbook.save('mahjong_rankings_{}.xlsx'.format(str(date.today())))

View File

@@ -157,3 +157,37 @@ class SeasonRankingManager(models.Manager):
'won_hanchans': user['won_hanchans']
})
return json_data
class KyuDanRankingManager(models.Manager):
def json_data(self):
""" Get all Rankings for a given Season and return them as a list of
dict objects, suitable for JSON exports and other processings.
:param season: Season that should be exported, current season if empty
:return: a list() of dict() objects suiteable for JSON export.
"""
json_data = list()
values = self.all()
values = values.values('user_id', 'user__username',
'user__first_name', 'user__last_name',
'dan', 'dan_points', 'kyu', 'kyu_points',
'hanchan_count', 'won_hanchans', 'good_hanchans')
for user in values:
if user['dan']:
rank = '{}. Dan'.format(user['dan'])
points = user['dan_points']
else:
rank = '{}. Kyū'.format(user['kyu'])
points = user['kyu_points']
json_data.append({
'user_id': user['user_id'],
'username': user['user__username'],
'full_name': " ".join([user['user__last_name'], user['user__first_name']]),
'rank': rank,
'points': points,
'hanchan_count': user['hanchan_count'],
'good_hanchans': user['good_hanchans'],
'won_hanchans': user['won_hanchans']
})
return json_data

View File

@@ -346,9 +346,11 @@ class KyuDanRanking(models.Model):
legacy_dan_points = models.PositiveIntegerField(default=0)
legacy_kyu_points = models.PositiveIntegerField(default=0)
wins_in_a_row = 0
objects = managers.KyuDanRankingManager()
class Meta(object):
ordering = ('-dan', '-dan_points', '-kyu_points',)
ordering = ('-dan_points', 'dan', '-kyu_points')
verbose_name = _(u'Kyū/Dan Ranking')
verbose_name_plural = _(u'Kyū/Dan Rankings')

View File

@@ -0,0 +1,53 @@
"""To geneate a Sitemap with all events."""
from datetime import date
from django.contrib.sitemaps import Sitemap
from django.urls import reverse
from events.models import Event
from kasu.sitemaps import GenericSitemap
from .models import SeasonRanking
class EventRankingSitemap(GenericSitemap):
@staticmethod
def items():
"""add all upcoming and archived events to the sitemap."""
return Event.objects.all().exclude(eventranking=None)
@staticmethod
def location(event):
return reverse('event-ranking', kwargs={'event': event.id})
class EventHanchanSitemap(GenericSitemap):
@staticmethod
def items():
"""add all upcoming and archived events to the sitemap."""
return Event.objects.all().exclude(eventranking=None)
@staticmethod
def location(event):
return reverse('event-hanchan-list', kwargs={'event': event.id})
class MajongSeasonSitemap(Sitemap):
priority = 0.5
@staticmethod
def items():
seasons = SeasonRanking.objects.all().distinct('season').order_by(
'season')
seasons = seasons.values_list('season', flat=True)
return seasons
@staticmethod
def location(season):
return reverse('mahjong-ladder', kwargs={'season': season})
@staticmethod
def changefreq(season):
if season == date.today().year:
return 'weekly'
else:
return 'never'