public function process() { $returnValue = new QtismInteger(0); $operands = $this->getOperands(); if (count($operands) >= 2) { $points = $operands[0]; $equation = $operands[1]; if (($points instanceof MultipleContainer || $points instanceof OrderedContainer) && ($points->getBaseType() === BaseType::POINT || $points->getBaseType() === BaseType::STRING) && $equation instanceof QtismString) { // Check every Point X,Y against the equation... $math = new \oat\beeme\Parser(); $math->setConstant('#pi', M_PI); try { foreach ($points as $point) { if ($point instanceof QtiPoint) { $x = floatval($point->getX()); $y = floatval($point->getY()); } else { $strs = explode(" ", $point->getValue()); if (count($strs) !== 2) { // Parsing error, the NULL value is returned. return null; } else { $x = floatval($strs[0]); $y = floatval($strs[1]); } } $result = $math->evaluate($equation->getValue(), array('x' => $x, 'y' => $y)); if ($result === true) { // The Point X,Y satisfies the equation... $returnValue->setValue($returnValue->getValue() + 1); } } } catch (\Exception $e) { // If an error occurs e.g. invalid expression, the NULL value is returned. return null; } } else { // Not supported operands, return the NULL value. return null; } } return $returnValue; }
/** * Process the setOutcomeValue/setTemplateValue rule. * * A RuleProcessingException will be thrown if: * * * The variable does not exist. * * The requested variable is not an OutcomeVariable/TemplateVariable. * * The variable's baseType does not match the baseType of the affected value. * * An error occurs while processing the related expression. * * @throws \qtism\runtime\rules\RuleProcessingException If one of the error described above arise. */ public function process() { $state = $this->getState(); $rule = $this->getRule(); $identifier = $rule->getIdentifier(); $var = $state->getVariable($identifier); if (is_null($var) === true) { $msg = "No variable with identifier '{$identifier}' to be set in the current state."; throw new RuleProcessingException($msg, $this, RuleProcessingException::NONEXISTENT_VARIABLE); } elseif (Reflection::isInstanceOf($var, $this->getVariableType()) === false) { $msg = "The variable to set '{$identifier}' is not an instance of '" . $this->getVariableType() . "'."; throw new RuleProcessingException($msg, $this, RuleProcessingException::WRONG_VARIABLE_TYPE); } // Process the expression. // Its result will be the value to set to the target variable. try { $expressionEngine = new ExpressionEngine($rule->getExpression(), $state); $val = $expressionEngine->process(); } catch (ExpressionProcessingException $e) { $msg = "An error occured while processing the expression bound with the '" . Reflection::shortClassName($rule) . "' rule."; throw new RuleProcessingException($msg, $this, RuleProcessingException::RUNTIME_ERROR, $e); } // The variable exists, its new value is processed. try { // juggle a little bit (int -> float, float -> int) if ($val !== null && $var->getCardinality() === Cardinality::SINGLE) { $baseType = $var->getBaseType(); if ($baseType === BaseType::INTEGER && $val instanceof QtiFloat) { $val = new QtiInteger(intval($val->getValue())); } elseif ($baseType === BaseType::FLOAT && $val instanceof QtiInteger) { $val = new QtiFloat(floatval($val->getValue())); } } $var->setValue($val); } catch (InvalidArgumentException $e) { $varBaseType = BaseType::getNameByConstant($var->getBaseType()) === false ? 'noBaseType' : BaseType::getNameByConstant($var->getBaseType()); $varCardinality = Cardinality::getNameByConstant($var->getCardinality()); // The affected value does not match the baseType of the variable $var. $msg = "Unable to set value {$val} to variable '{$identifier}' (cardinality = {$varCardinality}, baseType = {$varBaseType})."; throw new RuleProcessingException($msg, $this, RuleProcessingException::WRONG_VARIABLE_BASETYPE, $e); } }
/** * Process the Gcd operator. * * @return integer The integer value equal in value to the greatest common divisor of the sub-expressions. If any of the sub-expressions is NULL, the result is NULL. * @throws \qtism\runtime\expressions\operators\OperatorProcessingException */ public function process() { $operands = $this->getOperands(); if ($operands->containsNull() === true) { return null; } if ($operands->anythingButRecord() === false) { $msg = "The Gcd operator only accepts operands with a cardinality of single, multiple or ordered."; throw new OperatorProcessingException($msg, $this, OperatorProcessingException::WRONG_CARDINALITY); } if ($operands->exclusivelyInteger() === false) { $msg = "The Gcd operator only accepts operands with an integer baseType."; throw new OperatorProcessingException($msg, $this, OperatorProcessingException::WRONG_BASETYPE); } // Make a flat collection first. $flatCollection = new OperandsCollection(); $zeroCount = 0; $valueCount = 0; foreach ($operands as $operand) { if ($operand instanceof QtiScalar) { $valueCount++; if ($operand->getValue() !== 0) { $flatCollection[] = $operand; } else { $zeroCount++; } } elseif ($operand->contains(null)) { // Container with at least one null value inside. // -> If any of the sub-expressions is null or not numeric, returns null. return null; } else { // Container with no null values. foreach ($operand as $o) { $valueCount++; if ($o->getValue() !== 0) { $flatCollection[] = $o; } else { $zeroCount++; } } } } if ($zeroCount === $valueCount) { // All arguments of gcd() are 0. return new QtiInteger(0); } else { $g = $flatCollection[0]; $loopLimit = count($flatCollection) - 1; $i = 0; while ($i < $loopLimit) { $g = new QtiInteger(Utils::gcd($g->getValue(), $flatCollection[$i + 1]->getValue())); $i++; } return $g; } }
/** * Marshall a QTI integer datatype into its PCI JSON Representation. * * @param \qtism\common\datatypes\Integer $integer * @return array */ protected function marshallInteger(QtiInteger $integer) { return array('base' => array('integer' => $integer->getValue())); }