:py:mod:`oioioi.contests.controllers` ===================================== .. py:module:: oioioi.contests.controllers Module Contents --------------- Classes ~~~~~~~ .. autoapisummary:: oioioi.contests.controllers.RegistrationController oioioi.contests.controllers.PublicContestRegistrationController oioioi.contests.controllers.ContestControllerContext oioioi.contests.controllers.ContestController oioioi.contests.controllers.PastRoundsHiddenContestControllerMixin oioioi.contests.controllers.NotificationsMixinForContestController oioioi.contests.controllers.ProblemUploadingContestControllerMixin Functions ~~~~~~~~~ .. autoapisummary:: oioioi.contests.controllers.export_entries oioioi.contests.controllers.submission_template_context Attributes ~~~~~~~~~~ .. autoapisummary:: oioioi.contests.controllers.logger .. py:data:: logger .. py:function:: export_entries(registry, values) .. py:function:: submission_template_context(request, submission) .. py:class:: RegistrationController(contest) Bases: :py:obj:`oioioi.base.utils.RegisteredSubclassesBase`, :py:obj:`oioioi.base.utils.ObjectWithMixins` A base class for classes which should have a list of subclasses available. The list of subclasses is available in their :attr:`subclasses` class attributes. Classes which have *explicitly* set :attr:`abstract` class attribute to ``True`` are not added to :attr:`subclasses`. If a class has ``modules_with_subclasses`` attribute (list or string), then specified modules for all installed applications can be loaded by calling :meth:`~RegisteredSubclassesBase.load_subclasses`. .. py:method:: can_enter_contest(request) Determines if the current user is allowed to enter the contest, i.e. see any page related to the contest. The default implementation uses :meth:`filter_visible_contests` with a single-element contest queryset. :rtype: bool .. py:method:: visible_contests_query(request) Provides a :class:`django.db.models.Q` expression which can be used on :class:`oioioi.contests.models.Contest` queryset already limited to contests using this controller to filter for contests the user can enter. It must not make use of attribute `contest` of the controller, as it is not guaranteed to be set. It is called with None contest in :function:`oioioi.contests.utils.visible_contests`. .. py:method:: user_contests_query(request) :abstractmethod: Provides a :class:`django.db.models.Q` expression which can be used on :class:`oioioi.contests.models.Contest` queryset already limited to contests using this controller to filter for contests the user has entered. It must not make use of attribute `contest` of the controller, as it is not guaranteed to be set. It is called with None contest in :function:`oioioi.contests.utils.visible_contests`. .. py:method:: filter_visible_contests(request, contest_queryset) Filters a queryset of :class:`oioioi.contests.models.Contest` leaving only contests that the user can enter. contest_queryset should contain only contests that use a :class:`oioioi.contests.controllers.RegistrationController` subclass which :meth:`filter_visible_contests` is being called. For non-anonymous users default implementation checks their permissions and returns a union with what is returned from :meth:`filter_user_contests`. For anonymous, checks :meth:`anonymous_can_enter_contest`. :rtype: :class:`~django.db.models.query.QuerySet` .. py:method:: filter_user_contests(request, contest_queryset) Filters a queryset of :class:`oioioi.contests.models.Contest` leaving only contests that the user has entered. contest_queryset should contain only contests that use a :class:`oioioi.base.controllers.RegistractionController` subclass which :meth:`filter_user_contests` is being called. :rtype: :class:`~django.db.models.query.QuerySet` .. py:method:: anonymous_can_enter_contest() :classmethod: :abstractmethod: Determines if an anonymous user can enter the contest. Allowed anonymous users will have limited functionality, but they can see the problems, review questions etc. Modules should give them as much functionality as reasonably possible. :rtype: bool .. py:method:: filter_participants(queryset) :abstractmethod: Filters the queryset of :class:`~django.contrib.auth.model.User` to select only users which have access to the contest. .. py:method:: no_entry_view(request) View rendered when a user would like to perform an action not allowed by this registration controller. This may be a good place to put a redirection to a registration page etc. The default implementation just raises ``PermissionDenied``. .. py:method:: mixins_for_admin() Returns an iterable of mixins to add to the default :class:`oioioi.contests.admin.ContestAdmin` for the contest. The default implementation returns an empty tuple. .. py:method:: get_contest_participant_info_list(request, user) Returns a list of tuples (priority, info). Each entry represents a fragment of HTML with information about the user's participation in the contest. This information will be visible for contest admins. It can be any information an application wants to add. The fragments are sorted by priority (descending) and rendered in that order. The default implementation returns basic info about the contestant: his/her full name, e-mail, the user id, his/her submissions and round time extensions. To add additional info from another application, override this method. For integrity, include the result of the parent implementation in your output. .. py:method:: filter_users_with_accessible_personal_data(queryset) :abstractmethod: Filters the queryset of :class:`~django.contrib.auth.model.User` to select only users whose personal data is accessible to the admins. .. py:class:: PublicContestRegistrationController(contest) Bases: :py:obj:`RegistrationController` A base class for classes which should have a list of subclasses available. The list of subclasses is available in their :attr:`subclasses` class attributes. Classes which have *explicitly* set :attr:`abstract` class attribute to ``True`` are not added to :attr:`subclasses`. If a class has ``modules_with_subclasses`` attribute (list or string), then specified modules for all installed applications can be loaded by calling :meth:`~RegisteredSubclassesBase.load_subclasses`. .. py:attribute:: description .. py:method:: can_enter_contest(request) Determines if the current user is allowed to enter the contest, i.e. see any page related to the contest. The default implementation uses :meth:`filter_visible_contests` with a single-element contest queryset. :rtype: bool .. py:method:: anonymous_can_enter_contest() :classmethod: Determines if an anonymous user can enter the contest. Allowed anonymous users will have limited functionality, but they can see the problems, review questions etc. Modules should give them as much functionality as reasonably possible. :rtype: bool .. py:method:: visible_contests_query(request) Provides a :class:`django.db.models.Q` expression which can be used on :class:`oioioi.contests.models.Contest` queryset already limited to contests using this controller to filter for contests the user can enter. It must not make use of attribute `contest` of the controller, as it is not guaranteed to be set. It is called with None contest in :function:`oioioi.contests.utils.visible_contests`. .. py:method:: user_contests_query(request) Provides a :class:`django.db.models.Q` expression which can be used on :class:`oioioi.contests.models.Contest` queryset already limited to contests using this controller to filter for contests the user has entered. It must not make use of attribute `contest` of the controller, as it is not guaranteed to be set. It is called with None contest in :function:`oioioi.contests.utils.visible_contests`. .. py:method:: filter_participants(queryset) Filters the queryset of :class:`~django.contrib.auth.model.User` to select only users which have access to the contest. .. py:method:: filter_users_with_accessible_personal_data(queryset) Filters the queryset of :class:`~django.contrib.auth.model.User` to select only users whose personal data is accessible to the admins. .. py:class:: ContestControllerContext(contest, timestamp, is_admin) Bases: :py:obj:`object` .. py:class:: ContestController(contest) Bases: :py:obj:`oioioi.base.utils.RegisteredSubclassesBase`, :py:obj:`oioioi.base.utils.ObjectWithMixins` Contains the contest logic and rules. This is the computerized implementation of the contest's official rules. .. py:attribute:: modules_with_subclasses :annotation: = ['controllers'] .. py:attribute:: abstract :annotation: = True .. py:method:: registration_controller() .. py:method:: make_context(request_or_context) .. py:method:: default_view(request) Determines the default landing page for the user from the passed request. The default implementation returns the list of problems. .. py:method:: get_contest_participant_info_list(request, user) Returns a list of tuples (priority, info). Each entry represents a fragment of HTML with information about the user's participation in the contest. This information will be visible for contest admins. It can be any information an application wants to add. The fragments are sorted by priority (descending) and rendered in that order. The default implementation returns basic info about the contestant: his/her full name, e-mail, the user id, his/her submissions and round time extensions. To add additional info from another application, override this method. For integrity, include the result of the parent implementation in your output. .. py:method:: get_user_public_name(request, user) Returns the name of the user to be displayed in public contest views. The default implementation returns the user's full name or username if the former is not available. .. py:method:: get_round_times(request, round) Determines the times of the round for the user doing the request. The default implementation returns an instance of :class:`RoundTimes` cached by round_times() method. Round must belong to request.contest. Request is optional (round extensions won't be included if omitted). :returns: an instance of :class:`RoundTimes` .. py:method:: separate_public_results() Determines if there should be two separate dates for personal results (when participants can see their scores for a given round) and public results (when round ranking is published). Depending on the value returned, contest admins can see and modify both ``Results date`` and ``Public results date`` or only the first one. :rtype: bool .. py:method:: order_rounds_by_focus(request, queryset=None) Sorts the rounds in the queryset according to probable user's interest. The algorithm works as follows (roughly): 1. If a round starts or ends in 10 minutes or less or started less than a minute ago, it's prioritized. 1. Then active rounds are appended. 1. If a round starts in less than 6 hours or has ended in less than 1 hour, it's appended. 1. Then come past rounds. 1. Then other future rounds. See the implementation for corner cases. :param request: the Django request :param queryset: the set of :class:`~oioioi.contests.models.Round` instances to sort or ``None`` to return all rounds of the controller's contest .. py:method:: can_see_round(request_or_context, round) Determines if the current user is allowed to see the given round. If not, everything connected with this round will be hidden. The default implementation checks if the round is not in the future. .. py:method:: can_see_ranking(request_or_context) Determines if the current user is allowed to see the ranking. The default implementation checks if there exists a ranking visibility config for current contest and checks if ranking visibility is enabled. If there is no ranking visibility config for current contest or option 'AUTO' is chosen, returns default value (calls :meth:`default_can_see_ranking`) .. py:method:: default_can_see_ranking(request_or_context) .. py:method:: can_see_problem(request_or_context, problem_instance) Determines if the current user is allowed to see the given problem. If not, the problem will be hidden from all lists, so that its name should not be visible either. The default implementation checks if the user can see the given round (calls :meth:`can_see_round`). .. py:method:: can_see_statement(request_or_context, problem_instance) Determines if the current user is allowed to see the statement for the given problem. The default implementation checks if there exists a problem statement config for current contest and checks if statements' visibility is enabled. If there is no problem statement config for current contest or option 'AUTO' is chosen, returns default value (calls :meth:`default_can_see_statement`) .. py:method:: default_can_see_statement(request_or_context, problem_instance) .. py:method:: can_submit(request, problem_instance, check_round_times=True) Determines if the current user is allowed to submit a solution for the given problem. The default implementation checks if the user is not anonymous, and if the round is active for the given user. Subclasses should also call this default implementation. .. py:method:: get_default_submission_kind(request, **kwargs) Returns default kind of newly created submission by the current user. The default implementation returns ``'IGNORED'`` for non-contestants. In other cases it returns ``'NORMAL'``. .. py:method:: get_submissions_limit(request, problem_instance, kind='NORMAL') .. py:method:: get_submissions_left(request, problem_instance, kind=None) .. py:method:: is_submissions_limit_exceeded(request, problem_instance, kind=None) .. py:method:: adjust_submission_form(request, form, problem_instance) .. py:method:: validate_submission_form(request, problem_instance, form, cleaned_data) .. py:method:: create_submission(request, problem_instance, form_data, **kwargs) .. py:method:: judge(submission, extra_args=None, is_rejudge=False) .. py:method:: fill_evaluation_environ(environ, submission) .. py:method:: get_supported_extra_args(submission) Returns dict of all values which can be provided in extra_args argument to the judge method. .. py:method:: finalize_evaluation_environment(environ) This method gets called right before the environ becomes scheduled in the queue. This hook exists for inserting extra handlers to the recipe before judging the solution. .. py:method:: submission_judged(submission, rejudged=False) .. py:method:: _activate_newest_report(submission, queryset, kind=None) .. py:method:: update_report_statuses(submission, queryset) .. py:method:: update_submission_score(submission) Updates status, score and comment in a submission. Usually this involves looking at active reports and aggregating information from them. .. py:method:: update_user_result_for_problem(result) .. py:method:: update_problem_statistics(problem_statistics, user_statistics, submission) .. py:method:: _sum_scores(scores) .. py:method:: update_user_result_for_round(result) Updates a :class:`~oioioi.contests.models.UserResultForRound`. Usually this involves looking at user's results for problems and aggregating scores from them. Default implementation sums the scores. Saving the ``result`` is a responsibility of the caller. .. py:method:: update_user_result_for_contest(result) Updates a :class:`~oioioi.contests.models.UserResultForContest`. Usually this involves looking at user's results for rounds and aggregating scores from them. Default implementation sums the scores. Saving the ``result`` is a responsibility of the caller. .. py:method:: update_user_results(user, problem_instance) Updates score for problem instance, round and contest. Usually this method creates instances (if they don't exist) of: * :class:`~oioioi.contests.models.UserResultForProblem` * :class:`~oioioi.contests.models.UserResultForRound` * :class:`~oioioi.contests.models.UserResultForContest` and then calls proper methods of ContestController to update them. .. py:method:: filter_my_visible_submissions(request, queryset, filter_user=True) Returns the submissions which the user should see in the "My submissions" view. The default implementation returns all submissions belonging to the user for the problems that are visible, except for admins, which get all their submissions. Should return the updated queryset. .. py:method:: results_visible(request, submission) Determines whether it is a good time to show the submission's results. This method is not used directly in any code outside of the controllers. It's a helper method used in a number of other controller methods, as described. The default implementations uses the round's :attr:`~oioioi.contests.models.Round.results_date`. If it's ``None``, results are not available. Admins are always shown the results. .. py:method:: filter_visible_reports(request, submission, queryset) Determines which reports the user should be able to see. It need not check whether the submission is visible to the user. The default implementation uses :meth:`~ContestController.results_visible`. :param request: Django request :param submission: instance of :class:`~oioioi.contests.models.Submission` :param queryset: a queryset, initially filtered at least to select only given submission's reports :returns: updated queryset .. py:method:: can_see_submission_status(request, submission) .. py:method:: can_see_submission_score(request, submission) .. py:method:: can_see_submission_comment(request, submission) .. py:method:: render_submission_date(submission, shortened=False) .. py:method:: render_submission_score(submission) .. py:method:: render_submission(request, submission) :abstractmethod: Renders the given submission to HTML. This is usually a table with some basic submission info, source code download etc., displayed on the top of the submission details view, above the reports. .. py:method:: render_submission_footer(request, submission) .. py:method:: render_report(request, report) .. py:method:: render_my_submissions_header(request, submissions) Renders header on "My submissions" view. Default implementation returns empty string. .. py:method:: adjust_contest() Called when a (usually new) contest has just got the controller attached or after the contest has been modified. .. py:method:: valid_kinds_for_submission(submission) .. py:method:: change_submission_kind(submission, kind) .. py:method:: mixins_for_admin() Returns an iterable of mixins to add to the default :class:`oioioi.contests.admin.ContestAdmin` for this particular contest. The default implementation returns an empty tuple. .. py:method:: is_onsite() Determines whether the contest is on-site. .. py:method:: send_email(subject, body, recipients, headers=None) Send an email about something related to this contest (e.g. a submission confirmation). ``From:`` is set to DEFAULT_FROM_EMAIL, ``Reply-To:`` is taken from the ``Contact email`` contest setting and defaults to the value of ``From:``. .. py:method:: _is_partial_score(test_report) .. py:method:: show_default_fields(problem_instance) .. py:class:: PastRoundsHiddenContestControllerMixin Bases: :py:obj:`object` ContestController mixin that hides past rounds if another round is starting soon. The period when the past rounds are hidden is called round's *preparation time*. Do not use it with overlapping rounds. .. py:method:: can_see_round(request_or_context, round) Decides whether the given round should be shown for the given user. The algorithm is as follows: 1. Round is always visible for contest admins. 1. If any round is active, all active rounds are visible, all other rounds are hidden. 1. Let break_start = latest end_date of any past round break_end = closest start_date of any future round break_time = break_end - break_start then preparation_time is the last 30 minutes of the break, or if the break is shorter then just its second half. 1. During the preparation_time all rounds should be hidden. 1. Otherwise the decision is made by the superclass method. .. py:class:: NotificationsMixinForContestController Bases: :py:obj:`object` Sets default contest notification settings. .. py:method:: users_to_receive_public_message_notification() Decide if all users particiapting in a contest should be notified about a new global message. This should be disabled for contest with many users because of performance reasons - for each user, a single query to database is executed while sending a notification. .. py:method:: get_notification_message_submission_judged(submission) Returns a message to show in a notification when a submission has been judged. It doesn't validate any permissions. .. py:class:: ProblemUploadingContestControllerMixin Bases: :py:obj:`object` ContestController mixin that declares empty methods for extending problem uploading process. .. py:method:: adjust_upload_form(request, existing_problem, form) Adjusts the problem upload form created by some subclass of :class:`~oioioi.problems.problem_sources.PackageSource`. Called from :meth:`~oioioi.problems.problem_sources.PackageSource.view`. .. py:method:: fill_upload_environ(request, form, env) Extends the `env` dictionary used during problem uploading. Called from :meth:`~oioioi.problems.problem_sources.PackageSource.view`.