Ejemplo n.º 1
0
def get_round(user_dao, round_id):
    """
    Summary: Get juror-level details for a round, identified by round ID.
    """
    juror_dao = JurorDAO(user_dao)
    rnd = juror_dao.get_round(round_id)
    rnd_stats = juror_dao.get_round_task_counts(round_id)
    data = make_juror_round_details(rnd, rnd_stats)  # TODO: add to Round model
    return {'data': data}
Ejemplo n.º 2
0
def get_rankings_from_round(user_dao, round_id, request):
    juror_dao = JurorDAO(user_dao)
    rnd = juror_dao.get_round(round_id)
    if rnd.vote_method != 'ranking':
        return {
            'data': None,
            'status': 'failure',
            'errors': 'round %s is not a ranking round' % round_id
        }
    ret = get_votes_from_round(user_dao, round_id, request, rnd=rnd)
    return ret
Ejemplo n.º 3
0
def get_tasks_from_round(user_dao, round_id, request):
    count = request.values.get('count', 15)
    offset = request.values.get('offset', 0)
    juror_dao = JurorDAO(user_dao)
    juror_dao.confirm_active(round_id)
    rnd = juror_dao.get_round(round_id)
    if rnd.vote_method == 'ranking':
        count = MAX_RATINGS_SUBMIT  # TODO: better constant
    tasks = juror_dao.get_tasks_from_round(round_id, num=count, offset=offset)
    stats = juror_dao.get_round_task_counts(round_id)
    data = {'stats': stats, 'tasks': []}

    for task in tasks:
        data['tasks'].append(task.to_details_dict())

    return {'data': data}
Ejemplo n.º 4
0
def get_votes_from_round(user_dao, round_id, request, rnd=None):
    count = request.values.get('count', 15)
    offset = request.values.get('offset', 0)
    order_by = request.values.get('order_by', 'date')
    sort = request.values.get('sort', 'asc')
    juror_dao = JurorDAO(user_dao)
    if not rnd:
        rnd = juror_dao.get_round(round_id)
    if rnd.vote_method in ('yesno', 'rating'):
        ratings = juror_dao.get_ratings_from_round(round_id,
                                                   num=count,
                                                   offset=offset,
                                                   sort=sort,
                                                   order_by=order_by)
        data = [r.to_details_dict() for r in ratings]
    else:
        rankings = juror_dao.get_rankings_from_round(round_id)
        data = [r.to_details_dict() for r in rankings]
        data.sort(key=lambda x: x['value'])
    return {'data': data}
Ejemplo n.º 5
0
def get_votes_stats_from_round(user_dao, round_id):
    juror_dao = JurorDAO(user_dao)
    rnd = juror_dao.get_round(round_id)

    stats = None

    if rnd.vote_method == 'yesno':
        # dict: raw value => yes/no
        vote_map = {0.0: 'no', 1.0: 'yes'}
        stats = _get_summarized_votes_stats(juror_dao, round_id, vote_map)
    elif rnd.vote_method == 'rating':
        # dict: raw value => number of stars
        vote_map = {0.0: 1, 0.25: 2, 0.5: 3, 0.75: 4, 1.0: 5}
        stats = _get_summarized_votes_stats(juror_dao, round_id, vote_map)

    result = None
    if stats is not None:
        result = {'method': rnd.vote_method, 'stats': stats}

    return result
Ejemplo n.º 6
0
def submit_ratings(user_dao, request_dict):
    """message format:

    {"ratings": [{"vote_id": 10, "value": 0.0}, {"vote_id": 11, "value": 1.0}]}

    this function is used to submit ratings _and_ rankings. when
    submitting rankings does not support ranking ties at the moment
    """

    # TODO: can jurors change their vote?
    juror_dao = JurorDAO(user_dao)

    r_dicts = request_dict['ratings']

    if len(r_dicts) > MAX_RATINGS_SUBMIT:
        raise InvalidAction('can submit up to 100 ratings at once, not %r' %
                            len(r_dicts))
    elif not r_dicts:
        return {}  # submitting no ratings = immediate return

    review_map = {}

    for rd in r_dicts:
        review = rd.get('review')
        if review:
            review_stripped = review.strip()
            task_id = rd.get('vote_id') or rd['task_id']
            if len(review_stripped) > 8192:
                raise ValueError('review must be less than 8192 '
                                 'chars, not %r' % len(review_stripped))
            review_map[task_id] = review_stripped

    try:
        id_map = dict([(r['vote_id'], r['value']) for r in r_dicts])
    except KeyError as e:
        # fallback for old versions
        id_map = dict([(r['task_id'], r['value']) for r in r_dicts])
    if not len(id_map) == len(r_dicts):
        pass  # duplicate values

    tasks = juror_dao.get_tasks_by_id(id_map.keys())
    task_map = dict([(t.id, t) for t in tasks])
    round_id_set = set([t.round_entry.round_id for t in tasks])
    if not len(round_id_set) == 1:
        raise InvalidAction('can only submit ratings for one round at a time')

    round_id = list(round_id_set)[0]
    rnd = juror_dao.get_round(round_id)
    rnd.confirm_active()
    style = rnd.vote_method

    # validation
    if style == 'rating':
        invalid = [r for r in id_map.values() if r not in VALID_RATINGS]
        if invalid:
            raise InvalidAction('rating expected one of %s, not %r' %
                                (VALID_RATINGS, sorted(set(invalid))))
    elif style == 'yesno':
        invalid = [r not in VALID_YESNO for r in id_map.values()]
        if not all([r in VALID_YESNO for r in id_map.values()]):
            raise InvalidAction('yes/no rating expected one of %s, not %r' %
                                (VALID_YESNO, sorted(set(invalid))))
    elif style == 'ranking':
        invalid = [r for r in id_map.values() if r != int(r) or r < 0]
        if invalid:
            raise InvalidAction('ranking expects whole numbers >= 0, not %r' %
                                (sorted(set(invalid))))
        ranks = sorted([int(v) for v in id_map.values()])
        last_rank = max(ranks)
        len_rnd_entries = len(rnd.entries)
        max_ok_rank = len_rnd_entries - 1
        if last_rank > max_ok_rank:
            raise InvalidAction('ranking for round #%s expects ranks 0 - %s,'
                                ' not %s' % (rnd.id, max_ok_rank, last_rank))
        if len_rnd_entries != len(id_map):
            raise InvalidAction('must submit all rankings at once.'
                                ' (expected %s submissions, got %s.)' %
                                (len_rnd_entries, len(id_map)))

    if style in ('rating', 'yesno'):
        for t in tasks:
            val = id_map[t.id]
            review = review_map.get(t.id)
            juror_dao.edit_rating(t, val, review=review)

    elif style == 'ranking':
        # This part is designed to support ties ok though
        """
        [{"vote_id": 123,
          "value": 0,
          "review": "The light dances across the image."}]
        """
        ballot = []
        is_edit = False
        for rd in r_dicts:
            cur = dict(rd)
            vote_id = rd.get('vote_id')
            if not vote_id:
                vote_id = rd.get(
                    'task_id')  # fallback for old versions of the client
            cur['vote'] = task_map[vote_id]
            if cur['vote'].status == 'complete':
                is_edit = True
            elif is_edit:
                raise InvalidAction('all tasks must be complete or incomplete')
            ballot.append(cur)

        juror_dao.apply_ranking(ballot)

    return {}  # TODO?