# -*- encoding: utf-8 -*- from datetime import date import django.forms import django.http from django.contrib import auth from django.contrib.auth.mixins import LoginRequiredMixin, \ PermissionRequiredMixin from django.contrib.messages.views import SuccessMessageMixin from django.urls import reverse from django.utils.translation import ugettext as _ from django.views import generic from events.mixins import EventDetailMixin from kasu import xlsx from . import forms, models from .mixins import MahjongMixin DEFAULT_KYU_DAN_ORDER = '-score' 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',), '-hanchan_count': ('-hanchan_count',), '+rank': ('-kyu', 'dan'), '-rank': ('-dan', 'kyu'), '+score': ('dan_points', '-dan', 'kyu_points'), '-score': ('-dan_points', 'dan', '-kyu_points'), '+username': ('user__username',), '-username': ('-user__username',) } class DeleteHanchan(EventDetailMixin, PermissionRequiredMixin, generic.DeleteView): """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}) class HanchanForm(SuccessMessageMixin, EventDetailMixin, PermissionRequiredMixin, generic.UpdateView): """ 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_form_class(self): """ Users with hanchan edit persmission can also un-/confirm hanchans. :return: forms.HanchanForm, or forms.HanchanAdminForm """ 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 = 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']) hanchan = models.Hanchan( event=self.event, start=self.event.start ) return hanchan def get_success_url(self): """ Adding a new Hanchan redirect to create_hanchan form. Editing an exiting one: redierect to the Hanchanevent. """ if self.kwargs.get('hanchan'): return self.object.get_absolute_url() else: 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: return _( '%s has been added successfully. You can now add a new ' 'one.') % self.object class EventHanchanForm(EventDetailMixin, PermissionRequiredMixin, generic.TemplateView): """Display a Formset to add and Edit Hanchans of the specific Event.""" permission_required = 'mahjong_ranking.edit_hanchan' template_name = 'mahjong_ranking/eventhanchan_form.html' model=models.Hanchan def get_context_data(self, **kwargs): self.event = models.Event.objects.get(pk=self.kwargs['event']) context = super(EventHanchanForm, self).get_context_data() context['formset'] = self.formset return context def get(self, request, *args, **kwargs): self.get_queryset() self.formset = forms.HanchanFormset( instance=self.event, initial=[{'start': self.event.start}] ) context = self.get_context_data(**kwargs) return self.render_to_response(context) def post(self, request, *args, **kwargs): print("ICH WURDE GEPOSTET!!!!") self.get_queryset() self.formset = forms.HanchanFormset( self.request.POST, self.request.FILES, instance=self.event, initial=[{'start': self.event.start}] ) if self.formset.is_valid(): self.formset.save() return django.http.HttpResponseRedirect( reverse('event-hanchan-form', kwargs={'event': self.event.pk}) ) context = self.get_context_data(**kwargs) return self.render_to_response(context) class EventHanchanList(EventDetailMixin, generic.ListView): "List all hanchans played on a given event." model = models.Hanchan template_name = 'mahjong_ranking/eventhanchan_list.html' class EventRankingList(EventDetailMixin, generic.ListView): """Display the event ranking for the given event.""" model = models.EventRanking class KyuDanRankingList(MahjongMixin, generic.ListView): """List all Players with an Kyu or Dan score. """ order_by = None paginate_by = 25 def dispatch(self, request, *args, **kwargs): """Set the order_by settings, revert to default_order if necessary.""" if kwargs.get('order_by') in KYU_DAN_ORDER.keys(): self.order_by = KYU_DAN_ORDER[kwargs.get('order_by')] else: self.order_by = KYU_DAN_ORDER[DEFAULT_KYU_DAN_ORDER] return super(KyuDanRankingList, self).dispatch(request, *args, **kwargs) def get_queryset(self): queryset = models.KyuDanRanking.objects.filter( hanchan_count__gt=0).order_by(*self.order_by) return queryset.select_related() class SeasonRankingList(MahjongMixin, generic.ListView): model = models.SeasonRanking paginate_by = 25 season = None def get_queryset(self): self.season = int(self.kwargs.get('season', date.today().year)) queryset = self.model.objects.filter( season=self.season, placement__isnull=False ) return queryset.select_related() class PlayerScore(LoginRequiredMixin, generic.ListView): paginate_by = 25 user = auth.get_user_model() def get(self, request, *args, **kwargs): user_model = auth.get_user_model() try: self.user = user_model.objects.get( username=self.kwargs.get('username')) except user_model.DoesNotExist: raise django.http.Http404( _("No user found matching the name {}").format( self.kwargs.get('username'))) print(request.GET) if request.GET.get('download') == 'xlsx': return self.get_xlsx(request, *args, **kwargs) return super(PlayerScore, self).get(request, *args, **kwargs) def get_context_data(self, **kwargs): context = generic.ListView.get_context_data(self, **kwargs) context['membership'] = self.user try: context['kyu_dan_ranking'] = models.KyuDanRanking.objects.get( user=self.user) except models.KyuDanRanking.DoesNotExist: context['ranking'] = None try: context['ladder_ranking'] = models.SeasonRanking.objects.get( user=self.user, season=date.today().year) except models.SeasonRanking.DoesNotExist: context['ladder_ranking'] = models.SeasonRanking(user=self.user) return context def get_xlsx(self, request, *args, **kwargs): self.object_list = self.get_queryset() response = django.http.HttpResponse( content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') response['Content-Disposition'] = 'attachment; ' \ 'filename="{xlsx_filename}"'.format( xlsx_filename=self.xlsx_filename) xlxs_workbook = xlsx.Workbook() xlxs_workbook.generate_sheet( title=self.xlsx_filename.split('.')[0], columns_settings=self.xlsx_columns, object_list=self.object_list ) xlxs_workbook.save(response) return response class PlayerDanScore(PlayerScore): template_name = 'mahjong_ranking/player_dan_score.html' def get_queryset(self): self.kyu_dan_ranking = models.KyuDanRanking.objects.get(user=self.user) return models.Hanchan.objects.dan_hanchans( user=self.user, since=self.kyu_dan_ranking.legacy_date) @property def xlsx_columns(self): return ( {'col': 'A', 'title': 'Beginn', 'attr': 'start', 'style': 'Date Time', 'width': 14, 'footer': self.kyu_dan_ranking.legacy_date}, {'col': 'B', 'title': 'Termin', 'attr': 'event.name', 'style': 'Content', 'width': 16}, {'col': 'C', 'title': 'Platzierung', 'attr': 'placement', 'style': 'Integer', 'width': 11}, {'col': 'D', 'title': 'Spieler 1', 'attr': 'player1.username', 'style': 'Content', 'width': 16}, {'col': 'E', 'title': 'Punkte', 'attr': 'player1_game_score', 'style': 'Integer', 'width': 8}, {'col': 'F', 'title': 'Spieler 2', 'attr': 'player2.username', 'style': 'Content', 'width': 16}, {'col': 'G', 'title': 'Punkte', 'attr': 'player2_game_score', 'style': 'Integer', 'width': 8}, {'col': 'H', 'title': 'Spieler 3', 'attr': 'player3.username', 'style': 'Content', 'width': 16}, {'col': 'I', 'title': 'Punkte', 'attr': 'player3_game_score', 'style': 'Integer', 'width': 8}, {'col': 'J', 'title': 'Spieler 4', 'attr': 'player4.username', 'style': 'Content', 'width': 16}, {'col': 'K', 'title': 'Punkte', 'attr': 'player4_game_score', 'style': 'Integer', 'width': 8}, {'col': 'L', 'title': 'Dan Punkte', 'attr': 'dan_points', 'style': 'Integer', 'width': 12, 'footer': self.kyu_dan_ranking.legacy_dan_points}, {'col': 'M', 'title': 'Anmerkung', 'attr': 'player_comment', 'style': 'Content', 'width': 20, 'footer': 'Legacy Dan Punkte'}, ) @property def xlsx_filename(self): return "{username}_dan_score.xlsx".format(username=self.user.username) class PlayerInvalidScore(PlayerScore): template_name = 'mahjong_ranking/player_invalid_score.html' def get_queryset(self): self.xlsx_filename = "{username}_invalid_score.xlsx".format( username=self.user.username) return models.Hanchan.objects.unconfirmed(user=self.user) class PlayerKyuScore(PlayerScore): template_name = 'mahjong_ranking/player_kyu_score.html' def get_queryset(self): self.kyu_dan_ranking = models.KyuDanRanking.objects.get(user=self.user) return models.Hanchan.objects.kyu_hanchans( user=self.user, since=self.kyu_dan_ranking.legacy_date) @property def xlsx_columns(self): return ( {'col': 'A', 'title': 'Beginn', 'attr': 'start', 'style': 'Date Time', 'width': 14, 'footer': self.kyu_dan_ranking.legacy_date}, {'col': 'B', 'title': 'Termin', 'attr': 'event.name', 'style': 'Content', 'width': 16}, {'col': 'C', 'title': 'Platzierung', 'attr': 'placement', 'style': 'Integer', 'width': 11}, {'col': 'D', 'title': 'Spieler 1', 'attr': 'player1.username', 'style': 'Content', 'width': 16}, {'col': 'E', 'title': 'Punkte', 'attr': 'player1_game_score', 'style': 'Integer', 'width': 8}, {'col': 'F', 'title': 'Spieler 2', 'attr': 'player2.username', 'style': 'Content', 'width': 16}, {'col': 'G', 'title': 'Punkte', 'attr': 'player2_game_score', 'style': 'Integer', 'width': 8}, {'col': 'H', 'title': 'Spieler 3', 'attr': 'player3.username', 'style': 'Content', 'width': 16}, {'col': 'I', 'title': 'Punkte', 'attr': 'player3_game_score', 'style': 'Integer', 'width': 8}, {'col': 'J', 'title': 'Spieler 4', 'attr': 'player4.username', 'style': 'Content', 'width': 16}, {'col': 'K', 'title': 'Punkte', 'attr': 'player4_game_score', 'style': 'Integer', 'width': 8}, {'col': 'L', 'title': 'Kyū Punkte', 'attr': 'kyu_points', 'style': 'Integer', 'width': 12, 'footer': self.kyu_dan_ranking.legacy_kyu_points}, {'col': 'M', 'title': 'Anmerkung', 'attr': 'comment', 'style': 'Content', 'width': 24, 'footer': 'Legacy Kyū Punkte'}, ) @property def xlsx_filename(self): return "{username}_kyu_score.xlsx".format(username=self.user.username) class PlayerLadderScore(PlayerScore): season = None template_name = 'mahjong_ranking/player_ladder_score.html' def get_context_data(self, **kwargs): context = super(PlayerLadderScore, self).get_context_data(**kwargs) 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 return context def get_queryset(self, **kwargs): self.season = int(self.request.GET.get('season', date.today().year)) hanchan_list = models.Hanchan.objects.season_hanchans( user=self.user, season=self.season ) return hanchan_list @property def xlsx_columns(self): return ( {'col': 'A', 'title': 'Beginn', 'attr': 'start', 'style': 'Date Time', 'width': 14}, {'col': 'B', 'title': 'Termin', 'attr': 'event.name', 'style': 'Content', 'width': 16}, {'col': 'C', 'title': 'Platzierung', 'attr': 'placement', 'style': 'Integer', 'width': 11}, {'col': 'D', 'title': 'Spieler 1', 'attr': 'player1.username', 'style': 'Content', 'width': 16}, {'col': 'E', 'title': 'Punkte', 'attr': 'player1_game_score', 'style': 'Integer', 'width': 8}, {'col': 'F', 'title': 'Spieler 2', 'attr': 'player2.username', 'style': 'Content', 'width': 16}, {'col': 'G', 'title': 'Punkte', 'attr': 'player2_game_score', 'style': 'Integer', 'width': 8}, {'col': 'H', 'title': 'Spieler 3', 'attr': 'player3.username', 'style': 'Content', 'width': 16}, {'col': 'I', 'title': 'Punkte', 'attr': 'player3_game_score', 'style': 'Integer', 'width': 8}, {'col': 'J', 'title': 'Spieler 4', 'attr': 'player4.username', 'style': 'Content', 'width': 16}, {'col': 'K', 'title': 'Punkte', 'attr': 'player4_game_score', 'style': 'Integer', 'width': 8}, {'col': 'L', 'title': 'Punkte', 'attr': 'game_score', 'style': 'Integer', 'width': 8}, ) @property def xlsx_filename(self): return "{username}_ladder_score_{season}.xlsx".format( username=self.user.username, season=self.season )