Branch data Line data Source code
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 (jon@jsbsim.org) --------------
8 : :
9 : : This program is free software; you can redistribute it and/or modify it under
10 : : the terms of the GNU Lesser 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 Lesser General Public License for more
17 : : details.
18 : :
19 : : You should have received a copy of the GNU Lesser 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 Lesser 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 : : #include "input_output/FGXMLElement.h"
39 : : #include "input_output/FGPropertyManager.h"
40 : : #include <iostream>
41 : : #include <cstdlib>
42 : :
43 : : using namespace std;
44 : :
45 : : namespace JSBSim {
46 : :
47 : : static const char *IdSrc = "$Id: FGCondition.cpp,v 1.13 2010/07/14 05:50:40 ehofman Exp $";
48 : : static const char *IdHdr = ID_CONDITION;
49 : :
50 : : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
51 : : CLASS IMPLEMENTATION
52 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
53 : :
54 [ + + ][ + - ]: 6 : string FGCondition::indent = " ";
55 : :
56 : : // This constructor is called when tests are inside an element
57 : 9 : FGCondition::FGCondition(Element* element, FGPropertyManager* PropertyManager) :
58 : 9 : PropertyManager(PropertyManager), isGroup(true)
59 : : {
60 : 9 : string property1, property2, logic;
61 : : Element* condition_element;
62 : :
63 : 9 : InitializeConditionals();
64 : :
65 : 9 : TestParam1 = TestParam2 = 0L;
66 : 9 : TestValue = 0.0;
67 : 9 : Comparison = ecUndef;
68 : 9 : Logic = elUndef;
69 : 9 : conditions.clear();
70 : :
71 : 18 : logic = element->GetAttributeValue("logic");
72 [ + + # # ]: 9 : if (!logic.empty()) {
73 [ + - ][ # # ]: 1 : if (logic == "OR") Logic = eOR;
74 [ # # ][ # # ]: 0 : else if (logic == "AND") Logic = eAND;
75 : : else { // error
76 : 0 : cerr << "Unrecognized LOGIC token " << logic << endl;
77 : : }
78 : : } else {
79 : 8 : Logic = eAND; // default
80 : : }
81 : :
82 : 9 : condition_element = element->GetElement();
83 [ - + ][ # # ]: 9 : while (condition_element) {
84 : 0 : conditions.push_back(new FGCondition(condition_element, PropertyManager));
85 : 0 : condition_element = element->GetNextElement();
86 : : }
87 [ + + ][ # # ]: 18 : for (unsigned int i=0; i<element->GetNumDataLines(); i++) {
88 : 9 : string data = element->GetDataLine(i);
89 : 9 : conditions.push_back(new FGCondition(data, PropertyManager));
90 : : }
91 : :
92 : 9 : Debug(0);
93 : 9 : }
94 : :
95 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
96 : : // This constructor is called when there are no nested test groups inside the
97 : : // condition
98 : :
99 : 38 : FGCondition::FGCondition(const string& test, FGPropertyManager* PropertyManager) :
100 : 38 : PropertyManager(PropertyManager), isGroup(false)
101 : : {
102 : 38 : string property1, property2, compare_string;
103 : : vector <string> test_strings;
104 : :
105 : 38 : InitializeConditionals();
106 : :
107 : 38 : TestParam1 = TestParam2 = 0L;
108 : 38 : TestValue = 0.0;
109 : 38 : Comparison = ecUndef;
110 : 38 : Logic = elUndef;
111 : 38 : conditions.clear();
112 : :
113 : 38 : test_strings = split(test, ' ');
114 [ + - # # ]: 38 : if (test_strings.size() == 3) {
115 : : property1 = test_strings[0];
116 : 38 : conditional = test_strings[1];
117 : : property2 = test_strings[2];
118 : : } else {
119 : : cerr << endl << " Conditional test is invalid: \"" << test
120 : : << "\" has " << test_strings.size() << " elements in the "
121 : 0 : << "test condition." << endl;
122 : 0 : exit(-1);
123 : : }
124 : :
125 : 38 : TestParam1 = PropertyManager->GetNode(property1, false);
126 [ + + # # ]: 38 : if (!TestParam1) {
127 : : cerr << fgred << " In condition: " << test << ". Unknown property "
128 : : << property1 << " referenced." << endl
129 : 2 : << "Creating property. Check usage." << reset << endl;
130 : 1 : TestParam1 = PropertyManager->GetNode(property1, true);
131 : : }
132 : 38 : Comparison = mComparison[conditional];
133 [ - + # # ]: 38 : if (Comparison == ecUndef) {
134 : 0 : throw("Comparison operator: \""+conditional+"\" does not exist. Please check the conditional.");
135 : : }
136 [ + + ][ # # ]: 38 : if (is_number(property2)) {
137 : 36 : TestValue = atof(property2.c_str());
138 : : } else {
139 : 2 : TestParam2 = PropertyManager->GetNode(property2, false);
140 [ - + # # ]: 2 : if (!TestParam2) {
141 : : cerr << fgred << " In condition: " << test << ". Unknown property "
142 : : << property2 << " referenced." << endl
143 : 0 : << "Creating property. Check usage." << reset << endl;
144 : 0 : TestParam2 = PropertyManager->GetNode(property2, true);
145 : : }
146 : 38 : }
147 : 38 : }
148 : :
149 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
150 : :
151 : 47 : void FGCondition::InitializeConditionals(void)
152 : : {
153 : 47 : mComparison["EQ"] = eEQ;
154 : 47 : mComparison["NE"] = eNE;
155 : 47 : mComparison["GT"] = eGT;
156 : 47 : mComparison["GE"] = eGE;
157 : 47 : mComparison["LT"] = eLT;
158 : 47 : mComparison["LE"] = eLE;
159 : 47 : mComparison["eq"] = eEQ;
160 : 47 : mComparison["ne"] = eNE;
161 : 47 : mComparison["gt"] = eGT;
162 : 47 : mComparison["ge"] = eGE;
163 : 47 : mComparison["lt"] = eLT;
164 : 47 : mComparison["le"] = eLE;
165 : 47 : mComparison["=="] = eEQ;
166 : 47 : mComparison["!="] = eNE;
167 : 47 : mComparison[">"] = eGT;
168 : 47 : mComparison[">="] = eGE;
169 : 47 : mComparison["<"] = eLT;
170 : 47 : mComparison["<="] = eLE;
171 : 47 : }
172 : :
173 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
174 : :
175 : 47 : FGCondition::~FGCondition(void)
176 : : {
177 [ + - ][ + + ]: 56 : for (unsigned int i=0; i<conditions.size(); i++) delete conditions[i];
[ # # ][ # # ]
178 : :
179 : 47 : Debug(1);
180 : 47 : }
181 : :
182 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
183 : :
184 : 2166978 : bool FGCondition::Evaluate(void )
185 : : {
186 : 2166978 : bool pass = false;
187 : : double compareValue;
188 : :
189 [ + + ]: 2166978 : if (TestParam1 == 0L) {
190 : :
191 [ + + ]: 486027 : if (Logic == eAND) {
192 : :
193 : 432024 : pass = true;
194 [ + + ]: 810045 : for (unsigned int i=0; i<conditions.size(); i++) {
195 [ + + ]: 378021 : if (!conditions[i]->Evaluate()) pass = false;
196 : : }
197 : :
198 : : } else { // Logic must be eOR
199 : :
200 : 54003 : pass = false;
201 [ + + ]: 162009 : for (unsigned int i=0; i<conditions.size(); i++) {
202 [ + + ]: 108006 : if (conditions[i]->Evaluate()) pass = true;
203 : : }
204 : :
205 : : }
206 : :
207 : : } else {
208 : :
209 [ + + ]: 1680951 : if (TestParam2 != 0L) compareValue = TestParam2->getDoubleValue();
210 : 1572945 : else compareValue = TestValue;
211 : :
212 [ - + - + : 1680951 : switch (Comparison) {
+ - + - ]
213 : : case ecUndef:
214 : 0 : cerr << "Undefined comparison operator." << endl;
215 : : break;
216 : : case eEQ:
217 : 775344 : pass = TestParam1->getDoubleValue() == compareValue;
218 : 775344 : break;
219 : : case eNE:
220 : 0 : pass = TestParam1->getDoubleValue() != compareValue;
221 : 0 : break;
222 : : case eGT:
223 : 216018 : pass = TestParam1->getDoubleValue() > compareValue;
224 : 216018 : break;
225 : : case eGE:
226 : 579537 : pass = TestParam1->getDoubleValue() >= compareValue;
227 : 579537 : break;
228 : : case eLT:
229 : 0 : pass = TestParam1->getDoubleValue() < compareValue;
230 : 0 : break;
231 : : case eLE:
232 : 110052 : pass = TestParam1->getDoubleValue() <= compareValue;
233 : 110052 : break;
234 : : default:
235 : 0 : cerr << "Unknown comparison operator." << endl;
236 : : }
237 : : }
238 : :
239 : 2166978 : return pass;
240 : : }
241 : :
242 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
243 : :
244 : 47 : void FGCondition::PrintCondition(void )
245 : : {
246 : 47 : string scratch;
247 : :
248 [ + + ]: 47 : if (isGroup) {
249 [ - + + - ]: 9 : switch(Logic) {
250 : : case (elUndef):
251 : : scratch = " UNSET";
252 : 0 : cerr << "unset logic for test condition" << endl;
253 : : break;
254 : : case (eAND):
255 : : scratch = " if all of the following are true:";
256 : : break;
257 : : case (eOR):
258 : : scratch = " if any of the following are true:";
259 : : break;
260 : : default:
261 : : scratch = " UNKNOWN";
262 : 0 : cerr << "Unknown logic for test condition" << endl;
263 : : }
264 : :
265 : 9 : cout << scratch << endl;
266 [ + + ]: 18 : for (unsigned int i=0; i<conditions.size(); i++) conditions[i]->PrintCondition();
267 : :
268 : : } else {
269 [ + + ]: 38 : if (TestParam2 != 0L)
270 : : cout << " " << TestParam1->GetRelativeName() << " "
271 : : << conditional << " "
272 : 2 : << TestParam2->GetRelativeName();
273 : : else
274 : : cout << " " << TestParam1->GetRelativeName() << " "
275 : 72 : << conditional << " " << TestValue;
276 : 47 : }
277 : 47 : }
278 : :
279 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
280 : : // The bitmasked value choices are as follows:
281 : : // unset: In this case (the default) JSBSim would only print
282 : : // out the normally expected messages, essentially echoing
283 : : // the config files as they are read. If the environment
284 : : // variable is not set, debug_lvl is set to 1 internally
285 : : // 0: This requests JSBSim not to output any messages
286 : : // whatsoever.
287 : : // 1: This value explicity requests the normal JSBSim
288 : : // startup messages
289 : : // 2: This value asks for a message to be printed out when
290 : : // a class is instantiated
291 : : // 4: When this value is set, a message is displayed when a
292 : : // FGModel object executes its Run() method
293 : : // 8: When this value is set, various runtime state variables
294 : : // are printed out periodically
295 : : // 16: When set various parameters are sanity checked and
296 : : // a message is printed out when they go out of bounds
297 : :
298 : 56 : void FGCondition::Debug(int from)
299 : : {
300 [ + - ]: 56 : if (debug_lvl <= 0) return;
301 : :
302 : 56 : if (debug_lvl & 1) { // Standard console startup message output
303 : : if (from == 0) { // Constructor
304 : :
305 : : }
306 : : }
307 [ - + ]: 56 : if (debug_lvl & 2 ) { // Instantiation/Destruction notification
308 [ # # ]: 0 : if (from == 0) cout << "Instantiated: FGCondition" << endl;
309 [ # # ]: 0 : if (from == 1) cout << "Destroyed: FGCondition" << endl;
310 : : }
311 : 56 : if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
312 : : }
313 : 56 : if (debug_lvl & 8 ) { // Runtime state variables
314 : : }
315 : 56 : if (debug_lvl & 16) { // Sanity checking
316 : : }
317 [ - + ]: 56 : if (debug_lvl & 64) {
318 [ # # ]: 0 : if (from == 0) { // Constructor
319 : 0 : cout << IdSrc << endl;
320 : 0 : cout << IdHdr << endl;
321 : : }
322 : : }
323 : : }
324 : :
325 [ + + ][ + - ]: 12 : } //namespace JSBSim
326 : :
|