diff --git a/classes/output/renderer.php b/classes/output/renderer.php index 5249bd9c14073fdab24a8d06110492783e5e1567..8df3900218b421b881727d96fab27a431b7af305 100644 --- a/classes/output/renderer.php +++ b/classes/output/renderer.php @@ -140,11 +140,11 @@ class qtype_moopt_renderer extends qtype_renderer { } if (!$qa->get_state()->is_graded() && ($qa->get_question()->showstudgradingscheme || has_capability('mod/quiz:grade', $PAGE->context))) { $gradingscheme = $this->render_grading_scheme($qa); - //$o .= html_writer::tag('div', $gradingscheme, array('class' => 'gradingscheme')); if(!$qa->get_question()->showstudgradingscheme){ $o .= html_writer::tag('div', $gradingscheme, array('class' => 'gradingscheme')); + } else { + $o .= html_writer::tag('div', $gradingscheme); } - $o .= html_writer::tag('div', $gradingscheme); } if ($qa->get_state()->is_finished() || $laststep->has_behaviour_var('_completeForGrading')) { // state->is_finished() implies that a question attempt has been finished by the student, @@ -180,7 +180,7 @@ class qtype_moopt_renderer extends qtype_renderer { global $PAGE; $o = '<br>'; - $o .= $this->output->heading(get_string('gradingscheme', 'qtype_moopt'), 3);# + $o .= $this->output->heading(get_string('gradingscheme', 'qtype_moopt'), 3); $blockid = "moopt-gradingscheme-" . $qa->get_usage_id() . "-" . $qa->get_slot(); $PAGE->requires->js_call_amd('qtype_moopt/toggle_all_grading_scheme_buttons', 'init', [$blockid]); @@ -215,50 +215,68 @@ class qtype_moopt_renderer extends qtype_renderer { private function render_downloadable_files(question_attempt $qa, question_display_options $options) { global $DB; + $question = $qa->get_question(); + $questionid = $question->id; + $o = ''; + $isteacher = has_capability('mod/quiz:grade', $options->context); + + $studentfiles = $DB->get_records('qtype_moopt_files', array('questionid' => $questionid, + 'visibletostudents' => 'yes', 'usagebylms' => 'download')); + if(count($studentfiles) != 0) { + $o .= $this->render_downloadable_files_only($qa, $options, $studentfiles, 'providedfiles'); + } + + if ($isteacher){ + $teacherfiles = $DB->get_records('qtype_moopt_files', array('questionid' => $questionid, 'visibletostudents' => 'no')); + if(count($teacherfiles) != 0) { + $o .= $this->render_downloadable_files_only($qa, $options, $teacherfiles, 'providedfilesteacher'); + } + } + return $o; + } + + private function render_downloadable_files_only (question_attempt $qa, question_display_options $options, $files, $divclass) { $question = $qa->get_question(); $qubaid = $qa->get_usage_id(); $slot = $qa->get_slot(); $questionid = $question->id; - $o = ''; $isteacher = has_capability('mod/quiz:grade', $options->context); + $o = ''; - $files = $DB->get_records('qtype_moopt_files', array('questionid' => $questionid)); $anythingtodisplay = false; - if (count($files) != 0) { // TODO: this check should happen before these render methods are called - $downloadurls = ''; - $downloadurls .= $this->output->heading(get_string('providedfiles', 'qtype_moopt'), 3); - $downloadurls .= html_writer::start_div('providedfiles'); - $downloadurls .= '<ul>'; - foreach ($files as $file) { - // skip files that are - // - not configured to be downloadable (usagebylms) - // - not visible to students - if ($file->usagebylms == 'display' - || ($file->visibletostudents == 'no' && !$isteacher) - || ($file->usagebylms == 'edit' && !$isteacher)) { - continue; - } - - $anythingtodisplay = true; - $url = moodle_url::make_pluginfile_url($question->contextid, COMPONENT_NAME, $file->filearea, - "$qubaid/$slot/$questionid", $file->filepath, $file->filename, true); - if ($file->filearea == PROFORMA_ATTACHED_TASK_FILES_FILEAREA) { - $folderdisplay = $file->filepath; - // remove leading slash: - if (strlen($folderdisplay) > 0 && $folderdisplay[0] == '/') $folderdisplay = substr($folderdisplay, 1); - } else { - $folderdisplay = ''; - } - $linkdisplay = $folderdisplay . $file->filename; - $downloadurls .= '<li><a href="' . $url . '">' . $linkdisplay . '</a></li>'; + $downloadurls = ''; + if(!$isteacher) { + $o .= $this->output->heading(get_string('providedfiles', 'qtype_moopt'), 3); + } + $downloadurls .= html_writer::start_div($divclass); + $downloadurls .= '<ul>'; + foreach ($files as $file) { + // skip files that are + // - not configured to be downloadable (usagebylms) + if ($file->usagebylms == 'display') { + continue; } - $downloadurls .= '</ul>'; - $downloadurls .= html_writer::end_div('providedfiles'); - if ($anythingtodisplay) { - $o .= $downloadurls; + $anythingtodisplay = true; + $url = moodle_url::make_pluginfile_url($question->contextid, COMPONENT_NAME, $file->filearea, + "$qubaid/$slot/$questionid", $file->filepath, $file->filename, true); + if ($file->filearea == PROFORMA_ATTACHED_TASK_FILES_FILEAREA) { + $folderdisplay = $file->filepath; + // remove leading slash: + if (strlen($folderdisplay) > 0 && $folderdisplay[0] == '/') $folderdisplay = substr($folderdisplay, 1); + } else { + $folderdisplay = ''; } + $linkdisplay = $folderdisplay . $file->filename; + $downloadurls .= '<li><a href="' . $url . '">' . $linkdisplay . '</a></li>'; } + $downloadurls .= '</ul>'; + $downloadurls .= html_writer::end_div($divclass); + + if ($anythingtodisplay) { + $o .= $downloadurls; + } + return $o; } diff --git a/classes/utility/proforma_xml/grading_scheme_handler.php b/classes/utility/proforma_xml/grading_scheme_handler.php index d4d9259108eeec3a01c66c9bdc43ebe817b5b39c..1f6db5ba37a5bd1c23c6b55e532f069c627be0c1 100644 --- a/classes/utility/proforma_xml/grading_scheme_handler.php +++ b/classes/utility/proforma_xml/grading_scheme_handler.php @@ -238,10 +238,19 @@ class grading_scheme_handler { private function fill_grading_hints_node_with_testref_infos(\DOMElement $elem, grading_hints_node $node) { $refid = $elem->getAttribute('ref'); - if (($titlelist = $elem->getElementsByTagNameNS($this->namespace, 'title'))->length == 1) { - $node->set_title($titlelist[0]->nodeValue); - } else { - $node->set_title($this->tests[$refid] !== null && $this->tests[$refid]->getElementsByTagNameNS($this->namespace, 'title')[0]->nodeValue); + $foundTitle = false; + foreach($elem->childNodes as $child) { + if ($child->localName == 'title') { + $node->set_title($child->nodeValue); + $foundTitle = true; + } + } + if(!$foundTitle) { + $title = ""; + if ($this->tests[$refid] !== null && $this->tests[$refid]->getElementsByTagNameNS($this->namespace, 'title')->length >= 1) { + $title = $this->tests[$refid]->getElementsByTagNameNS($this->namespace, 'title')[0]->nodeValue; + } + $node->set_title($title); } if (($list = $elem->getElementsByTagNameNS($this->namespace, 'description'))->length == 1) { $node->set_description($list[0]->nodeValue); diff --git a/classes/utility/proforma_xml/separate_feedback_handler.php b/classes/utility/proforma_xml/separate_feedback_handler.php index 043849213e119371ac9a59e938ea9c64db8cd403..3425e3399a1215e5517223996a71bed08028c14b 100644 --- a/classes/utility/proforma_xml/separate_feedback_handler.php +++ b/classes/utility/proforma_xml/separate_feedback_handler.php @@ -257,20 +257,54 @@ class separate_feedback_handler { $gradinghintsnode->getSeparateFeedbackData()->set_has_internal_error($result->getAttribute('is-internal-error') == "true"); } + $gradinghintsnode->getSeparateFeedbackData()->set_rawscore($rawscore); + // Execute functions and only later set score to 0 because the above functions also fills the feedback elements. if ($this->should_be_nullified_node($gradinghintsnode)) { - $rawscore = 0; + $score = 0; $gradinghintsnode->getSeparateFeedbackData()->set_nullified(true); + } else { + $score = $rawscore * $gradinghintsnode->get_weight() * $this->scorecompensationfactor; } - $gradinghintsnode->getSeparateFeedbackData()->set_rawscore($rawscore); - - $score = $rawscore * $gradinghintsnode->get_weight() * $this->scorecompensationfactor; - $gradinghintsnode->getSeparateFeedbackData()->set_score($score); return $score; } + /** + * Only calculates the score of a given node and does not manipulate any data of the grading hints tree + * @param grading_hints_node $node The root of the subtree + * @param bool $scalescoretolms + * @return float + */ + private function calc_score_from_children(grading_hints_node $node) : float { + list("maxvalue" => $value, "mergefunc" => $mergefunc) = $this->get_merge_variables($node->get_accumulator_function()); + foreach ($node->get_children() as $id => $child) { + if (!$child->has_feedback_data()) { + // if the node was not processed already + $child->addSeparateFeedbackData(); + } + if ($child->get_type() === 'test') { + $score = $child->getSeparateFeedbackData()->get_score(); + if ($score === null) { + // if the test node was not processed already, process it now + $this->fill_test_node_with_feedback_data($child); + $score = $child->getSeparateFeedbackData()->get_score(); + } + $value = $mergefunc($value, $score); + } elseif ($child->get_type() === 'combine') { + if ($this->should_be_nullified_node($child)) { + $score = 0; + $child->getSeparateFeedbackData()->set_nullified(true); + } else { + $score = $this->calc_score_from_children($child); + } + $value = $mergefunc($value, $score); + } + } + return $value; + } + private function fill_feedback_node_with_testresult_infos(separate_feedback_text_node $node, ?\DOMElement $testresult) { if (isset($testresult)) { @@ -443,7 +477,12 @@ class separate_feedback_handler { private function get_nullify_combine_value(grading_hints_nullify_condition_combineref_operand $operand): float { $refid = $operand->get_ref(); $gradinghintsnode = $this->detailedfeedback->get_child_by_refid($refid); - return $gradinghintsnode->getSeparateFeedbackData()->get_score(); + if ($gradinghintsnode->has_feedback_data()) { + $score = $gradinghintsnode->getSeparateFeedbackData()->get_rawscore(); + } else { + $score = $this->calc_score_from_children($gradinghintsnode); + } + return $score; } /** @@ -458,9 +497,7 @@ class separate_feedback_handler { } else { $testresult = $this->testresults[$refid]; } - $score = $testresult->getElementsByTagNameNS($this->namespacefeedback, 'result')[0]->getElementsByTagNameNS( - $this->namespacefeedback, 'score')[0]->nodeValue; - return $score; + return $testresult->getElementsByTagNameNS($this->namespacefeedback, 'result')[0]->getElementsByTagNameNS($this->namespacefeedback, 'score')[0]->nodeValue; } /** diff --git a/styles.css b/styles.css index 4d54b9096b4cfe0d89b3e458efef337b5a49a51e..2134e1cd72044bd0a184a7333f60c4750fb09b1c 100644 --- a/styles.css +++ b/styles.css @@ -73,7 +73,7 @@ p.expandcollapselink a { margin-left: 10px; } -.providedfiles{ +.providedfiles, .providedfilesteacher{ margin-left: 10px; } @@ -90,7 +90,7 @@ p.expandcollapselink a { 100% { transform: rotate(360deg); } } -.internaldescription, .gradingscheme { +.internaldescription, .gradingscheme, .providedfilesteacher { background-color: #73afdc; margin-top: 10px; } \ No newline at end of file