Index: lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBActivityGridRowDTO.java =================================================================== diff -u -r506e82d55455419723f11c0a8f99270b39f04055 -r3d9ac24ccaeaccd16a79fcb948cc6191a570b306 --- lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBActivityGridRowDTO.java (.../GBActivityGridRowDTO.java) (revision 506e82d55455419723f11c0a8f99270b39f04055) +++ lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBActivityGridRowDTO.java (.../GBActivityGridRowDTO.java) (revision 3d9ac24ccaeaccd16a79fcb948cc6191a570b306) @@ -30,6 +30,7 @@ import org.apache.commons.lang.StringEscapeUtils; import org.lamsfoundation.lams.gradebook.util.GBGridView; import org.lamsfoundation.lams.gradebook.util.GradebookUtil; +import org.lamsfoundation.lams.learningdesign.Activity; import org.lamsfoundation.lams.learningdesign.CompetenceMapping; import org.lamsfoundation.lams.learningdesign.ToolActivity; @@ -56,7 +57,7 @@ this.groupId = groupId; } - public GBActivityGridRowDTO(ToolActivity activity, String groupName, Long groupId) { + public GBActivityGridRowDTO(Activity activity, String groupName, Long groupId) { if (groupName != null && groupId != null) { // Need to make the id unique, so appending the group id for this row @@ -71,21 +72,26 @@ this.rowName = StringEscapeUtils.escapeHtml(activity.getTitle()); } - //Constructs the competences for this activity. - Set competenceMappings = activity.getCompetenceMappings(); String competenceMappingsStr = ""; - if (competenceMappings != null) { - for (CompetenceMapping mapping : competenceMappings) { - competenceMappingsStr += mapping.getCompetence().getTitle() + ", "; - } - - // trim the last comma off - if (competenceMappingsStr.length() > 0) { - competenceMappingsStr = competenceMappingsStr.substring(0, competenceMappingsStr.lastIndexOf(",")); - } - } - + if ( activity.isToolActivity() ) { + ToolActivity toolActivity = (ToolActivity) activity; + //Constructs the competences for this activity. + Set competenceMappings = toolActivity.getCompetenceMappings(); + + if (competenceMappings != null) { + for (CompetenceMapping mapping : competenceMappings) { + competenceMappingsStr += mapping.getCompetence().getTitle() + ", "; + } + + // trim the last comma off + if (competenceMappingsStr.length() > 0) { + competenceMappingsStr = competenceMappingsStr.substring(0, competenceMappingsStr.lastIndexOf(",")); + } + } + + } this.competences = competenceMappingsStr; + } @Override Index: lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/service/GradebookService.java =================================================================== diff -u -r893729dfd59481fb75cd22f86a12ed41ff763305 -r3d9ac24ccaeaccd16a79fcb948cc6191a570b306 --- lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/service/GradebookService.java (.../GradebookService.java) (revision 893729dfd59481fb75cd22f86a12ed41ff763305) +++ lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/service/GradebookService.java (.../GradebookService.java) (revision 3d9ac24ccaeaccd16a79fcb948cc6191a570b306) @@ -56,10 +56,17 @@ import org.lamsfoundation.lams.gradebook.util.GradebookConstants; import org.lamsfoundation.lams.gradebook.util.LessonComparator; import org.lamsfoundation.lams.gradebook.util.UserComparator; +import org.lamsfoundation.lams.learning.service.ICoreLearnerService; +import org.lamsfoundation.lams.learning.web.bean.ActivityURL; import org.lamsfoundation.lams.learningdesign.Activity; import org.lamsfoundation.lams.learningdesign.ActivityEvaluation; +import org.lamsfoundation.lams.learningdesign.ComplexActivity; +import org.lamsfoundation.lams.learningdesign.FloatingActivity; import org.lamsfoundation.lams.learningdesign.Group; import org.lamsfoundation.lams.learningdesign.Grouping; +import org.lamsfoundation.lams.learningdesign.OptionsActivity; +import org.lamsfoundation.lams.learningdesign.ParallelActivity; +import org.lamsfoundation.lams.learningdesign.SequenceActivity; import org.lamsfoundation.lams.learningdesign.ToolActivity; import org.lamsfoundation.lams.learningdesign.dao.IActivityDAO; import org.lamsfoundation.lams.lesson.CompletedActivityProgress; @@ -90,8 +97,6 @@ import org.lamsfoundation.lams.web.util.AttributeNames; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; -import org.lamsfoundation.lams.learning.service.ICoreLearnerService; -import org.lamsfoundation.lams.learning.web.bean.ActivityURL; /** @@ -131,7 +136,7 @@ List gradebookActivityDTOs = new ArrayList(); - List activities = getLessonActivities(lesson); + List activities = getLessonActivitiesForLearner(lesson, userId); for (ToolActivity activity : activities) { String groupName = null; @@ -193,7 +198,7 @@ Lesson lesson = lessonService.getLesson(lessonId); List gradebookActivityDTOs = new ArrayList(); - List activities = getLessonActivities(lesson); + List activities = getLessonToolActivitiesForLesson(lesson); for (ToolActivity activity : activities) { @@ -739,35 +744,77 @@ } Map userToLearnerProgressMap = getUserToLearnerProgressMap(lesson, null); - List activities = getLessonActivities(lesson); + List activities = getLessonActivitiesForLesson(lesson); - for (ToolActivity activity : activities) { + for (Activity activity : activities) { + getActivityDataForLessonGradebookExport(activityToUserDTOMap, learners, userToLearnerProgressMap, activity); + } - Map userToGradebookUserActivityMap = getUserToGradebookUserActivityMap( - activity, null); + return activityToUserDTOMap; + } - List userDTOs = new ArrayList(); + @SuppressWarnings("unchecked") + private void getActivityDataForLessonGradebookExport( + Map> activityToUserDTOMap, Set learners, + Map userToLearnerProgressMap, Activity activity) { - for (User learner : learners) { - GBUserGridRowDTO userDTO = new GBUserGridRowDTO(learner); + if (activity.isToolActivity()) { + List userDTOs = getToolActivityDataForLessonGradebookExport(learners, + userToLearnerProgressMap, (ToolActivity) activity); + activityToUserDTOMap.put((ToolActivity) activity, userDTOs); - // Set the progress - LearnerProgress learnerProgress = userToLearnerProgressMap.get(learner.getUserId()); - userDTO.setTimeTaken(getActivityDuration(learnerProgress, activity)); - userDTO.setStartDate(getActivityStartDate(learnerProgress, activity, null)); - userDTO.setFinishDate(getActivityFinishDate(learnerProgress, activity, null)); + } else if (activity instanceof ComplexActivity) { + // encountered a sequence, branch, optional or parallel within a branching sequence + Set complexLearners = learners; - // Add marks and feedback - GradebookUserActivity gradebookUserActivity = userToGradebookUserActivityMap.get(learner.getUserId()); - if (gradebookUserActivity != null) { - userDTO.setMark(gradebookUserActivity.getMark()); + if (activity instanceof SequenceActivity) { + // use only a subset of learners for this branch of the branching activity based on who has started the branch + complexLearners = new TreeSet(new UserComparator()); + for (User learner : learners) { + LearnerProgress learnerProgress = userToLearnerProgressMap.get(learner.getUserId()); + if (learnerProgress != null + && (learnerProgress.getCompletedActivities().get(activity) != null || learnerProgress + .getAttemptedActivities().get(activity) != null)) { + complexLearners.add(learner); + } } - userDTOs.add(userDTO); } - activityToUserDTOMap.put(activity, userDTOs); + + ComplexActivity sequence = (ComplexActivity) activity; + Set childActivities = (Set) sequence.getActivities(); + for (Activity childActivity : childActivities) { + getActivityDataForLessonGradebookExport(activityToUserDTOMap, complexLearners, + userToLearnerProgressMap, activityDAO.getActivityByActivityId(childActivity.getActivityId())); + } } + } - return activityToUserDTOMap; + private List getToolActivityDataForLessonGradebookExport(Set learners, + Map userToLearnerProgressMap, ToolActivity toolActivity) { + + Map userToGradebookUserActivityMap = getUserToGradebookUserActivityMap( + toolActivity, null); + + List userDTOs = new ArrayList(); + + for (User learner : learners) { + GBUserGridRowDTO userDTO = new GBUserGridRowDTO(learner); + + // Set the progress + LearnerProgress learnerProgress = userToLearnerProgressMap.get(learner.getUserId()); + userDTO.setTimeTaken(getActivityDuration(learnerProgress, toolActivity)); + userDTO.setStartDate(getActivityStartDate(learnerProgress, toolActivity, null)); + userDTO.setFinishDate(getActivityFinishDate(learnerProgress, toolActivity, null)); + + // Add marks and feedback + GradebookUserActivity gradebookUserActivity = userToGradebookUserActivityMap.get(learner.getUserId()); + if (gradebookUserActivity != null) { + userDTO.setMark(gradebookUserActivity.getMark()); + } + userDTOs.add(userDTO); + } + + return userDTOs; } @Override @@ -937,32 +984,35 @@ } } - //construct activityRowName - String groupName = null; - Long groupId = null; - if (activity.getGrouping() != null) { - Group group = activity.getGroupFor(learner); - if (group != null) { - groupName = group.getGroupName(); - groupId = group.getGroupId(); + // userDto will be null if this tool activity was within a branch and the user has not attempted that branch + if ( userDto != null ) { + //construct activityRowName + String groupName = null; + Long groupId = null; + if (activity.getGrouping() != null) { + Group group = activity.getGroupFor(learner); + if (group != null) { + groupName = group.getGroupName(); + groupId = group.getGroupId(); + } } - } - String activityRowName = (groupName != null && groupId != null) - ? StringEscapeUtils.escapeHtml(activity.getTitle()) + " (" + groupName + ")" - : StringEscapeUtils.escapeHtml(activity.getTitle()); + String activityRowName = (groupName != null && groupId != null) + ? StringEscapeUtils.escapeHtml(activity.getTitle()) + " (" + groupName + ")" + : StringEscapeUtils.escapeHtml(activity.getTitle()); - String startDate = (userDto.getStartDate() == null) ? "" - : cellDateFormat.format(userDto.getStartDate()); - String finishDate = (userDto.getFinishDate() == null) ? "" - : cellDateFormat.format(userDto.getFinishDate()); + String startDate = (userDto.getStartDate() == null) ? "" + : cellDateFormat.format(userDto.getStartDate()); + String finishDate = (userDto.getFinishDate() == null) ? "" + : cellDateFormat.format(userDto.getFinishDate()); - ExcelCell[] activityDataRow = new ExcelCell[5]; - activityDataRow[0] = new ExcelCell(activityRowName, false); - activityDataRow[1] = new ExcelCell(startDate, false); - activityDataRow[2] = new ExcelCell(finishDate, false); - activityDataRow[3] = new ExcelCell(userDto.getTimeTakenSeconds(), false); - activityDataRow[4] = new ExcelCell(userDto.getMark(), false); - rowList.add(activityDataRow); + ExcelCell[] activityDataRow = new ExcelCell[5]; + activityDataRow[0] = new ExcelCell(activityRowName, false); + activityDataRow[1] = new ExcelCell(startDate, false); + activityDataRow[2] = new ExcelCell(finishDate, false); + activityDataRow[3] = new ExcelCell(userDto.getTimeTakenSeconds(), false); + activityDataRow[4] = new ExcelCell(userDto.getMark(), false); + rowList.add(activityDataRow); + } } rowList.add(GradebookService.EMPTY_ROW); @@ -1167,7 +1217,7 @@ allLearners.addAll(lesson.getAllLearners()); - List lessonActivities = getLessonActivities(lesson); + List lessonActivities = getLessonToolActivitiesForLesson(lesson); lessonActivitiesMap.put(lesson.getLessonId(), lessonActivities); allActivities.addAll(lessonActivities); } @@ -1366,23 +1416,88 @@ /** - * Returns lesson activities. It works almost the same as lesson.getLearningDesign().getActivities() except it - * solves problem with first activity unable to cast to ToolActivity. + * Returns a completely flat list of lesson activities for the whole lesson. */ - private List getLessonActivities(Lesson lesson) { + private List getLessonToolActivitiesForLesson(Lesson lesson) { List toolActivities = new ArrayList(); List activityUrls = getLearnerService().getStructuredActivityURLs(lesson.getLessonId()); for (ActivityURL activityUrl : activityUrls) { - Activity activity = activityDAO.getActivityByActivityId(activityUrl.getActivityId()); - if (activity instanceof ToolActivity) { - ToolActivity toolActivity = (ToolActivity) activity; - toolActivities.add(toolActivity); + processLessonToolActivity(activityUrl, toolActivities); + } + return toolActivities; + } + + private void processLessonToolActivity(ActivityURL activityUrl, List toolActivities) { + Activity activity = activityDAO.getActivityByActivityId(activityUrl.getActivityId()); + if (activity instanceof ToolActivity) { + ToolActivity toolActivity = (ToolActivity) activity; + toolActivities.add(toolActivity); + } else if (activity instanceof ComplexActivity ) { + for (ActivityURL childUrl : activityUrl.getChildActivities()) { + processLessonToolActivity(childUrl, toolActivities); + } + } + } + + /** + * Returns a list of lesson activities made up of tool activities and sequence activities for the whole lesson. + * The sequence activities allow the export to tweak the learner out. + */ + private List getLessonActivitiesForLesson(Lesson lesson) { + List activities = new ArrayList(); + List activityUrls = getLearnerService().getStructuredActivityURLs(lesson.getLessonId()); + for (ActivityURL activityUrl : activityUrls) { + processLessonActivity(activityUrl, activities); + } + return activities; + } + + private void processLessonActivity(ActivityURL activityUrl, List activities) { + Activity activity = activityDAO.getActivityByActivityId(activityUrl.getActivityId()); + if (activity instanceof ToolActivity || activity instanceof SequenceActivity) { + activities.add(activity); + } else if (activity instanceof ComplexActivity ) { + for (ActivityURL childUrl : activityUrl.getChildActivities()) { + processLessonActivity(childUrl, activities); + } + } + } + + /** + * Returns lesson activities for a particular user + */ + @SuppressWarnings("unchecked") + private List getLessonActivitiesForLearner(Lesson lesson, Integer learnerId) { + List toolActivities = new ArrayList(); + Object[] objs = getLearnerService().getStructuredActivityURLs(learnerId, lesson.getLessonId()); + // will be null if learner has not started the lesson. + if ( objs != null ) { + List activityUrls = (List) objs[0]; + for (ActivityURL activityUrl : activityUrls) { + processLearnerActivity(activityUrl, toolActivities, false); } } return toolActivities; } - + + private void processLearnerActivity(ActivityURL activityUrl, List toolActivities, boolean includeOnlyAttemptedCompleted) { + Activity activity = activityDAO.getActivityByActivityId(activityUrl.getActivityId()); + if (activity instanceof ToolActivity) { + if ( ! includeOnlyAttemptedCompleted || activityUrl.getStatus() != LearnerProgress.ACTIVITY_NOT_ATTEMPTED ) { + ToolActivity toolActivity = (ToolActivity) activity; + toolActivities.add(toolActivity); + } + } else if (activity instanceof ParallelActivity || activity instanceof FloatingActivity) { + for (ActivityURL childUrl : activityUrl.getChildActivities()) { + processLearnerActivity(childUrl, toolActivities, false); + } + } else if ( activity instanceof OptionsActivity ) { + for (ActivityURL childUrl : activityUrl.getChildActivities()) { + processLearnerActivity(childUrl, toolActivities, true); + } + } + } /** * Gets the internationalised date *