Index: lams_central/conf/language/lams/ApplicationResources_en_AU.properties =================================================================== diff -u -r6aa0f9c7abedde6c4c3cc7fe2b0b19176df284ed -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_central/conf/language/lams/ApplicationResources_en_AU.properties (.../ApplicationResources_en_AU.properties) (revision 6aa0f9c7abedde6c4c3cc7fe2b0b19176df284ed) +++ lams_central/conf/language/lams/ApplicationResources_en_AU.properties (.../ApplicationResources_en_AU.properties) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -896,7 +896,7 @@ label.create.question =Create question label.question.type.multiple.choice =Multiple choice label.question.type.matching.pairs =Matching pairs -label.question.type.short.answer =Short answer +label.question.type.short.answer =Very short answers label.question.type.numerical =Numerical label.question.type.true.false =True/False label.question.type.essay =Essay @@ -954,6 +954,7 @@ label.authoring.basic.general.feedback =General feedback label.authoring.basic.shuffle.the.choices =Shuffle answers? label.ask.for.hedging.justification =Ask for hedging justification? +label.autocomplete.as.student =Autocomplete (as student types answer autocomplete with stemming from answers) label.authoring.basic.penalty.factor =Penalty factor error.form.validation.hundred.score =One of the answers should have a grade of 100% so it is possible to get full marks for this question. error.form.validation.positive.accepted.errors =All the accepted errors should be positive. @@ -968,7 +969,7 @@ label.authoring.true.false.true =True label.authoring.basic.type.multiple.choice =Multiple choice label.authoring.basic.type.matching.pairs =Matching pairs -label.authoring.basic.type.short.answer =Short answer +label.authoring.basic.type.short.answer =Very short answers label.authoring.basic.type.numerical =Numerical label.authoring.basic.type.true.false =True/False label.authoring.basic.type.essay =Essay @@ -978,5 +979,6 @@ label.authoring.basic.option.answer =Answer label.authoring.basic.delete =Delete label.authoring.basic.none =None +error.positive.grade.required =One of the answers should have a positive grade #======= End labels: Exported 872 labels for en AU ===== Index: lams_central/src/java/org/lamsfoundation/lams/web/qb/EditQbQuestionController.java =================================================================== diff -u -rf0b909d0e482fe674e3c3d2f40ec7cc8d19b6803 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_central/src/java/org/lamsfoundation/lams/web/qb/EditQbQuestionController.java (.../EditQbQuestionController.java) (revision f0b909d0e482fe674e3c3d2f40ec7cc8d19b6803) +++ lams_central/src/java/org/lamsfoundation/lams/web/qb/EditQbQuestionController.java (.../EditQbQuestionController.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -2,6 +2,7 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.lang.reflect.InvocationTargetException; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Date; @@ -15,6 +16,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.log4j.Logger; @@ -106,7 +108,7 @@ */ @RequestMapping("/editQuestion") public String editQuestion(@ModelAttribute("assessmentQuestionForm") QbQuestionForm form, - HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, IllegalAccessException, InvocationTargetException { Long qbQuestionUid = WebUtil.readLongParam(request, "qbQuestionUid"); QbQuestion qbQuestion = qbService.getQuestionByUid(qbQuestionUid); if (qbQuestion == null) { @@ -136,10 +138,12 @@ form.setMaxWordsLimit(qbQuestion.getMaxWordsLimit()); form.setMinWordsLimit(qbQuestion.getMinWordsLimit()); form.setHedgingJustificationEnabled(qbQuestion.isHedgingJustificationEnabled()); + //TODO check autocomplete is saved and then maybe remove other property copying + BeanUtils.copyProperties(form, qbQuestion); Integer questionType = qbQuestion.getType(); if ((questionType == QbQuestion.TYPE_MULTIPLE_CHOICE) || (questionType == QbQuestion.TYPE_ORDERING) - || (questionType == QbQuestion.TYPE_MATCHING_PAIRS) || (questionType == QbQuestion.TYPE_SHORT_ANSWER) + || (questionType == QbQuestion.TYPE_MATCHING_PAIRS) || (questionType == QbQuestion.TYPE_VERY_SHORT_ANSWERS) || (questionType == QbQuestion.TYPE_NUMERICAL) || (questionType == QbQuestion.TYPE_MARK_HEDGING)) { List optionList = qbQuestion.getQbOptions(); request.setAttribute(QbConstants.ATTR_OPTION_LIST, optionList); @@ -267,8 +271,8 @@ // without eviction changes would be saved immediately into DB qbService.releaseFromCache(oldQuestion); - qbQuestion.setName(form.getTitle()); - qbQuestion.setDescription(form.getDescription()); + qbQuestion.setName(form.getTitle().strip()); + qbQuestion.setDescription(form.getDescription().strip()); if (!form.isAuthoringRestricted()) { qbQuestion.setMaxMark(form.getMaxMark()); @@ -290,27 +294,35 @@ qbQuestion.setFeedbackOnCorrect(form.getFeedbackOnCorrect()); qbQuestion.setFeedbackOnPartiallyCorrect(form.getFeedbackOnPartiallyCorrect()); qbQuestion.setFeedbackOnIncorrect(form.getFeedbackOnIncorrect()); + } else if ((type == QbQuestion.TYPE_MATCHING_PAIRS)) { qbQuestion.setPenaltyFactor(Float.parseFloat(form.getPenaltyFactor())); qbQuestion.setShuffle(form.isShuffle()); - } else if ((type == QbQuestion.TYPE_SHORT_ANSWER)) { + + } else if ((type == QbQuestion.TYPE_VERY_SHORT_ANSWERS)) { qbQuestion.setPenaltyFactor(Float.parseFloat(form.getPenaltyFactor())); qbQuestion.setCaseSensitive(form.isCaseSensitive()); + qbQuestion.setAutocompleteEnabled(form.isAutocompleteEnabled()); + } else if ((type == QbQuestion.TYPE_NUMERICAL)) { qbQuestion.setPenaltyFactor(Float.parseFloat(form.getPenaltyFactor())); + } else if ((type == QbQuestion.TYPE_TRUE_FALSE)) { qbQuestion.setPenaltyFactor(Float.parseFloat(form.getPenaltyFactor())); qbQuestion.setCorrectAnswer(form.isCorrectAnswer()); qbQuestion.setFeedbackOnCorrect(form.getFeedbackOnCorrect()); qbQuestion.setFeedbackOnIncorrect(form.getFeedbackOnIncorrect()); + } else if ((type == QbQuestion.TYPE_ESSAY)) { qbQuestion.setAllowRichEditor(form.isAllowRichEditor()); qbQuestion.setMaxWordsLimit(form.getMaxWordsLimit()); qbQuestion.setMinWordsLimit(form.getMinWordsLimit()); + } else if (type == QbQuestion.TYPE_ORDERING) { qbQuestion.setPenaltyFactor(Float.parseFloat(form.getPenaltyFactor())); qbQuestion.setFeedbackOnCorrect(form.getFeedbackOnCorrect()); qbQuestion.setFeedbackOnIncorrect(form.getFeedbackOnIncorrect()); + } else if (type == QbQuestion.TYPE_MARK_HEDGING) { qbQuestion.setShuffle(form.isShuffle()); qbQuestion.setFeedbackOnCorrect(form.getFeedbackOnCorrect()); @@ -321,7 +333,7 @@ // set options if ((type == QbQuestion.TYPE_MULTIPLE_CHOICE) || (type == QbQuestion.TYPE_ORDERING) - || (type == QbQuestion.TYPE_MATCHING_PAIRS) || (type == QbQuestion.TYPE_SHORT_ANSWER) + || (type == QbQuestion.TYPE_MATCHING_PAIRS) || (type == QbQuestion.TYPE_VERY_SHORT_ANSWERS) || (type == QbQuestion.TYPE_NUMERICAL) || (type == QbQuestion.TYPE_MARK_HEDGING)) { Set optionList = getOptionsFromRequest(request, true); List options = new ArrayList<>(); @@ -428,7 +440,7 @@ } option.setDisplayOrder(NumberUtils.toInt(displayOrder)); - if ((questionType == QbQuestion.TYPE_MULTIPLE_CHOICE) || (questionType == QbQuestion.TYPE_SHORT_ANSWER)) { + if ((questionType == QbQuestion.TYPE_MULTIPLE_CHOICE) || (questionType == QbQuestion.TYPE_VERY_SHORT_ANSWERS)) { String name = paramMap.get(QbConstants.ATTR_OPTION_NAME_PREFIX + i); if ((name == null) && isForSaving) { continue; @@ -496,6 +508,17 @@ optionList.add(option); } + +// //in case of VSA make sure it has 2 option groups, one of which having 0 maxMark +// if (questionType == QbQuestion.TYPE_VERY_SHORT_ANSWERS && optionList.size() == 1) { +// QbOption option = new QbOption(); +// option.setDisplayOrder(1); +// option.setName(""); +// option.setMaxMark(0); +// option.setFeedback(""); +// optionList.add(option); +// } + return optionList; } @@ -578,8 +601,8 @@ case QbQuestion.TYPE_MATCHING_PAIRS: forward = "qb/authoring/addmatchingpairs"; break; - case QbQuestion.TYPE_SHORT_ANSWER: - forward = "qb/authoring/addshortanswer"; + case QbQuestion.TYPE_VERY_SHORT_ANSWERS: + forward = "qb/authoring/addVsa"; break; case QbQuestion.TYPE_NUMERICAL: forward = "qb/authoring/addnumerical"; Index: lams_central/src/java/org/lamsfoundation/lams/web/qb/ImsQtiController.java =================================================================== diff -u -r7dc409ffd76dcebc2d210a3a128cdcbba171ff33 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_central/src/java/org/lamsfoundation/lams/web/qb/ImsQtiController.java (.../ImsQtiController.java) (revision 7dc409ffd76dcebc2d210a3a128cdcbba171ff33) +++ lams_central/src/java/org/lamsfoundation/lams/web/qb/ImsQtiController.java (.../ImsQtiController.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -90,7 +90,7 @@ qbQuestion.setPrefixAnswersWithLetters(false); } else { - qbQuestion.setType(QbQuestion.TYPE_SHORT_ANSWER); + qbQuestion.setType(QbQuestion.TYPE_VERY_SHORT_ANSWERS); qbQuestion.setCaseSensitive(false); } @@ -400,7 +400,7 @@ } break; - case QbQuestion.TYPE_SHORT_ANSWER: + case QbQuestion.TYPE_VERY_SHORT_ANSWERS: question.setType(Question.QUESTION_TYPE_FILL_IN_BLANK); for (QbOption assessmentAnswer : qbQuestion.getQbOptions()) { Index: lams_central/src/java/org/lamsfoundation/lams/web/qb/SearchQBController.java =================================================================== diff -u -r475b1970be027a5c59a08d33ad1aa1f6b2443402 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_central/src/java/org/lamsfoundation/lams/web/qb/SearchQBController.java (.../SearchQBController.java) (revision 475b1970be027a5c59a08d33ad1aa1f6b2443402) +++ lams_central/src/java/org/lamsfoundation/lams/web/qb/SearchQBController.java (.../SearchQBController.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -95,7 +95,12 @@ StringBuilder questionTypesAvailable = new StringBuilder(); //by default show MCQ type of questions (except for Q&A tool) int questionTypeDefault = QbQuestion.TYPE_MULTIPLE_CHOICE; - if (CommonConstants.TOOL_SIGNATURE_SCRATCHIE.equals(toolSignature) || CommonConstants.TOOL_SIGNATURE_MCQ.equals(toolSignature)) { + if (CommonConstants.TOOL_SIGNATURE_MCQ.equals(toolSignature)) { + + } else if (CommonConstants.TOOL_SIGNATURE_SCRATCHIE.equals(toolSignature)) { + questionTypesAvailable.append(QbQuestion.TYPE_MULTIPLE_CHOICE); + questionTypesAvailable.append(","); + questionTypesAvailable.append(QbQuestion.TYPE_VERY_SHORT_ANSWERS); //CommonConstants.TOOL_SIGNATURE_SURVEY } else if ("lasurv11".equals(toolSignature)) { @@ -108,7 +113,7 @@ questionTypesAvailable.append(","); questionTypesAvailable.append(QbQuestion.TYPE_MATCHING_PAIRS); questionTypesAvailable.append(","); - questionTypesAvailable.append(QbQuestion.TYPE_SHORT_ANSWER); + questionTypesAvailable.append(QbQuestion.TYPE_VERY_SHORT_ANSWERS); questionTypesAvailable.append(","); questionTypesAvailable.append(QbQuestion.TYPE_NUMERICAL); questionTypesAvailable.append(","); @@ -126,6 +131,8 @@ } request.setAttribute("questionType", questionTypeDefault); request.setAttribute("questionTypesAvailable", questionTypesAvailable.toString()); + //let jsp know it's Scratchie, so we can disable VSA questions not compatible with TBL + request.setAttribute("isScratchie", CommonConstants.TOOL_SIGNATURE_SCRATCHIE.equals(toolSignature)); //prepare data for displaying collections Integer userId = getUserId(); @@ -207,6 +214,11 @@ QbQuestion qbQuestion = (QbQuestion) userManagementService.findById(QbQuestion.class, questionUid); request.setAttribute("question", qbQuestion); + boolean isVsaAndCompatibleWithTbl = qbQuestion.isVsaAndCompatibleWithTbl(); + request.setAttribute("isVsaAndCompatibleWithTbl", isVsaAndCompatibleWithTbl); + boolean isScratchie = WebUtil.readBooleanParam(request, "isScratchie", false); + request.setAttribute("isScratchie", isScratchie); + List otherVersions = qbService.getQuestionsByQuestionId(qbQuestion.getQuestionId()); request.setAttribute("otherVersions", otherVersions); Index: lams_central/web/css/qb-question.scss =================================================================== diff -u -r6a00057c1bd113919030bcd00ce1e3c7327c7b2e -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_central/web/css/qb-question.scss (.../qb-question.scss) (revision 6a00057c1bd113919030bcd00ce1e3c7327c7b2e) +++ lams_central/web/css/qb-question.scss (.../qb-question.scss) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -95,26 +95,26 @@ } /*Style for text input fields. Rule does not apply in case this input has an error*/ -:not(.has-error) > input.borderless-text-input{ +:not(.has-error) > .borderless-text-input{ border: 0; box-shadow: none; padding: 0; } /* Remove bold style from title field */ -input.borderless-text-input::-webkit-input-placeholder { +.borderless-text-input::-webkit-input-placeholder { font-weight: normal; color:#999; } -input.borderless-text-input::-moz-placeholder { +.borderless-text-input::-moz-placeholder { font-weight: normal; color:#999; } -input.borderless-text-input:-ms-input-placeholder { +.borderless-text-input:-ms-input-placeholder { font-weight: normal; color:#999; } -input.borderless-text-input:-o-input-placeholder { +.borderless-text-input:-o-input-placeholder { font-weight: normal; color:#999; } @@ -223,9 +223,9 @@ border: 0.02em solid #bdc3c7; background: #e1e1e1; color: #222222; - margin-top: -0.02em; padding: 0.08em; opacity:0.8; + height: .4em; } .ui-state-default, .ui-widget-content.ui-slider .ui-state-default{ Index: lams_central/web/includes/javascript/qb-option.js =================================================================== diff -u -r6cbd849584c40532c6be292f9f009c88cde9439c -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_central/web/includes/javascript/qb-option.js (.../qb-option.js) (revision 6cbd849584c40532c6be292f9f009c88cde9439c) +++ lams_central/web/includes/javascript/qb-option.js (.../qb-option.js) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -105,31 +105,33 @@ } //init options sorting feature - new Sortable($('#option-table.sortable-on')[0], { - animation: 150, - ghostClass: 'sortable-placeholder', - direction: 'vertical', - onStart: function (evt) { - //stop answers' hover effect, once element dragging started - //$("#option-table").removeClass("hover-active"); - }, - onEnd: function (evt) { - //activate answers' hover effect, once element dragging ended - //$("#option-table").delay(50).queue(function(next){ - // $(this).addClass("hover-active"); - // next(); - //}); - }, - store: { - set: function (sortable) { - //update all displayOrders in order to later save it as options' order - var order = sortable.toArray(); - for (var i = 0; i < order.length; i++) { - var optionIndex = order[i]; - $('input[name="optionDisplayOrder' + optionIndex + '"]').val(i+1); + if ($('#option-table.sortable-on').length) { + new Sortable($('#option-table.sortable-on')[0], { + animation: 150, + ghostClass: 'sortable-placeholder', + direction: 'vertical', + onStart: function (evt) { + //stop answers' hover effect, once element dragging started + //$("#option-table").removeClass("hover-active"); + }, + onEnd: function (evt) { + //activate answers' hover effect, once element dragging ended + //$("#option-table").delay(50).queue(function(next){ + // $(this).addClass("hover-active"); + // next(); + //}); + }, + store: { + set: function (sortable) { + //update all displayOrders in order to later save it as options' order + var order = sortable.toArray(); + for (var i = 0; i < order.length; i++) { + var optionIndex = order[i]; + $('input[name="optionDisplayOrder' + optionIndex + '"]').val(i+1); + } } } - } - }); + }); + } } Index: lams_central/web/qb/authoring/addVsa.jsp =================================================================== diff -u --- lams_central/web/qb/authoring/addVsa.jsp (revision 0) +++ lams_central/web/qb/authoring/addVsa.jsp (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -0,0 +1,231 @@ + +<%@ include file="/common/taglibs.jsp"%> + + + + + <%@ include file="addQuestionHeader.jsp"%> + + + + + +
+
+ +
+ +
+ + + + + + + + + + + + + + +
+ +
+ + + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+
+ +
+
+ +
+
+ + + +
+ +
+ + +
+ + +
+ + +
+ +
+
+
+ +
+ + +
+ +
+
+ +
+ + +
+ + + + +
+
+ + +
+ + +
+ +
+ + +
+ + +
+ +
+ + +
+
+ <%@ include file="optionlist.jsp"%> + + + + +
+
+ +
+
+ + <%@ include file="addQuestionFooter.jsp"%> + +
Fisheye: Tag e8a7110708b15579af2c6b31ac52a6da427fef6d refers to a dead (removed) revision in file `lams_central/web/qb/authoring/addshortanswer.jsp'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_central/web/qb/authoring/optionlist.jsp =================================================================== diff -u -r6cbd849584c40532c6be292f9f009c88cde9439c -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_central/web/qb/authoring/optionlist.jsp (.../optionlist.jsp) (revision 6cbd849584c40532c6be292f9f009c88cde9439c) +++ lams_central/web/qb/authoring/optionlist.jsp (.../optionlist.jsp) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -83,7 +83,7 @@
class="sortable-on"> + class="sortable-on"> @@ -101,8 +101,8 @@ <%@ include file="matchingpairoption.jsp"%> - <%@ include file="shortansweroption.jsp"%> - + <%@ include file="vsaOption.jsp"%> + <%@ include file="numericaloption.jsp"%> Fisheye: Tag e8a7110708b15579af2c6b31ac52a6da427fef6d refers to a dead (removed) revision in file `lams_central/web/qb/authoring/shortansweroption.jsp'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_central/web/qb/authoring/vsaOption.jsp =================================================================== diff -u --- lams_central/web/qb/authoring/vsaOption.jsp (revision 0) +++ lams_central/web/qb/authoring/vsaOption.jsp (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -0,0 +1,23 @@ + + + +
+ + + + +
+ + + Index: lams_central/web/qb/qbQuestionDetails.jsp =================================================================== diff -u -rbc75f6b0213eeccefaf4b0b89298f757da37aaa2 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_central/web/qb/qbQuestionDetails.jsp (.../qbQuestionDetails.jsp) (revision bc75f6b0213eeccefaf4b0b89298f757da37aaa2) +++ lams_central/web/qb/qbQuestionDetails.jsp (.../qbQuestionDetails.jsp) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -10,10 +10,20 @@
- - - + + + + + + + + + + Not compatible with TBL + + +   Index: lams_central/web/qb/search.jsp =================================================================== diff -u -r847b6e17a50b828bed3c01f1d168f7c4f81004c4 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_central/web/qb/search.jsp (.../search.jsp) (revision 847b6e17a50b828bed3c01f1d168f7c4f81004c4) +++ lams_central/web/qb/search.jsp (.../search.jsp) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -236,7 +236,8 @@ $("#question-detail-area").show().load( '', { - questionUid: questionUid + questionUid: questionUid, + isScratchie: ${isScratchie} }, function() { } Index: lams_common/src/java/org/lamsfoundation/lams/confidencelevel/VsaAnswerDTO.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/confidencelevel/VsaAnswerDTO.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/confidencelevel/VsaAnswerDTO.java (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -0,0 +1,80 @@ +package org.lamsfoundation.lams.confidencelevel; + +import java.util.LinkedList; +import java.util.List; + +public class VsaAnswerDTO { + + private Long qbQuestionUid; + private Long qbOptionUid; + private String answer; + private boolean correct; + private Long userId; + private List confidenceLevels; + + public VsaAnswerDTO() { + this.confidenceLevels = new LinkedList<>(); + } + + /** + */ + public void setQbQuestionUid(Long qbQuestionUid) { + this.qbQuestionUid = qbQuestionUid; + } + + public Long getQbQuestionUid() { + return this.qbQuestionUid; + } + + /** + */ + public void setQbOptionUid(Long qbOptionUid) { + this.qbOptionUid = qbOptionUid; + } + + public Long getQbOptionUid() { + return this.qbOptionUid; + } + + /** + */ + public void setAnswer(String answer) { + this.answer = answer; + } + + public String getAnswer() { + return this.answer; + } + + public void setCorrect(boolean correct) { + this.correct = correct; + } + + public boolean isCorrect() { + return this.correct; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public Long getUserId() { + return this.userId; + } + + /** + */ + public void setConfidenceLevels(List confidenceLevels) { + this.confidenceLevels = confidenceLevels; + } + + /** + * Each ConfidenceLevelDTO contains userId, userName, portraitUuid, confidence level (if this option was enabled in + * Assessment) + * + * @return + */ + public List getConfidenceLevels() { + return this.confidenceLevels; + } +} Index: lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20190913.sql =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20190913.sql (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20190913.sql (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -0,0 +1,14 @@ +-- Turn off autocommit, so nothing is committed if there is an error +SET AUTOCOMMIT = 0; +SET FOREIGN_KEY_CHECKS=0; +----------------------Put all sql statements below here------------------------- + +-- LDEV-4875 Add VSA question type to Assessment and Scratchie +ALTER TABLE lams_qb_question ADD COLUMN autocomplete_enabled TINYINT(1) DEFAULT 0; + +----------------------Put all sql statements above here------------------------- + +-- If there were no errors, commit and restore autocommit to on +COMMIT; +SET AUTOCOMMIT = 1; +SET FOREIGN_KEY_CHECKS=1; \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/qb/form/QbQuestionForm.java =================================================================== diff -u -r9ebb0762842cde9a358626a248132bc7ca650f3c -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_common/src/java/org/lamsfoundation/lams/qb/form/QbQuestionForm.java (.../QbQuestionForm.java) (revision 9ebb0762842cde9a358626a248132bc7ca650f3c) +++ lams_common/src/java/org/lamsfoundation/lams/qb/form/QbQuestionForm.java (.../QbQuestionForm.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -62,6 +62,7 @@ private int maxWordsLimit; private int minWordsLimit; private boolean hedgingJustificationEnabled; + private boolean autocompleteEnabled; private boolean authoringRestricted; private Long oldCollectionUid; @@ -270,7 +271,15 @@ public void setHedgingJustificationEnabled(boolean hedgingJustificationEnabled) { this.hedgingJustificationEnabled = hedgingJustificationEnabled; } + + public boolean isAutocompleteEnabled() { + return autocompleteEnabled; + } + public void setAutocompleteEnabled(boolean autocompleteEnabled) { + this.autocompleteEnabled = autocompleteEnabled; + } + public boolean isAuthoringRestricted() { return authoringRestricted; } Index: lams_common/src/java/org/lamsfoundation/lams/qb/model/QbQuestion.java =================================================================== diff -u -r3190bef4d1c10ac3e955dd0492d6747ae4975629 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_common/src/java/org/lamsfoundation/lams/qb/model/QbQuestion.java (.../QbQuestion.java) (revision 3190bef4d1c10ac3e955dd0492d6747ae4975629) +++ lams_common/src/java/org/lamsfoundation/lams/qb/model/QbQuestion.java (.../QbQuestion.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -37,7 +37,7 @@ // not all tools can produce/consume all question types public static final int TYPE_MULTIPLE_CHOICE = 1; public static final int TYPE_MATCHING_PAIRS = 2; - public static final int TYPE_SHORT_ANSWER = 3; + public static final int TYPE_VERY_SHORT_ANSWERS = 3; public static final int TYPE_NUMERICAL = 4; public static final int TYPE_TRUE_FALSE = 5; public static final int TYPE_ESSAY = 6; @@ -131,9 +131,13 @@ @Column(name = "min_words_limit") private int minWordsLimit; - // only for hedging maxMark type of question + /** ---- only for hedging type of question ---- */ @Column(name = "hedging_justification_enabled") private boolean hedgingJustificationEnabled; + + /** ---- only for VSA type of question ---- */ + @Column(name = "autocomplete_enabled") + private boolean autocompleteEnabled; @OneToMany(mappedBy = "qbQuestion", fetch = FetchType.EAGER, cascade = CascadeType.ALL) @Fetch(FetchMode.SUBSELECT) @@ -172,7 +176,7 @@ if (((oldQuestion.getType() == QbQuestion.TYPE_ORDERING) && (oldOption.getDisplayOrder() != newOption.getDisplayOrder())) //short answer - || ((oldQuestion.getType() == QbQuestion.TYPE_SHORT_ANSWER) + || ((oldQuestion.getType() == QbQuestion.TYPE_VERY_SHORT_ANSWERS) && !StringUtils.equals(oldOption.getName(), newOption.getName())) //numbering || (oldOption.getNumericalOption() != newOption.getNumericalOption()) @@ -248,7 +252,25 @@ } } } + + /** + * Check if it's a TBL case, i.e. only two option groups available, one has 0%, second - 100% + */ + public boolean isVsaAndCompatibleWithTbl() { + boolean isVsaAndCompatibleWithTbl = false; + + if (qbOptions.size() == 2) { + float firstGroupMark = qbOptions.get(0).getMaxMark(); + float secondGroupMark = qbOptions.get(1).getMaxMark(); + isVsaAndCompatibleWithTbl = (firstGroupMark == 0 || firstGroupMark == 1) + && (secondGroupMark == 0 || secondGroupMark == 1) && (firstGroupMark != secondGroupMark) + && type == QbQuestion.TYPE_VERY_SHORT_ANSWERS; + } + + return isVsaAndCompatibleWithTbl; + } + public Long getUid() { return uid; } @@ -454,7 +476,15 @@ public void setHedgingJustificationEnabled(boolean hedgingJustificationEnabled) { this.hedgingJustificationEnabled = hedgingJustificationEnabled; } + + public boolean isAutocompleteEnabled() { + return autocompleteEnabled; + } + public void setAutocompleteEnabled(boolean autocompleteEnabled) { + this.autocompleteEnabled = autocompleteEnabled; + } + public boolean isPrefixAnswersWithLetters() { return prefixAnswersWithLetters; } Index: lams_common/src/java/org/lamsfoundation/lams/tool/service/ICommonAssessmentService.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/tool/service/ICommonAssessmentService.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/tool/service/ICommonAssessmentService.java (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -0,0 +1,19 @@ +package org.lamsfoundation.lams.tool.service; + +import java.util.Collection; + +import org.lamsfoundation.lams.confidencelevel.VsaAnswerDTO; + +public interface ICommonAssessmentService { + + /** + * Returns answers learners left for VSA questions in Assessment activity (together with according confidence + * levels, if such option is turned on in Assessment). Currently only Assessment tool is capable of producing VSA + * answers. + * + * @param toolSessionId + * @return + */ + Collection getVsaAnswers(Long toolSessionId); + +} Index: lams_common/src/java/org/lamsfoundation/lams/tool/service/ILamsCoreToolService.java =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_common/src/java/org/lamsfoundation/lams/tool/service/ILamsCoreToolService.java (.../ILamsCoreToolService.java) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_common/src/java/org/lamsfoundation/lams/tool/service/ILamsCoreToolService.java (.../ILamsCoreToolService.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -23,10 +23,12 @@ package org.lamsfoundation.lams.tool.service; +import java.util.Collection; import java.util.List; import java.util.SortedMap; import org.lamsfoundation.lams.confidencelevel.ConfidenceLevelDTO; +import org.lamsfoundation.lams.confidencelevel.VsaAnswerDTO; import org.lamsfoundation.lams.learningdesign.Activity; import org.lamsfoundation.lams.learningdesign.LearningDesign; import org.lamsfoundation.lams.learningdesign.ToolActivity; @@ -280,6 +282,16 @@ * @return */ List getConfidenceLevelsByToolSession(ToolSession toolSession); + + /** + * Returns answers learners left for VSA questions in Assessment activity (together with according confidence + * levels, if such option is turned on in Assessment). Currently only Assessment tool is capable of producing VSA + * answers. + * + * @param toolSession + * @return + */ + Collection getVsaAnswersByToolSession(ToolSession toolSession); /** * Notifies tool that the user is force completed. Currently it's been utilized only by leader aware tools, which Index: lams_common/src/java/org/lamsfoundation/lams/tool/service/ILamsToolService.java =================================================================== diff -u -r3bb7e0141ae1cc15ccd737c95d90b5762a34ad61 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_common/src/java/org/lamsfoundation/lams/tool/service/ILamsToolService.java (.../ILamsToolService.java) (revision 3bb7e0141ae1cc15ccd737c95d90b5762a34ad61) +++ lams_common/src/java/org/lamsfoundation/lams/tool/service/ILamsToolService.java (.../ILamsToolService.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -23,13 +23,14 @@ package org.lamsfoundation.lams.tool.service; import java.io.IOException; +import java.util.Collection; import java.util.List; import java.util.Set; import org.lamsfoundation.lams.confidencelevel.ConfidenceLevelDTO; +import org.lamsfoundation.lams.confidencelevel.VsaAnswerDTO; import org.lamsfoundation.lams.learning.service.LearnerServiceException; import org.lamsfoundation.lams.learningdesign.ToolActivity; -import org.lamsfoundation.lams.learningdesign.dto.ActivityPositionDTO; import org.lamsfoundation.lams.tool.Tool; import org.lamsfoundation.lams.tool.ToolOutput; import org.lamsfoundation.lams.tool.ToolSession; @@ -185,7 +186,16 @@ * toolContentId of the specified activity * @return */ - Set getPrecedingConfidenceLevelsActivities(Long toolContentId); + Set getActivitiesProvidingConfidenceLevels(Long toolContentId); + + /** + * Returns all activities that precede specified activity and can provide VSA answers. + * + * @param toolContentId + * toolContentId of the specified activity + * @return + */ + Set getActivitiesProvidingVsaAnswers(Long toolContentId); /** * Returns confidence levels from the specified activity. @@ -200,6 +210,20 @@ */ List getConfidenceLevelsByActivity(Integer confidenceLevelActivityUiid, Integer requestorUserId, Long requestorToolSessionId); + + /** + * Returns VSA answers from the specified activity. + * + * @param activityUiid + * activityUiid of the activity providing VSA answers + * @param requestorUserId + * userId of the requesting user. we need it in order to get tool's sessionId providing VSA answers + * @param requestorToolSessionId + * toolSessionId of the activity that calls this method + * @return + */ + Collection getVsaAnswersFromAssessment(Integer activityUiidProvidingVsaAnswers, + Integer requestorUserId, Long requestorToolSessionId); /** * Get a count of all the users that would be returned by getUsersForActivity(Long toolSessionId); Index: lams_common/src/java/org/lamsfoundation/lams/tool/service/LamsCoreToolService.java =================================================================== diff -u -r9f98b5e2b822f824d857d3d677f21b1149f794c8 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_common/src/java/org/lamsfoundation/lams/tool/service/LamsCoreToolService.java (.../LamsCoreToolService.java) (revision 9f98b5e2b822f824d857d3d677f21b1149f794c8) +++ lams_common/src/java/org/lamsfoundation/lams/tool/service/LamsCoreToolService.java (.../LamsCoreToolService.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -23,6 +23,7 @@ package org.lamsfoundation.lams.tool.service; +import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Set; @@ -31,6 +32,7 @@ import org.apache.log4j.Logger; import org.lamsfoundation.lams.confidencelevel.ConfidenceLevelDTO; +import org.lamsfoundation.lams.confidencelevel.VsaAnswerDTO; import org.lamsfoundation.lams.learningdesign.Activity; import org.lamsfoundation.lams.learningdesign.ActivityEvaluation; import org.lamsfoundation.lams.learningdesign.ComplexActivity; @@ -62,6 +64,7 @@ import org.lamsfoundation.lams.tool.exception.RequiredGroupMissingException; import org.lamsfoundation.lams.tool.exception.ToolException; import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.util.CommonConstants; import org.lamsfoundation.lams.util.MessageService; import org.lamsfoundation.lams.util.WebUtil; import org.lamsfoundation.lams.web.util.AttributeNames; @@ -534,6 +537,45 @@ } @Override + public Collection getVsaAnswersByToolSession(ToolSession toolSession) { + + if (toolSession == null) { + String error = "The toolSession is null. Unable to get confidence levels"; + LamsCoreToolService.log.error(error); + throw new DataMissingException(error); + } + + Tool tool = toolSession.getToolActivity().getTool(); + if (tool == null) { + String error = "The tool for toolSession " + toolSession.getToolSessionId() + " is missing."; + LamsCoreToolService.log.error(error); + throw new DataMissingException(error); + } + + if (!CommonConstants.TOOL_SIGNATURE_ASSESSMENT.equals(tool.getToolSignature())) { + String error = "Only Assessment is capable of providing VSA answers. Bu this session belongs to tool: " + + tool.getToolSignature(); + LamsCoreToolService.log.error(error); + throw new DataMissingException(error); + } + + try { + ICommonAssessmentService sessionManager = (ICommonAssessmentService) findToolService(tool); + return sessionManager.getVsaAnswers(toolSession.getToolSessionId()); + } catch (NoSuchBeanDefinitionException e) { + String message = "A tool which is defined in the database appears to missing from the classpath. Unable to get the tool output. toolActivity " + + toolSession.getToolActivity().getActivityId(); + LamsCoreToolService.log.error(message, e); + throw new ToolException(message, e); + } catch (java.lang.AbstractMethodError e) { + String message = "Tool " + tool.getToolDisplayName() + + " doesn't support the getToolOutput(name, toolSessionId, learnerId) method so no output definitions can be accessed."; + LamsCoreToolService.log.error(message, e); + throw new ToolException(message, e); + } + } + + @Override public List getConfidenceLevelsByToolSession(ToolSession toolSession) { if (toolSession == null) { Index: lams_common/src/java/org/lamsfoundation/lams/tool/service/LamsToolService.java =================================================================== diff -u -r3bb7e0141ae1cc15ccd737c95d90b5762a34ad61 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_common/src/java/org/lamsfoundation/lams/tool/service/LamsToolService.java (.../LamsToolService.java) (revision 3bb7e0141ae1cc15ccd737c95d90b5762a34ad61) +++ lams_common/src/java/org/lamsfoundation/lams/tool/service/LamsToolService.java (.../LamsToolService.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -24,6 +24,7 @@ package org.lamsfoundation.lams.tool.service; import java.io.IOException; +import java.util.Collection; import java.util.Date; import java.util.LinkedHashSet; import java.util.List; @@ -35,6 +36,7 @@ import org.hibernate.Hibernate; import org.hibernate.proxy.HibernateProxy; import org.lamsfoundation.lams.confidencelevel.ConfidenceLevelDTO; +import org.lamsfoundation.lams.confidencelevel.VsaAnswerDTO; import org.lamsfoundation.lams.gradebook.service.IGradebookService; import org.lamsfoundation.lams.learning.service.ILearnerService; import org.lamsfoundation.lams.learningdesign.Activity; @@ -357,7 +359,7 @@ } @Override - public Set getPrecedingConfidenceLevelsActivities(Long toolContentId) { + public Set getActivitiesProvidingConfidenceLevels(Long toolContentId) { ToolActivity specifiedActivity = activityDAO.getToolActivityByToolContentId(toolContentId); //if specifiedActivity is null - most likely author hasn't saved the sequence yet @@ -366,7 +368,7 @@ } Set confidenceProvidingActivityIds = new LinkedHashSet(); - findPrecedingConfidenceProvidingActivities(specifiedActivity, confidenceProvidingActivityIds); + findPrecedingAssessmentAndMcqActivities(specifiedActivity, confidenceProvidingActivityIds, true); Set confidenceProvidingActivities = new LinkedHashSet(); for (Long confidenceProvidingActivityId : confidenceProvidingActivityIds) { @@ -383,8 +385,8 @@ * them). Please note, it does not check whether enableConfidenceLevels advanced option is ON in those activities. */ @SuppressWarnings("rawtypes") - private void findPrecedingConfidenceProvidingActivities(Activity activity, - Set confidenceProvidingActivityIds) { + private void findPrecedingAssessmentAndMcqActivities(Activity activity, + Set confidenceProvidingActivityIds, boolean isMcqIncluded) { // check if current activity is Leader Select one. if so - stop searching and return it. Class activityClass = Hibernate.getClass(activity); if (activityClass.equals(ToolActivity.class)) { @@ -401,7 +403,8 @@ } String toolSignature = toolActivity.getTool().getToolSignature(); - if (TOOL_SIGNATURE_ASSESSMENT.equals(toolSignature) || TOOL_SIGNATURE_MCQ.equals(toolSignature)) { + if (TOOL_SIGNATURE_ASSESSMENT.equals(toolSignature) + || isMcqIncluded && TOOL_SIGNATURE_MCQ.equals(toolSignature)) { confidenceProvidingActivityIds.add(toolActivity.getActivityId()); } @@ -412,7 +415,7 @@ if (activityIter instanceof ToolActivity) { String toolSignatureIter = ((ToolActivity) activityIter).getTool().getToolSignature(); if (TOOL_SIGNATURE_ASSESSMENT.equals(toolSignatureIter) - || TOOL_SIGNATURE_MCQ.equals(toolSignatureIter)) { + || isMcqIncluded && TOOL_SIGNATURE_MCQ.equals(toolSignatureIter)) { confidenceProvidingActivityIds.add(activityIter.getActivityId()); } } @@ -424,18 +427,40 @@ Transition transitionTo = activity.getTransitionTo(); if (transitionTo != null) { Activity fromActivity = transitionTo.getFromActivity(); - findPrecedingConfidenceProvidingActivities(fromActivity, confidenceProvidingActivityIds); + findPrecedingAssessmentAndMcqActivities(fromActivity, confidenceProvidingActivityIds, isMcqIncluded); return; } // check parent activity Activity parent = activity.getParentActivity(); if (parent != null) { - findPrecedingConfidenceProvidingActivities(parent, confidenceProvidingActivityIds); + findPrecedingAssessmentAndMcqActivities(parent, confidenceProvidingActivityIds, isMcqIncluded); return; } } + + @Override + public Set getActivitiesProvidingVsaAnswers(Long toolContentId) { + ToolActivity specifiedActivity = activityDAO.getToolActivityByToolContentId(toolContentId); + //if specifiedActivity is null - most likely author hasn't saved the sequence yet + if (specifiedActivity == null) { + return null; + } + + Set providingVsaAnswersActivityIds = new LinkedHashSet(); + findPrecedingAssessmentAndMcqActivities(specifiedActivity, providingVsaAnswersActivityIds, false); + + Set activitiesProvidingVsaAnswers = new LinkedHashSet(); + for (Long confidenceProvidingActivityId : providingVsaAnswersActivityIds) { + ToolActivity activityProvidingVsaAnswers = (ToolActivity) activityDAO + .getActivityByActivityId(confidenceProvidingActivityId, ToolActivity.class); + activitiesProvidingVsaAnswers.add(activityProvidingVsaAnswers); + } + + return activitiesProvidingVsaAnswers; + } + @Override public List getConfidenceLevelsByActivity(Integer confidenceLevelActivityUiid, Integer requestorUserId, Long requestorToolSessionId) { @@ -458,7 +483,26 @@ return confidenceLevelDtos; } + + @Override + public Collection getVsaAnswersFromAssessment(Integer activityUiidProvidingVsaAnswers, + Integer requestorUserId, Long requestorToolSessionId) { + User user = (User) activityDAO.find(User.class, requestorUserId); + if (user == null) { + throw new ToolException("No user found for userId=" + requestorUserId); + } + ToolSession requestorSession = toolSessionDAO.getToolSession(requestorToolSessionId); + if (requestorSession == null) { + throw new ToolException("No session found for toolSessionId=" + requestorToolSessionId); + } + + Activity activityProvidingVsaAnswers = activityDAO.getActivityByUIID(activityUiidProvidingVsaAnswers, + requestorSession.getToolActivity().getLearningDesign()); + ToolSession assessmentSession = toolSessionDAO.getToolSessionByLearner(user, activityProvidingVsaAnswers); + return lamsCoreToolService.getVsaAnswersByToolSession(assessmentSession); + } + @Override public Integer getCountUsersForActivity(Long toolSessionId) { ToolSession session = toolSessionDAO.getToolSession(toolSessionId); Index: lams_tool_assessment/conf/language/lams/ApplicationResources_en_AU.properties =================================================================== diff -u -r8eefd9a2f57ce5b05eb75908e36bb042c5fe7fce -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_assessment/conf/language/lams/ApplicationResources_en_AU.properties (.../ApplicationResources_en_AU.properties) (revision 8eefd9a2f57ce5b05eb75908e36bb042c5fe7fce) +++ lams_tool_assessment/conf/language/lams/ApplicationResources_en_AU.properties (.../ApplicationResources_en_AU.properties) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -24,7 +24,7 @@ label.authoring.basic.list.header.question =Question label.authoring.basic.type.multiple.choice =Multiple choice label.authoring.basic.type.matching.pairs =Matching pairs -label.authoring.basic.type.short.answer =Short answer +label.authoring.basic.type.short.answer =Very short answers label.authoring.basic.type.numerical =Numerical label.authoring.basic.type.true.false =True/False label.authoring.basic.type.essay =Essay @@ -297,5 +297,12 @@ message.qb.modified.version =A new version of the question will be created in Question Bank message.qb.modified.new =A new question will be created in Question Bank label.import.from.question.bank =Import from question bank +label.answer.queue =Answer queue +label.drag.and.drop =drag and drop answer to tick or cross +label.correct =Correct +label.incorrect =Incorrect +label.answer.alternatives =Answer alternatives +label.close=Close + #======= End labels: Exported 337 labels for en AU ===== Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/assessmentApplicationContext.xml =================================================================== diff -u -rf9c66e78afa51f175afcaf22ee81f9b3460afea8 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/assessmentApplicationContext.xml (.../assessmentApplicationContext.xml) (revision f9c66e78afa51f175afcaf22ee81f9b3460afea8) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/assessmentApplicationContext.xml (.../assessmentApplicationContext.xml) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -138,6 +138,7 @@ PROPAGATION_REQUIRED,-java.lang.Exception PROPAGATION_REQUIRED,-java.lang.Exception PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception PROPAGATION_REQUIRED,-java.lang.Exception PROPAGATION_REQUIRED,-java.lang.Exception PROPAGATION_REQUIRED,-java.lang.Exception Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dao/AssessmentQuestionResultDAO.java =================================================================== diff -u -r9c3a64b840753192b333afb73c8fe7bdb54be638 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dao/AssessmentQuestionResultDAO.java (.../AssessmentQuestionResultDAO.java) (revision 9c3a64b840753192b333afb73c8fe7bdb54be638) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dao/AssessmentQuestionResultDAO.java (.../AssessmentQuestionResultDAO.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -37,6 +37,8 @@ List getAssessmentQuestionResultList(Long assessmentUid, Long userId, Long questionUid); AssessmentQuestionResult getAssessmentQuestionResultByUid(Long questionResultUid); + + List getQuestionResultsByQuestionUid(final Long questionUid); /** * Returns question result mark from the last finished assessment result, and null if not available. Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dao/hibernate/AssessmentQuestionResultDAOHibernate.java =================================================================== diff -u -rb41c8a8bc5134e78088378360a37f3906fadb3de -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dao/hibernate/AssessmentQuestionResultDAOHibernate.java (.../AssessmentQuestionResultDAOHibernate.java) (revision b41c8a8bc5134e78088378360a37f3906fadb3de) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dao/hibernate/AssessmentQuestionResultDAOHibernate.java (.../AssessmentQuestionResultDAOHibernate.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -42,6 +42,9 @@ + AssessmentQuestionResult.class.getName() + " AS q, " + AssessmentResult.class.getName() + " AS r " + " WHERE q.assessmentResult.uid = r.uid and r.assessment.uid = ? AND r.user.userId =? AND q.qbToolQuestion.uid =? ORDER BY r.startDate ASC"; + private static final String FIND_BY_QUESTION_UID = "FROM " + AssessmentQuestionResult.class.getName() + + " AS queRes " + " WHERE queRes.qbToolQuestion.uid =:questionUid ORDER BY queRes.finishDate ASC"; + private static final String FIND_WRONG_ANSWERS_NUMBER = "SELECT COUNT(q) FROM " + AssessmentQuestionResult.class.getName() + " AS q, " + AssessmentResult.class.getName() + " AS r " + " WHERE q.assessmentResult.uid = r.uid AND r.assessment.uid = ? AND r.user.userId =? AND q.qbToolQuestion.uid =? AND (ROUND(q.mark + q.penalty) < q.maxMark) AND (r.finishDate != null)"; @@ -77,6 +80,16 @@ } @Override + public List getQuestionResultsByQuestionUid(final Long questionUid) { + String FIND_BY_QUESTION_UID = "FROM " + AssessmentQuestionResult.class.getName() + + " AS queRes " + " WHERE queRes.qbToolQuestion.uid =:questionUid ORDER BY queRes.finishDate ASC"; + Query q = getSession().createQuery(FIND_BY_QUESTION_UID, + AssessmentQuestionResult.class); + q.setParameter("questionUid", questionUid); + return q.getResultList(); + } + + @Override public Float getQuestionResultMark(final Long assessmentUid, final Long userId, final int questionDisplayOrder) { Query q = getSession().createQuery(GET_ANSWER_MARK, Number.class); q.setParameter("assessmentUid", assessmentUid); Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dbupdates/patch20190913.sql =================================================================== diff -u --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dbupdates/patch20190913.sql (revision 0) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dbupdates/patch20190913.sql (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -0,0 +1,14 @@ +-- Turn off autocommit, so nothing is committed if there is an error +SET AUTOCOMMIT = 0; +SET FOREIGN_KEY_CHECKS=0; +----------------------Put all sql statements below here------------------------- + +-- LDEV-4875 Add VSA question type to Assessment and Scratchie +ALTER TABLE tl_lascrt11_scratchie ADD COLUMN activity_uuid_providing_vsa_answers INT(11); + +----------------------Put all sql statements above here------------------------- + +-- If there were no errors, commit and restore autocommit to on +COMMIT; +SET AUTOCOMMIT = 1; +SET FOREIGN_KEY_CHECKS=1; \ No newline at end of file Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dto/QuestionDTO.java =================================================================== diff -u -r2b3d3b2f61d37cf2fa7cccc0cf4565e5dfc4b88e -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dto/QuestionDTO.java (.../QuestionDTO.java) (revision 2b3d3b2f61d37cf2fa7cccc0cf4565e5dfc4b88e) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dto/QuestionDTO.java (.../QuestionDTO.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -61,6 +61,8 @@ private int minWordsLimit; private boolean hedgingJustificationEnabled; + + private boolean autocompleteEnabled; private boolean correctAnswersDisclosed; @@ -137,6 +139,7 @@ this.maxWordsLimit = qbQuestion.getMaxWordsLimit(); this.minWordsLimit = qbQuestion.getMinWordsLimit(); this.hedgingJustificationEnabled = qbQuestion.isHedgingJustificationEnabled(); + this.autocompleteEnabled = qbQuestion.isAutocompleteEnabled(); optionDtos = new TreeSet<>(); for (QbOption option : qbQuestion.getQbOptions()) { @@ -332,7 +335,15 @@ public void setHedgingJustificationEnabled(boolean hedgingJustificationEnabled) { this.hedgingJustificationEnabled = hedgingJustificationEnabled; } + + public boolean isAutocompleteEnabled() { + return autocompleteEnabled; + } + public void setAutocompleteEnabled(boolean autocompleteEnabled) { + this.autocompleteEnabled = autocompleteEnabled; + } + public boolean isCorrectAnswersDisclosed() { return correctAnswersDisclosed; } Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dto/QuestionSummary.java =================================================================== diff -u -r9c3a64b840753192b333afb73c8fe7bdb54be638 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dto/QuestionSummary.java (.../QuestionSummary.java) (revision 9c3a64b840753192b333afb73c8fe7bdb54be638) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dto/QuestionSummary.java (.../QuestionSummary.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -50,6 +50,11 @@ private QuestionDTO questionDto; private float averageMark; + //used only for question summary page + private List notAllocatedQuestionResults; + private boolean isTbl; + + //used only for export private List> questionResultsPerSession; public QuestionSummary(AssessmentQuestion question) { @@ -71,7 +76,23 @@ public void setAverageMark(float averageMark) { this.averageMark = averageMark; } + + public List getNotAllocatedQuestionResults() { + return notAllocatedQuestionResults; + } + public void setNotAllocatedQuestionResults(List notAllocatedQuestionResults) { + this.notAllocatedQuestionResults = notAllocatedQuestionResults; + } + + public boolean isTbl() { + return isTbl; + } + + public void setTbl(boolean isTbl) { + this.isTbl = isTbl; + } + public List> getQuestionResultsPerSession() { return questionResultsPerSession; } Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentImportContentVersionFilter.java =================================================================== diff -u -r7b01f2faaa0d72d872e4624687e4c269b8bf522a -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentImportContentVersionFilter.java (.../AssessmentImportContentVersionFilter.java) (revision 7b01f2faaa0d72d872e4624687e4c269b8bf522a) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentImportContentVersionFilter.java (.../AssessmentImportContentVersionFilter.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -186,6 +186,8 @@ "prefixAnswersWithLetters", "false", false, true); XMLUtil.rewriteTextElement(assessmentQuestion, qbQuestion, "caseSensitive", "caseSensitive", "false", false, true); + XMLUtil.rewriteTextElement(assessmentQuestion, qbQuestion, "autocompleteEnabled", + "autocompleteEnabled", "false", false, true); XMLUtil.rewriteTextElement(assessmentQuestion, qbQuestion, "correctAnswer", "correctAnswer", "false", false, true); XMLUtil.rewriteTextElement(assessmentQuestion, qbQuestion, "allowRichEditor", "allowRichEditor", Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java =================================================================== diff -u -r3004d09a72bb86597e40ef2277e1e158b6b62b0a -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java (.../AssessmentServiceImpl.java) (revision 3004d09a72bb86597e40ef2277e1e158b6b62b0a) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java (.../AssessmentServiceImpl.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -49,6 +49,7 @@ import org.apache.log4j.Logger; import org.apache.poi.ss.usermodel.IndexedColors; import org.lamsfoundation.lams.confidencelevel.ConfidenceLevelDTO; +import org.lamsfoundation.lams.confidencelevel.VsaAnswerDTO; import org.lamsfoundation.lams.contentrepository.client.IToolContentHandler; import org.lamsfoundation.lams.events.IEventNotificationService; import org.lamsfoundation.lams.learning.service.ILearnerService; @@ -103,6 +104,7 @@ import org.lamsfoundation.lams.tool.assessment.util.SequencableComparator; import org.lamsfoundation.lams.tool.exception.DataMissingException; import org.lamsfoundation.lams.tool.exception.ToolException; +import org.lamsfoundation.lams.tool.service.ICommonAssessmentService; import org.lamsfoundation.lams.tool.service.ILamsToolService; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; @@ -111,6 +113,7 @@ 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; @@ -120,8 +123,8 @@ /** * @author Andrey Balan */ -public class AssessmentServiceImpl - implements IAssessmentService, ToolContentManager, ToolSessionManager, ToolRestManager { +public class AssessmentServiceImpl implements IAssessmentService, ICommonAssessmentService, ToolContentManager, + ToolSessionManager, ToolRestManager { private static Logger log = Logger.getLogger(AssessmentServiceImpl.class.getName()); private AssessmentDAO assessmentDao; @@ -743,7 +746,7 @@ } } - } else if (questionDto.getType() == QbQuestion.TYPE_SHORT_ANSWER) { + } else if (questionDto.getType() == QbQuestion.TYPE_VERY_SHORT_ANSWERS) { //clear previous answer questionResult.setQbOption(null); @@ -1315,11 +1318,133 @@ @Override public QuestionSummary getQuestionSummary(Long contentId, Long questionUid) { AssessmentQuestion question = assessmentQuestionDao.getByUid(questionUid); + QbQuestion qbQuestion = question.getQbQuestion(); + List allQuestionResults = assessmentQuestionResultDao + .getQuestionResultsByQuestionUid(questionUid); - return new QuestionSummary(question); + QuestionSummary questionSummary = new QuestionSummary(question); + + //prepare extra data for VSA type of questions, so teachers can allocate answers into groups + if (question.getType() == QbQuestion.TYPE_VERY_SHORT_ANSWERS) { + //find all questionResults that are not allocated into groups yet + List notAllocatedQuestionResults = new ArrayList<>(); + for (AssessmentQuestionResult questionResult : allQuestionResults) { + String answer = questionResult.getAnswer(); + + boolean isAnswerAllocated = false; + for (QbOption option : qbQuestion.getQbOptions()) { + String[] alternatives = option.getName().split("\r\n"); + for (String alternative : alternatives) { + if (answer != null && alternative.equals(answer)) { + isAnswerAllocated = true; + break; + } + } + } + + if (!isAnswerAllocated) { + notAllocatedQuestionResults.add(questionResult); + } + } + 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(); + questionSummary.setTbl(isCompatibleWithTbl); + } + + return questionSummary; } @Override + public void allocateAnswerToOption(Long questionUid, Long targetOptionUid, Long previousOptionUid, + Long questionResultUid) { + AssessmentQuestion question = assessmentQuestionDao.getByUid(questionUid); + QbQuestion qbQuestion = question.getQbQuestion(); + AssessmentQuestionResult questionResult = assessmentQuestionResultDao.getAssessmentQuestionResultByUid(questionResultUid); + String answer = questionResult.getAnswer(); + + //adding + if (previousOptionUid.equals(-1L)) { + for (QbOption targetOption : qbQuestion.getQbOptions()) { + if (targetOption.getUid().equals(targetOptionUid)) { + String name = targetOption.getName(); + name += "\r\n" + answer; + targetOption.setName(name); + assessmentDao.saveObject(targetOption); + break; + } + } + + } + //removing + else if (targetOptionUid.equals(-1L)) { + 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)) { + nameWithoutUserAnswer += alternative + "\r\n"; + } + } + if (nameWithoutUserAnswer.length() > 2) { + previousOption.setName(nameWithoutUserAnswer.substring(0, nameWithoutUserAnswer.length() - 2)); + assessmentDao.saveObject(previousOption); + } + break; + } + } + + } + //reshuffling inside the same container - do nothing + else if (targetOptionUid.equals(previousOptionUid)) { + + } + //moving from one to another + else { + for (QbOption targetOption : qbQuestion.getQbOptions()) { + if (targetOption.getUid().equals(targetOptionUid)) { + String name = targetOption.getName(); + name += "\r\n" + answer; + targetOption.setName(name); + assessmentDao.saveObject(targetOption); + 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)) { + nameWithoutUserAnswer += alternative + "\r\n"; + } + } + if (nameWithoutUserAnswer.length() > 2) { + nameWithoutUserAnswer = nameWithoutUserAnswer.substring(0, nameWithoutUserAnswer.length() - 2); + } + previousOption.setName(nameWithoutUserAnswer); + assessmentDao.saveObject(previousOption); + break; + } + } + } + + //recalculate marks for all lessons in all cases except for reshuffling inside the same container + if (!targetOptionUid.equals(previousOptionUid)) { + //TODO + //recalculateUserAnswers(assessmentUid, toolContentId, oldQuestions, newQuestions, oldReferences, newReferences); + + } + } + + @Override public Map getQuestionSummaryForExport(Assessment assessment) { Map questionSummaries = new LinkedHashMap<>(); @@ -1599,7 +1724,7 @@ // set up the summary table data for the top of the question area. boolean doSummaryTable = question.getType() == QbQuestion.TYPE_MULTIPLE_CHOICE - || question.getType() == QbQuestion.TYPE_SHORT_ANSWER + || question.getType() == QbQuestion.TYPE_VERY_SHORT_ANSWERS || question.getType() == QbQuestion.TYPE_NUMERICAL || question.getType() == QbQuestion.TYPE_TRUE_FALSE; // For MC, Numeric & Short Answer Key is optionUid, Value is number of answers @@ -1959,7 +2084,7 @@ Long trueKey, Long falseKey) { ExcelCell[] summaryTable; int i = 0; - if (question.getType() == QbQuestion.TYPE_MULTIPLE_CHOICE || question.getType() == QbQuestion.TYPE_SHORT_ANSWER + 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]; @@ -2015,7 +2140,7 @@ if (!foundOption) { summaryNACount++; } - } else if (question.getType() == QbQuestion.TYPE_SHORT_ANSWER + } else if (question.getType() == QbQuestion.TYPE_VERY_SHORT_ANSWERS || question.getType() == QbQuestion.TYPE_NUMERICAL) { Long submittedOptionUid = questionResult.getQbOption() == null ? null : questionResult.getQbOption().getUid(); @@ -2057,7 +2182,7 @@ total += value; } int i = 0; - if (question.getType() == QbQuestion.TYPE_MULTIPLE_CHOICE || question.getType() == QbQuestion.TYPE_SHORT_ANSWER + 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); @@ -2092,7 +2217,7 @@ return "Numerical"; case QbQuestion.TYPE_ORDERING: return "Ordering"; - case QbQuestion.TYPE_SHORT_ANSWER: + case QbQuestion.TYPE_VERY_SHORT_ANSWERS: return "Short Answer"; case QbQuestion.TYPE_TRUE_FALSE: return "True/False"; @@ -2196,7 +2321,7 @@ if (oldOption.getDisplayOrder() == newOption.getDisplayOrder()) { //short answer - if (((oldQuestion.getType() == QbQuestion.TYPE_SHORT_ANSWER) + if (((oldQuestion.getType() == QbQuestion.TYPE_VERY_SHORT_ANSWERS) && !StringUtils.equals(oldOption.getName(), newOption.getName())) //numbering || (oldOption.getNumericalOption() != newOption.getNumericalOption()) @@ -2884,7 +3009,7 @@ } else if (qbQuestion.getType() == QbQuestion.TYPE_MATCHING_PAIRS) { - } else if (qbQuestion.getType() == QbQuestion.TYPE_SHORT_ANSWER) { + } else if (qbQuestion.getType() == QbQuestion.TYPE_VERY_SHORT_ANSWERS) { answers.add(questionResult.getAnswer()); } else if (qbQuestion.getType() == QbQuestion.TYPE_NUMERICAL) { @@ -2934,7 +3059,79 @@ return confidenceLevelDtos; } + + @Override + public Collection getVsaAnswers(Long toolSessionId) { + if (toolSessionId == null) { + return new ArrayList<>(); + } + + Map uid_answerToVsaAnswerDtoMap = new LinkedHashMap<>(); + Assessment assessment = getAssessmentBySessionId(toolSessionId); + //in case Assessment is leader aware return all leaders confidences, otherwise - confidences from the users from the same group as requestor + List assessmentResultsAndPortraits = assessment.isUseSelectLeaderToolOuput() + ? assessmentResultDao.getLeadersLastFinishedAssessmentResults(assessment.getContentId()) + : assessmentResultDao.getLastFinishedAssessmentResultsBySession(toolSessionId); + + for (Object[] assessmentResultsAndPortraitIter : assessmentResultsAndPortraits) { + AssessmentResult assessmentResult = (AssessmentResult) assessmentResultsAndPortraitIter[0]; + Long portraitUuid = assessmentResultsAndPortraitIter[1] == null ? null + : ((Number) assessmentResultsAndPortraitIter[1]).longValue(); + AssessmentUser user = assessmentResult.getUser(); + + //fill in question's and user answer's hashes + for (AssessmentQuestionResult questionResult : assessmentResult.getQuestionResults()) { + QbQuestion qbQuestion = questionResult.getQbQuestion(); + + 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()) { + if (optionAnswer.getAnswerBoolean() + && (optionAnswer.getOptionUid().equals(option.getUid()))) { + Long optionUid = option.getUid(); + vsaAnswerDTO.setQbOptionUid(optionUid); + break; + } + } + } + } + + ConfidenceLevelDTO confidenceLevelDto = new ConfidenceLevelDTO(); + confidenceLevelDto.setUserId(user.getUserId().intValue()); + String userName = StringUtils.isBlank(user.getFirstName()) + && StringUtils.isBlank(user.getLastName()) ? user.getLoginName() + : user.getFirstName() + " " + user.getLastName(); + confidenceLevelDto.setUserName(userName); + confidenceLevelDto.setPortraitUuid(portraitUuid); + confidenceLevelDto.setLevel(questionResult.getConfidenceLevel()); + + vsaAnswerDTO.getConfidenceLevels().add(confidenceLevelDto); + } + } + + } + + return uid_answerToVsaAnswerDtoMap.values(); + } + @Override public void forceCompleteUser(Long toolSessionId, User user) { Long userId = user.getUserId().longValue(); Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/IAssessmentService.java =================================================================== diff -u -r3004d09a72bb86597e40ef2277e1e158b6b62b0a -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/IAssessmentService.java (.../IAssessmentService.java) (revision 3004d09a72bb86597e40ef2277e1e158b6b62b0a) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/IAssessmentService.java (.../IAssessmentService.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -29,11 +29,7 @@ import java.util.Map; import java.util.Set; -import org.lamsfoundation.lams.confidencelevel.ConfidenceLevelDTO; import org.lamsfoundation.lams.notebook.model.NotebookEntry; -import org.lamsfoundation.lams.qb.model.QbOption; -import org.lamsfoundation.lams.qb.model.QbQuestion; -import org.lamsfoundation.lams.qb.model.QbQuestionUnit; import org.lamsfoundation.lams.tool.assessment.dto.AssessmentResultDTO; import org.lamsfoundation.lams.tool.assessment.dto.AssessmentUserDTO; import org.lamsfoundation.lams.tool.assessment.dto.LeaderResultsDTO; @@ -53,9 +49,9 @@ import org.lamsfoundation.lams.util.ExcelCell; /** + * Interface that defines the contract that all ShareAssessment service provider must follow. + * * @author Andrey Balan - * - * Interface that defines the contract that all ShareAssessment service provider must follow. */ public interface IAssessmentService extends ICommonToolService { @@ -87,8 +83,6 @@ void copyAnswersFromLeader(AssessmentUser user, AssessmentUser leader) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException; - List getConfidenceLevels(Long toolSessionId); - /** * Stores date when user has started activity with time limit. * @@ -430,6 +424,9 @@ * @return */ QuestionSummary getQuestionSummary(Long contentId, Long questionUid); + + void allocateAnswerToOption(Long questionUid, Long targetOptionUid, Long previousOptionUid, + Long questionResultUid); /** * For export purposes Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/util/AssessmentEscapeUtils.java =================================================================== diff -u -r2b3d3b2f61d37cf2fa7cccc0cf4565e5dfc4b88e -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/util/AssessmentEscapeUtils.java (.../AssessmentEscapeUtils.java) (revision 2b3d3b2f61d37cf2fa7cccc0cf4565e5dfc4b88e) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/util/AssessmentEscapeUtils.java (.../AssessmentEscapeUtils.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -159,7 +159,7 @@ break; case QbQuestion.TYPE_NUMERICAL: - case QbQuestion.TYPE_SHORT_ANSWER: + case QbQuestion.TYPE_VERY_SHORT_ANSWERS: case QbQuestion.TYPE_ESSAY: responseStr.append(questionResult.getAnswer()); break; @@ -243,7 +243,7 @@ return questionResult.getAnswer(); case QbQuestion.TYPE_ORDERING: return AssessmentEscapeUtils.getOptionResponse(questionResult, QbQuestion.TYPE_ORDERING); - case QbQuestion.TYPE_SHORT_ANSWER: + case QbQuestion.TYPE_VERY_SHORT_ANSWERS: return questionResult.getAnswer(); case QbQuestion.TYPE_TRUE_FALSE: return questionResult.getAnswerBoolean(); Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/controller/LearningController.java =================================================================== diff -u -r3004d09a72bb86597e40ef2277e1e158b6b62b0a -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/controller/LearningController.java (.../LearningController.java) (revision 3004d09a72bb86597e40ef2277e1e158b6b62b0a) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/controller/LearningController.java (.../LearningController.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -40,6 +40,7 @@ import java.util.SortedSet; import java.util.TimeZone; import java.util.TreeSet; +import java.util.regex.Pattern; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -49,6 +50,8 @@ import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.outcome.Outcome; +import org.lamsfoundation.lams.qb.model.QbOption; import org.lamsfoundation.lams.qb.model.QbQuestion; import org.lamsfoundation.lams.tool.ToolAccessMode; import org.lamsfoundation.lams.tool.assessment.AssessmentConstants; @@ -70,6 +73,8 @@ import org.lamsfoundation.lams.tool.assessment.web.form.ReflectionForm; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; import org.lamsfoundation.lams.util.AlphanumComparator; +import org.lamsfoundation.lams.util.Configuration; +import org.lamsfoundation.lams.util.ConfigurationKeys; import org.lamsfoundation.lams.util.DateUtil; import org.lamsfoundation.lams.util.ValidationUtil; import org.lamsfoundation.lams.util.WebUtil; @@ -85,6 +90,7 @@ import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; +import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -698,7 +704,40 @@ service.launchTimeLimit(assessmentUid, userId); } + + @RequestMapping("/vsaAutocomplete") + @ResponseBody + public String vsaAutocomplete(HttpServletRequest request, HttpServletResponse response) { + String userAnswer = WebUtil.readStrParam(request, "term", true); + Long questionUid = WebUtil.readLongParam(request, AssessmentConstants.PARAM_QUESTION_UID); + AssessmentQuestion question = service.getAssessmentQuestionByUid(questionUid); + QbQuestion qbQuestion = question.getQbQuestion(); + + ArrayNode responseJSON = JsonNodeFactory.instance.arrayNode(); + if (StringUtils.isNotBlank(userAnswer)) { + userAnswer = userAnswer.trim(); + userAnswer = qbQuestion.isCaseSensitive() ? userAnswer : userAnswer.toLowerCase(); + + for (QbOption option : qbQuestion.getQbOptions()) { + //filter out options not starting with 'term' and containing '*' + String optionTitle = qbQuestion.isCaseSensitive() ? option.getName() : option.getName().toLowerCase(); + int i = 0; + for (String optionAnswer : optionTitle.split("\\r\\n")) { + if (optionAnswer.startsWith(userAnswer) && !optionAnswer.contains("*")) { + ObjectNode optionJSON = JsonNodeFactory.instance.objectNode(); + String originalOptionAnswer = option.getName().split("\\r\\n")[i]; + optionJSON.put("label", originalOptionAnswer); + responseJSON.add(optionJSON); + } + i++; + } + } + } + response.setContentType("application/json;charset=utf-8"); + return responseJSON.toString(); + } + /** * Display empty reflection form. */ @@ -813,7 +852,7 @@ optionDto.setAnswerInt(answerInt); } - } else if (questionType == QbQuestion.TYPE_SHORT_ANSWER) { + } else if (questionType == QbQuestion.TYPE_VERY_SHORT_ANSWERS) { String answer = request.getParameter(AssessmentConstants.ATTR_QUESTION_PREFIX + i); questionDto.setAnswer(answer); @@ -913,7 +952,7 @@ isAnswered |= optionDto.getAnswerInt() != 0; } - } else if ((questionType == QbQuestion.TYPE_SHORT_ANSWER) + } else if ((questionType == QbQuestion.TYPE_VERY_SHORT_ANSWERS) || (questionType == QbQuestion.TYPE_NUMERICAL) || (questionType == QbQuestion.TYPE_TRUE_FALSE) || (questionType == QbQuestion.TYPE_ESSAY)) { @@ -1013,7 +1052,7 @@ } // required for showing right/wrong answers icons on results page correctly - if ((questionDto.getType() == QbQuestion.TYPE_SHORT_ANSWER + if ((questionDto.getType() == QbQuestion.TYPE_VERY_SHORT_ANSWERS || questionDto.getType() == QbQuestion.TYPE_NUMERICAL) && questionResult.getQbOption() != null) { boolean isAnsweredCorrectly = false; Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/controller/MonitoringController.java =================================================================== diff -u -r4dfbbc90e3d414eaf3f4282a3a38b4ec741384d7 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/controller/MonitoringController.java (.../MonitoringController.java) (revision 4dfbbc90e3d414eaf3f4282a3a38b4ec741384d7) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/controller/MonitoringController.java (.../MonitoringController.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -73,9 +73,12 @@ import org.lamsfoundation.lams.web.util.SessionMap; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.util.HtmlUtils; import com.fasterxml.jackson.databind.node.ArrayNode; @@ -188,6 +191,14 @@ request.setAttribute(AssessmentConstants.ATTR_QUESTION_SUMMARY, questionSummary); return "pages/monitoring/parts/questionsummary"; } + + @RequestMapping("/allocateUserAnswer") + @ResponseStatus(HttpStatus.OK) + public void allocateUserAnswer(HttpServletRequest request, HttpServletResponse response, + @RequestParam Long questionUid, @RequestParam Long targetOptionUid, @RequestParam Long previousOptionUid, + @RequestParam Long questionResultUid) { + service.allocateAnswerToOption(questionUid, targetOptionUid, previousOptionUid, questionResultUid); + } @RequestMapping("/userSummary") public String userSummary(HttpServletRequest request, HttpServletResponse response) { Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/controller/TblMonitoringController.java =================================================================== diff -u -r9c3a64b840753192b333afb73c8fe7bdb54be638 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/controller/TblMonitoringController.java (.../TblMonitoringController.java) (revision 9c3a64b840753192b333afb73c8fe7bdb54be638) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/controller/TblMonitoringController.java (.../TblMonitoringController.java) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -250,7 +250,7 @@ return sb.toString(); case QbQuestion.TYPE_MULTIPLE_CHOICE: - case QbQuestion.TYPE_SHORT_ANSWER: + case QbQuestion.TYPE_VERY_SHORT_ANSWERS: for (OptionDTO optionDto : questionDto.getOptionDtos()) { if (optionDto.getMaxMark() == 1f) { return optionDto.getName(); Index: lams_tool_assessment/web/pages/learning/learning.jsp =================================================================== diff -u -r394f403c289f0fd7808c228840bead5c4e7d5d32 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_assessment/web/pages/learning/learning.jsp (.../learning.jsp) (revision 394f403c289f0fd7808c228840bead5c4e7d5d32) +++ lams_tool_assessment/web/pages/learning/learning.jsp (.../learning.jsp) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -1,35 +1,35 @@ <%@ include file="/common/taglibs.jsp"%> +<%-- param has higher level for request attribute --%> + + + + + + + + + + + + + + + + <fmt:message key="label.learning.title" /> <%@ include file="/common/header.jsp"%> - - <%-- param has higher level for request attribute --%> - - - - - - - - - - - - - - - - - + + @@ -88,7 +88,15 @@ }); }); } - + + //autocomplete for VSA + $('.ui-autocomplete-input').each(function(){ + $(this).autocomplete({ + 'source' : '?questionUid=' + $(this).data("question-uid"), + 'delay' : 500, + 'minLength' : 3 + }); + }); }); function countHedgeQuestionSelectTotal(questionIndex) { Index: lams_tool_assessment/web/pages/learning/parts/allquestions.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_assessment/web/pages/learning/parts/allquestions.jsp (.../allquestions.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_assessment/web/pages/learning/parts/allquestions.jsp (.../allquestions.jsp) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -35,7 +35,7 @@ <%@ include file="matchingpairs.jsp"%> - <%@ include file="shortanswer.jsp"%> + <%@ include file="vsa.jsp"%> <%@ include file="numerical.jsp"%> Fisheye: Tag e8a7110708b15579af2c6b31ac52a6da427fef6d refers to a dead (removed) revision in file `lams_tool_assessment/web/pages/learning/parts/shortanswer.jsp'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_assessment/web/pages/learning/parts/vsa.jsp =================================================================== diff -u --- lams_tool_assessment/web/pages/learning/parts/vsa.jsp (revision 0) +++ lams_tool_assessment/web/pages/learning/parts/vsa.jsp (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -0,0 +1,19 @@ +<%@ include file="/common/taglibs.jsp"%> + +
+ +
+ +
+
+ + + +
+ ui-autocomplete-input" + value="" data-question-uid="${question.uid}" + disabled="disabled" + /> +
+
Index: lams_tool_assessment/web/pages/learning/results/allquestions.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_assessment/web/pages/learning/results/allquestions.jsp (.../allquestions.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_assessment/web/pages/learning/results/allquestions.jsp (.../allquestions.jsp) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -32,7 +32,7 @@ <%@ include file="matchingpairs.jsp"%> - <%@ include file="shortanswer.jsp"%> + <%@ include file="vsa.jsp"%> <%@ include file="numerical.jsp"%> Fisheye: Tag e8a7110708b15579af2c6b31ac52a6da427fef6d refers to a dead (removed) revision in file `lams_tool_assessment/web/pages/learning/results/shortanswer.jsp'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_assessment/web/pages/learning/results/vsa.jsp =================================================================== diff -u --- lams_tool_assessment/web/pages/learning/results/vsa.jsp (revision 0) +++ lams_tool_assessment/web/pages/learning/results/vsa.jsp (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -0,0 +1,33 @@ +<%@ include file="/common/taglibs.jsp"%> + +
+ +
+ +
+ + + + + + +
+ + + + + + + + +
+
+ + + + + Index: lams_tool_assessment/web/pages/monitoring/parts/questionsummary.jsp =================================================================== diff -u -r394f403c289f0fd7808c228840bead5c4e7d5d32 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_assessment/web/pages/monitoring/parts/questionsummary.jsp (.../questionsummary.jsp) (revision 394f403c289f0fd7808c228840bead5c4e7d5d32) +++ lams_tool_assessment/web/pages/monitoring/parts/questionsummary.jsp (.../questionsummary.jsp) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -1,22 +1,29 @@ <%@ include file="/common/taglibs.jsp"%> + + + +<% pageContext.setAttribute("newLineChar", "\r\n"); %> <%@ include file="/common/header.jsp"%> - - - - - + + + + + + + + + + +
+ + <%@ include file="addItemFooter.jsp"%> + + + Index: lams_tool_scratchie/web/pages/authoring/parts/addVsa.jsp =================================================================== diff -u --- lams_tool_scratchie/web/pages/authoring/parts/addVsa.jsp (revision 0) +++ lams_tool_scratchie/web/pages/authoring/parts/addVsa.jsp (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -0,0 +1,237 @@ + +<%@ include file="/common/taglibs.jsp"%> + + + + + + <%@ include file="/common/header.jsp"%> + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + + + + + + + + + +
+ +
+ + + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+
+ +
+
+ + + +
+ +
+ + +
+ +
+ + +
+ + + + +
+
+ +
+ + +
+ +
+ + +
+
+ +
+ + +
+
+
+ + + +
+ + + + + +
+ + + +
+ + + + + + + + + + + + + +
+ ${OPTION_LABEL} +
+ + + +
+ + +
+
+
+
+
+
+
+
+ +
+
+ + <%@ include file="addItemFooter.jsp"%> + +
Fisheye: Tag e8a7110708b15579af2c6b31ac52a6da427fef6d refers to a dead (removed) revision in file `lams_tool_scratchie/web/pages/authoring/parts/additem.jsp'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_scratchie/web/pages/authoring/parts/itemlist.jsp =================================================================== diff -u -r06d090eefddaafa108bcd8614d47d3d92f946210 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_scratchie/web/pages/authoring/parts/itemlist.jsp (.../itemlist.jsp) (revision 06d090eefddaafa108bcd8614d47d3d92f946210) +++ lams_tool_scratchie/web/pages/authoring/parts/itemlist.jsp (.../itemlist.jsp) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -39,7 +39,18 @@ v. ${item.qbQuestion.version} - + + + + + + + + + + + + Index: lams_tool_scratchie/web/pages/authoring/parts/optionlist.jsp =================================================================== diff -u -r06d090eefddaafa108bcd8614d47d3d92f946210 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_scratchie/web/pages/authoring/parts/optionlist.jsp (.../optionlist.jsp) (revision 06d090eefddaafa108bcd8614d47d3d92f946210) +++ lams_tool_scratchie/web/pages/authoring/parts/optionlist.jsp (.../optionlist.jsp) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -7,13 +7,13 @@ - + &#${status.index + 65};) - + Index: lams_tool_scratchie/web/pages/learning/learning.jsp =================================================================== diff -u -r394f403c289f0fd7808c228840bead5c4e7d5d32 -re8a7110708b15579af2c6b31ac52a6da427fef6d --- lams_tool_scratchie/web/pages/learning/learning.jsp (.../learning.jsp) (revision 394f403c289f0fd7808c228840bead5c4e7d5d32) +++ lams_tool_scratchie/web/pages/learning/learning.jsp (.../learning.jsp) (revision e8a7110708b15579af2c6b31ac52a6da427fef6d) @@ -1,15 +1,11 @@ - <%@ include file="/common/taglibs.jsp"%> - - <%-- param has higher level for request attribute --%> - @@ -18,21 +14,21 @@ <fmt:message key="label.learning.title" /> - + + - +