Index: lams_central/src/java/org/lamsfoundation/lams/web/qb/VsaController.java =================================================================== diff -u -r3085af1c7e3e6c3496af23a748d998886d7168fd -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_central/src/java/org/lamsfoundation/lams/web/qb/VsaController.java (.../VsaController.java) (revision 3085af1c7e3e6c3496af23a748d998886d7168fd) +++ lams_central/src/java/org/lamsfoundation/lams/web/qb/VsaController.java (.../VsaController.java) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -1,8 +1,11 @@ package org.lamsfoundation.lams.web.qb; +import java.util.Map; + import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; +import org.lamsfoundation.lams.qb.model.QbToolQuestion; import org.lamsfoundation.lams.qb.service.IQbService; import org.lamsfoundation.lams.tool.service.ILamsToolService; import org.lamsfoundation.lams.web.util.AttributeNames; @@ -30,8 +33,11 @@ @RequestMapping("/displayVsaAllocate") public String displayVsaAllocate(@RequestParam(name = AttributeNames.PARAM_TOOL_CONTENT_ID) long toolContentId, Model model) { - - model.addAttribute("questions", toolService.getUnallocatedVSAnswers(toolContentId)); + + // the mapping is tool question -> unallocated answer -> user ID + Map> toolQuestionToUnallocatedAnswersMap = toolService + .getUnallocatedVSAnswers(toolContentId); + model.addAttribute("toolQuestions", toolQuestionToUnallocatedAnswersMap); return "qb/vsa/vsaAllocate"; } Index: lams_central/web/qb/vsa/vsaAllocate.jsp =================================================================== diff -u -r3085af1c7e3e6c3496af23a748d998886d7168fd -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_central/web/qb/vsa/vsaAllocate.jsp (.../vsaAllocate.jsp) (revision 3085af1c7e3e6c3496af23a748d998886d7168fd) +++ lams_central/web/qb/vsa/vsaAllocate.jsp (.../vsaAllocate.jsp) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -57,9 +57,9 @@

- - - + + + <%@ include file="vsaQuestionAllocate.jsp"%> Index: lams_central/web/qb/vsa/vsaQuestionAllocate.jsp =================================================================== diff -u -r3085af1c7e3e6c3496af23a748d998886d7168fd -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_central/web/qb/vsa/vsaQuestionAllocate.jsp (.../vsaQuestionAllocate.jsp) (revision 3085af1c7e3e6c3496af23a748d998886d7168fd) +++ lams_central/web/qb/vsa/vsaQuestionAllocate.jsp (.../vsaQuestionAllocate.jsp) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -2,7 +2,7 @@ <%@ include file="/common/taglibs.jsp"%> - + @@ -41,13 +41,13 @@
:
@@ -61,16 +61,24 @@

- +

+ id="answer-queue${toolQuestion.uid}">
- + + +
+
+ + + +
+ ${answer.key}
@@ -94,13 +102,13 @@
:
@@ -123,13 +131,13 @@ : ${option.maxMark} -
:
Index: lams_common/src/java/org/lamsfoundation/lams/qb/QbUtils.java =================================================================== diff -u -r3085af1c7e3e6c3496af23a748d998886d7168fd -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_common/src/java/org/lamsfoundation/lams/qb/QbUtils.java (.../QbUtils.java) (revision 3085af1c7e3e6c3496af23a748d998886d7168fd) +++ lams_common/src/java/org/lamsfoundation/lams/qb/QbUtils.java (.../QbUtils.java) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -13,6 +13,7 @@ import org.apache.commons.lang.StringUtils; import org.lamsfoundation.lams.qb.form.QbQuestionForm; import org.lamsfoundation.lams.qb.model.QbCollection; +import org.lamsfoundation.lams.qb.model.QbOption; import org.lamsfoundation.lams.qb.model.QbQuestion; import org.lamsfoundation.lams.qb.service.IQbService; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; @@ -107,6 +108,38 @@ .anyMatch(s -> isCaseSensitive ? s.equals(answer) : s.equalsIgnoreCase(answer)); } + public static boolean isVSAnswerAllocated(QbQuestion qbQuestion, String answer, Set notAllocatedAnswers) { + if (StringUtils.isBlank(answer)) { + return false; + } + + String normalisedAnswer = QbUtils.normaliseVSAnswer(answer); + boolean isQuestionCaseSensitive = qbQuestion.isCaseSensitive(); + boolean isAnswerAllocated = false; + + for (QbOption option : qbQuestion.getQbOptions()) { + String name = option.getName(); + isAnswerAllocated = QbUtils.isVSAnswerAllocated(name, normalisedAnswer, isQuestionCaseSensitive); + if (isAnswerAllocated) { + break; + } + } + + if (!isAnswerAllocated) { + if (!isQuestionCaseSensitive) { + normalisedAnswer = normalisedAnswer.toLowerCase(); + } + // do not add repetitive students' suggestions for teacher to assign to an option + if (notAllocatedAnswers.contains(normalisedAnswer)) { + isAnswerAllocated = true; + } else { + notAllocatedAnswers.add(normalisedAnswer); + } + } + + return isAnswerAllocated; + } + private static Integer getUserId() { HttpSession ss = SessionManager.getSession(); UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); Index: lams_common/src/java/org/lamsfoundation/lams/qb/dao/IQbDAO.java =================================================================== diff -u -rc82d171dbdd8918839e396f2851d6e11b68bb9e8 -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_common/src/java/org/lamsfoundation/lams/qb/dao/IQbDAO.java (.../IQbDAO.java) (revision c82d171dbdd8918839e396f2851d6e11b68bb9e8) +++ lams_common/src/java/org/lamsfoundation/lams/qb/dao/IQbDAO.java (.../IQbDAO.java) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -26,6 +26,8 @@ */ List getQuestionsByQuestionId(Integer questionId); + List getToolQuestionForToolContentId(Class clazz, long toolContentId, long otherToolQuestionUid); + List getQuestionsByToolContentId(long toolContentId); // finds next question ID for Question Bank question Index: lams_common/src/java/org/lamsfoundation/lams/qb/dao/hibernate/QbDAO.java =================================================================== diff -u -r3248d9808412f06775532829889bb22b76da3a9e -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_common/src/java/org/lamsfoundation/lams/qb/dao/hibernate/QbDAO.java (.../QbDAO.java) (revision 3248d9808412f06775532829889bb22b76da3a9e) +++ lams_common/src/java/org/lamsfoundation/lams/qb/dao/hibernate/QbDAO.java (.../QbDAO.java) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -20,6 +20,7 @@ import org.lamsfoundation.lams.qb.dao.IQbDAO; import org.lamsfoundation.lams.qb.model.QbCollection; import org.lamsfoundation.lams.qb.model.QbQuestion; +import org.lamsfoundation.lams.qb.model.QbToolQuestion; import org.lamsfoundation.lams.tool.ToolContent; public class QbDAO extends LAMSBaseDAO implements IQbDAO { @@ -153,6 +154,18 @@ } @Override + public List getToolQuestionForToolContentId(Class clazz, long toolContentId, long otherToolQuestionUid) { + QbToolQuestion toolQuestion = find(QbToolQuestion.class, otherToolQuestionUid); + + String queryText = "FROM " + clazz.getName() + " AS tq " + + "WHERE tq.toolContentId = :toolContentId AND tq.qbQuestion.uid = :qbQuestionUid"; + + return getSession().createQuery(queryText, clazz).setParameter("toolContentId", toolContentId) + .setParameter("qbQuestionUid", toolQuestion.getQbQuestion().getUid()).setCacheable(true) + .getResultList(); + } + + @Override public int generateNextQuestionId() { int max = ((BigInteger) this.getSession().createNativeQuery(FIND_MAX_QUESTION_ID_FROM_GENERATOR).uniqueResult()) .intValue(); Index: lams_common/src/java/org/lamsfoundation/lams/qb/service/IQbService.java =================================================================== diff -u -r3085af1c7e3e6c3496af23a748d998886d7168fd -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_common/src/java/org/lamsfoundation/lams/qb/service/IQbService.java (.../IQbService.java) (revision 3085af1c7e3e6c3496af23a748d998886d7168fd) +++ lams_common/src/java/org/lamsfoundation/lams/qb/service/IQbService.java (.../IQbService.java) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -45,6 +45,8 @@ QbQuestion getQuestionByUUID(UUID uuid); + List getToolQuestionForToolContentId(Class clazz, long toolContentId, long otherToolQuestionUid); + /** * @param optionUid * @return QbOption by its uid. Besides, it releases returned object and associated qbQuestion from the cache. Index: lams_common/src/java/org/lamsfoundation/lams/qb/service/QbService.java =================================================================== diff -u -r3085af1c7e3e6c3496af23a748d998886d7168fd -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_common/src/java/org/lamsfoundation/lams/qb/service/QbService.java (.../QbService.java) (revision 3085af1c7e3e6c3496af23a748d998886d7168fd) +++ lams_common/src/java/org/lamsfoundation/lams/qb/service/QbService.java (.../QbService.java) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -105,6 +105,10 @@ return result.isEmpty() ? null : result.get(0); } + public List getToolQuestionForToolContentId(Class clazz, long toolContentId, long otherToolQuestionUid) { + return qbDAO.getToolQuestionForToolContentId(clazz, toolContentId, otherToolQuestionUid); + } + @Override public QbOption getOptionByUid(Long optionUid) { QbOption option = qbDAO.find(QbOption.class, optionUid); Index: lams_common/src/java/org/lamsfoundation/lams/tool/service/ICommonAssessmentService.java =================================================================== diff -u -re581d656fb9eae279adb11f28b8419fd49cd05c2 -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_common/src/java/org/lamsfoundation/lams/tool/service/ICommonAssessmentService.java (.../ICommonAssessmentService.java) (revision e581d656fb9eae279adb11f28b8419fd49cd05c2) +++ lams_common/src/java/org/lamsfoundation/lams/tool/service/ICommonAssessmentService.java (.../ICommonAssessmentService.java) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -35,5 +35,5 @@ */ Map countCorrectAnswers(long toolContentId); - boolean recalculateMarksForVsaQuestion(Long questionUid, String answer); + boolean recalculateMarksForVsaQuestion(Long qbQuestionUid, String answer); } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/tool/service/ICommonScratchieService.java =================================================================== diff -u -r3085af1c7e3e6c3496af23a748d998886d7168fd -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_common/src/java/org/lamsfoundation/lams/tool/service/ICommonScratchieService.java (.../ICommonScratchieService.java) (revision 3085af1c7e3e6c3496af23a748d998886d7168fd) +++ lams_common/src/java/org/lamsfoundation/lams/tool/service/ICommonScratchieService.java (.../ICommonScratchieService.java) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -1,10 +1,19 @@ package org.lamsfoundation.lams.tool.service; +import java.util.Map; + +import org.lamsfoundation.lams.qb.model.QbToolQuestion; + public interface ICommonScratchieService { boolean recalculateMarksForVsaQuestion(Long qbQuestionUid, String answer); /** * Counts how many questions were answered correctly on first attempt by the given user, regardless of mark given. */ Integer countCorrectAnswers(long toolContentId, int userId); + + /** + * Returns VS answers which require allocation for the given activity + */ + Map> getUnallocatedVSAnswers(long toolContentId); } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/tool/service/LamsToolService.java =================================================================== diff -u -re581d656fb9eae279adb11f28b8419fd49cd05c2 -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_common/src/java/org/lamsfoundation/lams/tool/service/LamsToolService.java (.../LamsToolService.java) (revision e581d656fb9eae279adb11f28b8419fd49cd05c2) +++ lams_common/src/java/org/lamsfoundation/lams/tool/service/LamsToolService.java (.../LamsToolService.java) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -539,29 +539,35 @@ ICommonAssessmentService sessionManager = (ICommonAssessmentService) lamsCoreToolService .findToolService(tool); return sessionManager.getUnallocatedVSAnswers(toolContentId); + } else if (tool.getToolSignature().equals(CommonConstants.TOOL_SIGNATURE_SCRATCHIE)) { + ICommonScratchieService sessionManager = (ICommonScratchieService) lamsCoreToolService + .findToolService(tool); + return sessionManager.getUnallocatedVSAnswers(toolContentId); } return null; } @Override public boolean recalculateMarksForVsaQuestion(Long toolQuestionUid, String answer) { - boolean answerFoundInLearnerResults = recalculateAssessmentMarksForVsaQuestion(toolQuestionUid, answer); - answerFoundInLearnerResults |= recalculateScratchieMarksForVsaQuestion(toolQuestionUid, answer); + QbToolQuestion toolQuestion = activityDAO.find(QbToolQuestion.class, toolQuestionUid); + Long qbQuestionUid = toolQuestion.getQbQuestion().getUid(); + boolean answerFoundInLearnerResults = recalculateAssessmentMarksForVsaQuestion(qbQuestionUid, answer); + answerFoundInLearnerResults |= recalculateScratchieMarksForVsaQuestion(qbQuestionUid, answer); return answerFoundInLearnerResults; } - private boolean recalculateAssessmentMarksForVsaQuestion(Long tooQuestionUid, String answer) { + private boolean recalculateAssessmentMarksForVsaQuestion(Long qbQuestionUid, String answer) { Tool assessmentTool = toolDAO.getToolBySignature(CommonConstants.TOOL_SIGNATURE_ASSESSMENT); ICommonAssessmentService sessionManager = (ICommonAssessmentService) lamsCoreToolService .findToolService(assessmentTool); - return sessionManager.recalculateMarksForVsaQuestion(tooQuestionUid, answer); + return sessionManager.recalculateMarksForVsaQuestion(qbQuestionUid, answer); } - private boolean recalculateScratchieMarksForVsaQuestion(Long toolQuestionUid, String answer) { + private boolean recalculateScratchieMarksForVsaQuestion(Long qbQuestionUid, String answer) { Tool scratchieTool = toolDAO.getToolBySignature(CommonConstants.TOOL_SIGNATURE_SCRATCHIE); ICommonScratchieService sessionManager = (ICommonScratchieService) lamsCoreToolService .findToolService(scratchieTool); - return sessionManager.recalculateMarksForVsaQuestion(toolQuestionUid, answer); + return sessionManager.recalculateMarksForVsaQuestion(qbQuestionUid, answer); } @Override Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java =================================================================== diff -u -re581d656fb9eae279adb11f28b8419fd49cd05c2 -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java (.../AssessmentServiceImpl.java) (revision e581d656fb9eae279adb11f28b8419fd49cd05c2) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java (.../AssessmentServiceImpl.java) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -1410,12 +1410,11 @@ if (question.getType().equals(QbQuestion.TYPE_VERY_SHORT_ANSWERS)) { // gets mapping answer -> user ID for all answers which were not allocation into VSA option yet QuestionSummary questionSummary = getQuestionSummary(toolContentId, question.getUid()); - Map unallocatedQuestionAnswers = questionSummary.getNotAllocatedQuestionResults() - .stream() + Map notAllocatedAnswerMap = questionSummary.getNotAllocatedQuestionResults().stream() .collect(Collectors.toMap(AssessmentQuestionResult::getAnswer, r -> r.getAssessmentResult().getUser().getUserId().intValue(), (user1, user2) -> user1, LinkedHashMap::new)); - result.put(question, unallocatedQuestionAnswers); + result.put(question, notAllocatedAnswerMap); } } return result; @@ -1433,36 +1432,15 @@ //prepare extra data for VSA type of questions, so teachers can allocate answers into groups if (isVSA) { - boolean isQuestionCaseSensitive = question.getQbQuestion().isCaseSensitive(); //find all questionResults that are not allocated into groups yet List notAllocatedQuestionResults = new ArrayList<>(); - Set notAllocatedAnswers = new HashSet<>(); - for (AssessmentQuestionResult questionResult : allQuestionResults) { - String answer = questionResult.getAnswer(); - if (StringUtils.isBlank(answer)) { - continue; - } - String normalisedAnswer = QbUtils.normaliseVSAnswer(answer); - - boolean isAnswerAllocated = false; - for (QbOption option : qbQuestion.getQbOptions()) { - String name = option.getName(); - isAnswerAllocated = QbUtils.isVSAnswerAllocated(name, normalisedAnswer, isQuestionCaseSensitive); - if (isAnswerAllocated) { - break; - } - } - + for (AssessmentQuestionResult questionResult : allQuestionResults) { + Set notAllocatedAnswers = new HashSet<>(); + boolean isAnswerAllocated = QbUtils.isVSAnswerAllocated(qbQuestion, questionResult.getAnswer(), + notAllocatedAnswers); if (!isAnswerAllocated) { - if (!isQuestionCaseSensitive) { - normalisedAnswer = normalisedAnswer.toLowerCase(); - } - // do not add repetitive students' suggestions for teacher to assign to an option - if (!notAllocatedAnswers.contains(normalisedAnswer)) { - notAllocatedAnswers.add(normalisedAnswer); - notAllocatedQuestionResults.add(questionResult); - } + notAllocatedQuestionResults.add(questionResult); } } questionSummary.setNotAllocatedQuestionResults(notAllocatedQuestionResults); @@ -1476,12 +1454,10 @@ } @Override - public boolean recalculateMarksForVsaQuestion(Long toolQuestionUid, String answer) { - AssessmentQuestion assessmentQuestion = assessmentQuestionDao.getByUid(toolQuestionUid); - QbQuestion qbQuestion = assessmentQuestion.getQbQuestion(); - // get all finished user results + public boolean recalculateMarksForVsaQuestion(Long qbQuestionUid, String answer) { + // get all user results List assessmentResults = assessmentResultDao - .getAssessmentResultsByQbQuestionAndAnswer(qbQuestion.getUid(), answer); + .getAssessmentResultsByQbQuestionAndAnswer(qbQuestionUid, answer); //stores userId->lastFinishedAssessmentResult Map assessmentResultsMap = new LinkedHashMap<>(); for (AssessmentResult assessmentResult : assessmentResults) { @@ -1495,13 +1471,13 @@ int assessmentMaxMark = assessmentResult.getMaximumGrade(); for (AssessmentQuestionResult questionResult : assessmentResult.getQuestionResults()) { - if (questionResult.getQbQuestion().getUid().equals(qbQuestion.getUid())) { + if (questionResult.getQbQuestion().getUid().equals(qbQuestionUid)) { Float oldQuestionAnswerMark = questionResult.getMark(); int oldResultMaxMark = questionResult.getMaxMark() == null ? 0 : questionResult.getMaxMark().intValue(); //actually recalculate marks - QuestionDTO questionDto = new QuestionDTO(assessmentQuestion); + QuestionDTO questionDto = new QuestionDTO(questionResult.getQbToolQuestion()); questionDto.setMaxMark(oldResultMaxMark); loadupQuestionResultIntoQuestionDto(questionDto, questionResult); calculateAnswerMark(assessmentResult.getAssessment().getUid(), user.getUserId(), questionResult, Index: lams_tool_scratchie/conf/language/lams/ApplicationResources.properties =================================================================== diff -u -reba4bfd253009e2910ee42d7852a05004f14b26d -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_tool_scratchie/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision eba4bfd253009e2910ee42d7852a05004f14b26d) +++ lams_tool_scratchie/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -314,3 +314,4 @@ label.monitoring.discussion.start = Start discussion sentiment label.authoring.advanced.discussion = Enable discussion sentiment voting label.authoring.advanced.discussion.tooltip = When enabled, in TBL monitoring, teachers are able to start instant polls for each burning question to assess the students' understanding. +label.vsa.allocate.button = Allocate VSAs Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/ScratchieAnswerVisitDAO.java =================================================================== diff -u -r7fdda695e029753cdb6cbd771cf897080afc942c -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/ScratchieAnswerVisitDAO.java (.../ScratchieAnswerVisitDAO.java) (revision 7fdda695e029753cdb6cbd771cf897080afc942c) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/ScratchieAnswerVisitDAO.java (.../ScratchieAnswerVisitDAO.java) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -33,20 +33,22 @@ * Get log for MCQ question. */ ScratchieAnswerVisitLog getLog(Long optionUid, Long itemUid, Long sessionId); - + /** * Get log for VSA question. */ ScratchieAnswerVisitLog getLog(Long sessionId, Long itemUid, boolean isCaseSensitive, String answer); int getLogCountTotal(Long sessionId); - + int getLogCountPerItem(Long sessionId, Long itemUid); List getLogsBySessionAndItem(Long sessionId, Long itemUid); List getLogsBySession(Long sessionId); - + + List getVsaLogsByItem(Long itemUid); + /** * @param scratchieUid * @return all visit logs left for the activity with specified scratchieUid Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/hibernate/ScratchieAnswerVisitDAOHibernate.java =================================================================== diff -u -r7fdda695e029753cdb6cbd771cf897080afc942c -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/hibernate/ScratchieAnswerVisitDAOHibernate.java (.../ScratchieAnswerVisitDAOHibernate.java) (revision 7fdda695e029753cdb6cbd771cf897080afc942c) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/hibernate/ScratchieAnswerVisitDAOHibernate.java (.../ScratchieAnswerVisitDAOHibernate.java) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -27,6 +27,7 @@ import org.hibernate.query.Query; import org.lamsfoundation.lams.dao.hibernate.LAMSBaseDAO; +import org.lamsfoundation.lams.qb.model.QbQuestion; import org.lamsfoundation.lams.tool.scratchie.dao.ScratchieAnswerVisitDAO; import org.lamsfoundation.lams.tool.scratchie.model.ScratchieAnswerVisitLog; import org.lamsfoundation.lams.tool.scratchie.model.ScratchieSession; @@ -36,29 +37,34 @@ public class ScratchieAnswerVisitDAOHibernate extends LAMSBaseDAO implements ScratchieAnswerVisitDAO { private static final String FIND_COUNT_BY_SESSION = "SELECT COUNT(*) FROM " + ScratchieAnswerVisitLog.class.getName() + " AS r WHERE r.sessionId=?"; - + private static final String FIND_COUNT_BY_SESSION_AND_ITEM = "SELECT COUNT(*) FROM " + ScratchieAnswerVisitLog.class.getName() + " AS r WHERE r.sessionId=? AND r.qbToolQuestion.uid = ?"; + private static final String FIND_VSA_BY_ITEM = "FROM " + ScratchieAnswerVisitLog.class.getName() + + " AS r WHERE r.qbToolQuestion.qbQuestion.type = " + QbQuestion.TYPE_VERY_SHORT_ANSWERS + + " AND r.qbToolQuestion.uid = :itemUid"; + @Override public ScratchieAnswerVisitLog getLog(Long optionUid, Long itemUid, Long sessionId) { final String FIND_BY_SESSION_AND_OPTION = "FROM " + ScratchieAnswerVisitLog.class.getName() + " AS r WHERE r.sessionId = ? AND r.qbToolQuestion.uid = ? AND r.qbOption.uid=?"; - + List list = doFind(FIND_BY_SESSION_AND_OPTION, new Object[] { sessionId, itemUid, optionUid }); if (list == null || list.size() == 0) { return null; } return (ScratchieAnswerVisitLog) list.get(0); } - + @Override public ScratchieAnswerVisitLog getLog(Long sessionId, Long itemUid, boolean isCaseSensitive, String answer) { final String FIND_BY_SESSION_AND_ANSWER = "FROM " + ScratchieAnswerVisitLog.class.getName() + " AS r WHERE r.sessionId = :sessionId AND r.qbToolQuestion.uid = :itemUid AND " + (isCaseSensitive ? "CAST(r.answer AS binary)=CAST(:answer AS binary)" : "r.answer=:answer"); - - Query q = getSession().createQuery(FIND_BY_SESSION_AND_ANSWER, ScratchieAnswerVisitLog.class); + + Query q = getSession().createQuery(FIND_BY_SESSION_AND_ANSWER, + ScratchieAnswerVisitLog.class); q.setParameter("sessionId", sessionId); q.setParameter("itemUid", itemUid); q.setParameter("answer", answer); @@ -73,7 +79,7 @@ } return ((Number) list.get(0)).intValue(); } - + @Override public int getLogCountPerItem(Long sessionId, Long itemUid) { List list = doFind(FIND_COUNT_BY_SESSION_AND_ITEM, new Object[] { sessionId, itemUid }); @@ -98,22 +104,31 @@ @Override public List getLogsBySession(Long sessionId) { final String FIND_BY_SESSION = "FROM " + ScratchieAnswerVisitLog.class.getName() - + " AS r WHERE r.sessionId=:sessionId ORDER BY r.accessDate ASC"; - + + " AS r WHERE r.sessionId=:sessionId ORDER BY r.accessDate ASC"; + Query query = getSession().createQuery(FIND_BY_SESSION, ScratchieAnswerVisitLog.class); query.setParameter("sessionId", sessionId); return query.list(); } - + @Override public List getLogsByScratchieUid(Long scratchieUid) { final String FIND_BY_SCRATCHIE_UID = "SELECT log FROM " + ScratchieAnswerVisitLog.class.getName() + " AS log, " + ScratchieSession.class.getName() + " AS session " + " WHERE log.sessionId = session.sessionId AND session.scratchie.uid=:scratchieUid ORDER BY log.accessDate ASC"; - Query query = getSession().createQuery(FIND_BY_SCRATCHIE_UID, ScratchieAnswerVisitLog.class); + Query query = getSession().createQuery(FIND_BY_SCRATCHIE_UID, + ScratchieAnswerVisitLog.class); query.setParameter("scratchieUid", scratchieUid); return query.list(); } + @Override + public List getVsaLogsByItem(Long itemUid) { + Query query = getSession().createQuery(FIND_VSA_BY_ITEM, + ScratchieAnswerVisitLog.class); + query.setParameter("itemUid", itemUid); + return query.list(); + } + } Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java =================================================================== diff -u -r3085af1c7e3e6c3496af23a748d998886d7168fd -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java (.../ScratchieServiceImpl.java) (revision 3085af1c7e3e6c3496af23a748d998886d7168fd) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java (.../ScratchieServiceImpl.java) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -34,7 +34,9 @@ import java.util.Collection; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -66,6 +68,7 @@ import org.lamsfoundation.lams.outcome.Outcome; import org.lamsfoundation.lams.outcome.OutcomeMapping; import org.lamsfoundation.lams.outcome.service.IOutcomeService; +import org.lamsfoundation.lams.qb.QbUtils; import org.lamsfoundation.lams.qb.model.QbCollection; import org.lamsfoundation.lams.qb.model.QbOption; import org.lamsfoundation.lams.qb.model.QbQuestion; @@ -599,6 +602,40 @@ return !sessionIds.isEmpty(); } + @Override + public Map> getUnallocatedVSAnswers(long toolContentId) { + Map> result = new LinkedHashMap<>(); + + List sessions = scratchieSessionDao.getByContentId(toolContentId); + if (sessions.isEmpty()) { + return result; + } + + Scratchie scratchie = sessions.get(0).getScratchie(); + Map sessionToLeaderMap = sessions.stream().filter(s -> s.getGroupLeader() != null).collect( + Collectors.toMap(ScratchieSession::getSessionId, s -> s.getGroupLeader().getUserId().intValue())); + + for (ScratchieItem item : scratchie.getScratchieItems()) { + QbQuestion qbQuestion = item.getQbQuestion(); + if (qbQuestion.getType().equals(QbQuestion.TYPE_VERY_SHORT_ANSWERS)) { + Set notAllocatedAnswers = new HashSet<>(); + Map notAllocatedAnswerMap = new LinkedHashMap<>(); + + List visitLogs = scratchieAnswerVisitDao.getVsaLogsByItem(item.getUid()); + for (ScratchieAnswerVisitLog visitLog : visitLogs) { + String answer = visitLog.getAnswer(); + boolean isAnswerAllocated = QbUtils.isVSAnswerAllocated(qbQuestion, answer, notAllocatedAnswers); + if (!isAnswerAllocated) { + notAllocatedAnswerMap.put(answer.strip(), sessionToLeaderMap.get(visitLog.getSessionId())); + } + } + + result.put(item, notAllocatedAnswerMap); + } + } + return result; + } + /** * Counts how many questions were answered correctly on first attempt by the given user, regardless of mark given. */ Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/MonitoringController.java =================================================================== diff -u -r804dca72fa2ac638a9d3e2e66054d82688951c31 -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/MonitoringController.java (.../MonitoringController.java) (revision 804dca72fa2ac638a9d3e2e66054d82688951c31) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/MonitoringController.java (.../MonitoringController.java) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -49,6 +49,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.lamsfoundation.lams.qb.dto.QbStatsActivityDTO; +import org.lamsfoundation.lams.qb.model.QbQuestion; import org.lamsfoundation.lams.qb.service.IQbService; import org.lamsfoundation.lams.tool.scratchie.ScratchieConstants; import org.lamsfoundation.lams.tool.scratchie.dto.BurningQuestionDTO; @@ -156,6 +157,13 @@ sessionMap.put(ScratchieConstants.ATTR_REFLECTIONS, reflections); } + for (ScratchieItem item : scratchie.getScratchieItems()) { + if (item.getQbQuestion().getType().equals(QbQuestion.TYPE_VERY_SHORT_ANSWERS)) { + request.setAttribute("vsaPresent", true); + break; + } + } + Map modelAttributes = scratchieService.prepareStudentChoicesData(scratchie); model.addAllAttributes(modelAttributes); Index: lams_tool_scratchie/web/pages/monitoring/summary.jsp =================================================================== diff -u -r01914e84eaec252cea509f1990122a58b555cbd5 -r6f0f844e82f555e8dc0df6916226fac35a2a7c36 --- lams_tool_scratchie/web/pages/monitoring/summary.jsp (.../summary.jsp) (revision 01914e84eaec252cea509f1990122a58b555cbd5) +++ lams_tool_scratchie/web/pages/monitoring/summary.jsp (.../summary.jsp) (revision 6f0f844e82f555e8dc0df6916226fac35a2a7c36) @@ -345,7 +345,7 @@ submissionDeadline: '${submissionDeadline}', submissionDateString: '${submissionDateString}', setSubmissionDeadlineUrl: '?', - toolContentID: '${param.toolContentID}', + toolContentID: '${scratchie.contentId}', messageNotification: '', messageRestrictionSet: '', messageRestrictionRemoved: '' @@ -384,7 +384,7 @@

<%@ include file="studentChoices.jsp"%> - +
@@ -396,6 +396,13 @@
+ + + + + +