From 9456b125831c9cbc06f340e269c261d9627ac083 Mon Sep 17 00:00:00 2001 From: Mike Major Date: Sat, 22 Aug 2009 02:20:02 +0000 Subject: Rewritten with MVC; Progressive levels; Tabbed user input. Levels start at 'rounding to 10' and proceed through the next decades. --- diff --git a/activity/activity.info b/activity/activity.info index 843f4a5..7abc7f6 100644 --- a/activity/activity.info +++ b/activity/activity.info @@ -3,6 +3,6 @@ name = Hop-A-Round bundle_id = org.laptop.HopaRound class = hoparound.HopaRoundActivity icon = hoparound-icon -activity_version = 6 +activity_version = 7 host_version = 1 show_launcher = yes diff --git a/data.py b/data.py new file mode 100644 index 0000000..dd45592 --- /dev/null +++ b/data.py @@ -0,0 +1,83 @@ +import random, math + +class LevelData(): + def __init__(self): + self.digits = [] + self.min_level = 1 + self.max_level = 5 + self.thresh_up = 6 + self.thresh_down = 0 + self.current_level = 1 + self.level_change = 0 + self.level_score = 0 + self.question_max = 6 + self.question_count = 0 + self.thresh_slider = 0 + self.thresh_mult = 2 + self.thresh_entry = 4 + random.seed() + + def check_answer(self, response): + if response == self.correct_answer: + self.level_score += 1 + else: + self.level_score -= 1 + if self.question_count == self.question_max: + if self.level_score >= self.thresh_up and self.current_level < self.max_level: + self.level_change = 1 + elif self.level_score <= self.thresh_down and self.current_level > self.min_level: + self.level_change = -1 + self.question_count = self.level_score = 0 + return self.correct_answer == response + + def increase_level(self): + if self.current_level < self.max_level: + self.current_level += 1 + self.answer_decade = int(10**self.current_level) + self.level_change = 0 + + def decrease_level(self): + if self.current_level > self.min_level: + self.current_level -= 1 + self.answer_decade = int(10**self.current_level) + self.level_change = 0 + + def gen_random(self): + if self.level_change == 1: + self.increase_level() + elif self.level_change == -1: + self.decrease_level() + self.question_count += 1 + # generate a random number. don't use digits 0 or 9; they cause duplicates in the mult choice answer set. + self.digits = range(1,9) + random.shuffle(self.digits) + str_num = "" + for x in range(0, self.current_level + 2): + str_num += str(random.choice(self.digits)) + self.random_number = int(str_num) + self.answer_decade = int(math.pow(10, self.current_level)) + self.correct_answer = int(round(self.random_number/(self.answer_decade*1.0), 0) * self.answer_decade) + # create the multiple choice possibilities + self.mult=[] + self.mult.append(int(math.floor(self.random_number/(self.answer_decade*1.0)) * self.answer_decade)) + self.mult.append(int(math.ceil(self.random_number/(self.answer_decade*1.0)) * self.answer_decade)) + if self.current_level == self.min_level: + self.mult.append(int(math.floor(self.random_number/(self.answer_decade*10.0)) * self.answer_decade * 10.0)) + self.mult.append(int(math.ceil(self.random_number/(self.answer_decade*10.0)) * self.answer_decade * 10.0)) + elif self.current_level == self.max_level: + self.mult.append(int(math.floor(self.random_number/(self.answer_decade*0.1)) * self.answer_decade * 0.1)) + self.mult.append(int(math.ceil(self.random_number/(self.answer_decade*0.1)) * self.answer_decade * 0.1)) + else: + factor = random.choice([0.1,10.0]) + self.mult.append(int(math.floor(self.random_number/(self.answer_decade*factor)) * self.answer_decade * factor)) + self.mult.append(int(math.ceil(self.random_number/(self.answer_decade*factor)) * self.answer_decade * factor)) + + def show_game_data(self): + temp = "\nLevel: " + str(self.current_level) + #temp += "\nRandom Number: " + str(self.random_number) + #temp += "\nDecade: " + str(self.answer_decade) + #temp += "\nCorrect Answer: " + str(self.correct_answer) + #temp += "\nMult Choices: " + str(self.mult) + temp += "\nScore: " + str(self.level_score) + temp += "\nCount: " + str(self.question_count) + return temp diff --git a/hoparound.py b/hoparound.py index 376a063..9d98c5e 100755..100644 --- a/hoparound.py +++ b/hoparound.py @@ -1,179 +1,50 @@ -import gtk, math -import random, locale +from data import LevelData +from view import Views +import gtk, locale from sugar.activity import activity - -class HopaRoundActivity(activity.Activity): - def __init__(self, handle): - activity.Activity.__init__(self, handle) - print "INFO: activity running" - locale.setlocale(locale.LC_ALL,"") - # make the toolbox - toolbox = activity.ActivityToolbox(self) - self.set_toolbox(toolbox) - toolbox.show() - #initialize variables - print "INFO: initialize variables" - self.decades = (10,100,1000,10000,100000) - self.rounded={0:0,1:1,2:2,3:3,4:4,9:0,10:0,11:0,99:0,100:0,101:0,999:0,1000:0,1001:0,9999:0,10000:0,10001:0,99999:0,100000:0,100001:0} - self.lower_bound = 1 - self.upper_bound = 500000 - self.correct = 0 - self.incorrect = 0 - self.dec_answer = 0 - random.seed() - self.correct_answer = gtk.gdk.pixbuf_new_from_file("hoppy-right.svg") - self.incorrect_answer = gtk.gdk.pixbuf_new_from_file("hoppy-wrong.svg") - self.image_answer = gtk.Image() - #create view ports - print "INFO: create view ports" - self.main_view = gtk.HBox() - self.panels = gtk.VBox() - self.panes = gtk.HBox(True) - self.left_view = gtk.VBox() - self.mid_view = gtk.VBox() - self.right_view = gtk.VBox() - self.instructions = gtk.Label() - self.instructions.set_justify(gtk.JUSTIFY_LEFT) - self.instructions.set_markup("\n\nLet's play...") - self.type_answer_instructions = gtk.Label("Type your answer below") - self.mult_instructions = gtk.Label("Choose one of the answers below") - self.answer = gtk.Entry() - self.answer.set_text("?") - self.answer.connect("activate", self.check_answer, 0) - self.play_btn = gtk.Button("Play") - self.play_btn.connect("clicked", self.play) - self.check_answer_btn = gtk.Button("Check Answer") - self.check_answer_btn.connect("clicked", self.check_answer, 0) - self.mult_1 = gtk.Button() - self.mult_1.connect("clicked", self.check_answer, 1) - self.mult_2 = gtk.Button() - self.mult_2.connect("clicked", self.check_answer, 2) - self.mult_3 = gtk.Button() - self.mult_3.connect("clicked", self.check_answer, 3) - self.mult_4 = gtk.Button() - self.mult_4.connect("clicked", self.check_answer, 4) - self.output = gtk.Label() - self.output.set_justify(gtk.JUSTIFY_LEFT) - #show the widgets - print "INFO: show widgets" - self.main_view.pack_start(self.panels, False, False, 10) - self.main_view.pack_start(self.right_view, False, False, 10) - self.panels.pack_start(self.instructions, False, False, 10) - self.panels.pack_start(self.play_btn, False, False, 10) - self.panels.pack_start(self.panes, False, False, 10) - self.panes.pack_start(self.left_view, False, False, 10) - self.panes.pack_start(self.mid_view, False, False, 10) - self.left_view.pack_start(self.type_answer_instructions, False, False, 10) - self.left_view.pack_start(self.answer, False, False, 10) - self.left_view.pack_start(self.check_answer_btn, False, False, 10) - self.mid_view.pack_start(self.mult_instructions, False, False, 10) - self.mid_view.pack_start(self.mult_1, False, False, 10) - self.mid_view.pack_start(self.mult_2, False, False, 10) - self.mid_view.pack_start(self.mult_3, False, False, 10) - self.mid_view.pack_start(self.mult_4, False, False, 10) - self.right_view.pack_start(self.output, False, False, 10) - self.right_view.pack_start(self.image_answer, False, False, 10) - self.set_canvas(self.main_view) - self.show_all() - self.play_btn.grab_focus() - - def play(self, widget): - print "INFO: play clicked" - self.dec_answer = random.choice(self.decades) - self.gen_random(self) - self.guesses = 0 - self.answer.set_text("?") - message = "\nRound the number " - message += locale.format("%d", self.rounded[0], True) - message += " to the nearest " - message += locale.format("%d", self.dec_answer, True) - message += ":\n" - self.instructions.set_markup(message) - self.mult_1.set_label(locale.format("%d", self.rounded[1], True)) - self.mult_2.set_label(locale.format("%d", self.rounded[2], True)) - self.mult_3.set_label(locale.format("%d", self.rounded[3], True)) - self.mult_4.set_label(locale.format("%d", self.rounded[4], True)) - message = "Correct:\t\t" + str(self.correct) - message += "\nIncorrect:\t" + str(self.incorrect) - self.image_answer.clear() - self.output.set_markup(message) - #self.show_random_numbers(self) - self.answer.grab_focus() - - def check_answer(self, widget, response=None): - print "INFO: check answer clicked" - print "INFO: response = '" + str(response) + "'" - try: - if response == 0: - print "INFO: entry = '" + str(self.answer.get_text()) + "'" - response = int(self.answer.get_text()) - elif response == 1: response = self.rounded[response] - elif response == 2: response = self.rounded[response] - elif response == 3: response = self.rounded[response] - elif response == 4: response = self.rounded[response] - if response == self.rounded[self.dec_answer]: - self.correct += 1 - message = "Correct:\t\t" + str(self.correct) - message += "\nIncorrect:\t" + str(self.incorrect) - message += "\n\nThat's correct!\n\n\n\n" - self.output.set_markup(message) - self.image_answer.set_from_pixbuf(self.correct_answer) - self.instructions.set_markup("\n\nLet's play...") - self.answer.set_text("?") - self.play_btn.grab_focus() - else: - self.incorrect += 1 - message = "Correct:\t\t" + str(self.correct) - message += "\nIncorrect:\t" + str(self.incorrect) - message += "\n\nSorry, the correct answer was\n" - message += locale.format('%d', self.rounded[self.dec_answer], True) - message += "\n\nYou answered\n" + str(response) - message += "" - self.output.set_markup(message) - self.image_answer.set_from_pixbuf(self.incorrect_answer) - self.answer.set_text("?") - self.play_btn.grab_focus() - except: - message = "Please enter a number only." - self.output.set_markup(message) - self.answer.grab_focus() - - def gen_random(self, widget): - print "INFO: generating random number" - #generate a random number and round it to the different decades - self.rounded[0] = random.randint(self.lower_bound,self.upper_bound) - for item in self.decades: - self.rounded[item-1] = int(math.floor(self.rounded[0]/(item*1.0)) * item) - self.rounded[item] = int(round(self.rounded[0]/(item*1.0), 0) * item) - self.rounded[item+1] = int(math.ceil(self.rounded[0]/(item*1.0)) * item) - #create a list of decades that are not the right answer and choose one - self.dec_temp_list = [10, 100, 1000, 10000, 100000] - del self.dec_temp_list[self.dec_temp_list.index(self.dec_answer)] - self.dec_temp = random.choice(self.dec_temp_list) - #generate the multiple choice answer set - self.mult = range(1,5) - self.mult_temp = random.choice(self.mult) - self.rounded[self.mult_temp] = self.rounded[self.dec_answer - 1] - del self.mult[self.mult.index(self.mult_temp)] - self.mult_temp = random.choice(self.mult) - self.rounded[self.mult_temp] = self.rounded[self.dec_answer + 1] - del self.mult[self.mult.index(self.mult_temp)] - self.mult_temp = random.choice(self.mult) - self.rounded[self.mult_temp] = self.rounded[self.dec_temp - 1] - del self.mult[self.mult.index(self.mult_temp)] - self.mult_temp = random.choice(self.mult) - self.rounded[self.mult_temp] = self.rounded[self.dec_temp + 1] - - def show_random_numbers(self, widget): - print "INFO: showing random numbers" - message = "Lower Bound: \t\t\t" + str(self.lower_bound) + "" - message += "\n\nUpper Bound: \t\t\t" + str(self.upper_bound) + "" - message += "\n\nNumber Generated: \t" + str(self.rounded[0]) + "" - message += "\n" - for item in self.rounded: - #1message += "\n\nRounded to 10" + str(int(math.log10(item))) + ": \t\t" + str(self.rounded[item]) + "" - #2message += str(item-1) + ": \t" + str(self.rounded[item-1]) + "\n" - #2message += str(item) + ": \t" + str(self.rounded[item]) + "\n" - #2message += str(item+1) + ": \t" + str(self.rounded[item+1]) + "\n" - message += str(item) + ":\t" + str(self.rounded[item]) + "\n" - self.output.set_markup(message) +import locale + +class HopaRoundActivity(activity.Activity): + def __init__(self, handle): + activity.Activity.__init__(self, handle) + # make the toolbox + toolbox = activity.ActivityToolbox(self) + self.set_toolbox(toolbox) + toolbox.show() + self.data = LevelData() + self.ui = Views() + self.ui.slider_click.connect("clicked", self.submit_answer, self.ui.slider_tool) + self.ui.mult_1.connect("clicked", self.submit_answer, self.ui.mult_1) + self.ui.mult_2.connect("clicked", self.submit_answer, self.ui.mult_2) + self.ui.mult_3.connect("clicked", self.submit_answer, self.ui.mult_3) + self.ui.mult_4.connect("clicked", self.submit_answer, self.ui.mult_4) + self.ui.entry_click.connect("clicked", self.submit_answer, self.ui.entry_tool) + self.ui.entry_tool.connect("activate", self.submit_answer, self.ui.entry_tool) + self.setup(self.data, self.ui) + #sugar canvas + self.set_canvas(self.ui.get_user_interaction()) + self.show_all() + + def setup(self, data, ui): + data.gen_random() + ui.set_rounding_phrase(self.data) + ui.set_choices(self.data.random_number, self.data.mult) + ui.set_tab(self.data) + + def submit_answer(self, widget, answer): + try: # for int answer because of entry field + if answer.get_name() == "GtkHScale": + num = int(answer.get_value()) + elif answer.get_name() == "GtkButton": + num = locale.atoi(answer.get_label()) + elif answer.get_name() == "GtkEntry": + num = locale.atoi(answer.get_text()) + except: + self.ui.answer_nan() + else: + if self.data.check_answer(num): + self.ui.answer_correct(self.data) + else: + self.ui.answer_incorrect(self.data) + self.setup(self.data, self.ui) + diff --git a/view.py b/view.py new file mode 100644 index 0000000..7b8bdbb --- /dev/null +++ b/view.py @@ -0,0 +1,115 @@ +import gtk, random +import locale + +class Views(): + def __init__(self): + locale.setlocale(locale.LC_ALL,"") + self.user_interaction = gtk.HBox() + self.user_input = gtk.VBox() + self.user_interaction.pack_start(self.user_input, False, False, 10) + self.rounding_phrase = gtk.Label("rounding phrase") + self.user_input.pack_start(self.rounding_phrase, False, False, 10) + #create the notebook + self.tabber = gtk.Notebook() + self.tabber.set_show_tabs(False) + self.user_input.pack_start(self.tabber, False, False, 10) + #create the slider tab + self.slider_tab = gtk.VButtonBox() + self.slider_instruction = gtk.Label("Move the slider to choose the correct answer") + self.slider_tab.pack_start(self.slider_instruction, False, False, 10) + self.slider_adjustment = gtk.Adjustment() + self.slider_tool = gtk.HScale(self.slider_adjustment) + self.slider_tool.set_digits(0) + self.slider_tab.pack_start(self.slider_tool, False, False, 10) + self.slider_click = gtk.Button("OK") + self.slider_tab.pack_start(self.slider_click, False, False, 10) + self.tabber.append_page(self.slider_tab) + #create the multiple choice tab + self.mult_tab = gtk.VBox() + self.mult_instruction = gtk.Label("Choose one of the answers below") + self.mult_tab.pack_start(self.mult_instruction, False, False, 10) + self.mult_1 = gtk.Button() + self.mult_tab.pack_start(self.mult_1, False, False, 10) + self.mult_2 = gtk.Button() + self.mult_tab.pack_start(self.mult_2, False, False, 10) + self.mult_3 = gtk.Button() + self.mult_tab.pack_start(self.mult_3, False, False, 10) + self.mult_4 = gtk.Button() + self.mult_tab.pack_start(self.mult_4, False, False, 10) + self.tabber.append_page(self.mult_tab) + #create the entry tab + self.entry_tab = gtk.VButtonBox() + self.entry_instruction = gtk.Label("Type your answer below and click 'OK'") + self.entry_tab.pack_start(self.entry_instruction, False, False, 10) + self.entry_tool = gtk.Entry() + self.entry_tab.pack_start(self.entry_tool, False, False, 10) + self.entry_click = gtk.Button("OK") + self.entry_tab.pack_start(self.entry_click, False, False, 10) + self.tabber.append_page(self.entry_tab) + #create the output + self.user_output = gtk.VBox() + self.user_interaction.pack_start(self.user_output, False, False, 10) + self.output = gtk.Label("") + self.output.set_alignment(0.1, 0.5) + self.user_output.pack_start(self.output, False, False, 10) + self.image_output = gtk.Image() + self.user_output.pack_start(self.image_output, False, False, 10) + self.image_correct_answer = gtk.gdk.pixbuf_new_from_file("hoppy-right.svg") + self.image_incorrect_answer = gtk.gdk.pixbuf_new_from_file("hoppy-wrong.svg") + + def get_user_interaction(self): + return self.user_interaction + + def set_rounding_phrase(self, data): + text = "Round the number " + text += self.locl(data.random_number) + text += " to the nearest " + text += self.locl(data.answer_decade) + "" + self.rounding_phrase.set_markup(text) + + def set_choices(self, number, choices): + self.slider_adjustment.set_all(number, choices[0], choices[1], 1) + # shuffle around the possibilities + random.shuffle(choices) + self.mult_1.set_label(self.locl(choices[0])) + self.mult_2.set_label(self.locl(choices[1])) + self.mult_3.set_label(self.locl(choices[2])) + self.mult_4.set_label(self.locl(choices[3])) + self.entry_tool.set_text("") + + def answer_correct(self, data): + text = "That's Right!!! =8-) \n\n" + text += self.locl(data.random_number) + " rounded to the nearest " + text += self.locl(data.answer_decade) + " is " + self.locl(data.correct_answer) + if data.level_change: + text += "\n\nYou made it to the next level! =8^P" + text += "\n" #+ data.show_game_data() + self.output.set_markup(text) + self.image_output.set_from_pixbuf(self.image_correct_answer) + + def answer_incorrect(self, data): + text = "Sorry Charlie >:( \n\n" + text += self.locl(data.random_number) + " rounded to the nearest " + text += self.locl(data.answer_decade) + " is " + self.locl(data.correct_answer) + if data.level_change: + text += "\n\nYou dropped a level. Concentrate! >8^|" + text += "\n" #+ data.show_game_data() + self.output.set_markup(text) + self.image_output.set_from_pixbuf(self.image_incorrect_answer) + + def answer_nan(self): + text = "Please enter only numbers. \n\n" + self.output.set_markup(text) + + def set_tab(self, data): + if data.question_count > data.thresh_entry: + self.tabber.set_current_page(2) + self.entry_tool.grab_focus() + elif data.question_count > data.thresh_mult: + self.tabber.set_current_page(1) + elif data.question_count > data.thresh_slider: + self.tabber.set_current_page(0) + self.slider_tool.grab_focus() + + def locl(self, characters): + return str(locale.format("%d", characters, True)) -- cgit v0.9.1