From 78233cf2810e6053d38de90e92b7a1b0f2b26e19 Mon Sep 17 00:00:00 2001 From: Frode Petterson Date: Mon, 17 Jul 2017 16:09:44 +0200 Subject: [PATCH] Improve sort of matching type tasks Will order by correct/wrong and group matches on same row HFP-1250 --- type-processors/matching-processor.class.php | 174 +++++++++++++++---- 1 file changed, 138 insertions(+), 36 deletions(-) diff --git a/type-processors/matching-processor.class.php b/type-processors/matching-processor.class.php index 9d950d1..4f03a35 100644 --- a/type-processors/matching-processor.class.php +++ b/type-processors/matching-processor.class.php @@ -172,6 +172,113 @@ function generateRows($mappedCRP, $mappedResponse, $dropzones, $draggables) { return $html; } + /** + * Sort handler for comparing result rows + * + * @param stdClass $a + * @param stdClass $b + * @return int + */ + private static function rowcmp($a, $b) { + if ($a->isCorrect && $b->isCorrect || !$a->isCorrect && !$b->isCorrect) { + return strcmp($a->response, $b->response); + } + if ($a->isCorrect && !$b->isCorrect) { + return -1; + } + if (!$a->isCorrect && $b->isCorrect) { + return 1; + } + } + + /** + * Creates the inital set of rows needed when generating the table HTML + * + * @param array $draggables + * @param array $crp + * @param array $response + * @return array + */ + private static function createUserAnswerRows(&$draggables, &$crp, &$response) { + // Create list with all rows to display + $rows = array(); + foreach ($response as $key => $answer) { + + $row = (object) array( + 'isCorrect' => in_array($answer, $crp), + 'crp' => '', + ); + + // Locate response label + foreach ($draggables as $draggable) { + if ($draggable->id === $answer) { + $row->response = $draggable->value; + break; + } + } + + $rows[] = $row; + } + + // Sort rows + usort($rows, array('MatchingProcessor', 'rowcmp')); + return $rows; + } + + /** + * Creates a list of soluton labels. + * + * @param array $draggables + * @param array $crp + * @return array + */ + private static function createSolutionRows(&$draggables, &$crp) { + // Create list of solution labels + $solutions = array(); + foreach ($crp as $pattern) { + $solutions[] = $draggables[$pattern]->value; + } + sort($solutions); + return $solutions; + } + + /** + * Puts the solutions labels into the approperiate rows. + * + * @param array $rows + * @param array $solutions + */ + private static function addSolutionsToRows(&$rows, &$solutions) { + // Add solution labels to rows + foreach ($rows as $key => &$row) { + if (empty($solutions)) { + break; // All solutions have been added + } + + if ($row->isCorrect) { + // Add solution if hasn't been added yet + $index = array_search($row->response, $solutions); + if ($index !== FALSE) { + $row->crp = $solutions[$index]; + unset($solutions[$index]); // Prevent adding multiple times + } + } + else { + // Add the next solution + $row->crp = array_shift($solutions); + } + } + + // In case we still have some solutions left, add extra rows for them + foreach ($solutions as $solution) { + $rows[] = (object) array( + 'isCorrect' => FALSE, + 'crp' => $solution, + 'response' => '', + ); + } + } + /** * Generate row for a single dropzone and populate it with correct answers and * user answers @@ -184,59 +291,54 @@ function generateRows($mappedCRP, $mappedResponse, $dropzones, $draggables) { * @return string Drop zone rows element */ function generateDropzoneRows($dropzone, $draggables, $crp, $response) { - $dzRows = sizeof($crp) > sizeof($response) ? sizeof($crp) : sizeof($response); - - // Skip row if no correct or user answers - if ($dzRows <= 0) { - return ''; + if (!count($response) && !count($crp)) { + return ''; // Skip if no correct or user answers } - $rows = ''; + // Get rows needed to display user answers + $rows = self::createUserAnswerRows($draggables, $crp, $response); + + // Get correct solutions labels for the task + $solutions = self::createSolutionRows($draggables, $crp); + + // Merges the solutions into the correct rows + self::addSolutionsToRows($rows, $solutions); + + // Ready to generate the HTML + $rowsHtml = ''; $lastCellInRow = 'h5p-matching-last-cell-in-row'; + $numRows = count($rows); - for ($i = 0; $i < $dzRows; $i++) { - $row = ''; - $tdClass = $i >= $dzRows - 1 ? $lastCellInRow : ''; + foreach ($rows as $key => &$row) { + $rowHtml = ''; + $tdClass = ($key >= $numRows - 1 ? $lastCellInRow : ''); - if ($i === 0) { - // Add drop zone - $row .= + if ($key === 0) { + // Print Drop Zone + $rowHtml .= '' . $dropzone->value . ''; } // Add correct response pattern - $crpCellContent = isset($crp[$i]) ? $draggables[$crp[$i]]->value : ''; - $row .= '' . - $crpCellContent . + $rowHtml .= '' . + $row->crp . ''; - - // Add user response - $isCorrectClass = ''; - $responseCellContent = ''; - if (isset($response[$i])) { - $isCorrectClass = isset($response[$i]) && in_array($response[$i], $crp) ? - 'h5p-matching-draggable-correct' : 'h5p-matching-draggable-wrong'; - foreach ($draggables as $draggable) { - if ($draggable->id === $response[$i]) { - $responseCellContent = $draggable->value; - break; - } - } - } - - $classes = $tdClass . (sizeof($isCorrectClass) ? ' ' : '') . $isCorrectClass; - $row .= '' . - $responseCellContent . + // Add user reponse + $correctClass = ($row->isCorrect ? 'h5p-matching-draggable-correct' : 'h5p-matching-draggable-wrong'); + $classes = $tdClass . ($tdClass !== '' && $correctClass !== '' ? ' ' : '') . ($row->response !== '' ? $correctClass : ''); + $rowHtml .= '' . + $row->response . ''; - $rows .= '' . $row . ''; + $rowsHtml .= '' . $rowHtml . ''; } - return $rows; + + return $rowsHtml; } /**