initialize($configstr); } protected function initialize($configstr) { // First initialize with the defaults foreach(["accept_pending_as_submitted"] as $key){ $this->$key = boolval(get_config('local_treestudyplan', "bistate_{$key}")); } // Next, decode json $config = \json_decode($configstr,true); if(is_array($config)){ // copy all valid config settings to this item foreach(["accept_pending_as_submitted"] as $key){ if(array_key_exists($key,$config)){ $this->$key = boolval($config[$key]); } } } else { debug::msg("ARRAY is NOT CONFIG",""); } } // Return active configuration model public function config_string() { return json_encode([ "accept_pending_as_submitted" => $this->accept_pending_as_submitted, ]); } public function needSelectGradables(){ return False;} public function isDeprecated() { return self::DEPRECATED;} public function useRequiredGrades() { return True;} public function useItemConditions() { return False;} public function usecorecompletioninfo() { return True; } /** * Return course completion information based on the core completion infromation * Possible states: * completion::EXCELLENT - Completed with excellent results * completion::GOOD - Completed with good results * completion::COMPLETED - Completed * completion::PROGRESS - Started, but not completed yey * completion::FAILED - Failed * completion::INCOMPLETE - Not yet started * * @param mixed $courseinfo * @param mixed $studyitem * @param mixed $userid * @return void */ public function aggregate_course(courseinfo $courseinfo, studyitem $studyitem, $userid){ // Retrieve the core completion info from the core $course = $courseinfo->course(); $completion = new \completion_info($course); if ($completion->is_enabled() && $completion->is_tracked_user($userid)){ if($completion->is_course_complete($userid)){ // Now, the trick is to determine what constitutes excellent and good completion.... // TODO: Determine excellent and maybe good completion // Option: Use course end grade to determine that... // Probably needs a config value in the aggregator.... return completion::COMPLETED; } else { // Check if the course is over or not, if it is over, display failed // Else, return PROGRESS // Retrieve timing through courseinfo $timing = courseinfo::coursetiming($course); // Not met and time is passed, means FAILED if($timing == "past"){ return completion::FAILED; } else { // Check if any of the requirements are being met? $completions = $completion->get_completions($userid); foreach($completions as $c){ if($c->is_complete()){ // If so, return progress return completion::PROGRESS; } } return completion::INCOMPLETE; } } } else{ return completion::INCOMPLETE; } } public function aggregate_junction(array $completion, studyitem $studyitem = null, $userid = 0){ // Aggregate multiple incoming states into one junction or finish. // Possible states: // - completion::EXCELLENT - All incoming states are excellent // - completion::GOOD - All incoming states are at least good // - completion::COMPLETED - All incoming states are at least completed // - completion::FAILED - All incoming states are failed // - completion::INCOMPLETE - All incoming states are incomplete // - completion::PROGRESS - All other states // First count all states $statecount = completion::count_states($completion); $total = count($completion); if( $total == $statecount[completion::EXCELLENT]){ return completion::EXCELLENT; } else if ( $total == $statecount[completion::EXCELLENT] + $statecount[completion::GOOD]){ return completion::GOOD; } else if ( $total == $statecount[completion::EXCELLENT] + $statecount[completion::GOOD] + $statecount[completion::COMPLETED]){ return completion::COMPLETED; } else if( $statecount[completion::FAILED]){ return completion::FAILED; } else if( $total == $statecount[completion::INCOMPLETE]){ return completion::INCOMPLETE; } else { return completion::PROGRESS; } } // CORE COMPLETION DOESN'T REALLY USE THE FUNCTIONS BELOW // AGGREGATORS ARE GOING TO BE DEPRECATED ANYWAY... but used in legacy parts of this plugin. public function grade_completion(gradeinfo $gradeinfo, $userid) { global $DB; $table = "local_treestudyplan_gradecfg"; $gradeitem = $gradeinfo->getGradeitem(); $grade = $gradeitem->get_final($userid); if(empty($grade)){ return completion::INCOMPLETE; } else if($grade->finalgrade === NULL) { // on assignments, grade NULL means a submission has not yet been graded, // but on quizes this can also mean a quiz might have been started // Therefor, we treat a NULL result as a reason to check the relevant gradingscanner for presence of pending items // Since we want old results to be visible until a pending item was graded, we only use this state here. // Pending items are otherwise expressly indicated by the "pendingsubmission" field in the user model if($gradeinfo->getGradingscanner()->pending($userid)){ return completion::PENDING; } else { return completion::INCOMPLETE; } } else { $grade = $gradeitem->get_final($userid); // first determine if we have a grade_config for this scale or this maximum grade $finalgrade = $grade->finalgrade; $scale = $gradeinfo->getScale(); if( isset($scale)){ $gradecfg = $DB->get_record($table,["scale_id"=>$scale->id]); } else if($gradeitem->grademin == 0) { $gradecfg = $DB->get_record($table,["grade_points"=>$gradeitem->grademax]); } else { $gradecfg = null; } // for point grades, a provided grade pass overrides the defaults in the gradeconfig // for scales, the configuration in the gradeconfig is leading if($gradecfg && (isset($scale) || $gradeitem->gradepass == 0)) { // if so, we need to know if the grade is if($finalgrade >= $gradecfg->min_completed){ // return completed if completed return completion::COMPLETED; } else if($this->use_failed && $finalgrade < $gradecfg->min_progress) { // return failed if failed is enabled and the grade is less than the minimum grade for progress return completion::FAILED; } else { return completion::PROGRESS; } } else if($gradeitem->gradepass > 0) { $range = floatval($gradeitem->grademax - $gradeitem->grademin); // if no gradeconfig and gradepass is set, use that one to determine config. if($finalgrade >= $gradeitem->gradepass){ return completion::COMPLETED; } else if($this->use_failed && $gradeitem->gradepass >= 3 && $range >= 3 && $finalgrade == 1) { // return failed if failed is enabled and the grade is 1, while there are at leas 3 states. return completion::FAILED; } else { return completion::PROGRESS; } } else { // Blind assumptions if nothing is provided // over 55% of range is completed // if range >= 3 and failed is enabled, assume that this means failed $g = floatval($finalgrade - $gradeitem->grademin); $range = floatval($gradeitem->grademax - $gradeitem->grademin); $score = $g / $range; if($score > 0.55){ return completion::COMPLETED; } else if($this->use_failed && $range >= 3 && $finalgrade == 1) { // return failed if failed is enabled and the grade is 1, while there are at leas 3 states. return completion::FAILED; } else { return completion::PROGRESS; } } } } }