Merge pull request #84 from AngelaMarchi/ChangingRuleBased
Changing rule based
This commit is contained in:
@@ -79,6 +79,7 @@ Global Const EN_LINKCOUNT = 2
|
||||
Global Const EN_PATCOUNT = 3
|
||||
Global Const EN_CURVECOUNT = 4
|
||||
Global Const EN_CONTROLCOUNT = 5
|
||||
Global Const EN_RULECOUNT = 6
|
||||
|
||||
Global Const EN_JUNCTION = 0 ' Node types
|
||||
Global Const EN_RESERVOIR = 1
|
||||
@@ -232,3 +233,16 @@ Global Const EN_CUSTOM = 2 ' user-defined custom curve
|
||||
Declare Function ENsetcurvevalue Lib "epanet2.dll" (ByVal Index As Long, ByVal Ptn As Long, ByVal X As Single, ByVal Y As Single) As Long
|
||||
Declare Function ENsetcurve Lib "epanet2.dll" (ByVal Index As Long, X As Any, Y As Any, ByVal N As Long) As Long
|
||||
Declare Function ENaddcurve Lib "epanet2.dll" (ByVal ID As String) As Long
|
||||
|
||||
Declare Function ENgetrule Lib "epanet2.dll" (ByVal index As Long, nPremises As Long, nTrueActions As Long, nFalseActions As Long, priority As Double) As Long
|
||||
Declare Function ENsetrulepriority Lib "epanet2.dll" (ByVal index As Long, ByVal priority As Double) As Long
|
||||
Declare Function ENgetpremise Lib "epanet2.dll" (ByVal indexRule As Long, ByVal indexPremise As Long, logop As Long, object As Long, indexObj As Long, variable As Long, relop As Long, status As Long, value As Double) As Long
|
||||
Declare Function ENsetpremise Lib "epanet2.dll" (ByVal indexRule As Long, ByVal indexPremise As Long, ByVal logop As Long, ByVal object As Long, ByVal indexObj As Long, ByVal variable As Long, ByVal relop As Long, ByVal status As Long, ByVal value As Double) As Long
|
||||
Declare Function ENsetpremiseindex Lib "epanet2.dll" (ByVal indexRule As Long, ByVal indexPremise As Long, ByVal indexObj As Long) As Long
|
||||
Declare Function ENsetpremisestatus Lib "epanet2.dll" (ByVal indexRule As Long, ByVal indexPremise As Long, ByVal status As Long) As Long
|
||||
Declare Function ENsetpremisevalue Lib "epanet2.dll" (ByVal indexRule As Long, ByVal indexPremise As Long, ByVal value As Double) As Long
|
||||
Declare Function ENgettrueaction Lib "epanet2.dll" (ByVal indexRule As Long, ByVal indexAction As Long, indexLink As Long, status As Long, setting As Double) As Long
|
||||
Declare Function ENsettrueaction Lib "epanet2.dll" (ByVal indexRule As Long, ByVal indexAction As Long, ByVal indexLink As Long, ByVal status As Long, ByVal setting As Double) As Long
|
||||
Decalre FUnction ENgetfalseaction Lib "epanet2.dll" (ByVal indexRule As Long, ByVal indexAction As Long, indexLink As Long, status As Long, setting As Double) As Long
|
||||
Declare Function ENsetfalseaction Lib "epanet2.dll" (ByVal indexRule As Long, ByVal indexAction As Long, ByVal indexLink As Long, ByVal status As Long, ByVal setting As Double) As Long
|
||||
Declare Function ENgetruleID Lib "epanet2.dll" (ByVal indexRule As Long, ByVal id As String) As Long
|
||||
|
||||
@@ -145,7 +145,8 @@ typedef enum {
|
||||
EN_LINKCOUNT = 2, /**< Number of Links (Pipes + Pumps + Valves) */
|
||||
EN_PATCOUNT = 3, /**< Number of Time Patterns */
|
||||
EN_CURVECOUNT = 4, /**< Number of Curves */
|
||||
EN_CONTROLCOUNT = 5 /**< Number of Control Statements */
|
||||
EN_CONTROLCOUNT = 5, /**< Number of Control Statements */
|
||||
EN_RULECOUNT = 6 /**< Number of Rule-based Control Statements */
|
||||
} EN_CountType;
|
||||
|
||||
typedef enum {
|
||||
@@ -904,6 +905,136 @@ extern "C" {
|
||||
*/
|
||||
int DLLEXPORT ENaddcurve(char *id);
|
||||
|
||||
|
||||
/**
|
||||
@brief Gets the number of premises, true actions, and false actions and the priority of an existing rule-based control.
|
||||
@param index The index of a rule-based control.
|
||||
@param nPremises The number of conditions in a rule-based control.
|
||||
@param nTrueActions The number of actions that are executed when the conditions in the rule-based control are met.
|
||||
@param nFalseActions The number of actions that are executed when the conditions in the rule-based control are not met.
|
||||
@param priority The priority of a rule-based control.
|
||||
@return Error code.
|
||||
*/
|
||||
int DLLEXPORT ENgetrule(int index, int *nPremises, int *nTrueActions, int *nFalseActions, double *priority);
|
||||
|
||||
/**
|
||||
@brief Sets the priority of the existing rule-based control.
|
||||
@param index The index of a rule-based control.
|
||||
@param priority The priority to be set in the rule-based control.
|
||||
@return Error code.
|
||||
*/
|
||||
int DLLEXPORT ENsetrulepriority(int index, double priority);
|
||||
|
||||
/**
|
||||
@brief Gets the components of a premise/condition in an existing rule-based control.
|
||||
@param indexRule The index of a rule-based control.
|
||||
@param indexPremise The index of the premise.
|
||||
@param logop The logiv operator (IF/AND/OR) in the premise
|
||||
@param object The object (e.g. TANK) the premise is looking at.
|
||||
@param indexObj The index of the object (e.g. the index of the tank).
|
||||
@param variable The variable to be checked (e.g. level).
|
||||
@param relop The relashionship operator (e.g. LARGER THAN) in the premise.
|
||||
@param status The status of the object to be checked (e.g. CLOSED)
|
||||
@param value The value of the variable to be checked (e.g. 5.5)
|
||||
@return Error code.
|
||||
*/
|
||||
int DLLEXPORT ENgetpremise(int indexRule, int indexPremise, int *logop, int *object, int *indexObj, int *variable, int *relop, int *status, double *value);
|
||||
|
||||
/**
|
||||
@brief Sets the components of a premise/condition in an existing rule-based control.
|
||||
@param indexRule The index of a rule-based control.
|
||||
@param indexPremise The index of the premise.
|
||||
@param logop The logiv operator (IF/AND/OR) in the premise
|
||||
@param object The object (e.g. TANK) the premise is looking at.
|
||||
@param indexObj The index of the object (e.g. the index of the tank).
|
||||
@param variable The variable to be checked (e.g. level).
|
||||
@param relop The relashionship operator (e.g. LARGER THAN) in the premise.
|
||||
@param status The status of the object to be checked (e.g. CLOSED)
|
||||
@param value The value of the variable to be checked (e.g. 5.5)
|
||||
@return Error code.
|
||||
*/
|
||||
int DLLEXPORT ENsetpremise(int indexRule, int indexPremise, int logop, int object, int indexObj, int variable, int relop, int status, double value);
|
||||
|
||||
/**
|
||||
@brief Sets the index of an object in a premise of an existing rule-based control.
|
||||
@param indexRule The index of a rule-based control.
|
||||
@param indexPremise The index of the premise.
|
||||
@param indexObj The index of the object (e.g. the index of the tank).
|
||||
@return Error code.
|
||||
*/
|
||||
int DLLEXPORT ENsetpremiseindex(int indexRule, int indexPremise, int indexObj);
|
||||
|
||||
/**
|
||||
@brief Sets the status in a premise of an existing rule-based control.
|
||||
@param indexRule The index of a rule-based control.
|
||||
@param indexPremise The index of the premise.
|
||||
@param status The status of the object to be checked (e.g. CLOSED)
|
||||
@return Error code.
|
||||
*/
|
||||
int DLLEXPORT ENsetpremisestatus(int indexRule, int indexPremise, int status);
|
||||
|
||||
/**
|
||||
@brief Sets the value in a premise of an existing rule-based control.
|
||||
@param indexRule The index of a rule-based control.
|
||||
@param indexPremise The index of the premise.
|
||||
@param value The value of the variable to be checked (e.g. 5.5)
|
||||
@return Error code.
|
||||
*/
|
||||
int DLLEXPORT ENsetpremisevalue(int indexRule, int indexPremise, double value);
|
||||
|
||||
/**
|
||||
@brief Gets the components of a true-action in an existing rule-based control.
|
||||
@param indexRule The index of a rule-based control.
|
||||
@param indexAction The index of the action when the conditions in the rule are met.
|
||||
@param indexLink The index of the link in the action (e.g. index of Pump 1)
|
||||
@param status The status of the link (e.g. CLOSED)
|
||||
@param setting The value of the link (e.g. pump speed 0.9)
|
||||
@return Error code.
|
||||
*/
|
||||
int DLLEXPORT ENgettrueaction(int indexRule, int indexAction, int *indexLink, int *status, double *setting);
|
||||
|
||||
/**
|
||||
@brief Sets the components of a true-action in an existing rule-based control.
|
||||
@param indexRule The index of a rule-based control.
|
||||
@param indexAction The index of the action when the conditions in the rule are met.
|
||||
@param indexLink The index of the link in the action (e.g. index of Pump 1)
|
||||
@param status The status of the link (e.g. CLOSED)
|
||||
@param setting The value of the link (e.g. pump speed 0.9)
|
||||
@return Error code.
|
||||
*/
|
||||
int DLLEXPORT ENsettrueaction(int indexRule, int indexAction, int indexLink, int status, double setting);
|
||||
|
||||
/**
|
||||
@brief Gets the components of a false-action in an existing rule-based control.
|
||||
@param indexRule The index of a rule-based control.
|
||||
@param indexAction The index of the action when the conditions in the rule are not met.
|
||||
@param indexLink The index of the link in the action (e.g. index of Pump 1)
|
||||
@param status The status of the link (e.g. CLOSED)
|
||||
@param setting The value of the link (e.g. pump speed 0.9)
|
||||
@return Error code.
|
||||
*/
|
||||
int DLLEXPORT ENgetfalseaction(int indexRule, int indexAction, int *indexLink, int *status, double *setting);
|
||||
|
||||
/**
|
||||
@brief Sets the components of a false-action in an existing rule-based control.
|
||||
@param indexRule The index of a rule-based control.
|
||||
@param indexAction The index of the action when the conditions in the rule are not met.
|
||||
@param indexLink The index of the link in the action (e.g. index of Pump 1)
|
||||
@param status The status of the link (e.g. CLOSED)
|
||||
@param setting The value of the link (e.g. pump speed 0.9)
|
||||
@return Error code.
|
||||
*/
|
||||
int DLLEXPORT ENsetfalseaction(int indexRule, int indexAction, int indexLink, int status,double setting);
|
||||
|
||||
/**
|
||||
@brief Returns the ID of a rule.
|
||||
@param indexRule The index of a rule-based control.
|
||||
@param id The ID of the rule
|
||||
@return Error code.
|
||||
*/
|
||||
int DLLEXPORT ENgetruleID(int indexRule, char* id);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -76,6 +76,7 @@ Public Const EN_LINKCOUNT = 2
|
||||
Public Const EN_PATCOUNT = 3
|
||||
Public Const EN_CURVECOUNT = 4
|
||||
Public Const EN_CONTROLCOUNT = 5
|
||||
Public Const EN_RULECOUNT = 6
|
||||
|
||||
Public Const EN_JUNCTION = 0 ' Node types
|
||||
Public Const EN_RESERVOIR = 1
|
||||
@@ -226,4 +227,21 @@ Public Const EN_CUSTOM = 2 ' user-defined custom curve
|
||||
Declare Function ENsetcurve Lib "epanet2.dll" (ByVal Index as Int32, ByRef X as Single, ByRef Y as Single, ByVal N as Int32) as Int32
|
||||
Declare Function ENaddcurve Lib "epanet2.dll" (ByVal ID As String) As Int32
|
||||
|
||||
Declare Function ENaddcurve Lib "epanet2.dll" (ByVal ID As String) As Long
|
||||
|
||||
Declare Function ENgetrule Lib "epanet2.dll" (ByVal index As Int32, ByRef nPremises As Int32, ByRef nTrueActions As Int32, ByRef nFalseActions As Int32, ByRef priority As Double) As Int32
|
||||
Declare Function ENsetrulepriority Lib "epanet2.dll" (ByVal index As Int32, ByVal priority As Double) As Int32
|
||||
Declare Function ENgetpremise Lib "epanet2.dll" (ByVal indexRule As Int32, ByVal indexPremise As Int32, ByRef logop As Int32, ByRef object As Int32, ByRef indexObj As Int32, ByRef variable As Int32, ByRef relop As Int32, ByRef status As Int32, ByRef value As Double) As Int32
|
||||
Declare Function ENsetpremise Lib "epanet2.dll" (ByVal indexRule As Int32, ByVal indexPremise As Int32, ByVal logop As Int32, ByVal object As Int32, ByVal indexObj As Int32, ByVal variable As Int32, ByVal relop As Int32, ByVal status As Int32, ByVal value As Double) As Int32
|
||||
Declare Function ENsetpremiseindex Lib "epanet2.dll" (ByVal indexRule As Int32, ByVal indexPremise As Int32, ByVal indexObj As Int32) As Int32
|
||||
Declare Function ENsetpremisestatus Lib "epanet2.dll" (ByVal indexRule As Int32, ByVal indexPremise As Int32, ByVal status As Int32) As Int32
|
||||
Declare Function ENsetpremisevalue Lib "epanet2.dll" (ByVal indexRule As Int32, ByVal indexPremise As Int32, ByVal value As Double) As Int32
|
||||
Declare Function ENgettrueaction Lib "epanet2.dll" (ByVal indexRule As Int32, ByVal indexAction As Int32, ByRef indexLink As Int32, ByRef status As Int32, ByRef setting As Double) As Int32
|
||||
Declare Function ENsettrueaction Lib "epanet2.dll" (ByVal indexRule As Int32, ByVal indexAction As Int32, ByVal indexLink As Int32, ByVal status As Int32, ByVal setting As Double) As Int32
|
||||
Decalre FUnction ENgetfalseaction Lib "epanet2.dll" (ByVal indexRule As Int32, ByVal indexAction As Int32, ByRef indexLink As Int32, ByRef status As Int32, ByRef setting As Double) As Int32
|
||||
Declare Function ENsetfalseaction Lib "epanet2.dll" (ByVal indexRule As Int32, ByVal indexAction As Int32, ByVal indexLink As Int32, ByVal status As Int32, ByVal setting As Double) As Int32
|
||||
Declare Function ENgetruleID Lib "epanet2.dll" (ByVal indexRule As Int32, ByVal id As StringBuilder) As Int32
|
||||
|
||||
|
||||
|
||||
End Module
|
||||
|
||||
291
src/epanet.c
291
src/epanet.c
@@ -815,6 +815,7 @@ int DLLEXPORT ENgetcount(int code, int *count)
|
||||
case EN_PATCOUNT: *count = Npats; break;
|
||||
case EN_CURVECOUNT: *count = Ncurves; break;
|
||||
case EN_CONTROLCOUNT: *count = Ncontrols; break;
|
||||
case EN_RULECOUNT: *count = Nrules; break;
|
||||
default: return(251);
|
||||
}
|
||||
return(0);
|
||||
@@ -3167,5 +3168,295 @@ int DLLEXPORT ENgetaveragepatternvalue(int index, EN_API_FLOAT_TYPE *value)
|
||||
}
|
||||
|
||||
|
||||
|
||||
int DLLEXPORT ENgetrule(int index, int *nPremises, int *nTrueActions, int *nFalseActions, double *priority)
|
||||
{
|
||||
/*----------------------------------------------------------------
|
||||
** Input: index = index of the rule
|
||||
** nPremises = number of conditions (IF AND OR)
|
||||
** nTrueActions = number of actions with true conditions (THEN)
|
||||
** nFalseActions = number of actions with false conditions (ELSE)
|
||||
** priority = rule priority
|
||||
** Output: none
|
||||
** Returns: error code
|
||||
**----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int count;
|
||||
struct Premise *p;
|
||||
struct Action *c;
|
||||
|
||||
if (index > Nrules) return(257);
|
||||
*priority = Rule[index].priority;
|
||||
count = 1;
|
||||
p = Rule[index].Pchain;
|
||||
while (p->next != NULL)
|
||||
{
|
||||
count++;
|
||||
p=p->next;
|
||||
}
|
||||
*nPremises = count;
|
||||
count = 1;
|
||||
c=Rule[index].Tchain;
|
||||
while (c->next != NULL)
|
||||
{
|
||||
count++;
|
||||
c = c->next;
|
||||
}
|
||||
*nTrueActions = count;
|
||||
|
||||
c = Rule[index].Fchain;
|
||||
count = 0;
|
||||
if (c != NULL)
|
||||
{
|
||||
count = 1;
|
||||
while (c->next != NULL)
|
||||
{
|
||||
count ++;
|
||||
c = c->next;
|
||||
}
|
||||
}
|
||||
*nFalseActions = count;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int DLLEXPORT ENgetpremise(int indexRule, int idxPremise, int *logop, int *object, int *indexObj, int *variable, int *relop, int *status, double *value)
|
||||
{
|
||||
int count = 1, error = 0, nPremises, a, b;
|
||||
double priority;
|
||||
struct Premise *p;
|
||||
|
||||
if (indexRule > Nrules) return(257);
|
||||
error = ENgetrule(indexRule, &nPremises, &a, &b, &priority);
|
||||
if (idxPremise > nPremises) return(258);
|
||||
|
||||
p = Rule[indexRule].Pchain;
|
||||
while (count < idxPremise)
|
||||
{
|
||||
count++;
|
||||
p = p->next;
|
||||
}
|
||||
*logop = p->logop;
|
||||
*object = p->object;
|
||||
*indexObj = p->index;
|
||||
*variable = p->variable;
|
||||
*relop = p->relop;
|
||||
*status = p->status;
|
||||
*value = p[0].value;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int DLLEXPORT ENsetrulepriority(int index, double priority)
|
||||
{
|
||||
/*----------------------------------------------------------------
|
||||
** Input: index = index of the rule
|
||||
** priority = rule priority
|
||||
** Output: none
|
||||
** Returns: error code
|
||||
**----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
if (index > Nrules) return(257);
|
||||
Rule[index].priority = priority;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int DLLEXPORT ENsetpremise(int indexRule, int indexPremise, int logop, int object, int indexObj, int variable, int relop, int status, double value)
|
||||
{
|
||||
int count = 1,error = 0, nPremises, a, b;
|
||||
double priority;
|
||||
struct Premise *p;
|
||||
|
||||
if (indexRule > Nrules) return(257);
|
||||
error = ENgetrule(indexRule, &nPremises, &a, &b, &priority);
|
||||
if (indexPremise > nPremises) return(258);
|
||||
|
||||
p = Rule[indexRule].Pchain;
|
||||
while (count < indexPremise)
|
||||
{
|
||||
count++;
|
||||
p = p->next;
|
||||
}
|
||||
p->logop = logop;
|
||||
p->object = object;
|
||||
p->index = indexObj;
|
||||
p->variable = variable;
|
||||
p->relop = relop;
|
||||
p->status = status;
|
||||
p->value = value;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int DLLEXPORT ENsetpremiseindex(int indexRule, int indexPremise, int indexObj)
|
||||
{
|
||||
int count = 1,error = 0, nPremises, a, b;
|
||||
double priority;
|
||||
struct Premise *p;
|
||||
|
||||
if (indexRule > Nrules) return(257);
|
||||
error = ENgetrule(indexRule, &nPremises, &a, &b, &priority);
|
||||
if (indexPremise > nPremises) return(258);
|
||||
|
||||
p = Rule[indexRule].Pchain;
|
||||
while (count < indexPremise)
|
||||
{
|
||||
count++;
|
||||
p = p->next;
|
||||
}
|
||||
p->index = indexObj;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int DLLEXPORT ENsetpremisestatus(int indexRule, int indexPremise, int status)
|
||||
{
|
||||
int count = 1, error = 0, nPremises, a, b;
|
||||
double priority;
|
||||
struct Premise *p;
|
||||
|
||||
if (indexRule > Nrules) return(257);
|
||||
error = ENgetrule(indexRule, &nPremises, &a, &b, &priority);
|
||||
if (indexPremise > nPremises) return(258);
|
||||
|
||||
p = Rule[indexRule].Pchain;
|
||||
while (count < indexPremise)
|
||||
{
|
||||
count++;
|
||||
p = p->next;
|
||||
}
|
||||
p->status = status;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int DLLEXPORT ENsetpremisevalue(int indexRule, int indexPremise, double value)
|
||||
{
|
||||
int count = 1,error = 0, nPremises, a, b;
|
||||
double priority;
|
||||
struct Premise *p;
|
||||
|
||||
if (indexRule > Nrules) return(257);
|
||||
error = ENgetrule(indexRule, &nPremises, &a, &b, &priority);
|
||||
if (indexPremise > nPremises) return(258);
|
||||
|
||||
p = Rule[indexRule].Pchain;
|
||||
while (count < indexPremise)
|
||||
{
|
||||
count++;
|
||||
p = p->next;
|
||||
}
|
||||
p->value = value;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int DLLEXPORT ENgettrueaction(int indexRule, int indexAction, int *indexLink, int *status, double *setting)
|
||||
{
|
||||
int count = 1, error = 0, nTrueAction, c, b;
|
||||
double priority;
|
||||
struct Action *a;
|
||||
|
||||
if (indexRule > Nrules) return(252);
|
||||
error = ENgetrule(indexRule, &c, &nTrueAction, &b, &priority);
|
||||
if (indexAction > nTrueAction) return(253);
|
||||
|
||||
a = Rule[indexRule].Tchain;
|
||||
while (count<indexAction)
|
||||
{
|
||||
count++;
|
||||
a = a->next;
|
||||
}
|
||||
*indexLink = a->link;
|
||||
*status = a->status;
|
||||
*setting = a->setting;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int DLLEXPORT ENsettrueaction(int indexRule, int indexAction, int indexLink, int status,double setting)
|
||||
{
|
||||
int count = 1, error = 0, nTrueAction, c, b;
|
||||
double priority;
|
||||
struct Action *a;
|
||||
|
||||
if (indexRule > Nrules) return(257);
|
||||
error = ENgetrule(indexRule, &c, &nTrueAction, &b, &priority);
|
||||
if (indexAction > nTrueAction) return(258);
|
||||
|
||||
a = Rule[indexRule].Tchain;
|
||||
while (count<indexAction)
|
||||
{
|
||||
count++;
|
||||
a = a->next;
|
||||
}
|
||||
a->link = indexLink;
|
||||
a->status = status;
|
||||
a->setting = setting;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int DLLEXPORT ENgetfalseaction(int indexRule, int indexAction, int *indexLink, int *status, double *setting)
|
||||
{
|
||||
int count = 1, error = 0, nFalseAction, c, b;
|
||||
double priority;
|
||||
struct Action *a;
|
||||
|
||||
if (indexRule > Nrules) return(257);
|
||||
error = ENgetrule(indexRule, &c, &b, &nFalseAction, &priority);
|
||||
if (indexAction > nFalseAction) return(258);
|
||||
|
||||
a = Rule[indexRule].Fchain;
|
||||
while (count < indexAction)
|
||||
{
|
||||
count++;
|
||||
a = a->next;
|
||||
}
|
||||
*indexLink = a->link;
|
||||
*status = a->status;
|
||||
*setting = a->setting;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int DLLEXPORT ENsetfalseaction(int indexRule, int indexAction, int indexLink, int status,double setting)
|
||||
{
|
||||
int count = 1, error = 0, nFalseAction, c, b;
|
||||
double priority;
|
||||
struct Action *a;
|
||||
|
||||
if (indexRule > Nrules) return(257);
|
||||
error = ENgetrule(indexRule, &c, &b, &nFalseAction, &priority);
|
||||
if (indexAction > nFalseAction) return(258);
|
||||
|
||||
a = Rule[indexRule].Fchain;
|
||||
while (count < indexAction)
|
||||
{
|
||||
count++;
|
||||
a = a->next;
|
||||
}
|
||||
a->link = indexLink;
|
||||
a->status = status;
|
||||
a->setting = setting;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int DLLEXPORT ENgetruleID(int indexRule, char* id)
|
||||
{
|
||||
|
||||
strcpy(id,"");
|
||||
if (!Openflag) return(102);
|
||||
if (indexRule < 1 || indexRule > Nrules) return(257);
|
||||
strcpy(id,Rule[indexRule].label);
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
||||
/*************************** END OF EPANET.C ***************************/
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ void saveauxdata(FILE *f) /
|
||||
if (sect == _END) break;
|
||||
switch(sect)
|
||||
{
|
||||
case _RULES:
|
||||
//case _RULES:
|
||||
case _COORDS: if (Coordflag == FALSE)
|
||||
{
|
||||
fprintf(f, "%s", line);
|
||||
@@ -95,7 +95,7 @@ void saveauxdata(FILE *f) /
|
||||
/* Write lines appearing in the section to file */
|
||||
switch(sect)
|
||||
{
|
||||
case _RULES:
|
||||
//case _RULES:
|
||||
case _COORDS: if (Coordflag == FALSE)
|
||||
{
|
||||
fprintf(f, "%s", line);
|
||||
@@ -120,6 +120,7 @@ int saveinpfile(char *fname)
|
||||
*/
|
||||
{
|
||||
int i,j,n;
|
||||
int errcode;
|
||||
double d,kc,ke,km,ucf;
|
||||
char s[MAXLINE+1], s1[MAXLINE+1], s2[MAXLINE+1];
|
||||
Pdemand demand;
|
||||
@@ -623,6 +624,15 @@ int saveinpfile(char *fname)
|
||||
}
|
||||
fprintf(f, "\n\n");
|
||||
|
||||
fprintf(f, "\n\n[RULES]");
|
||||
for (i=1; i<=Nrules; i++)
|
||||
{
|
||||
fprintf(f, "\nRULE %s",Rule[i].label);
|
||||
errcode = writeRuleinInp(f, i);
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
fprintf(f, "\n\n");
|
||||
|
||||
/* Write [COORDINATES] section */
|
||||
|
||||
if (Coordflag == TRUE)
|
||||
|
||||
251
src/rules.c
251
src/rules.c
@@ -36,48 +36,6 @@ AUTHOR: L. Rossman
|
||||
#define EXTERN extern
|
||||
#include "vars.h"
|
||||
|
||||
struct Premise /* Rule Premise Clause */
|
||||
{
|
||||
int logop; /* Logical operator */
|
||||
int object; /* Node or link */
|
||||
int index; /* Object's index */
|
||||
int variable; /* Pressure, flow, etc. */
|
||||
int relop; /* Relational operator */
|
||||
int status; /* Variable's status */
|
||||
double value; /* Variable's value */
|
||||
struct Premise *next;
|
||||
};
|
||||
|
||||
struct Action /* Rule Action Clause */
|
||||
{
|
||||
int link; /* Link index */
|
||||
int status; /* Link's status */
|
||||
double setting; /* Link's setting */
|
||||
struct Action *next;
|
||||
};
|
||||
|
||||
struct aRule /* Control Rule Structure */
|
||||
{
|
||||
char label[MAXID+1]; /* Rule character label */
|
||||
double priority; /* Priority level */
|
||||
struct Premise *Pchain; /* Linked list of premises */
|
||||
struct Action *Tchain; /* Linked list of actions if true */
|
||||
struct Action *Fchain; /* Linked list of actions if false */
|
||||
struct aRule *next;
|
||||
};
|
||||
|
||||
struct ActItem /* Action list item */
|
||||
{
|
||||
int ruleindex; /* Index of rule action belongs to */
|
||||
struct Action *action; /* An action structure */
|
||||
struct ActItem *next;
|
||||
};
|
||||
|
||||
struct aRule *Rule; /* Array of rules */
|
||||
struct ActItem *ActList; /* Linked list of action items */
|
||||
int RuleState; /* State of rule interpreter */
|
||||
long Time1; /* Start of rule evaluation time interval (sec) */
|
||||
struct Premise *Plast; /* Previous premise clause */
|
||||
|
||||
enum Rulewords {r_RULE,r_IF,r_AND,r_OR,r_THEN,r_ELSE,r_PRIORITY,r_ERROR};
|
||||
char *Ruleword[] = {w_RULE,w_IF,w_AND,w_OR,w_THEN,w_ELSE,w_PRIORITY,NULL};
|
||||
@@ -105,6 +63,8 @@ char *Value[] = {"XXXX", w_OPEN, w_CLOSED, w_ACTIVE,NULL};
|
||||
extern char *Tok[MAXTOKS];
|
||||
extern int Ntokens;
|
||||
|
||||
extern char *StatTxt[];
|
||||
|
||||
/*
|
||||
** Local function prototypes are defined here and not in FUNCS.H
|
||||
** because some of them utilize the Premise and Action structures
|
||||
@@ -125,7 +85,7 @@ int takeactions(void);
|
||||
void clearactlist(void);
|
||||
void clearrules(void);
|
||||
void ruleerrmsg(int);
|
||||
|
||||
int writeRuleinInp(FILE *f, int RuleIdx);
|
||||
|
||||
void initrules()
|
||||
/*
|
||||
@@ -967,5 +927,210 @@ void ruleerrmsg(int err)
|
||||
writeline(fmt);
|
||||
}
|
||||
|
||||
|
||||
int writeRuleinInp(FILE *f, int RuleIdx){
|
||||
|
||||
//int i,j;
|
||||
struct Premise *p;
|
||||
struct Action *a;
|
||||
int hours = 0, minutes = 0, seconds = 0;
|
||||
|
||||
p = Rule[RuleIdx].Pchain;
|
||||
if (p->value==MISSING)
|
||||
{
|
||||
fprintf(f, "\nIF ");
|
||||
if ((strncmp(Object[p->object], "NODE", 4)==0) || (strncmp(Object[p->object], "Junc", 4)==0) || (strncmp(Object[p->object], "Reser", 5)==0) || (strncmp(Object[p->object], "Tank", 4)==0) )
|
||||
{
|
||||
if (p->index <= Njuncs) fprintf(f,"JUNC %s %s %s %s", Node[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
|
||||
else if (Tank[p->index-Njuncs].A == 0.0) fprintf(f,"RESERV %s %s %s %s", Node[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
|
||||
else fprintf(f,"TANK %s %s %s %s", Node[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
|
||||
}
|
||||
else
|
||||
{ //it is a link
|
||||
if (Link[p->index].Type == PIPE || Link[p->index].Type == CV) fprintf(f,"PIPE %s %s %s %s", Link[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
|
||||
else if (Link[p->index].Type == PUMP) fprintf(f,"PUMP %s %s %s %s", Link[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
|
||||
else fprintf(f,"VALVE %s %s %s %s", Link[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p->variable == r_TIME)
|
||||
{
|
||||
hours = (int) p->value / 3600;
|
||||
minutes = (int) ((p->value - 3600*hours)/60);
|
||||
seconds = (int) (p->value - 3600*hours - minutes*60);
|
||||
fprintf(f, "\nIF %s %s %s %d:%02d:%02d", Object[p->object], Varword[p->variable], Operator[p->relop], hours, minutes, seconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p->variable == r_CLOCKTIME)
|
||||
{
|
||||
hours = (int) p->value / 3600;
|
||||
minutes = (int) ((p->value - 3600*hours)/60);
|
||||
seconds = (int) (p->value - 3600*hours - minutes*60);
|
||||
|
||||
if (hours < 12) fprintf(f, "\nIF %s %s %s %d:%02d:%02d AM", Object[p->object], Varword[p->variable], Operator[p->relop], hours, minutes, seconds);
|
||||
else fprintf(f, "\nIF %s %s %s %d:%02d:%02d PM", Object[p->object], Varword[p->variable], Operator[p->relop], hours-12, minutes, seconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p->variable == r_FILLTIME || p->variable == r_DRAINTIME) fprintf(f, "\nIF %s %s %s %s %.4lf", Object[p->object], Node[p->index].ID, Varword[p->variable], Operator[p->relop], p->value/3600.0);
|
||||
else
|
||||
{
|
||||
fprintf(f, "\nIF ");
|
||||
if ((strncmp(Object[p->object], "NODE", 4)==0) || (strncmp(Object[p->object], "Junc", 4)==0) || (strncmp(Object[p->object], "Reser", 5)==0) || (strncmp(Object[p->object], "Tank", 4)==0))
|
||||
{
|
||||
if (p->index <= Njuncs) fprintf(f,"JUNC %s %s %s %.4lf", Node[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
|
||||
else if (Tank[p->index-Njuncs].A == 0.0) fprintf(f,"RESERV %s %s %s %.4lf", Node[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
|
||||
else fprintf(f,"TANK %s %s %s %.4lf", Node[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
|
||||
}
|
||||
else
|
||||
{ //it is a link
|
||||
if (Link[p->index].Type == PIPE || Link[p->index].Type == CV) fprintf(f,"PIPE %s %s %s %.4lf", Link[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
|
||||
else if (Link[p->index].Type == PUMP) fprintf(f,"PUMP %s %s %s %.4lf", Link[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
|
||||
else fprintf(f,"VALVE %s %s %s %.4lf", Link[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p = p->next;
|
||||
while (p != NULL)
|
||||
{
|
||||
if (p->value==MISSING)
|
||||
{
|
||||
fprintf(f, "\n%s ", Ruleword[p->logop]);
|
||||
if ((strncmp(Object[p->object], "NODE", 4)==0) || (strncmp(Object[p->object], "Junc", 4)==0) || (strncmp(Object[p->object], "Reser", 5)==0) || (strncmp(Object[p->object], "Tank", 4)==0))
|
||||
{
|
||||
if (p->index <= Njuncs) fprintf(f,"JUNC %s %s %s %s", Node[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
|
||||
else if (Tank[p->index-Njuncs].A == 0.0) fprintf(f,"RESERV %s %s %s %s", Node[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
|
||||
else fprintf(f,"TANK %s %s %s %s", Node[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
|
||||
}
|
||||
else
|
||||
{ //it is a link
|
||||
if (Link[p->index].Type == PIPE || Link[p->index].Type == CV) fprintf(f,"PIPE %s %s %s %s", Link[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
|
||||
else if (Link[p->index].Type == PUMP) fprintf(f,"PUMP %s %s %s %s", Link[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
|
||||
else fprintf(f,"VALVE %s %s %s %s", Link[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p->variable == r_TIME)
|
||||
{
|
||||
hours = (int) p->value / 3600;
|
||||
minutes = (int) ((p->value - 3600*hours)/60);
|
||||
seconds = (int) (p->value - 3600*hours - minutes*60);
|
||||
fprintf(f, "\n%s %s %s %s %d:%02d:%02d", Ruleword[p->logop], Object[p->object], Varword[p->variable], Operator[p->relop], hours, minutes, seconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p->variable == r_CLOCKTIME)
|
||||
{
|
||||
hours = (int) p->value / 3600;
|
||||
minutes = (int) ((p->value - 3600*hours)/60);
|
||||
seconds = (int) (p->value - 3600*hours - minutes*60);
|
||||
|
||||
if (hours < 12) fprintf(f, "\n%s %s %s %s %d:%02d:%02d AM", Ruleword[p->logop], Object[p->object], Varword[p->variable], Operator[p->relop], hours, minutes, seconds);
|
||||
else fprintf(f, "\n%s %s %s %s %d:%02d:%02d PM", Ruleword[p->logop], Object[p->object], Varword[p->variable], Operator[p->relop], hours-12, minutes, seconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p->variable == r_FILLTIME || p->variable == r_DRAINTIME) fprintf(f, "\nIF %s %s %s %s %.4lf", Object[p->object], Node[p->index].ID, Varword[p->variable], Operator[p->relop], p->value/3600.0);
|
||||
else
|
||||
{
|
||||
fprintf(f, "\n%s ", Ruleword[p->logop]);
|
||||
if ((strncmp(Object[p->object], "NODE", 4)==0) || (strncmp(Object[p->object], "Junc", 4)==0) || (strncmp(Object[p->object], "Reser", 5)==0) || (strncmp(Object[p->object], "Tank", 4)==0)) {
|
||||
if (p->index <= Njuncs) fprintf(f,"JUNC %s %s %s %.4lf", Node[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
|
||||
else if (Tank[p->index-Njuncs].A == 0.0) fprintf(f,"RESERV %s %s %s %.4lf", Node[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
|
||||
else fprintf(f,"TANK %s %s %s %.4lf", Node[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
|
||||
}
|
||||
else
|
||||
{ //it is a link
|
||||
if (Link[p->index].Type == PIPE || Link[p->index].Type == CV) fprintf(f,"PIPE %s %s %s %.4lf", Link[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
|
||||
else if (Link[p->index].Type == PUMP) fprintf(f,"PUMP %s %s %s %.4lf", Link[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
|
||||
else fprintf(f,"VALVE %s %s %s %.4lf", Link[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
a = Rule[RuleIdx].Tchain;
|
||||
if (a->setting==MISSING)
|
||||
{
|
||||
if (Link[a->link].Type == PIPE || Link[a->link].Type == CV) fprintf(f, "\nTHEN PIPE %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
|
||||
else if (Link[a->link].Type == PUMP) fprintf(f, "\nTHEN PUMP %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
|
||||
else fprintf(f, "\nTHEN VALVE %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Link[a->link].Type == PIPE || Link[a->link].Type == CV) fprintf(f, "\nTHEN PIPE %s SETTING IS %.4f", Link[a->link].ID, a->setting);
|
||||
else if (Link[a->link].Type == PUMP) fprintf(f, "\nTHEN PUMP %s SETTING IS %.4f", Link[a->link].ID, a->setting);
|
||||
else fprintf(f, "\nTHEN VALVE %s SETTING IS %.4f", Link[a->link].ID, a->setting);
|
||||
}
|
||||
|
||||
a = a->next;
|
||||
while (a != NULL)
|
||||
{
|
||||
if (a->setting==MISSING)
|
||||
{
|
||||
if (Link[a->link].Type == PIPE || Link[a->link].Type == CV) fprintf(f, "\nAND PIPE %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
|
||||
else if (Link[a->link].Type == PUMP) fprintf(f, "\nAND PUMP %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
|
||||
else fprintf(f, "\nAND VALVE %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Link[a->link].Type == PIPE || Link[a->link].Type == CV) fprintf(f, "\nAND PIPE %s SETTING IS %.4f", Link[a->link].ID, a->setting);
|
||||
else if (Link[a->link].Type == PUMP) fprintf(f, "\nAND PUMP %s SETTING IS %.4f", Link[a->link].ID, a->setting);
|
||||
else fprintf(f, "\nAND VALVE %s SETTING IS %.4f", Link[a->link].ID, a->setting);
|
||||
}
|
||||
|
||||
a = a->next;
|
||||
}
|
||||
|
||||
|
||||
a = Rule[RuleIdx].Fchain;
|
||||
if (a != NULL)
|
||||
{
|
||||
if (a->setting==MISSING)
|
||||
{
|
||||
if (Link[a->link].Type == PIPE || Link[a->link].Type == CV) fprintf(f, "\nELSE PIPE %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
|
||||
else if (Link[a->link].Type == PUMP) fprintf(f, "\nELSE PUMP %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
|
||||
else fprintf(f, "\nELSE VALVE %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Link[a->link].Type == PIPE || Link[a->link].Type == CV) fprintf(f, "\nELSE PIPE %s SETTING IS %.4f", Link[a->link].ID, a->setting);
|
||||
else if (Link[a->link].Type == PUMP) fprintf(f, "\nELSE PUMP %s SETTING IS %.4f", Link[a->link].ID, a->setting);
|
||||
else fprintf(f, "\nELSE VALVE %s SETTING IS %.4f", Link[a->link].ID, a->setting);
|
||||
}
|
||||
|
||||
a = a->next;
|
||||
while (a != NULL)
|
||||
{
|
||||
if (a->setting==MISSING)
|
||||
{
|
||||
if (Link[a->link].Type == PIPE || Link[a->link].Type == CV) fprintf(f, "\nAND PIPE %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
|
||||
else if (Link[a->link].Type == PUMP) fprintf(f, "\nAND PUMP %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
|
||||
else fprintf(f, "\nAND VALVE %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Link[a->link].Type == PIPE || Link[a->link].Type == CV) fprintf(f, "\nAND PIPE %s SETTING IS %.4f", Link[a->link].ID, a->setting);
|
||||
else if (Link[a->link].Type == PUMP) fprintf(f, "\nAND PUMP %s SETTING IS %.4f", Link[a->link].ID, a->setting);
|
||||
else fprintf(f, "\nAND VALVE %s SETTING IS %.4f", Link[a->link].ID, a->setting);
|
||||
}
|
||||
|
||||
a = a->next;
|
||||
}
|
||||
}
|
||||
if (Rule[RuleIdx].priority != 0) fprintf(f, "\nPRIORITY %.4f", Rule[RuleIdx].priority);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/***************** END OF RULES.C ******************/
|
||||
|
||||
|
||||
@@ -497,6 +497,9 @@ AUTHOR: L. Rossman
|
||||
#define ERR254 "Input Error 254: Function call error - Node have no coordinates."
|
||||
#define ERR255 "Input Error 255: Function call error - Coordinates were not loaded."
|
||||
|
||||
#define ERR257 "Input Error 257: rule does not exist."
|
||||
#define ERR258 "Input Error 258: condition or action index specified in rule does not exist."
|
||||
|
||||
#define ERR301 "File Error 301: identical file names."
|
||||
#define ERR302 "File Error 302: cannot open input file."
|
||||
#define ERR303 "File Error 303: cannot open report file."
|
||||
|
||||
46
src/types.h
46
src/types.h
@@ -462,4 +462,50 @@ enum HdrType /* Type of table heading */
|
||||
NODEHDR, /* Node Results */
|
||||
LINKHDR}; /* Link Results */
|
||||
|
||||
|
||||
//AM 22Sept2016 moved from rules.c
|
||||
struct Premise /* Rule Premise Clause */
|
||||
{
|
||||
int logop; /* Logical operator */
|
||||
int object; /* Node or link */
|
||||
int index; /* Object's index */
|
||||
int variable; /* Pressure, flow, etc. */
|
||||
int relop; /* Relational operator */
|
||||
int status; /* Variable's status */
|
||||
double value; /* Variable's value */
|
||||
struct Premise *next;
|
||||
};
|
||||
|
||||
struct Action /* Rule Action Clause */
|
||||
{
|
||||
int link; /* Link index */
|
||||
int status; /* Link's status */
|
||||
double setting; /* Link's setting */
|
||||
struct Action *next;
|
||||
};
|
||||
|
||||
struct aRule /* Control Rule Structure */
|
||||
{
|
||||
char label[MAXID+1]; /* Rule character label */
|
||||
double priority; /* Priority level */
|
||||
struct Premise *Pchain; /* Linked list of premises */
|
||||
struct Action *Tchain; /* Linked list of actions if true */
|
||||
struct Action *Fchain; /* Linked list of actions if false */
|
||||
struct aRule *next;
|
||||
};
|
||||
|
||||
struct ActItem /* Action list item */
|
||||
{
|
||||
int ruleindex; /* Index of rule action belongs to */
|
||||
struct Action *action; /* An action structure */
|
||||
struct ActItem *next;
|
||||
};
|
||||
|
||||
struct aRule *Rule; /* Array of rules */
|
||||
struct ActItem *ActList; /* Linked list of action items */
|
||||
int RuleState; /* State of rule interpreter */
|
||||
long Time1; /* Start of rule evaluation time interval (sec) */
|
||||
struct Premise *Plast; /* Previous premise clause */
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user