]> git.mxchange.org Git - flightgear.git/blobdiff - src/Airports/dynamics.cxx
Alexis Bory:
[flightgear.git] / src / Airports / dynamics.cxx
index d608043b478bee48b05c9e6c6dc56b8f2e33f056..dde1983568d2520e0f8aab84f6d97d24fb22a7b6 100644 (file)
 #endif
 
 #include <algorithm>
+#include <string>
+#include <vector>
+
+#include <boost/foreach.hpp>
 
 #include <simgear/compiler.h>
 
 #include <simgear/props/props.hxx>
 #include <simgear/structure/subsystem_mgr.hxx>
 #include <simgear/debug/logstream.hxx>
-#include <simgear/route/waypoint.hxx>
 #include <Main/globals.hxx>
 #include <Main/fg_props.hxx>
 #include <Airports/runways.hxx>
+#include <ATCDCL/ATCutils.hxx>
 
-#include <string>
-#include <vector>
+#include "simple.hxx"
+#include "dynamics.hxx"
 
 using std::string;
 using std::vector;
 using std::sort;
 using std::random_shuffle;
 
-#include "simple.hxx"
-#include "dynamics.hxx"
-
 FGAirportDynamics::FGAirportDynamics(FGAirport * ap):
-_ap(ap), rwyPrefs(ap), SIDs(ap)
-{
-    lastUpdate = 0;
-
-    // For testing only. This needs to be refined when we move ATIS functionality over.
-    atisInformation = "Sierra";
-}
+    _ap(ap), rwyPrefs(ap),
+    startupController    (this),
+    towerController      (this),
+    approachController   (this),
+    atisSequenceIndex(-1),
+    atisSequenceTimeStamp(0.0)
 
-// Note that the ground network should also be copied
-FGAirportDynamics::
-FGAirportDynamics(const FGAirportDynamics & other):rwyPrefs(other.
-                                                            rwyPrefs),
-SIDs(other.SIDs)
 {
-    for (FGParkingVecConstIterator ip = other.parkings.begin();
-         ip != other.parkings.end(); ip++)
-        parkings.push_back(*(ip));
-    // rwyPrefs = other.rwyPrefs;
-    lastUpdate = other.lastUpdate;
-
-    stringVecConstIterator il;
-    for (il = other.landing.begin(); il != other.landing.end(); il++)
-        landing.push_back(*il);
-    for (il = other.takeoff.begin(); il != other.takeoff.end(); il++)
-        takeoff.push_back(*il);
-    lastUpdate = other.lastUpdate;
-    atisInformation = other.atisInformation;
+    lastUpdate = 0;
 }
 
 // Destructor
@@ -96,207 +79,120 @@ void FGAirportDynamics::init()
     random_shuffle(parkings.begin(), parkings.end());
     sort(parkings.begin(), parkings.end());
     // add the gate positions to the ground network. 
+    groundNetwork.setParent(_ap);
     groundNetwork.addNodes(&parkings);
     groundNetwork.init();
     groundNetwork.setTowerController(&towerController);
-    groundNetwork.setParent(_ap);
+    
 }
 
-bool FGAirportDynamics::getAvailableParking(double *lat, double *lon,
-                                            double *heading, int *gateId,
-                                            double rad,
-                                            const string & flType,
-                                            const string & acType,
-                                            const string & airline)
+int FGAirportDynamics::innerGetAvailableParking(double radius, const string & flType,
+                                           const string & acType,
+                                           const string & airline,
+                                           bool skipEmptyAirlineCode)
 {
-    bool found = false;
-    bool available = false;
-
-
-    FGParkingVecIterator i;
-    if (parkings.begin() == parkings.end()) {
-        //cerr << "Could not find parking spot at " << _ap->getId() << endl;
-        *lat = _ap->getLatitude();
-        *lon = _ap->getLongitude();
-        *heading = 0;
-        found = true;
-    } else {
-        // First try finding a parking with a designated airline code
-        for (i = parkings.begin(); !(i == parkings.end() || found); i++) {
-            available = true;
-            // Taken by another aircraft
-            if (!(i->isAvailable())) {
-                available = false;
-                continue;
-            }
-            // No airline codes, so skip
-            if (i->getCodes().empty()) {
-                available = false;
-                continue;
-            } else {             // Airline code doesn't match
-                //cerr << "Code = " << airline << ": Codes " << i->getCodes();
-                if (i->getCodes().find(airline, 0) == string::npos) {
-                    available = false;
-                    //cerr << "Unavailable" << endl;
-                    continue;
-                } else {
-                    //cerr << "Available" << endl;
-                }
-            }
-            // Type doesn't match
-            if (i->getType() != flType) {
-                available = false;
-                continue;
-            }
-            // too small
-            if (i->getRadius() < rad) {
-                available = false;
-                continue;
-            }
-
-            if (available) {
-                *lat = i->getLatitude();
-                *lon = i->getLongitude();
-                *heading = i->getHeading();
-                *gateId = i->getIndex();
-                i->setAvailable(false);
-                found = true;
-            }
-        }
-        // then try again for those without codes. 
-        for (i = parkings.begin(); !(i == parkings.end() || found); i++) {
-            available = true;
-            if (!(i->isAvailable())) {
-                available = false;
-                continue;
-            }
-            if (!(i->getCodes().empty())) {
-                if ((i->getCodes().find(airline, 0) == string::npos)) {
-                    available = false;
-                    continue;
-                }
-            }
-            if (i->getType() != flType) {
-                available = false;
-                continue;
-            }
-
-            if (i->getRadius() < rad) {
-                available = false;
-                continue;
-            }
-
-            if (available) {
-                *lat = i->getLatitude();
-                *lon = i->getLongitude();
-                *heading = i->getHeading();
-                *gateId = i->getIndex();
-                i->setAvailable(false);
-                found = true;
-            }
-        }
-        // And finally once more if that didn't work. Now ignore the airline codes, as a last resort
-        for (i = parkings.begin(); !(i == parkings.end() || found); i++) {
-            available = true;
-            if (!(i->isAvailable())) {
-                available = false;
-                continue;
-            }
-            if (i->getType() != flType) {
-                available = false;
-                continue;
-            }
-
-            if (i->getRadius() < rad) {
-                available = false;
-                continue;
-            }
-
-            if (available) {
-                *lat = i->getLatitude();
-                *lon = i->getLongitude();
-                *heading = i->getHeading();
-                *gateId = i->getIndex();
-                i->setAvailable(false);
-                found = true;
-            }
-        }
+  BOOST_FOREACH(FGParking* i, parkings) {
+    // Taken by another aircraft, or no airline codes
+    if (!i->isAvailable()) {
+      continue;
     }
-    if (!found) {
-        //cerr << "Traffic overflow at" << _ap->getId() 
-        //           << ". flType = " << flType 
-        //           << ". airline = " << airline 
-        //           << " Radius = " <<rad
-        //           << endl;
-        *lat = _ap->getLatitude();
-        *lon = _ap->getLongitude();
-        *heading = 0;
-        *gateId = -1;
-        //exit(1);
+    
+    if (skipEmptyAirlineCode && i->getCodes().empty()) {
+      continue;
     }
-    return found;
+    
+    // check airline codes match
+    if (!airline.empty() && !i->getCodes().empty()) {
+      if (i->getCodes().find(airline, 0) == string::npos) {
+        continue;
+      }
+    }
+    
+    // Type doesn't match
+    if (i->getType() != flType) {
+      continue;
+    }
+    // too small
+    if (i->getRadius() < radius) {
+      continue;
+    }
+    
+    i->setAvailable(false);
+    return i->getIndex();
+  }
+  
+  return -1;
 }
 
-void FGAirportDynamics::getParking(int id, double *lat, double *lon,
-                                   double *heading)
+int FGAirportDynamics::getAvailableParking(double radius, const string & flType,
+                                            const string & acType,
+                                            const string & airline)
 {
-    if (id < 0) {
-        *lat = _ap->getLatitude();
-        *lon = _ap->getLongitude();
-        *heading = 0;
-    } else {
-        FGParkingVecIterator i = parkings.begin();
-        for (i = parkings.begin(); i != parkings.end(); i++) {
-            if (id == i->getIndex()) {
-                *lat = i->getLatitude();
-                *lon = i->getLongitude();
-                *heading = i->getHeading();
-            }
-        }
+    if (parkings.empty()) {
+      return -1;
     }
+  
+  // most exact seach - airline codes must be present and match
+  int result = innerGetAvailableParking(radius, flType, acType, airline, true);
+  if (result >= 0) {
+    return result;
+  }
+  
+  // more tolerant - gates with empty airline codes are permitted
+  result = innerGetAvailableParking(radius, flType, acType, airline, false);
+  if (result >= 0) {
+    return result;
+  }
+
+  // fallback - ignore the airline code entirely
+  return innerGetAvailableParking(radius, flType, acType, string(), false);
 }
 
 FGParking *FGAirportDynamics::getParking(int id)
 {
-    FGParkingVecIterator i = parkings.begin();
-    for (i = parkings.begin(); i != parkings.end(); i++) {
-        if (id == i->getIndex()) {
-            return &(*i);
-        }
+  BOOST_FOREACH(FGParking* i, parkings) {
+    if (id == i->getIndex()) {
+      return i;
     }
-    return 0;
+  }
+  
+  return NULL;
 }
 
 string FGAirportDynamics::getParkingName(int id)
 {
-    FGParkingVecIterator i = parkings.begin();
-    for (i = parkings.begin(); i != parkings.end(); i++) {
-        if (id == i->getIndex()) {
-            return i->getName();
-        }
+  FGParking* p = getParking(id);
+  if (p) {
+    return p->getName();
+  }
+  
+  return string();
+}
+
+int FGAirportDynamics::findParkingByName(const std::string& name) const
+{
+  BOOST_FOREACH(FGParking* i, parkings) {
+    if (name == i->getName()) {
+      return i->getIndex();
     }
+  }
 
-    return string("overflow");
+  return -1;
 }
 
 void FGAirportDynamics::releaseParking(int id)
 {
     if (id >= 0) {
-
-        FGParkingVecIterator i = parkings.begin();
-        for (i = parkings.begin(); i != parkings.end(); i++) {
-            if (id == i->getIndex()) {
-                i->setAvailable(true);
-            }
-        }
+      FGParking* parking = getParking(id);
+      if (parking) {
+        parking->setAvailable(true);
+      }
     }
 }
 
 void FGAirportDynamics::setRwyUse(const FGRunwayPreference & ref)
 {
     rwyPrefs = ref;
-    //cerr << "Exiting due to not implemented yet" << endl;
-    //exit(1);
 }
 
 bool FGAirportDynamics::innerGetActiveRunway(const string & trafficType,
@@ -477,27 +373,17 @@ string FGAirportDynamics::chooseRunwayFallback()
     return rwy->ident();
 }
 
-void FGAirportDynamics::addParking(FGParking & park)
+void FGAirportDynamics::addParking(FGParking* park)
 {
     parkings.push_back(park);
 }
 
-double FGAirportDynamics::getLatitude() const
-{
-    return _ap->getLatitude();
-}
-
-double FGAirportDynamics::getLongitude() const
-{
-    return _ap->getLongitude();
-}
-
 double FGAirportDynamics::getElevation() const
 {
     return _ap->getElevation();
 }
 
-const string FGAirportDynamics::getId() const
+const string FGAirportDynamics::getId() const
 {
     return _ap->getId();
 }
@@ -512,25 +398,24 @@ const string & FGAirportDynamics::getId() const
 int FGAirportDynamics::getGroundFrequency(unsigned leg)
 {
     //return freqGround.size() ? freqGround[0] : 0; };
+    //cerr << "Getting frequency for : " << leg << endl;
     int groundFreq = 0;
-    if (leg < 2) {
+    if (leg < 1) {
         SG_LOG(SG_ATC, SG_ALERT,
-               "Leg value is smaller than two at " << SG_ORIGIN);
+               "Leg value is smaller than one at " << SG_ORIGIN);
     }
     if (freqGround.size() == 0) {
         return 0;
     }
-    if ((freqGround.size() > leg - 1) && (leg > 1)) {
-        groundFreq = freqGround[leg - 1];
-    }
-    if ((freqGround.size() < leg - 1) && (leg > 1)) {
+
+    if ((freqGround.size() < leg) && (leg > 0)) {
         groundFreq =
-            (freqGround.size() <
+            (freqGround.size() <=
              (leg - 1)) ? freqGround[freqGround.size() -
-                                     1] : freqGround[leg - 2];
+                                     1] : freqGround[leg - 1];
     }
-    if ((freqGround.size() >= leg - 1) && (leg > 1)) {
-        groundFreq = freqGround[leg - 2];
+    if ((freqGround.size() >= leg) && (leg > 0)) {
+        groundFreq = freqGround[leg - 1];
     }
     return groundFreq;
 }
@@ -560,9 +445,32 @@ int FGAirportDynamics::getTowerFrequency(unsigned nr)
     return towerFreq;
 }
 
+const std::string FGAirportDynamics::getAtisSequence()
+{
+   if (atisSequenceIndex == -1) {
+       updateAtisSequence(1, false);
+   }
+   
+   return GetPhoneticLetter(atisSequenceIndex);
+}
 
-FGAIFlightPlan *FGAirportDynamics::getSID(string activeRunway,
-                                          double heading)
+int FGAirportDynamics::updateAtisSequence(int interval, bool forceUpdate)
 {
-    return SIDs.getBest(activeRunway, heading);
+    double now = globals->get_sim_time_sec();
+    if (atisSequenceIndex == -1) {
+        // first computation
+        atisSequenceTimeStamp = now;
+        atisSequenceIndex = rand() % LTRS; // random initial sequence letters
+        return atisSequenceIndex;
+    }
+
+    int steps = static_cast<int>((now - atisSequenceTimeStamp) / interval);
+    atisSequenceTimeStamp += (interval * steps);
+    if (forceUpdate && (steps == 0)) {
+        ++steps; // a "special" ATIS update is required
+    } 
+    
+    atisSequenceIndex = (atisSequenceIndex + steps) % LTRS;
+    // return a huge value if no update occurred
+    return (atisSequenceIndex + (steps ? 0 : LTRS*1000));
 }