Commit fef2e2fe232cc5a3fd3b7ad57a664e86f8ef0824

Authored by Adabriand Furtado
1 parent 3baf5144
Exists in master

Adicionado um método na API para recuperar os rankings dos projetos.

pybossa/api/__init__.py
... ... @@ -52,6 +52,7 @@ from token import TokenAPI
52 52 from result import ResultAPI
53 53 from pybossa.core import project_repo, task_repo
54 54 from pybossa.contributions_guard import ContributionsGuard
  55 +from pybossa.cache import users as cached_users
55 56  
56 57 blueprint = Blueprint('api', __name__)
57 58  
... ... @@ -182,3 +183,13 @@ def user_progress(project_id=None, short_name=None):
182 183 return abort(404)
183 184 else: # pragma: no cover
184 185 return abort(404)
  186 +
  187 +@jsonpify
  188 +@blueprint.route('/leaderboard')
  189 +@crossdomain(origin='*', headers=cors_headers)
  190 +@ratelimit(limit=ratelimits.get('LIMIT'), per=ratelimits.get('PER'))
  191 +def leaderboard(limit=None):
  192 + user_id = None if current_user.is_anonymous() else current_user.id
  193 + limit = request.args.get('limit')
  194 + data = cached_users.get_complete_leaderboard(n=limit, user_id=user_id)
  195 + return Response(json.dumps(data), mimetype="application/json")
... ...
pybossa/cache/users.py
... ... @@ -62,45 +62,104 @@ def get_leaderboard(n, user_id=None):
62 62 top_users.append(user)
63 63 if (user_id is not None):
64 64 if not user_in_top:
65   - sql = text('''
66   - WITH global_rank AS (
67   - WITH scores AS (
68   - SELECT user_id, COUNT(*) AS score FROM task_run
69   - WHERE user_id IS NOT NULL GROUP BY user_id)
70   - SELECT user_id, score, rank() OVER
71   - (ORDER BY score desc)
72   - FROM scores)
73   - SELECT rank, id, name, fullname, email_addr, info, created,
74   - score FROM global_rank
75   - JOIN public."user" on (user_id=public."user".id)
76   - WHERE user_id=:user_id ORDER BY rank;
77   - ''')
78   - user_rank = session.execute(sql, dict(user_id=user_id))
79   - u = User.query.get(user_id)
80   - # Load by default user data with no rank
81   - user = dict(
82   - rank=-1,
83   - id=u.id,
84   - name=u.name,
85   - fullname=u.fullname,
86   - email_addr=u.email_addr,
87   - info=u.info,
88   - created=u.created,
89   - score=-1)
90   - for row in user_rank: # pragma: no cover
91   - user = dict(
92   - rank=row.rank,
93   - id=row.id,
94   - name=row.name,
95   - fullname=row.fullname,
96   - email_addr=row.email_addr,
97   - info=row.info,
98   - created=row.created,
99   - score=row.score)
  65 + user = get_user_leaderboard_data(user_id)
100 66 top_users.append(user)
  67 + return top_users
101 68  
  69 +def get_user_leaderboard_data(user_id, project_id=None):
  70 + filter_by_project = '' if project_id is None else 'AND task_run.project_id =:project_id'
  71 + sql = text('''
  72 + WITH global_rank AS (
  73 + WITH scores AS (
  74 + SELECT user_id, COUNT(*) AS score FROM task_run
  75 + WHERE user_id IS NOT NULL %s
  76 + GROUP BY user_id)
  77 + SELECT user_id, score, rank() OVER
  78 + (ORDER BY score desc)
  79 + FROM scores)
  80 + SELECT rank, id, name, fullname, email_addr, info, created,
  81 + score FROM global_rank
  82 + JOIN public."user" on (user_id=public."user".id)
  83 + WHERE user_id=:user_id ORDER BY rank;
  84 + ''' % (filter_by_project))
  85 +
  86 + user_rank = session.execute(sql, dict(user_id=user_id, project_id=project_id))
  87 + u = User.query.get(user_id)
  88 + # Load by default user data with no rank
  89 + user = dict(
  90 + rank=0,
  91 + id=u.id,
  92 + name=u.name,
  93 + fullname=u.fullname,
  94 + email_addr=u.email_addr,
  95 + info=u.info,
  96 + created=u.created,
  97 + score=0)
  98 + for row in user_rank: # pragma: no cover
  99 + user = dict(
  100 + rank=row.rank,
  101 + id=row.id,
  102 + name=row.name,
  103 + fullname=row.fullname,
  104 + email_addr=row.email_addr,
  105 + info=row.info,
  106 + created=row.created,
  107 + score=row.score)
  108 + return user
  109 +
  110 +@memoize(timeout=timeouts.get('LEADERBOARD_TIMEOUT'))
  111 +def get_leaderboard_by_project_id(project_id, n=None, user_id=None):
  112 + """Return the top n users with their rank."""
  113 + sql = text('''
  114 + WITH global_rank AS (
  115 + WITH scores AS (
  116 + SELECT user_id, COUNT(*) AS score FROM task_run
  117 + WHERE user_id IS NOT NULL AND task_run.project_id =:project_id GROUP BY user_id)
  118 + SELECT user_id, score, rank() OVER (ORDER BY score desc)
  119 + FROM scores)
  120 + SELECT rank, id, name, fullname, score FROM global_rank
  121 + JOIN public."user" on (user_id=public."user".id) ORDER BY rank
  122 + LIMIT :limit;
  123 + ''')
  124 + results = session.execute(sql, dict(project_id=project_id, limit=n))
  125 +
  126 + top_users = []
  127 + user_in_top = False
  128 + for row in results:
  129 + if (row.id == user_id):
  130 + user_in_top = True
  131 + user = dict(
  132 + rank=row.rank,
  133 + name=row.name,
  134 + fullname=row.fullname,
  135 + score=row.score)
  136 + top_users.append(user)
  137 + if (user_id is not None and not user_in_top):
  138 + user_data = get_user_leaderboard_data(user_id, project_id)
  139 + user = dict(
  140 + rank=user_data['rank'],
  141 + name=user_data['name'],
  142 + fullname=user_data['fullname'],
  143 + score=user_data['score'])
  144 + top_users.append(user)
102 145 return top_users
103 146  
  147 +@memoize(timeout=timeouts.get('LEADERBOARD_TIMEOUT'))
  148 +def get_complete_leaderboard(n=None, user_id=None):
  149 + """Return all projects."""
  150 + sql = text('''
  151 + SELECT id, short_name FROM project
  152 + ''')
  153 + results = session.execute(sql)
  154 +
  155 + complete_leaderboard = []
  156 + for row in results:
  157 + leaderboard = dict()
  158 + leaderboard['project_name'] = row.short_name
  159 + leaderboard['leaderboard'] = get_leaderboard_by_project_id(row.id, n, user_id)
  160 + complete_leaderboard.append(leaderboard)
  161 + return complete_leaderboard
  162 +
104 163  
105 164 @memoize(timeout=timeouts.get('USER_TIMEOUT'))
106 165 def get_user_summary(name):
... ...
pybossa/core.py
... ... @@ -573,6 +573,7 @@ def setup_cache_timeouts(app):
573 573 timeouts['USER_TIMEOUT'] = app.config['USER_TIMEOUT']
574 574 timeouts['USER_TOP_TIMEOUT'] = app.config['USER_TOP_TIMEOUT']
575 575 timeouts['USER_TOTAL_TIMEOUT'] = app.config['USER_TOTAL_TIMEOUT']
  576 + timeouts['LEADERBOARD_TIMEOUT'] = app.config['LEADERBOARD_TIMEOUT']
576 577  
577 578  
578 579 def setup_scheduled_jobs(app): # pragma: no cover
... ...
pybossa/default_settings.py
... ... @@ -81,6 +81,7 @@ CATEGORY_TIMEOUT = 24 * 60 * 60
81 81 USER_TIMEOUT = 15 * 60
82 82 USER_TOP_TIMEOUT = 24 * 60 * 60
83 83 USER_TOTAL_TIMEOUT = 24 * 60 * 60
  84 +LEADERBOARD_TIMEOUT = 5 * 60
84 85  
85 86 # Project Presenters
86 87 PRESENTERS = ["basic", "image", "sound", "video", "map", "pdf"]
... ...