From b5b051ef178983a97e303f68d66e2eec4cef0c06 Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Wed, 27 May 2020 16:29:01 +0200
Subject: [PATCH] OO-4707: allow time extension if start / end date specified
 in test el.

---
 .../org/olat/course/nodes/IQTESTCourseNode.java    | 13 ++++++-------
 .../course/nodes/iq/ExtraTimeCellRenderer.java     | 14 +++++++++++++-
 .../iq/IQIdentityListCourseNodeController.java     |  5 ++++-
 3 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java b/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java
index 7979b05a7d2..87784467b4c 100644
--- a/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java
@@ -52,6 +52,7 @@ import org.olat.core.logging.DBRuntimeException;
 import org.olat.core.logging.KnownIssueException;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.Util;
+import org.olat.core.util.ValidationStatus;
 import org.olat.core.util.coordinate.CoordinatorManager;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.course.ICourse;
@@ -220,7 +221,8 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements Pe
 		if(ImsQTI21Resource.TYPE_NAME.equals(testEntry.getOlatResource().getResourceableTypeName())) {
 			ModuleConfiguration config = getModuleConfiguration();
 			boolean configRef = config.getBooleanSafe(IQEditController.CONFIG_KEY_CONFIG_REF, false);
-			if(!configRef && config.getIntegerSafe(IQEditController.CONFIG_KEY_TIME_LIMIT, -1) > 0) {
+			if(!configRef && (config.getIntegerSafe(IQEditController.CONFIG_KEY_TIME_LIMIT, -1) > 0
+					|| config.getDateValue(IQEditController.CONFIG_KEY_RESULTS_END_TEST_DATE) != null)) {
 				timeLimit = true;
 			} else {
 				AssessmentTest assessmentTest = loadAssessmentTest(testEntry);
@@ -344,9 +346,6 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements Pe
 		return false;
 	}
 
-	/**
-	 * @see org.olat.course.nodes.CourseNode#isConfigValid()
-	 */
 	@Override
 	public StatusDescription isConfigValid() {
 		/*
@@ -357,7 +356,7 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements Pe
 		boolean isValid = getModuleConfiguration().get(IQEditController.CONFIG_KEY_REPOSITORY_SOFTKEY) != null;
 		if (isValid) {
 			/*
-			 * COnfiugre an IQxxx BB with a repo entry, do not publish
+			 * Configure an IQxxx BB with a repo entry, do not publish
 			 * this BB, mark IQxxx as deleted, remove repo entry, undelete BB IQxxx
 			 * and bang you enter this if.
 			 */
@@ -372,7 +371,7 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements Pe
 			String shortKey = "error.test.undefined.short";
 			String longKey = "error.test.undefined.long";
 			String[] params = new String[] { getShortTitle() };
-			sd = new StatusDescription(StatusDescription.ERROR, shortKey, longKey, params, translatorStr);
+			sd = new StatusDescription(ValidationStatus.ERROR, shortKey, longKey, params, translatorStr);
 			sd.setDescriptionForUnit(getIdent());
 			// set which pane is affected by error
 			sd.setActivateableViewIdentifier(IQEditController.PANE_TAB_IQCONFIG_TEST);
@@ -715,7 +714,7 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements Pe
 		try {
 			RepositoryEntry re = RepositoryManager.getInstance().lookupRepositoryEntryBySoftkey(repositorySoftKey, false);
 			if(re == null) {
-				log.error("Cannot archive course node. Missing repository entry with soft key: ", repositorySoftKey);
+				log.error("Cannot archive course node. Missing repository entry with soft key: {}", repositorySoftKey);
 				return false;
 			}
 			
diff --git a/src/main/java/org/olat/course/nodes/iq/ExtraTimeCellRenderer.java b/src/main/java/org/olat/course/nodes/iq/ExtraTimeCellRenderer.java
index 8537ef32fab..8577b5e8aa6 100644
--- a/src/main/java/org/olat/course/nodes/iq/ExtraTimeCellRenderer.java
+++ b/src/main/java/org/olat/course/nodes/iq/ExtraTimeCellRenderer.java
@@ -39,11 +39,13 @@ import org.olat.core.util.Formatter;
  */
 public class ExtraTimeCellRenderer implements FlexiCellRenderer {
 	
+	private final Date endDate;
 	private final boolean renderDueDate;
 	private final int timeLimitInSeconds;
 	private final Formatter formatter;
 	
-	public ExtraTimeCellRenderer(boolean renderDueDate, int timeLimitInSeconds, Locale locale) {
+	public ExtraTimeCellRenderer(boolean renderDueDate, int timeLimitInSeconds, Date endDate, Locale locale) {
+		this.endDate = endDate;
 		this.renderDueDate = renderDueDate;
 		this.timeLimitInSeconds = timeLimitInSeconds;
 		formatter = Formatter.getInstance(locale);
@@ -59,6 +61,16 @@ public class ExtraTimeCellRenderer implements FlexiCellRenderer {
 			if(renderDueDate) {
 				if(infos.getStart() != null) {
 					int totalTime = timeLimitInSeconds;
+					if(endDate != null) {
+						long leadingTimeInMilliSeconds = endDate.getTime() - infos.getStart().getTime();
+						int leadingTime = Math.round(leadingTimeInMilliSeconds / 1000f);
+						if(timeLimitInSeconds > 0) {
+							totalTime = Math.min(totalTime, leadingTime);
+						} else {
+							totalTime = leadingTime;
+						}
+					}
+	
 					if(extraTimeInSeconds != null) {
 						totalTime += extraTimeInSeconds;
 					}
diff --git a/src/main/java/org/olat/course/nodes/iq/IQIdentityListCourseNodeController.java b/src/main/java/org/olat/course/nodes/iq/IQIdentityListCourseNodeController.java
index fb2d2d8defb..c0ca3c4567b 100644
--- a/src/main/java/org/olat/course/nodes/iq/IQIdentityListCourseNodeController.java
+++ b/src/main/java/org/olat/course/nodes/iq/IQIdentityListCourseNodeController.java
@@ -148,7 +148,8 @@ public class IQIdentityListCourseNodeController extends IdentityListCourseNodeCo
 		if(testCourseNode != null && testCourseNode.hasQTI21TimeLimit(qtiTestEntry)) {
 			int timeLimitInSeconds = testCourseNode.getQTI21TimeLimitMaxInSeconds(qtiTestEntry);
 			boolean suspendEnabled = isSuspendEnable();
-			FlexiCellRenderer renderer = new ExtraTimeCellRenderer(!suspendEnabled, timeLimitInSeconds, getLocale());
+			Date endDate = testCourseNode.getModuleConfiguration().getDateValue(IQEditController.CONFIG_KEY_RESULTS_END_TEST_DATE);
+			FlexiCellRenderer renderer = new ExtraTimeCellRenderer(!suspendEnabled, timeLimitInSeconds, endDate, getLocale());
 			String header = suspendEnabled ? "table.header.extra.time" : "table.header.end.date";
 			columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(header, IdentityCourseElementCols.details.ordinal(), renderer));
 		}
@@ -323,6 +324,8 @@ public class IQIdentityListCourseNodeController extends IdentityListCourseNodeCo
 				doUpdateCourseNode(catse.getTestSessions(), catse.getAssessmentTest(), catse.getStatus());
 				loadModel(ureq);	
 				fireEvent(ureq, Event.CHANGED_EVENT);
+			} else if(event == Event.DONE_EVENT) {
+				loadModel(ureq);
 			}
 		}
 		super.event(ureq, source, event);
-- 
GitLab