示例#1
0
    def heatmap(self, request: Request) -> Response:
        """Get the data to generate a heatmap for the volunteer.

        This includes one entry for every weekday and every hour containing the
        number of transcriptions made in that time slot.
        For example, there will be an entry for Sundays at 13:00 UTC, counting
        how many transcriptions the volunteer made in that time.

        The week days are numbered Monday=1 through Sunday=7.
        """
        utc_offset = int(request.GET.get("utc_offset", "0"))
        # Construct a timezone from the offset
        tzinfo = datetime.timezone(datetime.timedelta(seconds=utc_offset))

        heatmap = (
            self.filter_queryset(Submission.objects).filter(complete_time__isnull=False)
            # Extract the day of the week and the hour the transcription was made in
            .annotate(
                day=ExtractIsoWeekDay("complete_time", tzinfo=tzinfo),
                hour=ExtractHour("complete_time", tzinfo=tzinfo),
            )
            # Group by the day and hour
            .values("day", "hour")
            # Count the transcription made in each time slot
            .annotate(count=Count("id"))
            # Return the values
            .values("day", "hour", "count")
            # Order by day first, then hour
            .order_by("day", "hour")
        )

        return Response(heatmap)
示例#2
0
    def values_by_direction(self):

        # Get all the count details for section and the year
        qs = CountDetail.objects.filter(
            id_lane__id_section__id=self.section_id,
            timestamp__year=self.year,
            # id_category__code__in=[1, 2],
            import_status=definitions.IMPORT_STATUS_DEFINITIVE,
        )

        # Total by day of the week (0->monday, 7->sunday) and by direction
        result = qs.annotate(weekday=ExtractIsoWeekDay('timestamp')) \
                   .values('weekday') \
                   .annotate(total=Sum('times')) \
                   .values('weekday', 'id_lane__direction', 'total')
示例#3
0
    def values_by_day_of_week(self):
        # Get all the count details for section and the year
        qs = CountDetail.objects.filter(
            id_lane__id_section__id=self.section_id,
            timestamp__year=self.year,
        )

        # TODO: don't divide by 51 but actually aggregate first by the
        # real days (with sum) and then aggregate by weekday (with average)

        # Group by day of the week (0->monday, 7->sunday)
        result = qs.annotate(weekday=ExtractIsoWeekDay('timestamp')) \
                   .values('weekday') \
                   .annotate(tjm=Sum('times') / 51) \
                   .values('weekday', 'tjm')

        return result
示例#4
0
    def values_by_day_and_month(self):
        # Get all the count details for section and the year
        qs = CountDetail.objects.filter(
            id_lane__id_section__id=self.section_id,
            timestamp__year=self.year,
            import_status=definitions.IMPORT_STATUS_DEFINITIVE,
        )

        # TODO: don't divide by 12 but actually aggregate first by the
        # real days (with sum) and then aggregate by weekday (with average)

        # Total by day of the week (0->monday, 6->sunday) and by month (1->12)
        result = qs.annotate(weekday=ExtractIsoWeekDay('timestamp')) \
                   .annotate(month=ExtractMonth('timestamp')) \
                   .values('weekday', 'month') \
                   .annotate(tjm=Sum('times') / 12) \
                   .values('weekday', 'month', 'tjm')

        return result
示例#5
0
def stats_order_heatmap(request):
    try:
        from_year = int(request.GET.get('from_year',
                                        2022))  # TODO: improve filtering
    except ValueError:
        raise Http404("Året finns inte")

    orders = models.Order.objects.filter(
        accepted=True, put_at__year__gte=from_year).annotate(
            weekday=ExtractIsoWeekDay('put_at'),
            hour=ExtractHour("put_at"),
            minute=ExtractMinute("put_at"),
        ).annotate(quarter=Case(
            When(minute__gte=0, minute__lt=15, then=Value(0)),
            When(minute__gte=15, minute__lt=30, then=Value(15)),
            When(minute__gte=30, minute__lt=45, then=Value(30)),
            When(minute__gte=45, then=Value(45)),
            output_field=IntegerField(),
        )).filter(weekday__lt=6, hour__gte=8,
                  hour__lte=16).values("weekday", "hour", "quarter").annotate(
                      count=Count("id")).order_by("weekday", "hour", "quarter")

    data = DataFrame()
    weekdays = ["Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag"]
    for timepoint in orders:
        data.at[weekdays[timepoint["weekday"] - 1],
                time(timepoint["hour"], timepoint["quarter"])] = int(
                    timepoint["count"])

    sns.set_theme()
    plt.figure(figsize=(16, 9))
    plot = sns.heatmap(data, cbar=False, cmap="YlGnBu")
    plot.figure.autofmt_xdate()

    buffer = BytesIO()
    plot.get_figure().savefig(buffer, format='png')
    buffer.seek(0)
    return FileResponse(buffer, filename='heatmap.png')
示例#6
0
    def get_queryset(self):

        calendar = self.request.GET.get('calendar', '')
        actual = self.request.GET.get('current', None)
        option = self.request.GET.get('option', '')
        hoy = datetime.today()
        optica = self.request.user.get_opticuser()

        if (calendar == 'month'):
            self.label = 'Mes'
            if not actual:
                self.current_year = hoy.year
                self.current = MESES[hoy.month]

            else:
                self.current_year = int(
                    self.request.GET.get('current_year', None))
                actual_num = list(MESES.keys())[list(
                    MESES.values()).index(actual)]

                if option == 'next':
                    if not (actual_num + 1 > hoy.month
                            and self.current_year == hoy.year):
                        if actual_num + 1 <= 12:
                            self.current = MESES[actual_num + 1]
                        else:
                            if self.current_year + 1 <= hoy.year:
                                self.current = MESES[1]
                                self.current_year += 1
                            else:
                                self.current = MESES[actual_num]
                    else:
                        self.current = MESES[actual_num]
                elif option == 'previus':
                    if actual_num - 1 > 0:
                        self.current = MESES[actual_num - 1]
                    else:
                        self.current = MESES[12]
                        self.current_year -= 1
            self.size = c.monthrange(
                self.current_year,
                list(MESES.keys())[list(MESES.values()).index(
                    self.current)])[1]
            query = Prescription.objects.filter(
                optic=optica,
                date__month=list(MESES.keys())[list(MESES.values()).index(
                    self.current)],
                date__year=self.current_year).annotate(
                    dato=Day('date')).values('dato').annotate(
                        total=Count('date')).order_by('dato')
        elif calendar == 'year':
            self.size = 12
            self.label = 'Año'
            if not actual:
                self.current = hoy.year
            else:
                if option == 'next':
                    if int(actual) + 1 <= hoy.year:
                        self.current = int(actual) + 1
                    else:
                        self.current = hoy.year
                elif option == 'previus':
                    self.current = int(actual) - 1

            query = Prescription.objects.filter(
                optic=optica, date__year=self.current).annotate(
                    dato=Month('date')).values('dato').annotate(
                        total=Count('date')).order_by('dato')
        elif calendar == 'week':
            self.size = 7
            self.label = 'Semana'
            if not actual:
                self.current = hoy.isocalendar().week  #int(hoy.strftime('%W'))
                self.current_year = hoy.year
            else:
                self.current_year = int(
                    self.request.GET.get('current_year', None))
                self.current = int(actual)
                if option == 'next':
                    if not (self.current + 1 > hoy.isocalendar().week
                            and self.current_year == hoy.year):
                        if self.current + 1 <= 53:
                            self.current += 1
                        else:
                            self.current = 1
                            self.current_year += 1
                    else:
                        self.current = hoy.isocalendar().week
                elif option == 'previus':
                    if self.current - 1 > 0:
                        self.current -= 1
                    else:
                        self.current = 53
                        self.current_year -= 1
            query = Prescription.objects.filter(
                optic=optica,
                date__week=self.current,
                date__year=self.current_year).annotate(
                    dato=ExtractIsoWeekDay('date')).values('dato').annotate(
                        total=Count('date')).order_by('dato')
            query2 = Prescription.objects.filter(
                optic=optica,
                date__week=self.current,
                date__year=self.current_year).annotate(
                    dato=ExtractIsoWeekDay('date')).values(
                        'dato', 'date__iso_week_day')
            print("lllllllllllllllllllllllll", query2)
            for i in query2:
                print(i)
        elif calendar == 'day':
            self.size = 24
            self.label = 'Dia'
            if not actual:
                self.current = hoy.day
                self.current_year = hoy.year
                self.current_month = hoy.month
            else:
                self.current_year = int(
                    self.request.GET.get('current_year', None))
                self.current = int(actual)
                self.current_month = int(
                    self.request.GET.get('current_month', None))
                cant_dias_mes = c.monthrange(self.current_year,
                                             self.current_month)[1]
                if option == 'next':
                    if not (self.current + 1 > hoy.day
                            and self.current == hoy.day):
                        if self.current + 1 <= cant_dias_mes:
                            self.current += 1
                        else:
                            if self.current_month + 1 <= 12:
                                self.current_month += 1
                            else:
                                self.current_month = 1
                                self.current_year += 1
                            self.current = 1
                elif option == 'previus':
                    if self.current - 1 > 0:
                        self.current -= 1
                    else:
                        if self.current_month - 1 > 0:
                            self.current_month -= 1
                        else:
                            self.current_month = 12
                            self.current_year -= 1
                        self.current = c.monthrange(self.current_year,
                                                    self.current_month)[1]

            query = Prescription.objects.filter(
                optic=optica,
                date__day=self.current,
                date__year=self.current_year,
                date__month=self.current_month).annotate(
                    dato=Hour('time')).values('dato').annotate(
                        total=Count('time')).order_by('dato')

        return query
示例#7
0
    def get_context_data(self, **kwargs):
        """
        OPTIONAL
        Override parent method to get context data for template (add JSON -
        format data about current user)
        :param kwargs: captured named param from url_dispatcher path()
        :return: additional context for template rendering
        """
        current_user = self.object
        context = super().get_context_data(**kwargs)
        context['json'] = serializers.serialize(
            'json',
            users.models.CustomUser.objects.filter(pk=self.kwargs['pk']),
            fields=('username', 'first_name', 'last_name', 'Email'))
        if self.request.user.pk != self.kwargs.get('pk'):
            games = Games.objects.prefetch_related('sessions').filter(
                sessions__scores__user__pk=self.kwargs['pk'],
                sessions__is_private=False,
            ).distinct().annotate(total_score=Sum("sessions__scores__score"),
                                  times_played=Count("sessions"))
        else:
            games = Games.objects.prefetch_related('sessions').filter(
                sessions__scores__user__pk=self.kwargs['pk'],
            ).distinct().annotate(total_score=Sum("sessions__scores__score"),
                                  times_played=Count("sessions"))

        games_data = []
        for game in games:
            if self.request.user.pk != self.kwargs['pk']:

                sessions_data = list(
                    game.sessions.filter(
                        is_private=False,
                        scores__user=current_user,
                    ).annotate(date=F('created_at'),
                               score=Sum('scores__score')).values(
                                   'date', 'score'))
                #  Expensive realization with 'for' loop: each iteration = db calls
                # for session in game.sessions.filter(scores__user=current_user, is_private=False).distinct():
                #     session_data = {
                #         "date": session.created_at,
                #         "score": GameScores.objects.filter(
                #             user=current_user,
                #             game_session=session
                #         ).aggregate(Sum('score'))['score__sum'],
                #     }
                #     sessions_data.append(session_data)

            else:
                sessions_data = list(
                    game.sessions.filter(scores__user=current_user).annotate(
                        date=F('created_at'),
                        score=Sum('scores__score')).values('date', 'score'))

                #  Expensive realization with 'for' loop: each iteration = db calls
                # for session in game.sessions.filter(scores__user=current_user).distinct():
                #     session_data = {
                #         "date": session.created_at,

                #  Realization with access through related GameSession object
                # "score": session.scores.filter(
                #     user=current_user,
                # ).aggregate(Sum('score'))['score__sum'],

                #  Realization with raw access to GameScores object
                # "score": GameScores.objects.filter(
                #     user=current_user,
                #     game_session=session
                # ).aggregate(Sum('score'))['score__sum'],
                # }
                # sessions_data.append(session_data)

            if not sessions_data:
                continue

            if bool(
                    game.cover_art
            ):  # checks for associated file for "cover_art" field (model attr)
                game_data = {
                    "name": game.name,
                    "cover": game.cover_art.url,
                    "total_score": game.total_score,
                    "times_played": game.times_played,
                    "sessions": sessions_data
                }
            else:
                game_data = {
                    "name": game.name,
                    "total_score": game.total_score,
                    "times_played": game.times_played,
                    "sessions": sessions_data
                }
            games_data.append(game_data)

        context["games"] = games_data

        if self.request.user.pk == self.kwargs['pk']:
            context["last_five_games_played"] = Games.objects.prefetch_related(
                'sessions').filter(
                    sessions__scores__user__pk=self.kwargs['pk']).distinct(
                    ).annotate(player_score=Sum("sessions__scores__score"))

        else:
            context["last_five_games_played"] = Games.objects.prefetch_related(
                'sessions').filter(
                    sessions__scores__user__pk=self.kwargs['pk'],
                    sessions__is_private=False).distinct().annotate(
                        player_score=Sum("sessions__scores__score"))

        context["self_sessions"] = GameSession.objects.prefetch_related(
            'scores').filter(scores__user__id=self.kwargs["pk"])

        if self.request.user.pk == self.kwargs['pk']:
            self_game_sessions = GameSession.objects.filter(scores__user__pk=self.kwargs["pk"]).\
                annotate(weekday=ExtractIsoWeekDay("created_at"))
        else:
            self_game_sessions = GameSession.objects.filter(
                scores__user__pk=self.kwargs["pk"], is_private=False).annotate(
                    weekday=ExtractIsoWeekDay("created_at"))

        context['sessions'] = self_game_sessions  # unclaimed yet

        context['most_active_day'] = get_the_most_played_day(
            self_game_sessions)

        context["frequency"] = get_player_calendar_with_week_day_name(
            self_game_sessions)

        return context