Ошибка веб-приложения викторины: функция для генерации 10 случайных вопросов иногда генерирует вместо 9 или 11 вопросов - PullRequest
0 голосов
/ 16 апреля 2019

Я пишу приложение для викторины на pythonany везде, где используется колба. Это первый раз, когда я когда-либо использовал флягу или питон, где-то еще, поэтому я очень много еще учусь. Приведенная ниже функция генерирует странную ошибку: иногда она генерирует 11 или 9 словарных статей вместо 10, хотя параметр Qnum никогда не изменяется.

Я подумал, что проблема может быть связана с псевдонимами (поскольку функция удаляет запись), поэтому я попытался составить отдельные списки, пройдя по словарным ключам и значениям. Код работал нормально, когда я писал его непосредственно в основной файл приложения, но как только я абстрагировал его в вспомогательную функцию, он начал воспроизводиться.

Из файла функций помощника:

  def create_answer_dict(Dict, Qnum):
        import random
        Qdict={}
        for i in range(Qnum):
            #Choose random word to test
            Qkeys=[]
            for key in Dict.keys():
                Qkeys.append(key)
            Qword=random.choice(Qkeys)

            #Get correct answer from dictionary
            correctAnswer = Dict[Qword]

            #Generate wrong answer options
            wrongAnswers=[]
            for value in Dict.values():
                wrongAnswers.append(value)
            del wrongAnswers[wrongAnswers.index(correctAnswer)]
            wrongAnswers = random.sample(wrongAnswers, 3)
            answerOptions = wrongAnswers + [correctAnswer]
            random.shuffle(answerOptions)
            Qdict[Qword]=answerOptions
        return Qdict

Из основного файла приложения:

@app.route("/", methods=["GET","POST"])
def index():
    Qdict=create_answer_dict(questions, total)
    if request.method == "GET":
        return render_template('main.html', q = Qdict, keys=Qdict.keys())
    elif request.method == 'POST':
        score=0
        for i in Qdict.keys():
            answered=request.form[i]
            if original_questions[i]==answered:
                score+=1
    return render_template("results.html", score=score, total=total)

Из представления html:

<form action='/' method='POST'>
    <ol>
        {% for i in keys %}
            <li>What is the French for <u>{{i}}</u> ?  </li>
            {% for j in q[i] %}
                <input type='radio' value='{{j}}' name='{{i}}'      style="margin-right: 5"/>{{j}}
                <br></br>
            {% endfor %}
        {% endfor %}
    </ol>
    <input type="submit" value="submit" />
</form>

Как это должно работать:

Возможные вопросы и ответы хранятся в объекте словаря.

В моем главном файле приложения я вызываю эту функцию из файла вспомогательных функций, используя свой словарь вопрос-ответ и переменную сумму в качестве параметров. Всего установлено 10.

Функция выбирает вопросы Qnum, находит соответствующий ответ и выбирает 3 случайных неправильных ответа.

Возвращает их в виде словаря в следующем формате:

{Question1:[CorrectAnswer, IncorrectAnswer1,IncorrectAnswer2, IncorrectAnswer3],
Question2:[CorrectAnswer, IncorrectAnswer1,IncorrectAnswer2, IncorrectAnswer3], 
etc.}

Все возвращается без сообщения об ошибке, просто в словаре иногда на одну или на одну запись больше, чем ожидалось.

1 Ответ

2 голосов
/ 16 апреля 2019

Вы не можете ожидать получения словаря длиной n, случайным образом выбирая n записей из другого словаря, потому что всегда есть возможность выбора дубликатов записей (и поскольку ключи словаря уникальны, дублирующиеся записи будут перезаписаныв результирующем словаре).

Гораздо лучший подход для выбора фиксированного числа n случайных ключей в словаре - это просто создать список из ключей словаря, перемешать этот список, а затем нарезать этот списоксохранить только первые n элементов.

В вашем коде это будет выглядеть так:

def create_answer_dict(Dict, Qnum):
    import random
    Qdict={}

    possibleQuestions = list(Dict.keys())
    random.shuffle(possibleQuestions)
    possibleQuestions = possibleQuestions[:Qnum]

    for Qword in possibleQuestions:
        #Get correct answer from dictionary
        correctAnswer = Dict[Qword]

        #Generate wrong answer options
        wrongAnswers = list(Dict.values())
        del wrongAnswers[wrongAnswers.index(correctAnswer)]
        wrongAnswers = random.sample(wrongAnswers, 3)
        answerOptions = wrongAnswers + [correctAnswer]
        random.shuffle(answerOptions)
        Qdict[Qword] = answerOptions
    return Qdict

Это будет гарантировать, что генерируется Qnum уникальных вопросов.

Редактировать: также в index(), чтобы избежать KeyErrors, если пользователь не отвечает на все вопросы, замените

for i in Qdict.keys():
        answered=request.form[i]
        ...

на

for i in request.form:
        answered=request.form[i]
        ...

Рабочая демонстрация:https://repl.it/@glhr/55701832

...