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;
 }
예제 #2
0
 /**
  * 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);
     }
 }
예제 #3
0
 /**
  * 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;
     }
 }
예제 #4
0
 /**
  * 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()));
 }