public function testAppendNumberOfItemsVariable()
 {
     $doc = new XmlDocument();
     $doc->load(self::samplesDir() . 'categories.xml');
     $this->assertEquals('MATH' . TestCategoryRulesUtils::NUMBER_ITEMS_SUFFIX, TestCategoryRulesUtils::appendNumberOfItemsVariable($doc->getDocumentComponent(), 'math'));
     $outcome = $doc->getDocumentComponent()->getComponentByIdentifier('MATH' . TestCategoryRulesUtils::NUMBER_ITEMS_SUFFIX);
     $this->assertInstanceOf('qtism\\data\\state\\OutcomeDeclaration', $outcome);
     $this->assertEquals(Cardinality::SINGLE, $outcome->getCardinality());
     $this->assertEquals(BaseType::INTEGER, $outcome->getBaseType());
     $this->assertEquals('MATH' . TestCategoryRulesUtils::NUMBER_ITEMS_SUFFIX, $outcome->getIdentifier());
     $defaultValue = $outcome->getDefaultValue();
     $this->assertInstanceOf('qtism\\data\\state\\DefaultValue', $defaultValue);
     $values = $defaultValue->getValues();
     $this->assertCount(1, $values);
     $this->assertTrue(is_int($values[0]->getValue()));
     $this->assertEquals(2, $values[0]->getValue());
 }
 /**
  * Apply Outcome Declaraton and Outcome Processing Rules.
  * 
  * This method will trigger the process of applying Outcome Declarations and Outcome Processing Rules on a given $test,
  * dependings on the assessmentItemRef categories found into it.
  * 
  * This method can be configure with the following flags:
  * 
  * TestCategoryRulesGenerator::COUNT:
  * 
  * The COUNT flag will trigger the process of creating Outcome Declarations where default values represent the number
  * of items involved in categories found in the $test. For instance, if $test contains two assessmentItemRef elements with a 'math'
  * category are found in the $test, an Outcome Declaration 'MATH_CATEGORY_NUMBER_ITEMS' with single cardinality, integer base type, and a default 
  * value of 2 will be injected in the $test definition.
  * 
  * TestCategoryRulesGenerator::CORRECT:
  * 
  * The CORRECT flag will trigger the process of creating Outcome Declarations and their related Outcome Processing Rules that
  * will take care of counting the number of items that were correctly responded, by category. As an example, if two assessmentItemRef elements with a
  * 'math' category are found in the $test, an Outcome Declaration 'MATH_CATEGORY_NUMBER_CORRECT' with single cardinality and integer base type
  * will be injected in the $test definition, in addition with the relevant Outcome Processing Rule in charge of computing the appropriate Outcome
  * value at test runtime.
  * 
  * TestCategoryRulesGenerator::SCORE:
  * 
  * The SCORE flag will trigger the process of creating Outcome Declarations and their related Outcome Processing Rules that
  * will take care of counting the total score of items, by category. As an example, if two assessmentItemRef elements with a
  * 'math' category are found in the $test, an Outcome Declaration 'MATH_CATEGORY_TOTAL_SCORE' with single cardinality and float base type
  * will be injected in the $test definition, in addition with the relevant Outcome Processing Rule in charge of computing the appropriate Outcome
  * value at test runtime. When this flag is enabled, the generation process for the Outcome Processing Rules will take into account the values
  * provided to the TestCategoryRulesGenerator::setScoreVariableIdentifier() and TestCategoryRulesGenerator::setWeightIdentifier() setters to
  * respectively identify which item variable (by default 'SCORE'), and which item weights should be used to compute total scores.
  * 
  * If no $flags are given, it is considered that all the flags above are enabled.
  * 
  * @param qtism\data\AssessmentTest $test A QTI-SDK AssessmentTest object.
  * @param integer $flags (optional) TestCategoryRulesGenerator::COUNT | TestCategoryRulesGenerator::CORRECT | TestCategoryRulesGenerator::SCORE
  */
 public function apply(AssessmentTest $test, $flags = 0)
 {
     if ($flags == 0) {
         $flags = self::COUNT | self::CORRECT | self::SCORE;
     }
     $categories = TestCategoryRulesUtils::extractCategories($test, $this->getCategoryExclusions());
     foreach ($categories as $category) {
         if ($flags & self::COUNT) {
             TestCategoryRulesUtils::appendNumberOfItemsVariable($test, $category);
         }
         if ($flags & self::CORRECT) {
             $numberCorrectVarName = TestCategoryRulesUtils::appendNumberCorrectVariable($test, $category);
             TestCategoryRulesUtils::appendNumberCorrectOutcomeProcessing($test, $category, $numberCorrectVarName);
         }
         if ($flags & self::SCORE) {
             $totalScoreVarName = TestCategoryRulesUtils::appendTotalScoreVariable($test, $category);
             TestCategoryRulesUtils::appendTotalScoreOutcomeProcessing($test, $category, $totalScoreVarName, $this->getScoreVariableIdentifier(), $this->getWeightIdentifier());
         }
     }
 }