/**
  * Finds the module id from a resource instance, which is needed for the "get_cm($moduleid)" function, to get module's name.
  * For that, uses the courses instances information, retrieved using "get_fast_modinfo($courseid)" function.
  *
  * @param array $instances Key is resource type name, and value is an array of each instance of the course of that type.
  * @param int $resourceid The resource we are finding the moduleid of.
  * @param int $courseid The course the module belongs to.
  * @return int Module id.
  */
 public static function get_resource_moduleid($instances, $resourceid, $courseid)
 {
     $db = new database_helper();
     foreach ($instances as $instancetype => $typeinstances) {
         $typeinstancesids = array_keys($typeinstances);
         if (in_array($resourceid, $typeinstancesids)) {
             $typeid = $db->get_module_type_id_by_name($instancetype);
             $moduleid = $db->get_module_id($courseid, $resourceid, $typeid);
             break;
         }
     }
     return $moduleid;
 }
 /**
  * Given the data of the historic users and the current ones, creates a matrix of association coefficients, with the
  * current users as rows, and the historic user as columns.
  *
  * @see cosine_similarity($vector1, $vector2).
  * @param array $currentdata A 2D array.
  * @param array $historicdata A 2D array.
  * @param \text_progress_trace $trace Text output trace.
  * @return array The association matrix; empty if no association could be made.
  */
 public function create_associations_matrix($currentdata, $historicdata, $trace)
 {
     $db = new database_helper();
     $trace->output("[mycourse " . date('d/m/Y H:i:s') . "]: Starting creation of associations matrix.");
     $trace->output("[mycourse " . date('d/m/Y H:i:s') . "]: Transforming receiving data to get a matrix of users x resources. " . " with the views as values.");
     $currenttransformeddata = $this->matrix->transform_queried_data($currentdata);
     $historictransformeddata = $this->matrix->transform_queried_data($historicdata);
     $trace->output('[mycourse ' . date('d/m/Y H:i:s') . ']: Both historic and current data have been transformed.');
     $currentusers = array_keys($currenttransformeddata);
     $historicusers = array_keys($historictransformeddata);
     $matrix = array();
     foreach ($currentusers as $currentuser) {
         $trace->output('[mycourse ' . date('d/m/Y H:i:s') . "]: Starting calculating associations for current user " . "{$currentuser}.");
         $currentviewsvector = $currenttransformeddata[$currentuser];
         $similarities = null;
         foreach ($historicusers as $historicuser) {
             $historicviewsvector = $historictransformeddata[$historicuser];
             $trace->output('[mycourse ' . date('d/m/Y H:i:s') . "]: Starting calculating cosine similarity between a vector " . "of " . count($currentviewsvector) . " elements with a vector of " . count($historicviewsvector) . " elements.");
             $similarity = $this->cosine_similarity($currentviewsvector, $historicviewsvector);
             $trace->output('[mycourse ' . date('d/m/Y H:i:s') . ']: Cosine similarity between those vectors has been ' . 'calculated.');
             $similarity = round($similarity, 4);
             $similarities[$historicuser] = $similarity;
             $db->insert_similarity($currentuser, $historicuser, $similarity, $this->currentweek);
         }
         $matrix[$currentuser] = $similarities;
         $trace->output('[mycourse ' . date('d/m/Y H:i:s') . "]: Similarities for current user {$currentuser} have been " . "calculated.");
     }
     return $matrix;
 }
 /**
  * Performs the data importation from Moodle core tables (courses, enrolled users, logs). This importation is done only if
  * database_helper->has_data_to_be_imported() returns true.
  *
  * @param int $courseid The current course id for which the data has to be imported.
  */
 protected function import_data($courseid)
 {
     $courseyear = $this->db->get_course_start_week_and_year($courseid)['year'];
     $previouscourses = $this->db->find_course_previous_teaching_ids_core_tables($courseid, $courseyear);
     foreach ($previouscourses as $previouscourse) {
         $this->db->dump_previous_core_info_to_historic_tables($previouscourse);
     }
     $previouscourses = $this->db->find_course_previous_teachings_ids_historic_tables($courseid, $courseyear);
     $this->db->insert_courses_associations($courseid, $previouscourses);
 }
 /**
  * Initializes the course, when is the first instance of the block, looking if it is personalizable or not, and
  * saving this in database.
  *
  * Currently, the students are being selected independently the course is personalizable or not, because maybe later
  * a csv importation is made, and like this there's no need to select students later.
  *
  * @param int $courseid The course where the first instance of this block has been loaded in.
  * @param int $courseyear The start year of the course.
  */
 private function initialize_course($courseid, $courseyear)
 {
     $this->recommendator->select_students($courseid, $courseyear);
     $personalizable = course_filter::is_course_personalizable($courseid, $courseyear);
     if ($personalizable) {
         $this->db->insert_course_selection($courseid, $courseyear, 1);
     } else {
         $this->db->insert_course_selection($courseid, $courseyear, 0);
     }
 }
 /**
  * Given the course identificator, selects, randomly, 50% of the students enrolled in the course,
  * who will be the ones receiving the personalized recommendations.
  * "array_rand" function returns the randomly selected keys, not values, so, we have to construct
  * manually the array with random users.
  *
  * @param int $courseid The course to select students from.
  * @param int $year The year the given course belongs to.
  */
 public function select_students($courseid, $year)
 {
     $coursestudents = $this->db->get_students_from_course($courseid);
     $count = count($coursestudents);
     $selectedstudentsindexes = array_rand($coursestudents, $count / 2);
     $selectedstudents = array();
     foreach ($selectedstudentsindexes as $selectedindex) {
         $selectedstudent = $coursestudents[$selectedindex];
         array_push($selectedstudents, $selectedstudent);
     }
     $this->db->insert_selections($selectedstudents, $courseid, $year);
 }
 /**
  * Imports the log views defined in the csv file, iterating each row. This is made under the transaction initiated in
  * import_data function.
  *
  * @param object $logsfile Course csv file.
  * @param object $formdata Submitted form data, needed to load the csv.
  * @param int $courseid Generated course id in this transaction.
  * @param \block_mycourse_recommendations\database_helper $db Database handler object, passed as argument to instance it
  * again.
  */
 public static function import_logs($logsfile, $formdata, $courseid, $db)
 {
     $iid = \csv_import_reader::get_new_iid('logsfile');
     $csvreader = new \csv_import_reader($iid, 'logsfile');
     $csvreader->load_csv_content($logsfile, $formdata->encoding, $formdata->delimiter_name);
     $csvreader->init();
     $fields = $csvreader->get_columns();
     while ($fields) {
         $userid = $fields[0];
         $resourcename = $fields[1];
         $resourcetype = $fields[2];
         $resourceid = $fields[3];
         $views = $fields[4];
         $timecreated = $fields[5];
         $db->insert_historic_logs($userid, $courseid, $resourcename, $resourcetype, $resourceid, $views, $timecreated);
         self::$lastinsertedlogs++;
         $fields = $csvreader->next();
     }
     $csvreader->close();
 }
 /**
  * Determines if the course has had the minimum number of students in previous teachings.
  * First, looks into Moodle core tables for existing previous students. If it doesn't find any, it tries luck in
  * plugin's historic table. If it doesn't found neither here, means that the course has not previous students.
  *
  * @param int $courseid The course to determine if meets the minimum students.
  * @param int $currentyear The year of the given current course.
  * @param \block_mycourse_recommendations\database_helper $db The object with deals with database.
  * @return boolean If the given course has the minimum students or not.
  */
 public static function meets_minimum_previous_students($courseid, $currentyear, $db)
 {
     $previousstudents = $db->get_previous_courses_students_number_core_tables($courseid, $currentyear);
     $minimum = false;
     if ($previousstudents >= self::MINIMUM_PREVIOUS_STUDENTS) {
         $minimum = true;
     }
     if (!$minimum) {
         $previousstudents = $db->get_previous_courses_resources_number_historic_tables($courseid, $currentyear);
         if ($previousstudents >= self::MINIMUM_PREVIOUS_STUDENTS) {
             $minimum = true;
         }
     }
     return $minimum;
 }