public function contextAction()
 {
     $context = $this->getDI()->getShared('ltiContext');
     // Send a statement tracking that they viewed this page
     $statementHelper = new StatementHelper();
     $statement = $statementHelper->buildStatement(["statementName" => "dashboardLaunched", "dashboardID" => "dashboard_select", "dashboardName" => "Dashboard Selector", "verbName" => "launched"], $context);
     if ($statement) {
         echo "working\n";
         $res = $statementHelper->sendStatements("visualization", [$statement]);
         echo $res;
     }
     echo $this->getDI()->getShared('ltiContext')->getCourseKey();
 }
 public function indexAction()
 {
     // Get our context (this takes care of starting the session, too)
     $context = $this->getDI()->getShared('ltiContext');
     $this->view->disable();
     // Use the StatementHelper class
     $statementHelper = new StatementHelper();
     // Make an actual xAPI statement from the post params
     $statement = $statementHelper->buildStatement($_POST, $context);
     if ($statement) {
         // If we've got a valid statement, send it to the visualization LRS (endpoint, username, password are defined in config.php)
         echo $statementHelper->sendStatements("visualization", [$statement]);
     } else {
         echo "Invalid statement parameters";
     }
 }
 public function recent_statementsAction()
 {
     // Get our context and check that it's valid
     $context = $this->getDI()->getShared('ltiContext');
     $this->view->context = $context;
     if (!$context->valid) {
         return;
     }
     $statementHelper = new StatementHelper();
     // Get all statements for current user
     $attempts = $statementHelper->getStatements("", ['statement.actor.name' => $context->getUserName()], []);
     // Get most recent statements first, and only get 100. (The query hasn't actually been run on the server yet, so we can still add more options)
     $cursor = $attempts["cursor"]->sort(['statement.timestamp' => -1]);
     $cursor = $attempts["cursor"]->limit(100);
     // Send result cursor to view
     $this->view->statements = $cursor;
 }
 public function studentsAction()
 {
     $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;
     }
     $classHelper = new ClassHelper();
     $masteryHelper = new MasteryHelper();
     $statementHelper = new StatementHelper();
     $students = $classHelper->allStudents();
     $studentInfo = [];
     for ($i = 0; $i < 10; $i++) {
         // For second parameter of what to query, see http://php.net/manual/en/mongocollection.find.php
         $statements = $statementHelper->getStatements("ayamel", ['statement.actor.name' => $students[$i]], ['statement.object.id' => true]);
         $count = $statements["cursor"]->count();
         $studentInfo[] = ["name" => $students[$i], "count" => $count];
     }
     echo json_encode($studentInfo);
 }
 public function calculatePersistenceScore($studentId, $raw = false, $debug = false)
 {
     // Calculate and store both parts of this skill score
     $statementHelper = new StatementHelper();
     // Calculate number of watched statements for student
     $statements = $statementHelper->getStatements("ayamel", ['statement.actor.name' => $studentId, 'statement.verb.id' => 'https://ayamel.byu.edu/watched', 'timestamp' => array('$gte' => new MongoDate(strtotime('midnight -2 weeks')))], ['statement.object.id' => true]);
     if ($statements["error"]) {
         $watchStatementCount = 0;
     } else {
         $watchStatementCount = $statements["cursor"]->count();
     }
     // Calculate number of question attempt (answered) statements for student
     $statements = $statementHelper->getStatements("openassessments", ['statement.actor.name' => $studentId, 'statement.verb.id' => 'http://adlnet.gov/expapi/verbs/answered', 'timestamp' => array('$gte' => new MongoDate(strtotime('midnight -2 weeks')))], ['statement.object.id' => true]);
     if ($statements["error"]) {
         $attemptCount = 0;
     } else {
         $attemptCount = $statements["cursor"]->count();
     }
     // store raw, and then return scaled
     $rawAttemptsScore = $attemptCount;
     $this->saveRawSkillScore($studentId, "persistence_attempts", $rawAttemptsScore);
     $rawWatchedScore = $watchStatementCount;
     $this->saveRawSkillScore($studentId, "persistence_watched", $rawWatchedScore);
     if ($raw) {
         return "{$rawAttemptsScore} , {$rawWatchedScore}";
     }
     return $this->getScaledSkillScore($studentId, "persistence");
 }
 public function studentsAction($start, $finish)
 {
     $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;
     }
     $timeArray[] = 280;
     $classHelper = new ClassHelper();
     $masteryHelper = new MasteryHelper();
     $statementHelper = new StatementHelper();
     $recent_concepts = MappingHelper::conceptsWithin2Weeks();
     $students = $classHelper->allStudents();
     //		$students = ["John Logie Baird","me"];
     $studentInfo = [];
     $maxCount = 0;
     //count($students)
     for ($i = $start; $i < $finish; $i++) {
         $startTime = microtime(true);
         $studentAverages = StudentMasteryHistory::findFirst(["conditions" => "email = ?1", "bind" => array(1 => $students[$i]), "order" => 'time_stored DESC']);
         // For second parameter of what to query, see http://php.net/manual/en/mongocollection.find.php
         $visStatements = $statementHelper->getStatements("visualization", ['statement.actor.name' => $students[$i]], ['statement.object.id' => true]);
         $hints = $statementHelper->getStatements("openassessments", ['statement.actor.name' => $students[$i], 'statement.verb.id' => 'http://adlnet.gov/expapi/verbs/showed-hint'], ['statement.object.id' => true]);
         $showAnswer = $statementHelper->getStatements("openassessments", ['statement.actor.name' => $students[$i], 'statement.verb.id' => 'http://adlnet.gov/expapi/verbs/showed-answer'], ['statement.object.id' => true]);
         $questionsAnswered = $statementHelper->getStatements("openassessments", ['statement.actor.name' => $students[$i], 'statement.verb.id' => 'http://adlnet.gov/expapi/verbs/answered'], ['statement.object.id' => true, 'statement.context.extensions' => true]);
         $hintsShowed = $hints["cursor"]->count();
         $answersShowed = $showAnswer["cursor"]->count();
         $high = 0;
         $medium = 0;
         $low = 0;
         $attempts = $questionsAnswered["cursor"]->count();
         $correct = 0;
         foreach ($questionsAnswered["cursor"] as $confidenceCheck) {
             $confidenceCheck = StatementHelper::replaceHtmlEntity($confidenceCheck, true);
             if ($confidenceCheck['statement']['context']['extensions']['http://byuopenanalytics.byu.edu/expapi/extensions/correct'] == true) {
                 $correct++;
             }
             if (array_key_exists('http://byuopenanalytics.byu.edu/expapi/extensions/confidence_level', $confidenceCheck['statement']['context']['extensions'])) {
                 if ($confidenceCheck['statement']['context']['extensions']['http://byuopenanalytics.byu.edu/expapi/extensions/confidence_level'] == "high") {
                     $high++;
                 }
                 if ($confidenceCheck['statement']['context']['extensions']['http://byuopenanalytics.byu.edu/expapi/extensions/confidence_level'] == "medium") {
                     $medium++;
                 }
                 if ($confidenceCheck['statement']['context']['extensions']['http://byuopenanalytics.byu.edu/expapi/extensions/confidence_level'] == "low") {
                     $low++;
                 }
             }
         }
         $commonConfidence = max($high, $medium, $low);
         if ($commonConfidence == $high) {
             $medianConfidence = "High";
         } else {
             if ($commonConfidence == $medium) {
                 $medianConfidence = "Medium";
             } else {
                 $medianConfidence = "Low";
             }
         }
         $count = $visStatements["cursor"]->count();
         $escapedString = str_replace("'", "", $students[$i]);
         //	echo $escapedString;
         $lastHistory = VideoHistory::findFirst(["student = '{$escapedString}'", "order" => "time_stored DESC"]);
         $vidPercent = $lastHistory->vidpercentage;
         if ($count > $maxCount && $students[$i] != 'John Logie Baird') {
             $maxCount = $count;
         }
         if (!is_object($studentAverages)) {
             $newStudent = ["name" => $students[$i], "average" => 0, "count" => $count, "vPercentage" => $vidPercent, "correct" => $correct, "attempts" => $attempts, "hintsShowed" => $hintsShowed, "answersShowed" => $answersShowed, "confidence" => $medianConfidence];
         } else {
             $newStudent = ["name" => $studentAverages->email, "average" => $studentAverages->recent_average, "count" => $count, "vPercentage" => $vidPercent, "correct" => $correct, "attempts" => $attempts, "hintsShowed" => $hintsShowed, "answersShowed" => $answersShowed, "confidence" => $medianConfidence];
         }
         if ($students[$i] != 'John Logie Baird' && $students[$i] != 'Bob Bodily') {
             $studentInfo[] = $newStudent;
         }
         $endTime = microtime(true);
         $timeArray[$i] = $endTime - $startTime;
         //echo "Execution time: " . ($endTime - $startTime) ." seconds\n";
     }
     $avg = 0;
     foreach ($timeArray as $time) {
         $avg += $time;
     }
     $avg = $avg / 280;
     //	echo "Average Time: ".$avg." seconds\n";
     //Sorts the students by their recent mastery average, from highest to lowest.
     usort($studentInfo, function ($student1, $student2) {
         return $student1["average"] <= $student2["average"];
     });
     $firstRow = ["max" => $maxCount];
     array_unshift($studentInfo, $firstRow);
     echo json_encode($studentInfo);
 }
 public function confidence_averageAction()
 {
     // TODO take out error reporting for production
     error_reporting(E_ALL);
     $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;
     }
     // This contains our different data elements
     $result = array();
     $statementHelper = new StatementHelper();
     // Numerical confidence values
     $levelValue = ["low" => -1, "medium" => 0, "high" => 1];
     $userConfidences = ["overall" => array(), "correct" => array(), "incorrect" => array()];
     $classConfidences = ["overall" => array(), "correct" => array(), "incorrect" => array()];
     //Get all user answer attempts
     $attempts = $statementHelper->getStatements("openassessments", ['statement.verb.id' => 'http://adlnet.gov/expapi/verbs/answered'], ['_id' => false, 'statement.actor.mbox' => true, 'statement.context.extensions' => true, 'statement.result.success' => true]);
     if ($attempts["error"]) {
         $result[] = ["error" => $attempts["error"]];
     } else {
         foreach ($attempts["cursor"] as $statement) {
             // Since we're now doing more than just counting, we need to do processing that Learning Locker normally would first:
             $statement = StatementHelper::replaceHtmlEntity($statement, true);
             if (isset($statement['statement']['context']['extensions']['http://byuopenanalytics.byu.edu/expapi/extensions/confidence_level']) && isset($statement['statement']['result']['success'])) {
                 $level = $statement['statement']['context']['extensions']['http://byuopenanalytics.byu.edu/expapi/extensions/confidence_level'];
                 $correct = $statement['statement']['result']['success'];
                 //Put this in user confidences if necessary
                 if (isset($statement['statement']['actor']['mbox']) && $statement['statement']['actor']['mbox'] == 'mailto:' . $context->getUserEmail()) {
                     $userConfidences["overall"][] = $levelValue[$level];
                     if ($correct == true) {
                         $userConfidences["correct"][] = $levelValue[$level];
                     } else {
                         $userConfidences["incorrect"][] = $levelValue[$level];
                     }
                 }
                 // Then always in class confidences
                 $classConfidences["overall"][] = $levelValue[$level];
                 if ($correct == true) {
                     $classConfidences["correct"][] = $levelValue[$level];
                 } else {
                     $classConfidences["incorrect"][] = $levelValue[$level];
                 }
             }
         }
         // User stats
         foreach ($userConfidences as $name => $list) {
             //Avoid division by 0
             $average = count($list) > 0 ? array_sum($list) / count($list) : 0;
             $result['user'][$name] = $average;
             //$result []= ["name" => $name, "value" => $average];
         }
         // Class stats
         foreach ($classConfidences as $name => $list) {
             //Avoid division by 0
             $average = count($list) > 0 ? array_sum($list) / count($list) : 0;
             $result['class'][$name] = $average;
             //$result []= ["name" => $name, "value" => $average];
         }
         echo json_encode($result);
     }
 }
 public function selectAction()
 {
     $this->tag->setTitle('Dashboard Selection');
     $this->view->pageTitle = 'Dashboard Selection';
     // Get our context (this takes care of starting the session, too)
     $context = $this->getDI()->getShared('ltiContext');
     // Send a statement tracking that they viewed this page
     $statementHelper = new StatementHelper();
     $statement = $statementHelper->buildStatement(["statementName" => "dashboardLaunched", "dashboardID" => "dashboard_select", "dashboardName" => "Dashboard Selector", "verbName" => "launched"], $context);
     if ($statement) {
         $statementHelper->sendStatements("visualization", [$statement]);
     }
 }
 public static function calculateUniqueVideoPercentageForVideo($studentId, $video, $debug = false)
 {
     // Length of each statement in video seconds
     $watchedStatementLength = 10;
     $possibleWatchedStatementCount = 0;
     $userWatchedStatementCount = 0;
     // TODO maybe check if $video is a string or int (so that just the ID, e.g. 1234, can be passed in), and then fetch the rest of the info based on that
     // 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);
     // Get the statement ID to search for
     $videoId = 'https://ayamel.byu.edu/content/' . $video["Video ID"];
     // Calculate how much time this video was watched
     $statementHelper = new StatementHelper();
     $statements = $statementHelper->getStatements("ayamel", ['statement.actor.name' => $studentId, 'statement.verb.id' => 'https://ayamel.byu.edu/watched', 'statement.object.id' => $videoId], ['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 {$videoId} : {$userWatchedStatementCount} unique watched statements out of {$possibleWatchedStatementCount} possible\n";
     }
     // 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);
 }