Package teamwork :: Package shell :: Module PsychShell
[hide private]
[frames] | no frames]

Source Code for Module teamwork.shell.PsychShell

  1  """ 
  2  The base engine with handlers for typical interactions with PsychSim agents 
  3  @version: 1.7 
  4  """ 
  5  try: 
  6      import inspect 
  7      __DOC__ = True 
  8  except ImportError: 
  9      __DOC__ = False 
 10  __PROFILE__ = False 
 11   
 12  import bz2 
 13  import os.path 
 14  from Queue import Queue 
 15  import re 
 16  import string 
 17  import sys 
 18  from xml.dom.minidom import parse 
 19   
 20  from teamwork.agent.Entities import * 
 21  from teamwork.agent.lightweight import PWLAgent 
 22  from teamwork.agent.AgentClasses import * 
 23  from teamwork.utils.PsychUtils import * 
 24  from teamwork.utils.Debugger import * 
 25  from teamwork.messages.PsychMessage import * 
 26  from teamwork.multiagent.sequential import SequentialAgents 
 27  from teamwork.action.PsychActions import * 
 28  from teamwork.multiagent.GenericSociety import * 
 29  from teamwork.multiagent.pwlSimulation import PWLSimulation 
 30   
 31  if __PROFILE__: 
 32      import hotshot,hotshot.stats 
 33   
34 -class PsychShell:
35 """The base API for the PsychSim engine 36 @cvar __VERSION__: the version of this shell 37 @cvar __UNDO__: flag indicating whether UNDO operations are supported 38 @type __UNDO__: boolean 39 @cvar __KQML__: flag indicating whether KQML communication is supported 40 @type __KQML__: boolean 41 @ivar multiagentClass: the class of the current scenario (default is L{SequentialAgents}) 42 @ivar agentClass: the class of individual agents in the scenario (default is L{PsychEntity}) 43 """ 44 __VERSION__ = '1.8beta' 45 __UNDO__ = False 46 __KQML__ = False 47 48 actionFormat = [('actor',True),('type',True),('object',False)] 49
50 - def __init__(self, 51 scenario=None, # Initial scenario 52 classes=None, # Class hierarchy 53 agentClass=None, # Class used for generating agents 54 multiagentClass=None, # Class for generating scenario 55 debug=0):
56 """ 57 @param scenario: a L{teamwork.multiagent.PsychAgents.PsychAgents} object (if none provided, shell starts up an initialization phase) 58 @type classes: L{GenericSociety} 59 """ 60 # Find root directory 61 path = os.path.dirname(__file__) 62 self.directory = os.path.realpath(os.path.join(path,'..')) 63 # Set up (multi)agent classes 64 if agentClass: 65 self.agentClass = agentClass 66 else: 67 self.agentClass = PsychEntity 68 if multiagentClass: 69 self.multiagentClass = multiagentClass 70 else: 71 self.multiagentClass = SequentialAgents 72 self.debug = TimedDebugger(debug) 73 # Set up class hierarchy 74 self.resetSociety() 75 self.societyFile = None 76 if isinstance(classes,str): 77 self.loadSociety(classes) 78 elif classes: 79 self.classes = classes 80 self.scenarioFile = None 81 self.scenario = None 82 if type(scenario) is StringType: 83 # String indicates a file name to load entities from 84 try: 85 PsychShell.load(self,scenario) 86 self.phase = 'run' 87 except IOError: 88 print 'No such file or directory:',scenario 89 self.scenario = None 90 elif scenario is None: 91 # If no entities provided, go into initialization phase 92 self.scenario = None 93 self.entities = self.classes 94 self.phase = 'setup' 95 elif isinstance(scenario,list): 96 # Convert into PsychAgents object 97 scenario = self.setupEntities(scenario) 98 self.setupScenario(scenario) 99 else: 100 # Assume that is instance of PsychAgents 101 self.scenario = scenario 102 self.entities = self.scenario 103 self.phase = 'run' 104 self.initEntities() 105 self.done = None 106 if self.__KQML__: 107 # Start up KQML listener 108 import teamwork.communication.SocketListener 109 self.router = teamwork.communication.SocketListener.KQMLListener() 110 self.router.registerHandler(self.handleMsg) 111 # Reset known susceptibilities to be empty 112 self.susceptibility = None 113 self.handlers = {} 114 self.tests = {} 115 # Add mappings here from command to function 116 # (see the 'save' method for an example handler) 117 self.handlers['entity'] = self.getEntity 118 self.handlers['belief'] = self.getBelief 119 self.handlers['act'] = self.performAct 120 self.handlers['step'] = self.step 121 self.handlers['save'] = self.save 122 self.handlers['load'] = self.load 123 self.handlers['export'] = self.export 124 self.handlers['distill'] = self.distill 125 self.handlers['message'] = self.send 126 self.handlers['goals'] = self.goals 127 self.handlers['policy'] = self.applyPolicy 128 self.handlers['entities'] = self.getEntities 129 self.handlers['test'] = self.test 130 self.handlers['help'] = self.help 131 self.handlers['debug'] = self.setDebugLevel 132 self.handlers['model'] = self.setModel 133 self.handlers['loadgeneric'] = self.loadSociety 134 self.handlers['savegeneric'] = self.saveSociety 135 if self.__UNDO__: 136 # Slot for saving last known entities 137 self.lastStep = None 138 self.handlers['undo'] = self.undo
139
140 - def setupScenario(self,agents,progress=None):
141 """initialize L{PsychShell} with given L{scenario<teamwork.multiagent.PsychAgents.PsychAgents>} 142 @param agents: the scenario to interact with 143 @type agents: L{MultiagentSimulation<teamwork.multiagent.Simulation.MultiagentSimulation>} 144 @param progress: optional progress display command 145 @type progress: C{lambda} 146 """ 147 self.scenario = agents 148 self.entities = self.scenario 149 self.phase = 'run' 150 self.initEntities(progress) 151 if self.__UNDO__: 152 self.lastStep=copy.deepcopy (self.entities) 153 return self.scenario
154
155 - def setupEntities(self,entities=None,progress=None,compileDynamics=True, 156 compilePolicies=None,distill=False):
157 """Creates a scenario instance from a list of entities and applies the default values across the board 158 @param entities: the entities to use in populating the scenario 159 @type entities: L{Agent}[] 160 @param progress: optional C{Queue} argument is used to give progress updates, in the form of C{(label,pct)}, where: 161 - I{label}: a string label to display for the current task 162 - I{pct}: an integer percentage (1-100) representing the amount of progress made since the last call 163 The thread puts C{None} into the queue when it has finished. 164 @type progress: Queue 165 @return: a newly created scenario instance 166 @rtype: L{multiagentClass} 167 @param compileDynamics: Flag indicating whether the scenario dynamics should be compiled as well (default is True) 168 @type compileDynamics: boolean 169 @param compilePolicies: The belief depth at which all agents will have their policies compiled, where 0 is the belief depth of the real agent. If the value of this flag is I{n}, then all agents at belief depthS{>=}I{n} will have their policies compiled, while no agents at belief depth<I{n} will. If omitted, no policies will be compiled 170 @type compilePolicies: int 171 @param distill: If C{True}, then create a distilled version of these agents (default is C{False} 172 @type distill: bool 173 """ 174 agents = self.multiagentClass() 175 agents.society = self.classes 176 for entity in entities: 177 agents.addMember(entity) 178 # Compute whether there are any compilations to be "progressed" through 179 if progress is not None: 180 if not isinstance(progress,Queue): 181 raise DeprecationWarning,'"progress" argument should be Queue for proper synchronization.' 182 total = agents.actorCount(compilePolicies) 183 if compileDynamics: 184 # Crude estimate of how many recursive belief there are 185 for entity in agents.members(): 186 depth = entity.getDefault('depth') 187 total += pow(len(agents.members()),depth) 188 # Count how many dynamics functions there are 189 total += agents.actionCount(False) 190 total = float(total) 191 # Nothing else to progress over, so might as well do it here 192 agents.applyDefaults(progress=progress,total=total, 193 doBeliefs=not distill) 194 if compileDynamics: 195 if __PROFILE__: 196 filename = '/tmp/stats' 197 prof = hotshot.Profile(filename) 198 prof.start() 199 agents.compileDynamics(progress,total) 200 if __PROFILE__: 201 prof.stop() 202 prof.close() 203 print 'loading stats...' 204 stats = hotshot.stats.load(filename) 205 stats.strip_dirs() 206 stats.sort_stats('time', 'calls') 207 stats.print_stats() 208 agents.compilePolicy(compilePolicies,progress,total) 209 if distill: 210 # Create lightweight agents right away 211 scenario = PWLSimulation(agents) 212 # Determine LHS of policies 213 attributes = {} 214 vectors = {} 215 keyList = filter(lambda k:isinstance(k,StateKey), 216 agents.getStateKeys().keys()) 217 maxAttrs = 8 218 for key in keyList: 219 for agent in scenario.members(): 220 for option in agent.actions.getOptions(): 221 for action in option: 222 if len(attributes) >= maxAttrs: 223 continue 224 entity = agents[key['entity']] 225 dynamics = entity.getDynamics(action, 226 key['feature']) 227 tree = dynamics.getTree() 228 del entity.dynamics[key['feature']][action] 229 for plane in tree.branches().values(): 230 if isinstance(plane.weights,ThresholdRow): 231 # Needs to be a bit more permissive, but... 232 label = plane.weights.simpleText() 233 try: 234 attributes[label][plane.threshold] = True 235 except KeyError: 236 attributes[label] = {plane.threshold: True} 237 vectors[label] = plane.weights 238 # Initialize everyone's policies with default order 239 keyList = agents.getStateKeys().keys() 240 keyList.sort() 241 del agents 242 for key,vector in vectors.items(): 243 vector.fill(keyList) 244 # Compile for just one agent 245 for agent in scenario.members(): 246 options = agent.actions.getOptions() 247 if len(options) > 0: 248 agent.policy.reset() 249 # Cap the # of attributes 250 for key,values in attributes.items(): 251 values = values.keys() 252 values.sort() 253 agent.policy.attributes.append((vectors[key],values)) 254 agent.policy.initialize(choices=options) 255 for index in xrange(len(agent.policy.rules)): 256 agent.policy.rules[index] = options[:] 257 scenario.save('/tmp/pynadath/test%02d_%d.xml' % \ 258 (len(scenario),len(agent.policy.rules))) 259 print agent.name 260 print 'done.' 261 sys.exit(0) 262 agents = scenario 263 # Report to the main thread that we're all done 264 if progress: 265 progress.put(None) 266 return agents
267
268 - def initEntities(self,progress=None):
269 """A method, to be overridden by subclass, that is invoked whenever there is a new set of entities""" 270 pass
271
272 - def getCommand(self):
273 """Abstract method for getting a command from user. 274 @rtype: C{str} 275 """ 276 raise NotImplementedError
277
278 - def executeCommand(self,cmd):
279 start = time.time() 280 result = self.execute(cmd) 281 diff = time.time()-start 282 if result: 283 self.displayResult(cmd,`self.debug`) 284 self.debug.reset() 285 self.displayResult(cmd,result) 286 self.displayResult(cmd,'Time: %7.4f' % (diff)) 287 else: 288 self.done = 1 289 return result
290
291 - def displayResult(self,cmd,result):
292 """Abstract method for displaying a result to the user 293 @param cmd: the command executed 294 @type cmd: C{str} 295 @param result: the results of the command 296 @type result: C{str[]} 297 """ 298 raise NotImplementedError
299
300 - def save(self,filename=None,results=None):
301 """Saves the state of the current simulation to the named file""" 302 if not filename: 303 return 'Usage: save <filename>' 304 self.scenario.save(filename) 305 self.scenarioFile = filename 306 return 1
307
308 - def saveSociety(self,filename=None,results=None):
309 """Saves the current generic society to the named file""" 310 if not filename: 311 return 'Usage: savegeneric <filename>' 312 self.classes.save(filename) 313 self.societyFile = filename 314 return 1
315
316 - def load(self,filename=None,results=None):
317 """Loads in a L{scenario<teamwork.multiagent.PsychAgents.PsychAgents>} object from the specified file""" 318 if not filename: 319 return 'Usage: load <filename>' 320 if filename[-4:] == '.xml': 321 f = open(filename,'r') 322 else: 323 import bz2 324 f = bz2.BZ2File(filename,'r') 325 data = f.read() 326 f.close() 327 doc = parseString(data) 328 scenarioClass = str(doc.documentElement.getAttribute('type')) 329 if scenarioClass == 'PWLSimulation': 330 self.scenario = PWLSimulation() 331 agentClass = PWLAgent 332 elif scenarioClass == 'GenericSociety': 333 # Whoops, we have a generic society instead 334 return self.loadSociety(filename,True,results) 335 else: 336 # We should also handle other specific types here 337 self.scenario = self.multiagentClass() 338 agentClass = self.agentClass 339 self.scenario.parse(doc.documentElement,agentClass,GenericSociety) 340 self.entities = self.scenario 341 self.scenario.initialize() 342 eList = self.entities.members() 343 while len(eList) > 0: 344 entity = eList.pop() 345 entity.setHierarchy(self.classes) 346 eList += entity.getEntityBeliefs() 347 self.scenarioFile = filename 348 self.initEntities() 349 return 1
350
351 - def loadSociety(self,filename=None,overwrite=True,results=None):
352 """Loads in a GenericSociety object from the specified file 353 @param overwrite: flag indicating, when C{True} that the existing society should be erased before loading in the new one 354 @type overwrite: boolean 355 """ 356 if not filename: 357 return 'usage: loadgeneric <filename>' 358 if filename[-4:] == '.xml': 359 f = open(filename,'r') 360 else: 361 import bz2 362 f = bz2.BZ2File(filename,'r') 363 data = f.read() 364 f.close() 365 doc = parseString(data) 366 newClasses = GenericSociety() 367 newClasses.parse(doc.documentElement) 368 if overwrite: 369 self.classes = newClasses 370 self.societyFile = filename 371 warnings = [] 372 else: 373 warnings = self.classes.merge(newClasses) 374 if not self.societyFile: 375 self.societyFile = filename 376 return warnings
377
378 - def export(self,filename=None,results=None):
379 """Writes a Web page representation of the current scenario""" 380 if filename: 381 f = open(filename,'w') 382 f.write(self.scenario.toHTML()) 383 f.close() 384 return 1 385 else: 386 return 'usage: export <filename>'
387
388 - def distill(self,filename=None,results=None):
389 """Writes a lightweight representation of the current scenario""" 390 if filename: 391 lightweight = PWLSimulation(self.scenario) 392 lightweight.save(filename) 393 return 1 394 else: 395 return 'usage: distill <filename>'
396
397 - def revert(self):
398 """Reverts the current scenario to the last loaded/saved scenario""" 399 if self.scenarioFile: 400 self.load(self.scenarioFile)
401
402 - def step(self,length=1,results=None):
403 """Steps the simulation the specified number of micro-steps 404 into the future (default is 1)""" 405 try: 406 length = int(length) 407 except TypeError: 408 results = length 409 length = 1 410 sequence = [] 411 for t in range(int(length)): 412 delta = self.entities.microstep(debug=self.debug) 413 sequence.append(delta) 414 if isinstance(results,list): 415 results.append(dict2str(delta,self.debug.level)) 416 return sequence
417
418 - def goals(self,results=None):
419 for name in self.entities.agents.keys(): 420 entity = self.entities.agents[name] 421 value = entity.applyGoals(entity,debug=self.debug) 422 if isinstance(results,list): 423 results.append(name + ': ' + `value`)
424
425 - def send(self,sender,receiver,*content):
426 try: 427 if receiver == '*': 428 # Message sent to all 429 receivers = self.entities.agents.keys() 430 else: 431 receivers = [receiver] 432 if type(content[len(content)-1]) is ListType: 433 results = content[len(content)-1] 434 msg = string.join(content[:len(content)-1]) 435 else: 436 results = [] 437 msg = string.join(content) 438 except IndexError: 439 return 'Usage: message <sender> <receiver> <content>' 440 result = self.entities.performMsg(msg,sender,receivers,[],self.debug) 441 if isinstance(results,list): 442 results.append(dict2str(result))
443
444 - def applyPolicy(self,name,results=None):
445 """Returns the action that <entity> will perform, following 446 its policy of behavior""" 447 entity = extractEntity(name,self.entities) 448 if entity: 449 action,explanation = entity.applyPolicy(debug=self.debug) 450 if isinstance(results,list): 451 results.append(entity.name + ' -> ' + `action`) 452 else: 453 if isinstance(results,list): 454 results.append('No such entity: '+name)
455
456 - def setDebugLevel(self,level,results=None):
457 """Sets the debug level to the specified integer""" 458 self.debug.level = int(level) 459 if isinstance(results,list): 460 results.append('Debug level: %d' % (self.debug.level)) 461 return self.debug.level
462
463 - def getEntities(self,results=None):
464 if isinstance(results,list): 465 results.append(`self.entities`)
466
467 - def help(self,results=None):
468 """Prints descriptions of available commands""" 469 if __DOC__: 470 helpStrings = [] 471 for key,value in self.handlers.items(): 472 doc = inspect.getdoc(value) 473 if doc: 474 doc = doc.replace('\n','\n\t\t') 475 else: 476 doc = '' 477 helpStrings.append('%-12s\t%s' % (key,doc)) 478 helpStrings.sort() 479 if isinstance(results,list): 480 results += helpStrings 481 else: 482 if isinstance(results,list): 483 results.append('Help unavailable under jython')
484
485 - def test(self,label,results=None):
486 try: 487 cmd = self.tests[label] 488 except KeyError: 489 return 'Valid tests: '+self.tests.keys() 490 if isinstance(results,list): 491 results.append('Executing "'+cmd+'"') 492 return self.execute(cmd,results)
493
494 - def undo(self,results=None):
495 if self.lastStep: 496 self.entities = copy.deepcopy (self.lastStep) 497 else: 498 if isinstance(results,list): 499 results.append('No previous state stored!')
500
501 - def getEntity(self,name,results=None):
502 """Returns a string representation of the named entity.""" 503 try: 504 entity = self.entities[name] 505 if isinstance(results,list): 506 results.append(`entity`) 507 except KeyError: 508 if isinstance(results,list): 509 results.append('Unknown entity: '+name)
510
511 - def getBelief(self,entityName,beliefName,results=None):
512 """Returns a string representation of the belief that the 513 first entity has about the second.""" 514 try: 515 entity = self.entities.agents[entityname] 516 except KeyError: 517 entity = None 518 if isinstance(results,list): 519 results.append('Unknown entity: '+entityName) 520 if entity: 521 if isinstance(results,list): 522 if beliefName in entity.getEntities(): 523 results.append(`entity.getEntity(name)`) 524 else: 525 results.append('Unknown entity: '+beliefName)
526
527 - def setModel(self,entityName,beliefName,modelName,results=None):
528 """Sets the mental model that 'entityName' holds in regard to 529 'beliefName' to be 'modelName'""" 530 entity = self.entities[entityName] 531 entity.getEntity(beliefName).setModel(modelName) 532 if isinstance(results,list): 533 results.append('%s now models %s as %s' \ 534 % (entityName,beliefName,modelName))
535
536 - def performAct(self,name,actType,obj,results=None):
537 """Performs the action of the specified type by the named entity on the specified object (use 'nil' if no object)""" 538 # For backward compatibility with previous command format 539 if type(obj) is ListType: 540 results = obj 541 obj = 'nil' 542 # Extract the action 543 if not obj or obj == 'nil': 544 actList = [name,actType] 545 else: 546 actList = [name,actType,obj] 547 return self.__act__(actList,results)
548
549 - def doActions(self,actions,results=None):
550 """Performs the actions, provided in dictionary form 551 @param actions: dictionary of actions to be performed, indexed by actor, e.g.: 552 - I{agent1}: [I{act11}, I{act12}, ... ] 553 - I{agent2}: [I{act21}, I{act22}, ... ] 554 - ... 555 @type actions: C{dict:strS{->}L{Action}[]} 556 """ 557 turns = [] 558 for actor,actList in actions.items(): 559 turns.append({'name':actor,'choices':[actList]}) 560 delta = self.entities.microstep(turns,hypothetical=False, 561 explain=True, 562 debug=self.debug) 563 if isinstance(results,list): 564 results.append(dict2str(delta)) 565 return delta
566
567 - def __act__(self,actList,results):
568 action = extractAction(actList,self.entities,self.actionFormat, 569 self.debug) 570 if action: 571 if self.__UNDO__: 572 self.lastStep=copy.deepcopy (self.entities) 573 return self.doActions(actions={action['actor'].name:action}, 574 results=results) 575 else: 576 results.append('Usage: act <entity> <type> <obj>') 577 return {}
578
579 - def execute(self,cmd,results=None):
580 if not results: 581 results = [] 582 cmd = string.strip(cmd) 583 cmd = string.split(cmd) 584 try: 585 cmd[0] = string.lower(cmd[0]) 586 except IndexError: 587 return '?' 588 if cmd[0] == 'quit': 589 return None 590 else: 591 try: 592 handler = self.handlers[cmd[0]] 593 except KeyError: 594 return 'Unknown command: '+cmd[0] 595 apply(handler,cmd[1:]+[results]) 596 return '\n'+string.join(results,'\n')
597
598 - def search(self,feature):
599 for entity in self.entities.members(): 600 self.__search__(entity,feature)
601
602 - def __search__(self,entity,feature):
603 try: 604 value = entity.getState(feature) 605 print entity.ancestry() 606 print '\t',value 607 except KeyError: 608 pass 609 for other in entity.getEntities(): 610 self.__search__(entity.getEntity(other),feature)
611
612 - def setupSusceptibility(self,addr=None):
613 self.susceptibility = addr
614
615 - def querySusceptibility(self,entity):
616 if self.susceptibility: 617 if type(entity) is InstanceType: 618 entity = entity.name 619 queryStr = 'request %s %d %s Theme' %\ 620 ('127.0.0.1', 621 self.router.server_address[1], 622 entity) 623 print queryStr 624 return self.router.send(self.susceptibility,queryStr) 625 else: 626 return None
627
628 - def handleMsg(self,msgList):
629 for msg in msgList: 630 print msg 631 if self.susceptibility == msg[0]: 632 exp = re.match('(\S+)\s*(\S+)\s*(Accepted):\s+'+\ 633 '(.*)\s+(Rejected):\s+(.*)\s+(Neutral):(.*)', 634 msg[1],re.DOTALL) 635 if exp: 636 themes = {} 637 for index in [3,5,7]: 638 key = exp.group(index) 639 themes[key] = [] 640 entries = string.split(exp.group(index+1),'\n') 641 for entry in entries: 642 items = string.split(entry,', ') 643 try: 644 if len(items[0]) > 0: 645 themes[key].append(items) 646 except IndexError: 647 pass 648 self.handleSusceptibility(exp.group(1),themes) 649 else: 650 print 'Unable to parse susceptibility response'
651
652 - def handleSusceptibility(self,entity,themes):
653 self.entities[entity].susceptibilities = themes['Accepted']
654
655 - def iterateModels(self,eList,pIndex,cIndex,modelsUsed):
656 if cIndex == len(eList): 657 print modelsUsed 658 entity = self.entities[eList[pIndex]] 659 action,explanation = entity.applyPolicy() 660 print action,explanation['value'] 661 for step in explanation['breakdown'][1:]: 662 print '\t',step['decision'] 663 print '\t',step['breakdown'][0] 664 print 665 sys.stdout.flush() 666 else: 667 parent = eList[pIndex] 668 child = eList[cIndex] 669 if parent == child: 670 self.iterateModels(eList,pIndex,cIndex+1,modelsUsed) 671 else: 672 parent = self.entities[parent] 673 child = self.entities[child] 674 for model in child.models: 675 parent.getEntity(child).setModel(model) 676 parent.getEntity(parent).getEntity(child).setModel(model) 677 modelsUsed[parent.name][child.name] = model 678 self.iterateModels(eList,pIndex,cIndex+1,modelsUsed)
679
680 - def resetSociety(self):
681 """Clears any classes in the current generic society""" 682 import teamwork.agent.AgentClasses 683 self.classes= GenericSociety() 684 self.classes.importDict(teamwork.agent.AgentClasses.classHierarchy) 685 self.societyFile = None
686
687 - def mainloop(self):
688 while not self.done: 689 cmd = self.getCommand() 690 self.executeCommand(cmd) 691 self.stop()
692
693 - def stop(self):
694 self.done = 1 695 if self.__KQML__: 696 self.router.server_close()
697 698 if __name__ == '__main__': 699 700 import getopt 701 import sys 702 703 try: 704 import psyco 705 psyco.full() 706 except ImportError: 707 print 'Unable to find psyco module for maximum speed' 708 709 script = None 710 scenario = None 711 society = None 712 domain = None 713 display = 'tk' 714 debug = 0 715 error = None 716 expert = False 717 dev = False 718 try: 719 optlist,args = getopt.getopt(sys.argv[1:],'hf:s:d:vx', 720 ['file=','shell=','domain=','society=', 721 'debug=','help','version','expert', 722 'dev']) 723 except getopt.error: 724 error = 1 725 optlist = [] 726 args = [] 727 728 for option in optlist: 729 if option[0] == '--file' or option[0] == '-f': 730 script = option[1] 731 elif option[0] == '--shell' or option[0] == '-s': 732 display = option[1] 733 elif option[0] == '--domain' or option[0] == '-d': 734 domain = option[1] 735 exec('import teamwork.examples.%s as classModule' % (domain)) 736 # Convert any old-school hierarchies 737 if isinstance(classModule.classHierarchy,dict): 738 society = GenericSociety() 739 society.importDict(classModule.classHierarchy) 740 else: 741 society = classModule.classHierarchy 742 elif option[0] == '--society': 743 society = option[1] 744 elif option[0] == '--help' or option[0] == '-h': 745 error = 1 746 elif option[0] == '--debug': 747 debug = int(option[1]) 748 elif option[0] == '--version' or option[0] == '-v': 749 print 'PsychSim %s' % (PsychShell.__VERSION__) 750 sys.exit(0) 751 elif option[0] == '--expert' or option[0] == '-x': 752 expert = True 753 elif option[0] == '--dev': 754 dev = True 755 else: 756 error = 1 757 758 if len(args) > 0: 759 if len(args) > 1: 760 error = 1 761 else: 762 scenario = args[0] 763 764 if error: 765 print 'PsychShell.py',\ 766 '[--domain|-d <domain>]',\ 767 '[--file|-f <script filename>]',\ 768 '[--shell|-s tk|terminal]',\ 769 '[--society <filename>]',\ 770 '[--expert|-x]',\ 771 '<scenario filename>' 772 print 773 print '--domain|-d\tIndicates the class path to the generic society definition' 774 print '--society\tIndicates the file name containing the generic society' 775 print '--file|-f\tIndicates the file containing a script of commands to execute' 776 print '--shell|-s\tIf "tk", use GUI; if "terminal", use interactive text (default is "tk")' 777 print '--expert|-x\tTurns on expert mode' 778 print '--version|-v\tPrints out version information' 779 print '--help|-h\tPrints out this message' 780 print 781 sys.exit(-1) 782 783 if display == 'tk': 784 from teamwork.widgets.PsychGUI.Gui import * 785 shell = GuiShell(scenario=scenario, 786 classes=society, 787 expert=expert,dev=dev, 788 debug=debug) 789 else: 790 from teamwork.shell.TerminalShell import TerminalShell 791 shell = TerminalShell(entities=scenario, 792 classes=society, 793 file=script, 794 debug=debug) 795 shell.mainloop() 796