public function videoRecommendationsAction($scope = 'all', $groupingId = 'all', $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;
     }
     // Get the list of videos associated with concepts for the given scope and grouping ID
     $videos = [];
     switch ($scope) {
         case "concept":
             // Filter based on concept
             $videos = MappingHelper::videosForConcept($groupingId);
             break;
         case "unit":
             // Filter based on unit
             $videos = MappingHelper::videosForConcepts(MappingHelper::conceptsInUnit($groupingId));
             break;
         default:
             // All videos
             $videos = MappingHelper::videosForConcepts(MappingHelper::allConcepts());
             break;
     }
     // Find percentage watched for each video
     foreach ($videos as $key => $video) {
         $percentageWatched = MasteryHelper::calculateUniqueVideoPercentageForVideo($context->getUserName(), $video, $debug);
         // Add the percentage to the video
         $video["percentageWatched"] = $percentageWatched;
         // Add the modified video back to the original array
         $videos[$key] = $video;
     }
     // Format each video for the frontend
     $formatted = [];
     foreach ($videos as $video) {
         $formatted[] = $video;
     }
     if ($debug) {
         echo "<pre>Getting information for these video IDs in scope {$scope} and ID {$groupingId}\n";
         foreach ($videos as $video) {
             echo $video["Video ID"] . "\n";
         }
     }
     echo json_encode($formatted);
 }
 public static function calculateUniqueVideoPercentageForConcepts($studentId, $conceptArray, $debug = false)
 {
     // Length of each statement in video seconds
     $watchedStatementLength = 10;
     // Find the videos related to this concept
     $relatedVideos = MappingHelper::videosForConcepts($conceptArray);
     $possibleWatchedStatementCount = 0;
     $userWatchedStatementCount = 0;
     $videoIds = array();
     foreach ($relatedVideos as $video) {
         // Length of video divided by 10 rounded down will be the total number of possible unique watched statements for that video
         $possibleWatchedStatementCount += floor($video["Video Length"] / $watchedStatementLength);
         // Add its ID to a list that we'll fetch watched statements for
         $videoIds[] = 'https://ayamel.byu.edu/content/' . $video["Video ID"];
     }
     // Calculate how much time these videos were watched
     // This is more efficient by using an $in query for all videos, rather than querying for each individual video as previously done
     $statementHelper = new StatementHelper();
     $statements = $statementHelper->getStatements("ayamel", ['statement.actor.name' => $studentId, 'statement.verb.id' => 'https://ayamel.byu.edu/watched', 'statement.object.id' => array('$in' => $videoIds)], ['statement.object.id' => true, 'statement.object.definition.extensions' => true]);
     if ($statements["error"]) {
         $userWatchedStatementCount = 0;
         if ($debug) {
             echo "Error in fetching watched statements for concept {$conceptId} and videos: \n";
             print_r($videoIds);
         }
     } else {
         // We need to track unique statements, so student can't get 100% video watched by watching the first half twice
         $videoTrackers = [];
         $watchStatementCount = $statements["cursor"]->count();
         foreach ($statements["cursor"] as $statement) {
             // We need to get rid of encoded "."s in extension names
             $statement = StatementHelper::replaceHtmlEntity($statement["statement"], true);
             // Set a flag for each rounded timestamp for each video
             $videoId = $statement["object"]["id"];
             $roundedTime = round($statement["object"]["definition"]["extensions"]["https://ayamel.byu.edu/playerTime"] / $watchedStatementLength);
             if (!isset($videoTrackers[$videoId])) {
                 $videoTrackers[$videoId] = [];
             }
             // See if a statement with the same rounded timestamp was already tracked
             if (isset($videoTrackers[$videoId][$roundedTime]) && $videoTrackers[$videoId][$roundedTime] == true) {
                 $isUnique = false;
             } else {
                 $isUnique = true;
                 $userWatchedStatementCount++;
                 // Track this statement
                 $videoTrackers[$videoId][$roundedTime] = true;
             }
             if ($debug) {
                 print_r($statement);
                 echo "Video id: {$videoId}, rounded time: {$roundedTime}, unique: {$isUnique} \n<hr>";
             }
         }
     }
     if ($debug) {
         echo "Videos for concept {$conceptId} : {$userWatchedStatementCount} unique watched statements out of {$possibleWatchedStatementCount} possible for the following videos: \n";
         print_r($videoIds);
     }
     // Return percentage (0-100) of videos watched, avoiding division by 0
     $percentage = $possibleWatchedStatementCount != 0 ? $userWatchedStatementCount / $possibleWatchedStatementCount : 0;
     $percentage = round($percentage * 100);
     return min($percentage, 100);
 }