24 #include <unordered_map>
26 #include <wx/datetime.h>
28 #include <wx/string.h>
31 #include "model/ais_target_data.h"
32 #include "model/config_vars.h"
33 #include "model/navutil_base.h"
34 #include "model/own_ship.h"
36 static std::unordered_map<int, wxString> s_ERI_hash;
38 void make_hash_ERI(
int key,
const wxString &description) {
39 s_ERI_hash[key] = description;
42 void clear_hash_ERI() { s_ERI_hash.clear(); }
44 static wxString FormatTimeAdaptive(
int seconds) {
47 return wxString::Format(_T(
"%3ds"), seconds);
48 else if (seconds < 3600) {
51 return wxString::Format(_T(
"%2dmin %02ds"), m, s);
53 int h = seconds / 3600;
55 return wxString::Format(_T(
"%2dh %02dmin"), h, m);
58 static wxString html_escape(
const wxString &src) {
62 ret.Replace(_T(
"<"), _T(
"<"));
63 ret.Replace(_T(
">"), _T(
">"));
75 wxString trimAISField(
char *data) {
78 wxString field = wxString::From8BitData(data);
79 while (field.Right(1) ==
'@' || field.Right(1) ==
' ') field.RemoveLast();
88 wxString ais_get_status(
int index) {
89 static const wxString ais_status[] = {
90 _(
"Underway using Engine"),
92 _(
"Not Under Command"),
93 _(
"Restricted Manoeuvrability"),
94 _(
"Constrained by draught"),
97 _(
"Engaged in Fishing"),
98 _(
"Underway Sailing"),
99 _(
"High Speed Craft"),
100 _(
"Wing In Ground Effect"),
101 _(
"Power-driven vessel towing astern (regional use)"),
102 _(
"Power-driven vessel pushing ahead or towing alongside (regional use)"),
107 _(
"AtoN Virtual (On Position)"),
108 _(
"AtoN Virtual (Off Position)"),
110 _(
"AtoN Real (On Position)"),
111 _(
"AtoN Real(Off Position)")};
113 return ais_status[index];
116 wxString ais_meteo_get_trend(
int tend) {
117 wxString trend = wxEmptyString;
122 trend = _(
"decreasing");
124 trend = _(
"increasing");
129 wxString aisMeteoPrecipType(
int precip) {
130 wxString prec = wxEmptyString;
139 prec =
"Thunderstorm";
142 prec =
"Freezing rain";
145 prec =
"Mixed / ice";
150 prec =
"not available";
156 wxString aisMeteoWaterLevelRef(
int refID) {
157 wxString ref = wxEmptyString;
205 strncpy(ShipName,
"Unknown ", SHIP_NAME_LEN);
206 strncpy(CallSign,
" ", 8);
207 strncpy(Destination,
" ", DESTINATION_LEN);
208 ShipNameExtension[0] = 0;
209 b_show_AIS_CPA =
false;
218 wxDateTime now = wxDateTime::Now();
220 PositionReportTicks = now.GetTicks();
221 StaticReportTicks = now.GetTicks();
228 NavStatus = UNDEFINED;
232 b_isDSCtarget =
false;
242 DimA = DimB = DimC = DimD = 0;
259 n_alert_state = AIS_NO_ALERT;
260 b_suppress_audio =
false;
261 b_positionDoubtful =
false;
262 b_positionOnceValid =
false;
268 strncpy(Euro_VIN,
" ", 8);
271 b_isEuroInland =
false;
272 b_blue_paddle =
false;
276 b_PersistTrack =
false;
277 b_mPropPersistTrack =
false;
278 b_in_ack_timeout =
false;
283 b_isFollower =
false;
285 b_show_track = g_bAISShowTracks;
286 b_SarAircraftPosnReport =
false;
288 b_nameFromCache =
false;
290 for (
unsigned int i = 0; i < AIS_TARGETDATA_MAX_CANVAS; i++)
292 met_data.original_mmsi = 0;
293 met_data.stationID = 0;
297 met_data.minute = 60;
298 met_data.pos_acc = 1;
299 met_data.wind_kn = 122;
300 met_data.wind_gust_kn = 127;
301 met_data.wind_dir = 360;
302 met_data.wind_gust_dir = 360;
303 met_data.air_temp = -102.4;
304 met_data.rel_humid = 101;
305 met_data.dew_point = 50.1;
306 met_data.airpress = 1310;
307 met_data.airpress_tend = 3;
308 met_data.hor_vis = 12.7;
309 met_data.hor_vis_GT =
false;
310 met_data.water_lev_dev = 4001 / 100 - 10;
311 met_data.water_level = -32;
312 met_data.water_lev_trend = 3;
313 met_data.current = 25.5;
314 met_data.curr_dir = 360;
315 met_data.wave_height = 25.5;
316 met_data.wave_period = 63;
317 met_data.wave_dir = 360;
318 met_data.swell_height = 25.5;
319 met_data.swell_per = 63;
320 met_data.swell_dir = 360;
321 met_data.seastate = 13;
322 met_data.water_temp = 501;
323 met_data.precipitation = 7;
324 met_data.salinity = 51.;
326 met_data.vertical_ref = 14;
330 strncpy(ShipName, q->ShipName, SHIP_NAME_LEN);
331 strncpy(CallSign, q->CallSign, 8);
332 strncpy(Destination, q->Destination, DESTINATION_LEN);
333 ShipNameExtension[0] = 0;
334 b_show_AIS_CPA = q->b_show_AIS_CPA;
344 PositionReportTicks = q->PositionReportTicks;
345 StaticReportTicks = q->StaticReportTicks;
347 b_removed = q->b_removed;
352 NavStatus = q->NavStatus;
353 SyncState = q->SyncState;
355 ShipType = q->ShipType;
356 b_isDSCtarget = q->b_isDSCtarget;
357 m_dscNature = q->m_dscNature;
358 m_dscTXmmsi = q->m_dscTXmmsi;
363 Range_NM = q->Range_NM;
372 ETA_Day = q->ETA_Day;
374 ETA_Min = q->ETA_Min;
378 RecentPeriod = q->RecentPeriod;
380 m_utc_hour = q->m_utc_hour;
381 m_utc_min = q->m_utc_min;
382 m_utc_sec = q->m_utc_sec;
385 n_alert_state = q->n_alert_state;
386 b_suppress_audio = q->b_suppress_audio;
387 b_positionDoubtful = q->b_positionDoubtful;
388 b_positionOnceValid = q->b_positionOnceValid;
389 b_nameValid = q->b_nameValid;
391 Euro_Length = q->Euro_Length;
392 Euro_Beam = q->Euro_Beam;
393 Euro_Draft = q->Euro_Draft;
394 memcpy(Euro_VIN, q->Euro_VIN, EURO_VIN_LEN);
395 UN_shiptype = q->UN_shiptype;
397 b_isEuroInland = q->b_isEuroInland;
398 b_blue_paddle = q->b_blue_paddle;
400 b_OwnShip = q->b_OwnShip;
401 b_in_ack_timeout = q->b_in_ack_timeout;
403 m_ptrack = q->m_ptrack;
405 b_active = q->b_active;
406 blue_paddle = q->blue_paddle;
407 bCPA_Valid = q->bCPA_Valid;
409 b_show_track = q->b_show_track;
410 b_SarAircraftPosnReport = q->b_SarAircraftPosnReport;
411 altitude = q->altitude;
414 AisTargetData::~AisTargetData() { m_ptrack.clear(); }
417 wxString AisTargetData::GetFullName(
void) {
420 wxString shipName = trimAISField(ShipName);
421 if (shipName == _T(
"Unknown"))
422 retName = wxGetTranslation(shipName);
426 if (strlen(ShipNameExtension)) {
427 wxString shipNameExt = trimAISField(ShipNameExtension);
428 retName += shipNameExt;
435 wxString AisTargetData::BuildQueryResult(
void) {
437 wxDateTime now = wxDateTime::Now();
439 wxString tableStart = _T(
"\n<table border=0 cellpadding=1 cellspacing=0>\n");
440 wxString tableEnd = _T(
"</table>\n\n");
441 wxString rowStart = _T(
"<tr><td><font size=-2>");
442 wxString rowStartH = _T(
"<tr><td nowrap>");
443 wxString rowSeparator = _T(
"</font></td><td></td><td><b>");
444 wxString rowSeparatorH = _T(
"</td><td></td><td>");
445 wxString colSeparator = _T(
"<td></td>");
446 wxString rowEnd = _T(
"</b></td></tr>\n");
447 wxString vertSpacer =
448 _T(
"<tr><td></td></tr><tr><td></td></tr><tr><td></td></tr>\n\n");
450 wxString IMOstr, MMSIstr, ClassStr;
452 html << tableStart << _T(
"<tr><td nowrap colspan=2>");
454 html << _T(
"<font size=+2><i><b>") << GetFullName();
455 html << _T(
"</b></i></font> <b>");
458 if ((Class != AIS_ATON) && (Class != AIS_BASE) && (Class != AIS_GPSG_BUDDY) &&
459 (Class != AIS_SART) && (Class != AIS_METEO)) {
460 html << trimAISField(CallSign) << _T(
"</b>") << rowEnd;
462 if (Class != AIS_CLASS_B) {
463 if (IMO > 0) IMOstr = wxString::Format(_T(
"%08d"), abs(IMO));
466 html << _T(
"</b>") << rowEnd;
470 if (Class != AIS_GPSG_BUDDY) {
471 MMSIstr = wxString::Format(_T(
"%09d"), abs(MMSI));
473 ClassStr = wxGetTranslation(Get_class_string(
false));
475 if (Class == AIS_ATON) {
476 wxString cls(_T(
"AtoN: "));
477 cls += Get_vessel_type_string(
false);
478 ClassStr = wxGetTranslation(cls);
481 if (b_SarAircraftPosnReport) {
482 int airtype = (MMSI % 1000) / 100;
483 ClassStr = airtype == 5 ? _(
"SAR Helicopter") : _(
"SAR Aircraft");
487 html << _T(
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
489 << rowStart << _("MMSI")
490 << _T("</font></td><td> </td><td><font size=-2>") << _("Class")
491 << _T("</font></td><td> </td><td align=right><font size=-2>")
492 << _("IMO") << _T("</font></td></tr>") << rowStartH << _T("<b>")
493 << MMSIstr << _T("</b></td><td> </td><td><b>") << ClassStr
494 << _T("</b></td><td> </td><td align=right><b>") << IMOstr
495 << rowEnd << _T("</table></td></tr>");
497 else if (Class == AIS_METEO) {
498 MMSIstr = wxString::Format(_T(
"%09d"), abs(met_data.original_mmsi));
499 html << _T(
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
501 << rowStart << _("MMSI")
502 << _T("</font></td><td> </td><td align=right><font size=-2>")
503 << _("Class") << _T("</font></td></tr>") << rowStartH << _T("<b>")
504 << MMSIstr << _T("</b></td><td> </td><td align=right><b>")
505 << _T("<font size=-1>") << ClassStr << rowEnd << rowStart
506 << _T("<b>ID: ") << MMSI;
507 if (met_data.stationID) {
509 wxString::Format(_T(
"%06d"), (met_data.stationID - 1000000));
510 html <<
"<td> </td><td align=right>" <<
"SK-ID: " << SK_ID;
512 html << rowEnd << _T(
"</b></table></td></tr>");
515 html << _T(
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
517 << rowStart << _("MMSI")
518 << _T("</font></td><td> </td><td align=right><font size=-2>")
519 << _("Class") << _T("</font></td></tr>") << rowStartH << _T("<b>")
520 << MMSIstr << _T("</b></td><td> </td><td align=right><b>")
521 << ClassStr << rowEnd << _T("</table></td></tr>");
523 if ((Class != AIS_SART))
524 html << _T("<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
527 << ((Class == AIS_BASE || Class == AIS_ATON || Class == AIS_METEO)
530 << rowEnd << _T("</font></td></tr>") << rowStartH
531 << _T("<font size=-1><b>")
532 << GetCountryCode(true) << rowEnd << _T("</font></table></td></tr>");
535 if ((Class != AIS_BASE) && (Class != AIS_CLASS_B) && (Class != AIS_SART) &&
536 (Class != AIS_METEO)) {
538 if ((NavStatus <= 21) && (NavStatus >= 0))
539 navStatStr = wxGetTranslation(ais_get_status(NavStatus));
540 }
else if (Class == AIS_SART) {
541 if (NavStatus == RESERVED_14)
542 navStatStr = _(
"Active");
543 else if (NavStatus == UNDEFINED)
544 navStatStr = _(
"Testing");
547 wxString sart_sub_type;
548 if (Class == AIS_SART) {
549 int mmsi_start = MMSI / 1000000;
550 switch (mmsi_start) {
555 sart_sub_type = _T(
"MOB");
558 sart_sub_type = _T(
"EPIRB");
561 sart_sub_type = _(
"Unknown");
566 wxString AISTypeStr, UNTypeStr, sizeString;
567 if ((Class != AIS_BASE) && (Class != AIS_SART) && (Class != AIS_DSC) &&
568 (Class != AIS_METEO)) {
570 AISTypeStr = wxGetTranslation(Get_vessel_type_string());
572 if (b_isEuroInland && UN_shiptype) {
573 auto it = s_ERI_hash.find(UN_shiptype);
575 if (it == s_ERI_hash.end())
576 type = _(
"Undefined");
580 UNTypeStr = wxGetTranslation(type);
583 if (b_SarAircraftPosnReport) {
589 if (Class == AIS_SART) {
590 if (MSG_14_text.Len()) {
591 html << rowStart << _(
"Safety Broadcast Message") << rowEnd << rowStartH
592 << _T(
"<b>") << MSG_14_text << rowEnd;
598 if (NavStatus != ATON_VIRTUAL && Class != AIS_ARPA && Class != AIS_APRS) {
599 if ((Class == AIS_CLASS_B) || (Class == AIS_ATON)) {
601 wxString::Format(_T(
"%dm x %dm"), (DimA + DimB), (DimC + DimD));
602 }
else if (!b_SarAircraftPosnReport) {
603 if ((DimA + DimB + DimC + DimD) == 0) {
604 if (b_isEuroInland) {
605 if (Euro_Length == 0.0) {
606 if (Euro_Draft > 0.01) {
607 sizeString << wxString::Format(_T(
"---m x ---m x %4.1fm"),
610 sizeString << _T(
"---m x ---m x ---m");
613 if (Euro_Draft > 0.01) {
614 sizeString << wxString::Format(_T(
"%5.1fm x %4.1fm x %4.1fm"),
615 Euro_Length, Euro_Beam,
618 sizeString << wxString::Format(_T(
"%5.1fm x %4.1fm x ---m\n\n"),
619 Euro_Length, Euro_Beam);
624 sizeString << wxString::Format(_T(
"---m x ---m x %4.1fm"), Draft);
626 sizeString << _T(
"---m x ---m x ---m");
629 }
else if (Draft < 0.01) {
630 sizeString << wxString::Format(_T(
"%dm x %dm x ---m"), (DimA + DimB),
633 sizeString << wxString::Format(_T(
"%dm x %dm x %4.1fm"),
634 (DimA + DimB), (DimC + DimD), Draft);
640 if (Class == AIS_SART) {
641 html << _T(
"<tr><td colspan=2>")
642 << _T(
"<b>") << AISTypeStr;
643 if (sart_sub_type.Length()) html << _T(
" (") << sart_sub_type << _T(
"), ");
645 html << rowEnd << _T(
"<tr><td colspan=2>")
646 << _T(
"<b>") << sizeString << rowEnd;
649 else if (Class == AIS_ATON) {
650 html << _T(
"<tr><td colspan=2>")
651 << _T(
"<b>") << navStatStr;
652 html << rowEnd << _T(
"<tr><td colspan=2>")
653 << _T(
"<b>") << sizeString << rowEnd;
655 else if (Class == AIS_DSC && (ShipType == 12 || ShipType == 16) ) {
656 if (ShipType == 16) {
657 html << _T(
"<tr><td colspan=2>") << _T(
"<b>") << _(
"Distress relay");
658 if (m_dscTXmmsi > 2000000) {
659 wxString mmsirelay = wxString::Format(_T(
" %09d"), abs(m_dscTXmmsi));
660 html << _T(
" ") << _(
"by:") << mmsirelay;
662 html << _T(
"<b>") << sizeString << rowEnd;
664 html << _T(
"<tr><td colspan=2>") << _(
"Nature of distress: ")
665 << rowEnd << _T(
"<tr><td colspan=2>");
666 if (m_dscNature < 13) {
667 html << _T(
"<tr><td colspan=2>") << _T(
"<b>") << GetNatureofDistress(m_dscNature)
668 << _T(
"<b>") << sizeString << rowEnd << _T(
"<tr><td colspan=2>");
671 else if ((Class != AIS_BASE) && (Class != AIS_DSC)) {
672 html << _T(
"<tr><td colspan=2>")
673 << _T(
"<b>") << AISTypeStr;
674 if (navStatStr.Length()) html << _T(
", ") << navStatStr;
675 if (UNTypeStr.Length()) html << _T(
" (UN Type ") << UNTypeStr << _T(
")");
676 html << rowEnd << _T(
"<tr><td colspan=2>")
677 << _T(
"<b>") << sizeString << rowEnd;
680 if (b_positionOnceValid) {
682 if (b_positionDoubtful) posTypeStr << _(
" (Last Known)");
685 int target_age = now.GetTicks() - PositionReportTicks;
690 html << vertSpacer << rowStart << _(
"Position") << posTypeStr
691 << _T(
"</font></td><td align=right><font size=-2>") << _(
"Report Age")
692 << _T(
"</font></td></tr>")
694 << rowStartH << _T(
"<b>") << toSDMM(1, Lat)
695 << _T(
"</b></td><td align=right><b>") << FormatTimeAdaptive(target_age)
696 << rowEnd << rowStartH << _T(
"<b>") << toSDMM(2, Lon);
697 if (Class != AIS_METEO) html << rowEnd;
700 wxString::Format(
" %02d:%02d", met_data.hour, met_data.minute);
701 html <<
" </td><td align=right></b></font><font size=-3>"
702 << _(
"Issued (UTC)") <<
"</font><font size=-1><b>" << meteoTime
703 <<
"</font>" << rowEnd;
707 wxString courseStr, sogStr, hdgStr, rotStr, rngStr, brgStr, destStr, etaStr;
709 if (Class == AIS_GPSG_BUDDY) {
710 long month, year, day;
711 m_date_string.Mid(0, 2).ToLong(&day);
712 m_date_string.Mid(2, 2).ToLong(&month);
713 m_date_string.Mid(4, 2).ToLong(&year);
716 date.SetMonth((wxDateTime::Month)(month - 1));
717 date.SetYear(year + 2000);
719 wxString f_date = date.FormatISODate();
721 html << vertSpacer << rowStart << _(
"Report as of") << rowEnd << rowStartH
722 << _T(
"<b>") << f_date + _T(
"</b> at <b>")
723 << wxString::Format(_T(
"%d:%d UTC "), m_utc_hour, m_utc_min) << rowEnd;
725 if (Class == AIS_CLASS_A && !b_SarAircraftPosnReport) {
726 html << vertSpacer << rowStart << _(
"Destination")
727 << _T(
"</font></td><td align=right><font size=-2>") << _(
"ETA (UTC)")
728 << _T(
"</font></td></tr>\n") << rowStartH << _T(
"<b>");
729 wxString dest = trimAISField(Destination);
731 html << html_escape(dest);
734 html << _T(
"</b></td><td nowrap align=right><b>");
736 if ((ETA_Mo) && (ETA_Hr < 24)) {
738 if (now.GetMonth() > (ETA_Mo - 1)) yearOffset = 1;
739 wxDateTime eta(ETA_Day, wxDateTime::Month(ETA_Mo - 1),
740 now.GetYear() + yearOffset, ETA_Hr, ETA_Min);
741 html << eta.Format(_T(
"%b %d %H:%M"));
747 if (Class == AIS_CLASS_A || Class == AIS_CLASS_B || Class == AIS_ARPA ||
748 Class == AIS_APRS || Class == AIS_SART) {
749 int crs = wxRound(COG);
751 wxString magString, trueString;
753 magString << wxString::Format(wxString(
"%03d%c(M)"),
754 static_cast<int>(m_callbacks.get_mag(COG)),
757 trueString << wxString::Format( wxString(
"%03d%c "), (
int)crs, 0x00B0 );
759 courseStr << trueString << magString;
760 }
else if (COG == 360.0)
761 courseStr = _T(
"---");
763 courseStr = _T(
"0°");
765 double speed_show = toUsrSpeed(SOG);
767 if ((SOG <= 102.2) || b_SarAircraftPosnReport) {
768 if (speed_show < 10.0)
770 wxString::Format(_T(
"%.2f "), speed_show) + getUsrSpeedUnit();
771 else if (speed_show < 100.0)
773 wxString::Format(_T(
"%.1f "), speed_show) + getUsrSpeedUnit();
776 wxString::Format(_T(
"%.0f "), speed_show) + getUsrSpeedUnit();
784 hdgStr = wxString::Format(_T(
"%03d°"), (
int)HDG);
788 if (ROTAIS != -128) {
790 rotStr << _T(
"> 5°/30s ") << _(
"Right");
791 else if (ROTAIS == -127)
792 rotStr << _T(
"> 5°/30s ") << _(
"Left");
795 rotStr << wxString::Format(_T(
"%3d°/Min "), ROTIND)
798 rotStr << wxString::Format(_T(
"%3d°/Min "), -ROTIND)
803 }
else if (!b_SarAircraftPosnReport)
808 if (b_positionOnceValid && bGPSValid && (Range_NM >= 0.))
809 rngStr = FormatDistanceAdaptive(Range_NM);
813 int brg = (int)wxRound(Brg);
814 if (Brg > 359.5) brg = 0;
815 if (b_positionOnceValid && bGPSValid && (Brg >= 0.) && (Range_NM > 0.) &&
817 wxString magString, trueString;
819 magString << wxString::Format(wxString(
"%03d%c(M)"),
820 static_cast<int>(m_callbacks.get_mag(Brg)),
823 trueString << wxString::Format( wxString(
"%03d%c "), (
int)Brg, 0x00B0 );
825 brgStr << trueString << magString;
829 wxString turnRateHdr;
830 if ((Class != AIS_ATON) && (Class != AIS_BASE) && (Class != AIS_DSC) &&
831 (Class != AIS_METEO)) {
833 << _T(
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
835 << rowStart << _("Speed")
836 << _T("</font></td><td> </td><td><font size=-2>") << _("Course")
837 << _T("</font></td><td> </td><td align=right><font size=-2>");
838 if (!b_SarAircraftPosnReport) html << _("Heading");
840 html << _T("</font></td></tr>") << rowStartH << _T("<b>") << sogStr
841 << _T("</b></td><td> </td><td><b>") << courseStr
842 << _T("</b></td><td> </td><td align=right><b>");
843 if (!b_SarAircraftPosnReport) html << hdgStr;
844 html << rowEnd << _T("</table></td></tr>") << vertSpacer;
846 if (!b_SarAircraftPosnReport) turnRateHdr = _("Turn Rate");
848 if (Class != AIS_METEO) {
849 html << _T(
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
851 << rowStart << _("Range")
852 << _T("</font></td><td> </td><td><font size=-2>") << _("Bearing")
853 << _T("</font></td><td> </td><td align=right><font size=-2>")
854 << turnRateHdr << _T("</font></td></tr>") << rowStartH << _T("<b>")
855 << rngStr << _T("</b></td><td> </td><td><b>") << brgStr
856 << _T("</b></td><td> </td><td align=right><b>");
857 if (!b_SarAircraftPosnReport) html << rotStr;
858 html << rowEnd << _T("</table></td></tr>") << vertSpacer;
861 if (bCPA_Valid && Class != AIS_METEO) {
863 tcpaStr << _T(
"</b> ") << _(
"in ") << _T(
"</td><td align=right><b>")
864 << FormatTimeAdaptive((
int)(TCPA * 60.));
866 html << rowStart << _T(
"<font size=-2>") << _(
"CPA")
867 << _T(
"</font>") << rowEnd << rowStartH << _T(
"<b>")
868 << FormatDistanceAdaptive(CPA) << tcpaStr << rowEnd;
871 if (Class != AIS_BASE && Class != AIS_METEO) {
872 if (blue_paddle == 1) {
873 html << rowStart << _(
"Inland Blue Flag") << rowEnd << rowStartH
874 << _T(
"<b>") << _(
"Clear") << rowEnd;
875 }
else if (blue_paddle == 2) {
876 html << rowStart << _(
"Inland Blue Flag") << rowEnd << rowStartH
877 << _T(
"<b>") << _(
"Set") << rowEnd;
881 if (b_SarAircraftPosnReport) {
883 if (altitude != 4095)
884 altStr.Printf(_T(
"%4d m"), altitude);
886 altStr = _(
"Unknown");
888 html << rowStart << _(
"Altitude")
889 << _T(
"</font></td><td> </td><td><font size=-0>") << rowStartH
890 << _T(
"<b>") << altStr << _T(
"</b></td><td> </td><td><b>")
891 << rowEnd << _T(
"</table></td></tr>") << vertSpacer;
894 if (Class == AIS_METEO) {
895 if (met_data.wind_kn < 122) {
896 double userwindspeed = toUsrWindSpeed(met_data.wind_kn);
897 wxString wspeed = wxString::Format(
"%0.1f %s %d%c", userwindspeed, getUsrWindSpeedUnit(),
898 met_data.wind_dir, 0x00B0);
900 double userwindgustspeed = toUsrWindSpeed(met_data.wind_gust_kn);
901 wxString wspeedGust = wxString::Format(
"%.0f %s %d%c", userwindgustspeed,
902 getUsrWindSpeedUnit(), met_data.wind_gust_dir, 0x00B0);
903 if (met_data.wind_gust_kn >= 126) wspeedGust = wxEmptyString;
905 html << vertSpacer << rowStart << _(
"Wind speed")
906 << _T(
"</font></td><td align=right><font size=-2>")
908 << _T(
"</font></td></tr>") << rowStartH << _T(
"<b>") << wspeed
909 << _T(
"</b></td><td align=right><b>") << wspeedGust << rowEnd;
912 if (met_data.water_lev_dev < 30. || met_data.water_level > -32. || met_data.current < 25.5) {
913 wxString wlevel_txt = _(
"Water level deviation");
915 if (met_data.water_lev_dev < 30.) {
916 double userlevel = toUsrDepth(met_data.water_lev_dev);
917 wlevel = wxString::Format(
"%.1f %s %s", userlevel, getUsrDepthUnit(),
918 ais_meteo_get_trend(met_data.water_lev_trend));
919 if (met_data.vertical_ref < 14) {
920 wlevel_txt = _(
"Water level dev. Ref: ");
921 wlevel_txt << aisMeteoWaterLevelRef(met_data.vertical_ref);
924 if (met_data.water_lev_dev >= 30.) wlevel = wxEmptyString;
926 }
else if (met_data.water_level > -32.) {
927 double userlevel = toUsrDepth(met_data.water_level);
928 wlevel = wxString::Format(
"%.1f %s %s", userlevel, getUsrDepthUnit(),
929 ais_meteo_get_trend(met_data.water_lev_trend));
930 wlevel_txt = _(
"Water level");
931 if (met_data.water_level <= -32.) wlevel = wxEmptyString;
934 wxString current = wxString::Format(
"%.1f kts %d%c", met_data.current,
935 met_data.curr_dir, 0x00B0);
936 if (met_data.current >= 25.5) current = wxEmptyString;
938 html << vertSpacer << rowStart << wlevel_txt
939 << _T(
"</font></td><td align=right><font size=-2>")
940 << _(
"Surface current ") << _T(
"</font></td></tr>") << rowStartH
941 << _T(
"<b>") << wlevel << _T(
"</b></td><td align=right><b>")
942 << current << rowEnd;
945 if (met_data.wave_height < 24.6 || met_data.swell_height < 24.6) {
946 double userwave = toUsrDepth(met_data.wave_height);
948 wxString::Format(
"%.1f %s %d%c %d %s ", userwave, getUsrDepthUnit(),
949 met_data.wave_dir, 0x00B0,
950 met_data.wave_period, _(
"s"));
951 if (met_data.wave_height >= 24.6) wave = wxEmptyString;
953 double userswell = toUsrDepth(met_data.swell_height);
955 wxString::Format(
"%.1f %s %d%c %d %s", userswell, getUsrDepthUnit(),
956 met_data.swell_dir, 0x00B0,
957 met_data.swell_per, _(
"s"));
958 if (met_data.swell_height >= 25.) swell = wxEmptyString;
960 html << vertSpacer << rowStart << _(
"Waves height & period")
961 << _T(
"</font></td><td align=right><font size=-2>")
962 << _(
"Swell height & period ")
963 << _T(
"</font></td></tr>") << rowStartH << _T(
"<b>") << wave
964 << _T(
"</b></td><td align=right><b>") << swell << rowEnd;
967 if (met_data.air_temp != -102.4 || met_data.airpress < 1310) {
968 double usertemp = toUsrTemp(met_data.air_temp);
970 wxString::Format(
"%.1f%c%s", usertemp, 0x00B0, getUsrTempUnit());
971 if (met_data.air_temp == -102.4) airtemp = wxEmptyString;
973 wxString airpress = wxString::Format(
974 "%d hPa %s", met_data.airpress,
975 ais_meteo_get_trend(met_data.airpress_tend));
976 const int ap = met_data.airpress;
977 if (ap < 800 || ap >= 1310) airpress = wxEmptyString;
979 html << vertSpacer << rowStart << _(
"Air Temperatur")
980 << _T(
"</font></td><td align=right><font size=-2>") << _(
"Air pressure")
981 << _T(
"</font></td></tr>") << rowStartH << _T(
"<b>") << airtemp
982 << _T(
"</b></td><td align=right><b>") << airpress << rowEnd;
985 if (met_data.rel_humid < 101 || met_data.dew_point < 50.) {
986 wxString humid = wxString::Format(
"%d%c", met_data.rel_humid,
'%');
987 if (met_data.rel_humid >= 101) humid = wxEmptyString;
989 double usertempDew = toUsrTemp(met_data.dew_point);
991 wxString::Format(
"%.1f%c%s", usertempDew, 0x00B0, getUsrTempUnit());
992 if (met_data.dew_point >= 50.) dewpoint = wxEmptyString;
994 html << vertSpacer << rowStart << _(
"Relative Humidity")
995 << _T(
"</font></td><td align=right><font size=-2>")
996 << _(
"Dew Point ") << _T(
"</font></td></tr>") << rowStartH
997 << _T(
"<b>") << humid << _T(
"</b></td><td align=right><b>")
998 << dewpoint << rowEnd;
1001 if (met_data.water_temp < 50.1 || met_data.seastate < 13) {
1002 double usertemp = toUsrTemp(met_data.water_temp);
1003 wxString watertemp =
1004 wxString::Format(
"%.1f%c%s", usertemp, 0x00B0, getUsrTempUnit());
1005 if (met_data.water_temp >= 50.1) watertemp = wxEmptyString;
1007 wxString seastate = wxString::Format(
"%d Bf ", met_data.seastate);
1008 if (met_data.seastate == 13) seastate = wxEmptyString;
1010 html << vertSpacer << rowStart << _(
"Water Temperatur")
1011 << _T(
"</font></td><td align=right><font size=-2>") << _(
"Sea state")
1012 << _T(
"</font></td></tr>") << rowStartH << _T(
"<b>") << watertemp
1013 << _T(
"</b></td><td align=right><b>") << seastate << rowEnd;
1016 if (met_data.precipitation < 7 || met_data.hor_vis < 12.7) {
1017 wxString precip = wxString::Format(
"%s",
1018 aisMeteoPrecipType(met_data.precipitation));
1019 if (met_data.precipitation >= 6) precip = wxEmptyString;
1021 double userVisDist = toUsrDistance(met_data.hor_vis);
1023 wxString::Format(
"%s%.1f %s", (met_data.hor_vis_GT ?
">" :
""),
1024 userVisDist, getUsrDistanceUnit());
1025 if (met_data.hor_vis >= 12.7) horVis = wxEmptyString;
1026 html << vertSpacer << rowStart << _(
"Precipitation")
1027 << _T(
"</font></td><td align=right><font size=-2>")
1028 << _(
"Horizontal Visibility") << _T(
"</font></td></tr>") << rowStartH
1029 << _T(
"<b>") << precip << _T(
"</b></td><td align=right><b>")
1030 << horVis << rowEnd;
1033 if (met_data.salinity < 50. || met_data.ice < 2) {
1034 wxString sal = wxString::Format(
"%.1f%c", met_data.salinity, 0x2030);
1035 if (met_data.salinity >= 50.) sal = wxEmptyString;
1037 wxString icestatus = _(
"No");
1038 if (met_data.ice == 1) icestatus = _(
"Yes");
1039 if (met_data.ice >= 2) icestatus = wxEmptyString;
1041 html << vertSpacer << rowStart << _(
"Sea salinity")
1042 << _T(
"</font></td><td align=right><font size=-2>")
1043 << _(
"Ice status") << _T(
"</font></td></tr>") << rowStartH
1044 << _T(
"<b>") << sal << _T(
"</b></td><td align=right><b>")
1045 << icestatus << rowEnd;
1048 html << _T(
"</table>");
1052 wxString AisTargetData::GetRolloverString(
void) {
1056 result.Append(_T(
"\""));
1057 result.Append(GetFullName());
1058 result.Append(_T(
"\" "));
1060 if (Class != AIS_GPSG_BUDDY) {
1061 t.Printf(_T(
"%09d"), abs(MMSI));
1063 result.Append(_T(
" "));
1064 result.Append(GetCountryCode(
false));
1066 t = trimAISField(CallSign);
1068 result.Append(_T(
" ("));
1070 result.Append(_T(
")"));
1072 if (g_bAISRolloverShowClass || (Class == AIS_SART)) {
1073 if (result.Len()) result.Append(_T(
"\n"));
1074 result.Append(_T(
"["));
1075 if (Class == AIS_ATON) {
1076 result.Append(wxGetTranslation(Get_class_string(
true)));
1077 result.Append(_T(
": "));
1078 result.Append(wxGetTranslation(Get_vessel_type_string(
false)));
1079 }
else if (b_SarAircraftPosnReport) {
1080 int airtype = (MMSI % 1000) / 100;
1081 result.Append(airtype == 5 ? _(
"SAR Helicopter") : _(
"SAR Aircraft"));
1083 result.Append(wxGetTranslation(Get_class_string(
false)));
1085 result.Append(_T(
"] "));
1086 if ((Class != AIS_ATON) && (Class != AIS_BASE)) {
1087 if (Class == AIS_SART) {
1088 int mmsi_start = MMSI / 1000000;
1089 switch (mmsi_start) {
1093 result += _T(
"MOB");
1096 result += _T(
"EPIRB");
1099 result += _(
"Unknown");
1104 if (Class != AIS_SART && Class != AIS_METEO) {
1105 if (!b_SarAircraftPosnReport)
1106 result.Append(wxGetTranslation(Get_vessel_type_string(
false)));
1109 if ((Class != AIS_CLASS_B) && (Class != AIS_SART) && Class != AIS_DSC &&
1110 Class != AIS_METEO && !b_SarAircraftPosnReport) {
1111 if ((NavStatus <= 15) && (NavStatus >= 0)) {
1112 result.Append(_T(
" ("));
1113 result.Append(wxGetTranslation(ais_get_status(NavStatus)));
1114 result.Append(_T(
")"));
1116 }
else if (Class == AIS_SART) {
1117 result.Append(_T(
" ("));
1118 if (NavStatus == RESERVED_14)
1119 result.Append(_(
"Active"));
1120 else if (NavStatus == UNDEFINED)
1121 result.Append(_(
"Testing"));
1122 result.Append(_T(
")"));
1123 }
else if (Class == AIS_DSC) {
1124 result.Append(_T(
" ("));
1125 result.Append(GetNatureofDistress(m_dscNature));
1126 result.Append(_T(
")"));
1131 if (g_bAISRolloverShowCOG && ((SOG <= 102.2) || b_SarAircraftPosnReport) &&
1132 !((Class == AIS_ATON) || (Class == AIS_BASE) || (Class == AIS_METEO))) {
1133 if (result.Len()) result << _T(
"\n");
1135 double speed_show = toUsrSpeed(SOG);
1136 if (speed_show < 10.0)
1137 result << wxString::Format(_T(
"SOG %.2f "), speed_show)
1138 << getUsrSpeedUnit() << _T(
" ");
1139 else if (speed_show < 100.0)
1140 result << wxString::Format(_T(
"SOG %.1f "), speed_show)
1141 << getUsrSpeedUnit() << _T(
" ");
1143 result << wxString::Format(_T(
"SOG %.0f "), speed_show)
1144 << getUsrSpeedUnit() << _T(
" ");
1146 int crs = wxRound(COG);
1147 if (b_positionOnceValid) {
1149 wxString magString, trueString;
1151 magString << wxString::Format(wxString(
"%03d%c(M) "),
1152 static_cast<int>(m_callbacks.get_mag(COG)),
1155 trueString << wxString::Format( wxString(
"%03d%c "), (
int)crs, 0x00B0 );
1157 result << trueString << magString;
1160 else if (COG == 360.0)
1161 result << _(
" COG Unavailable");
1162 else if (crs == 360)
1163 result << wxString(
" COG 000\u00B0");
1165 result << _(
" COG Unavailable");
1168 if (g_bAISRolloverShowCPA && bCPA_Valid && Class != AIS_METEO) {
1169 if (result.Len()) result << _T(
"\n");
1170 result << _(
"CPA") << _T(
" ") << FormatDistanceAdaptive(CPA) << _T(
" ")
1171 << _(
"in") << _T(
" ") << wxString::Format(_T(
"%.0f"), TCPA)
1172 << _T(
" ") << _(
"min");
1174 if (Class == AIS_METEO) {
1175 if (met_data.wind_kn < 122) {
1176 if (result.Len()) result <<
"\n";
1177 double userwindspeed = toUsrWindSpeed(met_data.wind_kn);
1178 result << _(
"Wind speed");
1179 result << wxString::Format(
": %0.1f %s", userwindspeed, getUsrWindSpeedUnit())
1180 << wxString::Format(
" %d%c ", met_data.wind_dir, 0x00B0);
1183 if (met_data.water_lev_dev < 30.) {
1184 if (result.Len()) result <<
"\n";
1185 result << _(
"Water level deviation");
1187 userdepth = toUsrDepth(met_data.water_lev_dev);
1188 result << wxString::Format(
": %.1f %s", userdepth,
1191 }
else if (met_data.water_level > -32.) {
1192 if (result.Len()) result <<
"\n";
1193 result << _(
"Water level");
1195 userdepth = toUsrDepth(met_data.water_level);
1196 result << wxString::Format(
": %.1f %s", userdepth, getUsrDepthUnit());
1199 if (met_data.current < 25.) {
1200 if (result.Len()) result <<
"\n";
1201 result << _(
"Current");
1202 result << wxString::Format(
": %.1f ", met_data.current) << _(
"kts")
1203 << wxString::Format(
" %d%c ", met_data.curr_dir, 0x00B0);
1206 if (met_data.wave_height < 24.6) {
1207 if (result.Len()) result <<
"\n";
1208 double userwh = toUsrDepth(met_data.wave_height);
1209 result << _(
"Wave height")
1210 << wxString::Format(
": %.1f %s", userwh, getUsrDepthUnit())
1211 <<
" / " << met_data.wave_period <<
" " << _(
"s");
1214 if (met_data.water_temp < 50.) {
1215 if (result.Len()) result <<
"\n";
1216 double usertemp = toUsrTemp(met_data.water_temp);
1217 result << _(
"Water temp");
1218 result << wxString::Format(
": %.1f%c", usertemp, 0x00B0)
1219 << getUsrTempUnit();
1222 if (met_data.air_temp != -102.4) {
1223 if (result.Len()) result <<
"\n";
1224 double usertemp = toUsrTemp(met_data.air_temp);
1225 result << _(
"Air temp");
1226 result << wxString::Format(
": %.1f%c", usertemp, 0x00B0)
1227 << getUsrTempUnit() <<
" ";
1230 if (met_data.airpress > 799 && met_data.airpress < 1310) {
1231 if (met_data.air_temp == -102.4 && result.Len()) result <<
"\n";
1232 result << _(
"Air press");
1233 result << wxString::Format(
": %d hPa", met_data.airpress);
1236 if (met_data.hor_vis < 12.) {
1237 if (result.Len()) result <<
"\n";
1238 double userVisDist = toUsrDistance(met_data.hor_vis);
1240 wxString::Format(
": %s%.1f %s", (met_data.hor_vis_GT ?
">" :
""),
1241 userVisDist, getUsrDistanceUnit());
1242 result << _(
"Visibility") << horVis;
1248 wxString AisTargetData::Get_vessel_type_string(
bool b_short) {
1250 if (Class == AIS_ATON) {
1304 if ((Class == AIS_CLASS_B) || (Class == AIS_CLASS_A)) {
1305 if ((ShipType >= 40) && (ShipType < 50)) i = 8;
1307 if ((ShipType >= 60) && (ShipType < 70)) i = 16;
1309 if ((ShipType >= 70) && (ShipType < 80)) i = 17;
1311 if ((ShipType >= 80) && (ShipType < 90)) i = 18;
1312 }
else if (Class == AIS_GPSG_BUDDY)
1314 else if (Class == AIS_ARPA)
1316 else if (Class == AIS_APRS)
1318 else if (Class == AIS_DSC)
1319 i = (ShipType == 12 || ShipType == 16) ? 54 : 53;
1322 return ais_get_type(i);
1324 return ais_get_short_type(i);
1327 wxString AisTargetData::Get_class_string(
bool b_short) {
1334 return b_short ? _(
"AtoN") : _(
"Aid to Navigation");
1336 return b_short ? _(
"Base") : _(
"Base Station");
1337 case AIS_GPSG_BUDDY:
1338 return b_short ? _(
"Buddy") : _(
"GPSGate Buddy");
1340 if (ShipType == 12 || ( ShipType == 16 && m_dscNature < 13))
1341 return b_short ? _(
"DSC") : _(
"DSC Distress");
1343 return b_short ? _(
"DSC") : _(
"DSC Position Report");
1345 return b_short ? _(
"SART") : _(
"SART");
1347 return b_short ? _(
"ARPA") : _(
"ARPA");
1349 return b_short ? _(
"APRS") : _(
"APRS Position Report");
1351 return b_short ? _(
"METEO") : _(
"Meteorologic");
1354 return b_short ? _(
"Unk") : _(
"Unknown");
1358 wxString AisTargetData::GetNatureofDistress(
int dscnature) {
1360 wxString dscDistressType[] = { _(
"Fire, explosion"), _(
"Flooding"),
1361 _(
"Collision"), _(
"Grounding"),
1362 _(
"Listing, in danger of capsizing"), _(
"Sinking"),
1363 _(
"Disabled and adrift"), _(
"Undesignated distress"),
1364 _(
"Abandoning ship"), _(
"Piracy/armed robbery attack"),
1365 _(
"Man overboard"), _T(
"-"), _(
"EPIRB emission") };
1366 if (dscnature >= 0 && dscnature < 13)
1367 return dscDistressType[dscnature];
1369 return wxEmptyString;
1372 void AisTargetData::Toggle_AIS_CPA(
void) {
1373 b_show_AIS_CPA = !b_show_AIS_CPA ? true :
false;
1376 void AisTargetData::ToggleShowTrack(
void) {
1377 b_show_track = !b_show_track ? true :
false;
1380 bool AisTargetData::IsValidMID(
int mid) {
1381 if (mid >= 201 && mid <= 775)
return true;
1387 wxString AisTargetData::GetCountryCode(
bool b_CntryLongStr) {
1390 int tmpMmsi = met_data.original_mmsi ? met_data.original_mmsi : MMSI;
1392 int nMID = tmpMmsi / 1000000;
1393 if (!IsValidMID(nMID) || Class == AIS_ATON) {
1396 if (tmpMmsi < 1000 || 97 == tmpMmsi / 10000000)
return wxEmptyString;
1401 bool foundMID =
false;
1403 i = nMID > 900 ? 2 : 0;
1404 for (i; i < s_mmsi.length() - 3; i++) {
1405 nMID = wxAtoi(s_mmsi.Mid(i, 3));
1406 if (IsValidMID(nMID)) {
1411 if (!foundMID)
return wxEmptyString;
1414 #if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
1418 return b_CntryLongStr ? _(
"Albania") : _T(
"AL");
1420 return b_CntryLongStr ? _(
"Andorra") : _T(
"AD");
1422 return b_CntryLongStr ? _(
"Austria") : _T(
"AT");
1424 return b_CntryLongStr ? _(
"Azores") : _T(
"AZ");
1426 return b_CntryLongStr ? _(
"Belgium") : _T(
"BE");
1428 return b_CntryLongStr ? _(
"Belarus") : _T(
"BY");
1430 return b_CntryLongStr ? _(
"Bulgaria") : _T(
"BG");
1432 return b_CntryLongStr ? _(
"Vatican City State") : _T(
"VA");
1435 return b_CntryLongStr ? _(
"Cyprus") : _T(
"CY");
1437 return b_CntryLongStr ? _(
"Germany") : _T(
"DE");
1439 return b_CntryLongStr ? _(
"Cyprus") : _T(
"CY");
1441 return b_CntryLongStr ? _(
"Georgia") : _T(
"GE");
1443 return b_CntryLongStr ? _(
"Moldova") : _T(
"MD");
1445 return b_CntryLongStr ? _(
"Malta") : _T(
"MT");
1447 return b_CntryLongStr ? _(
"Armenia") : _T(
"AM");
1449 return b_CntryLongStr ? _(
"Germany") : _T(
"DE");
1452 return b_CntryLongStr ? _(
"Denmark") : _T(
"DK");
1454 return b_CntryLongStr ? _(
"Spain") : _T(
"ES");
1456 return b_CntryLongStr ? _(
"Spain") : _T(
"ES");
1460 return b_CntryLongStr ? _(
"France") : _T(
"FR");
1462 return b_CntryLongStr ? _(
"Malta") : _T(
"MT");
1464 return b_CntryLongStr ? _(
"Finland") : _T(
"FI");
1466 return b_CntryLongStr ? _(
"Faroe Islands") : _T(
"FO");
1471 return b_CntryLongStr ? _(
"Great Britain") : _T(
"GB");
1473 return b_CntryLongStr ? _(
"Gibraltar") : _T(
"GI");
1475 return b_CntryLongStr ? _(
"Greece") : _T(
"GR");
1477 return b_CntryLongStr ? _(
"Croatia") : _T(
"HR");
1481 return b_CntryLongStr ? _(
"Greece") : _T(
"GR");
1483 return b_CntryLongStr ? _(
"Morocco") : _T(
"MA");
1485 return b_CntryLongStr ? _(
"Hungary") : _T(
"HU");
1489 return b_CntryLongStr ? _(
"Netherlands") : _T(
"NL");
1491 return b_CntryLongStr ? _(
"Italy") : _T(
"IT");
1494 return b_CntryLongStr ? _(
"Malta") : _T(
"MT");
1496 return b_CntryLongStr ? _(
"Ireland") : _T(
"IE");
1498 return b_CntryLongStr ? _(
"Iceland") : _T(
"IS");
1500 return b_CntryLongStr ? _(
"Liechtenstein") : _T(
"LI");
1502 return b_CntryLongStr ? _(
"Luxembourg") : _T(
"LU");
1504 return b_CntryLongStr ? _(
"Monaco") : _T(
"MC");
1506 return b_CntryLongStr ? _(
"Madeira") : _T(
"PT");
1508 return b_CntryLongStr ? _(
"Malta") : _T(
"MT");
1512 return b_CntryLongStr ? _(
"Norway") : _T(
"NO");
1514 return b_CntryLongStr ? _(
"Poland") : _T(
"PL");
1516 return b_CntryLongStr ? _(
"Montenegro") : _T(
"ME");
1518 return b_CntryLongStr ? _(
"Portugal") : _T(
"PT");
1520 return b_CntryLongStr ? _(
"Romania") : _T(
"RO");
1523 return b_CntryLongStr ? _(
"Sweden") : _T(
"SE");
1525 return b_CntryLongStr ? _(
"Slovak Republic") : _T(
"SK");
1527 return b_CntryLongStr ? _(
"San Marino") : _T(
"SM");
1529 return b_CntryLongStr ? _(
"Switzerland") : _T(
"CH");
1531 return b_CntryLongStr ? _(
"Czech Republic") : _T(
"CZ");
1533 return b_CntryLongStr ? _(
"Turkey") : _T(
"TR");
1535 return b_CntryLongStr ? _(
"Ukraine") : _T(
"UA");
1537 return b_CntryLongStr ? _(
"Russian") : _T(
"RU");
1539 return b_CntryLongStr ? _(
"Macedonia") : _T(
"MK");
1541 return b_CntryLongStr ? _(
"Latvia") : _T(
"LV");
1543 return b_CntryLongStr ? _(
"Estonia") : _T(
"EE");
1545 return b_CntryLongStr ? _(
"Lithuania") : _T(
"LT");
1547 return b_CntryLongStr ? _(
"Slovenia") : _T(
"SI");
1549 return b_CntryLongStr ? _(
"Serbia") : _T(
"RS");
1551 return b_CntryLongStr ? _(
"Anguilla") : _T(
"AI");
1553 return b_CntryLongStr ? _(
"Alaska") : _T(
"AK");
1556 return b_CntryLongStr ? _(
"Antigua and Barbuda") : _T(
"AG");
1558 return b_CntryLongStr ? _(
"Antilles") : _T(
"AN");
1560 return b_CntryLongStr ? _(
"Aruba") : _T(
"AW");
1563 return b_CntryLongStr ? _(
"Bahamas") : _T(
"BS");
1565 return b_CntryLongStr ? _(
"Bermuda") : _T(
"BM");
1567 return b_CntryLongStr ? _(
"Bahamas") : _T(
"BS");
1569 return b_CntryLongStr ? _(
"Belize") : _T(
"BZ");
1571 return b_CntryLongStr ? _(
"Barbados") : _T(
"BB");
1573 return b_CntryLongStr ? _(
"Canada") : _T(
"CA");
1575 return b_CntryLongStr ? _(
"Cayman Islands") : _T(
"KY");
1577 return b_CntryLongStr ? _(
"Costa Rica") : _T(
"CR");
1579 return b_CntryLongStr ? _(
"Cuba") : _T(
"CU");
1581 return b_CntryLongStr ? _(
"Dominica") : _T(
"DM");
1583 return b_CntryLongStr ? _(
"Dominican Republic") : _T(
"DM");
1585 return b_CntryLongStr ? _(
"Guadeloupe") : _T(
"GP");
1587 return b_CntryLongStr ? _(
"Grenada") : _T(
"GD");
1589 return b_CntryLongStr ? _(
"Greenland") : _T(
"GL");
1591 return b_CntryLongStr ? _(
"Guatemala") : _T(
"GT");
1593 return b_CntryLongStr ? _(
"Honduras") : _T(
"HN");
1595 return b_CntryLongStr ? _(
"Haiti") : _T(
"HT");
1597 return b_CntryLongStr ? _(
"United States of America") : _T(
"US");
1599 return b_CntryLongStr ? _(
"Jamaica") : _T(
"JM");
1601 return b_CntryLongStr ? _(
"Saint Kitts and Nevis") : _T(
"KN");
1603 return b_CntryLongStr ? _(
"Saint Lucia") : _T(
"LC");
1605 return b_CntryLongStr ? _(
"Mexico") : _T(
"MX");
1607 return b_CntryLongStr ? _(
"Martinique") : _T(
"MQ");
1609 return b_CntryLongStr ? _(
"Montserrat") : _T(
"MS");
1611 return b_CntryLongStr ? _(
"Nicaragua") : _T(
"NI");
1619 return b_CntryLongStr ? _(
"Panama") : _T(
"PA");
1621 return b_CntryLongStr ? _(
"Puerto Rico") : _T(
"PR");
1623 return b_CntryLongStr ? _(
"El Salvador") : _T(
"SV");
1625 return b_CntryLongStr ? _(
"Saint Pierre and Miquelon") : _T(
"PM");
1627 return b_CntryLongStr ? _(
"Trinidad and Tobago") : _T(
"TT");
1629 return b_CntryLongStr ? _(
"Turks and Caicos Islands") : _T(
"TC");
1634 return b_CntryLongStr ? _(
"United States of America") : _T(
"US");
1640 return b_CntryLongStr ? _(
"Panama") : _T(
"PA");
1644 return b_CntryLongStr ? _(
"Saint Vincent and the Grenadines") : _T(
"VC");
1646 return b_CntryLongStr ? _(
"British Virgin Islands") : _T(
"VG");
1648 return b_CntryLongStr ? _(
"United States Virgin Islands") : _T(
"AE");
1650 return b_CntryLongStr ? _(
"Afghanistan") : _T(
"AF");
1652 return b_CntryLongStr ? _(
"Saudi Arabia") : _T(
"SA");
1654 return b_CntryLongStr ? _(
"Bangladesh") : _T(
"BD");
1656 return b_CntryLongStr ? _(
"Bahrain") : _T(
"BH");
1658 return b_CntryLongStr ? _(
"Bhutan") : _T(
"BT");
1662 return b_CntryLongStr ? _(
"China") : _T(
"CN");
1664 return b_CntryLongStr ? _(
"Taiwan") : _T(
"TW");
1666 return b_CntryLongStr ? _(
"Sri Lanka") : _T(
"LK");
1668 return b_CntryLongStr ? _(
"India") : _T(
"IN");
1670 return b_CntryLongStr ? _(
"Iran") : _T(
"IR");
1672 return b_CntryLongStr ? _(
"Azerbaijani Republic") : _T(
"AZ");
1674 return b_CntryLongStr ? _(
"Iraq") : _T(
"IQ");
1676 return b_CntryLongStr ? _(
"Israel") : _T(
"IL");
1678 return b_CntryLongStr ? _(
"Japan") : _T(
"JP");
1680 return b_CntryLongStr ? _(
"Japan") : _T(
"JP");
1682 return b_CntryLongStr ? _(
"Turkmenistan") : _T(
"TM");
1684 return b_CntryLongStr ? _(
"Kazakhstan") : _T(
"KZ");
1686 return b_CntryLongStr ? _(
"Uzbekistan") : _T(
"UZ");
1688 return b_CntryLongStr ? _(
"Jordan") : _T(
"JO");
1691 return b_CntryLongStr ? _(
"Korea") : _T(
"KR");
1693 return b_CntryLongStr ? _(
"Palestine") : _T(
"PS");
1695 return b_CntryLongStr ? _(
"People's Rep. of Korea") : _T(
"KP");
1697 return b_CntryLongStr ? _(
"Kuwait") : _T(
"KW");
1699 return b_CntryLongStr ? _(
"Lebanon") : _T(
"LB");
1701 return b_CntryLongStr ? _(
"Kyrgyz Republic") : _T(
"KG");
1703 return b_CntryLongStr ? _(
"Macao") : _T(
"MO");
1705 return b_CntryLongStr ? _(
"Maldives") : _T(
"MV");
1707 return b_CntryLongStr ? _(
"Mongolia") : _T(
"MN");
1709 return b_CntryLongStr ? _(
"Nepal") : _T(
"NP");
1711 return b_CntryLongStr ? _(
"Oman") : _T(
"OM");
1713 return b_CntryLongStr ? _(
"Pakistan") : _T(
"PK");
1715 return b_CntryLongStr ? _(
"Qatar") : _T(
"QA");
1717 return b_CntryLongStr ? _(
"Syrian Arab Republic") : _T(
"SY");
1720 return b_CntryLongStr ? _(
"United Arab Emirates") : _T(
"AE");
1722 return b_CntryLongStr ? _(
"Tajikistan") : _T(
"TJ");
1725 return b_CntryLongStr ? _(
"Yemen") : _T(
"YE");
1727 return b_CntryLongStr ? _(
"Hong Kong") : _T(
"HK");
1729 return b_CntryLongStr ? _(
"Bosnia and Herzegovina") : _T(
"BA");
1731 return b_CntryLongStr ? _(
"Adelie Land") : _T(
"TF");
1733 return b_CntryLongStr ? _(
"Australia") : _T(
"AU");
1735 return b_CntryLongStr ? _(
"Myanmar") : _T(
"MM");
1737 return b_CntryLongStr ? _(
"Brunei Darussalam") : _T(
"BN");
1739 return b_CntryLongStr ? _(
"Micronesia") : _T(
"FM");
1741 return b_CntryLongStr ? _(
"Palau") : _T(
"PW");
1743 return b_CntryLongStr ? _(
"New Zealand") : _T(
"NZ");
1746 return b_CntryLongStr ? _(
"Cambodia") : _T(
"KH");
1748 return b_CntryLongStr ? _(
"Christmas Island") : _T(
"CX");
1750 return b_CntryLongStr ? _(
"Cook Islands") : _T(
"CK");
1752 return b_CntryLongStr ? _(
"Fiji") : _T(
"FJ");
1754 return b_CntryLongStr ? _(
"Cocos (Keeling) Islands") : _T(
"CC");
1756 return b_CntryLongStr ? _(
"Indonesia") : _T(
"ID");
1758 return b_CntryLongStr ? _(
"Kiribati") : _T(
"KI");
1760 return b_CntryLongStr ? _(
"Lao People's Dem. Rep.") : _T(
"LA");
1762 return b_CntryLongStr ? _(
"Malaysia") : _T(
"MY");
1764 return b_CntryLongStr ? _(
"Northern Mariana Islands") : _T(
"MP");
1766 return b_CntryLongStr ? _(
"Marshall Islands") : _T(
"MH");
1768 return b_CntryLongStr ? _(
"New Caledonia") : _T(
"NC");
1770 return b_CntryLongStr ? _(
"Niue") : _T(
"NU");
1772 return b_CntryLongStr ? _(
"Nauru") : _T(
"NR");
1774 return b_CntryLongStr ? _(
"French Polynesia") : _T(
"PF");
1776 return b_CntryLongStr ? _(
"Philippines") : _T(
"PH");
1778 return b_CntryLongStr ? _(
"East Timor") : _T(
"TL");
1780 return b_CntryLongStr ? _(
"Papua New Guinea") : _T(
"PG");
1782 return b_CntryLongStr ? _(
"Pitcairn Island") : _T(
"PN");
1784 return b_CntryLongStr ? _(
"Solomon Islands") : _T(
"SB");
1786 return b_CntryLongStr ? _(
"American Samoa") : _T(
"AS");
1788 return b_CntryLongStr ? _(
"Samoa") : _T(
"WS");
1793 return b_CntryLongStr ? _(
"Singapore") : _T(
"SG");
1795 return b_CntryLongStr ? _(
"Thailand") : _T(
"TH");
1797 return b_CntryLongStr ? _(
"Tonga") : _T(
"TO");
1799 return b_CntryLongStr ? _(
"Tuvalu") : _T(
"TV");
1801 return b_CntryLongStr ? _(
"Viet Nam") : _T(
"VN");
1804 return b_CntryLongStr ? _(
"Vanuatu") : _T(
"VU");
1806 return b_CntryLongStr ? _(
"Wallis and Futuna Islands") : _T(
"WF");
1808 return b_CntryLongStr ? _(
"South Africa") : _T(
"ZA");
1810 return b_CntryLongStr ? _(
"Angola") : _T(
"AO");
1812 return b_CntryLongStr ? _(
"Algeria") : _T(
"DZ");
1814 return b_CntryLongStr ? _(
"Saint Paul") : _T(
"TF");
1816 return b_CntryLongStr ? _(
"Ascension Island") : _T(
"SH");
1818 return b_CntryLongStr ? _(
"Burundi") : _T(
"BI");
1820 return b_CntryLongStr ? _(
"Benin") : _T(
"BJ");
1822 return b_CntryLongStr ? _(
"Botswana") : _T(
"BW");
1824 return b_CntryLongStr ? _(
"Central African Republic") : _T(
"CF");
1826 return b_CntryLongStr ? _(
"Cameroon") : _T(
"CM");
1828 return b_CntryLongStr ? _(
"Congo") : _T(
"CD");
1830 return b_CntryLongStr ? _(
"Comoros") : _T(
"KM");
1832 return b_CntryLongStr ? _(
"Capo Verde") : _T(
"CV");
1834 return b_CntryLongStr ? _(
"Crozet Archipelago") : _T(
"TF");
1836 return b_CntryLongStr ? _(
"Ivory Coast") : _T(
"CI");
1838 return b_CntryLongStr ? _(
"Comoros (Union of the)") : _T(
"KM");
1840 return b_CntryLongStr ? _(
"Djibouti") : _T(
"DJ");
1842 return b_CntryLongStr ? _(
"Egypt") : _T(
"EG");
1844 return b_CntryLongStr ? _(
"Ethiopia") : _T(
"ET");
1846 return b_CntryLongStr ? _(
"Eritrea") : _T(
"ER");
1848 return b_CntryLongStr ? _(
"Gabonese Republic") : _T(
"GA");
1850 return b_CntryLongStr ? _(
"Ghana") : _T(
"GH");
1852 return b_CntryLongStr ? _(
"Gambia") : _T(
"GM");
1854 return b_CntryLongStr ? _(
"Guinea-Bissau") : _T(
"GW");
1856 return b_CntryLongStr ? _(
"Equatorial Guinea") : _T(
"GQ");
1858 return b_CntryLongStr ? _(
"Guinea") : _T(
"GN");
1860 return b_CntryLongStr ? _(
"Burkina Faso") : _T(
"BF");
1862 return b_CntryLongStr ? _(
"Kenya") : _T(
"KE");
1864 return b_CntryLongStr ? _(
"Kerguelen Islands") : _T(
"TF");
1867 return b_CntryLongStr ? _(
"Liberia") : _T(
"LR");
1869 return b_CntryLongStr ? _(
"South Sudan (Republic of)") : _T(
"SS");
1871 return b_CntryLongStr ? _(
"Libya") : _T(
"LY");
1873 return b_CntryLongStr ? _(
"Lesotho") : _T(
"LS");
1875 return b_CntryLongStr ? _(
"Mauritius") : _T(
"MU");
1877 return b_CntryLongStr ? _(
"Madagascar") : _T(
"MG");
1879 return b_CntryLongStr ? _(
"Mali") : _T(
"ML");
1881 return b_CntryLongStr ? _(
"Mozambique") : _T(
"MZ");
1883 return b_CntryLongStr ? _(
"Mauritania") : _T(
"MR");
1885 return b_CntryLongStr ? _(
"Malawi") : _T(
"MW");
1887 return b_CntryLongStr ? _(
"Niger") : _T(
"NE");
1889 return b_CntryLongStr ? _(
"Nigeria") : _T(
"NG");
1891 return b_CntryLongStr ? _(
"Namibia") : _T(
"NA");
1893 return b_CntryLongStr ? _(
"Reunion") : _T(
"RE");
1895 return b_CntryLongStr ? _(
"Rwanda") : _T(
"RW");
1897 return b_CntryLongStr ? _(
"Sudan") : _T(
"SD");
1899 return b_CntryLongStr ? _(
"Senegal") : _T(
"SN");
1901 return b_CntryLongStr ? _(
"Seychelles") : _T(
"SC");
1903 return b_CntryLongStr ? _(
"Saint Helena") : _T(
"SH");
1905 return b_CntryLongStr ? _(
"Somalia") : _T(
"SO");
1907 return b_CntryLongStr ? _(
"Sierra Leone") : _T(
"SL");
1909 return b_CntryLongStr ? _(
"Sao Tome and Principe") : _T(
"ST");
1911 return b_CntryLongStr ? _(
"Eswatini") : _T(
"SZ");
1913 return b_CntryLongStr ? _(
"Chad") : _T(
"TD");
1915 return b_CntryLongStr ? _(
"Togolese Republic") : _T(
"TG");
1917 return b_CntryLongStr ? _(
"Tunisia") : _T(
"TN");
1919 return b_CntryLongStr ? _(
"Tanzania") : _T(
"TZ");
1921 return b_CntryLongStr ? _(
"Uganda") : _T(
"UG");
1923 return b_CntryLongStr ? _(
"Dem Rep.of the Congo") : _T(
"CD");
1925 return b_CntryLongStr ? _(
"Tanzania") : _T(
"TZ");
1927 return b_CntryLongStr ? _(
"Zambia") : _T(
"ZM");
1929 return b_CntryLongStr ? _(
"Zimbabwe") : _T(
"ZW");
1931 return b_CntryLongStr ? _(
"Argentine Republic") : _T(
"AR");
1933 return b_CntryLongStr ? _(
"Brazil") : _T(
"BR");
1935 return b_CntryLongStr ? _(
"Bolivia") : _T(
"BO");
1937 return b_CntryLongStr ? _(
"Chile") : _T(
"CL");
1939 return b_CntryLongStr ? _(
"Colombia") : _T(
"CO");
1941 return b_CntryLongStr ? _(
"Ecuador") : _T(
"EC");
1943 return b_CntryLongStr ? _(
"Falkland Islands") : _T(
"FK");
1945 return b_CntryLongStr ? _(
"France - Guiana") : _T(
"GY");
1947 return b_CntryLongStr ? _(
"Guyana") : _T(
"GY");
1949 return b_CntryLongStr ? _(
"Paraguay") : _T(
"PY");
1951 return b_CntryLongStr ? _(
"Peru") : _T(
"PE");
1953 return b_CntryLongStr ? _(
"Suriname") : _T(
"SR");
1955 return b_CntryLongStr ? _(
"Uruguay") : _T(
"UY");
1957 return b_CntryLongStr ? _(
"Venezuela") : _T(
"VE");
1960 return wxEmptyString;
1963 return wxEmptyString;
1968 wxString ais_get_type(
int index) {
1969 static const wxString ais_type[] = {
1970 _(
"Fishing Vessel"),
1972 _(
"Towing Vessel, Long"),
1974 _(
"Diving Ops Vessel"),
1975 _(
"Military Vessel"),
1976 _(
"Sailing Vessel"),
1977 _(
"Pleasure craft"),
1978 _(
"High Speed Craft"),
1980 _(
"Search and Rescue Vessel"),
1983 _(
"Pollution Control Vessel"),
1984 _(
"Law Enforcement Vessel"),
1985 _(
"Medical Transport"),
1986 _(
"Passenger Ship"),
1991 _(
"Reference Point"),
1993 _(
"Fixed Structure"),
1996 _(
"Light w/Sectors"),
1997 _(
"Leading Light Front"),
1998 _(
"Leading Light Rear"),
1999 _(
"Cardinal N Beacon"),
2000 _(
"Cardinal E Beacon"),
2001 _(
"Cardinal S Beacon"),
2002 _(
"Cardinal W Beacon"),
2003 _(
"Beacon, Port Hand"),
2004 _(
"Beacon, Starboard Hand"),
2005 _(
"Beacon, Preferred Channel Port Hand"),
2006 _(
"Beacon, Preferred Channel Starboard Hand"),
2007 _(
"Beacon, Isolated Danger"),
2008 _(
"Beacon, Safe Water"),
2009 _(
"Beacon, Special Mark"),
2010 _(
"Cardinal Mark N"),
2011 _(
"Cardinal Mark E"),
2012 _(
"Cardinal Mark S"),
2013 _(
"Cardinal Mark W"),
2014 _(
"Port Hand Mark"),
2015 _(
"Starboard Hand Mark"),
2016 _(
"Preferred Channel Port Hand"),
2017 _(
"Preferred Channel Starboard Hand"),
2018 _(
"Isolated Danger"),
2021 _(
"Light Vessel/Rig"),
2023 _(
"Position Report"),
2025 _(
"ARPA radar target"),
2026 _(
"APRS Position Report")
2029 return ais_type[index];
2032 wxString ais_get_short_type(
int index) {
2033 static const wxString short_ais_type[] = {
2093 return short_ais_type[index];
Global state for AIS decoder.