[BACK] Return to logic_condition.cpp CVS log [TXT][DIR] Up to Nevrax / code / nel / src / logic

File: Nevrax / code / nel / src / logic / logic_condition.cpp (download)
Revision 1.2, Thu Jun 20 12:17:56 2002 UTC (5 weeks, 3 days ago) by lecroart
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +156 -9 lines
CHANGED: now load/save state machine in XML format

/** \file logic_condition.cpp
 * 
 *
 * $Id: logic_condition.cpp,v 1.2 2002/06/20 12:17:56 lecroart Exp $
 */

/* Copyright, 2000 Nevrax Ltd.
 *
 * This file is part of NEVRAX NEL.
 * NEVRAX NEL is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.

 * NEVRAX NEL is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with NEVRAX NEL; see the file COPYING. If not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 * MA 02111-1307, USA.
 */


#include "nel/misc/o_xml.h"

#include "nel/logic/logic_condition.h"
#include "nel/logic/logic_variable.h"
#include "nel/logic/logic_state_machine.h"

using namespace NLMISC;
using namespace std;

namespace NLLOGIC
{

//-------------------------------------------------
// setLogicStateMachine :
//
//-------------------------------------------------
void CLogicComparisonBlock::setLogicStateMachine( CLogicStateMachine * logicStateMachine )
{ 
        if( logicStateMachine == 0 )
        {
                nlwarning("(LOGIC)<CLogicComparisonBlock::setLogicStateMachine> The state machine is null");
        }
        else
        {
                _LogicStateMachine = logicStateMachine; 
        }
        
} // setLogicStateMachine //


//-------------------------------------------------
// testLogic :
//
//-------------------------------------------------
bool CLogicComparisonBlock::testLogic()
{
        CLogicVariable var;
        if( _LogicStateMachine->getVariable( VariableName, var ) == false )
        {
                nlwarning("(LOGIC)<CLogicComparisonBlock::testLogic> The variable %s is unknown in the state machine",VariableName.c_str());
                return false;
        }

        if( Operator == "<"  )        return ( var.getValue() <  Comparand );
        if( Operator == "<=" )        return ( var.getValue() <= Comparand );
        if( Operator == ">"  )        return ( var.getValue() >  Comparand );
        if( Operator == ">=" )        return ( var.getValue() >= Comparand );
        if( Operator == "==" )        return ( var.getValue() == Comparand );
        if( Operator == "!=" )        return ( var.getValue() != Comparand );

        nlwarning("(LOGIC)<CLogicComparisonBlock::testLogic> The comparison block operator %s is unknown",Operator.c_str());
        return false;

} // testLogic //


//-------------------------------------------------
// serial :
//
//-------------------------------------------------
/*void CLogicComparisonBlock::serial( IStream &f )
{
        f.xmlPush("COMPARISON_BLOCK");
        
        f.serial( VariableName );
        f.serial( Operator );
        f.serial( Comparand );
        
        f.xmlPop();

} // serial //*/

void CLogicComparisonBlock::write (xmlNodePtr node) const
{
        xmlNodePtr elmPtr = xmlNewChild ( node, NULL, (const xmlChar*)"COMPARISON_BLOCK", NULL);
        xmlSetProp (elmPtr, (const xmlChar*)"VariableName", (const xmlChar*)VariableName.c_str());
        xmlSetProp (elmPtr, (const xmlChar*)"Operator", (const xmlChar*)Operator.c_str());
        xmlSetProp (elmPtr, (const xmlChar*)"Comparand", (const xmlChar*)toString(Comparand).c_str());
}

void CLogicComparisonBlock::read (xmlNodePtr node)
{
        xmlCheckNodeName (node, "COMPARISON_BLOCK");

        VariableName = getXMLProp (node, "VariableName");
        Operator = getXMLProp (node, "Operator");
        Comparand = atoiInt64(getXMLProp (node, "Comparand").c_str());
}







//-------------------------------------------------
// setLogicStateMachine :
//
//-------------------------------------------------
void CLogicConditionLogicBlock::setLogicStateMachine( CLogicStateMachine * logicStateMachine )
{ 
        if( logicStateMachine == 0 )
        {
                nlwarning("(LOGIC)<CCLogicConditionLogicBlock::setLogicStateMachine> The state machine is null");
        }
        else
        {
                // set the state machine of this node
                _LogicStateMachine = logicStateMachine; 

                // set the state machine of the logic block 
                ComparisonBlock.setLogicStateMachine( logicStateMachine );
        }

} // setLogicStateMachine //


//-------------------------------------------------
// testLogic :
//
//-------------------------------------------------
bool CLogicConditionLogicBlock::testLogic()
{
        switch( Type )
        {
                case NOT :
                {
                        return true;
                }
                break;

                case COMPARISON :
                {
                        return ComparisonBlock.testLogic();
                }
                break;

                case SUB_CONDITION :
                {
                        CLogicCondition condition;
                        if( _LogicStateMachine->getCondition(SubCondition,condition) )
                        {
                                return condition.testLogic();
                        }
                        else
                        {
                                nlwarning("(LOGIC)<CLogicConditionLogicBlock::testLogic> The subcondition \"%s\" is unknown in the state machine \"%s\"",
                                        SubCondition.c_str(),_LogicStateMachine->getName().c_str());
                        }
                        
                }

                default :
                        nlerror("(LOGIC)<CLogicConditionLogicBlock::testLogic> logic block type %d is unknown",Type);
        }
        
        return false;

} // testLogic //



//-------------------------------------------------
// fillVarSet :
//
//-------------------------------------------------
void CLogicConditionLogicBlock::fillVarSet( set<string>& condVars )
{
        if( Type == COMPARISON )
        {
                condVars.insert( ComparisonBlock.VariableName );
        }
        else
        {
                if( Type == SUB_CONDITION )
                {
                        CLogicCondition condition;
                        if( _LogicStateMachine->getCondition(SubCondition,condition) )
                        {
                                condition.fillVarSet( condVars );
                        }
                }
        }

} // fillVarSet //


//-------------------------------------------------
// serial :
//
//-------------------------------------------------
/*void CLogicConditionLogicBlock::serial( IStream &f )
{
        f.xmlPush("CONDITION_LOGIC_BLOCK");

        f.serialEnum( Type );
        switch( Type )
        {
                case NOT : break;
                        
                case COMPARISON :
                {
                        f.serial( ComparisonBlock );
                }
                break;

                case SUB_CONDITION :
                {
                        f.serial( SubCondition );
                }
                break;
        };
        
        f.xmlPop();
};*/

void CLogicConditionLogicBlock::write (xmlNodePtr node) const
{
        xmlNodePtr elmPtr = xmlNewChild ( node, NULL, (const xmlChar*)"CONDITION_LOGIC_NODE", NULL);
        xmlSetProp (elmPtr, (const xmlChar*)"Type", (const xmlChar*)toString(Type).c_str());
        switch( Type )
        {
                case NOT : break;
                        
                case COMPARISON :
                {
                        ComparisonBlock.write(elmPtr);
                }
                break;

                case SUB_CONDITION :
                {
                        xmlSetProp (elmPtr, (const xmlChar*)"SubCondition", (const xmlChar*)SubCondition.c_str());
                }
                break;
        };
}

void CLogicConditionLogicBlock::read (xmlNodePtr node)
{
        xmlCheckNodeName (node, "CONDITION_LOGIC_NODE");

        Type = (TLogicConditionLogicBlockType)atoi(getXMLProp (node, "Type").c_str());
        switch( Type )
        {
                case NOT : break;
                        
                case COMPARISON :
                {
                        ComparisonBlock.read (node);
                }
                break;

                case SUB_CONDITION :
                {
                        SubCondition = getXMLProp (node, "SubCondition");
                }
                break;
        };
}

//-----------------------------------------



//-------------------------------------------------
// setLogicStateMachine :
//
//-------------------------------------------------
void CLogicConditionNode::setLogicStateMachine( CLogicStateMachine * logicStateMachine )
{ 
        if( logicStateMachine == 0 )
        {
                nlwarning("(LOGIC)<CLogicConditionNode::setLogicStateMachine> The state machine is null");
        }
        else
        {
                // set the state machine of this node
                _LogicStateMachine = logicStateMachine; 

                // set the state machine of the logic block 
                LogicBlock.setLogicStateMachine( logicStateMachine );
                
                // set the state machine for the sub nodes
                vector<CLogicConditionNode *>::iterator itNodes;
                for( itNodes = _Nodes.begin(); itNodes != _Nodes.end(); ++itNodes )
                {
                        (*itNodes)->setLogicStateMachine( logicStateMachine );
                }
        }

} // setLogicStateMachine //


//-------------------------------------------------
// addNode :
//
//-------------------------------------------------
void CLogicConditionNode::addNode( CLogicConditionNode * node )
{
        node->setLogicStateMachine( _LogicStateMachine );
        _Nodes.push_back( node );

} // addToSubNodes //


//-------------------------------------------------
// testLogic :
//
//-------------------------------------------------
bool CLogicConditionNode::testLogic()
{
        // test the logic block
        if( LogicBlock.testLogic() == false )
        {
                return false;
        }

        // if there's no subtree we assess the subtree is true
        if( _Nodes.size() == 0 )
        {
                return true;
        }

        // test the subtree
        if( LogicBlock.isNotBlock() )
        {
                // the subtree is false if at least one node is true
                vector<CLogicConditionNode *>::iterator itNodes;
                for( itNodes = _Nodes.begin(); itNodes != _Nodes.end(); ++itNodes )
                {
                        if( (*itNodes)->testLogic() == true )
                        {
                                return false;
                        }
                }

                return true;
        }
        else
        {
                // the subtree is true if at least one node is true
                vector<CLogicConditionNode *>::iterator itNodes;
                for( itNodes = _Nodes.begin(); itNodes != _Nodes.end(); ++itNodes )
                {
                        if( (*itNodes)->testLogic() == true )
                        {
                                return true;
                        }
                }

                return false;
        }

} // testLogic //


//-------------------------------------------------
// fillVarSet :
//
//-------------------------------------------------
void CLogicConditionNode::fillVarSet( set<string>& condVars )
{
        if( Type == LOGIC_NODE )
        {
                LogicBlock.fillVarSet( condVars );
        }

        vector<CLogicConditionNode *>::iterator itNode;
        for( itNode = _Nodes.begin(); itNode != _Nodes.end(); ++itNode )
        {
                (*itNode)->fillVarSet( condVars );
        }

} // fillVarSet //


//-------------------------------------------------
// serial :
//
//-------------------------------------------------
/*void CLogicConditionNode::serial( IStream &f )
{
        f.xmlPush("CONDITION_NODE");
        
        f.serialEnum( Type );
        switch( Type )
        {
                case TERMINATOR : break;
                case LOGIC_NODE :
                {
                        f.serial( LogicBlock );
                        if( f.isReading() )
                        {
                                uint32 sz;
                                f.serial( sz );
                                uint i;
                                for( i = 0; i < sz; i++ )
                                {
                                        CLogicConditionNode * node = new CLogicConditionNode();
                                        f.serial( *node );
                                        _Nodes.push_back( node );
                                }
                        }
                        else
                        {
                                uint32 sz = _Nodes.size();
                                f.serial( sz );
                                vector<CLogicConditionNode *>::iterator itNode;
                                for( itNode = _Nodes.begin(); itNode != _Nodes.end(); ++itNode )
                                {
                                        f.serial( **itNode );
                                }
                        }
                }
                break;
        };

        f.xmlPop();

} // serial //*/

void CLogicConditionNode::write (xmlNodePtr node) const
{
        xmlNodePtr elmPtr = xmlNewChild ( node, NULL, (const xmlChar*)"CONDITION_NODE", NULL);
        xmlSetProp (elmPtr, (const xmlChar*)"Type", (const xmlChar*)toString(Type).c_str());

        switch( Type )
        {
                case TERMINATOR : break;
                case LOGIC_NODE :
                {
                        LogicBlock.write(elmPtr);
                        vector<CLogicConditionNode *>::const_iterator itNode = _Nodes.begin();
                        for( ; itNode != _Nodes.end(); ++itNode )
                        {
                                (*itNode)->write(elmPtr);
                        }
                }
                break;
        };
}

void CLogicConditionNode::read (xmlNodePtr node)
{
        xmlCheckNodeName (node, "CONDITION_NODE");

        Type = (TConditionNodeType )atoi(getXMLProp (node, "Type").c_str());
        switch( Type )
        {
                case TERMINATOR : break;
                case LOGIC_NODE :
                {
                        LogicBlock.read (node);

                        {
                                // Count the parent
                                uint nb = CIXml::countChildren (node, "CONDITION_NODE");
                                uint i = 0;
                                xmlNodePtr parent = CIXml::getFirstChildNode (node, "CONDITION_NODE");
                                while (i<nb)
                                {
                                        CLogicConditionNode *v = new CLogicConditionNode();
                                        v->read(parent);
                                        _Nodes.push_back (v);

                                        // Next parent
                                        parent = CIXml::getNextChildNode (parent, "CONDITION_NODE");
                                        i++;
                                }
                        }
                }
                break;
        };
}

//-------------------------------------------------
// ~CLogicConditionNode :
//
//-------------------------------------------------
CLogicConditionNode::~CLogicConditionNode()
{
        vector<CLogicConditionNode *>::iterator itNodes;
        for( itNodes = _Nodes.begin(); itNodes != _Nodes.end(); ++itNodes )
        {
                delete (*itNodes);
        }

} // ~CLogicConditionNode //







//-------------------------------------------------
// setLogicStateMachine :
//
//-------------------------------------------------
void CLogicCondition::setLogicStateMachine( CLogicStateMachine * logicStateMachine )
{ 
        if( logicStateMachine == 0 )
        {
                nlwarning("(LOGIC)<CLogicCondition::setLogicStateMachine> The state machine is null");
        }
        else
        {
                // init the logic state machine for each node
                vector<CLogicConditionNode>::iterator itNodes;
                for( itNodes = Nodes.begin(); itNodes != Nodes.end(); ++itNodes )
                {
                        (*itNodes).setLogicStateMachine( logicStateMachine );
                }
        }

} // setLogicStateMachine //


//-------------------------------------------------
// testLogic :
//
//-------------------------------------------------
bool CLogicCondition::testLogic()
{
        vector<CLogicConditionNode>::iterator itNodes;
        for( itNodes = Nodes.begin(); itNodes != Nodes.end(); ++itNodes )
        {
                if( (*itNodes).testLogic() == false )
                {
                        return false;
                }
        }

        return true;

} // testLogic //



//-------------------------------------------------
// fillVarSet :
//
//-------------------------------------------------
void CLogicCondition::fillVarSet( set<string>& condVars )
{
        vector<CLogicConditionNode>::iterator itNode;
        for( itNode = Nodes.begin(); itNode != Nodes.end(); ++itNode )
        {
                (*itNode).fillVarSet( condVars );
        }

} // fillVarSet //



//-------------------------------------------------
// serial :
//
//-------------------------------------------------
/*void CLogicCondition::serial( IStream &f )
{
        f.xmlPush("CONDITION");
        
        f.serial( _ConditionName );
        f.serialCont( Nodes );

        f.xmlPop();

} // serial //*/

void CLogicCondition::write (xmlNodePtr node) const
{
        xmlNodePtr elmPtr = xmlNewChild ( node, NULL, (const xmlChar*)"CONDITION", NULL);
        xmlSetProp (elmPtr, (const xmlChar*)"Name", (const xmlChar*)_ConditionName.c_str());

        uint i;
        for (i = 0; i < Nodes.size(); i++)
        {
                Nodes[i].write(elmPtr);
        }
}

void CLogicCondition::read (xmlNodePtr node)
{
        xmlCheckNodeName (node, "CONDITION");

        _ConditionName = getXMLProp (node, "Name");

        {
                // Count the parent
                uint nb = CIXml::countChildren (node, "CONDITION_NODE");
                uint i = 0;
                xmlNodePtr parent = CIXml::getFirstChildNode (node, "CONDITION_NODE");
                while (i<nb)
                {
                        CLogicConditionNode v;
                        v.read(parent);
                        Nodes.push_back (v);

                        // Next parent
                        parent = CIXml::getNextChildNode (parent, "CONDITION_NODE");
                        i++;
                }
        }
}


} // NLLOGIC