1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7 ------------- Copyright (C) 2000 -------------
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
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
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.
23 Further information about the GNU General Public License can also be found on
24 the world wide web at http://www.gnu.org.
26 FUNCTIONAL DESCRIPTION
27 --------------------------------------------------------------------------------
30 --------------------------------------------------------------------------------
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33 COMMENTS, REFERENCES, and NOTES
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 The SWITCH component is defined as follows (see the API documentation for more
39 <COMPONENT NAME="switch1" TYPE="SWITCH">
40 <TEST LOGIC="{AND|OR|DEFAULT}" OUTPUT="{property|value}">
41 {property} {conditional} {property|value}
42 <CONDITION_GROUP LOGIC="{AND|OR}">
43 {property} {conditional} {property|value}
48 <TEST LOGIC="{AND|OR}" OUTPUT="{property|value}">
49 {property} {conditional} {property|value}
55 Also, see the header file (FGSwitch.h) for further details.
57 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
59 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
65 static const char *IdSrc = "$Id$";
66 static const char *IdHdr = ID_SWITCH;
68 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
73 FGSwitch::FGSwitch(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
77 struct test *current_test;
80 Type = AC_cfg->GetValue("TYPE");
81 Name = AC_cfg->GetValue("NAME");
83 AC_cfg->GetNextConfigLine();
84 while ((token = AC_cfg->GetValue()) != string("/COMPONENT")) {
86 // See the above documentation, or the API docs, for information on what
87 // the SWITCH component is supposed to look like in the configuration file.
88 // Below, the switch component is read in.
90 if (token == "TEST") {
91 tests.push_back(test());
92 current_test = &tests.back();
94 if (AC_cfg->GetValue("LOGIC") == "OR") {
95 current_test->Logic = eOR;
96 } else if (AC_cfg->GetValue("LOGIC") == "AND") {
97 current_test->Logic = eAND;
98 } else if (AC_cfg->GetValue("LOGIC") == "DEFAULT") {
99 current_test->Logic = eDefault;
101 cerr << "Unrecognized LOGIC token in switch component: " << Name << endl;
104 value = AC_cfg->GetValue("VALUE");
106 cerr << "No VALUE supplied for switch component: " << Name << endl;
108 if (value.find_first_not_of("-.0123456789eE") == string::npos) {
109 // if true (and execution falls into this block), "value" is a number.
110 current_test->OutputVal = atof(value.c_str());
112 // "value" must be a property if execution passes to here.
113 if (value[0] == '-') {
114 current_test->sign = -1.0;
117 current_test->sign = 1.0;
119 current_test->OutputProp = PropertyManager->GetNode(value);
123 AC_cfg->GetNextConfigLine();
124 while (AC_cfg->GetValue() != string("/TEST")) {
125 current_test->conditions.push_back(FGCondition(AC_cfg, PropertyManager));
127 AC_cfg->GetNextConfigLine();
128 } else if (token == "OUTPUT") {
130 *AC_cfg >> sOutputIdx;
131 *AC_cfg >> sOutputIdx;
132 OutputNode = PropertyManager->GetNode( sOutputIdx, true );
136 FGFCSComponent::bind();
141 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
143 FGSwitch::~FGSwitch()
148 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
150 bool FGSwitch::Run(void )
152 vector <test>::iterator iTests = tests.begin();
153 vector <FGCondition>::iterator iConditions;
156 FGFCSComponent::Run(); // call the base class for initialization of Input
158 while (iTests < tests.end()) {
159 iConditions = iTests->conditions.begin();
161 if (iTests->Logic == eDefault) {
162 Output = iTests->GetValue();
163 } else if (iTests->Logic == eAND) {
165 while (iConditions < iTests->conditions.end()) {
166 if (!iConditions->Evaluate()) pass = false;
169 } else if (iTests->Logic == eOR) {
171 while (iConditions < iTests->conditions.end()) {
172 if (iConditions->Evaluate()) pass = true;
176 cerr << "Invalid logic test" << endl;
180 Output = iTests->GetValue();
186 if (IsOutput) SetOutput();
191 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
193 void FGSwitch::convert(void)
196 cout << " <component name=\"" << Name << "\" type=\"" << Type << "\">" << endl;
198 // cout << " <input>" << InputNodes[0]->GetName() << "</input>" << endl;
200 for (int i=0; i<tests.size(); i++) {
201 if (tests[i].Logic == eDefault) {
202 if (tests[i].OutputProp == 0L)
203 cout << " <default value=\"" << tests[i].OutputVal << "\"/>" << endl;
205 cout << " <default value=\"" << (tests[i].OutputProp->GetFullyQualifiedName()).substr(12) << "\"/>" << endl;
206 } else if (tests[i].Logic == eAND) {
207 if (tests[i].OutputProp == 0L)
208 cout << " <test logic=\"AND\" value=\"" << tests[i].OutputVal << "\">" << endl;
210 cout << " <test logic=\"AND\" value=\"" << (tests[i].OutputProp->GetFullyQualifiedName()).substr(12) << "\">" << endl;
211 } else if (tests[i].Logic == eOR) {
212 if (tests[i].OutputProp == 0L)
213 cout << " <test logic=\"OR\" value=\"" << tests[i].OutputVal << "\">" << endl;
215 cout << " <test logic=\"OR\" value=\"" << (tests[i].OutputProp->GetFullyQualifiedName()).substr(12) << "\">" << endl;
217 for (int j=0; j<tests[i].conditions.size(); j++) {
218 tests[i].conditions[j].convert();
220 if (tests[i].Logic != eDefault) cout << " </test>" << endl;
224 cout << " <output>" << (OutputNode->GetFullyQualifiedName()).substr(12) << "</output>" << endl;
226 cout << " </component>" << endl;
229 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
230 // The bitmasked value choices are as follows:
231 // unset: In this case (the default) JSBSim would only print
232 // out the normally expected messages, essentially echoing
233 // the config files as they are read. If the environment
234 // variable is not set, debug_lvl is set to 1 internally
235 // 0: This requests JSBSim not to output any messages
237 // 1: This value explicity requests the normal JSBSim
239 // 2: This value asks for a message to be printed out when
240 // a class is instantiated
241 // 4: When this value is set, a message is displayed when a
242 // FGModel object executes its Run() method
243 // 8: When this value is set, various runtime state variables
244 // are printed out periodically
245 // 16: When set various parameters are sanity checked and
246 // a message is printed out when they go out of bounds
248 void FGSwitch::Debug(int from)
250 vector <test>::iterator iTests = tests.begin();
251 vector <FGCondition>::iterator iConditions;
252 string comp, scratch;
256 if (debug_lvl <= 0) return;
258 if (debug_lvl & 1) { // Standard console startup message output
259 if (from == 0) { // Constructor
260 while (iTests < tests.end()) {
264 switch(iTests->Logic) {
267 cerr << "Unset logic for test condition" << endl;
276 scratch = " by default.";
280 cerr << "Unknown logic for test condition" << endl;
283 if (iTests->OutputProp != 0L)
284 if (iTests->sign < 0)
285 cout << indent << "Switch VALUE is - " << iTests->OutputProp->GetName() << scratch << endl;
287 cout << indent << "Switch VALUE is " << iTests->OutputProp->GetName() << scratch << endl;
289 cout << indent << "Switch VALUE is " << iTests->OutputVal << scratch << endl;
291 iConditions = iTests->conditions.begin();
293 while (iConditions < iTests->conditions.end()) {
294 if (!first) cout << indent << comp << " ";
295 else cout << indent << " ";
297 iConditions->PrintCondition();
304 if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl;
307 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
308 if (from == 0) cout << "Instantiated: FGSwitch" << endl;
309 if (from == 1) cout << "Destroyed: FGSwitch" << endl;
311 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
313 if (debug_lvl & 8 ) { // Runtime state variables
315 if (debug_lvl & 16) { // Sanity checking
317 if (debug_lvl & 64) {
318 if (from == 0) { // Constructor
319 cout << IdSrc << endl;
320 cout << IdHdr << endl;