Files
moodle/mod/workshop/grading/noerrors/strategy.php
T
2010-01-04 17:43:31 +00:00

197 lines
7.6 KiB
PHP

<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file defines a class with "Number of errors" grading strategy logic
*
* @package mod-workshop
* @copyright 2009 David Mudrak <david.mudrak@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once(dirname(dirname(__FILE__)) . '/strategy.php'); // parent class
/**
* "Number of errors" grading strategy logic.
*/
class workshop_noerrors_strategy extends workshop_base_strategy {
public function load_grading_form() {
global $DB;
$dims = $DB->get_records('workshop_forms_' . $this->name, array('workshopid' => $this->workshop->id), 'sort');
$maps = $DB->get_records('workshop_forms_noerrors_map', array('workshopid' => $this->workshop->id), 'nonegative');
$this->nodimensions = count($dims);
return $this->_cook_database_records($dims, $maps);
}
/**
* Transpones the dimension data from DB so the assessment form editor can be populated by set_data
*
* Called internally from load_grading_form(). Could be private but keeping protected
* for unit testing purposes.
*
* @param array $dims Array of raw dimension records as fetched by get_record()
* @param array $maps Array of grade mappings
* @return array Object to be used by the mform set_data
*/
protected function _cook_database_records(array $dims, array $maps) {
$formdata = array();
// cook dimensions
$key = 0;
foreach ($dims as $dimension) {
$formdata['dimensionid[' . $key . ']'] = $dimension->id;
$formdata['description[' . $key . ']'] = $dimension->description;
$formdata['descriptionformat[' . $key . ']'] = $dimension->descriptionformat;
$formdata['grade0[' . $key . ']'] = $dimension->grade0;
$formdata['grade1[' . $key . ']'] = $dimension->grade1;
$formdata['weight[' . $key . ']'] = $dimension->weight;
$key++;
}
// cook grade mappings
foreach ($maps as $map) {
$formdata['map[' . $map->nonegative . ']'] = $map->grade;
}
return (object)$formdata;
}
/**
* Save the definition of a "Number of errors" grading form
*
* The dimensions data are stored in workshop_forms_noerrors. The data that map the
* number of errors to a grade are saved into workshop_forms_noerrors_map.
*
* @uses $DB
* @param object $data Raw data returned by the dimension editor form
* @return void
*/
public function save_grading_form(stdClass $data) {
global $DB;
if (!isset($data->strategyname) || ($data->strategyname != $this->name)) {
// the workshop strategy has changed since the form was opened for editing
throw new moodle_exception('strategyhaschanged', 'workshop');
}
// save the dimensions data
$dims = $this->_cook_form_data($data);
$todelete = array();
foreach ($dims as $record) {
if (empty($record->description)) {
if (!empty($record->id)) {
// existing record with empty description - to be deleted
$todelete[] = $record->id;
}
continue;
}
if (empty($record->id)) {
// new field
$record->id = $DB->insert_record('workshop_forms_' . $this->name, $record);
} else {
// exiting field
$DB->update_record('workshop_forms_' . $this->name, $record);
}
}
// delete dimensions if the teacher removed the description
$DB->delete_records_list('workshop_forms_' . $this->name, 'id', $todelete);
// re-save the mappings
$current = array();
$currentx = $DB->get_records('workshop_forms_noerrors_map', array('workshopid' => $this->workshop->id));
foreach ($currentx as $id => $map) {
$current[$map->nonegative] = $map->grade;
}
unset($currentx);
$todelete = array();
foreach ($data->map as $nonegative => $grade) {
if ($nonegative == 0) {
// no negative response automatically maps to 100%, do not save such mapping
continue;
}
if (!is_numeric($grade)) {
// no grade set for this number of negative responses
$todelete[] = $nonegative;
continue;
}
if (isset($current[$nonegative])) {
$DB->set_field('workshop_forms_noerrors_map', 'grade', $grade,
array('workshopid' => $this->workshop->id, 'nonegative' => $nonegative));
} else {
$DB->insert_record('workshop_forms_noerrors_map',
(object)array('workshopid' => $this->workshop->id, 'nonegative' => $nonegative, 'grade' => $grade));
}
}
// clear mappings that are not valid any more
if (!empty($todelete)) {
list($insql, $params) = $DB->get_in_or_equal($todelete);
$insql = 'nonegative ' . $insql . ' OR ';
} else {
list($insql, $params) = array('', array());
}
$sql = 'DELETE FROM {workshop_forms_noerrors_map}
WHERE ((' . $insql . 'nonegative > ?) AND (workshopid = ?))';
$params[] = count($data->map) - 1;
$params[] = $this->workshop->id;
if (!$DB->execute($sql, $params)){
print_error('err_removegrademappings', 'workshop');
}
}
/**
* Prepares dimensions data returned by mform so they can be saved into database
*
* It automatically adds some columns into every record. The sorting is
* done by the order of the returned array and starts with 1.
* Called internally from save_grading_form() only. Could be private but
* keeping protected for unit testing purposes.
*
* @param object $raw Raw data returned by mform
* @return array Array of objects to be inserted/updated in DB
*/
protected function _cook_form_data(stdClass $raw) {
$cook = array();
for ($k = 0; $k < $raw->numofdimensions; $k++) {
$cook[$k] = new stdClass();
$cook[$k]->id = isset($raw->dimensionid[$k]) ? $raw->dimensionid[$k] : null;
$cook[$k]->workshopid = $this->workshop->id;
$cook[$k]->sort = $k + 1;
$cook[$k]->description = isset($raw->description[$k]) ? $raw->description[$k] : null;
$cook[$k]->descriptionformat = FORMAT_HTML;
$cook[$k]->grade0 = isset($raw->grade0[$k]) ? $raw->grade0[$k] : null;
$cook[$k]->grade1 = isset($raw->grade1[$k]) ? $raw->grade1[$k] : null;
$cook[$k]->weight = isset($raw->weight[$k]) ? $raw->weight[$k] : null;
}
return $cook;
}
}