diff --git a/src/ATCDCL/atis.cxx b/src/ATCDCL/atis.cxx index e5bda8b3d..357ff18a2 100644 --- a/src/ATCDCL/atis.cxx +++ b/src/ATCDCL/atis.cxx @@ -31,6 +31,7 @@ #endif #include "atis.hxx" +#include "atis_lexicon.hxx" #include <simgear/compiler.h> @@ -40,6 +41,7 @@ #include <iostream> #include <boost/tuple/tuple.hpp> +#include <boost/algorithm/string.hpp> #include <simgear/misc/sg_path.hxx> @@ -77,6 +79,23 @@ FGATIS::FGATIS() : SG_LOG(SG_ATC, SG_ALERT, "ERROR - _type not ATIS or AWOS in atis.cxx"); } fgTie("/environment/attention", this, (int_getter)0, &FGATIS::attend); + +/////////////// +// FIXME: This would be more flexible and more extensible +// if the mappings were taken from an XML file, not hard-coded ... +// ... although having it in a .hxx file is better than nothing. +// +// Load the remap list from the .hxx file: + using namespace lex; +# define NIL "" +# define REMAP(from,to) _remap[#from] = to; +# include <atis_remap.hxx> +# undef REMAP +# undef NIL + +#ifdef ATIS_TEST + SG_LOG(SG_ATC, SG_ALERT, "ATIS initialized"); +#endif } // Hint: @@ -192,6 +211,7 @@ const int minute(60); // measured in seconds // Returns 1 if we actually generated something. int FGATIS::GenTransmission(const int regen, const int special) { using namespace atmodel; + using namespace lex; string BRK = ".\n"; @@ -216,7 +236,7 @@ int FGATIS::GenTransmission(const int regen, const int special) { if (ident.substr(0,2) == "EG") { // UK CAA radiotelephony manual indicates ATIS transmissions start // with "This is ..." - transmission += "This_is + "; + transmission += This_is + " "; } else { // In the US they just start with the airport name. } @@ -225,34 +245,29 @@ int FGATIS::GenTransmission(const int regen, const int special) { // Note that at this point, multi-word facility names // will sometimes contain hyphens, not spaces. -// Force the issue, just to be safe: - - string name2 = name; - for(string::iterator p = name2.begin(); p != name2.end(); p++){ - if (*p == ' ') *p = '-'; - } - -/////////////// -// FIXME: This would be more flexible and more extensible -// if the mappings were taken from an XML file, not hard-coded. -/////////////// + + vector<string> name_words; + boost::split(name_words, name, boost::is_any_of(" -")); + for (vector<string>::const_iterator wordp = name_words.begin(); + wordp != name_words.end(); wordp++) { + string word(*wordp); // Remap some abbreviations that occur in apt.dat, to // make things nicer for the text-to-speech system: - name2 = replace_word(name2, "Intl", "International"); - name2 = replace_word(name2, "Rgnl", "Regional"); - name2 = replace_word(name2, "Co", "County"); - name2 = replace_word(name2, "Muni", "Municipal"); - name2 = replace_word(name2, "Mem", "Memorial"); - name2 = replace_word(name2, "Fld", "Field"); - name2 = replace_word(name2, "AFB", "Air-Force-Base"); - name2 = replace_word(name2, "AAF", "Army-Air-Field"); - name2 = replace_word(name2, "MCAS", "Marine-Corps-Air-Station"); - transmission += name2 + " "; + for (MSS::const_iterator replace = _remap.begin(); + replace != _remap.end(); replace++) { + if (word == replace->first) { + word = replace->second; + break; + } + } + transmission += word + " "; + } + if (_type == ATIS /* as opposed to AWOS */) { - transmission += "airport_information "; + transmission += airport_information + " "; } else { - transmission += "Automated_weather_observation "; + transmission += Automated_weather_observation + " "; } phonetic_seq_string = GetPhoneticLetter(sequence); // Add the sequence letter @@ -263,9 +278,9 @@ int FGATIS::GenTransmission(const int regen, const int special) { mins = time_str.substr(3,2).c_str(); // speak each digit separately: transmission += ConvertNumToSpokenDigits(hours + mins); - transmission += " zulu weather" + BRK; + transmission += " " + zulu_weather + BRK; - transmission += "Wind: "; + transmission += wind + ": "; double wind_speed = fgGetDouble("/environment/config/boundary/entry[0]/wind-speed-kt"); double wind_dir = fgGetDouble("/environment/config/boundary/entry[0]/wind-from-heading-deg"); @@ -288,14 +303,14 @@ int FGATIS::GenTransmission(const int regen, const int special) { // Force west-facing rwys to be used in no-wind situations // which is consistent with Flightgear's initial setup: wind_dir = 270; - transmission += " light_and_variable"; + transmission += " " + light_and_variable; } else { // FIXME: get gust factor in somehow snprintf(buf, bs, "%03.0f", 5*SGMiscd::round(wind_dir/5)); transmission += ConvertNumToSpokenDigits(buf); snprintf(buf, bs, "%1.0f", wind_speed); - transmission += " at " + ConvertNumToSpokenDigits(buf) + BRK; + transmission += " " + at + " " + ConvertNumToSpokenDigits(buf) + BRK; } int did_some(0); @@ -304,17 +319,17 @@ int FGATIS::GenTransmission(const int regen, const int special) { for (int layer = 0; layer <= 4; layer++) { snprintf(buf, bs, "/environment/clouds/layer[%i]/coverage", layer); string coverage = fgGetString(buf); - if (coverage == "clear") continue; + if (coverage == clear) continue; snprintf(buf, bs, "/environment/clouds/layer[%i]/thickness-ft", layer); if (fgGetDouble(buf) == 0) continue; snprintf(buf, bs, "/environment/clouds/layer[%i]/elevation-ft", layer); double ceiling = int(fgGetDouble(buf) - _geod.getElevationFt()); if (ceiling > 12000) continue; - if (coverage == "scattered") { - if (!did_some) transmission += " Sky_condition: "; + if (coverage == scattered) { + if (!did_some) transmission += " " + Sky_condition + ": "; did_some++; } else /* must be a ceiling */ if (!did_ceiling) { - transmission += " Ceiling: "; + transmission += " " + Ceiling + ": "; did_ceiling++; did_some++; } else { @@ -327,51 +342,52 @@ int FGATIS::GenTransmission(const int regen, const int special) { if (cig000) { snprintf(buf, bs, "%i", cig000); transmission += ConvertNumToSpokenDigits(buf); - transmission += " thousand "; + transmission += " " + thousand + " "; } if (cig00) { snprintf(buf, bs, "%i", cig00); transmission += ConvertNumToSpokenDigits(buf); - transmission += " hundred "; + transmission += " " + hundred + " "; } } else { // Should this be "sky obscured?" - transmission += " zero "; // not "zero hundred" + transmission += " " + zero + " "; // not "zero hundred" } transmission += coverage + BRK; } - transmission += "Temperature: "; + transmission += Temperature + ": "; double Tsl = fgGetDouble("/environment/temperature-sea-level-degc"); int temp = int(SGMiscd::round(FGAtmo().fake_T_vs_a_us(_geod.getElevationFt(), Tsl))); if(temp < 0) { - transmission += "minus "; + transmission += lex::minus + " "; } snprintf(buf, bs, "%i", abs(temp)); transmission += ConvertNumToSpokenDigits(buf); - transmission += " dewpoint "; + transmission += " " + Celsius; + transmission += " " + dewpoint + " "; double dpsl = fgGetDouble("/environment/dewpoint-sea-level-degc"); temp = int(SGMiscd::round(FGAtmo().fake_dp_vs_a_us(dpsl, _geod.getElevationFt()))); if(temp < 0) { - transmission += "minus "; + transmission += lex::minus + " "; } snprintf(buf, bs, "%i", abs(temp)); - transmission += ConvertNumToSpokenDigits(buf) + BRK; + transmission += ConvertNumToSpokenDigits(buf); + transmission += " " + Celsius + BRK; - - transmission += "Visibility: "; + transmission += Visibility + ": "; double visibility = fgGetDouble("/environment/config/boundary/entry[0]/visibility-m"); visibility /= atmodel::sm; // convert to statute miles if (visibility < 0.25) { - transmission += "less than one quarter"; + transmission += less_than_one_quarter; } else if (visibility < 0.5) { - transmission += "one quarter"; + transmission += one_quarter; } else if (visibility < 0.75) { - transmission += "one half"; + transmission += one_half; } else if (visibility < 1.0) { - transmission += "three quarters"; + transmission += three_quarters; } else if (visibility >= 1.5 && visibility < 2.0) { - transmission += "one and one half"; + transmission += one_and_one_half; } else { // integer miles if (visibility > 10) visibility = 10; @@ -380,7 +396,7 @@ int FGATIS::GenTransmission(const int regen, const int special) { } transmission += BRK; - transmission += "Altimeter: "; + transmission += Altimeter + ": "; double myQNH; double Psl = fgGetDouble("/environment/pressure-sea-level-inhg"); { @@ -412,7 +428,7 @@ int FGATIS::GenTransmission(const int regen, const int special) { assert(apt); string rwy_no = apt->getActiveRunwayForUsage()->ident(); if(rwy_no != "NN") { - transmission += "Landing_and_departing_runway "; + transmission += Landing_and_departing_runway + " "; transmission += ConvertRwyNumToSpokenString(rwy_no) + BRK; if (msg_OK) { msg_time = cur_time; @@ -420,7 +436,7 @@ int FGATIS::GenTransmission(const int regen, const int special) { // << " wind_dir: " << wind_dir << endl; } } - transmission += "On_initial_contact_advise_you_have_information "; + transmission += On_initial_contact_advise_you_have_information + " "; transmission += phonetic_seq_string; transmission += "... " + BRK; } diff --git a/src/ATCDCL/atis.hxx b/src/ATCDCL/atis.hxx index aeafe33fb..cd35ea476 100644 --- a/src/ATCDCL/atis.hxx +++ b/src/ATCDCL/atis.hxx @@ -34,6 +34,7 @@ //DCL - a complete guess for now. #define FG_ATIS_DEFAULT_RANGE 30 +typedef std::map<std::string,std::string> MSS; class FGATIS : public FGATC { @@ -52,6 +53,7 @@ class FGATIS : public FGATC { int attention; bool _prev_display; // Previous value of _display flag + MSS _remap; // abbreviations to be expanded // Aircraft position // ATIS is actually a special case in that unlike other ATC eg.tower it doesn't actually know about diff --git a/src/ATCDCL/atis_lexicon.hxx b/src/ATCDCL/atis_lexicon.hxx new file mode 100644 index 000000000..9d4300d0b --- /dev/null +++ b/src/ATCDCL/atis_lexicon.hxx @@ -0,0 +1,59 @@ +#ifndef _FG_ATIS_LEXICON_HXX +#define _FG_ATIS_LEXICON_HXX + +#include <string> + + +#define Q(word) const std::string word(#word); + +namespace lex { +Q(Airport) +Q(Airfield) +Q(Airbase) +Q(Junior) +Q(Celsius) +Q(wind) +Q(zulu_weather) +Q(Automated_weather_observation) +Q(weather) +Q(airport_information) +Q(International) +Q(Regional) +Q(County) +Q(Municipal) +Q(Memorial) +Q(Field) +Q(Air_Force_Base) +Q(Army_Air_Field) +Q(Marine_Corps_Air_Station) +Q(light_and_variable) +Q(at) +Q(thousand) +Q(hundred) +Q(zero) +Q(Temperature) +Q(clear) +Q(scattered) +Q(broken) +Q(overcast) +Q(Sky_condition) +Q(Ceiling) +Q(minus) +Q(dewpoint) +Q(Visibility) +Q(less_than_one_quarter) +Q(one_quarter) +Q(one_half) +Q(three_quarters) +Q(one_and_one_half) +Q(Altimeter) +Q(Landing_and_departing_runway) +Q(On_initial_contact_advise_you_have_information) +Q(This_is) +Q(left) +Q(right) +Q(center) +} + +#undef Q +#endif // _FG_ATIS_LEXICON_HXX diff --git a/src/ATCDCL/atis_remap.hxx b/src/ATCDCL/atis_remap.hxx new file mode 100644 index 000000000..f679b70b9 --- /dev/null +++ b/src/ATCDCL/atis_remap.hxx @@ -0,0 +1,15 @@ +REMAP(Intl, International) +REMAP(Rgnl, Regional) +REMAP(Co, County) +REMAP(Muni, Municipal) +REMAP(Mem, Memorial) +REMAP(Apt, Airport) +REMAP(Arpt, Airport) +REMAP(Fld, Field) +REMAP(AFLD, Airfield) +REMAP(AFB, Air_Force_Base) +REMAP(AB, Airbase) +REMAP(AAF, Army_Air_Field) +REMAP(MCAS, Marine_Corps_Air_Station) +REMAP(JR, Junior) +REMAP(GKI, NIL)