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
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)
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, )