Search in sources :

Example 6 with CandidateEvent

use of org.olat.ims.qti21.model.audit.CandidateEvent in project OpenOLAT by OpenOLAT.

the class AuditLogFormatter method log.

protected static void log(CandidateEvent candidateEvent, Map<Identifier, AssessmentResponse> candidateResponseMap, Writer writer) throws IOException {
    writer.append("QTI21 audit [");
    AssessmentTestSession testSession = candidateEvent.getCandidateSession();
    if (testSession != null) {
        RepositoryEntryRef testEntry = candidateEvent.getTestEntry();
        RepositoryEntryRef courseEntry = candidateEvent.getRepositoryEntry();
        if (courseEntry != null && !testEntry.getKey().equals(courseEntry.getKey())) {
            writer.write(courseEntry.getKey().toString());
            writer.write(":");
            if (testSession.getSubIdent() == null) {
                writer.write("NULL:");
            } else {
                writer.write(testSession.getSubIdent());
                writer.write(":");
            }
        }
        if (testEntry != null) {
            writer.write(testEntry.getKey().toString());
        }
    }
    writer.write("] ");
    if (candidateEvent.getTestEventType() != null) {
        writer.append("TestEvent:");
        writer.append(candidateEvent.getTestEventType().toString());
        writer.write(" ");
    }
    if (candidateEvent.getItemEventType() != null) {
        writer.append("ItemEvent:");
        writer.append(candidateEvent.getItemEventType().toString());
        writer.write(" ");
    }
    if (candidateEvent.getTestItemKey() != null) {
        writer.append("TestItemKey[");
        writer.append(candidateEvent.getTestItemKey());
        writer.write("] ");
    }
    if (candidateResponseMap != null) {
        writer.write("params=");
        for (Map.Entry<Identifier, AssessmentResponse> responseEntry : candidateResponseMap.entrySet()) {
            Identifier identifier = responseEntry.getKey();
            AssessmentResponse response = responseEntry.getValue();
            writer.append("|");
            writer.append(identifier.toString());
            writer.append("=");
            String stringuifiedResponse = response.getStringuifiedResponse();
            if (stringuifiedResponse == null) {
                writer.append("NULL");
            } else {
                writer.append(stringuifiedResponse);
            }
        }
    }
}
Also used : AssessmentTestSession(org.olat.ims.qti21.AssessmentTestSession) Identifier(uk.ac.ed.ph.jqtiplus.types.Identifier) RepositoryEntryRef(org.olat.repository.RepositoryEntryRef) Map(java.util.Map) AssessmentResponse(org.olat.ims.qti21.AssessmentResponse)

Example 7 with CandidateEvent

use of org.olat.ims.qti21.model.audit.CandidateEvent in project OpenOLAT by OpenOLAT.

the class AssessmentItemDisplayController method handleTemporaryResponses.

public void handleTemporaryResponses(UserRequest ureq, Map<Identifier, ResponseInput> stringResponseMap) {
    /* 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, 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()));
            }
        }
    }
    final Date timestamp = ureq.getRequestTimestamp();
    /* Attempt to bind responses */
    boolean allResponsesValid = false;
    boolean allResponsesBound = false;
    try {
        itemSessionController.bindResponses(timestamp, responseDataMap);
    } catch (final QtiCandidateStateException e) {
        candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.RESPONSES_NOT_EXPECTED, null);
        logError("RESPONSES_NOT_EXPECTED", e);
        return;
    } catch (final RuntimeException e) {
        logError("", e);
        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;
}
Also used : QtiCandidateStateException(uk.ac.ed.ph.jqtiplus.exception.QtiCandidateStateException) CandidateItemEventType(org.olat.ims.qti21.model.audit.CandidateItemEventType) HashMap(java.util.HashMap) ItemSessionState(uk.ac.ed.ph.jqtiplus.state.ItemSessionState) FileResponseData(uk.ac.ed.ph.jqtiplus.types.FileResponseData) StringResponseData(uk.ac.ed.ph.jqtiplus.types.StringResponseData) AssessmentResponseData(org.olat.ims.qti21.model.audit.AssessmentResponseData) ResponseData(uk.ac.ed.ph.jqtiplus.types.ResponseData) NotificationRecorder(uk.ac.ed.ph.jqtiplus.notification.NotificationRecorder) AssessmentResponse(org.olat.ims.qti21.AssessmentResponse) Date(java.util.Date) CandidateEvent(org.olat.ims.qti21.model.audit.CandidateEvent) StringInput(org.olat.ims.qti21.ui.ResponseInput.StringInput) Identifier(uk.ac.ed.ph.jqtiplus.types.Identifier) StringResponseData(uk.ac.ed.ph.jqtiplus.types.StringResponseData)

Example 8 with CandidateEvent

use of org.olat.ims.qti21.model.audit.CandidateEvent in project OpenOLAT by OpenOLAT.

the class AssessmentItemDisplayController method enterSession.

private ItemSessionController enterSession(UserRequest ureq) /*, final UserTestSession candidateSession */
{
    /* Set up listener to record any notifications */
    final NotificationRecorder notificationRecorder = new NotificationRecorder(NotificationLevel.INFO);
    /* Create fresh JQTI+ state Object and try to create controller */
    itemSessionController = createNewItemSessionStateAndController(notificationRecorder);
    if (itemSessionController == null) {
        logError("Cannot create item session controller for:" + itemFileRef, null);
        return null;
    }
    /* Try to Initialise JQTI+ state */
    final ItemSessionState itemSessionState = itemSessionController.getItemSessionState();
    try {
        final Date timestamp = ureq.getRequestTimestamp();
        itemSessionController.initialize(timestamp);
        itemSessionController.performTemplateProcessing(timestamp);
        itemSessionController.enterItem(timestamp);
    } catch (final RuntimeException e) {
        logError("", e);
        return null;
    }
    /* Record and log entry event */
    final CandidateEvent candidateEvent = qtiService.recordCandidateItemEvent(candidateSession, null, entry, CandidateItemEventType.ENTER, itemSessionState, notificationRecorder);
    candidateAuditLogger.logCandidateEvent(candidateEvent);
    lastEvent = candidateEvent;
    /* Record current result state */
    final AssessmentResult assessmentResult = computeAndRecordItemAssessmentResult(ureq);
    /* Handle immediate end of session */
    if (itemSessionState.isEnded()) {
        qtiService.finishItemSession(candidateSession, assessmentResult, ureq.getRequestTimestamp());
    }
    return itemSessionController;
}
Also used : ItemSessionState(uk.ac.ed.ph.jqtiplus.state.ItemSessionState) NotificationRecorder(uk.ac.ed.ph.jqtiplus.notification.NotificationRecorder) AssessmentResult(uk.ac.ed.ph.jqtiplus.node.result.AssessmentResult) Date(java.util.Date) CandidateEvent(org.olat.ims.qti21.model.audit.CandidateEvent)

Example 9 with CandidateEvent

use of org.olat.ims.qti21.model.audit.CandidateEvent in project OpenOLAT by OpenOLAT.

the class AssessmentItemDisplayController method endSession.

public void endSession(UserRequest ureq) {
    NotificationRecorder notificationRecorder = new NotificationRecorder(NotificationLevel.INFO);
    // final ItemSessionController itemSessionController = candidateDataService.createItemSessionController(mostRecentEvent, notificationRecorder);
    ItemSessionState itemSessionState = itemSessionController.getItemSessionState();
    if (itemSessionState.isEnded()) {
        logError("END_SESSION_WHEN_ALREADY_ENDED", null);
        candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.END_SESSION_WHEN_ALREADY_ENDED, null);
        return;
    }
    /* else if (!itemDeliverySettings.isAllowEnd()) {
            candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.END_SESSION_WHEN_INTERACTING_FORBIDDEN);
            return null;
        }*/
    /* Update state */
    final Date timestamp = ureq.getRequestTimestamp();
    try {
        itemSessionController.endItem(timestamp);
    } catch (QtiCandidateStateException e) {
        String msg = itemSessionState.isEnded() ? "END_SESSION_WHEN_ALREADY_ENDED" : "END_SESSION_WHEN_INTERACTING_FORBIDDEN";
        logError(msg, e);
        candidateAuditLogger.logAndThrowCandidateException(candidateSession, itemSessionState.isEnded() ? CandidateExceptionReason.END_SESSION_WHEN_ALREADY_ENDED : CandidateExceptionReason.END_SESSION_WHEN_INTERACTING_FORBIDDEN, null);
        return;
    } catch (final RuntimeException e) {
        logError("", e);
        // handleExplosion(e, candidateSession);
        return;
    }
    /* Record current result state */
    final AssessmentResult assessmentResult = computeAndRecordItemAssessmentResult(ureq);
    /* Record and log event */
    final CandidateEvent candidateEvent = qtiService.recordCandidateItemEvent(candidateSession, null, entry, CandidateItemEventType.END, itemSessionState, notificationRecorder);
    candidateAuditLogger.logCandidateEvent(candidateEvent);
    lastEvent = candidateEvent;
    /* Close session */
    qtiService.finishItemSession(candidateSession, assessmentResult, timestamp);
}
Also used : QtiCandidateStateException(uk.ac.ed.ph.jqtiplus.exception.QtiCandidateStateException) ItemSessionState(uk.ac.ed.ph.jqtiplus.state.ItemSessionState) NotificationRecorder(uk.ac.ed.ph.jqtiplus.notification.NotificationRecorder) AssessmentResult(uk.ac.ed.ph.jqtiplus.node.result.AssessmentResult) Date(java.util.Date) CandidateEvent(org.olat.ims.qti21.model.audit.CandidateEvent)

Example 10 with CandidateEvent

use of org.olat.ims.qti21.model.audit.CandidateEvent in project OpenOLAT by OpenOLAT.

the class AssessmentTestDisplayController method processAdvanceTestPart.

private void processAdvanceTestPart(UserRequest ureq) {
    /* Get current JQTI state and create JQTI controller */
    NotificationRecorder notificationRecorder = new NotificationRecorder(NotificationLevel.INFO);
    TestSessionState testSessionState = testSessionController.getTestSessionState();
    /* Perform action */
    final TestPlanNode nextTestPart;
    final Date currentTimestamp = ureq.getRequestTimestamp();
    try {
        nextTestPart = testSessionController.enterNextAvailableTestPart(currentTimestamp);
    } 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;
    }
    CandidateTestEventType eventType;
    if (nextTestPart != null) {
        /* Moved into next test part */
        eventType = CandidateTestEventType.ADVANCE_TEST_PART;
    } else {
        /* No more test parts.
             *
             * For single part tests, we terminate the test completely now as the test feedback was shown with the testPart feedback.
             * For multi-part tests, we shall keep the test open so that the test feedback can be viewed.
             */
        if (testSessionState.getTestPlan().getTestPartNodes().size() == 1) {
            eventType = CandidateTestEventType.EXIT_TEST;
            testSessionController.exitTest(currentTimestamp);
            candidateSession.setTerminationTime(currentTimestamp);
            candidateSession = qtiService.updateAssessmentTestSession(candidateSession);
        } else {
            eventType = CandidateTestEventType.ADVANCE_TEST_PART;
        }
    }
    boolean terminated = isTerminated();
    /* Record current result state */
    computeAndRecordTestAssessmentResult(currentTimestamp, testSessionState, terminated);
    /* Record and log event */
    final CandidateEvent candidateTestEvent = qtiService.recordCandidateTestEvent(candidateSession, testEntry, entry, eventType, testSessionState, notificationRecorder);
    candidateAuditLogger.logCandidateEvent(candidateTestEvent);
    this.lastEvent = candidateTestEvent;
    if (terminated) {
        qtiWorksCtrl.updateStatusAndResults(ureq);
        doExitTest(ureq);
    }
}
Also used : TestPlanNode(uk.ac.ed.ph.jqtiplus.state.TestPlanNode) QtiCandidateStateException(uk.ac.ed.ph.jqtiplus.exception.QtiCandidateStateException) OLATRuntimeException(org.olat.core.logging.OLATRuntimeException) TestSessionState(uk.ac.ed.ph.jqtiplus.state.TestSessionState) CandidateTestEventType(org.olat.ims.qti21.model.audit.CandidateTestEventType) NotificationRecorder(uk.ac.ed.ph.jqtiplus.notification.NotificationRecorder) Date(java.util.Date) CandidateEvent(org.olat.ims.qti21.model.audit.CandidateEvent)

Aggregations

CandidateEvent (org.olat.ims.qti21.model.audit.CandidateEvent)54 NotificationRecorder (uk.ac.ed.ph.jqtiplus.notification.NotificationRecorder)36 Date (java.util.Date)34 TestSessionState (uk.ac.ed.ph.jqtiplus.state.TestSessionState)32 OLATRuntimeException (org.olat.core.logging.OLATRuntimeException)22 QtiCandidateStateException (uk.ac.ed.ph.jqtiplus.exception.QtiCandidateStateException)21 AssessmentResult (uk.ac.ed.ph.jqtiplus.node.result.AssessmentResult)20 ItemSessionState (uk.ac.ed.ph.jqtiplus.state.ItemSessionState)20 TestPlanNodeKey (uk.ac.ed.ph.jqtiplus.state.TestPlanNodeKey)16 TestPlanNode (uk.ac.ed.ph.jqtiplus.state.TestPlanNode)14 CandidateTestEventType (org.olat.ims.qti21.model.audit.CandidateTestEventType)12 AssessmentResponse (org.olat.ims.qti21.AssessmentResponse)10 AssessmentTestSession (org.olat.ims.qti21.AssessmentTestSession)10 Identifier (uk.ac.ed.ph.jqtiplus.types.Identifier)10 HashMap (java.util.HashMap)8 CandidateItemEventType (org.olat.ims.qti21.model.audit.CandidateItemEventType)8 CandidateSessionContext (org.olat.ims.qti21.ui.CandidateSessionContext)8 StringInput (org.olat.ims.qti21.ui.ResponseInput.StringInput)8 FileResponseData (uk.ac.ed.ph.jqtiplus.types.FileResponseData)8 ResponseData (uk.ac.ed.ph.jqtiplus.types.ResponseData)8