# 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 threedobject import ThreeDObject from symbolobject import SymbolObject from instructionsobject import InstructionsObject from balanceobject import BalanceObject from problem import Problem from vector import Vector import gtk, math, random class MassProblem(Problem): """ Generates a problem in which two lengths 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 = False def generate_problem(self): # Set the 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)]) # The total number of problems. self.n_problems = 9 # Choose a random problem. while (self.problem_number in self.container.recently_used): self.problem_number = random.randrange(0, self.n_problems) # Uncomment to test a particular problem. #problem_number = 0 # Define the various problems. if self.problem_number == 0: size1 = 'short' size2 = 'short' self.mass1 = 1 self.mass2 = 2 elif self.problem_number == 1: size1 = 'short' size2 = 'short' self.mass1 = 2 self.mass2 = 1 elif self.problem_number == 2: size1 = 'short' size2 = 'short' self.mass1 = 1 self.mass2 = 1 elif self.problem_number == 3: size1 = 'tall' size2 = 'short' self.mass1 = 1 self.mass2 = 2 elif self.problem_number == 4: size1 = 'tall' size2 = 'short' self.mass1 = 2 self.mass2 = 1 elif self.problem_number == 5: size1 = 'tall' size2 = 'short' self.mass1 = 1 self.mass2 = 2 elif self.problem_number == 6: size1 = 'tall' size2 = 'tall' self.mass1 = 1 self.mass2 = 2 elif self.problem_number == 7: size1 = 'tall' size2 = 'tall' self.mass1 = 2 self.mass2 = 1 elif self.problem_number == 8: size1 = 'tall' size2 = 'tall' self.mass1 = 1 self.mass2 = 2 else: size1 = 'short' size2 = 'short' # Initial positions for the shapes. if size1 == 'short': left_position = Vector(1025, 300 - 200/2) else: left_position = Vector(1025, 300 - 225/2) if size2 == 'short': right_position = Vector(1025, 575 - 200/2) else: right_position = Vector(1025, 575 - 225/2) # Randomize the initial positions of the shapes. #(original_position1, original_position2) = random.choice([(left_position, right_position), \ # (right_position, left_position)]) (original_position1, original_position2) = (left_position, right_position) if size1 == 'short': points1 = [ Vector(0, 0), Vector(150, 0), Vector(150, 200), Vector(0, 200)] else: points1 = [ Vector(0, 0), Vector(125, 0), Vector(125, 225), Vector(0, 225)] if size2 == 'short': points2 = [ Vector(0, 0), Vector(150, 0), Vector(150, 200), Vector(0, 200)] else: points2 = [ Vector(0, 0), Vector(125, 0), Vector(125, 225), Vector(0, 225)] # Switch the shapes half the time (so we get > as well as < problems). if random.choice([0,1]) == 0: self.shape1 = ThreeDObject(color1, self.letter1, points1, original_position1, 0.0, mass=self.mass1) self.shape2 = ThreeDObject(color2, self.letter2, points2, original_position2, 0.0, mass=self.mass2) else: self.shape1 = ThreeDObject(color1, self.letter2, points1, original_position1, 0.0, mass=self.mass1) self.shape2 = ThreeDObject(color2, self.letter1, points2, original_position2, 0.0, mass=self.mass2) #self.balance_object = BalanceObject(Vector(100, 100), self.container) self.balance_object = BalanceObject(Vector(36, 207), self.container) self.container.add_object(self.balance_object) return def show_problem(self): self.container.configure_dragging_area(25, 48, 32, 2 * math.pi) self.container.add_object(self.shape1) self.container.add_object(self.shape2) # Randomize which object is initially selected. if random.choice([0,1]) == 0: self.container.select_object(self.shape1) else: self.container.select_object(self.shape1) # Add letter symbols. self.container.letter1 = SymbolObject(Vector(500 + 400 - 50, 650), self.shape1.symbol, None, None, size=100) self.container.letter2 = SymbolObject(Vector(700 + 400 - 50, 650), self.shape2.symbol, 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) self.container.instructions = InstructionsObject(Vector(50, 25), 'Compare the things in mass') self.container.add_object(self.container.instructions) def place_objects_in_final_positions(self): #print "MassProblem: place_objects_in_final_positions called" # The final position of the balance. x_balance_final = 145 y_balance_final = 300 if self.balance_object.state == 'left' or self.balance_object.state == 'right': y_balance_final = 300 else: y_balance_final = 350 for o in self.container.objects: if isinstance(o, BalanceObject): o.amount_scale = 0.65 o.move(Vector(x_balance_final, y_balance_final)) for o in self.container.objects: if isinstance(o, ThreeDObject): o.scale = 0.65 o.calculate_bounds() def finish_problem_stage1(self): #print "MassProblem: finish_problem_stage1 called" pass def check_problem_solved(self): #print "Mass Problem: check_problem_solved called" #print " shape1 position =", self.shape1.pos #print " shape2 position =", self.shape2.pos if self.shape1.pos.approx_equal(self.balance_object.pan1_position, tolerance=50): #print " first mass near pan 1" if not self.balance_object.left_pan_full: self.shape1.pos = self.balance_object.pan1_position self.shape1.selected = False self.shape1.selectable = False self.shape1.draggable = False self.left_pan_object = self.shape1 self.balance_object.left_pan_full = True self.adjust_balance_state() elif self.shape1.pos.approx_equal(self.balance_object.pan2_position, tolerance=50): #print " first mass near pan 2" if not self.balance_object.right_pan_full: self.shape1.pos = self.balance_object.pan2_position self.shape1.selected = False self.shape1.selectable = False self.shape1.draggable = False self.right_pan_object = self.shape1 self.balance_object.right_pan_full = True self.adjust_balance_state() if self.shape2.pos.approx_equal(self.balance_object.pan1_position, tolerance=50): #print " second mass near pan 1" if not self.balance_object.left_pan_full: self.shape2.pos = self.balance_object.pan1_position self.shape2.selected = False self.shape2.selectable = False self.shape2.draggable = False self.left_pan_object = self.shape2 self.balance_object.left_pan_full = True self.adjust_balance_state() elif self.shape2.pos.approx_equal(self.balance_object.pan2_position, tolerance=50): #print " second mass near pan 2" if not self.balance_object.right_pan_full: self.shape2.pos = self.balance_object.pan2_position self.shape2.selected = False self.shape2.selectable = False self.shape2.draggable = False self.right_pan_object = self.shape2 self.balance_object.right_pan_full = True self.adjust_balance_state() if self.balance_object.left_pan_full and self.balance_object.right_pan_full: #print " returning True" self.adjust_balance_state() self.place_objects_in_final_positions() return True #print " returning False" return False def adjust_balance_state(self): if self.balance_object.left_pan_full and not self.balance_object.right_pan_full: self.balance_object.state = 'left' self.balance_object.pos = Vector(36, 207 - 32) self.left_pan_object.pos = Vector(200 + 5, 500 + 68) elif not self.balance_object.left_pan_full and self.balance_object.right_pan_full: self.balance_object.state = 'right' self.balance_object.pos = Vector(36, 207 - 32) self.right_pan_object.pos = Vector(725 - 35, 500 + 68) elif self.balance_object.left_pan_full and self.balance_object.right_pan_full: if self.left_pan_object.mass > self.right_pan_object.mass: self.balance_object.state = 'left' self.left_pan_object.pos = Vector(310, 635 + 55) self.right_pan_object.pos = Vector(792, 635 - 75) elif self.left_pan_object.mass < self.right_pan_object.mass: self.balance_object.state = 'right' self.left_pan_object.pos = Vector(310, 635 - 75) self.right_pan_object.pos = Vector(792, 635 + 55) else: self.balance_object.state = 'middle' self.left_pan_object.pos = Vector(310, 635) self.right_pan_object.pos = Vector(792, 635) self.balance_object.pos = Vector(36, 207) self.balance_object.adjust_balance_state() self.shape1.calculate_bounds() self.shape2.calculate_bounds() def find_answer(self): if self.shape1.mass > self.shape2.mass: self.answer = 'greater' elif self.shape1.mass < self.shape2.mass: self.answer = 'less' else: self.answer = 'equal' return self.answer