]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/models/flight_control/FGCondition.cpp
Sync. w. JSBSim CVS.
[flightgear.git] / src / FDM / JSBSim / models / flight_control / FGCondition.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGCondition.cpp
4  Author:       Jon S. Berndt
5  Date started: 1/2/2003
6
7  -------------- Copyright (C) 2003 Jon S. Berndt (jsb@hal-pc.org) --------------
8
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17  details.
18
19  You should have received a copy of the GNU General Public License along with
20  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21  Place - Suite 330, Boston, MA  02111-1307, USA.
22
23  Further information about the GNU General Public License can also be found on
24  the world wide web at http://www.gnu.org.
25
26 HISTORY
27 --------------------------------------------------------------------------------
28
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
30 COMMENTS, REFERENCES,  and NOTES
31 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
32
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34 INCLUDES
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
36
37 #include "FGCondition.h"
38
39 namespace JSBSim {
40
41 static const char *IdSrc = "$Id$";
42 static const char *IdHdr = ID_CONDITION;
43
44 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
45 CLASS IMPLEMENTATION
46 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
47
48 string FGCondition::indent = "        ";
49
50
51 FGCondition::FGCondition(Element* element, FGPropertyManager* PropertyManager) :
52   PropertyManager(PropertyManager), isGroup(true)
53 {
54   string property1, property2, logic;
55   Element* condition_element;
56
57   InitializeConditionals();
58
59   TestParam1  = TestParam2 = 0L;
60   TestValue   = 0.0;
61   Comparison  = ecUndef;
62   Logic       = elUndef;
63   conditions.clear();
64
65   logic = element->GetAttributeValue("logic");
66   if (logic == "OR") Logic = eOR;
67   else if (logic == "AND") Logic = eAND;
68   else { // error
69     cerr << "Unrecognized LOGIC token " << logic << " in switch component: " << logic << endl;
70   }
71   condition_element = element->GetElement();
72   while (condition_element) {
73     conditions.push_back(FGCondition(condition_element, PropertyManager));
74     condition_element = element->GetNextElement();
75   }
76   for (int i=0; i<element->GetNumDataLines(); i++) {
77     conditions.push_back(FGCondition(element->GetDataLine(i), PropertyManager));
78   }
79
80   Debug(0);
81 }
82
83 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84
85 FGCondition::FGCondition(string test, FGPropertyManager* PropertyManager) :
86   PropertyManager(PropertyManager), isGroup(false)
87 {
88   string property1, property2, compare_string;
89   Element* condition_element;
90
91   InitializeConditionals();
92
93   TestParam1  = TestParam2 = 0L;
94   TestValue   = 0.0;
95   Comparison  = ecUndef;
96   Logic       = elUndef;
97   conditions.clear();
98
99   int start = 0, end = 0;
100   start = test.find_first_not_of(" ");
101   end = test.find_first_of(" ", start+1);
102   property1 = test.substr(start,end-start);
103   start = test.find_first_not_of(" ",end);
104   end = test.find_first_of(" ",start+1);
105   conditional = test.substr(start,end-start);
106   start = test.find_first_not_of(" ",end);
107   end = test.find_first_of(" ",start+1);
108   property2 = test.substr(start,end-start);
109
110   TestParam1 = PropertyManager->GetNode(property1, true);
111   Comparison = mComparison[conditional];
112   if (property2.find_first_not_of("-.0123456789eE") == string::npos) {
113     TestValue = atof(property2.c_str());
114   } else {
115     TestParam2 = PropertyManager->GetNode(property2, true);
116   }
117 }
118
119 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120
121 void FGCondition::InitializeConditionals(void)
122 {
123   mComparison["EQ"] = eEQ;
124   mComparison["NE"] = eNE;
125   mComparison["GT"] = eGT;
126   mComparison["GE"] = eGE;
127   mComparison["LT"] = eLT;
128   mComparison["LE"] = eLE;
129   mComparison["eq"] = eEQ;
130   mComparison["ne"] = eNE;
131   mComparison["gt"] = eGT;
132   mComparison["ge"] = eGE;
133   mComparison["lt"] = eLT;
134   mComparison["le"] = eLE;
135   mComparison["=="] = eEQ;
136   mComparison["!="] = eNE;
137   mComparison[">"]  = eGT;
138   mComparison[">="] = eGE;
139   mComparison["<"]  = eLT;
140   mComparison["<="] = eLE;
141 }
142
143 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
144
145 FGCondition::~FGCondition(void)
146 {
147   Debug(1);
148 }
149
150 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
151
152 bool FGCondition::Evaluate(void )
153 {
154   vector <FGCondition>::iterator iConditions;
155   bool pass = false;
156   double compareValue;
157
158   if (Logic == eAND) {
159
160     iConditions = conditions.begin();
161     pass = true;
162     while (iConditions < conditions.end()) {
163       if (!iConditions->Evaluate()) pass = false;
164       *iConditions++;
165     }
166
167   } else if (Logic == eOR) {
168
169     pass = false;
170     while (iConditions < conditions.end()) {
171       if (iConditions->Evaluate()) pass = true;
172       *iConditions++;
173     }
174
175   } else {
176
177     if (TestParam2 != 0L) compareValue = TestParam2->getDoubleValue();
178     else compareValue = TestValue;
179
180     switch (Comparison) {
181     case ecUndef:
182       cerr << "Undefined comparison operator." << endl;
183       break;
184     case eEQ:
185       pass = TestParam1->getDoubleValue() == compareValue;
186       break;
187     case eNE:
188       pass = TestParam1->getDoubleValue() != compareValue;
189       break;
190     case eGT:
191       pass = TestParam1->getDoubleValue() > compareValue;
192       break;
193     case eGE:
194       pass = TestParam1->getDoubleValue() >= compareValue;
195       break;
196     case eLT:
197       pass = TestParam1->getDoubleValue() < compareValue;
198       break;
199     case eLE:
200       pass = TestParam1->getDoubleValue() <= compareValue;
201       break;
202     default:
203      cerr << "Unknown comparison operator." << endl;
204     }
205   }
206
207   return pass;
208 }
209
210 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
211
212 void FGCondition::PrintCondition(void )
213 {
214   vector <FGCondition>::iterator iConditions;
215   string scratch;
216
217   if (isGroup) {
218     switch(Logic) {
219     case (elUndef):
220       scratch = " UNSET";
221       cerr << "unset logic for test condition" << endl;
222       break;
223     case (eAND):
224       scratch = " if all of the following are true";
225       break;
226     case (eOR):
227       scratch = " if any of the following are true:";
228       break;
229     default:
230       scratch = " UNKNOWN";
231       cerr << "Unknown logic for test condition" << endl;
232     }
233
234     iConditions = conditions.begin();
235     cout << scratch << endl;
236     while (iConditions < conditions.end()) {
237       iConditions->PrintCondition();
238       *iConditions++;
239     }
240   } else {
241     if (TestParam2 != 0L)
242       cout << TestParam1->GetName() << " " << conditional << " " << TestParam2->GetName();
243     else
244       cout << TestParam1->GetName() << " " << conditional << " " << TestValue;
245   }
246 }
247
248 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
249 //    The bitmasked value choices are as follows:
250 //    unset: In this case (the default) JSBSim would only print
251 //       out the normally expected messages, essentially echoing
252 //       the config files as they are read. If the environment
253 //       variable is not set, debug_lvl is set to 1 internally
254 //    0: This requests JSBSim not to output any messages
255 //       whatsoever.
256 //    1: This value explicity requests the normal JSBSim
257 //       startup messages
258 //    2: This value asks for a message to be printed out when
259 //       a class is instantiated
260 //    4: When this value is set, a message is displayed when a
261 //       FGModel object executes its Run() method
262 //    8: When this value is set, various runtime state variables
263 //       are printed out periodically
264 //    16: When set various parameters are sanity checked and
265 //       a message is printed out when they go out of bounds
266
267 void FGCondition::Debug(int from)
268 {
269   if (debug_lvl <= 0) return;
270
271   if (debug_lvl & 1) { // Standard console startup message output
272     if (from == 0) { // Constructor
273
274     }
275   }
276   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
277     if (from == 0) cout << "Instantiated: FGCondition" << endl;
278     if (from == 1) cout << "Destroyed:    FGCondition" << endl;
279   }
280   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
281   }
282   if (debug_lvl & 8 ) { // Runtime state variables
283   }
284   if (debug_lvl & 16) { // Sanity checking
285   }
286   if (debug_lvl & 64) {
287     if (from == 0) { // Constructor
288       cout << IdSrc << endl;
289       cout << IdHdr << endl;
290     }
291   }
292 }
293
294 } //namespace JSBSim
295