require_login($course, false, $cm);
require_capability('mod/workshop:overridegrades', $PAGE->context);
+// load the grading evaluator
+$evaluator = $workshop->grading_evaluation_instance();
+
if ($confirm) {
if (!confirm_sesskey()) {
throw new moodle_exception('confirmsesskeybad');
}
- $workshop->update_submission_grades();
- $workshop->update_grading_grades();
+ $workshop->aggregate_submission_grades();
+ //$evaluator->update_grading_grades();
+ //$workshop->aggregate_grading_grades();
+ //$workshop->aggregate_total_grades();
redirect($workshop->view_url());
}
defined('MOODLE_INTERNAL') || die();
require_once(dirname(dirname(__FILE__)) . '/lib.php'); // interface definition
+require_once($CFG->libdir . '/gradelib.php');
/**
* Defines the computation login of the grading evaluation subplugin
*/
class workshop_best_evaluation implements workshop_evaluation {
+ /** @var workshop the parent workshop instance */
+ protected $workshop;
+
+ /**
+ * Constructor
+ *
+ * @param workshop $workshop The workshop api instance
+ * @return void
+ */
+ public function __construct(workshop $workshop) {
+ $this->workshop = $workshop;
+ }
+
+ /**
+ * TODO
+ *
+ * @param null|int|array $restrict If null, update all reviewers, otherwise update just grades for the given reviewers(s)
+ *
+ * @return void
+ */
+ public function update_grading_grades($restrict=null) {
+ global $DB;
+
+ $grader = $this->workshop->grading_strategy_instance();
+ if (! $grader->supports_evaluation($this)) {
+ throw new coding_exception('The currently selected grading strategy plugin does not
+ support this method of grading evaluation.');
+ }
+
+ // fetch a recordset with all assessments to process
+ $rs = $grader->get_assessments_recordset($restrict);
+ $batch = array(); // will contain a set of all assessments of a single submission
+ $previous = null; // a previous record in the recordset
+ foreach ($rs as $current) {
+ if (is_null($previous)) {
+ // we are processing the very first record in the recordset
+ $previous = $current;
+ }
+ if ($current->submissionid == $previous->submissionid) {
+ $batch[] = $current;
+ } else {
+ // process all the assessments of a sigle submission
+ $this->process_assessments($batch);
+ // start with a new batch to be processed
+ $batch = array($current);
+ $previous = $current;
+ }
+ }
+ // do not forget to process the last batch!
+ $this->process_assessments($batch);
+ $rs->close();
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+// Internal methods //
+////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Given a list of all assessments of a single submission, updates the grading grades in database
+ *
+ * @param array $assessments of stdClass Object(->assessmentid ->assessmentweight ->reviewerid ->submissionid
+ * ->dimensionid ->grade ->dimensionweight)
+ * @return void
+ */
+ protected function process_assessments(array $assessments) {
+ global $DB;
+
+ $grades = $this->evaluate_assessments($assessments);
+ foreach ($grades as $assessmentid => $grade) {
+ $record = new stdClass();
+ $record->id = $assessmentid;
+ $record->gradinggrade = grade_floatval($grade);
+ $DB->update_record('workshop_assessments', $record, true);
+ }
+ }
+
+ /**
+ * Given a list of all assessments of a single submission, calculates the grading grades for them
+ *
+ * @param array $assessments same structure as for {@link self::process_assessments()}
+ * @return array [(int)assessmentid => (float)gradinggrade] to be saved into {workshop_assessments}
+ */
+ protected function evaluate_assessments(array $assessments) {
+ $gradinggrades = array();
+ foreach ($assessments as $assessment) {
+ $gradinggrades[$assessment->assessmentid] = grade_floatval(rand(0, 100)); // todo
+ }
+ return $gradinggrades;
+ }
+
}
* @param workshop_evaluation $evaluation the instance of grading evaluation class
* @return bool true if the evaluation method is supported, false otherwise
*/
- public function evaluation_supported(workshop_evaluation $evaluation) {
- return false; // todo does not support any evaluation yet
+ public function supports_evaluation(workshop_evaluation $evaluation) {
+ if (is_a($evaluation, 'workshop_best_evaluation')) {
+ return true;
+ }
+ // all other evaluation methods are not supported yet
+ return false;
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+// Methods needed by 'best' evaluation plugin //
+////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * TODO: short description.
+ *
+ * @param resource $restrict
+ * @return TODO
+ */
+ public function get_assessments_recordset($restrict) {
+ global $DB;
+
+ $sql = 'SELECT a.id AS assessmentid,a.weight AS assessmentweight,a.reviewerid,
+ s.id AS submissionid,
+ g.dimensionid,g.grade,
+ d.weight AS dimensionweight
+ FROM {workshop_submissions} s
+ JOIN {workshop_assessments} a ON (a.submissionid = s.id)
+ JOIN {workshop_grades} g ON (g.assessmentid = a.id AND g.strategy = :strategy)
+ JOIN {workshopform_accumulative} d ON (d.id = g.dimensionid)
+ WHERE s.example=0 AND s.workshopid=:workshopid'; // to be cont.
+ $params = array('workshopid' => $this->workshop->id, 'strategy' => $this->workshop->strategy);
+
+ if (is_null($restrict)) {
+ // update all users - no more conditions
+ } elseif (!empty($restrict)) {
+ list($usql, $uparams) = $DB->get_in_or_equal($restrict, SQL_PARAMS_NAMED);
+ $sql .= " AND a.reviewerid $usql";
+ $params = array_merge($params, $uparams);
+ } else {
+ throw new coding_exception('Empty value is not a valid parameter here');
+ }
+
+ $sql .= ' ORDER BY s.id'; // this is important for bulk processing
+
+ return $DB->get_recordset_sql($sql, $params);
}
////////////////////////////////////////////////////////////////////////////////
static $numofscaleitems = array();
if (!isset($numofscaleitems[$scaleid])) {
- $scale = $DB->get_field("scales", "scale", array("id" => $scaleid), MUST_EXIST);
+ $scale = $DB->get_field('scale', 'scale', array('id' => $scaleid), MUST_EXIST);
$items = explode(',', $scale);
$numofscaleitems[$scaleid] = count($items);
unset($scale);
$mockscale = 'E,D,C,B,A';
$this->strategy->dimensions[1008] = (object)array('grade' => '-10', 'weight' => 1);
$grades[] = (object)array('dimensionid' => 1008, 'grade' => '5.00000');
- $DB->expectOnce('get_field', array('scales', 'scale', array('id' => 10), MUST_EXIST));
+ $DB->expectOnce('get_field', array('scale', 'scale', array('id' => 10), MUST_EXIST));
$DB->setReturnValue('get_field', $mockscale);
// excercise SUT
// fixture set-up
$this->strategy->dimensions[1008] = (object)array('grade' => '-10', 'weight' => 1);
$grades[] = (object)array('dimensionid' => 1008, 'grade' => '1.00000');
- $DB->expectNever('get_field', array('scales', 'scale', array('id' => 10), MUST_EXIST)); // cached
+ $DB->expectNever('get_field', array('scale', 'scale', array('id' => 10), MUST_EXIST)); // cached
// excercise SUT
$suggested = $this->strategy->calculate_peer_grade($grades);
$grades[] = (object)array('dimensionid' => 1012, 'grade' => '2.00000'); // "Good"
$grades[] = (object)array('dimensionid' => 1019, 'grade' => '5.00000'); // "****"
- $DB->expectAt(0, 'get_field', array('scales', 'scale', array('id' => 13), MUST_EXIST));
+ $DB->expectAt(0, 'get_field', array('scale', 'scale', array('id' => 13), MUST_EXIST));
$DB->setReturnValueAt(0, 'get_field', $mockscale13);
- $DB->expectAt(1, 'get_field', array('scales', 'scale', array('id' => 17), MUST_EXIST));
+ $DB->expectAt(1, 'get_field', array('scale', 'scale', array('id' => 17), MUST_EXIST));
$DB->setReturnValueAt(1, 'get_field', $mockscale17);
// excercise SUT
// fixture set-up
$mockscale13 = 'Poor,Good,Excellent';
$this->strategy->dimensions[1012] = (object)array('grade' => -13, 'weight' => 1);
- $DB->expectNever('get_field', array('scales', 'scale', array('id' => 13), MUST_EXIST)); // cached
+ $DB->expectNever('get_field', array('scale', 'scale', array('id' => 13), MUST_EXIST)); // cached
$grades[] = (object)array('dimensionid' => 1012, 'grade' => '4.00000'); // exceeds the number of scale items
$this->expectException('coding_exception');
* @param workshop_evaluation $evaluation the instance of grading evaluation class
* @return bool true if the evaluation method is supported, false otherwise
*/
- public function evaluation_supported(workshop_evaluation $evaluation);
+ public function supports_evaluation(workshop_evaluation $evaluation);
}
* @param workshop_evaluation $evaluation the instance of grading evaluation class
* @return bool true if the evaluation method is supported, false otherwise
*/
- public function evaluation_supported(workshop_evaluation $evaluation) {
+ public function supports_evaluation(workshop_evaluation $evaluation) {
if (is_a($evaluation, 'workshop_best_evaluation')) {
return true;
}
if (! $workshop = $DB->get_record('workshop', array('id' => $id))) {
return false;
}
+ // delete all associated aggregations
+ $DB->delete_records('workshop_aggregations', array('workshopid' => $workshop->id));
+ // get the list of ids of all submissions
+ $submissions = $DB->get_records('workshop_submissions', array('workshopid' => $workshop->id), '', 'id');
+ // get the list of all allocated assessments
+ $assessments = $DB->get_records_list('workshop_assessments', 'submissionid', array_keys($submissions), '', 'id');
+ // delete the associated records from the workshop core tables
+ $DB->delete_records_list('workshop_grades', 'assessmentid', array_keys($assessments));
+ $DB->delete_records_list('workshop_assessments', 'id', array_keys($assessments));
+ $DB->delete_records_list('workshop_submissions', 'id', array_keys($submissions));
+ // todo call the static clean-up methods of all available subplugins
+ // ...
+ // finally remove the workshop record itself
+ $DB->delete_records('workshop', array('id' => $workshop->id));
- $result = true;
-
- # Delete any dependent records here #
-
- if (! $DB->delete_records('workshop', array('id' => $workshop->id))) {
- $result = false;
- }
-
- return $result;
+ return true;
}
/**
// this is intentional - IMO there should be no such field as it violates
// 3rd normal form with no real performance gain. This way I try to
// demonstrate how backwards compatibility could be achieved --mudrd8mz
- $this->context = get_context_instance(CONTEXT_MODULE, $this->id);
+ $this->context = get_context_instance(CONTEXT_MODULE, $this->cm->id);
}
////////////////////////////////////////////////////////////////////////////////
* @param null|int|array $restrict If null, update all authors, otherwise update just grades for the given author(s)
* @return void
*/
- public function update_submission_grades($restrict=null) {
+ public function aggregate_submission_grades($restrict=null) {
global $DB;
// fetch a recordset with all assessments to process
* @param null|int|array $restrict If null, update all reviewers, otherwise update just grades for the given reviewer(s)
* @return void
*/
- public function update_grading_grades($restrict=null) {
+ public function aggregate_grading_grades($restrict=null) {
global $DB;
// todo
$page = optional_param($pagingvar, 0, PARAM_INT);
$perpage = 10; // todo let the user modify this
$groups = ''; // todo let the user choose the group
- $sortby = 'submissiongrade'; // todo let the user choose the column to sort by
+ $sortby = 'assessmentgrade'; // todo let the user choose the column to sort by
$sorthow = 'DESC'; // todo detto
$data = $workshop->prepare_grading_report($USER->id, $groups, $page, $perpage, $sortby, $sorthow);