24#include <unordered_map>
26#include <wx/datetime.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"
36static std::unordered_map<int, wxString> s_ERI_hash;
38void make_hash_ERI(
int key,
const wxString &description) {
39 s_ERI_hash[key] = description;
42void clear_hash_ERI() { s_ERI_hash.clear(); }
44static 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);
58static wxString html_escape(
const wxString &src) {
62 ret.Replace(_T(
"<"), _T(
"<"));
63 ret.Replace(_T(
">"), _T(
">"));
75wxString trimAISField(
char *data) {
78 wxString field = wxString::From8BitData(data);
79 while (field.Right(1) ==
'@' || field.Right(1) ==
' ') field.RemoveLast();
87wxString ais_get_status(
int index) {
88 static const wxString ais_status[] = {
89 _(
"Underway using Engine"),
91 _(
"Not Under Command"),
92 _(
"Restricted Manoeuvrability"),
93 _(
"Constrained by draught"),
96 _(
"Engaged in Fishing"),
97 _(
"Underway Sailing"),
98 _(
"High Speed Craft"),
99 _(
"Wing In Ground Effect"),
100 _(
"Power-driven vessel towing astern (regional use)"),
101 _(
"Power-driven vessel pushing ahead or towing alongside (regional use)"),
106 _(
"AtoN Virtual (On Position)"),
107 _(
"AtoN Virtual (Off Position)"),
109 _(
"AtoN Real (On Position)"),
110 _(
"AtoN Real(Off Position)")};
112 return ais_status[index];
115wxString ais_meteo_get_trend(
int tend) {
116 wxString trend = wxEmptyString;
121 trend = _(
"decreasing");
123 trend = _(
"increasing");
128wxString aisMeteoPrecipType(
int precip) {
129 wxString prec = wxEmptyString;
138 prec =
"Thunderstorm";
141 prec =
"Freezing rain";
144 prec =
"Mixed / ice";
150 prec =
"not available";
156wxString aisMeteoWaterLevelRef(
int refID) {
157 wxString ref = wxEmptyString;
206 strncpy(ShipName,
"Unknown ", SHIP_NAME_LEN);
207 strncpy(CallSign,
" ", 8);
208 strncpy(Destination,
" ", DESTINATION_LEN);
209 ShipNameExtension[0] = 0;
210 b_show_AIS_CPA =
false;
219 wxDateTime now = wxDateTime::Now();
221 PositionReportTicks = now.GetTicks();
222 StaticReportTicks = now.GetTicks();
229 NavStatus = UNDEFINED;
233 b_isDSCtarget =
false;
243 DimA = DimB = DimC = DimD = 0;
260 n_alert_state = AIS_NO_ALERT;
261 b_suppress_audio =
false;
262 b_positionDoubtful =
false;
263 b_positionOnceValid =
false;
269 strncpy(Euro_VIN,
" ", 8);
272 b_isEuroInland =
false;
273 b_blue_paddle =
false;
277 b_PersistTrack =
false;
278 b_mPropPersistTrack =
false;
279 b_in_ack_timeout =
false;
284 b_isFollower =
false;
286 b_show_track = g_bAISShowTracks;
287 b_SarAircraftPosnReport =
false;
289 b_nameFromCache =
false;
291 for (
unsigned int i = 0; i < AIS_TARGETDATA_MAX_CANVAS; i++)
293 met_data.original_mmsi = 0;
294 met_data.stationID = 0;
298 met_data.minute = 60;
299 met_data.pos_acc = 1;
300 met_data.wind_kn = 122;
301 met_data.wind_gust_kn = 127;
302 met_data.wind_dir = 360;
303 met_data.wind_gust_dir = 360;
304 met_data.air_temp = -102.4;
305 met_data.rel_humid = 101;
306 met_data.dew_point = 50.1;
307 met_data.airpress = 1310;
308 met_data.airpress_tend = 3;
309 met_data.hor_vis = 12.7;
310 met_data.hor_vis_GT =
false;
311 met_data.water_lev_dev = 4001 / 100 - 10;
312 met_data.water_level = -32;
313 met_data.water_lev_trend = 3;
314 met_data.current = 25.5;
315 met_data.curr_dir = 360;
316 met_data.wave_height = 25.5;
317 met_data.wave_period = 63;
318 met_data.wave_dir = 360;
319 met_data.swell_height = 25.5;
320 met_data.swell_per = 63;
321 met_data.swell_dir = 360;
322 met_data.seastate = 13;
323 met_data.water_temp = 501;
324 met_data.precipitation = 7;
325 met_data.salinity = 51.;
327 met_data.vertical_ref = 14;
331 strncpy(ShipName, q->ShipName, SHIP_NAME_LEN);
332 strncpy(CallSign, q->CallSign, 8);
333 strncpy(Destination, q->Destination, DESTINATION_LEN);
334 ShipNameExtension[0] = 0;
335 b_show_AIS_CPA = q->b_show_AIS_CPA;
345 PositionReportTicks = q->PositionReportTicks;
346 StaticReportTicks = q->StaticReportTicks;
348 b_removed = q->b_removed;
353 NavStatus = q->NavStatus;
354 SyncState = q->SyncState;
356 ShipType = q->ShipType;
357 b_isDSCtarget = q->b_isDSCtarget;
358 m_dscNature = q->m_dscNature;
359 m_dscTXmmsi = q->m_dscTXmmsi;
364 Range_NM = q->Range_NM;
373 ETA_Day = q->ETA_Day;
375 ETA_Min = q->ETA_Min;
379 RecentPeriod = q->RecentPeriod;
381 m_utc_hour = q->m_utc_hour;
382 m_utc_min = q->m_utc_min;
383 m_utc_sec = q->m_utc_sec;
386 n_alert_state = q->n_alert_state;
387 b_suppress_audio = q->b_suppress_audio;
388 b_positionDoubtful = q->b_positionDoubtful;
389 b_positionOnceValid = q->b_positionOnceValid;
390 b_nameValid = q->b_nameValid;
392 Euro_Length = q->Euro_Length;
393 Euro_Beam = q->Euro_Beam;
394 Euro_Draft = q->Euro_Draft;
395 memcpy(Euro_VIN, q->Euro_VIN, EURO_VIN_LEN);
396 UN_shiptype = q->UN_shiptype;
398 b_isEuroInland = q->b_isEuroInland;
399 b_blue_paddle = q->b_blue_paddle;
401 b_OwnShip = q->b_OwnShip;
402 b_in_ack_timeout = q->b_in_ack_timeout;
404 m_ptrack = q->m_ptrack;
406 b_active = q->b_active;
407 blue_paddle = q->blue_paddle;
408 bCPA_Valid = q->bCPA_Valid;
410 b_show_track = q->b_show_track;
411 b_SarAircraftPosnReport = q->b_SarAircraftPosnReport;
412 altitude = q->altitude;
415AisTargetData::~AisTargetData() { m_ptrack.clear(); }
418wxString AisTargetData::GetFullName(
void) {
421 wxString shipName = trimAISField(ShipName);
422 if (shipName == _T(
"Unknown"))
423 retName = wxGetTranslation(shipName);
427 if (strlen(ShipNameExtension)) {
428 wxString shipNameExt = trimAISField(ShipNameExtension);
429 retName += shipNameExt;
436wxString AisTargetData::BuildQueryResult(
void) {
438 wxDateTime now = wxDateTime::Now();
440 wxString tableStart = _T(
"\n<table border=0 cellpadding=1 cellspacing=0>\n");
441 wxString tableEnd = _T(
"</table>\n\n");
442 wxString rowStart = _T(
"<tr><td><font size=-2>");
443 wxString rowStartH = _T(
"<tr><td nowrap>");
444 wxString rowSeparator = _T(
"</font></td><td></td><td><b>");
445 wxString rowSeparatorH = _T(
"</td><td></td><td>");
446 wxString colSeparator = _T(
"<td></td>");
447 wxString rowEnd = _T(
"</b></td></tr>\n");
448 wxString vertSpacer =
449 _T(
"<tr><td></td></tr><tr><td></td></tr><tr><td></td></tr>\n\n");
451 wxString IMOstr, MMSIstr, ClassStr;
453 html << tableStart << _T(
"<tr><td nowrap colspan=2>");
455 html << _T(
"<font size=+2><i><b>") << GetFullName();
456 html << _T(
"</b></i></font> <b>");
459 if ((Class != AIS_ATON) && (Class != AIS_BASE) && (Class != AIS_GPSG_BUDDY) &&
460 (Class != AIS_SART) && (Class != AIS_METEO)) {
461 html << trimAISField(CallSign) << _T(
"</b>") << rowEnd;
463 if (Class != AIS_CLASS_B) {
464 if (IMO > 0) IMOstr = wxString::Format(_T(
"%08d"), abs(IMO));
467 html << _T(
"</b>") << rowEnd;
471 if (Class != AIS_GPSG_BUDDY) {
472 MMSIstr = wxString::Format(_T(
"%09d"), abs(MMSI));
474 ClassStr = wxGetTranslation(Get_class_string(
false));
476 if (Class == AIS_ATON) {
477 wxString cls(_T(
"AtoN: "));
478 cls += Get_vessel_type_string(
false);
479 ClassStr = wxGetTranslation(cls);
482 if (b_SarAircraftPosnReport) {
483 int airtype = (MMSI % 1000) / 100;
484 ClassStr = airtype == 5 ? _(
"SAR Helicopter") : _(
"SAR Aircraft");
488 html << _T(
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
490 << rowStart << _("MMSI")
491 << _T("</font></td><td> </td><td><font size=-2>") << _("Class")
492 << _T("</font></td><td> </td><td align=right><font size=-2>")
493 << _("IMO") << _T("</font></td></tr>") << rowStartH << _T("<b>")
494 << MMSIstr << _T("</b></td><td> </td><td><b>") << ClassStr
495 << _T("</b></td><td> </td><td align=right><b>") << IMOstr
496 << rowEnd << _T("</table></td></tr>");
498 else if (Class == AIS_METEO) {
499 MMSIstr = wxString::Format(_T(
"%09d"), abs(met_data.original_mmsi));
500 html << _T(
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
502 << rowStart << _("MMSI")
503 << _T("</font></td><td> </td><td align=right><font size=-2>")
504 << _("Class") << _T("</font></td></tr>") << rowStartH << _T("<b>")
505 << MMSIstr << _T("</b></td><td> </td><td align=right><b>")
506 << _T("<font size=-1>") << ClassStr << rowEnd << rowStart
507 << _T("<b>ID: ") << MMSI;
508 if (met_data.stationID) {
510 wxString::Format(_T(
"%06d"), (met_data.stationID - 1000000));
511 html <<
"<td> </td><td align=right>"
512 <<
"SK-ID: " << SK_ID;
514 html << rowEnd << _T(
"</b></table></td></tr>");
516 html << _T(
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
518 << rowStart << _("MMSI")
519 << _T("</font></td><td> </td><td align=right><font size=-2>")
520 << _("Class") << _T("</font></td></tr>") << rowStartH << _T("<b>")
521 << MMSIstr << _T("</b></td><td> </td><td align=right><b>")
522 << ClassStr << rowEnd << _T("</table></td></tr>");
524 if ((Class != AIS_SART))
525 html << _T("<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
528 << ((Class == AIS_BASE || Class == AIS_ATON || Class == AIS_METEO)
531 << rowEnd << _T("</font></td></tr>") << rowStartH
532 << _T("<font size=-1><b>") << GetCountryCode(true) << rowEnd
533 << _T("</font></table></td></tr>");
536 if ((Class != AIS_BASE) && (Class != AIS_CLASS_B) && (Class != AIS_SART) &&
537 (Class != AIS_METEO)) {
539 if ((NavStatus <= 21) && (NavStatus >= 0))
540 navStatStr = wxGetTranslation(ais_get_status(NavStatus));
541 }
else if (Class == AIS_SART) {
542 if (NavStatus == RESERVED_14)
543 navStatStr = _(
"Active");
544 else if (NavStatus == UNDEFINED)
545 navStatStr = _(
"Testing");
548 wxString sart_sub_type;
549 if (Class == AIS_SART) {
550 int mmsi_start = MMSI / 1000000;
551 switch (mmsi_start) {
556 sart_sub_type = _T(
"MOB");
559 sart_sub_type = _T(
"EPIRB");
562 sart_sub_type = _(
"Unknown");
567 wxString AISTypeStr, UNTypeStr, sizeString;
568 if ((Class != AIS_BASE) && (Class != AIS_SART) && (Class != AIS_DSC) &&
569 (Class != AIS_METEO)) {
571 AISTypeStr = wxGetTranslation(Get_vessel_type_string());
573 if (b_isEuroInland && UN_shiptype) {
574 auto it = s_ERI_hash.find(UN_shiptype);
576 if (it == s_ERI_hash.end())
577 type = _(
"Undefined");
581 UNTypeStr = wxGetTranslation(type);
584 if (b_SarAircraftPosnReport) {
590 if (Class == AIS_SART) {
591 if (MSG_14_text.Len()) {
592 html << rowStart << _(
"Safety Broadcast Message") << rowEnd << rowStartH
593 << _T(
"<b>") << MSG_14_text << rowEnd;
599 if (NavStatus != ATON_VIRTUAL && Class != AIS_ARPA && Class != AIS_APRS &&
601 if ((Class == AIS_CLASS_B) || (Class == AIS_ATON)) {
603 wxString::Format(_T(
"%dm x %dm"), (DimA + DimB), (DimC + DimD));
604 }
else if (!b_SarAircraftPosnReport) {
605 if ((DimA + DimB + DimC + DimD) == 0) {
606 if (b_isEuroInland) {
607 if (Euro_Length == 0.0) {
608 if (Euro_Draft > 0.01) {
609 sizeString << wxString::Format(_T(
"---m x ---m x %4.1fm"),
612 sizeString << _T(
"---m x ---m x ---m");
615 if (Euro_Draft > 0.01) {
616 sizeString << wxString::Format(_T(
"%5.1fm x %4.1fm x %4.1fm"),
617 Euro_Length, Euro_Beam,
620 sizeString << wxString::Format(_T(
"%5.1fm x %4.1fm x ---m\n\n"),
621 Euro_Length, Euro_Beam);
626 sizeString << wxString::Format(_T(
"---m x ---m x %4.1fm"), Draft);
628 sizeString << _T(
"---m x ---m x ---m");
631 }
else if (Draft < 0.01) {
632 sizeString << wxString::Format(_T(
"%dm x %dm x ---m"), (DimA + DimB),
635 sizeString << wxString::Format(_T(
"%dm x %dm x %4.1fm"),
636 (DimA + DimB), (DimC + DimD), Draft);
642 if (Class == AIS_SART) {
643 html << _T(
"<tr><td colspan=2>")
644 << _T(
"<b>") << AISTypeStr;
645 if (sart_sub_type.Length()) html << _T(
" (") << sart_sub_type << _T(
"), ");
647 html << rowEnd << _T(
"<tr><td colspan=2>")
648 << _T(
"<b>") << sizeString << rowEnd;
651 else if (Class == AIS_ATON) {
652 html << _T(
"<tr><td colspan=2>")
653 << _T(
"<b>") << navStatStr;
654 html << rowEnd << _T(
"<tr><td colspan=2>")
655 << _T(
"<b>") << sizeString << rowEnd;
656 }
else if (Class == AIS_DSC && (ShipType == 12 || ShipType == 16)) {
657 if (ShipType == 16) {
658 html << _T(
"<tr><td colspan=2>")
659 << _T(
"<b>") << _(
"Distress relay");
660 if (m_dscTXmmsi > 2000000) {
661 wxString mmsirelay = wxString::Format(_T(
" %09d"), abs(m_dscTXmmsi));
662 html << _T(
" ") << _(
"by:") << mmsirelay;
664 html << _T(
"<b>") << sizeString << rowEnd;
666 html << _T(
"<tr><td colspan=2>") << _(
"Nature of distress: ") << rowEnd
667 << _T(
"<tr><td colspan=2>");
668 if (m_dscNature < 13) {
669 html << _T(
"<tr><td colspan=2>")
670 << _T(
"<b>") << GetNatureofDistress(m_dscNature) << _T(
"<b>")
671 << sizeString << rowEnd << _T(
"<tr><td colspan=2>");
673 }
else if ((Class != AIS_BASE) && (Class != AIS_DSC)) {
674 html << _T(
"<tr><td colspan=2>")
675 << _T(
"<b>") << AISTypeStr;
676 if (navStatStr.Length()) html << _T(
", ") << navStatStr;
677 if (UNTypeStr.Length()) html << _T(
" (UN Type ") << UNTypeStr << _T(
")");
678 html << rowEnd << _T(
"<tr><td colspan=2>")
679 << _T(
"<b>") << sizeString << rowEnd;
682 if (b_positionOnceValid) {
684 if (b_positionDoubtful) posTypeStr << _(
" (Last Known)");
687 int target_age = now.GetTicks() - PositionReportTicks;
692 html << vertSpacer << rowStart << _(
"Position") << posTypeStr
693 << _T(
"</font></td><td align=right><font size=-2>") << _(
"Report Age")
694 << _T(
"</font></td></tr>")
696 << rowStartH << _T(
"<b>") << toSDMM(1, Lat)
697 << _T(
"</b></td><td align=right><b>") << FormatTimeAdaptive(target_age)
698 << rowEnd << rowStartH << _T(
"<b>") << toSDMM(2, Lon);
699 if (Class != AIS_METEO)
703 wxString::Format(
" %02d:%02d", met_data.hour, met_data.minute);
704 html <<
" </td><td align=right></b></font><font size=-3>"
705 << _(
"Issued (UTC)") <<
"</font><font size=-1><b>" << meteoTime
706 <<
"</font>" << rowEnd;
710 wxString courseStr, sogStr, hdgStr, rotStr, rngStr, brgStr, destStr, etaStr;
712 if (Class == AIS_GPSG_BUDDY) {
713 long month, year, day;
714 m_date_string.Mid(0, 2).ToLong(&day);
715 m_date_string.Mid(2, 2).ToLong(&month);
716 m_date_string.Mid(4, 2).ToLong(&year);
719 date.SetMonth((wxDateTime::Month)(month - 1));
720 date.SetYear(year + 2000);
722 wxString f_date = date.FormatISODate();
724 html << vertSpacer << rowStart << _(
"Report as of") << rowEnd << rowStartH
725 << _T(
"<b>") << f_date + _T(
"</b> at <b>")
726 << wxString::Format(_T(
"%d:%d UTC "), m_utc_hour, m_utc_min) << rowEnd;
728 if (Class == AIS_CLASS_A && !b_SarAircraftPosnReport) {
729 html << vertSpacer << rowStart << _(
"Destination")
730 << _T(
"</font></td><td align=right><font size=-2>") << _(
"ETA (UTC)")
731 << _T(
"</font></td></tr>\n") << rowStartH << _T(
"<b>");
732 wxString dest = trimAISField(Destination);
734 html << html_escape(dest);
737 html << _T(
"</b></td><td nowrap align=right><b>");
739 if ((ETA_Mo) && (ETA_Hr < 24)) {
741 if (now.GetMonth() > (ETA_Mo - 1)) yearOffset = 1;
742 wxDateTime eta(ETA_Day, wxDateTime::Month(ETA_Mo - 1),
743 now.GetYear() + yearOffset, ETA_Hr, ETA_Min);
744 html << eta.Format(_T(
"%b %d %H:%M"));
750 if (Class == AIS_CLASS_A || Class == AIS_CLASS_B || Class == AIS_ARPA ||
751 Class == AIS_APRS || Class == AIS_SART || Class == AIS_BUOY) {
752 int crs = wxRound(COG);
754 wxString magString, trueString;
756 magString << wxString::Format(
757 wxString(
"%03d%c(M)"),
static_cast<int>(m_callbacks.get_mag(COG)),
760 trueString << wxString::Format(wxString(
"%03d%c "), (
int)crs, 0x00B0);
762 courseStr << trueString << magString;
763 }
else if (COG == 360.0)
764 courseStr = _T(
"---");
766 courseStr = _T(
"0°");
768 double speed_show = toUsrSpeed(SOG);
770 if ((SOG <= 102.2) || b_SarAircraftPosnReport) {
771 if (speed_show < 10.0)
773 wxString::Format(_T(
"%.2f "), speed_show) + getUsrSpeedUnit();
774 else if (speed_show < 100.0)
776 wxString::Format(_T(
"%.1f "), speed_show) + getUsrSpeedUnit();
779 wxString::Format(_T(
"%.0f "), speed_show) + getUsrSpeedUnit();
787 hdgStr = wxString::Format(_T(
"%03d°"), (
int)HDG);
791 if (ROTAIS != -128) {
793 rotStr << _T(
"> 5°/30s ") << _(
"Right");
794 else if (ROTAIS == -127)
795 rotStr << _T(
"> 5°/30s ") << _(
"Left");
798 rotStr << wxString::Format(_T(
"%3d°/Min "), ROTIND)
801 rotStr << wxString::Format(_T(
"%3d°/Min "), -ROTIND)
806 }
else if (!b_SarAircraftPosnReport)
811 if (b_positionOnceValid && bGPSValid && (Range_NM >= 0.))
812 rngStr = FormatDistanceAdaptive(Range_NM);
816 int brg = (int)wxRound(Brg);
817 if (Brg > 359.5) brg = 0;
818 if (b_positionOnceValid && bGPSValid && (Brg >= 0.) && (Range_NM > 0.) &&
820 wxString magString, trueString;
822 magString << wxString::Format(wxString(
"%03d%c(M)"),
823 static_cast<int>(m_callbacks.get_mag(Brg)),
826 trueString << wxString::Format(wxString(
"%03d%c "), (
int)Brg, 0x00B0);
828 brgStr << trueString << magString;
832 wxString turnRateHdr;
833 if ((Class != AIS_ATON) && (Class != AIS_BASE) && (Class != AIS_DSC) &&
834 (Class != AIS_METEO)) {
836 << _T(
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
838 << rowStart << _("Speed")
839 << _T("</font></td><td> </td><td><font size=-2>") << _("Course")
840 << _T("</font></td><td> </td><td align=right><font size=-2>");
841 if (!b_SarAircraftPosnReport) html << _("Heading");
843 html << _T("</font></td></tr>") << rowStartH << _T("<b>") << sogStr
844 << _T("</b></td><td> </td><td><b>") << courseStr
845 << _T("</b></td><td> </td><td align=right><b>");
846 if (!b_SarAircraftPosnReport) html << hdgStr;
847 html << rowEnd << _T("</table></td></tr>") << vertSpacer;
849 if (!b_SarAircraftPosnReport) turnRateHdr = _("Turn Rate");
851 if (Class != AIS_METEO) {
852 html << _T(
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
854 << rowStart << _("Range")
855 << _T("</font></td><td> </td><td><font size=-2>") << _("Bearing")
856 << _T("</font></td><td> </td><td align=right><font size=-2>")
857 << turnRateHdr << _T("</font></td></tr>") << rowStartH << _T("<b>")
858 << rngStr << _T("</b></td><td> </td><td><b>") << brgStr
859 << _T("</b></td><td> </td><td align=right><b>");
860 if (!b_SarAircraftPosnReport) html << rotStr;
861 html << rowEnd << _T("</table></td></tr>") << vertSpacer;
864 if (bCPA_Valid && Class != AIS_METEO) {
866 tcpaStr << _T(
"</b> ") << _(
"in ") << _T(
"</td><td align=right><b>")
867 << FormatTimeAdaptive((
int)(TCPA * 60.));
869 html << rowStart << _T(
"<font size=-2>") << _(
"CPA")
870 << _T(
"</font>") << rowEnd << rowStartH << _T(
"<b>")
871 << FormatDistanceAdaptive(CPA) << tcpaStr << rowEnd;
874 if (Class != AIS_BASE && Class != AIS_METEO) {
875 if (blue_paddle == 1) {
876 html << rowStart << _(
"Inland Blue Flag") << rowEnd << rowStartH
877 << _T(
"<b>") << _(
"Clear") << rowEnd;
878 }
else if (blue_paddle == 2) {
879 html << rowStart << _(
"Inland Blue Flag") << rowEnd << rowStartH
880 << _T(
"<b>") << _(
"Set") << rowEnd;
884 if (b_SarAircraftPosnReport) {
886 if (altitude != 4095)
887 altStr.Printf(_T(
"%4d m"), altitude);
889 altStr = _(
"Unknown");
891 html << rowStart << _(
"Altitude")
892 << _T(
"</font></td><td> </td><td><font size=-0>") << rowStartH
893 << _T(
"<b>") << altStr << _T(
"</b></td><td> </td><td><b>")
894 << rowEnd << _T(
"</table></td></tr>") << vertSpacer;
897 if (Class == AIS_METEO) {
898 if (met_data.wind_kn < 122) {
899 double userwindspeed = toUsrWindSpeed(met_data.wind_kn);
901 wxString::Format(
"%0.1f %s %d%c", userwindspeed,
902 getUsrWindSpeedUnit(), met_data.wind_dir, 0x00B0);
904 double userwindgustspeed = toUsrWindSpeed(met_data.wind_gust_kn);
905 wxString wspeedGust = wxString::Format(
"%.0f %s %d%c", userwindgustspeed,
906 getUsrWindSpeedUnit(),
907 met_data.wind_gust_dir, 0x00B0);
908 if (met_data.wind_gust_kn >= 126) wspeedGust = wxEmptyString;
910 html << vertSpacer << rowStart << _(
"Wind speed")
911 << _T(
"</font></td><td align=right><font size=-2>") << _(
"Wind gust")
912 << _T(
"</font></td></tr>") << rowStartH << _T(
"<b>") << wspeed
913 << _T(
"</b></td><td align=right><b>") << wspeedGust << rowEnd;
916 if (met_data.water_lev_dev < 30. || met_data.water_level > -32. ||
917 met_data.current < 25.5) {
918 wxString wlevel_txt = _(
"Water level deviation");
920 if (met_data.water_lev_dev < 30.) {
921 double userlevel = toUsrDepth(met_data.water_lev_dev);
923 wxString::Format(
"%.1f %s %s", userlevel, getUsrDepthUnit(),
924 ais_meteo_get_trend(met_data.water_lev_trend));
925 if (met_data.vertical_ref < 14) {
926 wlevel_txt = _(
"Water level dev. Ref: ");
927 wlevel_txt << aisMeteoWaterLevelRef(met_data.vertical_ref);
930 if (met_data.water_lev_dev >= 30.) wlevel = wxEmptyString;
932 }
else if (met_data.water_level > -32.) {
933 double userlevel = toUsrDepth(met_data.water_level);
935 wxString::Format(
"%.1f %s %s", userlevel, getUsrDepthUnit(),
936 ais_meteo_get_trend(met_data.water_lev_trend));
937 wlevel_txt = _(
"Water level");
938 if (met_data.water_level <= -32.) wlevel = wxEmptyString;
941 wxString current = wxString::Format(
"%.1f kts %d%c", met_data.current,
942 met_data.curr_dir, 0x00B0);
943 if (met_data.current >= 25.5) current = wxEmptyString;
945 html << vertSpacer << rowStart << wlevel_txt
946 << _T(
"</font></td><td align=right><font size=-2>")
947 << _(
"Surface current ") << _T(
"</font></td></tr>") << rowStartH
948 << _T(
"<b>") << wlevel << _T(
"</b></td><td align=right><b>")
949 << current << rowEnd;
952 if (met_data.wave_height < 24.6 || met_data.swell_height < 24.6) {
953 double userwave = toUsrDepth(met_data.wave_height);
954 wxString wave = wxString::Format(
"%.1f %s %d%c %d %s ", userwave,
955 getUsrDepthUnit(), met_data.wave_dir,
956 0x00B0, met_data.wave_period, _(
"s"));
957 if (met_data.wave_height >= 24.6) wave = wxEmptyString;
959 double userswell = toUsrDepth(met_data.swell_height);
960 wxString swell = wxString::Format(
"%.1f %s %d%c %d %s", userswell,
961 getUsrDepthUnit(), met_data.swell_dir,
962 0x00B0, met_data.swell_per, _(
"s"));
963 if (met_data.swell_height >= 25.) swell = wxEmptyString;
965 html << vertSpacer << rowStart << _(
"Waves height & period")
966 << _T(
"</font></td><td align=right><font size=-2>")
967 << _(
"Swell height & period ") << _T(
"</font></td></tr>")
968 << rowStartH << _T(
"<b>") << wave
969 << _T(
"</b></td><td align=right><b>") << swell << rowEnd;
972 if (met_data.air_temp != -102.4 || met_data.airpress < 1310) {
973 double usertemp = toUsrTemp(met_data.air_temp);
975 wxString::Format(
"%.1f%c%s", usertemp, 0x00B0, getUsrTempUnit());
976 if (met_data.air_temp == -102.4) airtemp = wxEmptyString;
979 wxString::Format(
"%d hPa %s", met_data.airpress,
980 ais_meteo_get_trend(met_data.airpress_tend));
981 const int ap = met_data.airpress;
982 if (ap < 800 || ap >= 1310) airpress = wxEmptyString;
984 html << vertSpacer << rowStart << _(
"Air Temperatur")
985 << _T(
"</font></td><td align=right><font size=-2>")
986 << _(
"Air pressure") << _T(
"</font></td></tr>") << rowStartH
987 << _T(
"<b>") << airtemp << _T(
"</b></td><td align=right><b>")
988 << airpress << rowEnd;
991 if (met_data.rel_humid < 101 || met_data.dew_point < 50.) {
992 wxString humid = wxString::Format(
"%d%c", met_data.rel_humid,
'%');
993 if (met_data.rel_humid >= 101) humid = wxEmptyString;
995 double usertempDew = toUsrTemp(met_data.dew_point);
997 wxString::Format(
"%.1f%c%s", usertempDew, 0x00B0, getUsrTempUnit());
998 if (met_data.dew_point >= 50.) dewpoint = wxEmptyString;
1000 html << vertSpacer << rowStart << _(
"Relative Humidity")
1001 << _T(
"</font></td><td align=right><font size=-2>")
1002 << _(
"Dew Point ") << _T(
"</font></td></tr>") << rowStartH
1003 << _T(
"<b>") << humid << _T(
"</b></td><td align=right><b>")
1004 << dewpoint << rowEnd;
1007 if (met_data.water_temp < 50.1 || met_data.seastate < 13) {
1008 double usertemp = toUsrTemp(met_data.water_temp);
1009 wxString watertemp =
1010 wxString::Format(
"%.1f%c%s", usertemp, 0x00B0, getUsrTempUnit());
1011 if (met_data.water_temp >= 50.1) watertemp = wxEmptyString;
1013 wxString seastate = wxString::Format(
"%d Bf ", met_data.seastate);
1014 if (met_data.seastate == 13) seastate = wxEmptyString;
1016 html << vertSpacer << rowStart << _(
"Water Temperatur")
1017 << _T(
"</font></td><td align=right><font size=-2>") << _(
"Sea state")
1018 << _T(
"</font></td></tr>") << rowStartH << _T(
"<b>") << watertemp
1019 << _T(
"</b></td><td align=right><b>") << seastate << rowEnd;
1022 if (met_data.precipitation < 7 || met_data.hor_vis < 12.7) {
1024 wxString::Format(
"%s", aisMeteoPrecipType(met_data.precipitation));
1025 if (met_data.precipitation >= 6) precip = wxEmptyString;
1027 double userVisDist = toUsrDistance(met_data.hor_vis);
1029 wxString::Format(
"%s%.1f %s", (met_data.hor_vis_GT ?
">" :
""),
1030 userVisDist, getUsrDistanceUnit());
1031 if (met_data.hor_vis >= 12.7) horVis = wxEmptyString;
1032 html << vertSpacer << rowStart << _(
"Precipitation")
1033 << _T(
"</font></td><td align=right><font size=-2>")
1034 << _(
"Horizontal Visibility") << _T(
"</font></td></tr>") << rowStartH
1035 << _T(
"<b>") << precip << _T(
"</b></td><td align=right><b>")
1036 << horVis << rowEnd;
1039 if (met_data.salinity < 50. || met_data.ice < 2) {
1040 wxString sal = wxString::Format(
"%.1f%c", met_data.salinity, 0x2030);
1041 if (met_data.salinity >= 50.) sal = wxEmptyString;
1043 wxString icestatus = _(
"No");
1044 if (met_data.ice == 1) icestatus = _(
"Yes");
1045 if (met_data.ice >= 2) icestatus = wxEmptyString;
1047 html << vertSpacer << rowStart << _(
"Sea salinity")
1048 << _T(
"</font></td><td align=right><font size=-2>")
1049 << _(
"Ice status") << _T(
"</font></td></tr>") << rowStartH
1050 << _T(
"<b>") << sal << _T(
"</b></td><td align=right><b>")
1051 << icestatus << rowEnd;
1054 html << _T(
"</table>");
1058wxString AisTargetData::GetRolloverString(
void) {
1062 result.Append(_T(
"\""));
1063 result.Append(GetFullName());
1064 result.Append(_T(
"\" "));
1066 if (Class != AIS_GPSG_BUDDY) {
1067 t.Printf(_T(
"%09d"), abs(MMSI));
1069 result.Append(_T(
" "));
1070 result.Append(GetCountryCode(
false));
1072 t = trimAISField(CallSign);
1074 result.Append(_T(
" ("));
1076 result.Append(_T(
")"));
1078 if (g_bAISRolloverShowClass || (Class == AIS_SART)) {
1079 if (result.Len()) result.Append(_T(
"\n"));
1080 result.Append(_T(
"["));
1081 if (Class == AIS_ATON) {
1082 result.Append(wxGetTranslation(Get_class_string(
true)));
1083 result.Append(_T(
": "));
1084 result.Append(wxGetTranslation(Get_vessel_type_string(
false)));
1085 }
else if (b_SarAircraftPosnReport) {
1086 int airtype = (MMSI % 1000) / 100;
1087 result.Append(airtype == 5 ? _(
"SAR Helicopter") : _(
"SAR Aircraft"));
1089 result.Append(wxGetTranslation(Get_class_string(
false)));
1091 result.Append(_T(
"] "));
1092 if ((Class != AIS_ATON) && (Class != AIS_BASE)) {
1093 if (Class == AIS_SART) {
1094 int mmsi_start = MMSI / 1000000;
1095 switch (mmsi_start) {
1099 result += _T(
"MOB");
1102 result += _T(
"EPIRB");
1105 result += _(
"Unknown");
1110 if (Class != AIS_SART && Class != AIS_METEO) {
1111 if (!b_SarAircraftPosnReport)
1112 result.Append(wxGetTranslation(Get_vessel_type_string(
false)));
1115 if ((Class != AIS_CLASS_B) && (Class != AIS_SART) && Class != AIS_DSC &&
1116 Class != AIS_METEO && !b_SarAircraftPosnReport) {
1117 if ((NavStatus <= 15) && (NavStatus >= 0)) {
1118 result.Append(_T(
" ("));
1119 result.Append(wxGetTranslation(ais_get_status(NavStatus)));
1120 result.Append(_T(
")"));
1122 }
else if (Class == AIS_SART) {
1123 result.Append(_T(
" ("));
1124 if (NavStatus == RESERVED_14)
1125 result.Append(_(
"Active"));
1126 else if (NavStatus == UNDEFINED)
1127 result.Append(_(
"Testing"));
1128 result.Append(_T(
")"));
1129 }
else if (Class == AIS_DSC) {
1130 result.Append(_T(
" ("));
1131 result.Append(GetNatureofDistress(m_dscNature));
1132 result.Append(_T(
")"));
1137 if (g_bAISRolloverShowCOG && ((SOG <= 102.2) || b_SarAircraftPosnReport) &&
1138 !((Class == AIS_ATON) || (Class == AIS_BASE) || (Class == AIS_METEO))) {
1139 if (result.Len()) result << _T(
"\n");
1141 double speed_show = toUsrSpeed(SOG);
1142 if (speed_show < 10.0)
1143 result << wxString::Format(_T(
"SOG %.2f "), speed_show)
1144 << getUsrSpeedUnit() << _T(
" ");
1145 else if (speed_show < 100.0)
1146 result << wxString::Format(_T(
"SOG %.1f "), speed_show)
1147 << getUsrSpeedUnit() << _T(
" ");
1149 result << wxString::Format(_T(
"SOG %.0f "), speed_show)
1150 << getUsrSpeedUnit() << _T(
" ");
1152 int crs = wxRound(COG);
1153 if (b_positionOnceValid) {
1155 wxString magString, trueString;
1157 magString << wxString::Format(
1158 wxString(
"%03d%c(M) "),
1159 static_cast<int>(m_callbacks.get_mag(COG)), 0x00B0);
1161 trueString << wxString::Format(wxString(
"%03d%c "), (
int)crs, 0x00B0);
1163 result << trueString << magString;
1166 else if (COG == 360.0)
1167 result << _(
" COG Unavailable");
1168 else if (crs == 360)
1169 result << wxString(
" COG 000\u00B0");
1171 result << _(
" COG Unavailable");
1174 if (g_bAISRolloverShowCPA && bCPA_Valid && Class != AIS_METEO) {
1175 if (result.Len()) result << _T(
"\n");
1176 result << _(
"CPA") << _T(
" ") << FormatDistanceAdaptive(CPA) << _T(
" ")
1177 << _(
"in") << _T(
" ") << wxString::Format(_T(
"%.0f"), TCPA)
1178 << _T(
" ") << _(
"min");
1180 if (Class == AIS_METEO) {
1181 if (met_data.wind_kn < 122) {
1182 if (result.Len()) result <<
"\n";
1183 double userwindspeed = toUsrWindSpeed(met_data.wind_kn);
1184 result << _(
"Wind speed");
1185 result << wxString::Format(
": %0.1f %s", userwindspeed,
1186 getUsrWindSpeedUnit())
1187 << wxString::Format(
" %d%c ", met_data.wind_dir, 0x00B0);
1190 if (met_data.water_lev_dev < 30.) {
1191 if (result.Len()) result <<
"\n";
1192 result << _(
"Water level deviation");
1194 userdepth = toUsrDepth(met_data.water_lev_dev);
1195 result << wxString::Format(
": %.1f %s", userdepth, getUsrDepthUnit());
1197 }
else if (met_data.water_level > -32.) {
1198 if (result.Len()) result <<
"\n";
1199 result << _(
"Water level");
1201 userdepth = toUsrDepth(met_data.water_level);
1202 result << wxString::Format(
": %.1f %s", userdepth, getUsrDepthUnit());
1205 if (met_data.current < 25.) {
1206 if (result.Len()) result <<
"\n";
1207 result << _(
"Current");
1208 result << wxString::Format(
": %.1f ", met_data.current) << _(
"kts")
1209 << wxString::Format(
" %d%c ", met_data.curr_dir, 0x00B0);
1212 if (met_data.wave_height < 24.6) {
1213 if (result.Len()) result <<
"\n";
1214 double userwh = toUsrDepth(met_data.wave_height);
1215 result << _(
"Wave height")
1216 << wxString::Format(
": %.1f %s", userwh, getUsrDepthUnit())
1217 <<
" / " << met_data.wave_period <<
" " << _(
"s");
1220 if (met_data.water_temp < 50.) {
1221 if (result.Len()) result <<
"\n";
1222 double usertemp = toUsrTemp(met_data.water_temp);
1223 result << _(
"Water temp");
1224 result << wxString::Format(
": %.1f%c", usertemp, 0x00B0)
1225 << getUsrTempUnit();
1228 if (met_data.air_temp != -102.4) {
1229 if (result.Len()) result <<
"\n";
1230 double usertemp = toUsrTemp(met_data.air_temp);
1231 result << _(
"Air temp");
1232 result << wxString::Format(
": %.1f%c", usertemp, 0x00B0)
1233 << getUsrTempUnit() <<
" ";
1236 if (met_data.airpress > 799 && met_data.airpress < 1310) {
1237 if (met_data.air_temp == -102.4 && result.Len()) result <<
"\n";
1238 result << _(
"Air press");
1239 result << wxString::Format(
": %d hPa", met_data.airpress);
1242 if (met_data.hor_vis < 12.) {
1243 if (result.Len()) result <<
"\n";
1244 double userVisDist = toUsrDistance(met_data.hor_vis);
1246 wxString::Format(
": %s%.1f %s", (met_data.hor_vis_GT ?
">" :
""),
1247 userVisDist, getUsrDistanceUnit());
1248 result << _(
"Visibility") << horVis;
1254wxString AisTargetData::Get_vessel_type_string(
bool b_short) {
1256 if (Class == AIS_ATON) {
1310 if ((Class == AIS_CLASS_B) || (Class == AIS_CLASS_A)) {
1311 if ((ShipType >= 40) && (ShipType < 50)) i = 8;
1313 if ((ShipType >= 60) && (ShipType < 70)) i = 16;
1315 if ((ShipType >= 70) && (ShipType < 80)) i = 17;
1317 if ((ShipType >= 80) && (ShipType < 90)) i = 18;
1318 }
else if (Class == AIS_GPSG_BUDDY)
1320 else if (Class == AIS_ARPA)
1322 else if (Class == AIS_APRS)
1324 else if (Class == AIS_BUOY)
1326 else if (Class == AIS_DSC)
1327 i = (ShipType == 12 || ShipType == 16) ? 54 : 53;
1330 return ais_get_type(i);
1332 return ais_get_short_type(i);
1335wxString AisTargetData::Get_class_string(
bool b_short) {
1342 return b_short ? _(
"AtoN") : _(
"Aid to Navigation");
1344 return b_short ? _(
"Base") : _(
"Base Station");
1345 case AIS_GPSG_BUDDY:
1346 return b_short ? _(
"Buddy") : _(
"GPSGate Buddy");
1348 if (ShipType == 12 || (ShipType == 16 && m_dscNature < 13))
1349 return b_short ? _(
"DSC") : _(
"DSC Distress");
1351 return b_short ? _(
"DSC") : _(
"DSC Position Report");
1353 return b_short ? _(
"SART") : _(
"SART");
1355 return b_short ? _(
"ARPA") : _(
"ARPA");
1357 return b_short ? _(
"Buoy") : _(
"BUOY");
1359 return b_short ? _(
"APRS") : _(
"APRS Position Report");
1361 return b_short ? _(
"Meteo") : _(
"Meteorologic");
1364 return b_short ? _(
"Unk") : _(
"Unknown");
1368wxString AisTargetData::GetNatureofDistress(
int dscnature) {
1370 wxString dscDistressType[] = {_(
"Fire, explosion"),
1374 _(
"Listing, in danger of capsizing"),
1376 _(
"Disabled and adrift"),
1377 _(
"Undesignated distress"),
1378 _(
"Abandoning ship"),
1379 _(
"Piracy/armed robbery attack"),
1382 _(
"EPIRB emission")};
1383 if (dscnature >= 0 && dscnature < 13)
return dscDistressType[dscnature];
1385 return wxEmptyString;
1388void AisTargetData::Toggle_AIS_CPA(
void) {
1389 b_show_AIS_CPA = !b_show_AIS_CPA ? true :
false;
1392void AisTargetData::ToggleShowTrack(
void) {
1393 b_show_track = !b_show_track ? true :
false;
1396bool AisTargetData::IsValidMID(
int mid) {
1397 if (mid >= 201 && mid <= 775)
return true;
1403wxString AisTargetData::GetCountryCode(
bool b_CntryLongStr) {
1404 if (Class == AIS_BUOY)
return wxEmptyString;
1407 int tmpMmsi = met_data.original_mmsi ? met_data.original_mmsi : MMSI;
1409 int nMID = tmpMmsi / 1000000;
1410 if (!IsValidMID(nMID) || Class == AIS_ATON) {
1413 if (tmpMmsi < 1000 || 97 == tmpMmsi / 10000000)
return wxEmptyString;
1418 bool foundMID =
false;
1420 i = nMID > 900 ? 2 : 0;
1421 for (i; i < s_mmsi.length() - 3; i++) {
1422 nMID = wxAtoi(s_mmsi.Mid(i, 3));
1423 if (IsValidMID(nMID)) {
1428 if (!foundMID)
return wxEmptyString;
1431#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
1435 return b_CntryLongStr ? _(
"Albania") : _T(
"AL");
1437 return b_CntryLongStr ? _(
"Andorra") : _T(
"AD");
1439 return b_CntryLongStr ? _(
"Austria") : _T(
"AT");
1441 return b_CntryLongStr ? _(
"Azores") : _T(
"AZ");
1443 return b_CntryLongStr ? _(
"Belgium") : _T(
"BE");
1445 return b_CntryLongStr ? _(
"Belarus") : _T(
"BY");
1447 return b_CntryLongStr ? _(
"Bulgaria") : _T(
"BG");
1449 return b_CntryLongStr ? _(
"Vatican City State") : _T(
"VA");
1452 return b_CntryLongStr ? _(
"Cyprus") : _T(
"CY");
1454 return b_CntryLongStr ? _(
"Germany") : _T(
"DE");
1456 return b_CntryLongStr ? _(
"Cyprus") : _T(
"CY");
1458 return b_CntryLongStr ? _(
"Georgia") : _T(
"GE");
1460 return b_CntryLongStr ? _(
"Moldova") : _T(
"MD");
1462 return b_CntryLongStr ? _(
"Malta") : _T(
"MT");
1464 return b_CntryLongStr ? _(
"Armenia") : _T(
"AM");
1466 return b_CntryLongStr ? _(
"Germany") : _T(
"DE");
1469 return b_CntryLongStr ? _(
"Denmark") : _T(
"DK");
1471 return b_CntryLongStr ? _(
"Spain") : _T(
"ES");
1473 return b_CntryLongStr ? _(
"Spain") : _T(
"ES");
1477 return b_CntryLongStr ? _(
"France") : _T(
"FR");
1479 return b_CntryLongStr ? _(
"Malta") : _T(
"MT");
1481 return b_CntryLongStr ? _(
"Finland") : _T(
"FI");
1483 return b_CntryLongStr ? _(
"Faroe Islands") : _T(
"FO");
1488 return b_CntryLongStr ? _(
"Great Britain") : _T(
"GB");
1490 return b_CntryLongStr ? _(
"Gibraltar") : _T(
"GI");
1492 return b_CntryLongStr ? _(
"Greece") : _T(
"GR");
1494 return b_CntryLongStr ? _(
"Croatia") : _T(
"HR");
1498 return b_CntryLongStr ? _(
"Greece") : _T(
"GR");
1500 return b_CntryLongStr ? _(
"Morocco") : _T(
"MA");
1502 return b_CntryLongStr ? _(
"Hungary") : _T(
"HU");
1506 return b_CntryLongStr ? _(
"Netherlands") : _T(
"NL");
1508 return b_CntryLongStr ? _(
"Italy") : _T(
"IT");
1511 return b_CntryLongStr ? _(
"Malta") : _T(
"MT");
1513 return b_CntryLongStr ? _(
"Ireland") : _T(
"IE");
1515 return b_CntryLongStr ? _(
"Iceland") : _T(
"IS");
1517 return b_CntryLongStr ? _(
"Liechtenstein") : _T(
"LI");
1519 return b_CntryLongStr ? _(
"Luxembourg") : _T(
"LU");
1521 return b_CntryLongStr ? _(
"Monaco") : _T(
"MC");
1523 return b_CntryLongStr ? _(
"Madeira") : _T(
"PT");
1525 return b_CntryLongStr ? _(
"Malta") : _T(
"MT");
1529 return b_CntryLongStr ? _(
"Norway") : _T(
"NO");
1531 return b_CntryLongStr ? _(
"Poland") : _T(
"PL");
1533 return b_CntryLongStr ? _(
"Montenegro") : _T(
"ME");
1535 return b_CntryLongStr ? _(
"Portugal") : _T(
"PT");
1537 return b_CntryLongStr ? _(
"Romania") : _T(
"RO");
1540 return b_CntryLongStr ? _(
"Sweden") : _T(
"SE");
1542 return b_CntryLongStr ? _(
"Slovak Republic") : _T(
"SK");
1544 return b_CntryLongStr ? _(
"San Marino") : _T(
"SM");
1546 return b_CntryLongStr ? _(
"Switzerland") : _T(
"CH");
1548 return b_CntryLongStr ? _(
"Czech Republic") : _T(
"CZ");
1550 return b_CntryLongStr ? _(
"Turkey") : _T(
"TR");
1552 return b_CntryLongStr ? _(
"Ukraine") : _T(
"UA");
1554 return b_CntryLongStr ? _(
"Russian") : _T(
"RU");
1556 return b_CntryLongStr ? _(
"Macedonia") : _T(
"MK");
1558 return b_CntryLongStr ? _(
"Latvia") : _T(
"LV");
1560 return b_CntryLongStr ? _(
"Estonia") : _T(
"EE");
1562 return b_CntryLongStr ? _(
"Lithuania") : _T(
"LT");
1564 return b_CntryLongStr ? _(
"Slovenia") : _T(
"SI");
1566 return b_CntryLongStr ? _(
"Serbia") : _T(
"RS");
1568 return b_CntryLongStr ? _(
"Anguilla") : _T(
"AI");
1570 return b_CntryLongStr ? _(
"Alaska") : _T(
"AK");
1573 return b_CntryLongStr ? _(
"Antigua and Barbuda") : _T(
"AG");
1575 return b_CntryLongStr ? _(
"Antilles") : _T(
"AN");
1577 return b_CntryLongStr ? _(
"Aruba") : _T(
"AW");
1580 return b_CntryLongStr ? _(
"Bahamas") : _T(
"BS");
1582 return b_CntryLongStr ? _(
"Bermuda") : _T(
"BM");
1584 return b_CntryLongStr ? _(
"Bahamas") : _T(
"BS");
1586 return b_CntryLongStr ? _(
"Belize") : _T(
"BZ");
1588 return b_CntryLongStr ? _(
"Barbados") : _T(
"BB");
1590 return b_CntryLongStr ? _(
"Canada") : _T(
"CA");
1592 return b_CntryLongStr ? _(
"Cayman Islands") : _T(
"KY");
1594 return b_CntryLongStr ? _(
"Costa Rica") : _T(
"CR");
1596 return b_CntryLongStr ? _(
"Cuba") : _T(
"CU");
1598 return b_CntryLongStr ? _(
"Dominica") : _T(
"DM");
1600 return b_CntryLongStr ? _(
"Dominican Republic") : _T(
"DM");
1602 return b_CntryLongStr ? _(
"Guadeloupe") : _T(
"GP");
1604 return b_CntryLongStr ? _(
"Grenada") : _T(
"GD");
1606 return b_CntryLongStr ? _(
"Greenland") : _T(
"GL");
1608 return b_CntryLongStr ? _(
"Guatemala") : _T(
"GT");
1610 return b_CntryLongStr ? _(
"Honduras") : _T(
"HN");
1612 return b_CntryLongStr ? _(
"Haiti") : _T(
"HT");
1614 return b_CntryLongStr ? _(
"United States of America") : _T(
"US");
1616 return b_CntryLongStr ? _(
"Jamaica") : _T(
"JM");
1618 return b_CntryLongStr ? _(
"Saint Kitts and Nevis") : _T(
"KN");
1620 return b_CntryLongStr ? _(
"Saint Lucia") : _T(
"LC");
1622 return b_CntryLongStr ? _(
"Mexico") : _T(
"MX");
1624 return b_CntryLongStr ? _(
"Martinique") : _T(
"MQ");
1626 return b_CntryLongStr ? _(
"Montserrat") : _T(
"MS");
1628 return b_CntryLongStr ? _(
"Nicaragua") : _T(
"NI");
1636 return b_CntryLongStr ? _(
"Panama") : _T(
"PA");
1638 return b_CntryLongStr ? _(
"Puerto Rico") : _T(
"PR");
1640 return b_CntryLongStr ? _(
"El Salvador") : _T(
"SV");
1642 return b_CntryLongStr ? _(
"Saint Pierre and Miquelon") : _T(
"PM");
1644 return b_CntryLongStr ? _(
"Trinidad and Tobago") : _T(
"TT");
1646 return b_CntryLongStr ? _(
"Turks and Caicos Islands") : _T(
"TC");
1651 return b_CntryLongStr ? _(
"United States of America") : _T(
"US");
1657 return b_CntryLongStr ? _(
"Panama") : _T(
"PA");
1661 return b_CntryLongStr ? _(
"Saint Vincent and the Grenadines") : _T(
"VC");
1663 return b_CntryLongStr ? _(
"British Virgin Islands") : _T(
"VG");
1665 return b_CntryLongStr ? _(
"United States Virgin Islands") : _T(
"AE");
1667 return b_CntryLongStr ? _(
"Afghanistan") : _T(
"AF");
1669 return b_CntryLongStr ? _(
"Saudi Arabia") : _T(
"SA");
1671 return b_CntryLongStr ? _(
"Bangladesh") : _T(
"BD");
1673 return b_CntryLongStr ? _(
"Bahrain") : _T(
"BH");
1675 return b_CntryLongStr ? _(
"Bhutan") : _T(
"BT");
1679 return b_CntryLongStr ? _(
"China") : _T(
"CN");
1681 return b_CntryLongStr ? _(
"Taiwan") : _T(
"TW");
1683 return b_CntryLongStr ? _(
"Sri Lanka") : _T(
"LK");
1685 return b_CntryLongStr ? _(
"India") : _T(
"IN");
1687 return b_CntryLongStr ? _(
"Iran") : _T(
"IR");
1689 return b_CntryLongStr ? _(
"Azerbaijani Republic") : _T(
"AZ");
1691 return b_CntryLongStr ? _(
"Iraq") : _T(
"IQ");
1693 return b_CntryLongStr ? _(
"Israel") : _T(
"IL");
1695 return b_CntryLongStr ? _(
"Japan") : _T(
"JP");
1697 return b_CntryLongStr ? _(
"Japan") : _T(
"JP");
1699 return b_CntryLongStr ? _(
"Turkmenistan") : _T(
"TM");
1701 return b_CntryLongStr ? _(
"Kazakhstan") : _T(
"KZ");
1703 return b_CntryLongStr ? _(
"Uzbekistan") : _T(
"UZ");
1705 return b_CntryLongStr ? _(
"Jordan") : _T(
"JO");
1708 return b_CntryLongStr ? _(
"Korea") : _T(
"KR");
1710 return b_CntryLongStr ? _(
"Palestine") : _T(
"PS");
1712 return b_CntryLongStr ? _(
"People's Rep. of Korea") : _T(
"KP");
1714 return b_CntryLongStr ? _(
"Kuwait") : _T(
"KW");
1716 return b_CntryLongStr ? _(
"Lebanon") : _T(
"LB");
1718 return b_CntryLongStr ? _(
"Kyrgyz Republic") : _T(
"KG");
1720 return b_CntryLongStr ? _(
"Macao") : _T(
"MO");
1722 return b_CntryLongStr ? _(
"Maldives") : _T(
"MV");
1724 return b_CntryLongStr ? _(
"Mongolia") : _T(
"MN");
1726 return b_CntryLongStr ? _(
"Nepal") : _T(
"NP");
1728 return b_CntryLongStr ? _(
"Oman") : _T(
"OM");
1730 return b_CntryLongStr ? _(
"Pakistan") : _T(
"PK");
1732 return b_CntryLongStr ? _(
"Qatar") : _T(
"QA");
1734 return b_CntryLongStr ? _(
"Syrian Arab Republic") : _T(
"SY");
1737 return b_CntryLongStr ? _(
"United Arab Emirates") : _T(
"AE");
1739 return b_CntryLongStr ? _(
"Tajikistan") : _T(
"TJ");
1742 return b_CntryLongStr ? _(
"Yemen") : _T(
"YE");
1744 return b_CntryLongStr ? _(
"Hong Kong") : _T(
"HK");
1746 return b_CntryLongStr ? _(
"Bosnia and Herzegovina") : _T(
"BA");
1748 return b_CntryLongStr ? _(
"Adelie Land") : _T(
"TF");
1750 return b_CntryLongStr ? _(
"Australia") : _T(
"AU");
1752 return b_CntryLongStr ? _(
"Myanmar") : _T(
"MM");
1754 return b_CntryLongStr ? _(
"Brunei Darussalam") : _T(
"BN");
1756 return b_CntryLongStr ? _(
"Micronesia") : _T(
"FM");
1758 return b_CntryLongStr ? _(
"Palau") : _T(
"PW");
1760 return b_CntryLongStr ? _(
"New Zealand") : _T(
"NZ");
1763 return b_CntryLongStr ? _(
"Cambodia") : _T(
"KH");
1765 return b_CntryLongStr ? _(
"Christmas Island") : _T(
"CX");
1767 return b_CntryLongStr ? _(
"Cook Islands") : _T(
"CK");
1769 return b_CntryLongStr ? _(
"Fiji") : _T(
"FJ");
1771 return b_CntryLongStr ? _(
"Cocos (Keeling) Islands") : _T(
"CC");
1773 return b_CntryLongStr ? _(
"Indonesia") : _T(
"ID");
1775 return b_CntryLongStr ? _(
"Kiribati") : _T(
"KI");
1777 return b_CntryLongStr ? _(
"Lao People's Dem. Rep.") : _T(
"LA");
1779 return b_CntryLongStr ? _(
"Malaysia") : _T(
"MY");
1781 return b_CntryLongStr ? _(
"Northern Mariana Islands") : _T(
"MP");
1783 return b_CntryLongStr ? _(
"Marshall Islands") : _T(
"MH");
1785 return b_CntryLongStr ? _(
"New Caledonia") : _T(
"NC");
1787 return b_CntryLongStr ? _(
"Niue") : _T(
"NU");
1789 return b_CntryLongStr ? _(
"Nauru") : _T(
"NR");
1791 return b_CntryLongStr ? _(
"French Polynesia") : _T(
"PF");
1793 return b_CntryLongStr ? _(
"Philippines") : _T(
"PH");
1795 return b_CntryLongStr ? _(
"East Timor") : _T(
"TL");
1797 return b_CntryLongStr ? _(
"Papua New Guinea") : _T(
"PG");
1799 return b_CntryLongStr ? _(
"Pitcairn Island") : _T(
"PN");
1801 return b_CntryLongStr ? _(
"Solomon Islands") : _T(
"SB");
1803 return b_CntryLongStr ? _(
"American Samoa") : _T(
"AS");
1805 return b_CntryLongStr ? _(
"Samoa") : _T(
"WS");
1810 return b_CntryLongStr ? _(
"Singapore") : _T(
"SG");
1812 return b_CntryLongStr ? _(
"Thailand") : _T(
"TH");
1814 return b_CntryLongStr ? _(
"Tonga") : _T(
"TO");
1816 return b_CntryLongStr ? _(
"Tuvalu") : _T(
"TV");
1818 return b_CntryLongStr ? _(
"Viet Nam") : _T(
"VN");
1821 return b_CntryLongStr ? _(
"Vanuatu") : _T(
"VU");
1823 return b_CntryLongStr ? _(
"Wallis and Futuna Islands") : _T(
"WF");
1825 return b_CntryLongStr ? _(
"South Africa") : _T(
"ZA");
1827 return b_CntryLongStr ? _(
"Angola") : _T(
"AO");
1829 return b_CntryLongStr ? _(
"Algeria") : _T(
"DZ");
1831 return b_CntryLongStr ? _(
"Saint Paul") : _T(
"TF");
1833 return b_CntryLongStr ? _(
"Ascension Island") : _T(
"SH");
1835 return b_CntryLongStr ? _(
"Burundi") : _T(
"BI");
1837 return b_CntryLongStr ? _(
"Benin") : _T(
"BJ");
1839 return b_CntryLongStr ? _(
"Botswana") : _T(
"BW");
1841 return b_CntryLongStr ? _(
"Central African Republic") : _T(
"CF");
1843 return b_CntryLongStr ? _(
"Cameroon") : _T(
"CM");
1845 return b_CntryLongStr ? _(
"Congo") : _T(
"CD");
1847 return b_CntryLongStr ? _(
"Comoros") : _T(
"KM");
1849 return b_CntryLongStr ? _(
"Capo Verde") : _T(
"CV");
1851 return b_CntryLongStr ? _(
"Crozet Archipelago") : _T(
"TF");
1853 return b_CntryLongStr ? _(
"Ivory Coast") : _T(
"CI");
1855 return b_CntryLongStr ? _(
"Comoros (Union of the)") : _T(
"KM");
1857 return b_CntryLongStr ? _(
"Djibouti") : _T(
"DJ");
1859 return b_CntryLongStr ? _(
"Egypt") : _T(
"EG");
1861 return b_CntryLongStr ? _(
"Ethiopia") : _T(
"ET");
1863 return b_CntryLongStr ? _(
"Eritrea") : _T(
"ER");
1865 return b_CntryLongStr ? _(
"Gabonese Republic") : _T(
"GA");
1867 return b_CntryLongStr ? _(
"Ghana") : _T(
"GH");
1869 return b_CntryLongStr ? _(
"Gambia") : _T(
"GM");
1871 return b_CntryLongStr ? _(
"Guinea-Bissau") : _T(
"GW");
1873 return b_CntryLongStr ? _(
"Equatorial Guinea") : _T(
"GQ");
1875 return b_CntryLongStr ? _(
"Guinea") : _T(
"GN");
1877 return b_CntryLongStr ? _(
"Burkina Faso") : _T(
"BF");
1879 return b_CntryLongStr ? _(
"Kenya") : _T(
"KE");
1881 return b_CntryLongStr ? _(
"Kerguelen Islands") : _T(
"TF");
1884 return b_CntryLongStr ? _(
"Liberia") : _T(
"LR");
1886 return b_CntryLongStr ? _(
"South Sudan (Republic of)") : _T(
"SS");
1888 return b_CntryLongStr ? _(
"Libya") : _T(
"LY");
1890 return b_CntryLongStr ? _(
"Lesotho") : _T(
"LS");
1892 return b_CntryLongStr ? _(
"Mauritius") : _T(
"MU");
1894 return b_CntryLongStr ? _(
"Madagascar") : _T(
"MG");
1896 return b_CntryLongStr ? _(
"Mali") : _T(
"ML");
1898 return b_CntryLongStr ? _(
"Mozambique") : _T(
"MZ");
1900 return b_CntryLongStr ? _(
"Mauritania") : _T(
"MR");
1902 return b_CntryLongStr ? _(
"Malawi") : _T(
"MW");
1904 return b_CntryLongStr ? _(
"Niger") : _T(
"NE");
1906 return b_CntryLongStr ? _(
"Nigeria") : _T(
"NG");
1908 return b_CntryLongStr ? _(
"Namibia") : _T(
"NA");
1910 return b_CntryLongStr ? _(
"Reunion") : _T(
"RE");
1912 return b_CntryLongStr ? _(
"Rwanda") : _T(
"RW");
1914 return b_CntryLongStr ? _(
"Sudan") : _T(
"SD");
1916 return b_CntryLongStr ? _(
"Senegal") : _T(
"SN");
1918 return b_CntryLongStr ? _(
"Seychelles") : _T(
"SC");
1920 return b_CntryLongStr ? _(
"Saint Helena") : _T(
"SH");
1922 return b_CntryLongStr ? _(
"Somalia") : _T(
"SO");
1924 return b_CntryLongStr ? _(
"Sierra Leone") : _T(
"SL");
1926 return b_CntryLongStr ? _(
"Sao Tome and Principe") : _T(
"ST");
1928 return b_CntryLongStr ? _(
"Eswatini") : _T(
"SZ");
1930 return b_CntryLongStr ? _(
"Chad") : _T(
"TD");
1932 return b_CntryLongStr ? _(
"Togolese Republic") : _T(
"TG");
1934 return b_CntryLongStr ? _(
"Tunisia") : _T(
"TN");
1936 return b_CntryLongStr ? _(
"Tanzania") : _T(
"TZ");
1938 return b_CntryLongStr ? _(
"Uganda") : _T(
"UG");
1940 return b_CntryLongStr ? _(
"Dem Rep.of the Congo") : _T(
"CD");
1942 return b_CntryLongStr ? _(
"Tanzania") : _T(
"TZ");
1944 return b_CntryLongStr ? _(
"Zambia") : _T(
"ZM");
1946 return b_CntryLongStr ? _(
"Zimbabwe") : _T(
"ZW");
1948 return b_CntryLongStr ? _(
"Argentine Republic") : _T(
"AR");
1950 return b_CntryLongStr ? _(
"Brazil") : _T(
"BR");
1952 return b_CntryLongStr ? _(
"Bolivia") : _T(
"BO");
1954 return b_CntryLongStr ? _(
"Chile") : _T(
"CL");
1956 return b_CntryLongStr ? _(
"Colombia") : _T(
"CO");
1958 return b_CntryLongStr ? _(
"Ecuador") : _T(
"EC");
1960 return b_CntryLongStr ? _(
"Falkland Islands") : _T(
"FK");
1962 return b_CntryLongStr ? _(
"France - Guiana") : _T(
"GY");
1964 return b_CntryLongStr ? _(
"Guyana") : _T(
"GY");
1966 return b_CntryLongStr ? _(
"Paraguay") : _T(
"PY");
1968 return b_CntryLongStr ? _(
"Peru") : _T(
"PE");
1970 return b_CntryLongStr ? _(
"Suriname") : _T(
"SR");
1972 return b_CntryLongStr ? _(
"Uruguay") : _T(
"UY");
1974 return b_CntryLongStr ? _(
"Venezuela") : _T(
"VE");
1977 return wxEmptyString;
1980 return wxEmptyString;
1984wxString ais_get_type(
int index) {
1985 static const wxString ais_type[] = {
1986 _(
"Fishing Vessel"),
1988 _(
"Towing Vessel, Long"),
1990 _(
"Diving Ops Vessel"),
1991 _(
"Military Vessel"),
1992 _(
"Sailing Vessel"),
1993 _(
"Pleasure craft"),
1994 _(
"High Speed Craft"),
1996 _(
"Search and Rescue Vessel"),
1999 _(
"Pollution Control Vessel"),
2000 _(
"Law Enforcement Vessel"),
2001 _(
"Medical Transport"),
2002 _(
"Passenger Ship"),
2007 _(
"Reference Point"),
2009 _(
"Fixed Structure"),
2012 _(
"Light w/Sectors"),
2013 _(
"Leading Light Front"),
2014 _(
"Leading Light Rear"),
2015 _(
"Cardinal N Beacon"),
2016 _(
"Cardinal E Beacon"),
2017 _(
"Cardinal S Beacon"),
2018 _(
"Cardinal W Beacon"),
2019 _(
"Beacon, Port Hand"),
2020 _(
"Beacon, Starboard Hand"),
2021 _(
"Beacon, Preferred Channel Port Hand"),
2022 _(
"Beacon, Preferred Channel Starboard Hand"),
2023 _(
"Beacon, Isolated Danger"),
2024 _(
"Beacon, Safe Water"),
2025 _(
"Beacon, Special Mark"),
2026 _(
"Cardinal Mark N"),
2027 _(
"Cardinal Mark E"),
2028 _(
"Cardinal Mark S"),
2029 _(
"Cardinal Mark W"),
2030 _(
"Port Hand Mark"),
2031 _(
"Starboard Hand Mark"),
2032 _(
"Preferred Channel Port Hand"),
2033 _(
"Preferred Channel Starboard Hand"),
2034 _(
"Isolated Danger"),
2037 _(
"Light Vessel/Rig"),
2039 _(
"Position Report"),
2041 _(
"ARPA radar target"),
2042 _(
"APRS Position Report"),
2043 _(
"Buoy or similar")
2046 return ais_type[index];
2049wxString ais_get_short_type(
int index) {
2050 static const wxString short_ais_type[] = {
2109 _(
"Buoy or similar")
2111 return short_ais_type[index];
Global state for AIS decoder.