~ubuntu-branches/debian/sid/flightgear/sid

« back to all changes in this revision

Viewing changes to src/Traffic/TrafficMgr.cxx

  • Committer: Package Import Robot
  • Author(s): Markus Wanner, Markus Wanner, Rebecca Palmer
  • Date: 2014-01-21 22:31:02 UTC
  • mfrom: (1.3.1) (15.1.2 experimental)
  • Revision ID: package-import@ubuntu.com-20140121223102-cjw7g9le25acd119
Tags: 3.0.0~git20140204+c99ea4-1
[ Markus Wanner ]
* Upload to unstable.
* Adjust B-D to allow building on kfreebsd-*. Closes: #724686.
* Add a lintian-overrides on autotools; we use cmake.
* Upstream corrected the fgfs manpage. Closes: #556362.
* Drop unnecessary man page for gl-info. Closes: #698308.
* Drop README.Linux: it's outdated to the point of uselessness.
  Closes: #574173.
* Add an upper limit of libsimgear-dev versions that flightgear can be
  built with. Closes: #738436.
* Drop the libsvn-dev dependency, neither flightgear nor simgear depend
  on libsvn, anymore. Closes: #682947.
* List icons in debian/install rather than copying around from rules.
* Update menu entry for flightgear, add one for fgcom; add .xpm icons.
  Closes: #713924.
* flightgear.desktop: add German translation
* Bump Standards-Version to 3.9.5; no changes needed.

[ Rebecca Palmer ]
* New upstream release.
* Install the icons (based on code by Saikrishna Arcot).  (Not a
  complete fix for LP908153 as it only sets the menu/Dash icon, not the
  running window's icon, but better than nothing).
* Disable screensaver while running. Closes: LP#793599. Add required
  libdbus-1-dev dependency.
* Remove outdated README.Debian.
* Terrasync now works after just ticking the box. Closes: #252899.
* Always set Terrasync directory.

Show diffs side-by-side

added added

removed removed

Lines of Context:
57
57
#include <simgear/misc/sg_dir.hxx>
58
58
#include <simgear/props/props.hxx>
59
59
#include <simgear/structure/subsystem_mgr.hxx>
 
60
#include <simgear/structure/exception.hxx>
 
61
 
60
62
#include <simgear/xml/easyxml.hxx>
61
63
#include <simgear/threads/SGThread.hxx>
62
64
#include <simgear/threads/SGGuard.hxx>
 
65
#include <simgear/scene/tsync/terrasync.hxx>
63
66
 
64
67
#include <AIModel/AIAircraft.hxx>
65
68
#include <AIModel/AIFlightPlan.hxx>
66
69
#include <AIModel/AIBase.hxx>
67
 
#include <Airports/simple.hxx>
 
70
#include <Airports/airport.hxx>
68
71
#include <Main/fg_init.hxx>
69
72
 
70
73
#include "TrafficMgr.hxx"
72
75
using std::sort;
73
76
using std::strcmp;
74
77
using std::endl;
 
78
using std::string;
 
79
using std::vector;
75
80
 
76
81
/**
77
82
 * Thread encapsulating parsing the traffic schedules. 
78
83
 */
79
 
class ScheduleParseThread : public SGThread
 
84
class ScheduleParseThread : public SGThread, public XMLVisitor
80
85
{
81
86
public:
82
87
  ScheduleParseThread(FGTrafficManager* traffic) :
83
88
    _trafficManager(traffic),
84
89
    _isFinished(false),
85
 
    _cancelThread(false)
 
90
    _cancelThread(false),
 
91
    cruiseAlt(0),
 
92
    score(0),
 
93
    acCounter(0),
 
94
    radius(0),
 
95
    offset(0),
 
96
    heavy(false)
86
97
  {
87
98
    
88
99
  }
100
111
    }
101
112
  }
102
113
  
103
 
  void setTrafficDir(const SGPath& trafficDirPath)
 
114
  void setTrafficDirs(const PathList& dirs)
104
115
  {
105
 
    _trafficDirPath = trafficDirPath;
 
116
    _trafficDirPaths = dirs;
106
117
  }
107
118
  
108
119
  bool isFinished() const
113
124
  
114
125
  virtual void run()
115
126
  {
116
 
    SGTimeStamp st;
117
 
    st.stamp();
118
 
    
119
 
    simgear::Dir trafficDir(_trafficDirPath);
120
 
    simgear::PathList d = trafficDir.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT);
121
 
    
122
 
    BOOST_FOREACH(SGPath p, d) {
123
 
      simgear::Dir d2(p);
124
 
      simgear::PathList trafficFiles = d2.children(simgear::Dir::TYPE_FILE, ".xml");
125
 
      BOOST_FOREACH(SGPath xml, trafficFiles) {
126
 
        _trafficManager->parseSchedule(xml);
127
 
        if (_cancelThread) {
128
 
          return;
129
 
        }
 
127
      BOOST_FOREACH(SGPath p, _trafficDirPaths) {
 
128
          parseTrafficDir(p);
 
129
          if (_cancelThread) {
 
130
              return;
 
131
          }
130
132
      }
131
 
    } // of sub-directories in AI/Traffic iteration
132
 
    
133
 
  //  _trafficManager->parseSchedules(schedulesToRead);
134
 
    SG_LOG(SG_AI, SG_INFO, "parsing traffic schedules took:" << st.elapsedMSec() << "msec");
135
133
    
136
134
    SGGuard<SGMutex> g(_lock);
137
135
    _isFinished = true;
138
136
  }
 
137
    
 
138
    void startXML()
 
139
    {
 
140
        //cout << "Start XML" << endl;
 
141
        requiredAircraft = "";
 
142
        homePort = "";
 
143
    }
 
144
    
 
145
    void endXML()
 
146
    {
 
147
        //cout << "End XML" << endl;
 
148
    }
 
149
    
 
150
    void startElement(const char *name,
 
151
                                        const XMLAttributes & atts)
 
152
    {
 
153
        const char *attval;
 
154
        //cout << "Start element " << name << endl;
 
155
        //FGTrafficManager temp;
 
156
        //for (int i = 0; i < atts.size(); i++)
 
157
        //  if (string(atts.getName(i)) == string("include"))
 
158
        attval = atts.getValue("include");
 
159
        if (attval != 0) {
 
160
            //cout << "including " << attval << endl;
 
161
            SGPath path = globals->get_fg_root();
 
162
            path.append("/Traffic/");
 
163
            path.append(attval);
 
164
            readXML(path.str(), *this);
 
165
        }
 
166
        elementValueStack.push_back("");
 
167
        //  cout << "  " << atts.getName(i) << '=' << atts.getValue(i) << endl;
 
168
    }
 
169
    
 
170
    void endElement(const char *name)
 
171
    {
 
172
        //cout << "End element " << name << endl;
 
173
        const string & value = elementValueStack.back();
 
174
        
 
175
        if (!strcmp(name, "model"))
 
176
            mdl = value;
 
177
        else if (!strcmp(name, "livery"))
 
178
            livery = value;
 
179
        else if (!strcmp(name, "home-port"))
 
180
            homePort = value;
 
181
        else if (!strcmp(name, "registration"))
 
182
            registration = value;
 
183
        else if (!strcmp(name, "airline"))
 
184
            airline = value;
 
185
        else if (!strcmp(name, "actype"))
 
186
            acType = value;
 
187
        else if (!strcmp(name, "required-aircraft"))
 
188
            requiredAircraft = value;
 
189
        else if (!strcmp(name, "flighttype"))
 
190
            flighttype = value;
 
191
        else if (!strcmp(name, "radius"))
 
192
            radius = atoi(value.c_str());
 
193
        else if (!strcmp(name, "offset"))
 
194
            offset = atoi(value.c_str());
 
195
        else if (!strcmp(name, "performance-class"))
 
196
            m_class = value;
 
197
        else if (!strcmp(name, "heavy")) {
 
198
            if (value == string("true"))
 
199
                heavy = true;
 
200
            else
 
201
                heavy = false;
 
202
        } else if (!strcmp(name, "callsign"))
 
203
            callsign = value;
 
204
        else if (!strcmp(name, "fltrules"))
 
205
            fltrules = value;
 
206
        else if (!strcmp(name, "port"))
 
207
            port = value;
 
208
        else if (!strcmp(name, "time"))
 
209
            timeString = value;
 
210
        else if (!strcmp(name, "departure")) {
 
211
            departurePort = port;
 
212
            departureTime = timeString;
 
213
        } else if (!strcmp(name, "cruise-alt"))
 
214
            cruiseAlt = atoi(value.c_str());
 
215
        else if (!strcmp(name, "arrival")) {
 
216
            arrivalPort = port;
 
217
            arrivalTime = timeString;
 
218
        } else if (!strcmp(name, "repeat"))
 
219
            repeat = value;
 
220
        else if (!strcmp(name, "flight")) {
 
221
            // We have loaded and parsed all the information belonging to this flight
 
222
            // so we temporarily store it.
 
223
            //cerr << "Pusing back flight " << callsign << endl;
 
224
            //cerr << callsign  <<  " " << fltrules     << " "<< departurePort << " " <<  arrivalPort << " "
 
225
            //   << cruiseAlt <<  " " << departureTime<< " "<< arrivalTime   << " " << repeat << endl;
 
226
            
 
227
            //Prioritize aircraft
 
228
            string apt = fgGetString("/sim/presets/airport-id");
 
229
            //cerr << "Airport information: " << apt << " " << departurePort << " " << arrivalPort << endl;
 
230
            //if (departurePort == apt) score++;
 
231
            //flights.push_back(new FGScheduledFlight(callsign,
 
232
            //                                fltrules,
 
233
            //                                departurePort,
 
234
            //                                arrivalPort,
 
235
            //                                cruiseAlt,
 
236
            //                                departureTime,
 
237
            //                                arrivalTime,
 
238
            //                                repeat));
 
239
            if (requiredAircraft == "") {
 
240
                char buffer[16];
 
241
                snprintf(buffer, 16, "%d", acCounter);
 
242
                requiredAircraft = buffer;
 
243
            }
 
244
            SG_LOG(SG_AI, SG_DEBUG, "Adding flight: " << callsign << " "
 
245
                   << fltrules << " "
 
246
                   << departurePort << " "
 
247
                   << arrivalPort << " "
 
248
                   << cruiseAlt << " "
 
249
                   << departureTime << " "
 
250
                   << arrivalTime << " " << repeat << " " << requiredAircraft);
 
251
            // For database maintainance purposes, it may be convenient to
 
252
            //
 
253
            if (fgGetBool("/sim/traffic-manager/dumpdata") == true) {
 
254
                SG_LOG(SG_AI, SG_ALERT, "Traffic Dump FLIGHT," << callsign << ","
 
255
                       << fltrules << ","
 
256
                       << departurePort << ","
 
257
                       << arrivalPort << ","
 
258
                       << cruiseAlt << ","
 
259
                       << departureTime << ","
 
260
                       << arrivalTime << "," << repeat << "," << requiredAircraft);
 
261
            }
 
262
            
 
263
            _trafficManager->flights[requiredAircraft].push_back(new FGScheduledFlight(callsign,
 
264
                                                                      fltrules,
 
265
                                                                      departurePort,
 
266
                                                                      arrivalPort,
 
267
                                                                      cruiseAlt,
 
268
                                                                      departureTime,
 
269
                                                                      arrivalTime,
 
270
                                                                      repeat,
 
271
                                                                      requiredAircraft));
 
272
            requiredAircraft = "";
 
273
        } else if (!strcmp(name, "aircraft")) {
 
274
            endAircraft();
 
275
        }
 
276
        
 
277
        elementValueStack.pop_back();
 
278
    }
 
279
 
 
280
    
 
281
    void data(const char *s, int len)
 
282
    {
 
283
        string token = string(s, len);
 
284
        //cout << "Character data " << string(s,len) << endl;
 
285
        elementValueStack.back() += token;
 
286
    }
 
287
    
 
288
    void pi(const char *target, const char *data)
 
289
    {
 
290
        //cout << "Processing instruction " << target << ' ' << data << endl;
 
291
    }
 
292
    
 
293
    void warning(const char *message, int line, int column)
 
294
    {
 
295
        SG_LOG(SG_IO, SG_WARN,
 
296
               "Warning: " << message << " (" << line << ',' << column << ')');
 
297
    }
 
298
    
 
299
    void error(const char *message, int line, int column)
 
300
    {
 
301
        SG_LOG(SG_IO, SG_ALERT,
 
302
               "Error: " << message << " (" << line << ',' << column << ')');
 
303
    }
 
304
    
139
305
private:
 
306
    void endAircraft()
 
307
    {
 
308
        string isHeavy = heavy ? "true" : "false";
 
309
        
 
310
        if (missingModels.find(mdl) != missingModels.end()) {
 
311
            // don't stat() or warn again
 
312
            requiredAircraft = homePort = "";
 
313
            return;
 
314
        }
 
315
        
 
316
        if (!FGAISchedule::validModelPath(mdl)) {
 
317
            missingModels.insert(mdl);
 
318
            SG_LOG(SG_AI, SG_WARN, "TrafficMgr: Missing model path:" << mdl);
 
319
            requiredAircraft = homePort = "";
 
320
            return;
 
321
        }
 
322
        
 
323
        int proportion =
 
324
        (int) (fgGetDouble("/sim/traffic-manager/proportion") * 100);
 
325
        int randval = rand() & 100;
 
326
        if (randval > proportion) {
 
327
            requiredAircraft = homePort = "";
 
328
            return;
 
329
        }
 
330
        
 
331
        if (fgGetBool("/sim/traffic-manager/dumpdata") == true) {
 
332
            SG_LOG(SG_AI, SG_ALERT, "Traffic Dump AC," << homePort << "," << registration << "," << requiredAircraft
 
333
                   << "," << acType << "," << livery << ","
 
334
                   << airline << ","  << m_class << "," << offset << "," << radius << "," << flighttype << "," << isHeavy << "," << mdl);
 
335
        }
 
336
        
 
337
        if (requiredAircraft == "") {
 
338
            char buffer[16];
 
339
            snprintf(buffer, 16, "%d", acCounter);
 
340
            requiredAircraft = buffer;
 
341
        }
 
342
        if (homePort == "") {
 
343
            homePort = departurePort;
 
344
        }
 
345
        
 
346
        // caution, modifying the scheduled aircraft strucutre from the
 
347
        // 'wrong' thread. This is safe becuase FGTrafficManager won't touch
 
348
        // the structure while we exist.
 
349
        _trafficManager->scheduledAircraft.push_back(new FGAISchedule(mdl,
 
350
                                                     livery,
 
351
                                                     homePort,
 
352
                                                     registration,
 
353
                                                     requiredAircraft,
 
354
                                                     heavy,
 
355
                                                     acType,
 
356
                                                     airline,
 
357
                                                     m_class,
 
358
                                                     flighttype,
 
359
                                                     radius, offset));
 
360
        
 
361
        acCounter++;
 
362
        requiredAircraft = "";
 
363
        homePort = "";
 
364
        score = 0;
 
365
    }
 
366
    
 
367
    void parseTrafficDir(const SGPath& path)
 
368
    {
 
369
        SGTimeStamp st;
 
370
        st.stamp();
 
371
        
 
372
        simgear::Dir trafficDir(path);
 
373
        simgear::PathList d = trafficDir.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT);
 
374
        
 
375
        BOOST_FOREACH(SGPath p, d) {
 
376
            simgear::Dir d2(p);
 
377
            SG_LOG(SG_AI, SG_INFO, "parsing traffic in:" << p);
 
378
            simgear::PathList trafficFiles = d2.children(simgear::Dir::TYPE_FILE, ".xml");
 
379
            BOOST_FOREACH(SGPath xml, trafficFiles) {                
 
380
                readXML(xml.str(), *this);
 
381
                if (_cancelThread) {
 
382
                    return;
 
383
                }
 
384
            }
 
385
        } // of sub-directories iteration
 
386
        
 
387
        SG_LOG(SG_AI, SG_INFO, "parsing traffic schedules took:" << st.elapsedMSec() << "msec");
 
388
    }
 
389
    
140
390
  FGTrafficManager* _trafficManager;
141
391
  mutable SGMutex _lock;
142
392
  bool _isFinished;
143
393
  bool _cancelThread;
144
 
  SGPath _trafficDirPath;
 
394
  PathList _trafficDirPaths;
 
395
   
 
396
// parser state
 
397
    
 
398
    string_list elementValueStack;
 
399
    // record model paths which are missing, to avoid duplicate
 
400
    // warnings when parsing traffic schedules.
 
401
    std::set<std::string> missingModels;
 
402
    
 
403
    std::string mdl, livery, registration, callsign, fltrules,
 
404
    port, timeString, departurePort, departureTime, arrivalPort, arrivalTime,
 
405
    repeat, acType, airline, m_class, flighttype, requiredAircraft, homePort;
 
406
    int cruiseAlt;
 
407
    int score, acCounter;
 
408
    double radius, offset;
 
409
    bool heavy;
 
410
 
145
411
};
146
412
 
147
413
/******************************************************************************
150
416
FGTrafficManager::FGTrafficManager() :
151
417
  inited(false),
152
418
  doingInit(false),
 
419
  trafficSyncRequested(false),
153
420
  waitingMetarTime(0.0),
154
 
  cruiseAlt(0),
155
 
  score(0),
156
 
  runCount(0),
157
 
  acCounter(0),
158
 
  radius(0),
159
 
  offset(0),
160
 
  heavy(false),
161
421
  enabled("/sim/traffic-manager/enabled"),
162
422
  aiEnabled("/sim/ai/enabled"),
163
423
  realWxEnabled("/environment/realwx/enabled"),
195
455
                       airport[0], airport[1], airport[2]);
196
456
            cacheData.append(buffer);
197
457
            if (!cacheData.exists()) {
198
 
                cacheData.create_dir(0777);
 
458
                cacheData.create_dir(0755);
199
459
            }
200
460
            cacheData.append(airport + "-cache.txt");
201
461
            //cerr << "Saving AI traffic heuristics" << endl;
223
483
    currAircraft = scheduledAircraft.begin();
224
484
    doingInit = false;
225
485
    inited = false;
226
 
}
227
 
 
228
 
/// caution - this is run on the helper thread to improve startup
229
 
/// responsiveness - do not access properties or global state from
230
 
/// here, since there's no locking protection at all
231
 
void FGTrafficManager::parseSchedule(const SGPath& path)
232
 
{
233
 
  readXML(path.str(), *this);
 
486
    trafficSyncRequested = false;
234
487
}
235
488
 
236
489
void FGTrafficManager::init()
240
493
    }
241
494
 
242
495
    assert(!doingInit);
 
496
    simgear::SGTerraSync* terraSync = static_cast<simgear::SGTerraSync*>(globals->get_subsystem("terrasync"));
 
497
    bool doDataSync = fgGetBool("/sim/terrasync/ai-data-enabled");
 
498
    if (doDataSync && terraSync) {
 
499
        if (!trafficSyncRequested) {
 
500
            SG_LOG(SG_AI, SG_INFO, "Sync of AI traffic via TerraSync enabled");
 
501
            terraSync->scheduleDataDir("AI/Traffic");
 
502
            trafficSyncRequested = true;
 
503
        }
 
504
        
 
505
        if (terraSync->isDataDirPending("AI/Traffic")) {
 
506
            return; // remain in the init state
 
507
        }
 
508
        
 
509
        SG_LOG(SG_AI, SG_INFO, "Traffic files sync complete");
 
510
    }
 
511
    
243
512
    doingInit = true;
244
513
    if (string(fgGetString("/sim/traffic-manager/datafile")).empty()) {
 
514
        PathList dirs = globals->get_data_paths("AI/Traffic");
 
515
        
 
516
        // temporary flag to restrict loading while traffic data is found
 
517
        // through terrasync /and/ fgdata. Ultimatley we *do* want to be able to
 
518
        // overlay sources.
 
519
        
 
520
        if (dirs.size() > 1) {
 
521
            SGPath p = dirs.back();
 
522
            if (simgear::strutils::starts_with(p.str(), globals->get_fg_root())) {
 
523
                dirs.pop_back();
 
524
            }
 
525
        }
 
526
        
 
527
        if (dirs.empty()) {
 
528
            doingInit = false;
 
529
            return;
 
530
        }
 
531
        
245
532
        scheduleParser.reset(new ScheduleParseThread(this));
246
 
        scheduleParser->setTrafficDir(SGPath(globals->get_fg_root(), "AI/Traffic"));      
 
533
        scheduleParser->setTrafficDirs(dirs);
247
534
        scheduleParser->start();
248
535
    } else {
249
536
        fgSetBool("/sim/traffic-manager/heuristics", false);
251
538
        string ext = path.extension();
252
539
        if (path.extension() == "xml") {
253
540
            if (path.exists()) {
254
 
                readXML(path.str(), *this);
 
541
                // use a SchedulerParser to parse, but run it in this thread,
 
542
                // i.e don't start it
 
543
                ScheduleParseThread parser(this);
 
544
                readXML(path.str(), parser);
255
545
            }
256
546
        } else if (path.extension() == "conf") {
257
547
            if (path.exists()) {
393
683
        if (!doingInit) {
394
684
            init();
395
685
        }
396
 
        
397
 
        if (!scheduleParser->isFinished()) {
 
686
                
 
687
        if (!doingInit || !scheduleParser->isFinished()) {
398
688
          return;
399
689
        }
400
690
      
455
745
         if (!tokens.empty()) {
456
746
             if (tokens[0] == string("AC")) {
457
747
                 if (tokens.size() != 13) {
458
 
                     SG_LOG(SG_AI, SG_ALERT, "Error parsing traffic file " << infileName.str() << " at " << buffString);
459
 
                     exit(1);
 
748
                     throw sg_io_exception("Error parsing traffic file @ " + buffString, sg_location(infileName.str()));
460
749
                 }
 
750
                 
 
751
                 
461
752
                 model          = tokens[12];
462
753
                 livery         = tokens[6];
463
754
                 homePort       = tokens[1];
598
889
}
599
890
 
600
891
 
601
 
void FGTrafficManager::startXML()
602
 
{
603
 
    //cout << "Start XML" << endl;
604
 
    requiredAircraft = "";
605
 
    homePort = "";
606
 
}
607
 
 
608
 
void FGTrafficManager::endXML()
609
 
{
610
 
    //cout << "End XML" << endl;
611
 
}
612
 
 
613
 
void FGTrafficManager::startElement(const char *name,
614
 
                                    const XMLAttributes & atts)
615
 
{
616
 
    const char *attval;
617
 
    //cout << "Start element " << name << endl;
618
 
    //FGTrafficManager temp;
619
 
    //for (int i = 0; i < atts.size(); i++)
620
 
    //  if (string(atts.getName(i)) == string("include"))
621
 
    attval = atts.getValue("include");
622
 
    if (attval != 0) {
623
 
        //cout << "including " << attval << endl;
624
 
        SGPath path = globals->get_fg_root();
625
 
        path.append("/Traffic/");
626
 
        path.append(attval);
627
 
        readXML(path.str(), *this);
628
 
    }
629
 
    elementValueStack.push_back("");
630
 
    //  cout << "  " << atts.getName(i) << '=' << atts.getValue(i) << endl; 
631
 
}
632
 
 
633
 
void FGTrafficManager::endElement(const char *name)
634
 
{
635
 
    //cout << "End element " << name << endl;
636
 
    const string & value = elementValueStack.back();
637
 
 
638
 
    if (!strcmp(name, "model"))
639
 
        mdl = value;
640
 
    else if (!strcmp(name, "livery"))
641
 
        livery = value;
642
 
    else if (!strcmp(name, "home-port"))
643
 
        homePort = value;
644
 
    else if (!strcmp(name, "registration"))
645
 
        registration = value;
646
 
    else if (!strcmp(name, "airline"))
647
 
        airline = value;
648
 
    else if (!strcmp(name, "actype"))
649
 
        acType = value;
650
 
    else if (!strcmp(name, "required-aircraft"))
651
 
        requiredAircraft = value;
652
 
    else if (!strcmp(name, "flighttype"))
653
 
        flighttype = value;
654
 
    else if (!strcmp(name, "radius"))
655
 
        radius = atoi(value.c_str());
656
 
    else if (!strcmp(name, "offset"))
657
 
        offset = atoi(value.c_str());
658
 
    else if (!strcmp(name, "performance-class"))
659
 
        m_class = value;
660
 
    else if (!strcmp(name, "heavy")) {
661
 
        if (value == string("true"))
662
 
            heavy = true;
663
 
        else
664
 
            heavy = false;
665
 
    } else if (!strcmp(name, "callsign"))
666
 
        callsign = value;
667
 
    else if (!strcmp(name, "fltrules"))
668
 
        fltrules = value;
669
 
    else if (!strcmp(name, "port"))
670
 
        port = value;
671
 
    else if (!strcmp(name, "time"))
672
 
        timeString = value;
673
 
    else if (!strcmp(name, "departure")) {
674
 
        departurePort = port;
675
 
        departureTime = timeString;
676
 
    } else if (!strcmp(name, "cruise-alt"))
677
 
        cruiseAlt = atoi(value.c_str());
678
 
    else if (!strcmp(name, "arrival")) {
679
 
        arrivalPort = port;
680
 
        arrivalTime = timeString;
681
 
    } else if (!strcmp(name, "repeat"))
682
 
        repeat = value;
683
 
    else if (!strcmp(name, "flight")) {
684
 
        // We have loaded and parsed all the information belonging to this flight
685
 
        // so we temporarily store it. 
686
 
        //cerr << "Pusing back flight " << callsign << endl;
687
 
        //cerr << callsign  <<  " " << fltrules     << " "<< departurePort << " " <<  arrivalPort << " "
688
 
        //   << cruiseAlt <<  " " << departureTime<< " "<< arrivalTime   << " " << repeat << endl;
689
 
 
690
 
        //Prioritize aircraft 
691
 
        string apt = fgGetString("/sim/presets/airport-id");
692
 
        //cerr << "Airport information: " << apt << " " << departurePort << " " << arrivalPort << endl;
693
 
        //if (departurePort == apt) score++;
694
 
        //flights.push_back(new FGScheduledFlight(callsign,
695
 
        //                                fltrules,
696
 
        //                                departurePort,
697
 
        //                                arrivalPort,
698
 
        //                                cruiseAlt,
699
 
        //                                departureTime,
700
 
        //                                arrivalTime,
701
 
        //                                repeat));
702
 
        if (requiredAircraft == "") {
703
 
            char buffer[16];
704
 
            snprintf(buffer, 16, "%d", acCounter);
705
 
            requiredAircraft = buffer;
706
 
        }
707
 
        SG_LOG(SG_AI, SG_DEBUG, "Adding flight: " << callsign << " "
708
 
               << fltrules << " "
709
 
               << departurePort << " "
710
 
               << arrivalPort << " "
711
 
               << cruiseAlt << " "
712
 
               << departureTime << " "
713
 
               << arrivalTime << " " << repeat << " " << requiredAircraft);
714
 
        // For database maintainance purposes, it may be convenient to
715
 
        // 
716
 
        if (fgGetBool("/sim/traffic-manager/dumpdata") == true) {
717
 
             SG_LOG(SG_AI, SG_ALERT, "Traffic Dump FLIGHT," << callsign << ","
718
 
                          << fltrules << ","
719
 
                          << departurePort << ","
720
 
                          << arrivalPort << ","
721
 
                          << cruiseAlt << ","
722
 
                          << departureTime << ","
723
 
                          << arrivalTime << "," << repeat << "," << requiredAircraft);
724
 
        }
725
 
        flights[requiredAircraft].push_back(new FGScheduledFlight(callsign,
726
 
                                                                  fltrules,
727
 
                                                                  departurePort,
728
 
                                                                  arrivalPort,
729
 
                                                                  cruiseAlt,
730
 
                                                                  departureTime,
731
 
                                                                  arrivalTime,
732
 
                                                                  repeat,
733
 
                                                                  requiredAircraft));
734
 
        requiredAircraft = "";
735
 
    } else if (!strcmp(name, "aircraft")) {
736
 
        endAircraft();
737
 
    }
738
 
    
739
 
    elementValueStack.pop_back();
740
 
}
741
 
 
742
 
void FGTrafficManager::endAircraft()
743
 
{
744
 
    string isHeavy = heavy ? "true" : "false";
745
 
 
746
 
    if (missingModels.find(mdl) != missingModels.end()) {
747
 
    // don't stat() or warn again
748
 
        requiredAircraft = homePort = "";
749
 
        return;
750
 
    }
751
 
    
752
 
    if (!FGAISchedule::validModelPath(mdl)) {
753
 
        missingModels.insert(mdl);
754
 
        SG_LOG(SG_AI, SG_WARN, "TrafficMgr: Missing model path:" << mdl);
755
 
        requiredAircraft = homePort = "";
756
 
        return;
757
 
    }
758
 
        
759
 
    int proportion =
760
 
        (int) (fgGetDouble("/sim/traffic-manager/proportion") * 100);
761
 
    int randval = rand() & 100;
762
 
    if (randval > proportion) {
763
 
        requiredAircraft = homePort = "";
764
 
        return;
765
 
    }
766
 
    
767
 
    if (fgGetBool("/sim/traffic-manager/dumpdata") == true) {
768
 
        SG_LOG(SG_AI, SG_ALERT, "Traffic Dump AC," << homePort << "," << registration << "," << requiredAircraft
769
 
               << "," << acType << "," << livery << "," 
770
 
               << airline << ","  << m_class << "," << offset << "," << radius << "," << flighttype << "," << isHeavy << "," << mdl);
771
 
    }
772
 
 
773
 
    if (requiredAircraft == "") {
774
 
        char buffer[16];
775
 
        snprintf(buffer, 16, "%d", acCounter);
776
 
        requiredAircraft = buffer;
777
 
    }
778
 
    if (homePort == "") {
779
 
        homePort = departurePort;
780
 
    }
781
 
    
782
 
    scheduledAircraft.push_back(new FGAISchedule(mdl,
783
 
                                                 livery,
784
 
                                                 homePort,
785
 
                                                 registration,
786
 
                                                 requiredAircraft,
787
 
                                                 heavy,
788
 
                                                 acType,
789
 
                                                 airline,
790
 
                                                 m_class,
791
 
                                                 flighttype,
792
 
                                                 radius, offset));
793
 
            
794
 
    acCounter++;
795
 
    requiredAircraft = "";
796
 
    homePort = "";
797
 
    score = 0;
798
 
}
799
 
    
800
 
void FGTrafficManager::data(const char *s, int len)
801
 
{
802
 
    string token = string(s, len);
803
 
    //cout << "Character data " << string(s,len) << endl;
804
 
    elementValueStack.back() += token;
805
 
}
806
 
 
807
 
void FGTrafficManager::pi(const char *target, const char *data)
808
 
{
809
 
    //cout << "Processing instruction " << target << ' ' << data << endl;
810
 
}
811
 
 
812
 
void FGTrafficManager::warning(const char *message, int line, int column)
813
 
{
814
 
    SG_LOG(SG_IO, SG_WARN,
815
 
           "Warning: " << message << " (" << line << ',' << column << ')');
816
 
}
817
 
 
818
 
void FGTrafficManager::error(const char *message, int line, int column)
819
 
{
820
 
    SG_LOG(SG_IO, SG_ALERT,
821
 
           "Error: " << message << " (" << line << ',' << column << ')');
822
 
}