class Test(unittest.TestCase): def setUp(self): self.loader = Loader() def test_correctly_formatted_input(self): # use the reload object functionality to load the simulation # this way the user doesn't have to select the correct file for each simulation self.loader.filename = 'ballformation.sim' # the visual library causes tracebacks on exit (on IDLE) scene.visible = 0 objects, errors = self.loader.loadObjects(True) self.assertEqual(Loader.OBJECTS_LOADED, errors) test_value = False if 'Ball1' in objects.keys(): test_value = True self.assertEqual(True, test_value) if 'Ball2' in objects.keys(): test_value = True self.assertEqual(True, test_value) if 'Ball3' in objects.keys(): test_value = True self.assertEqual(True, test_value) if 'Ball4' in objects.keys(): test_value = True self.assertEqual(True, test_value) if 'Ball5' in objects.keys(): test_value = True self.assertEqual(True, test_value) if 'Ball6' in objects.keys(): test_value = True self.assertEqual(True, test_value) def test_empty_file(self): scene.visible = 0 self.loader.filename = 'empty_file.sim' objects, errors = self.loader.loadObjects(True) self.assertEqual(0, errors) self.assertEqual(0, len(objects)) def test_invalid_input(self): # use the reload object functionality to load the simulation # this way the user doesn't have to select the correct file for each simulation self.loader.filename = 'broken_file.sim' # the visual library causes tracebacks on exit scene.visible = 0 objects, errors = self.loader.loadObjects(True) self.assertEqual(Loader.ERRORS_OCCURRED, errors) # check the errors from the errorlog-file def test_nonexistent_filename(self): # possible if someone loads a file, then removes the file from the # computer and hits reload simulation scene.visible = 0 self.loader.filename = 'nonexistent_file.sim' objects, errors = self.loader.loadObjects(True) self.assertEqual(Loader.FILE_NOT_OPENED, errors) self.assertEqual(None, objects)
class World(Thread): def __init__(self, controlwindow): super(World, self).__init__() self.objects = {} # dictionary holding the objects self.cw = controlwindow self.loader = Loader() self.solver = Solver(self.objects) self.condition = Condition() self.paused = True self.end = False self.show_vectors = False self.make_trail = False self.t = 0 # time self.count = 0 # used to count updates per second value self.speed = 0 # simulation speed in updates/second self.acceleration_gain = 1 # gain value that is used to adjust acceleration vector lengths self.acceleration_scale = 1 self.velocity_scale = 1 self.errors = 0 # error flag, ControlWindow checks this for errors when loading a new simulation self.lock = Lock() self.time_elapsed = 0 # amount of seconds simulated self.reference = None # camera reference object def run(self): while not self.end: self.waitRequest() if not self.paused: self.update() def waitRequest(self): if self.paused: try: with self.condition: #print "Waiting.." self.condition.wait() #print "Continuing.." except KeyboardInterrupt: self.paused = False def startSimulation(self): self.paused = False with self.condition: self.condition.notify() def stopSimulation(self): self.paused = True def update(self): if self.objects: try: self.solver.integrate(self.lock) self.time_elapsed += self.solver.dt except CollisionError as err: print err self.paused = True # if a collision happens, pause simulation self.cw.reportCollision(str(err)) if self.t+1.0>=clock(): self.count+=1 else: #print self.count, ' /s' self.speed = self.count self.count=0 self.t=clock() if self.reference is not None: scene.center = self.reference.position def setReference(self, reference): if reference is not None: self.reference = self.objects[reference] scene.center = self.reference.position else: self.reference = None scene.center = vector(0,0,0) def close(self): self.paused = False self.end = True with self.condition: self.condition.notify() def addObject(self, astronomical_object, name): self.lock.acquire() if name in self.objects: del self.objects[name] self.objects[name] = astronomical_object self.solver.setObjects(self.objects) self.lock.release() def getTimeStep(self): return self.solver.dt def setTimeStep(self, dt): self.solver.dt = float(dt) #def getObject(self, name): # return self.objects[name] def clearObjects(self): self.lock.acquire() self.objects.clear() self.lock.release() def deleteObject(self, name): self.lock.acquire() return_value = False if name in self.objects.keys(): del self.objects[name] return_value = True self.lock.release() return return_value def showTrails(self, make_trail): self.make_trail = make_trail for key in self.objects: self.objects[key].setTrail(make_trail) def showVectors(self, show_vectors): self.show_vectors = show_vectors for key in self.objects: self.objects[key].setVectors(show_vectors) def setVelocityVectorScale(self, scale): self.velocity_scale = scale*scale*scale for key in self.objects: self.objects[key].setVelocityVectorScale(self.velocity_scale) def setAccelerationGain(self, gain): self.acceleration_gain = gain*100 if gain==1: self.acceleration_gain = 1 temp = self.acceleration_scale*self.acceleration_gain for key in self.objects: self.objects[key].setAccelerationVectorScale(temp) def setAccelerationVectorScale(self, scale): self.acceleration_scale = scale*scale*scale temp = self.acceleration_scale*self.acceleration_gain for key in self.objects: self.objects[key].setAccelerationVectorScale(temp) def loadSimulation(self, reload_simulation=False): self.lock.acquire() self.loader.velocity_factor = self.velocity_scale self.loader.acceleration_factor = self.acceleration_scale*self.acceleration_gain temp, self.errors = self.loader.loadObjects(reload_simulation) if temp: for key in self.objects: self.objects[key].setVisible(False) self.objects.clear() self.objects = temp self.solver.setObjects(self.objects) if self.show_vectors is True: self.showVectors(True) if self.make_trail is True: self.showTrails(True) self.time_elapsed = 0 self.lock.release() def reloadSimulation(self): self.loadSimulation(True)