]> git.mxchange.org Git - flightgear.git/blob - src/Traffic/TrafficMgr.cxx
Support disabling AI traffic at run-time.
[flightgear.git] / src / Traffic / TrafficMgr.cxx
1 /******************************************************************************
2  * TrafficMGr.cxx
3  * Written by Durk Talsma, started May 5, 2004.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  *
19  *
20  **************************************************************************/
21
22 /* 
23  * Traffic manager parses airlines timetable-like data and uses this to 
24  * determine the approximate position of each AI aircraft in its database.
25  * When an AI aircraft is close to the user's position, a more detailed 
26  * AIModels based simulation is set up. 
27  * 
28  * I'm currently assuming the following simplifications:
29  * 1) The earth is a perfect sphere
30  * 2) Each aircraft flies a perfect great circle route.
31  * 3) Each aircraft flies at a constant speed (with infinite accelerations and
32  *    decelerations) 
33  * 4) Each aircraft leaves at exactly the departure time. 
34  * 5) Each aircraft arrives at exactly the specified arrival time. 
35  *
36  *
37  *****************************************************************************/
38
39 #ifdef HAVE_CONFIG_H
40 #  include "config.h"
41 #endif
42
43 #include <stdlib.h>
44 #include <time.h>
45 #include <cstring>
46 #include <iostream>
47 #include <fstream>
48
49
50 #include <string>
51 #include <vector>
52 #include <algorithm>
53 #include <boost/foreach.hpp>
54
55 #include <simgear/compiler.h>
56 #include <simgear/misc/sg_path.hxx>
57 #include <simgear/misc/sg_dir.hxx>
58 #include <simgear/props/props.hxx>
59 #include <simgear/route/waypoint.hxx>
60 #include <simgear/structure/subsystem_mgr.hxx>
61 #include <simgear/xml/easyxml.hxx>
62
63 #include <AIModel/AIAircraft.hxx>
64 #include <AIModel/AIFlightPlan.hxx>
65 #include <AIModel/AIBase.hxx>
66 #include <Airports/simple.hxx>
67 #include <Main/fg_init.hxx>
68
69
70
71 #include "TrafficMgr.hxx"
72
73 using std::sort;
74 using std::strcmp;
75
76 /******************************************************************************
77  * TrafficManager
78  *****************************************************************************/
79 FGTrafficManager::FGTrafficManager() :
80   inited(false),
81   doingInit(false),
82   enabled("/sim/traffic-manager/enabled"),
83   aiEnabled("/sim/ai/enabled"),
84   realWxEnabled("/environment/realwx/enabled"),
85   metarValid("/environment/metar/valid")
86 {
87     //score = 0;
88     //runCount = 0;
89     acCounter = 0;
90 }
91
92 FGTrafficManager::~FGTrafficManager()
93 {
94     shutdown();
95 }
96
97 void FGTrafficManager::shutdown()
98 {
99     // Save the heuristics data
100     bool saveData = false;
101     ofstream cachefile;
102     if (fgGetBool("/sim/traffic-manager/heuristics")) {
103         SGPath cacheData(fgGetString("/sim/fg-home"));
104         cacheData.append("ai");
105         string airport = fgGetString("/sim/presets/airport-id");
106
107         if ((airport) != "") {
108             char buffer[128];
109             ::snprintf(buffer, 128, "%c/%c/%c/",
110                        airport[0], airport[1], airport[2]);
111             cacheData.append(buffer);
112             if (!cacheData.exists()) {
113                 cacheData.create_dir(0777);
114             }
115             cacheData.append(airport + "-cache.txt");
116             //cerr << "Saving AI traffic heuristics" << endl;
117             saveData = true;
118             cachefile.open(cacheData.str().c_str());
119             cachefile << "[TrafficManagerCachedata:ref:2011:09:04]" << endl;
120         }
121     }
122     for (ScheduleVectorIterator sched = scheduledAircraft.begin();
123          sched != scheduledAircraft.end(); sched++) {
124         if (saveData) {
125             cachefile << (*sched)->getRegistration() << " "
126                 << (*sched)->getRunCount() << " "
127                 << (*sched)->getHits() << " "
128                 << (*sched)->getLastUsed() << endl;
129         }
130         delete(*sched);
131     }
132     if (saveData) {
133         cachefile.close();
134     }
135     scheduledAircraft.clear();
136     flights.clear();
137     releaseList.clear();
138
139     currAircraft = scheduledAircraft.begin();
140     doingInit = false;
141     inited = false;
142 }
143
144
145 void FGTrafficManager::init()
146 {
147     if (!enabled) {
148       return;
149     }
150
151     assert(!doingInit);
152     doingInit = true;
153     if (string(fgGetString("/sim/traffic-manager/datafile")) == string("")) {
154         simgear::Dir trafficDir(SGPath(globals->get_fg_root(), "AI/Traffic"));
155         simgear::PathList d = trafficDir.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT);
156         
157         BOOST_FOREACH(SGPath p, d) {
158           simgear::Dir d2(p);
159           simgear::PathList trafficFiles = d2.children(simgear::Dir::TYPE_FILE, ".xml");
160           schedulesToRead.insert(schedulesToRead.end(), trafficFiles.begin(), trafficFiles.end());
161         }
162     } else {
163         fgSetBool("/sim/traffic-manager/heuristics", false);
164         SGPath path = string(fgGetString("/sim/traffic-manager/datafile"));
165         string ext = path.extension();
166         if (path.extension() == "xml") {
167             if (path.exists()) {
168                 readXML(path.str(), *this);
169             }
170         } else if (path.extension() == "conf") {
171             if (path.exists()) {
172                 readTimeTableFromFile(path);
173             }
174         } else {
175              SG_LOG(SG_AI, SG_ALERT,
176                                "Unknown data format " << path.str()
177                                 << " for traffic");
178         }
179         //exit(1);
180     }
181 }
182
183 void FGTrafficManager::initStep()
184 {
185     assert(doingInit);
186     if (schedulesToRead.empty()) {
187         finishInit();
188         return;
189     }
190     
191     SGPath path = schedulesToRead.front();
192     schedulesToRead.erase(schedulesToRead.begin());
193     SG_LOG(SG_AI, SG_DEBUG, path << " for traffic");
194     readXML(path.str(), *this);
195 }
196
197 void FGTrafficManager::finishInit()
198 {
199     assert(doingInit);
200     SG_LOG(SG_AI, SG_INFO, "finishing AI-Traffic init");
201     loadHeuristics();
202     
203     // Do sorting and scoring separately, to take advantage of the "homeport| variable
204     for (currAircraft = scheduledAircraft.begin();
205          currAircraft != scheduledAircraft.end(); currAircraft++) {
206         (*currAircraft)->setScore();
207     }
208     
209     sort(scheduledAircraft.begin(), scheduledAircraft.end(),
210          compareSchedules);
211     currAircraft = scheduledAircraft.begin();
212     currAircraftClosest = scheduledAircraft.begin();
213     
214     doingInit = false;
215     inited = true;
216 }
217
218 void FGTrafficManager::loadHeuristics()
219 {
220     if (!fgGetBool("/sim/traffic-manager/heuristics")) {
221         return;
222     }
223   
224     HeuristicMap heurMap;
225     //cerr << "Processing Heuristics" << endl;
226     // Load the heuristics data
227     SGPath cacheData(fgGetString("/sim/fg-home"));
228     cacheData.append("ai");
229     string airport = fgGetString("/sim/presets/airport-id");
230     if ((airport) != "") {
231       char buffer[128];
232       ::snprintf(buffer, 128, "%c/%c/%c/",
233                  airport[0], airport[1], airport[2]);
234       cacheData.append(buffer);
235       cacheData.append(airport + "-cache.txt");
236       string revisionStr;
237       if (cacheData.exists()) {
238         ifstream data(cacheData.c_str());
239         data >> revisionStr;
240         if (revisionStr != "[TrafficManagerCachedata:ref:2011:09:04]") {
241           SG_LOG(SG_GENERAL, SG_ALERT,"Traffic Manager Warning: discarding outdated cachefile " << 
242                  cacheData.c_str() << " for Airport " << airport);
243         } else {
244           while (1) {
245             Heuristic h; // = new Heuristic;
246             data >> h.registration >> h.runCount >> h.hits >> h.lastRun;
247             if (data.eof())
248               break;
249             HeuristicMapIterator itr = heurMap.find(h.registration);
250             if (itr != heurMap.end()) {
251               SG_LOG(SG_GENERAL, SG_WARN,"Traffic Manager Warning: found duplicate tailnumber " << 
252                      h.registration << " for AI aircraft");
253             } else {
254               heurMap[h.registration] = h;
255             }
256           }
257         }
258       }
259     } 
260     
261   for(currAircraft = scheduledAircraft.begin(); currAircraft != scheduledAircraft.end(); ++currAircraft) {
262         string registration = (*currAircraft)->getRegistration();
263         HeuristicMapIterator itr = heurMap.find(registration);
264         if (itr != heurMap.end()) {
265             (*currAircraft)->setrunCount(itr->second.runCount);
266             (*currAircraft)->setHits(itr->second.hits);
267             (*currAircraft)->setLastUsed(itr->second.lastRun);
268         }
269     }
270 }
271
272 void FGTrafficManager::update(double /*dt */ )
273 {
274     if (!enabled)
275     {
276         if (inited || doingInit)
277             shutdown();
278         return;
279     }
280
281     if ((realWxEnabled && !metarValid)) {
282         return;
283     }
284
285     if (!aiEnabled)
286     {
287         // traffic depends on AI module
288         aiEnabled = true;
289     }
290
291     if (!inited) {
292         if (!doingInit) {
293             init();
294         }
295         
296         initStep();
297         if (!inited) {
298             return; // still more to do on next update() call
299         }
300     }
301         
302     time_t now = time(NULL) + fgGetLong("/sim/time/warp");
303     if (scheduledAircraft.size() == 0) {
304         return;
305     }
306
307     SGVec3d userCart = globals->get_aircraft_positon_cart();
308
309     if (currAircraft == scheduledAircraft.end()) {
310         currAircraft = scheduledAircraft.begin();
311     }
312     //cerr << "Processing << " << (*currAircraft)->getRegistration() << " with score " << (*currAircraft)->getScore() << endl;
313     if (!((*currAircraft)->update(now, userCart))) {
314         (*currAircraft)->taint();
315     }
316     currAircraft++;
317 }
318
319 void FGTrafficManager::release(int id)
320 {
321     releaseList.push_back(id);
322 }
323
324 bool FGTrafficManager::isReleased(int id)
325 {
326     IdListIterator i = releaseList.begin();
327     while (i != releaseList.end()) {
328         if ((*i) == id) {
329             releaseList.erase(i);
330             return true;
331         }
332         i++;
333     }
334     return false;
335 }
336
337
338 void FGTrafficManager::readTimeTableFromFile(SGPath infileName)
339 {
340     string model;
341     string livery;
342     string homePort;
343     string registration;
344     string flightReq;
345     bool   isHeavy;
346     string acType;
347     string airline;
348     string m_class;
349     string FlightType;
350     double radius;
351     double offset;
352
353     char buffer[256];
354     string buffString;
355     vector <string> tokens, depTime,arrTime;
356     vector <string>::iterator it;
357     ifstream infile(infileName.str().c_str());
358     while (1) {
359          infile.getline(buffer, 256);
360          if (infile.eof()) {
361              break;
362          }
363          //cerr << "Read line : " << buffer << endl;
364          buffString = string(buffer);
365          tokens.clear();
366          Tokenize(buffString, tokens, " \t");
367          //for (it = tokens.begin(); it != tokens.end(); it++) {
368          //    cerr << "Tokens: " << *(it) << endl;
369          //}
370          //cerr << endl;
371          if (!tokens.empty()) {
372              if (tokens[0] == string("AC")) {
373                  if (tokens.size() != 13) {
374                      SG_LOG(SG_GENERAL, SG_ALERT, "Error parsing traffic file " << infileName.str() << " at " << buffString);
375                      exit(1);
376                  }
377                  model          = tokens[12];
378                  livery         = tokens[6];
379                  homePort       = tokens[1];
380                  registration   = tokens[2];
381                  if (tokens[11] == string("false")) {
382                      isHeavy = false;
383                  } else {
384                      isHeavy = true;
385                  }
386                  acType         = tokens[4];
387                  airline        = tokens[5];
388                  flightReq      = tokens[3] + tokens[5];
389                  m_class        = tokens[10];
390                  FlightType     = tokens[9];
391                  radius         = atof(tokens[8].c_str());
392                  offset         = atof(tokens[7].c_str());;
393                  SG_LOG(SG_GENERAL, SG_ALERT, "Adding Aircraft" << model << " " << livery << " " << homePort << " " 
394                                                                 << registration << " " << flightReq << " " << isHeavy 
395                                                                 << " " << acType << " " << airline << " " << m_class 
396                                                                 << " " << FlightType << " " << radius << " " << offset);
397                  scheduledAircraft.push_back(new FGAISchedule(model, 
398                                                               livery, 
399                                                               homePort,
400                                                               registration, 
401                                                               flightReq,
402                                                               isHeavy,
403                                                               acType, 
404                                                               airline, 
405                                                               m_class, 
406                                                               FlightType,
407                                                               radius,
408                                                               offset));
409              }
410              if (tokens[0] == string("FLIGHT")) {
411                  //cerr << "Found flight " << buffString << " size is : " << tokens.size() << endl;
412                  if (tokens.size() != 10) {
413                      SG_LOG(SG_GENERAL, SG_ALERT, "Error parsing traffic file " << infileName.str() << " at " << buffString);
414                      exit(1);
415                  }
416                  string callsign = tokens[1];
417                  string fltrules = tokens[2];
418                  string weekdays = tokens[3];
419                  string departurePort = tokens[5];
420                  string arrivalPort   = tokens[7];
421                  int    cruiseAlt     = atoi(tokens[8].c_str());
422                  string depTimeGen    = tokens[4];
423                  string arrTimeGen    = tokens[6];
424                  string repeat        = "WEEK";
425                  string requiredAircraft = tokens[9];
426
427                  if (weekdays.size() != 7) {
428                      SG_LOG(SG_GENERAL, SG_ALERT, "Found misconfigured weekdays string" << weekdays);
429                      exit(1);
430                  }
431                  depTime.clear();
432                  arrTime.clear();
433                  Tokenize(depTimeGen, depTime, ":");
434                  Tokenize(arrTimeGen, arrTime, ":");
435                  double dep = atof(depTime[0].c_str()) + (atof(depTime[1].c_str()) / 60.0);
436                  double arr = atof(arrTime[0].c_str()) + (atof(arrTime[1].c_str()) / 60.0);
437                  //cerr << "Using " << dep << " " << arr << endl;
438                  bool arrivalWeekdayNeedsIncrement = false;
439                  if (arr < dep) {
440                        arrivalWeekdayNeedsIncrement = true;
441                  }
442                  for (int i = 0; i < 7; i++) {
443                      int j = i+1;
444                      if (weekdays[i] != '.') {
445                          char buffer[4];
446                          snprintf(buffer, 4, "%d/", j);
447                          string departureTime = string(buffer) + depTimeGen + string(":00");
448                          string arrivalTime;
449                          if (!arrivalWeekdayNeedsIncrement) {
450                              arrivalTime   = string(buffer) + arrTimeGen + string(":00");
451                          }
452                          if (arrivalWeekdayNeedsIncrement && i != 6 ) {
453                              snprintf(buffer, 4, "%d/", j+1);
454                              arrivalTime   = string(buffer) + arrTimeGen + string(":00");
455                          }
456                          if (arrivalWeekdayNeedsIncrement && i == 6 ) {
457                              snprintf(buffer, 4, "%d/", 0);
458                              arrivalTime   = string(buffer) + arrTimeGen  + string(":00");
459                          }
460                          SG_LOG(SG_GENERAL, SG_ALERT, "Adding flight " << callsign       << " "
461                                                       << fltrules       << " "
462                                                       <<  departurePort << " "
463                                                       <<  arrivalPort   << " "
464                                                       <<  cruiseAlt     << " "
465                                                       <<  departureTime << " "
466                                                       <<  arrivalTime   << " "
467                                                       << repeat        << " " 
468                                                       <<  requiredAircraft);
469
470                          flights[requiredAircraft].push_back(new FGScheduledFlight(callsign,
471                                                                  fltrules,
472                                                                  departurePort,
473                                                                  arrivalPort,
474                                                                  cruiseAlt,
475                                                                  departureTime,
476                                                                  arrivalTime,
477                                                                  repeat,
478                                                                  requiredAircraft));
479                     }
480                 }
481              }
482          }
483
484     }
485     //exit(1);
486 }
487
488
489 void FGTrafficManager::Tokenize(const string& str,
490                       vector<string>& tokens,
491                       const string& delimiters)
492 {
493     // Skip delimiters at beginning.
494     string::size_type lastPos = str.find_first_not_of(delimiters, 0);
495     // Find first "non-delimiter".
496     string::size_type pos     = str.find_first_of(delimiters, lastPos);
497
498     while (string::npos != pos || string::npos != lastPos)
499     {
500         // Found a token, add it to the vector.
501         tokens.push_back(str.substr(lastPos, pos - lastPos));
502         // Skip delimiters.  Note the "not_of"
503         lastPos = str.find_first_not_of(delimiters, pos);
504         // Find next "non-delimiter"
505         pos = str.find_first_of(delimiters, lastPos);
506     }
507 }
508
509
510 void FGTrafficManager::startXML()
511 {
512     //cout << "Start XML" << endl;
513     requiredAircraft = "";
514     homePort = "";
515 }
516
517 void FGTrafficManager::endXML()
518 {
519     //cout << "End XML" << endl;
520 }
521
522 void FGTrafficManager::startElement(const char *name,
523                                     const XMLAttributes & atts)
524 {
525     const char *attval;
526     //cout << "Start element " << name << endl;
527     //FGTrafficManager temp;
528     //for (int i = 0; i < atts.size(); i++)
529     //  if (string(atts.getName(i)) == string("include"))
530     attval = atts.getValue("include");
531     if (attval != 0) {
532         //cout << "including " << attval << endl;
533         SGPath path = globals->get_fg_root();
534         path.append("/Traffic/");
535         path.append(attval);
536         readXML(path.str(), *this);
537     }
538     elementValueStack.push_back("");
539     //  cout << "  " << atts.getName(i) << '=' << atts.getValue(i) << endl; 
540 }
541
542 void FGTrafficManager::endElement(const char *name)
543 {
544     //cout << "End element " << name << endl;
545     const string & value = elementValueStack.back();
546
547     if (!strcmp(name, "model"))
548         mdl = value;
549     else if (!strcmp(name, "livery"))
550         livery = value;
551     else if (!strcmp(name, "home-port"))
552         homePort = value;
553     else if (!strcmp(name, "registration"))
554         registration = value;
555     else if (!strcmp(name, "airline"))
556         airline = value;
557     else if (!strcmp(name, "actype"))
558         acType = value;
559     else if (!strcmp(name, "required-aircraft"))
560         requiredAircraft = value;
561     else if (!strcmp(name, "flighttype"))
562         flighttype = value;
563     else if (!strcmp(name, "radius"))
564         radius = atoi(value.c_str());
565     else if (!strcmp(name, "offset"))
566         offset = atoi(value.c_str());
567     else if (!strcmp(name, "performance-class"))
568         m_class = value;
569     else if (!strcmp(name, "heavy")) {
570         if (value == string("true"))
571             heavy = true;
572         else
573             heavy = false;
574     } else if (!strcmp(name, "callsign"))
575         callsign = value;
576     else if (!strcmp(name, "fltrules"))
577         fltrules = value;
578     else if (!strcmp(name, "port"))
579         port = value;
580     else if (!strcmp(name, "time"))
581         timeString = value;
582     else if (!strcmp(name, "departure")) {
583         departurePort = port;
584         departureTime = timeString;
585     } else if (!strcmp(name, "cruise-alt"))
586         cruiseAlt = atoi(value.c_str());
587     else if (!strcmp(name, "arrival")) {
588         arrivalPort = port;
589         arrivalTime = timeString;
590     } else if (!strcmp(name, "repeat"))
591         repeat = value;
592     else if (!strcmp(name, "flight")) {
593         // We have loaded and parsed all the information belonging to this flight
594         // so we temporarily store it. 
595         //cerr << "Pusing back flight " << callsign << endl;
596         //cerr << callsign  <<  " " << fltrules     << " "<< departurePort << " " <<  arrivalPort << " "
597         //   << cruiseAlt <<  " " << departureTime<< " "<< arrivalTime   << " " << repeat << endl;
598
599         //Prioritize aircraft 
600         string apt = fgGetString("/sim/presets/airport-id");
601         //cerr << "Airport information: " << apt << " " << departurePort << " " << arrivalPort << endl;
602         //if (departurePort == apt) score++;
603         //flights.push_back(new FGScheduledFlight(callsign,
604         //                                fltrules,
605         //                                departurePort,
606         //                                arrivalPort,
607         //                                cruiseAlt,
608         //                                departureTime,
609         //                                arrivalTime,
610         //                                repeat));
611         if (requiredAircraft == "") {
612             char buffer[16];
613             snprintf(buffer, 16, "%d", acCounter);
614             requiredAircraft = buffer;
615         }
616         SG_LOG(SG_GENERAL, SG_DEBUG, "Adding flight: " << callsign << " "
617                << fltrules << " "
618                << departurePort << " "
619                << arrivalPort << " "
620                << cruiseAlt << " "
621                << departureTime << " "
622                << arrivalTime << " " << repeat << " " << requiredAircraft);
623         // For database maintainance purposes, it may be convenient to
624         // 
625         if (fgGetBool("/sim/traffic-manager/dumpdata") == true) {
626              SG_LOG(SG_GENERAL, SG_ALERT, "Traffic Dump FLIGHT," << callsign << ","
627                           << fltrules << ","
628                           << departurePort << ","
629                           << arrivalPort << ","
630                           << cruiseAlt << ","
631                           << departureTime << ","
632                           << arrivalTime << "," << repeat << "," << requiredAircraft);
633         }
634         flights[requiredAircraft].push_back(new FGScheduledFlight(callsign,
635                                                                   fltrules,
636                                                                   departurePort,
637                                                                   arrivalPort,
638                                                                   cruiseAlt,
639                                                                   departureTime,
640                                                                   arrivalTime,
641                                                                   repeat,
642                                                                   requiredAircraft));
643         requiredAircraft = "";
644     } else if (!strcmp(name, "aircraft")) {
645         string isHeavy;
646         if (heavy) {
647             isHeavy = "true";
648         } else {
649             isHeavy = "false"; 
650         }
651         /*
652         cerr << "Traffic Dump AC," << homePort << "," << registration << "," << requiredAircraft 
653              << "," << acType << "," << livery << "," 
654              << airline << "," << offset << "," << radius << "," << flighttype << "," << isHeavy << "," << mdl << endl;*/
655         int proportion =
656             (int) (fgGetDouble("/sim/traffic-manager/proportion") * 100);
657         int randval = rand() & 100;
658         if (randval <= proportion) {
659             if (fgGetBool("/sim/traffic-manager/dumpdata") == true) {
660                 SG_LOG(SG_GENERAL, SG_ALERT, "Traffic Dump AC," << homePort << "," << registration << "," << requiredAircraft 
661                  << "," << acType << "," << livery << "," 
662                  << airline << ","  << m_class << "," << offset << "," << radius << "," << flighttype << "," << isHeavy << "," << mdl);
663             }
664             //scheduledAircraft.push_back(new FGAISchedule(mdl, 
665             //                                     livery, 
666             //                                     registration, 
667             //                                     heavy,
668             //                                     acType, 
669             //                                     airline, 
670             //                                     m_class, 
671             //                                     flighttype,
672             //                                     radius,
673             //                                     offset,
674             //                                     score,
675             //                                     flights));
676             if (requiredAircraft == "") {
677                 char buffer[16];
678                 snprintf(buffer, 16, "%d", acCounter);
679                 requiredAircraft = buffer;
680             }
681             if (homePort == "") {
682                 homePort = departurePort;
683             }
684             scheduledAircraft.push_back(new FGAISchedule(mdl,
685                                                          livery,
686                                                          homePort,
687                                                          registration,
688                                                          requiredAircraft,
689                                                          heavy,
690                                                          acType,
691                                                          airline,
692                                                          m_class,
693                                                          flighttype,
694                                                          radius, offset));
695
696             //  while(flights.begin() != flights.end()) {
697 //      flights.pop_back();
698 //       }
699         } else {
700             cerr << "Skipping : " << randval;
701         }
702         acCounter++;
703         requiredAircraft = "";
704         homePort = "";
705         //for (FGScheduledFlightVecIterator flt = flights.begin(); flt != flights.end(); flt++)
706         //  {
707         //    delete (*flt);
708         //  }
709         //flights.clear();
710         SG_LOG(SG_GENERAL, SG_BULK, "Reading aircraft : "
711                << registration << " with prioritization score " << score);
712         score = 0;
713     }
714     elementValueStack.pop_back();
715 }
716
717 void FGTrafficManager::data(const char *s, int len)
718 {
719     string token = string(s, len);
720     //cout << "Character data " << string(s,len) << endl;
721     elementValueStack.back() += token;
722 }
723
724 void FGTrafficManager::pi(const char *target, const char *data)
725 {
726     //cout << "Processing instruction " << target << ' ' << data << endl;
727 }
728
729 void FGTrafficManager::warning(const char *message, int line, int column)
730 {
731     SG_LOG(SG_IO, SG_WARN,
732            "Warning: " << message << " (" << line << ',' << column << ')');
733 }
734
735 void FGTrafficManager::error(const char *message, int line, int column)
736 {
737     SG_LOG(SG_IO, SG_ALERT,
738            "Error: " << message << " (" << line << ',' << column << ')');
739 }