]> git.mxchange.org Git - flightgear.git/blob - src/AIModel/performancedb.cxx
apt.dat parser: clearer log and exception messages
[flightgear.git] / src / AIModel / performancedb.cxx
1 #ifdef HAVE_CONFIG_H
2   #include "config.h"
3 #endif
4
5 #include "performancedb.hxx"
6
7 #include <boost/foreach.hpp>
8
9 #include <simgear/sg_inlines.h>
10 #include <simgear/misc/sg_path.hxx>
11 #include <simgear/props/props.hxx>
12 #include <simgear/props/props_io.hxx>
13 #include <simgear/structure/exception.hxx>
14
15 #include <Main/globals.hxx>
16 #include <iostream>
17 #include <fstream>
18
19 #include "performancedata.hxx"
20
21 using std::string;
22 using std::cerr;
23
24 PerformanceDB::PerformanceDB()
25 {
26 }
27
28
29 PerformanceDB::~PerformanceDB()
30 {
31 }
32
33 void PerformanceDB::init()
34 {
35     SGPath dbpath( globals->get_fg_root() );
36     dbpath.append( "/AI/Aircraft/" );
37     dbpath.append( "performancedb.xml");
38     load(dbpath);
39
40     if (getDefaultPerformance() == 0) {
41         SG_LOG(SG_AI, SG_WARN, "PerformanceDB: no default performance data found/loaded");
42     }
43 }
44
45 void PerformanceDB::shutdown()
46 {
47     PerformanceDataDict::iterator it;
48     for (it = _db.begin(); it != _db.end(); ++it) {
49         delete it->second;
50     }
51
52     _db.clear();
53     _aliases.clear();
54 }
55
56 void PerformanceDB::update(double dt)
57 {
58     SG_UNUSED(dt);
59     suspend();
60 }
61
62 void PerformanceDB::registerPerformanceData(const std::string& id, PerformanceData* data) {
63     //TODO if key exists already replace data "inplace", i.e. copy to existing PerfData instance
64     // this updates all aircraft currently using the PerfData instance.
65     _db[id] = data;
66 }
67
68 PerformanceData* PerformanceDB::getDataFor(const string& acType, const string& acClass) const
69 {
70   // first, try with the specific aircraft type, such as 738 or A322
71     PerformanceDataDict::const_iterator it;
72     it = _db.find(acType);
73     if (it != _db.end()) {
74         return it->second;
75     }
76     
77     const string& alias = findAlias(acType);
78     it = _db.find(alias);
79     if (it != _db.end()) {
80         return it->second;
81     }
82
83     it = _db.find(acClass);
84     if (it == _db.end()) {
85         return getDefaultPerformance();
86     }
87
88     return it->second;
89 }
90
91 PerformanceData* PerformanceDB::getDefaultPerformance() const
92 {
93     PerformanceDataDict::const_iterator it = _db.find("jet_transport");
94     if (it == _db.end())
95         return NULL;
96
97     return it->second;
98 }
99
100 bool PerformanceDB::havePerformanceDataForAircraftType(const std::string& acType) const
101 {
102     PerformanceDataDict::const_iterator it = _db.find(acType);
103     if (it != _db.end())
104         return true;
105
106     const std::string alias(findAlias(acType));
107     return (_db.find(alias) != _db.end());
108 }
109
110 void PerformanceDB::load(const SGPath& filename)
111 {
112     SGPropertyNode root;
113     try {
114         readProperties(filename.str(), &root);
115     } catch (const sg_exception &) {
116         SG_LOG(SG_AI, SG_ALERT,
117             "Error reading AI aircraft performance database: " << filename.str());
118         return;
119     }
120
121     SGPropertyNode * node = root.getNode("performancedb");
122     for (int i = 0; i < node->nChildren(); i++) {
123         SGPropertyNode * db_node = node->getChild(i);
124         if (!strcmp(db_node->getName(), "aircraft")) {
125             PerformanceData* data = NULL;
126             if (db_node->hasChild("base")) {
127               const string& baseName = db_node->getStringValue("base");
128               PerformanceData* baseData = _db[baseName];
129               if (!baseData) {
130                 SG_LOG(SG_AI, SG_ALERT,
131                        "Error reading AI aircraft performance database: unknown base type " << baseName);
132                 return;
133               }
134               
135               // clone base data to 'inherit' from it
136               data = new PerformanceData(baseData); 
137             } else {
138               data = new PerformanceData;
139             }
140           
141             data->initFromProps(db_node);
142             const string& name  = db_node->getStringValue("type", "heavy_jet");
143             registerPerformanceData(name, data);
144         } else if (!strcmp(db_node->getName(), "alias")) {
145             const string& alias(db_node->getStringValue("alias"));
146             if (alias.empty()) {
147                 SG_LOG(SG_AI, SG_ALERT, "performance DB alias entry with no <alias> definition");
148                 continue;
149             }
150           
151             BOOST_FOREACH(SGPropertyNode* matchNode, db_node->getChildren("match")) {
152                 const string& match(matchNode->getStringValue());
153                 _aliases.push_back(StringPair(match, alias));
154             }
155         } else {
156             SG_LOG(SG_AI, SG_ALERT, "unrecognized performance DB entry:" << db_node->getName());
157         }
158     } // of nodes iteration
159 }
160
161 const string& PerformanceDB::findAlias(const string& acType) const
162 {
163     BOOST_FOREACH(const StringPair& alias, _aliases) {
164         if (acType.find(alias.first) == 0) { // matched!
165             return alias.second;
166         }
167     } // of alias iteration
168   
169     static const string empty;
170     return empty;
171 }
172
173