Пример #1
0
def rate_contest(contest):
    from judge.models import Rating, Profile

    cursor = connection.cursor()
    cursor.execute('''
        SELECT judge_rating.user_id, judge_rating.rating, judge_rating.volatility, r.times
        FROM judge_rating INNER JOIN
             judge_contest ON (judge_contest.id = judge_rating.contest_id) INNER JOIN (
            SELECT judge_rating.user_id AS id, MAX(judge_contest.end_time) AS last_time,
                   COUNT(judge_rating.user_id) AS times
            FROM judge_contestparticipation INNER JOIN
                 judge_rating ON (judge_rating.user_id = judge_contestparticipation.user_id) INNER JOIN
                 judge_contest ON (judge_contest.id = judge_rating.contest_id)
            WHERE judge_contestparticipation.contest_id = %s AND judge_contest.end_time < %s AND
                  judge_contestparticipation.user_id NOT IN (
                      SELECT profile_id FROM judge_contest_rate_exclude WHERE contest_id = %s
                  ) AND judge_contestparticipation.virtual = 0
            GROUP BY judge_rating.user_id
            ORDER BY judge_contestparticipation.score DESC, judge_contestparticipation.cumtime ASC,
                     judge_contestparticipation.tiebreaker ASC
        ) AS r ON (judge_rating.user_id = r.id AND judge_contest.end_time = r.last_time)
    ''', (contest.id, contest.end_time, contest.id))
    data = {user: (rating, volatility, times) for user, rating, volatility, times in cursor.fetchall()}
    cursor.close()

    users = contest.users.order_by('is_disqualified', '-score', 'cumtime', 'tiebreaker') \
        .annotate(submissions=Count('submission')).exclude(user_id__in=contest.rate_exclude.all()) \
        .filter(virtual=0, user__is_unlisted=False).values_list('id', 'user_id', 'score', 'cumtime')
    if not contest.rate_all:
        users = users.filter(submissions__gt=0)
    if contest.rating_floor is not None:
        users = users.exclude(user__rating__lt=contest.rating_floor)
    if contest.rating_ceiling is not None:
        users = users.exclude(user__rating__gt=contest.rating_ceiling)
    users = list(tie_ranker(users, key=itemgetter(2, 3)))
    participation_ids = [user[1][0] for user in users]
    user_ids = [user[1][1] for user in users]
    ranking = list(map(itemgetter(0), users))
    old_data = [data.get(user, (1200, 535, 0)) for user in user_ids]
    old_rating = list(map(itemgetter(0), old_data))
    old_volatility = list(map(itemgetter(1), old_data))
    times_ranked = list(map(itemgetter(2), old_data))
    rating, volatility = recalculate_ratings(old_rating, old_volatility, ranking, times_ranked)

    now = timezone.now()
    ratings = [Rating(user_id=id, contest=contest, rating=r, volatility=v, last_rated=now, participation_id=p, rank=z)
               for id, p, r, v, z in zip(user_ids, participation_ids, rating, volatility, ranking)]
    cursor = connection.cursor()
    cursor.execute('CREATE TEMPORARY TABLE _profile_rating_update(id integer, rating integer)')
    cursor.executemany('INSERT INTO _profile_rating_update VALUES (%s, %s)', list(zip(user_ids, rating)))
    with transaction.atomic():
        Rating.objects.filter(contest=contest).delete()
        Rating.objects.bulk_create(ratings)
        cursor.execute('''
            UPDATE `%s` p INNER JOIN `_profile_rating_update` tmp ON (p.id = tmp.id)
            SET p.rating = tmp.rating
        ''' % Profile._meta.db_table)
    cursor.execute('DROP TABLE _profile_rating_update')
    cursor.close()
    return old_rating, old_volatility, ranking, times_ranked, rating, volatility
Пример #2
0
def rate_contest(contest):
    from judge.models import Rating, Profile

    rating_subquery = Rating.objects.filter(user=OuterRef('user'))
    rating_sorted = rating_subquery.order_by('-contest__end_time')
    users = contest.users.order_by('is_disqualified', '-score', 'cumtime', 'tiebreaker') \
        .annotate(submissions=Count('submission'),
                  last_rating=Coalesce(Subquery(rating_sorted.values('rating')[:1]), RATING_INIT),
                  last_mean=Coalesce(Subquery(rating_sorted.values('mean')[:1]), MEAN_INIT),
                  times=Coalesce(Subquery(rating_subquery.order_by().values('user_id')
                                          .annotate(count=Count('id')).values('count')), 0)) \
        .exclude(user_id__in=contest.rate_exclude.all()) \
        .filter(virtual=0).values('id', 'user_id', 'score', 'cumtime', 'tiebreaker',
                                  'last_rating', 'last_mean', 'times')
    if not contest.rate_all:
        users = users.filter(submissions__gt=0)
    if contest.rating_floor is not None:
        users = users.exclude(last_rating__lt=contest.rating_floor)
    if contest.rating_ceiling is not None:
        users = users.exclude(last_rating__gt=contest.rating_ceiling)

    users = list(users)
    participation_ids = list(map(itemgetter('id'), users))
    user_ids = list(map(itemgetter('user_id'), users))
    ranking = list(
        tie_ranker(users, key=itemgetter('score', 'cumtime', 'tiebreaker')))
    old_mean = list(map(itemgetter('last_mean'), users))
    times_ranked = list(map(itemgetter('times'), users))
    historical_p = [[] for _ in users]

    user_id_to_idx = {uid: i for i, uid in enumerate(user_ids)}
    for h in Rating.objects.filter(user_id__in=user_ids) \
            .order_by('-contest__end_time') \
            .values('user_id', 'performance'):
        idx = user_id_to_idx[h['user_id']]
        historical_p[idx].append(h['performance'])

    rating, mean, performance = recalculate_ratings(ranking, old_mean,
                                                    times_ranked, historical_p)

    now = timezone.now()
    ratings = [
        Rating(user_id=i,
               contest=contest,
               rating=r,
               mean=m,
               performance=perf,
               last_rated=now,
               participation_id=pid,
               rank=z) for i, pid, r, m, perf, z in
        zip(user_ids, participation_ids, rating, mean, performance, ranking)
    ]
    with transaction.atomic():
        Rating.objects.bulk_create(ratings)

        Profile.objects.filter(
            contest_history__contest=contest,
            contest_history__virtual=0).update(rating=Subquery(
                Rating.objects.filter(user=OuterRef('id')).order_by(
                    '-contest__end_time').values('rating')[:1]))
Пример #3
0
def rate_contest(contest):
    from judge.models import Rating, Profile

    rating_subquery = Rating.objects.filter(user=OuterRef('user'))
    rating_sorted = rating_subquery.order_by('-contest__end_time')
    users = contest.users.order_by('is_disqualified', '-score', 'cumtime', 'tiebreaker') \
        .annotate(submissions=Count('submission'),
                  last_rating=Coalesce(Subquery(rating_sorted.values('rating')[:1]), 1200),
                  volatility=Coalesce(Subquery(rating_sorted.values('volatility')[:1]), 535),
                  times=Coalesce(Subquery(rating_subquery.order_by().values('user_id')
                                          .annotate(count=Count('id')).values('count')), 0)) \
        .exclude(user_id__in=contest.rate_exclude.all()) \
        .filter(virtual=0).values('id', 'user_id', 'score', 'cumtime', 'tiebreaker', 'is_disqualified',
                                  'last_rating', 'volatility', 'times')
    if not contest.rate_all:
        users = users.filter(submissions__gt=0)
    if contest.rating_floor is not None:
        users = users.exclude(last_rating__lt=contest.rating_floor)
    if contest.rating_ceiling is not None:
        users = users.exclude(last_rating__gt=contest.rating_ceiling)

    users = list(users)
    participation_ids = list(map(itemgetter('id'), users))
    user_ids = list(map(itemgetter('user_id'), users))
    is_disqualified = list(map(itemgetter('is_disqualified'), users))
    ranking = list(
        tie_ranker(users, key=itemgetter('score', 'cumtime', 'tiebreaker')))
    old_rating = list(map(itemgetter('last_rating'), users))
    old_volatility = list(map(itemgetter('volatility'), users))
    times_ranked = list(map(itemgetter('times'), users))
    rating, volatility = recalculate_ratings(old_rating, old_volatility,
                                             ranking, times_ranked,
                                             is_disqualified)

    now = timezone.now()
    ratings = [
        Rating(user_id=i,
               contest=contest,
               rating=r,
               volatility=v,
               last_rated=now,
               participation_id=p,
               rank=z) for i, p, r, v, z in zip(user_ids, participation_ids,
                                                rating, volatility, ranking)
    ]
    with transaction.atomic():
        Rating.objects.bulk_create(ratings)

        Profile.objects.filter(
            contest_history__contest=contest,
            contest_history__virtual=0).update(rating=Subquery(
                Rating.objects.filter(user=OuterRef('id')).order_by(
                    '-contest__end_time').values('rating')[:1]))
Пример #4
0
def rate_contest(contest):
    from judge.models import Rating, Profile

    rating_subquery = Rating.objects.filter(user=OuterRef('user'))
    rating_sorted = rating_subquery.order_by('-contest__end_time')
    users = contest.users.order_by('is_disqualified', '-score', 'cumtime', 'tiebreaker') \
        .annotate(submissions=Count('submission'),
                  last_rating=Coalesce(Subquery(rating_sorted.values('rating')[:1]), 1200),
                  volatility=Coalesce(Subquery(rating_sorted.values('volatility')[:1]), 535),
                  times=Coalesce(Subquery(rating_subquery.order_by().values('user_id')
                                          .annotate(count=Count('id')).values('count')), 0)) \
        .exclude(user_id__in=contest.rate_exclude.all()) \
        .filter(virtual=0).values('id', 'user_id', 'score', 'cumtime', 'tiebreaker', 'is_disqualified',
                                  'last_rating', 'volatility', 'times')
    if not contest.rate_all:
        users = users.filter(submissions__gt=0)
    if contest.rating_floor is not None:
        users = users.exclude(last_rating__lt=contest.rating_floor)
    if contest.rating_ceiling is not None:
        users = users.exclude(last_rating__gt=contest.rating_ceiling)

    users = list(users)
    participation_ids = list(map(itemgetter('id'), users))
    user_ids = list(map(itemgetter('user_id'), users))
    is_disqualified = list(map(itemgetter('is_disqualified'), users))
    ranking = list(
        tie_ranker(users, key=itemgetter('score', 'cumtime', 'tiebreaker')))
    old_rating = list(map(itemgetter('last_rating'), users))
    old_volatility = list(map(itemgetter('volatility'), users))
    times_ranked = list(map(itemgetter('times'), users))
    rating, volatility = recalculate_ratings(old_rating, old_volatility,
                                             ranking, times_ranked,
                                             is_disqualified)

    now = timezone.now()
    ratings = [
        Rating(user_id=i,
               contest=contest,
               rating=r,
               volatility=v,
               last_rated=now,
               participation_id=p,
               rank=z) for i, p, r, v, z in zip(user_ids, participation_ids,
                                                rating, volatility, ranking)
    ]
    cursor = connection.cursor()
    cursor.execute(
        'CREATE TEMPORARY TABLE _profile_rating_update(id integer, rating integer)'
    )
    cursor.executemany('INSERT INTO _profile_rating_update VALUES (%s, %s)',
                       list(zip(user_ids, rating)))
    with transaction.atomic():
        Rating.objects.filter(contest=contest).delete()
        Rating.objects.bulk_create(ratings)
        cursor.execute('''
            UPDATE `%s` p INNER JOIN `_profile_rating_update` tmp ON (p.id = tmp.id)
            SET p.rating = tmp.rating
        ''' % Profile._meta.db_table)
    cursor.execute('DROP TABLE _profile_rating_update')
    cursor.close()
    return old_rating, old_volatility, ranking, times_ranked, rating, volatility