ModifyingRuleBaseControls

These modifications allow rule based controls to be modified with the
additional functions added in the dll toolkit
This commit is contained in:
AngelaMarchi
2016-09-23 13:07:06 +09:30
parent 8b4a03d349
commit 6f8be1be55
6 changed files with 664 additions and 46 deletions

View File

@@ -144,7 +144,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 {
@@ -903,6 +904,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

View File

@@ -75,6 +75,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
@@ -224,5 +225,22 @@ Public Const EN_CUSTOM = 2 ' user-defined custom curve
Declare Function ENsetcurvevalue Lib "epanet2.dll" (ByVal Index As Int32, ByVal Pnt As Int32, ByVal X As Single, ByVal Y As Single) As Int32
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

View File

@@ -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);
@@ -3163,5 +3164,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 ***************************/

View File

@@ -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)

View File

@@ -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 ******************/

View File

@@ -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."