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);
533 if (Class == AIS_CLASS_B && MMSIstr.StartsWith("8")) {
534 html <<
"<td align=right>" << _(
"Handheld");
536 html << rowEnd << _T(
"</font></table></td></tr>");
539 if ((Class != AIS_BASE) && (Class != AIS_CLASS_B) && (Class != AIS_SART) &&
540 (Class != AIS_METEO)) {
542 if ((NavStatus <= 21) && (NavStatus >= 0))
543 navStatStr = wxGetTranslation(ais_get_status(NavStatus));
544 }
else if (Class == AIS_SART) {
545 if (NavStatus == RESERVED_14)
546 navStatStr = _(
"Active");
547 else if (NavStatus == UNDEFINED)
548 navStatStr = _(
"Testing");
551 wxString sart_sub_type;
552 if (Class == AIS_SART) {
553 int mmsi_start = MMSI / 1000000;
554 switch (mmsi_start) {
559 sart_sub_type = _T(
"MOB");
562 sart_sub_type = _T(
"EPIRB");
565 sart_sub_type = _(
"Unknown");
570 wxString AISTypeStr, UNTypeStr, sizeString;
571 if ((Class != AIS_BASE) && (Class != AIS_SART) && (Class != AIS_DSC) &&
572 (Class != AIS_METEO)) {
574 AISTypeStr = wxGetTranslation(Get_vessel_type_string());
576 if (b_isEuroInland && UN_shiptype) {
577 auto it = s_ERI_hash.find(UN_shiptype);
579 if (it == s_ERI_hash.end())
580 type = _(
"Undefined");
584 UNTypeStr = wxGetTranslation(type);
587 if (b_SarAircraftPosnReport) {
593 if (Class == AIS_SART) {
594 if (MSG_14_text.Len()) {
595 html << rowStart << _(
"Safety Broadcast Message") << rowEnd << rowStartH
596 << _T(
"<b>") << MSG_14_text << rowEnd;
602 if (NavStatus != ATON_VIRTUAL && Class != AIS_ARPA && Class != AIS_APRS &&
604 if ((Class == AIS_CLASS_B) || (Class == AIS_ATON)) {
606 wxString::Format(_T(
"%dm x %dm"), (DimA + DimB), (DimC + DimD));
607 }
else if (!b_SarAircraftPosnReport) {
608 if ((DimA + DimB + DimC + DimD) == 0) {
609 if (b_isEuroInland) {
610 if (Euro_Length == 0.0) {
611 if (Euro_Draft > 0.01) {
612 sizeString << wxString::Format(_T(
"---m x ---m x %4.1fm"),
615 sizeString << _T(
"---m x ---m x ---m");
618 if (Euro_Draft > 0.01) {
619 sizeString << wxString::Format(_T(
"%5.1fm x %4.1fm x %4.1fm"),
620 Euro_Length, Euro_Beam,
623 sizeString << wxString::Format(_T(
"%5.1fm x %4.1fm x ---m\n\n"),
624 Euro_Length, Euro_Beam);
629 sizeString << wxString::Format(_T(
"---m x ---m x %4.1fm"), Draft);
631 sizeString << _T(
"---m x ---m x ---m");
634 }
else if (Draft < 0.01) {
635 sizeString << wxString::Format(_T(
"%dm x %dm x ---m"), (DimA + DimB),
638 sizeString << wxString::Format(_T(
"%dm x %dm x %4.1fm"),
639 (DimA + DimB), (DimC + DimD), Draft);
645 if (Class == AIS_SART) {
646 html << _T(
"<tr><td colspan=2>")
647 << _T(
"<b>") << AISTypeStr;
648 if (sart_sub_type.Length()) html << _T(
" (") << sart_sub_type << _T(
"), ");
650 html << rowEnd << _T(
"<tr><td colspan=2>")
651 << _T(
"<b>") << sizeString << rowEnd;
654 else if (Class == AIS_ATON) {
655 html << _T(
"<tr><td colspan=2>")
656 << _T(
"<b>") << navStatStr;
657 html << rowEnd << _T(
"<tr><td colspan=2>")
658 << _T(
"<b>") << sizeString << rowEnd;
659 }
else if (Class == AIS_DSC && (ShipType == 12 || ShipType == 16)) {
660 if (ShipType == 16) {
661 html << _T(
"<tr><td colspan=2>")
662 << _T(
"<b>") << _(
"Distress relay");
663 if (m_dscTXmmsi > 2000000) {
664 wxString mmsirelay = wxString::Format(_T(
" %09d"), abs(m_dscTXmmsi));
665 html << _T(
" ") << _(
"by:") << mmsirelay;
667 html << _T(
"<b>") << sizeString << rowEnd;
669 html << _T(
"<tr><td colspan=2>") << _(
"Nature of distress: ") << rowEnd
670 << _T(
"<tr><td colspan=2>");
671 if (m_dscNature < 13) {
672 html << _T(
"<tr><td colspan=2>")
673 << _T(
"<b>") << GetNatureofDistress(m_dscNature) << _T(
"<b>")
674 << sizeString << rowEnd << _T(
"<tr><td colspan=2>");
676 }
else if ((Class != AIS_BASE) && (Class != AIS_DSC)) {
677 html << _T(
"<tr><td colspan=2>")
678 << _T(
"<b>") << AISTypeStr;
679 if (navStatStr.Length()) html << _T(
", ") << navStatStr;
680 if (UNTypeStr.Length()) html << _T(
" (UN Type ") << UNTypeStr << _T(
")");
681 html << rowEnd << _T(
"<tr><td colspan=2>")
682 << _T(
"<b>") << sizeString << rowEnd;
685 if (b_positionOnceValid) {
687 if (b_positionDoubtful) posTypeStr << _(
" (Last Known)");
690 int target_age = now.GetTicks() - PositionReportTicks;
695 html << vertSpacer << rowStart << _(
"Position") << posTypeStr
696 << _T(
"</font></td><td align=right><font size=-2>") << _(
"Report Age")
697 << _T(
"</font></td></tr>")
699 << rowStartH << _T(
"<b>") << toSDMM(1, Lat)
700 << _T(
"</b></td><td align=right><b>") << FormatTimeAdaptive(target_age)
701 << rowEnd << rowStartH << _T(
"<b>") << toSDMM(2, Lon);
702 if (Class != AIS_METEO)
706 wxString::Format(
" %02d:%02d", met_data.hour, met_data.minute);
707 html <<
" </td><td align=right></b></font><font size=-3>"
708 << _(
"Issued (UTC)") <<
"</font><font size=-1><b>" << meteoTime
709 <<
"</font>" << rowEnd;
713 wxString courseStr, sogStr, hdgStr, rotStr, rngStr, brgStr, destStr, etaStr;
715 if (Class == AIS_GPSG_BUDDY) {
716 long month, year, day;
717 m_date_string.Mid(0, 2).ToLong(&day);
718 m_date_string.Mid(2, 2).ToLong(&month);
719 m_date_string.Mid(4, 2).ToLong(&year);
722 date.SetMonth((wxDateTime::Month)(month - 1));
723 date.SetYear(year + 2000);
725 wxString f_date = date.FormatISODate();
727 html << vertSpacer << rowStart << _(
"Report as of") << rowEnd << rowStartH
728 << _T(
"<b>") << f_date + _T(
"</b> at <b>")
729 << wxString::Format(_T(
"%d:%d UTC "), m_utc_hour, m_utc_min) << rowEnd;
731 if (Class == AIS_CLASS_A && !b_SarAircraftPosnReport) {
732 html << vertSpacer << rowStart << _(
"Destination")
733 << _T(
"</font></td><td align=right><font size=-2>") << _(
"ETA (UTC)")
734 << _T(
"</font></td></tr>\n") << rowStartH << _T(
"<b>");
735 wxString dest = trimAISField(Destination);
737 html << html_escape(dest);
740 html << _T(
"</b></td><td nowrap align=right><b>");
742 if ((ETA_Mo) && (ETA_Hr < 24)) {
744 if (now.GetMonth() > (ETA_Mo - 1)) yearOffset = 1;
745 wxDateTime eta(ETA_Day, wxDateTime::Month(ETA_Mo - 1),
746 now.GetYear() + yearOffset, ETA_Hr, ETA_Min);
747 html << eta.Format(_T(
"%b %d %H:%M"));
753 if (Class == AIS_CLASS_A || Class == AIS_CLASS_B || Class == AIS_ARPA ||
754 Class == AIS_APRS || Class == AIS_SART || Class == AIS_BUOY) {
755 int crs = wxRound(COG);
757 wxString magString, trueString;
759 magString << wxString::Format(
760 wxString(
"%03d%c(M)"),
static_cast<int>(m_callbacks.get_mag(COG)),
763 trueString << wxString::Format(wxString(
"%03d%c "), (
int)crs, 0x00B0);
765 courseStr << trueString << magString;
766 }
else if (COG == 360.0)
767 courseStr = _T(
"---");
769 courseStr = _T(
"0°");
771 double speed_show = toUsrSpeed(SOG);
773 if ((SOG <= 102.2) || b_SarAircraftPosnReport) {
774 if (speed_show < 10.0)
776 wxString::Format(_T(
"%.2f "), speed_show) + getUsrSpeedUnit();
777 else if (speed_show < 100.0)
779 wxString::Format(_T(
"%.1f "), speed_show) + getUsrSpeedUnit();
782 wxString::Format(_T(
"%.0f "), speed_show) + getUsrSpeedUnit();
790 hdgStr = wxString::Format(_T(
"%03d°"), (
int)HDG);
794 if (ROTAIS != -128) {
796 rotStr << _T(
"> 5°/30s ") << _(
"Right");
797 else if (ROTAIS == -127)
798 rotStr << _T(
"> 5°/30s ") << _(
"Left");
801 rotStr << wxString::Format(_T(
"%3d°/Min "), ROTIND)
804 rotStr << wxString::Format(_T(
"%3d°/Min "), -ROTIND)
809 }
else if (!b_SarAircraftPosnReport)
814 if (b_positionOnceValid && bGPSValid && (Range_NM >= 0.))
815 rngStr = FormatDistanceAdaptive(Range_NM);
819 int brg = (int)wxRound(Brg);
820 if (Brg > 359.5) brg = 0;
821 if (b_positionOnceValid && bGPSValid && (Brg >= 0.) && (Range_NM > 0.) &&
823 wxString magString, trueString;
825 magString << wxString::Format(wxString(
"%03d%c(M)"),
826 static_cast<int>(m_callbacks.get_mag(Brg)),
829 trueString << wxString::Format(wxString(
"%03d%c "), (
int)Brg, 0x00B0);
831 brgStr << trueString << magString;
835 wxString turnRateHdr;
836 if ((Class != AIS_ATON) && (Class != AIS_BASE) && (Class != AIS_DSC) &&
837 (Class != AIS_METEO)) {
839 << _T(
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
841 << rowStart << _("Speed")
842 << _T("</font></td><td> </td><td><font size=-2>") << _("Course")
843 << _T("</font></td><td> </td><td align=right><font size=-2>");
844 if (!b_SarAircraftPosnReport) html << _("Heading");
846 html << _T("</font></td></tr>") << rowStartH << _T("<b>") << sogStr
847 << _T("</b></td><td> </td><td><b>") << courseStr
848 << _T("</b></td><td> </td><td align=right><b>");
849 if (!b_SarAircraftPosnReport) html << hdgStr;
850 html << rowEnd << _T("</table></td></tr>") << vertSpacer;
852 if (!b_SarAircraftPosnReport) turnRateHdr = _("Turn Rate");
854 if (Class != AIS_METEO) {
855 html << _T(
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
857 << rowStart << _("Range")
858 << _T("</font></td><td> </td><td><font size=-2>") << _("Bearing")
859 << _T("</font></td><td> </td><td align=right><font size=-2>")
860 << turnRateHdr << _T("</font></td></tr>") << rowStartH << _T("<b>")
861 << rngStr << _T("</b></td><td> </td><td><b>") << brgStr
862 << _T("</b></td><td> </td><td align=right><b>");
863 if (!b_SarAircraftPosnReport) html << rotStr;
864 html << rowEnd << _T("</table></td></tr>") << vertSpacer;
867 if (bCPA_Valid && Class != AIS_METEO) {
869 tcpaStr << _T(
"</b> ") << _(
"in ") << _T(
"</td><td align=right><b>")
870 << FormatTimeAdaptive((
int)(TCPA * 60.));
872 html << rowStart << _T(
"<font size=-2>") << _(
"CPA")
873 << _T(
"</font>") << rowEnd << rowStartH << _T(
"<b>")
874 << FormatDistanceAdaptive(CPA) << tcpaStr << rowEnd;
877 if (Class != AIS_BASE && Class != AIS_METEO) {
878 if (blue_paddle == 1) {
879 html << rowStart << _(
"Inland Blue Flag") << rowEnd << rowStartH
880 << _T(
"<b>") << _(
"Clear") << rowEnd;
881 }
else if (blue_paddle == 2) {
882 html << rowStart << _(
"Inland Blue Flag") << rowEnd << rowStartH
883 << _T(
"<b>") << _(
"Set") << rowEnd;
887 if (b_SarAircraftPosnReport) {
889 if (altitude != 4095)
890 altStr.Printf(_T(
"%4d m"), altitude);
892 altStr = _(
"Unknown");
894 html << rowStart << _(
"Altitude")
895 << _T(
"</font></td><td> </td><td><font size=-0>") << rowStartH
896 << _T(
"<b>") << altStr << _T(
"</b></td><td> </td><td><b>")
897 << rowEnd << _T(
"</table></td></tr>") << vertSpacer;
900 if (Class == AIS_METEO) {
901 if (met_data.wind_kn < 122) {
902 double userwindspeed = toUsrWindSpeed(met_data.wind_kn);
904 wxString::Format(
"%0.1f %s %d%c", userwindspeed,
905 getUsrWindSpeedUnit(), met_data.wind_dir, 0x00B0);
907 double userwindgustspeed = toUsrWindSpeed(met_data.wind_gust_kn);
908 wxString wspeedGust = wxString::Format(
"%.0f %s %d%c", userwindgustspeed,
909 getUsrWindSpeedUnit(),
910 met_data.wind_gust_dir, 0x00B0);
911 if (met_data.wind_gust_kn >= 126) wspeedGust = wxEmptyString;
913 html << vertSpacer << rowStart << _(
"Wind speed")
914 << _T(
"</font></td><td align=right><font size=-2>") << _(
"Wind gust")
915 << _T(
"</font></td></tr>") << rowStartH << _T(
"<b>") << wspeed
916 << _T(
"</b></td><td align=right><b>") << wspeedGust << rowEnd;
919 if (met_data.water_lev_dev < 30. || met_data.water_level > -32. ||
920 met_data.current < 25.5) {
921 wxString wlevel_txt = _(
"Water level deviation");
923 if (met_data.water_lev_dev < 30.) {
924 double userlevel = toUsrDepth(met_data.water_lev_dev);
926 wxString::Format(
"%.1f %s %s", userlevel, getUsrDepthUnit(),
927 ais_meteo_get_trend(met_data.water_lev_trend));
928 if (met_data.vertical_ref < 14) {
929 wlevel_txt = _(
"Water level dev. Ref: ");
930 wlevel_txt << aisMeteoWaterLevelRef(met_data.vertical_ref);
933 if (met_data.water_lev_dev >= 30.) wlevel = wxEmptyString;
935 }
else if (met_data.water_level > -32.) {
936 double userlevel = toUsrDepth(met_data.water_level);
938 wxString::Format(
"%.1f %s %s", userlevel, getUsrDepthUnit(),
939 ais_meteo_get_trend(met_data.water_lev_trend));
940 wlevel_txt = _(
"Water level");
941 if (met_data.water_level <= -32.) wlevel = wxEmptyString;
944 wxString current = wxString::Format(
"%.1f kts %d%c", met_data.current,
945 met_data.curr_dir, 0x00B0);
946 if (met_data.current >= 25.5) current = wxEmptyString;
948 html << vertSpacer << rowStart << wlevel_txt
949 << _T(
"</font></td><td align=right><font size=-2>")
950 << _(
"Surface current ") << _T(
"</font></td></tr>") << rowStartH
951 << _T(
"<b>") << wlevel << _T(
"</b></td><td align=right><b>")
952 << current << rowEnd;
955 if (met_data.wave_height < 24.6 || met_data.swell_height < 24.6) {
956 double userwave = toUsrDepth(met_data.wave_height);
957 wxString wave = wxString::Format(
"%.1f %s %d%c %d %s ", userwave,
958 getUsrDepthUnit(), met_data.wave_dir,
959 0x00B0, met_data.wave_period, _(
"s"));
960 if (met_data.wave_height >= 24.6) wave = wxEmptyString;
962 double userswell = toUsrDepth(met_data.swell_height);
963 wxString swell = wxString::Format(
"%.1f %s %d%c %d %s", userswell,
964 getUsrDepthUnit(), met_data.swell_dir,
965 0x00B0, met_data.swell_per, _(
"s"));
966 if (met_data.swell_height >= 25.) swell = wxEmptyString;
968 html << vertSpacer << rowStart << _(
"Waves height & period")
969 << _T(
"</font></td><td align=right><font size=-2>")
970 << _(
"Swell height & period ") << _T(
"</font></td></tr>")
971 << rowStartH << _T(
"<b>") << wave
972 << _T(
"</b></td><td align=right><b>") << swell << rowEnd;
975 if (met_data.air_temp != -102.4 || met_data.airpress < 1310) {
976 double usertemp = toUsrTemp(met_data.air_temp);
978 wxString::Format(
"%.1f%c%s", usertemp, 0x00B0, getUsrTempUnit());
979 if (met_data.air_temp == -102.4) airtemp = wxEmptyString;
982 wxString::Format(
"%d hPa %s", met_data.airpress,
983 ais_meteo_get_trend(met_data.airpress_tend));
984 const int ap = met_data.airpress;
985 if (ap < 800 || ap >= 1310) airpress = wxEmptyString;
987 html << vertSpacer << rowStart << _(
"Air Temperatur")
988 << _T(
"</font></td><td align=right><font size=-2>")
989 << _(
"Air pressure") << _T(
"</font></td></tr>") << rowStartH
990 << _T(
"<b>") << airtemp << _T(
"</b></td><td align=right><b>")
991 << airpress << rowEnd;
994 if (met_data.rel_humid < 101 || met_data.dew_point < 50.) {
995 wxString humid = wxString::Format(
"%d%c", met_data.rel_humid,
'%');
996 if (met_data.rel_humid >= 101) humid = wxEmptyString;
998 double usertempDew = toUsrTemp(met_data.dew_point);
1000 wxString::Format(
"%.1f%c%s", usertempDew, 0x00B0, getUsrTempUnit());
1001 if (met_data.dew_point >= 50.) dewpoint = wxEmptyString;
1003 html << vertSpacer << rowStart << _(
"Relative Humidity")
1004 << _T(
"</font></td><td align=right><font size=-2>")
1005 << _(
"Dew Point ") << _T(
"</font></td></tr>") << rowStartH
1006 << _T(
"<b>") << humid << _T(
"</b></td><td align=right><b>")
1007 << dewpoint << rowEnd;
1010 if (met_data.water_temp < 50.1 || met_data.seastate < 13) {
1011 double usertemp = toUsrTemp(met_data.water_temp);
1012 wxString watertemp =
1013 wxString::Format(
"%.1f%c%s", usertemp, 0x00B0, getUsrTempUnit());
1014 if (met_data.water_temp >= 50.1) watertemp = wxEmptyString;
1016 wxString seastate = wxString::Format(
"%d Bf ", met_data.seastate);
1017 if (met_data.seastate == 13) seastate = wxEmptyString;
1019 html << vertSpacer << rowStart << _(
"Water Temperatur")
1020 << _T(
"</font></td><td align=right><font size=-2>") << _(
"Sea state")
1021 << _T(
"</font></td></tr>") << rowStartH << _T(
"<b>") << watertemp
1022 << _T(
"</b></td><td align=right><b>") << seastate << rowEnd;
1025 if (met_data.precipitation < 7 || met_data.hor_vis < 12.7) {
1027 wxString::Format(
"%s", aisMeteoPrecipType(met_data.precipitation));
1028 if (met_data.precipitation >= 6) precip = wxEmptyString;
1030 double userVisDist = toUsrDistance(met_data.hor_vis);
1032 wxString::Format(
"%s%.1f %s", (met_data.hor_vis_GT ?
">" :
""),
1033 userVisDist, getUsrDistanceUnit());
1034 if (met_data.hor_vis >= 12.7) horVis = wxEmptyString;
1035 html << vertSpacer << rowStart << _(
"Precipitation")
1036 << _T(
"</font></td><td align=right><font size=-2>")
1037 << _(
"Horizontal Visibility") << _T(
"</font></td></tr>") << rowStartH
1038 << _T(
"<b>") << precip << _T(
"</b></td><td align=right><b>")
1039 << horVis << rowEnd;
1042 if (met_data.salinity < 50. || met_data.ice < 2) {
1043 wxString sal = wxString::Format(
"%.1f%c", met_data.salinity, 0x2030);
1044 if (met_data.salinity >= 50.) sal = wxEmptyString;
1046 wxString icestatus = _(
"No");
1047 if (met_data.ice == 1) icestatus = _(
"Yes");
1048 if (met_data.ice >= 2) icestatus = wxEmptyString;
1050 html << vertSpacer << rowStart << _(
"Sea salinity")
1051 << _T(
"</font></td><td align=right><font size=-2>")
1052 << _(
"Ice status") << _T(
"</font></td></tr>") << rowStartH
1053 << _T(
"<b>") << sal << _T(
"</b></td><td align=right><b>")
1054 << icestatus << rowEnd;
1057 html << _T(
"</table>");
1061wxString AisTargetData::GetRolloverString(
void) {
1065 result.Append(_T(
"\""));
1066 result.Append(GetFullName());
1067 result.Append(_T(
"\" "));
1069 if (Class != AIS_GPSG_BUDDY) {
1070 t.Printf(_T(
"%09d"), abs(MMSI));
1072 result.Append(_T(
" "));
1073 result.Append(GetCountryCode(
false));
1075 t = trimAISField(CallSign);
1077 result.Append(_T(
" ("));
1079 result.Append(_T(
")"));
1081 if (g_bAISRolloverShowClass || (Class == AIS_SART)) {
1082 if (result.Len()) result.Append(_T(
"\n"));
1083 result.Append(_T(
"["));
1084 if (Class == AIS_ATON) {
1085 result.Append(wxGetTranslation(Get_class_string(
true)));
1086 result.Append(_T(
": "));
1087 result.Append(wxGetTranslation(Get_vessel_type_string(
false)));
1088 }
else if (b_SarAircraftPosnReport) {
1089 int airtype = (MMSI % 1000) / 100;
1090 result.Append(airtype == 5 ? _(
"SAR Helicopter") : _(
"SAR Aircraft"));
1092 result.Append(wxGetTranslation(Get_class_string(
false)));
1094 result.Append(_T(
"] "));
1095 if ((Class != AIS_ATON) && (Class != AIS_BASE)) {
1096 if (Class == AIS_SART) {
1097 int mmsi_start = MMSI / 1000000;
1098 switch (mmsi_start) {
1102 result += _T(
"MOB");
1105 result += _T(
"EPIRB");
1108 result += _(
"Unknown");
1113 if (Class != AIS_SART && Class != AIS_METEO) {
1114 if (!b_SarAircraftPosnReport)
1115 result.Append(wxGetTranslation(Get_vessel_type_string(
false)));
1118 if ((Class != AIS_CLASS_B) && (Class != AIS_SART) && Class != AIS_DSC &&
1119 Class != AIS_METEO && !b_SarAircraftPosnReport) {
1120 if ((NavStatus <= 15) && (NavStatus >= 0)) {
1121 result.Append(_T(
" ("));
1122 result.Append(wxGetTranslation(ais_get_status(NavStatus)));
1123 result.Append(_T(
")"));
1125 }
else if (Class == AIS_SART) {
1126 result.Append(_T(
" ("));
1127 if (NavStatus == RESERVED_14)
1128 result.Append(_(
"Active"));
1129 else if (NavStatus == UNDEFINED)
1130 result.Append(_(
"Testing"));
1131 result.Append(_T(
")"));
1132 }
else if (Class == AIS_DSC) {
1133 result.Append(_T(
" ("));
1134 result.Append(GetNatureofDistress(m_dscNature));
1135 result.Append(_T(
")"));
1140 if (g_bAISRolloverShowCOG && ((SOG <= 102.2) || b_SarAircraftPosnReport) &&
1141 !((Class == AIS_ATON) || (Class == AIS_BASE) || (Class == AIS_METEO))) {
1142 if (result.Len()) result << _T(
"\n");
1144 double speed_show = toUsrSpeed(SOG);
1145 if (speed_show < 10.0)
1146 result << wxString::Format(_T(
"SOG %.2f "), speed_show)
1147 << getUsrSpeedUnit() << _T(
" ");
1148 else if (speed_show < 100.0)
1149 result << wxString::Format(_T(
"SOG %.1f "), speed_show)
1150 << getUsrSpeedUnit() << _T(
" ");
1152 result << wxString::Format(_T(
"SOG %.0f "), speed_show)
1153 << getUsrSpeedUnit() << _T(
" ");
1155 int crs = wxRound(COG);
1156 if (b_positionOnceValid) {
1158 wxString magString, trueString;
1160 magString << wxString::Format(
1161 wxString(
"%03d%c(M) "),
1162 static_cast<int>(m_callbacks.get_mag(COG)), 0x00B0);
1164 trueString << wxString::Format(wxString(
"%03d%c "), (
int)crs, 0x00B0);
1166 result << trueString << magString;
1169 else if (COG == 360.0)
1170 result << _(
" COG Unavailable");
1171 else if (crs == 360)
1172 result << wxString(
" COG 000\u00B0");
1174 result << _(
" COG Unavailable");
1177 if (g_bAISRolloverShowCPA && bCPA_Valid && Class != AIS_METEO) {
1178 if (result.Len()) result << _T(
"\n");
1179 result << _(
"CPA") << _T(
" ") << FormatDistanceAdaptive(CPA) << _T(
" ")
1180 << _(
"in") << _T(
" ") << wxString::Format(_T(
"%.0f"), TCPA)
1181 << _T(
" ") << _(
"min");
1183 if (Class == AIS_METEO) {
1184 if (met_data.wind_kn < 122) {
1185 if (result.Len()) result <<
"\n";
1186 double userwindspeed = toUsrWindSpeed(met_data.wind_kn);
1187 result << _(
"Wind speed");
1188 result << wxString::Format(
": %0.1f %s", userwindspeed,
1189 getUsrWindSpeedUnit())
1190 << wxString::Format(
" %d%c ", met_data.wind_dir, 0x00B0);
1193 if (met_data.water_lev_dev < 30.) {
1194 if (result.Len()) result <<
"\n";
1195 result << _(
"Water level deviation");
1197 userdepth = toUsrDepth(met_data.water_lev_dev);
1198 result << wxString::Format(
": %.1f %s", userdepth, getUsrDepthUnit());
1200 }
else if (met_data.water_level > -32.) {
1201 if (result.Len()) result <<
"\n";
1202 result << _(
"Water level");
1204 userdepth = toUsrDepth(met_data.water_level);
1205 result << wxString::Format(
": %.1f %s", userdepth, getUsrDepthUnit());
1208 if (met_data.current < 25.) {
1209 if (result.Len()) result <<
"\n";
1210 result << _(
"Current");
1211 result << wxString::Format(
": %.1f ", met_data.current) << _(
"kts")
1212 << wxString::Format(
" %d%c ", met_data.curr_dir, 0x00B0);
1215 if (met_data.wave_height < 24.6) {
1216 if (result.Len()) result <<
"\n";
1217 double userwh = toUsrDepth(met_data.wave_height);
1218 result << _(
"Wave height")
1219 << wxString::Format(
": %.1f %s", userwh, getUsrDepthUnit())
1220 <<
" / " << met_data.wave_period <<
" " << _(
"s");
1223 if (met_data.water_temp < 50.) {
1224 if (result.Len()) result <<
"\n";
1225 double usertemp = toUsrTemp(met_data.water_temp);
1226 result << _(
"Water temp");
1227 result << wxString::Format(
": %.1f%c", usertemp, 0x00B0)
1228 << getUsrTempUnit();
1231 if (met_data.air_temp != -102.4) {
1232 if (result.Len()) result <<
"\n";
1233 double usertemp = toUsrTemp(met_data.air_temp);
1234 result << _(
"Air temp");
1235 result << wxString::Format(
": %.1f%c", usertemp, 0x00B0)
1236 << getUsrTempUnit() <<
" ";
1239 if (met_data.airpress > 799 && met_data.airpress < 1310) {
1240 if (met_data.air_temp == -102.4 && result.Len()) result <<
"\n";
1241 result << _(
"Air press");
1242 result << wxString::Format(
": %d hPa", met_data.airpress);
1245 if (met_data.hor_vis < 12.) {
1246 if (result.Len()) result <<
"\n";
1247 double userVisDist = toUsrDistance(met_data.hor_vis);
1249 wxString::Format(
": %s%.1f %s", (met_data.hor_vis_GT ?
">" :
""),
1250 userVisDist, getUsrDistanceUnit());
1251 result << _(
"Visibility") << horVis;
1257wxString AisTargetData::Get_vessel_type_string(
bool b_short) {
1259 if (Class == AIS_ATON) {
1313 if ((Class == AIS_CLASS_B) || (Class == AIS_CLASS_A)) {
1314 if ((ShipType >= 40) && (ShipType < 50)) i = 8;
1316 if ((ShipType >= 60) && (ShipType < 70)) i = 16;
1318 if ((ShipType >= 70) && (ShipType < 80)) i = 17;
1320 if ((ShipType >= 80) && (ShipType < 90)) i = 18;
1321 }
else if (Class == AIS_GPSG_BUDDY)
1323 else if (Class == AIS_ARPA)
1325 else if (Class == AIS_APRS)
1327 else if (Class == AIS_BUOY)
1329 else if (Class == AIS_DSC)
1330 i = (ShipType == 12 || ShipType == 16) ? 54 : 53;
1333 return ais_get_type(i);
1335 return ais_get_short_type(i);
1338wxString AisTargetData::Get_class_string(
bool b_short) {
1345 return b_short ? _(
"AtoN") : _(
"Aid to Navigation");
1347 return b_short ? _(
"Base") : _(
"Base Station");
1348 case AIS_GPSG_BUDDY:
1349 return b_short ? _(
"Buddy") : _(
"GPSGate Buddy");
1351 if (ShipType == 12 || (ShipType == 16 && m_dscNature < 13))
1352 return b_short ? _(
"DSC") : _(
"DSC Distress");
1354 return b_short ? _(
"DSC") : _(
"DSC Position Report");
1356 return b_short ? _(
"SART") : _(
"SART");
1358 return b_short ? _(
"ARPA") : _(
"ARPA");
1360 return b_short ? _(
"Buoy") : _(
"BUOY");
1362 return b_short ? _(
"APRS") : _(
"APRS Position Report");
1364 return b_short ? _(
"Meteo") : _(
"Meteorologic");
1367 return b_short ? _(
"Unk") : _(
"Unknown");
1371wxString AisTargetData::GetNatureofDistress(
int dscnature) {
1373 wxString dscDistressType[] = {_(
"Fire, explosion"),
1377 _(
"Listing, in danger of capsizing"),
1379 _(
"Disabled and adrift"),
1380 _(
"Undesignated distress"),
1381 _(
"Abandoning ship"),
1382 _(
"Piracy/armed robbery attack"),
1385 _(
"EPIRB emission")};
1386 if (dscnature >= 0 && dscnature < 13)
return dscDistressType[dscnature];
1388 return wxEmptyString;
1391void AisTargetData::Toggle_AIS_CPA(
void) {
1392 b_show_AIS_CPA = !b_show_AIS_CPA ? true :
false;
1395void AisTargetData::ToggleShowTrack(
void) {
1396 b_show_track = !b_show_track ? true :
false;
1399bool AisTargetData::IsValidMID(
int mid) {
1400 if (mid >= 201 && mid <= 775)
return true;
1406wxString AisTargetData::GetCountryCode(
bool b_CntryLongStr) {
1407 if (Class == AIS_BUOY)
return wxEmptyString;
1410 int tmpMmsi = met_data.original_mmsi ? met_data.original_mmsi : MMSI;
1412 int nMID = tmpMmsi / 1000000;
1413 if (!IsValidMID(nMID) || Class == AIS_ATON) {
1416 if (tmpMmsi < 1000 || 97 == tmpMmsi / 10000000)
return wxEmptyString;
1421 bool foundMID =
false;
1423 i = nMID > 900 ? 2 : 0;
1424 for (i; i < s_mmsi.length() - 3; i++) {
1425 nMID = wxAtoi(s_mmsi.Mid(i, 3));
1426 if (IsValidMID(nMID)) {
1431 if (!foundMID)
return wxEmptyString;
1434#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
1438 return b_CntryLongStr ? _(
"Albania") : _T(
"AL");
1440 return b_CntryLongStr ? _(
"Andorra") : _T(
"AD");
1442 return b_CntryLongStr ? _(
"Austria") : _T(
"AT");
1444 return b_CntryLongStr ? _(
"Azores") : _T(
"AZ");
1446 return b_CntryLongStr ? _(
"Belgium") : _T(
"BE");
1448 return b_CntryLongStr ? _(
"Belarus") : _T(
"BY");
1450 return b_CntryLongStr ? _(
"Bulgaria") : _T(
"BG");
1452 return b_CntryLongStr ? _(
"Vatican City State") : _T(
"VA");
1455 return b_CntryLongStr ? _(
"Cyprus") : _T(
"CY");
1457 return b_CntryLongStr ? _(
"Germany") : _T(
"DE");
1459 return b_CntryLongStr ? _(
"Cyprus") : _T(
"CY");
1461 return b_CntryLongStr ? _(
"Georgia") : _T(
"GE");
1463 return b_CntryLongStr ? _(
"Moldova") : _T(
"MD");
1465 return b_CntryLongStr ? _(
"Malta") : _T(
"MT");
1467 return b_CntryLongStr ? _(
"Armenia") : _T(
"AM");
1469 return b_CntryLongStr ? _(
"Germany") : _T(
"DE");
1472 return b_CntryLongStr ? _(
"Denmark") : _T(
"DK");
1474 return b_CntryLongStr ? _(
"Spain") : _T(
"ES");
1476 return b_CntryLongStr ? _(
"Spain") : _T(
"ES");
1480 return b_CntryLongStr ? _(
"France") : _T(
"FR");
1482 return b_CntryLongStr ? _(
"Malta") : _T(
"MT");
1484 return b_CntryLongStr ? _(
"Finland") : _T(
"FI");
1486 return b_CntryLongStr ? _(
"Faroe Islands") : _T(
"FO");
1491 return b_CntryLongStr ? _(
"Great Britain") : _T(
"GB");
1493 return b_CntryLongStr ? _(
"Gibraltar") : _T(
"GI");
1495 return b_CntryLongStr ? _(
"Greece") : _T(
"GR");
1497 return b_CntryLongStr ? _(
"Croatia") : _T(
"HR");
1501 return b_CntryLongStr ? _(
"Greece") : _T(
"GR");
1503 return b_CntryLongStr ? _(
"Morocco") : _T(
"MA");
1505 return b_CntryLongStr ? _(
"Hungary") : _T(
"HU");
1509 return b_CntryLongStr ? _(
"Netherlands") : _T(
"NL");
1511 return b_CntryLongStr ? _(
"Italy") : _T(
"IT");
1514 return b_CntryLongStr ? _(
"Malta") : _T(
"MT");
1516 return b_CntryLongStr ? _(
"Ireland") : _T(
"IE");
1518 return b_CntryLongStr ? _(
"Iceland") : _T(
"IS");
1520 return b_CntryLongStr ? _(
"Liechtenstein") : _T(
"LI");
1522 return b_CntryLongStr ? _(
"Luxembourg") : _T(
"LU");
1524 return b_CntryLongStr ? _(
"Monaco") : _T(
"MC");
1526 return b_CntryLongStr ? _(
"Madeira") : _T(
"PT");
1528 return b_CntryLongStr ? _(
"Malta") : _T(
"MT");
1532 return b_CntryLongStr ? _(
"Norway") : _T(
"NO");
1534 return b_CntryLongStr ? _(
"Poland") : _T(
"PL");
1536 return b_CntryLongStr ? _(
"Montenegro") : _T(
"ME");
1538 return b_CntryLongStr ? _(
"Portugal") : _T(
"PT");
1540 return b_CntryLongStr ? _(
"Romania") : _T(
"RO");
1543 return b_CntryLongStr ? _(
"Sweden") : _T(
"SE");
1545 return b_CntryLongStr ? _(
"Slovak Republic") : _T(
"SK");
1547 return b_CntryLongStr ? _(
"San Marino") : _T(
"SM");
1549 return b_CntryLongStr ? _(
"Switzerland") : _T(
"CH");
1551 return b_CntryLongStr ? _(
"Czech Republic") : _T(
"CZ");
1553 return b_CntryLongStr ? _(
"Turkey") : _T(
"TR");
1555 return b_CntryLongStr ? _(
"Ukraine") : _T(
"UA");
1557 return b_CntryLongStr ? _(
"Russian") : _T(
"RU");
1559 return b_CntryLongStr ? _(
"Macedonia") : _T(
"MK");
1561 return b_CntryLongStr ? _(
"Latvia") : _T(
"LV");
1563 return b_CntryLongStr ? _(
"Estonia") : _T(
"EE");
1565 return b_CntryLongStr ? _(
"Lithuania") : _T(
"LT");
1567 return b_CntryLongStr ? _(
"Slovenia") : _T(
"SI");
1569 return b_CntryLongStr ? _(
"Serbia") : _T(
"RS");
1571 return b_CntryLongStr ? _(
"Anguilla") : _T(
"AI");
1573 return b_CntryLongStr ? _(
"Alaska") : _T(
"AK");
1576 return b_CntryLongStr ? _(
"Antigua and Barbuda") : _T(
"AG");
1578 return b_CntryLongStr ? _(
"Antilles") : _T(
"AN");
1580 return b_CntryLongStr ? _(
"Aruba") : _T(
"AW");
1583 return b_CntryLongStr ? _(
"Bahamas") : _T(
"BS");
1585 return b_CntryLongStr ? _(
"Bermuda") : _T(
"BM");
1587 return b_CntryLongStr ? _(
"Bahamas") : _T(
"BS");
1589 return b_CntryLongStr ? _(
"Belize") : _T(
"BZ");
1591 return b_CntryLongStr ? _(
"Barbados") : _T(
"BB");
1593 return b_CntryLongStr ? _(
"Canada") : _T(
"CA");
1595 return b_CntryLongStr ? _(
"Cayman Islands") : _T(
"KY");
1597 return b_CntryLongStr ? _(
"Costa Rica") : _T(
"CR");
1599 return b_CntryLongStr ? _(
"Cuba") : _T(
"CU");
1601 return b_CntryLongStr ? _(
"Dominica") : _T(
"DM");
1603 return b_CntryLongStr ? _(
"Dominican Republic") : _T(
"DM");
1605 return b_CntryLongStr ? _(
"Guadeloupe") : _T(
"GP");
1607 return b_CntryLongStr ? _(
"Grenada") : _T(
"GD");
1609 return b_CntryLongStr ? _(
"Greenland") : _T(
"GL");
1611 return b_CntryLongStr ? _(
"Guatemala") : _T(
"GT");
1613 return b_CntryLongStr ? _(
"Honduras") : _T(
"HN");
1615 return b_CntryLongStr ? _(
"Haiti") : _T(
"HT");
1617 return b_CntryLongStr ? _(
"United States of America") : _T(
"US");
1619 return b_CntryLongStr ? _(
"Jamaica") : _T(
"JM");
1621 return b_CntryLongStr ? _(
"Saint Kitts and Nevis") : _T(
"KN");
1623 return b_CntryLongStr ? _(
"Saint Lucia") : _T(
"LC");
1625 return b_CntryLongStr ? _(
"Mexico") : _T(
"MX");
1627 return b_CntryLongStr ? _(
"Martinique") : _T(
"MQ");
1629 return b_CntryLongStr ? _(
"Montserrat") : _T(
"MS");
1631 return b_CntryLongStr ? _(
"Nicaragua") : _T(
"NI");
1639 return b_CntryLongStr ? _(
"Panama") : _T(
"PA");
1641 return b_CntryLongStr ? _(
"Puerto Rico") : _T(
"PR");
1643 return b_CntryLongStr ? _(
"El Salvador") : _T(
"SV");
1645 return b_CntryLongStr ? _(
"Saint Pierre and Miquelon") : _T(
"PM");
1647 return b_CntryLongStr ? _(
"Trinidad and Tobago") : _T(
"TT");
1649 return b_CntryLongStr ? _(
"Turks and Caicos Islands") : _T(
"TC");
1654 return b_CntryLongStr ? _(
"United States of America") : _T(
"US");
1660 return b_CntryLongStr ? _(
"Panama") : _T(
"PA");
1664 return b_CntryLongStr ? _(
"Saint Vincent and the Grenadines") : _T(
"VC");
1666 return b_CntryLongStr ? _(
"British Virgin Islands") : _T(
"VG");
1668 return b_CntryLongStr ? _(
"United States Virgin Islands") : _T(
"AE");
1670 return b_CntryLongStr ? _(
"Afghanistan") : _T(
"AF");
1672 return b_CntryLongStr ? _(
"Saudi Arabia") : _T(
"SA");
1674 return b_CntryLongStr ? _(
"Bangladesh") : _T(
"BD");
1676 return b_CntryLongStr ? _(
"Bahrain") : _T(
"BH");
1678 return b_CntryLongStr ? _(
"Bhutan") : _T(
"BT");
1682 return b_CntryLongStr ? _(
"China") : _T(
"CN");
1684 return b_CntryLongStr ? _(
"Taiwan") : _T(
"TW");
1686 return b_CntryLongStr ? _(
"Sri Lanka") : _T(
"LK");
1688 return b_CntryLongStr ? _(
"India") : _T(
"IN");
1690 return b_CntryLongStr ? _(
"Iran") : _T(
"IR");
1692 return b_CntryLongStr ? _(
"Azerbaijani Republic") : _T(
"AZ");
1694 return b_CntryLongStr ? _(
"Iraq") : _T(
"IQ");
1696 return b_CntryLongStr ? _(
"Israel") : _T(
"IL");
1698 return b_CntryLongStr ? _(
"Japan") : _T(
"JP");
1700 return b_CntryLongStr ? _(
"Japan") : _T(
"JP");
1702 return b_CntryLongStr ? _(
"Turkmenistan") : _T(
"TM");
1704 return b_CntryLongStr ? _(
"Kazakhstan") : _T(
"KZ");
1706 return b_CntryLongStr ? _(
"Uzbekistan") : _T(
"UZ");
1708 return b_CntryLongStr ? _(
"Jordan") : _T(
"JO");
1711 return b_CntryLongStr ? _(
"Korea") : _T(
"KR");
1713 return b_CntryLongStr ? _(
"Palestine") : _T(
"PS");
1715 return b_CntryLongStr ? _(
"People's Rep. of Korea") : _T(
"KP");
1717 return b_CntryLongStr ? _(
"Kuwait") : _T(
"KW");
1719 return b_CntryLongStr ? _(
"Lebanon") : _T(
"LB");
1721 return b_CntryLongStr ? _(
"Kyrgyz Republic") : _T(
"KG");
1723 return b_CntryLongStr ? _(
"Macao") : _T(
"MO");
1725 return b_CntryLongStr ? _(
"Maldives") : _T(
"MV");
1727 return b_CntryLongStr ? _(
"Mongolia") : _T(
"MN");
1729 return b_CntryLongStr ? _(
"Nepal") : _T(
"NP");
1731 return b_CntryLongStr ? _(
"Oman") : _T(
"OM");
1733 return b_CntryLongStr ? _(
"Pakistan") : _T(
"PK");
1735 return b_CntryLongStr ? _(
"Qatar") : _T(
"QA");
1737 return b_CntryLongStr ? _(
"Syrian Arab Republic") : _T(
"SY");
1740 return b_CntryLongStr ? _(
"United Arab Emirates") : _T(
"AE");
1742 return b_CntryLongStr ? _(
"Tajikistan") : _T(
"TJ");
1745 return b_CntryLongStr ? _(
"Yemen") : _T(
"YE");
1747 return b_CntryLongStr ? _(
"Hong Kong") : _T(
"HK");
1749 return b_CntryLongStr ? _(
"Bosnia and Herzegovina") : _T(
"BA");
1751 return b_CntryLongStr ? _(
"Adelie Land") : _T(
"TF");
1753 return b_CntryLongStr ? _(
"Australia") : _T(
"AU");
1755 return b_CntryLongStr ? _(
"Myanmar") : _T(
"MM");
1757 return b_CntryLongStr ? _(
"Brunei Darussalam") : _T(
"BN");
1759 return b_CntryLongStr ? _(
"Micronesia") : _T(
"FM");
1761 return b_CntryLongStr ? _(
"Palau") : _T(
"PW");
1763 return b_CntryLongStr ? _(
"New Zealand") : _T(
"NZ");
1766 return b_CntryLongStr ? _(
"Cambodia") : _T(
"KH");
1768 return b_CntryLongStr ? _(
"Christmas Island") : _T(
"CX");
1770 return b_CntryLongStr ? _(
"Cook Islands") : _T(
"CK");
1772 return b_CntryLongStr ? _(
"Fiji") : _T(
"FJ");
1774 return b_CntryLongStr ? _(
"Cocos (Keeling) Islands") : _T(
"CC");
1776 return b_CntryLongStr ? _(
"Indonesia") : _T(
"ID");
1778 return b_CntryLongStr ? _(
"Kiribati") : _T(
"KI");
1780 return b_CntryLongStr ? _(
"Lao People's Dem. Rep.") : _T(
"LA");
1782 return b_CntryLongStr ? _(
"Malaysia") : _T(
"MY");
1784 return b_CntryLongStr ? _(
"Northern Mariana Islands") : _T(
"MP");
1786 return b_CntryLongStr ? _(
"Marshall Islands") : _T(
"MH");
1788 return b_CntryLongStr ? _(
"New Caledonia") : _T(
"NC");
1790 return b_CntryLongStr ? _(
"Niue") : _T(
"NU");
1792 return b_CntryLongStr ? _(
"Nauru") : _T(
"NR");
1794 return b_CntryLongStr ? _(
"French Polynesia") : _T(
"PF");
1796 return b_CntryLongStr ? _(
"Philippines") : _T(
"PH");
1798 return b_CntryLongStr ? _(
"East Timor") : _T(
"TL");
1800 return b_CntryLongStr ? _(
"Papua New Guinea") : _T(
"PG");
1802 return b_CntryLongStr ? _(
"Pitcairn Island") : _T(
"PN");
1804 return b_CntryLongStr ? _(
"Solomon Islands") : _T(
"SB");
1806 return b_CntryLongStr ? _(
"American Samoa") : _T(
"AS");
1808 return b_CntryLongStr ? _(
"Samoa") : _T(
"WS");
1813 return b_CntryLongStr ? _(
"Singapore") : _T(
"SG");
1815 return b_CntryLongStr ? _(
"Thailand") : _T(
"TH");
1817 return b_CntryLongStr ? _(
"Tonga") : _T(
"TO");
1819 return b_CntryLongStr ? _(
"Tuvalu") : _T(
"TV");
1821 return b_CntryLongStr ? _(
"Viet Nam") : _T(
"VN");
1824 return b_CntryLongStr ? _(
"Vanuatu") : _T(
"VU");
1826 return b_CntryLongStr ? _(
"Wallis and Futuna Islands") : _T(
"WF");
1828 return b_CntryLongStr ? _(
"South Africa") : _T(
"ZA");
1830 return b_CntryLongStr ? _(
"Angola") : _T(
"AO");
1832 return b_CntryLongStr ? _(
"Algeria") : _T(
"DZ");
1834 return b_CntryLongStr ? _(
"Saint Paul") : _T(
"TF");
1836 return b_CntryLongStr ? _(
"Ascension Island") : _T(
"SH");
1838 return b_CntryLongStr ? _(
"Burundi") : _T(
"BI");
1840 return b_CntryLongStr ? _(
"Benin") : _T(
"BJ");
1842 return b_CntryLongStr ? _(
"Botswana") : _T(
"BW");
1844 return b_CntryLongStr ? _(
"Central African Republic") : _T(
"CF");
1846 return b_CntryLongStr ? _(
"Cameroon") : _T(
"CM");
1848 return b_CntryLongStr ? _(
"Congo") : _T(
"CD");
1850 return b_CntryLongStr ? _(
"Comoros") : _T(
"KM");
1852 return b_CntryLongStr ? _(
"Capo Verde") : _T(
"CV");
1854 return b_CntryLongStr ? _(
"Crozet Archipelago") : _T(
"TF");
1856 return b_CntryLongStr ? _(
"Ivory Coast") : _T(
"CI");
1858 return b_CntryLongStr ? _(
"Comoros (Union of the)") : _T(
"KM");
1860 return b_CntryLongStr ? _(
"Djibouti") : _T(
"DJ");
1862 return b_CntryLongStr ? _(
"Egypt") : _T(
"EG");
1864 return b_CntryLongStr ? _(
"Ethiopia") : _T(
"ET");
1866 return b_CntryLongStr ? _(
"Eritrea") : _T(
"ER");
1868 return b_CntryLongStr ? _(
"Gabonese Republic") : _T(
"GA");
1870 return b_CntryLongStr ? _(
"Ghana") : _T(
"GH");
1872 return b_CntryLongStr ? _(
"Gambia") : _T(
"GM");
1874 return b_CntryLongStr ? _(
"Guinea-Bissau") : _T(
"GW");
1876 return b_CntryLongStr ? _(
"Equatorial Guinea") : _T(
"GQ");
1878 return b_CntryLongStr ? _(
"Guinea") : _T(
"GN");
1880 return b_CntryLongStr ? _(
"Burkina Faso") : _T(
"BF");
1882 return b_CntryLongStr ? _(
"Kenya") : _T(
"KE");
1884 return b_CntryLongStr ? _(
"Kerguelen Islands") : _T(
"TF");
1887 return b_CntryLongStr ? _(
"Liberia") : _T(
"LR");
1889 return b_CntryLongStr ? _(
"South Sudan (Republic of)") : _T(
"SS");
1891 return b_CntryLongStr ? _(
"Libya") : _T(
"LY");
1893 return b_CntryLongStr ? _(
"Lesotho") : _T(
"LS");
1895 return b_CntryLongStr ? _(
"Mauritius") : _T(
"MU");
1897 return b_CntryLongStr ? _(
"Madagascar") : _T(
"MG");
1899 return b_CntryLongStr ? _(
"Mali") : _T(
"ML");
1901 return b_CntryLongStr ? _(
"Mozambique") : _T(
"MZ");
1903 return b_CntryLongStr ? _(
"Mauritania") : _T(
"MR");
1905 return b_CntryLongStr ? _(
"Malawi") : _T(
"MW");
1907 return b_CntryLongStr ? _(
"Niger") : _T(
"NE");
1909 return b_CntryLongStr ? _(
"Nigeria") : _T(
"NG");
1911 return b_CntryLongStr ? _(
"Namibia") : _T(
"NA");
1913 return b_CntryLongStr ? _(
"Reunion") : _T(
"RE");
1915 return b_CntryLongStr ? _(
"Rwanda") : _T(
"RW");
1917 return b_CntryLongStr ? _(
"Sudan") : _T(
"SD");
1919 return b_CntryLongStr ? _(
"Senegal") : _T(
"SN");
1921 return b_CntryLongStr ? _(
"Seychelles") : _T(
"SC");
1923 return b_CntryLongStr ? _(
"Saint Helena") : _T(
"SH");
1925 return b_CntryLongStr ? _(
"Somalia") : _T(
"SO");
1927 return b_CntryLongStr ? _(
"Sierra Leone") : _T(
"SL");
1929 return b_CntryLongStr ? _(
"Sao Tome and Principe") : _T(
"ST");
1931 return b_CntryLongStr ? _(
"Eswatini") : _T(
"SZ");
1933 return b_CntryLongStr ? _(
"Chad") : _T(
"TD");
1935 return b_CntryLongStr ? _(
"Togolese Republic") : _T(
"TG");
1937 return b_CntryLongStr ? _(
"Tunisia") : _T(
"TN");
1939 return b_CntryLongStr ? _(
"Tanzania") : _T(
"TZ");
1941 return b_CntryLongStr ? _(
"Uganda") : _T(
"UG");
1943 return b_CntryLongStr ? _(
"Dem Rep.of the Congo") : _T(
"CD");
1945 return b_CntryLongStr ? _(
"Tanzania") : _T(
"TZ");
1947 return b_CntryLongStr ? _(
"Zambia") : _T(
"ZM");
1949 return b_CntryLongStr ? _(
"Zimbabwe") : _T(
"ZW");
1951 return b_CntryLongStr ? _(
"Argentine Republic") : _T(
"AR");
1953 return b_CntryLongStr ? _(
"Brazil") : _T(
"BR");
1955 return b_CntryLongStr ? _(
"Bolivia") : _T(
"BO");
1957 return b_CntryLongStr ? _(
"Chile") : _T(
"CL");
1959 return b_CntryLongStr ? _(
"Colombia") : _T(
"CO");
1961 return b_CntryLongStr ? _(
"Ecuador") : _T(
"EC");
1963 return b_CntryLongStr ? _(
"Falkland Islands") : _T(
"FK");
1965 return b_CntryLongStr ? _(
"France - Guiana") : _T(
"GY");
1967 return b_CntryLongStr ? _(
"Guyana") : _T(
"GY");
1969 return b_CntryLongStr ? _(
"Paraguay") : _T(
"PY");
1971 return b_CntryLongStr ? _(
"Peru") : _T(
"PE");
1973 return b_CntryLongStr ? _(
"Suriname") : _T(
"SR");
1975 return b_CntryLongStr ? _(
"Uruguay") : _T(
"UY");
1977 return b_CntryLongStr ? _(
"Venezuela") : _T(
"VE");
1980 return wxEmptyString;
1983 return wxEmptyString;
1987wxString ais_get_type(
int index) {
1988 static const wxString ais_type[] = {
1989 _(
"Fishing Vessel"),
1991 _(
"Towing Vessel, Long"),
1993 _(
"Diving Ops Vessel"),
1994 _(
"Military Vessel"),
1995 _(
"Sailing Vessel"),
1996 _(
"Pleasure craft"),
1997 _(
"High Speed Craft"),
1999 _(
"Search and Rescue Vessel"),
2002 _(
"Pollution Control Vessel"),
2003 _(
"Law Enforcement Vessel"),
2004 _(
"Medical Transport"),
2005 _(
"Passenger Ship"),
2010 _(
"Reference Point"),
2012 _(
"Fixed Structure"),
2015 _(
"Light w/Sectors"),
2016 _(
"Leading Light Front"),
2017 _(
"Leading Light Rear"),
2018 _(
"Cardinal N Beacon"),
2019 _(
"Cardinal E Beacon"),
2020 _(
"Cardinal S Beacon"),
2021 _(
"Cardinal W Beacon"),
2022 _(
"Beacon, Port Hand"),
2023 _(
"Beacon, Starboard Hand"),
2024 _(
"Beacon, Preferred Channel Port Hand"),
2025 _(
"Beacon, Preferred Channel Starboard Hand"),
2026 _(
"Beacon, Isolated Danger"),
2027 _(
"Beacon, Safe Water"),
2028 _(
"Beacon, Special Mark"),
2029 _(
"Cardinal Mark N"),
2030 _(
"Cardinal Mark E"),
2031 _(
"Cardinal Mark S"),
2032 _(
"Cardinal Mark W"),
2033 _(
"Port Hand Mark"),
2034 _(
"Starboard Hand Mark"),
2035 _(
"Preferred Channel Port Hand"),
2036 _(
"Preferred Channel Starboard Hand"),
2037 _(
"Isolated Danger"),
2040 _(
"Light Vessel/Rig"),
2042 _(
"Position Report"),
2044 _(
"ARPA radar target"),
2045 _(
"APRS Position Report"),
2046 _(
"Buoy or similar")
2049 return ais_type[index];
2052wxString ais_get_short_type(
int index) {
2053 static const wxString short_ais_type[] = {
2112 _(
"Buoy or similar")
2114 return short_ais_type[index];
Global state for AIS decoder.