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