getName() + "-Ground";
atisInformation =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
- getDynamics()->getAtisInformation();
+ getDynamics()->getAtisSequence();
break;
case 4:
receiver =
#include <Main/fg_props.hxx>
#include <Main/globals.hxx>
#include <Airports/runways.hxx>
+#include <Airports/dynamics.hxx>
#include "ATCutils.hxx"
return 0;
}
-// Add structure and map for storing a log of atis transmissions
-// made in this session of FlightGear. This allows the callsign
-// to be allocated correctly wrt time.
-typedef struct {
- double tstamp;
- int sequence;
-} atis_transmission_type;
-
-typedef std::map < std::string, atis_transmission_type > atis_log_type;
-typedef atis_log_type::iterator atis_log_iterator;
-typedef atis_log_type::const_iterator atis_log_const_iterator;
-
-static atis_log_type atislog;
-
-int FGATIS::GetAtisSequence( const string& apt_id,
- const double tstamp, const int interval, const int special)
-{
- atis_transmission_type tran;
-
- if(atislog.find(apt_id) == atislog.end()) { // New station
- tran.tstamp = tstamp - interval;
-// Random number between 0 and 25 inclusive, i.e. 26 equiprobable outcomes:
- tran.sequence = int(sg_random() * LTRS);
- atislog[apt_id] = tran;
- //cout << "New ATIS station: " << apt_id << " seq-1: "
- // << tran.sequence << endl;
- }
-
-// calculate the appropriate identifier and update the log
- tran = atislog[apt_id];
-
- int delta = int((tstamp - tran.tstamp) / interval);
- tran.tstamp += delta * interval;
- if (special && !delta) delta++; // a "special" ATIS update is required
- tran.sequence = (tran.sequence + delta) % LTRS;
- atislog[apt_id] = tran;
- //if (delta) cout << "New ATIS sequence: " << tran.sequence
- // << " Delta: " << delta << endl;
- return(tran.sequence + (delta ? 0 : LTRS*1000));
-}
-
// Generate the actual broadcast ATIS transmission.
// Regen means regenerate the /current/ transmission.
// Special means generate a new transmission, with a new sequence.
string BRK = ".\n";
string PAUSE = " / ";
- double tstamp = atof(fgGetString("sim/time/elapsed-sec"));
int interval = _type == ATIS ?
ATIS_interval // ATIS updated hourly
: 2*minute; // AWOS updated more frequently
-
- int sequence = GetAtisSequence(ident, tstamp, interval, special);
+
+ FGAirport* apt = FGAirport::findByIdent(ident);
+ int sequence = apt->getDynamics()->updateAtisSequence(interval, special);
if (!regen && sequence > LTRS) {
//xx if (msg_OK) cout << "ATIS: no change: " << sequence << endl;
//xx msg_time = cur_time;
void TreeOut(int msgOK);
friend std::istream& operator>> ( std::istream&, FGATIS& );
-
- int GetAtisSequence( const std::string& apt_id,
- const double tstamp, const int interval, const int special);
+
};
typedef int (FGATIS::*int_getter)() const;
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
#include <Airports/runways.hxx>
+#include <ATCDCL/ATCutils.hxx>
#include <string>
#include <vector>
#include "dynamics.hxx"
FGAirportDynamics::FGAirportDynamics(FGAirport * ap):
-_ap(ap), rwyPrefs(ap), SIDs(ap)
+_ap(ap), rwyPrefs(ap), SIDs(ap),
+ atisSequenceIndex(-1),
+ atisSequenceTimeStamp(0.0)
{
lastUpdate = 0;
-
- // For testing only. This needs to be refined when we move ATIS functionality over.
- atisInformation = "Sierra";
-}
-
-// 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;
}
// Destructor
{
return SIDs.getBest(activeRunway, heading);
}
+
+const std::string FGAirportDynamics::getAtisSequence()
+{
+ if (atisSequenceIndex == -1) {
+ updateAtisSequence(1, false);
+ }
+
+ return GetPhoneticLetter(atisSequenceIndex);
+}
+
+int FGAirportDynamics::updateAtisSequence(int interval, bool forceUpdate)
+{
+ 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));
+}
#ifndef _AIRPORT_DYNAMICS_HXX_
#define _AIRPORT_DYNAMICS_HXX_
-
-#ifndef __cplusplus
-# error This library requires C++
-#endif
-
-#include <simgear/xml/easyxml.hxx>
-
#include <ATC/trafficcontrol.hxx>
#include "parking.hxx"
#include "groundnetwork.hxx"
#include "runwayprefs.hxx"
#include "sidstar.hxx"
-//typedef vector<float> DoubleVec;
-//typedef vector<float>::iterator DoubleVecIterator;
-
+// forward decls
class FGAirport;
-
+class FGEnvironment;
class FGAirportDynamics {
FGApproachController approachController;
time_t lastUpdate;
- string prevTrafficType;
+ std::string prevTrafficType;
stringVec landing;
stringVec takeoff;
stringVec milActive, comActive, genActive, ulActive;
intVec freqTower; // </TOWER>
intVec freqApproach; // </APPROACH>
- string atisInformation;
-
- string chooseRunwayFallback();
- bool innerGetActiveRunway(const string &trafficType, int action, string &runway, double heading);
- string chooseRwyByHeading(stringVec rwys, double heading);
+ int atisSequenceIndex;
+ double atisSequenceTimeStamp;
+
+ std::string chooseRunwayFallback();
+ bool innerGetActiveRunway(const std::string &trafficType, int action, std::string &runway, double heading);
+ std::string chooseRwyByHeading(stringVec rwys, double heading);
public:
FGAirportDynamics(FGAirport* ap);
- FGAirportDynamics(const FGAirportDynamics &other);
~FGAirportDynamics();
void addAwosFreq (int val) { freqAwos.push_back(val); };
FGTowerController *getTowerController() { return &towerController; };
FGApproachController *getApproachController() { return &approachController; };
- const string& getAtisInformation() { return atisInformation; };
- int getGroundFrequency(unsigned leg); //{ return freqGround.size() ? freqGround[0] : 0; };
+ int getGroundFrequency(unsigned leg);
+
+ /// get current ATIS sequence letter
+ const std::string getAtisSequence();
+
+ /// get the current ATIS sequence number, updating it if necessary
+ int updateAtisSequence(int interval, bool forceUpdate);
void setRwyUse(const FGRunwayPreference& ref);
};
FGAirportDynamics * FGAirport::getDynamics()
{
- if (_dynamics != 0) {
+ if (_dynamics) {
return _dynamics;
- } else {
- //cerr << "Trying to load dynamics for " << _id << endl;
- _dynamics = new FGAirportDynamics(this);
- XMLLoader::load(_dynamics);
-
- FGRunwayPreference rwyPrefs(this);
- XMLLoader::load(&rwyPrefs);
- _dynamics->setRwyUse(rwyPrefs);
+ }
+
+ _dynamics = new FGAirportDynamics(this);
+ XMLLoader::load(_dynamics);
- //FGSidStar SIDs(this);
- XMLLoader::load(_dynamics->getSIDs());
- }
+ FGRunwayPreference rwyPrefs(this);
+ XMLLoader::load(&rwyPrefs);
+ _dynamics->setRwyUse(rwyPrefs);
+ XMLLoader::load(_dynamics->getSIDs());
+
return _dynamics;
}