Package teamwork :: Package action :: Module PsychActions
[hide private]
[frames] | no frames]

Source Code for Module teamwork.action.PsychActions

  1  import copy 
  2  import string 
  3  from types import * 
  4  from xml.dom.minidom import * 
  5   
  6   
7 -class Action(dict):
8 nop = 'wait' 9 fields = {'type':{},'actor':{},'object':{},'command':{}, 10 '_observed':{},'_unobserved':{}, 11 'self':bool , 12 'repeatable':bool , 13 } 14 format = ['actor','type','object','command'] 15
16 - def __init__(self,arg={}):
17 """Translates an action in string form into a structured 18 representation of that same action (e.g., 19 'CLF-violence-to-UrbanPoor' becomes a PsychAction object 20 {'actor':CLF,'type':'violence','object':UrbanPoor}""" 21 if type(arg) is StringType: 22 raise DeprecationWarning,'PsychAction: Use dictionaries instead of strings (%s) in action creation' % (arg) 23 if len(arg) == 0: 24 dict.__init__(self,{'type': self.nop}) 25 else: 26 dict.__init__(self,arg) 27 if self['actor'] and not isinstance(self['actor'],str): 28 raise TypeError 29 if self['object'] and not isinstance(self['object'],str): 30 raise TypeError 31 self.name = ''
32 33
34 - def instantiate(self,entities=[]):
35 if isinstance(entities,dict): 36 for key in self.fields.keys(): 37 if entities.has_key(key): 38 self[key] = entities[key] 39 elif type(entities) is ListType: 40 for key in self.fields.keys(): 41 for entity in entities: 42 try: 43 if entity.name == self[key]: 44 self[key] = entity 45 break 46 except AttributeError: 47 pass 48 else: 49 raise TypeError,`type(entities)`+' not supported by '+\ 50 'PsychAgents instantiate method' 51 if self['command']: 52 self['command'].instantiate(entities)
53
54 - def makeRange(self,actType={}):
55 """Returns a list of all possible instantiations of this 56 partially specified action.""" 57 actList = [self] 58 for key,value in self.fields.items(): 59 if not self[key]: 60 try: 61 valRange = actType[key] 62 except KeyError: 63 try: 64 valRange = value['range'] 65 except KeyError: 66 continue 67 if len(valRange) > 0: 68 for oldAct in actList[:]: 69 actList.remove(oldAct) 70 for item in valRange: 71 newAct = copy.copy(oldAct) 72 newAct[key] = item 73 actList.append(newAct) 74 return actList
75
76 - def addField(self,key,value):
77 """Returns a *copy* of this action with the given key,value pair""" 78 new = self.__copy__() 79 new[key] = value 80 return new
81
82 - def __getitem__(self,index):
83 if self.fields.has_key(index): 84 try: 85 return dict.__getitem__(self,index) 86 except KeyError: 87 return None 88 else: 89 raise KeyError,'%s: Unknown field "%s"' \ 90 % (self.__class__.__name__,index)
91
92 - def __setitem__(self,index,value):
93 if self.fields.has_key(index): 94 dict.__setitem__(self,index,value) 95 else: 96 raise KeyError,'%s: Unknown field "%s"' \ 97 % (self.__class__.__name__,index) 98 self.name = ''
99
100 - def __delitem__(self,index):
101 if self.fields.has_key(index): 102 self[index] = None 103 else: 104 raise KeyError,'%s: Unknown field "%s"' \ 105 % (self.__class__.__name__,index) 106 self.name = ''
107
108 - def keys(self):
109 list = [] 110 for key in self.fields.keys(): 111 if self[key]: 112 list.append(key) 113 return list
114
115 - def __deepcopy__(self,memo):
116 result = {} 117 for key,value in self.items(): 118 if isinstance(value,Action): 119 result[key] = copy.copy(value) 120 elif isinstance(value,str): 121 result[key] = value 122 elif type(value) is InstanceType: 123 result[key] = value.name 124 else: 125 result[key] = value 126 result = self.__class__(result) 127 memo[id(self)] = result 128 return result
129
130 - def __str__(self):
131 """Translates a structured dictionary representation of an action 132 into a standardized string format (e.g., 133 {'actor':CLF,'type':'violence','object':UrbanPoor} becomes 134 'CLF-violence-to-UrbanPoor'""" 135 if len(self.name) == 0: 136 for key in self.format: 137 value = self[key] 138 if type(value) is NoneType: 139 continue 140 if len(self.name) > 0: 141 self.name += '-' 142 if isinstance(value,str): 143 self.name += value 144 elif isinstance(value,Action): 145 self.name += `value` 146 elif type(value) is InstanceType: 147 self.name += value.name 148 elif type(value) is FloatType: 149 self.name += '%6.4f' % (value) 150 return self.name
151
152 - def simpleText(self):
153 content = self['type'] 154 if isinstance(self['object'],str): 155 content += ' %s' % (self['object']) 156 elif type(self['object']) is InstanceType: 157 content += ' %s' % (self['object'].name) 158 return content
159
160 - def matchTemplate(self,template):
161 """ 162 @return: true iff the action matches the given template 163 @rtype: bool 164 """ 165 for key in self.fields: 166 if template.has_key(key) and template[key]: 167 if isinstance(self[key],str): 168 if template[key] != self[key]: 169 # Mismatch 170 break 171 elif isinstance(self[key],Agent): 172 if template[key] != self[key].name: 173 # Mismatch 174 break 175 else: 176 print 'Unable to match template fields of type:',self[key].__class__.__name__ 177 else: 178 # Successful match 179 return True 180 return False
181
182 - def __xml__(self):
183 doc = Document() 184 root = doc.createElement('action') 185 root.setAttribute('class',self.__class__.__name__) 186 doc.appendChild(root) 187 for key,value in self.items(): 188 if value is not None: 189 if isinstance(value,str): 190 data = doc.createTextNode(value) 191 elif type(value) is InstanceType: #isinstance(value,Agent): 192 data = doc.createTextNode(value.name) 193 elif isinstance(value,Action): 194 data = value.__xml__().documentElement 195 elif isinstance(value,bool): 196 data = doc.createTextNode(str(value)) 197 else: 198 # Not XMLizable 199 data = None 200 ## data = doc.createTextNode(`value`) 201 if not data is None: 202 node = doc.createElement(key) 203 root.appendChild(node) 204 node.appendChild(data) 205 return doc
206
207 - def parse(self,doc):
208 if doc.nodeType == Node.DOCUMENT_NODE: 209 root = doc.documentElement 210 else: 211 root = doc 212 clsName = str(root.getAttribute('class')) 213 if clsName and clsName != self.__class__.__name__: 214 for cls in self.__class__.__subclasses__(): 215 if clsName == cls.__name__: 216 obj = cls() 217 return obj.parse(doc) 218 else: 219 raise NameError,'Unknown Action subclass: %s' % (clsName) 220 child = root.firstChild 221 while child: 222 if child.nodeType == Node.ELEMENT_NODE: 223 key = str(child.tagName) 224 grandchild = child.firstChild 225 if grandchild and grandchild.nodeType == Node.TEXT_NODE: 226 value = string.strip(str(child.firstChild.data)) 227 if self.fields.has_key(key): 228 if self.fields[key] is bool: 229 if value == 'True': 230 value = True 231 else: 232 value = False 233 self[key] = value 234 child = child.nextSibling 235 return self
236
237 - def __hash__(self):
238 return str(self).__hash__()
239
240 -class ActionCondition:
241 """ 242 Class for specifying a template for matching joint actions 243 @ivar verbs: dictionary of verbs that this condition matches 244 @type verbs: strS{->}C{True} 245 @ivar only: C{True} iff only actions in the verb set are allowed (default is C{False}) 246 @type only: bool 247 @ivar count: C{True} iff we are interested in how many actions match, not just a boolean value (default is C{False}) 248 @type count: bool 249 """
250 - def __init__(self,only=False,count=False):
251 self.verbs = {} 252 self.only = only 253 self.count = count
254
255 - def addCondition(self,verb):
256 self.verbs[verb] = True
257
258 - def delCondition(self,verb):
259 del self.verbs[verb]
260
261 - def __len__(self):
262 return len(self.verbs)
263
264 - def match(self,actions):
265 """ 266 @return: If C{self.count} is C{False}, then return C{True} iff the given joint action meets this condition; otherwise, return number of matching actions, or 0 if match fails 267 @rtype: bool or int 268 """ 269 if isinstance(actions,dict): 270 # Dictionary of agent->action lists 271 actions = sum(actions.values(),[]) 272 match = {} # Verbs found so far 273 if self.only: 274 # Check whether there are any extra actions 275 for action in actions: 276 if self.verbs.has_key(action['type']): 277 match[action['type']] = True 278 elif self.count: 279 return 0 280 else: 281 return False 282 # All actions match, comes down to numbers 283 if self.count: 284 return len(actions) 285 else: 286 return len(match) == len(self.verbs) 287 elif self.count: 288 # Count how many desired verbs are present 289 count = 0 290 for action in actions: 291 if self.verbs.has_key(action['type']): 292 match[action['type']] = True 293 count += 1 294 if len(match) == len(self.verbs): 295 return count 296 else: 297 return 0 298 else: 299 # Check whether all desired verbs are present 300 index = 0 301 while len(match) < len(self.verbs): 302 if index < len(actions): 303 if self.verbs.has_key(actions[index]['type']): 304 match[actions[index]['type']] = True 305 index += 1 306 else: 307 # Get out of here as quickly as possible 308 break 309 # Check whether we have matched 310 return len(match) == len(self.verbs)
311
312 - def __str__(self):
313 if self.only: 314 return 'Only '+','.join(self.verbs.keys()) 315 elif len(self.verbs) == 0: 316 return 'Any' 317 else: 318 return ','.join(self.verbs.keys())
319
320 - def __xml__(self):
321 doc = Document() 322 root = doc.createElement('condition') 323 doc.appendChild(root) 324 root.setAttribute('only',str(self.only)) 325 root.setAttribute('count',str(self.count)) 326 for verb in self.verbs.keys(): 327 if self.verbs[verb]: 328 node = doc.createElement('verb') 329 node.appendChild(doc.createTextNode(verb)) 330 root.appendChild(node) 331 return doc
332
333 - def parse(self,element):
334 self.verbs.clear() 335 self.only = str(element.getAttribute('only')).lower() == 'true' 336 self.count = str(element.getAttribute('count')).lower() == 'true' 337 node = element.firstChild 338 while node: 339 if node.nodeType == node.ELEMENT_NODE: 340 assert str(node.tagName) == 'verb' 341 child = node.firstChild 342 while child: 343 if child.nodeType == child.TEXT_NODE: 344 self.verbs[str(child.data).strip()] = True 345 child = child.nextSibling 346 node = node.nextSibling
347 348 349 if __name__ == '__main__': 350 import os.path 351 352 353 act = Action({'actor':'CortinaGov','type':'wait'}) 354 name = '/tmp/%s.xml' % (os.path.basename(__file__)) 355 file = open(name,'w') 356 file.write(act.__xml__().toxml()) 357 file.close() 358 359 new = Action() 360 new.parse(parse(name)) 361 print new 362