Skip to content
Snippets Groups Projects
Commit 03809711 authored by srosse's avatar srosse
Browse files

Merge remote-tracking branch 'origin/OpenOLAT_15.1'

parents 1910ea6f 7b567f97
No related branches found
No related tags found
No related merge requests found
......@@ -49,6 +49,7 @@ import uk.ac.ed.ph.jqtiplus.reading.QtiXmlReader;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentItem;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentObject;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentTest;
import uk.ac.ed.ph.jqtiplus.running.TestSessionController;
import uk.ac.ed.ph.jqtiplus.serialization.QtiSerializer;
import uk.ac.ed.ph.jqtiplus.state.ItemSessionState;
import uk.ac.ed.ph.jqtiplus.state.TestPlanNodeKey;
......@@ -512,5 +513,10 @@ public interface QTI21Service {
* @return A number of seconds, 0 if nothing found
*/
public Long getMetadataCorrectionTimeInSeconds(RepositoryEntry testEntry, AssessmentTestSession candidateSession);
public void putCachedTestSessionController(AssessmentTestSession testSession, TestSessionController testSessionController);
public TestSessionController getCachedTestSessionController(AssessmentTestSession testSession, TestSessionController testSessionController);
}
......@@ -149,6 +149,7 @@ import uk.ac.ed.ph.jqtiplus.reading.QtiXmlReader;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentItem;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentObject;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentTest;
import uk.ac.ed.ph.jqtiplus.running.TestSessionController;
import uk.ac.ed.ph.jqtiplus.serialization.QtiSerializer;
import uk.ac.ed.ph.jqtiplus.serialization.SaxFiringOptions;
import uk.ac.ed.ph.jqtiplus.state.AssessmentSectionSessionState;
......@@ -229,6 +230,7 @@ public class QTI21ServiceImpl implements QTI21Service, UserDataDeletable, Initia
private InfinispanXsltStylesheetCache xsltStylesheetCache;
private CacheWrapper<File,ResolvedAssessmentTest> assessmentTestsCache;
private CacheWrapper<File,ResolvedAssessmentItem> assessmentItemsCache;
private CacheWrapper<AssessmentTestSession,TestSessionController> testSessionControllersCache;
private final ConcurrentMap<String,URI> resourceToTestURI = new ConcurrentHashMap<>();
......@@ -255,6 +257,7 @@ public class QTI21ServiceImpl implements QTI21Service, UserDataDeletable, Initia
Cacher cacher = coordinatorManager.getInstance().getCoordinator().getCacher();
assessmentTestsCache = cacher.getCache("QTIWorks", "assessmentTests");
assessmentItemsCache = cacher.getCache("QTIWorks", "assessmentItems");
testSessionControllersCache = cacher.getCache("QTIWorks", "testSessionControllers");
}
@Override
......@@ -593,6 +596,8 @@ public class QTI21ServiceImpl implements QTI21Service, UserDataDeletable, Initia
@Override
public AssessmentTestSession reloadAssessmentTestSession(AssessmentTestSession session) {
if(session == null) return null;
if(session.getKey() == null) return session;
return testSessionDao.loadByKey(session.getKey());
}
......@@ -1582,4 +1587,18 @@ public class QTI21ServiceImpl implements QTI21Service, UserDataDeletable, Initia
return Long.valueOf(timeInMinutes * 60l);
}
@Override
public void putCachedTestSessionController(AssessmentTestSession testSession, TestSessionController testSessionController) {
if(testSession == null || testSessionController == null) return;
testSessionControllersCache.put(testSession, testSessionController);
}
@Override
public TestSessionController getCachedTestSessionController(AssessmentTestSession testSession, TestSessionController testSessionController) {
if(testSession == null) return null;
TestSessionController result = testSessionControllersCache.get(testSession);
return result == null ? testSessionController : result;
}
}
......@@ -415,8 +415,11 @@ public class AssessmentTestDisplayController extends BasicController implements
resourcesList.deregisterResourceable(entry, subIdent, getWindow());
}
try {
suspendAssessmentTest(new Date());
candidateSession = qtiService.reloadAssessmentTestSession(candidateSession);
if(candidateSession != null) {
testSessionController = qtiService.getCachedTestSessionController(candidateSession, testSessionController);
suspendAssessmentTest(new Date());
OLATResourceable sessionOres = OresHelper
.createOLATResourceableInstance(AssessmentTestSession.class, candidateSession.getKey());
CoordinatorManager.getInstance().getCoordinator().getEventBus().deregisterFor(this, sessionOres);
......@@ -570,6 +573,8 @@ public class AssessmentTestDisplayController extends BasicController implements
}
private void doSuspend(UserRequest ureq) {
testSessionController = qtiService.getCachedTestSessionController(candidateSession, testSessionController);
VelocityContainer suspendedVC = createVelocityContainer("suspended");
mainPanel.setContent(suspendedVC);
suspendAssessmentTest(ureq.getRequestTimestamp());
......@@ -648,6 +653,17 @@ public class AssessmentTestDisplayController extends BasicController implements
return sessionDeleted;
}
private boolean sessionEndedOrSuspended() {
TestSessionState testSessionState = testSessionController.getTestSessionState();
if(testSessionState.isEnded() || testSessionState.isSuspended()) {
candidateSession = qtiService.reloadAssessmentTestSession(candidateSession);
showWarning("warning.suspended.ended.assessmenttest");
logAudit("Try to work on an ended/suspended test");
return true;
}
return false;
}
/**
* This method maintains the assessment test in cache during
* a test session. This controller doesn't need the cache, the
......@@ -765,7 +781,9 @@ public class AssessmentTestDisplayController extends BasicController implements
}
private void processQTIEvent(UserRequest ureq, QTIWorksAssessmentTestEvent qe) {
if(timeLimitBarrier(ureq) || sessionReseted(ureq)) {
testSessionController = qtiService.getCachedTestSessionController(candidateSession, testSessionController);
if(timeLimitBarrier(ureq) || sessionReseted(ureq) || sessionEndedOrSuspended()) {
return;
}
......@@ -1720,6 +1738,7 @@ public class AssessmentTestDisplayController extends BasicController implements
if (notificationRecorder!=null) {
result.addNotificationListener(notificationRecorder);
}
qtiService.putCachedTestSessionController(candidateSession, result);
return result;
}
......@@ -1727,9 +1746,9 @@ public class AssessmentTestDisplayController extends BasicController implements
Date requestTimestamp = ureq.getRequestTimestamp();
final NotificationRecorder notificationRecorder = new NotificationRecorder(NotificationLevel.INFO);
TestSessionController controller = createTestSessionController(notificationRecorder);
TestSessionController controller = createTestSessionController(notificationRecorder);
if(!controller.getTestSessionState().isEnded() && !controller.getTestSessionState().isExited()) {
controller.unsuspendTestSession(requestTimestamp);
controller.unsuspendTestSession(requestTimestamp);
TestSessionState testSessionState = controller.getTestSessionState();
TestPlanNodeKey currentItemKey = testSessionState.getCurrentItemKey();
......@@ -1749,8 +1768,13 @@ public class AssessmentTestDisplayController extends BasicController implements
}
private TestSessionController createTestSessionController(NotificationRecorder notificationRecorder) {
final TestSessionState testSessionState = qtiService.loadTestSessionState(candidateSession);
return createTestSessionController(testSessionState, notificationRecorder);
TestSessionController result = qtiService.getCachedTestSessionController(candidateSession, null);
if(result == null) {
final TestSessionState testSessionState = qtiService.loadTestSessionState(candidateSession);
result = createTestSessionController(testSessionState, notificationRecorder);
qtiService.putCachedTestSessionController(candidateSession, result);
}
return result;
}
public TestSessionController createTestSessionController(TestSessionState testSessionState, NotificationRecorder notificationRecorder) {
......
......@@ -282,5 +282,6 @@ validate.xml.signature.ok=Testquittung und Datei konnte erfolgreich validiert we
warning.download.log=Es gibt leider kein Logdatei f\u00FCr diesen Test.
warning.reset.assessmenttest.data=Die Test-Resultate wurden von einem Administrator oder Kursbesitzer zur\u00FCckgesetzt. Sie k\u00F6nnen den Test nicht fortsetzen und m\u00FCssen ihn erneut starten.
warning.reset.test.data.nobody=Es gibt kein Teilnehmer zu zur\u00FCcksetzen
warning.suspended.ended.assessmenttest=Sie haben schon den Test unterbrochen oder beendet, wahrscheinlich in einem anderen Fenster. Bitte, diese Fenster jetzt schliessen.
warning.xml.signature.notok=Unterschrift und Datei konnte nicht validiert werden.
warning.xml.signature.session.not.found=Die Resultaten konnte nicht gefunden werden.
......@@ -281,6 +281,7 @@ validate.xml.signature.file=XML file
validate.xml.signature.ok=Test receipt and results was successfully validated.
warning.download.log=There is not a log file for this test.
warning.reset.assessmenttest.data=The test results were reset by an administrator or course owner. You cannot continue the test and have to restart it.
warning.suspended.ended.assessmenttest=You have already suspended or ended this test, probably in an other window. Please close this window.
warning.reset.test.data.nobody=There isn't any participant which data can be reseted.
warning.xml.signature.notok=Signature and results cannot be validate each other.
warning.xml.signature.session.not.found=Tests results cannot be found.
......@@ -77,6 +77,13 @@
<expiration max-idle="1800000" interval="15000" />
</local-cache>
<local-cache name="QTIWorks@testSessionControllers" simple-cache="true" statistics="true" statistics-available="true">
<locking isolation="READ_COMMITTED" concurrency-level="1000" acquire-timeout="15000" striping="false" />
<transaction mode="NONE" auto-commit="true" />
<memory max-count="50000" when-full="REMOVE" />
<expiration max-idle="7200000" interval="15000" />
</local-cache>
<local-cache name="WebDAVManager@webdav" simple-cache="true" statistics="true" statistics-available="true">
<locking isolation="READ_COMMITTED" concurrency-level="1000" acquire-timeout="15000" striping="false" />
<transaction mode="NONE" auto-commit="true" />
......
......@@ -517,13 +517,14 @@ public class QTI21Page {
*/
public QTI21Page answerGraphicGapClick(String item, String gap) {
By sourceBy = By.xpath("//div[contains(@class,'gap_container')]/div[contains(@class,'o_gap_item')][@data-qti-id='" + item + "']");
OOGraphene.waitElement(sourceBy, 5, browser);
OOGraphene.waitElement(sourceBy, browser);
browser.findElement(sourceBy).click();
By areaBy = By.xpath("//div[@class='graphicGapMatchInteraction']//map/area[@data-qti-id='" + gap + "']");
WebElement areaEl = browser.findElement(areaBy);
String coords = areaEl.getAttribute("coords");
By imgBy = By.xpath("//div[contains(@class,'graphicGapMatchInteraction')]/div/div/img");
WebElement element = browser.findElement(imgBy);
By canvasBy = By.xpath("//div[contains(@class,'graphicGapMatchInteraction')]/div/div/canvas");
OOGraphene.waitElement(canvasBy, browser);
WebElement element = browser.findElement(canvasBy);
Dimension dim = element.getSize();
Position pos = Position.valueOf(coords, dim);
new Actions(browser)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment