Im trying to send the quiz score from my js code to my learner controller so I can insert the score in the result table and display the result to the user.
I tried to create a hidden form and set the input hidden inside the form with the score from my js and than request it from the server but still giving errors
The errors:
POST http://127.0.0.1:5000/submit_quiz 500 (INTERNAL SERVER ERROR)
SyntaxError: Unexpected token ‘<‘, “<!DOCTYPE “… is not valid JSON
#app.py
# learner show exam
@app.route('/learner_show_exam', methods=['GET', 'POST'])
@login_required(role='Learner')
def learner_show_exam():
return learner_dashboard_controller.show_exam()
# learner submit result
@app.route('/submit_quiz', methods=['GET', 'POST'])
@login_required(role='Learner')
def submit_quiz():
return learner_dashboard_controller.submit_result()
#learner_controller.py:
#============================================================================
# show exam
#============================================================================
def show_exam(self):
try:
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
learner_implementation = UserService()
quiz_implementation = QuizService()
learner_id = session.get('user_id')
user_data = learner_implementation.getLearnerDataById(learner_id)
lang = user_data[12]
level = user_data[13]
quiz_data = quiz_implementation.read_all_quizzes_data_by_lang_level(lang, level)
data = {
'quiz_data': quiz_data,
}
return jsonify(data)
learner_id = session.get('user_id')
learner_implementation = UserService()
user_picture = learner_implementation.getLearnerDataById(learner_id)
return render_template("learner/exam/show_exam.html", profil_picture=user_picture)
except Exception as e:
print(f"An error occurred while showing the exam: {e}")
# Handle the error gracefully, you may want to return an error page or message.
return "An error occurred while showing the exam."
#logging.basicConfig(level=logging.DEBUG)
#logging.error("An error occurred while submitting quiz: %s", e)
def submit_result():
try:
if request.method == 'POST':
# Get form data
user_id = session.get('user_id')
learner_implementation = UserService()
quiz_implementation = QuizService()
user_data = learner_implementation.getLearnerDataById(user_id)
lang = user_data[12]
level = user_data[13]
quiz_data = quiz_implementation.read_all_quizzes_data_by_lang_level(lang, level)
quiz_id = quiz_data[0]
score = request.form.get('score')
print("quiz id: " , quiz_id)
print("score: " , score)
if score >= 70: # Check if score is 70% or higher
passed = True
else:
passed = False
result = Result()
# Set Result object properties
result.set_user_id(user_id)
result.set_quiz_id(quiz_id)
result.set_score(score)
result.set_passed(passed)
result_implementation = ResultService()
if result_implementation.create_result(result):
return jsonify({'success': True})
else:
return jsonify({'success': False, 'message': 'Une erreur s'est produite. Veuillez réessayer'})
except Exception as e:
print("Error:", e)
return jsonify({'success': False, 'message': str(e)})
#html code:
<h1 id="scroll" class="title">Examin et Resultat</h1>
<ul class="breadcrumbs">
<li><a href="#">Examin & Resultat</a></li>
<li class="divider">/</li>
<li><a href="#" class="active">Examin</a></li>
</ul>
<div class="table">
<div id="scroll-table" class="table-header">
<p>Repond aux quiz pour passez l'examin</p>
</div>
<div id="feedback_message"></div>
<div id="loading-spinner">
<div class="alert alert-info">
<i class="fa fa-spinner fa-spin"></i> Chargement en cours...
</div>
</div>
</div>
<div id="quiz_data"></div>
<form id="score-form" class="needs-validation" method="post" novalidate style="display:none;">
<input type="hidden" name="csrf_token" id="csrf_token" value="{{ csrf_token() }}">
<input type="hidden" name="score" id="score">
<input type="submit" id="submit-btn" style="display: none;">
</form>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script async src="{{ url_for('static', filename='js/learner/exam/show_exam_client_side.js') }}"></script>
show_exam_client_side.js code:
const quizContainer = document.getElementById("quiz_data");
let currentQuestionIndex = 0;
let score = 0;
let questions = []; // Array to store fetched questions
function fetchQuizesData() {
$.ajax({
url: '/learner_show_exam',
type: 'GET',
dataType: 'json',
success: function (response) {
$('html, body').css('cursor', 'default');
$('.pagination-link').removeClass('loading');
questions = response.quiz_data;
$('#loading-spinner').hide();
startQuiz();
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(errorThrown);
$('html, body').css('cursor', 'default');
$('.pagination-link').removeClass('loading');
}
});
}
function startQuiz() {
currentQuestionIndex = 0;
score = 0;
showQuestion();
}
function showQuestion() {
const shuffledAnswers = shuffleArray(questions[currentQuestionIndex].slice(2));
const correctAnswerIndex = shuffledAnswers.findIndex(answer => answer === questions[currentQuestionIndex][2]);
const quizHtml = `
<div class="app">
<div class="quiz">
<h2 id="question">${currentQuestionIndex + 1}. ${questions[currentQuestionIndex][1]}</h2>
<div id="answer-buttons">
${shuffledAnswers.map((answer, index) => `
<button class="btn answer-btn" data-correct="${index === correctAnswerIndex}">${answer}</button>
`).join('')}
</div>
<button id="next-btn" type="button" class="btn btn-primary" style="display: none;">Suivant</button>
</div>
</div>
`;
quizContainer.innerHTML = quizHtml;
const nextButton = document.getElementById("next-btn");
// Attach event listener to dynamically created buttons
document.querySelectorAll('.answer-btn').forEach(button => {
button.addEventListener('click', selectAnswer);
});
nextButton.addEventListener("click", () => {
currentQuestionIndex++;
if (currentQuestionIndex < questions.length) {
showQuestion();
} else {
showScore();
}
});
}
// Function to shuffle an array
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
function selectAnswer(e) {
const selectedBtn = e.target;
const isCorrect = selectedBtn.dataset.correct === "true";
if (isCorrect) {
selectedBtn.classList.add("correct");
score++;
} else {
selectedBtn.classList.add("incorrect");
}
const answerButtons = document.getElementById('answer-buttons');
Array.from(answerButtons.children).forEach(button => {
if (button.dataset.correct === "true") {
button.classList.add("correct");
}
button.disabled = true;
});
const nextButton = document.getElementById("next-btn");
nextButton.style.display = "block";
}
function showScore() {
const percentageScore = (score / questions.length) * 100;
const csrfToken = document.getElementById('csrf_token').value;
let resultHtml = '';
if (percentageScore < 70) {
// Afficher un message d'échec si le score est inférieur à 70%
const URL_pict = "static/images/failed_quiz.png";
resultHtml = `
<div class="app2">
<img src="${URL_pict}" alt="Image du quiz échoué">
<p>Vous avez obtenu ${percentageScore.toFixed(0)}% sur 100%! <br> Vous devez obtenir au moins 70% pour réussir.</p>
<button id="restart-btn" class="btn btn-primary">Commencer le quiz à nouveau</button>
</div>
`;
} else {
// Afficher un message de réussite
resultHtml = `
<div class="app2">
<i class="fa fa-check-circle"></i>
<p>Félicitations! Vous avez obtenu ${percentageScore.toFixed(0)}% sur 100%!</p>
<a href="/learner_show_result"><button id="see-results-btn" class="btn btn-primary">Voir les résultats</button></a>
</div>
`;
}
quizContainer.innerHTML = resultHtml;
// Attach event listener to restart button
const restartButton = document.getElementById("restart-btn");
if (restartButton) {
restartButton.addEventListener("click", startQuiz);
}
// Submit the form after everything is set up
submitFormIfNeeded(percentageScore, csrfToken);
}
function submitFormIfNeeded(percentageScore, csrfToken) {
if (percentageScore >= 70) {
const form = document.getElementById("score-form");
if (form) {
// Attach event listener to form submission
form.addEventListener('submit', (event) => {
event.preventDefault();
const formData = new FormData(form);
const csrfToken = document.getElementById('csrf_token').value;
formData.append('csrf_token', csrfToken);
fetch('/submit_quiz', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
// Handle response if needed
})
.catch(error => {
console.error(error);
document.getElementById('feedback_message').innerHTML = `
<div class="alert alert-danger">
<span class="closeBtn" onclick="closeAlert(this);">×</span>
<i class="fa fa-exclamation-circle"></i>
Une erreur s'est produite lors du traitement de la demande. Veuillez réessayer.
</div>`;
});
});
// Set the score value to the hidden input field
const scoreInput = form.querySelector("#score");
if (scoreInput) {
scoreInput.value = score;
}
// Click the submit button automatically
const submitButton = document.getElementById("submit-btn");
submitButton.click();
}
}
}
// call fetchQuizesData initially to fetch the quiz data
fetchQuizesData();