/** * From a moodle course_modinfo object, it creates an intuitel LO * @author elever * @see \intuitel\LOFactory::createLOFromNative() * @param \course_modinfo $rawData : moodle course_modinfo object * @return CourseLO $course : intuitelLO course object */ function createLOFromNative($rawData) { $lmscourse = $rawData->get_course(); $courseLoid = Intuitel::getIDFactory()->getLoIdfromId('course', $lmscourse->id); // course object is created, constructor sets the compulsory attributes: LOId, loName, hasPrecedingSib, hasParent; and the optional: hasFollowingSib $course = new CourseLO($courseLoid, $lmscourse->fullname, null, null); // optional attributes $courseLang = $this->getLang($rawData); $course->setLang($courseLang); $childrenLoId = $this->getChildren($rawData); $course->sethasChildren($childrenLoId); return $course; }
/** * Compute a list of LOs for this LMS * * @param array $attributes * name=>value filter array */ public function findLObyAttributes(array $attributes) { if (array_key_exists('loId', $attributes) && array_key_exists('getFullCourse', $attributes) && $attributes['getFullCourse'] == 'true') { // retrieve all objects in course $id = $attributes['loId']; $loId = $id instanceof LOId ? $id : new LOId($id); try { $adaptor = Intuitel::getAdaptorInstanceForCourseLOId($loId); $list = $adaptor->findLOAll(); return $list; } catch (UnknownLOException $ex) { return array(); } catch (UnknownIDException $ex) { return array(); } } else { if (array_key_exists('loId', $attributes)) { // return one object $id = $attributes['loId']; $loId = $id instanceof LOId ? $id : new LOId($id); try { $lo = IntuitelAdaptor::createLO($loId); return array($lo); } catch (UnknownLOException $ex) { return array(); } catch (UnknownIDException $ex) { return array(); } } else { // search every course by params $courses = Intuitel::getIntuitelEnabledCourses(); $total_list = array(); foreach ($courses as $course) { $filter = array('loId' => $course->loId, 'getFullCourse' => 'true'); $list = $this->findLObyAttributes($filter); $total_list = array_merge($total_list, $list); } // filter out unwanted items $final_list = $this->filterUnmatched($total_list, $attributes); return $final_list; } } }
/** * Get the list of INUITEL-enabled courses in the LMS * @return array(intuitel\CourseLO) */ public static function getIntuitelEnabledCourses() { return Intuitel::getAdaptorInstanceForCourse(null)->getIntuitelEnabledCourses(); }
/** * (non-PHPdoc) * @see \intuitel\IntuitelAdaptor::getUseData() */ public function getUseData($lo, $native_user_id) { $useData = array('completion' => null, 'grade' => null, 'grademax' => null, 'grademin' => null, 'accessed' => null, 'seenPercentage' => null); // if this is a section get access data (a section is seen once main screen of the course is seen) if (get_class($lo) == 'intuitel\\SectionLO') { $courseLOid = $lo->getParent(); $courseid = Intuitel::getIDFactory()->getIdfromLoId($courseLOid); $useData['accessed'] = block_intuitel_get_access_status_course($courseid, $native_user_id); } else { if (get_class($lo) == 'intuitel\\CourseLO') { //the lo is the CourseLO, get the completion, accessed and grade data $loId = $lo->getloId(); $lo_id = Intuitel::getIDFactory()->getIdfromLoId($loId); $useData['accessed'] = block_intuitel_get_access_status_course($lo_id, $native_user_id); $useData['completion'] = block_intuitel_get_completion_status_course($lo_id, $native_user_id); block_intuitel_get_grade_info_course($lo_id, $native_user_id); } else { //this is a module (activity or resource) $loId = $lo->getloId(); $lo_id = Intuitel::getIDFactory()->getIdfromLoId($loId); $cm = get_coursemodule_from_id(null, $lo_id); $course_modinfo = get_fast_modinfo($cm->course); $coursemodule_info = $course_modinfo->get_cm($lo_id); //get the completion status from Moodle $useData['completion'] = block_intuitel_get_completion_status($coursemodule_info, $native_user_id); $useData['accessed'] = block_intuitel_get_access_status($lo_id, $native_user_id); $grade_info = block_intuitel_get_grade_info($coursemodule_info, $native_user_id); //grade_info contains info of the grade obtained as well as maximum and minimum grade of the module if ($grade_info != null) { $useData['grade'] = $grade_info['grade']; $useData['grademax'] = $grade_info['grademax']; $useData['grademin'] = $grade_info['grademin']; } if ($lo->media == 'video' || $lo->media == 'audio') { $viewed = block_intuitel_get_access_status($lo_id, $native_user_id); if ($viewed) { $useData['seenPercentage'] = 100; } else { $useData['seenPercentage'] = 0; } } } } return $useData; }
/** * For an activity LO, retrieves the moodle id of the following activity/resource (course_module) in the section of the activity * or null if this is the last activity in that section * @param \cm_info $rawData Moodle internal info for a course module * @return string|NULL id of the following activity/resource (Course_module) */ private function getFollowingSib($rawData) { $course_info = $rawData->get_modinfo(); //get the course_modinfo object with all data of the course $section = $course_info->get_section_info($rawData->sectionnum); $cmsId = explode(',', $section->sequence); //array with the ids of the cms in that section $position = array_keys($cmsId, $rawData->id); //position of the cm in the sequence $pos = $position[0]; $num_mods = count($cmsId); while (true) { // if($position[0]==(count($cmsId)-1)){ //it is the last in the section, not previous cm if ($pos == $num_mods - 1) { //it is the last in the section, not previous cm $FollowingSib = null; break; } else { // get the previous cm in the sequence $FollowingSib = $cmsId[$pos + 1]; // check if type is ignored $factory = Intuitel::getAdaptorInstance()->getGuessedFactory($course_info->get_cm($FollowingSib)); if (!$factory->toBeIgnored()) { break; } } $pos++; } // end of while return $FollowingSib; }
/** * (non-PHPdoc) * @see \intuitel\simulator::process_learner_update_request() */ public function process_learner_update_request($loId, $learnerid, $courseLo) { if ($learnerid instanceof UserId) { $userID = $learnerid; } else { $userID = new UserId((string) $learnerid); } $user = $this->intuitelAdaptor->getNativeUserFromUId($userID); // Select user interface language the same way Mooodle does: // First Course forced lang // second user preference $courseid = Intuitel::getIDFactory()->getIdfromLoId($courseLo->loId); global $DB; if (!($course = $DB->get_record("course", array("id" => $courseid)))) { print_error('coursemisconf'); } global $USER; $USER = $user; if ($course->lang != '') { $USER->lang = $course->lang; } global $SESSION; $SESSION->lang = $USER->lang; // end language selection $timeFrom = time() - $this->time_window; $events_user = $this->intuitelAdaptor->getLearnerUpdateData(array($user->id), $courseLo, $timeFrom, null, false); $events = array(); if (array_key_exists((string) $userID->id, $events_user)) { $events = $events_user[(string) $userID->id]; } list($revisits, $durations) = IntuitelController::compute_revisits($events); $this->durations = $durations; $this->revisits = $revisits; $currentKOEvent = count($durations) > 0 ? $durations[0] : null; $previousKOEvent = count($durations) > 1 ? $durations[1] : null; $previousKO = $previousKOEvent != null ? $this->intuitelAdaptor->createLO($previousKOEvent->loId) : null; $previous_use_data = $previousKO != null ? $this->intuitelAdaptor->getUseData($previousKO, $user->id) : array(array()); $currentKO = $currentKOEvent != null ? $this->intuitelAdaptor->createLO($currentKOEvent->loId) : null; $current_use_data = $currentKO != null ? $this->intuitelAdaptor->getUseData($currentKO, $user->id) : array(array()); $currentKOType = $currentKOEvent != null ? Intuitel::getIDFactory()->getType($currentKOEvent->loId) : null; $previousKOType = $previousKOEvent != null ? Intuitel::getIDFactory()->getType($previousKOEvent->loId) : null; // // simulate intelligent behaviour // /** * Use case: Obvius and tedious tutor: Inform me what I'm doing. * DEBUG Use case */ if (false && $currentKO) { // disabled $mid = Intuitel::getIDFactory()->getNewMessageUUID(); $count = $revisits[(string) $currentKOEvent->loId]; $previous = ''; if ($previousKOEvent) { $previous = "Antes has estado en {$previousKOEvent->loId} durante {$previousKOEvent->duration} segundos"; } $this->tugFragment .= <<<xml <intuirr:Tug uId="jmb0001" mId="{$mid}"> \t<intuirr:MType>2</intuirr:MType> \t<intuirr:MData>Mensaje Obvio de depuración: Ahora estás en {$currentKOEvent->loId} donde has estado {$count} veces. {$previous}.</intuirr:MData> </intuirr:Tug> xml; } /* * ******************** * Use case: Fast Pace User spends less than N seconds in previous LO */ if ($previousKOEvent != null && $previousKOEvent->duration < $this->enough_time && $previousKOType != 'course' && $previousKOType != 'forum' && $previousKOType != 'folder' && (!$previous_use_data['grade'] || !$previous_use_data['grade'] > $previous_use_data['grademax'] * 2 / 3)) { $mid = Intuitel::getIDFactory()->getNewMessageUUID(); $a = new \stdClass(); $a->duration = $previousKOEvent->duration; $a->loId = (string) $previousKOEvent->loId; $advice_duration_str = get_string('advice_duration', 'block_intuitel', $a); $this->tugFragment .= <<<xml <intuirr:Tug uId="jmb0001" mId="{$mid}"> \t<intuirr:MType>2</intuirr:MType> \t<intuirr:MData>{$advice_duration_str}</intuirr:MData> </intuirr:Tug> xml; $this->selectedLORE[] = new loreRecommendation($previousKOEvent->loId, 70); } /* * **************************** * Use case: out-of-sequence */ $previousSiblingCount = $currentKO && $currentKO->hasPrecedingSib && array_key_exists($currentKO->hasPrecedingSib->id, $revisits) ? $revisits[$currentKO->hasPrecedingSib->id] : 0; if ($currentKO && $currentKO->hasPrecedingSib && $previousSiblingCount == 0 && !($current_use_data['grade'] > $current_use_data['grademax'] * 2 / 3)) { $mid = Intuitel::getIDFactory()->getNewMessageUUID(); $a = new \stdClass(); $a->previousLoId = (string) $currentKO->hasPrecedingSib; $a->currentLoId = (string) $currentKO->loId; $advice_sequence_str = get_string('advice_outofsequence', 'block_intuitel', $a); $this->tugFragment .= <<<xml <intuirr:Tug uId="jmb0001" mId="{$mid}"> \t<intuirr:MType>2</intuirr:MType> \t<intuirr:MData>{$advice_sequence_str}</intuirr:MData> </intuirr:Tug> xml; // recommend $this->selectedLORE[] = new loreRecommendation($currentKO->hasPrecedingSib, 100); $this->selectedLORE[] = new loreRecommendation($currentKO->loId, 100); } /* * ***************************** * Use case: excessive revisits */ // print_object($this->revisits[$currentKOEvent->loId->id]);die; if ($currentKOEvent != null && $this->revisits[$currentKOEvent->loId->id] > 2 && $currentKOType != 'course' && $currentKOType != 'forum' && $currentKOType != 'folder') { $count = $revisits[$currentKOEvent->loId->id]; $mid = Intuitel::getIDFactory()->getNewMessageUUID(); $params_str = new \stdClass(); $params_str->count = $count; $params_str->loId = (string) $currentKOEvent->loId; $advice_revisits_str = get_string('advice_revisits', 'block_intuitel', $params_str); $this->tugFragment .= <<<xml <intuirr:Tug uId="jmb0001" mId="{$mid}"> \t<intuirr:MType>2</intuirr:MType> \t<intuirr:MData>{$advice_revisits_str}</intuirr:MData> </intuirr:Tug> xml; } /* * Test case. Graded activity is abandoned with low grade */ if ($previousKOEvent != null && $previous_use_data['grade'] < $previous_use_data['grademax'] * 2 / 3) { $grade = number_format($previous_use_data['grade']); $grademax = number_format($previous_use_data['grademax']); $mid = Intuitel::getIDFactory()->getNewMessageUUID(); $params_str = new \stdClass(); $params_str->loId = (string) $previousKOEvent->loId; $params_str->grade = $grade; $params_str->grademax = $grademax; $advice_grade_str = get_string('advice_grade', 'block_intuitel', $params_str); $this->tugFragment .= <<<xml <intuirr:Tug uId="jmb0001" mId="{$mid}"> \t<intuirr:MType>2</intuirr:MType> \t<intuirr:MData>{$advice_grade_str}</intuirr:MData> </intuirr:Tug> xml; // recommends previous LO if (isset($previousKO->hasPrecedingSib)) { $this->selectedLORE[] = new loreRecommendation($previousKO->hasPrecedingSib, 100); } $this->selectedLORE[] = new loreRecommendation($previousKOEvent->loId, 80); } /* * Test case. Graded activity is abandoned with high grade. The student is congratulated for good result */ if ($previousKOEvent != null && $previous_use_data['grade'] > $previous_use_data['grademax'] * 2 / 3) { $grade = number_format($previous_use_data['grade']); $grademax = number_format($previous_use_data['grademax']); $mid = Intuitel::getIDFactory()->getNewMessageUUID(); $params_str = new \stdClass(); $params_str->loId = (string) $previousKOEvent->loId; $params_str->grade = $grade; $params_str->grademax = $grademax; $congratulate_grade_str = get_string('congratulate_grade', 'block_intuitel', $params_str); $this->tugFragment .= <<<xml <intuirr:Tug uId="jmb0001" mId="{$mid}"> \t<intuirr:MType>1</intuirr:MType> \t<intuirr:MData>{$congratulate_grade_str}</intuirr:MData> </intuirr:Tug> xml; // recommends previous LO if (isset($previousKO->hasPrecedingSib)) { $this->selectedLORE[] = new loreRecommendation($previousKO->hasPrecedingSib, 100); } $this->selectedLORE[] = new loreRecommendation($previousKOEvent->loId, 80); } /* * Test case. Graded activity is visited with high grade. The student is remembered about */ if ($currentKOEvent != null && $current_use_data['grade'] > $current_use_data['grademax'] * 2 / 3) { $grade = number_format($current_use_data['grade']); $grademax = number_format($current_use_data['grademax']); $mid = Intuitel::getIDFactory()->getNewMessageUUID(); $params_str = new \stdClass(); $params_str->loId = (string) $currentKOEvent->loId; $params_str->grade = $grade; $params_str->grademax = $grademax; $remember_graded_str = get_string('remember_already_graded', 'block_intuitel', $params_str); $this->tugFragment .= <<<xml <intuirr:Tug uId="jmb0001" mId="{$mid}"> \t<intuirr:MType>1</intuirr:MType> \t<intuirr:MData>{$remember_graded_str}</intuirr:MData> </intuirr:Tug> xml; } if ($currentKO != null) { /* * First LO in the course */ $parent = $currentKO->hasParent != null ? $this->intuitelAdaptor->createLO($currentKO->hasParent) : null; if ($currentKO->hasPrecedingSib == null && $parent != null && $parent->hasPrecedingSib == null) { $this->tugFragment .= <<<xml <intuirr:Tug uId="intuitelstudent1" mId="db4d7ada-58fb-4939-ba0d-41c9ac585efd" rId="dcbcf826-a5fe-4fe8-bcc2-609c299afe04"> <intuirr:MType>4</intuirr:MType> <intuirr:MData xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <![CDATA[ <h4>You just started the available material. Very good!</h4> Please, select a Learning Pathway:<br/> <input type="radio" name="invalidateLpSelection[]" value="1">Classically structured learning path sequenced by matters.</input><br/> \t<input type="radio" name="invalidateLpSelection[]" value="2">Hierarchically structured material organized by levels of abstraction.</input><br/> \t]]></intuirr:MData> </intuirr:Tug> xml; } /* * Last LO in the course */ if ($currentKO->hasFollowingSib == null && $parent != null && $parent->hasFollowingSib == null) { $this->tugFragment .= <<<xml <intuirr:Tug uId="intuitelstudent1" mId="db4d7ada-58fb-4939-ba0d-41c9ac585efd" rId="dcbcf826-a5fe-4fe8-bcc2-609c299afe04"> <intuirr:MType>4</intuirr:MType> <intuirr:MData xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><![CDATA[<h4>You just completed all your assigned material. Very good!</h4> Do you want to restart it following another Learning Pathway? <select name="invalidateLpSelection[]" ><option name="invalidateLpSelection-Y" value="Y">yes</option><option name="invalidateLpSelection-N" value="N">no</option></select>]]></intuirr:MData> </intuirr:Tug> xml; } /* $this->tugFragment.= <<<xml <Tug uId="jmb0001" mId="12345678-1234-abcd-ef12-123456789014"> <MType>1</MType> <MData>Estás visitando $currentKOEvent->loId y vienes de $previousKOEvent->loId donde has estado $previousKOEvent->duration segundos.</MData> </Tug> xml; */ // if currentKO is the course use previousKO if (!isset($currentKO->hasParent)) { // course $currentKO = $previousKO; } if (isset($currentKO->hasFollowingSib)) { $following = $this->intuitelAdaptor->createLO($currentKOEvent->loId); $followingType = Intuitel::getIDFactory()->getType($following->loId); if ($followingType == 'section') { $this->selectedLORE[] = new loreRecommendation($following->hasFollowingSib, 70); } else { $this->selectedLORE[] = new loreRecommendation($currentKO->hasFollowingSib, 70); } } else { if (isset($currentKO->hasParent)) { // suppose section $sectionLo = $currentKO->hasParent ? $this->intuitelAdaptor->createLO($currentKO->hasParent) : null; //section $nextsectionLo = $sectionLo != null && $sectionLo->hasFollowingSib ? $this->intuitelAdaptor->createLO($sectionLo->hasFollowingSib) : null; // next section if ($nextsectionLo && isset($nextsectionLo->hasChild[0])) { $this->selectedLORE[] = new loreRecommendation($nextsectionLo->hasChild[0], 70); } } } } // simulate a sequencing $lastLoreRec = count($this->selectedLORE) > 0 ? $this->selectedLORE[count($this->selectedLORE) - 1] : null; $lastLoreId = $lastLoreRec ? $lastLoreRec->loId : null; for ($i = 0; $i < 4; $i++) { if (!$lastLoreId) { break; } try { $loreLO = $this->intuitelAdaptor->createLO($lastLoreId); if (isset($loreLO->hasFollowingSib)) { $lastLoreId = $loreLO->hasFollowingSib; $this->selectedLORE[] = new loreRecommendation($lastLoreId, $lastLoreRec->score / ($i + 2)); } } catch (UnknownLOTypeException $e) { break; } } }
private function getMedia($loId) { // get the id of the section in Moodle $id = Intuitel::getIDFactory()->getIdfromLoId($loId); $section_info = get_section_info($id); $media = block_intuitel_getMediaType($section_info->summary); //array containing the media types contained in the summary of the section return $media; }
public function getIDRegExpr() { $lmsid = Intuitel::getAdaptorInstance()->getLMSId(); return "/{$lmsid}-([a-zA-z]+)([0-9]+)/"; }