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); }