24#include <simgear/structure/exception.hxx>
25#include <simgear/props/props_io.hxx>
33using simgear::PropertyList;
37#define SPACE append(1,' ')
41 return globals->get_locale()->getLocalizedString(text,
"atc", text);
45 const string& defaultValue)
47 return globals->get_locale()->getLocalizedString(text,
"atc", defaultValue);
52 string key =
"n" + std::to_string(
i);
59 for( string::iterator it = number.begin(); it != number.end(); ++it ) {
70 bool negative =
false;
84 while( n++ < digits ) {
94 while( !spokenDigits.empty() ) {
98 result.append( spokenDigits.back() );
99 spokenDigits.pop_back();
109 int hundreds = (
altitude % 1000) / 100;
111 if( thousands > 0 ) {
163SGPropertyNode_ptr
findAtisTemplate(
const std::string & stationId, SGPropertyNode_ptr atisSchemaNode )
165 using simgear::strutils::starts_with;
166 SGPropertyNode_ptr atisTemplate;
168 PropertyList schemaNodes = atisSchemaNode->getChildren(
"atis-schema");
169 for( PropertyList::iterator asit = schemaNodes.begin(); asit != schemaNodes.end(); ++asit ) {
170 SGPropertyNode_ptr ppp = (*asit)->getNode(
"station-starts-with",
false );
171 atisTemplate = (*asit)->getNode(
"atis",
false );
172 if( !atisTemplate.valid() )
continue;
174 PropertyList startsWithNodes = (*asit)->getChildren(
"station-starts-with");
175 for( PropertyList::iterator swit = startsWithNodes.begin(); swit != startsWithNodes.end(); ++swit ) {
177 if( starts_with( stationId, (*swit)->getStringValue() ) ) {
189 using simgear::strutils::lowercase;
195 SG_LOG( SG_ATC, SG_WARN,
"ATISEncoder: unknown airport id " << atisInformation->
airportId() );
199 _atis = atisInformation;
206 SGPath path =
globals->resolve_maybe_aircraft_path(
"ATC/atis.xml");
209 catch (
const sg_exception& e)
211 SG_LOG( SG_ATC, SG_ALERT,
"ATISEncoder: Failed to load atis schema definition: " << e.getMessage());
216 string stationId = lowercase(
airport->ident() );
219 if( !atisTemplate.valid() ) {
220 SG_LOG(SG_ATC, SG_WARN,
"no matching atis template for station " << stationId );
231 for(
int i = 0;
i < node->nChildren();
i++ ) {
240 HandlerMap::iterator it =
handlerMap.find( token->getNameString());
242 SG_LOG(SG_ATC, SG_WARN,
"ATISEncoder: unknown token: " << token->getNameString() );
246 return (this->*h)( token );
251 return token->getStringValue();
256 HandlerMap::iterator it =
handlerMap.find( token->getStringValue());
258 SG_LOG(SG_ATC, SG_WARN,
"ATISEncoder: unknown token: " << token->getStringValue() );
262 return (this->*h)( token );
267 using namespace simgear::strutils;
269 SGPropertyNode_ptr n;
271 if( (n = token->getChild(
"empty",
false )).valid() ) {
277 if( (n = token->getChild(
"not-empty",
false )).valid() ) {
283 if( (n = token->getChild(
"contains",
false )).valid() ) {
289 if( (n = token->getChild(
"not-contains",
false )).valid() ) {
295 if( (n = token->getChild(
"ends-with",
false )).valid() ) {
301 if( (n = token->getChild(
"not-ends-with",
false )).valid() ) {
307 if( (n = token->getChild(
"equals",
false )).valid() ) {
313 if( (n = token->getChild(
"not-equals",
false )).valid() ) {
319 if( (n = token->getChild(
"starts-with",
false )).valid() ) {
325 if( (n = token->getChild(
"not-starts-with",
false )).valid() ) {
326 return checkCondition( n,
false, &starts_with,
"not-starts-with") ?
331 SG_LOG(SG_ATC, SG_WARN,
"ATISEncoder: no valid token found for <if> element" );
338 SGPropertyNode_ptr n1 = node->getNode(
"token",
false );
340 SG_LOG(SG_ATC, SG_WARN,
"missing <token> node for (not)-empty" );
347 bool (*fp)(
const string &,
const string &),
const string &
name )
349 using namespace simgear::strutils;
351 SGPropertyNode_ptr n1 = node->getNode(
"token", 0,
false );
352 SGPropertyNode_ptr n2 = node->getNode(
"token", 1,
false );
354 if( n1.valid() && n2.valid() ) {
356 return comp == notInverted;
359 if( n1.valid() && !n2.valid() ) {
360 SGPropertyNode_ptr t1 = node->getNode(
"text", 0,
false );
364 return fp( n1s, t1s ) == notInverted;
366 SG_LOG(SG_ATC, SG_WARN,
"missing <token> or <text> node for " <<
name);
370 SG_LOG(SG_ATC, SG_WARN,
"missing <token> node for " <<
name);
377 if( NULL != dynamics ) {
399 return airport->findBestRunwayForHeading( windDeg, &
p );
405 if( runway.valid() ) {
406 if (runway->ILS() !=
nullptr) {
418 if( runway.valid() ) {
419 string runwayIdent = runway->ident();
420 if(runwayIdent !=
"NN") {
435 double hPa =
_atis->getQnh();
448 }
else if (hPa <= 1013) {
450 }
else if (hPa <= 1046) {
458 int e = int(
airport->getElevation() / 1000.0);
471 bool vrb =
_atis->getWindMinDeg() == 0 &&
_atis->getWindMaxDeg() == 359;
492 int g =
_atis->getGustsKt();
509 int v =
_atis->getVisibilityMeters();
512 if( v >= 9999 )
return reply.append(
getSpokenNumber(10) ).SPACE.append( km ).SPACE.append(or_more);
520 int v =
_atis->getVisibilityMeters();
521 int vft = int( v * SG_METER_TO_FEET / 100 + 0.5 ) * 100;
522 int vsm = int( v * SG_METER_TO_SM + 0.5 );
525 if( vsm < 1 )
return reply.append(
getSpokenAltitude( vft ) ).SPACE.append( feet );
532 return _atis->getPhenomena();
542 for (ATISInformationProvider::CloudEntries::iterator it = cloudEntries.begin(); it != cloudEntries.end(); ++it) {
545 reply.append( it->second ).SPACE.append(
getSpokenAltitude(it->first).SPACE.append( FEET ) );
557 for (ATISInformationProvider::CloudEntries::iterator it = cloudEntries.begin(); it != cloudEntries.end(); ++it) {
559 reply.append(
",").SPACE;
583 double qnh =
_atis->getQnhInHg();
589 double qnh =
_atis->getQnhInHg();
590 int f = int(100 * (qnh -
int(qnh)) + 0.5);
598 .SPACE.append(DECIMAL).SPACE
604 return _atis->getTrend();
static string getSpokenFormWithDefault(const string &text, const string &defaultValue)
SGPropertyNode_ptr findAtisTemplate(const std::string &stationId, SGPropertyNode_ptr atisSchemaNode)
static FGRunwayRef findBestRunwayForWind(FGAirportRef airport, int windDeg, int windKt)
static string NO_ATIS("nil")
static string getSpokenForm(const string &text)
SGSharedPtr< FGAirport > FGAirportRef
SGSharedPtr< FGRunway > FGRunwayRef
static std::string getSpokenNumber(std::string number)
static std::string getSpokenAltitude(int altitude)
static std::string getSpokenDigit(int i)
virtual std::string getCavok(SGPropertyNode_ptr)
virtual std::string getInhg(SGPropertyNode_ptr)
ATISInformationProvider * _atis
virtual std::string getAtisId(SGPropertyNode_ptr)
virtual std::string getVisibilityMiles(SGPropertyNode_ptr)
static bool equals(const std::string &s1, const std::string &s2)
std::string processTokenToken(SGPropertyNode_ptr baseNode)
virtual std::string getVisibilityMetric(SGPropertyNode_ptr)
virtual std::string getCloudsBrief(SGPropertyNode_ptr)
virtual std::string getQnh(SGPropertyNode_ptr)
virtual std::string getApproachType(SGPropertyNode_ptr)
virtual std::string getInhgFraction(SGPropertyNode_ptr)
std::string processIfToken(SGPropertyNode_ptr baseNode)
virtual std::string getPhenomena(SGPropertyNode_ptr)
virtual std::string getAirportName(SGPropertyNode_ptr)
std::string processTextToken(SGPropertyNode_ptr baseNode)
std::string processTokens(SGPropertyNode_ptr baseNode)
virtual std::string getLandingRunway(SGPropertyNode_ptr)
std::string(ATISEncoder::* handler_t)(SGPropertyNode_ptr baseNode)
virtual std::string getTakeoffRunway(SGPropertyNode_ptr)
bool checkCondition(SGPropertyNode_ptr node, bool notInverted, bool(*fp)(const std::string &, const std::string &), const std::string &name)
std::string processToken(SGPropertyNode_ptr baseNode)
virtual std::string getClouds(SGPropertyNode_ptr)
virtual std::string encodeATIS(ATISInformationProvider *atisInformationProvider)
virtual std::string getDewpointDeg(SGPropertyNode_ptr)
virtual std::string getTransitionLevel(SGPropertyNode_ptr)
virtual std::string getWindMaxDirection(SGPropertyNode_ptr)
virtual std::string getTemperatureDeg(SGPropertyNode_ptr)
virtual std::string getTime(SGPropertyNode_ptr)
virtual std::string getInhgInteger(SGPropertyNode_ptr)
SGPropertyNode_ptr atisSchemaNode
virtual std::string getWindDirection(SGPropertyNode_ptr)
virtual std::string getWindMinDirection(SGPropertyNode_ptr)
virtual std::string getGustsKnots(SGPropertyNode_ptr)
static bool contains(const std::string &s, const std::string &substring)
virtual std::string getWindspeedKnots(SGPropertyNode_ptr)
virtual std::string getTrend(SGPropertyNode_ptr)
bool checkEmptyCondition(SGPropertyNode_ptr node, bool isEmpty)
const std::string getAtisSequence()
get current ATIS sequence letter
int updateAtisSequence(int interval, bool forceUpdate)
get the current ATIS sequence number, updating it if necessary
static FGAirportRef getByIdent(const std::string &aIdent)
Helper to look up an FGAirport instance by unique ident.
std::vector< std::string > string_list
FlightGear Localization Support.