Search in sources :

Example 76 with ItemSessionState

use of uk.ac.ed.ph.jqtiplus.state.ItemSessionState in project openolat by klemens.

the class QTI21ServiceImpl method reopenTestPart.

private TestPlanNodeKey reopenTestPart(TestPlanNode lastItem, TestSessionState testSessionState) {
    TestPlan plan = testSessionState.getTestPlan();
    List<TestPlanNode> testPartNodes = lastItem.searchAncestors(TestNodeType.TEST_PART);
    if (testPartNodes.isEmpty()) {
        return null;
    }
    // reopen the test part of the selected item
    TestPlanNode partNode = testPartNodes.get(0);
    TestPlanNodeKey partKey = partNode.getKey();
    TestPartSessionState partState = testSessionState.getTestPartSessionStates().get(partKey);
    partState.setEndTime(null);
    partState.setExitTime(null);
    // reopen all sections the test part
    for (Map.Entry<TestPlanNodeKey, AssessmentSectionSessionState> sectionEntry : testSessionState.getAssessmentSectionSessionStates().entrySet()) {
        TestPlanNodeKey sectionKey = sectionEntry.getKey();
        TestPlanNode sectionNode = plan.getNode(sectionKey);
        if (sectionNode.hasAncestor(partNode)) {
            AssessmentSectionSessionState sectionState = sectionEntry.getValue();
            sectionState.setEndTime(null);
            sectionState.setExitTime(null);
        }
    }
    // reopen all items the test part
    for (Map.Entry<TestPlanNodeKey, ItemSessionState> itemEntry : testSessionState.getItemSessionStates().entrySet()) {
        TestPlanNodeKey itemKey = itemEntry.getKey();
        TestPlanNode itemNode = plan.getNode(itemKey);
        if (itemNode.hasAncestor(partNode)) {
            ItemSessionState itemState = itemEntry.getValue();
            itemState.setEndTime(null);
            itemState.setExitTime(null);
        }
    }
    return partKey;
}
Also used : TestPlanNode(uk.ac.ed.ph.jqtiplus.state.TestPlanNode) TestPlan(uk.ac.ed.ph.jqtiplus.state.TestPlan) ItemSessionState(uk.ac.ed.ph.jqtiplus.state.ItemSessionState) TestPartSessionState(uk.ac.ed.ph.jqtiplus.state.TestPartSessionState) AssessmentSectionSessionState(uk.ac.ed.ph.jqtiplus.state.AssessmentSectionSessionState) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) ConcurrentMap(java.util.concurrent.ConcurrentMap) TestPlanNodeKey(uk.ac.ed.ph.jqtiplus.state.TestPlanNodeKey)

Example 77 with ItemSessionState

use of uk.ac.ed.ph.jqtiplus.state.ItemSessionState 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;
}
Also used : QtiCandidateStateException(uk.ac.ed.ph.jqtiplus.exception.QtiCandidateStateException) ItemSessionState(uk.ac.ed.ph.jqtiplus.state.ItemSessionState) AssessmentResult(uk.ac.ed.ph.jqtiplus.node.result.AssessmentResult) Date(java.util.Date) CandidateEvent(org.olat.ims.qti21.model.audit.CandidateEvent)

Example 78 with ItemSessionState

use of uk.ac.ed.ph.jqtiplus.state.ItemSessionState in project openolat by klemens.

the class AssessmentItemDisplayController method updateSessionFinishedStatus.

private AssessmentTestSession updateSessionFinishedStatus(UserRequest ureq) {
    /* Record current result state and maybe close session */
    final ItemSessionState itemSessionState = itemSessionController.getItemSessionState();
    final AssessmentResult assessmentResult = computeAndRecordItemAssessmentResult(ureq);
    if (itemSessionState.isEnded()) {
        qtiService.finishItemSession(candidateSession, assessmentResult, null);
    } else {
        if (candidateSession != null && candidateSession.getFinishTime() != null) {
            /* (Session is being reopened) */
            candidateSession.setFinishTime(null);
            candidateSession = qtiService.updateAssessmentTestSession(candidateSession);
        }
    }
    return candidateSession;
}
Also used : ItemSessionState(uk.ac.ed.ph.jqtiplus.state.ItemSessionState) AssessmentResult(uk.ac.ed.ph.jqtiplus.node.result.AssessmentResult)

Example 79 with ItemSessionState

use of uk.ac.ed.ph.jqtiplus.state.ItemSessionState 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);
}
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) FileInput(org.olat.ims.qti21.ui.ResponseInput.FileInput) 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) FileResponseData(uk.ac.ed.ph.jqtiplus.types.FileResponseData) Base64Input(org.olat.ims.qti21.ui.ResponseInput.Base64Input) File(java.io.File) AssessmentResponseData(org.olat.ims.qti21.model.audit.AssessmentResponseData)

Example 80 with ItemSessionState

use of uk.ac.ed.ph.jqtiplus.state.ItemSessionState in project openolat by klemens.

the class AssessmentObjectVelocityRenderDecorator method getVisibleOrderedSimpleChoices.

public List<SimpleChoice> getVisibleOrderedSimpleChoices(OrderInteraction interaction) {
    List<SimpleChoice> choices;
    if (interaction.getShuffle()) {
        // <xsl:variable name="shuffledChoiceOrders" select="$itemSessionState/qw:shuffledInteractionChoiceOrder"
        // as="element(qw:shuffledInteractionChoiceOrder)*"/>
        // <xsl:variable name="choiceSequence" as="xs:string?"
        // select="$shuffledChoiceOrders[@responseIdentifier=$interaction/@responseIdentifier]/@choiceSequence"/>
        List<Identifier> choiceOrders = itemSessionState.getShuffledInteractionChoiceOrder(interaction.getResponseIdentifier());
        choices = new ArrayList<>();
        for (Identifier choiceOrder : choiceOrders) {
            choices.add(interaction.getSimpleChoice(choiceOrder));
        }
    } else {
        choices = interaction.getSimpleChoices();
    }
    return choices.stream().filter((choice) -> isVisible(choice, itemSessionState)).collect(Collectors.toList());
}
Also used : URLBuilder(org.olat.core.gui.render.URLBuilder) HottextInteraction(uk.ac.ed.ph.jqtiplus.node.item.interaction.HottextInteraction) GraphicAssociateInteraction(uk.ac.ed.ph.jqtiplus.node.item.interaction.GraphicAssociateInteraction) Identifier(uk.ac.ed.ph.jqtiplus.types.Identifier) Choice(uk.ac.ed.ph.jqtiplus.node.item.interaction.choice.Choice) Map(java.util.Map) Flow(uk.ac.ed.ph.jqtiplus.node.content.basic.Flow) InlineChoiceInteraction(uk.ac.ed.ph.jqtiplus.node.item.interaction.InlineChoiceInteraction) StringOutput(org.olat.core.gui.render.StringOutput) OLog(org.olat.core.logging.OLog) ListValue(uk.ac.ed.ph.jqtiplus.value.ListValue) FlowStatic(uk.ac.ed.ph.jqtiplus.node.content.basic.FlowStatic) HotspotInteraction(uk.ac.ed.ph.jqtiplus.node.item.interaction.HotspotInteraction) Translator(org.olat.core.gui.translator.Translator) InlineChoice(uk.ac.ed.ph.jqtiplus.node.item.interaction.choice.InlineChoice) ResponseDeclaration(uk.ac.ed.ph.jqtiplus.node.item.response.declaration.ResponseDeclaration) FormJSHelper(org.olat.core.gui.components.form.flexible.impl.FormJSHelper) AssociateInteraction(uk.ac.ed.ph.jqtiplus.node.item.interaction.AssociateInteraction) StringInteraction(uk.ac.ed.ph.jqtiplus.node.item.interaction.StringInteraction) Value(uk.ac.ed.ph.jqtiplus.value.Value) ChoiceInteraction(uk.ac.ed.ph.jqtiplus.node.item.interaction.ChoiceInteraction) AssociableHotspot(uk.ac.ed.ph.jqtiplus.node.item.interaction.graphic.AssociableHotspot) Collectors(java.util.stream.Collectors) GapImg(uk.ac.ed.ph.jqtiplus.node.item.interaction.choice.GapImg) List(java.util.List) BlockStatic(uk.ac.ed.ph.jqtiplus.node.content.basic.BlockStatic) MatchInteraction(uk.ac.ed.ph.jqtiplus.node.item.interaction.MatchInteraction) AssessmentRenderFunctions.renderValue(org.olat.ims.qti21.ui.components.AssessmentRenderFunctions.renderValue) TextOrVariable(uk.ac.ed.ph.jqtiplus.node.content.variable.TextOrVariable) BaseType(uk.ac.ed.ph.jqtiplus.value.BaseType) VelocityRenderDecorator(org.olat.core.gui.render.velocity.VelocityRenderDecorator) RecordValue(uk.ac.ed.ph.jqtiplus.value.RecordValue) GraphicOrderInteraction(uk.ac.ed.ph.jqtiplus.node.item.interaction.GraphicOrderInteraction) Block(uk.ac.ed.ph.jqtiplus.node.content.basic.Block) Settings(org.olat.core.helpers.Settings) Orientation(uk.ac.ed.ph.jqtiplus.value.Orientation) QtiNode(uk.ac.ed.ph.jqtiplus.node.QtiNode) GapChoice(uk.ac.ed.ph.jqtiplus.node.item.interaction.choice.GapChoice) QueryUtils(uk.ac.ed.ph.jqtiplus.utils.QueryUtils) CandidateSessionContext(org.olat.ims.qti21.ui.CandidateSessionContext) ResolvedAssessmentItem(uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentItem) HashMap(java.util.HashMap) StringMultipleAttribute(uk.ac.ed.ph.jqtiplus.attribute.value.StringMultipleAttribute) Prompt(uk.ac.ed.ph.jqtiplus.node.item.interaction.Prompt) ItemSessionState(uk.ac.ed.ph.jqtiplus.state.ItemSessionState) ResponseData(uk.ac.ed.ph.jqtiplus.types.ResponseData) ArrayList(java.util.ArrayList) Gap(uk.ac.ed.ph.jqtiplus.node.item.interaction.content.Gap) SliderInteraction(uk.ac.ed.ph.jqtiplus.node.item.interaction.SliderInteraction) Cardinality(uk.ac.ed.ph.jqtiplus.value.Cardinality) ExtendedTextInteraction(uk.ac.ed.ph.jqtiplus.node.item.interaction.ExtendedTextInteraction) OrderInteraction(uk.ac.ed.ph.jqtiplus.node.item.interaction.OrderInteraction) StringHelper(org.olat.core.util.StringHelper) AssessmentItem(uk.ac.ed.ph.jqtiplus.node.item.AssessmentItem) AssessmentTestSession(org.olat.ims.qti21.AssessmentTestSession) Iterator(java.util.Iterator) SimpleChoice(uk.ac.ed.ph.jqtiplus.node.item.interaction.choice.SimpleChoice) HotspotChoice(uk.ac.ed.ph.jqtiplus.node.item.interaction.graphic.HotspotChoice) Interaction(uk.ac.ed.ph.jqtiplus.node.item.interaction.Interaction) SimpleAssociableChoice(uk.ac.ed.ph.jqtiplus.node.item.interaction.choice.SimpleAssociableChoice) IOException(java.io.IOException) SingleValue(uk.ac.ed.ph.jqtiplus.value.SingleValue) Shape(uk.ac.ed.ph.jqtiplus.node.expression.operator.Shape) GraphicGapMatchInteraction(uk.ac.ed.ph.jqtiplus.node.item.interaction.GraphicGapMatchInteraction) NullValue(uk.ac.ed.ph.jqtiplus.value.NullValue) GapMatchInteraction(uk.ac.ed.ph.jqtiplus.node.item.interaction.GapMatchInteraction) Tracing(org.olat.core.logging.Tracing) FileValue(uk.ac.ed.ph.jqtiplus.value.FileValue) BodyElement(uk.ac.ed.ph.jqtiplus.node.content.BodyElement) SimpleChoice(uk.ac.ed.ph.jqtiplus.node.item.interaction.choice.SimpleChoice) Identifier(uk.ac.ed.ph.jqtiplus.types.Identifier)

Aggregations

ItemSessionState (uk.ac.ed.ph.jqtiplus.state.ItemSessionState)88 ResolvedAssessmentItem (uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentItem)30 Date (java.util.Date)28 HashMap (java.util.HashMap)28 AssessmentItem (uk.ac.ed.ph.jqtiplus.node.item.AssessmentItem)28 TestPlanNodeKey (uk.ac.ed.ph.jqtiplus.state.TestPlanNodeKey)26 TestSessionState (uk.ac.ed.ph.jqtiplus.state.TestSessionState)24 Identifier (uk.ac.ed.ph.jqtiplus.types.Identifier)24 TestPlanNode (uk.ac.ed.ph.jqtiplus.state.TestPlanNode)22 AssessmentTestSession (org.olat.ims.qti21.AssessmentTestSession)20 CandidateEvent (org.olat.ims.qti21.model.audit.CandidateEvent)20 NotificationRecorder (uk.ac.ed.ph.jqtiplus.notification.NotificationRecorder)20 ItemSessionController (uk.ac.ed.ph.jqtiplus.running.ItemSessionController)20 ArrayList (java.util.ArrayList)18 Map (java.util.Map)18 ResponseData (uk.ac.ed.ph.jqtiplus.types.ResponseData)18 Interaction (uk.ac.ed.ph.jqtiplus.node.item.interaction.Interaction)16 List (java.util.List)14 Block (uk.ac.ed.ph.jqtiplus.node.content.basic.Block)12 Flow (uk.ac.ed.ph.jqtiplus.node.content.basic.Flow)12