00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "nel/logic/logic_state_machine.h"
00028
00029 #include "nel/net/service.h"
00030
00031 using namespace std;
00032 using namespace NLMISC;
00033 using namespace NLNET;
00034
00035 namespace NLLOGIC
00036 {
00037
00038
00039 bool testNameWithFilter( sint8 filter, string motif, string varName );
00040
00041 void xmlCheckNodeName (xmlNodePtr &node, const char *nodeName)
00042 {
00043
00044 if ( node == NULL || ((const char*)node->name == NULL) || (strcmp ((const char*)node->name, nodeName) != 0) )
00045 {
00046
00047
00048 if (node != NULL)
00049 {
00050 node = CIXml::getFirstChildNode (node, nodeName);
00051 if ( node != NULL && ((const char*)node->name != NULL) && (strcmp ((const char*)node->name, nodeName) == 0) )
00052 {
00053 nlinfo ("check node %s ok in the child", nodeName);
00054 return;
00055 }
00056 }
00057
00058
00059 char tmp[512];
00060 smprintf (tmp, 512, "LogicStateMachine STATE_MACHINE XML Syntax error in block line %d, node %s should be %s",
00061 (int)node->content, node->name, nodeName);
00062
00063 nlinfo (tmp);
00064 nlstop;
00065 throw EXmlParsingError (tmp);
00066 }
00067
00068 nlinfo ("check node %s ok", nodeName);
00069 }
00070
00071 std::string getXMLProp (xmlNodePtr node, const char *propName)
00072 {
00073 const char *name = (const char*)xmlGetProp (node, (xmlChar*)propName);
00074 if (name)
00075 {
00076 nlinfo ("get prop %s = %s", propName, name);
00077 string n = name;
00078 xmlFree ((void*)name);
00079 return n;
00080 }
00081 else
00082 {
00083
00084 char tmp[512];
00085 smprintf (tmp, 512, "LogicStateMachine XML Syntax error in block %s line %d, aguments Name not found",
00086 node->name, (int)node->content);
00087 throw EXmlParsingError (tmp);
00088 return "";
00089 }
00090 }
00091
00092
00093
00094
00095
00096
00097 void CLogicStateMachine::setCurrentState( string stateName )
00098 {
00099 map<string,CLogicState>::iterator itStates = _States.find( stateName );
00100 if( itStates != _States.end() )
00101 {
00102 (*itStates).second.exitState();
00103
00104 _CurrentState = stateName;
00105
00106 (*itStates).second.enterState();
00107
00108 nlinfo("Switching to state \"%s\"",_CurrentState.c_str());
00109 }
00110 else
00111 {
00112 nlwarning("(LOGIC)<CLogicStateMachine::setCurrentState> The state \"%s\" is not in the state machine \"%s\"",stateName.c_str(),_Name.c_str());
00113 }
00114
00115 }
00116
00117
00118
00119
00120
00121
00122
00123 void CLogicStateMachine::addCondition( CLogicCondition condition )
00124 {
00125 condition.setLogicStateMachine(this);
00126 _Conditions.insert(make_pair(condition.getName(),condition));
00127
00128 }
00129
00130
00131
00132
00133
00134
00135
00136 void CLogicStateMachine::addState( CLogicState logicState )
00137 {
00138 logicState.setLogicStateMachine( this );
00139 _States.insert( std::make_pair(logicState.getName(),logicState) );
00140
00141 }
00142
00143
00144
00145
00146
00147
00148
00149
00150 void CLogicStateMachine::addSIdMap( const TSIdMap& sIdMap )
00151 {
00152
00153 map<string,CLogicState>::iterator itStates;
00154 for( itStates = _States.begin(); itStates != _States.end(); ++itStates )
00155 {
00156 (*itStates).second.addSIdMap( sIdMap );
00157 }
00158
00159 }
00160
00161
00162
00163
00164
00165
00166
00167 void CLogicStateMachine::processLogic()
00168 {
00169
00170 map<string,CLogicState>::iterator itStates = _States.find( _CurrentState );
00171 nlassert( itStates != _States.end() )
00172 (*itStates).second.processLogic();
00173
00174
00175 map<string,CLogicCounter>::iterator itCount;
00176 for( itCount = _Counters.begin(); itCount != _Counters.end(); ++itCount )
00177 {
00178 (*itCount).second.update();
00179 }
00180
00181 }
00182
00183
00184
00185
00186
00187
00188
00189 void CLogicStateMachine::getMessagesToSend( multimap<CEntityId,CMessage>& msgs )
00190 {
00191 map<std::string, CLogicState>::iterator itState;
00192 for( itState = _States.begin(); itState != _States.end(); ++itState )
00193 {
00194 (*itState).second.getMessagesToSend( msgs );
00195 }
00196
00197 }
00198
00199
00200
00201
00202
00203
00204
00205
00206 bool CLogicStateMachine::getVariable( std::string& varName, CLogicVariable& var )
00207 {
00208 map<string,CLogicVariable>::iterator itVar = _Variables.find( varName );
00209 if( itVar != _Variables.end() )
00210 {
00211 var = (*itVar).second;
00212 return true;
00213 }
00214
00215 map<string,CLogicCounter>::iterator itCount = _Counters.find( varName );
00216 if( itCount != _Counters.end() )
00217 {
00218 var = (*itCount).second;
00219 return true;
00220 }
00221
00222 return false;
00223
00224 }
00225
00226
00227
00228
00229
00230
00231
00232 bool CLogicStateMachine::getCondition( const std::string& condName, CLogicCondition& cond )
00233 {
00234 map<string,CLogicCondition>::iterator itCond = _Conditions.find( condName );
00235 if( itCond != _Conditions.end() )
00236 {
00237 cond = (*itCond).second;
00238 return true;
00239 }
00240 else
00241 {
00242 return false;
00243 }
00244
00245 }
00246
00247
00248
00249
00250
00251
00252 void CLogicStateMachine::modifyVariable( string varName, string modifOperator, sint64 value )
00253 {
00254 map<string,CLogicVariable>::iterator itVar = _Variables.find( varName );
00255 if( itVar != _Variables.end() )
00256 {
00257 (*itVar).second.applyModification( modifOperator, value );
00258 return;
00259 }
00260 map<string,CLogicCounter>::iterator itCount = _Counters.find( varName );
00261 if( itCount != _Counters.end() )
00262 {
00263 (*itCount).second.applyModification( modifOperator, value );
00264 return;
00265 }
00266
00267 nlwarning("(LOGIC)<CLogicStateMachine::modifyVariable> The variable \"%s\" is not in the state machine \"%s\"",varName.c_str(),_Name.c_str());
00268
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 void CLogicStateMachine::displayVariables()
00316 {
00317 multimap<CEntityId,string> allVariables;
00318
00319
00320 map<string, CLogicState>::iterator itS;
00321 for( itS = _States.begin(); itS != _States.end(); ++itS )
00322 {
00323 (*itS).second.fillVarMap( allVariables );
00324 }
00325
00326
00327 vector<string> unclaimedVariables;
00328 CEntityId unknown;
00329 unknown.setType( 0xfe );
00330 unknown.setCreatorId( 0 );
00331 unknown.setDynamicId( 0 );
00332 pair<multimap<CEntityId,string>::iterator,multimap<CEntityId,string>::iterator> itVarsRng = allVariables.equal_range(unknown);
00333 multimap<CEntityId,string>::iterator itVars;
00334
00335 for( itVars = itVarsRng.first; itVars != itVarsRng.second; )
00336 {
00337 multimap<CEntityId,string>::iterator itDel = itVars++;
00338 unclaimedVariables.push_back( (*itDel).second );
00339 allVariables.erase( itDel );
00340 }
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 nlinfo("VARIABLES/COUNTERS in %s : %d/%d are registered : ",_Name.c_str(),allVariables.size(),allVariables.size()+unclaimedVariables.size());
00357
00358 for( itVars = allVariables.begin(); itVars != allVariables.end(); ++itVars )
00359 {
00360 map<string, CLogicVariable>::const_iterator itV = _Variables.find( (*itVars).second );
00361 nlinfo("[%d] %s = %f",(uint8)(*itVars).first.getDynamicId(),(*itV).first.c_str(),(double)(*itV).second.getValue());
00362 }
00363
00364
00365 sort( unclaimedVariables.begin(), unclaimedVariables.end() );
00366 vector<string>::iterator itUV;
00367 for( itUV = unclaimedVariables.begin(); itUV != unclaimedVariables.end(); ++itUV )
00368 {
00369 map<string, CLogicVariable>::const_iterator itV = _Variables.find( *itUV );
00370 nlinfo("(-)%s = %f",(*itV).first.c_str(),(double)(*itV).second.getValue());
00371 }
00372
00373 }
00374
00375
00376
00377
00378
00379
00380 void CLogicStateMachine::displayStates()
00381 {
00382 nlinfo("There are %d STATES in the state machine \"%s\": ",_States.size(),_Name.c_str());
00383 map<string, CLogicState>::const_iterator itS;
00384 for( itS = _States.begin(); itS != _States.end(); ++itS )
00385 {
00386 nlinfo("%s",(*itS).first.c_str());
00387 }
00388 nlinfo("The current state is : \"%s\"",_CurrentState.c_str());
00389
00390 }
00391
00392
00393
00394
00395
00396
00397 void CLogicStateMachine::setVerbose( string varName, bool b )
00398 {
00399 if( varName == "all" )
00400 {
00401 map<string, CLogicVariable>::iterator itV;
00402 for( itV = _Variables.begin(); itV != _Variables.end(); ++itV )
00403 {
00404 (*itV).second.setVerbose( b );
00405 }
00406 map<string, CLogicCounter>::iterator itC;
00407 for( itC = _Counters.begin(); itC != _Counters.end(); ++itC )
00408 {
00409 (*itC).second.setVerbose( b );
00410 }
00411 if(b)
00412 {
00413 nlinfo("the verbose mode has been activated for all the variables",varName.c_str());
00414 }
00415 else
00416 {
00417 nlinfo("the verbose mode has been desactivated for all the variables",varName.c_str());
00418 }
00419 return;
00420 }
00421
00422 sint8 filter = -1;
00423 string motif;
00424
00425 if( varName[0]=='*' && varName[varName.size()-1]=='*')
00426 {
00427 motif = varName.substr(1,varName.size()-2);
00428 filter = 0;
00429 }
00430 else
00431
00432 if( varName[0]=='*' )
00433 {
00434 motif = varName.substr(1,varName.size()-1);
00435 filter = 1;
00436 }
00437 else
00438
00439 if( varName[varName.size()-1]=='*' )
00440 {
00441 motif = varName.substr(0,varName.size()-1);
00442 filter = 2;
00443 }
00444
00445
00446 if( filter == -1 )
00447 {
00448 map<string, CLogicVariable>::iterator itV = _Variables.find( varName );
00449 if( itV != _Variables.end() )
00450 {
00451 (*itV).second.setVerbose( b );
00452 }
00453 map<string, CLogicCounter>::iterator itC = _Counters.find( varName );
00454 if( itC != _Counters.end() || varName =="all" )
00455 {
00456 (*itC).second.setVerbose( b );
00457 }
00458 }
00459
00460 else
00461 {
00462 map<string, CLogicVariable>::iterator itV;
00463 for( itV = _Variables.begin(); itV != _Variables.end(); ++itV )
00464 {
00465 if( testNameWithFilter( filter, motif,(*itV).second.getName()) )
00466 {
00467 (*itV).second.setVerbose( b );
00468 }
00469 }
00470 map<string, CLogicCounter>::iterator itC;
00471 for( itC = _Counters.begin(); itC != _Counters.end(); ++itC )
00472 {
00473 if( testNameWithFilter( filter, motif,(*itC).second.getName()) )
00474 {
00475 (*itC).second.setVerbose( b );
00476 }
00477 }
00478 }
00479 if(b)
00480 {
00481 nlinfo("the verbose mode for variable \"%s\" has been activated",varName.c_str());
00482 }
00483 else
00484 {
00485 nlinfo("the verbose mode for variable \"%s\" has been desactivated",varName.c_str());
00486 }
00487
00488 }
00489
00490
00491
00492
00493
00494
00495
00496 bool testNameWithFilter( sint8 filter, string motif, string varName )
00497 {
00498 if( varName.size() > motif.size() )
00499 {
00500 switch( filter )
00501 {
00502
00503 case 0 :
00504 {
00505 if(varName.find(motif) != -1)
00506 {
00507 return true;
00508 }
00509 }
00510 break;
00511
00512
00513 case 1 :
00514 {
00515 sint beginIndex = varName.size() - motif.size() - 1;
00516 string endOfVarName = varName.substr(beginIndex,motif.size());
00517 if( endOfVarName == motif )
00518 {
00519 return true;
00520 }
00521 }
00522 break;
00523
00524
00525 case 2 :
00526 {
00527 string beginOfVarName = varName.substr(0,motif.size());
00528 if( beginOfVarName == motif )
00529 {
00530 return true;
00531 }
00532 }
00533 break;
00534 }
00535 }
00536
00537 return false;
00538
00539 }
00540
00541 void CLogicStateMachine::write (xmlDocPtr doc) const
00542 {
00543
00544 xmlNodePtr node = xmlNewDocNode (doc, NULL, (const xmlChar*)"STATE_MACHINE", NULL);
00545 xmlDocSetRootElement (doc, node);
00546 xmlSetProp (node, (const xmlChar*)"Name", (const xmlChar*)_Name.c_str());
00547 xmlSetProp (node, (const xmlChar*)"CurrentState", (const xmlChar*)_CurrentState.c_str());
00548
00549 for (std::map<std::string, CLogicVariable>::const_iterator vit = _Variables.begin(); vit != _Variables.end(); vit++)
00550 {
00551 (*vit).second.write(node);
00552 }
00553
00554 for (std::map<std::string, CLogicCounter>::const_iterator cit = _Counters.begin(); cit != _Counters.end(); cit++)
00555 {
00556 (*cit).second.write(node);
00557 }
00558
00559 for (std::map<std::string, CLogicCondition>::const_iterator c2it = _Conditions.begin(); c2it != _Conditions.end(); c2it++)
00560 {
00561 (*c2it).second.write(node);
00562 }
00563
00564 for (std::map<std::string, CLogicState>::const_iterator sit = _States.begin(); sit != _States.end(); sit++)
00565 {
00566 (*sit).second.write(node);
00567 }
00568 }
00569
00570 void CLogicStateMachine::read (xmlNodePtr node)
00571 {
00572 xmlCheckNodeName (node, "STATE_MACHINE");
00573
00574 setName (getXMLProp (node, "Name"));
00575
00576 {
00577
00578 uint nb = CIXml::countChildren (node, "VARIABLE");
00579 uint i = 0;
00580 xmlNodePtr parent = CIXml::getFirstChildNode (node, "VARIABLE");
00581 while (i<nb)
00582 {
00583 CLogicVariable v;
00584 v.read(parent);
00585 _Variables.insert (make_pair(v.getName(), v));
00586
00587
00588 parent = CIXml::getNextChildNode (parent, "VARIABLE");
00589 i++;
00590 }
00591 }
00592
00593 {
00594
00595 uint nb = CIXml::countChildren (node, "COUNTER");
00596 uint i = 0;
00597 xmlNodePtr parent = CIXml::getFirstChildNode (node, "COUNTER");
00598 while (i<nb)
00599 {
00600 CLogicCounter v;
00601 v.read(parent);
00602 _Counters.insert (make_pair(v.getName(), v));
00603
00604
00605 parent = CIXml::getNextChildNode (parent, "COUNTER");
00606 i++;
00607 }
00608 }
00609
00610 {
00611
00612 uint nb = CIXml::countChildren (node, "CONDITION");
00613 uint i = 0;
00614 xmlNodePtr parent = CIXml::getFirstChildNode (node, "CONDITION");
00615 while (i<nb)
00616 {
00617 CLogicCondition v;
00618 v.read(parent);
00619 _Conditions.insert (make_pair(v.getName(), v));
00620
00621
00622 parent = CIXml::getNextChildNode (parent, "CONDITION");
00623 i++;
00624 }
00625 }
00626
00627 {
00628
00629 uint nb = CIXml::countChildren (node, "STATE");
00630 uint i = 0;
00631 xmlNodePtr parent = CIXml::getFirstChildNode (node, "STATE");
00632 while (i<nb)
00633 {
00634 CLogicState v;
00635 v.read(parent);
00636 _States.insert (make_pair(v.getName(), v));
00637
00638
00639 parent = CIXml::getNextChildNode (parent, "STATE");
00640 i++;
00641 }
00642 }
00643
00644 setCurrentState (getXMLProp (node, "CurrentState"));
00645 }
00646
00647 }