]> git.mxchange.org Git - flightgear.git/blob - src/Traffic/TrafficMgr.cxx
#248: support enabling AI module 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     // Save the heuristics data
95     bool saveData = false;
96     ofstream cachefile;
97     if (fgGetBool("/sim/traffic-manager/heuristics")) {
98         SGPath cacheData(fgGetString("/sim/fg-home"));
99         cacheData.append("ai");
100         string airport = fgGetString("/sim/presets/airport-id");
101
102         if ((airport) != "") {
103             char buffer[128];
104             ::snprintf(buffer, 128, "%c/%c/%c/",
105                        airport[0], airport[1], airport[2]);
106             cacheData.append(buffer);
107             if (!cacheData.exists()) {
108                 cacheData.create_dir(0777);
109             }
110             cacheData.append(airport + "-cache.txt");
111             //cerr << "Saving AI traffic heuristics" << endl;
112             saveData = true;
113             cachefile.open(cacheData.str().c_str());
114             cachefile << "[TrafficManagerCachedata:ref:2011:09:04]" << endl;
115         }
116     }
117     for (ScheduleVectorIterator sched = scheduledAircraft.begin();
118          sched != scheduledAircraft.end(); sched++) {
119         if (saveData) {
120             cachefile << (*sched)->getRegistration() << " "
121                 << (*sched)->getRunCount() << " "
122                 << (*sched)->getHits() << " "
123                 << (*sched)->getLastUsed() << endl;
124         }
125         delete(*sched);
126     }
127     if (saveData) {
128         cachefile.close();
129     }
130     scheduledAircraft.clear();
131     flights.clear();
132 }
133
134
135 void FGTrafficManager::init()
136 {
137     if (!enabled) {
138       return;
139     }
140
141     assert(!doingInit);
142     doingInit = true;
143     if (string(fgGetString("/sim/traffic-manager/datafile")) == string("")) {
144         simgear::Dir trafficDir(SGPath(globals->get_fg_root(), "AI/Traffic"));
145         simgear::PathList d = trafficDir.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT);
146         
147         BOOST_FOREACH(SGPath p, d) {
148           simgear::Dir d2(p);
149           simgear::PathList trafficFiles = d2.children(simgear::Dir::TYPE_FILE, ".xml");
150           schedulesToRead.insert(schedulesToRead.end(), trafficFiles.begin(), trafficFiles.end());
151         }
152     } else {
153         fgSetBool("/sim/traffic-manager/heuristics", false);
154         SGPath path = string(fgGetString("/sim/traffic-manager/datafile"));
155         string ext = path.extension();
156         if (path.extension() == "xml") {
157             if (path.exists()) {
158                 readXML(path.str(), *this);
159             }
160         } else if (path.extension() == "conf") {
161             if (path.exists()) {
162                 readTimeTableFromFile(path);
163             }
164         } else {
165              SG_LOG(SG_AI, SG_ALERT,
166                                "Unknown data format " << path.str()
167                                 << " for traffic");
168         }
169         //exit(1);
170     }
171 }
172
173 void FGTrafficManager::initStep()
174 {
175     assert(doingInit);
176     if (schedulesToRead.empty()) {
177         finishInit();
178         return;
179     }
180     
181     SGPath path = schedulesToRead.front();
182     schedulesToRead.erase(schedulesToRead.begin());
183     SG_LOG(SG_AI, SG_DEBUG, path << " for traffic");
184     readXML(path.str(), *this);
185 }
186
187 void FGTrafficManager::finishInit()
188 {
189     assert(doingInit);
190     SG_LOG(SG_AI, SG_INFO, "finishing AI-Traffic init");
191     loadHeuristics();
192     
193     // Do sorting and scoring separately, to take advantage of the "homeport| variable
194     for (currAircraft = scheduledAircraft.begin();
195          currAircraft != scheduledAircraft.end(); currAircraft++) {
196         (*currAircraft)->setScore();
197     }
198     
199     sort(scheduledAircraft.begin(), scheduledAircraft.end(),
200          compareSchedules);
201     currAircraft = scheduledAircraft.begin();
202     currAircraftClosest = scheduledAircraft.begin();
203     
204     doingInit = false;
205     inited = true;
206 }
207
208 void FGTrafficManager::loadHeuristics()
209 {
210     if (!fgGetBool("/sim/traffic-manager/heuristics")) {
211         return;
212     }
213   
214     HeuristicMap heurMap;
215     //cerr << "Processing Heuristics" << endl;
216     // Load the heuristics data
217     SGPath cacheData(fgGetString("/sim/fg-home"));
218     cacheData.append("ai");
219     string airport = fgGetString("/sim/presets/airport-id");
220     if ((airport) != "") {
221       char buffer[128];
222       ::snprintf(buffer, 128, "%c/%c/%c/",
223                  airport[0], airport[1], airport[2]);
224       cacheData.append(buffer);
225       cacheData.append(airport + "-cache.txt");
226       string revisionStr;
227       if (cacheData.exists()) {
228         ifstream data(cacheData.c_str());
229         data >> revisionStr;
230         if (revisionStr != "[TrafficManagerCachedata:ref:2011:09:04]") {
231           SG_LOG(SG_GENERAL, SG_ALERT,"Traffic Manager Warning: discarding outdated cachefile " << 
232                  cacheData.c_str() << " for Airport " << airport);
233         } else {
234           while (1) {
235             Heuristic h; // = new Heuristic;
236             data >> h.registration >> h.runCount >> h.hits >> h.lastRun;
237             if (data.eof())
238               break;
239             HeuristicMapIterator itr = heurMap.find(h.registration);
240             if (itr != heurMap.end()) {
241               SG_LOG(SG_GENERAL, SG_WARN,"Traffic Manager Warning: found duplicate tailnumber " << 
242                      h.registration << " for AI aircraft");
243             } else {
244               heurMap[h.registration] = h;
245             }
246           }
247         }
248       }
249     } 
250     
251   for(currAircraft = scheduledAircraft.begin(); currAircraft != scheduledAircraft.end(); ++currAircraft) {
252         string registration = (*currAircraft)->getRegistration();
253         HeuristicMapIterator itr = heurMap.find(registration);
254         if (itr != heurMap.end()) {
255             (*currAircraft)->setrunCount(itr->second.runCount);
256             (*currAircraft)->setHits(itr->second.hits);
257             (*currAircraft)->setLastUsed(itr->second.lastRun);
258         }
259     }
260 }
261
262 void FGTrafficManager::update(double /*dt */ )
263 {
264     if (!enabled || (realWxEnabled && !metarValid)) {
265         return;
266     }
267
268     if (!aiEnabled)
269     {
270         // traffic depends on AI module
271         aiEnabled = true;
272     }
273
274     if (!inited) {
275         if (!doingInit) {
276             init();
277         }
278         
279         initStep();
280         if (!inited) {
281             return; // still more to do on next update() call
282         }
283     }
284         
285     time_t now = time(NULL) + fgGetLong("/sim/time/warp");
286     if (scheduledAircraft.size() == 0) {
287         return;
288     }
289
290     SGVec3d userCart = globals->get_aircraft_positon_cart();
291
292     if (currAircraft == scheduledAircraft.end()) {
293         currAircraft = scheduledAircraft.begin();
294     }
295     //cerr << "Processing << " << (*currAircraft)->getRegistration() << " with score " << (*currAircraft)->getScore() << endl;
296     if (!((*currAircraft)->update(now, userCart))) {
297         (*currAircraft)->taint();
298     }
299     currAircraft++;
300 }
301
302 void FGTrafficManager::release(int id)
303 {
304     releaseList.push_back(id);
305 }
306
307 bool FGTrafficManager::isReleased(int id)
308 {
309     IdListIterator i = releaseList.begin();
310     while (i != releaseList.end()) {
311         if ((*i) == id) {
312             releaseList.erase(i);
313             return true;
314         }
315         i++;
316     }
317     return false;
318 }
319
320
321 void FGTrafficManager::readTimeTableFromFile(SGPath infileName)
322 {
323     string model;
324     string livery;
325     string homePort;
326     string registration;
327     string flightReq;
328     bool   isHeavy;
329     string acType;
330     string airline;
331     string m_class;
332     string FlightType;
333     double radius;
334     double offset;
335
336     char buffer[256];
337     string buffString;
338     vector <string> tokens, depTime,arrTime;
339     vector <string>::iterator it;
340     ifstream infile(infileName.str().c_str());
341     while (1) {
342          infile.getline(buffer, 256);
343          if (infile.eof()) {
344              break;
345          }
346          //cerr << "Read line : " << buffer << endl;
347          buffString = string(buffer);
348          tokens.clear();
349          Tokenize(buffString, tokens, " \t");
350          //for (it = tokens.begin(); it != tokens.end(); it++) {
351          //    cerr << "Tokens: " << *(it) << endl;
352          //}
353          //cerr << endl;
354          if (!tokens.empty()) {
355              if (tokens[0] == string("AC")) {
356                  if (tokens.size() != 13) {
357                      SG_LOG(SG_GENERAL, SG_ALERT, "Error parsing traffic file " << infileName.str() << " at " << buffString);
358                      exit(1);
359                  }
360                  model          = tokens[12];
361                  livery         = tokens[6];
362                  homePort       = tokens[1];
363                  registration   = tokens[2];
364                  if (tokens[11] == string("false")) {
365                      isHeavy = false;
366                  } else {
367                      isHeavy = true;
368                  }
369                  acType         = tokens[4];
370                  airline        = tokens[5];
371                  flightReq      = tokens[3] + tokens[5];
372                  m_class        = tokens[10];
373                  FlightType     = tokens[9];
374                  radius         = atof(tokens[8].c_str());
375                  offset         = atof(tokens[7].c_str());;
376                  SG_LOG(SG_GENERAL, SG_ALERT, "Adding Aircraft" << model << " " << livery << " " << homePort << " " 
377                                                                 << registration << " " << flightReq << " " << isHeavy 
378                                                                 << " " << acType << " " << airline << " " << m_class 
379                                                                 << " " << FlightType << " " << radius << " " << offset);
380                  scheduledAircraft.push_back(new FGAISchedule(model, 
381                                                               livery, 
382                                                               homePort,
383                                                               registration, 
384                                                               flightReq,
385                                                               isHeavy,
386                                                               acType, 
387                                                               airline, 
388                                                               m_class, 
389                                                               FlightType,
390                                                               radius,
391                                                               offset));
392              }
393              if (tokens[0] == string("FLIGHT")) {
394                  //cerr << "Found flight " << buffString << " size is : " << tokens.size() << endl;
395                  if (tokens.size() != 10) {
396                      SG_LOG(SG_GENERAL, SG_ALERT, "Error parsing traffic file " << infileName.str() << " at " << buffString);
397                      exit(1);
398                  }
399                  string callsign = tokens[1];
400                  string fltrules = tokens[2];
401                  string weekdays = tokens[3];
402                  string departurePort = tokens[5];
403                  string arrivalPort   = tokens[7];
404                  int    cruiseAlt     = atoi(tokens[8].c_str());
405                  string depTimeGen    = tokens[4];
406                  string arrTimeGen    = tokens[6];
407                  string repeat        = "WEEK";
408                  string requiredAircraft = tokens[9];
409
410                  if (weekdays.size() != 7) {
411                      SG_LOG(SG_GENERAL, SG_ALERT, "Found misconfigured weekdays string" << weekdays);
412                      exit(1);
413                  }
414                  depTime.clear();
415                  arrTime.clear();
416                  Tokenize(depTimeGen, depTime, ":");
417                  Tokenize(arrTimeGen, arrTime, ":");
418                  double dep = atof(depTime[0].c_str()) + (atof(depTime[1].c_str()) / 60.0);
419                  double arr = atof(arrTime[0].c_str()) + (atof(arrTime[1].c_str()) / 60.0);
420                  //cerr << "Using " << dep << " " << arr << endl;
421                  bool arrivalWeekdayNeedsIncrement = false;
422                  if (arr < dep) {
423                        arrivalWeekdayNeedsIncrement = true;
424                  }
425                  for (int i = 0; i < 7; i++) {
426                      int j = i+1;
427                      if (weekdays[i] != '.') {
428                          char buffer[4];
429                          snprintf(buffer, 4, "%d/", j);
430                          string departureTime = string(buffer) + depTimeGen + string(":00");
431                          string arrivalTime;
432                          if (!arrivalWeekdayNeedsIncrement) {
433                              arrivalTime   = string(buffer) + arrTimeGen + string(":00");
434                          }
435                          if (arrivalWeekdayNeedsIncrement && i != 6 ) {
436                              snprintf(buffer, 4, "%d/", j+1);
437                              arrivalTime   = string(buffer) + arrTimeGen + string(":00");
438                          }
439                          if (arrivalWeekdayNeedsIncrement && i == 6 ) {
440                              snprintf(buffer, 4, "%d/", 0);
441                              arrivalTime   = string(buffer) + arrTimeGen  + string(":00");
442                          }
443                          SG_LOG(SG_GENERAL, SG_ALERT, "Adding flight " << callsign       << " "
444                                                       << fltrules       << " "
445                                                       <<  departurePort << " "
446                                                       <<  arrivalPort   << " "
447                                                       <<  cruiseAlt     << " "
448                                                       <<  departureTime << " "
449                                                       <<  arrivalTime   << " "
450                                                       << repeat        << " " 
451                                                       <<  requiredAircraft);
452
453                          flights[requiredAircraft].push_back(new FGScheduledFlight(callsign,
454                                                                  fltrules,
455                                                                  departurePort,
456                                                                  arrivalPort,
457                                                                  cruiseAlt,
458                                                                  departureTime,
459                                                                  arrivalTime,
460                                                                  repeat,
461                                                                  requiredAircraft));
462                     }
463                 }
464              }
465          }
466
467     }
468     //exit(1);
469 }
470
471
472 void FGTrafficManager::Tokenize(const string& str,
473                       vector<string>& tokens,
474                       const string& delimiters)
475 {
476     // Skip delimiters at beginning.
477     string::size_type lastPos = str.find_first_not_of(delimiters, 0);
478     // Find first "non-delimiter".
479     string::size_type pos     = str.find_first_of(delimiters, lastPos);
480
481     while (string::npos != pos || string::npos != lastPos)
482     {
483         // Found a token, add it to the vector.
484         tokens.push_back(str.substr(lastPos, pos - lastPos));
485         // Skip delimiters.  Note the "not_of"
486         lastPos = str.find_first_not_of(delimiters, pos);
487         // Find next "non-delimiter"
488         pos = str.find_first_of(delimiters, lastPos);
489     }
490 }
491
492
493 void FGTrafficManager::startXML()
494 {
495     //cout << "Start XML" << endl;
496     requiredAircraft = "";
497     homePort = "";
498 }
499
500 void FGTrafficManager::endXML()
501 {
502     //cout << "End XML" << endl;
503 }
504
505 void FGTrafficManager::startElement(const char *name,
506                                     const XMLAttributes & atts)
507 {
508     const char *attval;
509     //cout << "Start element " << name << endl;
510     //FGTrafficManager temp;
511     //for (int i = 0; i < atts.size(); i++)
512     //  if (string(atts.getName(i)) == string("include"))
513     attval = atts.getValue("include");
514     if (attval != 0) {
515         //cout << "including " << attval << endl;
516         SGPath path = globals->get_fg_root();
517         path.append("/Traffic/");
518         path.append(attval);
519         readXML(path.str(), *this);
520     }
521     elementValueStack.push_back("");
522     //  cout << "  " << atts.getName(i) << '=' << atts.getValue(i) << endl; 
523 }
524
525 void FGTrafficManager::endElement(const char *name)
526 {
527     //cout << "End element " << name << endl;
528     const string & value = elementValueStack.back();
529
530     if (!strcmp(name, "model"))
531         mdl = value;
532     else if (!strcmp(name, "livery"))
533         livery = value;
534     else if (!strcmp(name, "home-port"))
535         homePort = value;
536     else if (!strcmp(name, "registration"))
537         registration = value;
538     else if (!strcmp(name, "airline"))
539         airline = value;
540     else if (!strcmp(name, "actype"))
541         acType = value;
542     else if (!strcmp(name, "required-aircraft"))
543         requiredAircraft = value;
544     else if (!strcmp(name, "flighttype"))
545         flighttype = value;
546     else if (!strcmp(name, "radius"))
547         radius = atoi(value.c_str());
548     else if (!strcmp(name, "offset"))
549         offset = atoi(value.c_str());
550     else if (!strcmp(name, "performance-class"))
551         m_class = value;
552     else if (!strcmp(name, "heavy")) {
553         if (value == string("true"))
554             heavy = true;
555         else
556             heavy = false;
557     } else if (!strcmp(name, "callsign"))
558         callsign = value;
559     else if (!strcmp(name, "fltrules"))
560         fltrules = value;
561     else if (!strcmp(name, "port"))
562         port = value;
563     else if (!strcmp(name, "time"))
564         timeString = value;
565     else if (!strcmp(name, "departure")) {
566         departurePort = port;
567         departureTime = timeString;
568     } else if (!strcmp(name, "cruise-alt"))
569         cruiseAlt = atoi(value.c_str());
570     else if (!strcmp(name, "arrival")) {
571         arrivalPort = port;
572         arrivalTime = timeString;
573     } else if (!strcmp(name, "repeat"))
574         repeat = value;
575     else if (!strcmp(name, "flight")) {
576         // We have loaded and parsed all the information belonging to this flight
577         // so we temporarily store it. 
578         //cerr << "Pusing back flight " << callsign << endl;
579         //cerr << callsign  <<  " " << fltrules     << " "<< departurePort << " " <<  arrivalPort << " "
580         //   << cruiseAlt <<  " " << departureTime<< " "<< arrivalTime   << " " << repeat << endl;
581
582         //Prioritize aircraft 
583         string apt = fgGetString("/sim/presets/airport-id");
584         //cerr << "Airport information: " << apt << " " << departurePort << " " << arrivalPort << endl;
585         //if (departurePort == apt) score++;
586         //flights.push_back(new FGScheduledFlight(callsign,
587         //                                fltrules,
588         //                                departurePort,
589         //                                arrivalPort,
590         //                                cruiseAlt,
591         //                                departureTime,
592         //                                arrivalTime,
593         //                                repeat));
594         if (requiredAircraft == "") {
595             char buffer[16];
596             snprintf(buffer, 16, "%d", acCounter);
597             requiredAircraft = buffer;
598         }
599         SG_LOG(SG_GENERAL, SG_DEBUG, "Adding flight: " << callsign << " "
600                << fltrules << " "
601                << departurePort << " "
602                << arrivalPort << " "
603                << cruiseAlt << " "
604                << departureTime << " "
605                << arrivalTime << " " << repeat << " " << requiredAircraft);
606         // For database maintainance purposes, it may be convenient to
607         // 
608         if (fgGetBool("/sim/traffic-manager/dumpdata") == true) {
609              SG_LOG(SG_GENERAL, SG_ALERT, "Traffic Dump FLIGHT," << callsign << ","
610                           << fltrules << ","
611                           << departurePort << ","
612                           << arrivalPort << ","
613                           << cruiseAlt << ","
614                           << departureTime << ","
615                           << arrivalTime << "," << repeat << "," << requiredAircraft);
616         }
617         flights[requiredAircraft].push_back(new FGScheduledFlight(callsign,
618                                                                   fltrules,
619                                                                   departurePort,
620                                                                   arrivalPort,
621                                                                   cruiseAlt,
622                                                                   departureTime,
623                                                                   arrivalTime,
624                                                                   repeat,
625                                                                   requiredAircraft));
626         requiredAircraft = "";
627     } else if (!strcmp(name, "aircraft")) {
628         string isHeavy;
629         if (heavy) {
630             isHeavy = "true";
631         } else {
632             isHeavy = "false"; 
633         }
634         /*
635         cerr << "Traffic Dump AC," << homePort << "," << registration << "," << requiredAircraft 
636              << "," << acType << "," << livery << "," 
637              << airline << "," << offset << "," << radius << "," << flighttype << "," << isHeavy << "," << mdl << endl;*/
638         int proportion =
639             (int) (fgGetDouble("/sim/traffic-manager/proportion") * 100);
640         int randval = rand() & 100;
641         if (randval <= proportion) {
642             if (fgGetBool("/sim/traffic-manager/dumpdata") == true) {
643                 SG_LOG(SG_GENERAL, SG_ALERT, "Traffic Dump AC," << homePort << "," << registration << "," << requiredAircraft 
644                  << "," << acType << "," << livery << "," 
645                  << airline << ","  << m_class << "," << offset << "," << radius << "," << flighttype << "," << isHeavy << "," << mdl);
646             }
647             //scheduledAircraft.push_back(new FGAISchedule(mdl, 
648             //                                     livery, 
649             //                                     registration, 
650             //                                     heavy,
651             //                                     acType, 
652             //                                     airline, 
653             //                                     m_class, 
654             //                                     flighttype,
655             //                                     radius,
656             //                                     offset,
657             //                                     score,
658             //                                     flights));
659             if (requiredAircraft == "") {
660                 char buffer[16];
661                 snprintf(buffer, 16, "%d", acCounter);
662                 requiredAircraft = buffer;
663             }
664             if (homePort == "") {
665                 homePort = departurePort;
666             }
667             scheduledAircraft.push_back(new FGAISchedule(mdl,
668                                                          livery,
669                                                          homePort,
670                                                          registration,
671                                                          requiredAircraft,
672                                                          heavy,
673                                                          acType,
674                                                          airline,
675                                                          m_class,
676                                                          flighttype,
677                                                          radius, offset));
678
679             //  while(flights.begin() != flights.end()) {
680 //      flights.pop_back();
681 //       }
682         } else {
683             cerr << "Skipping : " << randval;
684         }
685         acCounter++;
686         requiredAircraft = "";
687         homePort = "";
688         //for (FGScheduledFlightVecIterator flt = flights.begin(); flt != flights.end(); flt++)
689         //  {
690         //    delete (*flt);
691         //  }
692         //flights.clear();
693         SG_LOG(SG_GENERAL, SG_BULK, "Reading aircraft : "
694                << registration << " with prioritization score " << score);
695         score = 0;
696     }
697     elementValueStack.pop_back();
698 }
699
700 void FGTrafficManager::data(const char *s, int len)
701 {
702     string token = string(s, len);
703     //cout << "Character data " << string(s,len) << endl;
704     elementValueStack.back() += token;
705 }
706
707 void FGTrafficManager::pi(const char *target, const char *data)
708 {
709     //cout << "Processing instruction " << target << ' ' << data << endl;
710 }
711
712 void FGTrafficManager::warning(const char *message, int line, int column)
713 {
714     SG_LOG(SG_IO, SG_WARN,
715            "Warning: " << message << " (" << line << ',' << column << ')');
716 }
717
718 void FGTrafficManager::error(const char *message, int line, int column)
719 {
720     SG_LOG(SG_IO, SG_ALERT,
721            "Error: " << message << " (" << line << ',' << column << ')');
722 }