finished off the app
This commit is contained in:
parent
5585f1bdb8
commit
36f4ee2501
|
@ -1,8 +1,12 @@
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
from settings import load_words_from_file, manually_add_question, save_questions_to_file
|
from settings import load_words_from_file, manually_add_question, save_questions_to_file
|
||||||
|
from exercise import Question
|
||||||
|
|
||||||
class CallbackHandler(object):
|
class CallbackHandler(object):
|
||||||
def __init__(self, gtk_builder):
|
def __init__(self, gtk_builder):
|
||||||
self.builder = gtk_builder
|
self.builder = gtk_builder
|
||||||
|
self.question = None
|
||||||
def on_manually_add_submit_button_clicked(self, widget):
|
def on_manually_add_submit_button_clicked(self, widget):
|
||||||
question_view = self.builder.get_object("add_question_question_view")
|
question_view = self.builder.get_object("add_question_question_view")
|
||||||
answer_view = self.builder.get_object("add_question_answer_view")
|
answer_view = self.builder.get_object("add_question_answer_view")
|
||||||
|
@ -10,18 +14,65 @@ class CallbackHandler(object):
|
||||||
question = question_view.get_text()
|
question = question_view.get_text()
|
||||||
answer = answer_view.get_text()
|
answer = answer_view.get_text()
|
||||||
|
|
||||||
|
try:
|
||||||
manually_add_question(question, answer)
|
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_chooser = self.builder.get_object("load_from_file_chooser")
|
||||||
file_name = file_chooser.get_filename()
|
file_name = file_chooser.get_filename()
|
||||||
load_words_from_file(file_name)
|
load_words_from_file(file_name)
|
||||||
|
|
||||||
def on_save_question_to_file_submit_button_clicked(self, widget):
|
def on_save_questions_to_file_button_clicked(self, widget):
|
||||||
file_chooser = self.builder.get_object("save_questions_to_file_chooser")
|
dialog = Gtk.FileChooserDialog("Please choose a file", None
|
||||||
file_name = file_chooser.get_filename()
|
, 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)
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,8 @@ def create_database():
|
||||||
|
|
||||||
db = sqlite3.connect(database_path)
|
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()
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,24 +30,42 @@ def update_correct(question, correct):
|
||||||
"""
|
"""
|
||||||
db = open_database()
|
db = open_database()
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
|
try:
|
||||||
cursor.execute("UPDATE QUESTIONS SET correct=correct + ? WHERE question = ?", (correct, question))
|
cursor.execute("UPDATE QUESTIONS SET correct=correct + ? WHERE question = ?", (correct, question))
|
||||||
|
except sqlite3.IntegrityError:
|
||||||
|
pass
|
||||||
|
db.commit()
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
def add_word(question, answer):
|
def add_word(question, answer):
|
||||||
db = open_database()
|
db = open_database()
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
cursor.execute("INSERT INTO QUESTIONS(question, answer, correct) VALUES(?, ?, 0)", (question, answer))
|
cursor.execute("INSERT INTO QUESTIONS(question, answer, correct) VALUES(?, ?, 0)", (question, answer))
|
||||||
|
db.commit()
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
def add_words(input_data):
|
def add_words(input_data):
|
||||||
db = open_database()
|
db = open_database()
|
||||||
cursor = db.cursor()
|
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()
|
db.close()
|
||||||
print("added words")
|
|
||||||
|
|
||||||
def fetch_question():
|
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()
|
db = open_database()
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
|
|
||||||
|
@ -58,10 +77,10 @@ def fetch_question():
|
||||||
if(fetch_questions == 0):
|
if(fetch_questions == 0):
|
||||||
fetch_questions = 1
|
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)
|
my_result = random.choice(result)
|
||||||
return result[:2]
|
return my_result[:2]
|
||||||
|
|
||||||
|
|
41
exam/ex3/exercise.py
Normal file
41
exam/ex3/exercise.py
Normal file
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -49,8 +49,10 @@
|
||||||
<object class="GtkButton" id="submit_answer_button">
|
<object class="GtkButton" id="submit_answer_button">
|
||||||
<property name="label" translatable="yes">Submit Answer</property>
|
<property name="label" translatable="yes">Submit Answer</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
<property name="sensitive">False</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
|
<signal name="clicked" handler="on_submit_answer_button_clicked" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
|
@ -72,6 +74,7 @@
|
||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
<property name="spacing">4</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
@ -114,6 +117,7 @@
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
|
<signal name="clicked" handler="on_next_question_button_clicked" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
|
@ -124,7 +128,8 @@
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">False</property>
|
||||||
|
<property name="padding">2</property>
|
||||||
<property name="position">3</property>
|
<property name="position">3</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
@ -152,6 +157,7 @@
|
||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
<property name="spacing">12</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel">
|
<object class="GtkLabel">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
@ -169,6 +175,7 @@
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="title" translatable="yes"/>
|
<property name="title" translatable="yes"/>
|
||||||
|
<signal name="file-set" handler="on_load_from_file_chooser_file_set" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
|
@ -176,20 +183,6 @@
|
||||||
<property name="position">1</property>
|
<property name="position">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<object class="GtkButton" id="load_from_file_submit_button">
|
|
||||||
<property name="label" translatable="yes">Submit</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="receives_default">True</property>
|
|
||||||
<signal name="clicked" handler="on_load_from_file_submit_button_clicked" swapped="no"/>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">True</property>
|
|
||||||
<property name="position">2</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
|
@ -296,6 +289,7 @@
|
||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
<property name="spacing">25</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel">
|
<object class="GtkLabel">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
@ -309,10 +303,12 @@
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkFileChooserButton" id="save_questions_to_file_chooser">
|
<object class="GtkButton" id="save_questions_to_file_button">
|
||||||
|
<property name="label" translatable="yes">Save Questions to File</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="title" translatable="yes"/>
|
<property name="receives_default">True</property>
|
||||||
|
<signal name="clicked" handler="on_save_questions_to_file_button_clicked" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
|
@ -320,20 +316,6 @@
|
||||||
<property name="position">1</property>
|
<property name="position">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<object class="GtkButton" id="save_question_to_file_submit_button">
|
|
||||||
<property name="label" translatable="yes">Submit</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="receives_default">True</property>
|
|
||||||
<signal name="clicked" handler="on_save_question_to_file_submit_button_clicked" swapped="no"/>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">True</property>
|
|
||||||
<property name="position">2</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
|
|
|
@ -13,8 +13,10 @@ callback_handler = CallbackHandler(builder)
|
||||||
handlers = {
|
handlers = {
|
||||||
"onDestroy": Gtk.main_quit
|
"onDestroy": Gtk.main_quit
|
||||||
, "on_manually_add_submit_button_clicked": callback_handler.on_manually_add_submit_button_clicked
|
, "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_load_from_file_chooser_file_set": callback_handler.on_load_from_file_chooser_file_set
|
||||||
, "on_save_question_to_file_submit_button_clicked": callback_handler.on_save_question_to_file_submit_button_clicked
|
, "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)
|
builder.connect_signals(handlers)
|
||||||
|
|
|
@ -10,7 +10,6 @@ def load_words_from_file(file_name):
|
||||||
data = {line[0]: line[1] for line in
|
data = {line[0]: line[1] for line in
|
||||||
[ line.split() for line in fin if line]
|
[ line.split() for line in fin if line]
|
||||||
if len(line) == 2}
|
if len(line) == 2}
|
||||||
print("adding", data)
|
|
||||||
add_words(data)
|
add_words(data)
|
||||||
|
|
||||||
def manually_add_question(question, answer):
|
def manually_add_question(question, answer):
|
||||||
|
@ -18,10 +17,10 @@ def manually_add_question(question, answer):
|
||||||
|
|
||||||
def save_questions_to_file(file_name):
|
def save_questions_to_file(file_name):
|
||||||
db = open_database()
|
db = open_database()
|
||||||
with open(file_name) as fout:
|
with open(file_name, "w") as fout:
|
||||||
cursor = db.cursor()
|
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()]
|
data = [{"question":i[0], "answer": i[1], "correct": i[2]} for i in cursor.fetchall()]
|
||||||
|
|
||||||
json.dump(fout)
|
json.dump(data, fout)
|
||||||
db.close()
|
db.close()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user