X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;ds=sidebyside;f=src%2FAirports%2Fdynamics.cxx;h=5916c68b0645080e0933249d3833bb040bfb7cb7;hb=e7dec994b80c409f59e6fafaeee57c5a98181c4a;hp=21d45d08be4296056321b0aa59ed221545d052bb;hpb=b1854459b3100e4c51e3a5704caa4e2c3869228c;p=flightgear.git diff --git a/src/Airports/dynamics.cxx b/src/Airports/dynamics.cxx index 21d45d08b..5916c68b0 100644 --- a/src/Airports/dynamics.cxx +++ b/src/Airports/dynamics.cxx @@ -38,10 +38,11 @@ #include #include
#include
+#include
#include -#include +#include -#include "simple.hxx" +#include "airport.hxx" #include "dynamics.hxx" using std::string; @@ -49,6 +50,105 @@ using std::vector; using std::sort; using std::random_shuffle; +class ParkingAssignment::ParkingAssignmentPrivate +{ +public: + ParkingAssignmentPrivate(FGParking* pk, FGAirport* apt) : + refCount(0), + parking(pk), + airport(apt) + { + assert(pk); + assert(apt); + retain(); // initial count of 1 + } + + ~ParkingAssignmentPrivate() + { + airport->getDynamics()->releaseParking(parking->guid()); + } + + void release() + { + if ((--refCount) == 0) { + delete this; + } + } + + void retain() + { + ++refCount; + } + + unsigned int refCount; + SGSharedPtr parking; + SGSharedPtr airport; +}; + +ParkingAssignment::ParkingAssignment() : + _sharedData(NULL) +{ +} + +ParkingAssignment::~ParkingAssignment() +{ + if (_sharedData) { + _sharedData->release(); + } +} + +ParkingAssignment::ParkingAssignment(FGParking* pk, FGAirport* apt) : + _sharedData(NULL) +{ + if (pk) { + _sharedData = new ParkingAssignmentPrivate(pk, apt); + } +} + +ParkingAssignment::ParkingAssignment(const ParkingAssignment& aOther) : + _sharedData(aOther._sharedData) +{ + if (_sharedData) { + _sharedData->retain(); + } +} + +void ParkingAssignment::operator=(const ParkingAssignment& aOther) +{ + if (_sharedData == aOther._sharedData) { + return; // self-assignment, special case + } + + if (_sharedData) { + _sharedData->release(); + } + + _sharedData = aOther._sharedData; + if (_sharedData) { + _sharedData->retain(); + } +} + +void ParkingAssignment::release() +{ + if (_sharedData) { + _sharedData->release(); + _sharedData = NULL; + } +} + +bool ParkingAssignment::isValid() const +{ + return (_sharedData != NULL); +} + +FGParking* ParkingAssignment::parking() const +{ + return _sharedData ? _sharedData->parking.ptr() : NULL; +} + +//////////////////////////////////////////////////////////////////////////////// + FGAirportDynamics::FGAirportDynamics(FGAirport * ap): _ap(ap), rwyPrefs(ap), startupController (this), @@ -70,131 +170,109 @@ FGAirportDynamics::~FGAirportDynamics() // Initialization required after XMLRead void FGAirportDynamics::init() { - // This may seem a bit weird to first randomly shuffle the parkings - // and then sort them again. However, parkings are sorted here by ascending - // radius. Since many parkings have similar radii, with each radius class they will - // still be allocated relatively systematically. Randomizing prior to sorting will - // prevent any initial orderings to be destroyed, leading (hopefully) to a more - // naturalistic gate assignment. - 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.init(_ap); groundNetwork.setTowerController(&towerController); } -int FGAirportDynamics::innerGetAvailableParking(double radius, const string & flType, - const string & acType, +FGParking* FGAirportDynamics::innerGetAvailableParking(double radius, const string & flType, const string & airline, bool skipEmptyAirlineCode) { - FGParkingVecIterator i; - for (i = parkings.begin(); i != parkings.end(); i++) { - // Taken by another aircraft, or no airline codes - if (!i->isAvailable()) { + flightgear::NavDataCache* cache = flightgear::NavDataCache::instance(); + BOOST_FOREACH(PositionedID pk, cache->findAirportParking(_ap->guid(), flType, radius)) { + if (!isParkingAvailable(pk)) { continue; } - if (skipEmptyAirlineCode && i->getCodes().empty()) { + FGParking* parking = getParking(pk); + if (skipEmptyAirlineCode && parking->getCodes().empty()) { continue; } - // check airline codes match - if (!airline.empty() && !i->getCodes().empty()) { - if (i->getCodes().find(airline, 0) == string::npos) { + if (!airline.empty() && !parking->getCodes().empty()) { + if (parking->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(); + setParkingAvailable(pk, false); + return parking; } - return -1; + return NULL; } -int FGAirportDynamics::getAvailableParking(double radius, const string & flType, +ParkingAssignment FGAirportDynamics::getAvailableParking(double radius, const string & flType, const string & acType, const string & airline) { - if (parkings.empty()) { - return -1; - } + SG_UNUSED(acType); // sadly not used at the moment // most exact seach - airline codes must be present and match - int result = innerGetAvailableParking(radius, flType, acType, airline, true); - if (result >= 0) { - return result; + FGParking* result = innerGetAvailableParking(radius, flType, airline, true); + if (result) { + return ParkingAssignment(result, _ap); } // more tolerant - gates with empty airline codes are permitted - result = innerGetAvailableParking(radius, flType, acType, airline, false); - if (result >= 0) { - return result; + result = innerGetAvailableParking(radius, flType, airline, false); + if (result) { + return ParkingAssignment(result, _ap); } // fallback - ignore the airline code entirely - return innerGetAvailableParking(radius, flType, acType, string(), false); + result = innerGetAvailableParking(radius, flType, string(), false); + return result ? ParkingAssignment(result, _ap) : ParkingAssignment(); } -FGParking *FGAirportDynamics::getParking(int id) +FGParkingRef FGAirportDynamics::getParking(PositionedID id) const { - FGParkingVecIterator i = parkings.begin(); - for (i = parkings.begin(); i != parkings.end(); i++) { - if (id == i->getIndex()) { - return &(*i); - } - } - return 0; + return FGPositioned::loadById(id); } -string FGAirportDynamics::getParkingName(int id) +string FGAirportDynamics::getParkingName(PositionedID id) const { - FGParkingVecIterator i = parkings.begin(); - for (i = parkings.begin(); i != parkings.end(); i++) { - if (id == i->getIndex()) { - return i->getName(); - } - } - - return string("overflow"); + FGParking* p = getParking(id); + if (p) { + return p->getName(); + } + + return string(); } -int FGAirportDynamics::findParkingByName(const std::string& name) const +ParkingAssignment FGAirportDynamics::getParkingByName(const std::string& name) const { - FGParkingVec::const_iterator i = parkings.begin(); - for (i = parkings.begin(); i != parkings.end(); i++) { - if (i->getName() == name) { - return i->getIndex(); - } + PositionedID guid = flightgear::NavDataCache::instance()->airportItemWithIdent(parent()->guid(), FGPositioned::PARKING, name); + if (guid == 0) { + return ParkingAssignment(); } - return -1; + return ParkingAssignment(getParking(guid), _ap); } -void FGAirportDynamics::releaseParking(int id) +void FGAirportDynamics::setParkingAvailable(PositionedID guid, bool available) { - if (id >= 0) { + if (available) { + releaseParking(guid); + } else { + occupiedParkings.insert(guid); + } +} - FGParkingVecIterator i = parkings.begin(); - for (i = parkings.begin(); i != parkings.end(); i++) { - if (id == i->getIndex()) { - i->setAvailable(true); - } - } - } +bool FGAirportDynamics::isParkingAvailable(PositionedID parking) const +{ + return (occupiedParkings.find(parking) == occupiedParkings.end()); +} + +void FGAirportDynamics::releaseParking(PositionedID id) +{ + ParkingSet::iterator it = occupiedParkings.find(id); + if (it == occupiedParkings.end()) { + return; + } + + occupiedParkings.erase(it); } void FGAirportDynamics::setRwyUse(const FGRunwayPreference & ref) @@ -380,11 +458,6 @@ string FGAirportDynamics::chooseRunwayFallback() return rwy->ident(); } -void FGAirportDynamics::addParking(FGParking & park) -{ - parkings.push_back(park); -} - double FGAirportDynamics::getElevation() const { return _ap->getElevation(); @@ -457,8 +530,12 @@ const std::string FGAirportDynamics::getAtisSequence() if (atisSequenceIndex == -1) { updateAtisSequence(1, false); } + + char atisSequenceString[2]; + atisSequenceString[0] = 'a' + atisSequenceIndex; + atisSequenceString[1] = 0; - return GetPhoneticLetter(atisSequenceIndex); + return globals->get_locale()->getLocalizedString(atisSequenceString, "atc", "unknown"); } int FGAirportDynamics::updateAtisSequence(int interval, bool forceUpdate) @@ -467,7 +544,7 @@ int FGAirportDynamics::updateAtisSequence(int interval, bool forceUpdate) if (atisSequenceIndex == -1) { // first computation atisSequenceTimeStamp = now; - atisSequenceIndex = rand() % LTRS; // random initial sequence letters + atisSequenceIndex = rand() % 26; // random initial sequence letters return atisSequenceIndex; } @@ -477,7 +554,7 @@ int FGAirportDynamics::updateAtisSequence(int interval, bool forceUpdate) ++steps; // a "special" ATIS update is required } - atisSequenceIndex = (atisSequenceIndex + steps) % LTRS; + atisSequenceIndex = (atisSequenceIndex + steps) % 26; // return a huge value if no update occurred - return (atisSequenceIndex + (steps ? 0 : LTRS*1000)); + return (atisSequenceIndex + (steps ? 0 : 26*1000)); }