Commit 9a9d06d3 authored by Artem Baranovskyi's avatar Artem Baranovskyi
Browse files

Changed the source of request payload generation from DB to existing Manual Grading frontend page.

parent 0b8d71f6
<?php
// local/asystgrade/api.php
require_once('../../config.php');
require_once('lib.php');
......@@ -30,7 +29,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
} catch (Exception $e) {
echo json_encode(['error' => $e->getMessage()]);
}
} else {
echo json_encode(['error' => 'No data received']);
}
......
<?php
namespace local_asystgrade\db;
class quizquery implements quizquery_interface
{
private $db;
public function __construct() {
global $DB;
$this->db = $DB;
}
/**
* @param $qid
* @param $slot
* @return mixed
*/
public function get_question_attempts($qid, $slot) {
return $this->db->get_recordset(
'question_attempts',
[
'questionid' => $qid,
'slot' => $slot
],
'',
'*'
);
}
/**
* @param $qid
* @return mixed
*/
public function get_reference_answer($qid) {
return $this->db->get_record(
'qtype_essay_options',
[
'questionid' => $qid
],
'*',
MUST_EXIST
)->graderinfo;
}
/**
* @param $question_attempt_id
* @return mixed
*/
public function get_attempt_steps($question_attempt_id) {
return $this->db->get_recordset(
'question_attempt_steps',
[
'questionattemptid' => $question_attempt_id
],
'',
'*'
);
}
/**
* @param $attemptstepid
* @return mixed
*/
public function get_student_answer($attemptstepid) {
return $this->db->get_record(
'question_attempt_step_data',
[
'attemptstepid' => $attemptstepid,
'name' => 'answer'
],
'*',
MUST_EXIST
)->value;
}
/**
* Checks if scores exist for a given quizid and userid.
* *
* * @param int $quizid quiz ID.
* * @param int $userid user ID.
* * @return bool Returns true if scores exist for a given quizid and userid, otherwise false.
*/
public function gradesExist(int $quizid, int $userid): bool {
global $DB;
// Check for the presence of an entry in the mdl_quiz_grades table for this quizid and userid
return $DB->record_exists(
'quiz_grades',
[
'quiz' => $quizid,
'userid' => $userid
]
);
}
}
M.local_asystgrade = {
init: function(Y, js_data) { // YUI Module entry point
init: function(Y, js_data) {
window.gradeData = js_data;
document.addEventListener('DOMContentLoaded', function() {
const apiEndpoint = M.cfg.wwwroot + '/local/asystgrade/api.php';
const gradesDataRequest = window.gradeData.request;
const maxmark = document.querySelectorAll("input[name$='-maxmark']")[0].value;
const answerDivs = document.querySelectorAll(".qtype_essay_response");
const studentAnswers = Array.from(answerDivs).map(element => element.innerText || element.value);
if (gradesDataRequest) {
fetch(apiEndpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(gradesDataRequest)
})
.then(response => response.json())
.then(data => {
const gradesDataRequest = {
referenceAnswer: document.querySelectorAll(".essay .qtext p")[0].innerHTML,
studentAnswers: studentAnswers
};
fetch(apiEndpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(gradesDataRequest)
})
.then(response => response.json())
.then(data => {
if (data.success && data.grades) {
console.log(data.grades);
updateMarks(data.grades);
})
.catch(error => console.error('Error:', error));
}
} else {
console.error('Error in grade response:', data.error);
}
})
.catch(error => console.error('Error:', error));
function updateMarks(grades) {
const inputs = document.querySelectorAll("input[name$='_-mark']");
grades.forEach((grade, index) => {
console.log(grade, index)
const predictedGrade = grade.predicted_grade === 'correct' ? window.gradeData.maxmark : 0;
const inputName = window.gradeData.formNames[index];
const gradeInput = document.querySelector(`input[name="${inputName}"]`);
const predictedGrade = grade.predicted_grade === 'correct' ? maxmark : 0;
if (gradeInput) {
gradeInput.value = predictedGrade;
if (inputs[index]) {
inputs[index].value = predictedGrade;
} else {
console.error(`Input field not found for name: ${inputName}`);
console.error(`No grade input found for index: ${index}`);
}
});
}
});
}
};
\ No newline at end of file
};
......@@ -20,8 +20,6 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
use local_asystgrade\db\quizquery;
defined('MOODLE_INTERNAL') || die();
/**
......@@ -34,85 +32,19 @@ defined('MOODLE_INTERNAL') || die();
function local_asystgrade_before_footer()
{
global $PAGE;
// Obtaining parameters from URL
$qid = optional_param('qid', null, PARAM_INT);
$slot = optional_param('slot', false, PARAM_INT);
if ($PAGE->url->compare(new moodle_url('/mod/quiz/report.php'), URL_MATCH_BASE) && $slot) {
$quizQuery = new quizquery();
if ($quizQuery->gradesExist($qid, $slot)) {
error_log('Grades already exist in the database.');
return;
}
$question_attempts = $quizQuery->get_question_attempts($qid, $slot);
$referenceAnswer = $quizQuery->get_reference_answer($qid);
$maxmark = (float)$question_attempts->current()->maxmark;
$data = prepare_api_data($quizQuery, $question_attempts, $referenceAnswer);
foreach (array_keys($data['studentData']) as $studentId) {
if ($quizQuery->gradesExist($qid, $studentId)) {
return;
}
}
$studentData = $data['studentData'];
$inputNames = array_column($studentData, 'inputName');
$js_data = [
'apiendpoint' => 'http://flask:5000/api/autograde',
'formNames' => $inputNames,
'maxmark' => $maxmark,
'request' => [
'referenceAnswer' => $data['referenceAnswer'],
'studentAnswers' => array_column($studentData, 'studentAnswer')
]
'qid' => $qid,
'slot' => $slot
];
$PAGE->requires->js(new moodle_url('/local/asystgrade/js/grade.js', ['v' => time()]));
$PAGE->requires->js_init_call('M.local_asystgrade.init', [$js_data]);
}
}
/**
* Processes question attempts and answers to prepare for API a data to estimate answers
*
* @param quizquery $database
* @param $question_attempts
* @param $referenceAnswer
* @return array
*/
function prepare_api_data(quizquery $database, $question_attempts, $referenceAnswer): array
{
$studentData = [];
foreach ($question_attempts as $question_attempt) {
$quizattempt_steps = $database->get_attempt_steps($question_attempt->id);
foreach ($quizattempt_steps as $quizattempt_step) {
if ($quizattempt_step->state === 'complete') {
$studentAnswer = $database->get_student_answer($quizattempt_step->id);
$studentId = $quizattempt_step->userid;
$inputName = "q" . $question_attempt->questionusageid . ":" . $question_attempt->slot . "_-mark";
// Adding data to an associative array
$studentData[$studentId] = [
'studentAnswer' => $studentAnswer,
'inputName' => $inputName // identifying name for mark input field updating
];
error_log("Student ID: $studentId, Student Answer: $studentAnswer, Input Name: $inputName");
}
}
$quizattempt_steps->close();
}
$question_attempts->close();
return [
'referenceAnswer' => $referenceAnswer,
'studentData' => $studentData
];
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment