# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

logic_state.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 
00027 #include "nel/logic/logic_state.h"
00028 #include "nel/logic/logic_state_machine.h"
00029 
00030 
00031 using namespace std;
00032 using namespace NLMISC;
00033 using namespace NLNET;
00034 
00035 namespace NLLOGIC
00036 {
00037 
00038 //---------------------------------------------------
00039 //      CLogicState
00040 //
00041 //---------------------------------------------------
00042 CLogicState::CLogicState()
00043 {
00044         _StateName = "no_state";
00045         _LogicStateMachine = 0;
00046 
00047 } // CLogicState //
00048 
00049 
00050 //---------------------------------------------------
00051 //      setLogicStateMachine
00052 //
00053 //---------------------------------------------------
00054 void CLogicState::setLogicStateMachine( CLogicStateMachine * logicStateMachine ) 
00055 { 
00056         if( logicStateMachine == 0 )
00057         {
00058                 nlwarning("(LOGIC)<CLogicCondition::setLogicStateMachine> The state machine is null");
00059         }
00060         else
00061         {
00062                 // init the logic state machine for this state
00063                 _LogicStateMachine = logicStateMachine; 
00064 
00065                 // init the logic state machine in each event
00066                 vector<CLogicEvent>::iterator itEvent;
00067                 for( itEvent = _Events.begin(); itEvent != _Events.end(); ++itEvent )
00068                 {
00069                         (*itEvent).setLogicStateMachine( logicStateMachine );
00070                 }
00071         }
00072 
00073 } // setLogicStateMachine //
00074 
00075 
00076 
00077 //---------------------------------------------------
00078 // addEvent :
00079 // 
00080 //---------------------------------------------------
00081 void CLogicState::addEvent( CLogicEvent event ) 
00082 { 
00083         event.setLogicStateMachine( _LogicStateMachine );
00084         _Events.push_back( event ); 
00085 
00086 } // addEvent //
00087 
00088 
00089 
00090 //---------------------------------------------------
00091 // addSIdMap :
00092 //
00093 // looks in all the messages of the state if the 
00094 // destination names can be associated with a sid.
00095 //---------------------------------------------------
00096 void CLogicState::addSIdMap( const TSIdMap& sIdMap )
00097 {
00098         vector<CLogicEventMessage>::iterator itMsg;
00099 
00101         for( itMsg = _EntryMessages.begin(); itMsg != _EntryMessages.end(); ++itMsg )
00102         {
00103                 TSIdMap::const_iterator itId = sIdMap.find( (*itMsg).Destination );
00104                 // if message destination exists in the map we associate the sid with the message
00105                 if( itId != sIdMap.end() )
00106                 {
00107                         (*itMsg).DestinationId = (*itId).second;
00108                 }
00109         }
00111         trySendEntryMessages();
00112                 
00113 
00114         // event messages
00115         vector<CLogicEvent>::iterator itEvt;
00116         for( itEvt = _Events.begin(); itEvt != _Events.end(); ++itEvt )
00117         {
00118                 string dest = (*itEvt).EventAction.EventMessage.Destination;
00119                 TSIdMap::const_iterator itId = sIdMap.find( dest );
00120                 // if message destination exists in the map we associate the sid with the message
00121                 if( itId != sIdMap.end() )
00122                 {
00123                         (*itEvt).EventAction.EventMessage.DestinationId = (*itId).second;
00124                 }
00125         }
00127         trySendEventMessages();
00128 
00129 
00131         for( itMsg = _ExitMessages.begin(); itMsg != _ExitMessages.end(); ++itMsg )
00132         {
00133                 TSIdMap::const_iterator itId = sIdMap.find( (*itMsg).Destination );
00134                 // if message destination exists in the map we associate the sid with the message
00135                 if( itId != sIdMap.end() )
00136                 {
00137                         (*itMsg).DestinationId = (*itId).second;
00138                 }
00139         }
00140         
00141 } // addSIdMap //
00142 
00143 
00144 //---------------------------------------------------
00145 // processLogic :
00146 // 
00147 //---------------------------------------------------
00148 void CLogicState::processLogic()
00149 {
00150         // test all conditions managed by this state
00151         vector<CLogicEvent>::iterator itEvent;
00152         for( itEvent = _Events.begin(); itEvent != _Events.end(); ++itEvent )
00153         {
00154                 if( (*itEvent).testCondition() )
00155                 {
00156                         //nlinfo("The condition %s is valid",(*itEvent).ConditionName.c_str());
00157                         if( (*itEvent).EventAction.IsStateChange )
00158                         {
00159                                 _LogicStateMachine->setCurrentState( (*itEvent).EventAction.StateChange );
00160                         }
00161                         else
00162                         {
00163                                 // this message will be sent as soon as the dest id will be given
00164                                 (*itEvent).EventAction.enableSendMessage();
00165 
00167                                 trySendEventMessages();
00168                         }
00169                 }
00170                 else
00171                 {
00172                         // reset message send status here to be able to send messages several times in the logic state
00173                         // --> this has to be done if we want messages to be sent every time the condition becomes verified
00174                 }
00175         }
00176 
00177 } // processLogic //
00178 
00179 
00180 //---------------------------------------------------
00181 // enterState :
00182 // 
00183 //---------------------------------------------------
00184 void CLogicState::enterState()
00185 {
00187         trySendEntryMessages();
00188 
00189 } // enterState //
00190 
00191 
00192 //---------------------------------------------------
00193 // exitState :
00194 // 
00195 //---------------------------------------------------
00196 void CLogicState::exitState()
00197 {
00198         vector<CLogicEventMessage>::iterator itMsg;
00199         for( itMsg = _ExitMessages.begin(); itMsg != _ExitMessages.end(); ++itMsg )
00200         {
00201                 if( (*itMsg).DestinationId != CEntityId() )
00202                 {
00203                         CMessage msgOut( (*itMsg).MessageId );
00204                         msgOut.serial( (*itMsg).Arguments );
00205                         
00206                         _MessagesToSend.insert( make_pair((*itMsg).DestinationId,msgOut) );
00207                 }
00208         }
00209 
00210         // reset the entry messages send status
00211         for( itMsg = _EntryMessages.begin(); itMsg != _EntryMessages.end(); ++itMsg )
00212         {
00213                 (*itMsg).ToSend = false;
00214                 (*itMsg).Sent = false;
00215         }
00216 
00217         // reset all events
00218         vector<CLogicEvent>::iterator itEvent;
00219         for( itEvent = _Events.begin(); itEvent != _Events.end(); ++itEvent )
00220         {
00221                 (*itEvent).reset();
00222         }
00223 
00224         // reset the exit messages send status
00225         for( itMsg = _ExitMessages.begin(); itMsg != _ExitMessages.end(); ++itMsg )
00226         {
00227                 (*itMsg).ToSend = false;
00228                 (*itMsg).Sent = false;
00229         }
00230         
00231 } // exitState //
00232 
00233 
00234 
00235 //---------------------------------------------------
00236 // trySendEntryMessages :
00237 // 
00238 //---------------------------------------------------
00239 void CLogicState::trySendEntryMessages()
00240 {
00242         vector<CLogicEventMessage>::iterator itMsg;
00243         for( itMsg = _EntryMessages.begin(); itMsg != _EntryMessages.end(); ++itMsg )
00244         {
00245                 if( !(*itMsg).Sent && (*itMsg).DestinationId.getType() != 0xfe )
00246                 {
00247                         CMessage msgOut( (*itMsg).MessageId );
00248                         msgOut.serial( (*itMsg).Arguments );
00249 
00250                         _MessagesToSend.insert( make_pair((*itMsg).DestinationId,msgOut) );
00251                         
00252                         (*itMsg).ToSend = false;
00253                         (*itMsg).Sent = true;
00254                 }
00255         }
00256 
00257 } // trySendEntryMessages //
00258 
00259 
00260 
00261 //---------------------------------------------------
00262 // trySendEventMessages :
00263 // 
00264 //---------------------------------------------------
00265 void CLogicState::trySendEventMessages()
00266 {
00267         // test all conditions managed by this state
00268         vector<CLogicEvent>::iterator itEvent;
00269         for( itEvent = _Events.begin(); itEvent != _Events.end(); ++itEvent )
00270         {
00271                 if( (*itEvent).EventAction.EventMessage.ToSend == true )
00272                 {
00273                         if( (*itEvent).EventAction.EventMessage.Sent == false )
00274                         {
00275                                 if( (*itEvent).EventAction.EventMessage.DestinationId.getType() != 0xfe )
00276                                 {
00277                                         CMessage msgOut( (*itEvent).EventAction.EventMessage.MessageId );
00278                                         msgOut.serial( (*itEvent).EventAction.EventMessage.Arguments );
00279                                         
00280                                         _MessagesToSend.insert( make_pair((*itEvent).EventAction.EventMessage.DestinationId,msgOut) );
00281 
00282                                         (*itEvent).EventAction.EventMessage.ToSend = false;
00283                                         (*itEvent).EventAction.EventMessage.Sent = true;
00284                                 }
00285                         }
00286                 }
00287         }
00288 
00289 } // trySendEventMessages //
00290 
00291 
00292 //---------------------------------------------------
00293 // getMessagesToSend :
00294 // 
00295 //---------------------------------------------------
00296 void CLogicState::getMessagesToSend( multimap<CEntityId,CMessage>& msgs )
00297 {
00298         multimap<CEntityId,CMessage>::iterator itMsg;
00299         for( itMsg = _MessagesToSend.begin(); itMsg != _MessagesToSend.end(); ++itMsg )
00300         {
00301                 msgs.insert( *itMsg );
00302         }
00303 
00304         // erase all the messages
00305         _MessagesToSend.clear();
00306 
00307 } // getMessagesToSend //
00308 
00309 
00310 
00311 //---------------------------------------------------
00312 // fillVarMap :
00313 // 
00314 //---------------------------------------------------
00315 void CLogicState::fillVarMap( multimap<CEntityId,string >& stateMachineVariables )
00316 {
00317         // events
00318         vector<CLogicEvent>::iterator itEvt;
00319         for( itEvt = _Events.begin(); itEvt != _Events.end(); ++itEvt )
00320         {
00321                 // get the condition used in the event
00322                 CLogicCondition condition;
00323                 if( _LogicStateMachine->getCondition((*itEvt).ConditionName,condition) )
00324                 {
00325                         // get vars used in the conditions
00326                         set<string> condVars;
00327                         condition.fillVarSet( condVars );
00328 
00329                         // add var with related service
00330                         set<string>::iterator itCV;
00331                         for( itCV = condVars.begin(); itCV != condVars.end(); ++itCV )
00332                         {
00333                                 stateMachineVariables.insert( make_pair((*itEvt).EventAction.EventMessage.DestinationId,*itCV) );
00334                         }
00335                 }
00336         }
00337 
00338 } // fillVarMap //
00339 
00340 
00341 
00342 //---------------------------------------------------
00343 // serial :
00344 // 
00345 //---------------------------------------------------
00346 /*void CLogicState::serial( IStream &f )
00347 {
00348         f.xmlPush( "STATE");
00349 
00350         f.serial( _StateName );
00351         f.serialCont( _EntryMessages );
00352         f.serialCont( _ExitMessages );
00353         f.serialCont( _Events );
00354 
00355         f.xmlPop();
00356 
00357 } // serial //*/
00358 
00359 void CLogicState::write (xmlNodePtr node) const
00360 {
00361         xmlNodePtr elmPtr = xmlNewChild ( node, NULL, (const xmlChar*)"STATE", NULL);
00362         xmlSetProp (elmPtr, (const xmlChar*)"Name", (const xmlChar*)_StateName.c_str());
00363 
00364         uint i;
00365         for (i = 0; i < _EntryMessages.size(); i++)
00366         {
00367                 _EntryMessages[i].write(elmPtr, "ENTRY_");
00368         }
00369         for (i = 0; i < _ExitMessages.size(); i++)
00370         {
00371                 _ExitMessages[i].write(elmPtr, "EXIT_");
00372         }
00373         for (i = 0; i < _Events.size(); i++)
00374         {
00375                 _Events[i].write(elmPtr);
00376         }
00377 }
00378 
00379 void CLogicState::read (xmlNodePtr node)
00380 {
00381         xmlCheckNodeName (node, "STATE");
00382 
00383         _StateName = getXMLProp (node, "Name");
00384 
00385         {
00386                 // Count the parent
00387                 uint nb = CIXml::countChildren (node, "ENTRY_EVENT_MESSAGE");
00388                 uint i = 0;
00389                 xmlNodePtr parent = CIXml::getFirstChildNode (node, "ENTRY_EVENT_MESSAGE");
00390                 while (i<nb)
00391                 {
00392                         CLogicEventMessage v;
00393                         v.read(parent);
00394                         _EntryMessages.push_back(v);
00395 
00396                         // Next parent
00397                         parent = CIXml::getNextChildNode (parent, "ENTRY_EVENT_MESSAGE");
00398                         i++;
00399                 }
00400         }
00401         
00402         {
00403                 // Count the parent
00404                 uint nb = CIXml::countChildren (node, "EXIT_EVENT_MESSAGE");
00405                 uint i = 0;
00406                 xmlNodePtr parent = CIXml::getFirstChildNode (node, "EXIT_EVENT_MESSAGE");
00407                 while (i<nb)
00408                 {
00409                         CLogicEventMessage v;
00410                         v.read(parent);
00411                         _ExitMessages.push_back(v);
00412 
00413                         // Next parent
00414                         parent = CIXml::getNextChildNode (parent, "EXIT_EVENT_MESSAGE");
00415                         i++;
00416                 }
00417         }
00418 
00419         {
00420                 // Count the parent
00421                 uint nb = CIXml::countChildren (node, "EVENT");
00422                 uint i = 0;
00423                 xmlNodePtr parent = CIXml::getFirstChildNode (node, "EVENT");
00424                 while (i<nb)
00425                 {
00426                         CLogicEvent v;
00427                         v.read(parent);
00428                         _Events.push_back(v);
00429 
00430                         // Next parent
00431                         parent = CIXml::getNextChildNode (parent, "EVENT");
00432                         i++;
00433                 }
00434         }
00435 
00436 }
00437 
00438 
00439 } // NLLOGIC
00440