Index: lams_build/lib/lams/lams.jar =================================================================== diff -u -rce9f4e0c6d1e5814bf0dcb0fa16ae888a8c854a3 -r14c33274b785517e5e3f6a7642dc7c6752a34411 Binary files differ Index: lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/lesson/CompletedActivityProgress.hbm.xml =================================================================== diff -u -rc7798d2b81a0595194a5e905ef6c33e372ad8007 -r14c33274b785517e5e3f6a7642dc7c6752a34411 --- lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/lesson/CompletedActivityProgress.hbm.xml (.../CompletedActivityProgress.hbm.xml) (revision c7798d2b81a0595194a5e905ef6c33e372ad8007) +++ lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/lesson/CompletedActivityProgress.hbm.xml (.../CompletedActivityProgress.hbm.xml) (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -4,13 +4,6 @@ "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" > - - Index: lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/lesson/CompletedActivityProgressArchive.hbm.xml =================================================================== diff -u --- lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/lesson/CompletedActivityProgressArchive.hbm.xml (revision 0) +++ lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/lesson/CompletedActivityProgressArchive.hbm.xml (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file Index: lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/lesson/LearnerProgressArchive.hbm.xml =================================================================== diff -u --- lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/lesson/LearnerProgressArchive.hbm.xml (revision 0) +++ lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/lesson/LearnerProgressArchive.hbm.xml (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch2040064.sql =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch2040064.sql (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch2040064.sql (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -0,0 +1,49 @@ +-- Turn off autocommit, so nothing is committed if there is an error +SET AUTOCOMMIT = 0; + +CREATE TABLE lams_learner_progress_archive ( + learner_progress_id bigint(20) NOT NULL AUTO_INCREMENT, + user_id bigint(20) NOT NULL, + lesson_id bigint(20) NOT NULL, + attempt_id TINYINT NOT NULL DEFAULT 1, + lesson_completed_flag tinyint(1) NOT NULL DEFAULT 0, + start_date_time datetime NOT NULL, + finish_date_time datetime, + current_activity_id bigint(20), + PRIMARY KEY (learner_progress_id), + UNIQUE KEY IX_lams_learner_progress_archive_1 (user_id, lesson_id, attempt_id), + CONSTRAINT FK_lams_learner_progress_archive_1 FOREIGN KEY (user_id) + REFERENCES lams_user (user_id) ON UPDATE CASCADE ON DELETE CASCADE, + CONSTRAINT FK_lams_learner_progress_archive_2 FOREIGN KEY (lesson_id) + REFERENCES lams_lesson (lesson_id) ON UPDATE CASCADE ON DELETE CASCADE, + CONSTRAINT FK_lams_learner_progress_archive_3 FOREIGN KEY (current_activity_id) + REFERENCES lams_learning_activity (activity_id) ON UPDATE CASCADE ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET utf8mb4; + + +CREATE TABLE lams_progress_attempted_archive ( + learner_progress_id bigint(20) NOT NULL, + activity_id bigint(20) NOT NULL, + start_date_time datetime, + PRIMARY KEY (learner_progress_id, activity_id), + CONSTRAINT FK_lams_progress_current_archive_1 FOREIGN KEY (learner_progress_id) + REFERENCES lams_learner_progress_archive (learner_progress_id) ON UPDATE CASCADE ON DELETE CASCADE, + CONSTRAINT FK_lams_progress_current_archive_2 FOREIGN KEY (activity_id) + REFERENCES lams_learning_activity (activity_id) ON UPDATE CASCADE ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET utf8mb4; + + +CREATE TABLE lams_progress_completed_archive ( + learner_progress_id bigint(20) NOT NULL, + activity_id bigint(20) NOT NULL, + completed_date_time datetime, + start_date_time datetime, + PRIMARY KEY (learner_progress_id,activity_id), + CONSTRAINT FK_lams_progress_completed_archive_1 FOREIGN KEY (learner_progress_id) + REFERENCES lams_learner_progress_archive (learner_progress_id) ON UPDATE CASCADE ON DELETE CASCADE, + CONSTRAINT FK_lams_progress_completed_archive_2 FOREIGN KEY (activity_id) + REFERENCES lams_learning_activity (activity_id) ON UPDATE CASCADE ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +COMMIT; +SET AUTOCOMMIT = 1; \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/lesson/CompletedActivityProgressArchive.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/lesson/CompletedActivityProgressArchive.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/lesson/CompletedActivityProgressArchive.java (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -0,0 +1,104 @@ +/**************************************************************** + * Copyright (C) 2008 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.lesson; + +import java.io.Serializable; +import java.util.Date; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.lamsfoundation.lams.learningdesign.Activity; + +public class CompletedActivityProgressArchive implements Serializable { + + LearnerProgress learnerProgress; + Activity activity; + Date startDate; + Date finishDate; + + public CompletedActivityProgressArchive() { + } + + public CompletedActivityProgressArchive(LearnerProgress learnerProgress, Activity activity, Date startDate, + Date finishDate) { + this.learnerProgress = learnerProgress; + this.activity = activity; + this.startDate = startDate; + this.finishDate = finishDate; + } + + public LearnerProgress getLearnerProgress() { + return learnerProgress; + } + + public void setLearnerProgress(LearnerProgress learnerProgress) { + this.learnerProgress = learnerProgress; + } + + public Activity getActivity() { + return activity; + } + + public void setActivity(Activity activity) { + this.activity = activity; + } + + public Date getStartDate() { + return startDate; + } + + public void setStartDate(Date startDate) { + this.startDate = startDate; + } + + public Date getFinishDate() { + return finishDate; + } + + public void setFinishDate(Date finishDate) { + this.finishDate = finishDate; + } + + @Override + public boolean equals(Object other) { + if ((this == other)) { + return true; + } + if (!(other instanceof CompletedActivityProgressArchive)) { + return false; + } + CompletedActivityProgressArchive castOther = (CompletedActivityProgressArchive) other; + + EqualsBuilder eq = new EqualsBuilder(); + eq.append(this.getActivity().getActivityId(), castOther.getActivity().getActivityId()); + eq.append(this.getLearnerProgress().getLearnerProgressId(), + castOther.getLearnerProgress().getLearnerProgressId()); + return eq.isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(this.getActivity().getActivityId().toString() + + this.getLearnerProgress().getLearnerProgressId().toString()).toHashCode(); + } +} \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/lesson/LearnerProgressArchive.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/lesson/LearnerProgressArchive.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/lesson/LearnerProgressArchive.java (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -0,0 +1,220 @@ +/*************************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * ***********************************************************************/ + +package org.lamsfoundation.lams.lesson; + +import java.io.Serializable; +import java.util.Date; +import java.util.Map; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.lamsfoundation.lams.learningdesign.Activity; +import org.lamsfoundation.lams.usermanagement.User; + +public class LearnerProgressArchive implements Serializable { + /** Identifier field */ + private Long learnerProgressId; + + /** The User to whom this progress data belongs. */ + private User user; + + /** The Lesson this progress data is for */ + private Lesson lesson; + + private Integer attemptId; + + /** Map of attempted activities with their start date */ + private Map attemptedActivities; + + /** + * Set of completed activities that includes all completed activities before + * current activity + */ + private Map completedActivities; + + /** + * The current activity always present the activity with transition, which + * means it won't be leaf node of a complex activity. To understand the + * activity tree, please read relevant documentation and comment. The + * current content could be the same as next activity if next activity is + * not the leaf node. The main purpose of current activity is to restore the + * progress states if the user exist without finishing the activity. + */ + private Activity currentActivity; + + /** + * Indicates is the User has completed this lesson. + */ + private Byte lessonComplete; + + private Date startDate; + private Date finishDate; + + //--------------------------------------------------------------------- + // Constructors + //--------------------------------------------------------------------- + /** default constructor */ + public LearnerProgressArchive() { + } + + public LearnerProgressArchive(User user, Lesson lesson, Integer attemptId, Map attemptedActivities, + Map completedActivities, Activity currentActivity, + Byte lessonComplete, Date startDate, Date finishDate) { + this.user = user; + this.lesson = lesson; + this.attemptId = attemptId; + this.attemptedActivities = attemptedActivities; + this.completedActivities = completedActivities; + this.currentActivity = currentActivity; + this.lessonComplete = lessonComplete; + this.startDate = startDate; + this.finishDate = finishDate; + } + + //--------------------------------------------------------------------- + // Getters and Setters + //--------------------------------------------------------------------- + public Long getLearnerProgressId() { + return this.learnerProgressId; + } + + public void setLearnerProgressId(Long learnerProgressId) { + this.learnerProgressId = learnerProgressId; + } + + public User getUser() { + return this.user; + } + + public void setUser(User user) { + this.user = user; + } + + public Lesson getLesson() { + return this.lesson; + } + + public void setLesson(Lesson lesson) { + this.lesson = lesson; + } + + public Integer getAttemptId() { + return attemptId; + } + + public void setAttemptId(Integer attemptId) { + this.attemptId = attemptId; + } + + public Map getAttemptedActivities() { + return this.attemptedActivities; + } + + public void setAttemptedActivities(Map attemptedActivities) { + this.attemptedActivities = attemptedActivities; + } + + public Map getCompletedActivities() { + return this.completedActivities; + } + + public void setCompletedActivities(Map completedActivities) { + this.completedActivities = completedActivities; + } + + @Override + public String toString() { + return new ToStringBuilder(this).append("learnerProgressId", getLearnerProgressId()).toString(); + } + + @Override + public boolean equals(Object other) { + if ((this == other)) { + return true; + } + if (!(other instanceof LearnerProgressArchive)) { + return false; + } + LearnerProgressArchive castOther = (LearnerProgressArchive) other; + return new EqualsBuilder().append(this.getLearnerProgressId(), castOther.getLearnerProgressId()).isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(getLearnerProgressId()).toHashCode(); + } + + public Activity getCurrentActivity() { + return this.currentActivity; + } + + public void setCurrentActivity(Activity currentActivity) { + this.currentActivity = currentActivity; + } + + /** + * Has the user completed the lesson? We don't care how (ie at end of + * sequence or after a "stop after activity") + */ + public boolean isComplete() { + return lessonComplete == LearnerProgress.LESSON_END_OF_DESIGN_COMPLETE + || lessonComplete == LearnerProgress.LESSON_IN_DESIGN_COMPLETE; + } + + /** + * The "real" value for lessonComplete. + * + * @return LESSON_NOT_COMPLETE, LESSON_END_OF_DESIGN_COMPLETE, + * LESSON_IN_DESIGN_COMPLETE + */ + public Byte getLessonComplete() { + return lessonComplete; + } + + /** + * Setter for property lessonComplete. + * + * @param lessonComplete + * New value of property lessonComplete. + */ + public void setLessonComplete(Byte lessonComplete) { + this.lessonComplete = lessonComplete; + } + + public Date getFinishDate() { + return finishDate; + } + + public void setFinishDate(Date finishDate) { + this.finishDate = finishDate; + } + + public Date getStartDate() { + return startDate; + } + + public void setStartDate(Date startDate) { + this.startDate = startDate; + } +} \ No newline at end of file Fisheye: Tag 14c33274b785517e5e3f6a7642dc7c6752a34411 refers to a dead (removed) revision in file `lams_common/src/java/org/lamsfoundation/lams/lesson/ProgressCompletedActivity.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_common/src/java/org/lamsfoundation/lams/lesson/dao/ILearnerProgressDAO.java =================================================================== diff -u -r51fb2a37254f24bb2a805d4ffd54482c779f43fa -r14c33274b785517e5e3f6a7642dc7c6752a34411 --- lams_common/src/java/org/lamsfoundation/lams/lesson/dao/ILearnerProgressDAO.java (.../ILearnerProgressDAO.java) (revision 51fb2a37254f24bb2a805d4ffd54482c779f43fa) +++ lams_common/src/java/org/lamsfoundation/lams/lesson/dao/ILearnerProgressDAO.java (.../ILearnerProgressDAO.java) (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -150,8 +150,8 @@ List getLearnersAttemptedActivity(Activity activity); /** - * Get all the users records where the user has ever attempted the given activity. Uses the progress records to - * determine the users. + * Get all the users records where the user has completed the given activity. Uses the progress records to determine + * the users. */ List getLearnersCompletedActivity(Activity activity); @@ -196,4 +196,9 @@ * Get number of learners who are at the given activities at the moment. */ Map getNumUsersCurrentActivities(Long[] activityIds); + + /** + * Get the last attempt ID for the given learner and lesson. + */ + Integer getLearnerProgressArchiveMaxAttemptID(Integer userId, Long lessonId); } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/lesson/dao/hibernate/LearnerProgressDAO.java =================================================================== diff -u -r51fb2a37254f24bb2a805d4ffd54482c779f43fa -r14c33274b785517e5e3f6a7642dc7c6752a34411 --- lams_common/src/java/org/lamsfoundation/lams/lesson/dao/hibernate/LearnerProgressDAO.java (.../LearnerProgressDAO.java) (revision 51fb2a37254f24bb2a805d4ffd54482c779f43fa) +++ lams_common/src/java/org/lamsfoundation/lams/lesson/dao/hibernate/LearnerProgressDAO.java (.../LearnerProgressDAO.java) (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -47,9 +47,11 @@ protected Logger log = Logger.getLogger(LearnerProgressDAO.class); - private final static String LOAD_PROGRESS_BY_LEARNER = "from LearnerProgress p where p.user.id = :learnerId and p.lesson.id = :lessonId"; + private final static String LOAD_PROGRESS_BY_LEARNER = "from LearnerProgress p where p.user.id = :learnerId " + + "and p.lesson.id = :lessonId"; - private final static String LOAD_PROGRESS_REFFERING_TO_ACTIVITY = "from LearnerProgress p where p.previousActivity = :activity or p.currentActivity = :activity or p.nextActivity = :activity "; + private final static String LOAD_PROGRESS_REFFERING_TO_ACTIVITY = "from LearnerProgress p " + + "where p.previousActivity = :activity or p.currentActivity = :activity or p.nextActivity = :activity "; private final static String LOAD_COMPLETED_PROGRESS_BY_LESSON = "FROM LearnerProgress p WHERE p.lessonComplete > 0 " + "AND p.lesson.id = :lessonId ORDER BY p.user.firstName , p.user.lastName , p.user.login "; @@ -75,7 +77,8 @@ + " index(compAct) = act"; private final static String COUNT_CURRENT_ACTIVITY = "select prog.currentActivity.activityId, count(prog) " - + "from LearnerProgress prog WHERE prog.currentActivity.activityId IN (:activityIds) GROUP BY prog.currentActivity.activityId"; + + "from LearnerProgress prog WHERE prog.currentActivity.activityId IN (:activityIds) " + + "GROUP BY prog.currentActivity.activityId"; private final static String LOAD_PROGRESS_BY_LESSON = "from LearnerProgress p " + " where p.lesson.id = :lessonId order by p.user.lastName, p.user.firstName, p.user.userId"; @@ -110,6 +113,9 @@ private final static String LOAD_LEARNERS_BY_MOST_PROGRESS_ORDER_CLAUSE = " GROUP BY u.user_id " + "ORDER BY prog.lesson_completed_flag DESC, comp_count DESC, u.first_name ASC, u.last_name ASC, u.login ASC"; + private final static String FIND_PROGRESS_ARCHIVE_MAX_ATTEMPT = "SELECT MAX(p.attemptId) FROM LearnerProgressArchive p " + + "WHERE p.user.id = :learnerId AND p.lesson.id = :lessonId"; + @Override public LearnerProgress getLearnerProgress(Long learnerProgressId) { return (LearnerProgress) getSession().get(LearnerProgress.class, learnerProgressId); @@ -338,4 +344,11 @@ } return result; } + + @Override + public Integer getLearnerProgressArchiveMaxAttemptID(Integer userId, Long lessonId) { + Object value = getSession().createQuery(LearnerProgressDAO.FIND_PROGRESS_ARCHIVE_MAX_ATTEMPT) + .setInteger("learnerId", userId).setLong("lessonId", lessonId).uniqueResult(); + return value == null ? null : ((Number) value).intValue(); + } } \ No newline at end of file Index: lams_learning/.classpath =================================================================== diff -u -r9c603f82a3332d5e2e5b290bcc550f263c09a8f8 -r14c33274b785517e5e3f6a7642dc7c6752a34411 --- lams_learning/.classpath (.../.classpath) (revision 9c603f82a3332d5e2e5b290bcc550f263c09a8f8) +++ lams_learning/.classpath (.../.classpath) (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -20,5 +20,6 @@ + Index: lams_learning/conf/language/lams/ApplicationResources.properties =================================================================== diff -u -r51fb2a37254f24bb2a805d4ffd54482c779f43fa -r14c33274b785517e5e3f6a7642dc7c6752a34411 --- lams_learning/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 51fb2a37254f24bb2a805d4ffd54482c779f43fa) +++ lams_learning/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -14,6 +14,8 @@ message.activity.loading =The next task is loading. Please wait.... message.lesson.finished =Congratulations, {0}, you have finished. message.lesson.finishedCont =You have now completed the {0} lesson. You can return at anytime to this lesson and revisit and review activities by double clicking on the blue icons in the left hand progress bar. You can now close this window. +message.lesson.restart =You can give the lesson another an attempt by pressing this button: +message.lesson.restart.button =Restart exit.heading =You have exited from this Lesson. exit.message =You can resume this lesson using the Resume button. label.next.button =Next Index: lams_learning/src/java/org/lamsfoundation/lams/learning/service/ICoreLearnerService.java =================================================================== diff -u -r51fb2a37254f24bb2a805d4ffd54482c779f43fa -r14c33274b785517e5e3f6a7642dc7c6752a34411 --- lams_learning/src/java/org/lamsfoundation/lams/learning/service/ICoreLearnerService.java (.../ICoreLearnerService.java) (revision 51fb2a37254f24bb2a805d4ffd54482c779f43fa) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/service/ICoreLearnerService.java (.../ICoreLearnerService.java) (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -91,6 +91,11 @@ * in case of problems. */ LearnerProgress getProgress(Integer learnerId, Long lessonId); + + /** + * Get the last attempt ID for the given learner and lesson. + */ + Integer getProgressArchiveMaxAttemptID(Integer userId, Long lessonId); /** * Returns the current progress data, in the DTO format required by the jsp progress screen, of the User. Index: lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerService.java =================================================================== diff -u -r51fb2a37254f24bb2a805d4ffd54482c779f43fa -r14c33274b785517e5e3f6a7642dc7c6752a34411 --- lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerService.java (.../LearnerService.java) (revision 51fb2a37254f24bb2a805d4ffd54482c779f43fa) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerService.java (.../LearnerService.java) (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -383,6 +383,11 @@ public LearnerProgress getProgressById(Long progressId) { return learnerProgressDAO.getLearnerProgress(progressId); } + + @Override + public Integer getProgressArchiveMaxAttemptID(Integer userId, Long lessonId) { + return learnerProgressDAO.getLearnerProgressArchiveMaxAttemptID(userId, lessonId); + } /** * @see org.lamsfoundation.lams.learning.service.ICoreLearnerService#getStructuredProgressDTOs(java.lang.Long, Index: lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerServiceProxy.java =================================================================== diff -u -r51fb2a37254f24bb2a805d4ffd54482c779f43fa -r14c33274b785517e5e3f6a7642dc7c6752a34411 --- lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerServiceProxy.java (.../LearnerServiceProxy.java) (revision 51fb2a37254f24bb2a805d4ffd54482c779f43fa) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerServiceProxy.java (.../LearnerServiceProxy.java) (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -27,6 +27,7 @@ import javax.servlet.ServletContext; import org.lamsfoundation.lams.learning.web.util.ActivityMapping; +import org.lamsfoundation.lams.monitoring.service.IMonitoringService; import org.lamsfoundation.lams.tool.service.ILamsToolService; import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; import org.springframework.web.context.WebApplicationContext; @@ -81,6 +82,10 @@ return (ILamsToolService) LearnerServiceProxy.getDomainService(serlvetContext, "lamsToolService"); } + public static final IMonitoringService getMonitoringService(ServletContext servletContext) { + return (IMonitoringService) LearnerServiceProxy.getDomainService(servletContext, "monitoringService"); + } + /** * Return the activity mapping service object. * Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/CompleteActivityAction.java =================================================================== diff -u -r51fb2a37254f24bb2a805d4ffd54482c779f43fa -r14c33274b785517e5e3f6a7642dc7c6752a34411 --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/CompleteActivityAction.java (.../CompleteActivityAction.java) (revision 51fb2a37254f24bb2a805d4ffd54482c779f43fa) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/CompleteActivityAction.java (.../CompleteActivityAction.java) (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -89,6 +89,7 @@ if (lessonFinishCallbackUrl != null) { request.setAttribute("lessonFinishUrl", lessonFinishCallbackUrl); } + request.setAttribute("lessonID", progress.getLesson().getLessonId()); } ActionForward forward = null; Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LearnerAction.java =================================================================== diff -u -r3f6c00240dc337444f6c371b7a56334f61a4bb9f -r14c33274b785517e5e3f6a7642dc7c6752a34411 --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LearnerAction.java (.../LearnerAction.java) (revision 3f6c00240dc337444f6c371b7a56334f61a4bb9f) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LearnerAction.java (.../LearnerAction.java) (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -24,7 +24,11 @@ package org.lamsfoundation.lams.learning.web.action; import java.io.IOException; +import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -44,10 +48,15 @@ import org.lamsfoundation.lams.learning.web.util.ActivityMapping; import org.lamsfoundation.lams.learning.web.util.LearningWebUtil; import org.lamsfoundation.lams.learningdesign.Activity; +import org.lamsfoundation.lams.lesson.CompletedActivityProgress; +import org.lamsfoundation.lams.lesson.CompletedActivityProgressArchive; import org.lamsfoundation.lams.lesson.LearnerProgress; +import org.lamsfoundation.lams.lesson.LearnerProgressArchive; import org.lamsfoundation.lams.lesson.Lesson; +import org.lamsfoundation.lams.monitoring.service.IMonitoringService; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; import org.lamsfoundation.lams.util.Configuration; import org.lamsfoundation.lams.util.ConfigurationKeys; import org.lamsfoundation.lams.util.WebUtil; @@ -172,6 +181,53 @@ } /** + * Archives current learner progress and moves a learner back to the start of lesson. + */ + public ActionForward restartLesson(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + // fetch necessary parameters + long lessonID = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + User user = LearningWebUtil.getUser(learnerService); + Integer userID = user.getUserId(); + + // find number of previous attempts + Integer attemptID = learnerService.getProgressArchiveMaxAttemptID(userID, lessonID); + if (attemptID == null) { + attemptID = 0; + } + attemptID++; + + // make a copy of attempted and completed activities + LearnerProgress learnerProgress = learnerService.getProgress(userID, lessonID); + Map attemptedActivities = new HashMap(learnerProgress.getAttemptedActivities()); + Map completedActivities = new HashMap(); + for (Entry entry : learnerProgress.getCompletedActivities().entrySet()) { + CompletedActivityProgressArchive activityArchive = new CompletedActivityProgressArchive(learnerProgress, + entry.getKey(), entry.getValue().getStartDate(), entry.getValue().getFinishDate()); + completedActivities.put(entry.getKey(), activityArchive); + } + + // save the historic attempt + LearnerProgressArchive learnerProgressArchive = new LearnerProgressArchive(user, learnerProgress.getLesson(), + attemptID, attemptedActivities, completedActivities, learnerProgress.getCurrentActivity(), + learnerProgress.getLessonComplete(), learnerProgress.getStartDate(), learnerProgress.getFinishDate()); + + // move learner to the beginning of lesson the same way Monitor can + IMonitoringService monitoringService = LearnerServiceProxy + .getMonitoringService(getServlet().getServletContext()); + monitoringService.forceCompleteActivitiesByUser(userID, userID, lessonID, + learnerProgress.getLesson().getLearningDesign().getFirstActivity().getActivityId(), true); + + IUserManagementService userManagementService = LearnerServiceProxy + .getUserManagementService(getServlet().getServletContext()); + userManagementService.save(learnerProgressArchive); + + // display Learner interface with updated data + return joinLesson(mapping, form, request, response); + } + + /** * Produces necessary data for learner progress bar. */ @SuppressWarnings("unchecked") Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LessonCompleteActivityAction.java =================================================================== diff -u -r51fb2a37254f24bb2a805d4ffd54482c779f43fa -r14c33274b785517e5e3f6a7642dc7c6752a34411 --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LessonCompleteActivityAction.java (.../LessonCompleteActivityAction.java) (revision 51fb2a37254f24bb2a805d4ffd54482c779f43fa) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LessonCompleteActivityAction.java (.../LessonCompleteActivityAction.java) (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -84,6 +84,7 @@ if (lessonFinishCallbackUrl != null) { request.setAttribute("lessonFinishUrl", lessonFinishCallbackUrl); } + request.setAttribute("lessonID", learnerProgress.getLesson().getLessonId()); return mapping.findForward("lessonComplete"); } Index: lams_learning/web/lessonComplete.jsp =================================================================== diff -u -r02e61ba9a9752984ac1296ac635e4d61c7ce5d2c -r14c33274b785517e5e3f6a7642dc7c6752a34411 --- lams_learning/web/lessonComplete.jsp (.../lessonComplete.jsp) (revision 02e61ba9a9752984ac1296ac635e4d61c7ce5d2c) +++ lams_learning/web/lessonComplete.jsp (.../lessonComplete.jsp) (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -56,6 +56,13 @@ +
+ + + + +
+
Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java =================================================================== diff -u -r3399163940c61c9132223c758d274486e57ff9b7 -r14c33274b785517e5e3f6a7642dc7c6752a34411 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java (.../MonitoringService.java) (revision 3399163940c61c9132223c758d274486e57ff9b7) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java (.../MonitoringService.java) (revision 14c33274b785517e5e3f6a7642dc7c6752a34411) @@ -989,7 +989,11 @@ @Override public String forceCompleteActivitiesByUser(Integer learnerId, Integer requesterId, long lessonId, Long activityId, boolean removeLearnerContent) { - securityService.isLessonMonitor(lessonId, requesterId, "force complete", true); + if (requesterId.equals(learnerId)) { + securityService.isLessonLearner(lessonId, requesterId, "force complete", true); + } else { + securityService.isLessonMonitor(lessonId, requesterId, "force complete", true); + } Lesson lesson = lessonDAO.getLesson(new Long(lessonId)); User learner = (User) baseDAO.find(User.class, learnerId);