Index: lams_common/src/java/org/lamsfoundation/lams/util/JsonUtil.java =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r83ad7bbcfa9124cdf2b8d891f91252b1ed35f74a --- lams_common/src/java/org/lamsfoundation/lams/util/JsonUtil.java (.../JsonUtil.java) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_common/src/java/org/lamsfoundation/lams/util/JsonUtil.java (.../JsonUtil.java) (revision 83ad7bbcfa9124cdf2b8d891f91252b1ed35f74a) @@ -41,7 +41,7 @@ public static final ObjectMapper objectMapper = new ObjectMapper(); public static JsonNode opt(JsonNode object, String field) { - return opt(object, field, null); + return JsonUtil.opt(object, field, null); } public static JsonNode opt(JsonNode object, String field, JsonNode defaultValue) { @@ -57,15 +57,15 @@ } public static Boolean optBoolean(JsonNode object, String field) { - return optBoolean(object, field, null); + return JsonUtil.optBoolean(object, field, null); } public static Boolean optBoolean(JsonNode object, String field, Boolean defaultValue) { return object.hasNonNull(field) ? (Boolean) object.get(field).asBoolean() : defaultValue; } public static Long optLong(JsonNode object, String field) { - return optLong(object, field, null); + return JsonUtil.optLong(object, field, null); } public static Long optLong(JsonNode object, String field, Long defaultValue) { @@ -76,20 +76,20 @@ return object.hasNonNull(field) ? (Double) object.get(field).asDouble() : defaultValue; } - public static Integer optDouble(JsonNode object, String field) { - return optInt(object, field, null); + public static Double optDouble(JsonNode object, String field) { + return JsonUtil.optDouble(object, field, null); } public static Integer optInt(JsonNode object, String field) { - return optInt(object, field, null); + return JsonUtil.optInt(object, field, null); } public static Integer optInt(JsonNode object, String field, Integer defaultValue) { return object.hasNonNull(field) ? (Integer) object.get(field).asInt() : defaultValue; } public static String optString(JsonNode object, String field) { - return optString(object, field, null); + return JsonUtil.optString(object, field, null); } public static String optString(JsonNode object, String field, String defaultValue) { Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java =================================================================== diff -u -r122ff0d8419be3fac72ddb842cbbce1cea01e542 -r83ad7bbcfa9124cdf2b8d891f91252b1ed35f74a --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java (.../AssessmentServiceImpl.java) (revision 122ff0d8419be3fac72ddb842cbbce1cea01e542) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java (.../AssessmentServiceImpl.java) (revision 83ad7bbcfa9124cdf2b8d891f91252b1ed35f74a) @@ -113,7 +113,6 @@ import org.lamsfoundation.lams.util.JsonUtil; import org.lamsfoundation.lams.util.MessageService; import org.lamsfoundation.lams.util.NumberUtil; -import org.springframework.web.bind.annotation.RequestParam; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; @@ -809,8 +808,7 @@ Pattern pattern = Pattern.compile(regex, java.util.regex.Pattern.CASE_INSENSITIVE | java.util.regex.Pattern.UNICODE_CASE); if (pattern.matcher(answer).matches()) { - String answerFloatStr = answer.substring(0, - answer.length() - unit.getName().length()); + String answerFloatStr = answer.substring(0, answer.length() - unit.getName().length()); try { float answerFloat = Float.valueOf(answerFloatStr); answerFloat = answerFloat / unit.getMultiplier(); @@ -1354,10 +1352,10 @@ questionSummary.setNotAllocatedQuestionResults(notAllocatedQuestionResults); //check is it a TBL case, i.e. only two option groups available, one has 0%, second - 100% - boolean isCompatibleWithTbl = qbQuestion.isVsaAndCompatibleWithTbl(); + boolean isCompatibleWithTbl = qbQuestion.isVsaAndCompatibleWithTbl(); questionSummary.setTbl(isCompatibleWithTbl); } - + return questionSummary; } @@ -1366,9 +1364,10 @@ Long questionResultUid) { AssessmentQuestion assessmentQuestion = assessmentQuestionDao.getByUid(questionUid); QbQuestion qbQuestion = assessmentQuestion.getQbQuestion(); - AssessmentQuestionResult questionRes = assessmentQuestionResultDao.getAssessmentQuestionResultByUid(questionResultUid); + AssessmentQuestionResult questionRes = assessmentQuestionResultDao + .getAssessmentQuestionResultByUid(questionResultUid); String answer = questionRes.getAnswer(); - + //adding if (previousOptionUid.equals(-1L)) { for (QbOption targetOption : qbQuestion.getQbOptions()) { @@ -1388,7 +1387,7 @@ if (previousOption.getUid().equals(previousOptionUid)) { String name = previousOption.getName(); String[] alternatives = name.split("\r\n"); - + String nameWithoutUserAnswer = ""; for (String alternative : alternatives) { if (!alternative.equals(answer)) { @@ -1402,11 +1401,11 @@ break; } } - + } //reshuffling inside the same container - do nothing else if (targetOptionUid.equals(previousOptionUid)) { - + } //moving from one to another else { @@ -1419,12 +1418,12 @@ break; } } - + for (QbOption previousOption : qbQuestion.getQbOptions()) { if (previousOption.getUid().equals(previousOptionUid)) { String name = previousOption.getName(); String[] alternatives = name.split("\r\n"); - + String nameWithoutUserAnswer = ""; for (String alternative : alternatives) { if (!alternative.equals(answer)) { @@ -1441,10 +1440,10 @@ } } assessmentResultDao.flush(); - + //recalculate marks for all lessons in all cases except for reshuffling inside the same container if (!targetOptionUid.equals(previousOptionUid)) { - + // get all finished user results List assessmentResults = assessmentResultDao .getAssessmentResultsByQbQuestion(qbQuestion.getUid()); @@ -1486,7 +1485,7 @@ storeAssessmentResultMarkAndMaxMark(assessmentResult, lastFinishedAssessmentResult, assessmentMark, assessmentMaxMark, user); } - + //recalculate marks in all Scratchie activities, that use modified QbQuestion toolService.recalculateScratchieMarksForVsaQuestion(qbQuestion.getUid()); } @@ -2132,7 +2131,8 @@ Long trueKey, Long falseKey) { ExcelCell[] summaryTable; int i = 0; - if (question.getType() == QbQuestion.TYPE_MULTIPLE_CHOICE || question.getType() == QbQuestion.TYPE_VERY_SHORT_ANSWERS + if (question.getType() == QbQuestion.TYPE_MULTIPLE_CHOICE + || question.getType() == QbQuestion.TYPE_VERY_SHORT_ANSWERS || question.getType() == QbQuestion.TYPE_NUMERICAL) { List options = question.getQbQuestion().getQbOptions(); summaryTable = new ExcelCell[options.size() + 1]; @@ -2230,7 +2230,8 @@ total += value; } int i = 0; - if (question.getType() == QbQuestion.TYPE_MULTIPLE_CHOICE || question.getType() == QbQuestion.TYPE_VERY_SHORT_ANSWERS + if (question.getType() == QbQuestion.TYPE_MULTIPLE_CHOICE + || question.getType() == QbQuestion.TYPE_VERY_SHORT_ANSWERS || question.getType() == QbQuestion.TYPE_NUMERICAL) { for (QbOption option : question.getQbQuestion().getQbOptions()) { summaryTable[i] = new ExcelCell(valueAsPercentage(summaryOfAnswers.get(option.getUid()), total), false); @@ -2563,12 +2564,13 @@ } } } - + /** * Store new mark and maxMark if they were changed */ - private void storeAssessmentResultMarkAndMaxMark(AssessmentResult assessmentResult, AssessmentResult lastFinishedAssessmentResult, - float newAssessmentMark, int newAssessmentMaxMark, AssessmentUser user) { + private void storeAssessmentResultMarkAndMaxMark(AssessmentResult assessmentResult, + AssessmentResult lastFinishedAssessmentResult, float newAssessmentMark, int newAssessmentMaxMark, + AssessmentUser user) { // store new mark and maxMark if they were changed if ((assessmentResult.getGrade() != newAssessmentMark) || (assessmentResult.getMaximumGrade() != newAssessmentMaxMark)) { @@ -3114,13 +3116,13 @@ return confidenceLevelDtos; } - + @Override public Collection getVsaAnswers(Long toolSessionId) { if (toolSessionId == null) { return new ArrayList<>(); } - + Map uid_answerToVsaAnswerDtoMap = new LinkedHashMap<>(); Assessment assessment = getAssessmentBySessionId(toolSessionId); @@ -3142,20 +3144,20 @@ if (qbQuestion.getType() == QbQuestion.TYPE_VERY_SHORT_ANSWERS) { //uid_answer should be unique in the final list String uid_answer = qbQuestion.getUid() + "_" + questionResult.getAnswer(); - + //find VsaAnswerDTO in the map, or create the new one if it doesn't exist VsaAnswerDTO vsaAnswerDTO; if (uid_answerToVsaAnswerDtoMap.containsKey(uid_answer)) { vsaAnswerDTO = uid_answerToVsaAnswerDtoMap.get(uid_answer); - + } else { vsaAnswerDTO = new VsaAnswerDTO(); vsaAnswerDTO.setQbQuestionUid(qbQuestion.getUid()); vsaAnswerDTO.setAnswer(questionResult.getAnswer()); vsaAnswerDTO.setCorrect(questionResult.getMark() > 0); vsaAnswerDTO.setUserId(user.getUserId()); uid_answerToVsaAnswerDtoMap.put(uid_answer, vsaAnswerDTO); - + //find and store optionUid for (QbOption option : qbQuestion.getQbOptions()) { for (AssessmentOptionAnswer optionAnswer : questionResult.getOptionAnswers()) { @@ -3168,7 +3170,7 @@ } } } - + ConfidenceLevelDTO confidenceLevelDto = new ConfidenceLevelDTO(); confidenceLevelDto.setUserId(user.getUserId().intValue()); String userName = StringUtils.isBlank(user.getFirstName()) @@ -3178,7 +3180,7 @@ confidenceLevelDto.setPortraitUuid(portraitUuid); confidenceLevelDto.setLevel(questionResult.getConfidenceLevel()); - vsaAnswerDTO.getConfidenceLevels().add(confidenceLevelDto); + vsaAnswerDTO.getConfidenceLevels().add(confidenceLevelDto); } } @@ -3399,34 +3401,37 @@ for (JsonNode questionJSONData : questions) { AssessmentQuestion question = new AssessmentQuestion(); Integer type = JsonUtil.optInt(questionJSONData, "type"); - question.getQbQuestion().setType(type); - question.getQbQuestion().setName(questionJSONData.get(RestTags.QUESTION_TITLE).asText()); - question.getQbQuestion().setDescription(questionJSONData.get(RestTags.QUESTION_TEXT).asText()); + + QbQuestion qbQuestion = new QbQuestion(); + qbQuestion.setQuestionId(qbService.generateNextQuestionId()); + qbQuestion.setType(type); + qbQuestion.setName(questionJSONData.get(RestTags.QUESTION_TITLE).asText()); + qbQuestion.setDescription(questionJSONData.get(RestTags.QUESTION_TEXT).asText()); + question.setQbQuestion(qbQuestion); question.setDisplayOrder(JsonUtil.optInt(questionJSONData, RestTags.DISPLAY_ORDER)); - question.getQbQuestion().setAllowRichEditor( + qbQuestion.setAllowRichEditor( JsonUtil.optBoolean(questionJSONData, RestTags.ALLOW_RICH_TEXT_EDITOR, Boolean.FALSE)); - question.getQbQuestion() - .setAnswerRequired(JsonUtil.optBoolean(questionJSONData, "answerRequired", Boolean.FALSE)); - question.getQbQuestion() - .setCaseSensitive(JsonUtil.optBoolean(questionJSONData, "caseSensitive", Boolean.FALSE)); - question.getQbQuestion() - .setCorrectAnswer(JsonUtil.optBoolean(questionJSONData, "correctAnswer", Boolean.FALSE)); - question.getQbQuestion().setMaxMark(JsonUtil.optInt(questionJSONData, "maxMark", 1)); - question.getQbQuestion().setFeedback(JsonUtil.optString(questionJSONData, "feedback")); - question.getQbQuestion().setFeedbackOnCorrect(JsonUtil.optString(questionJSONData, "feedbackOnCorrect")); - question.getQbQuestion() - .setFeedbackOnIncorrect(JsonUtil.optString(questionJSONData, "feedbackOnIncorrect")); - question.getQbQuestion() + qbQuestion.setAnswerRequired(JsonUtil.optBoolean(questionJSONData, "answerRequired", Boolean.FALSE)); + qbQuestion.setCaseSensitive(JsonUtil.optBoolean(questionJSONData, "caseSensitive", Boolean.FALSE)); + qbQuestion.setCorrectAnswer(JsonUtil.optBoolean(questionJSONData, "correctAnswer", Boolean.FALSE)); + qbQuestion.setMaxMark(JsonUtil.optInt(questionJSONData, "maxMark", 1)); + qbQuestion.setFeedback(JsonUtil.optString(questionJSONData, "feedback")); + qbQuestion.setFeedbackOnCorrect(JsonUtil.optString(questionJSONData, "feedbackOnCorrect")); + qbQuestion.setFeedbackOnIncorrect(JsonUtil.optString(questionJSONData, "feedbackOnIncorrect")); + qbQuestion .setFeedbackOnPartiallyCorrect(JsonUtil.optString(questionJSONData, "feedbackOnPartiallyCorrect")); - question.getQbQuestion().setMaxWordsLimit(JsonUtil.optInt(questionJSONData, "maxWordsLimit", 0)); - question.getQbQuestion().setMinWordsLimit(JsonUtil.optInt(questionJSONData, "minWordsLimit", 0)); - question.getQbQuestion().setMultipleAnswersAllowed( + qbQuestion.setMaxWordsLimit(JsonUtil.optInt(questionJSONData, "maxWordsLimit", 0)); + qbQuestion.setMinWordsLimit(JsonUtil.optInt(questionJSONData, "minWordsLimit", 0)); + qbQuestion.setMultipleAnswersAllowed( JsonUtil.optBoolean(questionJSONData, "multipleAnswersAllowed", Boolean.FALSE)); - question.getQbQuestion().setIncorrectAnswerNullifiesMark( + qbQuestion.setIncorrectAnswerNullifiesMark( JsonUtil.optBoolean(questionJSONData, "incorrectAnswerNullifiesMark", Boolean.FALSE)); - question.getQbQuestion() - .setPenaltyFactor(JsonUtil.optDouble(questionJSONData, "penaltyFactor", 0.0).floatValue()); + qbQuestion.setPenaltyFactor(JsonUtil.optDouble(questionJSONData, "penaltyFactor", 0.0).floatValue()); + + assessmentDao.insert(qbQuestion); + question.setToolContentId(toolContentID); + // question.setUnits(units); Needed for numerical type question if ((type == QbQuestion.TYPE_MATCHING_PAIRS) || (type == QbQuestion.TYPE_MULTIPLE_CHOICE) @@ -3441,8 +3446,10 @@ ArrayNode optionsData = JsonUtil.optArray(questionJSONData, RestTags.ANSWERS); for (JsonNode answerData : optionsData) { QbOption option = new QbOption(); + option.setQbQuestion(qbQuestion); option.setDisplayOrder(JsonUtil.optInt(answerData, RestTags.DISPLAY_ORDER)); - option.setMaxMark(answerData.get("maxMark").floatValue()); + Double maxMark = JsonUtil.optDouble(answerData, "maxMark"); + option.setMaxMark(maxMark == null ? 1 : maxMark.floatValue()); option.setCorrect(JsonUtil.optBoolean(answerData, "correct", false)); option.setAcceptedError(JsonUtil.optDouble(answerData, "acceptedError", 0.0).floatValue()); option.setFeedback(JsonUtil.optString(answerData, "feedback")); Index: lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/service/McService.java =================================================================== diff -u -r8e97adb8dda2f984a9b43f71eacd9a5033244bff -r83ad7bbcfa9124cdf2b8d891f91252b1ed35f74a --- lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/service/McService.java (.../McService.java) (revision 8e97adb8dda2f984a9b43f71eacd9a5033244bff) +++ lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/service/McService.java (.../McService.java) (revision 83ad7bbcfa9124cdf2b8d891f91252b1ed35f74a) @@ -2041,9 +2041,12 @@ ArrayNode questions = JsonUtil.optArray(toolContentJSON, RestTags.QUESTIONS); for (JsonNode questionData : questions) { QbQuestion qbQuestion = new QbQuestion(); + qbQuestion.setQuestionId(qbService.generateNextQuestionId()); qbQuestion.setType(QbQuestion.TYPE_MULTIPLE_CHOICE); qbQuestion.setName(JsonUtil.optString(questionData, RestTags.QUESTION_TEXT)); qbQuestion.setMaxMark(1); + userManagementService.save(qbQuestion); + McQueContent question = new McQueContent(qbQuestion, JsonUtil.optInt(questionData, RestTags.DISPLAY_ORDER), mcq); @@ -2053,6 +2056,7 @@ qbOption.setName(JsonUtil.optString(optionData, RestTags.ANSWER_TEXT)); qbOption.setCorrect(JsonUtil.optBoolean(optionData, RestTags.CORRECT)); qbOption.setDisplayOrder(JsonUtil.optInt(optionData, RestTags.DISPLAY_ORDER)); + qbOption.setQbQuestion(qbQuestion); question.getQbQuestion().getQbOptions().add(qbOption); } saveOrUpdateMcQueContent(question); Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java =================================================================== diff -u -r8d982bb83bb4040e0eba0076df8ab05ff715f2e9 -r83ad7bbcfa9124cdf2b8d891f91252b1ed35f74a --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java (.../ScratchieServiceImpl.java) (revision 8d982bb83bb4040e0eba0076df8ab05ff715f2e9) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java (.../ScratchieServiceImpl.java) (revision 83ad7bbcfa9124cdf2b8d891f91252b1ed35f74a) @@ -413,7 +413,7 @@ public void saveOrUpdateScratchieSession(ScratchieSession resSession) { scratchieSessionDao.saveObject(resSession); } - + @Override public ScratchieAnswerVisitLog getLog(Long sessionId, Long itemUid, boolean isCaseSensitive, String answer) { return scratchieAnswerVisitDao.getLog(sessionId, itemUid, isCaseSensitive, answer); @@ -435,11 +435,11 @@ log.setQbToolQuestion(qbToolQuestion); log.setAccessDate(new Timestamp(new Date().getTime())); scratchieAnswerVisitDao.saveObject(log); - + recalculateMarkForSession(sessionId, false); } } - + @Override public void recordVsaAnswer(Long sessionId, Long itemUid, boolean isCaseSensitive, String answer) { ScratchieAnswerVisitLog log = scratchieAnswerVisitDao.getLog(sessionId, itemUid, isCaseSensitive, answer); @@ -698,7 +698,7 @@ QbQuestion qbQuestion = item.getQbQuestion(); List itemLogs = scratchieAnswerVisitDao.getLogsBySessionAndItem(sessionId, item.getUid()); - + for (OptionDTO optionDto : item.getOptionDtos()) { if (QbQuestion.TYPE_MULTIPLE_CHOICE == qbQuestion.getType()) { int attemptNumber; @@ -713,7 +713,7 @@ } optionDto.setAttemptOrder(attemptNumber); - //process VSA questions + //process VSA questions } else { // -1 if there is no log int attemptNumber = -1; @@ -730,32 +730,30 @@ } } } - + private boolean isAnswersEqual(ScratchieItem item, String answer1, String answer2) { if (answer1 == null || answer2 == null) { return false; } - - return item.getQbQuestion().isCaseSensitive() - ? answer1.equals(answer2) - : answer1.equalsIgnoreCase(answer2); + + return item.getQbQuestion().isCaseSensitive() ? answer1.equals(answer2) : answer1.equalsIgnoreCase(answer2); } @Override public Collection getItemsWithIndicatedScratches(Long toolSessionId) { List userLogs = scratchieAnswerVisitDao.getLogsBySession(toolSessionId); - + Scratchie scratchie = getScratchieBySessionId(toolSessionId); Set items = new TreeSet<>(new ScratchieItemComparator()); items.addAll(scratchie.getScratchieItems()); - + //populate Scratchie items with VSA answers fillItemsWithVsaAnswers(items, toolSessionId, scratchie, userLogs); - + //mark scratched options for (ScratchieItem item : items) { for (OptionDTO optionDto : item.getOptionDtos()) { - + // find according log if it exists boolean isScratched = false; if (QbQuestion.TYPE_MULTIPLE_CHOICE == item.getQbQuestion().getType()) { @@ -767,7 +765,7 @@ } } - //process VSA question + //process VSA question } else { // find according log if it exists for (ScratchieAnswerVisitLog userLog : userLogs) { @@ -787,7 +785,7 @@ return items; } - + /** * Populate Scratchie item with VSA answers (both from Assessment tool and entered by current learner) */ @@ -798,10 +796,10 @@ ? toolService.getVsaAnswersFromAssessment(scratchie.getActivityUiidProvidingVsaAnswers(), leader.getUserId().intValue(), toolSessionId) : null; - + for (ScratchieItem item : items) { Long itemQbQuestionUid = item.getQbQuestion().getUid(); - + //process only VSA items if (item.getQbQuestion().getType() != QbQuestion.TYPE_VERY_SHORT_ANSWERS) { continue; @@ -903,8 +901,8 @@ isItemUnraveled |= option.isCorrect(); } } - - //VSA question + + //VSA question } else { List userAnswers = new ArrayList<>(); for (ScratchieAnswerVisitLog userLog : userLogs) { @@ -918,7 +916,7 @@ return isItemUnraveled; } - + public static boolean isItemUnraveledByAnswers(ScratchieItem item, List userAnswers) { QbQuestion qbQuestion = item.getQbQuestion(); @@ -928,7 +926,7 @@ String[] correctAnswers = correctAnswersGroup.getName().strip().split("\\r\\n"); for (String correctAnswer : correctAnswers) { correctAnswer = correctAnswer.strip(); - + //prepare regex which takes into account only * special character String regexWithOnlyAsteriskSymbolActive = "\\Q"; for (int i = 0; i < correctAnswer.length(); i++) { @@ -949,7 +947,7 @@ pattern = Pattern.compile(regexWithOnlyAsteriskSymbolActive, java.util.regex.Pattern.CASE_INSENSITIVE | java.util.regex.Pattern.UNICODE_CASE); } - + for (String userAnswer : userAnswers) { // check is item unraveled if (pattern.matcher(userAnswer.strip()).matches()) { @@ -971,8 +969,8 @@ * presetMarks to reduce number of queries to DB * @return */ - private static int getUserMarkPerItem(Scratchie scratchie, ScratchieItem item, List userLogs, - String[] presetMarks) { + private static int getUserMarkPerItem(Scratchie scratchie, ScratchieItem item, + List userLogs, String[] presetMarks) { int mark = 0; // add mark only if an item was unraveled @@ -1011,7 +1009,7 @@ Scratchie scratchie = getScratchieByContentId(contentId); ScratchieItem item = scratchieItemDao.getByUid(itemUid); boolean isMcqItem = item.getQbQuestion().getType() == QbQuestion.TYPE_MULTIPLE_CHOICE; - + List sessionList = scratchieSessionDao.getByContentId(contentId); for (ScratchieSession session : sessionList) { Long sessionId = session.getSessionId(); @@ -1048,7 +1046,8 @@ int attemptNumber = 0; for (ScratchieAnswerVisitLog attempt : sessionAttempts) { - Long optionUidOrAnswer = isMcqItem ? attempt.getQbOption().getUid() : attempt.getAnswer().hashCode(); + Long optionUidOrAnswer = isMcqItem ? attempt.getQbOption().getUid() + : attempt.getAnswer().hashCode(); OptionDTO optionDto = optionMap.get(optionUidOrAnswer); int[] attempts = optionDto == null ? new int[optionMap.size()] : optionDto.getAttempts(); // +1 for corresponding choice @@ -1566,7 +1565,7 @@ answer += "(" + getMessage("label.monitoring.item.summary.correct") + ")"; color = IndexedColors.GREEN; } - + columnCount = 0; row[columnCount++] = new ExcelCell(answer, color); @@ -1664,7 +1663,8 @@ for (ScratchieAnswerVisitLog log : logs) { row = new ExcelCell[4]; row[0] = new ExcelCell(new Long(i++), false); - String optionDescr = isMcqItem ? removeHtmlMarkup(log.getQbOption().getName()) : log.getAnswer(); + String optionDescr = isMcqItem ? removeHtmlMarkup(log.getQbOption().getName()) + : log.getAnswer(); row[1] = new ExcelCell(optionDescr, false); row[3] = new ExcelCell(fullDateFormat.format(log.getAccessDate()), false); rowList.add(row); @@ -1910,7 +1910,7 @@ List logs = scratchieAnswerVisitDao.getLogsBySession(sessionId); //populate Scratchie items with VSA answers (both from Assessment tool and entered by current learner) fillItemsWithVsaAnswers(sortedItems, sessionId, scratchie, logs); - + for (ScratchieItem item : sortedItems) { ScratchieItemDTO itemDto = new ScratchieItemDTO(); int numberOfAttempts = 0; @@ -1932,9 +1932,11 @@ numberOfAttempts = visitLogs.size(); // for displaying purposes if there is no attemps we assign -1 which will be shown as "-" - mark = (numberOfAttempts == 0) ? -1 : ScratchieServiceImpl.getUserMarkPerItem(scratchie, item, logs, presetMarks); + mark = (numberOfAttempts == 0) ? -1 + : ScratchieServiceImpl.getUserMarkPerItem(scratchie, item, logs, presetMarks); - isUnraveledOnFirstAttempt = (numberOfAttempts == 1) && ScratchieServiceImpl.isItemUnraveled(item, logs); + isUnraveledOnFirstAttempt = (numberOfAttempts == 1) + && ScratchieServiceImpl.isItemUnraveled(item, logs); // find out options' sequential letters - A,B,C... for (ScratchieAnswerVisitLog itemAttempt : visitLogs) { @@ -1952,7 +1954,7 @@ } optionCount++; } - + optionsSequence += optionsSequence.isEmpty() ? sequencialLetter : ", " + sequencialLetter; } } @@ -2490,7 +2492,8 @@ scratchie.setShowScrachiesInResults(JsonUtil.optBoolean(toolContentJSON, "showScrachiesInResults", true)); scratchie.setConfidenceLevelsActivityUiid( JsonUtil.optInt(toolContentJSON, RestTags.CONFIDENCE_LEVELS_ACTIVITY_UIID)); - scratchie.setActivityUiidProvidingVsaAnswers(JsonUtil.optInt(toolContentJSON, "activityUiidProvidingVsaAnswers")); + scratchie.setActivityUiidProvidingVsaAnswers( + JsonUtil.optInt(toolContentJSON, "activityUiidProvidingVsaAnswers")); // Scratchie Items Set newItems = new LinkedHashSet<>(); @@ -2501,9 +2504,15 @@ ScratchieItem item = new ScratchieItem(); item.setDisplayOrder(JsonUtil.optInt(questionData, RestTags.DISPLAY_ORDER)); - item.getQbQuestion().setName(JsonUtil.optString(questionData, RestTags.QUESTION_TITLE)); - item.getQbQuestion().setDescription(JsonUtil.optString(questionData, RestTags.QUESTION_TEXT)); + QbQuestion qbQuestion = new QbQuestion(); + + qbQuestion.setType(QbQuestion.TYPE_MULTIPLE_CHOICE); + qbQuestion.setQuestionId(qbService.generateNextQuestionId()); + qbQuestion.setName(JsonUtil.optString(questionData, RestTags.QUESTION_TITLE)); + qbQuestion.setDescription(JsonUtil.optString(questionData, RestTags.QUESTION_TEXT)); item.setToolContentId(scratchie.getContentId()); + scratchieDao.insert(qbQuestion); + item.setQbQuestion(qbQuestion); newItems.add(item); // set options