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 get_course_info(self, data, suffix=''):
     # assert self._is_staff()
     t = requests.get(CONFIG.get('COURSE_INFO') % data)
     return t.text
예제 #3
0
    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)
예제 #4
0
 def get_course_info(self, data, suffix=''):
     # assert self._is_staff()
     t = requests.get(CONFIG.get('COURSE_INFO') % data)
     return t.text
예제 #5
0
class AntXBlockFields(object):

    # Отображаемое имя
    display_name = String(
        display_name="Display name",
        default='AcademicNT Assignment',
        help="This name appears in the horizontal navigation at the top of "
        "the page.",
        scope=Scope.settings)

    # Отображаемый текстовый комментарий
    content = String(display_name="Content",
                     default='',
                     help="Text.",
                     scope=Scope.settings)

    # Максимальный результат за задание
    points = Float(
        default=0,
        scope=Scope.user_state,
    )

    # Вес задания в рамках всего Grading'а
    weight = Float(
        display_name="Problem Weight",
        help=("Defines the number of points each problem is worth. "
              "If the value is not set, the problem is worth the sum of the "
              "option point values."),
        values={
            "min": 0,
            "step": .1
        },
        default=1,
        scope=Scope.settings)

    # Идентификатор курса в рамках СУО ANT
    ant_course_id = String(display_name="Course id",
                           default='',
                           help="Course id in ant.",
                           scope=Scope.settings)

    # Идентификатор юнита лабораторной работы с рамках СУО ANT
    ant_unit_id = String(display_name="Course id",
                         default='',
                         help="Unit id in ant.",
                         scope=Scope.settings)

    # Время, отведённое на выполнение работы в ANT
    ant_time_limit = Integer(display_name="Time limit",
                             default=0,
                             help="Time limit (in minutes)",
                             scope=Scope.settings)

    # Количество попыток, отведённое на выполнение работы в ANT
    ant_attempts_limit = Integer(
        default=0,
        help="Submission id",
        scope=Scope.settings,
    )

    # Статус выполнения задания, магическая строка: RUNNING, IDLE
    ant_status = String(scope=Scope.user_state, )

    # Время последнего обновления лимитов (время, попытки), переданных от СУО
    limit_renewal = DateTime(display_name="Limits renewal",
                             help="When limits have been renewed.",
                             default=None,
                             scope=Scope.settings)

    # Пользовательские баллы за лабораторную
    score = Float(display_name="Grade score",
                  default=0,
                  help="Total calculated score.",
                  scope=Scope.user_state)

    # Количество затраченных на выполнение попыток
    attempts = Integer(display_name="Attempts used",
                       default=0,
                       help="Total used attempts.",
                       scope=Scope.user_state)

    # Идентификатор текущего задания проверки, поставленного в очередь
    # (Возможно, больше не нужен)
    celery_task_id = String(display_name="Task id",
                            default="",
                            scope=Scope.user_state)

    # Результат последней проверки лабораторной, полученный от СУО
    ant_result = String(display_name="Latest ANT result",
                        default="",
                        help="Latest result retrieved by grade() method",
                        scope=Scope.user_state)

    # Адрес для вытягивания информации о выполнении
    attempts_url = DefaultedDescriptor(
        base_class=String,
        display_name="Attempts API url",
        default=CONFIG.get('ATTEMPTS_URL'),
        help="Url api to get latest user attempts.",
        # scope=Scope(UserScope.NONE, BlockScope.TYPE)
        scope=Scope.content,
    )

    # Адрес с лабораторной, открывается в попапе
    lab_url = DefaultedDescriptor(
        base_class=String,
        display_name="Lab API url",
        default=CONFIG.get('LAB_URL'),
        help="Lab url.",
        # scope=Scope(UserScope.NONE, BlockScope.TYPE)
        scope=Scope.content,
    )