Better configurable backend for couse competency aggregation
This commit is contained in:
parent
54a8823bbd
commit
932587d2af
13 changed files with 302 additions and 85 deletions
2
amd/build/studyplan-editor-components.min.js
vendored
2
amd/build/studyplan-editor-components.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -3467,7 +3467,7 @@ export default {
|
||||||
return cgroup.completion?'completed':'incomplete';
|
return cgroup.completion?'completed':'incomplete';
|
||||||
},
|
},
|
||||||
|
|
||||||
pathtags(competency,use_idnumber=false) {
|
pathtags(competency) {
|
||||||
const path = competency.path;
|
const path = competency.path;
|
||||||
let s = "";
|
let s = "";
|
||||||
for (const ix in path) {
|
for (const ix in path) {
|
||||||
|
@ -3475,8 +3475,16 @@ export default {
|
||||||
if ( ix > 0) {
|
if ( ix > 0) {
|
||||||
s += " / ";
|
s += " / ";
|
||||||
}
|
}
|
||||||
s += `<a href="/admin/tool/lp/competencies.php?competencyid=${p.id}">${(use_idnumber)?p.idnumber:p.shortname}</a>`;
|
let url;
|
||||||
|
if (p.type =='competency') {
|
||||||
|
url = `/admin/tool/lp/competencies.php?competencyid=${p.id}`;
|
||||||
|
} else {
|
||||||
|
url = `/admin/tool/lp/competencies.php?competencyframeworkid=${p.id}&pagecontextid=${p.contextid}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s += `<a href="${url}">${p.title}</a>`;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
@ -3489,12 +3497,11 @@ export default {
|
||||||
</tr>
|
</tr>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<tr v-for='c in value.competencies'>
|
<tr v-for='c in value.competencies'>
|
||||||
<td><a href='#' v-b-modal="'modal-competency-id-'+c.id"><span v-html='c.shortname'></span></a></td>
|
<td><a href='#' v-b-modal="'modal-competency-id-'+c.id"><span v-html='c.title'></span></a></td>
|
||||||
<td v-if="c.description">
|
<td v-if="c.details">
|
||||||
<span v-html='c.description'></span>
|
<span v-html='c.details'></span>
|
||||||
</td>
|
</td>
|
||||||
<b-modal :id="'modal-competency-id-'+c.id"
|
<b-modal :id="'modal-competency-id-'+c.id"
|
||||||
:title="c.path.join(' / ')"
|
|
||||||
size="lg"
|
size="lg"
|
||||||
ok-only
|
ok-only
|
||||||
centered
|
centered
|
||||||
|
@ -3502,14 +3509,21 @@ export default {
|
||||||
>
|
>
|
||||||
<template #modal-header>
|
<template #modal-header>
|
||||||
<div>
|
<div>
|
||||||
<h1><i class="fa fa-certificate"></i>
|
<h1><i class="fa fa-puzzle-piece"></i>
|
||||||
<a :href="'/admin/tool/lp/competencies.php?competencyid='+c.id'" target="_blank"
|
<a :href="'/admin/tool/lp/competencies.php?competencyid='+c.id" target="_blank"
|
||||||
>{{c.shortname}}</a
|
>{{c.title}} {{c.details}} </a
|
||||||
></h1>
|
></h1>
|
||||||
<div>{{ pathtags(c) }}</div>
|
<div><span v-html="pathtags(c)"></span></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<span v-html='c.description'></span>
|
||||||
|
<table v-if="c.children">
|
||||||
|
<tr v-for="cc in c.children">
|
||||||
|
<td><span v-html='cc.displayfield'></span>
|
||||||
|
</td><td><span v-html='cc.description'></span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</b-modal>
|
</b-modal>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -226,10 +226,6 @@ class badgeinfo {
|
||||||
$badge['issuedlink'] = (new \moodle_url('/badges/badge.php', ['hash' => $issueinfo->uniquehash]))->out(false);
|
$badge['issuedlink'] = (new \moodle_url('/badges/badge.php', ['hash' => $issueinfo->uniquehash]))->out(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
$f = fopen("/tmp/badgedebug","a");
|
|
||||||
fputs($f,date("Y-m-d H:M:S")." Badge info\n");
|
|
||||||
fputs($f,print_r($badge,true)."\n\n");
|
|
||||||
fclose($f);
|
|
||||||
return $badge;
|
return $badge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,10 +528,6 @@ class badgeinfo {
|
||||||
if(isset($userid)) {
|
if(isset($userid)) {
|
||||||
$coursecompletion = new \completion_completion(["userid" => $userid, "course" => $course->id]);
|
$coursecompletion = new \completion_completion(["userid" => $userid, "course" => $course->id]);
|
||||||
$coursecompleted = $coursecompletion->is_complete();
|
$coursecompleted = $coursecompletion->is_complete();
|
||||||
$f = fopen("/tmp/debug","a+");
|
|
||||||
fputs($f,$course->fullname." ".($coursecompleted?"(COMPLETED)":"(NOT completed)")."\n");
|
|
||||||
fputs($f,print_r($coursecompletion,true));
|
|
||||||
fclose($f);
|
|
||||||
$subcrit["requirements"]["completion"]["completed"] = (bool) $coursecompleted;
|
$subcrit["requirements"]["completion"]["completed"] = (bool) $coursecompleted;
|
||||||
|
|
||||||
$check_grade = true;
|
$check_grade = true;
|
||||||
|
|
|
@ -30,6 +30,7 @@ require_once($CFG->dirroot.'/course/lib.php');
|
||||||
use core_competency\course_competency;
|
use core_competency\course_competency;
|
||||||
use core_competency\competency;
|
use core_competency\competency;
|
||||||
use core_competency\api as c_api;
|
use core_competency\api as c_api;
|
||||||
|
use core_competency\competency_rule_points;
|
||||||
use stdClass;
|
use stdClass;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,13 +70,15 @@ class coursecompetencyinfo {
|
||||||
public static function competencyinfo_structure($recurse=true) : \external_description {
|
public static function competencyinfo_structure($recurse=true) : \external_description {
|
||||||
$struct = [
|
$struct = [
|
||||||
"id" => new \external_value(PARAM_INT, 'competency id'),
|
"id" => new \external_value(PARAM_INT, 'competency id'),
|
||||||
"shortname" => new \external_value(PARAM_RAW, 'competency short name'),
|
"title" => new \external_value(PARAM_RAW, 'competency display title'),
|
||||||
"idnumber" => new \external_value(PARAM_TEXT, 'competency ID number'),
|
"details" => new \external_value(PARAM_RAW, 'competency details'),
|
||||||
"description" => new \external_value(PARAM_RAW, 'competency description'),
|
"description" => new \external_value(PARAM_RAW, 'competency description'),
|
||||||
|
"ruleoutcome" => new \external_value(PARAM_TEXT, 'competency rule outcome text', VALUE_OPTIONAL),
|
||||||
|
"rule" => new \external_value(PARAM_RAW, 'competency rule description', VALUE_OPTIONAL),
|
||||||
"path" => new \external_multiple_structure(new \external_single_structure([
|
"path" => new \external_multiple_structure(new \external_single_structure([
|
||||||
"id" => new \external_value(PARAM_INT),
|
"id" => new \external_value(PARAM_INT),
|
||||||
"shortname" => new \external_value(PARAM_RAW),
|
"title" => new \external_value(PARAM_RAW),
|
||||||
"idnumber" => new \external_value(PARAM_TEXT),
|
"type" => new \external_value(PARAM_TEXT),
|
||||||
]), 'competency path'),
|
]), 'competency path'),
|
||||||
"grade" => new \external_value(PARAM_TEXT, 'competency grade', VALUE_OPTIONAL),
|
"grade" => new \external_value(PARAM_TEXT, 'competency grade', VALUE_OPTIONAL),
|
||||||
"coursegrade" => new \external_value(PARAM_TEXT, 'course competency grade', VALUE_OPTIONAL),
|
"coursegrade" => new \external_value(PARAM_TEXT, 'course competency grade', VALUE_OPTIONAL),
|
||||||
|
@ -84,6 +87,8 @@ class coursecompetencyinfo {
|
||||||
"nproficient" => new \external_value(PARAM_INT, 'number of students with proficiency',VALUE_OPTIONAL),
|
"nproficient" => new \external_value(PARAM_INT, 'number of students with proficiency',VALUE_OPTIONAL),
|
||||||
"ncourseproficient" => new \external_value(PARAM_INT, 'number of students with course proficiency',VALUE_OPTIONAL),
|
"ncourseproficient" => new \external_value(PARAM_INT, 'number of students with course proficiency',VALUE_OPTIONAL),
|
||||||
"count" => new \external_value(PARAM_INT, 'number of students in stats',VALUE_OPTIONAL),
|
"count" => new \external_value(PARAM_INT, 'number of students in stats',VALUE_OPTIONAL),
|
||||||
|
"required" => new \external_value(PARAM_BOOL, 'if required in parent competency rule',VALUE_OPTIONAL),
|
||||||
|
"points" => new \external_value(PARAM_INT, 'number of points in parent competency rule',VALUE_OPTIONAL),
|
||||||
];
|
];
|
||||||
if($recurse) {
|
if($recurse) {
|
||||||
$struct["children"] = new \external_multiple_structure(self::competencyinfo_structure(false),'child competencies',VALUE_OPTIONAL);
|
$struct["children"] = new \external_multiple_structure(self::competencyinfo_structure(false),'child competencies',VALUE_OPTIONAL);
|
||||||
|
@ -120,27 +125,54 @@ class coursecompetencyinfo {
|
||||||
* @param Object $competency
|
* @param Object $competency
|
||||||
*/
|
*/
|
||||||
private function competencyinfo_model($competency) : array {
|
private function competencyinfo_model($competency) : array {
|
||||||
|
$displayfield = get_config("local_treestudyplan","competency_displayname");
|
||||||
|
$detailfield = get_config("local_treestudyplan","competency_detailfield");
|
||||||
|
$headingfield = ($displayfield != 'description')?$displayfield:"shortname";
|
||||||
|
$framework = $competency->get_framework();
|
||||||
|
|
||||||
$path = [];
|
$heading = $framework->get($headingfield);
|
||||||
|
if(empty(trim($heading))) {
|
||||||
|
$heading = $framework->get('shortname'); // Fall back to shortname if heading field is empty
|
||||||
|
}
|
||||||
|
$path = [[
|
||||||
|
'id' => $framework->get('id'),
|
||||||
|
'title' => $heading,
|
||||||
|
'contextid' => $framework->get('contextid'),
|
||||||
|
'type' => 'framework',
|
||||||
|
]];
|
||||||
foreach ($competency->get_ancestors() as $c) {
|
foreach ($competency->get_ancestors() as $c) {
|
||||||
$competencypath[] = $c->get('shortname');
|
$competencypath[] = $c->get('shortname');
|
||||||
|
$heading = $c->get($headingfield);
|
||||||
|
if(empty(trim($heading))) {
|
||||||
|
$heading = $c->get('shortname'); // Fall back to shortname if heading field is empty
|
||||||
|
}
|
||||||
$path[] = [
|
$path[] = [
|
||||||
'id' => $c->get('id'),
|
'id' => $c->get('id'),
|
||||||
'shortname' => $c->get('shortname'),
|
'title' => $heading,
|
||||||
'idnumber' => $c->get('idnumber'),
|
'contextid' => $framework->get('contextid'),
|
||||||
|
'type' => 'competency',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$heading = $competency->get($headingfield);
|
||||||
|
if(empty(trim($heading))) {
|
||||||
|
$heading = $competency->get('shortname'); // Fall back to shortname if heading field is empty
|
||||||
|
}
|
||||||
$path[] = [
|
$path[] = [
|
||||||
'id' => $competency->get('id'),
|
'id' => $competency->get('id'),
|
||||||
'shortname' => $competency->get('shortname'),
|
'title' => $heading,
|
||||||
'idnumber' => $competency->get('idnumber'),
|
'contextid' => $framework->get('contextid'),
|
||||||
|
'type' => 'competency',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
$title = $competency->get($displayfield);
|
||||||
|
if(empty(trim($title))) {
|
||||||
|
$title = $competency->get('shortname'); // Fall back to shortname if heading field is empty
|
||||||
|
}
|
||||||
$model = [
|
$model = [
|
||||||
'id' => $competency->get('id'),
|
'id' => $competency->get('id'),
|
||||||
'shortname' => $competency->get('shortname'),
|
'title' => $title,
|
||||||
'idnumber' => $competency->get('idnumber'),
|
'details' => $competency->get($detailfield),
|
||||||
'description' => $competency->get('description'),
|
'description' => $competency->get('description'),
|
||||||
'path' => $path,
|
'path' => $path,
|
||||||
];
|
];
|
||||||
|
@ -162,16 +194,50 @@ class coursecompetencyinfo {
|
||||||
$ncourseproficient = 0;
|
$ncourseproficient = 0;
|
||||||
|
|
||||||
foreach($coursecompetencies as $c) {
|
foreach($coursecompetencies as $c) {
|
||||||
|
if(!empty($studentslist)){
|
||||||
$stats = $this->proficiency_stats($c,$studentlist);
|
$stats = $this->proficiency_stats($c,$studentlist);
|
||||||
$count += $stats->count;
|
$count += $stats->count;
|
||||||
$nproficient += $stats->nproficient;
|
$nproficient += $stats->nproficient;
|
||||||
$ncourseproficient += $stats->ncourseproficient;
|
$ncourseproficient += $stats->ncourseproficient;
|
||||||
|
}
|
||||||
$ci = $this->competencyinfo_model($c);
|
$ci = $this->competencyinfo_model($c);
|
||||||
// Copy proficiency stats to model.
|
// Copy proficiency stats to model.
|
||||||
foreach ((array)$stats as $key => $value) {
|
foreach ((array)$stats as $key => $value) {
|
||||||
$ci[$key] = $value;
|
$ci[$key] = $value;
|
||||||
}
|
}
|
||||||
|
$ci['required'] = $this->is_required($c);
|
||||||
|
|
||||||
|
|
||||||
|
$rule = $c->get_rule_object();
|
||||||
|
$ruleoutcome = $c->get('ruleoutcome');
|
||||||
|
if($rule && $ruleoutcome != competency::OUTCOME_NONE) {
|
||||||
|
$ruletext = $rule->get_name();
|
||||||
|
$ruleconfig = $c->get('ruleconfig');
|
||||||
|
|
||||||
|
if ($ruleoutcome == competency::OUTCOME_EVIDENCE) {
|
||||||
|
$outcometag = "evidence";
|
||||||
|
} else if ($ruleoutcome == competency::OUTCOME_COMPLETE) {
|
||||||
|
$outcometag = "complete";
|
||||||
|
} else if ($ruleoutcome == competency::OUTCOME_RECOMMEND) {
|
||||||
|
$outcometag = "recommend";
|
||||||
|
} else {
|
||||||
|
$outcometag = "none";
|
||||||
|
}
|
||||||
|
$model["ruleoutcome"] = get_string("coursemodulecompetencyoutcome_{$outcometag}","core_competency");
|
||||||
|
|
||||||
|
if ($rule instanceof competency_rule_points) {
|
||||||
|
$ruleconfig = json_decode($ruleconfig);
|
||||||
|
$points = $ruleconfig->base->points;
|
||||||
|
|
||||||
|
// Make a nice map of the competency rule config
|
||||||
|
$crlist = [];
|
||||||
|
foreach($ruleconfig->competencies as $cr){
|
||||||
|
$crlist[$cr->id] = $cr;
|
||||||
|
}
|
||||||
|
$model["rule"] = $ruletext . " ({$points} ".get_string("points","core_grades").")";
|
||||||
|
} else {
|
||||||
|
$model["rule"] = $ruletext;
|
||||||
|
}
|
||||||
|
|
||||||
// get one level of children
|
// get one level of children
|
||||||
$dids = competency::get_descendants_ids($c);
|
$dids = competency::get_descendants_ids($c);
|
||||||
|
@ -180,19 +246,28 @@ class coursecompetencyinfo {
|
||||||
foreach($dids as $did) {
|
foreach($dids as $did) {
|
||||||
$cc = new competency($did);
|
$cc = new competency($did);
|
||||||
$cci = $this->competencyinfo_model($cc);
|
$cci = $this->competencyinfo_model($cc);
|
||||||
|
if($rule instanceof competency_rule_points) {
|
||||||
|
if(array_key_exists($did,$crlist)) {
|
||||||
|
$cr = $crlist[$did];
|
||||||
|
$cci["points"] = (int) $cr->points;
|
||||||
|
$cci["required"] = (int) $cr->required;
|
||||||
|
}
|
||||||
|
}
|
||||||
$children[] = $cci;
|
$children[] = $cci;
|
||||||
}
|
}
|
||||||
|
|
||||||
$ci["children"] = $children;
|
$ci["children"] = $children;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
$cis[] = $ci;
|
$cis[] = $ci;
|
||||||
}
|
}
|
||||||
$info = [
|
$info = [
|
||||||
"competencies" => $cis,
|
"competencies" => $cis,
|
||||||
"fproficient" => (float)($nproficient)/(float)($count),
|
|
||||||
"fcourseproficient" => (float)($ncourseproficient)/(float)($count),
|
|
||||||
];
|
];
|
||||||
|
if(!empty($studentslist)){
|
||||||
|
$info["fproficient"] = (float)($nproficient)/(float)($count);
|
||||||
|
$info["fcourseproficient"] = (float)($ncourseproficient)/(float)($count);
|
||||||
|
}
|
||||||
return $info;
|
return $info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,6 +293,35 @@ class coursecompetencyinfo {
|
||||||
$progress += 1;
|
$progress += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$rule = $c->get_rule_object();
|
||||||
|
$ruleoutcome = $c->get('ruleoutcome');
|
||||||
|
if($rule && $ruleoutcome != competency::OUTCOME_NONE) {
|
||||||
|
$ruletext = $rule->get_name();
|
||||||
|
$ruleconfig = $c->get('ruleconfig');
|
||||||
|
|
||||||
|
if ($ruleoutcome == competency::OUTCOME_EVIDENCE) {
|
||||||
|
$outcometag = "evidence";
|
||||||
|
} else if ($ruleoutcome == competency::OUTCOME_COMPLETE) {
|
||||||
|
$outcometag = "complete";
|
||||||
|
} else if ($ruleoutcome == competency::OUTCOME_RECOMMEND) {
|
||||||
|
$outcometag = "recommend";
|
||||||
|
} else {
|
||||||
|
$outcometag = "none";
|
||||||
|
}
|
||||||
|
$model["ruleoutcome"] = get_string("coursemodulecompetencyoutcome_{$outcometag}","core_competency");
|
||||||
|
|
||||||
|
if ($rule instanceof competency_rule_points) {
|
||||||
|
$ruleconfig = json_decode($ruleconfig);
|
||||||
|
$pointsreq = $ruleconfig->base->points;
|
||||||
|
$points = 0;
|
||||||
|
// Make a nice map of the competency rule config
|
||||||
|
$crlist = [];
|
||||||
|
foreach($ruleconfig->competencies as $cr){
|
||||||
|
$crlist[$cr->id] = $cr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// get one level of children
|
// get one level of children
|
||||||
$dids = competency::get_descendants_ids($c);
|
$dids = competency::get_descendants_ids($c);
|
||||||
if(count($dids) > 0) {
|
if(count($dids) > 0) {
|
||||||
|
@ -225,17 +329,35 @@ class coursecompetencyinfo {
|
||||||
foreach($dids as $did) {
|
foreach($dids as $did) {
|
||||||
$cc = new competency($did);
|
$cc = new competency($did);
|
||||||
$cci = $this->competencyinfo_model($cc);
|
$cci = $this->competencyinfo_model($cc);
|
||||||
$cp = $this->proficiency($cc,$userid);
|
if($rule instanceof competency_rule_points) {
|
||||||
|
$cp = $p = $this->proficiency($cc,$userid);
|
||||||
// Copy proficiency info to model.
|
// Copy proficiency info to model.
|
||||||
foreach ((array)$cp as $key => $value) {
|
foreach ((array)$cp as $key => $value) {
|
||||||
$cci[$key] = $value;
|
$cci[$key] = $value;
|
||||||
}
|
}
|
||||||
|
if(array_key_exists($did,$crlist)) {
|
||||||
|
$cr = $crlist[$did];
|
||||||
|
$cci["points"] = (int) $cr->points;
|
||||||
|
$cci["required"] = (int) $cr->required;
|
||||||
|
if($cp->proficient) {
|
||||||
|
$points += (int) $cr->points;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
$children[] = $cci;
|
$children[] = $cci;
|
||||||
}
|
}
|
||||||
|
|
||||||
$ci["children"] = $children;
|
$ci["children"] = $children;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($rule instanceof competency_rule_points) {
|
||||||
|
$model["rule"] = $ruletext . " ({$points} / {$pointsreq} ".get_string("points","core_grades").")";
|
||||||
|
} else {
|
||||||
|
$model["rule"] = $ruletext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
$cis[] = $ci;
|
$cis[] = $ci;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,4 +421,63 @@ class coursecompetencyinfo {
|
||||||
$r->coursegrade = $scale->get_nearest_item($ucc->get('grade'));
|
$r->coursegrade = $scale->get_nearest_item($ucc->get('grade'));
|
||||||
return $r;
|
return $r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Webservice executor to mark competency as required
|
||||||
|
* @param int $competencyid ID of the competency
|
||||||
|
* @param int $itemid ID of the study item
|
||||||
|
* @param bool $required Mark competency as required or not
|
||||||
|
* @return success Always returns successful success object
|
||||||
|
*/
|
||||||
|
public static function require_competency(int $competencyid, int $itemid, bool $required) {
|
||||||
|
global $DB;
|
||||||
|
$item = studyitem::find_by_id($itemid);
|
||||||
|
// Make sure conditions are properly configured;
|
||||||
|
$conditions = [];
|
||||||
|
try {
|
||||||
|
$conditions = json_decode($item->conditions(),true);
|
||||||
|
} catch (\Exception $x) {}
|
||||||
|
|
||||||
|
// Make sure the competencied field exists
|
||||||
|
if (!isset($conditions["competencies"]) || !is_array($conditions["competencies"])) {
|
||||||
|
$conditions["competencies"] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure a record exits.
|
||||||
|
if (!array_key_exists($competencyid,$conditions["competencies"])){
|
||||||
|
$conditions["competencies"][$competencyid] = [
|
||||||
|
"required" => boolval($required),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$conditions["competencies"][$competencyid]["required"] = boolval($required);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store conditions;
|
||||||
|
$item->edit(["conditions" => json_encode($conditions)]);
|
||||||
|
return success::success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this gradable item is marked required in the studyitem
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function is_required($competency) {
|
||||||
|
if ($this->studyitem) {
|
||||||
|
$conditions = [];
|
||||||
|
try {
|
||||||
|
$conditions = json_decode($this->studyitem->conditions(),true);
|
||||||
|
} catch (\Exception $x) {}
|
||||||
|
|
||||||
|
// Make sure the competencied field exists
|
||||||
|
if ( isset($conditions["competencies"])
|
||||||
|
&& is_array($conditions["competencies"])
|
||||||
|
&& isset($conditions["competencies"][$competency->get("id")])
|
||||||
|
&& isset($conditions["competencies"][$competency->get("id")]["required"])
|
||||||
|
) {
|
||||||
|
return boolval($conditions["competencies"][$competency->get("id")]["required"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,6 +173,8 @@ class competency_aggregator extends \local_treestudyplan\aggregator {
|
||||||
$count = 0;
|
$count = 0;
|
||||||
$courseproficient = 0;
|
$courseproficient = 0;
|
||||||
$proficient = 0;
|
$proficient = 0;
|
||||||
|
$requiredmet = 0;
|
||||||
|
$requiredcount = 0;
|
||||||
foreach ($competencies as $c) {
|
foreach ($competencies as $c) {
|
||||||
$count += 1;
|
$count += 1;
|
||||||
$p = $cci->proficiency($c,$userid);
|
$p = $cci->proficiency($c,$userid);
|
||||||
|
@ -182,19 +184,26 @@ class competency_aggregator extends \local_treestudyplan\aggregator {
|
||||||
if ($p->courseproficient) {
|
if ($p->courseproficient) {
|
||||||
$courseproficient += 1;
|
$courseproficient += 1;
|
||||||
}
|
}
|
||||||
|
if ($cci->is_required(($c))){
|
||||||
|
$requiredcount += 1;
|
||||||
|
if ($p->proficient) {
|
||||||
|
$requiredmet += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine minimum for
|
// Determine minimum for
|
||||||
$limit = $this->cfg()->thresh_completed * $count;
|
$limit = $this->cfg()->thresh_completed * $count;
|
||||||
$coursefinished = ($course->enddate) ? ($course->enddate < time()) : false;
|
$coursefinished = ($course->enddate) ? ($course->enddate < time()) : false;
|
||||||
|
|
||||||
if ($courseproficient >= $count) {
|
if ($courseproficient >= $count && $requiredmet >= $requiredcount) {
|
||||||
if ($limit < $count) {
|
if ($limit < $count) {
|
||||||
return completion::EXCELLENT;
|
return completion::EXCELLENT;
|
||||||
} else {
|
} else {
|
||||||
return completion::COMPLETED;
|
return completion::COMPLETED;
|
||||||
}
|
}
|
||||||
} else if ($courseproficient > $limit) {
|
} else if ($courseproficient > $limit && $requiredmet >= $requiredcount) {
|
||||||
return completion::COMPLETED;
|
return completion::COMPLETED;
|
||||||
} else if ($courseproficient > 0) {
|
} else if ($courseproficient > 0) {
|
||||||
if ( $this->cfg()->use_failed && $coursefinished) {
|
if ( $this->cfg()->use_failed && $coursefinished) {
|
||||||
|
|
|
@ -132,10 +132,8 @@ class tristate_aggregator extends \local_treestudyplan\aggregator {
|
||||||
* @return int Aggregated completion as completion class constant
|
* @return int Aggregated completion as completion class constant
|
||||||
*/
|
*/
|
||||||
public function aggregate_course(courseinfo $courseinfo, studyitem $studyitem, $userid) {
|
public function aggregate_course(courseinfo $courseinfo, studyitem $studyitem, $userid) {
|
||||||
$condition = $studyitem->conditions();
|
|
||||||
if (empty($condition)) {
|
|
||||||
$condition = self::DEFAULT_CONDITION;
|
$condition = self::DEFAULT_CONDITION;
|
||||||
}
|
|
||||||
$list = [];
|
$list = [];
|
||||||
foreach (gradeinfo::list_studyitem_gradables($studyitem) as $gi) {
|
foreach (gradeinfo::list_studyitem_gradables($studyitem) as $gi) {
|
||||||
$list[] = $this->grade_completion($gi, $userid);
|
$list[] = $this->grade_completion($gi, $userid);
|
||||||
|
|
|
@ -84,8 +84,12 @@ class studyitem {
|
||||||
* Return the condition string for this item
|
* Return the condition string for this item
|
||||||
*/
|
*/
|
||||||
public function conditions() : string {
|
public function conditions() : string {
|
||||||
|
if($this->r->type == self::COURSE) {
|
||||||
|
return (!empty($this->r->conditions)) ? $this->r->conditions : "";
|
||||||
|
} else {
|
||||||
return (!empty($this->r->conditions)) ? $this->r->conditions : "ALL";
|
return (!empty($this->r->conditions)) ? $this->r->conditions : "ALL";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find record in database and return management object
|
* Find record in database and return management object
|
||||||
|
|
|
@ -288,6 +288,10 @@ $string["settingdesc_bistate_thresh_progress"] = 'Minimum percentage of outcomes
|
||||||
$string["setting_bistate_accept_pending_submitted"] = 'Accept submitted but ungraded result as "progress"';
|
$string["setting_bistate_accept_pending_submitted"] = 'Accept submitted but ungraded result as "progress"';
|
||||||
$string["settingdesc_bistate_accept_pending_submitted"] = 'If enabled, submitted but ungraded outcomes will still count toward progress. If disabled, only graded outcomes will count';
|
$string["settingdesc_bistate_accept_pending_submitted"] = 'If enabled, submitted but ungraded outcomes will still count toward progress. If disabled, only graded outcomes will count';
|
||||||
|
|
||||||
|
$string["setting_competency_displayname"] = 'Competency display title';
|
||||||
|
$string["settingdesc_competency_displayname"] = 'The competency field used as it\'s title in the studyplan';
|
||||||
|
$string["setting_competency_detailfield"] = 'Competency detail field';
|
||||||
|
$string["settingdesc_competency_detailfield"] = 'The competency field used for competency details';
|
||||||
$string["setting_competency_heading"] = 'Defults for course competencies ';
|
$string["setting_competency_heading"] = 'Defults for course competencies ';
|
||||||
$string["settingdesc_competency_heading"] = 'Set the defaults for this aggregation method';
|
$string["settingdesc_competency_heading"] = 'Set the defaults for this aggregation method';
|
||||||
$string["setting_competency_thresh_completed"] = 'Threshold for good (%)';
|
$string["setting_competency_thresh_completed"] = 'Threshold for good (%)';
|
||||||
|
|
|
@ -287,6 +287,10 @@ $string["settingdesc_bistate_thresh_progress"] = 'Minimumpercentage van doelen d
|
||||||
$string["setting_bistate_accept_pending_submitted"] = 'Accepteer nog niet beoordeelde doelen als "in ontwikkeling"';
|
$string["setting_bistate_accept_pending_submitted"] = 'Accepteer nog niet beoordeelde doelen als "in ontwikkeling"';
|
||||||
$string["settingdesc_bistate_accept_pending_submitted"] = 'Neem leerdoelen waarbij bewijs is ingeleverd, maar wat nog niet is beoordeeld mee als "in ontwikkeling", zolang er nog geen beoordeling is';
|
$string["settingdesc_bistate_accept_pending_submitted"] = 'Neem leerdoelen waarbij bewijs is ingeleverd, maar wat nog niet is beoordeeld mee als "in ontwikkeling", zolang er nog geen beoordeling is';
|
||||||
|
|
||||||
|
$string["setting_competency_displayname"] = 'Weergavetitel competentie';
|
||||||
|
$string["settingdesc_competency_displayname"] = 'Veld dat wordt gebruikt als titel voor een competentie';
|
||||||
|
$string["setting_competency_detailfield"] = 'Detailinfo competentie';
|
||||||
|
$string["settingdesc_competency_detailfield"] = 'Veld dat wordt gebruikt voor korte competentie details. ';
|
||||||
$string["setting_competency_heading"] = 'Standaardwaarden voor cursuscompetenties ';
|
$string["setting_competency_heading"] = 'Standaardwaarden voor cursuscompetenties ';
|
||||||
$string["settingdesc_competency_heading"] = 'Stel de standaardwaarden in voor deze verzamelmethode';
|
$string["settingdesc_competency_heading"] = 'Stel de standaardwaarden in voor deze verzamelmethode';
|
||||||
$string["setting_competency_thresh_completed"] = 'Drempelwaarde voor voltooid (%)';
|
$string["setting_competency_thresh_completed"] = 'Drempelwaarde voor voltooid (%)';
|
||||||
|
|
9
lib.php
9
lib.php
|
@ -405,15 +405,6 @@ function local_treestudyplan_pluginfile(
|
||||||
): bool {
|
): bool {
|
||||||
global $DB,$USER;
|
global $DB,$USER;
|
||||||
|
|
||||||
$fp = fopen("/tmp/debug","a+");
|
|
||||||
fputs($fp, print_r([
|
|
||||||
'context' => $context,
|
|
||||||
'filearea' => $filearea,
|
|
||||||
'args' => $args,
|
|
||||||
'forcedownload' => $forcedownload,
|
|
||||||
'options' => $options,
|
|
||||||
],true)."\n\n");
|
|
||||||
fclose($fp);
|
|
||||||
|
|
||||||
$studyplan_filecaps = ["local/treestudyplan:editstudyplan","local/treestudyplan:viewuserreports"];
|
$studyplan_filecaps = ["local/treestudyplan:editstudyplan","local/treestudyplan:viewuserreports"];
|
||||||
|
|
||||||
|
|
22
settings.php
22
settings.php
|
@ -107,7 +107,27 @@ if ($hassiteconfig) {
|
||||||
$displayfields
|
$displayfields
|
||||||
));
|
));
|
||||||
|
|
||||||
// BISTATE AGGREGATON DEFAULTS.
|
// COMPETENCY AGGREGATON DEFAULTS.
|
||||||
|
|
||||||
|
$page->add(new admin_setting_configselect('local_treestudyplan/competency_displayname',
|
||||||
|
get_string('setting_competency_displayname', 'local_treestudyplan'),
|
||||||
|
get_string('settingdesc_competency_displayname', 'local_treestudyplan'),
|
||||||
|
"idnumber",
|
||||||
|
["shortname" => get_string("name","core",),
|
||||||
|
"idnumber" => get_string("idnumber","core",),
|
||||||
|
"description" => get_string("description","core",)]
|
||||||
|
));
|
||||||
|
|
||||||
|
$page->add(new admin_setting_configselect('local_treestudyplan/competency_detailfield',
|
||||||
|
get_string('setting_competency_detailfield', 'local_treestudyplan'),
|
||||||
|
get_string('settingdesc_competency_detailfield', 'local_treestudyplan'),
|
||||||
|
"shortname",
|
||||||
|
["" => get_string("none","core",),
|
||||||
|
"shortname" => get_string("name","core",),
|
||||||
|
"idnumber" => get_string("idnumber","core",),
|
||||||
|
"description" => get_string("description","core",)]
|
||||||
|
));
|
||||||
|
|
||||||
$page->add(new admin_setting_heading('local_treestudyplan/competency_aggregation_heading',
|
$page->add(new admin_setting_heading('local_treestudyplan/competency_aggregation_heading',
|
||||||
get_string('setting_competency_heading', 'local_treestudyplan'),
|
get_string('setting_competency_heading', 'local_treestudyplan'),
|
||||||
get_string('settingdesc_competency_heading', 'local_treestudyplan')
|
get_string('settingdesc_competency_heading', 'local_treestudyplan')
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
defined('MOODLE_INTERNAL') || die();
|
defined('MOODLE_INTERNAL') || die();
|
||||||
|
|
||||||
$plugin->component = 'local_treestudyplan'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494).
|
$plugin->component = 'local_treestudyplan'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494).
|
||||||
$plugin->version = 2023111700; // YYYYMMDDHH (year, month, day, iteration).
|
$plugin->version = 2023112301; // YYYYMMDDHH (year, month, day, iteration).
|
||||||
$plugin->requires = 2021051700; // YYYYMMDDHH (This is the release version for Moodle 3.11).
|
$plugin->requires = 2021051700; // YYYYMMDDHH (This is the release version for Moodle 3.11).
|
||||||
|
|
||||||
$plugin->release = "1.1.0-b";
|
$plugin->release = "1.1.0-b";
|
||||||
|
|
Loading…
Reference in a new issue