public function questionRecommendationsAction($scope = 'unit', $groupingId = '3', $debug = false) { $this->view->disable(); // Get our context (this takes care of starting the session, too) $context = $this->getDI()->getShared('ltiContext'); if (!$context->valid) { echo '[{"error":"Invalid lti context"}]'; return; } if (!isset($groupingId)) { echo '[{"error":"No scope grouping ID specified"}]'; return; } $classHelper = new ClassHelper(); $group1 = []; $group2 = []; $group3 = []; $group4 = []; // Get the list of questions associated with concepts for the given scope and grouping ID $questionRows = []; switch ($scope) { case "concept": // Filter based on concept $questionRows = MappingHelper::questionsInConcept($groupingId); break; case "unit": // Filter based on unit $questionRows = MappingHelper::questionsInConcepts(MappingHelper::conceptsInUnit($groupingId)); break; default: // Allowing all would take too long echo '[{"error":"Invalid scope option"}]'; return; break; } if ($debug) { echo "<pre>Getting information for these questions in scope {$scope} and ID {$groupingId}\n"; print_r($questionRows); } $questions = []; // Get some info about each question foreach ($questionRows as $question) { // Get number of attempts and number of correct attempts $question["attempts"] = MasteryHelper::countAttemptsForQuestion($context->getUserName(), $question["OA Quiz ID"], $question["Question Number"], $debug); $question["correctAttempts"] = MasteryHelper::countCorrectAttemptsForQuestion($context->getUserName(), $question["OA Quiz ID"], $question["Question Number"], $debug); // Get amount of associated videos watched $question["videoPercentage"] = MasteryHelper::calculateUniqueVideoPercentageForQuestion($context->getUserName(), $question); // Variables used in the display table // This is one place where we're just using correct, not better correct, attempts $question["correct"] = $question["correctAttempts"]["correct"] > 0; $question["classAverageAttempts"] = $classHelper->calculateAverageAttemptsForQuestion($question["OA Quiz ID"], $question["Question Number"], $debug); $question["classViewedHint"] = $classHelper->calculateViewedHintPercentageForQuestion($question["OA Quiz ID"], $question["Question Number"], $debug); $question["classViewedAnswer"] = $classHelper->calculateViewedAnswerPercentageForQuestion($question["OA Quiz ID"], $question["Question Number"], $debug); $questions[] = $question; } // Fetch question texts for all questions in these assessments // Get the Open Assessments API endpoint from config $assessmentsEndpoint = $this->getDI()->getShared('config')->openassessments_endpoint; // Extract a list of assessment IDs from our list of questions. We'll get question texts for these. $assessmentIDs = ["assessment_ids" => array_values(array_unique(array_column($questions, "OA Quiz ID")))]; $request = $assessmentsEndpoint . "api/question_text"; //$request = "http://192.168.33.102/api/question_text"; if ($debug) { echo "Fetching question texts for these assessment IDs:\n"; print_r(array_column($questions, "OA Quiz ID")); print_r($assessmentIDs); echo $request; } #print_r($assessmentIDs); #echo json_encode($request); $session = curl_init($request); curl_setopt($session, CURLOPT_RETURNTRANSFER, true); curl_setopt($session, CURLOPT_POST, 1); curl_setopt($session, CURLOPT_POSTFIELDS, json_encode($assessmentIDs)); $response = curl_exec($session); #echo json_encode($questionRows); // Catch curl errors if (curl_errno($session)) { $error = "Curl error: " . curl_error($session); } curl_close($session); #print_r($response); $questionTexts = json_decode($response, true); if ($debug) { print_r($questionTexts); } foreach ($questions as $key => $q) { // Make sure the question text exists before setting it $questions[$key]["display"] = isset($questionTexts[$q["OA Quiz ID"]][$q["Question Number"] - 1]) ? $questionTexts[$q["OA Quiz ID"]][$q["Question Number"] - 1] : "Error getting question text for #{$q["OA Quiz ID"]} # #{$q["Question Number"]}-1"; // Avoid off-by-one error. The question id from statement object id will be 1 to n+1 //$q["questionText"] = $questionText; } // Now go through the questions for each group and find matching questions foreach ($questions as $question) { // Group 1: // Questions with 0 attempts if ($question["attempts"] == 0) { $group1[] = $question; } // Group 2: // >0 attempts for each question // No correct statements without a show answer statement in the preceding minute for each question (correctAttempts < 1) // Watched less than half of the videos associated with each question if ($question["attempts"] > 0 && $question["correctAttempts"]["betterCorrect"] == 0 && $question["videoPercentage"] < 0.5) { $group2[] = $question; } // Group 3: // >0 attempts for each question // No correct statements without a show answer statement in the preceding minute for each question (correctAttempts < 1) // Watched more than half of the videos associated with each question if ($question["attempts"] > 0 && $question["correctAttempts"]["betterCorrect"] == 0 && $question["videoPercentage"] >= 0.5) { $group3[] = $question; } // Group 4: // > 0 correct statements without a show answer statement in the preceding minute for each question (correctAttempts > 0) // More than 1 attempt if ($question["correctAttempts"]["betterCorrect"] > 0 && $question["attempts"] > 1) { $group4[] = $question; } } if ($debug) { print_r($questions); } $result = ["group1" => $group1, "group2" => $group2, "group3" => $group3, "group4" => $group4]; echo json_encode($result); }