From 87e9604de87c9a6d37cdea650e5ad1e1ebe3820d Mon Sep 17 00:00:00 2001 From: = Date: Tue, 12 Jan 2016 16:37:03 +0100 Subject: [PATCH] Default values in use when no Mapping. --- .../expressions/MapResponsePointProcessor.php | 88 +++++++------- .../expressions/MapResponseProcessor.php | 109 +++++++++--------- .../MapResponsePointProcessorTest.php | 5 +- .../expressions/MapResponseProcessorTest.php | 7 +- 4 files changed, 104 insertions(+), 105 deletions(-) diff --git a/src/qtism/runtime/expressions/MapResponsePointProcessor.php b/src/qtism/runtime/expressions/MapResponsePointProcessor.php index 832741f02..9104f67d1 100644 --- a/src/qtism/runtime/expressions/MapResponsePointProcessor.php +++ b/src/qtism/runtime/expressions/MapResponsePointProcessor.php @@ -14,7 +14,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Copyright (c) 2013-2014 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT); + * Copyright (c) 2013-2016 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT); * * @author Jérôme Bogaerts * @license GPLv2 @@ -73,66 +73,64 @@ public function process() if ($var instanceof ResponseVariable) { $areaMapping = $var->getAreaMapping(); - if (!is_null($areaMapping)) { + if (is_null($areaMapping)) { + return new QtiFloat(0.0); + } - // Correct cardinality ? - if ($var->getBaseType() === BaseType::POINT && ($var->isSingle() || $var->isMultiple())) { + // Correct cardinality ? + if ($var->getBaseType() === BaseType::POINT && ($var->isSingle() || $var->isMultiple())) { - // We can begin! + // We can begin! - // -- Null value, nothing will match - if ($var->isNull()) { - return new QtiFloat($areaMapping->getDefaultValue()); - } + // -- Null value, nothing will match + if ($var->isNull()) { + return new QtiFloat($areaMapping->getDefaultValue()); + } - if ($var->isSingle()) { - $val = new MultipleContainer(BaseType::POINT, array($state[$identifier])); - } else { - $val = $state[$identifier]; - } + if ($var->isSingle()) { + $val = new MultipleContainer(BaseType::POINT, array($state[$identifier])); + } else { + $val = $state[$identifier]; + } - $result = 0; - $mapped = array(); + $result = 0; + $mapped = array(); - foreach ($val as $point) { - foreach ($areaMapping->getAreaMapEntries() as $areaMapEntry) { + foreach ($val as $point) { + foreach ($areaMapping->getAreaMapEntries() as $areaMapEntry) { - $coords = $areaMapEntry->getCoords(); + $coords = $areaMapEntry->getCoords(); - if (!in_array($coords, $mapped) && $coords->inside($point)) { - $mapped[] = $coords; - $result += $areaMapEntry->getMappedValue(); - } + if (!in_array($coords, $mapped) && $coords->inside($point)) { + $mapped[] = $coords; + $result += $areaMapEntry->getMappedValue(); } } + } - // If no relevant mapping found, return the default. - if (count($mapped) === 0) { - return new QtiFloat($areaMapping->getDefaultValue()); - } else { - // Check upper and lower bound. - if ($areaMapping->hasLowerBound() && $result < $areaMapping->getLowerBound()) { - return new QtiFloat($areaMapping->getLowerBound()); - } elseif ($areaMapping->hasUpperBound() && $result > $areaMapping->getUpperBound()) { - return new QtiFloat($areaMapping->getUpperBound()); - } else { - return new QtiFloat(floatval($result)); - } - } + // If no relevant mapping found, return the default. + if (count($mapped) === 0) { + return new QtiFloat($areaMapping->getDefaultValue()); } else { - if ($var->isRecord()) { - $msg = "The MapResponsePoint expression cannot be applied to RECORD variables."; - throw new ExpressionProcessingException($msg, $this, ExpressionProcessingException::WRONG_VARIABLE_CARDINALITY); + // Check upper and lower bound. + if ($areaMapping->hasLowerBound() && $result < $areaMapping->getLowerBound()) { + return new QtiFloat($areaMapping->getLowerBound()); + } elseif ($areaMapping->hasUpperBound() && $result > $areaMapping->getUpperBound()) { + return new QtiFloat($areaMapping->getUpperBound()); } else { - $strBaseType = BaseType::getNameByConstant($var->getBaseType()); - $msg = "The MapResponsePoint expression applies only on variables with baseType 'point', baseType '${strBaseType}' given."; - throw new ExpressionProcessingException($msg, $this, ExpressionProcessingException::WRONG_VARIABLE_BASETYPE); + return new QtiFloat(floatval($result)); } } } else { - $msg = "Variable with identifier '${identifier}' has no areaMapping."; - throw new ExpressionProcessingException($msg, $this, ExpressionProcessingException::INCONSISTENT_VARIABLE); - } + if ($var->isRecord()) { + $msg = "The MapResponsePoint expression cannot be applied to RECORD variables."; + throw new ExpressionProcessingException($msg, $this, ExpressionProcessingException::WRONG_VARIABLE_CARDINALITY); + } else { + $strBaseType = BaseType::getNameByConstant($var->getBaseType()); + $msg = "The MapResponsePoint expression applies only on variables with baseType 'point', baseType '${strBaseType}' given."; + throw new ExpressionProcessingException($msg, $this, ExpressionProcessingException::WRONG_VARIABLE_BASETYPE); + } + } } else { $msg = "The variable with identifier '${identifier}' is not a ResponseVariable."; throw new ExpressionProcessingException($msg, $this, ExpressionProcessingException::WRONG_VARIABLE_TYPE); diff --git a/src/qtism/runtime/expressions/MapResponseProcessor.php b/src/qtism/runtime/expressions/MapResponseProcessor.php index f6ddaea27..ab9a1851c 100644 --- a/src/qtism/runtime/expressions/MapResponseProcessor.php +++ b/src/qtism/runtime/expressions/MapResponseProcessor.php @@ -14,7 +14,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Copyright (c) 2013-2014 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT); + * Copyright (c) 2013-2016 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT); * * @author Jérôme Bogaerts * @license GPLv2 @@ -78,89 +78,88 @@ public function process() $mapping = $variable->getMapping(); - if (!is_null($mapping)) { + if (is_null($mapping)) { + return new QtiFloat(0.0); + } - if ($variable->isSingle()) { + if ($variable->isSingle()) { - foreach ($mapping->getMapEntries() as $mapEntry) { + foreach ($mapping->getMapEntries() as $mapEntry) { - $val = $state[$identifier]; - $mapKey = $mapEntry->getMapKey(); + $val = $state[$identifier]; + $mapKey = $mapEntry->getMapKey(); - if ($val instanceof QtiString && $mapEntry->isCaseSensitive() === false) { - $val = mb_strtolower($val->getValue(), 'UTF-8'); - $mapKey = mb_strtolower($mapKey, 'UTF-8'); - } + if ($val instanceof QtiString && $mapEntry->isCaseSensitive() === false) { + $val = mb_strtolower($val->getValue(), 'UTF-8'); + $mapKey = mb_strtolower($mapKey, 'UTF-8'); + } - if ($val instanceof Comparable && $val->equals($mapKey) || $val === $mapKey) { - // relevant mapping found. - $mappedValue = $mapEntry->getMappedValue(); + if ($val instanceof Comparable && $val->equals($mapKey) || $val === $mapKey) { + // relevant mapping found. + $mappedValue = $mapEntry->getMappedValue(); - return new QtiFloat($mappedValue); - } + return new QtiFloat($mappedValue); } + } - // No relevant mapping found, return mapping default. - return new QtiFloat($mapping->getDefaultValue()); - } elseif ($variable->isMultiple()) { - - $result = 0.0; + // No relevant mapping found, return mapping default. + return new QtiFloat($mapping->getDefaultValue()); + } elseif ($variable->isMultiple()) { - if (!is_null($variable->getValue())) { - $mapped = array(); // already mapped keys. - $mapEntries = $mapping->getMapEntries(); + $result = 0.0; - foreach ($variable->getValue() as $val) { + if (!is_null($variable->getValue())) { + $mapped = array(); // already mapped keys. + $mapEntries = $mapping->getMapEntries(); - for ($i = 0; $i < count($mapEntries); $i++) { + foreach ($variable->getValue() as $val) { - $mapKey = $rawMapKey = $mapEntries[$i]->getMapKey(); + for ($i = 0; $i < count($mapEntries); $i++) { - if ($val instanceof QtiString && $mapEntries[$i]->isCaseSensitive() === false) { - $val = mb_strtolower($val->getValue(), 'UTF-8'); - $mapKey = mb_strtolower($mapKey, 'UTF-8'); - } + $mapKey = $rawMapKey = $mapEntries[$i]->getMapKey(); - if (($val instanceof Comparable && $val->equals($mapKey) === true) || $val === $mapKey) { - if (in_array($rawMapKey, $mapped, true) === false) { - $result += $mapEntries[$i]->getMappedValue(); - $mapped[] = $rawMapKey; + if ($val instanceof QtiString && $mapEntries[$i]->isCaseSensitive() === false) { + $val = mb_strtolower($val->getValue(), 'UTF-8'); + $mapKey = mb_strtolower($mapKey, 'UTF-8'); + } - } - // else... - // This value has already been mapped. + if (($val instanceof Comparable && $val->equals($mapKey) === true) || $val === $mapKey) { + if (in_array($rawMapKey, $mapped, true) === false) { + $result += $mapEntries[$i]->getMappedValue(); + $mapped[] = $rawMapKey; - break; } - } + // else... + // This value has already been mapped. - if ($i >= count($mapEntries)) { - // No explicit mapping found for source value $val. - $result += $mapping->getDefaultValue(); + break; } } - // When mapping a container, try to apply lower or upper bound. - if ($mapping->hasLowerBound() && $result < $mapping->getLowerBound()) { - return new QtiFloat($mapping->getLowerBound()); - } elseif ($mapping->hasUpperBound() && $result > $mapping->getUpperBound()) { - return new QtiFloat($mapping->getUpperBound()); - } else { - return new QtiFloat($result); + if ($i >= count($mapEntries)) { + // No explicit mapping found for source value $val. + $result += $mapping->getDefaultValue(); } + } + + // When mapping a container, try to apply lower or upper bound. + if ($mapping->hasLowerBound() && $result < $mapping->getLowerBound()) { + return new QtiFloat($mapping->getLowerBound()); + } elseif ($mapping->hasUpperBound() && $result > $mapping->getUpperBound()) { + return new QtiFloat($mapping->getUpperBound()); } else { - // Returns a 0.0 result. return new QtiFloat($result); } - } else { - $msg = "MapResponse cannot be applied on a RECORD container."; - throw new ExpressionProcessingException($msg, $this, ExpressionProcessingException::WRONG_VARIABLE_BASETYPE); + // Returns a 0.0 result. + return new QtiFloat($result); } + } else { - $msg = "The target variable has no mapping while processing MapResponse."; - throw new ExpressionProcessingException($msg, $this, ExpressionProcessingException::INCONSISTENT_VARIABLE); + $msg = "MapResponse cannot be applied on a RECORD container."; + throw new ExpressionProcessingException($msg, $this, ExpressionProcessingException::WRONG_VARIABLE_BASETYPE); } + } else { $msg = "The target variable must be a ResponseVariable, OutcomeVariable given while processing MapResponse."; throw new ExpressionProcessingException($msg, $this, ExpressionProcessingException::WRONG_VARIABLE_TYPE); diff --git a/test/qtismtest/runtime/expressions/MapResponsePointProcessorTest.php b/test/qtismtest/runtime/expressions/MapResponsePointProcessorTest.php index 7c80a0e97..34edb3734 100644 --- a/test/qtismtest/runtime/expressions/MapResponsePointProcessorTest.php +++ b/test/qtismtest/runtime/expressions/MapResponsePointProcessorTest.php @@ -151,6 +151,7 @@ public function testWrongBaseType() { } public function testNoAreaMapping() { + // When no areaMapping is found, we consider a default value of 0.0. $expr = $this->createComponentFromXml(''); $variableDeclaration = $this->createComponentFromXml(' @@ -159,8 +160,8 @@ public function testNoAreaMapping() { $processor = new MapResponsePointProcessor($expr); $processor->setState(new State(array($variable))); - $this->setExpectedException("qtism\\runtime\\expressions\\ExpressionProcessingException"); $result = $processor->process(); + $this->assertEquals(0.0, $result->getValue()); } public function testWrongVariableType() { @@ -234,4 +235,4 @@ public function testWithRecord() { $this->setExpectedException('qtism\\runtime\\expressions\\ExpressionProcessingException', 'The MapResponsePoint expression cannot be applied to RECORD variables.', ExpressionProcessingException::WRONG_VARIABLE_CARDINALITY); $result = $processor->process(); } -} \ No newline at end of file +} diff --git a/test/qtismtest/runtime/expressions/MapResponseProcessorTest.php b/test/qtismtest/runtime/expressions/MapResponseProcessorTest.php index e31b02a40..466bf8a7b 100644 --- a/test/qtismtest/runtime/expressions/MapResponseProcessorTest.php +++ b/test/qtismtest/runtime/expressions/MapResponseProcessorTest.php @@ -123,14 +123,15 @@ public function testVariableNotDefined() { } public function testNoMapping() { - $this->setExpectedException("qtism\\runtime\\expressions\\ExpressionProcessingException"); + // When no mapping is set. We consider a "fake" mapping with a default value of 0. $variableDeclaration = $this->createComponentFromXml(''); $variable = ResponseVariable::createFromDataModel($variableDeclaration); $mapResponseExpr = $this->createComponentFromXml(''); $mapResponseProcessor = new MapResponseProcessor($mapResponseExpr); $mapResponseProcessor->setState(new State(array($variable))); - $mapResponseProcessor->process(); + $result = $mapResponseProcessor->process(); + $this->assertEquals(0.0, $result->getValue()); } public function testMultipleCardinalityIdentifierToFloat() { @@ -221,4 +222,4 @@ public function testOutcomeDeclaration() { $mapResponseProcessor->setState(new State(array($variable))); $mapResponseProcessor->process(); } -} \ No newline at end of file +}