From b042647b68abdc82490ca6e059993b8eba28904c Mon Sep 17 00:00:00 2001 From: Russell Cohen Date: Wed, 24 Nov 2010 01:09:12 -0500 Subject: Refactoring complete! Made modules/packages as appropriate. Finally. --- operationscore/Behavior.py | 33 ++++++++++++++++++++++++++++ operationscore/Input.py | 46 +++++++++++++++++++++++++++++++++++++++ operationscore/LayoutEngine.py | 30 +++++++++++++++++++++++++ operationscore/PixelEvent.py | 13 +++++++++++ operationscore/Renderer.py | 12 ++++++++++ operationscore/SmootCoreObject.py | 23 ++++++++++++++++++++ operationscore/__init__.py | 0 7 files changed, 157 insertions(+) create mode 100644 operationscore/Behavior.py create mode 100644 operationscore/Input.py create mode 100644 operationscore/LayoutEngine.py create mode 100644 operationscore/PixelEvent.py create mode 100644 operationscore/Renderer.py create mode 100644 operationscore/SmootCoreObject.py create mode 100644 operationscore/__init__.py (limited to 'operationscore') diff --git a/operationscore/Behavior.py b/operationscore/Behavior.py new file mode 100644 index 0000000..f29430f --- /dev/null +++ b/operationscore/Behavior.py @@ -0,0 +1,33 @@ +#Abstract class for a behavior. On every time step, the behavior is passed the +#inputs from all sensors it is bound to as well as any recursive inputs that it +#spawned during the last time step. Inheriting classes MUST define +#processResponse. processResponse should return a list of dictionaries which +#define the properties of the light response. They must give a location and +#color. They may define a function pointer which defines a custom mapping. +#[More on this later. Bug Russell if you want to do it]. +#recursiveResponse to queue a input on the next iteration with a dictionary +#argument. This will be passed in via recursive inputs. +import pdb +from operationscore.SmootCoreObject import * +#timeStep is called on every iteration of the LightInstallation +#addInput is called on each individual input received, and the inputs queue +class Behavior(SmootCoreObject): + def init(self): + self.validateArgs('Behavior.params') + if type(self['Inputs']) != type([]): + self['Inputs'] = [self['Inputs']] + self.recursiveResponseQueue = [] + self.sensorResponseQueue = [] + self.outGoingQueue = [] + def processResponse(self, sensorInputs, recursiveInputs): + pass + def addInput(self, sensorInputs): + self.sensorResponseQueue.append(sensorInputs) + def recursiveReponse(self, args): + self.responseQueue.append(args) + def timeStep(self): + responses = self.processResponse(self.sensorResponseQueue, \ + self.recursiveResponseQueue) + self.sensorResponseQueue = [] + self.recursiveResponseQueue = [] + return responses diff --git a/operationscore/Input.py b/operationscore/Input.py new file mode 100644 index 0000000..1ba4528 --- /dev/null +++ b/operationscore/Input.py @@ -0,0 +1,46 @@ +import threading,time,Util +#Abstract class for inputs. Inheriting classes should call "respond" to raise +#their event. Inheriting classes MUST define sensingLoop. Called at the +#interval specified in RefreshInterval while the input is active. For example, if you are writing +#webserver, this is where the loop should go. +#Inheriting classes MAY define inputInit. This is called before the loop +#begins. +import pdb +class Input(threading.Thread): + #Event scope is a function pointer the function that will get called when + #an Parent is raised. + def __init__(self, argDict): + self.eventQueue = [] + self.parentScope = argDict['parentScope'] + self.argDict = argDict + if not 'InputId' in argDict: + raise Exception('InputId must be defined in config xml') + if not 'RefreshInterval' in argDict: + print 'RefreshInterval not defined. Defaulting to .5s.' + self.argDict['RefreshInterval'] = 500 + self.inputInit() + threading.Thread.__init__(self) + self.daemon = True #This kills this thread when the main thread stops + def respond(self, eventDict): + #if eventDict != []: + #pdb.set_trace() + self.parentScope.processResponse(self.argDict, eventDict) + def newEvent(self, event): #Mostly just useful for grabbing events from the + #computer running the sim (key presses, clicks etc.) + self.eventQueue.append(event) + def parentAlive(self): + try: + parentAlive = self.parentScope.alive() + return parentAlive + except: + return False + def run(self): + while self.parentAlive(): + time.sleep(self.argDict['RefreshInterval']/float(1000)) + self.sensingLoop() + def sensingLoop(self): + pass + def inputInit(self): + pass + + diff --git a/operationscore/LayoutEngine.py b/operationscore/LayoutEngine.py new file mode 100644 index 0000000..700b554 --- /dev/null +++ b/operationscore/LayoutEngine.py @@ -0,0 +1,30 @@ +from operationscore.SmootCoreObject import * +import Util +import pdb +class LayoutEngine(SmootCoreObject): + def init(self): + self.validateArgs('LayoutEngine.params') + self.initLayout() + def layoutFunc(self, lastLocation): #Must be defined by inheriting class. + #Returns tuple pair (x,y) + pass + def getPixelLocations(self): #returns a complete list of locations of Pixels + #for a strip + locations = [self.argDict['originLocation']] + for pixelIndex in range(self['numPixels']-1): #-1 because origin + #already exists + newLocation = self.layoutFunc(locations[-1]) + if newLocation == None: + raise Exception('Location cannot be null. layoutFunc not \ + defined or improperly defined.') + if Util.dist(newLocation, locations[-1]) > \ + self['pixelToPixelSpacing']: + raise Exception('Illegal pixel location. Distance \ + between adjacent pixels must be less than \ + pixelToPixelSpacing.') + locations.append(newLocation) + return locations + def initLayout(self): + pass + def getStripArgs(self): #TODO: triage and remove + return self.argDict diff --git a/operationscore/PixelEvent.py b/operationscore/PixelEvent.py new file mode 100644 index 0000000..07669cd --- /dev/null +++ b/operationscore/PixelEvent.py @@ -0,0 +1,13 @@ +#Class defining a light response. Inheriting classes should define lightState, +#which should return a color, or None if the response is complete. Consider +#requiring a generate event. +from operationscore.SmootCoreObject import * +class PixelEvent(SmootCoreObject): + def init(self): + self.validateArgs('PixelEvent.params') + self.initEvent() + def initEvent(self): + pass + def state(self,timeDelay): + pass + diff --git a/operationscore/Renderer.py b/operationscore/Renderer.py new file mode 100644 index 0000000..11fd8ca --- /dev/null +++ b/operationscore/Renderer.py @@ -0,0 +1,12 @@ +#Renderer abstract class. Doesn't do much now, but might do more later. +#Inheriting classes MUST define render which takes a light system and renders it. +#Inheriting classes may define initRenderer which is called after the dictionary +#is pulled from config. +from operationscore.SmootCoreObject import * +class Renderer(SmootCoreObject): + def init(self): + self.initRenderer() + def render(lightSystem): + pass + def initRenderer(self): + pass diff --git a/operationscore/SmootCoreObject.py b/operationscore/SmootCoreObject.py new file mode 100644 index 0000000..2901ef6 --- /dev/null +++ b/operationscore/SmootCoreObject.py @@ -0,0 +1,23 @@ +import Util +import pdb +class SmootCoreObject: + def __init__(self, argDict): + self.argDict = argDict + self.init() #call init of inheriting class + def init(self): + pass + def __setitem__(self,k, item): + self.argDict[k] = item + def __getitem__(self, item): + if item in self.argDict: + return self.argDict[item] + else: + return None + def __getiter__(self): + return self.argDict.__getiter__() + def validateArgs(self, argFileName): + self.validateArgDict(Util.loadParamRequirementDict(argFileName)) + def validateArgDict(self, validationDict): + for item in validationDict: + if not item in self.argDict: + raise Exception(validationDict[item]) diff --git a/operationscore/__init__.py b/operationscore/__init__.py new file mode 100644 index 0000000..e69de29 -- cgit v1.2.3