Module Contents



Make subclasses preserve the alters_data attribute on overridden methods.


Represents the state (i.e. is it up to date) and data (both in


Single page of a ranking


clamp(minimum, x, maximum)


save_pages(ranking, pages_list)

save_recalc_results(recalc, date_before, date_after, ...)


class oioioi.rankings.models.RankingRecalc(*args, **kwargs)[source]

Bases: django.db.models.Model

Make subclasses preserve the alters_data attribute on overridden methods.

class oioioi.rankings.models.Ranking(*args, **kwargs)[source]

Bases: django.db.models.Model

Represents the state (i.e. is it up to date) and data (both in serialized and html formats) for a single ranking.

For the purposes of this class, we identify the ranking by its contest and key. The generated ranking must NOT depend on the request or any other ranking.

This class is responsible only for dealing with WHEN to recalculate and to store the serialized data and html for the ranking. Anything beyond that should be delegated to RankingController.

Invalidation is handled explicitly. We assume our ranking is valid, until someone else (probably ContestController and friends) tells us that something changed. Then the ranking is marked as invalid (not up to date) with the help of invalidate_* methods.

We use _cooldown_ strategy of recalculation. Anytime we regenerate ranking we set a cooldown, based on how much time the previous recalculation took. If the ranking is invalidated during the cooldown period, we don’t recalculate until the cooldown period is over.

Consider the following example of how cooldowns work:

  1. 00:01 - First invalidation event.

    The ranking is invalid.

  2. 00:02 - The recalculation starts. It didn’t start immediately

    at the time of invalidation, because daemon polls for the rankings needing regeneration so it needed some time to notice.

  3. 00:12 - The recalculation ends, duration was 10 seconds. Ranking

    is up to date now.

  4. 01:00 - Second invalidation event. Ranking is invalid.

  5. 01:01 - Second recalculation starts.

    Let’s assume RANKING_COOLDOWN_FACTOR = 2. Then the cooldown is 20 seconds, until 01:21

  6. 01:03 - Third invalidation event.

7) 01:05 - Fourth invalidation event. 7) 01:08 - Ranking recalculation initiated by the second event ends.

Ranking is still invalid, because of the third event. It took 7 seconds.

  1. 01:21 - Cooldown is over. We recalculate ranking because of 3rd

    and 4th events. The new cooldown is set for 14 seconds, until 01:35.

  2. 01:30 - The recalculation ends.

The cooldowns can be configured by setting: RANKING_COOLDOWN_FACTOR - how long should the cooldown be, related to

the last recalculation.

RANKING_MIN_COOLDOWN - minimum cooldown duration (safety limit) RANKING_MAX_COOLDOWN - maximum cooldown duration (safety limit)

NOTE: We use the local time (and not the database time), for all time calculations, including the cooldowns, so be careful about drastic changes of system time on the generating machine.

class Meta[source]

Bases: object

unique_together = ['contest', 'key'][source]
property serialized[source]

Serialized data of this ranking


RankingController of the contest

classmethod invalidate_queryset(qs)[source]

Marks queryset of rankings as invalid

classmethod invalidate_contest(contest)[source]

Marks all the keys in the constest as invalid


Is all the data for this contest up to date (i.e. not invalidated since the last recalculation succeeded)?

If it is not up_to_date we still guarantee that the data is in consistent state from the last recalculation.

class oioioi.rankings.models.RankingPage(*args, **kwargs)[source]

Bases: django.db.models.Model

Single page of a ranking

oioioi.rankings.models.clamp(minimum, x, maximum)[source]
oioioi.rankings.models.save_pages(ranking, pages_list)[source]
oioioi.rankings.models.save_recalc_results(recalc, date_before, date_after, serialized, pages_list)[source]