def _check_lab(self, data):
        """
        Проверить лабораторную работу.

        Вызывается, когда пользователь нажал кнопку "Проверить лабораторную".

        :param data:
        :return:
        """

        # Если в конфигурации лабораторной ошибки -- вообще ничего не делаем
        has_errors, data_obj = self._validate_lab_config()
        if has_errors:
            return data_obj

        # Проверяем лабораторную только в том случае, если срок не истёк
        if self._past_due():
            return {
                "result": "error",
                "message":
                "Время, отведённое на лабораторную работу, истекло.",
            }

        need_save, student_input = (True, self._get_student_input()) if data.get('user_login') is None else \
            (False, self._get_student_input_no_auth(username=data.get('user_login')))
        if not student_input:
            return {
                "result": "error",
                "message": "Не удалось определить пользователя для проверки",
            }

        # Предварительно проверим наличие модуля, чтобы не инициировать
        # проверку для несуществующего.
        try:
            StudentModule.objects.get(
                module_state_key=self.location,
                student__username=student_input.get('user_login'))
        except StudentModule.DoesNotExist:
            return {
                'state': "Модуль для указанного пользователя не существует."
            }

        task = reserve_task(self if need_save else None,
                            grader_payload=self._get_grader_payload(),
                            system_payload=self._get_system_payload(
                                student_input.get('user_id')),
                            student_input=student_input,
                            save=need_save,
                            task_type='ANT_CHECK')
        submit_ant_check(task, countdown=0)
        return {
            "result": "success",
            "message": "Лабораторная работа поставлена в очередь на проверку.",
        }
    def _check_lab(self, data):
        """
        Проверить лабораторную работу.

        Вызывается, когда пользователь нажал кнопку "Проверить лабораторную".

        :param data:
        :return:
        """

        # Если в конфигурации лабораторной ошибки -- вообще ничего не делаем
        has_errors, data_obj = self._validate_lab_config()
        if has_errors:
            return data_obj

        # Проверяем лабораторную только в том случае, если срок не истёк
        if self._past_due():
            return {
                "result": "error",
                "message": "Время, отведённое на лабораторную работу, истекло.",
            }

        need_save, student_input = (True, self._get_student_input()) if data.get('user_login') is None else \
            (False, self._get_student_input_no_auth(username=data.get('user_login')))
        if not student_input:
            return {
                "result": "error",
                "message": "Не удалось определить пользователя для проверки",
            }

        # Предварительно проверим наличие модуля, чтобы не инициировать
        # проверку для несуществующего.
        try:
            StudentModule.objects.get(module_state_key=self.location,
                                      student__username=student_input.get('user_login'))
        except StudentModule.DoesNotExist:
            return {
                'state': "Модуль для указанного пользователя не существует."
            }

        task = reserve_task(self if need_save else None,
                            grader_payload=self._get_grader_payload(),
                            system_payload=self._get_system_payload(student_input.get('user_id')),
                            student_input=student_input,
                            save=need_save,
                            task_type='ANT_CHECK')
        submit_ant_check(task, countdown=0)
        return {
            "result": "success",
            "message": "Лабораторная работа поставлена в очередь на проверку.",
        }
    def start_lab(self, request, suffix=''):
        """
        Начало выполнение лабораторной.

        Вызывается, когда пользователь нажал кнопку "Начать лабораторную".

        :param request:
        :param suffix:

        :return:
        """

        # Проверим лабораторную на ошибки конфигурации
        has_errors, data_obj = self._validate_lab_config()
        if has_errors:
            return HTTPInternalServerError(json=data_obj)

        # Начинаем лабораторную только в том случае, если срок не истёк
        if self._past_due():
            return HTTPForbidden(json={"result": "error", "message": "Past due"})

        # Собираем мета-данные для блока
        lab_meta = {
            'user_id': self.runtime.get_real_user(self.runtime.anonymous_student_id).id,
            'user_login': self.runtime.get_real_user(self.runtime.anonymous_student_id).username,
            'user_email': self.runtime.get_real_user(self.runtime.anonymous_student_id).email,
            'course_id': self.ant_course_id,
            'unit_id': self.ant_unit_id,
        }

        # Нужно ли нам создавать новое отложенное задание для проверки?
        need_new_task = False

        # Если нет связанного с блоком задания...
        if self.celery_task_id is None:

            # ... то нужно
            need_new_task = True

        else:

            # В противном случае создадим новое задание только, если в очереди
            # на выполнение не висит другого, которое привязано к этому блоку
            try:
                task = GraderTask.objects.get(task_id=self.celery_task_id)
                if task.task_state != PENDING:
                    need_new_task = True

            # Если задания нет вообще, то, естественно, создаём
            except GraderTask.DoesNotExist:
                need_new_task = True

        # А теперь просто перечеркнём всё, что мы делали раньше. Дело в том,
        # что задания могут быть разных типов, и задание "проверить результат
        # через некоторое время" не должен блокировать задание "проверить
        # результат прямое сейчас". Чтобы таких блокировок не происходило, мы
        # просто будет создавать новое задание на отложенную проверку каждый
        # раз, когда пользователь начинает выполнение лабораторной. Хотя на
        # самом деле, нажатие кнопки "начать лабораторную" совсем не означает,
        # что пользователь начал новую лабораторную, а только лишь то, что он
        # открыл окно, таким образом, открыватется простор для start-флуда,
        # который нужно прикрыть.
        # И вообще, нужно решить, что делать с мёртвым кодом выше.
        need_new_task = True

        # Если нужно задание, резервируем его и ставим в очередь
        if need_new_task:
            task = reserve_task(self,
                                grader_payload=self._get_grader_payload(),
                                system_payload=self._get_system_payload(),
                                student_input=self._get_student_input(),
                                save=True,
                                task_type='ANT_START')

            # Запоминаем, что с этим блоком связано задание
            self.celery_task_id = submit_delayed_ant_precheck(task).task_id

        self.save_now()

        # Особенность ANT: пользователя нужно зарегистрировать на курс, прежде
        # чем показывать ему лабораторную; делаем это в том случае, если есть
        # url для регистрации в конфигурации.
        register_url = CONFIG.get('REGISTER_URL')
        if register_url is not None:
            register_url = register_url % lab_meta
            requests.post(register_url)

        # Делаем редирект на страницу с лабораторной
        lab_url = self.lab_url % lab_meta
        return HTTPFound(location=lab_url)
    def start_lab(self, request, suffix=''):
        """
        Начало выполнение лабораторной.

        Вызывается, когда пользователь нажал кнопку "Начать лабораторную".

        :param request:
        :param suffix:

        :return:
        """

        # Проверим лабораторную на ошибки конфигурации
        has_errors, data_obj = self._validate_lab_config()
        if has_errors:
            return HTTPInternalServerError(json=data_obj)

        # Начинаем лабораторную только в том случае, если срок не истёк
        if self._past_due():
            return HTTPForbidden(json={
                "result": "error",
                "message": "Past due"
            })

        # Собираем мета-данные для блока
        lab_meta = {
            'user_id':
            self.runtime.get_real_user(self.runtime.anonymous_student_id).id,
            'user_login':
            self.runtime.get_real_user(
                self.runtime.anonymous_student_id).username,
            'user_email':
            self.runtime.get_real_user(
                self.runtime.anonymous_student_id).email,
            'course_id':
            self.ant_course_id,
            'unit_id':
            self.ant_unit_id,
        }

        # Нужно ли нам создавать новое отложенное задание для проверки?
        need_new_task = False

        # Если нет связанного с блоком задания...
        if self.celery_task_id is None:

            # ... то нужно
            need_new_task = True

        else:

            # В противном случае создадим новое задание только, если в очереди
            # на выполнение не висит другого, которое привязано к этому блоку
            try:
                task = GraderTask.objects.get(task_id=self.celery_task_id)
                if task.task_state != PENDING:
                    need_new_task = True

            # Если задания нет вообще, то, естественно, создаём
            except GraderTask.DoesNotExist:
                need_new_task = True

        # А теперь просто перечеркнём всё, что мы делали раньше. Дело в том,
        # что задания могут быть разных типов, и задание "проверить результат
        # через некоторое время" не должен блокировать задание "проверить
        # результат прямое сейчас". Чтобы таких блокировок не происходило, мы
        # просто будет создавать новое задание на отложенную проверку каждый
        # раз, когда пользователь начинает выполнение лабораторной. Хотя на
        # самом деле, нажатие кнопки "начать лабораторную" совсем не означает,
        # что пользователь начал новую лабораторную, а только лишь то, что он
        # открыл окно, таким образом, открыватется простор для start-флуда,
        # который нужно прикрыть.
        # И вообще, нужно решить, что делать с мёртвым кодом выше.
        need_new_task = True

        # Если нужно задание, резервируем его и ставим в очередь
        if need_new_task:
            task = reserve_task(self,
                                grader_payload=self._get_grader_payload(),
                                system_payload=self._get_system_payload(),
                                student_input=self._get_student_input(),
                                save=True,
                                task_type='ANT_START')

            # Запоминаем, что с этим блоком связано задание
            self.celery_task_id = submit_delayed_ant_precheck(task).task_id

        self.save_now()

        # Особенность ANT: пользователя нужно зарегистрировать на курс, прежде
        # чем показывать ему лабораторную; делаем это в том случае, если есть
        # url для регистрации в конфигурации.
        register_url = CONFIG.get('REGISTER_URL')
        if register_url is not None:
            register_url = register_url % lab_meta
            requests.post(register_url)

        # Делаем редирект на страницу с лабораторной
        lab_url = self.lab_url % lab_meta
        return HTTPFound(location=lab_url)