public function testAppendNumberCorrectOutcomeProcessing()
 {
     $doc = new XmlDocument();
     $doc->load(self::samplesDir() . 'categories.xml');
     TestCategoryRulesUtils::appendNumberCorrectOutcomeProcessing($doc->getDocumentComponent(), 'math', 'MATH' . TestCategoryRulesUtils::NUMBER_CORRECT_SUFFIX);
     $this->assertInstanceOf('qtism\\data\\processing\\OutcomeProcessing', $doc->getDocumentComponent()->getOutcomeProcessing());
     $outcomeRules = $doc->getDocumentComponent()->getOutcomeProcessing()->getOutcomeRules();
     $this->assertCount(1, $outcomeRules);
     $this->assertInstanceOf('qtism\\data\\rules\\setOutcomeValue', $outcomeRules[0]);
     $this->assertEquals('MATH' . TestCategoryRulesUtils::NUMBER_CORRECT_SUFFIX, $outcomeRules[0]->getIdentifier());
     $this->assertInstanceOF('qtism\\data\\expressions\\NumberCorrect', $outcomeRules[0]->getExpression());
     $this->assertEquals(array('math'), $outcomeRules[0]->getExpression()->getIncludeCategories()->getArrayCopy());
     // If a second call to TestCategoryRulesUtils::appendNumberCorrectOutcomeProcessing occurs for a variable wich
     // is already targeted by a setOutcomeValue rule, no new outcome rule should appear to avoid duplicates.
     TestCategoryRulesUtils::appendNumberCorrectOutcomeProcessing($doc->getDocumentComponent(), 'math', 'MATH' . TestCategoryRulesUtils::NUMBER_CORRECT_SUFFIX);
     $outcomeRules = $doc->getDocumentComponent()->getOutcomeProcessing()->getOutcomeRules();
     $this->assertCount(1, $outcomeRules);
 }
 /**
  * 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());
         }
     }
 }