aboutsummaryrefslogtreecommitdiff
path: root/operationscore/Behavior.py
blob: 7090a235e54075e3071205b9677679ab32ecd370 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import pdb
from operationscore.SmootCoreObject import *
from logger import main_log
class Behavior(SmootCoreObject):
    """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, (outputs, recursions).  They must give a location and
    color.  They may define a PixelEvent to more closely control the outgoing
    data, however, this is normally handled by routing the event to a behavior
    specifically designed to do this (like AddPixelEvent). 
    timeStep is called on every iteration of the LightInstallation
    addInput is called on each individual input received, and the inputs queue"""
    def init(self):
        self.validateArgs('Behavior.params')
        if type(self['Inputs']) != type([]):
            self['Inputs'] = [self['Inputs']]
        self.recursiveResponseQueue = []
        self.sensorResponseQueue = []
        self.outGoingQueue = []
        self.lastState = None
        self.behaviorInit()
    def behaviorInit(self):
        pass
    def addMapper(fn):
        def withmap(fn):
            return self.addMapperToResponse(fn())
        return withmap
    def processResponse(self, sensorInputs, recursiveInputs):
        raise Exception('ProcessResponse not defined!')
    def addInput(self, sensorInput):
        self.sensorResponseQueue.append(sensorInput)
    #used for behavior chaining
    def immediateProcessInput(self, sensorInputs, recursiveInputs=[]): 
            (outputs,recursions) = self.processResponse(sensorInputs, \
                    recursiveInputs)
            return self.addMapperToResponse((outputs,recursions))
    def addInputs(self, sensorInputs):
        if type(sensorInputs) == type([]):
            [self.addInput(sensorInput) for sensorInput in sensorInputs]
        else:
            self.addInput(sensorInputs)
    #private
    def getLastOutput(self):
        return self.lastState
    def setLastOutput(self, output):
        """Override to modify state.  For example: if you are using a behavior that does uses
        strings for location specification, you will want to override this to point to a single
        location.  Make sure you keep lastState as a [] of {}.  (List of dicts)"""
        self.lastState = output
    def addMapperToResponse(self, responses):
        if self['Mapper'] != None:
            if type(responses) == type(tuple):
                (out, recurs) = responses
                return (self.addMapperToResponse(out), self.addMapperToResponse(recurs))
            if type(responses) == type([]):
                    for r in responses:
                        r['Mapper'] = self['Mapper']
                    return responses
        return responses
    def timeStep(self): #TODO: type checking.  clean this up
        (outputs, recursions) = self.processResponse(self.sensorResponseQueue, \
                self.recursiveResponseQueue)
        self.sensorResponseQueue = []
        self.recursiveResponseQueue = recursions 
        self.setLastOutput(outputs)
        main_log.debug(self['Id'] + ' Ouputs ' + str(outputs))
        return self.addMapperToResponse(outputs)