diff --git a/mod/workshop/eval/best/lang/en/workshopeval_best.php b/mod/workshop/eval/best/lang/en/workshopeval_best.php index 7e0b63ca139..6af9f37dbaf 100644 --- a/mod/workshop/eval/best/lang/en/workshopeval_best.php +++ b/mod/workshop/eval/best/lang/en/workshopeval_best.php @@ -33,4 +33,3 @@ $string['comparisonlevel7'] = 'lax'; $string['comparisonlevel9'] = 'very lax'; $string['configcomparison'] = 'Default value of the factor that influence the grading evaluation.'; $string['pluginname'] = 'Comparison with the best assessment'; -$string['settings'] = 'Grading evaluation settings'; diff --git a/mod/workshop/eval/best/lib.php b/mod/workshop/eval/best/lib.php index 0857396756c..546b0e21cc9 100644 --- a/mod/workshop/eval/best/lib.php +++ b/mod/workshop/eval/best/lib.php @@ -33,7 +33,7 @@ require_once($CFG->libdir . '/gradelib.php'); /** * Defines the computation login of the grading evaluation subplugin */ -class workshop_best_evaluation implements workshop_evaluation { +class workshop_best_evaluation extends workshop_evaluation { /** @var workshop the parent workshop instance */ protected $workshop; @@ -67,7 +67,7 @@ class workshop_best_evaluation implements workshop_evaluation { public function update_grading_grades(stdclass $settings, $restrict=null) { global $DB; - // remember the recently used settings for this workshop + // Remember the recently used settings for this workshop. if (empty($this->settings)) { $record = new stdclass(); $record->workshopid = $this->workshop->id; @@ -78,7 +78,7 @@ class workshop_best_evaluation implements workshop_evaluation { array('workshopid' => $this->workshop->id)); } - // get the grading strategy instance + // Get the grading strategy instance. $grader = $this->workshop->grading_strategy_instance(); // get the information about the assessment dimensions @@ -109,14 +109,11 @@ class workshop_best_evaluation implements workshop_evaluation { } /** - * TODO: short description. + * Returns an instance of the form to provide evaluation settings. * - * @return TODO + * @return workshop_best_evaluation_settings_form */ public function get_settings_form(moodle_url $actionurl=null) { - global $CFG; // needed because the included files use it - global $DB; - require_once(dirname(__FILE__) . '/settings_form.php'); $customdata['workshop'] = $this->workshop; $customdata['current'] = $this->settings; @@ -403,3 +400,30 @@ class workshop_best_evaluation implements workshop_evaluation { } } } + + +/** + * Represents the settings form for this plugin. + */ +class workshop_best_evaluation_settings_form extends workshop_evaluation_settings_form { + + /** + * Defines specific fields for this evaluation method. + */ + protected function definition_sub() { + $mform = $this->_form; + + $plugindefaults = get_config('workshopeval_best'); + $current = $this->_customdata['current']; + + $options = array(); + for ($i = 9; $i >= 1; $i = $i-2) { + $options[$i] = get_string('comparisonlevel' . $i, 'workshopeval_best'); + } + $mform->addElement('select', 'comparison', get_string('comparison', 'workshopeval_best'), $options); + $mform->addHelpButton('comparison', 'comparison', 'workshopeval_best'); + $mform->setDefault('comparison', $plugindefaults->comparison); + + $this->set_data($current); + } +} diff --git a/mod/workshop/eval/best/settings_form.php b/mod/workshop/eval/best/settings_form.php deleted file mode 100644 index 9352ef1c7db..00000000000 --- a/mod/workshop/eval/best/settings_form.php +++ /dev/null @@ -1,59 +0,0 @@ -. - -/** - * Best evaluation settings form - * - * @package workshopeval - * @subpackage best - * @copyright 2009 David Mudrak - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -require_once($CFG->dirroot . '/lib/formslib.php'); - -class workshop_best_evaluation_settings_form extends moodleform { - - function definition() { - $mform = $this->_form; - - $plugindefaults = get_config('workshopeval_best'); - $current = $this->_customdata['current']; - $workshop = $this->_customdata['workshop']; - - $mform->addElement('header', 'general', get_string('settings', 'workshopeval_best')); - - $label = get_string('evaluationmethod', 'workshop'); - $mform->addElement('static', 'methodname', $label, get_string('pluginname', 'workshopeval_best')); - $mform->addHelpButton('methodname', 'evaluationmethod', 'workshop'); - - $options = array(); - for ($i = 9; $i >= 1; $i = $i-2) { - $options[$i] = get_string('comparisonlevel' . $i, 'workshopeval_best'); - } - $label = get_string('comparison', 'workshopeval_best'); - $mform->addElement('select', 'comparison', $label, $options); - $mform->addHelpButton('comparison', 'comparison', 'workshopeval_best'); - $mform->setDefault('comparison', $plugindefaults->comparison); - - $mform->addElement('submit', 'submit', get_string('aggregategrades', 'workshop')); - - $this->set_data($current); - } -} diff --git a/mod/workshop/eval/lib.php b/mod/workshop/eval/lib.php index bfec05f945d..82eeafbcedb 100644 --- a/mod/workshop/eval/lib.php +++ b/mod/workshop/eval/lib.php @@ -26,12 +26,37 @@ defined('MOODLE_INTERNAL') || die(); +require_once($CFG->dirroot . '/lib/formslib.php'); + /** - * Defines all methods that grading evaluation subplugins has to implement - * - * @todo the final interface is not decided yet as we have only one implementation so far + * Base class for all grading evaluation subplugins. */ -interface workshop_evaluation { +abstract class workshop_evaluation { + + /** + * Calculates grades for assessment and updates 'gradinggrade' fields in 'workshop_assessments' table + * + * @param stdClass $settings settings for this round of evaluation + * @param null|int|array $restrict if null, update all reviewers, otherwise update just grades for the given reviewers(s) + */ + abstract public function update_grading_grades(stdClass $settings, $restrict=null); + + /** + * Returns an instance of the form to provide evaluation settings. + * + * This is called by view.php (to display) and aggregate.php (to process and dispatch). + * It returns the basic form with just the submit button by default. Evaluators may + * extend or overwrite the default form to include some custom settings. + * + * @return workshop_evaluation_settings_form + */ + public function get_settings_form(moodle_url $actionurl=null) { + + $customdata = array('workshop' => $this->workshop); + $attributes = array('class' => 'evalsettingsform'); + + return new workshop_evaluation_settings_form($actionurl, $customdata, 'post', '', $attributes); + } /** * Delete all data related to a given workshop module instance @@ -41,5 +66,35 @@ interface workshop_evaluation { * @param int $workshopid id of the workshop module instance being deleted * @return void */ - public static function delete_instance($workshopid); + public static function delete_instance($workshopid) { + + } +} + + +/** + * Base form to hold eventual evaluation settings. + */ +class workshop_evaluation_settings_form extends moodleform { + + /** + * Defines the common form fields. + */ + public function definition() { + $mform = $this->_form; + + $workshop = $this->_customdata['workshop']; + + $mform->addElement('header', 'general', get_string('evaluationsettings', 'mod_workshop')); + + $this->definition_sub(); + + $mform->addElement('submit', 'submit', get_string('aggregategrades', 'workshop')); + } + + /** + * Defines the subplugin specific fields. + */ + protected function definition_sub() { + } } diff --git a/mod/workshop/lang/en/workshop.php b/mod/workshop/lang/en/workshop.php index 6efe8498e6d..f2fbd0dead1 100644 --- a/mod/workshop/lang/en/workshop.php +++ b/mod/workshop/lang/en/workshop.php @@ -100,7 +100,8 @@ $string['err_removegrademappings'] = 'Unable to remove the unused grade mappings $string['evaluategradeswait'] = 'Please wait until the assessments are evaluated and the grades are calculated'; $string['evaluation'] = 'Grading evaluation'; $string['evaluationmethod'] = 'Grading evaluation method'; -$string['evaluationmethod_help'] = 'The grading evaluation method determines how the grade for assessment is calculated. There is currently just one option - comparison with the best assessment.'; +$string['evaluationmethod_help'] = 'The grading evaluation method determines how the grade for assessment is calculated. You can let it re-calculate grades repeatedly with different settings unless you are happy with the result.'; +$string['evaluationsettings'] = 'Grading evaluation settings'; $string['example'] = 'Example submission'; $string['exampleadd'] = 'Add example submission'; $string['exampleassess'] = 'Assess example submission'; diff --git a/mod/workshop/lib.php b/mod/workshop/lib.php index b66bd4fcf7b..7250fe36676 100644 --- a/mod/workshop/lib.php +++ b/mod/workshop/lib.php @@ -136,7 +136,6 @@ function workshop_update_instance(stdclass $workshop) { $workshop->useselfassessment = (int)!empty($workshop->useselfassessment); $workshop->latesubmissions = (int)!empty($workshop->latesubmissions); $workshop->phaseswitchassessment = (int)!empty($workshop->phaseswitchassessment); - $workshop->evaluation = 'best'; // todo - if the grading strategy is being changed, we must replace all aggregated peer grades with nulls // todo - if maximum grades are being changed, we should probably recalculate or invalidate them diff --git a/mod/workshop/locallib.php b/mod/workshop/locallib.php index 340e771d179..20c579d98e8 100644 --- a/mod/workshop/locallib.php +++ b/mod/workshop/locallib.php @@ -185,7 +185,6 @@ class workshop { } else { $this->context = $context; } - $this->evaluation = 'best'; // todo make this configurable although we have no alternatives yet } //////////////////////////////////////////////////////////////////////////////// @@ -283,6 +282,19 @@ class workshop { return $forms; } + /** + * Returns the list of available grading evaluation methods + * + * @return array of (string)name => (string)localized title + */ + public static function available_evaluators_list() { + $evals = array(); + foreach (get_plugin_list_with_file('workshopeval', 'lib.php', false) as $eval => $evalpath) { + $evals[$eval] = get_string('pluginname', 'workshopeval_' . $eval); + } + return $evals; + } + /** * Return an array of possible values of assessment dimension weight * @@ -1229,6 +1241,28 @@ class workshop { return $this->strategyinstance; } + /** + * Sets the current evaluation method to the given plugin. + * + * @param string $method the name of the workshopeval subplugin + * @return bool true if successfully set + * @throws coding_exception if attempting to set a non-installed evaluation method + */ + public function set_grading_evaluation_method($method) { + global $DB; + + $evaluationlib = dirname(__FILE__) . '/eval/' . $method . '/lib.php'; + + if (is_readable($evaluationlib)) { + $this->evaluationinstance = null; + $this->evaluation = $method; + $DB->set_field('workshop', 'evaluation', $method, array('id' => $this->id)); + return true; + } + + throw new coding_exception('Attempt to set a non-existing evaluation method.'); + } + /** * Returns instance of grading evaluation class * @@ -1238,16 +1272,27 @@ class workshop { global $CFG; // because we require other libs here if (is_null($this->evaluationinstance)) { + if (empty($this->evaluation)) { + $this->evaluation = 'best'; + } $evaluationlib = dirname(__FILE__) . '/eval/' . $this->evaluation . '/lib.php'; if (is_readable($evaluationlib)) { require_once($evaluationlib); } else { - throw new coding_exception('the grading evaluation subplugin must contain library ' . $evaluationlib); + // Fall back in case the subplugin is not available. + $this->evaluation = 'best'; + $evaluationlib = dirname(__FILE__) . '/eval/' . $this->evaluation . '/lib.php'; + if (is_readable($evaluationlib)) { + require_once($evaluationlib); + } else { + // Fall back in case the subplugin is not available any more. + throw new coding_exception('Missing default grading evaluation library ' . $evaluationlib); + } } $classname = 'workshop_' . $this->evaluation . '_evaluation'; $this->evaluationinstance = new $classname($this); - if (!in_array('workshop_evaluation', class_implements($this->evaluationinstance))) { - throw new coding_exception($classname . ' does not implement workshop_evaluation interface'); + if (!in_array('workshop_evaluation', class_parents($this->evaluationinstance))) { + throw new coding_exception($classname . ' does not extend workshop_evaluation class'); } } return $this->evaluationinstance; diff --git a/mod/workshop/styles.css b/mod/workshop/styles.css index 6f9c01409ce..88e13362c2b 100644 --- a/mod/workshop/styles.css +++ b/mod/workshop/styles.css @@ -520,3 +520,8 @@ .path-mod-workshop div.buttonwithhelp div { display: inline; } + +.path-mod-workshop #evaluationmethodchooser { + margin: 2em auto; + text-align: center; +} diff --git a/mod/workshop/view.php b/mod/workshop/view.php index e5817dd263f..43db74407a7 100644 --- a/mod/workshop/view.php +++ b/mod/workshop/view.php @@ -38,6 +38,7 @@ $page = optional_param('page', 0, PARAM_INT); $perpage = optional_param('perpage', null, PARAM_INT); $sortby = optional_param('sortby', 'lastname', PARAM_ALPHA); $sorthow = optional_param('sorthow', 'ASC', PARAM_ALPHA); +$eval = optional_param('eval', null, PARAM_PLUGIN); if ($id) { $cm = get_coursemodule_from_id('workshop', $id, 0, false, MUST_EXIST); @@ -73,6 +74,13 @@ if ($perpage and $perpage > 0 and $perpage <= 1000) { redirect($PAGE->url); } +if ($eval) { + require_sesskey(); + require_capability('mod/workshop:overridegrades', $workshop->context); + $workshop->set_grading_evaluation_method($eval); + redirect($PAGE->url); +} + $output = $PAGE->get_renderer('mod_workshop'); $userplan = new workshop_user_plan($workshop, $USER->id); @@ -395,6 +403,13 @@ case workshop::PHASE_EVALUATION: $showreviewernames = has_capability('mod/workshop:viewreviewernames', $workshop->context); if (has_capability('mod/workshop:overridegrades', $PAGE->context)) { + // Print a drop-down selector to change the current evaluation method. + $selector = new single_select($PAGE->url, 'eval', workshop::available_evaluators_list(), + $workshop->evaluation, false, 'evaluationmethodchooser'); + $selector->set_label(get_string('evaluationmethod', 'mod_workshop')); + $selector->set_help_icon('evaluationmethod', 'mod_workshop'); + $selector->method = 'post'; + echo $output->render($selector); // load the grading evaluator $evaluator = $workshop->grading_evaluation_instance(); $form = $evaluator->get_settings_form(new moodle_url($workshop->aggregate_url(),