]> git.mxchange.org Git - flightgear.git/blobdiff - src/Traffic/TrafficMgr.cxx
Canvas: CSS like property value inheritance.
[flightgear.git] / src / Traffic / TrafficMgr.cxx
index 615bb6c8c49e4275d337f539a744c1e8327e0972..a4562d3b49a924a4a1dcfc152a5c2bf5b4719819 100644 (file)
 #include <string>
 #include <vector>
 #include <algorithm>
-
-#include <plib/ul.h>
+#include <boost/foreach.hpp>
 
 #include <simgear/compiler.h>
 #include <simgear/misc/sg_path.hxx>
+#include <simgear/misc/sg_dir.hxx>
 #include <simgear/props/props.hxx>
-#include <simgear/route/waypoint.hxx>
 #include <simgear/structure/subsystem_mgr.hxx>
 #include <simgear/xml/easyxml.hxx>
 
@@ -76,7 +75,13 @@ using std::strcmp;
 /******************************************************************************
  * TrafficManager
  *****************************************************************************/
-FGTrafficManager::FGTrafficManager()
+FGTrafficManager::FGTrafficManager() :
+  inited(false),
+  doingInit(false),
+  enabled("/sim/traffic-manager/enabled"),
+  aiEnabled("/sim/ai/enabled"),
+  realWxEnabled("/environment/realwx/enabled"),
+  metarValid("/environment/metar/valid")
 {
     //score = 0;
     //runCount = 0;
@@ -84,6 +89,11 @@ FGTrafficManager::FGTrafficManager()
 }
 
 FGTrafficManager::~FGTrafficManager()
+{
+    shutdown();
+}
+
+void FGTrafficManager::shutdown()
 {
     // Save the heuristics data
     bool saveData = false;
@@ -105,6 +115,7 @@ FGTrafficManager::~FGTrafficManager()
             //cerr << "Saving AI traffic heuristics" << endl;
             saveData = true;
             cachefile.open(cacheData.str().c_str());
+            cachefile << "[TrafficManagerCachedata:ref:2011:09:04]" << endl;
         }
     }
     for (ScheduleVectorIterator sched = scheduledAircraft.begin();
@@ -112,7 +123,8 @@ FGTrafficManager::~FGTrafficManager()
         if (saveData) {
             cachefile << (*sched)->getRegistration() << " "
                 << (*sched)->getRunCount() << " "
-                << (*sched)->getHits() << endl;
+                << (*sched)->getHits() << " "
+                << (*sched)->getLastUsed() << endl;
         }
         delete(*sched);
     }
@@ -121,46 +133,30 @@ FGTrafficManager::~FGTrafficManager()
     }
     scheduledAircraft.clear();
     flights.clear();
+    releaseList.clear();
+
+    currAircraft = scheduledAircraft.begin();
+    doingInit = false;
+    inited = false;
 }
 
 
 void FGTrafficManager::init()
 {
-    ulDir *d, *d2;
-    ulDirEnt *dent, *dent2;
-
-    heuristicsVector heuristics;
-    HeuristicMap heurMap;
+    if (!enabled) {
+      return;
+    }
 
+    assert(!doingInit);
+    doingInit = true;
     if (string(fgGetString("/sim/traffic-manager/datafile")) == string("")) {
-        SGPath aircraftDir = globals->get_fg_root();
-        SGPath path = aircraftDir;
-
-        aircraftDir.append("AI/Traffic");
-        if ((d = ulOpenDir(aircraftDir.c_str())) != NULL) {
-            while ((dent = ulReadDir(d)) != NULL) {
-                if (string(dent->d_name) != string(".") &&
-                    string(dent->d_name) != string("..") && dent->d_isdir) {
-                    SGPath currACDir = aircraftDir;
-                    currACDir.append(dent->d_name);
-                    if ((d2 = ulOpenDir(currACDir.c_str())) == NULL)
-                        return;
-                    while ((dent2 = ulReadDir(d2)) != NULL) {
-                        SGPath currFile = currACDir;
-                        currFile.append(dent2->d_name);
-                        if (currFile.extension() == string("xml")) {
-                            SGPath currFile = currACDir;
-                            currFile.append(dent2->d_name);
-                            SG_LOG(SG_GENERAL, SG_DEBUG,
-                                   "Scanning " << currFile.
-                                   str() << " for traffic");
-                            readXML(currFile.str(), *this);
-                        }
-                    }
-                    ulCloseDir(d2);
-                }
-            }
-            ulCloseDir(d);
+        simgear::Dir trafficDir(SGPath(globals->get_fg_root(), "AI/Traffic"));
+        simgear::PathList d = trafficDir.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT);
+        
+        BOOST_FOREACH(SGPath p, d) {
+          simgear::Dir d2(p);
+          simgear::PathList trafficFiles = d2.children(simgear::Dir::TYPE_FILE, ".xml");
+          schedulesToRead.insert(schedulesToRead.end(), trafficFiles.begin(), trafficFiles.end());
         }
     } else {
         fgSetBool("/sim/traffic-manager/heuristics", false);
@@ -175,95 +171,146 @@ void FGTrafficManager::init()
                 readTimeTableFromFile(path);
             }
         } else {
-             SG_LOG(SG_GENERAL, SG_ALERT,
+             SG_LOG(SG_AI, SG_ALERT,
                                "Unknown data format " << path.str()
                                 << " for traffic");
         }
         //exit(1);
     }
-    if (fgGetBool("/sim/traffic-manager/heuristics")) {
-        //cerr << "Processing Heuristics" << endl;
-        // Load the heuristics data
-        SGPath cacheData(fgGetString("/sim/fg-home"));
-        cacheData.append("ai");
-        string airport = fgGetString("/sim/presets/airport-id");
-        if ((airport) != "") {
-            char buffer[128];
-            ::snprintf(buffer, 128, "%c/%c/%c/",
-                       airport[0], airport[1], airport[2]);
-            cacheData.append(buffer);
-            cacheData.append(airport + "-cache.txt");
-            if (cacheData.exists()) {
-                ifstream data(cacheData.c_str());
-                while (1) {
-                    Heuristic h; // = new Heuristic;
-                    data >> h.registration >> h.runCount >> h.hits;
-                    if (data.eof())
-                        break;
-                    HeuristicMapIterator itr = heurMap.find(h.registration);
-                    if (itr != heurMap.end()) {
-                         SG_LOG(SG_GENERAL, SG_WARN,"Traffic Manager Warning: found duplicate tailnumber " << 
-                         h.registration << " for AI aircraft");
-                    }
-                    heurMap[h.registration] = h;
-                    heuristics.push_back(h);
-                }
-            }
-        }
-        for (currAircraft = scheduledAircraft.begin();
-             currAircraft != scheduledAircraft.end(); currAircraft++) {
-            string registration = (*currAircraft)->getRegistration();
-            HeuristicMapIterator itr = heurMap.find(registration);
-            //cerr << "Processing heuristics for" << (*currAircraft)->getRegistration() << endl;
-            if (itr == heurMap.end()) {
-                //cerr << "No heuristics found for " << registration << endl;
-            } else {
-                (*currAircraft)->setrunCount(itr->second.runCount);
-                (*currAircraft)->setHits(itr->second.hits);
-                //cerr <<"Runcount " << itr->second->runCount << ".Hits " << itr->second->hits << endl;
-            }
-        }
-        //cerr << "Done" << endl;
-        //for (heuristicsVectorIterator hvi = heuristics.begin();
-        //     hvi != heuristics.end(); hvi++) {
-        //    delete(*hvi);
-        //}
+}
+
+void FGTrafficManager::initStep()
+{
+    assert(doingInit);
+    if (schedulesToRead.empty()) {
+        finishInit();
+        return;
     }
+    
+    SGPath path = schedulesToRead.front();
+    schedulesToRead.erase(schedulesToRead.begin());
+    SG_LOG(SG_AI, SG_DEBUG, path << " for traffic");
+    readXML(path.str(), *this);
+}
+
+void FGTrafficManager::finishInit()
+{
+    assert(doingInit);
+    SG_LOG(SG_AI, SG_INFO, "finishing AI-Traffic init");
+    loadHeuristics();
+    
     // Do sorting and scoring separately, to take advantage of the "homeport| variable
     for (currAircraft = scheduledAircraft.begin();
          currAircraft != scheduledAircraft.end(); currAircraft++) {
         (*currAircraft)->setScore();
     }
+    
     sort(scheduledAircraft.begin(), scheduledAircraft.end(),
          compareSchedules);
     currAircraft = scheduledAircraft.begin();
     currAircraftClosest = scheduledAircraft.begin();
+    
+    doingInit = false;
+    inited = true;
+}
+
+void FGTrafficManager::loadHeuristics()
+{
+    if (!fgGetBool("/sim/traffic-manager/heuristics")) {
+        return;
+    }
+  
+    HeuristicMap heurMap;
+    //cerr << "Processing Heuristics" << endl;
+    // Load the heuristics data
+    SGPath cacheData(fgGetString("/sim/fg-home"));
+    cacheData.append("ai");
+    string airport = fgGetString("/sim/presets/airport-id");
+    if ((airport) != "") {
+      char buffer[128];
+      ::snprintf(buffer, 128, "%c/%c/%c/",
+                 airport[0], airport[1], airport[2]);
+      cacheData.append(buffer);
+      cacheData.append(airport + "-cache.txt");
+      string revisionStr;
+      if (cacheData.exists()) {
+        ifstream data(cacheData.c_str());
+        data >> revisionStr;
+        if (revisionStr != "[TrafficManagerCachedata:ref:2011:09:04]") {
+          SG_LOG(SG_GENERAL, SG_ALERT,"Traffic Manager Warning: discarding outdated cachefile " << 
+                 cacheData.c_str() << " for Airport " << airport);
+        } else {
+          while (1) {
+            Heuristic h; // = new Heuristic;
+            data >> h.registration >> h.runCount >> h.hits >> h.lastRun;
+            if (data.eof())
+              break;
+            HeuristicMapIterator itr = heurMap.find(h.registration);
+            if (itr != heurMap.end()) {
+              SG_LOG(SG_GENERAL, SG_WARN,"Traffic Manager Warning: found duplicate tailnumber " << 
+                     h.registration << " for AI aircraft");
+            } else {
+              heurMap[h.registration] = h;
+            }
+          }
+        }
+      }
+    } 
+    
+  for(currAircraft = scheduledAircraft.begin(); currAircraft != scheduledAircraft.end(); ++currAircraft) {
+        string registration = (*currAircraft)->getRegistration();
+        HeuristicMapIterator itr = heurMap.find(registration);
+        if (itr != heurMap.end()) {
+            (*currAircraft)->setrunCount(itr->second.runCount);
+            (*currAircraft)->setHits(itr->second.hits);
+            (*currAircraft)->setLastUsed(itr->second.lastRun);
+        }
+    }
 }
 
 void FGTrafficManager::update(double /*dt */ )
 {
-    if (fgGetBool("/environment/metar/valid") == false) {
+    if (!enabled)
+    {
+        if (inited || doingInit)
+            shutdown();
         return;
     }
+
+    if ((realWxEnabled && !metarValid)) {
+        return;
+    }
+
+    if (!aiEnabled)
+    {
+        // traffic depends on AI module
+        aiEnabled = true;
+    }
+
+    if (!inited) {
+        if (!doingInit) {
+            init();
+        }
+        
+        initStep();
+        if (!inited) {
+            return; // still more to do on next update() call
+        }
+    }
+        
     time_t now = time(NULL) + fgGetLong("/sim/time/warp");
     if (scheduledAircraft.size() == 0) {
         return;
     }
 
-    SGVec3d userCart =
-        SGVec3d::fromGeod(SGGeod::
-                          fromDeg(fgGetDouble("/position/longitude-deg"),
-                                  fgGetDouble("/position/latitude-deg")));
+    SGVec3d userCart = globals->get_aircraft_positon_cart();
 
     if (currAircraft == scheduledAircraft.end()) {
         currAircraft = scheduledAircraft.begin();
     }
     //cerr << "Processing << " << (*currAircraft)->getRegistration() << " with score " << (*currAircraft)->getScore() << endl;
     if (!((*currAircraft)->update(now, userCart))) {
-        // NOTE: With traffic manager II, this statement below is no longer true
-        // after proper initialization, we shouldnt get here.
-        // But let's make sure
-        //SG_LOG( SG_GENERAL, SG_ALERT, "Failed to update aircraft schedule in traffic manager");
+        (*currAircraft)->taint();
     }
     currAircraft++;
 }
@@ -342,7 +389,13 @@ void FGTrafficManager::readTimeTableFromFile(SGPath infileName)
                  FlightType     = tokens[9];
                  radius         = atof(tokens[8].c_str());
                  offset         = atof(tokens[7].c_str());;
-                 SG_LOG(SG_GENERAL, SG_ALERT, "Adding Aircraft" << model << " " << livery << " " << homePort << " " 
+                 
+                 if (!FGAISchedule::validModelPath(model)) {
+                     SG_LOG(SG_GENERAL, SG_WARN, "TrafficMgr: Missing model path:" << 
+                            model << " from " << infileName.str());
+                 } else {
+                 
+                 SG_LOG(SG_GENERAL, SG_INFO, "Adding Aircraft" << model << " " << livery << " " << homePort << " " 
                                                                 << registration << " " << flightReq << " " << isHeavy 
                                                                 << " " << acType << " " << airline << " " << m_class 
                                                                 << " " << FlightType << " " << radius << " " << offset);
@@ -358,6 +411,7 @@ void FGTrafficManager::readTimeTableFromFile(SGPath infileName)
                                                               FlightType,
                                                               radius,
                                                               offset));
+                 } // of valid model path
              }
              if (tokens[0] == string("FLIGHT")) {
                  //cerr << "Found flight " << buffString << " size is : " << tokens.size() << endl;
@@ -594,78 +648,72 @@ void FGTrafficManager::endElement(const char *name)
                                                                   requiredAircraft));
         requiredAircraft = "";
     } else if (!strcmp(name, "aircraft")) {
-        string isHeavy;
-        if (heavy) {
-            isHeavy = "true";
-        } else {
-            isHeavy = "false"; 
-        }
-        /*
-        cerr << "Traffic Dump AC," << homePort << "," << registration << "," << requiredAircraft 
-             << "," << acType << "," << livery << "," 
-             << airline << "," << offset << "," << radius << "," << flighttype << "," << isHeavy << "," << mdl << endl;*/
-        int proportion =
-            (int) (fgGetDouble("/sim/traffic-manager/proportion") * 100);
-        int randval = rand() & 100;
-        if (randval <= proportion) {
-            if (fgGetBool("/sim/traffic-manager/dumpdata") == true) {
-                SG_LOG(SG_GENERAL, SG_ALERT, "Traffic Dump AC," << homePort << "," << registration << "," << requiredAircraft 
-                 << "," << acType << "," << livery << "," 
-                 << airline << ","  << m_class << "," << offset << "," << radius << "," << flighttype << "," << isHeavy << "," << mdl);
-            }
-            //scheduledAircraft.push_back(new FGAISchedule(mdl, 
-            //                                     livery, 
-            //                                     registration, 
-            //                                     heavy,
-            //                                     acType, 
-            //                                     airline, 
-            //                                     m_class, 
-            //                                     flighttype,
-            //                                     radius,
-            //                                     offset,
-            //                                     score,
-            //                                     flights));
-            if (requiredAircraft == "") {
-                char buffer[16];
-                snprintf(buffer, 16, "%d", acCounter);
-                requiredAircraft = buffer;
-            }
-            if (homePort == "") {
-                homePort = departurePort;
-            }
-            scheduledAircraft.push_back(new FGAISchedule(mdl,
-                                                         livery,
-                                                         homePort,
-                                                         registration,
-                                                         requiredAircraft,
-                                                         heavy,
-                                                         acType,
-                                                         airline,
-                                                         m_class,
-                                                         flighttype,
-                                                         radius, offset));
-
-            //  while(flights.begin() != flights.end()) {
-//      flights.pop_back();
-//       }
-        } else {
-            cerr << "Skipping : " << randval;
-        }
-        acCounter++;
-        requiredAircraft = "";
-        homePort = "";
-        //for (FGScheduledFlightVecIterator flt = flights.begin(); flt != flights.end(); flt++)
-        //  {
-        //    delete (*flt);
-        //  }
-        //flights.clear();
-        SG_LOG(SG_GENERAL, SG_BULK, "Reading aircraft : "
-               << registration << " with prioritization score " << score);
-        score = 0;
+        endAircraft();
     }
+    
     elementValueStack.pop_back();
 }
 
+void FGTrafficManager::endAircraft()
+{
+    string isHeavy = heavy ? "true" : "false";
+
+    if (missingModels.find(mdl) != missingModels.end()) {
+    // don't stat() or warn again
+        requiredAircraft = homePort = "";
+        return;
+    }
+    
+    if (!FGAISchedule::validModelPath(mdl)) {
+        missingModels.insert(mdl);
+        SG_LOG(SG_GENERAL, SG_WARN, "TrafficMgr: Missing model path:" << mdl);
+        requiredAircraft = homePort = "";
+        return;
+    }
+        
+    int proportion =
+        (int) (fgGetDouble("/sim/traffic-manager/proportion") * 100);
+    int randval = rand() & 100;
+    if (randval > proportion) {
+        requiredAircraft = homePort = "";
+        return;
+    }
+    
+    if (fgGetBool("/sim/traffic-manager/dumpdata") == true) {
+        SG_LOG(SG_GENERAL, SG_ALERT, "Traffic Dump AC," << homePort << "," << registration << "," << requiredAircraft 
+               << "," << acType << "," << livery << "," 
+               << airline << ","  << m_class << "," << offset << "," << radius << "," << flighttype << "," << isHeavy << "," << mdl);
+    }
+
+    if (requiredAircraft == "") {
+        char buffer[16];
+        snprintf(buffer, 16, "%d", acCounter);
+        requiredAircraft = buffer;
+    }
+    if (homePort == "") {
+        homePort = departurePort;
+    }
+    
+    scheduledAircraft.push_back(new FGAISchedule(mdl,
+                                                 livery,
+                                                 homePort,
+                                                 registration,
+                                                 requiredAircraft,
+                                                 heavy,
+                                                 acType,
+                                                 airline,
+                                                 m_class,
+                                                 flighttype,
+                                                 radius, offset));
+            
+    acCounter++;
+    requiredAircraft = "";
+    homePort = "";
+    SG_LOG(SG_GENERAL, SG_BULK, "Reading aircraft : "
+           << registration << " with prioritization score " << score);
+    score = 0;
+}
+    
 void FGTrafficManager::data(const char *s, int len)
 {
     string token = string(s, len);