1 import copy
2 import string
3 from types import *
4 from xml.dom.minidom import *
5
6
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
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
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
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
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
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
99
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
109 list = []
110 for key in self.fields.keys():
111 if self[key]:
112 list.append(key)
113 return list
114
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
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
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
170 break
171 elif isinstance(self[key],Agent):
172 if template[key] != self[key].name:
173
174 break
175 else:
176 print 'Unable to match template fields of type:',self[key].__class__.__name__
177 else:
178
179 return True
180 return False
181
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:
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
199 data = None
200
201 if not data is None:
202 node = doc.createElement(key)
203 root.appendChild(node)
204 node.appendChild(data)
205 return doc
206
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
239
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
256 self.verbs[verb] = True
257
260
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
271 actions = sum(actions.values(),[])
272 match = {}
273 if self.only:
274
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
283 if self.count:
284 return len(actions)
285 else:
286 return len(match) == len(self.verbs)
287 elif self.count:
288
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
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
308 break
309
310 return len(match) == len(self.verbs)
311
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
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