From 36f4ee2501f6f938e8d411ecc9c1de0134f236a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kn=C3=BCttel?= Date: Thu, 31 Jan 2019 19:53:49 +0100 Subject: [PATCH] finished off the app --- exam/ex3/callbacks.py | 61 +++++++++++++++++++++++++++++++++++++++---- exam/ex3/database.py | 33 ++++++++++++++++++----- exam/ex3/exercise.py | 41 +++++++++++++++++++++++++++++ exam/ex3/main.glade | 46 ++++++++++---------------------- exam/ex3/main.py | 6 +++-- exam/ex3/settings.py | 7 +++-- 6 files changed, 144 insertions(+), 50 deletions(-) create mode 100644 exam/ex3/exercise.py diff --git a/exam/ex3/callbacks.py b/exam/ex3/callbacks.py index 244f614..bcf1679 100644 --- a/exam/ex3/callbacks.py +++ b/exam/ex3/callbacks.py @@ -1,8 +1,12 @@ +from gi.repository import Gtk + from settings import load_words_from_file, manually_add_question, save_questions_to_file +from exercise import Question class CallbackHandler(object): def __init__(self, gtk_builder): self.builder = gtk_builder + self.question = None def on_manually_add_submit_button_clicked(self, widget): question_view = self.builder.get_object("add_question_question_view") answer_view = self.builder.get_object("add_question_answer_view") @@ -10,18 +14,65 @@ class CallbackHandler(object): question = question_view.get_text() answer = answer_view.get_text() - manually_add_question(question, answer) + try: + manually_add_question(question, answer) + except: + return - def on_load_from_file_submit_button_clicked(self, widget): + question_view.set_text("") + answer_view.set_text("") + + def on_load_from_file_chooser_file_set(self, widget): file_chooser = self.builder.get_object("load_from_file_chooser") file_name = file_chooser.get_filename() load_words_from_file(file_name) - def on_save_question_to_file_submit_button_clicked(self, widget): - file_chooser = self.builder.get_object("save_questions_to_file_chooser") - file_name = file_chooser.get_filename() + def on_save_questions_to_file_button_clicked(self, widget): + dialog = Gtk.FileChooserDialog("Please choose a file", None + , Gtk.FileChooserAction.SAVE + , (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL + , Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) + response = dialog.run() + if(response == Gtk.ResponseType.CANCEL): + dialog.destroy() + return + file_name = dialog.get_filename() + dialog.destroy() save_questions_to_file(file_name) + def on_submit_answer_button_clicked(self, widget): + answer_view = self.builder.get_object("answer_view") + correct_answer_view = self.builder.get_object("correct_answer_view") + answer_was_correct_view = self.builder.get_object("answer_was_correct_view") + + dispatch_answer_was_correct = {True: "That is correct:" + , False: "Wrong, correct was:"} + + submit_answer_button = widget + submit_answer_button.set_sensitive(False) + + answer = answer_view.get_text() + was_correct = self.question.submit_answer(answer) + + correct_answer_view.set_text(self.question.answer) + answer_was_correct_view.set_text(dispatch_answer_was_correct[was_correct]) + + def on_next_question_button_clicked(self, widget): + answer_view = self.builder.get_object("answer_view") + correct_answer_view = self.builder.get_object("correct_answer_view") + answer_was_correct_view = self.builder.get_object("answer_was_correct_view") + submit_answer_button = self.builder.get_object("submit_answer_button") + question_view = self.builder.get_object("question_view") + + submit_answer_button.set_sensitive(True) + answer_view.set_text("") + correct_answer_view.set_text("") + answer_was_correct_view.set_text("") + + self.question = Question.fetch() + + question_view.set_text(self.question.question) + diff --git a/exam/ex3/database.py b/exam/ex3/database.py index aae1541..0dd9ec8 100644 --- a/exam/ex3/database.py +++ b/exam/ex3/database.py @@ -13,7 +13,8 @@ def create_database(): db = sqlite3.connect(database_path) - db.execute('''CREATE TABLE QUESTIONS(question TEXT, answer TEXT, correct INT)''') + db.execute('''CREATE TABLE QUESTIONS(question TEXT UNIQUE, answer TEXT, correct INT)''') + db.commit() db.close() @@ -29,24 +30,42 @@ def update_correct(question, correct): """ db = open_database() cursor = db.cursor() - cursor.execute("UPDATE QUESTIONS SET correct=correct + ? WHERE question = ?", (correct, question)) + try: + cursor.execute("UPDATE QUESTIONS SET correct=correct + ? WHERE question = ?", (correct, question)) + except sqlite3.IntegrityError: + pass + db.commit() db.close() def add_word(question, answer): db = open_database() cursor = db.cursor() cursor.execute("INSERT INTO QUESTIONS(question, answer, correct) VALUES(?, ?, 0)", (question, answer)) + db.commit() db.close() + def add_words(input_data): db = open_database() cursor = db.cursor() - cursor.executemany("INSERT INTO QUESTIONS(question, answer, correct) VALUES(?, ?, 0)", input_data.items()) + cursor.executemany("INSERT INTO QUESTIONS(question, answer, correct) VALUES(?, ?, 0)", list(input_data.items())) + db.commit() db.close() - print("added words") + def fetch_question(): + """ + Fetches a new question from the database. + The list of question is sorted ascending by number of + times the question has been answered correctly + and from the least n elements one is chosen randomly. + + n is either the number of questions in the database divided + by ``cfg.config["WORD_BUCKET_SIZE"]`` or (if this number is zero) + or one. + + """ db = open_database() cursor = db.cursor() @@ -58,10 +77,10 @@ def fetch_question(): if(fetch_questions == 0): fetch_questions = 1 - cursor.execute("SELECT question, answer, correct FROM QUESTIONS SORT BY correct") + cursor.execute("SELECT question, answer, correct FROM QUESTIONS ORDER BY correct ASC") - result = cursor.fetch(fetch_questions) + result = cursor.fetchmany(fetch_questions) my_result = random.choice(result) - return result[:2] + return my_result[:2] diff --git a/exam/ex3/exercise.py b/exam/ex3/exercise.py new file mode 100644 index 0000000..36d4c60 --- /dev/null +++ b/exam/ex3/exercise.py @@ -0,0 +1,41 @@ +from database import fetch_question, update_correct + +class Question(object): + """ + This is the throwaway container types for questions. + It basically stores the question and the answer and + handles the database access. + + One can fetch a (semi random (see database.fetch_question)) + question from the database using Question.fetch() + and use submit_question() to both update the database and + check whether the answer was correct. + """ + __slots__ = ["question", "answer"] + + def __init__(self, question, answer): + self.question = question + self.answer = answer + + @classmethod + def fetch(cls): + data = fetch_question() + return cls(data[0], data[1]) + + def submit_answer(self, answer): + """ + Check whether ``answer`` is correct, + update the database accordingly and + return ``True`` if the answer was correct, + ``False`` otherwise. + """ + + correct = -1 + if(answer == self.answer): + correct = 1 + + update_correct(self.question, correct) + + return correct > 0 + + diff --git a/exam/ex3/main.glade b/exam/ex3/main.glade index 9dc2289..2c42bd5 100644 --- a/exam/ex3/main.glade +++ b/exam/ex3/main.glade @@ -49,8 +49,10 @@ Submit Answer True + False True True + False @@ -72,6 +74,7 @@ True False + 4 True @@ -114,6 +117,7 @@ True True True + False @@ -124,7 +128,8 @@ False - True + False + 2 3 @@ -152,6 +157,7 @@ True False + 12 True @@ -169,6 +175,7 @@ True False + False @@ -176,20 +183,6 @@ 1 - - - Submit - True - True - True - - - - False - True - 2 - - False @@ -296,6 +289,7 @@ True False + 25 True @@ -309,10 +303,12 @@ - + + Save Questions to File True - False - + True + True + False @@ -320,20 +316,6 @@ 1 - - - Submit - True - True - True - - - - False - True - 2 - - False diff --git a/exam/ex3/main.py b/exam/ex3/main.py index 9d5c4f1..8896e4a 100644 --- a/exam/ex3/main.py +++ b/exam/ex3/main.py @@ -13,8 +13,10 @@ callback_handler = CallbackHandler(builder) handlers = { "onDestroy": Gtk.main_quit , "on_manually_add_submit_button_clicked": callback_handler.on_manually_add_submit_button_clicked - , "on_load_from_file_submit_button_clicked": callback_handler.on_load_from_file_submit_button_clicked - , "on_save_question_to_file_submit_button_clicked": callback_handler.on_save_question_to_file_submit_button_clicked + , "on_load_from_file_chooser_file_set": callback_handler.on_load_from_file_chooser_file_set + , "on_save_questions_to_file_button_clicked": callback_handler.on_save_questions_to_file_button_clicked + , "on_submit_answer_button_clicked": callback_handler.on_submit_answer_button_clicked + , "on_next_question_button_clicked": callback_handler.on_next_question_button_clicked } builder.connect_signals(handlers) diff --git a/exam/ex3/settings.py b/exam/ex3/settings.py index a2cca38..4569149 100644 --- a/exam/ex3/settings.py +++ b/exam/ex3/settings.py @@ -10,7 +10,6 @@ def load_words_from_file(file_name): data = {line[0]: line[1] for line in [ line.split() for line in fin if line] if len(line) == 2} - print("adding", data) add_words(data) def manually_add_question(question, answer): @@ -18,10 +17,10 @@ def manually_add_question(question, answer): def save_questions_to_file(file_name): db = open_database() - with open(file_name) as fout: + with open(file_name, "w") as fout: cursor = db.cursor() - cursor.execute("SELCT question, answer, correct FROM QUESTIONS") + cursor.execute("SELECT question, answer, correct FROM QUESTIONS") data = [{"question":i[0], "answer": i[1], "correct": i[2]} for i in cursor.fetchall()] - json.dump(fout) + json.dump(data, fout) db.close()