From df09babb893d5c712bfba81105db7ed5eaacca2a Mon Sep 17 00:00:00 2001 From: Sam Ottenhoff Date: Tue, 16 Nov 2021 10:58:11 -0500 Subject: [PATCH] SAK-45667 before timer-submitting a student assessment, (#10002) * SAK-45667 before timer-submitting a student assessment, check the ExtendedTime to see if an instructor gave the student more time to finish. * Refactor and use lombok * Also handle case where time is modified for the entire assessment and not just one student extension --- .../delivery/BeginDeliveryActionListener.java | 2 +- .../delivery/TimedAssessmentGradingModel.java | 152 +++--------------- .../delivery/TimedAssessmentRunnable.java | 32 +++- 3 files changed, 47 insertions(+), 139 deletions(-) diff --git a/samigo/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/delivery/BeginDeliveryActionListener.java b/samigo/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/delivery/BeginDeliveryActionListener.java index 92098016587e..7a24890d8730 100755 --- a/samigo/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/delivery/BeginDeliveryActionListener.java +++ b/samigo/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/delivery/BeginDeliveryActionListener.java @@ -470,7 +470,7 @@ else if (minute > 1) { TimedAssessmentGradingModel timedAG = queue. get(unSubmittedAssessmentGrading.getAssessmentGradingId()); // if it was submitted (race condition) while checking, unblock it - sam will synch soon - if(timedAG != null && !timedAG.getSubmittedForGrade()) { + if(timedAG != null && !timedAG.isSubmittedForGrade()) { delivery.setTimeExpired(true); } } diff --git a/samigo/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/model/delivery/TimedAssessmentGradingModel.java b/samigo/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/model/delivery/TimedAssessmentGradingModel.java index 7847d1c54192..269f707d9026 100644 --- a/samigo/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/model/delivery/TimedAssessmentGradingModel.java +++ b/samigo/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/model/delivery/TimedAssessmentGradingModel.java @@ -24,17 +24,10 @@ import java.util.Date; +import lombok.Data; import org.sakaiproject.tool.assessment.facade.PublishedAssessmentFacade; -/** - *

Title:

- *

Description:

- *

Copyright: Copyright (c) 2004

- *

Company:

- * @author not attributable - * @version 1.0 - */ - +@Data public class TimedAssessmentGradingModel { private Long assessmentGradingId; @@ -62,9 +55,6 @@ public class TimedAssessmentGradingModel */ private int transactionBuffer=30; // 30 sec - public TimedAssessmentGradingModel() { - } - public TimedAssessmentGradingModel(Long assessmentGradingId, int timeLimit, int timeLeft, Date beginDate, Date localBeginDate, @@ -73,136 +63,34 @@ public TimedAssessmentGradingModel(Long assessmentGradingId, this.timeLimit = timeLimit; this.timeLeft = timeLeft; this.beginDate = beginDate; - this.expirationDate = new Date(beginDate.getTime() + timeLeft*1000L); - this.bufferedExpirationDate = new Date(beginDate.getTime() + timeLeft*1000L + latencyBuffer*1000); this.submittedForGrade = submittedForGrade; this.localBeginDate = localBeginDate; - this.localExpirationDate = new Date(localBeginDate.getTime() + timeLeft*1000L); this.timerId = timerId; this.publishedAssessment = publishedAssessment; - } - public TimedAssessmentGradingModel(Long assessmentGradingId, - int timeLimit, int timeLeft, - int latencyBuffer, int transactionBuffer, - Date beginDate, Date localBeginDate, - boolean submittedForGrade, String timerId, PublishedAssessmentFacade publishedAssessment){ - this.assessmentGradingId = assessmentGradingId; - this.timeLimit = timeLimit; - this.timeLeft = timeLeft; - this.latencyBuffer = latencyBuffer; - this.transactionBuffer = transactionBuffer; - this.beginDate = beginDate; - this.expirationDate = new Date(beginDate.getTime() + timeLeft*1000L); - this.bufferedExpirationDate = new Date(beginDate.getTime() + timeLeft*1000L + latencyBuffer*1000); - this.submittedForGrade = submittedForGrade; - this.localBeginDate = localBeginDate; - this.localExpirationDate = new Date(localBeginDate.getTime() + timeLeft*1000L); - this.timerId = timerId; - this.publishedAssessment = publishedAssessment; - } - - public Long getAssessmentGradingId() { - return assessmentGradingId; - } - - public void setAssessmentGradingId(Long assessmentGradingId) { - this.assessmentGradingId = assessmentGradingId; + setExpirationDates(beginDate, localBeginDate, timeLeft); } - public int getTimeLimit() { - return timeLimit; + /** + * This method can be used to adjust an in-process assessment + * @param newTimeLimit amount of time left starting now + */ + public void setNewTimeLimit(final int newTimeLimit) { + setExpirationDates(new Date(), new Date(), newTimeLimit - this.timeLimit); + setTimeLimit(newTimeLimit); } - public void setTimeLimit(int timeLimit) { - this.timeLimit = timeLimit; - } - - public int getTimeLeft() { - return timeLeft; - } - - public void setTimeLeft(int timeLeft) { + /** + * This method can also be used to adjust the expirations for an in-process assessment + * @param beginDate + * @param localBeginDate + * @param timeLeft + */ + private void setExpirationDates(Date beginDate, Date localBeginDate, int timeLeft) { this.timeLeft = timeLeft; + this.expirationDate = new Date(beginDate.getTime() + timeLeft*1000L); + this.bufferedExpirationDate = new Date(beginDate.getTime() + timeLeft*1000L + latencyBuffer*1000); + this.localExpirationDate = new Date(localBeginDate.getTime() + timeLeft*1000L); } - public int getLatencyBuffer() { - return latencyBuffer; - } - - public void setLatencyBuffer(int latencyBuffer) { - this.latencyBuffer = latencyBuffer; - } - - public int getTransactionBuffer() { - return transactionBuffer; - } - - public void setTransactionBuffer(int transactionBuffer) { - this.transactionBuffer = transactionBuffer; - } - - public Date getBeginDate() { - return beginDate; - } - - public void setBeginDate(Date beginDate) { - this.beginDate = beginDate; - } - - public Date getExpirationDate() { - return expirationDate; - } - - public void setExpirationDate(Date expirationDate) { - this.expirationDate = expirationDate; - } - - public Date getBufferedExpirationDate() { - return bufferedExpirationDate; - } - - public void setBufferedExpirationDate(Date bufferedExpirationDate) { - this.bufferedExpirationDate = bufferedExpirationDate; - } - - public Date getLocalBeginDate() { - return localBeginDate; - } - - public void setLocalBeginDate(Date localBeginDate) { - this.localBeginDate = localBeginDate; - } - - public Date getLocalExpirationDate() { - return localExpirationDate; - } - - public void setLocalExpirationDate(Date localExpirationDate) { - this.localExpirationDate = localExpirationDate; - } - - public boolean getSubmittedForGrade() { - return submittedForGrade; - } - - public void setSubmittedForGrade(boolean submittedForGrade) { - this.submittedForGrade = submittedForGrade; - } - - public String getTimerId(){ - return timerId; - } - - public void setTimerId(String timerId) { - this.timerId = timerId; - } - - public PublishedAssessmentFacade getPublishedAssessment(){ - return publishedAssessment; - } - - public void setPublishedAssessment(PublishedAssessmentFacade publishedAssessment) { - this.publishedAssessment = publishedAssessment; - } } diff --git a/samigo/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/queue/delivery/TimedAssessmentRunnable.java b/samigo/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/queue/delivery/TimedAssessmentRunnable.java index 18a04b53d661..765e3fc97a1e 100644 --- a/samigo/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/queue/delivery/TimedAssessmentRunnable.java +++ b/samigo/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/queue/delivery/TimedAssessmentRunnable.java @@ -44,6 +44,7 @@ import org.sakaiproject.tool.assessment.services.assessment.EventLogService; import org.sakaiproject.tool.assessment.services.assessment.PublishedAssessmentService; import org.sakaiproject.tool.assessment.ui.model.delivery.TimedAssessmentGradingModel; +import org.sakaiproject.tool.assessment.util.ExtendedTimeDeliveryService; import org.sakaiproject.user.cover.UserDirectoryService; import org.sakaiproject.util.api.FormattedText; @@ -85,7 +86,7 @@ public void run(){ TimedAssessmentGradingModel timedAG = this.queue.get(this.timedAGId); String serverName = serverConfigurationService.getServerName(); - boolean submitted = timedAG.getSubmittedForGrade(); + boolean submitted = timedAG.isSubmittedForGrade(); long bufferedExpirationTime = timedAG.getBufferedExpirationDate().getTime(); // in millesec long currentTime = (new Date()).getTime(); // in millisec @@ -93,13 +94,36 @@ public void run(){ if (!submitted){ if (currentTime > bufferedExpirationTime){ // time's up, i.e. timeLeft + latency buffer reached - timedAG.setSubmittedForGrade(true); + // set all the properties right and persist status to DB GradingService service = new GradingService(); AssessmentGradingData ag = service.load(String.valueOf(this.timedAGId), false); + PublishedAssessmentService publishedAssessmentService = new PublishedAssessmentService(); + String siteId = publishedAssessmentService.getPublishedAssessmentOwner(ag.getPublishedAssessmentId()); + PublishedAssessmentFacade publishedAssessment = publishedAssessmentService.getPublishedAssessment(ag.getPublishedAssessmentId().toString()); + ExtendedTimeDeliveryService assessmentExtended = new ExtendedTimeDeliveryService(publishedAssessment, ag.getAgentId()); + Integer extendedTime = null; + + // The specific student has more time than the thread knows about + if (assessmentExtended != null && assessmentExtended.hasExtendedTime()) { + extendedTime = assessmentExtended.getTimeLimit(); + } + // Maybe the instructor extended the time allowed after the student began? + else if (publishedAssessment != null && publishedAssessment.getTimeLimit() != null) { + extendedTime = publishedAssessment.getTimeLimit(); + } + + // Did the instructor add more time after student started assessment? + if (extendedTime != null && extendedTime > timedAG.getTimeLimit()) { + log.info("SAMIGO_TIMED_ASSESSMENT:EXTENDED ID:{} old_limit:{}, extended_time:{}", this.timedAGId, timedAG.getTimeLimit(), extendedTime); + timedAG.setNewTimeLimit(extendedTime); + return; + } log.info("SAMIGO_TIMED_ASSESSMENT:SUBMIT ID:{} userId:{}", this.timedAGId, ag.getAgentId()); + timedAG.setSubmittedForGrade(true); + if (!ag.getForGrade()) { Date submitDate = new Date(); @@ -132,10 +156,6 @@ public void run(){ service.completeItemGradingData(ag); service.saveOrUpdateAssessmentGrading(ag); - PublishedAssessmentService publishedAssessmentService = new PublishedAssessmentService(); - String siteId = publishedAssessmentService.getPublishedAssessmentOwner(ag.getPublishedAssessmentId()); - PublishedAssessmentFacade publishedAssessment = publishedAssessmentService.getPublishedAssessment(ag.getPublishedAssessmentId().toString()); - EventLogService eventService = new EventLogService(); EventLogFacade eventLogFacade = new EventLogFacade(); EventLogData eventLogData;