# Copyright 2008 by Peter Moxhay and Wade Brainerd. # This file is part of Math. # # Math is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Math is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Math. If not, see . from objectarea import ObjectArea, Color from vector import Vector from symbolobject import SymbolObject from instructionsobject import InstructionsObject from modelobject import ModelObject from problem import Problem from vector import Vector from groupobject import GroupObject from amountobject import AmountObject import gtk, math, random class AmountProblem(Problem): """ Generates a problem in which two amounts of discrete objects are compared. """ def __init__(self, container, color_scheme, (letter1, letter2) ): self.container = container self.color_scheme = color_scheme self.letter1 = letter1 self.letter2 = letter2 self.problem_number = -1 self.generate_problem() self.show_problem() self.answer = self.find_answer() self.container.moons_visible = True def generate_problem(self): # Choose two random colors. if self.color_scheme == 'red_green': (color1, color2) = random.choice([(Color.RED, Color.GREEN), (Color.GREEN, Color.RED)]) elif self.color_scheme == 'green_blue': (color1, color2) = random.choice([(Color.GREEN, Color.BLUE), (Color.BLUE, Color.GREEN)]) else: (color1, color2) = random.choice([(Color.RED, Color.BLUE), (Color.BLUE, Color.RED)]) square_side = 65 triangle_side = 80 # Several different small shapes SQUARE = [ Vector(0, 0), Vector(square_side, 0), Vector(square_side, square_side), Vector(0, square_side) ] TRIANGLE = [ Vector(0, 0), Vector(triangle_side/2, -triangle_side * math.sqrt(3)/2), Vector(triangle_side, 0) ] CIRCLE = [ Vector(0, 0), Vector(square_side, 0), Vector(square_side, square_side), Vector(0, square_side) ] # Standard initial positions for the shapes. upper_left_position = Vector(150, 150) lower_right_position = Vector(250, 600) # Set the initial positions of the shapes. original_position1 = upper_left_position original_position2 = lower_right_position original_position1_model = Vector(1000, 100) original_position2_model = Vector(1000, 200) # The total number of problems. self.n_problems = 8 # Choose a random problem. shape_scheme = random.randrange(0,6) # Choose a random problem. while (self.problem_number in self.container.recently_used): self.problem_number = random.randrange(0, self.n_problems) self.n_shape1 = 8 self.n_shape2 = 7 #if random.choice([0,1]) == 0: # self.shape1_in_pair = True #else: # self.shape1_in_pair = False #self.problem_number = 4 #print "problem_number =", self.problem_number if self.problem_number == 0: self.n_shape1 = 6 self.n_shape2 = 6 self.shape1_in_pair = False elif self.problem_number == 1: self.n_shape1 = 6 self.n_shape2 = 6 self.shape1_in_pair = True elif self.problem_number == 2: self.n_shape1 = 6 self.n_shape2 = 5 self.shape1_in_pair = False elif self.problem_number == 3: self.n_shape1 = 6 self.n_shape2 = 5 self.shape1_in_pair = True elif self.problem_number == 4: self.n_shape1 = 4 self.n_shape2 = 4 self.shape1_in_pair = False elif self.problem_number == 5: self.n_shape1 = 4 self.n_shape2 = 4 self.shape1_in_pair = True elif self.problem_number == 6: self.n_shape1 = 4 self.n_shape2 = 3 self.shape1_in_pair = False elif self.problem_number == 7: self.n_shape1 = 4 self.n_shape2 = 3 self.shape1_in_pair = True else: self.n_shape1 = 6 self.n_shape2 = 6 self.shape1_in_pair = False self.n_shape2_model = 1 if self.shape1_in_pair: self.n_shape1_model = 2 else: self.n_shape1_model = 1 # Define the various problems. if shape_scheme == 0: object1 = SQUARE self.shape1_name = 'square' centroid_shift_1 = Vector(0, 0) object2 = TRIANGLE self.shape2_name = 'triangle' centroid_shift_2 = Vector(0, 11) elif shape_scheme == 1: object2 = SQUARE self.shape2_name = 'square' centroid_shift_2 = Vector(0, 0) object1 = TRIANGLE self.shape1_name = 'triangle' centroid_shift_1 = Vector(0, 11) elif shape_scheme == 2: object1 = SQUARE self.shape1_name = 'square' centroid_shift_1 = Vector(0, 0) object2 = CIRCLE self.shape2_name = 'circle' centroid_shift_2 = Vector(0, 0) elif shape_scheme == 3: object2 = SQUARE self.shape2_name = 'square' centroid_shift_2 = Vector(0, 0) object1 = CIRCLE self.shape1_name = 'circle' centroid_shift_1 = Vector(0, 0) elif shape_scheme == 4: object1 = TRIANGLE self.shape1_name = 'triangle' centroid_shift_1 = Vector(0, 11) object2 = CIRCLE self.shape2_name = 'circle' centroid_shift_2 = Vector(0, 0) elif shape_scheme == 5: object2 = TRIANGLE self.shape2_name = 'triangle' centroid_shift_2 = Vector(0, 11) object1 = CIRCLE self.shape1_name = 'circle' centroid_shift_1 = Vector(0, 0) else: object1 = SQUARE self.shape1_name = 'square' centroid_shift_1 = Vector(0, 0) object2 = TRIANGLE self.shape2_name ='triangle' centroid_shift_2 = Vector(0, 11) self.shape1 = [] self.shape2 = [] self.shape1_model = [] self.shape2_model = [] for i in range(0, self.n_shape1): self.shape1.append(AmountObject(original_position1 + Vector(i*75, i % 2 *75), color1, self.shape1_name, self)) for i in range(0, self.n_shape1_model): self.shape1_model.append(AmountObject(original_position1_model + Vector(i*100, 0), color1, self.shape1_name, self)) self.shape1_model[i].draggable = False self.shape1_model[i].selectable = False for i in range(0, self.n_shape2): self.shape2.append(AmountObject(original_position2 + Vector(i*75, i % 2 *75), color2, self.shape2_name, self)) for i in range(0, self.n_shape2_model): self.shape2_model.append(AmountObject(original_position2_model + Vector(i*100, 0), color2, self.shape2_name, self)) self.shape2_model[i].draggable = False self.shape2_model[i].selectable = False def show_problem(self): self.container.configure_dragging_area(25, 48, 32, 2 * math.pi) self.container.instructions = InstructionsObject(Vector(50, 25), 'Compare the things in amount') self.container.add_object(self.container.instructions) self.model_object = ModelObject(Vector(950, 50), Vector(200, 250), self.container) self.container.add_object(self.model_object) for i in range(0, self.n_shape1): self.container.add_object(self.shape1[i]) for i in range(0, self.n_shape2): self.container.add_object(self.shape2[i]) for i in range(0, self.n_shape1_model): self.container.add_object(self.shape1_model[i]) for i in range(0, self.n_shape2_model): self.container.add_object(self.shape2_model[i]) # Randomize which object is initially selected. if random.choice([0,1]) == 0: self.container.select_object(self.shape1[0]) else: self.container.select_object(self.shape2[0]) # Add letter symbols. self.container.letter1 = SymbolObject(Vector(850, 650), self.letter1, None, None, size=100) self.container.letter2 = SymbolObject(Vector(1050, 650), self.letter2, None, None, size=100) self.container.letter1.draggable = False self.container.letter1.selectable = False self.container.letter2.draggable = False self.container.letter2.selectable = False self.container.add_object(self.container.letter1) self.container.add_object(self.container.letter2) self.container.questionmark = SymbolObject(Vector(600 + 400 - 50, 650), '?', None, None, size=80) self.container.questionmark.draggable = False self.container.questionmark.selectable = False self.container.add_object(self.container.questionmark) # Add letter symbols next to amounts. self.amount_letter1 = SymbolObject(Vector(55, 235), self.letter1, None, None, size=50) self.amount_letter2 = SymbolObject(Vector(155, 690), self.letter2, None, None, size=50) self.amount_letter1.draggable = False self.amount_letter1.selectable = False self.amount_letter2.draggable = False self.amount_letter2.selectable = False self.container.add_object(self.amount_letter1) self.container.add_object(self.amount_letter2) def scaled(self, vectors, factor): for vector in vectors: new_vectors = [v.scaled(factor) for v in vectors] return new_vectors def larger(self, vectors): for vector in vectors: new_vectors = [v.scaled(1.2) for v in vectors] return new_vectors def smaller(self, vectors): for vector in vectors: new_vectors = [v.scaled(0.8) for v in vectors] return new_vectors def place_objects_in_final_positions(self): #print "AmountProblem: place_objects_in_final_positions called" shift_x = 125 shift_y = -290 x_initial = 100 i = 0 for o in self.container.objects: if isinstance(o, GroupObject): if self.shape1_in_pair: o.amount_scale = 0.65 if self.container.problem_type == 'amount': o.move(Vector(x_initial + i * 250 + shift_x, 300 + 225 + shift_y)) else: o.move(Vector(x_initial + i * 250, 300 + 225)) else: o.amount_scale = 0.65 if self.container.problem_type == 'amount': o.move(Vector(x_initial + i * 150 + shift_x, 300 + 225 + shift_y)) else: o.move(Vector(x_initial + i * 150, 300 + 225)) o.selected = False o.selectable = False o.draggable = False i += 1 #print "There were ", i ,"GroupObjects placed into final position." j = 0 for o in self.container.objects: if isinstance(o, AmountObject): if self.shape1_in_pair: o.amount_scale = 0.65 if self.container.problem_type == 'amount': o.move(Vector(x_initial + shift_x + i * 250 + 75 + j * 250, 450 + 225 + shift_y)) else: o.move(Vector(x_initial + i * 250 + 75 + j * 250, 450 + 225)) else: o.amount_scale = 0.65 #o.move(Vector(x_initial + i * 150 + 125 + j * 150, 450 + 225)) if self.n_shape1 > self.n_shape2: #print "self.n_shape1 > self.n_shape2" #o.pos = Vector(x_initial + i * 150 + 75 + j * 150, 350 + 225) if self.container.problem_type == 'amount': o.move(Vector(x_initial + shift_x + i * 150 + 75 + j * 150, 350 + 225 + shift_y)) else: o.move(Vector(x_initial + i * 150 + 75 + j * 150, 350 + 225)) else: #print "self.n_shape1 < self.n_shape2" #o.pos = Vector(x_initial + i * 150 + 75 + j * 150, 450 + 225) if self.container.problem_type == 'amount': o.move(Vector(x_initial + shift_x + i * 150 + 75 + j * 150, 450 + 225 + shift_y)) else: o.move(Vector(x_initial + i * 150 + 75 + j * 150, 450 + 225)) o.selected = False o.selectable = False o.draggable = False j += 1 #print "There were ", j ,"AmountObjects placed into final position." def finish_problem_stage1(self): #print "AmountProblem: finish_problem_stage1 called" if self.container.problem_type == 'amount': self.amount_letter1.move(Vector(90, 180)) self.amount_letter2.move(Vector(90, 260)) else: self.amount_letter1.move(Vector(375, 275)) self.amount_letter2.move(Vector(375, 525)) self.amount_letter1.symbol_visible = True self.amount_letter2.symbol_visible = True def check_problem_solved(self): #print "Amount Problem: check_problem_solved called" if self.shape1_in_pair: self.check_problem_solved_pair() if (len(self.shape1) == 0 or len(self.shape2) == 0): for i in range(0, self.n_shape1_model): self.container.remove_object(self.shape1_model[i]) for i in range(0, self.n_shape2_model): self.container.remove_object(self.shape2_model[i]) if self.container and self.model_object: self.container.remove_object(self.model_object) self.place_objects_in_final_positions() return True else: return False i_to_be_removed = -1 j_to_be_removed = -1 time_to_break_outer_loop = False for i in range(0, len(self.shape1)): if time_to_break_outer_loop: break for j in range(0, len(self.shape2)): if Vector.approx_equal(self.shape1[i].pos, self.shape2[j].pos, 100): #print "Amount Problem: check_problem_solved adding a group" #print " New x =", (self.shape1[i].pos.x + self.shape2[j].pos.x)/2 #print " New y =", (self.shape1[i].pos.y + self.shape2[j].pos.y)/2 self.group_object = GroupObject( Vector((self.shape1[i].pos.x + self.shape2[j].pos.x)/2 - 50, \ 300), \ Vector(125, 200), self.shape1[i].color, self.shape1_name, \ self.shape2[j].color, self.shape2_name, False, self.container) self.container.add_object(self.group_object) self.group_object.selectable = True self.container.select_object(self.group_object) self.container.adjust_tab_order() self.container.moons_visible = False self.amount_letter1.symbol_visible = False self.amount_letter2.symbol_visible = False i_to_be_removed = i j_to_be_removed = j time_to_break_outer_loop = True break if i_to_be_removed != -1: self.shape1[i_to_be_removed].selected = False self.shape1[i_to_be_removed].selectable = False self.container.remove_object(self.shape1[i_to_be_removed]) self.shape1.remove(self.shape1[i_to_be_removed]) if j_to_be_removed != -1: self.shape2[j_to_be_removed].selected = False self.shape2[j_to_be_removed].selectable = False self.container.remove_object(self.shape2[j_to_be_removed]) self.shape2.remove(self.shape2[j_to_be_removed]) if (len(self.shape1) == 0 or len(self.shape2) == 0): for i in range(0, self.n_shape1_model): self.container.remove_object(self.shape1_model[i]) for i in range(0, self.n_shape2_model): self.container.remove_object(self.shape2_model[i]) if self.container and self.model_object: self.container.remove_object(self.model_object) self.place_objects_in_final_positions() return True else: return False return False def check_problem_solved_pair(self): #print "Amount Problem: check_problem_solved_pair called" time_to_break_outer_loop = False time_to_break_middle_loop = False for i in range(0, len(self.shape1)): if time_to_break_outer_loop: break for j in range(0, len(self.shape2)): if time_to_break_middle_loop: break for k in range(0, len(self.shape1)): if i != k and \ Vector.approx_equal(self.shape1[i].pos, self.shape2[j].pos, 100) and \ Vector.approx_equal(self.shape1[k].pos, self.shape2[j].pos, 100): #self.group_object = GroupObject( Vector((self.shape1[i].pos.x + self.shape2[j].pos.x)/2 - 50, \ # (self.shape1[i].pos.y + self.shape2[j].pos.y)/2 - 100), \ # Vector(125, 200), self.shape1[i].color, self.shape1_name, \ # self.shape2[j].color, self.shape2_name, True, self.container) self.group_object = GroupObject( Vector((self.shape1[i].pos.x + self.shape2[j].pos.x)/2 - 50, \ 300), \ Vector(125, 200), self.shape1[i].color, self.shape1_name, \ self.shape2[j].color, self.shape2_name, True, self.container) self.group_object.selectable = True self.container.select_object(self.group_object) self.container.moons_visible = False self.amount_letter1.symbol_visible = False self.amount_letter2.symbol_visible = False self.container.remove_object(self.shape1[i]) self.shape1.remove(self.shape1[i]) self.container.remove_object(self.shape1[k - 1]) self.shape1.remove(self.shape1[k - 1]) self.container.remove_object(self.shape2[j]) self.shape2.remove(self.shape2[j]) self.container.add_object(self.group_object) time_to_break_middle_loop = True time_to_break_outer_loop = True break #print "len(self.shape1) =", len(self.shape1) #print "len(self.shape2) =", len(self.shape2) if (len(self.shape1) == 0 or len(self.shape2) == 0): return True else: return False def find_answer(self): if self.shape1_in_pair: if self.n_shape1/2 > self.n_shape2: self.answer = 'greater' elif self.n_shape1/2 < self.n_shape2: self.answer = 'less' else: self.answer = 'equal' else: if self.n_shape1 > self.n_shape2: self.answer = 'greater' elif self.n_shape1 < self.n_shape2: self.answer = 'less' else: self.answer = 'equal' return self.answer