$peers = array();
$rs = $this->workshop->get_allocations_recordset();
- foreach ($rs as $allocation) {
- $currentuserid = $allocation->authorid;
- if (!isset($peers[$currentuserid])) {
- $peers[$currentuserid] = new stdClass();
- $peers[$currentuserid]->id = $allocation->authorid;
- $peers[$currentuserid]->firstname = $allocation->authorfirstname;
- $peers[$currentuserid]->lastname = $allocation->authorlastname;
- $peers[$currentuserid]->picture = $allocation->authorpicture;
- $peers[$currentuserid]->imagealt = $allocation->authorimagealt;
- $peers[$currentuserid]->submissionid = $allocation->submissionid;
- $peers[$currentuserid]->submissiontitle = $allocation->submissiontitle;
- $peers[$currentuserid]->submissiongrade = $allocation->submissiongrade;
- $peers[$currentuserid]->reviewedby = array(); // users who are reviewing this user's submission
- $peers[$currentuserid]->reviewerof = array(); // users whom submission is being reviewed by this user
- }
- if (!empty($allocation->reviewerid)) {
- // example: "submission of user with id 45 is reviewed by user with id 87 in the assessment record 12"
- $peers[$currentuserid]->reviewedby[$allocation->reviewerid] = $allocation->assessmentid;
+ if (!is_null($rs)) {
+ foreach ($rs as $allocation) {
+ $currentuserid = $allocation->authorid;
+ if (!isset($peers[$currentuserid])) {
+ $peers[$currentuserid] = new stdClass();
+ $peers[$currentuserid]->id = $allocation->authorid;
+ $peers[$currentuserid]->firstname = $allocation->authorfirstname;
+ $peers[$currentuserid]->lastname = $allocation->authorlastname;
+ $peers[$currentuserid]->picture = $allocation->authorpicture;
+ $peers[$currentuserid]->imagealt = $allocation->authorimagealt;
+ $peers[$currentuserid]->submissionid = $allocation->submissionid;
+ $peers[$currentuserid]->submissiontitle = $allocation->submissiontitle;
+ $peers[$currentuserid]->submissiongrade = $allocation->submissiongrade;
+ $peers[$currentuserid]->reviewedby = array(); // users who are reviewing this user's submission
+ $peers[$currentuserid]->reviewerof = array(); // users whom submission is being reviewed by this user
+ }
+ if (!empty($allocation->reviewerid)) {
+ // example: "submission of user with id 45 is reviewed by user with id 87 in the assessment record 12"
+ $peers[$currentuserid]->reviewedby[$allocation->reviewerid] = $allocation->assessmentid;
+ }
}
+ $rs->close();
}
- $rs->close();
foreach ($peers as $author) {
foreach ($author->reviewedby as $reviewerid => $assessmentid) {
$data = new stdClass();
$data->wsoutput = $wsoutput;
$data->peers = $peers;
- $data->authors = $this->workshop->get_potential_authors();
- $data->reviewers = $this->workshop->get_potential_reviewers();
+ $data->authors = $this->workshop->get_potential_authors($PAGE->context);
+ $data->reviewers = $this->workshop->get_potential_reviewers($PAGE->context);
$data->hlauthorid = $hlauthorid;
$data->hlreviewerid = $hlreviewerid;
$data->msg = $msg;
$o = array(); // list of output messages
$numofreviews = required_param('numofreviews', PARAM_INT);
$numper = required_param('numper', PARAM_INT);
- $removecurrent = required_param('removecurrent', PARAM_INT);
- $assesswosubmission = required_param('assesswosubmission', PARAM_INT);
+ $removecurrent = optional_param('removecurrent', false, PARAM_BOOL);
+ $assesswosubmission = optional_param('assesswosubmission', false, PARAM_BOOL);
+ $addselfassessment = optional_param('addselfassessment', false, PARAM_BOOL);
$musthavesubmission = empty($assesswosubmission);
- $addselfassessment = optional_param('addselfassessment', false, PARAM_INT); // may be frozen in the form
- $authors = $this->workshop->get_potential_authors();
+ $authors = $this->workshop->get_potential_authors($PAGE->context);
$authors = $this->workshop->get_grouped($authors);
- $reviewers = $this->workshop->get_potential_reviewers($musthavesubmission);
+ $reviewers = $this->workshop->get_potential_reviewers($PAGE->context, $musthavesubmission);
$reviewers = $this->workshop->get_grouped($reviewers);
$assessments = $this->workshop->get_all_assessments();
$mform->setDefault('numper', workshop_random_allocator::USERTYPE_AUTHOR);
$mform->addGroup($grpnumofreviews, 'grpnumofreviews', get_string('numofreviews', 'workshop'), array(' '), false);
- $mform->addElement('advcheckbox', 'removecurrent', get_string('removecurrentallocations', 'workshopallocation_random'));
+ $mform->addElement('checkbox', 'removecurrent', get_string('removecurrentallocations', 'workshopallocation_random'));
$mform->setDefault('removecurrent', 0);
- $mform->addElement('advcheckbox', 'assesswosubmission', get_string('assesswosubmission', 'workshopallocation_random'));
+ $mform->addElement('checkbox', 'assesswosubmission', get_string('assesswosubmission', 'workshopallocation_random'));
$mform->setDefault('assesswosubmission', 0);
- $grpselfassessment = array();
- $grpselfassessment[] = $mform->createElement('advcheckbox', 'addselfassessment');
- $mform->setDefault('addselfassessment', 0);
- if (!$workshop->useselfassessment) {
- $grpselfassessment[] = $mform->createElement('static', 'selfassessmentcheck', '',
- get_string('selfassessmentdisabled', 'workshop'));
- }
- $mform->addGroup($grpselfassessment, 'grpselfassessment', get_string('addselfassessment', 'workshopallocation_random'));
- if (!$workshop->useselfassessment) {
- $mform->freeze(array('grpselfassessment'));
+ if (empty($workshop->useselfassessment)) {
+ $mform->addElement('static', 'addselfassessment', get_string('addselfassessment', 'workshopallocation_random'),
+ get_string('selfassessmentdisabled', 'workshop'));
+ } else {
+ $mform->addElement('checkbox', 'addselfassessment', get_string('addselfassessment', 'workshopallocation_random'));
}
$this->add_action_buttons();
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
- * Unit tests for mod/workshop/allocation/random/allocator.php
+ * Unit tests for Random allocation
*
* @package mod-workshop
* @copyright 2009 David Mudrak <david.mudrak@gmail.com>
defined('MOODLE_INTERNAL') || die();
// Include the code to test
-require_once($CFG->dirroot . '/mod/workshop/allocation/random/allocator.php');
+require_once($CFG->dirroot . '/mod/workshop/locallib.php');
+require_once($CFG->dirroot . '/mod/workshop/allocation/random/lib.php');
/**
* Make protected methods we want to test public
<?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="mod/workshop/db" VERSION="20090907" COMMENT="XMLDB file for Moodle mod/workshop"
+<XMLDB PATH="mod/workshop/db" VERSION="20090908" COMMENT="XMLDB file for Moodle mod/workshop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
<KEY NAME="overriddenby_fk" TYPE="foreign" FIELDS="gradinggradeoverby" REFTABLE="user" REFFIELDS="id" PREVIOUS="reviewer_fk"/>
</KEYS>
</TABLE>
- <TABLE NAME="workshop_grades" COMMENT="How the reviewers filled-up the grading forms, given grades and comments" PREVIOUS="workshop_assessments" NEXT="workshop_forms">
+ <TABLE NAME="workshop_grades" COMMENT="How the reviewers filled-up the grading forms, given grades and comments" PREVIOUS="workshop_assessments">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="assessmentid"/>
- <FIELD NAME="assessmentid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="Part of which assessment this grade is of" PREVIOUS="id" NEXT="dimensionid"/>
- <FIELD NAME="dimensionid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="Foreign key. References dimension id in one of the grading strategy tables." PREVIOUS="assessmentid" NEXT="grade"/>
- <FIELD NAME="grade" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="Given grade in the referenced assessment dimension." PREVIOUS="dimensionid" NEXT="peercomment"/>
+ <FIELD NAME="assessmentid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="Part of which assessment this grade is of" PREVIOUS="id" NEXT="strategy"/>
+ <FIELD NAME="strategy" TYPE="char" LENGTH="30" NOTNULL="true" SEQUENCE="false" PREVIOUS="assessmentid" NEXT="dimensionid"/>
+ <FIELD NAME="dimensionid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="Foreign key. References dimension id in one of the grading strategy tables." PREVIOUS="strategy" NEXT="grade"/>
+ <FIELD NAME="grade" TYPE="number" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" DECIMALS="5" COMMENT="Given grade in the referenced assessment dimension." PREVIOUS="dimensionid" NEXT="peercomment"/>
<FIELD NAME="peercomment" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" COMMENT="Reviewer's comment to the grade value." PREVIOUS="grade" NEXT="peercommentformat"/>
<FIELD NAME="peercommentformat" TYPE="int" LENGTH="3" NOTNULL="false" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" COMMENT="The format of peercomment field" PREVIOUS="peercomment"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="assessment_fk"/>
- <KEY NAME="assessment_fk" TYPE="foreign" FIELDS="assessmentid" REFTABLE="workshop_assessments" REFFIELDS="id" PREVIOUS="primary" NEXT="dimension_fk"/>
- <KEY NAME="dimension_fk" TYPE="foreign" FIELDS="dimensionid" REFTABLE="workshop_forms" REFFIELDS="id" PREVIOUS="assessment_fk" NEXT="formfield"/>
- <KEY NAME="formfield" TYPE="unique" FIELDS="assessmentid, dimensionid" COMMENT="The combination of assessmentid and dimensionid must be unique" PREVIOUS="dimension_fk"/>
- </KEYS>
- </TABLE>
- <TABLE NAME="workshop_forms" COMMENT="Meta table to provide unique id for every assessment dimension which is needed for file api support." PREVIOUS="workshop_grades">
- <FIELDS>
- <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="workshopid"/>
- <FIELD NAME="workshopid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="Workshop ID" PREVIOUS="id" NEXT="sort"/>
- <FIELD NAME="sort" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="Defines the dimension order within the assessment form" PREVIOUS="workshopid" NEXT="strategy"/>
- <FIELD NAME="strategy" TYPE="char" LENGTH="30" NOTNULL="true" SEQUENCE="false" COMMENT="Defines the target assessment form table" PREVIOUS="sort" NEXT="localid"/>
- <FIELD NAME="localid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="The foreign primary key of one of the assessment forms tables." PREVIOUS="strategy"/>
- </FIELDS>
- <KEYS>
- <KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="workshop_fk"/>
- <KEY NAME="workshop_fk" TYPE="foreign" FIELDS="workshopid" REFTABLE="workshop" REFFIELDS="id" PREVIOUS="primary"/>
+ <KEY NAME="assessment_fk" TYPE="foreign" FIELDS="assessmentid" REFTABLE="workshop_assessments" REFFIELDS="id" PREVIOUS="primary" NEXT="formfield_uk"/>
+ <KEY NAME="formfield_uk" TYPE="unique" FIELDS="assessmentid, strategy, dimensionid" COMMENT="The combination of assessmentid, strategy and dimensionid must be unique" PREVIOUS="assessment_fk"/>
</KEYS>
</TABLE>
</TABLES>
switch ($tool) {
case 'mksubmissions':
- $authors = $workshop->get_potential_authors(false);
- $authorswithsubmission = $workshop->get_potential_authors(true);
+ $authors = $workshop->get_potential_authors($PAGE->context, false);
+ $authorswithsubmission = $workshop->get_potential_authors($PAGE->context, true);
$authors = array_diff_key($authors, $authorswithsubmission);
echo $OUTPUT->header();
$c = 0; // counter
echo $OUTPUT->header();
$currenttab = 'editform';
include(dirname(__FILE__) . '/tabs.php');
-echo $OUTPUT->heading(get_string('pluginname', 'workshopgrading_' . $workshop->strategy));
+echo $OUTPUT->heading(get_string('pluginname', 'workshopform_' . $workshop->strategy));
$mform->display();
for ($i = 0; $i < $nodims; $i++) {
// dimension header
- $dimtitle = get_string('dimensionnumber', 'workshopgrading_accumulative', $i+1);
- $mform->addElement('header', "dimensionhdr__idx_$i", $dimtitle);
+ $dimtitle = get_string('dimensionnumber', 'workshopform_accumulative', $i+1);
+ $mform->addElement('header', 'dimensionhdr__idx_'.$i, $dimtitle);
// dimension id
$mform->addElement('hidden', 'dimensionid__idx_'.$i, $fields->{'dimensionid__idx_'.$i});
$mform->addElement('html', $desc);
// grade for this aspect
- $label = get_string('dimensiongrade', 'workshopgrading_accumulative');
+ $label = get_string('dimensiongrade', 'workshopform_accumulative');
$options = make_grades_menu($fields->{'grade__idx_' . $i});
$mform->addElement('select', 'grade__idx_' . $i, $label, $options);
// comment
- $label = get_string('dimensioncomment', 'workshopgrading_accumulative');
+ $label = get_string('dimensioncomment', 'workshopform_accumulative');
//$mform->addElement('editor', 'peercomment__idx_' . $i, $label, null, array('maxfiles' => 0));
$mform->addElement('textarea', 'peercomment__idx_' . $i, $label, array('cols' => 60, 'rows' => 5));
}
<?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="mod/workshop/db" VERSION="20090813" COMMENT="XMLDB file for Moodle mod/workshop"
+<XMLDB PATH="mod/workshop/db" VERSION="20090908" COMMENT="XMLDB file for Moodle mod/workshop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
- <TABLE NAME="workshop_forms_accumulative" COMMENT="The assessment dimensions definitions of Accumulative grading strategy forms">
+ <TABLE NAME="workshopform_accumulative" COMMENT="The assessment dimensions definitions of Accumulative grading strategy forms">
<FIELDS>
- <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="description"/>
- <FIELD NAME="description" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" COMMENT="The description of the dimension" PREVIOUS="id" NEXT="descriptionformat"/>
+ <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="workshopid"/>
+ <FIELD NAME="workshopid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="Workshop ID" PREVIOUS="id" NEXT="sort"/>
+ <FIELD NAME="sort" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="Defines the dimension order within the assessment form" PREVIOUS="workshopid" NEXT="description"/>
+ <FIELD NAME="description" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" COMMENT="The description of the dimension" PREVIOUS="sort" NEXT="descriptionformat"/>
<FIELD NAME="descriptionformat" TYPE="int" LENGTH="3" NOTNULL="false" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="The format of the description field" PREVIOUS="description" NEXT="grade"/>
<FIELD NAME="grade" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" SEQUENCE="false" COMMENT="If greater than 0, then the value is maximum grade on a scale 0..grade. If lesser than 0, then its absolute value is the id of a record in scale table. If equals 0, then no grading is possible for this dimension, just commenting." PREVIOUS="descriptionformat" NEXT="weight"/>
<FIELD NAME="weight" TYPE="int" LENGTH="5" NOTNULL="false" UNSIGNED="false" DEFAULT="1" SEQUENCE="false" COMMENT="The weigh of the dimension" PREVIOUS="grade"/>
</FIELDS>
<KEYS>
- <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
+ <KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="workshop_fk"/>
+ <KEY NAME="workshop_fk" TYPE="foreign" FIELDS="workshopid" REFTABLE="workshop" REFFIELDS="id" PREVIOUS="primary"/>
</KEYS>
</TABLE>
</TABLES>
-</XMLDB>
+</XMLDB>
\ No newline at end of file
$weights = workshop_get_dimension_weights();
for ($i = 0; $i < $norepeats; $i++) {
- $mform->addElement('header', 'dimension'.$i, get_string('dimensionnumber', 'workshopgrading_accumulative', $i+1));
- $mform->addElement('hidden', 'dimensionid__idx_'.$i); // the id in workshop_forms
+ $mform->addElement('header', 'dimension'.$i, get_string('dimensionnumber', 'workshopform_accumulative', $i+1));
+ $mform->addElement('hidden', 'dimensionid__idx_'.$i);
$mform->addElement('editor', 'description__idx_'.$i.'_editor',
- get_string('dimensiondescription', 'workshopgrading_accumulative'), '', $descriptionopts);
+ get_string('dimensiondescription', 'workshopform_accumulative'), '', $descriptionopts);
+ // todo replace modgrade with an advanced element (usability issue discussed with Olli)
$mform->addElement('modgrade', 'grade__idx_'.$i,
- get_string('dimensionmaxgrade','workshopgrading_accumulative'), null, true);
+ get_string('dimensionmaxgrade','workshopform_accumulative'), null, true);
$mform->setDefault('grade__idx_'.$i, 10);
$mform->addElement('select', 'weight__idx_'.$i,
- get_string('dimensionweight', 'workshopgrading_accumulative'), $weights);
+ get_string('dimensionweight', 'workshopform_accumulative'), $weights);
$mform->setDefault('weight__idx_'.$i, 1);
}
$mform->registerNoSubmitButton('noadddims');
- $mform->addElement('submit', 'noadddims', get_string('addmoredimensions', 'workshopgrading_accumulative',
+ $mform->addElement('submit', 'noadddims', get_string('addmoredimensions', 'workshopform_accumulative',
WORKSHOP_STRATEGY_ADDDIMS));
$mform->closeHeaderBefore('noadddims');
$this->set_data($current);
$this->descriptionopts = array('trusttext' => true, 'subdirs' => false, 'maxfiles' => -1);
}
-/// Public API
-
/**
* Factory method returning an instance of an assessment form editor class
*
$norepeats = $data->norepeats;
$data = $this->prepare_database_fields($data);
- $masters = $data->forms; // data to be saved into workshop_forms
- $locals = $data->accumulative; // data to be saved into workshop_forms_accumulative
- $todelete = array(); // master ids to be deleted
+ $records = $data->accumulative; // records to be saved into {workshopform_accumulative}
+ $todelete = array(); // dimension ids to be deleted
for ($i=0; $i < $norepeats; $i++) {
- $local = $locals[$i];
- $master = $masters[$i];
- if (empty($local->description_editor['text'])) {
- if (!empty($master->id)) {
+ $record = $records[$i];
+ if (empty($record->description_editor['text'])) {
+ if (!empty($record->id)) {
// existing record with empty description - to be deleted
- $todelete[] = $master->id;
+ $todelete[] = $record->id;
}
continue;
}
- if (empty($master->id)) {
+ if (empty($record->id)) {
// new field
- $local->id = $DB->insert_record("workshop_forms_accumulative", $local);
- $master->localid = $local->id;
- $master->id = $DB->insert_record("workshop_forms", $master);
+ $record->id = $DB->insert_record('workshopform_accumulative', $record);
} else {
// exiting field
- $DB->update_record("workshop_forms", $master);
- $local->id = $DB->get_field("workshop_forms", "localid", array("id" => $master->id), MUST_EXIST);
+ $DB->update_record('workshopform_accumulative', $record);
}
// re-save with correct path to embeded media files
- $local = file_postupdate_standard_editor($local, 'description', $this->descriptionopts,
- $PAGE->context, 'workshop_dimension_description', $master->id);
- $DB->update_record("workshop_forms_accumulative", $local);
+ $record = file_postupdate_standard_editor($record, 'description', $this->descriptionopts,
+ $PAGE->context, 'workshopform_accumulative_description', $record->id);
+ $DB->update_record('workshopform_accumulative', $record);
}
$this->delete_dimensions($todelete);
}
// rewrite URLs to the embeded files
for ($i = 0; $i < $nodimensions; $i++) {
$fields->{'description__idx_'.$i} = file_rewrite_pluginfile_urls($fields->{'description__idx_'.$i},
- 'pluginfile.php', $PAGE->context->id, 'workshop_dimension_description', $fields->{'dimensionid__idx_'.$i});
+ 'pluginfile.php', $PAGE->context->id, 'workshopform_accumulative_description', $fields->{'dimensionid__idx_'.$i});
}
if ('assessment' === $mode and !empty($assessment)) {
// load the previously saved assessment data
- $grades = $this->reindex_grades_by_dimension($this->get_current_assessment_data($assessment));
+ $grades = $this->get_current_assessment_data($assessment);
$current = new stdClass();
for ($i = 0; $i < $nodimensions; $i++) {
$dimid = $fields->{'dimensionid__idx_'.$i};
// set up the required custom data common for all strategies
$customdata['strategy'] = $this;
+ $customdata['workshop'] = $this->workshop;
$customdata['mode'] = $mode;
// set up strategy-specific custom data
$grade = new stdClass();
$grade->id = $data->{'gradeid__idx_' . $i};
$grade->assessmentid = $assessment->id;
+ $grade->strategy = 'accumulative';
$grade->dimensionid = $data->{'dimensionid__idx_' . $i};
$grade->grade = $data->{'grade__idx_' . $i};
$grade->peercomment = $data->{'peercomment__idx_' . $i};
- $grade->peercommentformat = FORMAT_HTML;
+ $grade->peercommentformat = FORMAT_MOODLE;
if (empty($grade->id)) {
// new grade
$grade->id = $DB->insert_record('workshop_grades', $grade);
return false;
}
-/// Internal methods
+////////////////////////////////////////////////////////////////////////////////
+// Internal methods //
+////////////////////////////////////////////////////////////////////////////////
/**
* Loads the fields of the assessment form currently used in this workshop
protected function load_fields() {
global $DB;
- $sql = "SELECT master.id,dim.description,dim.descriptionformat,dim.grade,dim.weight
- FROM {workshop_forms} master
- INNER JOIN {workshop_forms_accumulative} dim ON (dim.id=master.localid)
- WHERE master.workshopid = :workshopid AND master.strategy = :strategy
- ORDER BY master.sort";
- $params = array("workshopid" => $this->workshop->id, "strategy" => $this->workshop->strategy);
+ $sql = 'SELECT *
+ FROM {workshopform_accumulative}
+ WHERE workshopid = :workshopid
+ ORDER BY sort';
+ $params = array('workshopid' => $this->workshop->id);
return $DB->get_records_sql($sql, $params);
}
$formdata = new stdClass();
$key = 0;
foreach ($raw as $dimension) {
- $formdata->{'dimensionid__idx_' . $key} = $dimension->id; // master id, not the local one!
+ $formdata->{'dimensionid__idx_' . $key} = $dimension->id;
$formdata->{'description__idx_' . $key} = $dimension->description;
$formdata->{'description__idx_' . $key.'format'} = $dimension->descriptionformat;
$formdata->{'grade__idx_' . $key} = $dimension->grade;
* @param array $masterids
* @return void
*/
- protected function delete_dimensions($masterids) {
+ protected function delete_dimensions(array $ids) {
global $DB, $PAGE;
- $masters = $DB->get_records_list("workshop_forms", "id", $masterids, "", "id,localid");
- $masterids = array_keys($masters); // now contains only those really existing
- $localids = array();
- $fs = get_file_storage();
-
- foreach ($masters as $itemid => $master) {
- $fs->delete_area_files($PAGE->context->id, 'workshop_dimension_description', $itemid);
- $localids[] = $master->localid;
+ $fs = get_file_storage();
+ foreach ($ids as $id) {
+ if (!empty($id)) { // to prevent accidental removal of all files in the area
+ $fs->delete_area_files($PAGE->context->id, 'workshopform_accumulative_description', $id);
+ }
}
- $DB->delete_records_list("workshop_forms_accumulative", "id", $localids);
- $DB->delete_records_list("workshop_forms", "id", $masterids);
+ $DB->delete_records_list('workshopform_accumulative', 'id', $ids);
}
/**
global $PAGE;
$cook = new stdClass(); // to be returned
- $cook->forms = array(); // to be stored in {workshop_forms}
- $cook->accumulative = array(); // to be stored in {workshop_forms_accumulative}
+ $cook->accumulative = array(); // records to be stored in {workshopform_accumulative}
for ($i = 0; $i < $raw->norepeats; $i++) {
- $cook->forms[$i] = new stdClass();
- $cook->forms[$i]->id = $raw->{'dimensionid__idx_'.$i};
- $cook->forms[$i]->workshopid = $this->workshop->id;
- $cook->forms[$i]->sort = $i + 1;
- $cook->forms[$i]->strategy = 'accumulative';
-
- $cook->accumulative[$i] = new stdClass();
+ $cook->accumulative[$i] = new stdClass();
+ $cook->accumulative[$i]->id = $raw->{'dimensionid__idx_'.$i};
+ $cook->accumulative[$i]->workshopid = $this->workshop->id;
+ $cook->accumulative[$i]->sort = $i + 1;
$cook->accumulative[$i]->description_editor = $raw->{'description__idx_'.$i.'_editor'};
- $cook->accumulative[$i]->grade = $raw->{'grade__idx_'.$i};
- $cook->accumulative[$i]->weight = $raw->{'weight__idx_'.$i};
+ $cook->accumulative[$i]->grade = $raw->{'grade__idx_'.$i};
+ $cook->accumulative[$i]->weight = $raw->{'weight__idx_'.$i};
}
return $cook;
}
/**
- * Returns the list of current grades filled by the reviewer
+ * Returns the list of current grades filled by the reviewer indexed by dimensionid
*
* @param stdClass $assessment Assessment record
- * @return array of filtered records from the table workshop_grades
+ * @return array [int dimensionid] => stdClass workshop_grades record
*/
protected function get_current_assessment_data(stdClass $assessment) {
global $DB;
- // fetch all grades accociated with this assessment
- $grades = $DB->get_records("workshop_grades", array("assessmentid" => $assessment->id));
-
- // filter grades given under an other strategy or assessment form
- foreach ($grades as $grade) {
- if (!isset($this->dimensions[$grade->dimensionid])) {
- unset ($grades[$grade->id]);
- }
- }
- return $grades;
- }
+ list($dimsql, $dimparams) = $DB->get_in_or_equal(array_keys($this->dimensions), SQL_PARAMS_NAMED);
+ // beware! the caller may rely on the returned array is indexed by dimensionid
+ $sql = "SELECT dimensionid, *
+ FROM {workshop_grades}
+ WHERE assessmentid = :assessmentid AND strategy= :strategy AND dimensionid $dimsql";
+ $params = array('assessmentid' => $assessment->id, 'strategy' => 'acumulative');
+ $params = array_merge($params, $dimparams);
- /**
- * Reindexes the records returned by {@link get_current_assessment_data} by dimensionid
- *
- * @param mixed $grades
- * @return array
- */
- protected function reindex_grades_by_dimension($grades) {
- $reindexed = array();
- foreach ($grades as $grade) {
- $reindexed[$grade->dimensionid] = $grade;
- }
- return $reindexed;
+ return $DB->get_records_sql($sql, $params);
}
/**
if ($dimension->weight < 0) {
throw new coding_exception('Negative weights are not supported any more. Something is wrong with your data');
}
- if ($dimension->weight == 0 or $dimension->grade == 0) {
+ if (grade_floats_equal($dimension->weight, 0) or grade_floats_equal($dimension->grade, 0)) {
// does not influence the final grade
continue;
}
if ($sumweights === 0) {
return 0;
}
- return $sumgrades / $sumweights;
+ return grade_floatval($sumgrades / $sumweights);
}
/**
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
- * Unit tests for (some of) mod/workshop/grading/accumulative/strategy.php
+ * Unit tests for Accumulative grading strategy logic
*
* @package mod-workshop
* @copyright 2009 David Mudrak <david.mudrak@gmail.com>
defined('MOODLE_INTERNAL') || die();
// Include the code to test
-require_once($CFG->dirroot . '/mod/workshop/grading/accumulative/strategy.php');
+require_once($CFG->dirroot . '/mod/workshop/locallib.php');
+require_once($CFG->dirroot . '/mod/workshop/form/accumulative/lib.php');
global $DB;
Mock::generate(get_class($DB), 'mockDB');
public function test_calculate_peer_grade_one_numerical() {
// fixture set-up
- $this->strategy->dimensions[1003] = (object)array('grade' => 20, 'weight' => 1);
- $grades[] = (object)array('dimensionid' => 1003, 'grade' => 5);
+ $this->strategy->dimensions[1003] = (object)array('grade' => '20', 'weight' => '1');
+ $grades[] = (object)array('dimensionid' => 1003, 'grade' => '5.00000');
// excercise SUT
$suggested = $this->strategy->calculate_peer_grade($grades);
// validate
- $this->assertEqual(5/20, $suggested);
+ $this->assertEqual(grade_floatval(5/20), $suggested);
}
public function test_calculate_peer_grade_negative_weight() {
// fixture set-up
- $this->strategy->dimensions[1003] = (object)array('grade' => 20, 'weight' => -1);
- $grades[] = (object)array('dimensionid' => 1003, 'grade' => 20);
+ $this->strategy->dimensions[1003] = (object)array('grade' => '20', 'weight' => '-1');
+ $grades[] = (object)array('dimensionid' => 1003, 'grade' => '20');
$this->expectException('coding_exception');
// excercise SUT
$suggested = $this->strategy->calculate_peer_grade($grades);
public function test_calculate_peer_grade_one_numerical_weighted() {
// fixture set-up
- $this->strategy->dimensions[1003] = (object)array('grade' => 20, 'weight' => 3);
- $grades[] = (object)array('dimensionid' => 1003, 'grade' => 5);
+ $this->strategy->dimensions[1003] = (object)array('grade' => '20', 'weight' => '3');
+ $grades[] = (object)array('dimensionid' => '1003', 'grade' => '5');
// excercise SUT
$suggested = $this->strategy->calculate_peer_grade($grades);
// validate
- $this->assertEqual(5/20, $suggested);
+ $this->assertEqual(grade_floatval(5/20), $suggested);
}
public function test_calculate_peer_grade_three_numericals_same_weight() {
// fixture set-up
- $this->strategy->dimensions[1003] = (object)array('grade' =>20, 'weight' => 2);
- $this->strategy->dimensions[1004] = (object)array('grade' =>100, 'weight' => 2);
- $this->strategy->dimensions[1005] = (object)array('grade' =>10, 'weight' => 2);
+ $this->strategy->dimensions[1003] = (object)array('grade' => '20', 'weight' => '2');
+ $this->strategy->dimensions[1004] = (object)array('grade' => '100', 'weight' => '2');
+ $this->strategy->dimensions[1005] = (object)array('grade' => '10', 'weight' => '2');
- $grades[] = (object)array('dimensionid' => 1003, 'grade' => 11);
- $grades[] = (object)array('dimensionid' => 1004, 'grade' => 87);
- $grades[] = (object)array('dimensionid' => 1005, 'grade' => 10);
+ $grades[] = (object)array('dimensionid' => 1003, 'grade' => '11.00000');
+ $grades[] = (object)array('dimensionid' => 1004, 'grade' => '87.00000');
+ $grades[] = (object)array('dimensionid' => 1005, 'grade' => '10.00000');
// excercise SUT
$suggested = $this->strategy->calculate_peer_grade($grades);
// validate
- $this->assertEqual((11/20 + 87/100 + 10/10)/3, $suggested);
+ $this->assertEqual(grade_floatval((11/20 + 87/100 + 10/10)/3), $suggested);
}
public function test_calculate_peer_grade_three_numericals_different_weights() {
// fixture set-up
- $this->strategy->dimensions[1003] = (object)array('grade' =>15, 'weight' => 3);
- $this->strategy->dimensions[1004] = (object)array('grade' =>80, 'weight' => 1);
- $this->strategy->dimensions[1005] = (object)array('grade' =>5, 'weight' => 2);
+ $this->strategy->dimensions[1003] = (object)array('grade' => '15', 'weight' => 3);
+ $this->strategy->dimensions[1004] = (object)array('grade' => '80', 'weight' => 1);
+ $this->strategy->dimensions[1005] = (object)array('grade' => '5', 'weight' => 2);
- $grades[] = (object)array('dimensionid' => 1003, 'grade' => 7);
- $grades[] = (object)array('dimensionid' => 1004, 'grade' => 66);
- $grades[] = (object)array('dimensionid' => 1005, 'grade' => 4);
+ $grades[] = (object)array('dimensionid' => 1003, 'grade' => '7.00000');
+ $grades[] = (object)array('dimensionid' => 1004, 'grade' => '66.00000');
+ $grades[] = (object)array('dimensionid' => 1005, 'grade' => '4.00000');
// excercise SUT
$suggested = $this->strategy->calculate_peer_grade($grades);
// validate
- $this->assertEqual((7/15*3 + 66/80*1 + 4/5*2)/6, $suggested);
+ $this->assertEqual(grade_floatval((7/15*3 + 66/80*1 + 4/5*2)/6), $suggested);
}
public function test_calculate_peer_grade_one_scale_max() {
// fixture set-up
$mockscale = 'E,D,C,B,A';
- $this->strategy->dimensions[1008] = (object)array('grade' => -10, 'weight' => 1);
- $grades[] = (object)array('dimensionid' => 1008, 'grade' => 5);
- $DB->expectOnce('get_field', array("scales", "scale", array("id" => 10), MUST_EXIST));
+ $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->setReturnValue('get_field', $mockscale);
// excercise SUT
$suggested = $this->strategy->calculate_peer_grade($grades);
// validate
- $this->assertEqual(1, $suggested);
+ $this->assertEqual(1.00000, $suggested);
}
public function test_calculate_peer_grade_one_scale_min_with_scale_caching() {
global $DB;
// fixture set-up
- $this->strategy->dimensions[1008] = (object)array('grade' => -10, 'weight' => 1);
- $grades[] = (object)array('dimensionid' => 1008, 'grade' => 1);
- $DB->expectNever('get_field', array("scales", "scale", array("id" => 10), MUST_EXIST)); // cached
+ $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
// excercise SUT
$suggested = $this->strategy->calculate_peer_grade($grades);
// validate
- $this->assertEqual(0, $suggested);
+ $this->assertEqual(0.00000, $suggested);
}
public function test_calculate_peer_grade_two_scales_weighted() {
$mockscale13 = 'Poor,Good,Excellent';
$mockscale17 = '-,*,**,***,****,*****,******';
- $this->strategy->dimensions[1012] = (object)array('grade' => -13, 'weight' => 2);
- $this->strategy->dimensions[1019] = (object)array('grade' => -17, 'weight' => 3);
+ $this->strategy->dimensions[1012] = (object)array('grade' => '-13', 'weight' => 2);
+ $this->strategy->dimensions[1019] = (object)array('grade' => '-17', 'weight' => 3);
- $grades[] = (object)array('dimensionid' => 1012, 'grade' => 2); // "Good"
- $grades[] = (object)array('dimensionid' => 1019, 'grade' => 5); // "****"
+ $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('scales', '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('scales', 'scale', array('id' => 17), MUST_EXIST));
$DB->setReturnValueAt(1, 'get_field', $mockscale17);
// excercise SUT
$suggested = $this->strategy->calculate_peer_grade($grades);
// validate
- $this->assertEqual((1/2*2 + 4/6*3)/5, $suggested);
+ $this->assertEqual(grade_floatval((1/2*2 + 4/6*3)/5), $suggested);
}
public function test_calculate_peer_grade_scale_exception() {
// 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
- $grades[] = (object)array('dimensionid' => 1012, 'grade' => 4); // exceeds the number of scale items
+ $DB->expectNever('get_field', array('scales', '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');
// excercise SUT
$mform = $this->_form;
$this->mode = $this->_customdata['mode']; // influences the save buttons
- $this->strategy = $this->_customdata['strategy']; // strategy name sends back for cross check
+ $this->strategy = $this->_customdata['strategy']; // instance of the strategy api class
+ $this->workshop = $this->_customdata['workshop']; // instance of the workshop api class
+
+ // add the data common for all subplugins
+ $mform->addElement('hidden', 'strategy', $this->workshop->strategy);
// add the strategy-specific fields
$this->definition_inner($mform);
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<XMLDB PATH="mod/workshop/db" VERSION="20090908" COMMENT="XMLDB file for Moodle Comments grading strategy"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
+>
+ <TABLES>
+ <TABLE NAME="workshopform_comments" COMMENT="The assessment dimensions definitions of Comments strategy forms">
+ <FIELDS>
+ <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="workshopid"/>
+ <FIELD NAME="workshopid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="Workshop ID" PREVIOUS="id" NEXT="sort"/>
+ <FIELD NAME="sort" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="Defines the dimension order within the assessment form" PREVIOUS="workshopid" NEXT="description"/>
+ <FIELD NAME="description" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" COMMENT="The description of the dimension" PREVIOUS="sort" NEXT="descriptionformat"/>
+ <FIELD NAME="descriptionformat" TYPE="int" LENGTH="3" NOTNULL="false" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="The format of the description field" PREVIOUS="description"/>
+ </FIELDS>
+ <KEYS>
+ <KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="workshop_fk"/>
+ <KEY NAME="workshop_fk" TYPE="foreign" FIELDS="workshopid" REFTABLE="workshop" REFFIELDS="id" PREVIOUS="primary"/>
+ </KEYS>
+ </TABLE>
+ </TABLES>
+</XMLDB>
\ No newline at end of file
$this->workshop = $this->_customdata['workshop'];
$this->strategy = $this->_customdata['strategy'];
- $mform->addElement('hidden', 'workshopid', $this->workshop->id);
+ $mform->addElement('hidden', 'workshopid', $this->workshop->id); // workshopid
+ $mform->addElement('hidden', 'strategy', $this->workshop->strategy); // strategy name
$this->definition_inner($mform);
*
* Assessment dimension (also know as assessment element) represents one aspect or criterion
* to be evaluated. Each dimension consists of a set of form fields. Strategy-specific information
- * are saved in workshop_forms_{strategyname} tables.
+ * are saved in workshopform_{strategyname} tables.
*
* @param stdClass $data Raw data as returned by the form editor
* @return void
* Saves the filled assessment and returns the grade for submission as suggested by the reviewer
*
* This method processes data submitted using the form returned by {@link get_assessment_form()}
+ * The returned grade should be rounded to 5 decimals as with round($grade, 5).
*
+ * @see grade_floatval()
* @param stdClass $assessment Assessment being filled
* @param stdClass $data Raw data as returned by the assessment form
* @return float|null Raw grade (0 to 1) for submission as suggested by the peer or null if impossible to count
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
- * This file defines an mform to assess a submission by noerrors grading strategy
+ * This file defines an mform to assess a submission by numerrors grading strategy
*
* @package mod-workshop
* @copyright 2009 David Mudrak <david.mudrak@gmail.com>
require_once(dirname(dirname(__FILE__)).'/assessment_form.php'); // parent class definition
/**
- * Class representing a form for assessing submissions by noerrors grading strategy
+ * Class representing a form for assessing submissions by numerrors grading strategy
*
* @uses moodleform
*/
-class workshop_noerrors_assessment_form extends workshop_assessment_form {
+class workshop_numerrors_assessment_form extends workshop_assessment_form {
/**
* Define the elements to be displayed at the form
for ($i = 0; $i < $nodims; $i++) {
// dimension header
- $dimtitle = get_string('dimensionnumber', 'workshopgrading_noerrors', $i+1);
+ $dimtitle = get_string('dimensionnumber', 'workshopform_numerrors', $i+1);
$mform->addElement('header', "dimensionhdr__idx_$i", $dimtitle);
// dimension id
$mform->addElement('hidden', 'gradeid__idx_'.$i); // value set by set_data() later
// dimension description
- $desc = '<div id="id_dim_'.$fields->{'dimensionid__idx_'.$i}.'_desc" class="fitem description noerrors">'."\n";
+ $desc = '<div id="id_dim_'.$fields->{'dimensionid__idx_'.$i}.'_desc" class="fitem description numerrors">'."\n";
$desc .= format_text($fields->{'description__idx_'.$i}, $fields->{'description__idx_'.$i.'format'});
$desc .= "\n</div>";
$mform->addElement('html', $desc);
// evaluation of the assertion
- $label = get_string('dimensiongrade', 'workshopgrading_noerrors');
+ $label = get_string('dimensiongrade', 'workshopform_numerrors');
$mform->addElement('radio', 'grade__idx_' . $i, 'Your assessment', $fields->{'grade0__idx_'.$i}, 0); // todo localize
$mform->addElement('radio', 'grade__idx_' . $i, '', $fields->{'grade1__idx_'.$i}, 1);
$mform->setDefault('grade__idx_' . $i, 0);
// comment
- $label = get_string('dimensioncomment', 'workshopgrading_noerrors');
+ $label = get_string('dimensioncomment', 'workshopform_numerrors');
$mform->addElement('textarea', 'peercomment__idx_' . $i, $label, array('cols' => 60, 'rows' => 5));
}
$this->set_data($current);
<?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="mod/workshop/db" VERSION="20090831" COMMENT="XMLDB file for Moodle mod/workshop/grading/noerrors"
+<XMLDB PATH="mod/workshop/db" VERSION="20090908" COMMENT="XMLDB file for Moodle Number of errors subplugin"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
- <TABLE NAME="workshop_forms_noerrors" COMMENT="The assessment dimensions definitions of Number of errors grading strategy forms" NEXT="workshop_forms_noerrors_map">
+ <TABLE NAME="workshopform_numerrors" COMMENT="The assessment dimensions definitions of Number of errors grading strategy forms" NEXT="workshopform_numerrors_map">
<FIELDS>
- <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="description"/>
- <FIELD NAME="description" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" COMMENT="The description of the dimension" PREVIOUS="id" NEXT="descriptionformat"/>
+ <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="workshopid"/>
+ <FIELD NAME="workshopid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="Workshop ID" PREVIOUS="id" NEXT="sort"/>
+ <FIELD NAME="sort" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="Defines the dimension order within the assessment form" PREVIOUS="workshopid" NEXT="description"/>
+ <FIELD NAME="description" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" COMMENT="The description of the dimension" PREVIOUS="sort" NEXT="descriptionformat"/>
<FIELD NAME="descriptionformat" TYPE="int" LENGTH="3" NOTNULL="false" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="The format of the description field" PREVIOUS="description" NEXT="descriptiontrust"/>
<FIELD NAME="descriptiontrust" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" PREVIOUS="descriptionformat" NEXT="grade0"/>
<FIELD NAME="grade0" TYPE="char" LENGTH="50" NOTNULL="false" SEQUENCE="false" COMMENT="The word describing the negative evaluation (like Poor, Missing, Absent, etc.). If NULL, it defaults to a translated string False" PREVIOUS="descriptiontrust" NEXT="grade1"/>
<FIELD NAME="weight" TYPE="int" LENGTH="5" NOTNULL="false" UNSIGNED="false" DEFAULT="1" SEQUENCE="false" COMMENT="Weight of this dimension" PREVIOUS="grade1"/>
</FIELDS>
<KEYS>
- <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
+ <KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="workshop_fk"/>
+ <KEY NAME="workshop_fk" TYPE="foreign" FIELDS="workshopid" REFTABLE="workshop" REFFIELDS="id" PREVIOUS="primary"/>
</KEYS>
</TABLE>
- <TABLE NAME="workshop_forms_noerrors_map" COMMENT="This maps the number of errors to a percentual grade for submission" PREVIOUS="workshop_forms_noerrors">
+ <TABLE NAME="workshopform_numerrors_map" COMMENT="This maps the number of errors to a percentual grade for submission" PREVIOUS="workshopform_numerrors">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="workshopid"/>
<FIELD NAME="workshopid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="The id of the workshop" PREVIOUS="id" NEXT="nonegative"/>
*
* @uses moodleform
*/
-class workshop_edit_noerrors_strategy_form extends workshop_edit_strategy_form {
+class workshop_edit_numerrors_strategy_form extends workshop_edit_strategy_form {
/**
* Define the elements to be displayed at the form
*/
protected function definition_inner(&$mform) {
- $plugindefaults = get_config('workshopgrading_noerrors');
+ $plugindefaults = get_config('workshopform_numerrors');
$nodimensions = $this->_customdata['nodimensions']; // number of currently filled dimensions
$norepeats = $this->_customdata['norepeats']; // number of dimensions to display
$descriptionopts = $this->_customdata['descriptionopts']; // wysiwyg fields options
$weights = workshop_get_dimension_weights();
for ($i = 0; $i < $norepeats; $i++) {
- $mform->addElement('header', 'dimension'.$i, get_string('dimensionnumber', 'workshopgrading_noerrors', $i+1));
+ $mform->addElement('header', 'dimension'.$i, get_string('dimensionnumber', 'workshopform_numerrors', $i+1));
$mform->addElement('hidden', 'dimensionid__idx_'.$i); // the id in workshop_forms
$mform->addElement('editor', 'description__idx_'.$i.'_editor',
- get_string('dimensiondescription', 'workshopgrading_noerrors'), '', $descriptionopts);
- $mform->addElement('text', 'grade0__idx_'.$i, get_string('grade0', 'workshopgrading_noerrors'), array('size'=>'15'));
+ get_string('dimensiondescription', 'workshopform_numerrors'), '', $descriptionopts);
+ $mform->addElement('text', 'grade0__idx_'.$i, get_string('grade0', 'workshopform_numerrors'), array('size'=>'15'));
$mform->setDefault('grade0__idx_'.$i, $plugindefaults->grade0);
$mform->setType('grade0__idx_'.$i, PARAM_TEXT);
- $mform->addElement('text', 'grade1__idx_'.$i, get_string('grade1', 'workshopgrading_noerrors'), array('size'=>'15'));
+ $mform->addElement('text', 'grade1__idx_'.$i, get_string('grade1', 'workshopform_numerrors'), array('size'=>'15'));
$mform->setDefault('grade1__idx_'.$i, $plugindefaults->grade1);
$mform->setType('grade1__idx_'.$i, PARAM_TEXT);
- $mform->addElement('select', 'weight__idx_'.$i, get_string('dimensionweight', 'workshopgrading_noerrors'), $weights);
+ $mform->addElement('select', 'weight__idx_'.$i, get_string('dimensionweight', 'workshopform_numerrors'), $weights);
$mform->setDefault('weight__idx_'.$i, 1);
}
- $mform->addElement('header', 'mappingheader', get_string('grademapping', 'workshopgrading_noerrors'));
- $mform->addElement('static', 'mappinginfo', get_string('maperror', 'workshopgrading_noerrors'),
- get_string('mapgrade', 'workshopgrading_noerrors'));
+ $mform->addElement('header', 'mappingheader', get_string('grademapping', 'workshopform_numerrors'));
+ $mform->addElement('static', 'mappinginfo', get_string('maperror', 'workshopform_numerrors'),
+ get_string('mapgrade', 'workshopform_numerrors'));
// get the total weight of all items == maximum weighted number of errors
$totalweight = 0;
$percents = array();
$percents[''] = '';
for ($i = 100; $i >= 0; $i--) {
- $percents[$i] = get_string('percents', 'workshopgrading_noerrors', $i);
+ $percents[$i] = get_string('percents', 'workshopform_numerrors', $i);
}
- $mform->addElement('static', 'mappingzero', 0, get_string('percents', 'workshopgrading_noerrors', 100));
+ $mform->addElement('static', 'mappingzero', 0, get_string('percents', 'workshopform_numerrors', 100));
for ($i = 1; $i <= $totalweight; $i++) {
$selects = array();
$selects[] = $mform->createElement('select', 'map__idx_'.$i, $i, $percents);
$selects[] = $mform->createElement('static', 'mapdefault__idx_'.$i, '',
- get_string('percents', 'workshopgrading_noerrors', floor(100 - $i * 100 / $totalweight)));
+ get_string('percents', 'workshopform_numerrors', floor(100 - $i * 100 / $totalweight)));
$mform->addGroup($selects, 'grademapping'.$i, $i, array(' '), false);
$mform->setDefault('map__idx_'.$i, '');
}
$mform->registerNoSubmitButton('noadddims');
- $mform->addElement('submit', 'noadddims', get_string('addmoredimensions', 'workshopgrading_noerrors',
+ $mform->addElement('submit', 'noadddims', get_string('addmoredimensions', 'workshopform_numerrors',
WORKSHOP_STRATEGY_ADDDIMS));
$mform->closeHeaderBefore('noadddims');
$this->set_data($current);
defined('MOODLE_INTERNAL') || die();
-require_once(dirname(dirname(__FILE__)) . '/lib.php'); // interface definition
+require_once(dirname(dirname(__FILE__)) . '/lib.php'); // interface definition
+require_once($CFG->libdir . '/gradelib.php'); // to handle float vs decimal issues
/**
* "Number of errors" grading strategy logic.
*/
-class workshop_noerrors_strategy implements workshop_strategy {
+class workshop_numerrors_strategy implements workshop_strategy {
/** @var workshop the parent workshop instance */
protected $workshop;
$this->descriptionopts = array('trusttext' => true, 'subdirs' => false, 'maxfiles' => -1);
}
-/// Public API methods
-
/**
* Factory method returning an instance of an assessment form editor class
*
for ($i = 0; $i < $nodimensions; $i++) {
// prepare all editor elements
$fields = file_prepare_standard_editor($fields, 'description__idx_'.$i, $this->descriptionopts,
- $PAGE->context, 'workshop_dimension_description', $fields->{'dimensionid__idx_'.$i});
+ $PAGE->context, 'workshopform_numerrors_description', $fields->{'dimensionid__idx_'.$i});
}
$customdata = array();
$customdata['current'] = $fields;
$attributes = array('class' => 'editstrategyform');
- return new workshop_edit_noerrors_strategy_form($actionurl, $customdata, 'post', '', $attributes);
+ return new workshop_edit_numerrors_strategy_form($actionurl, $customdata, 'post', '', $attributes);
}
/**
$norepeats = $data->norepeats;
$data = $this->prepare_database_fields($data);
- $masters = $data->forms; // data to be saved into {workshop_forms}
- $locals = $data->noerrors; // data to be saved into {workshop_forms_noerrors}
- $mappings = $data->mappings; // data to be saved into {workshop_forms_noerrors_map}
- $todelete = array(); // master ids to be deleted
+ $records = $data->numerrors; // data to be saved into {workshopform_numerrors}
+ $mappings = $data->mappings; // data to be saved into {workshopform_numerrors_map}
+ $todelete = array(); // dimension ids to be deleted
for ($i=0; $i < $norepeats; $i++) {
- $local = $locals[$i];
- $master = $masters[$i];
- if (empty($local->description_editor['text'])) {
- if (!empty($master->id)) {
- // existing record with empty description - to be deleted
- $todelete[] = $master->id;
+ $record = $records[$i];
+ if (empty($record->description_editor['text'])) {
+ if (!empty($record->id)) {
+ // existing dimension record with empty description - to be deleted
+ $todelete[] = $record->id;
}
continue;
}
- if (empty($master->id)) {
+ if (empty($record->id)) {
// new field
- $local->id = $DB->insert_record('workshop_forms_noerrors', $local);
- $master->localid = $local->id;
- $master->id = $DB->insert_record('workshop_forms', $master);
+ $record->id = $DB->insert_record('workshopform_numerrors', $record);
} else {
// exiting field
- $DB->update_record('workshop_forms', $master);
- $local->id = $DB->get_field('workshop_forms', 'localid', array('id' => $master->id), MUST_EXIST);
+ $DB->update_record('workshopform_numerrors', $record);
}
// re-save with correct path to embeded media files
- $local = file_postupdate_standard_editor($local, 'description', $this->descriptionopts,
- $PAGE->context, 'workshop_dimension_description', $master->id);
- $DB->update_record('workshop_forms_noerrors', $local);
+ $record = file_postupdate_standard_editor($record, 'description', $this->descriptionopts, $PAGE->context,
+ 'workshopform_numerrors_description', $record->id);
+ $DB->update_record('workshopform_numerrors', $record);
}
$this->delete_dimensions($todelete);
continue;
}
if (isset($this->mappings[$nonegative])) {
- $DB->set_field('workshop_forms_noerrors_map', 'grade', $grade,
+ $DB->set_field('workshopform_numerrors_map', 'grade', $grade,
array('workshopid' => $this->workshop->id, 'nonegative' => $nonegative));
} else {
- $DB->insert_record('workshop_forms_noerrors_map',
+ $DB->insert_record('workshopform_numerrors_map',
(object)array('workshopid' => $this->workshop->id, 'nonegative' => $nonegative, 'grade' => $grade));
}
}
} else {
$insql = '';
}
- $sql = "DELETE FROM {workshop_forms_noerrors_map}
+ $sql = "DELETE FROM {workshopform_numerrors_map}
WHERE (($insql nonegative > :nodimensions) AND (workshopid = :workshopid))";
$params['nodimensions'] = $norepeats;
$params['workshopid'] = $this->workshop->id;
- if (!$DB->execute($sql, $params)){
- print_error('err_removegrademappings', 'workshop');
- }
+ $DB->execute($sql, $params);
}
/**
// rewrite URLs to the embeded files
for ($i = 0; $i < $nodimensions; $i++) {
$fields->{'description__idx_'.$i} = file_rewrite_pluginfile_urls($fields->{'description__idx_'.$i},
- 'pluginfile.php', $PAGE->context->id, 'workshop_dimension_description', $fields->{'dimensionid__idx_'.$i});
+ 'pluginfile.php', $PAGE->context->id, 'workshopform_numerrors_description', $fields->{'dimensionid__idx_'.$i});
}
if ('assessment' === $mode and !empty($assessment)) {
// load the previously saved assessment data
- $grades = $this->reindex_grades_by_dimension($this->get_current_assessment_data($assessment));
+ $grades = $this->get_current_assessment_data($assessment);
$current = new stdClass();
for ($i = 0; $i < $nodimensions; $i++) {
$dimid = $fields->{'dimensionid__idx_'.$i};
}
// set up the required custom data common for all strategies
+ $customdata['workshop'] = $this->workshop;
$customdata['strategy'] = $this;
$customdata['mode'] = $mode;
$customdata['nodims'] = $nodimensions;
$customdata['fields'] = $fields;
$customdata['current'] = isset($current) ? $current : null;
- $attributes = array('class' => 'assessmentform noerrors');
+ $attributes = array('class' => 'assessmentform numerrors');
- return new workshop_noerrors_assessment_form($actionurl, $customdata, 'post', '', $attributes);
+ return new workshop_numerrors_assessment_form($actionurl, $customdata, 'post', '', $attributes);
}
/**
}
for ($i = 0; $i < $data->nodims; $i++) {
$grade = new stdClass();
- $grade->id = $data->{'gradeid__idx_' . $i};
- $grade->assessmentid = $assessment->id;
- $grade->dimensionid = $data->{'dimensionid__idx_' . $i};
- $grade->grade = $data->{'grade__idx_' . $i};
- $grade->peercomment = $data->{'peercomment__idx_' . $i};
- $grade->peercommentformat = FORMAT_HTML;
+ $grade->id = $data->{'gradeid__idx_' . $i};
+ $grade->assessmentid = $assessment->id;
+ $grade->strategy = 'numerrors';
+ $grade->dimensionid = $data->{'dimensionid__idx_' . $i};
+ $grade->grade = $data->{'grade__idx_' . $i};
+ $grade->peercomment = $data->{'peercomment__idx_' . $i};
+ $grade->peercommentformat = FORMAT_HTML;
if (empty($grade->id)) {
// new grade
$grade->id = $DB->insert_record('workshop_grades', $grade);
return false;
}
-/// Internal methods
+////////////////////////////////////////////////////////////////////////////////
+// Internal methods //
+////////////////////////////////////////////////////////////////////////////////
/**
* Loads the fields of the assessment form currently used in this workshop
protected function load_fields() {
global $DB;
- $sql = 'SELECT master.id,dim.description,dim.descriptionformat,dim.grade0,dim.grade1,dim.weight
- FROM {workshop_forms} master
- INNER JOIN {workshop_forms_noerrors} dim ON (dim.id=master.localid)
- WHERE master.workshopid = :workshopid AND master.strategy = :strategy
- ORDER BY master.sort';
- $params = array('workshopid' => $this->workshop->id, 'strategy' => $this->workshop->strategy);
+ $sql = 'SELECT *
+ FROM {workshopform_numerrors}
+ WHERE workshopid = :workshopid
+ ORDER BY sort';
+ $params = array('workshopid' => $this->workshop->id);
return $DB->get_records_sql($sql, $params);
}
*/
protected function load_mappings() {
global $DB;
- return $DB->get_records('workshop_forms_noerrors_map', array('workshopid' => $this->workshop->id), 'nonegative',
+ return $DB->get_records('workshopform_numerrors_map', array('workshopid' => $this->workshop->id), 'nonegative',
'nonegative,grade'); // we can use nonegative as key here as it must be unique within workshop
}
$formdata = new stdClass();
$key = 0;
foreach ($dims as $dimension) {
- $formdata->{'dimensionid__idx_' . $key} = $dimension->id; // master id, not the local one!
+ $formdata->{'dimensionid__idx_' . $key} = $dimension->id;
$formdata->{'description__idx_' . $key} = $dimension->description;
$formdata->{'description__idx_' . $key.'format'} = $dimension->descriptionformat;
$formdata->{'grade0__idx_' . $key} = $dimension->grade0;
*
* todo we may check that there are no assessments done using these dimensions and probably remove them
*
- * @param array $masterids
+ * @param array $ids list to delete
* @return void
*/
- protected function delete_dimensions($masterids) {
+ protected function delete_dimensions(array $ids) {
global $DB, $PAGE;
- $masters = $DB->get_records_list('workshop_forms', 'id', $masterids, '', 'id,localid');
- $masterids = array_keys($masters); // now contains only those really existing
- $localids = array();
$fs = get_file_storage();
-
- foreach ($masters as $itemid => $master) {
- $fs->delete_area_files($PAGE->context->id, 'workshop_dimension_description', $itemid);
- $localids[] = $master->localid;
+ foreach ($ids as $id) {
+ $fs->delete_area_files($PAGE->context->id, 'workshopform_numerrors_description', $id);
}
- $DB->delete_records_list('workshop_forms_noerrors', 'id', $localids);
- $DB->delete_records_list('workshop_forms', 'id', $masterids);
+ $DB->delete_records_list('workshopform_numerrors', 'id', $ids);
}
/**
- * Prepares data returned by {@link workshop_edit_noerrors_strategy_form} so they can be saved into database
+ * Prepares data returned by {@link workshop_edit_numerrors_strategy_form} 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.
protected function prepare_database_fields(stdClass $raw) {
global $PAGE;
- $cook = new stdClass(); // to be returned
- $cook->forms = array(); // to be stored in {workshop_forms}
- $cook->noerrors = array(); // to be stored in {workshop_forms_noerrors}
- $cook->mappings = array(); // to be stored in {workshop_forms_noerrors_map}
+ $cook = new stdClass(); // to be returned
+ $cook->numerrors = array(); // to be stored in {workshopform_numerrors}
+ $cook->mappings = array(); // to be stored in {workshopform_numerrors_map}
for ($i = 0; $i < $raw->norepeats; $i++) {
- $cook->forms[$i] = new stdClass();
- $cook->forms[$i]->id = $raw->{'dimensionid__idx_'.$i};
- $cook->forms[$i]->workshopid = $this->workshop->id;
- $cook->forms[$i]->sort = $i + 1;
- $cook->forms[$i]->strategy = 'noerrors';
-
- $cook->noerrors[$i] = new stdClass();
- $cook->noerrors[$i]->description_editor = $raw->{'description__idx_'.$i.'_editor'};
- $cook->noerrors[$i]->grade0 = $raw->{'grade0__idx_'.$i};
- $cook->noerrors[$i]->grade1 = $raw->{'grade1__idx_'.$i};
- $cook->noerrors[$i]->weight = $raw->{'weight__idx_'.$i};
+ $cook->numerrors[$i] = new stdClass();
+ $cook->numerrors[$i]->id = $raw->{'dimensionid__idx_'.$i};
+ $cook->numerrors[$i]->workshopid = $this->workshop->id;
+ $cook->numerrors[$i]->sort = $i + 1;
+ $cook->numerrors[$i]->description_editor = $raw->{'description__idx_'.$i.'_editor'};
+ $cook->numerrors[$i]->grade0 = $raw->{'grade0__idx_'.$i};
+ $cook->numerrors[$i]->grade1 = $raw->{'grade1__idx_'.$i};
+ $cook->numerrors[$i]->weight = $raw->{'weight__idx_'.$i};
}
$i = 1;
protected function get_current_assessment_data(stdClass $assessment) {
global $DB;
- // fetch all grades accociated with this assessment
- $grades = $DB->get_records('workshop_grades', array('assessmentid' => $assessment->id));
+ list($dimsql, $dimparams) = $DB->get_in_or_equal(array_keys($this->dimensions), SQL_PARAMS_NAMED);
+ // beware! the caller may rely on the returned array is indexed by dimensionid
+ $sql = "SELECT dimensionid, *
+ FROM {workshop_grades}
+ WHERE assessmentid = :assessmentid AND strategy= :strategy AND dimensionid $dimsql";
+ $params = array('assessmentid' => $assessment->id, 'strategy' => 'numerrors');
+ $params = array_merge($params, $dimparams);
- // filter grades given under an other strategy or assessment form
- foreach ($grades as $grade) {
- if (!isset($this->dimensions[$grade->dimensionid])) {
- unset ($grades[$grade->id]);
- }
- }
- return $grades;
- }
-
- /**
- * Reindexes the records returned by {@link get_current_assessment_data} by dimensionid
- *
- * @param mixed $grades
- * @return array
- */
- protected function reindex_grades_by_dimension($grades) {
- $reindexed = array();
- foreach ($grades as $grade) {
- $reindexed[$grade->dimensionid] = $grade;
- }
- return $reindexed;
+ return $DB->get_records_sql($sql, $params);
}
/**
$grades = $this->get_current_assessment_data($assessment);
$suggested = $this->calculate_peer_grade($grades);
if (!is_null($suggested)) {
- // todo save into workshop_assessments
+ $this->workshop->set_peer_grade($assessment->id, $suggested);
}
return $suggested;
}
}
$sumerrors = 0; // sum of the weighted errors (ie the negative responses)
foreach ($grades as $grade) {
- if (empty($grade->grade)) {
+ if (grade_floats_different($grade->grade, 1.00000)) {
// negative reviewer's response
$sumerrors += $this->dimensions[$grade->dimensionid]->weight;
}
* 6 | 0%
* With this mapping, one error is mapped to 100% grade and 4 errors is mapped to 60%.
*
- * @param mixed $noerrors Number of errors
+ * @param mixed $numerrors Number of errors
* @return float Raw grade (0 to 1) for the given number of negative assertions
*/
- protected function errors_to_grade($noerrors) {
+ protected function errors_to_grade($numerrors) {
$grade = 100;
- for ($i = 1; $i <= $noerrors; $i++) {
+ for ($i = 1; $i <= $numerrors; $i++) {
if (isset($this->mappings[$i])) {
$grade = $this->mappings[$i]->grade;
}
if ($grade < 0) {
$grade = 0;
}
- return $grade/100;
+ return grade_floatval($grade/100);
}
}
defined('MOODLE_INTERNAL') || die();
-$settings->add(new admin_setting_configtext('workshopgrading_noerrors/grade0', get_string('grade0', 'workshopgrading_noerrors'),
- get_string('configgrade0', 'workshopgrading_noerrors'),
- get_string('grade0default', 'workshopgrading_noerrors'), $paramtype=PARAM_TEXT, $size=15));
+$settings->add(new admin_setting_configtext('workshopform_numerrors/grade0', get_string('grade0', 'workshopform_numerrors'),
+ get_string('configgrade0', 'workshopform_numerrors'),
+ get_string('grade0default', 'workshopform_numerrors'), $paramtype=PARAM_TEXT, $size=15));
-$settings->add(new admin_setting_configtext('workshopgrading_noerrors/grade1', get_string('grade1', 'workshopgrading_noerrors'),
- get_string('configgrade1', 'workshopgrading_noerrors'),
- get_string('grade1default', 'workshopgrading_noerrors'), $paramtype=PARAM_TEXT, $size=15));
+$settings->add(new admin_setting_configtext('workshopform_numerrors/grade1', get_string('grade1', 'workshopform_numerrors'),
+ get_string('configgrade1', 'workshopform_numerrors'),
+ get_string('grade1default', 'workshopform_numerrors'), $paramtype=PARAM_TEXT, $size=15));
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
- * Unit tests for (some of) mod/workshop/grading/noerrors/strategy.php
+ * Unit tests for Number of errors grading logic
*
* @package mod-workshop
* @copyright 2009 David Mudrak <david.mudrak@gmail.com>
defined('MOODLE_INTERNAL') || die();
// Include the code to test
-require_once($CFG->dirroot . '/mod/workshop/grading/noerrors/strategy.php');
+require_once($CFG->dirroot . '/mod/workshop/locallib.php');
+require_once($CFG->dirroot . '/mod/workshop/form/numerrors/lib.php');
global $DB;
Mock::generate(get_class($DB), 'mockDB');
/**
* Test subclass that makes all the protected methods we want to test public
*/
-class testable_workshop_noerrors_strategy extends workshop_noerrors_strategy {
+class testable_workshop_numerrors_strategy extends workshop_numerrors_strategy {
/** allows to set dimensions manually */
public $dimensions = array();
}
}
-class workshop_noerrors_strategy_test extends UnitTestCase {
+class workshop_numerrors_strategy_test extends UnitTestCase {
/** real database */
protected $realDB;
$cm = (object)array('id' => 3);
$course = (object)array('id' => 11);
- $workshop = (object)array('id' => 42, 'strategy' => 'noerrors');
+ $workshop = (object)array('id' => 42, 'strategy' => 'numerrors');
$this->workshop = new workshop($workshop, $cm, $course);
- $this->strategy = new testable_workshop_noerrors_strategy($this->workshop);
+ $this->strategy = new testable_workshop_numerrors_strategy($this->workshop);
}
public function tearDown() {
public function test_calculate_peer_grade_no_error() {
// fixture set-up
$this->strategy->dimensions = array();
- $this->strategy->dimensions[108] = (object)array('weight' => 1);
- $this->strategy->dimensions[109] = (object)array('weight' => 1);
- $this->strategy->dimensions[111] = (object)array('weight' => 1);
+ $this->strategy->dimensions[108] = (object)array('weight' => '1');
+ $this->strategy->dimensions[109] = (object)array('weight' => '1');
+ $this->strategy->dimensions[111] = (object)array('weight' => '1');
$this->strategy->mappings = array();
$grades = array();
- $grades[] = (object)array('dimensionid' => 108, 'grade' => 1);
- $grades[] = (object)array('dimensionid' => 111, 'grade' => 1);
- $grades[] = (object)array('dimensionid' => 109, 'grade' => 1);
+ $grades[] = (object)array('dimensionid' => 108, 'grade' => '1.00000');
+ $grades[] = (object)array('dimensionid' => 111, 'grade' => '1.00000');
+ $grades[] = (object)array('dimensionid' => 109, 'grade' => '1.00000');
// excercise SUT
$suggested = $this->strategy->calculate_peer_grade($grades);
// validate
public function test_calculate_peer_grade_one_error() {
// fixture set-up
$this->strategy->dimensions = array();
- $this->strategy->dimensions[108] = (object)array('weight' => 1);
- $this->strategy->dimensions[109] = (object)array('weight' => 1);
- $this->strategy->dimensions[111] = (object)array('weight' => 1);
+ $this->strategy->dimensions[108] = (object)array('weight' => '1');
+ $this->strategy->dimensions[109] = (object)array('weight' => '1');
+ $this->strategy->dimensions[111] = (object)array('weight' => '1');
$this->strategy->mappings = array(
- 1 => (object)array('grade' => 80.0),
- 2 => (object)array('grade' => 60.0),
+ 1 => (object)array('grade' => '80.00000'),
+ 2 => (object)array('grade' => '60.00000'),
);
$grades = array();
- $grades[] = (object)array('dimensionid' => 108, 'grade' => 1);
- $grades[] = (object)array('dimensionid' => 111, 'grade' => 0);
- $grades[] = (object)array('dimensionid' => 109, 'grade' => 1);
+ $grades[] = (object)array('dimensionid' => 108, 'grade' => '1.00000');
+ $grades[] = (object)array('dimensionid' => 111, 'grade' => '0.00000');
+ $grades[] = (object)array('dimensionid' => 109, 'grade' => '1.00000');
// excercise SUT
$suggested = $this->strategy->calculate_peer_grade($grades);
public function test_calculate_peer_grade_three_errors_same_weight_a() {
// fixture set-up
$this->strategy->dimensions = array();
- $this->strategy->dimensions[108] = (object)array('weight' => 1);
- $this->strategy->dimensions[109] = (object)array('weight' => 1);
- $this->strategy->dimensions[111] = (object)array('weight' => 1);
+ $this->strategy->dimensions[108] = (object)array('weight' => '1.00000');
+ $this->strategy->dimensions[109] = (object)array('weight' => '1.00000');
+ $this->strategy->dimensions[111] = (object)array('weight' => '1.00000');
$this->strategy->mappings = array(
- 1 => (object)array('grade' => 80.0),
- 2 => (object)array('grade' => 60.0),
- 3 => (object)array('grade' => 10.0),
+ 1 => (object)array('grade' => '80.00000'),
+ 2 => (object)array('grade' => '60.00000'),
+ 3 => (object)array('grade' => '10.00000'),
);
$grades = array();
- $grades[] = (object)array('dimensionid' => 108, 'grade' => 0);
- $grades[] = (object)array('dimensionid' => 111, 'grade' => 0);
- $grades[] = (object)array('dimensionid' => 109, 'grade' => 0);
+ $grades[] = (object)array('dimensionid' => 108, 'grade' => '0.00000');
+ $grades[] = (object)array('dimensionid' => 111, 'grade' => '0.00000');
+ $grades[] = (object)array('dimensionid' => 109, 'grade' => '0.00000');
// excercise SUT
$suggested = $this->strategy->calculate_peer_grade($grades);
public function test_calculate_peer_grade_three_errors_same_weight_b() {
// fixture set-up
$this->strategy->dimensions = array();
- $this->strategy->dimensions[108] = (object)array('weight' => 1);
- $this->strategy->dimensions[109] = (object)array('weight' => 1);
- $this->strategy->dimensions[111] = (object)array('weight' => 1);
+ $this->strategy->dimensions[108] = (object)array('weight' => '1.00000');
+ $this->strategy->dimensions[109] = (object)array('weight' => '1.00000');
+ $this->strategy->dimensions[111] = (object)array('weight' => '1.00000');
$this->strategy->mappings = array(
- 1 => (object)array('grade' => 80.0),
- 2 => (object)array('grade' => 60.0),
- 3 => (object)array('grade' => 0.0),
+ 1 => (object)array('grade' => '80.00000'),
+ 2 => (object)array('grade' => '60.00000'),
+ 3 => (object)array('grade' => '0.00000'),
);
$grades = array();
- $grades[] = (object)array('dimensionid' => 108, 'grade' => 0);
- $grades[] = (object)array('dimensionid' => 111, 'grade' => 0);
- $grades[] = (object)array('dimensionid' => 109, 'grade' => 0);
+ $grades[] = (object)array('dimensionid' => 108, 'grade' => '0.00000');
+ $grades[] = (object)array('dimensionid' => 111, 'grade' => '0.00000');
+ $grades[] = (object)array('dimensionid' => 109, 'grade' => '0.00000');
// excercise SUT
$suggested = $this->strategy->calculate_peer_grade($grades);
public function test_calculate_peer_grade_one_error_weighted() {
// fixture set-up
$this->strategy->dimensions = array();
- $this->strategy->dimensions[108] = (object)array('weight' => 1);
- $this->strategy->dimensions[109] = (object)array('weight' => 2);
- $this->strategy->dimensions[111] = (object)array('weight' => 0);
+ $this->strategy->dimensions[108] = (object)array('weight' => '1');
+ $this->strategy->dimensions[109] = (object)array('weight' => '2');
+ $this->strategy->dimensions[111] = (object)array('weight' => '0');
$this->strategy->mappings = array(
- 1 => (object)array('grade' => 66.0),
- 2 => (object)array('grade' => 33.0),
- 3 => (object)array('grade' => 0.0),
+ 1 => (object)array('grade' => '66.00000'),
+ 2 => (object)array('grade' => '33.00000'),
+ 3 => (object)array('grade' => '0.00000'),
);
$grades = array();
- $grades[] = (object)array('dimensionid' => 108, 'grade' => 1);
- $grades[] = (object)array('dimensionid' => 111, 'grade' => 1);
- $grades[] = (object)array('dimensionid' => 109, 'grade' => 0);
+ $grades[] = (object)array('dimensionid' => 108, 'grade' => '1.00000');
+ $grades[] = (object)array('dimensionid' => 111, 'grade' => '1.00000');
+ $grades[] = (object)array('dimensionid' => 109, 'grade' => '0.00000');
// excercise SUT
$suggested = $this->strategy->calculate_peer_grade($grades);
public function test_calculate_peer_grade_zero_weight() {
// fixture set-up
$this->strategy->dimensions = array();
- $this->strategy->dimensions[108] = (object)array('weight' => 1);
- $this->strategy->dimensions[109] = (object)array('weight' => 2);
- $this->strategy->dimensions[111] = (object)array('weight' => 0);
+ $this->strategy->dimensions[108] = (object)array('weight' => '1');
+ $this->strategy->dimensions[109] = (object)array('weight' => '2');
+ $this->strategy->dimensions[111] = (object)array('weight' => '0');
$this->strategy->mappings = array(
- 1 => (object)array('grade' => 66.0),
- 2 => (object)array('grade' => 33.0),
- 3 => (object)array('grade' => 0.0),
+ 1 => (object)array('grade' => '66.00000'),
+ 2 => (object)array('grade' => '33.00000'),
+ 3 => (object)array('grade' => '0.00000'),
);
$grades = array();
- $grades[] = (object)array('dimensionid' => 108, 'grade' => 1);
- $grades[] = (object)array('dimensionid' => 111, 'grade' => 0);
- $grades[] = (object)array('dimensionid' => 109, 'grade' => 1);
+ $grades[] = (object)array('dimensionid' => 108, 'grade' => '1.00000');
+ $grades[] = (object)array('dimensionid' => 111, 'grade' => '0.00000');
+ $grades[] = (object)array('dimensionid' => 109, 'grade' => '1.00000');
// excercise SUT
$suggested = $this->strategy->calculate_peer_grade($grades);
public function test_calculate_peer_grade_sum_weight() {
// fixture set-up
$this->strategy->dimensions = array();
- $this->strategy->dimensions[108] = (object)array('weight' => 1);
- $this->strategy->dimensions[109] = (object)array('weight' => 2);
- $this->strategy->dimensions[111] = (object)array('weight' => 3);
+ $this->strategy->dimensions[108] = (object)array('weight' => '1');
+ $this->strategy->dimensions[109] = (object)array('weight' => '2');
+ $this->strategy->dimensions[111] = (object)array('weight' => '3');
$this->strategy->mappings = array(
- 1 => (object)array('grade' => 90.0),
- 2 => (object)array('grade' => 80.0),
- 3 => (object)array('grade' => 70.0),
- 4 => (object)array('grade' => 60.0),
- 5 => (object)array('grade' => 30.0),
- 6 => (object)array('grade' => 5.0),
- 7 => (object)array('grade' => 0.0),
+ 1 => (object)array('grade' => '90.00000'),
+ 2 => (object)array('grade' => '80.00000'),
+ 3 => (object)array('grade' => '70.00000'),
+ 4 => (object)array('grade' => '60.00000'),
+ 5 => (object)array('grade' => '30.00000'),
+ 6 => (object)array('grade' => '5.00000'),
+ 7 => (object)array('grade' => '0.00000'),
);
$grades = array();
- $grades[] = (object)array('dimensionid' => 108, 'grade' => 0);
- $grades[] = (object)array('dimensionid' => 111, 'grade' => 0);
- $grades[] = (object)array('dimensionid' => 109, 'grade' => 0);
+ $grades[] = (object)array('dimensionid' => 108, 'grade' => '0.00000');
+ $grades[] = (object)array('dimensionid' => 111, 'grade' => '0.00000');
+ $grades[] = (object)array('dimensionid' => 109, 'grade' => '0.00000');
// excercise SUT
$suggested = $this->strategy->calculate_peer_grade($grades);
<?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="mod/workshop/db" VERSION="20090831" COMMENT="XMLDB file for Moodle mod/workshop/grading/rubric"
+<XMLDB PATH="mod/workshop/db" VERSION="20090908" COMMENT="XMLDB file for workshop Rubric grading strategy"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
- <TABLE NAME="workshop_forms_rubric" COMMENT="The assessment dimensions definitions of Rubric grading strategy forms" PREVIOUS="workshop_forms_nograding" NEXT="workshop_forms_rubric_levels">
+ <TABLE NAME="workshopform_rubric" COMMENT="The assessment dimensions definitions of Rubric grading strategy forms" NEXT="workshopform_rubric_levels">
<FIELDS>
- <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="description"/>
- <FIELD NAME="description" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" COMMENT="The description of the dimension" PREVIOUS="id" NEXT="descriptionformat"/>
+ <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="workshopid"/>
+ <FIELD NAME="workshopid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="Workshop ID" PREVIOUS="id" NEXT="sort"/>
+ <FIELD NAME="sort" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="Defines the dimension order within the assessment form" PREVIOUS="workshopid" NEXT="description"/>
+ <FIELD NAME="description" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" COMMENT="The description of the dimension" PREVIOUS="sort" NEXT="descriptionformat"/>
<FIELD NAME="descriptionformat" TYPE="int" LENGTH="3" NOTNULL="false" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="The format of the description field" PREVIOUS="description"/>
</FIELDS>
<KEYS>
- <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
+ <KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="workshop_fk"/>
+ <KEY NAME="workshop_fk" TYPE="foreign" FIELDS="workshopid" REFTABLE="workshop" REFFIELDS="id" PREVIOUS="primary"/>
</KEYS>
</TABLE>
- <TABLE NAME="workshop_forms_rubric_levels" COMMENT="The definition of rubric rating scales" PREVIOUS="workshop_forms_rubric">
+ <TABLE NAME="workshopform_rubric_levels" COMMENT="The definition of rubric rating scales" PREVIOUS="workshopform_rubric">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="dimensionid"/>
<FIELD NAME="dimensionid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="Which criterion this level is part of" PREVIOUS="id" NEXT="grade"/>
- <FIELD NAME="grade" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="Grade representing this level." PREVIOUS="dimensionid" NEXT="description"/>
+ <FIELD NAME="grade" TYPE="number" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" DECIMALS="5" COMMENT="Grade representing this level." PREVIOUS="dimensionid" NEXT="description"/>
<FIELD NAME="description" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" COMMENT="The definition of this level" PREVIOUS="grade" NEXT="descriptionformat"/>
<FIELD NAME="descriptionformat" TYPE="int" LENGTH="3" NOTNULL="false" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="The format of the description field" PREVIOUS="description"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="dimension_fk"/>
- <KEY NAME="dimension_fk" TYPE="foreign" FIELDS="dimensionid" REFTABLE="workshop_forms_rubric" REFFIELDS="id" PREVIOUS="primary"/>
+ <KEY NAME="dimension_fk" TYPE="foreign" FIELDS="dimensionid" REFTABLE="workshopform_rubric" REFFIELDS="id" PREVIOUS="primary"/>
</KEYS>
</TABLE>
</TABLES>
-</XMLDB>
+</XMLDB>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="mod/workshop/db" VERSION="20090831" COMMENT="XMLDB file for Moodle mod/workshop/grading/nograding"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
->
- <TABLES>
- <TABLE NAME="workshop_forms_nograding" COMMENT="The assessment dimensions definitions of No grading strategy forms">
- <FIELDS>
- <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="description"/>
- <FIELD NAME="description" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" COMMENT="The description of the dimension" PREVIOUS="id" NEXT="descriptionformat"/>
- <FIELD NAME="descriptionformat" TYPE="int" LENGTH="3" NOTNULL="false" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="The format of the description field" PREVIOUS="description"/>
- </FIELDS>
- <KEYS>
- <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
- </KEYS>
- </TABLE>
- </TABLES>
-</XMLDB>
$string['allocationdone'] = 'Allocation done';
$string['allocationerror'] = 'Allocation error';
$string['allocation'] = 'Submission allocation';
-$string['areadimensiondescription'] = 'Assessment form fields';
$string['areasubmissionattachment'] = 'Submission attachments';
$string['areasubmissioncontent'] = 'Submission texts';
$string['assessallexamples'] = 'Assess all examples';
case FEATURE_GROUPMEMBERSONLY: return true;
case FEATURE_MOD_INTRO: return true;
case FEATURE_MOD_SUBPLUGINS: return array(
- 'workshopgrading' => 'mod/workshop/grading',
+ 'workshopform' => 'mod/workshop/form',
'workshopallocation' => 'mod/workshop/allocation'
);
default: return null;
$data->timemodified = time();
$data->id = $data->instance;
+ // 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
+
$DB->update_record('workshop', $data);
$context = get_context_instance(CONTEXT_MODULE, $data->coursemodule);
* The file area workshop_intro for the activity introduction field is added automatically
* by {@link file_browser::get_file_info_module()}
*
+ * TODO: we use the following areas
+ * workshopform_accumulative_description
+ * workshopform_numerrors_description
+ *
* @param stdClass $course
* @param stdClass $cm
* @param stdClass $context
$areas = array();
if (has_capability('moodle/course:managefiles', $context)) {
$areas['workshop_instructauthors'] = get_string('areainstructauthors', 'workshop');
- $areas['workshop_dimension_description'] = get_string('areadimensiondescription', 'workshop');
$areas['workshop_submission_content'] = get_string('areasubmissioncontent', 'workshop');
$areas['workshop_submission_attachment'] = get_string('areasubmissionattachment', 'workshop');
}
send_stored_file($file, $lifetime, 0);
}
+ /** todo - this filearea has been replaced by subplugins' areas
if ($filearea === 'workshop_dimension_description') {
$itemid = (int)array_shift($args);
if (!$dimension = $DB->get_record('workshop_forms', array('id' => $itemid))) {
// finally send the file
send_stored_file($file);
}
+ */
if ($filearea === 'workshop_submission_content' or $filearea === 'workshop_submission_attachment') {
$itemid = (int)array_shift($args);
return new file_info_stored($browser, $context, $storedfile, $urlbase, $topvisiblename, true, true, false, false);
}
+ /* todo was replaced by subplugins' areas
if ($filearea === 'workshop_dimension_description') {
// always only itemid 0 - TODO not true, review
}
return new file_info_stored($browser, $context, $storedfile, $urlbase, $areas[$filearea], false, true, true, false);
}
+ */
if ($filearea === 'workshop_instructauthors') {
// always only itemid 0
/**
* Return an array of the localized grading strategy names
*
+ * @todo remove this function from lib.php
* $return array Array ['string' => 'string']
*/
function workshop_get_strategies() {
- $installed = get_plugin_list('workshopgrading');
+ $installed = get_plugin_list('workshopform');
$forms = array();
foreach ($installed as $strategy => $strategypath) {
- if (file_exists($strategypath . '/strategy.php')) {
- $forms[$strategy] = get_string('pluginname', 'workshopgrading_' . $strategy);
+ if (file_exists($strategypath . '/lib.php')) {
+ $forms[$strategy] = get_string('pluginname', 'workshopform_' . $strategy);
}
}
return $forms;
/** @var stdClass course record */
public $course = null;
- /** @var stdClass the workshop instance context */
- public $context = null;
-
/**
* @var workshop_strategy grading strategy instance
* Do not use directly, get the instance using {@link workshop::grading_strategy_instance()}
*/
protected $strategyinstance = null;
- /** @var stdClass underlying database record */
- protected $dbrecord = null;
-
/**
* Initializes the workshop API instance using the data from DB
*
* @param stdClass $course Course record from {course} table
*/
public function __construct(stdClass $dbrecord, stdClass $cm, stdClass $course) {
- $this->dbrecord = $dbrecord;
- $this->cm = $cm;
- $this->course = $course;
- $this->context = get_context_instance(CONTEXT_MODULE, $this->cm->id);
- }
-
- /**
- * Magic method to retrieve the value of the underlying database record's field
- *
- * @throws coding_exception if the field does not exist
- * @param mixed $key the name of the database field
- * @return mixed|null the value of the field
- */
- public function __get($key) {
- if (!isset($this->dbrecord->{$key})) {
- // todo remove the comment here // throw new coding_exception('You are trying to get a non-existing property');
- return null;
+ foreach ($dbrecord as $field => $value) {
+ $this->{$field} = $value;
}
- return $this->dbrecord->{$key};
+ $this->cm = $cm;
+ $this->course = $course; // beware - this replaces the standard course field in the instance table
+ // this is intentional - IMO there should be no such field as it violates
+ // 3rd normal form with no real performance gain
}
/**
*
* Example submissions are ignored.
*
- * @param array $userids
- * @return TODO
+ * @param array $userids
+ * @return array
*/
protected function users_with_submission(array $userids) {
global $DB;
+ if (empty($userids)) {
+ return array();
+ }
$userswithsubmission = array();
list($usql, $uparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
$sql = "SELECT id,userid
*
* The returned objects contain id, lastname and firstname properties and are ordered by lastname,firstname
*
+ * @param stdClass $context
* @param bool $musthavesubmission If true, return only users who have already submitted. All possible authors otherwise.
* @return array array[userid] => stdClass{->id ->lastname ->firstname}
*/
- public function get_potential_authors($musthavesubmission=true) {
- $users = get_users_by_capability($this->context, 'mod/workshop:submit',
+ public function get_potential_authors(stdClass $context, $musthavesubmission=true) {
+ $users = get_users_by_capability($context, 'mod/workshop:submit',
'u.id, u.lastname, u.firstname', 'u.lastname,u.firstname', '', '', '', '', false, false, true);
if ($musthavesubmission) {
$users = array_intersect_key($users, $this->users_with_submission(array_keys($users)));
*
* The returned objects contain id, lastname and firstname properties and are ordered by lastname,firstname
*
+ * @param stdClass $context
* @param bool $musthavesubmission If true, return only users who have already submitted. All possible users otherwise.
* @return array array[userid] => stdClass{->id ->lastname ->firstname}
*/
- public function get_potential_reviewers($musthavesubmission=false) {
- $users = get_users_by_capability($this->context, 'mod/workshop:peerassess',
+ public function get_potential_reviewers(stdClass $context, $musthavesubmission=false) {
+ $users = get_users_by_capability($context, 'mod/workshop:peerassess',
'u.id, u.lastname, u.firstname', 'u.lastname,u.firstname', '', '', '', '', false, false, true);
if ($musthavesubmission) {
// users without their own submission can not be reviewers
*
* @param mixed $userid int|array|'all' If set to [array of] integer, return submission[s] of the given user[s] only
* @param mixed $examples false|true|'all' Only regular submissions, only examples, all submissions
- * @return stdClass moodle_recordset
+ * @return array
*/
public function get_submissions($userid='all', $examples=false) {
global $DB;
* Note that the returned recordset includes participants without submission as well as those
* without any review allocated yet.
*
- * @return stdClass moodle_recordset
+ * @return null|stdClass moodle_recordset
*/
public function get_allocations_recordset() {
- global $DB;
+ global $DB, $PAGE;
- $users = get_users_by_capability($this->context, array('mod/workshop:submit', 'mod/workshop:peerassess'),
+ $users = get_users_by_capability($PAGE->context, array('mod/workshop:submit', 'mod/workshop:peerassess'),
'u.id', 'u.lastname,u.firstname', '', '', '', '', false, false, true);
+ if (empty($users)) {
+ return null;
+ }
+
list($usql, $params) = $DB->get_in_or_equal(array_keys($users), SQL_PARAMS_NAMED);
$params['workshopid'] = $this->id;
global $CFG; // because we require other libs here
if (is_null($this->strategyinstance)) {
- $strategylib = dirname(__FILE__) . '/grading/' . $this->strategy . '/strategy.php';
+ $strategylib = dirname(__FILE__) . '/form/' . $this->strategy . '/lib.php';
if (is_readable($strategylib)) {
require_once($strategylib);
} else {
- throw new coding_exception('the grading subplugin must contain library ' . $strategylib);
+ throw new coding_exception('the grading forms subplugin must contain library ' . $strategylib);
}
$classname = 'workshop_' . $this->strategy . '_strategy';
$this->strategyinstance = new $classname($this);
$installed = get_plugin_list('workshopallocation');
$forms = array();
foreach ($installed as $allocation => $allocationpath) {
- if (file_exists($allocationpath . '/allocator.php')) {
+ if (file_exists($allocationpath . '/lib.php')) {
$forms[$allocation] = get_string('pluginname', 'workshopallocation_' . $allocation);
}
}
public function allocator_instance($method) {
global $CFG; // because we require other libs here
- $allocationlib = dirname(__FILE__) . '/allocation/' . $method . '/allocator.php';
+ $allocationlib = dirname(__FILE__) . '/allocation/' . $method . '/lib.php';
if (is_readable($allocationlib)) {
require_once($allocationlib);
} else {
- throw new coding_exception('Unable to find allocator.php');
+ throw new coding_exception('Unable to find the allocation library ' . $allocationlib);
}
$classname = 'workshop_' . $method . '_allocator';
return new $classname($this);
* @return string
*/
public function strategy_name() {
- return get_string('pluginname', 'workshopgrading_' . $this->strategy);
+ return get_string('pluginname', 'workshopform_' . $this->strategy);
}
/**
* Prepare an individual workshop plan for the given user.
*
- * @param mixed $userid
- * @return TODO
+ * @param int $userid whom the plan is prepared for
+ * @param stdClass context of the planned workshop
+ * @return stdClass data object to be passed to the renderer
*/
- public function prepare_user_plan($userid) {
+ public function prepare_user_plan($userid, stdClass $context) {
global $DB;
$phases = array();
$phase = new stdClass();
$phase->title = get_string('phasesetup', 'workshop');
$phase->tasks = array();
- if (has_capability('moodle/course:manageactivities', $this->context, $userid)) {
+ if (has_capability('moodle/course:manageactivities', $context, $userid)) {
$task = new stdClass();
$task->title = get_string('taskintro', 'workshop');
$task->link = $this->updatemod_url();
$task->completed = !(trim(strip_tags($this->intro)) == '');
$phase->tasks['intro'] = $task;
}
- if (has_capability('moodle/course:manageactivities', $this->context, $userid)) {
+ if (has_capability('moodle/course:manageactivities', $context, $userid)) {
$task = new stdClass();
$task->title = get_string('taskinstructauthors', 'workshop');
$task->link = $this->updatemod_url();
$task->completed = !(trim(strip_tags($this->instructauthors)) == '');
$phase->tasks['instructauthors'] = $task;
}
- if (has_capability('mod/workshop:editdimensions', $this->context, $userid)) {
+ if (has_capability('mod/workshop:editdimensions', $context, $userid)) {
$task = new stdClass();
$task->title = get_string('editassessmentform', 'workshop');
$task->link = $this->editform_url();
$phase = new stdClass();
$phase->title = get_string('phasesubmission', 'workshop');
$phase->tasks = array();
- if (has_capability('mod/workshop:submit', $this->context, $userid)) {
+ if (has_capability('mod/workshop:submit', $context, $userid)) {
$task = new stdClass();
$task->title = get_string('tasksubmit', 'workshop');
$task->link = $this->submission_url();
}
$phase->tasks['submit'] = $task;
}
- if (has_capability('moodle/course:manageactivities', $this->context, $userid)) {
+ if (has_capability('moodle/course:manageactivities', $context, $userid)) {
$task = new stdClass();
$task->title = get_string('taskinstructreviewers', 'workshop');
$task->link = $this->updatemod_url();
$phase->tasks['instructreviewers'] = $task;
}
$phases[self::PHASE_SUBMISSION] = $phase;
- if (has_capability('mod/workshop:allocate', $this->context, $userid)) {
+ if (has_capability('mod/workshop:allocate', $context, $userid)) {
$task = new stdClass();
$task->title = get_string('allocate', 'workshop');
$task->link = $this->allocation_url();
- $rs = $this->get_allocations_recordset();
$authors = array();
$allocations = array(); // 'submissionid' => isallocated
- foreach ($rs as $allocation) {
- if (!isset($authors[$allocation->authorid])) {
- $authors[$allocation->authorid] = true;
- }
- if (isset($allocation->submissionid)) {
- if (!isset($allocations[$allocation->submissionid])) {
- $allocations[$allocation->submissionid] = false;
+ $rs = $this->get_allocations_recordset();
+ if (!is_null($rs)) {
+ foreach ($rs as $allocation) {
+ if (!isset($authors[$allocation->authorid])) {
+ $authors[$allocation->authorid] = true;
}
- if (!empty($allocation->reviewerid)) {
- $allocations[$allocation->submissionid] = true;
+ if (isset($allocation->submissionid)) {
+ if (!isset($allocations[$allocation->submissionid])) {
+ $allocations[$allocation->submissionid] = false;
+ }
+ if (!empty($allocation->reviewerid)) {
+ $allocations[$allocation->submissionid] = true;
+ }
}
}
+ $rs->close();
}
$numofauthors = count($authors);
$numofsubmissions = count($allocations);
$numofallocated = count(array_filter($allocations));
- $rs->close();
if ($numofsubmissions == 0) {
$task->completed = null;
} elseif ($numofsubmissions == $numofallocated) {
$phase = new stdClass();
$phase->title = get_string('phaseassessment', 'workshop');
$phase->tasks = array();
- $phase->isreviewer = has_capability('mod/workshop:peerassess', $this->context, $userid);
+ $phase->isreviewer = has_capability('mod/workshop:peerassess', $context, $userid);
$phase->assessments = $this->get_assessments_by_reviewer($userid);
$numofpeers = 0; // number of allocated peer-assessments
$numofpeerstodo = 0; // number of peer-assessments to do
}
// Add phase swithing actions
- if (has_capability('mod/workshop:switchphase', $this->context, $userid)) {
+ if (has_capability('mod/workshop:switchphase', $context, $userid)) {
foreach ($phases as $phasecode => $phase) {
if (! $phase->active) {
$action = new stdClass();
get_string('configassessmentcomps', 'workshop'), WORKSHOP_COMPARISON_NORMAL, $levels));
// include the settings of grading strategy subplugins
-$strategies = get_plugin_list('workshopgrading');
+$strategies = get_plugin_list('workshopform');
foreach ($strategies as $strategy => $path) {
if (file_exists($settingsfile = $path . '/settings.php')) {
- $settings->add(new admin_setting_heading('workshopgradingsetting'.$strategy,
- get_string('pluginname', 'workshopgrading_' . $strategy), ''));
+ $settings->add(new admin_setting_heading('workshopformsetting'.$strategy,
+ get_string('pluginname', 'workshopform_' . $strategy), ''));
include($settingsfile);
}
}
/**
* Submission - one line summary display
*/
-.submission-summary {
+.mod-workshop .submission-summary {
position: relative;
margin-bottom: 10px;
}
-.submission-summary .title,
-.submission-summary .author,
-.submission-summary .author .fullname,
-.submission-summary .author .picture {
+.mod-workshop .submission-summary .title,
+.mod-workshop .submission-summary .author,
+.mod-workshop .submission-summary .author .fullname,
+.mod-workshop .submission-summary .author .picture {
display: inline;
}
-.submission-summary .title,
-.submission-summary .userdate {
+.mod-workshop .submission-summary .title,
+.mod-workshop .submission-summary .userdate {
margin: 0px 0px 0px 40px;
}
-.submission-summary .author {
+.mod-workshop .submission-summary .author {
margin-left: 1ex;
}
-.submission-summary.anonymous .title,
-.submission-summary.anonymous .author,
-.submission-summary.anonymous .userdate {
+.mod-workshop .submission-summary.anonymous .title,
+.mod-workshop .submission-summary.anonymous .author,
+.mod-workshop .submission-summary.anonymous .userdate {
margin: 0px 0px 0px 5px;
}
-.submission-summary .userdate {
+.mod-workshop .submission-summary .userdate {
font-size: x-small;
color: #333;
}
-.submission-summary .userdate span {
+.mod-workshop .submission-summary .userdate span {
font-style: italic;
}
-.submission-summary .author .picture {
+.mod-workshop .submission-summary .author .picture {
position: absolute;
top: 0px;
left: 0px;
/**
* Submission - full display
*/
-.submission-full {
+.mod-workshop .submission-full {
border: 1px solid #ddd;
margin: 0px 0px 1em 0px;
}
-.submission-full .header {
+.mod-workshop .submission-full .header {
position: relative;
background-color: #ddd;
padding: 3px;
}
-.submission-full .header .title,
-.submission-full .header .author,
-.submission-full .header .userdate {
+.mod-workshop .submission-full .header .title,
+.mod-workshop .submission-full .header .author,
+.mod-workshop .submission-full .header .userdate {
margin: 0px 0px 0px 80px;
}
-.submission-full.anonymous .header .title,
-.submission-full.anonymous .header .author,
-.submission-full.anonymous .header .userdate {
+.mod-workshop .submission-full.anonymous .header .title,
+.mod-workshop .submission-full.anonymous .header .author,
+.mod-workshop .submission-full.anonymous .header .userdate {
margin: 0px 0px 0px 5px;
}
-.submission-full .header .userdate.modified {
+.mod-workshop .submission-full .header .userdate.modified {
margin-left: 10px;
padding-left: 10px;
border-left: 1px solid #000;
}
-.submission-full .header .userdate {
+.mod-workshop .submission-full .header .userdate {
font-size: x-small;
color: #333;
display: inline;
}
-.submission-full .header .userdate span {
+.mod-workshop .submission-full .header .userdate span {
font-style: italic;
}
-.submission-full .header .author .picture {
+.mod-workshop .submission-full .header .author .picture {
position: absolute;
top: 3px;
left: 3px;
}
-.submission-full .content,
-.submission-full .attachments {
+.mod-workshop .submission-full .content,
+.mod-workshop .submission-full .attachments {
padding: 5px 10px;
}
-.submission-full .attachments .files img.icon {
+.mod-workshop .submission-full .attachments .files img.icon {
margin-right: 5px;
}
margin-top: 1em;
}
-/**
- * Assessment
- */
-.assessmentform .description {
- margin: 0px 1em;
-}
-
/**
* User plan
*/
-.userplan {
+.mod-workshop .userplan {
width: 70%;
margin: 1em auto 1em auto;
font-size: 80%;
+ border-left: 1px solid #ddd;
+ border-right: 1px solid #ddd;
}
-.userplan th {
+.mod-workshop .userplan th {
vertical-align: bottom;
white-space: normal;
color: #999;
+ border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
padding: 3px;
}
-.userplan th.active {
+.mod-workshop .userplan th.active {
vertical-align: top;
color: black;
font-size: 140%;
border: 1px solid #ddd;
border-bottom: none;
- background-color: #e7f1c3;
+ background: #e7f1c3;
}
-.userplan td {
+.mod-workshop .userplan td {
width: 20%;
vertical-align: top;
border-right: 1px solid #ddd;
background-color: #f5f5f5;
}
-.userplan td,
-.userplan td a,
-.userplan td a:link,
-.userplan td a:hover,
-.userplan td a:visited,
-.userplan td a:active {
+.mod-workshop .userplan td,
+.mod-workshop .userplan td a,
+.mod-workshop .userplan td a:link,
+.mod-workshop .userplan td a:hover,
+.mod-workshop .userplan td a:visited,
+.mod-workshop .userplan td a:active {
color: #999;
}
-.userplan td.active,
-.userplan td.active a,
-.userplan td.active a:link,
-.userplan td.active a:hover,
-.userplan td.active a:visited,
-.userplan td.active a:active {
+.mod-workshop .userplan td.active,
+.mod-workshop .userplan td.active a,
+.mod-workshop .userplan td.active a:link,
+.mod-workshop .userplan td.active a:hover,
+.mod-workshop .userplan td.active a:visited,
+.mod-workshop .userplan td.active a:active {
color: black;
}
-.userplan td.lastcol {
+.mod-workshop .userplan td.lastcol {
border-right: none;
}
-.userplan td.active {
+.mod-workshop .userplan td.active {
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
background-color: #e7f1c3;
}
-.userplan tr.phasetasks li {
+.mod-workshop .userplan tr.phasetasks li {
background-image: url(../../pix/i/completion-auto-n.gif);
background-position: top left;
background-repeat: no-repeat;
}
-.userplan tr.phasetasks li.completed {
+.mod-workshop .userplan tr.phasetasks li.completed {
background-image: url(../../pix/i/completion-auto-y.gif);
}
-.userplan tr.phasetasks li.fail {
+.mod-workshop .userplan tr.phasetasks li.fail {
background-image: url(../../pix/i/completion-auto-fail.gif);
}
-.userplan tr.phasetasks li.info {
+.mod-workshop .userplan tr.phasetasks li.info {
background-image: url(../../pix/i/info.gif);
}
-.userplan tr.phasetasks .tasks {
+.mod-workshop .userplan tr.phasetasks .tasks {
list-style:none;
margin: 3px;
padding: 0px;
}
-.userplan tr.phasetasks .title {
+.mod-workshop .userplan tr.phasetasks .title {
padding: 0px 10px 0px 20px;
}
-.userplan tr.phasetasks .details {
+.mod-workshop .userplan tr.phasetasks .details {
padding: 0px 10px 0px 25px;
font-size: 80%;
}
/**
* Assessment
*/
-.assessment-summary.graded {
+.mod-workshop .assessment-summary.graded {
background-color: #e7f1c3;
}
+.mod-workshop .assessmentform .description {
+ margin: 0px 1em;
+}
$activated = array();
// top level tabs
-if (has_capability('mod/workshop:view', $workshop->context)) {
+if (has_capability('mod/workshop:view', $PAGE->context)) {
$row[] = new tabobject('info', $workshop->view_url()->out(), get_string('info', 'workshop'));
}
-if (has_capability('mod/workshop:editdimensions', $workshop->context)) {
+if (has_capability('mod/workshop:editdimensions', $PAGE->context)) {
$row[] = new tabobject('editform', $workshop->editform_url()->out(), get_string('editassessmentform', 'workshop'));
}
-if (has_capability('mod/workshop:submit', $workshop->context)) {
+if (has_capability('mod/workshop:submit', $PAGE->context)) {
$row[] = new tabobject('submission', $workshop->submission_url()->out(), get_string('submission', 'workshop'));
}
-if (has_capability('mod/workshop:allocate', $workshop->context)) {
+if (has_capability('mod/workshop:allocate', $PAGE->context)) {
$row[] = new tabobject('allocation', $workshop->allocation_url()->out(), get_string('allocate', 'workshop'));
}
if (has_capability('moodle/site:config', get_system_context())) {
echo $OUTPUT->header();
include(dirname(__FILE__) . '/tabs.php');
echo $OUTPUT->heading(format_string($workshop->name), 2);
-echo $wsoutput->user_plan($workshop->prepare_user_plan($USER->id));
+echo $wsoutput->user_plan($workshop->prepare_user_plan($USER->id, $PAGE->context));
switch ($workshop->phase) {
case workshop::PHASE_SETUP: