24#include <unordered_map>
26#include <wx/datetime.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(
"%3ds", seconds);
48 else if (seconds < 3600) {
51 return wxString::Format(
"%2dmin %02ds", m, s);
53 int h = seconds / 3600;
55 return wxString::Format(
"%2dh %02dmin", h, m);
58static wxString html_escape(
const wxString &src) {
62 ret.Replace(
"<",
"<");
63 ret.Replace(
">",
">");
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) {
121 trend = _(
"decreasing");
123 trend = _(
"increasing");
128wxString aisMeteoPrecipType(
int precip) {
138 prec =
"Thunderstorm";
141 prec =
"Freezing rain";
144 prec =
"Mixed / ice";
150 prec =
"not available";
156wxString aisMeteoWaterLevelRef(
int refID) {
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() {
421 wxString shipName = trimAISField(ShipName);
422 if (shipName ==
"Unknown")
423 retName = wxGetTranslation(shipName);
427 if (strlen(ShipNameExtension)) {
428 wxString shipNameExt = trimAISField(ShipNameExtension);
429 retName += shipNameExt;
436wxString AisTargetData::BuildQueryResult() {
438 wxDateTime now = wxDateTime::Now();
440 wxString tableStart =
441 "\n<table width=100% border=0 cellpadding=1 cellspacing=0>\n";
443 wxString tableEnd =
"</table>\n\n";
444 wxString rowStart =
"<tr><td><font size=-2>";
445 wxString rowStartH =
"<tr><td nowrap>";
446 wxString rowSeparator =
"</font></td><td></td><td><b>";
447 wxString rowSeparatorH =
"</td><td></td><td>";
448 wxString colSeparator =
"<td></td>";
449 wxString rowEnd =
"</b></td></tr>\n";
450 wxString vertSpacer =
"<tr><td></td></tr>\n\n";
452 wxString IMOstr, MMSIstr, ClassStr;
454 html << tableStart <<
"<tr><td nowrap colspan=2>";
456 html <<
"<font size=+2><i><b>" << GetFullName();
457 html <<
"</b></i></font> <b>";
460 if ((Class != AIS_ATON) && (Class != AIS_BASE) && (Class != AIS_GPSG_BUDDY) &&
461 (Class != AIS_SART) && (Class != AIS_METEO)) {
462 html << trimAISField(CallSign) <<
"</b>" << rowEnd;
464 if (Class != AIS_CLASS_B) {
465 if (IMO > 0) IMOstr = wxString::Format(
"%08d", abs(IMO));
468 html <<
"</b>" << rowEnd;
472 if (Class != AIS_GPSG_BUDDY) {
473 MMSIstr = wxString::Format(
"%09d", abs(MMSI));
475 ClassStr = wxGetTranslation(Get_class_string(
false));
477 if (Class == AIS_ATON) {
478 wxString cls(
"AtoN: ");
479 cls += Get_vessel_type_string(
false);
480 ClassStr = wxGetTranslation(cls);
483 if (b_SarAircraftPosnReport) {
484 int airtype = (MMSI % 1000) / 100;
485 ClassStr = airtype == 5 ? _(
"SAR Helicopter") : _(
"SAR Aircraft");
489 html <<
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 "
491 << rowStart << _(
"MMSI")
492 <<
"</font></td><td> </td><td><font size=-2>" << _(
"Class")
493 <<
"</font></td><td> </td><td align=right><font size=-2>"
494 << _(
"IMO") <<
"</font></td></tr>" << rowStartH <<
"<b>" << MMSIstr
495 <<
"</b></td><td> </td><td><b>" << ClassStr
496 <<
"</b></td><td> </td><td align=right><b>" << IMOstr << rowEnd
497 <<
"</table></td></tr>";
499 else if (Class == AIS_METEO) {
500 MMSIstr = wxString::Format(
"%09d", abs(met_data.original_mmsi));
501 html <<
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 "
503 << rowStart << _(
"MMSI")
504 <<
"</font></td><td> </td><td align=right><font size=-2>"
505 << _(
"Class") <<
"</font></td></tr>" << rowStartH <<
"<b>" << MMSIstr
506 <<
"</b></td><td> </td><td align=right><b>"
507 <<
"<font size=-1>" << ClassStr << rowEnd << rowStart
508 <<
"<b>ID: " << MMSI;
509 if (met_data.stationID) {
510 wxString SK_ID = wxString::Format(
"%06d", (met_data.stationID - 1000000));
511 html <<
"<td> </td><td align=right>"
512 <<
"SK-ID: " << SK_ID;
514 html << rowEnd <<
"</b></table></td></tr>";
516 html <<
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 "
518 << rowStart << _(
"MMSI")
519 <<
"</font></td><td> </td><td align=right><font size=-2>"
520 << _(
"Class") <<
"</font></td></tr>" << rowStartH <<
"<b>" << MMSIstr
521 <<
"</b></td><td> </td><td align=right><b>" << ClassStr << rowEnd
522 <<
"</table></td></tr>";
524 if ((Class != AIS_SART))
525 html <<
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 "
528 << ((Class == AIS_BASE || Class == AIS_ATON || Class == AIS_METEO)
531 << rowEnd <<
"</font></td></tr>" << rowStartH <<
"<font size=-1><b>"
532 << GetCountryCode(true);
533 if (Class == AIS_CLASS_B && MMSIstr.StartsWith(
"8")) {
534 html <<
"<td align=right>" << _(
"Handheld");
536 html << rowEnd <<
"</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 =
"MOB";
562 sart_sub_type =
"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 <<
"<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(
"%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(
"---m x ---m x %4.1fm",
615 sizeString <<
"---m x ---m x ---m";
618 if (Euro_Draft > 0.01) {
619 sizeString << wxString::Format(
"%5.1fm x %4.1fm x %4.1fm",
620 Euro_Length, Euro_Beam,
623 sizeString << wxString::Format(
"%5.1fm x %4.1fm x ---m\n\n",
624 Euro_Length, Euro_Beam);
629 sizeString << wxString::Format(
"---m x ---m x %4.1fm", Draft);
631 sizeString <<
"---m x ---m x ---m";
634 }
else if (Draft < 0.01) {
635 sizeString << wxString::Format(
"%dm x %dm x ---m", (DimA + DimB),
638 sizeString << wxString::Format(
"%dm x %dm x %4.1fm", (DimA + DimB),
639 (DimC + DimD), Draft);
645 if (Class == AIS_SART) {
646 html <<
"<tr><td colspan=2>"
647 <<
"<b>" << AISTypeStr;
648 if (sart_sub_type.Length()) html <<
" (" << sart_sub_type <<
"), ";
650 html << rowEnd <<
"<tr><td colspan=2>"
651 <<
"<b>" << sizeString << rowEnd;
654 else if (Class == AIS_ATON) {
655 html <<
"<tr><td colspan=2>"
656 <<
"<b>" << navStatStr;
657 html << rowEnd <<
"<tr><td colspan=2>"
658 <<
"<b>" << sizeString << rowEnd;
659 }
else if (Class == AIS_DSC && (ShipType == 12 || ShipType == 16)) {
660 if (ShipType == 16) {
661 html <<
"<tr><td colspan=2>"
662 <<
"<b>" << _(
"Distress relay");
663 if (m_dscTXmmsi > 2000000) {
664 wxString mmsirelay = wxString::Format(
" %09d", abs(m_dscTXmmsi));
665 html <<
" " << _(
"by:") << mmsirelay;
667 html <<
"<b>" << sizeString << rowEnd;
669 html <<
"<tr><td colspan=2>" << _(
"Nature of distress: ") << rowEnd
670 <<
"<tr><td colspan=2>";
671 if (m_dscNature < 13) {
672 html <<
"<tr><td colspan=2>"
673 <<
"<b>" << GetNatureofDistress(m_dscNature) <<
"<b>" << sizeString
674 << rowEnd <<
"<tr><td colspan=2>";
676 }
else if ((Class != AIS_BASE) && (Class != AIS_DSC)) {
677 html <<
"<tr><td colspan=2>"
678 <<
"<b>" << AISTypeStr;
679 if (navStatStr.Length()) html <<
", " << navStatStr;
680 if (UNTypeStr.Length()) html <<
" (UN Type " << UNTypeStr <<
")";
681 html << rowEnd <<
"<tr><td colspan=2>"
682 <<
"<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 <<
"</font></td><td align=right><font size=-2>" << _(
"Report Age")
697 <<
"</font></td></tr>"
699 << rowStartH <<
"<b>" << toSDMM(1, Lat)
700 <<
"</b></td><td align=right><b>" << FormatTimeAdaptive(target_age)
701 << rowEnd << rowStartH <<
"<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 <<
"<b>" << f_date +
"</b> at <b>"
729 << wxString::Format(
"%d:%d UTC ", m_utc_hour, m_utc_min) << rowEnd;
731 if (Class == AIS_CLASS_A && !b_SarAircraftPosnReport) {
732 html << vertSpacer << rowStart << _(
"Destination")
733 <<
"</font></td><td align=right><font size=-2>" << _(
"ETA (UTC)")
734 <<
"</font></td></tr>\n"
735 << rowStartH <<
"<b>";
736 wxString dest = trimAISField(Destination);
738 html << html_escape(dest);
741 html <<
"</b></td><td nowrap align=right><b>";
743 if ((ETA_Mo) && (ETA_Hr < 24)) {
745 if (now.GetMonth() > (ETA_Mo - 1)) yearOffset = 1;
746 wxDateTime eta(ETA_Day, wxDateTime::Month(ETA_Mo - 1),
747 now.GetYear() + yearOffset, ETA_Hr, ETA_Min);
748 html << eta.Format(
"%b %d %H:%M");
754 if (Class == AIS_CLASS_A || Class == AIS_CLASS_B || Class == AIS_ARPA ||
755 Class == AIS_APRS || Class == AIS_SART || Class == AIS_BUOY) {
756 int crs = wxRound(COG);
758 wxString magString, trueString;
760 magString << wxString::Format(
761 wxString(
"%03d%c(M)"),
static_cast<int>(m_callbacks.get_mag(COG)),
764 trueString << wxString::Format(wxString(
"%03d%c "), (
int)crs, 0x00B0);
766 courseStr << trueString << magString;
767 }
else if (COG == 360.0)
770 courseStr =
"0°";
772 double speed_show = toUsrSpeed(SOG);
774 if ((SOG <= 102.2) || b_SarAircraftPosnReport) {
775 if (speed_show < 10.0)
776 sogStr = wxString::Format(
"%.2f ", speed_show) + getUsrSpeedUnit();
777 else if (speed_show < 100.0)
778 sogStr = wxString::Format(
"%.1f ", speed_show) + getUsrSpeedUnit();
780 sogStr = wxString::Format(
"%.0f ", speed_show) + getUsrSpeedUnit();
788 hdgStr = wxString::Format(
"%03d°", (
int)HDG);
792 if (ROTAIS != -128) {
794 rotStr <<
"> 5°/30s " << _(
"Right");
795 else if (ROTAIS == -127)
796 rotStr <<
"> 5°/30s " << _(
"Left");
799 rotStr << wxString::Format(
"%3d°/Min ", ROTIND) << _(
"Right");
801 rotStr << wxString::Format(
"%3d°/Min ", -ROTIND) << _(
"Left");
805 }
else if (!b_SarAircraftPosnReport)
810 if (b_positionOnceValid &&
bGPSValid && (Range_NM >= 0.))
815 int brg = (int)wxRound(Brg);
816 if (Brg > 359.5) brg = 0;
817 if (b_positionOnceValid &&
bGPSValid && (Brg >= 0.) && (Range_NM > 0.) &&
819 wxString magString, trueString;
821 magString << wxString::Format(wxString(
"%03d%c(M)"),
822 static_cast<int>(m_callbacks.get_mag(Brg)),
825 trueString << wxString::Format(wxString(
"%03d%c "), (
int)Brg, 0x00B0);
827 brgStr << trueString << magString;
831 wxString turnRateHdr;
832 if ((Class != AIS_ATON) && (Class != AIS_BASE) && (Class != AIS_DSC) &&
833 (Class != AIS_METEO)) {
835 <<
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 "
837 << rowStart << _(
"Speed")
838 <<
"</font></td><td> </td><td><font size=-2>" << _(
"Course")
839 <<
"</font></td><td> </td><td align=right><font size=-2>";
840 if (!b_SarAircraftPosnReport) html << _(
"Heading");
842 html <<
"</font></td></tr>" << rowStartH <<
"<b>" << sogStr
843 <<
"</b></td><td> </td><td><b>" << courseStr
844 <<
"</b></td><td> </td><td align=right><b>";
845 if (!b_SarAircraftPosnReport) html << hdgStr;
846 html << rowEnd <<
"</table></td></tr>" << vertSpacer;
848 if (!b_SarAircraftPosnReport) turnRateHdr = _(
"Turn Rate");
850 if (Class != AIS_METEO) {
851 html <<
"<tr><td colspan=2><table width=100% border=0 cellpadding=0 "
853 << rowStart << _(
"Range")
854 <<
"</font></td><td> </td><td><font size=-2>" << _(
"Bearing")
855 <<
"</font></td><td> </td><td align=right><font size=-2>"
856 << turnRateHdr <<
"</font></td></tr>" << rowStartH <<
"<b>" << rngStr
857 <<
"</b></td><td> </td><td><b>" << brgStr
858 <<
"</b></td><td> </td><td align=right><b>";
859 if (!b_SarAircraftPosnReport) html << rotStr;
860 html << rowEnd <<
"</table></td></tr>" << vertSpacer;
863 if (bCPA_Valid && Class != AIS_METEO) {
865 tcpaStr <<
"</b> " << _(
"in ") <<
"</td><td align=right><b>"
866 << FormatTimeAdaptive((
int)(TCPA * 60.));
868 html << rowStart <<
"<font size=-2>" << _(
"CPA")
869 <<
"</font>" << rowEnd << rowStartH <<
"<b>"
873 if (Class != AIS_BASE && Class != AIS_METEO) {
874 if (blue_paddle == 1) {
875 html << rowStart << _(
"Inland Blue Flag") << rowEnd << rowStartH <<
"<b>"
876 << _(
"Clear") << rowEnd;
877 }
else if (blue_paddle == 2) {
878 html << rowStart << _(
"Inland Blue Flag") << rowEnd << rowStartH <<
"<b>"
879 << _(
"Set") << rowEnd;
883 if (b_SarAircraftPosnReport) {
885 if (altitude != 4095)
886 altStr.Printf(
"%4d m", altitude);
888 altStr = _(
"Unknown");
890 html << rowStart << _(
"Altitude")
891 <<
"</font></td><td> </td><td><font size=-0>" << rowStartH
892 <<
"<b>" << altStr <<
"</b></td><td> </td><td><b>" << rowEnd
893 <<
"</table></td></tr>" << vertSpacer;
896 if (Class == AIS_METEO) {
897 if (met_data.wind_kn < 122) {
898 double userwindspeed = toUsrWindSpeed(met_data.wind_kn);
900 wxString::Format(
"%0.1f %s %d%c", userwindspeed,
901 getUsrWindSpeedUnit(), met_data.wind_dir, 0x00B0);
903 double userwindgustspeed = toUsrWindSpeed(met_data.wind_gust_kn);
904 wxString wspeedGust = wxString::Format(
"%.0f %s %d%c", userwindgustspeed,
905 getUsrWindSpeedUnit(),
906 met_data.wind_gust_dir, 0x00B0);
907 if (met_data.wind_gust_kn >= 126) wspeedGust =
"";
909 html << vertSpacer << rowStart << _(
"Wind speed")
910 <<
"</font></td><td align=right><font size=-2>" << _(
"Wind gust")
911 <<
"</font></td></tr>" << rowStartH <<
"<b>" << wspeed
912 <<
"</b></td><td align=right><b>" << wspeedGust << rowEnd;
915 if (met_data.water_lev_dev < 30. || met_data.water_level > -32. ||
916 met_data.current < 25.5) {
917 wxString wlevel_txt = _(
"Water level deviation");
919 if (met_data.water_lev_dev < 30.) {
920 double userlevel =
toUsrDepth(met_data.water_lev_dev);
922 wxString::Format(
"%.1f %s %s", userlevel, getUsrDepthUnit(),
923 ais_meteo_get_trend(met_data.water_lev_trend));
924 if (met_data.vertical_ref < 14) {
925 wlevel_txt = _(
"Water level dev. Ref: ");
926 wlevel_txt << aisMeteoWaterLevelRef(met_data.vertical_ref);
929 if (met_data.water_lev_dev >= 30.) wlevel =
"";
931 }
else if (met_data.water_level > -32.) {
932 double userlevel =
toUsrDepth(met_data.water_level);
934 wxString::Format(
"%.1f %s %s", userlevel, getUsrDepthUnit(),
935 ais_meteo_get_trend(met_data.water_lev_trend));
936 wlevel_txt = _(
"Water level");
937 if (met_data.water_level <= -32.) wlevel =
"";
940 wxString current = wxString::Format(
"%.1f kts %d%c", met_data.current,
941 met_data.curr_dir, 0x00B0);
942 if (met_data.current >= 25.5) current =
"";
944 html << vertSpacer << rowStart << wlevel_txt
945 <<
"</font></td><td align=right><font size=-2>"
946 << _(
"Surface current ") <<
"</font></td></tr>" << rowStartH <<
"<b>"
947 << wlevel <<
"</b></td><td align=right><b>" << current << rowEnd;
950 if (met_data.wave_height < 24.6 || met_data.swell_height < 24.6) {
951 double userwave =
toUsrDepth(met_data.wave_height);
952 wxString wave = wxString::Format(
"%.1f %s %d%c %d %s ", userwave,
953 getUsrDepthUnit(), met_data.wave_dir,
954 0x00B0, met_data.wave_period, _(
"s"));
955 if (met_data.wave_height >= 24.6) wave =
"";
957 double userswell =
toUsrDepth(met_data.swell_height);
958 wxString swell = wxString::Format(
"%.1f %s %d%c %d %s", userswell,
959 getUsrDepthUnit(), met_data.swell_dir,
960 0x00B0, met_data.swell_per, _(
"s"));
961 if (met_data.swell_height >= 25.) swell =
"";
963 html << vertSpacer << rowStart << _(
"Waves height & period")
964 <<
"</font></td><td align=right><font size=-2>"
965 << _(
"Swell height & period ") <<
"</font></td></tr>" << rowStartH
966 <<
"<b>" << wave <<
"</b></td><td align=right><b>" << swell
970 if (met_data.air_temp != -102.4 || met_data.airpress < 1310) {
971 double usertemp =
toUsrTemp(met_data.air_temp);
973 wxString::Format(
"%.1f%c%s", usertemp, 0x00B0, getUsrTempUnit());
974 if (met_data.air_temp == -102.4) airtemp =
"";
977 wxString::Format(
"%d hPa %s", met_data.airpress,
978 ais_meteo_get_trend(met_data.airpress_tend));
979 const int ap = met_data.airpress;
980 if (ap < 800 || ap >= 1310) airpress =
"";
982 html << vertSpacer << rowStart << _(
"Air Temperatur")
983 <<
"</font></td><td align=right><font size=-2>" << _(
"Air pressure")
984 <<
"</font></td></tr>" << rowStartH <<
"<b>" << airtemp
985 <<
"</b></td><td align=right><b>" << airpress << rowEnd;
988 if (met_data.rel_humid < 101 || met_data.dew_point < 50.) {
989 wxString humid = wxString::Format(
"%d%c", met_data.rel_humid,
'%');
990 if (met_data.rel_humid >= 101) humid =
"";
992 double usertempDew =
toUsrTemp(met_data.dew_point);
994 wxString::Format(
"%.1f%c%s", usertempDew, 0x00B0, getUsrTempUnit());
995 if (met_data.dew_point >= 50.) dewpoint =
"";
997 html << vertSpacer << rowStart << _(
"Relative Humidity")
998 <<
"</font></td><td align=right><font size=-2>" << _(
"Dew Point ")
999 <<
"</font></td></tr>" << rowStartH <<
"<b>" << humid
1000 <<
"</b></td><td align=right><b>" << dewpoint << rowEnd;
1003 if (met_data.water_temp < 50.1 || met_data.seastate < 13) {
1004 double usertemp =
toUsrTemp(met_data.water_temp);
1005 wxString watertemp =
1006 wxString::Format(
"%.1f%c%s", usertemp, 0x00B0, getUsrTempUnit());
1007 if (met_data.water_temp >= 50.1) watertemp =
"";
1009 wxString seastate = wxString::Format(
"%d Bf ", met_data.seastate);
1010 if (met_data.seastate == 13) seastate =
"";
1012 html << vertSpacer << rowStart << _(
"Water Temperatur")
1013 <<
"</font></td><td align=right><font size=-2>" << _(
"Sea state")
1014 <<
"</font></td></tr>" << rowStartH <<
"<b>" << watertemp
1015 <<
"</b></td><td align=right><b>" << seastate << rowEnd;
1018 if (met_data.precipitation < 7 || met_data.hor_vis < 12.7) {
1020 wxString::Format(
"%s", aisMeteoPrecipType(met_data.precipitation));
1021 if (met_data.precipitation >= 6) precip =
"";
1025 wxString::Format(
"%s%.1f %s", (met_data.hor_vis_GT ?
">" :
""),
1026 userVisDist, getUsrDistanceUnit());
1027 if (met_data.hor_vis >= 12.7) horVis =
"";
1028 html << vertSpacer << rowStart << _(
"Precipitation")
1029 <<
"</font></td><td align=right><font size=-2>"
1030 << _(
"Horizontal Visibility") <<
"</font></td></tr>" << rowStartH
1031 <<
"<b>" << precip <<
"</b></td><td align=right><b>" << horVis
1035 if (met_data.salinity < 50. || met_data.ice < 2) {
1036 wxString sal = wxString::Format(
"%.1f%c", met_data.salinity, 0x2030);
1037 if (met_data.salinity >= 50.) sal =
"";
1039 wxString icestatus = _(
"No");
1040 if (met_data.ice == 1) icestatus = _(
"Yes");
1041 if (met_data.ice >= 2) icestatus =
"";
1043 html << vertSpacer << rowStart << _(
"Sea salinity")
1044 <<
"</font></td><td align=right><font size=-2>" << _(
"Ice status")
1045 <<
"</font></td></tr>" << rowStartH <<
"<b>" << sal
1046 <<
"</b></td><td align=right><b>" << icestatus << rowEnd;
1053wxString AisTargetData::GetRolloverString() {
1057 result.Append(
"\"");
1058 result.Append(GetFullName());
1059 result.Append(
"\" ");
1061 if (Class != AIS_GPSG_BUDDY) {
1062 t.Printf(
"%09d", abs(MMSI));
1065 result.Append(GetCountryCode(
false));
1067 t = trimAISField(CallSign);
1069 result.Append(
" (");
1073 if (g_bAISRolloverShowClass || (Class == AIS_SART)) {
1074 if (result.Len()) result.Append(
"\n");
1076 if (Class == AIS_ATON) {
1077 result.Append(wxGetTranslation(Get_class_string(
true)));
1078 result.Append(
": ");
1079 result.Append(wxGetTranslation(Get_vessel_type_string(
false)));
1080 }
else if (b_SarAircraftPosnReport) {
1081 int airtype = (MMSI % 1000) / 100;
1082 result.Append(airtype == 5 ? _(
"SAR Helicopter") : _(
"SAR Aircraft"));
1084 result.Append(wxGetTranslation(Get_class_string(
false)));
1086 result.Append(
"] ");
1087 if ((Class != AIS_ATON) && (Class != AIS_BASE)) {
1088 if (Class == AIS_SART) {
1089 int mmsi_start = MMSI / 1000000;
1090 switch (mmsi_start) {
1100 result += _(
"Unknown");
1105 if (Class != AIS_SART && Class != AIS_METEO) {
1106 if (!b_SarAircraftPosnReport)
1107 result.Append(wxGetTranslation(Get_vessel_type_string(
false)));
1110 if ((Class != AIS_CLASS_B) && (Class != AIS_SART) && Class != AIS_DSC &&
1111 Class != AIS_METEO && !b_SarAircraftPosnReport) {
1112 if ((NavStatus <= 15) && (NavStatus >= 0)) {
1113 result.Append(
" (");
1114 result.Append(wxGetTranslation(ais_get_status(NavStatus)));
1117 }
else if (Class == AIS_SART) {
1118 result.Append(
" (");
1119 if (NavStatus == RESERVED_14)
1120 result.Append(_(
"Active"));
1121 else if (NavStatus == UNDEFINED)
1122 result.Append(_(
"Testing"));
1124 }
else if (Class == AIS_DSC) {
1125 result.Append(
" (");
1126 result.Append(GetNatureofDistress(m_dscNature));
1132 if (g_bAISRolloverShowCOG && ((SOG <= 102.2) || b_SarAircraftPosnReport) &&
1133 !((Class == AIS_ATON) || (Class == AIS_BASE) || (Class == AIS_METEO))) {
1134 if (result.Len()) result <<
"\n";
1136 double speed_show = toUsrSpeed(SOG);
1137 if (speed_show < 10.0)
1138 result << wxString::Format(
"SOG %.2f ", speed_show) << getUsrSpeedUnit()
1140 else if (speed_show < 100.0)
1141 result << wxString::Format(
"SOG %.1f ", speed_show) << getUsrSpeedUnit()
1144 result << wxString::Format(
"SOG %.0f ", speed_show) << getUsrSpeedUnit()
1147 int crs = wxRound(COG);
1148 if (b_positionOnceValid) {
1150 wxString magString, trueString;
1152 magString << wxString::Format(
1153 wxString(
"%03d%c(M) "),
1154 static_cast<int>(m_callbacks.get_mag(COG)), 0x00B0);
1156 trueString << wxString::Format(wxString(
"%03d%c "), (
int)crs, 0x00B0);
1158 result << trueString << magString;
1161 else if (COG == 360.0)
1162 result << _(
" COG Unavailable");
1163 else if (crs == 360)
1164 result << wxString(
" COG 000\u00B0");
1166 result << _(
" COG Unavailable");
1169 if (g_bAISRolloverShowCPA && bCPA_Valid && Class != AIS_METEO) {
1170 if (result.Len()) result <<
"\n";
1172 <<
" " << wxString::Format(
"%.0f", TCPA) <<
" " << _(
"min");
1174 if (Class == AIS_METEO) {
1175 if (met_data.wind_kn < 122) {
1176 if (result.Len()) result <<
"\n";
1177 double userwindspeed = toUsrWindSpeed(met_data.wind_kn);
1178 result << _(
"Wind speed");
1179 result << wxString::Format(
": %0.1f %s", userwindspeed,
1180 getUsrWindSpeedUnit())
1181 << wxString::Format(
" %d%c ", met_data.wind_dir, 0x00B0);
1184 if (met_data.water_lev_dev < 30.) {
1185 if (result.Len()) result <<
"\n";
1186 result << _(
"Water level deviation");
1188 userdepth =
toUsrDepth(met_data.water_lev_dev);
1189 result << wxString::Format(
": %.1f %s", userdepth, getUsrDepthUnit());
1191 }
else if (met_data.water_level > -32.) {
1192 if (result.Len()) result <<
"\n";
1193 result << _(
"Water level");
1195 userdepth =
toUsrDepth(met_data.water_level);
1196 result << wxString::Format(
": %.1f %s", userdepth, getUsrDepthUnit());
1199 if (met_data.current < 25.) {
1200 if (result.Len()) result <<
"\n";
1201 result << _(
"Current");
1202 result << wxString::Format(
": %.1f ", met_data.current) << _(
"kts")
1203 << wxString::Format(
" %d%c ", met_data.curr_dir, 0x00B0);
1206 if (met_data.wave_height < 24.6) {
1207 if (result.Len()) result <<
"\n";
1208 double userwh =
toUsrDepth(met_data.wave_height);
1209 result << _(
"Wave height")
1210 << wxString::Format(
": %.1f %s", userwh, getUsrDepthUnit())
1211 <<
" / " << met_data.wave_period <<
" " << _(
"s");
1214 if (met_data.water_temp < 50.) {
1215 if (result.Len()) result <<
"\n";
1216 double usertemp =
toUsrTemp(met_data.water_temp);
1217 result << _(
"Water temp");
1218 result << wxString::Format(
": %.1f%c", usertemp, 0x00B0)
1219 << getUsrTempUnit();
1222 if (met_data.air_temp != -102.4) {
1223 if (result.Len()) result <<
"\n";
1224 double usertemp =
toUsrTemp(met_data.air_temp);
1225 result << _(
"Air temp");
1226 result << wxString::Format(
": %.1f%c", usertemp, 0x00B0)
1227 << getUsrTempUnit() <<
" ";
1230 if (met_data.airpress > 799 && met_data.airpress < 1310) {
1231 if (met_data.air_temp == -102.4 && result.Len()) result <<
"\n";
1232 result << _(
"Air press");
1233 result << wxString::Format(
": %d hPa", met_data.airpress);
1236 if (met_data.hor_vis < 12.) {
1237 if (result.Len()) result <<
"\n";
1240 wxString::Format(
": %s%.1f %s", (met_data.hor_vis_GT ?
">" :
""),
1241 userVisDist, getUsrDistanceUnit());
1242 result << _(
"Visibility") << horVis;
1248wxString AisTargetData::Get_vessel_type_string(
bool b_short) {
1250 if (Class == AIS_ATON) {
1304 if ((Class == AIS_CLASS_B) || (Class == AIS_CLASS_A)) {
1305 if ((ShipType >= 40) && (ShipType < 50)) i = 8;
1307 if ((ShipType >= 60) && (ShipType < 70)) i = 16;
1309 if ((ShipType >= 70) && (ShipType < 80)) i = 17;
1311 if ((ShipType >= 80) && (ShipType < 90)) i = 18;
1312 }
else if (Class == AIS_GPSG_BUDDY)
1314 else if (Class == AIS_ARPA)
1316 else if (Class == AIS_APRS)
1318 else if (Class == AIS_BUOY)
1320 else if (Class == AIS_DSC)
1321 i = (ShipType == 12 || ShipType == 16) ? 54 : 53;
1324 return ais_get_type(i);
1326 return ais_get_short_type(i);
1329wxString AisTargetData::Get_class_string(
bool b_short) {
1336 return b_short ? _(
"AtoN") : _(
"Aid to Navigation");
1338 return b_short ? _(
"Base") : _(
"Base Station");
1339 case AIS_GPSG_BUDDY:
1340 return b_short ? _(
"Buddy") : _(
"GPSGate Buddy");
1342 if (ShipType == 12 || (ShipType == 16 && m_dscNature < 13))
1343 return b_short ? _(
"DSC") : _(
"DSC Distress");
1345 return b_short ? _(
"DSC") : _(
"DSC Position Report");
1347 return b_short ? _(
"SART") : _(
"SART");
1349 return b_short ? _(
"ARPA") : _(
"ARPA");
1351 return b_short ? _(
"Buoy") : _(
"BUOY");
1353 return b_short ? _(
"APRS") : _(
"APRS Position Report");
1355 return b_short ? _(
"Meteo") : _(
"Meteorologic");
1358 return b_short ? _(
"Unk") : _(
"Unknown");
1362wxString AisTargetData::GetNatureofDistress(
int dscnature) {
1364 wxString dscDistressType[] = {_(
"Fire, explosion"),
1368 _(
"Listing, in danger of capsizing"),
1370 _(
"Disabled and adrift"),
1371 _(
"Undesignated distress"),
1372 _(
"Abandoning ship"),
1373 _(
"Piracy/armed robbery attack"),
1376 _(
"EPIRB emission")};
1377 if (dscnature >= 0 && dscnature < 13)
return dscDistressType[dscnature];
1382void AisTargetData::Toggle_AIS_CPA() {
1383 b_show_AIS_CPA = !b_show_AIS_CPA ? true :
false;
1386void AisTargetData::ToggleShowTrack() {
1387 b_show_track = !b_show_track ? true :
false;
1390bool AisTargetData::IsValidMID(
int mid) {
1391 if (mid >= 201 && mid <= 775)
return true;
1397wxString AisTargetData::GetCountryCode(
bool b_CntryLongStr) {
1398 if (Class == AIS_BUOY)
return "";
1401 int tmpMmsi = met_data.original_mmsi ? met_data.original_mmsi : MMSI;
1403 int nMID = tmpMmsi / 1000000;
1404 if (!IsValidMID(nMID) || Class == AIS_ATON) {
1407 if (tmpMmsi < 1000 || 97 == tmpMmsi / 10000000)
return "";
1412 bool foundMID =
false;
1414 i = nMID > 900 ? 2 : 0;
1415 for (i; i < s_mmsi.length() - 3; i++) {
1416 nMID = wxAtoi(s_mmsi.Mid(i, 3));
1417 if (IsValidMID(nMID)) {
1422 if (!foundMID)
return "";
1425#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
1429 return b_CntryLongStr ? _(
"Albania") :
"AL";
1431 return b_CntryLongStr ? _(
"Andorra") :
"AD";
1433 return b_CntryLongStr ? _(
"Austria") :
"AT";
1435 return b_CntryLongStr ? _(
"Azores") :
"AZ";
1437 return b_CntryLongStr ? _(
"Belgium") :
"BE";
1439 return b_CntryLongStr ? _(
"Belarus") :
"BY";
1441 return b_CntryLongStr ? _(
"Bulgaria") :
"BG";
1443 return b_CntryLongStr ? _(
"Vatican City State") :
"VA";
1446 return b_CntryLongStr ? _(
"Cyprus") :
"CY";
1448 return b_CntryLongStr ? _(
"Germany") :
"DE";
1450 return b_CntryLongStr ? _(
"Cyprus") :
"CY";
1452 return b_CntryLongStr ? _(
"Georgia") :
"GE";
1454 return b_CntryLongStr ? _(
"Moldova") :
"MD";
1456 return b_CntryLongStr ? _(
"Malta") :
"MT";
1458 return b_CntryLongStr ? _(
"Armenia") :
"AM";
1460 return b_CntryLongStr ? _(
"Germany") :
"DE";
1463 return b_CntryLongStr ? _(
"Denmark") :
"DK";
1465 return b_CntryLongStr ? _(
"Spain") :
"ES";
1467 return b_CntryLongStr ? _(
"Spain") :
"ES";
1471 return b_CntryLongStr ? _(
"France") :
"FR";
1473 return b_CntryLongStr ? _(
"Malta") :
"MT";
1475 return b_CntryLongStr ? _(
"Finland") :
"FI";
1477 return b_CntryLongStr ? _(
"Faroe Islands") :
"FO";
1482 return b_CntryLongStr ? _(
"Great Britain") :
"GB";
1484 return b_CntryLongStr ? _(
"Gibraltar") :
"GI";
1486 return b_CntryLongStr ? _(
"Greece") :
"GR";
1488 return b_CntryLongStr ? _(
"Croatia") :
"HR";
1492 return b_CntryLongStr ? _(
"Greece") :
"GR";
1494 return b_CntryLongStr ? _(
"Morocco") :
"MA";
1496 return b_CntryLongStr ? _(
"Hungary") :
"HU";
1500 return b_CntryLongStr ? _(
"Netherlands") :
"NL";
1502 return b_CntryLongStr ? _(
"Italy") :
"IT";
1505 return b_CntryLongStr ? _(
"Malta") :
"MT";
1507 return b_CntryLongStr ? _(
"Ireland") :
"IE";
1509 return b_CntryLongStr ? _(
"Iceland") :
"IS";
1511 return b_CntryLongStr ? _(
"Liechtenstein") :
"LI";
1513 return b_CntryLongStr ? _(
"Luxembourg") :
"LU";
1515 return b_CntryLongStr ? _(
"Monaco") :
"MC";
1517 return b_CntryLongStr ? _(
"Madeira") :
"PT";
1519 return b_CntryLongStr ? _(
"Malta") :
"MT";
1523 return b_CntryLongStr ? _(
"Norway") :
"NO";
1525 return b_CntryLongStr ? _(
"Poland") :
"PL";
1527 return b_CntryLongStr ? _(
"Montenegro") :
"ME";
1529 return b_CntryLongStr ? _(
"Portugal") :
"PT";
1531 return b_CntryLongStr ? _(
"Romania") :
"RO";
1534 return b_CntryLongStr ? _(
"Sweden") :
"SE";
1536 return b_CntryLongStr ? _(
"Slovak Republic") :
"SK";
1538 return b_CntryLongStr ? _(
"San Marino") :
"SM";
1540 return b_CntryLongStr ? _(
"Switzerland") :
"CH";
1542 return b_CntryLongStr ? _(
"Czech Republic") :
"CZ";
1544 return b_CntryLongStr ? _(
"Turkey") :
"TR";
1546 return b_CntryLongStr ? _(
"Ukraine") :
"UA";
1548 return b_CntryLongStr ? _(
"Russian") :
"RU";
1550 return b_CntryLongStr ? _(
"Macedonia") :
"MK";
1552 return b_CntryLongStr ? _(
"Latvia") :
"LV";
1554 return b_CntryLongStr ? _(
"Estonia") :
"EE";
1556 return b_CntryLongStr ? _(
"Lithuania") :
"LT";
1558 return b_CntryLongStr ? _(
"Slovenia") :
"SI";
1560 return b_CntryLongStr ? _(
"Serbia") :
"RS";
1562 return b_CntryLongStr ? _(
"Anguilla") :
"AI";
1564 return b_CntryLongStr ? _(
"Alaska") :
"AK";
1567 return b_CntryLongStr ? _(
"Antigua and Barbuda") :
"AG";
1569 return b_CntryLongStr ? _(
"Antilles") :
"AN";
1571 return b_CntryLongStr ? _(
"Aruba") :
"AW";
1574 return b_CntryLongStr ? _(
"Bahamas") :
"BS";
1576 return b_CntryLongStr ? _(
"Bermuda") :
"BM";
1578 return b_CntryLongStr ? _(
"Bahamas") :
"BS";
1580 return b_CntryLongStr ? _(
"Belize") :
"BZ";
1582 return b_CntryLongStr ? _(
"Barbados") :
"BB";
1584 return b_CntryLongStr ? _(
"Canada") :
"CA";
1586 return b_CntryLongStr ? _(
"Cayman Islands") :
"KY";
1588 return b_CntryLongStr ? _(
"Costa Rica") :
"CR";
1590 return b_CntryLongStr ? _(
"Cuba") :
"CU";
1592 return b_CntryLongStr ? _(
"Dominica") :
"DM";
1594 return b_CntryLongStr ? _(
"Dominican Republic") :
"DM";
1596 return b_CntryLongStr ? _(
"Guadeloupe") :
"GP";
1598 return b_CntryLongStr ? _(
"Grenada") :
"GD";
1600 return b_CntryLongStr ? _(
"Greenland") :
"GL";
1602 return b_CntryLongStr ? _(
"Guatemala") :
"GT";
1604 return b_CntryLongStr ? _(
"Honduras") :
"HN";
1606 return b_CntryLongStr ? _(
"Haiti") :
"HT";
1608 return b_CntryLongStr ? _(
"United States of America") :
"US";
1610 return b_CntryLongStr ? _(
"Jamaica") :
"JM";
1612 return b_CntryLongStr ? _(
"Saint Kitts and Nevis") :
"KN";
1614 return b_CntryLongStr ? _(
"Saint Lucia") :
"LC";
1616 return b_CntryLongStr ? _(
"Mexico") :
"MX";
1618 return b_CntryLongStr ? _(
"Martinique") :
"MQ";
1620 return b_CntryLongStr ? _(
"Montserrat") :
"MS";
1622 return b_CntryLongStr ? _(
"Nicaragua") :
"NI";
1630 return b_CntryLongStr ? _(
"Panama") :
"PA";
1632 return b_CntryLongStr ? _(
"Puerto Rico") :
"PR";
1634 return b_CntryLongStr ? _(
"El Salvador") :
"SV";
1636 return b_CntryLongStr ? _(
"Saint Pierre and Miquelon") :
"PM";
1638 return b_CntryLongStr ? _(
"Trinidad and Tobago") :
"TT";
1640 return b_CntryLongStr ? _(
"Turks and Caicos Islands") :
"TC";
1645 return b_CntryLongStr ? _(
"United States of America") :
"US";
1651 return b_CntryLongStr ? _(
"Panama") :
"PA";
1655 return b_CntryLongStr ? _(
"Saint Vincent and the Grenadines") :
"VC";
1657 return b_CntryLongStr ? _(
"British Virgin Islands") :
"VG";
1659 return b_CntryLongStr ? _(
"United States Virgin Islands") :
"AE";
1661 return b_CntryLongStr ? _(
"Afghanistan") :
"AF";
1663 return b_CntryLongStr ? _(
"Saudi Arabia") :
"SA";
1665 return b_CntryLongStr ? _(
"Bangladesh") :
"BD";
1667 return b_CntryLongStr ? _(
"Bahrain") :
"BH";
1669 return b_CntryLongStr ? _(
"Bhutan") :
"BT";
1673 return b_CntryLongStr ? _(
"China") :
"CN";
1675 return b_CntryLongStr ? _(
"Taiwan") :
"TW";
1677 return b_CntryLongStr ? _(
"Sri Lanka") :
"LK";
1679 return b_CntryLongStr ? _(
"India") :
"IN";
1681 return b_CntryLongStr ? _(
"Iran") :
"IR";
1683 return b_CntryLongStr ? _(
"Azerbaijani Republic") :
"AZ";
1685 return b_CntryLongStr ? _(
"Iraq") :
"IQ";
1687 return b_CntryLongStr ? _(
"Israel") :
"IL";
1689 return b_CntryLongStr ? _(
"Japan") :
"JP";
1691 return b_CntryLongStr ? _(
"Japan") :
"JP";
1693 return b_CntryLongStr ? _(
"Turkmenistan") :
"TM";
1695 return b_CntryLongStr ? _(
"Kazakhstan") :
"KZ";
1697 return b_CntryLongStr ? _(
"Uzbekistan") :
"UZ";
1699 return b_CntryLongStr ? _(
"Jordan") :
"JO";
1702 return b_CntryLongStr ? _(
"Korea") :
"KR";
1704 return b_CntryLongStr ? _(
"Palestine") :
"PS";
1706 return b_CntryLongStr ? _(
"People's Rep. of Korea") :
"KP";
1708 return b_CntryLongStr ? _(
"Kuwait") :
"KW";
1710 return b_CntryLongStr ? _(
"Lebanon") :
"LB";
1712 return b_CntryLongStr ? _(
"Kyrgyz Republic") :
"KG";
1714 return b_CntryLongStr ? _(
"Macao") :
"MO";
1716 return b_CntryLongStr ? _(
"Maldives") :
"MV";
1718 return b_CntryLongStr ? _(
"Mongolia") :
"MN";
1720 return b_CntryLongStr ? _(
"Nepal") :
"NP";
1722 return b_CntryLongStr ? _(
"Oman") :
"OM";
1724 return b_CntryLongStr ? _(
"Pakistan") :
"PK";
1726 return b_CntryLongStr ? _(
"Qatar") :
"QA";
1728 return b_CntryLongStr ? _(
"Syrian Arab Republic") :
"SY";
1731 return b_CntryLongStr ? _(
"United Arab Emirates") :
"AE";
1733 return b_CntryLongStr ? _(
"Tajikistan") :
"TJ";
1736 return b_CntryLongStr ? _(
"Yemen") :
"YE";
1738 return b_CntryLongStr ? _(
"Hong Kong") :
"HK";
1740 return b_CntryLongStr ? _(
"Bosnia and Herzegovina") :
"BA";
1742 return b_CntryLongStr ? _(
"Adelie Land") :
"TF";
1744 return b_CntryLongStr ? _(
"Australia") :
"AU";
1746 return b_CntryLongStr ? _(
"Myanmar") :
"MM";
1748 return b_CntryLongStr ? _(
"Brunei Darussalam") :
"BN";
1750 return b_CntryLongStr ? _(
"Micronesia") :
"FM";
1752 return b_CntryLongStr ? _(
"Palau") :
"PW";
1754 return b_CntryLongStr ? _(
"New Zealand") :
"NZ";
1757 return b_CntryLongStr ? _(
"Cambodia") :
"KH";
1759 return b_CntryLongStr ? _(
"Christmas Island") :
"CX";
1761 return b_CntryLongStr ? _(
"Cook Islands") :
"CK";
1763 return b_CntryLongStr ? _(
"Fiji") :
"FJ";
1765 return b_CntryLongStr ? _(
"Cocos (Keeling) Islands") :
"CC";
1767 return b_CntryLongStr ? _(
"Indonesia") :
"ID";
1769 return b_CntryLongStr ? _(
"Kiribati") :
"KI";
1771 return b_CntryLongStr ? _(
"Lao People's Dem. Rep.") :
"LA";
1773 return b_CntryLongStr ? _(
"Malaysia") :
"MY";
1775 return b_CntryLongStr ? _(
"Northern Mariana Islands") :
"MP";
1777 return b_CntryLongStr ? _(
"Marshall Islands") :
"MH";
1779 return b_CntryLongStr ? _(
"New Caledonia") :
"NC";
1781 return b_CntryLongStr ? _(
"Niue") :
"NU";
1783 return b_CntryLongStr ? _(
"Nauru") :
"NR";
1785 return b_CntryLongStr ? _(
"French Polynesia") :
"PF";
1787 return b_CntryLongStr ? _(
"Philippines") :
"PH";
1789 return b_CntryLongStr ? _(
"East Timor") :
"TL";
1791 return b_CntryLongStr ? _(
"Papua New Guinea") :
"PG";
1793 return b_CntryLongStr ? _(
"Pitcairn Island") :
"PN";
1795 return b_CntryLongStr ? _(
"Solomon Islands") :
"SB";
1797 return b_CntryLongStr ? _(
"American Samoa") :
"AS";
1799 return b_CntryLongStr ? _(
"Samoa") :
"WS";
1804 return b_CntryLongStr ? _(
"Singapore") :
"SG";
1806 return b_CntryLongStr ? _(
"Thailand") :
"TH";
1808 return b_CntryLongStr ? _(
"Tonga") :
"TO";
1810 return b_CntryLongStr ? _(
"Tuvalu") :
"TV";
1812 return b_CntryLongStr ? _(
"Viet Nam") :
"VN";
1815 return b_CntryLongStr ? _(
"Vanuatu") :
"VU";
1817 return b_CntryLongStr ? _(
"Wallis and Futuna Islands") :
"WF";
1819 return b_CntryLongStr ? _(
"South Africa") :
"ZA";
1821 return b_CntryLongStr ? _(
"Angola") :
"AO";
1823 return b_CntryLongStr ? _(
"Algeria") :
"DZ";
1825 return b_CntryLongStr ? _(
"Saint Paul") :
"TF";
1827 return b_CntryLongStr ? _(
"Ascension Island") :
"SH";
1829 return b_CntryLongStr ? _(
"Burundi") :
"BI";
1831 return b_CntryLongStr ? _(
"Benin") :
"BJ";
1833 return b_CntryLongStr ? _(
"Botswana") :
"BW";
1835 return b_CntryLongStr ? _(
"Central African Republic") :
"CF";
1837 return b_CntryLongStr ? _(
"Cameroon") :
"CM";
1839 return b_CntryLongStr ? _(
"Congo") :
"CD";
1841 return b_CntryLongStr ? _(
"Comoros") :
"KM";
1843 return b_CntryLongStr ? _(
"Capo Verde") :
"CV";
1845 return b_CntryLongStr ? _(
"Crozet Archipelago") :
"TF";
1847 return b_CntryLongStr ? _(
"Ivory Coast") :
"CI";
1849 return b_CntryLongStr ? _(
"Comoros (Union of the)") :
"KM";
1851 return b_CntryLongStr ? _(
"Djibouti") :
"DJ";
1853 return b_CntryLongStr ? _(
"Egypt") :
"EG";
1855 return b_CntryLongStr ? _(
"Ethiopia") :
"ET";
1857 return b_CntryLongStr ? _(
"Eritrea") :
"ER";
1859 return b_CntryLongStr ? _(
"Gabonese Republic") :
"GA";
1861 return b_CntryLongStr ? _(
"Ghana") :
"GH";
1863 return b_CntryLongStr ? _(
"Gambia") :
"GM";
1865 return b_CntryLongStr ? _(
"Guinea-Bissau") :
"GW";
1867 return b_CntryLongStr ? _(
"Equatorial Guinea") :
"GQ";
1869 return b_CntryLongStr ? _(
"Guinea") :
"GN";
1871 return b_CntryLongStr ? _(
"Burkina Faso") :
"BF";
1873 return b_CntryLongStr ? _(
"Kenya") :
"KE";
1875 return b_CntryLongStr ? _(
"Kerguelen Islands") :
"TF";
1878 return b_CntryLongStr ? _(
"Liberia") :
"LR";
1880 return b_CntryLongStr ? _(
"South Sudan (Republic of)") :
"SS";
1882 return b_CntryLongStr ? _(
"Libya") :
"LY";
1884 return b_CntryLongStr ? _(
"Lesotho") :
"LS";
1886 return b_CntryLongStr ? _(
"Mauritius") :
"MU";
1888 return b_CntryLongStr ? _(
"Madagascar") :
"MG";
1890 return b_CntryLongStr ? _(
"Mali") :
"ML";
1892 return b_CntryLongStr ? _(
"Mozambique") :
"MZ";
1894 return b_CntryLongStr ? _(
"Mauritania") :
"MR";
1896 return b_CntryLongStr ? _(
"Malawi") :
"MW";
1898 return b_CntryLongStr ? _(
"Niger") :
"NE";
1900 return b_CntryLongStr ? _(
"Nigeria") :
"NG";
1902 return b_CntryLongStr ? _(
"Namibia") :
"NA";
1904 return b_CntryLongStr ? _(
"Reunion") :
"RE";
1906 return b_CntryLongStr ? _(
"Rwanda") :
"RW";
1908 return b_CntryLongStr ? _(
"Sudan") :
"SD";
1910 return b_CntryLongStr ? _(
"Senegal") :
"SN";
1912 return b_CntryLongStr ? _(
"Seychelles") :
"SC";
1914 return b_CntryLongStr ? _(
"Saint Helena") :
"SH";
1916 return b_CntryLongStr ? _(
"Somalia") :
"SO";
1918 return b_CntryLongStr ? _(
"Sierra Leone") :
"SL";
1920 return b_CntryLongStr ? _(
"Sao Tome and Principe") :
"ST";
1922 return b_CntryLongStr ? _(
"Eswatini") :
"SZ";
1924 return b_CntryLongStr ? _(
"Chad") :
"TD";
1926 return b_CntryLongStr ? _(
"Togolese Republic") :
"TG";
1928 return b_CntryLongStr ? _(
"Tunisia") :
"TN";
1930 return b_CntryLongStr ? _(
"Tanzania") :
"TZ";
1932 return b_CntryLongStr ? _(
"Uganda") :
"UG";
1934 return b_CntryLongStr ? _(
"Dem Rep.of the Congo") :
"CD";
1936 return b_CntryLongStr ? _(
"Tanzania") :
"TZ";
1938 return b_CntryLongStr ? _(
"Zambia") :
"ZM";
1940 return b_CntryLongStr ? _(
"Zimbabwe") :
"ZW";
1942 return b_CntryLongStr ? _(
"Argentine Republic") :
"AR";
1944 return b_CntryLongStr ? _(
"Brazil") :
"BR";
1946 return b_CntryLongStr ? _(
"Bolivia") :
"BO";
1948 return b_CntryLongStr ? _(
"Chile") :
"CL";
1950 return b_CntryLongStr ? _(
"Colombia") :
"CO";
1952 return b_CntryLongStr ? _(
"Ecuador") :
"EC";
1954 return b_CntryLongStr ? _(
"Falkland Islands") :
"FK";
1956 return b_CntryLongStr ? _(
"France - Guiana") :
"GY";
1958 return b_CntryLongStr ? _(
"Guyana") :
"GY";
1960 return b_CntryLongStr ? _(
"Paraguay") :
"PY";
1962 return b_CntryLongStr ? _(
"Peru") :
"PE";
1964 return b_CntryLongStr ? _(
"Suriname") :
"SR";
1966 return b_CntryLongStr ? _(
"Uruguay") :
"UY";
1968 return b_CntryLongStr ? _(
"Venezuela") :
"VE";
1978wxString ais_get_type(
int index) {
1979 static const wxString ais_type[] = {
1980 _(
"Fishing Vessel"),
1982 _(
"Towing Vessel, Long"),
1984 _(
"Diving Ops Vessel"),
1985 _(
"Military Vessel"),
1986 _(
"Sailing Vessel"),
1987 _(
"Pleasure craft"),
1988 _(
"High Speed Craft"),
1990 _(
"Search and Rescue Vessel"),
1993 _(
"Pollution Control Vessel"),
1994 _(
"Law Enforcement Vessel"),
1995 _(
"Medical Transport"),
1996 _(
"Passenger Ship"),
2001 _(
"Reference Point"),
2003 _(
"Fixed Structure"),
2006 _(
"Light w/Sectors"),
2007 _(
"Leading Light Front"),
2008 _(
"Leading Light Rear"),
2009 _(
"Cardinal N Beacon"),
2010 _(
"Cardinal E Beacon"),
2011 _(
"Cardinal S Beacon"),
2012 _(
"Cardinal W Beacon"),
2013 _(
"Beacon, Port Hand"),
2014 _(
"Beacon, Starboard Hand"),
2015 _(
"Beacon, Preferred Channel Port Hand"),
2016 _(
"Beacon, Preferred Channel Starboard Hand"),
2017 _(
"Beacon, Isolated Danger"),
2018 _(
"Beacon, Safe Water"),
2019 _(
"Beacon, Special Mark"),
2020 _(
"Cardinal Mark N"),
2021 _(
"Cardinal Mark E"),
2022 _(
"Cardinal Mark S"),
2023 _(
"Cardinal Mark W"),
2024 _(
"Port Hand Mark"),
2025 _(
"Starboard Hand Mark"),
2026 _(
"Preferred Channel Port Hand"),
2027 _(
"Preferred Channel Starboard Hand"),
2028 _(
"Isolated Danger"),
2031 _(
"Light Vessel/Rig"),
2033 _(
"Position Report"),
2035 _(
"ARPA radar target"),
2036 _(
"APRS Position Report"),
2037 _(
"Buoy or similar")
2040 return ais_type[index];
2043wxString ais_get_short_type(
int index) {
2044 static const wxString short_ais_type[] = {
2103 _(
"Buoy or similar")
2105 return short_ais_type[index];
Global state for AIS decoder.
Global variables stored in configuration file.
double toUsrDepth(double m_depth, int unit)
Convert a depth from meters to user display units.
double toUsrTemp(double cel_temp, int unit)
Convert a temperature from Celsius to user display units.
double toUsrDistance(double nm_distance, int unit)
Convert a distance from nautical miles (NMi) to user display units.
wxString FormatDistanceAdaptive(double distance)
Format a distance (given in nautical miles) using the current distance preference,...
Navigation Utility Functions without GUI dependencies.
bool bGPSValid
Indicate whether the Global Navigation Satellite System (GNSS) has a valid position.
Position, course, speed, etc.