use of uk.ac.ed.ph.jqtiplus.exception.QtiCandidateStateException in project OpenOLAT by OpenOLAT.
the class AssessmentTestDisplayController method nextItemIfAllowed.
/**
* Try to go to the next item. It will check fi the current
* item want to show some feedback (modal or element), has some
* bad or invalid responses, state of the test session... or if
* the item is an adaptive one.
*
* @param ureq
*/
private void nextItemIfAllowed(UserRequest ureq) {
if (testSessionController.hasFollowingNonLinearItem() && testSessionController.getTestSessionState() != null && !testSessionController.getTestSessionState().isEnded() && !testSessionController.getTestSessionState().isExited()) {
try {
TestSessionState testSessionState = testSessionController.getTestSessionState();
TestPlanNodeKey itemNodeKey = testSessionState.getCurrentItemKey();
if (itemNodeKey != null) {
TestPlanNode currentItemNode = testSessionState.getTestPlan().getNode(itemNodeKey);
boolean hasFeedbacks = qtiWorksCtrl.willShowSomeAssessmentItemFeedbacks(currentItemNode);
// allow skipping
if (!hasFeedbacks) {
processNextItem(ureq);
}
}
} catch (QtiCandidateStateException e) {
// log informations
logError("", e);
ServletUtil.printOutRequestParameters(ureq.getHttpReq());
}
}
}
use of uk.ac.ed.ph.jqtiplus.exception.QtiCandidateStateException in project OpenOLAT by OpenOLAT.
the class AssessmentTestDisplayController method processEndTestPart.
// public CandidateSession endCurrentTestPart(final CandidateSessionContext candidateSessionContext)
private void processEndTestPart(UserRequest ureq) {
/* Update state */
final Date requestTimestamp = ureq.getRequestTimestamp();
testSessionController.endCurrentTestPart(requestTimestamp);
TestSessionState testSessionState = testSessionController.getTestSessionState();
TestPlanNode nextTestPart = testSessionController.findNextEnterableTestPart();
// Record current result state
final AssessmentResult assessmentResult = computeAndRecordTestAssessmentResult(requestTimestamp, testSessionState, nextTestPart == null);
if (nextTestPart == null) {
candidateSession = qtiService.finishTestSession(candidateSession, testSessionState, assessmentResult, requestTimestamp, getDigitalSignatureOptions(), getIdentity());
if (!qtiWorksCtrl.willShowSomeAssessmentTestFeedbacks()) {
// need feedback, no more parts, quickly exit
try {
// end current test part
testSessionController.enterNextAvailableTestPart(requestTimestamp);
} catch (final QtiCandidateStateException e) {
candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.CANNOT_ADVANCE_TEST_PART, e);
logError("CANNOT_ADVANCE_TEST_PART", e);
return;
} catch (final RuntimeException e) {
candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.CANNOT_ADVANCE_TEST_PART, e);
logError("RuntimeException", e);
// handleExplosion(e, candidateSession);
return;
}
// exit the test
NotificationRecorder notificationRecorder = new NotificationRecorder(NotificationLevel.INFO);
CandidateTestEventType eventType = CandidateTestEventType.EXIT_TEST;
testSessionController.exitTest(requestTimestamp);
candidateSession.setTerminationTime(requestTimestamp);
candidateSession = qtiService.updateAssessmentTestSession(candidateSession);
/* Record and log event */
final CandidateEvent candidateTestEvent = qtiService.recordCandidateTestEvent(candidateSession, testEntry, entry, eventType, testSessionState, notificationRecorder);
candidateAuditLogger.logCandidateEvent(candidateTestEvent);
this.lastEvent = candidateTestEvent;
qtiWorksCtrl.updateStatusAndResults(ureq);
doExitTest(ureq);
}
} else if (!qtiWorksCtrl.willShowSomeTestPartFeedbacks()) {
// no feedback, go to the next part
processAdvanceTestPart(ureq);
}
}
use of uk.ac.ed.ph.jqtiplus.exception.QtiCandidateStateException in project OpenOLAT by OpenOLAT.
the class AssessmentTestDisplayController method processFinishLinearItem.
// public CandidateSession finishLinearItem(final CandidateSessionContext candidateSessionContext)
// throws CandidateException {
private void processFinishLinearItem(UserRequest ureq) {
NotificationRecorder notificationRecorder = new NotificationRecorder(NotificationLevel.INFO);
TestSessionState testSessionState = testSessionController.getTestSessionState();
try {
if (!testSessionController.mayAdvanceItemLinear()) {
candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.CANNOT_FINISH_LINEAR_TEST_ITEM, null);
logError("CANNOT_FINISH_LINEAR_TEST_ITEM", null);
return;
}
} catch (QtiCandidateStateException e) {
candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.CANNOT_FINISH_LINEAR_TEST_ITEM, e);
logError("CANNOT_FINISH_LINEAR_TEST_ITEM", e);
return;
} catch (RuntimeException e) {
candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.CANNOT_FINISH_LINEAR_TEST_ITEM, e);
logError("CANNOT_FINISH_LINEAR_TEST_ITEM", e);
// handleExplosion(e, candidateSession);
return;
}
// Update state
final Date requestTimestamp = ureq.getRequestTimestamp();
final TestPlanNode nextItemNode = testSessionController.advanceItemLinear(requestTimestamp);
// boolean terminated = nextItemNode == null && testSessionController.findNextEnterableTestPart() == null;
// Record current result state
final AssessmentResult assessmentResult = computeAndRecordTestAssessmentResult(requestTimestamp, testSessionState, false);
/* If we ended the testPart and there are now no more available testParts, then finish the session now */
if (nextItemNode == null && testSessionController.findNextEnterableTestPart() == null) {
candidateSession = qtiService.finishTestSession(candidateSession, testSessionState, assessmentResult, requestTimestamp, getDigitalSignatureOptions(), getIdentity());
}
// Record and log event
final CandidateTestEventType eventType = nextItemNode != null ? CandidateTestEventType.FINISH_ITEM : CandidateTestEventType.FINISH_FINAL_ITEM;
final CandidateEvent candidateTestEvent = qtiService.recordCandidateTestEvent(candidateSession, testEntry, entry, eventType, null, null, testSessionState, notificationRecorder);
this.lastEvent = candidateTestEvent;
candidateAuditLogger.logCandidateEvent(candidateTestEvent);
}
use of uk.ac.ed.ph.jqtiplus.exception.QtiCandidateStateException in project openolat by klemens.
the class AssessmentItemDisplayController method requestSolution.
public void requestSolution(UserRequest ureq) {
ItemSessionState itemSessionState = itemSessionController.getItemSessionState();
/* Make sure caller may do this */
// itemDeliverySettings.isAllowSolutionWhenOpen()
boolean allowSolutionWhenOpen = true;
if (!itemSessionState.isEnded() && !allowSolutionWhenOpen) {
candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.SOLUTION_WHEN_INTERACTING_FORBIDDEN, null);
logError("SOLUTION_WHEN_INTERACTING_FORBIDDEN", null);
return;
} else if (itemSessionState.isEnded()) /* && !itemDeliverySettings.isAllowSoftResetWhenEnded() */
{
candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.SOLUTION_WHEN_ENDED_FORBIDDEN, null);
logError("SOLUTION_WHEN_ENDED_FORBIDDEN", null);
return;
}
/* End session if still open */
final Date timestamp = ureq.getRequestTimestamp();
boolean isClosingSession = false;
if (!itemSessionState.isEnded()) {
isClosingSession = true;
try {
itemSessionController.endItem(timestamp);
} catch (final QtiCandidateStateException e) {
candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.SOLUTION_WHEN_ENDED_FORBIDDEN, null);
logError("SOLUTION_WHEN_ENDED_FORBIDDEN", e);
return;
} catch (final RuntimeException e) {
logError("", e);
// handleExplosion(e, candidateSession);
return;
}
}
/* Record current result state, and maybe close session */
final AssessmentResult assessmentResult = computeAndRecordItemAssessmentResult(ureq);
if (isClosingSession) {
qtiService.finishItemSession(candidateSession, assessmentResult, timestamp);
}
/* Record and log event */
final CandidateEvent candidateEvent = qtiService.recordCandidateItemEvent(candidateSession, null, entry, CandidateItemEventType.SOLUTION, itemSessionState);
candidateAuditLogger.logCandidateEvent(candidateEvent);
lastEvent = candidateEvent;
}
use of uk.ac.ed.ph.jqtiplus.exception.QtiCandidateStateException in project openolat by klemens.
the class AssessmentItemDisplayController method handleResponses.
public void handleResponses(UserRequest ureq, Map<Identifier, ResponseInput> stringResponseMap, Map<Identifier, ResponseInput> fileResponseMap, String candidateComment) {
/* Retrieve current JQTI state and set up JQTI controller */
NotificationRecorder notificationRecorder = new NotificationRecorder(NotificationLevel.INFO);
ItemSessionState itemSessionState = itemSessionController.getItemSessionState();
/* Make sure an attempt is allowed */
if (itemSessionState.isEnded()) {
candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.RESPONSES_NOT_EXPECTED, null);
logError("RESPONSES_NOT_EXPECTED", null);
return;
}
/* Build response map in required format for JQTI+.
* NB: The following doesn't test for duplicate keys in the two maps. I'm not sure
* it's worth the effort.
*/
final Map<Identifier, ResponseData> responseDataMap = new HashMap<>();
// final Map<Identifier, CandidateFileSubmission> fileSubmissionMap = new HashMap<>();
final Map<Identifier, AssessmentResponse> assessmentResponseDataMap = new HashMap<>();
if (stringResponseMap != null) {
for (final Entry<Identifier, ResponseInput> stringResponseEntry : stringResponseMap.entrySet()) {
Identifier identifier = stringResponseEntry.getKey();
ResponseInput responseData = stringResponseEntry.getValue();
if (responseData instanceof StringInput) {
responseDataMap.put(identifier, new StringResponseData(((StringInput) responseData).getResponseData()));
} else if (responseData instanceof Base64Input) {
// TODO
} else if (responseData instanceof FileInput) {
}
}
}
if (fileResponseMap != null) {
for (final Entry<Identifier, ResponseInput> fileResponseEntry : fileResponseMap.entrySet()) {
final Identifier identifier = fileResponseEntry.getKey();
final FileInput multipartFile = (FileInput) fileResponseEntry.getValue();
if (!multipartFile.isEmpty()) {
// final CandidateFileSubmission fileSubmission = candidateUploadService.importFileSubmission(candidateSession, multipartFile);
File storedFile = qtiService.importFileSubmission(candidateSession, multipartFile.getMultipartFileInfos());
final FileResponseData fileResponseData = new FileResponseData(storedFile, multipartFile.getContentType(), multipartFile.getFileName());
responseDataMap.put(identifier, fileResponseData);
assessmentResponseDataMap.put(identifier, new AssessmentResponseData(identifier, fileResponseData));
// fileSubmissionMap.put(identifier, fileSubmission);
}
}
}
/* Submit comment (if provided)
* NB: Do this first in case next actions end the item session.
*/
final Date timestamp = ureq.getRequestTimestamp();
if (candidateComment != null) {
try {
itemSessionController.setCandidateComment(timestamp, candidateComment);
} catch (final QtiCandidateStateException e) {
candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.CANDIDATE_COMMENT_FORBIDDEN, e);
logError("CANDIDATE_COMMENT_FORBIDDEN", null);
return;
} catch (final RuntimeException e) {
logError("", e);
// handleExplosion(e, candidateSession);
return;
}
}
/* Attempt to bind responses */
boolean allResponsesValid = false, allResponsesBound = false;
try {
itemSessionController.bindResponses(timestamp, responseDataMap);
/* Note any responses that failed to bind */
final Set<Identifier> badResponseIdentifiers = itemSessionState.getUnboundResponseIdentifiers();
allResponsesBound = badResponseIdentifiers.isEmpty();
/* Now validate the responses according to any constraints specified by the interactions */
if (allResponsesBound) {
final Set<Identifier> invalidResponseIdentifiers = itemSessionState.getInvalidResponseIdentifiers();
allResponsesValid = invalidResponseIdentifiers.isEmpty();
}
/* (We commit responses immediately here) */
itemSessionController.commitResponses(timestamp);
/* Invoke response processing (only if responses are valid) */
if (allResponsesValid) {
itemSessionController.performResponseProcessing(timestamp);
}
} catch (final QtiCandidateStateException e) {
candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.RESPONSES_NOT_EXPECTED, null);
logError("RESPONSES_NOT_EXPECTED", e);
return;
} catch (final RuntimeException e) {
logError("", e);
// handleExplosion(e, candidateSession);
return;
}
/* Record resulting attempt and event */
final CandidateItemEventType eventType = allResponsesBound ? (allResponsesValid ? CandidateItemEventType.ATTEMPT_VALID : CandidateItemEventType.RESPONSE_INVALID) : CandidateItemEventType.RESPONSE_BAD;
final CandidateEvent candidateEvent = qtiService.recordCandidateItemEvent(candidateSession, null, entry, eventType, itemSessionState, notificationRecorder);
candidateAuditLogger.logCandidateEvent(candidateEvent, assessmentResponseDataMap);
lastEvent = candidateEvent;
/* Record current result state, or finish session */
updateSessionFinishedStatus(ureq);
}
Aggregations