# coding: utf-8 ''' Created on 16.02.2017 @author: d.gulyakin ''' #from java.sql import Timestamp from java.util import Date from java.util import Calendar from time import time import json from uuid import uuid4 from qt._qt_orm import TestingVariantAssignCursor, QtiVariantQuestionCursor, QtiVariantAnswerCursor,\ QtiQuestionCursor, QtiDestructorCursor, \ QtiVariantDestructorCursor, QtiVariantDestructorAnswerCursor,\ QtiResourceCursor, QtiVariantParamsCursor # QtiVariantCursor, ContentCursor, QtiPackageAttributeCursor, \ # Content_AttributeValueCursor, listAttributeContentCursor, \ #from qt.navigator import getAttributeValue from ru.curs.celesta.showcase.utils import XMLJSONConverter from qt.functions import completeTest, getImageById, getPrevNextQuestionId,\ getAttributeValue from fileRepository.functions import getRelativePathById try: from ru.curs.showcase.core.jython import JythonDTO from ru.curs.showcase.core.jython import JythonDownloadResult except: from ru.curs.celesta.showcase import JythonDTO from qt.functions import getShowCorrectAnswerPermission def cardData(context, main=None, add=None, filterinfo=None, session=None, elementId=None): u'''Карточка вопроса с одиночным выбором и для вопроса с множественным выбором. ''' begin = time() session = json.loads(session) TVA = TestingVariantAssignCursor(context) # QtiVariant = QtiVariantCursor(context) # QtiPackageAttribute = QtiPackageAttributeCursor(context) QtiQuestion = QtiQuestionCursor(context) QtiVariantQuestion = QtiVariantQuestionCursor(context) QtiVariantAnswer = QtiVariantAnswerCursor(context) QtiDestructor = QtiDestructorCursor(context) QtiVariantDestructor = QtiVariantDestructorCursor(context) QtiVariantDestructorAnswer = QtiVariantDestructorAnswerCursor(context) # QtiResource = QtiResourceCursor(context) # Content = ContentCursor(context) # Content_Attribute = Content_AttributeValueCursor(context) # listAttributeContent = listAttributeContentCursor(context) variantQuestionId = main QtiVariantQuestion.get(variantQuestionId) variantId = QtiVariantQuestion.VariantID QtiVariantQuestion.setRange('VariantID',variantId) QtiVariantQuestion.orderBy('QuestionNumber') questionNumber = QtiVariantQuestion.QuestionNumber questionCount = QtiVariantQuestion.count() QtiQuestion.get(QtiVariantQuestion.QuestionID) print 'start', time() - begin #Получение содержания вопроса questionHtml = QtiQuestion.QuestionHtml if QtiQuestion.QuestionHtml is not None else '' # questionHtml2 = QtiQuestion.QuestionHtml2 if QtiQuestion.QuestionHtml2 is not None else '' questionImg = '/'.join(getRelativePathById(context, str(QtiQuestion.QuestionImg), file_version_id=None)) # questionImg = getImageById(QtiResource,QtiQuestion.QuestionImg, isImage=False) print 'load', time() - begin #Проверка на то, нужно ли отображать правильный ответ correctAnswerFlag = getShowCorrectAnswerPermission(context, session, variantId) print 'countquest', time() - begin TVA.get(variantId) if TVA.AlgorithmTestingID == 1: testingAlgorithm = u'Тестирование для самоконтроля' elif TVA.AlgorithmTestingID == 2: testingAlgorithm = u'Аудиторное тестирование' else: testingAlgorithm = u'Тестирование' questionHeader = u'Вопрос %s из %s'%(questionNumber,questionCount) print 'header', time() - begin #Получение идентификаторов предыдущего и следующего вопросов # QtiVariantQuestion.setRange("QuestionNumber",1) # QtiVariantQuestion.first() # # firstVariantQuestionId = QtiVariantQuestion.VariantQuestionID # # QtiVariantQuestion.setRange("QuestionNumber") # QtiVariantQuestion.get(variantQuestionId) # # nextVariantQuestionId = 'ID_FINISH' # if QtiVariantQuestion.navigate('>'): # nextVariantQuestionId = QtiVariantQuestion.VariantQuestionID # # prevVariantQuestionId = firstVariantQuestionId # QtiVariantQuestion.get(variantQuestionId) # if QtiVariantQuestion.navigate('<'): # prevVariantQuestionId = QtiVariantQuestion.VariantQuestionID # prevVariantQuestionId, nextVariantQuestionId = getPrevNextQuestionId(context, QtiVariantQuestion, variantQuestionId) QtiVariantQuestion.close() QtiVariantAnswer.setRange('VariantID',variantId) QtiVariantAnswer.first() #Тестирование завершилось или нет timeEnd = QtiVariantAnswer.TimeEnd timeout = '1' if QtiVariantAnswer.TimeEnd < Date() else '0' if QtiVariantAnswer.TimeFinish is None and QtiVariantAnswer.TimeEnd < Date(): testingStatus = '2' elif QtiVariantAnswer.TimeFinish is not None: testingStatus = '1' else: testingStatus = '0' QtiVariantDestructor.setRange('VariantQuestionID',variantQuestionId) optionList = [] resultList = [] letter = ord('A') QtiVariantDestructor.orderBy('VariantDestructorID') print 'prequest', time() - begin #Получение вариантов ответа for QtiVariantDestructor in QtiVariantDestructor.iterate(): QtiDestructor.get(QtiVariantDestructor.DestructorID) variantDestructorId = QtiVariantDestructor.VariantDestructorID destructorHtml = QtiDestructor.DestructorHtml if QtiDestructor.DestructorHtml is not None else '' # destructorHtml2 = QtiDestructor.DestructorHtml2 if QtiDestructor.DestructorHtml2 is not None else '' answerText = QtiDestructor.AnswerText if QtiDestructor.AnswerText is not None else '' # destructorImg = getImageById(QtiResource,QtiDestructor.DestructorImg) correctFlag = False if correctAnswerFlag: if QtiDestructor.IsTrue: correctFlag = True optionList.append({"id":variantDestructorId, "letter": chr(letter), "destructorHTML": destructorHtml, # + destructorImg + destructorHtml2, "answerText": answerText, "isTrue":'true' if correctFlag else 'false' }) checked = '1_' if testingStatus != '0' else '0_' #Проверям выбирал ли текущий вариант пользователь, когда в предыдущий раз отвечал на этот вопрос QtiVariantDestructorAnswer.setRange('VariantDestructorID',QtiVariantDestructor.VariantDestructorID) if QtiVariantDestructorAnswer.tryFirst(): if QtiVariantDestructorAnswer.IsTrue: checked += '1' else: checked += '0' else: checked += '0' resultList.append({"@id": "variant{}".format(chr(letter)), "letter": chr(letter),"id":variantDestructorId, "checked":checked}) letter += 1 print 'calcList', time() - begin calNow = Calendar.getInstance() timeNow = Date() calNow.setTime(timeNow) calEnd = Calendar.getInstance() calEnd.setTime(timeEnd) print 'quest', time() - begin #Скрипт, который вставляет счётчик оставшегося времени js = '''javascript: injectCounter(new Date(%s,%s,%s,%s,%s,%s),new Date(%s,%s,%s,%s,%s,%s));''' % \ (calEnd.get(Calendar.YEAR),calEnd.get(Calendar.MONTH),calEnd.get(Calendar.DAY_OF_MONTH),\ calEnd.get(Calendar.HOUR_OF_DAY),calEnd.get(Calendar.MINUTE),calEnd.get(Calendar.SECOND),\ calNow.get(Calendar.YEAR),calNow.get(Calendar.MONTH),calNow.get(Calendar.DAY_OF_MONTH),\ calNow.get(Calendar.HOUR_OF_DAY),calNow.get(Calendar.MINUTE),calNow.get(Calendar.SECOND)) QtiVariantParams = QtiVariantParamsCursor(context) skipQuestions = getAttributeValue(QtiVariantParams, variantId, 'SkipQuestions') QtiVariantParams.close() xformsdata = {"schema": { "@xmlns":"", "description": { "testingAlgorithm": testingAlgorithm, "js":js, "questionHeader":questionHeader, "questionType":'7', "skipQuestions": skipQuestions, "question_img_file": questionImg, "testingStatus": testingStatus, "showCorrect": 'true' if correctAnswerFlag else 'false', "captchaText":'', "question": {"@number": questionNumber, "@isLastQuestion":'1' if nextVariantQuestionId == 'ID_FINISH' else '0', "@timeout":timeout, "#text":questionHtml# + questionImg + questionHtml2 + ']]>' }, "options":{"option":optionList} }, "result":{"option":resultList}}} #Переходы к следующему и предыдущему вопросам, завершению тестирования и списку вопросов xformssettings = {"properties":{ "event":[{ "@name":"single_click", "@linkId": "1", "action":{ "#sorted": [ {"navigator": {"@element": prevVariantQuestionId} }]} }, {"@name":"single_click", "@linkId": "2", "action":{ "#sorted": [ {"navigator": {"@element": nextVariantQuestionId} }]} }, {"@name":"single_click", "@linkId": "3", "action":{ "#sorted": [ {"navigator": {"@element": "ID_FINISH"} }]} }, {"@name":"single_click", "@linkId": "4", "action":{ "#sorted": [ {"navigator": {"@element": "ID_CONTENTS"}}]}}]}} data = XMLJSONConverter.jsonToXml(json.dumps(xformsdata)) data = data.replace(' ','&nbsp;') settings = XMLJSONConverter.jsonToXml(json.dumps(xformssettings)) print 'finish', time() - begin return JythonDTO(data, settings) def cardDataSave(context, main=None, add=None, filterinfo=None, session=None, elementId=None, xformsdata=None): u'''Процедура сохранения ответа на вопрос. Для всех типов вопросов используется общая процедура сохранения''' session = json.loads(session) data = json.loads(xformsdata) # raise Exception(data) ip = session['sessioncontext']['ip'] QtiVariantQuestion = QtiVariantQuestionCursor(context) QtiQuestion = QtiQuestionCursor(context) QtiVariantAnswer = QtiVariantAnswerCursor(context) QtiVariantDestructor = QtiVariantDestructorCursor(context) QtiVariantDestructorAnswer = QtiVariantDestructorAnswerCursor(context) variantQuestionId = main QtiVariantQuestion.get(variantQuestionId) QtiQuestion.get(QtiVariantQuestion.QuestionID) questionType = QtiQuestion.QuestionType variantId = QtiVariantQuestion.VariantID now = Date() QtiVariantAnswer.setRange('VariantID',variantId) QtiVariantAnswer.first() timeEnd = QtiVariantAnswer.TimeFinish if QtiVariantAnswer.TimeFinish is not None else QtiVariantAnswer.TimeEnd timeout = True if now > timeEnd else False #Если время тестирования завершилось, то ответ на текущий вопрос не сохраняем и завешаем тестирование if timeout: completeTest(context,variantId) return #Удаляем предыдущий ответ на вопрос QtiVariantDestructor.setRange('VariantQuestionID',variantQuestionId) for QtiVariantDestructor in QtiVariantDestructor.iterate(): QtiVariantDestructorAnswer.setRange('VariantDestructorID',QtiVariantDestructor.VariantDestructorID) QtiVariantDestructorAnswer.deleteAll() if questionType in (1, 2, 7): #Для вопрсов с одиночным и множественным выбором в ответы пишутся идентификаторы выбранных вариантов optionsList = data['schema']['result']['option'] if not isinstance(optionsList,list): optionsList = [optionsList] for option in optionsList: if option['checked'] == '0_1': QtiVariantDestructor.get(option['id']) QtiVariantDestructorAnswer.VariantDestructorAnswerID = unicode(uuid4()) QtiVariantDestructorAnswer.VariantDestructorID = option['id'] QtiVariantDestructorAnswer.IsTrue = True QtiVariantDestructorAnswer.AnswerIP = ip QtiVariantDestructorAnswer.insert() elif questionType == 3: #Для текстового вопрос записывается текст ответ в поле DestructorText variantDestructorId = data['schema']['result']['option']['@id'] QtiVariantDestructorAnswer.VariantDestructorAnswerID = unicode(uuid4()) QtiVariantDestructorAnswer.VariantDestructorID = variantDestructorId QtiVariantDestructorAnswer.DestructorText = data['schema']['result']['option']['answer'] QtiVariantDestructorAnswer.IsTrue = True QtiVariantDestructorAnswer.AnswerIP = ip QtiVariantDestructorAnswer.insert() elif questionType in (4, 6): #Для соответствия и классификации в DestructorId пишутся какой вариант из правого столбца был выбран if 'option2' in data['schema']['result']: optionsList = data['schema']['result']['option2'] if not isinstance(optionsList,list): optionsList = [optionsList] for option in optionsList: QtiVariantDestructorAnswer.VariantDestructorAnswerID = unicode(uuid4()) QtiVariantDestructorAnswer.VariantDestructorID = option['@VariantDestructorID'] QtiVariantDestructorAnswer.DestructorID = option['@DestructorID'] QtiVariantDestructorAnswer.IsTrue = True QtiVariantDestructorAnswer.AnswerIP = ip QtiVariantDestructorAnswer.insert() elif questionType == 5: #Для сортировки в DestructorText пишется порядковый номер варианта if 'option2' in data['schema']['result']: optionsList = data['schema']['result']['option2'] if not isinstance(optionsList,list): optionsList = [optionsList] for option in optionsList: QtiVariantDestructorAnswer.VariantDestructorAnswerID = unicode(uuid4()) QtiVariantDestructorAnswer.VariantDestructorID = option['@id'] QtiVariantDestructorAnswer.DestructorText = option['@text'] QtiVariantDestructorAnswer.IsTrue = True QtiVariantDestructorAnswer.AnswerIP = ip QtiVariantDestructorAnswer.insert()