Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/model/AssessmentQuestionResult.java =================================================================== diff -u -r7f09ca6e27d33ac2afa5859c4b482178657748c4 -rff6537798655584102f5dba4dd2fc293f7186118 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/model/AssessmentQuestionResult.java (.../AssessmentQuestionResult.java) (revision 7f09ca6e27d33ac2afa5859c4b482178657748c4) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/model/AssessmentQuestionResult.java (.../AssessmentQuestionResult.java) (revision ff6537798655584102f5dba4dd2fc293f7186118) @@ -94,6 +94,8 @@ private String answerEscaped; @Transient private QuestionDTO questionDto; + @Transient + private boolean answerModified; public QbQuestion getQbQuestion() { return qbToolQuestion.getQbQuestion(); @@ -224,4 +226,12 @@ public void setQuestionDto(QuestionDTO questionDto) { this.questionDto = questionDto; } + + public boolean isAnswerModified() { + return answerModified; + } + + public void setAnswerModified(boolean answerModified) { + this.answerModified = answerModified; + } } \ No newline at end of file Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java =================================================================== diff -u -r5a579db63172ae32b83984fb7cde499217bbcdd4 -rff6537798655584102f5dba4dd2fc293f7186118 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java (.../AssessmentServiceImpl.java) (revision 5a579db63172ae32b83984fb7cde499217bbcdd4) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java (.../AssessmentServiceImpl.java) (revision ff6537798655584102f5dba4dd2fc293f7186118) @@ -38,6 +38,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; @@ -646,10 +647,12 @@ return false; } + boolean isAnswerModified = false; // store all answers (in all pages) for (Set questionsForOnePage : pagedQuestions) { for (QuestionDTO questionDto : questionsForOnePage) { - storeUserAnswer(result, questionDto); + AssessmentQuestionResult questionResult = storeUserAnswer(result, questionDto); + isAnswerModified |= questionResult.isAnswerModified(); } } @@ -680,9 +683,23 @@ result.setMaximumGrade(maximumGrade); result.setGrade(grade); - if (!isAutosave) { + + if (isAutosave) { + if (isAnswerModified && assessment.isUseSelectLeaderToolOuput()) { + AssessmentSession session = getSessionBySessionId(result.getSessionId()); + Long leaderUid = session.getGroupLeader() == null ? null : session.getGroupLeader().getUid(); + Set userIds = session.getAssessmentUsers().stream().filter(u -> !u.getUid().equals(leaderUid)) + .collect(Collectors.mapping(assessmentUser -> assessmentUser.getUserId().intValue(), + Collectors.toSet())); + + ObjectNode jsonCommand = JsonNodeFactory.instance.objectNode(); + jsonCommand.put("hookTrigger", "assessment-leader-triggered-refresh-" + result.getSessionId()); + learnerService.createCommandForLearners(assessment.getContentId(), userIds, jsonCommand.toString()); + } + } else { result.setFinishDate(new Timestamp(new Date().getTime())); } + assessmentResultDao.update(result); return true; @@ -700,16 +717,25 @@ for (AssessmentQuestionResult questionResultIter : assessmentResult.getQuestionResults()) { if (questionDto.getUid().equals(questionResultIter.getQbToolQuestion().getUid())) { questionResult = questionResultIter; + break; } } + boolean isAnswerModified = false; + //if teacher modified question in monitor - update questionDto now if (assessment.isContentModifiedInMonitor(assessmentResult.getStartDate())) { AssessmentQuestion modifiedQuestion = assessmentQuestionDao.getByUid(questionDto.getUid()); QuestionDTO updatedQuestionDto = modifiedQuestion.getQuestionDTO(); PropertyUtils.copyProperties(questionDto, updatedQuestionDto); + + isAnswerModified = true; } + isAnswerModified |= !Objects.equals(questionResult.getAnswerBoolean(), questionDto.getAnswerBoolean()) + || !Objects.equals(questionResult.getAnswerFloat(), questionDto.getAnswerFloat()) + || !Objects.equals(questionResult.getAnswer(), questionDto.getAnswer()); + // store question answer values questionResult.setAnswerBoolean(questionDto.getAnswerBoolean()); questionResult.setAnswerFloat(questionDto.getAnswerFloat()); @@ -722,28 +748,38 @@ for (AssessmentOptionAnswer optionAnswerIter : questionResult.getOptionAnswers()) { if (optionDto.getUid().equals(optionAnswerIter.getOptionUid())) { optionAnswer = optionAnswerIter; + break; } } // store option answer values + isAnswerModified |= !Objects.equals(optionAnswer.getAnswerBoolean(), optionDto.getAnswerBoolean()); + optionAnswer.setAnswerBoolean(optionDto.getAnswerBoolean()); - optionAnswer.setAnswerInt(optionDto.getAnswerInt()); if (questionDto.getType() == QbQuestion.TYPE_ORDERING) { + isAnswerModified |= !Objects.equals(optionAnswer.getAnswerInt(), optionDto.getDisplayOrder()); optionAnswer.setAnswerInt(optionDto.getDisplayOrder()); + } else { + isAnswerModified |= !Objects.equals(optionAnswer.getAnswerInt(), optionDto.getAnswerInt()); + optionAnswer.setAnswerInt(optionDto.getAnswerInt()); } } // store confidence levels entered by the learner if (assessment.isEnableConfidenceLevels()) { + isAnswerModified |= !Objects.equals(questionResult.getConfidenceLevel(), questionDto.getConfidenceLevel()); questionResult.setConfidenceLevel(questionDto.getConfidenceLevel()); } // store justification entered by the learner if (assessment.isAllowAnswerJustification() || (questionDto.getType().equals(QbQuestion.TYPE_MARK_HEDGING) && questionDto.isHedgingJustificationEnabled())) { + isAnswerModified |= !Objects.equals(questionResult.getJustification(), questionDto.getJustification()); questionResult.setJustification(questionDto.getJustification()); } + questionResult.setAnswerModified(isAnswerModified); + ; return questionResult; } @@ -4024,7 +4060,7 @@ Collectors.mapping(assessmentUser -> assessmentUser.getUserId().intValue(), Collectors.toSet())); ObjectNode jsonCommand = JsonNodeFactory.instance.objectNode(); - jsonCommand.put("hookTrigger", "assessment-leader-change-refresh-" + toolSessionId); + jsonCommand.put("hookTrigger", "assessment-leader-triggered-refresh-" + toolSessionId); learnerService.createCommandForLearners(assessment.getContentId(), userIds, jsonCommand.toString()); } } \ No newline at end of file Index: lams_tool_assessment/web/pages/learning/learning.jsp =================================================================== diff -u -r0f91c5ccc4cb27ccd6afa12a7be94f071247c99f -rff6537798655584102f5dba4dd2fc293f7186118 --- lams_tool_assessment/web/pages/learning/learning.jsp (.../learning.jsp) (revision 0f91c5ccc4cb27ccd6afa12a7be94f071247c99f) +++ lams_tool_assessment/web/pages/learning/learning.jsp (.../learning.jsp) (revision ff6537798655584102f5dba4dd2fc293f7186118) @@ -164,7 +164,7 @@ // command websocket stuff for refreshing // trigger is an unique ID of page and action that command websocket code in Page.tag recognises - commandWebsocketHookTrigger = 'assessment-leader-change-refresh-${toolSessionID}'; + commandWebsocketHookTrigger = 'assessment-leader-triggered-refresh-${toolSessionID}'; // if the trigger is recognised, the following action occurs commandWebsocketHook = function() { location.reload();