Index: lams_build/lib/lams/lams.jar =================================================================== diff -u -r79a5b84a312572845e14580f38b7193bdb9ae076 -rbb726a241f9e92f7eb88ff9c9a844a294446a141 Binary files differ Index: lams_common/src/java/org/lamsfoundation/lams/learningdesign/strategy/BranchingActivityStrategy.java =================================================================== diff -u -r51fb2a37254f24bb2a805d4ffd54482c779f43fa -rbb726a241f9e92f7eb88ff9c9a844a294446a141 --- lams_common/src/java/org/lamsfoundation/lams/learningdesign/strategy/BranchingActivityStrategy.java (.../BranchingActivityStrategy.java) (revision 51fb2a37254f24bb2a805d4ffd54482c779f43fa) +++ lams_common/src/java/org/lamsfoundation/lams/learningdesign/strategy/BranchingActivityStrategy.java (.../BranchingActivityStrategy.java) (revision bb726a241f9e92f7eb88ff9c9a844a294446a141) @@ -30,6 +30,7 @@ import org.lamsfoundation.lams.learningdesign.BranchingActivity; import org.lamsfoundation.lams.learningdesign.ComplexActivity; import org.lamsfoundation.lams.learningdesign.ContributionTypes; +import org.lamsfoundation.lams.learningdesign.SequenceActivity; import org.lamsfoundation.lams.lesson.LearnerProgress; /** @@ -54,7 +55,7 @@ * activity itself so as to select a branch either determined by the server or to display * the wait screen (for the normal learner) or for the author to select a particular * branch (in preview). - * + * * @see org.lamsfoundation.lams.learningdesign.strategy.ComplexActivityStrategy#getNextActivityByParent(Activity, * Activity) */ @@ -83,24 +84,31 @@ public boolean areChildrenCompleted(LearnerProgress learnerProgress) { ComplexActivity complexActivity = getComplexActivity(); boolean isPreview = learnerProgress.getLesson().isPreviewLesson(); + Boolean isOrderedAsc = false; if (complexActivity != null && complexActivity.getActivities().size() > 0) { for (Iterator i = complexActivity.getActivities().iterator(); i.hasNext();) { - Activity currentActivity = (Activity) i.next(); - boolean actComplete = learnerProgress.getCompletedActivities().containsKey(currentActivity); - if (isPreview && !actComplete) { - // found one not complete, so can try more branches + // we need the real activity, not proxy + SequenceActivity sequenceActivity = (SequenceActivity) activityDAO + .getActivityByActivityId(((Activity) i.next()).getActivityId()); + boolean actComplete = learnerProgress.getCompletedActivities().containsKey(sequenceActivity); + if (actComplete) { + // if activity is complete and it is not preview nor ordered branching where all branches need to get passed, + // then branching activity is complete + if (!isPreview && isOrderedAsc == null) { + return true; + } + // if it is preview or there are not completed branches with conditions in ordered branching, + // then this branching activity is not finished yet + } else if (isPreview || (isOrderedAsc != null && !sequenceActivity.getBranchEntries().isEmpty())) { return false; - } else if (!isPreview && actComplete) { - // found one complete, so branching is finished - return true; } } - // We've checked all the activities. If we are in preview, then they are all + // We've checked all the activities. If we are in preview or ordered branching, then they are all // completed so return true. If we are not in preview (ie normal learner) then - // we haven't found any that were completed so we return false. So we can just + // we haven't found any that were completed so we return false. So we can just // return isPreview as that is the correct boolean state. - return (isPreview); + return isPreview || isOrderedAsc != null; } // didn't find any child activities so we are complete Index: lams_common/src/java/org/lamsfoundation/lams/learningdesign/strategy/ComplexActivityStrategy.java =================================================================== diff -u -r51fb2a37254f24bb2a805d4ffd54482c779f43fa -rbb726a241f9e92f7eb88ff9c9a844a294446a141 --- lams_common/src/java/org/lamsfoundation/lams/learningdesign/strategy/ComplexActivityStrategy.java (.../ComplexActivityStrategy.java) (revision 51fb2a37254f24bb2a805d4ffd54482c779f43fa) +++ lams_common/src/java/org/lamsfoundation/lams/learningdesign/strategy/ComplexActivityStrategy.java (.../ComplexActivityStrategy.java) (revision bb726a241f9e92f7eb88ff9c9a844a294446a141) @@ -29,6 +29,7 @@ import org.lamsfoundation.lams.learningdesign.Activity; import org.lamsfoundation.lams.learningdesign.ComplexActivity; +import org.lamsfoundation.lams.learningdesign.dao.IActivityDAO; import org.lamsfoundation.lams.lesson.LearnerProgress; /** @@ -40,6 +41,9 @@ * @version 1.1 */ public abstract class ComplexActivityStrategy implements Serializable, IContributionTypeStrategy { + + protected static IActivityDAO activityDAO; + /** *

* Check up all children completion status for a complex activity. @@ -146,4 +150,13 @@ protected void setUpContributionType(ArrayList contributionTypes) { } + + /** + * Ugly, but sometimes we need to get real child activity, not proxy + */ + public void setActivityDAO(IActivityDAO activityDAO) { + if (ComplexActivityStrategy.activityDAO == null) { + ComplexActivityStrategy.activityDAO = activityDAO; + } + } } Index: lams_learning/src/java/org/lamsfoundation/lams/learning/progress/ProgressEngine.java =================================================================== diff -u -r045ebfd1d11d9ed0a1f81a00abb1a2ea373e8d93 -rbb726a241f9e92f7eb88ff9c9a844a294446a141 --- lams_learning/src/java/org/lamsfoundation/lams/learning/progress/ProgressEngine.java (.../ProgressEngine.java) (revision 045ebfd1d11d9ed0a1f81a00abb1a2ea373e8d93) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/progress/ProgressEngine.java (.../ProgressEngine.java) (revision bb726a241f9e92f7eb88ff9c9a844a294446a141) @@ -57,11 +57,11 @@ public static final String AUDIT_ACTIVITY_START_KEY = "audit.activity.started"; public static final String AUDIT_ACTIVITY_STOP_KEY = "audit.activity.stopped"; public static final String AUDIT_LESSON_COMPLETE_KEY = "audit.learner.lesson.complete"; - + private IActivityDAO activityDAO; private ILogEventService logEventService; private MessageService messageService; - + /** * Method determines next step for a learner based on the activity they have * just completed. Will clear the Parallel Waiting Complete value if it is @@ -327,6 +327,7 @@ ComplexActivity complexParent = (ComplexActivity) activityDAO .getActivityByActivityId(parent.getActivityId(), ComplexActivity.class); + complexParent.getComplexActivityStrategy().setActivityDAO(activityDAO); if (!learnerProgress.getCompletedActivities().containsKey(complexParent) && !complexParent.areChildrenCompleted(learnerProgress)) { Activity nextActivity = complexParent.getNextActivityByParent(completedActivity); @@ -434,9 +435,9 @@ public void setLogEventService(ILogEventService logEventService) { this.logEventService = logEventService; } + public void setMessageService(MessageService messageService) { - this.messageService = messageService; + this.messageService = messageService; } - } \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerService.java =================================================================== diff -u -rb32cbfc76a3cd150823b3696160d5fd4fa6cde84 -rbb726a241f9e92f7eb88ff9c9a844a294446a141 --- lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerService.java (.../LearnerService.java) (revision b32cbfc76a3cd150823b3696160d5fd4fa6cde84) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerService.java (.../LearnerService.java) (revision bb726a241f9e92f7eb88ff9c9a844a294446a141) @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -976,7 +977,6 @@ } if (toolSession != null) { - // Get all the conditions for this branching activity, ordered by order id. Map conditionsMap = new TreeMap(); Iterator branchIterator = branchingActivity.getActivities().iterator(); @@ -997,6 +997,10 @@ // Cache the tool output so that we aren't calling it over an over again. Map toolOutputMap = new HashMap(); Iterator conditionIterator = conditionsMap.keySet().iterator(); + Boolean isOrderedAsc = false; + // map of order chosen by learner -> condition with question and answer uid encoded + Map conditionOrder = isOrderedAsc == null ? null + : isOrderedAsc ? new TreeMap<>() : new TreeMap<>(Collections.reverseOrder()); while ((matchedBranch == null) && conditionIterator.hasNext()) { BranchCondition condition = conditionIterator.next(); @@ -1011,9 +1015,25 @@ toolOutputMap.put(conditionName, toolOutput); } } + if (toolOutput != null) { + if (isOrderedAsc != null) { + // put this option's order ID chosen by the learner + conditionOrder.put(toolOutput.getValue().getLong(), condition); + } else if (condition.isMet(toolOutput)) { + matchedBranch = conditionsMap.get(condition); + } + } + } - if ((toolOutput != null) && condition.isMet(toolOutput)) { - matchedBranch = conditionsMap.get(condition); + // find first branch that has not been passed yet + if (isOrderedAsc != null) { + LearnerProgress learnerProgress = getProgress(learner.getUserId(), lesson.getLessonId()); + for (BranchCondition condition : conditionOrder.values()) { + SequenceActivity sequenceActivity = conditionsMap.get(condition); + if (!learnerProgress.getCompletedActivities().containsKey(sequenceActivity)) { + matchedBranch = sequenceActivity; + break; + } } } } Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/AssessmentConstants.java =================================================================== diff -u -r78f8dc6b716a04f673bb80bc8023436f409be139 -rbb726a241f9e92f7eb88ff9c9a844a294446a141 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/AssessmentConstants.java (.../AssessmentConstants.java) (revision 78f8dc6b716a04f673bb80bc8023436f409be139) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/AssessmentConstants.java (.../AssessmentConstants.java) (revision bb726a241f9e92f7eb88ff9c9a844a294446a141) @@ -59,23 +59,23 @@ // for action forward name public static final String SUCCESS = "success"; - + public static final String LEARNING = "learning"; - + public static final String SHOW_RESULTS = "showResults"; public static final String ERROR = "error"; public static final String DEFINE_LATER = "definelater"; public static final String WAIT_FOR_LEADER = "waitForLeader"; - + public static final String WAIT_FOR_LEADER_TIME_LIMIT = "waitForLeaderTimeLimit"; // for parameters' name - + public static final String PARAM_WAITING_MESSAGE_KEY = "waitingMessageKey"; - + public static final String PARAM_TOOL_CONTENT_ID = "toolContentID"; public static final String PARAM_TOOL_SESSION_ID = "toolSessionID"; @@ -134,7 +134,7 @@ public static final String ATTR_OPTION_QUESTION_PREFIX = "optionQuestion"; public static final String ATTR_QUESTION_PREFIX = "question"; - + public static final String ATTR_CONFIDENCE_LEVEL_PREFIX = "confidenceLevel"; public static final String ATTR_QUESTION_TYPE = "questionType"; @@ -152,11 +152,11 @@ public static final String ATTR_UNIT_LIST = "unitList"; public static final String ATTR_QUESTION_REFERENCES_GRADES = "referenceGrades"; - + public static final String ATTR_HAS_EDIT_RIGHT = "hasEditRight"; - + public static final String ATTR_IS_TIME_LIMIT_NOT_LAUNCHED = "isTimeLimitNotLaunched"; - + public static final String ATTR_SECONDS_LEFT = "secondsLeft"; public static final String ATTR_UNIT_COUNT = "unitCount"; @@ -228,7 +228,7 @@ public static final String ATTR_QUESTION_NUMBERING_OFFSET = "questionNumberingOffset"; public static final String ATTR_SUBMISSION_DEADLINE = "submissionDeadline"; - + public static final String ATTR_SUBMISSION_DEADLINE_DATESTRING = "submissionDateString"; public static final String ATTR_IS_SUBMISSION_DEADLINE_PASSED = "isSubmissionDeadlinePassed"; @@ -257,9 +257,9 @@ public static final String OUTPUT_NAME_BEST_SCORE = "best.score"; public static final String OUTPUT_NAME_FIRST_SCORE = "first.score"; public static final String OUTPUT_NAME_AVERAGE_SCORE = "average.score"; - - public static final String OUTPUT_NAME_ORDERED_ANSWERS = "ordered.answers"; + public static final String OUTPUT_NAME_ORDERED_ANSWERS = "ordered.answers"; + public static final String OUTPUT_NAME_CONDITION_ORDERED_ANSWER = "ordered.answer"; // error message keys public static final String ERROR_MSG_QUESTION_NAME_BLANK = "error.question.name.blank"; Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentOutputFactory.java =================================================================== diff -u -r78f8dc6b716a04f673bb80bc8023436f409be139 -rbb726a241f9e92f7eb88ff9c9a844a294446a141 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentOutputFactory.java (.../AssessmentOutputFactory.java) (revision 78f8dc6b716a04f673bb80bc8023436f409be139) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentOutputFactory.java (.../AssessmentOutputFactory.java) (revision bb726a241f9e92f7eb88ff9c9a844a294446a141) @@ -37,8 +37,11 @@ import org.lamsfoundation.lams.tool.assessment.AssessmentConstants; import org.lamsfoundation.lams.tool.assessment.dto.AssessmentUserDTO; import org.lamsfoundation.lams.tool.assessment.model.Assessment; +import org.lamsfoundation.lams.tool.assessment.model.AssessmentOptionAnswer; import org.lamsfoundation.lams.tool.assessment.model.AssessmentQuestion; import org.lamsfoundation.lams.tool.assessment.model.AssessmentQuestionOption; +import org.lamsfoundation.lams.tool.assessment.model.AssessmentQuestionResult; +import org.lamsfoundation.lams.tool.assessment.model.AssessmentResult; import org.lamsfoundation.lams.tool.assessment.model.AssessmentSession; import org.lamsfoundation.lams.tool.assessment.model.QuestionReference; import org.lamsfoundation.lams.tool.assessment.util.SequencableComparator; @@ -116,7 +119,8 @@ for (AssessmentQuestion question : assessment.getQuestions()) { if (question.getType() == AssessmentConstants.QUESTION_TYPE_ORDERING) { - String outputName = AssessmentConstants.OUTPUT_NAME_ORDERED_ANSWERS + "#" + question.getUid(); + String outputName = AssessmentConstants.OUTPUT_NAME_ORDERED_ANSWERS + "#" + + question.getSequenceId(); ToolOutputDefinition orderedAnswersDefinition = buildLongOutputDefinition(outputName); orderedAnswersDefinition.setShowConditionNameOnly(true); orderedAnswersDefinition.setDescription( @@ -125,9 +129,11 @@ orderedAnswersDefinition.setConditions(conditions); int orderId = 1; for (AssessmentQuestionOption option : question.getOptions()) { - String value = WebUtil.removeHTMLtags(option.getOptionString()); - conditions.add(new BranchCondition(null, null, orderId++, "ordered.answer#" + option.getUid(), - value, BranchCondition.OUTPUT_TYPE_LONG, null, null, value)); + conditions.add(new BranchCondition(null, null, orderId++, + AssessmentConstants.OUTPUT_NAME_CONDITION_ORDERED_ANSWER + "#" + + question.getSequenceId() + "#" + option.getSequenceId(), + WebUtil.removeHTMLtags(option.getOptionString()), BranchCondition.OUTPUT_TYPE_LONG, + null, null, null)); } definitionMap.put(outputName, orderedAnswersDefinition); } @@ -170,6 +176,14 @@ output.put(AssessmentConstants.OUTPUT_NAME_LEARNER_NUMBER_ATTEMPTS, getNumberAttempts(assessmentService, learnerId, assessment)); } + if (names != null) { + for (String name : names) { + if (name.startsWith(AssessmentConstants.OUTPUT_NAME_CONDITION_ORDERED_ANSWER)) { + output.put(AssessmentConstants.OUTPUT_NAME_CONDITION_ORDERED_ANSWER, + getAnswerOrder(assessmentService, assessment, learnerId, name)); + } + } + } Set questions = assessment.getQuestions(); for (AssessmentQuestion question : questions) { if (names == null || names.contains(String.valueOf(question.getSequenceId()))) { @@ -208,6 +222,8 @@ } else if (name.equals(AssessmentConstants.OUTPUT_NAME_LEARNER_NUMBER_ATTEMPTS)) { return getNumberAttempts(assessmentService, learnerId, assessment); + } else if (name.startsWith(AssessmentConstants.OUTPUT_NAME_CONDITION_ORDERED_ANSWER)) { + return getAnswerOrder(assessmentService, assessment, learnerId, name); } else { Set questions = assessment.getQuestions(); for (AssessmentQuestion question : questions) { @@ -223,36 +239,36 @@ public List getToolOutputs(String name, IAssessmentService assessmentService, Long toolContentId) { if ((name != null) && (toolContentId != null)) { - if (name.equals(AssessmentConstants.OUTPUT_NAME_LEARNER_TOTAL_SCORE)) { List results = assessmentService.getLastTotalScoresByContentId(toolContentId); return convertToToolOutputs(results); - - } else if (name.equals(AssessmentConstants.OUTPUT_NAME_BEST_SCORE)) { + } + if (name.equals(AssessmentConstants.OUTPUT_NAME_BEST_SCORE)) { List results = assessmentService.getBestTotalScoresByContentId(toolContentId); return convertToToolOutputs(results); - - } else if (name.equals(AssessmentConstants.OUTPUT_NAME_FIRST_SCORE)) { + } + if (name.equals(AssessmentConstants.OUTPUT_NAME_FIRST_SCORE)) { List results = assessmentService.getFirstTotalScoresByContentId(toolContentId); return convertToToolOutputs(results); - - } else if (name.equals(AssessmentConstants.OUTPUT_NAME_AVERAGE_SCORE)) { + } + if (name.equals(AssessmentConstants.OUTPUT_NAME_AVERAGE_SCORE)) { List results = assessmentService.getAverageTotalScoresByContentId(toolContentId); return convertToToolOutputs(results); - - } else if (name.equals(AssessmentConstants.OUTPUT_NAME_LEARNER_TIME_TAKEN)) { + } + if (name.equals(AssessmentConstants.OUTPUT_NAME_LEARNER_TIME_TAKEN)) { return null; - - } else if (name.equals(AssessmentConstants.OUTPUT_NAME_LEARNER_NUMBER_ATTEMPTS)) { + } + if (name.equals(AssessmentConstants.OUTPUT_NAME_LEARNER_NUMBER_ATTEMPTS)) { return null; - - } else { - Assessment assessment = assessmentService.getAssessmentByContentId(toolContentId); - Set questions = assessment.getQuestions(); - for (AssessmentQuestion question : questions) { - if (name.equals(String.valueOf(question.getSequenceId()))) { - return null; - } + } + if (name.startsWith(AssessmentConstants.OUTPUT_NAME_ORDERED_ANSWERS)) { + return null; + } + Assessment assessment = assessmentService.getAssessmentByContentId(toolContentId); + Set questions = assessment.getQuestions(); + for (AssessmentQuestion question : questions) { + if (name.equals(String.valueOf(question.getSequenceId()))) { + return null; } } } @@ -261,7 +277,7 @@ /** * Simply converts List to List. - * + * * @param results * @return */ @@ -359,4 +375,43 @@ return new ToolOutput(String.valueOf(questionSequenceId), "description", questionResultMark); } + /** + * Get order ID selected by the learner for the given option + */ + private ToolOutput getAnswerOrder(IAssessmentService assessmentService, Assessment assessment, Long learnerId, + String conditionName) { + // condition name is prefix#questionSequenceId#optionSequenceId + String[] conditionNameSplit = conditionName.split("#"); + Integer questionSequenceId = Integer.valueOf(conditionNameSplit[1]); + Integer optionSequenceId = Integer.valueOf(conditionNameSplit[2]); + AssessmentQuestion question = null; + // find question + for (AssessmentQuestion questionCandidate : assessment.getQuestions()) { + if (questionSequenceId.equals(questionCandidate.getSequenceId())) { + question = questionCandidate; + break; + } + } + // find option + Long optionUid = null; + for (AssessmentQuestionOption optionCandidate : question.getOptions()) { + if (optionSequenceId.equals(optionCandidate.getSequenceId())) { + optionUid = optionCandidate.getUid(); + break; + } + } + // find order in which the given learner put the option + AssessmentResult result = assessmentService.getLastAssessmentResult(assessment.getUid(), learnerId); + for (AssessmentQuestionResult questionResult : result.getQuestionResults()) { + if (questionResult.getAssessmentQuestion().getUid().equals(question.getUid())) { + for (AssessmentOptionAnswer answer : questionResult.getOptionAnswers()) { + if (answer.getOptionUid().equals(optionUid)) { + return new ToolOutput(conditionName, null, answer.getAnswerInt()); + } + } + } + } + return null; + } + }