/** * <a href="http://www.openolat.org"> * OpenOLAT - Online Learning and Training</a><br> * <p> * Licensed under the Apache License, Version 2.0 (the "License"); <br> * you may not use this file except in compliance with the License.<br> * You may obtain a copy of the License at the * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> * <p> * Unless required by applicable law or agreed to in writing,<br> * software distributed under the License is distributed on an "AS IS" BASIS, <br> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> * See the License for the specific language governing permissions and <br> * limitations under the License. * <p> * Initial code contributed and copyrighted by<br> * frentix GmbH, http://www.frentix.com * <p> */ package org.olat.ims.qti21.model.xml; import java.util.List; import org.olat.ims.qti21.QTI21Constants; import uk.ac.ed.ph.jqtiplus.node.expression.Expression; import uk.ac.ed.ph.jqtiplus.node.expression.general.BaseValue; import uk.ac.ed.ph.jqtiplus.node.expression.general.Variable; import uk.ac.ed.ph.jqtiplus.node.expression.operator.And; import uk.ac.ed.ph.jqtiplus.node.expression.operator.Match; import uk.ac.ed.ph.jqtiplus.node.test.AssessmentTest; import uk.ac.ed.ph.jqtiplus.node.test.TestFeedback; import uk.ac.ed.ph.jqtiplus.node.test.outcome.processing.OutcomeCondition; import uk.ac.ed.ph.jqtiplus.node.test.outcome.processing.OutcomeIf; import uk.ac.ed.ph.jqtiplus.node.test.outcome.processing.OutcomeRule; import uk.ac.ed.ph.jqtiplus.node.test.outcome.processing.SetOutcomeValue; import uk.ac.ed.ph.jqtiplus.types.ComplexReferenceIdentifier; import uk.ac.ed.ph.jqtiplus.types.Identifier; import uk.ac.ed.ph.jqtiplus.value.BooleanValue; import uk.ac.ed.ph.jqtiplus.value.IdentifierValue; import uk.ac.ed.ph.jqtiplus.value.SingleValue; /** * * Initial date: 11.12.2015<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ public class TestFeedbackBuilder { private final TestFeedback testFeedback; private final AssessmentTest assessmentTest; private String title; private String text; private Identifier identifier; public TestFeedbackBuilder(AssessmentTest assessmentTest, TestFeedback testFeedback) { this.assessmentTest = assessmentTest; this.testFeedback = testFeedback; if(testFeedback != null) { text = new AssessmentHtmlBuilder().flowStaticString(testFeedback.getChildren()); title = testFeedback.getTitle(); identifier = testFeedback.getOutcomeValue(); } } public TestFeedback getTestFeedback() { return testFeedback; } public Identifier getModalFeedbackIdentifier() { return testFeedback.getOutcomeValue(); } public OutcomeRule getResponseRule() { OutcomeRule feedbackRule = findFeedbackRule(testFeedback.getOutcomeValue()); return feedbackRule; } public boolean isPassedRule() { OutcomeRule feedbackRule = findFeedbackRule(testFeedback.getOutcomeValue()); return findFeedbackMatch(feedbackRule, true, QTI21Constants.PASS_CLX_IDENTIFIER); } public boolean isFailedRule() { OutcomeRule feedbackRule = findFeedbackRule(testFeedback.getOutcomeValue()); return findFeedbackMatch(feedbackRule, false, QTI21Constants.PASS_CLX_IDENTIFIER); } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getText() { return text; } public void setText(String text) { this.text = text; } public Identifier getIdentifier() { return identifier; } public void setIdentifier(Identifier identifier) { this.identifier = identifier; } private OutcomeRule findFeedbackRule(Identifier feedbackIdentifier) { List<OutcomeRule> outcomeRules = assessmentTest.getOutcomeProcessing().getOutcomeRules(); for(OutcomeRule outcomeRule:outcomeRules) { if(outcomeRule instanceof OutcomeCondition) { if(findFeedbackRuleInSetOutcomeVariable(outcomeRule, feedbackIdentifier)) { return outcomeRule; } } } return null; } private boolean findFeedbackRuleInSetOutcomeVariable(OutcomeRule responseRule, Identifier feedbackIdentifier) { if(responseRule instanceof OutcomeCondition) { OutcomeCondition outcomeCondition = (OutcomeCondition)responseRule; OutcomeIf outcomeIf = outcomeCondition.getOutcomeIf(); List<OutcomeRule> ifOutcomeRules = outcomeIf.getOutcomeRules(); for(OutcomeRule ifOutcomeRule:ifOutcomeRules) { if(ifOutcomeRule instanceof SetOutcomeValue) { SetOutcomeValue setOutcomeValue = (SetOutcomeValue)ifOutcomeRule; if(findFeedbackRuleInExpression(setOutcomeValue.getExpression(), feedbackIdentifier)) { return true; } } } } return false; } private boolean findFeedbackMatch(OutcomeRule outcomeRule, boolean pass, ComplexReferenceIdentifier id) { if(outcomeRule instanceof OutcomeCondition) { OutcomeCondition outcomeCondition = (OutcomeCondition)outcomeRule; OutcomeIf outcomeIf = outcomeCondition.getOutcomeIf(); if(outcomeIf != null && outcomeIf.getExpressions().size() == 1) { Expression mustBeAnd = outcomeIf.getExpressions().get(0); if(mustBeAnd instanceof And && mustBeAnd.getExpressions().size() == 1) { Expression mustBeMatch = mustBeAnd.getExpressions().get(0); if(mustBeMatch instanceof Match && mustBeMatch.getExpressions().size() == 2) { return findFeedbackMatch((Match)mustBeMatch, pass, id); } } } } return false; } private boolean findFeedbackMatch(Match match, boolean pass, ComplexReferenceIdentifier id) { Expression firstExpression = match.getExpressions().get(0); Expression secondExpression = match.getExpressions().get(1); if(findBaseValue(firstExpression, pass) && findVariable(secondExpression, id)) { return true; } if(findBaseValue(secondExpression, pass) && findVariable(firstExpression, id)) { return true; } return false; } private boolean findBaseValue(Expression expression, boolean value) { if(expression instanceof BaseValue) { BaseValue bValue = (BaseValue)expression; SingleValue sValue = bValue.getSingleValue(); if(sValue instanceof BooleanValue) { BooleanValue booleanValue = (BooleanValue)sValue; return booleanValue.booleanValue() == value; } } return false; } private boolean findVariable(Expression expression, ComplexReferenceIdentifier variableIdentifier) { if(expression instanceof Variable) { Variable variable = (Variable)expression; return variable.getIdentifier() != null && variable.getIdentifier().equals(variableIdentifier); } return false; } private boolean findFeedbackRuleInExpression(Expression expression, Identifier feedbackIdentifier) { if(expression instanceof BaseValue) { BaseValue bValue = (BaseValue)expression; SingleValue sValue = bValue.getSingleValue(); if(sValue instanceof IdentifierValue) { IdentifierValue iValue = (IdentifierValue)sValue; if(feedbackIdentifier.equals(iValue.identifierValue())) { return true; } } } else { List<Expression> childExpressions = expression.getExpressions(); for(Expression childExpression:childExpressions) { if(findFeedbackRuleInExpression(childExpression, feedbackIdentifier)) { return true; } } } return false; } }