Тест с несколькими вариантами ответов или генератор экзаменов - PullRequest
0 голосов
/ 20 января 2020

Я пытаюсь создать скрипт или приложение для создания тестов с несколькими вариантами ответов. Это позволит пользователю ввести вопрос, а затем дать верный ответ и количество ответов на выбор. Пользователь может повторить этот процесс столько раз, сколько он пожелает. Затем пользователю нужно будет ввести количество вопросов, которое будет иметь созданный тест. В конце концов, тест будет сохранен в виде документа PDF или Word. Все это должно быть gui сделано в Qt. До сих пор я сделал большую часть сценария викторины, и он работает правильно. (все еще нужно выяснить, как добавить a, b, c ... перед ответами и сохранить в pdf, но это не должно быть проблемой). gui также сделан, и я думаю, что он должен работать должным образом.

Проблема в том, что я не знаю, как соединить скрипт викторины с gui. Я перепробовал много вещей, и ни одна из них не сработала.

import json
import random

def quiz_name():
    name = input('Enter the name of the quiz file: ')
    return name

def question_generator():
    question_text = input('Enter a question. When done entering questions type \'stop\': ')
    if question_text.lower() == 'stop':
        return None

    true = input('Enter the correct answer: ')

    answer_dict = []
    while True:
        answer = input('Enter an answer. When done entering questions type \'stop\': ')
        if answer.lower() == 'stop':
            break
        answer_dict.append(answer)         
    qapair = (question_text, true, answer_dict) 

    return qapair



def question_list_builder():
    questions = []
    while True:
        qg_method = question_generator()
        if qg_method is None:
            break
        q = (qg_method[0], qg_method[1],qg_method[2]) 
        questions.append(q)
    return questions

#lista_pitanja = question_list_builder()

#for lp in lista_pitanja:
#    pitanje=lista_pitanja
#    broj =0
#    while broj <len(lista_pitanja[2]):
#        print(broj+1,+': '+)
#        broj+=1

class ObjectEncoder(json.JSONEncoder):
  def default(self, obj):
    return obj.__dict__

if __name__ == '__main__':
    quest = question_list_builder()
    name = quiz_name()
    def JSONWrite(quiz, filepath):
        with open(f'{filepath}.json', 'w') as fp:
            fp.write(quiz)
    print(json.dumps(quest, cls=ObjectEncoder))
#    random.sample(pitanja,4)
    JSONWrite(json.dumps(random.sample(quest,3), cls=ObjectEncoder, indent=4),name)

При необходимости я вставлю gui код

Редактировать: добавлен gui код

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(1077, 943)
        self.gridLayout = QtWidgets.QGridLayout(Form)
        self.gridLayout.setObjectName("gridLayout")
        self.line_3 = QtWidgets.QFrame(Form)
        self.line_3.setFrameShape(QtWidgets.QFrame.VLine)
        self.line_3.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_3.setObjectName("line_3")
        self.gridLayout.addWidget(self.line_3, 0, 4, 1, 1)
        self.line_4 = QtWidgets.QFrame(Form)
        self.line_4.setFrameShape(QtWidgets.QFrame.VLine)
        self.line_4.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_4.setObjectName("line_4")
        self.gridLayout.addWidget(self.line_4, 0, 0, 1, 1)
        self.gridLayout_2 = QtWidgets.QGridLayout()
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.Answer_btn = QtWidgets.QPushButton(Form)
        self.Answer_btn.setObjectName("Answer_btn")
        self.gridLayout_2.addWidget(self.Answer_btn, 4, 2, 1, 1)
        self.LE_datName = QtWidgets.QLineEdit(Form)
        self.LE_datName.setObjectName("LE_datName")
        self.gridLayout_2.addWidget(self.LE_datName, 7, 1, 1, 1)
        self.label_datName = QtWidgets.QLabel(Form)
        self.label_datName.setObjectName("label_datName")
        self.gridLayout_2.addWidget(self.label_datName, 7, 0, 1, 1)
        self.Question_btn = QtWidgets.QPushButton(Form)
        self.Question_btn.setObjectName("Question_btn")
        self.gridLayout_2.addWidget(self.Question_btn, 1, 2, 1, 1)
        self.LE_TAnswer = QtWidgets.QLineEdit(Form)
        self.LE_TAnswer.setObjectName("LE_TAnswer")
        self.gridLayout_2.addWidget(self.LE_TAnswer, 3, 1, 1, 1)
        self.LE_Answer = QtWidgets.QLineEdit(Form)
        self.LE_Answer.setObjectName("LE_Answer")
        self.gridLayout_2.addWidget(self.LE_Answer, 4, 1, 1, 1)
        self.line_2 = QtWidgets.QFrame(Form)
        self.line_2.setFrameShape(QtWidgets.QFrame.HLine)
        self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_2.setObjectName("line_2")
        self.gridLayout_2.addWidget(self.line_2, 8, 0, 1, 4)
        self.label_NQuestion = QtWidgets.QLabel(Form)
        self.label_NQuestion.setObjectName("label_NQuestion")
        self.gridLayout_2.addWidget(self.label_NQuestion, 9, 0, 1, 1)
        self.label_Answer = QtWidgets.QLabel(Form)
        self.label_Answer.setFrameShape(QtWidgets.QFrame.NoFrame)
        self.label_Answer.setTextFormat(QtCore.Qt.AutoText)
        self.label_Answer.setScaledContents(False)
        self.label_Answer.setObjectName("label_Answer")
        self.gridLayout_2.addWidget(self.label_Answer, 4, 0, 1, 1)
        self.LE_NQuestions = QtWidgets.QLineEdit(Form)
        self.LE_NQuestions.setObjectName("LE_NQuestions")
        self.gridLayout_2.addWidget(self.LE_NQuestions, 9, 1, 1, 1)
        self.New_Question_btn = QtWidgets.QPushButton(Form)
        self.New_Question_btn.setObjectName("New_Question_btn")
        self.gridLayout_2.addWidget(self.New_Question_btn, 4, 3, 1, 1)
        self.TAnswer_btn = QtWidgets.QPushButton(Form)
        self.TAnswer_btn.setObjectName("TAnswer_btn")
        self.gridLayout_2.addWidget(self.TAnswer_btn, 3, 2, 1, 1)
        self.line = QtWidgets.QFrame(Form)
        self.line.setFrameShape(QtWidgets.QFrame.HLine)
        self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line.setObjectName("line")
        self.gridLayout_2.addWidget(self.line, 6, 0, 1, 4)
        self.Dat_btn = QtWidgets.QPushButton(Form)
        self.Dat_btn.setObjectName("Dat_btn")
        self.gridLayout_2.addWidget(self.Dat_btn, 7, 2, 1, 1)
        self.label_TAnswer = QtWidgets.QLabel(Form)
        self.label_TAnswer.setObjectName("label_TAnswer")
        self.gridLayout_2.addWidget(self.label_TAnswer, 3, 0, 1, 1)
        self.Generate_btn = QtWidgets.QPushButton(Form)
        self.Generate_btn.setObjectName("Generate_btn")
        self.gridLayout_2.addWidget(self.Generate_btn, 9, 3, 1, 1)
        self.NQuestion_btn = QtWidgets.QPushButton(Form)
        self.NQuestion_btn.setObjectName("NQuestion_btn")
        self.gridLayout_2.addWidget(self.NQuestion_btn, 9, 2, 1, 1)
        self.LE_Question = QtWidgets.QLineEdit(Form)
        self.LE_Question.setToolTipDuration(-1)
        self.LE_Question.setText("")
        self.LE_Question.setObjectName("LE_Question")
        self.gridLayout_2.addWidget(self.LE_Question, 1, 1, 1, 1)
        self.Done_btn = QtWidgets.QPushButton(Form)
        self.Done_btn.setObjectName("Done_btn")
        self.gridLayout_2.addWidget(self.Done_btn, 5, 2, 1, 1)
        self.line_okv2 = QtWidgets.QFrame(Form)
        self.line_okv2.setLineWidth(5)
        self.line_okv2.setFrameShape(QtWidgets.QFrame.HLine)
        self.line_okv2.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_okv2.setObjectName("line_okv2")
        self.gridLayout_2.addWidget(self.line_okv2, 10, 0, 1, 4)
        self.line_okv1 = QtWidgets.QFrame(Form)
        self.line_okv1.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_okv1.setLineWidth(3)
        self.line_okv1.setFrameShape(QtWidgets.QFrame.HLine)
        self.line_okv1.setObjectName("line_okv1")
        self.gridLayout_2.addWidget(self.line_okv1, 0, 0, 1, 4)
        self.label_Question = QtWidgets.QLabel(Form)
        self.label_Question.setObjectName("label_Question")
        self.gridLayout_2.addWidget(self.label_Question, 1, 0, 1, 1)
        self.gridLayout.addLayout(self.gridLayout_2, 0, 1, 1, 1)

        self.retranslateUi(Form)
        self.Answer_btn.pressed.connect(self.LE_Answer.clear)
        self.New_Question_btn.clicked.connect(self.LE_Question.clear)
        self.New_Question_btn.clicked.connect(self.LE_TAnswer.clear)
        self.New_Question_btn.clicked.connect(self.LE_Answer.clear)
        self.Generate_btn.clicked.connect(self.LE_NQuestions.clear)
        self.Generate_btn.clicked.connect(self.LE_datName.clear)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Kolokvij"))
        self.Answer_btn.setText(_translate("Form", "Enter Answer"))
        self.label_datName.setText(_translate("Form", "Enter the name of the file:"))
        self.Question_btn.setToolTip(_translate("Form", "Pritisnite ovo"))
        self.Question_btn.setText(_translate("Form", "Enter Question"))
        self.label_NQuestion.setText(_translate("Form", "Number of questions in exam:"))
        self.label_Answer.setText(_translate("Form", "Enter all the possible answers:"))
        self.New_Question_btn.setText(_translate("Form", "New Question"))
        self.TAnswer_btn.setText(_translate("Form", "Enter T Answer"))
        self.Dat_btn.setText(_translate("Form", "Enter"))
        self.label_TAnswer.setText(_translate("Form", "Enter the corect answer:"))
        self.Generate_btn.setText(_translate("Form", "Create exam"))
        self.NQuestion_btn.setText(_translate("Form", "Enter"))
        self.LE_Question.setToolTip(_translate("Form", "Unesite pitanje te pritisnite dugme Unesi pitanje"))
        self.Done_btn.setText(_translate("Form", "Done"))
        self.label_Question.setText(_translate("Form", "Enter a question:"))





    def quiz_name(self):
        name = self.LE_datName.text()
        return name

    def question_generator(self):
        question_text = self.LE_Question.text()
        if question_text.lower() == self.New_Question_btn.clicked.connect(self.question_generator):
            return None

        true = self.LE_TAnswer.text()

        answer_dict = []
#        while True:
        answer = self.LE_Answer.text()
#            if answer.lower() == 'stop':
#                break
        answer_dict.append(answer)         
        qapair = (question_text, true, answer_dict) 

        return qapair,print (qapair)

    def question_list_builder(self):
        questions = []
        while True:
            qg_method = self.question_generator()
            if qg_method is None:
                break
            q = (qg_method[0], qg_method[1],qg_method[2]) 
            questions.append(q)
        return questions

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Form = QtWidgets.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

1 Ответ

0 голосов
/ 21 января 2020

Ваш код имеет серьезные логики c, концептуальные и программные проблемы.

Прежде всего: даже если это не кажется очень важным, никогда не использует слишком переменные имена переменных похож на встроенные типы (в вашем случае, true). True (вместе с False) является встроенным логическим значением, и использование такого имени (даже с другим регистром) может привести к проблемам с читабельностью и, в конце концов, к отладке.
Всегда используйте clear и уникальные имена переменных, в вашем случае это может быть что-то вроде correctAnswer.

Во-вторых, не используйте некоторое время l oop при работе с элементами пользовательского интерфейса. Графический интерфейс c обычно основан на событии l oop, которое ожидает некоторый тип взаимодействия (от пользователя или системы) и просто ожидает, пока это не произойдет. Использование while l oop (или, что стоит, любой цикл, включая for циклы или рекурсивные вызовы функции) заблокирует возможность получения этих событий, делая интерфейс непригодным для использования. .

Третий; Вы не можете использовать оператор if между строкой и возвращаемым значением соединения (обычно это None): это яблоки и апельсины. Когда вы делаете someSignal.connect(someSlot), вы на самом деле говорите Qt, что он будет вызывать этот someSlot всякий раз, когда испускается someSignal.
Представьте себе что-то вроде этого:

self.fridge.empty.connect(self.goToMall)

Это вызовет goToMall всякий раз, когда холодильник говорит, что он пуст. Затем предположим, что вы собираетесь в отпуск и не хотите, чтобы ваш холодильник был заполнен:

self.fridge.empty.disconnect(self.goToMall)

Как вы можете видеть, connect не дает вам ничего полезного для сравнения со строкой: это все равно что сказать «проверь, совпадает ли мое имя с тем фактом, что я буду go в торговый центр, когда холодильник пуст».
Примечание: документация гласит что connect() возвращает Connection объект, который впоследствии может быть использован для разъединения. В (довольно старой) версии PyQt, которую я использую, он просто возвращает None, но это можно было бы изменить за это время. Тем не менее, проблема с недопустимым сравнением все еще существует.

В-четвертых, не возвращайте print(): просто возвращается None, это просто не нужно.

Наконец; никогда смешивать сгенерированный код из pyuic для ваших программ. Оставьте эти py-файлы такими, какие они есть, и импортируйте их как модули, как описано в документации .


. Теперь сгенерируйте файл .ui, созданный в Designer, и используйте что-нибудь как это в другом файле , который будет вашим основным программным скриптом:

from PyQt5 import QtWidgets
from ui_form import Ui_Form

# I'm using the third method described in the designer documentation given above, 
# the multiple inheritance approach
class QuestionBuilder(QtWidgets.QWidget, Ui_Form):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.New_Question_btn.clicked.connect(self.question_generator)

        self.questions = []

    def question_generator(self):
        question_text = self.LE_Question.text()
        # I don't really know what you meant by comparing the string with the
        # connection, I'm assuming you didn't want to add the same question twice
        if self.questions and self.questions[-1].lower() == question_text:
        for existing_questions in self.questions:
            if question_text.lower() == existing_questions[0]:
                print('question already exists, ignoring')
                return

        correctAnswer = self.LE_TAnswer.text()

        answers = []
        answers.append(self.LE_Answer.text())
        self.questions.append((question_text, correctAnswer, answers))

        self.LE_Answer.clear()
        self.LE_Question.clear()
        self.LE_TAnswer.clear()

        print(self.questions)

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = QuestionBuilder()
    window.show()
    sys.exit(app.exec_())

Обратите внимание, что в приведенном выше примере я не реализовал проверку правильного ответа (ни проверку для * 1060) * все возможные ответы, а также функции, связанные с другими кнопками).

Позвольте мне сказать, что у вашего подхода есть несколько проблем с пользовательским интерфейсом, которые могут привести к сложным отладкам побочных эффектов (программно и из опыта пользователя). ), и я считаю, что наиболее важной проблемой является добавление слишком большого количества кнопок с ненужными функциями (и неясными описаниями), которые вам придется учитывать - не считая создания интерфейса, который вводит в заблуждение конечного пользователя.
Что будет Вы делаете, когда нажимаете «Enter T answer» и не существует никаких вопросов? А что, если вы нажмете «Ввести ответ», и поле действительного ответа будет пустым? Что если ответ похож на другой, но с другой буквой, и только один из них является правильно правильным? Как вы могли бы действительно обнаружить и уведомить пользователя, когда какое-то поле недопустимо?

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

...