10 Commits

Author SHA1 Message Date
aa85d3fd94 requirements changed to django<2.0 for compatibility reasons. 2018-04-28 11:11:12 +02:00
432673a967 Updated all translations 2018-04-27 10:34:37 +02:00
877715f613 Event gallery shows most recent albums first.
Doubled the shown events in the gallery to 24 per page.
2018-04-27 10:20:29 +02:00
1d2fb44250 Fixed typo Player List (Spieler Liste) is now
Players list (Spielerliste)
2018-04-27 10:12:39 +02:00
3af8e64f1f Added the full address to the next/upcoming event in the redbox. 2018-04-27 10:11:19 +02:00
8ddbe03ff8 adapted cleanup script to new file locations and parameters. 2018-04-27 10:10:02 +02:00
4bd017ec4f Fixed queryset so that EventDetailView will work too. 2017-11-24 19:48:21 +01:00
52ec7d42b7 Fixed Hanchan count and filter from last merge. 2017-11-24 19:47:28 +01:00
d62f549a30 Squashed commit of the following:
commit bb5081a78b
Author: Xeniac <xeniac@posteo.at>
Date:   Thu Nov 23 22:02:40 2017 +0100

    Added a setting where the exported excel files should be stored.
    Added a option to send the exported excel as mail attachment.

commit 854fd38740
Author: Xeniac <xeniac@posteo.at>
Date:   Thu Nov 23 22:01:38 2017 +0100

    Fixed: enumerate the Seasonrankings starting with 1
    Fixed: Logging error when a value changed from/to None

commit 6de1ecb102
Author: Christian Berg <xeniac@posteo.at>
Date:   Thu Nov 23 14:15:36 2017 +0100

    add a latest method to query the latest x events

commit bf12060c3b
Author: Christian Berg <xeniac@posteo.at>
Date:   Thu Nov 23 14:15:12 2017 +0100

    add a latest method to query the latest x events

commit 5ad628f33a
Author: Christian Berg <xeniac@posteo.at>
Date:   Mon Nov 20 07:47:47 2017 +0100

    Changed PlayerDanScore to only list non-legacy hanchans

commit 36272c60d6
Author: Christian Berg <xeniac@posteo.at>
Date:   Mon Nov 20 07:42:44 2017 +0100

    fixed import of MIN_HANCHANS_FOR_LADDER that moved to settings

commit c428f6ed1f
Author: Christian Berg <xeniac@posteo.at>
Date:   Mon Nov 20 07:41:04 2017 +0100

    Updated docstrings for new since and until kwargs

commit 9276e97c36
Author: Christian Berg <xeniac@posteo.at>
Date:   Mon Nov 20 07:33:54 2017 +0100

    added a since parameter to the hanchan queries to return only hanchans since the give date and time

commit fd244f10e8
Author: Christian Berg <xeniac@posteo.at>
Date:   Sun Nov 19 16:55:10 2017 +0100

    new command: resetdanranking YYYY-MM-DD, sets every dan player to 1st dan with zero dan_points at the given date.

commit 0a45cf1fd8
Author: Christian Berg <xeniac@posteo.at>
Date:   Sun Nov 19 16:14:59 2017 +0100

    added new fields to KyuDanRanking that allow to pick up the calculation from the last state of the KyuDanRanking.
    last_hanchan_date: it contains the start of the latest hanchan content for this players ranking.
    wins_in_row: to save the currents wins in a row

    Added option to calcuclate rankings until a given datetime.
2017-11-23 22:26:22 +01:00
fa6a81c710 FIXED: DateTimeField Hanchan.start received a naive datetime 2017-11-13 22:59:13 +01:00
36 changed files with 1423 additions and 1105 deletions

View File

@@ -4,18 +4,17 @@ echo "aktualisiere Übersetzungen..."
cd src
unset DJANGO_SETTINGS_MODULE
for dir in *
do
do
if [ -d ${dir}/locale ]
echo "Übersetze $dir"
then
echo -n "$dir: "
cd ${dir}
django-admin.py makemessages -l de
cd ..
fi
done
done
sleep 5s
export DJANGO_SETTINGS_MODULE="kasu.settings.production"
export DJANGO_SETTINGS_MODULE="kasu.settings"
./manage.py compilemessages
echo "lösche den Python Compiler Cache..."
@@ -23,5 +22,5 @@ find . -name "*.pyc" -exec rm -rf {} \;
echo "Aktualisiere Statics"
./manage.py collectstatic --noinput -c
echo "Erstelle Vorschaubilder"
./manage.py generateimages
./manage.py thumbnail_cleanup
touch kasu/wsgi.py

View File

@@ -1,5 +1,5 @@
beautifulsoup4
django
django<2.0
django-appconf
django-ckeditor
django-contrib-comments

View File

@@ -8,271 +8,262 @@ msgid ""
msgstr ""
"Project-Id-Version: kasu.content\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-06-19 22:46+0200\n"
"PO-Revision-Date: 2016-09-28 00:24+0200\n"
"Last-Translator: Christian Berg <xeniac@posteo.at>\n"
"POT-Creation-Date: 2018-04-27 09:49+0200\n"
"PO-Revision-Date: 2018-04-27 10:05+0105\n"
"Last-Translator: b'Christian Berg <kasu@xendynastie.at>'\n"
"Language-Team: Deutsch <>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Translated-Using: django-rosetta 0.7.2\n"
"X-Generator: Poedit 1.8.9\n"
"X-Translated-Using: django-rosetta 0.7.14\n"
#: content/feeds.py:16
#: feeds.py:18
msgid "Current news from Kasu"
msgstr "Aktuelle Nachrichten von Kasu"
#: content/feeds.py:43
#: feeds.py:51
msgid "Latest comments on kasu.at"
msgstr "Neueste Kommentare auf Kasu.at "
#: content/feeds.py:44
#: feeds.py:52
msgid "Kasu - latest comments"
msgstr "Kasu - neue Kommentare"
#: content/forms.py:52 content/models.py:308
#: forms.py:57 models.py:315
msgid "Please upload a PDF-File to this PDF-Page."
msgstr "Bitte eine PDF Datei für diese PDF Seite hochladen."
#: content/models.py:62
#: models.py:68
msgid "Headline"
msgstr "Schlagzeile"
#: content/models.py:64
#: models.py:70
msgid "Content"
msgstr "Inhalt"
#: content/models.py:66 content/models.py:137
#: content/templates/content/article_detail.html:25
#: models.py:72 models.py:143 templates/content/article_detail.html:25
msgid "Category"
msgstr "Kategorie"
#: content/models.py:67 content/models.py:130
#: models.py:73 models.py:136
msgid "Image"
msgstr "Bild"
#: content/models.py:69 content/models.py:132
#: models.py:75 models.py:138
msgid "Slug"
msgstr "Slug"
#: content/models.py:71 content/templates/content/article_detail.html:23
#: models.py:77 templates/content/article_detail.html:23
msgid "Author"
msgstr "Autor"
#: content/models.py:72
#: models.py:78
msgid "Status"
msgstr "Status"
#: content/models.py:74
#: models.py:80
msgid "Created"
msgstr "Erstellt"
#: content/models.py:75
#: models.py:81
msgid "Modified"
msgstr "Bearbeitet"
#: content/models.py:80
#: models.py:86
msgid "Article"
msgstr "Artikel"
#: content/models.py:81
#: models.py:87
msgid "Articles"
msgstr "Artikel"
#: content/models.py:126 content/models.py:127
#: models.py:132 models.py:133
msgid "Name"
msgstr "Name"
#: content/models.py:128 content/models.py:129
#: models.py:134 models.py:135
msgid "Description"
msgstr "Beschreibung"
#: content/models.py:138
#: models.py:144
msgid "Categories"
msgstr "Kategorien"
#: content/models.py:169 content/models.py:175
#: models.py:176 models.py:182
msgid "The short name for the menu-entry of this page"
msgstr "Ein kurzer Name für den Menüeintrag"
#: content/models.py:180 content/models.py:185
#: models.py:187 models.py:192
msgid "The page title as you'd like it to be seen by the public"
msgstr ""
msgstr "Der Seitentitel der öffentlich gemacht wird."
#: content/models.py:187
#: models.py:194
msgid "slug"
msgstr "Slug"
#: content/models.py:190
#: models.py:197
msgid ""
"The name of the page as it will appear in URLs e.g http://domain.com/blog/"
"[my-slug]/"
"The name of the page as it will appear in URLs e.g "
"http://domain.com/blog/[my-slug]/"
msgstr ""
"Der Seitenname wie er in der URL erscheint. z.B: "
"http://domain.com/blog/[slug]/"
#: content/models.py:199
#: models.py:206
msgid "Path"
msgstr "Pfad"
#: content/models.py:211
#: models.py:218
msgid "Position"
msgstr "Position"
#: content/models.py:216
#: models.py:223
msgid "status"
msgstr "Status"
#: content/models.py:219 content/models.py:221
#, fuzzy
#: models.py:226 models.py:228
#| msgid "Description"
msgid "search description"
msgstr "Beschreibung"
msgstr "Suchbeschreibung"
#: content/models.py:224
#, fuzzy
#: models.py:231
#| msgid "Content"
msgid "content type"
msgstr "Inhalt"
msgstr "Inhaltstyp"
#: content/models.py:229
#: models.py:236
msgid "enable comments"
msgstr "Kommentare möglich"
#: content/models.py:234
#: models.py:241
msgid "Template"
msgstr "Vorlage"
#: content/models.py:242
#, fuzzy
#: models.py:249
#| msgid "created on"
msgid "first created at"
msgstr "erstellt am"
#: content/models.py:247
#: models.py:254
msgid "latest updated at"
msgstr ""
msgstr "letzte Änderung"
#: content/models.py:322
#: models.py:328
msgid "Page"
msgstr "Seite"
#: content/models.py:323
#: models.py:329
msgid "Pages"
msgstr "Seiten"
#: content/templates/content/article_archive.html:5
#: content/templates/content/article_archive.html:20
#: templates/content/article_archive.html:5
#: templates/content/article_archive.html:20
msgid "Article Archive"
msgstr "Nachrichtenarchiv"
#: content/templates/content/article_archive.html:35
#: content/templates/content/article_archive_month.html:5
#: content/templates/content/article_archive_year.html:7
#: templates/content/article_archive.html:35
#: templates/content/article_archive_month.html:5
#: templates/content/article_archive_year.html:7
msgid "Archive"
msgstr "Archiv"
#: content/templates/content/article_archive.html:56
#: templates/content/article_archive.html:56
msgid "All Categories"
msgstr "Alle Kategorien"
#: content/templates/content/article_archive.html:71
#: templates/content/article_archive.html:71
msgid "created on"
msgstr "erstellt am"
#: content/templates/content/article_archive.html:73
#: templates/content/article_archive.html:73
msgid "by"
msgstr "von"
#: content/templates/content/article_archive.html:74
#: content/templates/content/article_archive.html:75
#: templates/content/article_archive.html:74
#: templates/content/article_archive.html:75
msgid "comments"
msgstr "Kommentare"
#: content/templates/content/article_archive.html:81
#: templates/content/article_archive.html:81
msgid "Read More"
msgstr "Mehr lesen"
#: content/templates/content/article_archive.html:86
#: templates/content/article_archive.html:86
msgid "We're sorry. Your search yielded no results."
msgstr "Es tut uns leid. Deine Suche ergab keine Treffer."
#: content/templates/content/article_archive.html:104
#: templates/content/article_archive.html:104
msgid "Add Article"
msgstr "neuer Artikel "
#: content/templates/content/article_archive_month.html:7
#: templates/content/article_archive_month.html:7
msgid "back"
msgstr "Zurück"
#: content/templates/content/article_detail.html:24
#: templates/content/article_detail.html:24
msgid "Created on"
msgstr "Erstellt am"
#: content/templates/content/article_detail.html:36
#: templates/content/article_detail.html:36
msgid "share on"
msgstr "Teile auf"
#: content/templates/content/article_detail.html:51
#: content/templates/content/article_form.html:20 content/views.py:138
#: templates/content/article_detail.html:51 views.py:156
msgid "Edit Article"
msgstr "Artikel bearbeiten"
#: content/templates/content/article_form.html:20 content/views.py:139
msgid "Create Article"
msgstr "Artikel erstellen"
#: content/templates/content/article_form.html:25
#: content/templates/content/page_form.html:49
#: content/templates/content/page_form.html:56
#: templates/content/article_form.html:32 templates/content/page_form.html:42
#: templates/content/page_form.html:49
msgid "German"
msgstr "Deutsch"
#: content/templates/content/article_form.html:26
#: content/templates/content/page_form.html:50
#: content/templates/content/page_form.html:64
#: templates/content/article_form.html:33 templates/content/page_form.html:43
#: templates/content/page_form.html:57
msgid "English"
msgstr "Englisch"
#: content/templates/content/article_form.html:45
#: content/templates/content/page_form.html:73
#: templates/content/article_form.html:59 templates/content/page_form.html:66
msgid "reset"
msgstr "Zurücksetzen"
#: content/templates/content/article_form.html:46
#: content/templates/content/page_form.html:74
#: templates/content/article_form.html:60 templates/content/page_form.html:67
msgid "save"
msgstr "Speichern"
#: content/templates/content/page_form.html:5
#: content/templates/content/page_form.html:42
#: templates/content/page_form.html:5 templates/content/page_form.html:35
msgid "Edit Page"
msgstr "Seite bearbeiten"
#: content/templates/content/page_form.html:5
#: content/templates/content/page_form.html:28
#: content/templates/content/page_form.html:42
#: templates/content/page_form.html:5 templates/content/page_form.html:19
#: templates/content/page_form.html:35
msgid "Add Page"
msgstr "Seite hinzufügen"
#: content/templates/content/page_form.html:27
#: templates/content/page_form.html:18
msgid "Edit"
msgstr "Bearbeiten"
#: content/templates/content/page_form.html:44
#: templates/content/page_form.html:37
msgid "HTML Specific"
msgstr "HTML spezifisch"
#: content/views.py:35
#: views.py:53
msgid "This Category does not exist."
msgstr "Diese Kategorie existiert nicht."
#: content/views.py:205
#: views.py:157
msgid "Create Article"
msgstr "Artikel erstellen"
#: views.py:233
#, python-format
msgid "No Page found matching the Path %s"
msgstr "Keine Seite unter dem Pfad %s gefunden"
#: content/views.py:219
#: views.py:262
#, python-format
msgid "No PDF Document found matching the Path %s"
msgstr "Kein PDF Dokument unter dem Pfad %s gefunden."

View File

@@ -0,0 +1,91 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.7 on 2017-11-15 05:53
from __future__ import unicode_literals
import ckeditor_uploader.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('content', '0005_auto_20161012_2236'),
]
operations = [
migrations.AlterField(
model_name='article',
name='content_de',
field=ckeditor_uploader.fields.RichTextUploadingField(verbose_name='Inhalt'),
),
migrations.AlterField(
model_name='article',
name='content_en',
field=ckeditor_uploader.fields.RichTextUploadingField(blank=True, verbose_name='Content'),
),
migrations.AlterField(
model_name='article',
name='headline_en',
field=models.CharField(blank=True, max_length=255, verbose_name='Headline'),
),
migrations.AlterField(
model_name='article',
name='image',
field=models.ImageField(blank=True, null=True, upload_to='news/', verbose_name='Bild'),
),
migrations.AlterField(
model_name='article',
name='slug',
field=models.SlugField(unique_for_month='date_created', verbose_name='Slug'),
),
migrations.AlterField(
model_name='category',
name='image',
field=models.ImageField(blank=True, null=True, upload_to='news/categories/', verbose_name='Bild'),
),
migrations.AlterField(
model_name='page',
name='content_de',
field=ckeditor_uploader.fields.RichTextUploadingField(blank=True, verbose_name='Inhalt'),
),
migrations.AlterField(
model_name='page',
name='content_en',
field=ckeditor_uploader.fields.RichTextUploadingField(blank=True, verbose_name='Content'),
),
migrations.AlterField(
model_name='page',
name='menu_name_de',
field=models.CharField(help_text='Ein kurzer Name für den Menüeintrag', max_length=255, verbose_name='Menü Name'),
),
migrations.AlterField(
model_name='page',
name='menu_name_en',
field=models.CharField(blank=True, help_text='Ein kurzer Name für den Menüeintrag', max_length=255, verbose_name='Menu Name'),
),
migrations.AlterField(
model_name='page',
name='pdf_de',
field=models.FileField(blank=True, null=True, upload_to='pdf/de/'),
),
migrations.AlterField(
model_name='page',
name='pdf_en',
field=models.FileField(blank=True, null=True, upload_to='pdf/en/'),
),
migrations.AlterField(
model_name='page',
name='template',
field=models.CharField(default='content/page.html', max_length=255, verbose_name='Vorlage'),
),
migrations.AlterField(
model_name='page',
name='title_de',
field=models.CharField(help_text="The page title as you'd like it to be seen by the public", max_length=255, verbose_name='Titel'),
),
migrations.AlterField(
model_name='page',
name='title_en',
field=models.CharField(blank=True, help_text="The page title as you'd like it to be seen by the public", max_length=255, verbose_name='Title'),
),
]

View File

@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: kasu.events\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-06-19 22:46+0200\n"
"PO-Revision-Date: 2016-09-28 00:24+0200\n"
"Last-Translator: Christian Berg <xeniac@posteo.at>\n"
"POT-Creation-Date: 2018-04-27 09:49+0200\n"
"PO-Revision-Date: 2018-04-27 10:29+0105\n"
"Last-Translator: b'Christian Berg <kasu@xendynastie.at>'\n"
"Language-Team: Kasu <verein@kasu.at>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
@@ -17,60 +17,61 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.8.9\n"
"X-Translated-Using: django-rosetta 0.7.6\n"
"X-Translated-Using: django-rosetta 0.7.14\n"
#: events/admin.py:14 events/models.py:82
#: admin.py:14 models.py:82
msgid "Event Series"
msgstr "Veranstaltungsreihen"
#: events/forms.py:18
#: forms.py:17
msgid "Images"
msgstr "Bilder"
#: events/forms.py:46
#: forms.py:46
msgid "start"
msgstr "Beginn"
#: events/forms.py:50
#: forms.py:49
msgid "end"
msgstr "Ende"
#: events/models.py:52 events/models.py:176 events/models.py:217
#: mixins.py:57 views.py:149
msgid "Event does not exist"
msgstr "Veranstaltung gibt es nicht"
#: models.py:52 models.py:176 models.py:217
msgid "Name"
msgstr "Name"
#: events/models.py:53 events/models.py:177 events/models.py:225
#: models.py:53 models.py:177 models.py:225
msgid "Description"
msgstr "Beschreibung"
#: events/models.py:55 events/templates/events/event_detail.html:29
#: events/templates/events/event_detail.html:87
#: events/templates/events/event_list.html:28
#: events/templates/events/photo_upload.html:13
#: models.py:55 templates/events/event_detail.html:29
#: templates/events/event_detail.html:87 templates/events/event_list.html:28
#: templates/events/photo_upload.html:13
msgid "Start"
msgstr "Beginn"
#: events/models.py:56 events/templates/events/event_detail.html:30
#: events/templates/events/event_detail.html:89
#: models.py:56 templates/events/event_detail.html:30
#: templates/events/event_detail.html:89
msgid "End"
msgstr "Ende"
#: events/models.py:57 events/models.py:185
#: events/templates/events/event_detail.html:34
#: events/templates/events/event_detail.html:80
#: events/templates/events/event_detail.html:92
#: models.py:57 models.py:185 templates/events/event_detail.html:34
#: templates/events/event_detail.html:80 templates/events/event_detail.html:92
msgid "Homepage"
msgstr "Homepage"
#: events/models.py:59 events/models.py:179 events/models.py:219
#: models.py:59 models.py:179 models.py:219
msgid "Image"
msgstr "Bild"
#: events/models.py:66
#: models.py:66
msgid "Mahjong Tournament"
msgstr "Mahjong Turnier"
#: events/models.py:68
#: models.py:68
msgid ""
"This event is a tournament, different rules apply for the kyu "
"ranking."
@@ -78,11 +79,11 @@ msgstr ""
"Diese Veranstaltung ist ein Turnier, es gelten andere Regeln für das Kyu "
"Ranking."
#: events/models.py:72
#: models.py:72
msgid "Mahjong Season"
msgstr "Mahjong Saison"
#: events/models.py:83
#: models.py:83
msgid ""
"Wenn dieser Event zu einer Veranstaltungsreihe gehört werden Ort, "
"Beschreibung, Bild und Homepage von dem hier angegebenen Event "
@@ -91,247 +92,231 @@ msgstr ""
"Wenn dieser Termin zu einer Veranstaltungsreihe gehört werden Ort, "
"Beschreibung, Bild und Homepage von dem hier angegebenen Event übernommen."
#: events/models.py:92 events/models.py:195 events/models.py:247
#: models.py:92 models.py:195 models.py:247
msgid "first created at"
msgstr ""
msgstr "Erstellt am"
#: events/models.py:97 events/models.py:200 events/models.py:252
#: models.py:97 models.py:200 models.py:252
msgid "latest updated at"
msgstr ""
msgstr "Geändert am"
#: events/models.py:103
#: models.py:103
msgid "Event"
msgstr "Termin"
#: events/models.py:104
#: models.py:104
msgid "Events"
msgstr "Termine"
#: events/models.py:117
#: models.py:117
msgid "A event can't end before it had started"
msgstr "Eine Veranstaltung kann nicht enden bevor sie begonnen hat"
#: events/models.py:186
#: models.py:186
msgid "Postal Code"
msgstr "Postleitzahl"
#: events/models.py:187
#: models.py:187
msgid "Street Address"
msgstr "Straße"
#: events/models.py:188
#: models.py:188
msgid "Locality"
msgstr "Ort"
#: events/models.py:189
#: models.py:189
msgid "Country"
msgstr "Land"
#: events/models.py:204
#: models.py:204
msgid "Venue"
msgstr "Veranstaltungsort"
#: events/models.py:205
#: models.py:205
msgid "Venues"
msgstr "Veranstaltungsorte"
#: events/models.py:231
#: models.py:231
msgid "Startpage"
msgstr "Startseite"
#: events/models.py:234
#: models.py:234
msgid "Display this Photo on the Startpage Teaser"
msgstr "Foto als Teaser auf der Startseite verwenden."
#: events/models.py:236
#: models.py:236
msgid "Published on"
msgstr "Veröffentlicht am"
#: events/models.py:238
#: models.py:238
msgid "Number of views"
msgstr "Wie oft gesehen"
#: events/models.py:262 events/templates/events/event_archive.html:38
#: events/templates/events/event_list.html:18
#: models.py:262 templates/events/event_archive.html:38
#: templates/events/event_list.html:18
msgid "Event Image"
msgstr "Veranstaltungsbild"
#: events/models.py:263
#: models.py:263
msgid "Event Images"
msgstr "Veranstaltungsbilder"
#: events/templates/events/event_archive.html:5
#: events/templates/events/event_archive.html:9
#: templates/events/event_archive.html:5 templates/events/event_archive.html:9
msgid "Event Archive"
msgstr "Veranstaltungsarchiv"
#: events/templates/events/event_archive.html:42
#: events/templates/events/event_detail.html:85
#: events/templates/events/event_list.html:22
#: events/templates/events/photo_detail.html:53
#: templates/events/event_archive.html:42
#: templates/events/event_detail.html:85 templates/events/event_list.html:22
#: templates/events/photo_detail.html:53
msgid "Date"
msgstr "Datum"
#: events/templates/events/event_archive.html:47
#: templates/events/event_archive.html:47
msgid "Time"
msgstr "Zeit"
#: events/templates/events/event_archive.html:49
#: events/templates/events/photo_upload.html:16
#: templates/events/event_archive.html:49
#: templates/events/photo_upload.html:16
msgid "from"
msgstr "von"
#: events/templates/events/event_archive.html:49
#: events/templates/events/photo_upload.html:16
#: templates/events/event_archive.html:49
#: templates/events/photo_upload.html:16
msgid "to"
msgstr "bis"
#: events/templates/events/event_archive.html:57
#: events/templates/events/event_detail.html:31
#: events/templates/events/event_detail.html:72
#: events/templates/events/event_list.html:32
#: events/templates/events/photo_upload.html:23
#: templates/events/event_archive.html:57
#: templates/events/event_detail.html:31 templates/events/event_detail.html:72
#: templates/events/event_list.html:32 templates/events/photo_upload.html:23
msgid "Location"
msgstr "Ort"
#: events/templates/events/event_archive.html:58
#: events/templates/events/event_list.html:35
#: events/templates/events/photo_upload.html:25
#: events/templates/events/photo_upload.html:26
#: templates/events/event_archive.html:58 templates/events/event_list.html:35
#: templates/events/photo_upload.html:25 templates/events/photo_upload.html:26
msgid "Comments"
msgstr "Kommentare"
#: events/templates/events/event_archive.html:59
#: events/templates/events/event_detail.html:36
#: events/templates/events/event_detail.html:48
#: events/templates/events/photo_upload.html:28
#: events/templates/events/photo_upload.html:29
#: templates/events/event_archive.html:59
#: templates/events/event_detail.html:36 templates/events/event_detail.html:48
#: templates/events/photo_list.html:4 templates/events/photo_upload.html:28
#: templates/events/photo_upload.html:29
msgid "Photos"
msgstr "Fotos"
#: events/templates/events/event_archive.html:60
#: events/templates/events/event_archive.html:61
#: events/templates/events/event_detail.html:35
#: events/templates/events/event_detail.html:51
#: templates/events/event_archive.html:60
#: templates/events/event_archive.html:61
#: templates/events/event_detail.html:35 templates/events/event_detail.html:51
msgid "Hanchans"
msgstr "Hanchans"
#: events/templates/events/event_detail.html:37
#: templates/events/event_detail.html:37
msgid "tourney"
msgstr "Turnier"
#: events/templates/events/event_detail.html:37
#: templates/events/event_detail.html:37
msgid "other rules apply here"
msgstr "hier gelten andere Regeln"
#: events/templates/events/event_detail.html:45
#: templates/events/event_detail.html:45
msgid "Info"
msgstr "Info"
#: events/templates/events/event_detail.html:54
#: templates/events/event_detail.html:54
msgid "Mai-Star Games"
msgstr "Mai-Star Spiele"
#: events/templates/events/event_detail.html:57
#: templates/events/event_detail.html:57
msgid "Event Ranking"
msgstr "Veranstaltungs Wertung"
#: events/templates/events/event_detail.html:100
#: templates/events/event_detail.html:100
msgid "Share on Facebook"
msgstr "Auf Facebook teilen"
#: events/templates/events/event_detail.html:104
#: templates/events/event_detail.html:104
msgid "Share on Google+"
msgstr "Auf Google+ teilen"
#: events/templates/events/event_detail.html:109
#: templates/events/event_detail.html:109
msgid "Share on Twitter"
msgstr "Auf Twitter teilen"
#: events/templates/events/event_detail.html:113
#: templates/events/event_detail.html:113
msgid "Show on Google Maps"
msgstr "Auf Google Maps zeigen"
#: events/templates/events/event_detail.html:127
#: events/templates/events/event_form.html:9 events/views.py:104
#: templates/events/event_detail.html:127 templates/events/event_form.html:9
#: views.py:62
msgid "Edit Event"
msgstr "Termin bearbeiten"
#: events/templates/events/event_detail.html:131
#: templates/events/event_detail.html:131
msgid "Add Dates"
msgstr "Termine hinzufügen"
#: events/templates/events/event_form.html:9
#: events/templates/events/page.html:9 events/views.py:106
#: templates/events/event_form.html:9 templates/events/page.html:9 views.py:64
msgid "Add Event"
msgstr "Neuer Termin"
#: events/templates/events/event_form.html:18
#: events/templates/events/photo_list.html:35
#: templates/events/event_form.html:18 templates/events/photo_list.html:35
msgid "reset"
msgstr "Zurücksetzen"
#: events/templates/events/event_form.html:19
#: events/templates/events/eventseries_form.html:25
#: templates/events/event_form.html:19
#: templates/events/eventseries_form.html:25
msgid "save"
msgstr "Speichern"
#: events/templates/events/event_list.html:4
#: events/templates/events/event_list.html:5
#: templates/events/event_list.html:4 templates/events/event_list.html:5
msgid "Upcoming Events"
msgstr "Bevorstehende Veranstaltungen"
#: events/templates/events/eventseries_form.html:24
#: templates/events/eventseries_form.html:24
msgid "back"
msgstr "Zurück"
#: events/templates/events/photo_confirm_delete.html:17
#: templates/events/photo_confirm_delete.html:17
msgid "Cancel"
msgstr "Abbrechen"
#: events/templates/events/photo_confirm_delete.html:21
#: events/templates/events/photo_list.html:21
#: templates/events/photo_confirm_delete.html:21
#: templates/events/photo_list.html:21
msgid "Delete"
msgstr "Löschen"
#: events/templates/events/photo_detail.html:44
#: templates/events/photo_detail.html:44
msgid "previous"
msgstr "Zurück"
#: events/templates/events/photo_detail.html:52
#: templates/events/photo_detail.html:52
msgid "Photographer"
msgstr "Fotograf"
#: events/templates/events/photo_detail.html:58
#: templates/events/photo_detail.html:58
msgid "share on"
msgstr "Teile auf"
#: events/templates/events/photo_detail.html:81
#: templates/events/photo_detail.html:81
msgid "download"
msgstr "Herunterladen"
#: events/templates/events/photo_detail.html:82
#: templates/events/photo_detail.html:82
msgid "Rotate counter clockwise"
msgstr "mit dem Uhrzeiger drehen"
#: events/templates/events/photo_detail.html:83
#: templates/events/photo_detail.html:83
msgid "Rotate clockwise"
msgstr "gegen den Uhrzeiger drehen"
#: events/templates/events/photo_detail.html:84
#: templates/events/photo_detail.html:84
msgid "Save"
msgstr "Speichern"
#: events/templates/events/photo_list.html:36
#: events/templates/events/photo_upload.html:35
#: events/templates/events/photo_upload.html:49
#: templates/events/photo_list.html:36 templates/events/photo_upload.html:35
#: templates/events/photo_upload.html:49
msgid "Upload"
msgstr "Hochladen"
#: events/views.py:203
msgid "Event does not exist"
msgstr "Veranstaltung gibt es nicht"
#~ msgid " Edit"
#~ msgstr "Bearbeiten"

View File

@@ -31,6 +31,10 @@ class EventManager(models.Manager):
"""Returns all past events."""
return self.filter(start__lt=now())
def latest(self, limit=None):
result = self.filter(start__lt=now()).order_by('-start', '-end')
return result[0:limit] if limit else result
def upcoming(self, limit=None):
"""Returns the next 'limit' upcoming events.

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,6 @@
"""Mixins for Events."""
from django.http import Http404
from . import models
@@ -9,7 +11,6 @@ class EventArchiveMixin(object):
date_field = 'start'
make_object_list = True
model = models.Event
ordering = ('start', 'end')
paginate_by = 15
template_name = 'events/event_archive.html'
@@ -40,3 +41,18 @@ class EventDetailMixin(object):
elif hasattr(self, 'object') and hasattr(self.object, 'event'):
context['event'] = self.object.event
return context
def get_queryset(self):
"""set event attribute from the URL kwarg event and
load all related objects from the set model.
:return: a django QuerySets
"""
if self.model == models.Event:
return models.Event.objects.all()
try:
self.event = models.Event.objects.get(pk=self.kwargs['event'])
queryset = self.model.objects.filter(event=self.event)
except models.Event.DoesNotExist:
raise Http404(_('Event does not exist'))
return queryset.prefetch_related()

View File

@@ -30,7 +30,6 @@ class DeleteEventPhoto(PermissionRequiredMixin, mixins.EventDetailMixin,
class EventArchiveIndex(mixins.EventArchiveMixin, generic.ArchiveIndexView):
"""Index of the event archive, displays the upcoming events first."""
allow_empty = True
ordering = ('-start', '-end')
class EventArchiveMonth(mixins.EventArchiveMixin, generic.MonthArchiveView):
@@ -73,7 +72,7 @@ class EventForm(PermissionRequiredMixin, mixins.EventDetailMixin,
if self.kwargs.get('pk') else models.Event()
class EventGallery(mixins.EventDetailMixin, generic.ListView):
class EventGallery(generic.ListView):
"""Display a overview of all event photo albums."""
template_name = 'events/photo_gallery.html'
queryset = models.Event.objects.filter(
@@ -81,7 +80,8 @@ class EventGallery(mixins.EventDetailMixin, generic.ListView):
event_series__isnull=True,
photo_count__gt=0
)
paginate_by = 12
queryset = queryset.order_by('-start')
paginate_by = 24
class EventListIcal(generic.View):

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: kasu.utils\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-06-19 22:46+0200\n"
"POT-Creation-Date: 2018-04-27 09:49+0200\n"
"PO-Revision-Date: 2016-09-28 00:24+0200\n"
"Last-Translator: Christian Berg <xeniac.at@gmail.com>\n"
"Language-Team: Kasu <verein@kasu.at>\n"
@@ -19,174 +19,176 @@ msgstr ""
"X-Generator: Poedit 1.8.9\n"
"X-Translated-Using: django-rosetta 0.7.6\n"
#: kasu/settings.py:153
#: settings.py:157
msgid "German"
msgstr "Deutsch"
#: kasu/settings.py:153
#: settings.py:157
msgid "English"
msgstr "Englisch"
#: kasu/templates/404.html:8
#: templates/404.html:8
msgid "The page your requested does not exist on this server."
msgstr "Die angeforderte Seite existiert auf diesem Server nicht."
#: kasu/templates/base.html:22
#: templates/base.html:22
msgid "Current News"
msgstr "Aktuelle Neuigkeiten"
#: kasu/templates/base.html:24 kasu/templates/index.html:40
#: templates/base.html:24 templates/index.html:40
msgid "Recent Comments"
msgstr "Kürzliche Kommentare"
#: kasu/templates/base.html:45
#: templates/base.html:45
msgid "Menu"
msgstr "Menü"
#: kasu/templates/base.html:69
#: templates/base.html:69 templates/redbox.html:3
msgid "Current Event"
msgstr "Aktuelle Veranstaltung"
#: kasu/templates/base.html:72
#: templates/base.html:72 templates/redbox.html:6
msgid "Since"
msgstr "seit"
#: kasu/templates/base.html:73 kasu/templates/base.html:85
#: templates/base.html:73 templates/base.html:85 templates/redbox.html:8
#: templates/redbox.html:22
msgid "Start"
msgstr "Beginn"
#: kasu/templates/base.html:76 kasu/templates/base.html:88
#: templates/base.html:76 templates/base.html:88 templates/redbox.html:11
#: templates/redbox.html:25
msgid "Location"
msgstr "Ort"
#: kasu/templates/base.html:79 kasu/templates/base.html:90
#: templates/base.html:79 templates/base.html:90 templates/redbox.html:14
#: templates/redbox.html:28
msgid "More Details"
msgstr "Mehr Details"
#: kasu/templates/base.html:81
#: templates/base.html:81 templates/redbox.html:17
msgid "Next Event"
msgstr "Nächste Veranstaltung"
#: kasu/templates/base.html:84
#: templates/base.html:84 templates/redbox.html:20
msgid "in"
msgstr "in"
#: kasu/templates/base.html:93
#: templates/base.html:93 templates/redbox.html:30
msgid "Upcoming events"
msgstr "Bevorstehende Veranstaltungen"
#: kasu/templates/base.html:143
#: templates/base.html:143
msgid "Add Subpage"
msgstr "Unterseite Hinzufügen"
#: kasu/templates/base.html:148
#: templates/base.html:148
msgid "Edit Page"
msgstr "Seite bearbeiten"
#: kasu/templates/base.html:156
#: templates/base.html:156
msgid "Imprint"
msgstr "Impressum"
#: kasu/templates/base.html:157
#: templates/base.html:157
msgid "contact"
msgstr "Kontakt"
#: kasu/templates/base.html:162
#: templates/base.html:162
msgid "Language"
msgstr "Sprache"
#: kasu/templates/base.html:171
#: templates/base.html:171
msgid "Go"
msgstr "Los"
#: kasu/templates/base.html:176
#: templates/base.html:176
msgid "Logged in as"
msgstr "Angemeldet als"
#: kasu/templates/base.html:178
#: templates/base.html:178
msgid "Admin"
msgstr "Admin"
#: kasu/templates/base.html:179
#: templates/base.html:179
msgid "Logout"
msgstr "Abmelden"
#: kasu/templates/base.html:181
#: templates/base.html:181
msgid "no user logged in"
msgstr "Niemand angemeldet"
#: kasu/templates/base.html:182 kasu/templates/comments/form.html:43
#: templates/base.html:182 templates/comments/form.html:43
msgid "register"
msgstr "Registrieren"
#: kasu/templates/base.html:183 kasu/templates/comments/form.html:44
#: templates/base.html:183 templates/comments/form.html:44
msgid "login"
msgstr "anmelden"
#: kasu/templates/base.html:185
#: templates/base.html:185
msgid "Login with Facebook"
msgstr "über Facebook anmelden"
#: kasu/templates/base.html:187
#: templates/base.html:187
msgid "Login with Twitter"
msgstr "über Twitter anmelden"
#: kasu/templates/base.html:189
#: templates/base.html:189
msgid "Login with Google"
msgstr "über Google anmelden"
#: kasu/templates/comments/form.html:5
#: templates/comments/form.html:5
msgid "New Comment"
msgstr "Neuer Kommentar"
#: kasu/templates/comments/form.html:20
#: templates/comments/form.html:20
msgid "now"
msgstr "Jetzt"
#: kasu/templates/comments/form.html:25
#: templates/comments/form.html:25
msgid "Preview"
msgstr "Vorschau"
#: kasu/templates/comments/form.html:26
#: templates/comments/form.html:26
msgid "Post"
msgstr "Schreiben"
#: kasu/templates/comments/form.html:34
#: templates/comments/form.html:34
msgid "not logged in"
msgstr "Nicht angemeldet"
#: kasu/templates/comments/form.html:38
#: templates/comments/form.html:38
msgid "Register now, or Login to leave a comment here."
msgstr "Jetzt registrieren, oder anmelden um einen Kommentar zu schreiben."
#: kasu/templates/comments/list.html:2 kasu/templates/index.html:25
#: templates/comments/list.html:2 templates/index.html:25
msgid "Comments"
msgstr "Kommentare"
#: kasu/templates/comments/posted.html:4 kasu/templates/comments/posted.html:7
#: templates/comments/posted.html:4 templates/comments/posted.html:7
msgid "Thank you for your comment"
msgstr "Danke für deinen Kommentar."
#: kasu/templates/comments/preview.html:4
#: kasu/templates/comments/preview.html:6
#: templates/comments/preview.html:4 templates/comments/preview.html:6
msgid "Preview your comment"
msgstr "Vorschau deines Kommentars"
#: kasu/templates/comments/preview.html:10
#: templates/comments/preview.html:10
msgid "Please correct the error below"
msgid_plural "Please correct the errors below"
msgstr[0] "Bitte den Fehler weiter unten beheben"
msgstr[1] "Bitte die Fehler weiter unten beheben"
#: kasu/templates/index.html:4
#: templates/index.html:4
msgid "traditional Asian game culture"
msgstr "traditionelle asiatische Spielkultur"
#: kasu/templates/index.html:33
#: templates/index.html:33
msgid "Read More"
msgstr "Mehr lesen"
#: kasu/templates/index.html:47
#: templates/index.html:47
#, python-format
msgid ""
"\n"
@@ -203,23 +205,23 @@ msgstr ""
" <time datetime=\"%(submit_date)s\">%(since)s</time>\n"
" "
#: kasu/templates/index.html:59
#: templates/index.html:59
msgid "Kasu in the social network"
msgstr "Kasu im sozialem Netzwerk"
#: kasu/templates/index.html:62 kasu/templates/index.html:65
#: templates/index.html:62 templates/index.html:65
msgid "Visit us on"
msgstr "Besuche uns auf"
#: kasu/templates/index.html:74
#: templates/index.html:74
msgid "Add Article"
msgstr "Artikel hinzufügen"
#: kasu/templates/paginator.html:8
#: templates/paginator.html:8
msgid "Previous"
msgstr "Vorherige"
#: kasu/templates/paginator.html:20
#: templates/paginator.html:20
msgid "Next"
msgstr "Nächste"

View File

@@ -273,6 +273,7 @@ KYU_RANKS = (
DAN_ALLOW_DROP_DOWN = True
MIN_HANCHANS_FOR_LADDER = 5
RANKING_EXPORT_PATH = path.join(PROJECT_PATH, 'backup', 'mahjong_ranking')
try:
from .local_settings import * # Ignore PyLintBear (W0401, W0614)

View File

@@ -73,7 +73,9 @@
<li><span class="fa-li fa fa-calendar"></span><strong>{% trans "Start" %}:</strong>
<time datetime="{{current_event.start|date:'c'}}">{{current_event.start|date:'DATETIME_FORMAT'}}</time>
</li>
<li><span class="fa-li fa fa-map-marker"></span><strong>{% trans "Location" %}:</strong> {{ current_event.location }}</li>
<li><span class="fa-li fa fa-map-marker"></span><strong>{% trans "Location" %}:</strong> {{ current_event.location }}
- {{current_event.location.street_address}}, {{current_event.location.postal_code}} {{current_event.location.locality}}
</li>
</ul>
<div class="right"><a class="button" href="{{current_event.get_absolute_url}}">
{% trans "More Details" %} <span class="fa fa-arrow-right"></span></a></div>
@@ -85,7 +87,9 @@
<li><span class="fa-li fa fa-calendar"></span><strong>{% trans "Start" %}:</strong>
<time datetime="{{next_event.start|date:'c'}}">{{next_event.start|date:'DATETIME_FORMAT' }}</time>
</li>
<li><span class="fa-li fa fa-map-marker"></span><strong>{% trans "Location" %}:</strong> {{ next_event.location }}</li>
<li><span class="fa-li fa fa-map-marker"></span><strong>{% trans "Location" %}:</strong> {{ next_event.location }}
- {{next_event.location.street_address}}, {{next_event.location.postal_code}} {{next_event.location.locality}}
</li>
</ul>
<div class="right"><a class="button" href="{{next_event.get_absolute_url}}">{% trans "More Details" %}
<span class="fa fa-arrow-right"></span></a></div>

View File

@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: kasu.mahjong_ranking\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-06-19 22:46+0200\n"
"PO-Revision-Date: 2016-09-28 00:24+0200\n"
"Last-Translator: Christian Berg <xeniac.at@gmail.com>\n"
"POT-Creation-Date: 2018-04-27 09:49+0200\n"
"PO-Revision-Date: 2018-04-27 09:54+0105\n"
"Last-Translator: b'Christian Berg <kasu@xendynastie.at>'\n"
"Language-Team: Kasu <verein@kasu.at>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
@@ -17,381 +17,377 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.8.9\n"
"X-Translated-Using: django-rosetta 0.7.6\n"
"X-Translated-Using: django-rosetta 0.7.14\n"
#: mahjong_ranking/admin.py:26
#: admin.py:26
msgid "Recalculate"
msgstr "Neuberechnen"
#: mahjong_ranking/admin.py:36
#: admin.py:36
msgid "Confirm"
msgstr "Bestätigen"
#: mahjong_ranking/admin.py:46
#: admin.py:46
msgid "Set unconfirmed"
msgstr "Als unbestätigt markieren"
#: mahjong_ranking/forms.py:21
#: forms.py:21
msgid "start"
msgstr "Beginn"
#: mahjong_ranking/models.py:89
#: mahjong_ranking/templates/mahjong_ranking/player_dan_score.html:14
#: mahjong_ranking/templates/mahjong_ranking/player_invalid_score.html:13
#: mahjong_ranking/templates/mahjong_ranking/player_kyu_score.html:15
#: mahjong_ranking/templates/mahjong_ranking/player_ladder_score.html:15
#: mahjong_ranking/templates/mahjong_ranking/seasonranking_list.html:10
#: models.py:91 templates/mahjong_ranking/player_dan_score.html:14
#: templates/mahjong_ranking/player_invalid_score.html:13
#: templates/mahjong_ranking/player_kyu_score.html:15
#: templates/mahjong_ranking/player_ladder_score.html:15
#: templates/mahjong_ranking/seasonranking_list.html:10
msgid "Start"
msgstr "Beginn"
#: mahjong_ranking/models.py:90
#: models.py:92
msgid "This is crucial to get the right Hanchans that scores"
msgstr "Wichtig damit die richtigen Hanchans in die Wertung kommen."
#: mahjong_ranking/models.py:97
#: models.py:99
msgid "Player 1"
msgstr "Spieler 1"
#: mahjong_ranking/models.py:98 mahjong_ranking/models.py:100
#: mahjong_ranking/models.py:117 mahjong_ranking/models.py:119
#: mahjong_ranking/models.py:136 mahjong_ranking/models.py:138
#: mahjong_ranking/models.py:155 mahjong_ranking/models.py:157
#: mahjong_ranking/templates/mahjong_ranking/eventhanchan_list.html:19
#: mahjong_ranking/templates/mahjong_ranking/eventranking_list.html:21
#: mahjong_ranking/templates/mahjong_ranking/hanchan_confirm_delete.html:16
#: mahjong_ranking/templates/mahjong_ranking/hanchan_form.html:19
#: mahjong_ranking/templates/mahjong_ranking/kyudanranking_list.html:35
#: mahjong_ranking/templates/mahjong_ranking/seasonranking_list.html:32
#: models.py:100 models.py:102 models.py:119 models.py:121 models.py:138
#: models.py:140 models.py:157 models.py:159
#: templates/mahjong_ranking/eventhanchan_list.html:19
#: templates/mahjong_ranking/eventranking_list.html:21
#: templates/mahjong_ranking/hanchan_confirm_delete.html:16
#: templates/mahjong_ranking/hanchan_form.html:19
#: templates/mahjong_ranking/kyudanranking_list.html:35
#: templates/mahjong_ranking/seasonranking_list.html:32
msgid "Score"
msgstr "Punkte"
#: mahjong_ranking/models.py:110 mahjong_ranking/models.py:129
#: mahjong_ranking/models.py:148 mahjong_ranking/models.py:167
#: mahjong_ranking/models.py:169
#: mahjong_ranking/templates/mahjong_ranking/hanchan_form.html:20
#: mahjong_ranking/templates/mahjong_ranking/player_dan_score.html:18
#: mahjong_ranking/templates/mahjong_ranking/player_invalid_score.html:17
#: models.py:112 models.py:131 models.py:150 models.py:169 models.py:171
#: templates/mahjong_ranking/hanchan_form.html:20
#: templates/mahjong_ranking/player_dan_score.html:18
#: templates/mahjong_ranking/player_invalid_score.html:17
msgid "Comment"
msgstr "Kommentar"
#: mahjong_ranking/models.py:116
#: models.py:118
msgid "Player 2"
msgstr "Spieler 2"
#: mahjong_ranking/models.py:135
#: models.py:137
msgid "Player 3"
msgstr "Spieler 3"
#: mahjong_ranking/models.py:154
#: models.py:156
msgid "Player 4"
msgstr "Spieler 4"
#: mahjong_ranking/models.py:170
#: models.py:173
msgid "Has been Confirmed"
msgstr "Wurde bestätigt"
#: mahjong_ranking/models.py:172
#: models.py:174
msgid "Only valid and confirmed Hanchans will be counted in the rating."
msgstr "Nur gültige und bestätigte Hanchans kommen in die Wertung."
#: mahjong_ranking/models.py:177 mahjong_ranking/models.py:576
#: mahjong_ranking/templates/mahjong_ranking/ladder_redbox.html:29
#: mahjong_ranking/templates/mahjong_ranking/player_ladder_score.html:63
#: models.py:179 models.py:603 templates/mahjong_ranking/ladder_redbox.html:29
#: templates/mahjong_ranking/player_ladder_score.html:63
msgid "Season"
msgstr "Saison"
#: mahjong_ranking/models.py:182
#: models.py:184
msgid "Hanchan"
msgstr "Hanchan"
#: mahjong_ranking/models.py:183
#: mahjong_ranking/templates/mahjong_ranking/eventranking_list.html:17
#: models.py:185 templates/mahjong_ranking/eventranking_list.html:17
msgid "Hanchans"
msgstr "Hanchans"
#: mahjong_ranking/models.py:186
#: models.py:188
msgid "Hanchan from {0:%Y-%m-%d} at {0:%H:%M} with {1}"
msgstr "Hanchan vom {0:%Y-%m-%d} um {0:%H:%M} mit {1}"
#: mahjong_ranking/models.py:213
#: models.py:215
#, python-format
msgid "%s can't attend the same game multiple times"
msgstr "%s kann an einem Spiel nicht mehrfach teilnehmen."
#: mahjong_ranking/models.py:221
#: models.py:223
msgid "Games in the future may not be added, Dr. Brown"
msgstr "Spiele aus der Zukunft dürfen noch nicht erfasst werden. Dr. Brown."
#: mahjong_ranking/models.py:223
#: models.py:225
msgid "Only games during the event are allowed"
msgstr "Nur Spiele während der Veranstaltung zählen."
#: mahjong_ranking/models.py:226
#: models.py:228
msgid "Gamescore is lower then 100.000 Pt."
msgstr "Spielstand ist weniger als 100.000 Punkte"
#: mahjong_ranking/models.py:228
#: models.py:230
msgid "Gamescore is over 100.000 Pt."
msgstr "Spielstand ist über 100.000 Punkte."
#: mahjong_ranking/models.py:352
#: models.py:356
msgid "Kyū/Dan Ranking"
msgstr "Kyū/Dan Wertung"
#: mahjong_ranking/models.py:353
#: models.py:357
msgid "Kyū/Dan Rankings"
msgstr "Kyū/Dan Wertungen"
#: mahjong_ranking/templates/mahjong_ranking/eventhanchan_list.html:7
#: templates/mahjong_ranking/eventhanchan_list.html:7
msgid "Played Hanchans"
msgstr "Gespielte Hanchans"
#: mahjong_ranking/templates/mahjong_ranking/eventhanchan_list.html:18
#: mahjong_ranking/templates/mahjong_ranking/hanchan_confirm_delete.html:15
#: templates/mahjong_ranking/eventhanchan_list.html:18
#: templates/mahjong_ranking/hanchan_confirm_delete.html:15
msgid "Place"
msgstr "Platz"
#: mahjong_ranking/templates/mahjong_ranking/eventhanchan_list.html:21
#: mahjong_ranking/templates/mahjong_ranking/hanchan_confirm_delete.html:18
#: mahjong_ranking/templates/mahjong_ranking/player_dan_score.html:17
#: templates/mahjong_ranking/eventhanchan_list.html:21
#: templates/mahjong_ranking/hanchan_confirm_delete.html:18
#: templates/mahjong_ranking/player_dan_score.html:17
msgid "Dan Points"
msgstr "Dan Punkte"
#: mahjong_ranking/templates/mahjong_ranking/eventhanchan_list.html:23
#: mahjong_ranking/templates/mahjong_ranking/hanchan_confirm_delete.html:20
#: mahjong_ranking/templates/mahjong_ranking/player_invalid_score.html:16
#: mahjong_ranking/templates/mahjong_ranking/player_kyu_score.html:18
#: templates/mahjong_ranking/eventhanchan_list.html:23
#: templates/mahjong_ranking/hanchan_confirm_delete.html:20
#: templates/mahjong_ranking/player_invalid_score.html:16
#: templates/mahjong_ranking/player_kyu_score.html:18
msgid "Kyu Points"
msgstr "Kyu Punkte"
#: mahjong_ranking/templates/mahjong_ranking/eventhanchan_list.html:37
#: mahjong_ranking/templates/mahjong_ranking/hanchan_confirm_delete.html:4
#: mahjong_ranking/templates/mahjong_ranking/hanchan_confirm_delete.html:33
#: mahjong_ranking/templates/mahjong_ranking/player_dan_score.html:44
#: mahjong_ranking/templates/mahjong_ranking/player_invalid_score.html:33
#: mahjong_ranking/templates/mahjong_ranking/player_kyu_score.html:41
#: mahjong_ranking/templates/mahjong_ranking/player_ladder_score.html:52
#: templates/mahjong_ranking/eventhanchan_list.html:37
#: templates/mahjong_ranking/hanchan_confirm_delete.html:4
#: templates/mahjong_ranking/hanchan_confirm_delete.html:33
#: templates/mahjong_ranking/player_dan_score.html:44
#: templates/mahjong_ranking/player_invalid_score.html:33
#: templates/mahjong_ranking/player_kyu_score.html:41
#: templates/mahjong_ranking/player_ladder_score.html:52
msgid "Delete Hanchan"
msgstr "Hanchan löschen"
#: mahjong_ranking/templates/mahjong_ranking/eventhanchan_list.html:43
#: mahjong_ranking/templates/mahjong_ranking/hanchan_form.html:4
#: mahjong_ranking/templates/mahjong_ranking/hanchan_form.html:14
#: mahjong_ranking/templates/mahjong_ranking/player_dan_score.html:47
#: mahjong_ranking/templates/mahjong_ranking/player_invalid_score.html:36
#: mahjong_ranking/templates/mahjong_ranking/player_kyu_score.html:44
#: mahjong_ranking/templates/mahjong_ranking/player_ladder_score.html:55
#: templates/mahjong_ranking/eventhanchan_list.html:43
#: templates/mahjong_ranking/hanchan_form.html:4
#: templates/mahjong_ranking/hanchan_form.html:14
#: templates/mahjong_ranking/player_dan_score.html:47
#: templates/mahjong_ranking/player_invalid_score.html:36
#: templates/mahjong_ranking/player_kyu_score.html:44
#: templates/mahjong_ranking/player_ladder_score.html:55
msgid "Edit Hanchan"
msgstr "Hanchan bearbeiten"
#: mahjong_ranking/templates/mahjong_ranking/eventhanchan_list.html:48
#: templates/mahjong_ranking/eventhanchan_list.html:48
msgid "No Hanchan has been added to this event yet."
msgstr "Für diese Veranstaltung wurde noch keine Hanchan eingetragen."
#: mahjong_ranking/templates/mahjong_ranking/eventhanchan_list.html:54
#: mahjong_ranking/templates/mahjong_ranking/eventranking_list.html:51
#: templates/mahjong_ranking/eventhanchan_list.html:54
#: templates/mahjong_ranking/eventranking_list.html:51
msgid "Edit Event"
msgstr "Veranstaltung bearbeiten"
#: mahjong_ranking/templates/mahjong_ranking/eventhanchan_list.html:55
#: mahjong_ranking/templates/mahjong_ranking/eventranking_list.html:52
#: mahjong_ranking/templates/mahjong_ranking/hanchan_form.html:4
#: mahjong_ranking/templates/mahjong_ranking/hanchan_form.html:14
#: templates/mahjong_ranking/eventhanchan_list.html:55
#: templates/mahjong_ranking/eventranking_list.html:52
#: templates/mahjong_ranking/hanchan_form.html:4
#: templates/mahjong_ranking/hanchan_form.html:14
msgid "Add Hanchan"
msgstr "Hanchan hinzufügen"
#: mahjong_ranking/templates/mahjong_ranking/eventranking_list.html:4
#: mahjong_ranking/templates/mahjong_ranking/eventranking_list.html:5
#: templates/mahjong_ranking/eventranking_list.html:4
#: templates/mahjong_ranking/eventranking_list.html:5
msgid "Tournament Ranking"
msgstr "Turnierwertung"
#: mahjong_ranking/templates/mahjong_ranking/eventranking_list.html:12
#: mahjong_ranking/templates/mahjong_ranking/kyudanranking_list.html:30
#: mahjong_ranking/templates/mahjong_ranking/seasonranking_list.html:23
#: templates/mahjong_ranking/eventranking_list.html:12
#: templates/mahjong_ranking/kyudanranking_list.html:30
#: templates/mahjong_ranking/seasonranking_list.html:23
msgid "Rank"
msgstr "Rang"
#: mahjong_ranking/templates/mahjong_ranking/eventranking_list.html:13
#: mahjong_ranking/templates/mahjong_ranking/kyudanranking_list.html:17
#: mahjong_ranking/templates/mahjong_ranking/seasonranking_list.html:24
#: templates/mahjong_ranking/eventranking_list.html:13
#: templates/mahjong_ranking/kyudanranking_list.html:17
#: templates/mahjong_ranking/seasonranking_list.html:24
msgid "Avatar"
msgstr "Avatar"
#: mahjong_ranking/templates/mahjong_ranking/eventranking_list.html:14
#: mahjong_ranking/templates/mahjong_ranking/kyudanranking_list.html:20
#: mahjong_ranking/templates/mahjong_ranking/seasonranking_list.html:25
#: templates/mahjong_ranking/eventranking_list.html:14
#: templates/mahjong_ranking/kyudanranking_list.html:20
#: templates/mahjong_ranking/seasonranking_list.html:25
msgid "Nickname"
msgstr "Spitzname"
#: mahjong_ranking/templates/mahjong_ranking/eventranking_list.html:15
#: mahjong_ranking/templates/mahjong_ranking/seasonranking_list.html:26
#: templates/mahjong_ranking/eventranking_list.html:15
#: templates/mahjong_ranking/seasonranking_list.html:26
msgid "Name"
msgstr "Name"
#: mahjong_ranking/templates/mahjong_ranking/eventranking_list.html:16
#: mahjong_ranking/templates/mahjong_ranking/seasonranking_list.html:27
#: templates/mahjong_ranking/eventranking_list.html:16
#: templates/mahjong_ranking/seasonranking_list.html:27
msgid "Average"
msgstr "Durchschnitt"
#: mahjong_ranking/templates/mahjong_ranking/eventranking_list.html:20
#: mahjong_ranking/templates/mahjong_ranking/player_dan_score.html:15
#: mahjong_ranking/templates/mahjong_ranking/player_invalid_score.html:15
#: mahjong_ranking/templates/mahjong_ranking/player_kyu_score.html:16
#: mahjong_ranking/templates/mahjong_ranking/player_ladder_score.html:16
#: mahjong_ranking/templates/mahjong_ranking/seasonranking_list.html:31
#: templates/mahjong_ranking/eventranking_list.html:20
#: templates/mahjong_ranking/player_dan_score.html:15
#: templates/mahjong_ranking/player_invalid_score.html:15
#: templates/mahjong_ranking/player_kyu_score.html:16
#: templates/mahjong_ranking/player_ladder_score.html:16
#: templates/mahjong_ranking/seasonranking_list.html:31
msgid "Placement"
msgstr "Platzierung"
#: mahjong_ranking/templates/mahjong_ranking/eventranking_list.html:22
#: mahjong_ranking/templates/mahjong_ranking/seasonranking_list.html:33
#: templates/mahjong_ranking/eventranking_list.html:22
#: templates/mahjong_ranking/seasonranking_list.html:33
msgid "count"
msgstr "Anzahl"
#: mahjong_ranking/templates/mahjong_ranking/eventranking_list.html:23
#: mahjong_ranking/templates/mahjong_ranking/seasonranking_list.html:34
#: templates/mahjong_ranking/eventranking_list.html:23
#: templates/mahjong_ranking/seasonranking_list.html:34
msgid "good"
msgstr "gut"
#: mahjong_ranking/templates/mahjong_ranking/eventranking_list.html:24
#: mahjong_ranking/templates/mahjong_ranking/seasonranking_list.html:35
#: templates/mahjong_ranking/eventranking_list.html:24
#: templates/mahjong_ranking/seasonranking_list.html:35
msgid "won"
msgstr "gewonnen"
#: mahjong_ranking/templates/mahjong_ranking/hanchan_confirm_delete.html:39
#: templates/mahjong_ranking/hanchan_confirm_delete.html:39
msgid "Cancel"
msgstr "Abbruch"
#: mahjong_ranking/templates/mahjong_ranking/hanchan_confirm_delete.html:40
#: templates/mahjong_ranking/hanchan_confirm_delete.html:40
msgid "Delete"
msgstr "Löschen"
#: mahjong_ranking/templates/mahjong_ranking/hanchan_form.html:18
#: templates/mahjong_ranking/hanchan_form.html:18
msgid "Player"
msgstr "Spieler"
#: mahjong_ranking/templates/mahjong_ranking/hanchan_form.html:58
#: templates/mahjong_ranking/hanchan_form.html:58
msgid "Total"
msgstr "Total"
#: mahjong_ranking/templates/mahjong_ranking/hanchan_form.html:71
#: templates/mahjong_ranking/hanchan_form.html:71
msgid "back"
msgstr "Zurück"
#: mahjong_ranking/templates/mahjong_ranking/hanchan_form.html:72
#: templates/mahjong_ranking/hanchan_form.html:72
msgid "save"
msgstr "Speichern"
#: mahjong_ranking/templates/mahjong_ranking/kyudanranking_list.html:4
#: mahjong_ranking/templates/mahjong_ranking/kyudanranking_list.html:9
#: templates/mahjong_ranking/kyudanranking_list.html:4
#| msgid "Player List"
msgid "Players list"
msgstr "Spielerliste"
#: templates/mahjong_ranking/kyudanranking_list.html:9
msgid "Player List"
msgstr "Spieler Liste"
#: mahjong_ranking/templates/mahjong_ranking/kyudanranking_list.html:25
#: templates/mahjong_ranking/kyudanranking_list.html:25
msgid "Full Name"
msgstr "Voller Name"
#: mahjong_ranking/templates/mahjong_ranking/kyudanranking_list.html:40
#: templates/mahjong_ranking/kyudanranking_list.html:40
msgid "Games Total"
msgstr "Spiele total"
#: mahjong_ranking/templates/mahjong_ranking/ladder_redbox.html:3
#: templates/mahjong_ranking/ladder_redbox.html:3
msgid "Latest Hanchans"
msgstr "Letzten Hanchans"
#: mahjong_ranking/templates/mahjong_ranking/ladder_redbox.html:15
#: templates/mahjong_ranking/ladder_redbox.html:15
msgid "Latest Events"
msgstr "Letzte Veranstaltungen"
#: mahjong_ranking/templates/mahjong_ranking/ladder_redbox.html:27
#: templates/mahjong_ranking/ladder_redbox.html:27
msgid "Ladder Archive"
msgstr "Ladder Archiv"
#: mahjong_ranking/templates/mahjong_ranking/player_dan_score.html:4
#: mahjong_ranking/templates/mahjong_ranking/player_dan_score.html:5
#: templates/mahjong_ranking/player_dan_score.html:4
#: templates/mahjong_ranking/player_dan_score.html:5
msgid "Dan Score for"
msgstr "Dan Wertung für"
#: mahjong_ranking/templates/mahjong_ranking/player_dan_score.html:8
#: templates/mahjong_ranking/player_dan_score.html:8
msgid "Hanchans that apply to the Dan Score"
msgstr "Hanchans welche zur Dan Wertung zählen"
#: mahjong_ranking/templates/mahjong_ranking/player_dan_score.html:12
#: mahjong_ranking/templates/mahjong_ranking/player_kyu_score.html:13
#: mahjong_ranking/templates/mahjong_ranking/player_ladder_score.html:13
#: templates/mahjong_ranking/player_dan_score.html:12
#: templates/mahjong_ranking/player_kyu_score.html:13
#: templates/mahjong_ranking/player_ladder_score.html:13
msgid "Date"
msgstr "Datum"
#: mahjong_ranking/templates/mahjong_ranking/player_dan_score.html:13
#: mahjong_ranking/templates/mahjong_ranking/player_invalid_score.html:12
#: mahjong_ranking/templates/mahjong_ranking/player_kyu_score.html:14
#: mahjong_ranking/templates/mahjong_ranking/player_ladder_score.html:14
#: templates/mahjong_ranking/player_dan_score.html:13
#: templates/mahjong_ranking/player_invalid_score.html:12
#: templates/mahjong_ranking/player_kyu_score.html:14
#: templates/mahjong_ranking/player_ladder_score.html:14
msgid "Event"
msgstr "Veranstaltung"
#: mahjong_ranking/templates/mahjong_ranking/player_dan_score.html:16
#: mahjong_ranking/templates/mahjong_ranking/player_invalid_score.html:14
#: mahjong_ranking/templates/mahjong_ranking/player_kyu_score.html:17
#: mahjong_ranking/templates/mahjong_ranking/player_ladder_score.html:17
#: templates/mahjong_ranking/player_dan_score.html:16
#: templates/mahjong_ranking/player_invalid_score.html:14
#: templates/mahjong_ranking/player_kyu_score.html:17
#: templates/mahjong_ranking/player_ladder_score.html:17
msgid "Players"
msgstr "Spieler"
#: mahjong_ranking/templates/mahjong_ranking/player_invalid_score.html:4
#: mahjong_ranking/templates/mahjong_ranking/player_invalid_score.html:6
#: templates/mahjong_ranking/player_invalid_score.html:4
#: templates/mahjong_ranking/player_invalid_score.html:6
msgid "Unconfirmed Hanchans from"
msgstr "Nicht bestätigte Hanchans von"
#: mahjong_ranking/templates/mahjong_ranking/player_invalid_score.html:9
#: templates/mahjong_ranking/player_invalid_score.html:9
msgid "Invalid hanchans with"
msgstr "Ungültige Hanchans mit"
#: mahjong_ranking/templates/mahjong_ranking/player_kyu_score.html:4
#: mahjong_ranking/templates/mahjong_ranking/player_kyu_score.html:6
#: templates/mahjong_ranking/player_kyu_score.html:4
#: templates/mahjong_ranking/player_kyu_score.html:6
msgid "Kyu Score for"
msgstr "Kyu Wertung für"
#: mahjong_ranking/templates/mahjong_ranking/player_kyu_score.html:9
#: templates/mahjong_ranking/player_kyu_score.html:9
msgid "Hanchans that apply to the Kyu Score"
msgstr "Hanchans welche zur Kyu Wertung zählen"
#: mahjong_ranking/templates/mahjong_ranking/player_ladder_score.html:4
#: mahjong_ranking/templates/mahjong_ranking/player_ladder_score.html:5
#: templates/mahjong_ranking/player_ladder_score.html:4
#: templates/mahjong_ranking/player_ladder_score.html:5
msgid "Ladder Score for"
msgstr "Ladder Wertung für"
#: mahjong_ranking/templates/mahjong_ranking/player_ladder_score.html:8
#: templates/mahjong_ranking/player_ladder_score.html:8
msgid "Hanchans that apply to the Ladder Score"
msgstr "Hanchans welche in der Ladder zählen"
#: mahjong_ranking/templates/mahjong_ranking/player_ladder_score.html:71
#: templates/mahjong_ranking/player_ladder_score.html:71
msgid "Go"
msgstr "Los"
#: mahjong_ranking/templates/mahjong_ranking/seasonranking_list.html:11
#: templates/mahjong_ranking/seasonranking_list.html:11
msgid "End"
msgstr "Ende"
#: mahjong_ranking/templates/mahjong_ranking/seasonranking_list.html:12
#: templates/mahjong_ranking/seasonranking_list.html:12
msgid "Participants"
msgstr "Teilnehmer"
#: mahjong_ranking/views.py:98
#: views.py:102
#, python-format
msgid "%s has been updated successfully."
msgstr "%s wurde erfolgreich aktualisiert."
#: mahjong_ranking/views.py:101
#: views.py:105
#, python-format
msgid "%s has been added successfully. You can now add a new one."
msgstr "%s wurde erfolgreich hinzugefügt. Du kannst eine neue eintragen."
#: mahjong_ranking/views.py:119 mahjong_ranking/views.py:135
msgid "Event does not exist"
msgstr "Veranstaltung existiert nicht"
#: mahjong_ranking/views.py:199
#: views.py:169
msgid "No user found matching the name {}"
msgstr "Kein Benutzer mit dem Namen %s gefunden"
#~ msgid "Event does not exist"
#~ msgstr "Veranstaltung existiert nicht"
#~ msgid "It's not allowed to enter future games."
#~ msgstr "Spiele in der Zukunft sind nicht erlaubt."

View File

@@ -1,11 +1,14 @@
"""Export Mahjong Rankings as excel files."""
from datetime import date
from operator import itemgetter
import os
from datetime import date, time, datetime
import openpyxl
from django.conf import settings
from django.core.management.base import BaseCommand
from openpyxl.styles import Border
from django.utils import timezone
from django.utils.dateparse import parse_date
from django.core.mail import EmailMessage
from mahjong_ranking.models import SeasonRanking, KyuDanRanking
@@ -34,7 +37,24 @@ FLOAT_STYLE.font = DEFAULT_STYLE.font
FLOAT_STYLE.border = DEFAULT_STYLE.border
FLOAT_STYLE.number_format = '#,##0.00'
DATE_STYLE = openpyxl.styles.NamedStyle(name='date')
DATE_STYLE.font = DEFAULT_STYLE.font
DATE_STYLE.border = DEFAULT_STYLE.border
DATE_STYLE.number_format = 'dd.mm.yyyy'
MAIL_BODY = """
Hallo! Ich bin's dein Server.
Ich habe gerade die Mahjong Rankings als Excel exportiert und dachte mir das
ich sie dir am besten gleich schicke.
Bitte versuche nicht auf diese E-Mail zu antworten.
Ich bin nur ein dummes Programm.
mit lieben Grüßen
Der Kasu Server
"""
def geneate_excel():
"""Generate an excel .xlsx spreadsheet from json data of the kyu/dan
rankings.
@@ -45,8 +65,9 @@ def geneate_excel():
workbook.add_named_style(DEFAULT_STYLE)
workbook.add_named_style(INT_STYLE)
workbook.add_named_style(FLOAT_STYLE)
workbook.add_named_style(DATE_STYLE)
for sheet in workbook.worksheets:
print(sheet)
workbook.remove(sheet)
return workbook
@@ -55,6 +76,8 @@ def generate_sheet(workbook, title, columns_settings, json_data):
row = 1
ws = workbook.create_sheet()
ws.title = title
ws.syncHorizontal = True
ws.filterMode = True
# setup print orientation
ws.page_setup.orientation = ws.ORIENTATION_PORTRAIT
@@ -90,10 +113,10 @@ def generate_sheet(workbook, title, columns_settings, json_data):
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)
def export_season_rankings(workbook, until):
SeasonRanking.objects.update(until=until)
json_data = SeasonRanking.objects.json_data()
title = "Mahjong Ladder - {}".format(until.year)
columns_settings = (
{'col': 'A', 'title': 'Rang', 'attr': 'placement', 'style': 'int',
'width': 8},
@@ -101,7 +124,7 @@ def export_season_rankings(workbook):
'style': 'content',
'width': 25},
{'col': 'C', 'title': '⌀ Platz', 'attr': 'avg_placement',
'style': 'int', 'width': 8},
'style': 'float', 'width': 8},
{'col': 'D', 'title': '⌀ Punkte', 'attr': 'avg_score',
'style': 'float', 'width': 12},
{'col': 'E', 'title': 'Hanchans', 'attr': 'hanchan_count',
@@ -111,7 +134,6 @@ def export_season_rankings(workbook):
{'col': 'G', 'title': 'Gewonnen', 'attr': 'won_hanchans',
'style': 'int', 'width': 10},
)
generate_sheet(
workbook=workbook,
title=title,
@@ -119,7 +141,8 @@ def export_season_rankings(workbook):
json_data=json_data)
def export_kyu_dan_rankings(workbook):
def export_kyu_dan_rankings(workbook, until):
KyuDanRanking.objects.update(until=until)
json_data = KyuDanRanking.objects.json_data()
title = "Kyū & Dan Rankings"
columns_settings = (
@@ -136,7 +159,9 @@ def export_kyu_dan_rankings(workbook):
{'col': 'F', 'title': 'Gut', 'attr': 'good_hanchans',
'style': 'int', 'width': 5},
{'col': 'G', 'title': 'Gewonnen', 'attr': 'won_hanchans',
'style': 'int', 'width': 10},
'style': 'int', 'width': 8},
{'col': 'H', 'title': 'letzte Hanchan', 'attr': 'last_hanchan_date',
'style': 'date', 'width': 16},
)
generate_sheet(
workbook=workbook,
@@ -147,12 +172,43 @@ def export_kyu_dan_rankings(workbook):
class Command(BaseCommand):
"""Exports the SeasonRankings"""
filename = str()
until = datetime
def add_arguments(self, parser):
parser.add_argument(
'--until', nargs='?', type=parse_date,
default=date.today(), metavar='YYYY-MM-DD',
help='Calculate and export rankings until the given date.')
parser.add_argument(
'--mail', nargs='*', type=str, metavar='user@example.com',
help='Send the spreadsheet via eMail to the given recipient.')
def handle(self, *args, **options):
"""Exports the current ladder ranking in a spreadsheet.
This is useful as a backup in form of a hardcopy."""
self.until = timezone.make_aware(datetime.combine(
options['until'], time(23, 59, 59)
))
self.filename = os.path.join(
settings.RANKING_EXPORT_PATH,
'mahjong_rankings_{:%Y-%m-%d}.xlsx'.format(self.until)
)
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())))
export_season_rankings(workbook, until=self.until)
export_kyu_dan_rankings(workbook, until=self.until)
os.makedirs(settings.RANKING_EXPORT_PATH, exist_ok=True)
workbook.save(self.filename)
if options['mail']:
self.send_mail(options['mail'])
def send_mail(self, recipients):
mail = EmailMessage(
subject='Mahjong Rankings vom {:%d.%m.%Y}'.format(self.until),
body=MAIL_BODY,
from_email=settings.DEFAULT_FROM_EMAIL,
to=recipients)
mail.attach_file(self.filename)
mail.send()

View File

@@ -0,0 +1,32 @@
"""
Rest all dan points to 0 at a given date.
"""
from django.core.management.base import BaseCommand
from datetime import date, datetime, time
from mahjong_ranking import models
from django.utils.dateparse import parse_date
from django.utils import timezone
class Command(BaseCommand):
""" Recalculate all Kyu/Dan Rankings """
help = "reset every dan player to 1st dan with 0 points."
def add_arguments(self, parser):
parser.add_argument('reset_date', type=parse_date)
def handle(self, *args, **options):
reset_date = timezone.make_aware(datetime.combine(options.get('reset_date'), time(23, 59, 59)))
# models.KyuDanRanking.objects.update(until=reset_date, force_recalc=True)
dan_rankigns = models.KyuDanRanking.objects.filter(dan__isnull=False)
for ranking in dan_rankigns:
ranking.dan = 1
ranking.dan_points = 0
ranking.legacy_date = reset_date.date()
ranking.legacy_hanchan_count = ranking.hanchan_count
ranking.legacy_dan_points = ranking.dan_points
ranking.legacy_kyu_points = ranking.kyu_points
ranking.save()

View File

@@ -5,27 +5,29 @@ Recalculate Mahjong Rankings...
"""
from django.core.management.base import BaseCommand
from mahjong_ranking import LOGGER
from datetime import date, datetime, time
from mahjong_ranking import models
from django.utils.dateparse import parse_date
from django.utils import timezone
class Command(BaseCommand):
""" Recalculate all Kyu/Dan Rankings """
help = "Recalculate all Kyu/Dan Rankings"
def add_arguments(self, parser):
parser.add_argument('--since', nargs='?', type=parse_date)
parser.add_argument('--until', nargs='?', type=parse_date)
parser.add_argument('--forcerecalc', action='store_true')
def handle(self, *args, **options):
old_attr = {'dan': None, 'dan_points': None,
'kyu': None, 'kyu_points': None, 'won_hanchans': None,
'good_hanchans': None, 'hanchan_count': None}
for ranking in models.KyuDanRanking.objects.all():
old_attr = {attr: getattr(ranking, attr) for attr in old_attr.keys()}
ranking.recalculate()
for attr, old_value in old_attr.items():
if getattr(ranking, attr) != old_value:
LOGGER.warning(
"%(user)s recalc shows differences in %(attr)s! old: %(old)d, new: %(new)d",
{'user': ranking.user, 'attr': attr,
'old': old_value, 'new': getattr(ranking, attr)}
)
since = options.get('since', None)
until = options.get('until', None)
force_recalc = options.get('forecerecalc', False)
if isinstance(since, date):
since = datetime.combine(since, time(0, 0, 0))
since = timezone.make_aware(since)
if isinstance(until, date):
until = datetime.combine(until, time(23, 59, 59))
until = timezone.make_aware(until)
models.KyuDanRanking.objects.update(since=since, until=until, force_recalc=force_recalc)

View File

@@ -1,7 +1,8 @@
"""ObjectManagers for the Django Models used in the Mahjong-Ranking."""
from datetime import date
from . import LOGGER
from django.db import models
from django.conf import settings
class HanchanManager(models.Manager):
@@ -12,23 +13,31 @@ class HanchanManager(models.Manager):
"""
use_for_related_fields = True
def confirmed_hanchans(self, user=None, **filter_args):
def confirmed(self, user=None, since=None, until=None, **filter_args):
""" Return all valid and confirmed Hanchans.
:param user: Only return Hanchans where this user participated.
:param since: only return Hanchans played since the given datetime
:param until: only return Hanchans played until the given datetime
:param filter_args: To add specific arguments to the Django filter.
:return: QuerySet Object
"""
if user:
return self.user_hanchans(user, confirmed=True, **filter_args)
else:
return self.filter(confirmed=True, **filter_args)
return self.user_hanchans(
user, confirmed=True, since=since, until=until, **filter_args)
hanchans = self.filter(confirmed=True, **filter_args)
if since:
hanchans = hanchans.filter(start__gt=since)
if until:
hanchans = hanchans.filter(start__lte=until)
return hanchans
def dan_hanchans(self, user, **filter_args):
def dan_hanchans(self, user, since = None, **filter_args):
""" Return all Hanchans where a specific user has participated and had
gain dan points and make his gamestats availabale.
:param user: Only return Hanchans where this user participated.
:param since: only return Hanchans played since the given datetime
:param filter_args: To add specific arguments to the Django filter.
:return: QuerySet Object
"""
@@ -38,15 +47,18 @@ class HanchanManager(models.Manager):
models.Q(player3=user, player3_dan_points__isnull=False) |
models.Q(player4=user, player4_dan_points__isnull=False)
).filter(confirmed=True, **filter_args)
if since:
queryset = queryset.filter(start__gt=since)
queryset = queryset.select_related().order_by('-start')
[ hanchan.get_playerdata(user) for hanchan in queryset ]
[hanchan.get_playerdata(user) for hanchan in queryset]
return queryset
def kyu_hanchans(self, user, **filter_args):
def kyu_hanchans(self, user, since = None, **filter_args):
""" Return all Hanchans where a specific user has participated and had
gain kyū points and make his gamestats availabale.
:param user: Only return Hanchans where this user participated.
:param since: only return Hanchans played since the given datetime
:param filter_args: To add specific arguments to the Django filter.
:return: QuerySet Object
"""
@@ -56,25 +68,30 @@ class HanchanManager(models.Manager):
models.Q(player3=user, player3_kyu_points__isnull=False) |
models.Q(player4=user, player4_kyu_points__isnull=False)
).filter(confirmed=True, **filter_args)
if since:
queryset = queryset.filter(start__gt=since)
queryset = queryset.select_related().order_by('-start')
[ hanchan.get_playerdata(user) for hanchan in queryset ]
[hanchan.get_playerdata(user) for hanchan in queryset]
return queryset
def season_hanchans(self, user=None, season=None):
def season_hanchans(self, user=None, season=None, until=None):
"""Return all Hanchans that belong to a given or the current season.
:param user: Only return Hanchans where this user participated.
:param season: the year of the wanted season, current year if None.
:return: QuerySet Object
"""
season = season or date.today().year
return self.confirmed_hanchans(user=user, season=season)
try:
season = season or until.year
except AttributeError:
season = date.today().year
return self.confirmed(user=user, season=season, until=until)
def user_hanchans(self, user, since=None, **filter_args):
def user_hanchans(self, user, since=None, until=None, **filter_args):
"""Return all Hanchans where a specific user has participated.
:param user: Return Hanchans where this user participated.
:param since: optional a date value since when you want to hanchans
:param since: only return Hanchans played since the given datetime
:param filter_args: To add specific arguments to the Django filter.
:return: a QuerySet Object
"""
@@ -82,15 +99,16 @@ class HanchanManager(models.Manager):
models.Q(player1=user) | models.Q(player2=user) |
models.Q(player3=user) | models.Q(player4=user)
)
if since:
queryset = queryset.filter(start__gte=since, **filter_args)
else:
queryset = queryset.filter(**filter_args)
if since:
queryset = queryset.filter(start__gt=since)
if until:
queryset = queryset.filter(start__lte=until)
queryset = queryset.select_related().order_by('-start')
[ hanchan.get_playerdata(user) for hanchan in queryset ]
[hanchan.get_playerdata(user) for hanchan in queryset]
return queryset
def unconfirmed_hanchans(self, user=None, **filter_args):
def unconfirmed(self, user=None, **filter_args):
""" Return all Hanchans that have been set to unconfirmed.
:param user: Only return Hanchans where this user participated.
@@ -158,8 +176,27 @@ class SeasonRankingManager(models.Manager):
})
return json_data
class KyuDanRankingManager(models.Manager):
def update(self, season=None, until=None, force_recalc=False):
try:
season = season or until.year
except AttributeError:
season = date.today().year
if until or force_recalc:
for ranking in self.filter(season=season):
ranking.recalculate(until=until)
for placement, ranking in enumerate(self.season_rankings(season), start=1):
ranking.placement = placement
ranking.save(force_update=True, update_fields=['placement'])
def season_rankings(self, season=None):
season = season or date.today().year
rankings = self.filter(
season=season,
hanchan_count__gt=settings.MIN_HANCHANS_FOR_LADDER)
return rankings.order_by('avg_placement', '-avg_score')
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.
@@ -172,9 +209,12 @@ class KyuDanRankingManager(models.Manager):
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')
'hanchan_count', 'won_hanchans', 'good_hanchans',
'last_hanchan_date')
for user in values:
if user['dan']:
if user['hanchan_count'] == 0:
continue
elif user['dan']:
rank = '{}. Dan'.format(user['dan'])
points = user['dan_points']
else:
@@ -183,11 +223,31 @@ class KyuDanRankingManager(models.Manager):
json_data.append({
'user_id': user['user_id'],
'username': user['user__username'],
'full_name': " ".join([user['user__last_name'], user['user__first_name']]),
'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']
'won_hanchans': user['won_hanchans'],
'last_hanchan_date': user['last_hanchan_date']
})
return json_data
def update(self, since=None, until=None, force_recalc=False):
old_attr = {'dan': None, 'dan_points': None,
'kyu': None, 'kyu_points': None, 'won_hanchans': None,
'good_hanchans': None, 'hanchan_count': None}
for ranking in self.all():
old_attr = {attr: getattr(ranking, attr) for attr in
old_attr.keys()}
ranking.calculate(since=since, until=until,
force_recalc=force_recalc)
for attr, old_value in old_attr.items():
if getattr(ranking, attr) != old_value:
LOGGER.warning(
"%(user)s recalc shows differences in %(attr)s! old: %(old)d, new: %(new)d",
{'user': ranking.user, 'attr': attr,
'old': old_value or 0, 'new': getattr(ranking, attr) or 0}
)

View File

@@ -1,8 +1,7 @@
"""Middleware to defer slow denormalization at the end of a request."""
from django.core.cache import cache
from mahjong_ranking import models
from . import LOGGER, MIN_HANCHANS_FOR_LADDER
from . import LOGGER
class DenormalizationUpdateMiddleware(object): # Ignore PyLintBear (R0903)
@@ -35,7 +34,7 @@ class DenormalizationUpdateMiddleware(object): # Ignore PyLintBear (R0903)
user_id, hanchan_start = kyu_dan_ranking_queue.pop()
kyu_dan_ranking = models.KyuDanRanking.objects.get_or_create(
user_id=user_id)[0]
kyu_dan_ranking.recalculate(hanchan_start)
kyu_dan_ranking.calculate(since=hanchan_start)
cache.set('kyu_dan_ranking_queue', set(), 360)
ladder_ranking_queue = cache.get('ladder_ranking_queue', set())
@@ -58,12 +57,5 @@ class DenormalizationUpdateMiddleware(object): # Ignore PyLintBear (R0903)
for season in season_queue:
LOGGER.info(u'Recalculate placements for Season %d', season)
season_rankings = models.SeasonRanking.objects.filter(
season=season, hanchan_count__gt=MIN_HANCHANS_FOR_LADDER
).order_by('avg_placement', '-avg_score')
placement = 1
for ranking in season_rankings:
ranking.placement = placement
ranking.save(force_update=True)
placement += 1
models.SeasonRanking.objects.update(season=season)
return response

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.7 on 2017-11-15 05:53
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('mahjong_ranking', '0004_auto_20170218_1947'),
]
operations = [
migrations.AlterModelOptions(
name='kyudanranking',
options={'ordering': ('-dan_points', 'dan', '-kyu_points'), 'verbose_name': 'Kyū/Dan Wertung', 'verbose_name_plural': 'Kyū/Dan Wertungen'},
),
migrations.AddField(
model_name='kyudanranking',
name='last_hanchan_date',
field=models.DateTimeField(blank=True, null=True),
),
migrations.AddField(
model_name='kyudanranking',
name='wins_in_a_row',
field=models.PositiveIntegerField(default=0),
),
]

View File

@@ -0,0 +1,18 @@
from datetime import date
from .models import Hanchan, SeasonRanking
from events.models import Event
class MahjongMixin(object):
def get_context_data(self, **kwargs):
context = super(MahjongMixin, self).get_context_data(**kwargs)
try:
context['season'] = self.season
context['season_start'] = date(year=self.season, month=1, day=1)
context['season_end'] = date(year=self.season, month=12, day=31)
context['season_list'] = SeasonRanking.objects.season_list
except AttributeError:
pass
context['latest_hanchan_list'] = Hanchan.objects.confirmed()[:3]
context['latest_event_list'] = Event.objects.latest(limit=3)
return context

View File

@@ -5,6 +5,8 @@
from __future__ import division
from datetime import datetime, time
from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse
@@ -56,7 +58,7 @@ class EventRanking(models.Model):
)
sum_placement = 0.0
sum_score = 0.0
event_hanchans = Hanchan.objects.confirmed_hanchans(
event_hanchans = Hanchan.objects.confirmed(
user=self.user_id,
event=self.event_id
)
@@ -345,10 +347,10 @@ class KyuDanRanking(models.Model):
legacy_hanchan_count = models.PositiveIntegerField(default=0)
legacy_dan_points = models.PositiveIntegerField(default=0)
legacy_kyu_points = models.PositiveIntegerField(default=0)
wins_in_a_row = 0
wins_in_a_row = models.PositiveIntegerField(default=0)
last_hanchan_date = models.DateTimeField(blank=True, null=True)
objects = managers.KyuDanRankingManager()
class Meta(object):
ordering = ('-dan_points', 'dan', '-kyu_points')
verbose_name = _(u'Kyū/Dan Ranking')
@@ -436,11 +438,19 @@ class KyuDanRanking(models.Model):
else:
return reverse('player-kyu-score', args=[self.user.username])
def recalculate(self, hanchan_start=None):
def calculate(self, since=None, until=None, force_recalc=False):
"""
Fetches all valid Hanchans from this Player and recalculates his
Kyu/Dan Ranking.
"""
valid_hanchans = Hanchan.objects.confirmed(user=self.user)
valid_hanchans = valid_hanchans.order_by('start')
if since and self.last_hanchan_date and since < self.last_hanchan_date:
force_recalc = True
if until and self.last_hanchan_date and until < self.last_hanchan_date:
force_recalc = True
if force_recalc:
# Setze alles auf die legacy Werte und berechne alles von neuem.
self.dan = None
self.dan_points = self.legacy_dan_points or 0
self.kyu = None
@@ -449,23 +459,32 @@ class KyuDanRanking(models.Model):
self.good_hanchans = 0
self.won_hanchans = 0
self.update_rank()
LOGGER.info(
"recalculating Kyu/Dan points for %s since %s...",
self.user, str(hanchan_start)
)
valid_hanchans = Hanchan.objects.confirmed_hanchans(
user=self.user).order_by('start')
self.last_hanchan_date = None
if self.legacy_date:
valid_hanchans = valid_hanchans.filter(start__gt=self.legacy_date)
since = timezone.make_aware(
datetime.combine(self.legacy_date, time(0, 0, 0)))
else:
since = None
elif self.last_hanchan_date:
since = self.last_hanchan_date
elif self.legacy_date:
since = timezone.make_aware(
datetime.combine(self.legacy_date, time(0, 0, 0))
)
LOGGER.info(
"recalculating Kyu/Dan points for %(user)s since %(since)s...",
{'user': self.user, 'since': str(since)}
)
if since:
valid_hanchans = valid_hanchans.filter(start__gt=since)
if until:
valid_hanchans = valid_hanchans.filter(start__lte=until)
""" TODO: Hanchan Punkte nur neu berechnen wenn sie nach hachan_start
lagen. Es müssen aber alle durch die Schleife rennen, damit die Punkte
richtig gezählt werden."""
self.hanchan_count += valid_hanchans.count()
for hanchan in valid_hanchans:
hanchan.get_playerdata(self.user)
if hanchan_start and hanchan_start < hanchan.start:
if since and hanchan.start < since:
print(hanchan, "<", since, "no recalc")
self.dan_points += hanchan.dan_points or 0
self.kyu_points += hanchan.kyu_points or 0
self.update_rank()
@@ -482,6 +501,7 @@ class KyuDanRanking(models.Model):
hanchan.save(recalculate=False)
self.won_hanchans += 1 if hanchan.placement == 1 else 0
self.good_hanchans += 1 if hanchan.placement == 2 else 0
self.last_hanchan_date = hanchan.start
LOGGER.debug(
'id: %(id)d, start: %(start)s, placement: %(placement)d, '
'score: %(score)d, kyu points: %(kyu_points)d, dan points: '
@@ -494,6 +514,7 @@ class KyuDanRanking(models.Model):
)
self.save(force_update=True)
def update_hanchan_points(self, hanchan):
"""
Berechne die Kyu bzw. Dan Punkte für eine Hanchan neu.
@@ -547,6 +568,7 @@ class KyuDanRanking(models.Model):
hanchan.kyu_points -= (self.kyu_points + hanchan.kyu_points)
self.kyu_points += hanchan.kyu_points
# TODO: Merkwürdige Methode die zwar funktioniert aber nicht sehr
# aussagekräfig ist. Überarbeiten?
def update_rank(self):
@@ -566,7 +588,7 @@ class KyuDanRanking(models.Model):
self.kyu = 10
elif self.kyu_points > 50:
self.dan = 1
self.kyu = None
self.kyu = 0
self.dan_points = 0
self.kyu_points = 0
else:
@@ -593,9 +615,9 @@ class SeasonRanking(models.Model):
def get_absolute_url(self):
return reverse('player-ladder-score', args=[self.user.username])
def recalculate(self):
def recalculate(self, until=None):
season_hanchans = Hanchan.objects.season_hanchans(
user=self.user, season=self.season)
user=self.user, season=self.season, until=until)
sum_placement = 0
sum_score = 0
self.placement = None

View File

@@ -1,12 +1,12 @@
{% extends "mahjong_ranking/page.html" %}
{% load i18n thumbnail %}
{% block title %}{% trans 'Player List' %}{% endblock %}
{% block title %}{% trans 'Players list' %}{% endblock %}
{% block extra_head %}
<link rel="canonical" href="{% url 'kyudanranking-list' %}?page={{page_obj.number}}" />
{% endblock %}
{% block teaser %}<h1>{% trans 'Player List' %}</h1>{% endblock %}
{% block teaser %}<h1>{% trans 'Players list' %}</h1>{% endblock %}
{% block redbox %}{% include 'mahjong_ranking/ladder_redbox.html' %}{% endblock %}

View File

@@ -34,7 +34,7 @@ class KyuDanTest(TestCase):
for ranking in KyuDanRanking.objects.all():
original = {a: getattr(ranking, a) for a in self.equal_attrs}
ranking.recalculate()
ranking.calculate()
for attr in self.equal_attrs:
self.assertEqual(
original[attr],
@@ -54,7 +54,7 @@ class KyuDanTest(TestCase):
for ranking in KyuDanRanking.objects.all():
original = {a: getattr(ranking, a) for a in self.equal_attrs}
confirmed_hanchans = Hanchan.objects.confirmed_hanchans(
confirmed_hanchans = Hanchan.objects.confirmed(
user=ranking.user,
since=ranking.legacy_date
)
@@ -62,7 +62,7 @@ class KyuDanTest(TestCase):
continue
rnd = random.randrange(confirmed_hanchans.count())
since = confirmed_hanchans[rnd].start
ranking.recalculate(hanchan_start=since)
ranking.calculate(since=since)
for attr in self.equal_attrs:
self.assertEqual(
original[attr],
@@ -86,7 +86,7 @@ class KyuDanTest(TestCase):
'dan_points': ranking.legacy_dan_points or 0,
'kyu_points': ranking.legacy_kyu_points or 0
}
confirmed_hanchans = Hanchan.objects.confirmed_hanchans(
confirmed_hanchans = Hanchan.objects.confirmed(
user=ranking.user,
since=ranking.legacy_date
)

View File

@@ -11,11 +11,11 @@ from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _
from django.views import generic
from events.models import Event
from events.mixins import EventDetailMixin
from . import forms, models
from .mixins import MahjongMixin
kyu_dan_order = {
KYU_DAN_ORDER = { # map sort URL args to Django ORM order_by args
'+full_name': ('user__last_name', 'user__first_name'),
'-full_name': ('-user__last_name', '-user__first_name'),
'+hanchan_count': ('hanchan_count',),
@@ -31,16 +31,17 @@ kyu_dan_order = {
class DeleteHanchan(EventDetailMixin, PermissionRequiredMixin,
generic.DeleteView):
"""
Fragt zuerst nach, ob die Hanchan wirklich gelöscht werden soll.
Wir die Frage mit "Ja" beantwortet, wird die die Hanchan gelöscht.
"""
"""Deletes a Hanchan if confimration has been answerd with 'yes'."""
form_class = forms.HanchanForm
model = models.Hanchan
permission_required = 'mahjong_ranking.delete_hanchan'
pk_url_kwarg = 'hanchan'
def get_success_url(self):
"""
Return to the HachanList of the event form the deleted hanchan.
:return: URL of the EventHanchanList for the event
"""
return reverse('event-hanchan-list',
kwargs={'event': self.object.event.pk})
@@ -48,32 +49,30 @@ class DeleteHanchan(EventDetailMixin, PermissionRequiredMixin,
class HanchanForm(SuccessMessageMixin, EventDetailMixin,
PermissionRequiredMixin, generic.UpdateView):
"""
Ein Formular um neue Hanchans anzulegen, bzw. eine bestehende zu
bearbeitsen
A Form to add a new or edit an existing Hanchan.
"""
form_class = forms.HanchanForm
model = models.Hanchan
permission_required = 'mahjong_ranking.add_hanchan'
def get_context_data(self, **kwargs):
context = generic.UpdateView.get_context_data(self, **kwargs)
context['event'] = self.event
return context
def get_form_class(self):
"""
Users with edit Persmission will see the AdminForm to confirm
unconfirmed Hanchans.
Users with hanchan edit persmission can also un-/confirm hanchans.
:return: forms.HanchanForm, or forms.HanchanAdminForm
"""
if self.request.user.has_perm('mahjong_ranking.change_hanchan'):
return forms.HanchanAdminForm
else:
return forms.HanchanForm
return forms.HanchanAdminForm if self.request.user.has_perm(
'mahjong_ranking.change_hanchan') else forms.HanchanForm
def get_object(self, queryset=None):
"""
load the hanchan form the db, or create a new one with the event set.
Also sets the event attribute.
:param queryset:
:return: models.Hanchan object
"""
if self.kwargs.get('hanchan') and self.request.user.has_perm(
'mahjong_ranking.change_hanchan'):
hanchan = models.Hanchan.objects.get(id=self.kwargs['hanchan'])
hanchan = self.model.objects.get(id=self.kwargs['hanchan'])
self.event = hanchan.event
elif self.kwargs.get('event'):
self.event = models.Event.objects.get(id=self.kwargs['event'])
@@ -94,6 +93,11 @@ class HanchanForm(SuccessMessageMixin, EventDetailMixin,
return reverse('add-hanchan-form', kwargs={'event': self.event.pk})
def get_success_message(self, cleaned_data):
"""
Get the right sucsess message for the django notification subsystem.
:param cleaned_data:
:return: Sucsess message
"""
if self.kwargs.get('hanchan'):
return _('%s has been updated successfully.') % self.object
else:
@@ -103,72 +107,36 @@ class HanchanForm(SuccessMessageMixin, EventDetailMixin,
class EventHanchanList(EventDetailMixin, generic.ListView):
"""
Auflistung aller Hanchan die während der Veranstaltung gespielt wurden.
"""
"List all hanchans played on a given event."
model = models.Hanchan
template_name = 'mahjong_ranking/eventhanchan_list.html'
def get_queryset(self):
try:
self.event = models.Event.objects.get(pk=self.kwargs['event'])
queryset = models.Hanchan.objects.filter(event=self.event)
queryset = queryset.order_by('start')
return queryset
except models.Event.DoesNotExist:
raise django.http.Http404(_('Event does not exist'))
class EventRankingList(EventDetailMixin, generic.ListView):
"""
Anzeige des Eventrankings, daß erstellt wurde falls der Termin als internes
Turnier markiert wurde.
"""
"""Display the event ranking for the given event."""
model = models.EventRanking
def get_queryset(self):
try:
self.event = models.Event.objects.get(pk=self.kwargs['event'])
queryset = models.EventRanking.objects.filter(event=self.event)
return queryset.prefetch_related()
except models.Event.DoesNotExist:
raise django.http.Http404(_('Event does not exist'))
class MahjongMixin(object):
def get_context_data(self, **kwargs):
context = super(MahjongMixin, self).get_context_data(**kwargs)
try:
context['season'] = self.season
context['season_start'] = date(year=self.season, month=1, day=1)
context['season_end'] = date(year=self.season, month=12, day=31)
context['season_list'] = models.SeasonRanking.objects.season_list
except AttributeError:
pass
context[
'latest_hanchan_list'] = \
models.Hanchan.objects.confirmed_hanchans()[
:3]
context['latest_event_list'] = Event.objects.upcoming(limit=3)
return context
class KyuDanRankingList(MahjongMixin, generic.ListView):
"""
Anzeige aller Spiele mit ihrem Kyu bzw Dan Grad.
"""
"""List all Players with an Kyu or Dan score. """
default_order = '-score'
order_by = ''
paginate_by = 25
def dispatch(self, request, *args, **kwargs):
self.order_by = kyu_dan_order[
"""Set the order_by settings, revert to default_order if necessary."""
self.order_by = KYU_DAN_ORDER[
kwargs.get('order_by', self.default_order)
]
return generic.ListView.dispatch(self, request, *args, **kwargs)
return super(KyuDanRankingList, self).dispatch(request, *args, **kwargs)
def get_queryset(self):
queryset = models.KyuDanRanking.objects.all().order_by(*self.order_by)
queryset = models.KyuDanRanking.objects.filter(
hanchan_count__gt=0).order_by(*self.order_by)
return queryset.select_related()
@@ -223,14 +191,16 @@ class PlayerDanScore(PlayerScore):
template_name = 'mahjong_ranking/player_dan_score.html'
def get_queryset(self):
return models.Hanchan.objects.dan_hanchans(user=self.user)
kyu_dan_ranking = models.KyuDanRanking.objects.get(user=self.user)
return models.Hanchan.objects.dan_hanchans(user=self.user,
since=kyu_dan_ranking.legacy_date)
class PlayerInvalidScore(PlayerScore):
template_name = 'mahjong_ranking/player_invalid_score.html'
def get_queryset(self):
return models.Hanchan.objects.unconfirmed_hanchans(user=self.user)
return models.Hanchan.objects.unconfirmed(user=self.user)
class PlayerKyuScore(PlayerScore):

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: kasu.mahjong_ranking\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-06-19 22:46+0200\n"
"POT-Creation-Date: 2018-04-27 09:49+0200\n"
"PO-Revision-Date: 2016-09-28 00:24+0200\n"
"Last-Translator: Christian Berg <xeniac.at@gmail.com>\n"
"Language-Team: Kasu <verein@kasu.at>\n"
@@ -19,208 +19,205 @@ msgstr ""
"X-Generator: Poedit 1.8.9\n"
"X-Translated-Using: django-rosetta 0.7.2\n"
#: maistar_ranking/admin.py:19
#: admin.py:24
msgid "Recalculate"
msgstr "Neuberechnen"
#: maistar_ranking/forms.py:33
#: forms.py:35
#, python-format
msgid "%s may only participate once."
msgstr "%s darf nur einmal teilnehmen."
#: maistar_ranking/models.py:20
#: models.py:20
msgid "Comment"
msgstr "Kommentar"
#: maistar_ranking/models.py:22
#: models.py:22
msgid "Player 1"
msgstr "Spieler 1"
#: maistar_ranking/models.py:24 maistar_ranking/models.py:30
#: maistar_ranking/models.py:36 maistar_ranking/models.py:42
#: maistar_ranking/models.py:48 maistar_ranking/models.py:54
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:19
#: models.py:24 models.py:30 models.py:36 models.py:42 models.py:48
#: models.py:54 templates/maistar_ranking/ranking_list.html:19
msgid "Score"
msgstr "Punkte"
#: maistar_ranking/models.py:28
#: models.py:28
msgid "Player 2"
msgstr "Spieler 2"
#: maistar_ranking/models.py:34
#: models.py:34
msgid "Player 3"
msgstr "Spieler 3"
#: maistar_ranking/models.py:40
#: models.py:40
msgid "Player 4"
msgstr "Spieler 4"
#: maistar_ranking/models.py:46
#: models.py:46
msgid "Player 5"
msgstr "Spieler 5"
#: maistar_ranking/models.py:52
#: models.py:52
msgid "Player 6"
msgstr "Spieler 6"
#: maistar_ranking/models.py:58
#: models.py:58
msgid "Has been confirmed"
msgstr "Wurde bestätigt"
#: maistar_ranking/models.py:60
#: models.py:60
msgid "the game only counts whe it has been confirmed"
msgstr "das Spiel zählt nur wenn es bestätigt wurde"
#: maistar_ranking/models.py:63 maistar_ranking/models.py:148
#: maistar_ranking/templates/maistar_ranking/player_game_list.html:6
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:4
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:72
#: models.py:63 models.py:147 templates/maistar_ranking/player_game_list.html:6
#: templates/maistar_ranking/ranking_list.html:4
#: templates/maistar_ranking/ranking_list.html:72
msgid "Season"
msgstr "Saison"
#: maistar_ranking/models.py:69
#: models.py:74
msgid "Mai-Star Game with {0} from {1:%Y-%m-%d}"
msgstr "Mai-Star Spiel mit {0} vom {1:%Y-%m-%d}"
#: maistar_ranking/templates/maistar_ranking/game_form.html:5
#: maistar_ranking/templates/maistar_ranking/game_form.html:16
#: maistar_ranking/templates/maistar_ranking/game_list.html:27
#: maistar_ranking/templates/maistar_ranking/player_game_list.html:44
#: templates/maistar_ranking/game_form.html:5
#: templates/maistar_ranking/game_form.html:16
#: templates/maistar_ranking/game_list.html:27
#: templates/maistar_ranking/player_game_list.html:44
msgid "Edit Game"
msgstr "Spiel bearbeiten"
#: maistar_ranking/templates/maistar_ranking/game_form.html:5
#: maistar_ranking/templates/maistar_ranking/game_form.html:16
#: maistar_ranking/templates/maistar_ranking/game_list.html:41
#: templates/maistar_ranking/game_form.html:5
#: templates/maistar_ranking/game_form.html:16
#: templates/maistar_ranking/game_list.html:41
msgid "Add Game"
msgstr "Spiel hinzufügen"
#: maistar_ranking/templates/maistar_ranking/game_form.html:76
#: templates/maistar_ranking/game_form.html:76
msgid "Back"
msgstr "Zurück"
#: maistar_ranking/templates/maistar_ranking/game_form.html:77
#: templates/maistar_ranking/game_form.html:77
msgid "Save"
msgstr "Speichern"
#: maistar_ranking/templates/maistar_ranking/game_list.html:4
#: maistar_ranking/templates/maistar_ranking/player_game_list.html:6
#: templates/maistar_ranking/game_list.html:4
#: templates/maistar_ranking/player_game_list.html:6
msgid "Mai-Star Games"
msgstr "Mai-Star Spiele"
#: maistar_ranking/templates/maistar_ranking/game_list.html:7
#: templates/maistar_ranking/game_list.html:7
msgid "Played Mai-Star Games"
msgstr "Gespielte Mai-Star Spiele"
#: maistar_ranking/templates/maistar_ranking/game_list.html:11
#: templates/maistar_ranking/game_list.html:11
msgid "Game"
msgstr "Spiel"
#: maistar_ranking/templates/maistar_ranking/game_list.html:14
#: templates/maistar_ranking/game_list.html:14
msgid "Place"
msgstr "Platz"
#: maistar_ranking/templates/maistar_ranking/game_list.html:19
#: maistar_ranking/templates/maistar_ranking/player_game_list.html:36
#: templates/maistar_ranking/game_list.html:19
#: templates/maistar_ranking/player_game_list.html:36
msgid "Points"
msgstr "Punkte"
#: maistar_ranking/templates/maistar_ranking/game_list.html:24
#: maistar_ranking/templates/maistar_ranking/player_game_list.html:41
#: templates/maistar_ranking/game_list.html:24
#: templates/maistar_ranking/player_game_list.html:41
msgid "Delete Game"
msgstr "Spiel löschen"
#: maistar_ranking/templates/maistar_ranking/game_list.html:33
#: templates/maistar_ranking/game_list.html:33
msgid "No Mai-Star games have been added to this event yet."
msgstr "Für diese Veranstaltung wurden noch keine Mai-Star Spiele erfasst."
#: maistar_ranking/templates/maistar_ranking/game_list.html:40
#: templates/maistar_ranking/game_list.html:40
msgid "Edit Event"
msgstr "Veranstaltung bearbeiten"
#: maistar_ranking/templates/maistar_ranking/hanchan_confirm_delete.html:4
#: maistar_ranking/templates/maistar_ranking/hanchan_confirm_delete.html:10
#: templates/maistar_ranking/hanchan_confirm_delete.html:4
#: templates/maistar_ranking/hanchan_confirm_delete.html:10
msgid "Delete game"
msgstr "Spiel löschen"
#: maistar_ranking/templates/maistar_ranking/hanchan_confirm_delete.html:13
#: templates/maistar_ranking/hanchan_confirm_delete.html:13
msgid "Cancel"
msgstr "Abbrechen"
#: maistar_ranking/templates/maistar_ranking/hanchan_confirm_delete.html:14
#: templates/maistar_ranking/hanchan_confirm_delete.html:14
msgid "Delete"
msgstr "Löschen"
#: maistar_ranking/templates/maistar_ranking/page.html:5
#: templates/maistar_ranking/page.html:5
msgid "Archive"
msgstr "Archiv"
#: maistar_ranking/templates/maistar_ranking/page.html:7
#: templates/maistar_ranking/page.html:7
msgid "Add Event"
msgstr "Veranstaltung hinzufügen"
#: maistar_ranking/templates/maistar_ranking/player_game_list.html:4
#: templates/maistar_ranking/player_game_list.html:4
msgid "Ladder Score for"
msgstr "Ladder Wertung für"
#: maistar_ranking/templates/maistar_ranking/player_game_list.html:9
#: templates/maistar_ranking/player_game_list.html:9
msgid "Mai-Star Games with"
msgstr "Mai-Star Spiele mit"
#: maistar_ranking/templates/maistar_ranking/player_game_list.html:14
#: templates/maistar_ranking/player_game_list.html:14
msgid "Date"
msgstr "Datum"
#: maistar_ranking/templates/maistar_ranking/player_game_list.html:15
#: templates/maistar_ranking/player_game_list.html:15
msgid "Event"
msgstr "Veranstaltung"
#: maistar_ranking/templates/maistar_ranking/player_game_list.html:16
#: templates/maistar_ranking/player_game_list.html:16
msgid "Players"
msgstr "Spieler"
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:4
#: templates/maistar_ranking/ranking_list.html:4
msgid "Mai-Star Ranking"
msgstr "Mai-Star Platzierung"
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:10
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:18
#: templates/maistar_ranking/ranking_list.html:10
#: templates/maistar_ranking/ranking_list.html:18
msgid "Placement"
msgstr "Platzierung"
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:11
#: templates/maistar_ranking/ranking_list.html:11
msgid "Avatar"
msgstr "Avatar"
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:12
#: templates/maistar_ranking/ranking_list.html:12
msgid "Nickname"
msgstr "Spitzname"
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:13
#: templates/maistar_ranking/ranking_list.html:13
msgid "Name"
msgstr "Name"
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:14
#: templates/maistar_ranking/ranking_list.html:14
msgid "Average"
msgstr "Durchschnitt"
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:15
#: templates/maistar_ranking/ranking_list.html:15
msgid "Games"
msgstr "Spiele"
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:20
#: templates/maistar_ranking/ranking_list.html:20
msgid "count"
msgstr "Anzahl"
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:21
#: templates/maistar_ranking/ranking_list.html:21
msgid "good"
msgstr "Gut"
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:22
#: templates/maistar_ranking/ranking_list.html:22
msgid "won"
msgstr "Gewonnen"
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:43
#: templates/maistar_ranking/ranking_list.html:43
msgid ""
"Unfortunately, nobody has it been done in the ranking.\n"
" A player must have 6 games done, to be added to the ranking."
@@ -229,15 +226,15 @@ msgstr ""
"als 6 Spiele innerhalb einer Saison absolviert haben, werden für das "
"Endergebnis nicht gewertet."
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:52
#: templates/maistar_ranking/ranking_list.html:52
msgid "Latest Games"
msgstr "Letzten Spiele"
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:63
#: templates/maistar_ranking/ranking_list.html:63
msgid "Latest Events"
msgstr "Letzten Veranstaltungen"
#: maistar_ranking/templates/maistar_ranking/ranking_list.html:70
#: templates/maistar_ranking/ranking_list.html:70
msgid "Ladder Archive"
msgstr "Archiv"

View File

@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.7 on 2017-11-15 05:53
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('maistar_ranking', '0005_auto_20170218_1947'),
]
operations = [
migrations.AlterModelOptions(
name='game',
options={'ordering': ('-event__start', '-id')},
),
]

View File

@@ -7,196 +7,193 @@ msgid ""
msgstr ""
"Project-Id-Version: kasu.membership\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-06-19 22:46+0200\n"
"PO-Revision-Date: 2016-09-28 00:24+0200\n"
"Last-Translator: Christian Berg <xeniac@posteo.at>\n"
"POT-Creation-Date: 2018-04-27 09:49+0200\n"
"PO-Revision-Date: 2018-04-27 10:30+0105\n"
"Last-Translator: b'Christian Berg <kasu@xendynastie.at>'\n"
"Language-Team: Kasu <verein@kasu.at>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Translated-Using: django-rosetta 0.7.2\n"
"X-Generator: Poedit 1.8.9\n"
"X-Translated-Using: django-rosetta 0.7.14\n"
#: membership/admin.py:22
#: __init__.py:11
msgid "Male"
msgstr "Männlich"
#: __init__.py:12
msgid "Female"
msgstr "Weiblich"
#: admin.py:22
msgid "Activate selected User"
msgstr "Ausgewählte Benutzer freischalten"
#: membership/admin.py:31
#: admin.py:38
msgid "Cleanup selected Activation Requests"
msgstr "Ausgewählte Aktivierungsanfragen bereinigen"
#: membership/admin.py:37
#: admin.py:47
msgid "Group"
msgstr "Gruppe"
#: membership/admin.py:38
#: admin.py:48
msgid "Groups"
msgstr "Gruppen"
#: membership/admin.py:59 membership/models.py:164 membership/models.py:215
#: membership/templates/membership/register_form.html:32
#: admin.py:72 models.py:162 models.py:215
#: templates/membership/register_form.html:32
msgid "Membership"
msgstr "Mitgliedschaft"
#: membership/admin.py:64
#: admin.py:77
msgid "Permissions"
msgstr "Berechtigung"
#: membership/admin.py:66
#: admin.py:79
msgid "Important dates"
msgstr "Wichtige Daten"
#: membership/forms.py:23
#: forms.py:23
msgid "birthday"
msgstr "Geburtstag"
#: membership/forms.py:25
#: forms.py:25
msgid "Input format: yyyy-mm-dd"
msgstr "Eingabeformat: tt.mm.jjjj"
#: membership/forms.py:27
#: forms.py:27
msgid "Email"
msgstr "E-Mail"
#: membership/forms.py:39 membership/forms.py:46 membership/forms.py:53
#: forms.py:42 forms.py:50 forms.py:58
msgid ""
"For your membership, we need this. Please fill out this field "
"yet."
msgstr "Diese Angabe wird für eine Mitgliedschaft benötigt, bitte ausfüllen."
#: membership/forms.py:59
#: forms.py:65
msgid ""
"For your membership, we need this. Please fill out this field "
"yet."
msgstr "Diese Angabe wird für eine Mitgliedschaft benötigt, bitte ausfüllen."
#: membership/forms.py:72
#: forms.py:78
msgid "password"
msgstr "Passwort"
#: membership/forms.py:74
#: forms.py:80
msgid "password (again)"
msgstr "Passwort (wiederholen)"
#: membership/forms.py:97
#: forms.py:102
msgid "This username is already taken. Please choose another."
msgstr "Diesen Benutzername ist schon vergeben. Bitte einen anderen auswählen."
msgstr ""
"Diesen Benutzername ist schon vergeben. Bitte einen anderen auswählen."
#: membership/forms.py:106
#: forms.py:109
msgid ""
"This email address is already in use. Please supply a different "
"email address."
msgstr "Die E-Mail Adresse wird schon verwendet. Bitte eine andere angeben."
#: membership/forms.py:115
#: forms.py:119
msgid "The two password fields didn't match."
msgstr "Die beiden Passwörter passen nicht."
#: membership/models.py:20
msgid "Male"
msgstr "Männlich"
#: membership/models.py:21
msgid "Female"
msgstr "Weiblich"
#: membership/models.py:90
#: models.py:83
msgid "user"
msgstr "Benutzer"
#: membership/models.py:92
#: models.py:85
msgid "activation key"
msgstr "Aktivierungsschlüssel"
#: membership/models.py:96
#: models.py:89
msgid "pending activation"
msgstr "Ausstehende Aktivierung"
#: membership/models.py:97
#: models.py:90
msgid "pending activations"
msgstr "Wartende Aktivierungen"
#: membership/models.py:100
#: models.py:93
#, python-format
msgid "user registration for %s"
msgstr "Benutzerregistrierung für %s"
#: membership/models.py:147
#: models.py:148
msgid "Gender"
msgstr "Geschlecht"
#: membership/models.py:166
#: models.py:164
msgid ""
"Yes, I confirm that I am in agreement with the statutes and would "
"like to become a member."
msgstr "Ja, ich bin mit den Statuen einverstanden und möchte Mitglied werden."
#: membership/models.py:170
#: models.py:168
msgid "Birthday Date"
msgstr "Geburtstag"
#: membership/models.py:174
#: models.py:172
msgid "Telephone"
msgstr "Telefon"
#: membership/models.py:180
#: models.py:178
msgid "Address"
msgstr "Adresse"
#: membership/models.py:186
#: models.py:184
msgid "Postcode"
msgstr "Postleitzahl"
#: membership/models.py:191
#: models.py:189
msgid "Town/City"
msgstr "Ort"
#: membership/models.py:199
#: models.py:197
msgid "Paid until"
msgstr "Bezahlt bis"
#: membership/models.py:205
#: models.py:203
msgid "Confirmed"
msgstr "Bestätigt"
#: membership/models.py:207
#: models.py:205
msgid "This person has paid the membership fee."
msgstr "Diese Person hat ihre Mitgliedschaft bezahlt"
#: membership/models.py:216
#: models.py:216
msgid "Memberships"
msgstr "Mitgliedschaften"
#: membership/templates/membership/email/activation_email.txt:2
#: templates/membership/email/activation_email.txt:2
#, python-format
msgid "Welcome %(user)s,"
msgstr "Herzlich willkommen %(user)s,"
#: membership/templates/membership/email/activation_email.txt:4
#: templates/membership/email/activation_email.txt:4
#, python-format
msgid ""
"We received an account request on %(site.domain)s for your email address.\n"
"To activate your account please visit the following link:"
msgstr ""
"Jemand (hoffentlich du selbst) möchte mit dieser E-Mail Adresse einen neuen "
"Benutzer Account für %(site.domain)s anlegen.\n"
"Solltest du diesen Account aktivieren wollen, klicke bitte auf den unten "
"stehenden Link, oder kopiere diesen in die Adresszeile deines Browsers:"
"Jemand (hoffentlich du selbst) möchte mit dieser E-Mail Adresse einen neuen Benutzer Account für %(site.domain)s anlegen.\n"
"Solltest du diesen Account aktivieren wollen, klicke bitte auf den unten stehenden Link, oder kopiere diesen in die Adresszeile deines Browsers:"
#: membership/templates/membership/email/activation_email.txt:9
#: templates/membership/email/activation_email.txt:9
#, python-format
msgid ""
"If you do not want to open an account on %(site.domain)s, please ignore this "
"email.\n"
"If you do not want to open an account on %(site.domain)s, please ignore this email.\n"
"Your information will then be deleted in a few days time."
msgstr ""
"Wenn du keinen Zugang für %(site.domain)s eröffnen willst, ignoriere diese E-"
"Mail bitte.\n"
"Wenn du keinen Zugang für %(site.domain)s eröffnen willst, ignoriere diese E-Mail bitte.\n"
"Die Zugangsdaten werden dann in ein paar Tagen automatisch gelöscht."
#: membership/templates/membership/email/activation_email.txt:12
#: templates/membership/email/activation_email.txt:12
#, python-format
msgid ""
"Best Regards,\n"
@@ -205,216 +202,210 @@ msgstr ""
"mit den besten Wünschen\n"
"Das Team von %(site.domain)s"
#: membership/templates/membership/email/password_reset_email.html:2
#: templates/membership/email/password_reset_email.html:2
msgid "You're receiving this e-mail because you requested a password reset"
msgstr ""
"Du hast diese E-Mail erhalten, weil jemand die das Passwort zurücksetzen "
"möchte. "
#: membership/templates/membership/email/password_reset_email.html:3
#: templates/membership/email/password_reset_email.html:3
#, python-format
msgid "for your user account at %(site_name)s"
msgstr "Für deinen Benutzerzugang auf %(site_name)s"
#: membership/templates/membership/email/password_reset_email.html:5
#: templates/membership/email/password_reset_email.html:5
msgid "Please go to the following page and choose a new password:"
msgstr "Bitte gehe auf folgende Seite und wähle ein neues Passwort aus:"
#: membership/templates/membership/email/password_reset_email.html:9
#: templates/membership/email/password_reset_email.html:9
msgid "Your username, in case you've forgotten:"
msgstr "Dein Benutzername, für den Fall das du diesen vergessen hast:"
#: membership/templates/membership/email/password_reset_email.html:11
#: templates/membership/email/password_reset_email.html:11
msgid "Thanks for using our site!"
msgstr "Danke das du unsere Seite verwendest!"
#: membership/templates/membership/email/password_reset_email.html:13
#: templates/membership/email/password_reset_email.html:13
#, python-format
msgid "The %(site_name)s team"
msgstr "Das %(site_name)s Team"
#: membership/templates/membership/email/password_reset_subject.txt:2
#: templates/membership/email/password_reset_subject.txt:2
#, python-format
msgid "Password reset on %(site_name)s"
msgstr "Passwort auf %(site_name)s zurücksetzen"
#: membership/templates/membership/hanchan_table.html:5
#: templates/membership/hanchan_table.html:5
msgid "Start"
msgstr "Beginn"
#: membership/templates/membership/hanchan_table.html:6
#: templates/membership/hanchan_table.html:6
msgid "Event"
msgstr "Termin"
#: membership/templates/membership/hanchan_table.html:7
#: templates/membership/hanchan_table.html:7
msgid "Players"
msgstr "Spieler"
#: membership/templates/membership/hanchan_table.html:8
#: templates/membership/hanchan_table.html:8
msgid "Kyu Points"
msgstr "Kyū Punkte"
#: membership/templates/membership/hanchan_table.html:9
#: templates/membership/hanchan_table.html:9
msgid "Dan Points"
msgstr "Dan Punkte"
#: membership/templates/membership/hanchan_table.html:10
#: templates/membership/hanchan_table.html:10
msgid "Bonus Points"
msgstr "Bonus Punkte"
#: membership/templates/membership/hanchan_table.html:11
#: templates/membership/hanchan_table.html:11
msgid "Comment"
msgstr "Anmerkung"
#: membership/templates/membership/hanchan_table.html:26
#: templates/membership/hanchan_table.html:26
msgid "This Hanchan does not validate"
msgstr "Diese Hanchan ist ungültig"
#: membership/templates/membership/membership_detail.html:6
#: templates/membership/membership_detail.html:6
msgid "profile for"
msgstr "Profil für"
#: membership/templates/membership/membership_detail.html:10
#: templates/membership/membership_detail.html:10
msgid "Ladder Hanchans"
msgstr "Ladder Hanchans"
#: membership/templates/membership/membership_detail.html:11
#: templates/membership/membership_detail.html:11
msgid "Kyu Hanchans"
msgstr "Kyū Hanchans"
#: membership/templates/membership/membership_detail.html:12
#: templates/membership/membership_detail.html:12
msgid "Dan Hanchans"
msgstr "Dan Hanchans"
#: membership/templates/membership/membership_detail.html:13
#: templates/membership/membership_detail.html:13
msgid "Invalid Hanchans"
msgstr "Ungültige Hanchans"
#: membership/templates/membership/membership_detail.html:14
#: templates/membership/membership_detail.html:14
msgid "Mai-Star Games"
msgstr "Mai-Star Spiele"
#: membership/templates/membership/membership_detail.html:20
#: templates/membership/membership_detail.html:20
msgid "Profile Image"
msgstr "Profilbild"
#: membership/templates/membership/membership_detail.html:28
#: templates/membership/membership_detail.html:28
msgid "Member Since"
msgstr "Mitglied seit"
#: membership/templates/membership/membership_detail.html:29
#: templates/membership/membership_detail.html:29
msgid "Last Login"
msgstr "Letzte Anmeldung"
#: membership/templates/membership/membership_detail.html:38
#: membership/templates/membership/membership_detail.html:40
#: templates/membership/membership_detail.html:38
#: templates/membership/membership_detail.html:40
msgid "Points"
msgstr "Punkte"
#: membership/templates/membership/membership_detail.html:42
#: templates/membership/membership_detail.html:42
msgid "Games Total"
msgstr "Spiele gesamt"
#: membership/templates/membership/membership_detail.html:43
#: membership/templates/membership/membership_detail.html:45
#: templates/membership/membership_detail.html:43
#: templates/membership/membership_detail.html:45
msgid "Won"
msgstr "Gewonnen"
#: membership/templates/membership/membership_detail.html:43
#: membership/templates/membership/membership_detail.html:45
#: templates/membership/membership_detail.html:43
#: templates/membership/membership_detail.html:45
msgid "Good"
msgstr "Gut"
#: membership/templates/membership/membership_detail.html:45
#: templates/membership/membership_detail.html:45
msgid "Current Season"
msgstr "Aktuelle Saison"
#: membership/templates/membership/membership_detail.html:55
#: templates/membership/membership_detail.html:55
msgid "Edit Profile"
msgstr "Profil bearbeiten"
#: membership/templates/membership/membership_detail.html:59
#: membership/templates/registration/password_change_form.html:23
#: templates/membership/membership_detail.html:59
#: templates/registration/password_change_form.html:23
msgid "Change Password"
msgstr "Passwort ändern"
#: membership/templates/membership/membership_detail.html:63
#: membership/templates/membership/membership_detail.html:67
#: membership/templates/membership/membership_detail.html:71
#: templates/membership/membership_detail.html:63
#: templates/membership/membership_detail.html:67
#: templates/membership/membership_detail.html:71
#, python-format
msgid "Associate with %(name)s"
msgstr "Verbinde mit %(name)s"
#: membership/templates/membership/membership_form.html:4
#: membership/templates/membership/membership_form.html:6
#: membership/templates/membership/membership_form.html:11
#: templates/membership/membership_form.html:4
#: templates/membership/membership_form.html:6
#: templates/membership/membership_form.html:11
msgid "Edit Userprofile"
msgstr "Profil bearbeiten"
#: membership/templates/membership/membership_form.html:15
#: templates/membership/membership_form.html:15
msgid "Reset"
msgstr "Zurücksetzen"
#: membership/templates/membership/membership_form.html:16
#: templates/membership/membership_form.html:16
msgid "Save"
msgstr "Speichern"
#: membership/templates/membership/register_form.html:4
#: membership/templates/membership/register_form.html:7
#: templates/membership/register_form.html:4
#: templates/membership/register_form.html:7
msgid "Registration"
msgstr "Registrieren"
#: membership/templates/membership/register_form.html:9
#: templates/membership/register_form.html:9
msgid ""
"After you've provided your account data, you'll receive\n"
" an email asking you to verify your email address. You have to click on "
"the\n"
" link in this verification email to confirm your email address, "
"otherwise\n"
" an email asking you to verify your email address. You have to click on the\n"
" link in this verification email to confirm your email address, otherwise\n"
" your can't login."
msgstr ""
"Nach dem du deine Daten eingegeben hast, wirst du eine E-Mail zur "
"Bestätigung bekommen.\n"
"Bitte klicke auf den Link in dieser E-Mail zur Verifizierung, erst dann ist "
"die Anmeldung möglich."
"Nach dem du deine Daten eingegeben hast, wirst du eine E-Mail zur Bestätigung bekommen.\n"
"Bitte klicke auf den Link in dieser E-Mail zur Verifizierung, erst dann ist die Anmeldung möglich."
#: membership/templates/membership/register_form.html:20
#: templates/membership/register_form.html:20
msgid "name"
msgstr "Name"
#: membership/templates/membership/register_form.html:26
#: membership/templates/registration/login.html:41
#: templates/membership/register_form.html:26
#: templates/registration/login.html:41
msgid "login"
msgstr "Anmelden"
#: membership/templates/membership/register_form.html:39
#: templates/membership/register_form.html:39
msgid "reset"
msgstr "Zurücksetzen"
#: membership/templates/membership/register_form.html:41
#: membership/templates/registration/login.html:35
#: templates/membership/register_form.html:41
#: templates/registration/login.html:35
msgid "register"
msgstr "Registrieren"
#: membership/templates/membership/register_successful.html:5
#: membership/templates/membership/register_successful.html:7
#: membership/templates/membership/register_successful.html:10
#: templates/membership/register_successful.html:5
#: templates/membership/register_successful.html:7
#: templates/membership/register_successful.html:10
msgid "Activation sent"
msgstr "Aktivierung wurde zugesendet"
#: membership/templates/registration/login.html:4
#: membership/templates/registration/login.html:11
#: membership/templates/registration/login.html:53
#: membership/templates/registration/password_reset_complete.html:13
#: templates/registration/login.html:4 templates/registration/login.html:11
#: templates/registration/login.html:53
#: templates/registration/password_reset_complete.html:13
msgid "Login"
msgstr "Anmelden"
#: membership/templates/registration/login.html:17
#: templates/registration/login.html:17
msgid "Have you already registered?"
msgstr "Bereits registriert?"
#: membership/templates/registration/login.html:18
#, fuzzy
#: templates/registration/login.html:18
#| msgid ""
#| "\n"
#| "<p>As a registered member you can:</p>\n"
@@ -441,17 +432,14 @@ msgstr ""
" <li>Kommentare auf dieser Seite hinterlassen.</li>\n"
" <li>Dich für unseren Newsletter anmelden</li>\n"
" <li>Mitglied in unserem Verein werden</li>\n"
" <li>Vereinsmitglieder haben auch vollen Zugang zu unserem Ranking System</"
"li>\n"
"</ul>\n"
" <li>Vereinsmitglieder haben auch vollen Zugang zu unserem Ranking System</li>\n"
"</ul>"
#: membership/templates/registration/login.html:27
#, fuzzy
#: templates/registration/login.html:27
#| msgid ""
#| "\n"
#| "<p>You can register here with your Google, or Facebook account.\n"
#| "If you don't own such an account, or do not want to use it for "
#| "authentication,\n"
#| "If you don't own such an account, or do not want to use it for authentication,\n"
#| "you can fill out our registration form.</p>\n"
msgid ""
"\n"
@@ -462,80 +450,79 @@ msgid ""
" "
msgstr ""
"\n"
"<p>Du kannst dich auch über deinen Facebook, Google, oder Twitter Account "
"anmelden.\n"
"<p>Du kannst dich auch über deinen Facebook, Google, oder Twitter Account anmelden.\n"
"Wenn du so etwas nicht besitzt, oder nicht verwenden möchtest, \n"
"kannst du auch das Registrierungsformular ausfüllen.</p>\n"
"kannst du auch das Registrierungsformular ausfüllen.</p>"
#: membership/templates/registration/login.html:45
#, fuzzy
#: templates/registration/login.html:45
#| msgid "Your username and password didn't match. Please try again."
msgid ""
"Your username and password didn't match. Please try\n"
" again."
msgstr ""
"Benutzername und Passwort stimmen nicht überein. Bitte noch einmal versuchen."
"Benutzername und Passwort stimmen nicht überein. Bitte noch einmal "
"versuchen."
#: membership/templates/registration/login.html:50
#: templates/registration/login.html:50
msgid "Forgot your Password?"
msgstr "Passwort vergessen?"
#: membership/templates/registration/login.html:60
#: templates/registration/login.html:60
msgid "or login with an existing Account"
msgstr "oder über einen existierenden Account anmelden"
#: membership/templates/registration/login.html:63
#: templates/registration/login.html:63
msgid "Login with Facebook"
msgstr "Über Facebook anmelden"
#: membership/templates/registration/login.html:66
#: templates/registration/login.html:66
msgid "Login with Twitter"
msgstr "Über Twitter anmelden"
#: membership/templates/registration/login.html:69
#: templates/registration/login.html:69
msgid "Login with Google"
msgstr "Über Google Anmelden"
#: membership/templates/registration/password_change_done.html:4
#: membership/templates/registration/password_change_done.html:7
#: templates/registration/password_change_done.html:4
#: templates/registration/password_change_done.html:7
msgid "Password change successful"
msgstr "Benutzerprofil erfolgreich geändert."
#: membership/templates/registration/password_change_done.html:8
#: templates/registration/password_change_done.html:8
msgid "Your password was changed."
msgstr "Passwort geändet"
#: membership/templates/registration/password_change_form.html:4
#: membership/templates/registration/password_change_form.html:9
#: membership/templates/registration/password_change_form.html:16
#: templates/registration/password_change_form.html:4
#: templates/registration/password_change_form.html:9
#: templates/registration/password_change_form.html:16
msgid "Password change"
msgstr "Passwort wechseln"
#: membership/templates/registration/password_change_form.html:10
#: templates/registration/password_change_form.html:10
msgid ""
"Please enter your old password, for security's sake, and then enter your new "
"password twice so we can verify you typed it in correctly."
"Please enter your old password, for security's sake, and then enter your new"
" password twice so we can verify you typed it in correctly."
msgstr ""
"Zur Sicherheit bitte altes Passwort einmal und das gewünschte neue Passwort "
"zweimal angeben, so können Tippfehler abgefangen werden."
"Zur Sicherheit bitte altes Passwort einmal und das gewünschte neue Passwort"
" zweimal angeben, so können Tippfehler abgefangen werden."
#: membership/templates/registration/password_reset_complete.html:4
#: membership/templates/registration/password_reset_complete.html:6
#: membership/templates/registration/password_reset_complete.html:9
#: templates/registration/password_reset_complete.html:4
#: templates/registration/password_reset_complete.html:6
#: templates/registration/password_reset_complete.html:9
msgid "Password reset complete"
msgstr "Das Rücksetzen des Passwortes ist abgeschlossen."
#: membership/templates/registration/password_reset_complete.html:10
#: templates/registration/password_reset_complete.html:10
msgid "Your password has been set. You may go ahead and log in now."
msgstr "Das Passwort wurde gesetzt, Du kannst dich nun damit anmelden."
#: membership/templates/registration/password_reset_confirm.html:4
#: membership/templates/registration/password_reset_confirm.html:6
#: membership/templates/registration/password_reset_confirm.html:15
#: templates/registration/password_reset_confirm.html:4
#: templates/registration/password_reset_confirm.html:6
#: templates/registration/password_reset_confirm.html:15
msgid "Enter new password"
msgstr "Neues Passwort eingeben"
#: membership/templates/registration/password_reset_confirm.html:12
#: templates/registration/password_reset_confirm.html:12
msgid ""
"Please enter your new password twice so we can verify you typed it in "
"correctly."
@@ -543,15 +530,15 @@ msgstr ""
"Bitte das Passwort zweimal eingeben, um sicher zu stellen das es korrekt "
"eingetippt wurde."
#: membership/templates/registration/password_reset_confirm.html:18
#: templates/registration/password_reset_confirm.html:18
msgid "Change my password"
msgstr "Passwort ändern"
#: membership/templates/registration/password_reset_confirm.html:26
#: templates/registration/password_reset_confirm.html:26
msgid "Password reset unsuccessful"
msgstr "Passwort rücksetzen fehlgeschlagen"
#: membership/templates/registration/password_reset_confirm.html:27
#: templates/registration/password_reset_confirm.html:27
msgid ""
"The password reset link was invalid, possibly because it has already been "
"used. Please request a new password reset."
@@ -559,22 +546,22 @@ msgstr ""
"Der Link für die Rücksetzung des Passwortes war ungültig, vermutlich wurde "
"er schon einmal benutzt. Bitte eine neue Rücksetzung beantragen."
#: membership/templates/registration/password_reset_done.html:4
#: membership/templates/registration/password_reset_done.html:6
#: membership/templates/registration/password_reset_done.html:12
#: templates/registration/password_reset_done.html:4
#: templates/registration/password_reset_done.html:6
#: templates/registration/password_reset_done.html:12
msgid "Password reset successful"
msgstr "Passwort erfolgreich zurückgesetzt."
#: membership/templates/registration/password_reset_form.html:4
#: membership/templates/registration/password_reset_form.html:6
#: templates/registration/password_reset_form.html:4
#: templates/registration/password_reset_form.html:6
msgid "Password reset"
msgstr "Passwort zurücksetzen"
#: membership/templates/registration/password_reset_form.html:21
#: templates/registration/password_reset_form.html:21
msgid "Transmit"
msgstr "Übermitteln"
#: membership/views.py:63
#: views.py:61
msgid ""
"Activation successful. You can now login anytime with you username "
"and password."
@@ -582,15 +569,14 @@ msgstr ""
"Die Aktivierung war erfolgreich. Du kannst dich ab jetzt jederzeit mit "
"deinem Benutzernamen und Passwort anmelden."
#: membership/views.py:83
#: views.py:88
msgid "User Profile changed successfully"
msgstr "Benutzerprofil erfolgreich geändert."
#: membership/views.py:97
#, fuzzy
#: views.py:112
#| msgid "No %(verbose_name)s found matching the query"
msgid "No Membership found matching the query"
msgstr "Kein %(verbose_name)s gefunden welche der Anfrage entspricht"
msgstr "Keine Mitgliedschaft gefunden welche der Anfrage entspricht"
#~ msgid "Given Name"
#~ msgstr "Vorname"
@@ -599,9 +585,9 @@ msgstr "Kein %(verbose_name)s gefunden welche der Anfrage entspricht"
#~ msgstr "Nachname"
#~ msgid ""
#~ "The Username can only contain the letters from A to Z, Numbers, "
#~ "and the underscore. It must be at least 2 characters long, and "
#~ "cannot be longer the 30. The first character must be a letter."
#~ "The Username can only contain the letters from A to Z, Numbers, and "
#~ "the underscore. It must be at least 2 characters long, and cannot be"
#~ " longer the 30. The first character must be a letter."
#~ msgstr ""
#~ "Der Benutzername kann aus den Buchstaben A-Z, Ziffern und dem Unterstrich "
#~ "bestehen. Es sollte wenigstens 2, aber maximal 30 Zeichen lang sein. Das "

View File

@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.7 on 2017-11-15 05:53
from __future__ import unicode_literals
import django.contrib.auth.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('membership', '0006_auto_20160916_1759'),
]
operations = [
migrations.AlterField(
model_name='membership',
name='gender',
field=models.CharField(blank=True, choices=[('m', 'Male'), ('f', 'Female')], max_length=1, null=True, verbose_name='Geschlecht'),
),
migrations.AlterField(
model_name='membership',
name='username',
field=models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username'),
),
]

File diff suppressed because it is too large Load Diff