Index: lams_tool_assessment/.classpath =================================================================== RCS file: /usr/local/cvsroot/lams_tool_assessment/.classpath,v diff -u -r1.10 -r1.11 --- lams_tool_assessment/.classpath 4 Sep 2013 17:25:04 -0000 1.10 +++ lams_tool_assessment/.classpath 8 Jan 2014 17:47:02 -0000 1.11 @@ -18,6 +18,11 @@ + + + + + Index: lams_tool_assessment/conf/language/lams/ApplicationResources_en_AU.properties =================================================================== RCS file: /usr/local/cvsroot/lams_tool_assessment/conf/language/lams/ApplicationResources_en_AU.properties,v diff -u -r1.48 -r1.49 --- lams_tool_assessment/conf/language/lams/ApplicationResources_en_AU.properties 29 Sep 2013 23:24:38 -0000 1.48 +++ lams_tool_assessment/conf/language/lams/ApplicationResources_en_AU.properties 8 Jan 2014 17:47:02 -0000 1.49 @@ -283,5 +283,11 @@ label.authoring.advance.numbered.questions =Enable questions' numbering label.learning.draft.autosaved =Draft autosaved +label.waiting.for.leader =Please, wait while somebody will become a group leader. +label.users.from.group =Other users participating in current group: +label.use.select.leader.tool.output =Use leaders from Select Leader tool +label.group.leader =Group Leader: {0} +label.refresh =Refresh +label.display.name.column =Display name column #======= End labels: Exported 276 labels for en AU ===== Index: lams_tool_assessment/conf/xdoclet/struts-actions.xml =================================================================== RCS file: /usr/local/cvsroot/lams_tool_assessment/conf/xdoclet/struts-actions.xml,v diff -u -r1.18 -r1.19 --- lams_tool_assessment/conf/xdoclet/struts-actions.xml 27 Sep 2013 17:16:31 -0000 1.18 +++ lams_tool_assessment/conf/xdoclet/struts-actions.xml 8 Jan 2014 17:47:02 -0000 1.19 @@ -218,7 +218,8 @@ parameter="start" > - + + + + + Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/AssessmentConstants.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/AssessmentConstants.java,v diff -u -r1.21 -r1.22 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/AssessmentConstants.java 17 Feb 2013 16:12:00 -0000 1.21 +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/AssessmentConstants.java 8 Jan 2014 17:47:02 -0000 1.22 @@ -61,6 +61,8 @@ public static final String ERROR = "error"; public static final String DEFINE_LATER = "definelater"; + + public static final String WAIT_FOR_LEADER = "waitForLeader"; // for parameters' name public static final String PARAM_TOOL_CONTENT_ID = "toolContentID"; @@ -94,6 +96,12 @@ public static final String PARAM_QUESTION_RESULT_UID = "questionResultUid"; // for request attribute name + public static final String ATTR_GROUP_USERS = "groupUsers"; + + public static final String ATTR_IS_USER_LEADER = "isUserLeader"; + + public static final String ATTR_GROUP_LEADER = "groupLeader"; + public static final String ATTR_TOOL_CONTENT_ID = "toolContentID"; public static final String ATTR_TOOL_SESSION_ID = "toolSessionID"; Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/assessmentApplicationContext.xml =================================================================== RCS file: /usr/local/cvsroot/lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/assessmentApplicationContext.xml,v diff -u -r1.11 -r1.12 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/assessmentApplicationContext.xml 27 Sep 2013 17:16:31 -0000 1.11 +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/assessmentApplicationContext.xml 8 Jan 2014 17:47:02 -0000 1.12 @@ -123,7 +123,13 @@ - + + + + + + + @@ -157,6 +163,9 @@ PROPAGATION_REQUIRED,+java.lang.Exception PROPAGATION_REQUIRED,+java.lang.Exception PROPAGATION_REQUIRED,+java.lang.Exception + PROPAGATION_REQUIRED,+java.lang.Exception + PROPAGATION_REQUIRED,+java.lang.Exception + PROPAGATION_REQUIRED,+java.lang.Exception Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dbupdates/patch20140101.sql =================================================================== RCS file: /usr/local/cvsroot/lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dbupdates/patch20140101.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/dbupdates/patch20140101.sql 8 Jan 2014 17:47:02 -0000 1.1 @@ -0,0 +1,19 @@ +-- Turn off autocommit, so nothing is committed if there is an error +SET AUTOCOMMIT = 0; +SET FOREIGN_KEY_CHECKS=0; +----------------------Put all sql statements below here------------------------- + +-- LDEV-3155 adding all the leader aware tools (lamc,assessment,qa) to regular LAMS +ALTER TABLE tl_laasse10_assessment ADD COLUMN use_select_leader_tool_ouput TINYINT(1) NOT NULL DEFAULT 0; +ALTER TABLE tl_laasse10_session ADD COLUMN group_leader_uid BIGINT; +ALTER TABLE tl_laasse10_session ADD INDEX FK_laasse10_session_1 (group_leader_uid), ADD CONSTRAINT tl_laasse10_session FOREIGN KEY (group_leader_uid) REFERENCES tl_laasse10_user (uid) ON DELETE CASCADE ON UPDATE CASCADE; + +-- adding a constraint to the assessment user table so no same user_id and session_id can be repetead +ALTER TABLE tl_laasse10_user ADD UNIQUE INDEX(user_id, session_uid); + +----------------------Put all sql statements above here------------------------- + +-- If there were no errors, commit and restore autocommit to on +COMMIT; +SET AUTOCOMMIT = 1; +SET FOREIGN_KEY_CHECKS=1; \ No newline at end of file Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/model/Assessment.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/model/Assessment.java,v diff -u -r1.13 -r1.14 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/model/Assessment.java 11 Jun 2013 10:30:18 -0000 1.13 +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/model/Assessment.java 8 Jan 2014 17:47:01 -0000 1.14 @@ -61,6 +61,8 @@ private String instructions; // advance + private boolean useSelectLeaderToolOuput; + private int timeLimit; private int questionsPerPage; @@ -424,7 +426,21 @@ public void setRunOffline(boolean forceOffline) { runOffline = forceOffline; } + + /** + * If the tool utilizes leaders from Select Leader tool. + * + * @return + * @hibernate.property column="use_select_leader_tool_ouput" + */ + public boolean isUseSelectLeaderToolOuput() { + return useSelectLeaderToolOuput; + } + public void setUseSelectLeaderToolOuput(boolean useSelectLeaderToolOuput) { + this.useSelectLeaderToolOuput = useSelectLeaderToolOuput; + } + /** * @return Returns the time limitation, that students have to complete an attempt. * Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/model/AssessmentSession.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/model/AssessmentSession.java,v diff -u -r1.2 -r1.3 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/model/AssessmentSession.java 1 Jul 2009 02:39:10 -0000 1.2 +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/model/AssessmentSession.java 8 Jan 2014 17:47:02 -0000 1.3 @@ -51,6 +51,7 @@ // assessment Questions private Set assessmentQuestions; private Set assessmentUsers; + private AssessmentUser groupLeader; // ********************************************************** // Get/Set methods @@ -164,8 +165,6 @@ /** - * - * * @hibernate.set lazy="true" inverse="false" cascade="all" order-by="last_name asc" * @hibernate.collection-key column="session_uid" * @hibernate.collection-one-to-many class="org.lamsfoundation.lams.tool.assessment.model.AssessmentUser" @@ -180,6 +179,16 @@ this.assessmentUsers = assessmentUsers; } - + /** + * @hibernate.many-to-one column="group_leader_uid" cascade="all" + * @return + */ + public AssessmentUser getGroupLeader() { + return this.groupLeader; + } + public void setGroupLeader(AssessmentUser groupLeader) { + this.groupLeader = groupLeader; + } + } Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java,v diff -u -r1.34 -r1.35 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java 18 Nov 2013 19:45:31 -0000 1.34 +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java 8 Jan 2014 17:47:02 -0000 1.35 @@ -32,6 +32,7 @@ import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedHashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -47,7 +48,6 @@ import org.lamsfoundation.lams.contentrepository.AccessDeniedException; import org.lamsfoundation.lams.contentrepository.ICredentials; import org.lamsfoundation.lams.contentrepository.ITicket; -import org.lamsfoundation.lams.contentrepository.IVersionedNode; import org.lamsfoundation.lams.contentrepository.InvalidParameterException; import org.lamsfoundation.lams.contentrepository.LoginException; import org.lamsfoundation.lams.contentrepository.NodeKey; @@ -58,9 +58,13 @@ import org.lamsfoundation.lams.events.IEventNotificationService; import org.lamsfoundation.lams.gradebook.service.IGradebookService; import org.lamsfoundation.lams.learning.service.ILearnerService; +import org.lamsfoundation.lams.learningdesign.Activity; +import org.lamsfoundation.lams.learningdesign.ToolActivity; +import org.lamsfoundation.lams.learningdesign.dao.IActivityDAO; import org.lamsfoundation.lams.learningdesign.service.ExportToolContentException; import org.lamsfoundation.lams.learningdesign.service.IExportToolContentService; import org.lamsfoundation.lams.learningdesign.service.ImportToolContentException; +import org.lamsfoundation.lams.lesson.Lesson; import org.lamsfoundation.lams.lesson.service.ILessonService; import org.lamsfoundation.lams.notebook.model.NotebookEntry; import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; @@ -69,6 +73,7 @@ import org.lamsfoundation.lams.tool.ToolContentManager; import org.lamsfoundation.lams.tool.ToolOutput; import org.lamsfoundation.lams.tool.ToolOutputDefinition; +import org.lamsfoundation.lams.tool.ToolSession; import org.lamsfoundation.lams.tool.ToolSessionExportOutputData; import org.lamsfoundation.lams.tool.ToolSessionManager; import org.lamsfoundation.lams.tool.assessment.AssessmentConstants; @@ -104,16 +109,17 @@ import org.lamsfoundation.lams.tool.exception.SessionDataExistsException; import org.lamsfoundation.lams.tool.exception.ToolException; import org.lamsfoundation.lams.tool.service.ILamsToolService; +import org.lamsfoundation.lams.usermanagement.Organisation; +import org.lamsfoundation.lams.usermanagement.OrganisationType; +import org.lamsfoundation.lams.usermanagement.Role; 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.MessageService; import org.lamsfoundation.lams.util.audit.IAuditService; /** - * * @author Andrey Balan - * */ public class AssessmentServiceImpl implements IAssessmentService, ToolContentManager, ToolSessionManager, ToolContentImport102Manager { @@ -146,7 +152,7 @@ private ILamsToolService toolService; private ILearnerService learnerService; - + private IAuditService auditService; private IUserManagementService userManagementService; @@ -160,11 +166,140 @@ private IEventNotificationService eventNotificationService; private ILessonService lessonService; + + private IActivityDAO activityDAO; + + private IUserManagementService userService; // ******************************************************************************* // Service method // ******************************************************************************* + @Override + public boolean isUserGroupLeader(AssessmentUser user, Long toolSessionId) { + AssessmentSession session = this.getAssessmentSessionBySessionId(toolSessionId); + AssessmentUser groupLeader = session.getGroupLeader(); + + boolean isUserLeader = (groupLeader != null) && user.getUid().equals(groupLeader.getUid()); + return isUserLeader; + } + + @Override + public AssessmentUser checkLeaderSelectToolForSessionLeader(AssessmentUser user, Long toolSessionId) { + if (user == null || toolSessionId == null) { + return null; + } + + AssessmentSession assessmentSession = this.getAssessmentSessionBySessionId(toolSessionId); + AssessmentUser leader = assessmentSession.getGroupLeader(); + // check leader select tool for a leader only in case QA tool doesn't know it. As otherwise it will screw + // up previous scratches done + if (leader == null) { + + Long leaderUserId = toolService.getLeaderUserId(toolSessionId, user.getUserId().intValue()); + if (leaderUserId != null) { + leader = this.getUserByIDAndSession(leaderUserId, toolSessionId); + + // create new user in a DB + if (leader == null) { + log.debug("creating new user with userId: " + leaderUserId); + User leaderDto = (User) getUserManagementService().findById(User.class, leaderUserId.intValue()); + String userName = leaderDto.getLogin(); + String fullName = leaderDto.getFirstName() + " " + leaderDto.getLastName(); + leader = new AssessmentUser(leaderDto.getUserDTO(), assessmentSession); + this.createUser(leader); + } + + // set group leader + assessmentSession.setGroupLeader(leader); + assessmentSessionDao.saveObject(assessmentSession); + } + } + + return leader; + } + + @Override + public void copyAnswersFromLeader(AssessmentUser user, AssessmentUser leader) { + + if ((user == null) || (leader == null) || user.getUid().equals(leader.getUid())) { + return; + } + Long assessmentUid = leader.getSession().getAssessment().getUid(); + + AssessmentResult leaderResult = assessmentResultDao.getLastFinishedAssessmentResult(assessmentUid, leader.getUserId()); + AssessmentResult userResult = assessmentResultDao.getLastAssessmentResult(assessmentUid, user.getUserId()); + Set leaderQuestionResults = leaderResult.getQuestionResults(); + + // if response doesn't exist create new empty objects which we populate on the next step + if (userResult == null) { + userResult = new AssessmentResult(); + userResult.setAssessment(leaderResult.getAssessment()); + userResult.setUser(user); + userResult.setSessionId(leaderResult.getSessionId()); + + Set userQuestionResults = userResult.getQuestionResults(); + for (AssessmentQuestionResult leaderQuestionResult: leaderQuestionResults) { + AssessmentQuestionResult userQuestionResult = new AssessmentQuestionResult(); + userQuestionResult.setAssessmentQuestion(leaderQuestionResult.getAssessmentQuestion()); + userQuestionResult.setAssessmentResult(userResult); + userQuestionResults.add(userQuestionResult); + + Set leaderOptionAnswers = leaderQuestionResult.getOptionAnswers(); + Set userOptionAnswers = userQuestionResult.getOptionAnswers(); + for (AssessmentOptionAnswer leaderOptionAnswer: leaderOptionAnswers) { + AssessmentOptionAnswer userOptionAnswer = new AssessmentOptionAnswer(); + userOptionAnswer.setQuestionOptionUid(leaderOptionAnswer.getQuestionOptionUid()); + userOptionAnswers.add(userOptionAnswer); + } + } + } + + //copy results from leader to user in both cases (when there is no userResult yet and when if it's been changed by the leader) + userResult.setStartDate(leaderResult.getStartDate()); + userResult.setFinishDate(leaderResult.getFinishDate()); + userResult.setMaximumGrade(leaderResult.getMaximumGrade()); + userResult.setGrade(leaderResult.getGrade()); + + Set userQuestionResults = userResult.getQuestionResults(); + for (AssessmentQuestionResult leaderQuestionResult : leaderQuestionResults) { + for (AssessmentQuestionResult userQuestionResult : userQuestionResults) { + if (userQuestionResult.getAssessmentQuestion().getUid().equals(leaderQuestionResult.getAssessmentQuestion().getUid())) { + + userQuestionResult.setAnswerString(leaderQuestionResult.getAnswerString()); + userQuestionResult.setAnswerFloat(leaderQuestionResult.getAnswerFloat()); + userQuestionResult.setAnswerBoolean(leaderQuestionResult.getAnswerBoolean()); + userQuestionResult.setSubmittedOptionUid(leaderQuestionResult.getSubmittedOptionUid()); + userQuestionResult.setMark(leaderQuestionResult.getMark()); + userQuestionResult.setMaxMark(leaderQuestionResult.getMaxMark()); + userQuestionResult.setPenalty(leaderQuestionResult.getPenalty()); + + Set leaderOptionAnswers = leaderQuestionResult.getOptionAnswers(); + Set userOptionAnswers = userQuestionResult.getOptionAnswers(); + for (AssessmentOptionAnswer leaderOptionAnswer : leaderOptionAnswers) { + for (AssessmentOptionAnswer userOptionAnswer : userOptionAnswers) { + if (userOptionAnswer.getQuestionOptionUid().equals(leaderOptionAnswer.getQuestionOptionUid())) { + + userOptionAnswer.setAnswerBoolean(leaderOptionAnswer.getAnswerBoolean()); + userOptionAnswer.setAnswerInt(leaderOptionAnswer.getAnswerInt()); + + } + } + + } + + } + } + } + + assessmentResultDao.saveObject(userResult); + } + + @Override + public List getUsersBySession(Long toolSessionID) { + return assessmentUserDao.getBySessionID(toolSessionID); + } + /** * This method verifies the credentials of the Assessment Tool and gives it the Ticket to login and * access the Content Repository. @@ -608,10 +743,20 @@ List sessionList = assessmentSessionDao.getByContentId(contentId); for (AssessmentSession session : sessionList) { Long sessionId = session.getSessionId(); + Assessment assessment = session.getAssessment(); // one new summary for one session. Summary summary = new Summary(sessionId, session.getSessionName()); - List users = assessmentUserDao.getBySessionID(sessionId); + List users = new LinkedList(); + if (assessment.isUseSelectLeaderToolOuput()) { + AssessmentUser groupLeader = session.getGroupLeader(); + if (groupLeader != null) { + users.add(groupLeader); + } + } else { + users = assessmentUserDao.getBySessionID(sessionId); + } + ArrayList assessmentResults = new ArrayList(); for (AssessmentUser user : users) { AssessmentResult assessmentResult = assessmentResultDao.getLastFinishedAssessmentResultBySessionId( @@ -709,11 +854,23 @@ List> questionResults = new ArrayList>(); SortedSet sessionList = new TreeSet(new AssessmentSessionComparator()); sessionList.addAll(assessmentSessionDao.getByContentId(contentId)); + for (AssessmentSession session : sessionList) { + + Assessment assessment = session.getAssessment(); Long sessionId = session.getSessionId(); - List users = assessmentUserDao.getBySessionID(sessionId); - // Set sessionQuestionResults = new TreeSet( - // new AssessmentQuestionResultComparator()); + List users = new ArrayList(); + + //in case of leader aware tool show only leaders' responses + if (assessment.isUseSelectLeaderToolOuput()) { + AssessmentUser leader = session.getGroupLeader(); + if (leader != null) { + users.add(leader); + } + } else { + users = assessmentUserDao.getBySessionID(sessionId); + } + ArrayList sessionQuestionResults = new ArrayList(); for (AssessmentUser user : users) { AssessmentResult assessmentResult = assessmentResultDao.getLastFinishedAssessmentResultBySessionId( @@ -763,22 +920,145 @@ AssessmentQuestionResult questionResult = assessmentQuestionResultDao .getAssessmentQuestionResultByUid(questionResultUid); float oldMark = questionResult.getMark(); - questionResult.setMark(newMark); - assessmentQuestionResultDao.saveObject(questionResult); + AssessmentResult assessmentResult = questionResult.getAssessmentResult(); + float totalMark = assessmentResult.getGrade() - oldMark + newMark; + + Long toolSessionId = questionResult.getAssessmentResult().getSessionId(); + Assessment assessment = questionResult.getAssessmentResult().getAssessment(); + Long questionUid = questionResult.getAssessmentQuestion().getUid(); + + // When changing a mark for user and isUseSelectLeaderToolOuput is true, the mark should be propagated to all + // students within the group + List users = new ArrayList(); + if (assessment.isUseSelectLeaderToolOuput()) { + users = this.getUsersBySession(toolSessionId); + } else { + users = new ArrayList(); + AssessmentUser leader = questionResult.getUser(); + users.add(leader); + } + + for (AssessmentUser user : users) { + Long userId = user.getUserId(); + + List questionResults = assessmentQuestionResultDao + .getAssessmentQuestionResultList(assessment.getUid(), userId, questionUid); - AssessmentResult result = questionResult.getAssessmentResult(); - float totalMark = result.getGrade() - oldMark + newMark; - result.setGrade(totalMark); - assessmentResultDao.saveObject(result); + if (questionResults == null || questionResults.isEmpty()) { + log.warn("User with uid: " + user.getUid() + " doesn't have any results despite the fact group leader has some."); + continue; + } + + Object[] lastAssessmentQuestionResultObj = questionResults.get(questionResults.size() - 1); + AssessmentQuestionResult lastAssessmentQuestionResult = (AssessmentQuestionResult) lastAssessmentQuestionResultObj[0]; + + lastAssessmentQuestionResult.setMark(newMark); + assessmentQuestionResultDao.saveObject(lastAssessmentQuestionResult); - // propagade changes to Gradebook - Integer userId = result.getUser().getUserId().intValue(); - Long toolSessionId = result.getUser().getSession().getSessionId(); - gradebookService.updateActivityMark(new Double(totalMark), null, userId, toolSessionId, true); + AssessmentResult result = lastAssessmentQuestionResult.getAssessmentResult(); + result.setGrade(totalMark); + assessmentResultDao.saveObject(result); + + // propagade changes to Gradebook + gradebookService.updateActivityMark(new Double(totalMark), null, userId.intValue(), toolSessionId, true); + + // records mark change with audit service + auditService.logMarkChange(AssessmentConstants.TOOL_SIGNATURE, userId, user.getLoginName(), "" + oldMark, + "" + totalMark); + } + + } + + @Override + public void recalculateMarkForLesson(UserDTO requestUserDTO, Long lessonId) { - //records mark change with audit service - auditService.logMarkChange(AssessmentConstants.TOOL_SIGNATURE, result.getUser().getUserId(), result.getUser() - .getLoginName(), "" + oldMark, "" + totalMark); + User requestUser = userService.getUserByLogin(requestUserDTO.getLogin()); + Lesson lesson = lessonService.getLesson(lessonId); + Organisation organisation = lesson.getOrganisation(); + + // skip doing anything if the user doesn't have permission + Integer organisationToCheckPermission = (organisation.getOrganisationType().getOrganisationTypeId() + .equals(OrganisationType.COURSE_TYPE)) ? organisation.getOrganisationId() : organisation + .getParentOrganisation().getOrganisationId(); + boolean isGroupManager = userService.isUserInRole(requestUser.getUserId(), organisationToCheckPermission, + Role.GROUP_MANAGER); + if (!(lesson.getLessonClass().isStaffMember(requestUser) || isGroupManager)) { + return; + } + + //get all lesson activities + Set lessonActivities = new TreeSet(); + /* + * Hibernate CGLIB is failing to load the first activity in the sequence as a ToolActivity for some mysterious + * reason Causes a ClassCastException when you try to cast it, even if it is a ToolActivity. + * + * THIS IS A HACK to retrieve the first tool activity manually so it can be cast as a ToolActivity - if it is + * one + */ + Activity firstActivity = activityDAO.getActivityByActivityId(lesson.getLearningDesign().getFirstActivity() + .getActivityId()); + lessonActivities.add(firstActivity); + lessonActivities.addAll(lesson.getLearningDesign().getActivities()); + + //iterate through all assessment activities in the lesson + for (Activity activity : lessonActivities) { + + // check if it's assessment activity + if ((activity instanceof ToolActivity) + && ((ToolActivity) activity).getTool().getToolSignature() + .equals(AssessmentConstants.TOOL_SIGNATURE)) { + ToolActivity assessmentActivity = (ToolActivity) activity; + + for (ToolSession toolSession : (Set) assessmentActivity.getToolSessions()) { + Long toolSessionId = toolSession.getToolSessionId(); + AssessmentSession assessmentSession = this.getAssessmentSessionBySessionId(toolSessionId); + Assessment assessment = assessmentSession.getAssessment(); + + if (assessment.isUseSelectLeaderToolOuput()) { + + AssessmentUser leader = assessmentSession.getGroupLeader(); + if (leader == null) { + continue; + } + + AssessmentResult leaderLastResult = this.getLastFinishedAssessmentResult(assessment.getUid(), + leader.getUserId()); + if (leaderLastResult == null) { + continue; + } + Double mark = new Double(leaderLastResult.getGrade()); + + // update marks for all learners in a group + List users = this.getUsersBySession(toolSessionId); + for (AssessmentUser user : users) { + this.copyAnswersFromLeader(user, leader); + + // propagade total mark to Gradebook + gradebookService.updateActivityMark(mark, null, user.getUserId().intValue(), toolSessionId, + true); + } + } else { + + // update marks for all learners in a group + List users = this.getUsersBySession(toolSessionId); + for (AssessmentUser user : users) { + AssessmentResult userLastResult = this.getLastFinishedAssessmentResult(assessment.getUid(), + user.getUserId()); + if (userLastResult == null) { + continue; + } + Double mark = new Double(userLastResult.getGrade()); + + // propagade total mark to Gradebook + gradebookService.updateActivityMark(mark, null, user.getUserId().intValue(), toolSessionId, + true); + } + } + + } + } + } + } @Override @@ -1284,4 +1564,13 @@ public String getToolContentTitle(Long toolContentId) { return getAssessmentByContentId(toolContentId).getTitle(); } + + + public void setActivityDAO(IActivityDAO activityDAO) { + this.activityDAO = activityDAO; + } + + public void setUserService(IUserManagementService userService) { + this.userService = userService; + } } Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/IAssessmentService.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/IAssessmentService.java,v diff -u -r1.19 -r1.20 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/IAssessmentService.java 15 Nov 2013 10:04:44 -0000 1.19 +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/IAssessmentService.java 8 Jan 2014 17:47:02 -0000 1.20 @@ -23,6 +23,7 @@ /* $$Id$$ */ package org.lamsfoundation.lams.tool.assessment.service; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; @@ -44,13 +45,49 @@ import org.lamsfoundation.lams.tool.assessment.model.AssessmentSession; import org.lamsfoundation.lams.tool.assessment.model.AssessmentUser; import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; /** * @author Andrey Balan * * Interface that defines the contract that all ShareAssessment service provider must follow. */ public interface IAssessmentService { + + /** + * @param user + * @param toolSessionId + * @return + */ + boolean isUserGroupLeader(AssessmentUser user, Long toolSessionId); + + /** + * Set specified user as a leader. Also the previous leader (if any) is marked as non-leader. + * + * @param userId + * @param toolSessionID + */ + AssessmentUser checkLeaderSelectToolForSessionLeader(AssessmentUser user, Long toolSessionID); + + /** + * Check user has the same answers logs as group leader. If not - creates missing ones. + * + * @param user + * @param leader + * @throws NoSuchMethodException + * @throws InvocationTargetException + * @throws InstantiationException + * @throws IllegalAccessException + */ + void copyAnswersFromLeader(AssessmentUser user, AssessmentUser leader) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException; + + /** + * Get users by given toolSessionID. + * + * @param toolSessionID + * @return + */ + List getUsersBySession(Long toolSessionID); /** * Get Assessment by toolContentID. @@ -307,14 +344,23 @@ boolean isGroupedActivity(long toolContentID); /** - * Return content folder (unique to each learner and lesson) which is used for storing user generated content. - * It's been used by CKEditor. + * Return content folder (unique to each learner and lesson) which can be used for storing user generated content. + * Currently is used for CKEditor. * * @param toolSessionId * @param userId * @return */ String getLearnerContentFolder(Long toolSessionId, Long userId); + + /** + * Recalculate mark for leader and sets it to all members of a group. Authentication check: user must be either lesson stuff or group manager. + * + * @param requestUserDTO + * @param lessonId + */ + void recalculateMarkForLesson(UserDTO requestUserDTO, Long lessonId); + } Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/action/LearningAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/action/LearningAction.java,v diff -u -r1.32 -r1.33 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/action/LearningAction.java 15 Nov 2013 10:04:43 -0000 1.32 +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/action/LearningAction.java 8 Jan 2014 17:47:02 -0000 1.33 @@ -25,6 +25,7 @@ package org.lamsfoundation.lams.tool.assessment.web.action; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -51,6 +52,8 @@ import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; import org.lamsfoundation.lams.events.IEventNotificationService; import org.lamsfoundation.lams.learning.web.bean.ActivityPositionDTO; import org.lamsfoundation.lams.learning.web.util.LearningWebUtil; @@ -91,7 +94,7 @@ @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, - HttpServletResponse response) throws IOException, ServletException { + HttpServletResponse response) throws IOException, ServletException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException, JSONException { String param = mapping.getParameter(); if (param.equals("start")) { @@ -118,6 +121,9 @@ if (param.equals("autoSaveAnswers")) { return autoSaveAnswers(mapping, form, request, response); } + if (param.equals("checkLeaderProgress")) { + return checkLeaderProgress(mapping, form, request, response); + } // ================ Reflection ======================= if (param.equals("newReflection")) { return newReflection(mapping, form, request, response); @@ -135,11 +141,15 @@ * * This method will avoid read database again and lost un-saved resouce question lost when user "refresh page", * @throws ServletException + * @throws NoSuchMethodException + * @throws InvocationTargetException + * @throws InstantiationException + * @throws IllegalAccessException * */ @SuppressWarnings("unchecked") private ActionForward start(ActionMapping mapping, ActionForm form, HttpServletRequest request, - HttpServletResponse response) throws ServletException { + HttpServletResponse response) throws ServletException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException { // initialize Session Map SessionMap sessionMap = new SessionMap(); @@ -165,8 +175,43 @@ } else { assessmentUser = getCurrentUser(service, toolSessionId); } - + Assessment assessment = service.getAssessmentBySessionId(toolSessionId); + + //*LKC* added the next chunk + AssessmentUser groupLeader = null; + if (assessment.isUseSelectLeaderToolOuput()) { + groupLeader = service.checkLeaderSelectToolForSessionLeader(assessmentUser, new Long(toolSessionId).longValue()); + + // forwards to the leaderSelection page + if (groupLeader == null && !mode.isTeacher()) { + + List groupUsers = service.getUsersBySession(new Long(toolSessionId).longValue()); + request.setAttribute(AssessmentConstants.ATTR_GROUP_USERS, groupUsers); + request.setAttribute(AssessmentConstants.ATTR_ASSESSMENT, assessment); + + return mapping.findForward(AssessmentConstants.WAIT_FOR_LEADER); + } + + // check if leader has submitted all answers + if (groupLeader.isSessionFinished() && !mode.equals(ToolAccessMode.TEACHER.toString())) { + + // in case user joins the lesson after leader has answers some answers already - we need to make sure + // he has the same scratches as leader + service.copyAnswersFromLeader(assessmentUser, groupLeader); + + //service.finishToolSession(toolSessionId, assessmentUser.getUserId()); +// user.setSessionFinished(true); +// assessmentUserDao.saveObject(user); +// assessmentUser.setSessionFinished(true); +// service.saupdateAssessmentUser(assessmentUser); + } + } + + sessionMap.put(AssessmentConstants.ATTR_GROUP_LEADER, groupLeader); + boolean isUserLeader = service.isUserGroupLeader(assessmentUser, new Long(toolSessionId)); + sessionMap.put(AssessmentConstants.ATTR_IS_USER_LEADER, isUserLeader); + Set questionReferences = new TreeSet(new SequencableComparator()); questionReferences.addAll(assessment.getQuestionReferences()); HashMap questionToReferenceMap = new HashMap(); @@ -200,17 +245,19 @@ boolean isResubmitAllowed = ((attemptsAllowed > dbResultCount) | (attemptsAllowed == 0)); AssessmentResult lastResult = service.getLastAssessmentResult(assessment.getUid(), assessmentUser.getUserId()); + boolean hasEditRight = !assessment.isUseSelectLeaderToolOuput() || assessment.isUseSelectLeaderToolOuput() && isUserLeader; boolean isLastResultFinished = (lastResult != null) && (lastResult.getFinishDate() != null); //finishedLockForMonitor is a lock for displaying results page for teacher only if user see it, and displaying learner page if user see it accordingly boolean finishedLockForMonitor = (mode != null) && mode.isTeacher() && isLastResultFinished; boolean finishedLock = assessmentUser.isSessionFinished() || finishedLockForMonitor || isLastResultFinished; // get notebook entry String entryText = new String(); - NotebookEntry notebookEntry = service.getEntry(toolSessionId, assessmentUser.getUserId().intValue()); - if (notebookEntry != null) { - entryText = notebookEntry.getEntry(); - } + AssessmentUser notebookCreator = (groupLeader == null) ? assessmentUser : groupLeader; + NotebookEntry notebookEntry = service.getEntry(toolSessionId, notebookCreator.getUserId().intValue()); + if (notebookEntry != null) { + entryText = notebookEntry.getEntry(); + } // basic information sessionMap.put(AssessmentConstants.ATTR_TITLE, assessment.getTitle()); @@ -299,13 +346,13 @@ } //setAttemptStarted - if (!finishedLock) { + if (!finishedLock && hasEditRight) { service.setAttemptStarted(assessment, assessmentUser, toolSessionId); } //paging ArrayList> pagedQuestions = new ArrayList>(); - int maxQuestionsPerPage = (assessment.getQuestionsPerPage() != 0) ? assessment.getQuestionsPerPage() + int maxQuestionsPerPage = ((assessment.getQuestionsPerPage() != 0) && hasEditRight) ? assessment.getQuestionsPerPage() : questionList.size(); LinkedHashSet questionsForOnePage = new LinkedHashSet(); pagedQuestions.add(questionsForOnePage); @@ -338,6 +385,28 @@ } /** + * Checks Leader Progress + */ + private ActionForward checkLeaderProgress(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws JSONException, IOException { + + IAssessmentService service = getAssessmentService(); + Long toolSessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + + AssessmentSession session = service.getAssessmentSessionBySessionId(toolSessionId); + AssessmentUser leader = session.getGroupLeader(); + + boolean isLeaderResponseFinalized = leader.isSessionFinished(); + + JSONObject JSONObject = new JSONObject(); + JSONObject.put("isLeaderResponseFinalized", isLeaderResponseFinalized); + response.setContentType("application/x-json;charset=utf-8"); + response.getWriter().print(JSONObject); + return null; + } + + + /** * Display same entire authoring page content from HttpSession variable. */ private ActionForward nextPage(ActionMapping mapping, ActionForm form, HttpServletRequest request, @@ -722,7 +791,7 @@ Long userId = ((AssessmentUser) sessionMap.get(AssessmentConstants.ATTR_USER)).getUserId(); //get the latest result (it can be unfinished one) AssessmentResult lastResult = service.getLastAssessmentResult(assessmentUid,userId); - //if there is no results yet - no action required + //if there is no results yet - no action required if (lastResult == null) { return; } Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/servlet/PopulateMarksServlet.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/servlet/Attic/PopulateMarksServlet.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/servlet/PopulateMarksServlet.java 8 Jan 2014 17:47:02 -0000 1.1 @@ -0,0 +1,84 @@ +/**************************************************************** + * 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 + * **************************************************************** + */ + +/* $Id: PopulateMarksServlet.java,v 1.1 2014/01/08 17:47:02 andreyb Exp $ */ +package org.lamsfoundation.lams.tool.assessment.web.servlet; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.log4j.Logger; +import org.lamsfoundation.lams.tool.assessment.model.AssessmentSession; +import org.lamsfoundation.lams.tool.assessment.service.AssessmentServiceProxy; +import org.lamsfoundation.lams.tool.assessment.service.IAssessmentService; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; + +public class PopulateMarksServlet extends HttpServlet { + + private static Logger log = Logger.getLogger(PopulateMarksServlet.class); + + private IAssessmentService service; + + @Override + public void init() throws ServletException { + service = AssessmentServiceProxy.getAssessmentService(getServletContext()); + super.init(); + } + + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + + PrintWriter out = response.getWriter(); + try { + Long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + + HttpSession ss = SessionManager.getSession(); + UserDTO userDTO = (UserDTO) ss.getAttribute(AttributeNames.USER); + + service.recalculateMarkForLesson(userDTO, lessonId); + log.debug("recalculateMarkForLesson lessonId:" + lessonId); + out.println("recalculateMarkForLesson uid:" + lessonId); + + } catch (Exception e) { + log.error("LAMS ERROR: " + e.getMessage() + e.getCause()); + out.println("LAMS ERROR: " + e.getMessage() + e.getCause()); + throw new ServletException("LAMS ERROR: " + e.getMessage() + e.getCause()); + } + + out.println("OK. User marks have been updated."); + + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, + IOException { + doGet(request, response); + } + +} Index: lams_tool_assessment/web/WEB-INF/web.xml =================================================================== RCS file: /usr/local/cvsroot/lams_tool_assessment/web/WEB-INF/web.xml,v diff -u -r1.9 -r1.10 --- lams_tool_assessment/web/WEB-INF/web.xml 30 Jul 2012 18:49:56 -0000 1.9 +++ lams_tool_assessment/web/WEB-INF/web.xml 8 Jan 2014 17:47:02 -0000 1.10 @@ -92,6 +92,11 @@ + populateMarks + org.lamsfoundation.lams.tool.assessment.web.servlet.PopulateMarksServlet + + + action org.apache.struts.action.ActionServlet @@ -160,6 +165,11 @@ /exportPortfolio + + populateMarks + /populateMarks + + Index: lams_tool_assessment/web/pages/authoring/advance.jsp =================================================================== RCS file: /usr/local/cvsroot/lams_tool_assessment/web/pages/authoring/advance.jsp,v diff -u -r1.10 -r1.11 --- lams_tool_assessment/web/pages/authoring/advance.jsp 11 Jun 2013 10:30:18 -0000 1.10 +++ lams_tool_assessment/web/pages/authoring/advance.jsp 8 Jan 2014 17:47:02 -0000 1.11 @@ -23,13 +23,31 @@ $('#allowHistoryResponsesAfterAttempt').prop("checked", false); }); + $("#useSelectLeaderToolOuput").click(function() { + if ($("#useSelectLeaderToolOuput").is(':checked')) { + $("#display-summary").prop("checked", true).prop("disabled", true); + $('#display-summary-area').show('slow'); + + } else { + $("#display-summary").prop("disabled", false); + } + }); + $("#passingMark").prop("disabled", true); $("#attemptsAllowed").prop("disabled", true); + $("#display-summary").prop("disabled", true); }); +

+ + +

+