public function conceptsAction($unit = '1') { $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; } $concepts = MappingHelper::conceptsInUnit($unit); $maxPercentage = 0; $conceptArray = []; foreach ($concepts as $concept) { $conceptID = $concept['Lecture Number']; $historicalConceptMasteryScores = ClassConceptHistory::find(["concept_id = '{$conceptID}'", "order" => 'time_stored DESC']); $newConcept = ["id" => $conceptID, "title" => $concept["Concept Title"], "history" => []]; foreach ($historicalConceptMasteryScores as $score) { $newConcept["history"][] = ["date" => $score->time_stored, "average" => $score->average_mastery, "percent" => $score->videopercentage]; } $newConcept["history"] = $newConcept["history"][0]; if ($newConcept["history"]["percent"] > $maxPercentage) { $maxPercentage = $newConcept["history"]["percent"]; } $conceptsArray[] = $newConcept; } $firstRow = ["max" => $maxPercentage]; array_unshift($conceptsArray, $firstRow); echo json_encode($conceptsArray); }
public function callMappingForFormDataFromPost($form_data) { $elements = array(); foreach ($form_data as $element_index => $element) { if (!empty($element['element_mapping']) && !empty($element['element_required']) && $element['element_required'] === "true") { if (!empty($element['element_value'])) { $callable_name = MappingHelper::getHandler($element['element_mapping']); if ($callable_name[0] == $element['element_mapping']) { if ($this->_callObjectFromCache($callable_name[0]) instanceof $callable_name[0]) { if (is_callable($callable_name, false, $real_callable_name)) { $element['element_mapping_value'] = call_user_func(array($this->_callObjectFromCache($callable_name[0]), $callable_name[1]), $element['element_value']); } } } } else { $element['element_required_message'] = 'Required Field Missing!'; } } $elements[$element_index] = $element; } return $elements; }
public function mappingsAction() { echo "<pre>"; echo "All units\n"; print_r(MappingHelper::allUnits()); echo "<hr>Concepts in unit 4\n"; print_r(MappingHelper::conceptsInUnit("4")); echo "<hr>Questions in concept (lecture number) 1\n"; print_r(MappingHelper::questionsInConcept("1")); echo "<hr>Question info for question 78.4\n"; print_r(MappingHelper::questionInformation("78.4")); echo "<hr>Videos for concept 9\n"; print_r(MappingHelper::videosForConcept("9")); echo "<hr>Resources for concept 1\n"; print_r(MappingHelper::resourcesForConcept("1")); echo "<hr>Concepts within the past 2 weeks: \n"; print_r(MappingHelper::conceptsWithin2Weeks()); }
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 static function videosInConceptLength($concept) { $videos = MappingHelper::videosForConcept($concept); $length = 0; foreach ($videos as $vid) { $length += $vid["Video Length"]; } return $length; }
public function videoHistoryAction() { $config = $this->getDI()->getShared('config'); if (!isset($_GET["p"])) { die("No history saver password provided."); } if ($_GET["p"] != $config->historySaverPassword) { die("Invalid history saver password provided. Should be {$config->historySaverPassword}"); } // We want to time this $startTime = microtime(true); $raw = false; $debug = false; $classHelper = new ClassHelper(); $masteryHelper = new MasteryHelper(); $studentIds = $classHelper->allStudents(); $recent_concepts = MappingHelper::conceptsWithin2Weeks(); foreach ($studentIds as $student) { $escStudent = str_replace("'", "", $student); $lastHistory = VideoHistory::findFirst(["student = '{$escStudent}'", "order" => "time_stored DESC"]); if (date("Y-m-d") == date("Y-m-d", strtotime($lastHistory->time_stored))) { echo " History already saved today for student: {$student}\n"; continue; } $videoPercentage = $masteryHelper->calculateUniqueVideoPercentageForConcepts($student, $recent_concepts); $videoHistory = new VideoHistory(); $videoHistory->student = $escStudent; $videoHistory->vidpercentage = $videoPercentage; if ($videoHistory->create() == false) { echo "*** Error saving concept history for {$concept}\n"; } else { } } // Print total time taken $endTime = microtime(true); echo "Execution time: " . ($endTime - $startTime) . " seconds\n"; }
public function conceptsAction($scope = 'all', $groupingId = '', $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; } $result = []; // Get the list of concepts for the given scope and grouping ID $concepts = []; switch ($scope) { case "concept": // Get a specific concept $conceptId = $groupingId; $concepts = array_filter(MappingHelper::allConcepts(), function ($concept) use($conceptId) { return $concept["Lecture Number"] == $conceptId; }); break; case "unit": // Filter based on unit $concepts = MappingHelper::conceptsInUnit($groupingId); break; default: // All concepts $concepts = MappingHelper::allConcepts(); break; } $masteryHelper = new MasteryHelper(); foreach ($concepts as $c) { $score = $masteryHelper::calculateConceptMasteryScore($context->getUserName(), $c["Lecture Number"], $debug); $videoPercentage = $masteryHelper::calculateUniqueVideoPercentageForConcept($context->getUserName(), $c["Lecture Number"], $debug); //$score = rand(0,100) / 10; //$videoPercentage = rand(0,100); if ($debug) { echo "Concept mapping info\n"; print_r($c); } $result[] = ["id" => $c["Lecture Number"], "title" => $c["Concept Title"], "masteryScore" => $score, "videoPercentage" => $videoPercentage, "unit" => $c["Unit Number"]]; } echo json_encode($result); }
public function masteryGraphAction($scope = 'all', $groupingId = '', $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; } $result = []; // Get the list of concepts for the given scope and grouping ID $concepts = []; switch ($scope) { case "unit": // Filter based on unit $concepts = MappingHelper::conceptsInUnit($groupingId); break; default: // All concepts $concepts = MappingHelper::allConcepts(); break; } $masteryHelper = new MasteryHelper(); foreach ($concepts as $c) { $score = $masteryHelper::calculateConceptMasteryScore($context->getUserName(), $c["Lecture Number"], $debug); if ($debug) { echo "Concept mapping info\n"; print_r($c); } $result[] = ["id" => $c["Lecture Number"], "display" => $c["Concept Title"], "score" => $score, "unit" => $c["Unit Number"]]; } echo json_encode($result); }
public function resourcesAction() { $this->tag->setTitle('Course Resources | Student Dashboard'); $this->view->pageTitle = 'Course Resources | Student Dashboard'; // Get our context (this takes care of starting the session, too) $context = $this->getDI()->getShared('ltiContext'); // Get list of concepts $conceptsMapping = MappingHelper::allConcepts(); $concepts = []; $resources = []; // Get list of resources for each concept foreach ($conceptsMapping as $c) { // Formatting for view $concepts[] = ["id" => $c["Lecture Number"], "title" => $c["Concept Title"], "date" => $c["Date"]]; // Get resources for each of the concepts $conceptId = $c["Lecture Number"]; $resourceLists[$conceptId] = MappingHelper::resourcesForConcept($conceptId); // Get videos for each of the concepts $videos = MappingHelper::videosForConcept($conceptId); // Format videos to be the same format as ayamel links from the resources.csv mapping foreach ($videos as $video) { $resourceLists[$conceptId][] = ["Lecture Number" => $video["Lecture Number"], "Resource Type" => "ayamel", "Resource Title" => $video["Video Title"], "Resource Link" => $video["Video ID"], "Resource Tracking Number" => $video["Video ID"]]; } } // Figure out which concept to position the list at (based on the current day) $currentConceptID = $conceptsMapping[0]["Date"]; // This is assuming that every concept has a date, and that they are listed in concepts.csv in chronological non-descending order // Find the first concept that's past today, and then use the previous concept $today = strtotime("today"); foreach ($conceptsMapping as $concept) { if (strtotime($concept["Date"]) > $today) { break; } else { $currentConceptID = $concept["Lecture Number"]; // If this concept has a date of today, then stop if (strtotime($concept["Date"]) == $today) { break; } } } $this->view->concepts = $concepts; $this->view->resources = $resourceLists; $this->view->currentConceptID = $currentConceptID; }
public function performDelete($url, $arguments, $accept) { // Decode url UrlHelper::Decode($url, $model, $objectId); // Get Mapping $mapping = MappingHelper::GetMapping($model); if ($mapping != null) { $object = $mapping->DbTableName; } else { $object = $model; } // Delete $dbWriter = new DbWriter(); $dbWriter->Open(); $dbWriter->Delete($object, $objectId); $dbWriter->Close(); header('Content-type: application/json; charset=utf-8'); header('', true, HttpStatus::OK); }
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); }