Index: lams_tool_scratchie/.classpath =================================================================== RCS file: /usr/local/cvsroot/lams_tool_scratchie/.classpath,v diff -u -r1.6 -r1.7 --- lams_tool_scratchie/.classpath 17 Sep 2013 04:52:28 -0000 1.6 +++ lams_tool_scratchie/.classpath 12 Dec 2016 16:54:44 -0000 1.7 @@ -13,6 +13,11 @@ + + + + + Index: lams_tool_scratchie/conf/language/lams/ApplicationResources_en_AU.properties =================================================================== RCS file: /usr/local/cvsroot/lams_tool_scratchie/conf/language/lams/ApplicationResources_en_AU.properties,v diff -u -r1.34 -r1.35 --- lams_tool_scratchie/conf/language/lams/ApplicationResources_en_AU.properties 20 Jul 2016 15:44:38 -0000 1.34 +++ lams_tool_scratchie/conf/language/lams/ApplicationResources_en_AU.properties 12 Dec 2016 16:54:45 -0000 1.35 @@ -203,5 +203,8 @@ label.time.is.over =Time is over. Processing your answers... label.are.you.ready =You are going to participate in activity that has time limitation. Are you ready to start? label.ok =OK - +label.waiting.for.leader.launch.time.limit =Leader has not started the activity. Please wait until he commences it. +label.waiting.for.leader.submit.notebook =Time limit set by teacher is expired. Please wait until a group leader submits notebook. +label.waiting.for.leader.submit.burning.questions =Time limit set by teacher is expired. Please wait until a group leader submits burning questions. + #======= End labels: Exported 182 labels for en AU ===== Index: lams_tool_scratchie/conf/xdoclet/struts-actions.xml =================================================================== RCS file: /usr/local/cvsroot/lams_tool_scratchie/conf/xdoclet/struts-actions.xml,v diff -u -r1.26 -r1.27 --- lams_tool_scratchie/conf/xdoclet/struts-actions.xml 6 Dec 2016 14:13:43 -0000 1.26 +++ lams_tool_scratchie/conf/xdoclet/struts-actions.xml 12 Dec 2016 16:54:44 -0000 1.27 @@ -161,6 +161,7 @@ parameter="start" > + @@ -172,6 +173,10 @@ parameter="refreshQuestionList" > + + Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/ScratchieConstants.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/ScratchieConstants.java,v diff -u -r1.28 -r1.29 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/ScratchieConstants.java 11 May 2016 08:10:17 -0000 1.28 +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/ScratchieConstants.java 12 Dec 2016 16:54:45 -0000 1.29 @@ -42,6 +42,8 @@ public static final String ERROR = "error"; public static final String DEFINE_LATER = "definelater"; + + public static final String WAIT_FOR_LEADER_TIME_LIMIT = "waitForLeaderTimeLimit"; // for parameters' name public static final String PARAM_TOOL_CONTENT_ID = "toolContentID"; @@ -108,6 +110,10 @@ public static final String ATTR_IS_SCRATCHING_FINISHED = "isScratchingFinished"; public static final String ATTR_IS_WAITING_FOR_LEADER_TO_SUBMIT_NOTEBOOK = "isWaitingForLeaderToSubmitNotebook"; + + public static final String ATTR_IS_TIME_LIMIT_EXCEEDED = "isTimeLimitExceeded"; + + public static final String ATTR_WAITING_MESSAGE_KEY = "waitingMessageKey"; public static final String ATTR_LEARNERS = "learners"; @@ -162,6 +168,12 @@ public static final String ATTR_GROUP_LEADER_NAME = "groupLeaderName"; public static final String ATTR_IS_USER_LEADER = "isUserLeader"; + + public static final String ATTR_IS_TIME_LIMIT_ENABLED = "isTimeLimitEnabled"; + + public static final String ATTR_IS_TIME_LIMIT_NOT_LAUNCHED = "isTimeLimitNotLaunched"; + + public static final String ATTR_SECONDS_LEFT = "secondsLeft"; public static final String ATTR_SUBMISSION_DEADLINE = "submissionDeadline"; Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/scratchieApplicationContext.xml =================================================================== RCS file: /usr/local/cvsroot/lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/scratchieApplicationContext.xml,v diff -u -r1.21 -r1.22 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/scratchieApplicationContext.xml 4 Apr 2016 19:19:17 -0000 1.21 +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/scratchieApplicationContext.xml 12 Dec 2016 16:54:45 -0000 1.22 @@ -113,6 +113,7 @@ + @@ -135,6 +136,7 @@ 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 PROPAGATION_REQUIRED,-java.lang.Exception Fisheye: Tag 1.1 refers to a dead (removed) revision in file `lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dbupdates/patch20161205.sql'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieSession.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieSession.java,v diff -u -r1.8 -r1.9 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieSession.java 11 May 2016 08:10:17 -0000 1.8 +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieSession.java 12 Dec 2016 16:54:45 -0000 1.9 @@ -47,6 +47,8 @@ private Scratchie scratchie; private Date sessionStartDate; private Date sessionEndDate; + //date when user has started activity (pressed start button) that has time limitation + private Date timeLimitLaunchedDate; // finish or not private int status; // scratchie Items @@ -81,7 +83,19 @@ public void setSessionEndDate(Date sessionEndDate) { this.sessionEndDate = sessionEndDate; } + + /** + * @hibernate.property column="time_limit_launched_date" + * @return + */ + public Date getTimeLimitLaunchedDate() { + return timeLimitLaunchedDate; + } + public void setTimeLimitLaunchedDate(Date timeLimitLaunchedDate) { + this.timeLimitLaunchedDate = timeLimitLaunchedDate; + } + /** * @hibernate.property column="session_start_date" * Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/IScratchieService.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/IScratchieService.java,v diff -u -r1.36 -r1.37 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/IScratchieService.java 11 May 2016 08:10:17 -0000 1.36 +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/IScratchieService.java 12 Dec 2016 16:54:45 -0000 1.37 @@ -41,6 +41,7 @@ import org.lamsfoundation.lams.tool.scratchie.model.ScratchieSession; import org.lamsfoundation.lams.tool.scratchie.model.ScratchieUser; import org.lamsfoundation.lams.util.ExcelCell; +import org.quartz.SchedulerException; /** * Interface that defines the contract that all ShareScratchie service provider must follow. @@ -64,6 +65,22 @@ * @param toolSessionId */ ScratchieUser checkLeaderSelectToolForSessionLeader(ScratchieUser user, Long toolSessionId); + + /** + * Stores date when user has started activity with time limit. + * + * @param sessionId + * @throws SchedulerException + */ + void launchTimeLimit(Long sessionId) throws SchedulerException; + + /** + * check if the time limit is exceeded + * + * @param session + * @return + */ + boolean isTimeLimitExceeded(ScratchieSession session); List getBurningQuestionsBySession(Long sessionId); Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java,v diff -u -r1.74 -r1.75 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java 20 Jul 2016 15:44:38 -0000 1.74 +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java 12 Dec 2016 16:54:45 -0000 1.75 @@ -27,8 +27,10 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; import java.util.Collection; import java.util.Date; +import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; @@ -39,6 +41,7 @@ import java.util.Map; import java.util.Set; import java.util.SortedMap; +import java.util.TimeZone; import java.util.TreeSet; import org.apache.commons.lang.StringEscapeUtils; @@ -88,6 +91,7 @@ import org.lamsfoundation.lams.tool.scratchie.model.ScratchieItem; import org.lamsfoundation.lams.tool.scratchie.model.ScratchieSession; import org.lamsfoundation.lams.tool.scratchie.model.ScratchieUser; +import org.lamsfoundation.lams.tool.scratchie.util.FinishScratchingJob; import org.lamsfoundation.lams.tool.scratchie.util.ScratchieAnswerComparator; import org.lamsfoundation.lams.tool.scratchie.util.ScratchieItemComparator; import org.lamsfoundation.lams.tool.scratchie.util.ScratchieToolContentHandler; @@ -99,6 +103,11 @@ import org.lamsfoundation.lams.util.JsonUtil; import org.lamsfoundation.lams.util.MessageService; import org.lamsfoundation.lams.util.audit.IAuditService; +import org.quartz.JobDetail; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.SimpleTrigger; +import org.quartz.Trigger; /** * @author Andrey Balan @@ -149,6 +158,8 @@ private IEventNotificationService eventNotificationService; private ScratchieOutputFactory scratchieOutputFactory; + + private Scheduler scheduler; // ******************************************************************************* // Service method @@ -256,7 +267,55 @@ } return leader; } + + @Override + public void launchTimeLimit(Long sessionId) throws SchedulerException { + ScratchieSession session = getScratchieSessionBySessionId(sessionId); + int timeLimit = session.getScratchie().getTimeLimit(); + if (timeLimit == 0) { + return; + } + + //store timeLimitLaunchedDate into DB + Date timeLimitLaunchedDate = new Date(); + session.setTimeLimitLaunchedDate(timeLimitLaunchedDate); + scratchieSessionDao.saveObject(session); + + //calculate timeLimit finish date + Calendar timeLimitFinishDate = new GregorianCalendar(TimeZone.getDefault()); + timeLimitFinishDate.setTime(timeLimitLaunchedDate); + timeLimitFinishDate.add(Calendar.MINUTE, timeLimit); + //adding 5 extra seconds to let leader auto-submit results and store them in DB + timeLimitFinishDate.add(Calendar.SECOND, 5); + + //start quartz job to notify non-leaders time is over + JobDetail emailScheduleMessageJob = new JobDetail(); + emailScheduleMessageJob.setJobClass(FinishScratchingJob.class); + emailScheduleMessageJob.setName("finishScratching:" + sessionId); + emailScheduleMessageJob.setDescription("Group name: " + session.getSessionName()); + emailScheduleMessageJob.getJobDataMap().put("toolSessionId", sessionId); + + // create customized triggers + Trigger startLessonTrigger = new SimpleTrigger("fnishScratchingTrigger:" + sessionId, Scheduler.DEFAULT_GROUP, + timeLimitFinishDate.getTime()); + // start the scheduling job + scheduler.scheduleJob(emailScheduleMessageJob, startLessonTrigger); + } + + @Override + public boolean isTimeLimitExceeded(ScratchieSession session) { + Scratchie scratchie = session.getScratchie(); + //if activity doesn't have time limit or leader hasn't launched time limit yet - return false + if (scratchie.getTimeLimit() == 0 || session.getTimeLimitLaunchedDate() == null) { + return false; + } + // check if the time limit is exceeded + boolean isTimeLimitExceeded = session.getTimeLimitLaunchedDate().getTime() + + scratchie.getTimeLimit() * 60000 < System.currentTimeMillis(); + return isTimeLimitExceeded; + } + @Override public void changeUserMark(Long userId, Long sessionId, Integer newMark) { if (newMark == null) { @@ -2055,6 +2114,10 @@ public void setScratchieOutputFactory(ScratchieOutputFactory scratchieOutputFactory) { this.scratchieOutputFactory = scratchieOutputFactory; } + + public void setScheduler(Scheduler scheduler) { + this.scheduler = scheduler; + } // ****************** REST methods ************************* Fisheye: Tag 1.1 refers to a dead (removed) revision in file `lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/util/FinishScratchingJob.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/action/LearningAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/action/LearningAction.java,v diff -u -r1.58 -r1.59 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/action/LearningAction.java 11 May 2016 08:10:17 -0000 1.58 +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/action/LearningAction.java 12 Dec 2016 16:54:45 -0000 1.59 @@ -73,6 +73,7 @@ import org.lamsfoundation.lams.web.session.SessionManager; import org.lamsfoundation.lams.web.util.AttributeNames; import org.lamsfoundation.lams.web.util.SessionMap; +import org.quartz.SchedulerException; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; @@ -88,7 +89,7 @@ @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) - throws IOException, ServletException, JSONException, ScratchieApplicationException { + throws IOException, ServletException, JSONException, ScratchieApplicationException, SchedulerException { String param = mapping.getParameter(); // -----------------------Scratchie Learner function --------------------------- @@ -104,6 +105,9 @@ if (param.equals("recordItemScratched")) { return recordItemScratched(mapping, form, request, response); } + if (param.equals("launchTimeLimit")) { + return launchTimeLimit(mapping, form, request, response); + } if (param.equals("finish")) { return finish(mapping, form, request, response); } @@ -149,9 +153,9 @@ ToolAccessMode mode = WebUtil.readToolAccessModeParam(request, AttributeNames.PARAM_MODE, true); final Long toolSessionId = new Long(request.getParameter(ScratchieConstants.PARAM_TOOL_SESSION_ID)); - ScratchieSession toolSession = LearningAction.service.getScratchieSessionBySessionId(toolSessionId); + ScratchieSession toolSession = service.getScratchieSessionBySessionId(toolSessionId); // get back the scratchie and item list and display them on page - final Scratchie scratchie = LearningAction.service.getScratchieBySessionId(toolSessionId); + final Scratchie scratchie = service.getScratchieBySessionId(toolSessionId); boolean isReflectOnActivity = scratchie.isReflectOnActivity(); final ScratchieUser user; @@ -163,13 +167,13 @@ user = getCurrentUser(toolSessionId); } - ScratchieUser groupLeader = LearningAction.service.checkLeaderSelectToolForSessionLeader(user, toolSessionId); + ScratchieUser groupLeader = service.checkLeaderSelectToolForSessionLeader(user, toolSessionId); // forwards to the leaderSelection page if ((groupLeader == null) && !mode.isTeacher()) { // get group users and store it to request as DTO objects - List groupUsers = LearningAction.service.getUsersBySession(toolSessionId); + List groupUsers = service.getUsersBySession(toolSessionId); List groupUserDtos = new ArrayList(); for (ScratchieUser groupUser : groupUsers) { User groupUserDto = new User(); @@ -191,7 +195,7 @@ // get notebook entry NotebookEntry notebookEntry = null; if (isReflectOnActivity && (groupLeader != null)) { - notebookEntry = LearningAction.service.getEntry(toolSessionId, CoreNotebookConstants.NOTEBOOK_TOOL, + notebookEntry = service.getEntry(toolSessionId, CoreNotebookConstants.NOTEBOOK_TOOL, ScratchieConstants.TOOL_SIGNATURE, groupLeader.getUserId().intValue()); } String entryText = (notebookEntry == null) ? null : notebookEntry.getEntry(); @@ -253,18 +257,18 @@ } // set scratched flag for display purpose - Collection items = LearningAction.service.getItemsWithIndicatedScratches(toolSessionId); + Collection items = service.getItemsWithIndicatedScratches(toolSessionId); // for teacher in monitoring display the number of attempt. if (mode.isTeacher()) { - LearningAction.service.getScratchesOrder(items, toolSessionId); + service.getScratchesOrder(items, toolSessionId); } // populate items with the existing burning questions for displaying purposes List burningQuestions = null; if (scratchie.isBurningQuestionsEnabled()) { - burningQuestions = LearningAction.service.getBurningQuestionsBySession(toolSessionId); + burningQuestions = service.getBurningQuestionsBySession(toolSessionId); for (ScratchieItem item : items) { // find corresponding burningQuestion @@ -313,30 +317,70 @@ redirect.addParameter(ScratchieConstants.ATTR_SESSION_MAP_ID, sessionMap.getSessionID()); return redirect; - // show leader notebook page + // show leader notebook page } else if (isUserLeader && isScratchingFinished && isWaitingForLeaderToSubmitNotebook) { ActionRedirect redirect = new ActionRedirect(mapping.findForwardConfig("newReflection")); redirect.addParameter(ScratchieConstants.ATTR_SESSION_MAP_ID, sessionMap.getSessionID()); redirect.addParameter(AttributeNames.ATTR_MODE, mode); return redirect; - // show results page + // show results page } else if (isShowResults) { ActionRedirect redirect = new ActionRedirect(mapping.findForwardConfig("showResults")); redirect.addParameter(ScratchieConstants.ATTR_SESSION_MAP_ID, sessionMap.getSessionID()); redirect.addParameter(AttributeNames.ATTR_MODE, mode); return redirect; - // show learning.jsp page + // show learning.jsp page } else { - // make non leaders also wait for burning questions submit - isWaitingForLeaderToSubmitNotebook |= isWaitingForLeaderToSubmitBurningQuestions; + // time limit feature + boolean isTimeLimitEnabled = isUserLeader && !isScratchingFinished && scratchie.getTimeLimit() != 0; + boolean isTimeLimitNotLaunched = toolSession.getTimeLimitLaunchedDate() == null; + long secondsLeft = 1; + if (isTimeLimitEnabled) { + // if user has pressed OK button already - calculate remaining time, and full time otherwise + secondsLeft = isTimeLimitNotLaunched ? scratchie.getTimeLimit() * 60 + : scratchie.getTimeLimit() * 60 + - (System.currentTimeMillis() - toolSession.getTimeLimitLaunchedDate().getTime()) / 1000; + // change negative number or zero to 1 so it can autosubmit results + secondsLeft = Math.max(1, secondsLeft); + } + request.setAttribute(ScratchieConstants.ATTR_IS_TIME_LIMIT_ENABLED, isTimeLimitEnabled); + request.setAttribute(ScratchieConstants.ATTR_IS_TIME_LIMIT_NOT_LAUNCHED, isTimeLimitNotLaunched); + request.setAttribute(ScratchieConstants.ATTR_SECONDS_LEFT, secondsLeft); + // in case we can't show learning.jsp to non-leaders forward them to the waitForLeaderTimeLimit page + if (!isUserLeader && scratchie.getTimeLimit() != 0 && !mode.isTeacher()) { + + //show waitForLeaderLaunchTimeLimit page if the leader hasn't started activity or hasn't pressed OK button to launch time limit + if (toolSession.getTimeLimitLaunchedDate() == null) { + request.setAttribute(ScratchieConstants.ATTR_WAITING_MESSAGE_KEY, + "label.waiting.for.leader.launch.time.limit"); + return mapping.findForward("waitForLeaderTimeLimit"); + } + + // check if the time limit is exceeded + boolean isTimeLimitExceeded = service.isTimeLimitExceeded(toolSession); + + // if the time limit is over and the leader hasn't submitted notebook or burning questions (thus + // non-leaders should wait) - show waitForLeaderFinish page + if (isTimeLimitExceeded && isWaitingForLeaderToSubmitNotebook) { + request.setAttribute(ScratchieConstants.ATTR_WAITING_MESSAGE_KEY, + "label.waiting.for.leader.submit.notebook"); + return mapping.findForward(ScratchieConstants.WAIT_FOR_LEADER_TIME_LIMIT); + } else if (isTimeLimitExceeded && isWaitingForLeaderToSubmitBurningQuestions) { + request.setAttribute(ScratchieConstants.ATTR_WAITING_MESSAGE_KEY, + "label.waiting.for.leader.submit.burning.questions"); + return mapping.findForward(ScratchieConstants.WAIT_FOR_LEADER_TIME_LIMIT); + } + } + sessionMap.put(ScratchieConstants.ATTR_IS_SCRATCHING_FINISHED, isScratchingFinished); + // make non leaders also wait for burning questions submit sessionMap.put(ScratchieConstants.ATTR_IS_WAITING_FOR_LEADER_TO_SUBMIT_NOTEBOOK, - isWaitingForLeaderToSubmitNotebook); + isWaitingForLeaderToSubmitNotebook | isWaitingForLeaderToSubmitBurningQuestions); return mapping.findForward(ScratchieConstants.SUCCESS); } @@ -355,10 +399,10 @@ request.setAttribute(ScratchieConstants.ATTR_SESSION_MAP_ID, sessionMapID); Long toolSessionId = (Long) sessionMap.get(AttributeNames.PARAM_TOOL_SESSION_ID); - ScratchieSession toolSession = LearningAction.service.getScratchieSessionBySessionId(toolSessionId); + ScratchieSession toolSession = service.getScratchieSessionBySessionId(toolSessionId); // set scratched flag for display purpose - Collection items = LearningAction.service.getItemsWithIndicatedScratches(toolSessionId); + Collection items = service.getItemsWithIndicatedScratches(toolSessionId); sessionMap.put(ScratchieConstants.ATTR_ITEM_LIST, items); // refresh leadership status @@ -369,6 +413,9 @@ // refresh ScratchingFinished status sessionMap.put(ScratchieConstants.ATTR_IS_SCRATCHING_FINISHED, toolSession.isScratchingFinished()); + // refresh TimeLimitExceeded status + request.setAttribute(ScratchieConstants.ATTR_IS_TIME_LIMIT_EXCEEDED, service.isTimeLimitExceeded(toolSession)); + return mapping.findForward(ScratchieConstants.SUCCESS); } @@ -388,28 +435,31 @@ .get(ScratchieConstants.ATTR_IS_BURNING_QUESTIONS_ENABLED); Long toolSessionId = (Long) sessionMap.get(AttributeNames.PARAM_TOOL_SESSION_ID); - ScratchieSession toolSession = LearningAction.service.getScratchieSessionBySessionId(toolSessionId); + ScratchieSession toolSession = service.getScratchieSessionBySessionId(toolSessionId); ScratchieUser groupLeader = toolSession.getGroupLeader(); // get notebook entry NotebookEntry notebookEntry = null; if (isReflectOnActivity && (groupLeader != null)) { - notebookEntry = LearningAction.service.getEntry(toolSessionId, CoreNotebookConstants.NOTEBOOK_TOOL, + notebookEntry = service.getEntry(toolSessionId, CoreNotebookConstants.NOTEBOOK_TOOL, ScratchieConstants.TOOL_SIGNATURE, groupLeader.getUserId().intValue()); } boolean isWaitingForLeaderToSubmitNotebook = isReflectOnActivity && (notebookEntry == null); // make non leaders also wait for burning questions submit List burningQuestions = null; if (isBurningQuestionsEnabled) { - burningQuestions = LearningAction.service.getBurningQuestionsBySession(toolSessionId); + burningQuestions = service.getBurningQuestionsBySession(toolSessionId); } isWaitingForLeaderToSubmitNotebook |= isBurningQuestionsEnabled && ((burningQuestions == null) || burningQuestions.isEmpty()) && !toolSession.isSessionFinished(); JSONObject JSONObject = new JSONObject(); JSONObject.put(ScratchieConstants.ATTR_IS_WAITING_FOR_LEADER_TO_SUBMIT_NOTEBOOK, isWaitingForLeaderToSubmitNotebook); + // refresh TimeLimitExceeded status + boolean isTimeLimitExceeded = service.isTimeLimitExceeded(toolSession); + JSONObject.put(ScratchieConstants.ATTR_IS_TIME_LIMIT_EXCEEDED, isTimeLimitExceeded); response.setContentType("application/x-json;charset=utf-8"); response.getWriter().print(JSONObject); @@ -430,7 +480,7 @@ final Long toolSessionId = (Long) sessionMap.get(AttributeNames.PARAM_TOOL_SESSION_ID); final Long answerUid = NumberUtils.createLong(request.getParameter(ScratchieConstants.PARAM_ANSWER_UID)); - ScratchieSession toolSession = LearningAction.service.getScratchieSessionBySessionId(toolSessionId); + ScratchieSession toolSession = service.getScratchieSessionBySessionId(toolSessionId); ScratchieUser leader = this.getCurrentUser(toolSessionId); // only leader is allowed to scratch answers @@ -445,7 +495,7 @@ } // Return whether scratchie answer is correct or not - ScratchieAnswer answer = LearningAction.service.getScratchieAnswerByUid(answerUid); + ScratchieAnswer answer = service.getScratchieAnswerByUid(answerUid); if (answer == null) { return null; } @@ -460,14 +510,39 @@ Thread recordItemScratchedThread = new Thread(new Runnable() { @Override public void run() { - LearningAction.service.recordItemScratched(toolSessionId, answerUid); + service.recordItemScratched(toolSessionId, answerUid); } }, "LAMS_recordItemScratched_thread"); recordItemScratchedThread.start(); return null; } + + /** + * Stores date when user has started activity with time limit + * @throws ScratchieApplicationException + * @throws SchedulerException + */ + private ActionForward launchTimeLimit(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws ScratchieApplicationException, SchedulerException { + initializeScratchieService(); + String sessionMapID = WebUtil.readStrParam(request, ScratchieConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapID); + final Long toolSessionId = (Long) sessionMap.get(AttributeNames.PARAM_TOOL_SESSION_ID); + ScratchieSession toolSession = service.getScratchieSessionBySessionId(toolSessionId); + + ScratchieUser leader = getCurrentUser(toolSessionId); + // only leader is allowed to launch time limit + if (!toolSession.isUserGroupLeader(leader.getUid())) { + return null; + } + + service.launchTimeLimit(toolSessionId); + return null; + } + /** * Displays results page. When leader gets to this page, scratchingFinished column is set to true for all users. * @@ -491,13 +566,13 @@ .get(ScratchieConstants.ATTR_IS_BURNING_QUESTIONS_ENABLED); final Long toolSessionId = (Long) sessionMap.get(AttributeNames.PARAM_TOOL_SESSION_ID); - ScratchieSession toolSession = LearningAction.service.getScratchieSessionBySessionId(toolSessionId); + ScratchieSession toolSession = service.getScratchieSessionBySessionId(toolSessionId); Long userUid = (Long) sessionMap.get(ScratchieConstants.ATTR_USER_UID); // in case of the leader (and if he hasn't done this when accessing notebook) we should let all other learners // see Next Activity button if (toolSession.isUserGroupLeader(userUid) && !toolSession.isScratchingFinished()) { - LearningAction.service.setScratchingFinished(toolSessionId); + service.setScratchingFinished(toolSessionId); } // get updated score from ScratchieSession @@ -509,14 +584,14 @@ // display other groups' BurningQuestions if (isBurningQuestionsEnabled) { Scratchie scratchie = toolSession.getScratchie(); - List burningQuestionItemDtos = LearningAction.service + List burningQuestionItemDtos = service .getBurningQuestionDtos(scratchie, toolSessionId); request.setAttribute(ScratchieConstants.ATTR_BURNING_QUESTION_ITEM_DTOS, burningQuestionItemDtos); } // display other groups' notebooks if (isReflectOnActivity) { - List reflections = LearningAction.service + List reflections = service .getReflectionList(toolSession.getScratchie().getContentId()); // remove current session leader reflection @@ -554,7 +629,7 @@ SessionMap sessionMap = (SessionMap) request.getSession() .getAttribute(sessionMapID); final Long sessionId = (Long) sessionMap.get(AttributeNames.PARAM_TOOL_SESSION_ID); - ScratchieSession toolSession = LearningAction.service.getScratchieSessionBySessionId(sessionId); + ScratchieSession toolSession = service.getScratchieSessionBySessionId(sessionId); Long burningQuestionUid = WebUtil.readLongParam(request, ScratchieConstants.PARAM_BURNING_QUESTION_UID); @@ -586,7 +661,7 @@ SessionMap sessionMap = (SessionMap) request.getSession() .getAttribute(sessionMapID); final Long sessionId = (Long) sessionMap.get(AttributeNames.PARAM_TOOL_SESSION_ID); - ScratchieSession toolSession = LearningAction.service.getScratchieSessionBySessionId(sessionId); + ScratchieSession toolSession = service.getScratchieSessionBySessionId(sessionId); Long burningQuestionUid = WebUtil.readLongParam(request, ScratchieConstants.PARAM_BURNING_QUESTION_UID); @@ -625,11 +700,11 @@ String nextActivityUrl = null; try { - nextActivityUrl = LearningAction.service.finishToolSession(toolSessionId, userId); + nextActivityUrl = service.finishToolSession(toolSessionId, userId); request.setAttribute(ScratchieConstants.ATTR_NEXT_ACTIVITY_URL, nextActivityUrl); } catch (ScratchieApplicationException e) { - LearningAction.log.error("Failed get next activity url:" + e.getMessage()); + log.error("Failed get next activity url:" + e.getMessage()); } return mapping.findForward(ScratchieConstants.SUCCESS); } @@ -656,12 +731,12 @@ // set scratched flag for display purpose Collection items = (Collection) sessionMap.get(ScratchieConstants.ATTR_ITEM_LIST); - LearningAction.service.getItemsWithIndicatedScratches(toolSessionId, items); + service.getItemsWithIndicatedScratches(toolSessionId, items); // in case of the leader we should let all other learners see Next Activity button - ScratchieSession toolSession = LearningAction.service.getScratchieSessionBySessionId(toolSessionId); + ScratchieSession toolSession = service.getScratchieSessionBySessionId(toolSessionId); if (toolSession.isUserGroupLeader(userUid) && !toolSession.isScratchingFinished()) { - LearningAction.service.setScratchingFinished(toolSessionId); + service.setScratchingFinished(toolSessionId); } return mapping.findForward(ScratchieConstants.SUCCESS); @@ -703,12 +778,12 @@ item.setBurningQuestion(question); // update new entry - LearningAction.service.saveBurningQuestion(sessionId, itemUid, question); + service.saveBurningQuestion(sessionId, itemUid, question); } // handle general burning question final String generalQuestion = request.getParameter(ScratchieConstants.ATTR_GENERAL_BURNING_QUESTION); - LearningAction.service.saveBurningQuestion(sessionId, null, generalQuestion); + service.saveBurningQuestion(sessionId, null, generalQuestion); // update general question in sessionMap sessionMap.put(ScratchieConstants.ATTR_GENERAL_BURNING_QUESTION, generalQuestion); @@ -753,18 +828,18 @@ refForm.setSessionMapID(sessionMapID); // get the existing reflection entry - NotebookEntry entry = LearningAction.service.getEntry(toolSessionId, CoreNotebookConstants.NOTEBOOK_TOOL, + NotebookEntry entry = service.getEntry(toolSessionId, CoreNotebookConstants.NOTEBOOK_TOOL, ScratchieConstants.TOOL_SIGNATURE, user.getUserID()); if (entry != null) { refForm.setEntryText(entry.getEntry()); } - ScratchieSession toolSession = LearningAction.service.getScratchieSessionBySessionId(toolSessionId); + ScratchieSession toolSession = service.getScratchieSessionBySessionId(toolSessionId); // in case of the leader we should let all other learners see Next Activity button if (toolSession.isUserGroupLeader(userUid) && !toolSession.isScratchingFinished()) { - LearningAction.service.setScratchingFinished(toolSessionId); + service.setScratchingFinished(toolSessionId); } return mapping.findForward(ScratchieConstants.NOTEBOOK); @@ -793,18 +868,18 @@ final Long sessionId = (Long) sessionMap.get(AttributeNames.PARAM_TOOL_SESSION_ID); // check for existing notebook entry - final NotebookEntry entry = LearningAction.service.getEntry(sessionId, CoreNotebookConstants.NOTEBOOK_TOOL, + final NotebookEntry entry = service.getEntry(sessionId, CoreNotebookConstants.NOTEBOOK_TOOL, ScratchieConstants.TOOL_SIGNATURE, userId); if (entry == null) { // create new entry - LearningAction.service.createNotebookEntry(sessionId, CoreNotebookConstants.NOTEBOOK_TOOL, + service.createNotebookEntry(sessionId, CoreNotebookConstants.NOTEBOOK_TOOL, ScratchieConstants.TOOL_SIGNATURE, userId, entryText); } else { // update existing entry entry.setEntry(entryText); entry.setLastModified(new Date()); - LearningAction.service.updateEntry(entry); + service.updateEntry(entry); } sessionMap.put(ScratchieConstants.ATTR_REFLECTION_ENTRY, entryText); @@ -818,10 +893,10 @@ // ************************************************************************************* private void initializeScratchieService() { - if (LearningAction.service == null) { + if (service == null) { WebApplicationContext wac = WebApplicationContextUtils .getRequiredWebApplicationContext(getServlet().getServletContext()); - LearningAction.service = (IScratchieService) wac.getBean(ScratchieConstants.SCRATCHIE_SERVICE); + service = (IScratchieService) wac.getBean(ScratchieConstants.SCRATCHIE_SERVICE); } } @@ -830,23 +905,23 @@ HttpSession ss = SessionManager.getSession(); // get back login user DTO UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); - ScratchieUser scratchieUser = LearningAction.service.getUserByIDAndSession(user.getUserID().longValue(), + ScratchieUser scratchieUser = service.getUserByIDAndSession(user.getUserID().longValue(), sessionId); if (scratchieUser == null) { - ScratchieSession session = LearningAction.service.getScratchieSessionBySessionId(sessionId); + ScratchieSession session = service.getScratchieSessionBySessionId(sessionId); final ScratchieUser newScratchieUser = new ScratchieUser(user, session); - LearningAction.service.createUser(newScratchieUser); + service.createUser(newScratchieUser); scratchieUser = newScratchieUser; } return scratchieUser; } private ScratchieUser getSpecifiedUser(Long sessionId, Integer userId) { - ScratchieUser scratchieUser = LearningAction.service.getUserByIDAndSession(userId.longValue(), sessionId); + ScratchieUser scratchieUser = service.getUserByIDAndSession(userId.longValue(), sessionId); if (scratchieUser == null) { - LearningAction.log + log .error("Unable to find specified user for scratchie activity. Screens are likely to fail. SessionId=" + sessionId + " UserId=" + userId); } Index: lams_tool_scratchie/web/pages/learning/learning.jsp =================================================================== RCS file: /usr/local/cvsroot/lams_tool_scratchie/web/pages/learning/learning.jsp,v diff -u -r1.24 -r1.25 --- lams_tool_scratchie/web/pages/learning/learning.jsp 20 Jul 2016 15:44:38 -0000 1.24 +++ lams_tool_scratchie/web/pages/learning/learning.jsp 12 Dec 2016 16:54:44 -0000 1.25 @@ -21,7 +21,7 @@ <%@ include file="/common/header.jsp"%> - + @@ -66,20 +66,35 @@ } //time limit feature - + $(document).ready(function(){ - //show confirmation dialog - $.blockUI({ - message: $('#timelimit-start-dialog'), - css: { width: '325px', height: '120px'}, - overlayCSS: { opacity: '.98'} - }); + + //show timelimit-start-dialog in order to start countdown + if (${isTimeLimitNotLaunched}) { + + $.blockUI({ + message: $('#timelimit-start-dialog'), + css: { width: '325px', height: '120px'}, + overlayCSS: { opacity: '.98'} + }); - //once OK button pressed start countdown - $('#timelimit-start-ok').click(function() { - $.unblockUI(); - displayCountdown(); - }); + //once OK button pressed start countdown + $('#timelimit-start-ok').click(function() { + + //store date when user has started activity with time limit + $.ajax({ + async: true, + url: '', + data: 'sessionMapID=${sessionMapID}', + type: 'post' + }); + + $.unblockUI(); + displayCountdown(); + }); + } else { + displayCountdown(); + } }); function displayCountdown(){ @@ -100,7 +115,7 @@ }); $('#countdown').countdown({ - until: '+${scratchie.timeLimit * 60}S', + until: '+${secondsLeft}S', format: 'hMS', compact: true, onTick: function(periods) { @@ -147,6 +162,7 @@ function refreshQuestionList() { var url = "", scrollTop = document.documentElement.scrollTop || document.body.scrollTop; + $("#questionListArea").load( url, { Index: lams_tool_scratchie/web/pages/learning/questionlist.jsp =================================================================== RCS file: /usr/local/cvsroot/lams_tool_scratchie/web/pages/learning/questionlist.jsp,v diff -u -r1.16 -r1.17 --- lams_tool_scratchie/web/pages/learning/questionlist.jsp 20 Jul 2016 15:44:38 -0000 1.16 +++ lams_tool_scratchie/web/pages/learning/questionlist.jsp 12 Dec 2016 16:54:44 -0000 1.17 @@ -29,12 +29,18 @@ } }); - //query for leader status (only in case there is notebook at the end of activity and leader hasn't answered it yet) + + // if time limit is ON and time is over (i.e. isScratchingFinished is true) - refresh page for non-leaders in order to stop showing them learning.jsp + if (${!isUserLeader && isScratchingFinished && (scratchie.timeLimit > 0) && isTimeLimitExceeded && mode != "teacher"}) { + alert("isTimeLimitExceeded${isTimeLimitExceeded}"); + location.reload(); + } + + // in case there is notebook at the end of activity and leader hasn't answered it yet - query for leader's status var checkLeaderIntervalId = null; if (${!isUserLeader && isScratchingFinished && isWaitingForLeaderToSubmitNotebook && mode != "teacher"}) { - checkLeaderIntervalId = setInterval("checkLeaderSubmittedNotebook();",2000);// ask for leader status every 20 seconds - } - + checkLeaderIntervalId = setInterval("checkLeaderSubmittedNotebook();", 2000);// ask for leader status every 20 seconds + } //check Leader Submitted Notebook and if true show finishButton function checkLeaderSubmittedNotebook() { $.ajax({ @@ -43,6 +49,11 @@ dataType: 'json', type: 'post', success: function (json) { + if (json.isTimeLimitExceeded) { + alert("isTimeLimitExceededx${isTimeLimitExceeded}"); + location.reload(); + } + if (!json.isWaitingForLeaderToSubmitNotebook) { if (checkLeaderIntervalId != null) { clearInterval(checkLeaderIntervalId); Fisheye: Tag 1.1 refers to a dead (removed) revision in file `lams_tool_scratchie/web/pages/learning/waitForLeaderTimeLimit.jsp'. Fisheye: No comparison available. Pass `N' to diff?