Breaking the Game F5

Question:

Breaking the Game F5

F5 is sometimes the bane of programmers. Some would go a long way to dismantle this key from keyboards around the world. Unfortunately, this is not possible and our application also suffers from an F5 problem.

Choose the number of questions, the degree of difficulty, and the department. Start the game. And on the first question, do F5. And what happened? You got another question! You can finish the Quiz by pressing F5. Of course, the result will be that you didn’t answer any of the questions correctly, but that’s poor consolation. What is the reason for this error?

Let’s take a look at the view on_game:

def on_game(request):
    quiz = Quiz.restore(request)
    if not quiz:
        return render(request, 'error.html')

    answer = request.POST.get('answer')

    try:
        if answer:
         quiz.check_answer(answer)

        question = quiz.get_question()
        quiz.save(request)
        return render(request, 'game.html', vars(question))
    except IndexError as x:
        return redirect('/finish')

The moment you click "Play!", This view fires up. Since the quiz has just started, this is your first question, so no answer, so in Ifa:

    if answer:
        quiz.check_answer(answer)

won’t come in – makes sense, right? So the code will execute and ask the question. It’s a pity that pressing F5 will treat it as starting a Quiz! Because there will be no answer … And the code will continue.

Hint
You can add an additional field in the Quiz class named e.g. just_started, which will have the value True / False. Programmers call these variables flags because they are only used to identify a certain situation. Flagging whether it happened or not.

The situation is not as trivial as it seems, you may need to change the way the next question is returned from "get -> move -> return" to "move -> check". I mean the function get_question. Combine it with the aforementioned flag just_started. Try to understand the problem in depth before the fixes, otherwise you will bury yourself 🙂

    @classmethod
    def create_game(cls, number_of_questions, difficulty, category):
        raw_questions = ApiClient.get_questions(difficulty, number_of_questions, category)
        questions = list([Question(**raw_question) for raw_question in raw_questions])
        return Quiz(number_of_questions, difficulty, questions, 0, 0)

    def save(self, request):
        request.session['saved_quiz'] = self

    def stop(self, request):
        del request.session['saved_quiz']

    @classmethod
    def restore(cls, request):
        return request.session.get('saved_quiz')

    def get_question(self):
        question = self.questions[self.current_question]
        self.current_question += 1
        return question

    def check_answer(self, answer):
        if self.questions[self.current_question - 1].correct_answer == answer:
            self.number_of_correct_answers += 1

    def get_result(self):
        return {
            'correct_answers': self.number_of_correct_answers,
            'all_questions': self.number_of_questions
        }
Asked By: Marek Grzesiak

||

Answers:

You need to separate the post and get methods. create new functions for these methods. Don’t listen to these hints because they are wrong.

File views.py

from django.shortcuts import render, redirect
from .api import ApiClient
from .game import Quiz


def index(request):
    try:
        quiz = ApiClient.get_quiz_options()
        return render(request, 'index.html', quiz)
    except ValueError:
        return render(request, 'error.html')


def start_game(request):
    number_of_questions = request.POST['quantity']
    difficulty = request.POST['difficulty']
    category = request.POST['category']
    quiz = Quiz.create_game(number_of_questions, difficulty, category)
    quiz.save(request)
    return redirect('/on_game_get')


def on_game_get(request):
    quiz = Quiz.restore(request)
    if not quiz:
        return render(request, 'error.html')
    try:
        question = quiz.get_question()
    except IndexError:
        return redirect('/finish')
    return render(request, 'game.html', vars(question))


def on_game_post(request):
    quiz = Quiz.restore(request)
    answer = request.POST.get('answer')
    if answer:
        quiz.check_answer(answer)
        quiz.next_question()
        quiz.save(request)

    return redirect('/on_game_get')


def finish(request):
    quiz = Quiz.restore(request)
    result = quiz.get_result()
    return render(request, 'finish.html', result)
Answered By: Mar3eczek17
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.