Source code for vulyk.ext.leaderboard

# -*- coding: utf-8 -*-
from collections import defaultdict
from operator import itemgetter
from typing import Dict, List, Tuple, Union

from bson import ObjectId

from vulyk.models.tasks import AbstractAnswer
from vulyk.models.user import User

__all__ = [
    'LeaderBoardManager'
]


[docs]class LeaderBoardManager: def __init__(self, task_type_name: str, answer_model: AbstractAnswer, user_model: type) -> None: """ :param task_type_name: Current task type name :type task_type_name: str :param answer_model: Current answer model :type answer_model: AbstractAnswer :param user_model: Active user model :type user_model: User """ self._task_type_name = task_type_name self._answer_model = answer_model self._user_model = user_model
[docs] def get_leaders(self) -> List[Tuple[ObjectId, int]]: """Return sorted list of tuples (user_id, tasks_done) :returns: list of tuples (user_id, tasks_done) :rtype: List[Tuple[ObjectId, int]] """ scores = self._answer_model \ .objects(task_type=self._task_type_name) \ .item_frequencies('created_by') return sorted(scores.items(), key=itemgetter(1), reverse=True)
[docs] def get_leaderboard(self, limit: int) -> List[Dict[str, Union[User, int]]]: """Find users who contributed the most :param limit: number of top users to return :type limit: int :returns: List of dicts {user: user_obj, freq: count} :rtype: List[Dict[str, Union[User, int]]] """ result = [] top = defaultdict(list) _ = [top[e[1]].append(e) for e in self.get_leaders() if len(top) < limit] sorted_top = sorted(top.values(), key=lambda r: r[0][1], reverse=True) for i, el in enumerate(sorted_top): for v in el: result.append({ 'rank': i + 1, 'user': self._user_model.objects.get(id=v[0]), 'freq': v[1]}) return result