OpenCPN Partial API docs
Loading...
Searching...
No Matches
ais_target_data.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * Copyright (C) 2010 by David S. Register *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, see <https://www.gnu.org/licenses/>. *
16 **************************************************************************/
17
24#include <unordered_map>
25
26#include <wx/datetime.h>
27#include <wx/intl.h>
28#include <wx/string.h>
29
32#include "model/config_vars.h"
33#include "model/navutil_base.h"
34#include "model/own_ship.h"
35
36static std::unordered_map<int, wxString> s_ERI_hash;
37
38void make_hash_ERI(int key, const wxString &description) {
39 s_ERI_hash[key] = description;
40}
41
42void clear_hash_ERI() { s_ERI_hash.clear(); }
43
44static wxString FormatTimeAdaptive(int seconds) {
45 int m = seconds / 60;
46 if (seconds < 100)
47 return wxString::Format("%3ds", seconds);
48 else if (seconds < 3600) {
49 int m = seconds / 60;
50 int s = seconds % 60;
51 return wxString::Format("%2dmin %02ds", m, s);
52 }
53 int h = seconds / 3600;
54 m -= h * 60;
55 return wxString::Format("%2dh %02dmin", h, m);
56}
57
58static wxString html_escape(const wxString &src) {
59 // Escape &, <, > as well as single and double quotes for HTML.
60 wxString ret = src;
61
62 ret.Replace("<", "&lt;");
63 ret.Replace(">", "&gt;");
64
65 // only < and > in 6 bits AIS ascii
66 // ret.Replace("\"", "&quot;");
67 // ret.Replace("&", "&amp;");
68 // ret.Replace("'", "&#39;");
69
70 // Do we care about multiple spaces?
71 // ret.Replace(" ", "&nbsp;");
72 return ret;
73}
74
75wxString trimAISField(char *data) {
76 // Clip any unused characters (@) from data
77
78 wxString field = wxString::From8BitData(data);
79 while (field.Right(1) == '@' || field.Right(1) == ' ') field.RemoveLast();
80
81 // And remove any leading spaces to properly sort and display
82 field.Trim(false);
83
84 return field;
85}
86
87wxString ais_get_status(int index) {
88 static const wxString ais_status[] = {
89 _("Underway using Engine"),
90 _("At Anchor"),
91 _("Not Under Command"),
92 _("Restricted Manoeuvrability"),
93 _("Constrained by draught"),
94 _("Moored"),
95 _("Aground"),
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)"),
102 _("Reserved 13"),
103 _("Reserved 14"),
104 _("Undefined"),
105 _("AtoN Virtual"),
106 _("AtoN Virtual (On Position)"),
107 _("AtoN Virtual (Off Position)"),
108 _("AtoN Real"),
109 _("AtoN Real (On Position)"),
110 _("AtoN Real(Off Position)")};
111
112 return ais_status[index];
113}
114
115wxString ais_meteo_get_trend(int tend) {
116 wxString trend = "";
117 if (tend < 3) {
118 if (tend == 0)
119 trend = _("steady");
120 else if (tend == 1)
121 trend = _("decreasing");
122 else if (tend == 2)
123 trend = _("increasing");
124 }
125 return trend;
126}
127
128wxString aisMeteoPrecipType(int precip) {
129 wxString prec = "";
130 switch (precip) {
131 case 0:
132 prec = "Reserved";
133 break;
134 case 1:
135 prec = "Rain";
136 break;
137 case 2:
138 prec = "Thunderstorm";
139 break;
140 case 3:
141 prec = "Freezing rain";
142 break;
143 case 4:
144 prec = "Mixed / ice";
145 break;
146 case 5:
147 prec = "Snow";
148 break;
149 default:
150 prec = "not available";
151 // 6 = reserved 7 = not available = default
152 }
153 return prec;
154}
155
156wxString aisMeteoWaterLevelRef(int refID) {
157 wxString ref = "";
158 switch (refID) {
159 case 0:
160 ref = "MLLW";
161 break;
162 case 1:
163 ref = "IGLD-85";
164 break;
165 case 2:
166 ref = "Local river";
167 break;
168 case 3:
169 ref = "STND";
170 break;
171 case 4:
172 ref = "MHHW";
173 break;
174 case 5:
175 ref = "MHW";
176 break;
177 case 6:
178 ref = "MSL";
179 break;
180 case 7:
181 ref = "MLW";
182 break;
183 case 8:
184 ref = "NGVD-29";
185 break;
186 case 9:
187 ref = "NAVD-88";
188 break;
189 case 10:
190 ref = "WGS-84";
191 break;
192 case 11:
193 ref = "LAT";
194 break;
195 case 12:
196 ref = "Pool";
197 break;
198 case 13:
199 ref = "Gauge";
200 break;
201 }
202 return ref;
203}
204
205AisTargetData::AisTargetData(AisTargetCallbacks cb) : m_callbacks(cb) {
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;
211
212 SOG = 555.;
213 COG = 666.;
214 HDG = 511.;
215 ROTAIS = -128;
216 Lat = 0.;
217 Lon = 0.;
218
219 wxDateTime now = wxDateTime::Now();
220 now.MakeGMT();
221 PositionReportTicks = now.GetTicks(); // Default is my idea of NOW
222 StaticReportTicks = now.GetTicks();
223 b_lost = false;
224 b_removed = false;
225
226 IMO = 0;
227 MID = 555;
228 MMSI = 666;
229 NavStatus = UNDEFINED;
230 SyncState = 888;
231 SlotTO = 999;
232 ShipType = 19; // "Unknown"
233 b_isDSCtarget = false;
234 m_dscNature = 99;
235 m_dscTXmmsi = 666;
236
237 CPA = 100; // Large values avoid false alarms
238 TCPA = 100;
239
240 Range_NM = -1.;
241 Brg = -1.;
242
243 DimA = DimB = DimC = DimD = 0;
244 ;
245
246 ETA_Mo = 0;
247 ETA_Day = 0;
248 ETA_Hr = 24;
249 ETA_Min = 60;
250
251 Draft = 0.;
252
253 RecentPeriod = 0;
254
255 m_utc_hour = 0;
256 m_utc_min = 0;
257 m_utc_sec = 0;
258
259 Class = AIS_CLASS_A; // default
260 n_alert_state = AIS_NO_ALERT;
261 b_suppress_audio = false;
262 b_positionDoubtful = false;
263 b_positionOnceValid = false;
264 b_nameValid = false;
265 b_VDM_secure_Pos = false;
266
267 Euro_Length = 0; // Extensions for European Inland AIS
268 Euro_Beam = 0;
269 Euro_Draft = 0;
270 strncpy(Euro_VIN, " ", 8);
271 UN_shiptype = 0;
272
273 b_isEuroInland = false;
274 b_blue_paddle = false;
275
276 b_NoTrack = false;
277 b_OwnShip = false;
278 b_PersistTrack = false;
279 b_mPropPersistTrack = false;
280 b_in_ack_timeout = false;
281
282 b_active = false;
283 blue_paddle = 0;
284 bCPA_Valid = false;
285 b_isFollower = false;
286 ROTIND = 0;
287 b_show_track = g_bAISShowTracks;
288 b_SarAircraftPosnReport = false;
289 altitude = 0;
290 b_nameFromCache = false;
291 importance = 0.0;
292 for (unsigned int i = 0; i < AIS_TARGETDATA_MAX_CANVAS; i++)
293 last_scale[i] = 50;
294 met_data.original_mmsi = 0;
295 met_data.stationID = 0;
296 met_data.month = 0;
297 met_data.day = 0;
298 met_data.hour = 24;
299 met_data.minute = 60;
300 met_data.pos_acc = 1;
301 met_data.wind_kn = 122;
302 met_data.wind_gust_kn = 127;
303 met_data.wind_dir = 360;
304 met_data.wind_gust_dir = 360;
305 met_data.air_temp = -102.4;
306 met_data.rel_humid = 101;
307 met_data.dew_point = 50.1;
308 met_data.airpress = 1310;
309 met_data.airpress_tend = 3;
310 met_data.hor_vis = 12.7;
311 met_data.hor_vis_GT = false;
312 met_data.water_lev_dev = 4001 / 100 - 10;
313 met_data.water_level = -32;
314 met_data.water_lev_trend = 3;
315 met_data.current = 25.5;
316 met_data.curr_dir = 360;
317 met_data.wave_height = 25.5;
318 met_data.wave_period = 63;
319 met_data.wave_dir = 360;
320 met_data.swell_height = 25.5;
321 met_data.swell_per = 63;
322 met_data.swell_dir = 360;
323 met_data.seastate = 13;
324 met_data.water_temp = 501;
325 met_data.precipitation = 7;
326 met_data.salinity = 51.;
327 met_data.ice = 3;
328 met_data.vertical_ref = 14;
329}
330
331void AisTargetData::CloneFrom(AisTargetData *q) {
332 strncpy(ShipName, q->ShipName, SHIP_NAME_LEN);
333 strncpy(CallSign, q->CallSign, 8);
334 strncpy(Destination, q->Destination, DESTINATION_LEN);
335 ShipNameExtension[0] = 0;
336 b_show_AIS_CPA = q->b_show_AIS_CPA;
337 ;
338
339 SOG = q->SOG;
340 COG = q->COG;
341 HDG = q->HDG;
342 ROTAIS = q->ROTAIS;
343 Lat = q->Lat;
344 Lon = q->Lon;
345
346 PositionReportTicks = q->PositionReportTicks;
347 StaticReportTicks = q->StaticReportTicks;
348 b_lost = q->b_lost;
349 b_removed = q->b_removed;
350
351 IMO = q->IMO;
352 MID = q->MID;
353 MMSI = q->MMSI;
354 NavStatus = q->NavStatus;
355 SyncState = q->SyncState;
356 SlotTO = q->SlotTO;
357 ShipType = q->ShipType;
358 b_isDSCtarget = q->b_isDSCtarget;
359 m_dscNature = q->m_dscNature;
360 m_dscTXmmsi = q->m_dscTXmmsi;
361
362 CPA = q->CPA;
363 TCPA = q->TCPA;
364
365 Range_NM = q->Range_NM;
366 Brg = q->Brg;
367
368 DimA = q->DimA;
369 DimB = q->DimB;
370 DimC = q->DimC;
371 DimD = q->DimD;
372
373 ETA_Mo = q->ETA_Mo;
374 ETA_Day = q->ETA_Day;
375 ETA_Hr = q->ETA_Hr;
376 ETA_Min = q->ETA_Min;
377
378 Draft = q->Draft;
379
380 RecentPeriod = q->RecentPeriod;
381
382 m_utc_hour = q->m_utc_hour;
383 m_utc_min = q->m_utc_min;
384 m_utc_sec = q->m_utc_sec;
385
386 Class = q->Class;
387 n_alert_state = q->n_alert_state;
388 b_suppress_audio = q->b_suppress_audio;
389 b_positionDoubtful = q->b_positionDoubtful;
390 b_positionOnceValid = q->b_positionOnceValid;
391 b_nameValid = q->b_nameValid;
392
393 Euro_Length = q->Euro_Length; // Extensions for European Inland AIS
394 Euro_Beam = q->Euro_Beam;
395 Euro_Draft = q->Euro_Draft;
396 memcpy(Euro_VIN, q->Euro_VIN, EURO_VIN_LEN);
397 UN_shiptype = q->UN_shiptype;
398
399 b_isEuroInland = q->b_isEuroInland;
400 b_blue_paddle = q->b_blue_paddle;
401
402 b_OwnShip = q->b_OwnShip;
403 b_in_ack_timeout = q->b_in_ack_timeout;
404
405 m_ptrack = q->m_ptrack;
406
407 b_active = q->b_active;
408 blue_paddle = q->blue_paddle;
409 bCPA_Valid = q->bCPA_Valid;
410 ROTIND = q->ROTIND;
411 b_show_track = q->b_show_track;
412 b_SarAircraftPosnReport = q->b_SarAircraftPosnReport;
413 altitude = q->altitude;
414}
415
416AisTargetData::~AisTargetData() { m_ptrack.clear(); }
417// AisTargetData::~AisTargetData() { m_pMetPoint.clear(); } //TODO Needed?
418
419wxString AisTargetData::GetFullName() {
420 wxString retName;
421 if (b_nameValid) {
422 wxString shipName = trimAISField(ShipName);
423 if (shipName == "Unknown")
424 retName = wxGetTranslation(shipName);
425 else
426 retName = shipName;
427
428 if (strlen(ShipNameExtension)) {
429 wxString shipNameExt = trimAISField(ShipNameExtension);
430 retName += shipNameExt;
431 }
432 }
433
434 return retName;
435}
436
437wxString AisTargetData::BuildQueryResult() {
438 wxString html;
439 wxDateTime now = wxDateTime::Now();
440
441 wxString tableStart =
442 "\n<table width=100% border=0 cellpadding=1 cellspacing=0>\n";
443
444 wxString tableEnd = "</table>\n\n";
445 wxString rowStart = "<tr><td><font size=-2>";
446 wxString rowStartH = "<tr><td nowrap>";
447 wxString rowSeparator = "</font></td><td></td><td><b>";
448 wxString rowSeparatorH = "</td><td></td><td>";
449 wxString colSeparator = "<td></td>";
450 wxString rowEnd = "</b></td></tr>\n";
451 wxString vertSpacer = "<tr><td></td></tr>\n\n";
452
453 wxString IMOstr, MMSIstr, ClassStr;
454
455 html << tableStart << "<tr><td nowrap colspan=2>";
456 if (b_nameValid) {
457 html << "<font size=+2><i><b>" << GetFullName();
458 html << "</b></i></font>&nbsp;&nbsp;<b>";
459 }
460
461 if ((Class != AIS_ATON) && (Class != AIS_BASE) && (Class != AIS_GPSG_BUDDY) &&
462 (Class != AIS_SART) && (Class != AIS_METEO)) {
463 html << trimAISField(CallSign) << "</b>" << rowEnd;
464
465 if (Class != AIS_CLASS_B) {
466 if (IMO > 0) IMOstr = wxString::Format("%08d", abs(IMO));
467 }
468 } else
469 html << "</b>" << rowEnd;
470
471 html << vertSpacer;
472
473 if (Class != AIS_GPSG_BUDDY) {
474 MMSIstr = wxString::Format("%09d", abs(MMSI));
475 }
476 ClassStr = wxGetTranslation(Get_class_string(false));
477
478 if (Class == AIS_ATON) {
479 wxString cls("AtoN: ");
480 cls += Get_vessel_type_string(false);
481 ClassStr = wxGetTranslation(cls);
482 }
483
484 if (b_SarAircraftPosnReport) {
485 int airtype = (MMSI % 1000) / 100;
486 ClassStr = airtype == 5 ? _("SAR Helicopter") : _("SAR Aircraft");
487 }
488
489 if (IMOstr.Length())
490 html << "<tr><td colspan=2><table width=100% border=0 cellpadding=0 "
491 "cellspacing=0>"
492 << rowStart << _("MMSI")
493 << "</font></td><td>&nbsp;</td><td><font size=-2>" << _("Class")
494 << "</font></td><td>&nbsp;</td><td align=right><font size=-2>"
495 << _("IMO") << "</font></td></tr>" << rowStartH << "<b>" << MMSIstr
496 << "</b></td><td>&nbsp;</td><td><b>" << ClassStr
497 << "</b></td><td>&nbsp;</td><td align=right><b>" << IMOstr << rowEnd
498 << "</table></td></tr>";
499
500 else if (Class == AIS_METEO) {
501 MMSIstr = wxString::Format("%09d", abs(met_data.original_mmsi));
502 html << "<tr><td colspan=2><table width=100% border=0 cellpadding=0 "
503 "cellspacing=0>"
504 << rowStart << _("MMSI")
505 << "</font></td><td>&nbsp;</td><td align=right><font size=-2>"
506 << _("Class") << "</font></td></tr>" << rowStartH << "<b>" << MMSIstr
507 << "</b></td><td>&nbsp;</td><td align=right><b>"
508 << "<font size=-1>" << ClassStr << rowEnd << rowStart
509 << "<b>ID: " << MMSI;
510 if (met_data.stationID) { // Facilitate to find a Meteo target on SignalK
511 wxString SK_ID = wxString::Format("%06d", (met_data.stationID - 1000000));
512 html << "<td>&nbsp;</td><td align=right>"
513 << "SK-ID: " << SK_ID;
514 }
515 html << rowEnd << "</b></table></td></tr>";
516 } else
517 html << "<tr><td colspan=2><table width=100% border=0 cellpadding=0 "
518 "cellspacing=0>"
519 << rowStart << _("MMSI")
520 << "</font></td><td>&nbsp;</td><td align=right><font size=-2>"
521 << _("Class") << "</font></td></tr>" << rowStartH << "<b>" << MMSIstr
522 << "</b></td><td>&nbsp;</td><td align=right><b>" << ClassStr << rowEnd
523 << "</table></td></tr>";
524 html << "<tr><td colspan=2><table width=100% border=0 cellpadding=0 "
525 "cellspacing=0>"
526 << rowStart;
527 if ((Class != AIS_SART) && (Class != AIS_ARPA)) {
528 html << ((Class == AIS_BASE || Class == AIS_ATON || Class == AIS_METEO)
529 ? _("Nation")
530 : _("Flag"))
531 << rowEnd << "</font></td></tr>" << rowStartH << "<font size=-1><b>"
532 << GetCountryCode(true);
533 }
534 if (Class == AIS_CLASS_B && MMSIstr.StartsWith("8")) {
535 html << "<td align=right>" << _("Handheld");
536 }
537 html << rowEnd << "</font></table></td></tr>";
538
539 wxString navStatStr;
540 if ((Class != AIS_BASE) && (Class != AIS_CLASS_B) && (Class != AIS_SART) &&
541 (Class != AIS_METEO)) {
542 html << vertSpacer;
543 if ((NavStatus <= 21) && (NavStatus >= 0))
544 navStatStr = wxGetTranslation(ais_get_status(NavStatus));
545 } else if (Class == AIS_SART) {
546 if (NavStatus == RESERVED_14)
547 navStatStr = _("Active");
548 else if (NavStatus == UNDEFINED)
549 navStatStr = _("Testing");
550 }
551
552 wxString sart_sub_type;
553 if (Class == AIS_SART) {
554 int mmsi_start = MMSI / 1000000;
555 switch (mmsi_start) {
556 case 970:
557 // sart_sub_type = "SART";
558 break;
559 case 972:
560 sart_sub_type = "MOB";
561 break;
562 case 974:
563 sart_sub_type = "EPIRB";
564 break;
565 default:
566 sart_sub_type = _("Unknown");
567 break;
568 }
569 }
570
571 wxString AISTypeStr, UNTypeStr, sizeString;
572 if ((Class != AIS_BASE) && (Class != AIS_SART) && (Class != AIS_DSC) &&
573 (Class != AIS_METEO)) {
574 // Ship type
575 AISTypeStr = wxGetTranslation(Get_vessel_type_string());
576
577 if (b_isEuroInland && UN_shiptype) {
578 auto it = s_ERI_hash.find(UN_shiptype);
579 wxString type;
580 if (it == s_ERI_hash.end())
581 type = _("Undefined");
582 else
583 type = it->second;
584
585 UNTypeStr = wxGetTranslation(type);
586 }
587
588 if (b_SarAircraftPosnReport) {
589 AISTypeStr.Clear();
590 UNTypeStr.Clear();
591 navStatStr.Clear();
592 }
593
594 // Dimensions
595
596 if (NavStatus != ATON_VIRTUAL && Class != AIS_ARPA && Class != AIS_APRS &&
597 Class != AIS_BUOY) {
598 if ((Class == AIS_CLASS_B) || (Class == AIS_ATON)) {
599 sizeString =
600 wxString::Format("%dm x %dm", (DimA + DimB), (DimC + DimD));
601 } else if (!b_SarAircraftPosnReport) {
602 if ((DimA + DimB + DimC + DimD) == 0) {
603 if (b_isEuroInland) {
604 if (Euro_Length == 0.0) {
605 if (Euro_Draft > 0.01) {
606 sizeString << wxString::Format("---m x ---m x %4.1fm",
607 Euro_Draft);
608 } else {
609 sizeString << "---m x ---m x ---m";
610 }
611 } else {
612 if (Euro_Draft > 0.01) {
613 sizeString << wxString::Format("%5.1fm x %4.1fm x %4.1fm",
614 Euro_Length, Euro_Beam,
615 Euro_Draft);
616 } else {
617 sizeString << wxString::Format("%5.1fm x %4.1fm x ---m\n\n",
618 Euro_Length, Euro_Beam);
619 }
620 }
621 } else {
622 if (Draft > 0.01) {
623 sizeString << wxString::Format("---m x ---m x %4.1fm", Draft);
624 } else {
625 sizeString << "---m x ---m x ---m";
626 }
627 }
628 } else if (Draft < 0.01) {
629 sizeString << wxString::Format("%dm x %dm x ---m", (DimA + DimB),
630 (DimC + DimD));
631 } else {
632 sizeString << wxString::Format("%dm x %dm x %4.1fm", (DimA + DimB),
633 (DimC + DimD), Draft);
634 }
635 }
636 }
637 }
638
639 if (Class == AIS_SART) {
640 html << "<tr><td colspan=2>"
641 << "<b>" << AISTypeStr;
642 if (sart_sub_type.Length()) html << " (" << sart_sub_type << "), ";
643 html << navStatStr;
644 html << rowEnd << "<tr><td colspan=2>"
645 << "<b>" << sizeString << rowEnd;
646 }
647
648 else if (Class == AIS_ATON) {
649 html << "<tr><td colspan=2>"
650 << "<b>" << navStatStr;
651 html << rowEnd << "<tr><td colspan=2>"
652 << "<b>" << sizeString << rowEnd;
653 } else if (Class == AIS_DSC && (ShipType == 12 || ShipType == 16)) {
654 if (ShipType == 16) { // Distress relay
655 html << "<tr><td colspan=2>"
656 << "<b>" << _("Distress relay");
657 if (m_dscTXmmsi > 2000000) {
658 wxString mmsirelay = wxString::Format(" %09d", abs(m_dscTXmmsi));
659 html << " " << _("by:") << mmsirelay;
660 }
661 html << "<b>" << sizeString << rowEnd;
662 }
663 html << "<tr><td colspan=2>" << _("Nature of distress: ") << rowEnd
664 << "<tr><td colspan=2>";
665 if (m_dscNature < 13) {
666 html << "<tr><td colspan=2>"
667 << "<b>" << GetNatureofDistress(m_dscNature) << "<b>" << sizeString
668 << rowEnd << "<tr><td colspan=2>";
669 }
670 } else if ((Class != AIS_BASE) && (Class != AIS_DSC)) {
671 html << "<tr><td colspan=2>"
672 << "<b>" << AISTypeStr;
673 if (navStatStr.Length()) html << ", " << navStatStr;
674 if (UNTypeStr.Length()) html << " (UN Type " << UNTypeStr << ")";
675 html << rowEnd << "<tr><td colspan=2>"
676 << "<b>" << sizeString << rowEnd;
677 }
678
679 if (MSG_14_text.Len()) {
680 // The safety message is displayed for all target's AIS Query
681 // For an Active SART a Target Alert is also created.
682 html << rowStart << "<tr><td colspan=1>" << _("Safety Broadcast Message")
683 << rowEnd << rowStartH << "<b>" << MSG_14_text << "</b>" << rowEnd;
684 }
685
686 if (b_positionOnceValid) {
687 wxString posTypeStr;
688 if (b_positionDoubtful) posTypeStr << _(" (Last Known)");
689
690 now.MakeGMT();
691 int target_age = now.GetTicks() - PositionReportTicks;
692 // wxLogMessage(wxString::Format("** PositionReportTicks %ld %ld %d",
693 // now.GetTicks(), PositionReportTicks,
694 // target_age));
695
696 html << vertSpacer << rowStart << _("Position") << posTypeStr
697 << "</font></td><td align=right><font size=-2>" << _("Report Age")
698 << "</font></td></tr>"
699
700 << rowStartH << "<b>" << toSDMM(1, Lat)
701 << "</b></td><td align=right><b>" << FormatTimeAdaptive(target_age)
702 << rowEnd << rowStartH << "<b>" << toSDMM(2, Lon);
703 if (Class != AIS_METEO)
704 html << rowEnd;
705 else {
706 wxString meteoTime =
707 wxString::Format(" %02d:%02d", met_data.hour, met_data.minute);
708 html << " </td><td align=right></b></font><font size=-3>"
709 << _("Issued (UTC)") << "</font><font size=-1><b>" << meteoTime
710 << "</font>" << rowEnd;
711 }
712 }
713
714 wxString courseStr, sogStr, hdgStr, rotStr, rngStr, brgStr, destStr, etaStr;
715
716 if (Class == AIS_GPSG_BUDDY) {
717 long month, year, day;
718 m_date_string.Mid(0, 2).ToLong(&day);
719 m_date_string.Mid(2, 2).ToLong(&month);
720 m_date_string.Mid(4, 2).ToLong(&year);
721 wxDateTime date;
722 date.SetDay(day);
723 date.SetMonth((wxDateTime::Month)(month - 1));
724 date.SetYear(year + 2000);
725
726 wxString f_date = date.FormatISODate();
727
728 html << vertSpacer << rowStart << _("Report as of") << rowEnd << rowStartH
729 << "<b>" << f_date + "</b> at <b>"
730 << wxString::Format("%d:%d UTC ", m_utc_hour, m_utc_min) << rowEnd;
731 } else {
732 if (Class == AIS_CLASS_A && !b_SarAircraftPosnReport) {
733 html << vertSpacer << rowStart << _("Destination")
734 << "</font></td><td align=right><font size=-2>" << _("ETA (UTC)")
735 << "</font></td></tr>\n"
736 << rowStartH << "<b>";
737 wxString dest = trimAISField(Destination);
738 if (dest.Length())
739 html << html_escape(dest);
740 else
741 html << "---";
742 html << "</b></td><td nowrap align=right><b>";
743
744 if ((ETA_Mo) && (ETA_Hr < 24)) {
745 int yearOffset = 0;
746 if (now.GetMonth() > (ETA_Mo - 1)) yearOffset = 1;
747 wxDateTime eta(ETA_Day, wxDateTime::Month(ETA_Mo - 1),
748 now.GetYear() + yearOffset, ETA_Hr, ETA_Min);
749 html << eta.Format("%b %d %H:%M");
750 } else
751 html << "---";
752 html << rowEnd;
753 }
754
755 if (Class == AIS_CLASS_A || Class == AIS_CLASS_B || Class == AIS_ARPA ||
756 Class == AIS_APRS || Class == AIS_SART || Class == AIS_BUOY) {
757 int crs = wxRound(COG);
758 if (crs < 360) {
759 wxString magString, trueString;
760 if (g_bShowMag)
761 magString << wxString::Format(
762 wxString("%03d%c(M)"), static_cast<int>(m_callbacks.get_mag(COG)),
763 0x00B0);
764 if (g_bShowTrue)
765 trueString << wxString::Format(wxString("%03d%c "), (int)crs, 0x00B0);
766
767 courseStr << trueString << magString;
768 } else if (COG == 360.0)
769 courseStr = "---";
770 else if (crs == 360)
771 courseStr = "0&deg;";
772
773 double speed_show = toUsrSpeed(SOG);
774
775 if ((SOG <= 102.2) || b_SarAircraftPosnReport) {
776 if (speed_show < 10.0)
777 sogStr = wxString::Format("%.2f ", speed_show) + getUsrSpeedUnit();
778 else if (speed_show < 100.0)
779 sogStr = wxString::Format("%.1f ", speed_show) + getUsrSpeedUnit();
780 else
781 sogStr = wxString::Format("%.0f ", speed_show) + getUsrSpeedUnit();
782 }
783 // sogStr = wxString::Format( "%5.2f " +
784 // getUsrSpeedUnit(), toUsrSpeed( SOG ) );
785 else
786 sogStr = "---";
787
788 if ((int)HDG != 511)
789 hdgStr = wxString::Format("%03d&deg;", (int)HDG);
790 else
791 hdgStr = "---";
792
793 if (ROTAIS != -128) {
794 if (ROTAIS == 127)
795 rotStr << "> 5&deg;/30s " << _("Right");
796 else if (ROTAIS == -127)
797 rotStr << "> 5&deg;/30s " << _("Left");
798 else {
799 if (ROTIND > 0)
800 rotStr << wxString::Format("%3d&deg;/Min ", ROTIND) << _("Right");
801 else if (ROTIND < 0)
802 rotStr << wxString::Format("%3d&deg;/Min ", -ROTIND) << _("Left");
803 else
804 rotStr = "0";
805 }
806 } else if (!b_SarAircraftPosnReport)
807 rotStr = "---";
808 }
809 }
810
811 if (b_positionOnceValid && bGPSValid && (Range_NM >= 0.))
812 rngStr = FormatDistanceAdaptive(Range_NM);
813 else
814 rngStr = "---";
815
816 int brg = (int)wxRound(Brg);
817 if (Brg > 359.5) brg = 0;
818 if (b_positionOnceValid && bGPSValid && (Brg >= 0.) && (Range_NM > 0.) &&
819 (fabs(Lat) < 85.)) {
820 wxString magString, trueString;
821 if (g_bShowMag)
822 magString << wxString::Format(wxString("%03d%c(M)"),
823 static_cast<int>(m_callbacks.get_mag(Brg)),
824 0x00B0);
825 if (g_bShowTrue)
826 trueString << wxString::Format(wxString("%03d%c "), (int)Brg, 0x00B0);
827
828 brgStr << trueString << magString;
829 } else
830 brgStr = "---";
831
832 wxString turnRateHdr; // Blank if ATON or BASE or Special Position Report (9)
833 if ((Class != AIS_ATON) && (Class != AIS_BASE) && (Class != AIS_DSC) &&
834 (Class != AIS_METEO)) {
835 html << vertSpacer
836 << "<tr><td colspan=2><table width=100% border=0 cellpadding=0 "
837 "cellspacing=0>"
838 << rowStart << _("Speed")
839 << "</font></td><td>&nbsp;</td><td><font size=-2>" << _("Course")
840 << "</font></td><td>&nbsp;</td><td align=right><font size=-2>";
841 if (!b_SarAircraftPosnReport) html << _("Heading");
842
843 html << "</font></td></tr>" << rowStartH << "<b>" << sogStr
844 << "</b></td><td>&nbsp;</td><td><b>" << courseStr
845 << "</b></td><td>&nbsp;</td><td align=right><b>";
846 if (!b_SarAircraftPosnReport) html << hdgStr;
847 html << rowEnd << "</table></td></tr>" << vertSpacer;
848
849 if (!b_SarAircraftPosnReport) turnRateHdr = _("Turn Rate");
850 }
851 if (Class != AIS_METEO) {
852 html << "<tr><td colspan=2><table width=100% border=0 cellpadding=0 "
853 "cellspacing=0>"
854 << rowStart << _("Range")
855 << "</font></td><td>&nbsp;</td><td><font size=-2>" << _("Bearing")
856 << "</font></td><td>&nbsp;</td><td align=right><font size=-2>"
857 << turnRateHdr << "</font></td></tr>" << rowStartH << "<b>" << rngStr
858 << "</b></td><td>&nbsp;</td><td><b>" << brgStr
859 << "</b></td><td>&nbsp;</td><td align=right><b>";
860 if (!b_SarAircraftPosnReport) html << rotStr;
861 html << rowEnd << "</table></td></tr>" << vertSpacer;
862 }
863
864 if (bCPA_Valid && Class != AIS_METEO) {
865 wxString tcpaStr;
866 tcpaStr << "</b> " << _("in ") << "</td><td align=right><b>"
867 << FormatTimeAdaptive((int)(TCPA * 60.));
868
869 html << /*vertSpacer << */ rowStart << "<font size=-2>" << _("CPA")
870 << "</font>" << rowEnd << rowStartH << "<b>"
871 << FormatDistanceAdaptive(CPA) << tcpaStr << rowEnd;
872 }
873
874 if (Class != AIS_BASE && Class != AIS_METEO) {
875 if (blue_paddle == 1) {
876 html << rowStart << _("Inland Blue Flag") << rowEnd << rowStartH << "<b>"
877 << _("Clear") << rowEnd;
878 } else if (blue_paddle == 2) {
879 html << rowStart << _("Inland Blue Flag") << rowEnd << rowStartH << "<b>"
880 << _("Set") << rowEnd;
881 }
882 }
883
884 if (b_SarAircraftPosnReport) {
885 wxString altStr;
886 if (altitude != 4095)
887 altStr.Printf("%4d m", altitude);
888 else
889 altStr = _("Unknown");
890
891 html << rowStart << _("Altitude")
892 << "</font></td><td>&nbsp;</td><td><font size=-0>" << rowStartH
893 << "<b>" << altStr << "</b></td><td>&nbsp;</td><td><b>" << rowEnd
894 << "</table></td></tr>" << vertSpacer;
895 }
896
897 if (Class == AIS_METEO) {
898 if (met_data.wind_kn < 122) {
899 double userwindspeed = toUsrWindSpeed(met_data.wind_kn);
900 wxString wspeed =
901 wxString::Format("%0.1f %s %d%c", userwindspeed,
902 getUsrWindSpeedUnit(), met_data.wind_dir, 0x00B0);
903
904 double userwindgustspeed = toUsrWindSpeed(met_data.wind_gust_kn);
905 wxString wspeedGust = wxString::Format("%.0f %s %d%c", userwindgustspeed,
906 getUsrWindSpeedUnit(),
907 met_data.wind_gust_dir, 0x00B0);
908 if (met_data.wind_gust_kn >= 126) wspeedGust = "";
909
910 html << vertSpacer << rowStart << _("Wind speed")
911 << "</font></td><td align=right><font size=-2>" << _("Wind gust")
912 << "</font></td></tr>" << rowStartH << "<b>" << wspeed
913 << "</b></td><td align=right><b>" << wspeedGust << rowEnd;
914 }
915
916 if (met_data.water_lev_dev < 30. || met_data.water_level > -32. ||
917 met_data.current < 25.5) {
918 wxString wlevel_txt = _("Water level deviation");
919 wxString wlevel;
920 if (met_data.water_lev_dev < 30.) {
921 double userlevel = toUsrDepth(met_data.water_lev_dev);
922 wlevel =
923 wxString::Format("%.1f %s %s", userlevel, getUsrDepthUnit(),
924 ais_meteo_get_trend(met_data.water_lev_trend));
925 if (met_data.vertical_ref < 14) {
926 wlevel_txt = _("Water level dev. Ref: ");
927 wlevel_txt << aisMeteoWaterLevelRef(met_data.vertical_ref);
928 }
929
930 if (met_data.water_lev_dev >= 30.) wlevel = "";
931
932 } else if (met_data.water_level > -32.) {
933 double userlevel = toUsrDepth(met_data.water_level);
934 wlevel =
935 wxString::Format("%.1f %s %s", userlevel, getUsrDepthUnit(),
936 ais_meteo_get_trend(met_data.water_lev_trend));
937 wlevel_txt = _("Water level");
938 if (met_data.water_level <= -32.) wlevel = "";
939 }
940
941 wxString current = wxString::Format("%.1f kts %d%c", met_data.current,
942 met_data.curr_dir, 0x00B0);
943 if (met_data.current >= 25.5) current = "";
944
945 html << vertSpacer << rowStart << wlevel_txt
946 << "</font></td><td align=right><font size=-2>"
947 << _("Surface current ") << "</font></td></tr>" << rowStartH << "<b>"
948 << wlevel << "</b></td><td align=right><b>" << current << rowEnd;
949 }
950
951 if (met_data.wave_height < 24.6 || met_data.swell_height < 24.6) {
952 double userwave = toUsrDepth(met_data.wave_height);
953 wxString wave = wxString::Format("%.1f %s %d%c %d %s ", userwave,
954 getUsrDepthUnit(), met_data.wave_dir,
955 0x00B0, met_data.wave_period, _("s"));
956 if (met_data.wave_height >= 24.6) wave = "";
957
958 double userswell = toUsrDepth(met_data.swell_height);
959 wxString swell = wxString::Format("%.1f %s %d%c %d %s", userswell,
960 getUsrDepthUnit(), met_data.swell_dir,
961 0x00B0, met_data.swell_per, _("s"));
962 if (met_data.swell_height >= 25.) swell = "";
963
964 html << vertSpacer << rowStart << _("Waves height & period")
965 << "</font></td><td align=right><font size=-2>"
966 << _("Swell height & period ") << "</font></td></tr>" << rowStartH
967 << "<b>" << wave << "</b></td><td align=right><b>" << swell
968 << rowEnd;
969 }
970
971 if (met_data.air_temp != -102.4 || met_data.airpress < 1310) {
972 double usertemp = toUsrTemp(met_data.air_temp);
973 wxString airtemp =
974 wxString::Format("%.1f%c%s", usertemp, 0x00B0, getUsrTempUnit());
975 if (met_data.air_temp == -102.4) airtemp = "";
976
977 wxString airpress =
978 wxString::Format("%d hPa %s", met_data.airpress,
979 ais_meteo_get_trend(met_data.airpress_tend));
980 const int ap = met_data.airpress;
981 if (ap < 800 || ap >= 1310) airpress = "";
982
983 html << vertSpacer << rowStart << _("Air Temperatur")
984 << "</font></td><td align=right><font size=-2>" << _("Air pressure")
985 << "</font></td></tr>" << rowStartH << "<b>" << airtemp
986 << "</b></td><td align=right><b>" << airpress << rowEnd;
987 }
988
989 if (met_data.rel_humid < 101 || met_data.dew_point < 50.) {
990 wxString humid = wxString::Format("%d%c", met_data.rel_humid, '%');
991 if (met_data.rel_humid >= 101) humid = "";
992
993 double usertempDew = toUsrTemp(met_data.dew_point);
994 wxString dewpoint =
995 wxString::Format("%.1f%c%s", usertempDew, 0x00B0, getUsrTempUnit());
996 if (met_data.dew_point >= 50.) dewpoint = "";
997
998 html << vertSpacer << rowStart << _("Relative Humidity")
999 << "</font></td><td align=right><font size=-2>" << _("Dew Point ")
1000 << "</font></td></tr>" << rowStartH << "<b>" << humid
1001 << "</b></td><td align=right><b>" << dewpoint << rowEnd;
1002 }
1003
1004 if (met_data.water_temp < 50.1 || met_data.seastate < 13) {
1005 double usertemp = toUsrTemp(met_data.water_temp);
1006 wxString watertemp =
1007 wxString::Format("%.1f%c%s", usertemp, 0x00B0, getUsrTempUnit());
1008 if (met_data.water_temp >= 50.1) watertemp = "";
1009
1010 wxString seastate = wxString::Format("%d Bf ", met_data.seastate);
1011 if (met_data.seastate == 13) seastate = "";
1012
1013 html << vertSpacer << rowStart << _("Water Temperatur")
1014 << "</font></td><td align=right><font size=-2>" << _("Sea state")
1015 << "</font></td></tr>" << rowStartH << "<b>" << watertemp
1016 << "</b></td><td align=right><b>" << seastate << rowEnd;
1017 }
1018
1019 if (met_data.precipitation < 7 || met_data.hor_vis < 12.7) {
1020 wxString precip =
1021 wxString::Format("%s", aisMeteoPrecipType(met_data.precipitation));
1022 if (met_data.precipitation >= 6) precip = "";
1023
1024 double userVisDist = toUsrDistance(met_data.hor_vis);
1025 wxString horVis =
1026 wxString::Format("%s%.1f %s", (met_data.hor_vis_GT ? ">" : ""),
1027 userVisDist, getUsrDistanceUnit());
1028 if (met_data.hor_vis >= 12.7) horVis = "";
1029 html << vertSpacer << rowStart << _("Precipitation")
1030 << "</font></td><td align=right><font size=-2>"
1031 << _("Horizontal Visibility") << "</font></td></tr>" << rowStartH
1032 << "<b>" << precip << "</b></td><td align=right><b>" << horVis
1033 << rowEnd;
1034 }
1035
1036 if (met_data.salinity < 50. || met_data.ice < 2) {
1037 wxString sal = wxString::Format("%.1f%c", met_data.salinity, 0x2030);
1038 if (met_data.salinity >= 50.) sal = "";
1039
1040 wxString icestatus = _("No");
1041 if (met_data.ice == 1) icestatus = _("Yes");
1042 if (met_data.ice >= 2) icestatus = "";
1043
1044 html << vertSpacer << rowStart << _("Sea salinity")
1045 << "</font></td><td align=right><font size=-2>" << _("Ice status")
1046 << "</font></td></tr>" << rowStartH << "<b>" << sal
1047 << "</b></td><td align=right><b>" << icestatus << rowEnd;
1048 }
1049 }
1050 html << "</table>";
1051 return html;
1052}
1053
1054wxString AisTargetData::GetRolloverString() {
1055 wxString result;
1056 wxString t;
1057 if (b_nameValid) {
1058 result.Append("\"");
1059 result.Append(GetFullName());
1060 result.Append("\" ");
1061 }
1062 if (Class != AIS_GPSG_BUDDY) {
1063 t.Printf("%09d", abs(MMSI));
1064 result.Append(t);
1065 result.Append(" ");
1066 result.Append(GetCountryCode(false));
1067 }
1068 t = trimAISField(CallSign);
1069 if (t.Len()) {
1070 result.Append(" (");
1071 result.Append(t);
1072 result.Append(")");
1073 }
1074 if (g_bAISRolloverShowClass || (Class == AIS_SART)) {
1075 if (result.Len()) result.Append("\n");
1076 result.Append("[");
1077 if (Class == AIS_ATON) {
1078 result.Append(wxGetTranslation(Get_class_string(true)));
1079 result.Append(": ");
1080 result.Append(wxGetTranslation(Get_vessel_type_string(false)));
1081 } else if (b_SarAircraftPosnReport) {
1082 int airtype = (MMSI % 1000) / 100;
1083 result.Append(airtype == 5 ? _("SAR Helicopter") : _("SAR Aircraft"));
1084 } else
1085 result.Append(wxGetTranslation(Get_class_string(false)));
1086
1087 result.Append("] ");
1088 if ((Class != AIS_ATON) && (Class != AIS_BASE)) {
1089 if (Class == AIS_SART) {
1090 int mmsi_start = MMSI / 1000000;
1091 switch (mmsi_start) {
1092 case 970:
1093 break;
1094 case 972:
1095 result += "MOB";
1096 break;
1097 case 974:
1098 result += "EPIRB";
1099 break;
1100 default:
1101 result += _("Unknown");
1102 break;
1103 }
1104 }
1105
1106 if (Class != AIS_SART && Class != AIS_METEO) {
1107 if (!b_SarAircraftPosnReport)
1108 result.Append(wxGetTranslation(Get_vessel_type_string(false)));
1109 }
1110
1111 if ((Class != AIS_CLASS_B) && (Class != AIS_SART) && Class != AIS_DSC &&
1112 Class != AIS_METEO && !b_SarAircraftPosnReport) {
1113 if ((NavStatus <= 15) && (NavStatus >= 0)) {
1114 result.Append(" (");
1115 result.Append(wxGetTranslation(ais_get_status(NavStatus)));
1116 result.Append(")");
1117 }
1118 } else if (Class == AIS_SART) {
1119 result.Append(" (");
1120 if (NavStatus == RESERVED_14)
1121 result.Append(_("Active"));
1122 else if (NavStatus == UNDEFINED)
1123 result.Append(_("Testing"));
1124 result.Append(")");
1125 } else if (Class == AIS_DSC) {
1126 result.Append(" (");
1127 result.Append(GetNatureofDistress(m_dscNature));
1128 result.Append(")");
1129 }
1130 }
1131 }
1132
1133 if (g_bAISRolloverShowCOG && ((SOG <= 102.2) || b_SarAircraftPosnReport) &&
1134 !((Class == AIS_ATON) || (Class == AIS_BASE) || (Class == AIS_METEO))) {
1135 if (result.Len()) result << "\n";
1136
1137 double speed_show = toUsrSpeed(SOG);
1138 if (speed_show < 10.0)
1139 result << wxString::Format("SOG %.2f ", speed_show) << getUsrSpeedUnit()
1140 << " ";
1141 else if (speed_show < 100.0)
1142 result << wxString::Format("SOG %.1f ", speed_show) << getUsrSpeedUnit()
1143 << " ";
1144 else
1145 result << wxString::Format("SOG %.0f ", speed_show) << getUsrSpeedUnit()
1146 << " ";
1147
1148 int crs = wxRound(COG);
1149 if (b_positionOnceValid) {
1150 if (crs < 360) {
1151 wxString magString, trueString;
1152 if (g_bShowMag)
1153 magString << wxString::Format(
1154 wxString("%03d%c(M) "),
1155 static_cast<int>(m_callbacks.get_mag(COG)), 0x00B0);
1156 if (g_bShowTrue)
1157 trueString << wxString::Format(wxString("%03d%c "), (int)crs, 0x00B0);
1158
1159 result << trueString << magString;
1160 }
1161
1162 else if (COG == 360.0)
1163 result << _(" COG Unavailable");
1164 else if (crs == 360)
1165 result << wxString(" COG 000\u00B0");
1166 } else
1167 result << _(" COG Unavailable");
1168 }
1169
1170 if (g_bAISRolloverShowCPA && bCPA_Valid && Class != AIS_METEO) {
1171 if (result.Len()) result << "\n";
1172 result << _("CPA") << " " << FormatDistanceAdaptive(CPA) << " " << _("in")
1173 << " " << wxString::Format("%.0f", TCPA) << " " << _("min");
1174 }
1175 if (Class == AIS_METEO) {
1176 if (met_data.wind_kn < 122) {
1177 if (result.Len()) result << "\n";
1178 double userwindspeed = toUsrWindSpeed(met_data.wind_kn);
1179 result << _("Wind speed");
1180 result << wxString::Format(": %0.1f %s", userwindspeed,
1181 getUsrWindSpeedUnit())
1182 << wxString::Format(" %d%c ", met_data.wind_dir, 0x00B0);
1183 }
1184
1185 if (met_data.water_lev_dev < 30.) {
1186 if (result.Len()) result << "\n";
1187 result << _("Water level deviation");
1188 double userdepth;
1189 userdepth = toUsrDepth(met_data.water_lev_dev);
1190 result << wxString::Format(": %.1f %s", userdepth, getUsrDepthUnit());
1191
1192 } else if (met_data.water_level > -32.) {
1193 if (result.Len()) result << "\n";
1194 result << _("Water level");
1195 double userdepth;
1196 userdepth = toUsrDepth(met_data.water_level);
1197 result << wxString::Format(": %.1f %s", userdepth, getUsrDepthUnit());
1198 }
1199
1200 if (met_data.current < 25.) {
1201 if (result.Len()) result << "\n";
1202 result << _("Current");
1203 result << wxString::Format(": %.1f ", met_data.current) << _("kts")
1204 << wxString::Format(" %d%c ", met_data.curr_dir, 0x00B0);
1205 }
1206
1207 if (met_data.wave_height < 24.6) {
1208 if (result.Len()) result << "\n";
1209 double userwh = toUsrDepth(met_data.wave_height);
1210 result << _("Wave height")
1211 << wxString::Format(": %.1f %s", userwh, getUsrDepthUnit())
1212 << " / " << met_data.wave_period << " " << _("s");
1213 }
1214
1215 if (met_data.water_temp < 50.) {
1216 if (result.Len()) result << "\n";
1217 double usertemp = toUsrTemp(met_data.water_temp);
1218 result << _("Water temp");
1219 result << wxString::Format(": %.1f%c", usertemp, 0x00B0)
1220 << getUsrTempUnit();
1221 }
1222
1223 if (met_data.air_temp != -102.4) {
1224 if (result.Len()) result << "\n";
1225 double usertemp = toUsrTemp(met_data.air_temp);
1226 result << _("Air temp");
1227 result << wxString::Format(": %.1f%c", usertemp, 0x00B0)
1228 << getUsrTempUnit() << " ";
1229 }
1230
1231 if (met_data.airpress > 799 && met_data.airpress < 1310) {
1232 if (met_data.air_temp == -102.4 && result.Len()) result << "\n";
1233 result << _("Air press");
1234 result << wxString::Format(": %d hPa", met_data.airpress);
1235 }
1236
1237 if (met_data.hor_vis < 12.) {
1238 if (result.Len()) result << "\n";
1239 double userVisDist = toUsrDistance(met_data.hor_vis);
1240 wxString horVis =
1241 wxString::Format(": %s%.1f %s", (met_data.hor_vis_GT ? ">" : ""),
1242 userVisDist, getUsrDistanceUnit());
1243 result << _("Visibility") << horVis;
1244 }
1245 }
1246 return result;
1247}
1248
1249wxString AisTargetData::Get_vessel_type_string(bool b_short) {
1250 int i = 19;
1251 if (Class == AIS_ATON) {
1252 i = ShipType + 20;
1253 } else
1254 switch (ShipType) {
1255 case 30:
1256 i = 0;
1257 break;
1258 case 31:
1259 i = 1;
1260 break;
1261 case 32:
1262 i = 2;
1263 break;
1264 case 33:
1265 i = 3;
1266 break;
1267 case 34:
1268 i = 4;
1269 break;
1270 case 35:
1271 i = 5;
1272 break;
1273 case 36:
1274 i = 6;
1275 break;
1276 case 37:
1277 i = 7;
1278 break;
1279 case 50:
1280 i = 9;
1281 break;
1282 case 51:
1283 i = 10;
1284 break;
1285 case 52:
1286 i = 11;
1287 break;
1288 case 53:
1289 i = 12;
1290 break;
1291 case 54:
1292 i = 13;
1293 break;
1294 case 55:
1295 i = 14;
1296 break;
1297 case 58:
1298 i = 15;
1299 break;
1300 default:
1301 i = 19;
1302 break;
1303 }
1304
1305 if ((Class == AIS_CLASS_B) || (Class == AIS_CLASS_A)) {
1306 if ((ShipType >= 40) && (ShipType < 50)) i = 8;
1307
1308 if ((ShipType >= 60) && (ShipType < 70)) i = 16;
1309
1310 if ((ShipType >= 70) && (ShipType < 80)) i = 17;
1311
1312 if ((ShipType >= 80) && (ShipType < 90)) i = 18;
1313 } else if (Class == AIS_GPSG_BUDDY)
1314 i = 52;
1315 else if (Class == AIS_ARPA)
1316 i = 55;
1317 else if (Class == AIS_APRS)
1318 i = 56;
1319 else if (Class == AIS_BUOY)
1320 i = 57;
1321 else if (Class == AIS_DSC)
1322 i = (ShipType == 12 || ShipType == 16) ? 54 : 53; // 12 & 16 is distress
1323
1324 if (!b_short)
1325 return ais_get_type(i);
1326 else
1327 return ais_get_short_type(i);
1328}
1329
1330wxString AisTargetData::Get_class_string(bool b_short) {
1331 switch (Class) {
1332 case AIS_CLASS_A:
1333 return _("A");
1334 case AIS_CLASS_B:
1335 return _("B");
1336 case AIS_ATON:
1337 return b_short ? _("AtoN") : _("Aid to Navigation");
1338 case AIS_BASE:
1339 return b_short ? _("Base") : _("Base Station");
1340 case AIS_GPSG_BUDDY:
1341 return b_short ? _("Buddy") : _("GPSGate Buddy");
1342 case AIS_DSC:
1343 if (ShipType == 12 || (ShipType == 16 && m_dscNature < 13))
1344 return b_short ? _("DSC") : _("DSC Distress");
1345 else
1346 return b_short ? _("DSC") : _("DSC Position Report");
1347 case AIS_SART:
1348 return b_short ? _("SART") : _("SART");
1349 case AIS_ARPA:
1350 return b_short ? _("ARPA") : _("ARPA");
1351 case AIS_BUOY:
1352 return b_short ? _("Buoy") : _("BUOY");
1353 case AIS_APRS:
1354 return b_short ? _("APRS") : _("APRS Position Report");
1355 case AIS_METEO:
1356 return b_short ? _("Meteo") : _("Meteorologic");
1357
1358 default:
1359 return b_short ? _("Unk") : _("Unknown");
1360 }
1361}
1362
1363wxString AisTargetData::GetNatureofDistress(int dscnature) {
1364 // Natures of distress from: Rec. ITU-R M.493-10.
1365 wxString dscDistressType[] = {_("Fire, explosion"),
1366 _("Flooding"),
1367 _("Collision"),
1368 _("Grounding"),
1369 _("Listing, in danger of capsizing"),
1370 _("Sinking"),
1371 _("Disabled and adrift"),
1372 _("Undesignated distress"),
1373 _("Abandoning ship"),
1374 _("Piracy/armed robbery attack"),
1375 _("Man overboard"),
1376 "-",
1377 _("EPIRB emission")};
1378 if (dscnature >= 0 && dscnature < 13) return dscDistressType[dscnature];
1379
1380 return "";
1381}
1382
1383void AisTargetData::Toggle_AIS_CPA() {
1384 b_show_AIS_CPA = !b_show_AIS_CPA ? true : false;
1385}
1386
1387void AisTargetData::ToggleShowTrack() {
1388 b_show_track = !b_show_track ? true : false;
1389}
1390
1391bool AisTargetData::IsValidMID(int mid) {
1392 if (mid >= 201 && mid <= 775) return true;
1393 return false;
1394}
1395
1396// Get country name and code according to ITU 2023-02
1397// (http://www.itu.int/en/ITU-R/terrestrial/fmd/Pages/mid.aspx)
1398wxString AisTargetData::GetCountryCode(bool b_CntryLongStr) {
1399 if (Class == AIS_BUOY || Class == AIS_ARPA) return "";
1400 /***** Check for a valid MID *****/
1401 // Meteo adaption
1402 int tmpMmsi = met_data.original_mmsi ? met_data.original_mmsi : MMSI;
1403 // First check the most common case
1404 int nMID = tmpMmsi / 1000000;
1405 if (!IsValidMID(nMID) || Class == AIS_ATON) {
1406 // SART, MOB, EPIRB starts with 97 and don't use MID (ITU-R M.1371-5)
1407 // or healthy check
1408 if (tmpMmsi < 1000 || 97 == tmpMmsi / 10000000) return "";
1409
1410 // Find MID when not in first position like e.g. SAR/ATON
1411 wxString s_mmsi;
1412 s_mmsi << tmpMmsi;
1413 bool foundMID = false;
1414 size_t i;
1415 i = nMID > 900 ? 2 : 0; // AIS_ATON or others where MMSI starts with 9x
1416 for (i; i < s_mmsi.length() - 3; i++) {
1417 nMID = wxAtoi(s_mmsi.Mid(i, 3));
1418 if (IsValidMID(nMID)) {
1419 foundMID = true;
1420 break;
1421 }
1422 }
1423 if (!foundMID) return "";
1424 }
1425
1426#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
1427
1428 switch (nMID) {
1429 case 201:
1430 return b_CntryLongStr ? _("Albania") : "AL";
1431 case 202:
1432 return b_CntryLongStr ? _("Andorra") : "AD";
1433 case 203:
1434 return b_CntryLongStr ? _("Austria") : "AT";
1435 case 204:
1436 return b_CntryLongStr ? _("Azores") : "AZ";
1437 case 205:
1438 return b_CntryLongStr ? _("Belgium") : "BE";
1439 case 206:
1440 return b_CntryLongStr ? _("Belarus") : "BY";
1441 case 207:
1442 return b_CntryLongStr ? _("Bulgaria") : "BG";
1443 case 208:
1444 return b_CntryLongStr ? _("Vatican City State") : "VA";
1445 case 209:
1446 case 210:
1447 return b_CntryLongStr ? _("Cyprus") : "CY";
1448 case 211:
1449 return b_CntryLongStr ? _("Germany") : "DE";
1450 case 212:
1451 return b_CntryLongStr ? _("Cyprus") : "CY";
1452 case 213:
1453 return b_CntryLongStr ? _("Georgia") : "GE";
1454 case 214:
1455 return b_CntryLongStr ? _("Moldova") : "MD";
1456 case 215:
1457 return b_CntryLongStr ? _("Malta") : "MT";
1458 case 216:
1459 return b_CntryLongStr ? _("Armenia") : "AM";
1460 case 218:
1461 return b_CntryLongStr ? _("Germany") : "DE";
1462 case 219:
1463 case 220:
1464 return b_CntryLongStr ? _("Denmark") : "DK";
1465 case 224:
1466 return b_CntryLongStr ? _("Spain") : "ES";
1467 case 225:
1468 return b_CntryLongStr ? _("Spain") : "ES";
1469 case 226:
1470 case 227:
1471 case 228:
1472 return b_CntryLongStr ? _("France") : "FR";
1473 case 229:
1474 return b_CntryLongStr ? _("Malta") : "MT";
1475 case 230:
1476 return b_CntryLongStr ? _("Finland") : "FI";
1477 case 231:
1478 return b_CntryLongStr ? _("Faroe Islands") : "FO";
1479 case 232:
1480 case 233:
1481 case 234:
1482 case 235:
1483 return b_CntryLongStr ? _("Great Britain") : "GB";
1484 case 236:
1485 return b_CntryLongStr ? _("Gibraltar") : "GI";
1486 case 237:
1487 return b_CntryLongStr ? _("Greece") : "GR";
1488 case 238:
1489 return b_CntryLongStr ? _("Croatia") : "HR";
1490 case 239:
1491 case 240:
1492 case 241:
1493 return b_CntryLongStr ? _("Greece") : "GR";
1494 case 242:
1495 return b_CntryLongStr ? _("Morocco") : "MA";
1496 case 243:
1497 return b_CntryLongStr ? _("Hungary") : "HU";
1498 case 244:
1499 case 245:
1500 case 246:
1501 return b_CntryLongStr ? _("Netherlands") : "NL";
1502 case 247:
1503 return b_CntryLongStr ? _("Italy") : "IT";
1504 case 248:
1505 case 249:
1506 return b_CntryLongStr ? _("Malta") : "MT";
1507 case 250:
1508 return b_CntryLongStr ? _("Ireland") : "IE";
1509 case 251:
1510 return b_CntryLongStr ? _("Iceland") : "IS";
1511 case 252:
1512 return b_CntryLongStr ? _("Liechtenstein") : "LI";
1513 case 253:
1514 return b_CntryLongStr ? _("Luxembourg") : "LU";
1515 case 254:
1516 return b_CntryLongStr ? _("Monaco") : "MC";
1517 case 255:
1518 return b_CntryLongStr ? _("Madeira") : "PT";
1519 case 256:
1520 return b_CntryLongStr ? _("Malta") : "MT";
1521 case 257:
1522 case 258:
1523 case 259:
1524 return b_CntryLongStr ? _("Norway") : "NO";
1525 case 261:
1526 return b_CntryLongStr ? _("Poland") : "PL";
1527 case 262:
1528 return b_CntryLongStr ? _("Montenegro") : "ME";
1529 case 263:
1530 return b_CntryLongStr ? _("Portugal") : "PT";
1531 case 264:
1532 return b_CntryLongStr ? _("Romania") : "RO";
1533 case 265:
1534 case 266:
1535 return b_CntryLongStr ? _("Sweden") : "SE";
1536 case 267:
1537 return b_CntryLongStr ? _("Slovak Republic") : "SK";
1538 case 268:
1539 return b_CntryLongStr ? _("San Marino") : "SM";
1540 case 269:
1541 return b_CntryLongStr ? _("Switzerland") : "CH";
1542 case 270:
1543 return b_CntryLongStr ? _("Czech Republic") : "CZ";
1544 case 271:
1545 return b_CntryLongStr ? _("Turkey") : "TR";
1546 case 272:
1547 return b_CntryLongStr ? _("Ukraine") : "UA";
1548 case 273:
1549 return b_CntryLongStr ? _("Russian") : "RU";
1550 case 274:
1551 return b_CntryLongStr ? _("Macedonia") : "MK";
1552 case 275:
1553 return b_CntryLongStr ? _("Latvia") : "LV";
1554 case 276:
1555 return b_CntryLongStr ? _("Estonia") : "EE";
1556 case 277:
1557 return b_CntryLongStr ? _("Lithuania") : "LT";
1558 case 278:
1559 return b_CntryLongStr ? _("Slovenia") : "SI";
1560 case 279:
1561 return b_CntryLongStr ? _("Serbia") : "RS";
1562 case 301:
1563 return b_CntryLongStr ? _("Anguilla") : "AI";
1564 case 303:
1565 return b_CntryLongStr ? _("Alaska") : "AK";
1566 case 304:
1567 case 305:
1568 return b_CntryLongStr ? _("Antigua and Barbuda") : "AG";
1569 case 306:
1570 return b_CntryLongStr ? _("Antilles") : "AN";
1571 case 307:
1572 return b_CntryLongStr ? _("Aruba") : "AW";
1573 case 308:
1574 case 309:
1575 return b_CntryLongStr ? _("Bahamas") : "BS";
1576 case 310:
1577 return b_CntryLongStr ? _("Bermuda") : "BM";
1578 case 311:
1579 return b_CntryLongStr ? _("Bahamas") : "BS";
1580 case 312:
1581 return b_CntryLongStr ? _("Belize") : "BZ";
1582 case 314:
1583 return b_CntryLongStr ? _("Barbados") : "BB";
1584 case 316:
1585 return b_CntryLongStr ? _("Canada") : "CA";
1586 case 319:
1587 return b_CntryLongStr ? _("Cayman Islands") : "KY";
1588 case 321:
1589 return b_CntryLongStr ? _("Costa Rica") : "CR";
1590 case 323:
1591 return b_CntryLongStr ? _("Cuba") : "CU";
1592 case 325:
1593 return b_CntryLongStr ? _("Dominica") : "DM";
1594 case 327:
1595 return b_CntryLongStr ? _("Dominican Republic") : "DM";
1596 case 329:
1597 return b_CntryLongStr ? _("Guadeloupe") : "GP";
1598 case 330:
1599 return b_CntryLongStr ? _("Grenada") : "GD";
1600 case 331:
1601 return b_CntryLongStr ? _("Greenland") : "GL";
1602 case 332:
1603 return b_CntryLongStr ? _("Guatemala") : "GT";
1604 case 334:
1605 return b_CntryLongStr ? _("Honduras") : "HN";
1606 case 336:
1607 return b_CntryLongStr ? _("Haiti") : "HT";
1608 case 338:
1609 return b_CntryLongStr ? _("United States of America") : "US";
1610 case 339:
1611 return b_CntryLongStr ? _("Jamaica") : "JM";
1612 case 341:
1613 return b_CntryLongStr ? _("Saint Kitts and Nevis") : "KN";
1614 case 343:
1615 return b_CntryLongStr ? _("Saint Lucia") : "LC";
1616 case 345:
1617 return b_CntryLongStr ? _("Mexico") : "MX";
1618 case 347:
1619 return b_CntryLongStr ? _("Martinique") : "MQ";
1620 case 348:
1621 return b_CntryLongStr ? _("Montserrat") : "MS";
1622 case 350:
1623 return b_CntryLongStr ? _("Nicaragua") : "NI";
1624 case 351:
1625 case 352:
1626 case 353:
1627 case 354:
1628 case 355:
1629 case 356:
1630 case 357:
1631 return b_CntryLongStr ? _("Panama") : "PA";
1632 case 358:
1633 return b_CntryLongStr ? _("Puerto Rico") : "PR";
1634 case 359:
1635 return b_CntryLongStr ? _("El Salvador") : "SV";
1636 case 361:
1637 return b_CntryLongStr ? _("Saint Pierre and Miquelon") : "PM";
1638 case 362:
1639 return b_CntryLongStr ? _("Trinidad and Tobago") : "TT";
1640 case 364:
1641 return b_CntryLongStr ? _("Turks and Caicos Islands") : "TC";
1642 case 366:
1643 case 367:
1644 case 368:
1645 case 369:
1646 return b_CntryLongStr ? _("United States of America") : "US";
1647 case 370:
1648 case 371:
1649 case 372:
1650 case 373:
1651 case 374:
1652 return b_CntryLongStr ? _("Panama") : "PA";
1653 case 375:
1654 case 376:
1655 case 377:
1656 return b_CntryLongStr ? _("Saint Vincent and the Grenadines") : "VC";
1657 case 378:
1658 return b_CntryLongStr ? _("British Virgin Islands") : "VG";
1659 case 379:
1660 return b_CntryLongStr ? _("United States Virgin Islands") : "AE";
1661 case 401:
1662 return b_CntryLongStr ? _("Afghanistan") : "AF";
1663 case 403:
1664 return b_CntryLongStr ? _("Saudi Arabia") : "SA";
1665 case 405:
1666 return b_CntryLongStr ? _("Bangladesh") : "BD";
1667 case 408:
1668 return b_CntryLongStr ? _("Bahrain") : "BH";
1669 case 410:
1670 return b_CntryLongStr ? _("Bhutan") : "BT";
1671 case 412:
1672 case 413:
1673 case 414:
1674 return b_CntryLongStr ? _("China") : "CN";
1675 case 416:
1676 return b_CntryLongStr ? _("Taiwan") : "TW";
1677 case 417:
1678 return b_CntryLongStr ? _("Sri Lanka") : "LK";
1679 case 419:
1680 return b_CntryLongStr ? _("India") : "IN";
1681 case 422:
1682 return b_CntryLongStr ? _("Iran") : "IR";
1683 case 423:
1684 return b_CntryLongStr ? _("Azerbaijani Republic") : "AZ";
1685 case 425:
1686 return b_CntryLongStr ? _("Iraq") : "IQ";
1687 case 428:
1688 return b_CntryLongStr ? _("Israel") : "IL";
1689 case 431:
1690 return b_CntryLongStr ? _("Japan") : "JP";
1691 case 432:
1692 return b_CntryLongStr ? _("Japan") : "JP";
1693 case 434:
1694 return b_CntryLongStr ? _("Turkmenistan") : "TM";
1695 case 436:
1696 return b_CntryLongStr ? _("Kazakhstan") : "KZ";
1697 case 437:
1698 return b_CntryLongStr ? _("Uzbekistan") : "UZ";
1699 case 438:
1700 return b_CntryLongStr ? _("Jordan") : "JO";
1701 case 440:
1702 case 441:
1703 return b_CntryLongStr ? _("Korea") : "KR";
1704 case 443:
1705 return b_CntryLongStr ? _("Palestine") : "PS";
1706 case 445:
1707 return b_CntryLongStr ? _("People's Rep. of Korea") : "KP";
1708 case 447:
1709 return b_CntryLongStr ? _("Kuwait") : "KW";
1710 case 450:
1711 return b_CntryLongStr ? _("Lebanon") : "LB";
1712 case 451:
1713 return b_CntryLongStr ? _("Kyrgyz Republic") : "KG";
1714 case 453:
1715 return b_CntryLongStr ? _("Macao") : "MO";
1716 case 455:
1717 return b_CntryLongStr ? _("Maldives") : "MV";
1718 case 457:
1719 return b_CntryLongStr ? _("Mongolia") : "MN";
1720 case 459:
1721 return b_CntryLongStr ? _("Nepal") : "NP";
1722 case 461:
1723 return b_CntryLongStr ? _("Oman") : "OM";
1724 case 463:
1725 return b_CntryLongStr ? _("Pakistan") : "PK";
1726 case 466:
1727 return b_CntryLongStr ? _("Qatar") : "QA";
1728 case 468:
1729 return b_CntryLongStr ? _("Syrian Arab Republic") : "SY";
1730 case 470:
1731 case 471:
1732 return b_CntryLongStr ? _("United Arab Emirates") : "AE";
1733 case 472:
1734 return b_CntryLongStr ? _("Tajikistan") : "TJ";
1735 case 473:
1736 case 475:
1737 return b_CntryLongStr ? _("Yemen") : "YE";
1738 case 477:
1739 return b_CntryLongStr ? _("Hong Kong") : "HK";
1740 case 478:
1741 return b_CntryLongStr ? _("Bosnia and Herzegovina") : "BA";
1742 case 501:
1743 return b_CntryLongStr ? _("Adelie Land") : "TF";
1744 case 503:
1745 return b_CntryLongStr ? _("Australia") : "AU";
1746 case 506:
1747 return b_CntryLongStr ? _("Myanmar") : "MM";
1748 case 508:
1749 return b_CntryLongStr ? _("Brunei Darussalam") : "BN";
1750 case 510:
1751 return b_CntryLongStr ? _("Micronesia") : "FM";
1752 case 511:
1753 return b_CntryLongStr ? _("Palau") : "PW";
1754 case 512:
1755 return b_CntryLongStr ? _("New Zealand") : "NZ";
1756 case 514:
1757 case 515:
1758 return b_CntryLongStr ? _("Cambodia") : "KH";
1759 case 516:
1760 return b_CntryLongStr ? _("Christmas Island") : "CX";
1761 case 518:
1762 return b_CntryLongStr ? _("Cook Islands") : "CK";
1763 case 520:
1764 return b_CntryLongStr ? _("Fiji") : "FJ";
1765 case 523:
1766 return b_CntryLongStr ? _("Cocos (Keeling) Islands") : "CC";
1767 case 525:
1768 return b_CntryLongStr ? _("Indonesia") : "ID";
1769 case 529:
1770 return b_CntryLongStr ? _("Kiribati") : "KI";
1771 case 531:
1772 return b_CntryLongStr ? _("Lao People's Dem. Rep.") : "LA";
1773 case 533:
1774 return b_CntryLongStr ? _("Malaysia") : "MY";
1775 case 536:
1776 return b_CntryLongStr ? _("Northern Mariana Islands") : "MP";
1777 case 538:
1778 return b_CntryLongStr ? _("Marshall Islands") : "MH";
1779 case 540:
1780 return b_CntryLongStr ? _("New Caledonia") : "NC";
1781 case 542:
1782 return b_CntryLongStr ? _("Niue") : "NU";
1783 case 544:
1784 return b_CntryLongStr ? _("Nauru") : "NR";
1785 case 546:
1786 return b_CntryLongStr ? _("French Polynesia") : "PF";
1787 case 548:
1788 return b_CntryLongStr ? _("Philippines") : "PH";
1789 case 550:
1790 return b_CntryLongStr ? _("East Timor") : "TL";
1791 case 553:
1792 return b_CntryLongStr ? _("Papua New Guinea") : "PG";
1793 case 555:
1794 return b_CntryLongStr ? _("Pitcairn Island") : "PN";
1795 case 557:
1796 return b_CntryLongStr ? _("Solomon Islands") : "SB";
1797 case 559:
1798 return b_CntryLongStr ? _("American Samoa") : "AS";
1799 case 561:
1800 return b_CntryLongStr ? _("Samoa") : "WS";
1801 case 563:
1802 case 564:
1803 case 565:
1804 case 566:
1805 return b_CntryLongStr ? _("Singapore") : "SG";
1806 case 567:
1807 return b_CntryLongStr ? _("Thailand") : "TH";
1808 case 570:
1809 return b_CntryLongStr ? _("Tonga") : "TO";
1810 case 572:
1811 return b_CntryLongStr ? _("Tuvalu") : "TV";
1812 case 574:
1813 return b_CntryLongStr ? _("Viet Nam") : "VN";
1814 case 576:
1815 case 577:
1816 return b_CntryLongStr ? _("Vanuatu") : "VU";
1817 case 578:
1818 return b_CntryLongStr ? _("Wallis and Futuna Islands") : "WF";
1819 case 601:
1820 return b_CntryLongStr ? _("South Africa") : "ZA";
1821 case 603:
1822 return b_CntryLongStr ? _("Angola") : "AO";
1823 case 605:
1824 return b_CntryLongStr ? _("Algeria") : "DZ";
1825 case 607:
1826 return b_CntryLongStr ? _("Saint Paul") : "TF";
1827 case 608:
1828 return b_CntryLongStr ? _("Ascension Island") : "SH";
1829 case 609:
1830 return b_CntryLongStr ? _("Burundi") : "BI";
1831 case 610:
1832 return b_CntryLongStr ? _("Benin") : "BJ";
1833 case 611:
1834 return b_CntryLongStr ? _("Botswana") : "BW";
1835 case 612:
1836 return b_CntryLongStr ? _("Central African Republic") : "CF";
1837 case 613:
1838 return b_CntryLongStr ? _("Cameroon") : "CM";
1839 case 615:
1840 return b_CntryLongStr ? _("Congo") : "CD";
1841 case 616:
1842 return b_CntryLongStr ? _("Comoros") : "KM";
1843 case 617:
1844 return b_CntryLongStr ? _("Capo Verde") : "CV";
1845 case 618:
1846 return b_CntryLongStr ? _("Crozet Archipelago") : "TF";
1847 case 619:
1848 return b_CntryLongStr ? _("Ivory Coast") : "CI";
1849 case 620:
1850 return b_CntryLongStr ? _("Comoros (Union of the)") : "KM";
1851 case 621:
1852 return b_CntryLongStr ? _("Djibouti") : "DJ";
1853 case 622:
1854 return b_CntryLongStr ? _("Egypt") : "EG";
1855 case 624:
1856 return b_CntryLongStr ? _("Ethiopia") : "ET";
1857 case 625:
1858 return b_CntryLongStr ? _("Eritrea") : "ER";
1859 case 626:
1860 return b_CntryLongStr ? _("Gabonese Republic") : "GA";
1861 case 627:
1862 return b_CntryLongStr ? _("Ghana") : "GH";
1863 case 629:
1864 return b_CntryLongStr ? _("Gambia") : "GM";
1865 case 630:
1866 return b_CntryLongStr ? _("Guinea-Bissau") : "GW";
1867 case 631:
1868 return b_CntryLongStr ? _("Equatorial Guinea") : "GQ";
1869 case 632:
1870 return b_CntryLongStr ? _("Guinea") : "GN";
1871 case 633:
1872 return b_CntryLongStr ? _("Burkina Faso") : "BF";
1873 case 634:
1874 return b_CntryLongStr ? _("Kenya") : "KE";
1875 case 635:
1876 return b_CntryLongStr ? _("Kerguelen Islands") : "TF";
1877 case 636:
1878 case 637:
1879 return b_CntryLongStr ? _("Liberia") : "LR";
1880 case 638:
1881 return b_CntryLongStr ? _("South Sudan (Republic of)") : "SS";
1882 case 642:
1883 return b_CntryLongStr ? _("Libya") : "LY";
1884 case 644:
1885 return b_CntryLongStr ? _("Lesotho") : "LS";
1886 case 645:
1887 return b_CntryLongStr ? _("Mauritius") : "MU";
1888 case 647:
1889 return b_CntryLongStr ? _("Madagascar") : "MG";
1890 case 649:
1891 return b_CntryLongStr ? _("Mali") : "ML";
1892 case 650:
1893 return b_CntryLongStr ? _("Mozambique") : "MZ";
1894 case 654:
1895 return b_CntryLongStr ? _("Mauritania") : "MR";
1896 case 655:
1897 return b_CntryLongStr ? _("Malawi") : "MW";
1898 case 656:
1899 return b_CntryLongStr ? _("Niger") : "NE";
1900 case 657:
1901 return b_CntryLongStr ? _("Nigeria") : "NG";
1902 case 659:
1903 return b_CntryLongStr ? _("Namibia") : "NA";
1904 case 660:
1905 return b_CntryLongStr ? _("Reunion") : "RE";
1906 case 661:
1907 return b_CntryLongStr ? _("Rwanda") : "RW";
1908 case 662:
1909 return b_CntryLongStr ? _("Sudan") : "SD";
1910 case 663:
1911 return b_CntryLongStr ? _("Senegal") : "SN";
1912 case 664:
1913 return b_CntryLongStr ? _("Seychelles") : "SC";
1914 case 665:
1915 return b_CntryLongStr ? _("Saint Helena") : "SH";
1916 case 666:
1917 return b_CntryLongStr ? _("Somalia") : "SO";
1918 case 667:
1919 return b_CntryLongStr ? _("Sierra Leone") : "SL";
1920 case 668:
1921 return b_CntryLongStr ? _("Sao Tome and Principe") : "ST";
1922 case 669:
1923 return b_CntryLongStr ? _("Eswatini") : "SZ";
1924 case 670:
1925 return b_CntryLongStr ? _("Chad") : "TD";
1926 case 671:
1927 return b_CntryLongStr ? _("Togolese Republic") : "TG";
1928 case 672:
1929 return b_CntryLongStr ? _("Tunisia") : "TN";
1930 case 674:
1931 return b_CntryLongStr ? _("Tanzania") : "TZ";
1932 case 675:
1933 return b_CntryLongStr ? _("Uganda") : "UG";
1934 case 676:
1935 return b_CntryLongStr ? _("Dem Rep.of the Congo") : "CD";
1936 case 677:
1937 return b_CntryLongStr ? _("Tanzania") : "TZ";
1938 case 678:
1939 return b_CntryLongStr ? _("Zambia") : "ZM";
1940 case 679:
1941 return b_CntryLongStr ? _("Zimbabwe") : "ZW";
1942 case 701:
1943 return b_CntryLongStr ? _("Argentine Republic") : "AR";
1944 case 710:
1945 return b_CntryLongStr ? _("Brazil") : "BR";
1946 case 720:
1947 return b_CntryLongStr ? _("Bolivia") : "BO";
1948 case 725:
1949 return b_CntryLongStr ? _("Chile") : "CL";
1950 case 730:
1951 return b_CntryLongStr ? _("Colombia") : "CO";
1952 case 735:
1953 return b_CntryLongStr ? _("Ecuador") : "EC";
1954 case 740:
1955 return b_CntryLongStr ? _("Falkland Islands") : "FK";
1956 case 745:
1957 return b_CntryLongStr ? _("France - Guiana") : "GY";
1958 case 750:
1959 return b_CntryLongStr ? _("Guyana") : "GY";
1960 case 755:
1961 return b_CntryLongStr ? _("Paraguay") : "PY";
1962 case 760:
1963 return b_CntryLongStr ? _("Peru") : "PE";
1964 case 765:
1965 return b_CntryLongStr ? _("Suriname") : "SR";
1966 case 770:
1967 return b_CntryLongStr ? _("Uruguay") : "UY";
1968 case 775:
1969 return b_CntryLongStr ? _("Venezuela") : "VE";
1970
1971 default:
1972 return "";
1973 }
1974#else
1975 return "";
1976#endif
1977}
1978
1979wxString ais_get_type(int index) {
1980 static const wxString ais_type[] = {
1981 _("Fishing Vessel"), // 30 0
1982 _("Towing Vessel"), // 31 1
1983 _("Towing Vessel, Long"), // 32 2
1984 _("Dredger"), // 33 3
1985 _("Diving Ops Vessel"), // 34 4
1986 _("Military Vessel"), // 35 5
1987 _("Sailing Vessel"), // 36 6
1988 _("Pleasure craft"), // 37 7
1989 _("High Speed Craft"), // 4x 8
1990 _("Pilot Vessel"), // 50 9
1991 _("Search and Rescue Vessel"), // 51 10
1992 _("Tug"), // 52 11
1993 _("Port Tender"), // 53 12
1994 _("Pollution Control Vessel"), // 54 13
1995 _("Law Enforcement Vessel"), // 55 14
1996 _("Medical Transport"), // 58 15
1997 _("Passenger Ship"), // 6x 16
1998 _("Cargo Ship"), // 7x 17
1999 _("Tanker"), // 8x 18
2000 _("Unknown"), // 19
2001 _("Unspecified"), // 00 20
2002 _("Reference Point"), // 01 21
2003 _("RACON"), // 02 22
2004 _("Fixed Structure"), // 03 23
2005 _("Spare"), // 04 24
2006 _("Light"), // 05 25
2007 _("Light w/Sectors"), // 06 26
2008 _("Leading Light Front"), // 07 27
2009 _("Leading Light Rear"), // 08 28
2010 _("Cardinal N Beacon"), // 09 29
2011 _("Cardinal E Beacon"), // 10 30
2012 _("Cardinal S Beacon"), // 11 31
2013 _("Cardinal W Beacon"), // 12 32
2014 _("Beacon, Port Hand"), // 13 33
2015 _("Beacon, Starboard Hand"), // 14 34
2016 _("Beacon, Preferred Channel Port Hand"), // 15 35
2017 _("Beacon, Preferred Channel Starboard Hand"), // 16 36
2018 _("Beacon, Isolated Danger"), // 17 37
2019 _("Beacon, Safe Water"), // 18 38
2020 _("Beacon, Special Mark"), // 19 39
2021 _("Cardinal Mark N"), // 20 40
2022 _("Cardinal Mark E"), // 21 41
2023 _("Cardinal Mark S"), // 22 42
2024 _("Cardinal Mark W"), // 23 43
2025 _("Port Hand Mark"), // 24 44
2026 _("Starboard Hand Mark"), // 25 45
2027 _("Preferred Channel Port Hand"), // 26 46
2028 _("Preferred Channel Starboard Hand"), // 27 47
2029 _("Isolated Danger"), // 28 48
2030 _("Safe Water"), // 29 49
2031 _("Special Mark"), // 30 50
2032 _("Light Vessel/Rig"), // 31 51
2033 _("GpsGate Buddy"), // xx 52
2034 _("Position Report"), // xx 53
2035 _("Distress"), // xx 54
2036 _("ARPA radar target"), // xx 55
2037 _("APRS Position Report"), // xx 56
2038 _("Buoy or similar") // xx 57
2039 };
2040
2041 return ais_type[index];
2042}
2043
2044wxString ais_get_short_type(int index) {
2045 static const wxString short_ais_type[] = {
2046 _("F/V"), // 30 0
2047 _("Tow"), // 31 1
2048 _("Long Tow"), // 32 2
2049 _("Dredge"), // 33 3
2050 _("D/V"), // 34 4
2051 _("Mil/V"), // 35 5
2052 _("S/V"), // 36 6
2053 _("Yat"), // 37 7
2054 _("HSC"), // 4x 8
2055 _("P/V"), // 50 9
2056 _("SAR/V"), // 51 10
2057 _("Tug"), // 52 11
2058 _("Tender"), // 53 12
2059 _("PC/V"), // 54 13
2060 _("LE/V"), // 55 14
2061 _("Med/V"), // 58 15
2062 _("Pass/V"), // 6x 16
2063 _("M/V"), // 7x 17
2064 _("M/T"), // 8x 18
2065 _("?"), // 19
2066
2067 _("AtoN"), // 00 20
2068 _("Ref. Pt"), // 01 21
2069 _("RACON"), // 02 22
2070 _("Fix.Struct."), // 03 23
2071 _("?"), // 04 24
2072 _("Lt"), // 05 25
2073 _("Lt sect."), // 06 26
2074 _("Ldg Lt Front"), // 07 27
2075 _("Ldg Lt Rear"), // 08 28
2076 _("Card. N"), // 09 29
2077 _("Card. E"), // 10 30
2078 _("Card. S"), // 11 31
2079 _("Card. W"), // 12 32
2080 _("Port"), // 13 33
2081 _("Stbd"), // 14 34
2082 _("Pref. Chnl"), // 15 35
2083 _("Pref. Chnl"), // 16 36
2084 _("Isol. Dngr"), // 17 37
2085 _("Safe Water"), // 18 38
2086 _("Special"), // 19 39
2087 _("Card. N"), // 20 40
2088 _("Card. E"), // 21 41
2089 _("Card. S"), // 22 42
2090 _("Card. W"), // 23 43
2091 _("Port Hand"), // 24 44
2092 _("Stbd Hand"), // 25 45
2093 _("Pref. Chnl"), // 26 46
2094 _("Pref. Chnl"), // 27 47
2095 _("Isol. Dngr"), // 28 48
2096 _("Safe Water"), // 29 49
2097 _("Special"), // 30 50
2098 _("LtV/Rig"), // 31 51
2099 _("Buddy"), // xx 52
2100 _("DSC"), // xx 53
2101 _("Distress"), // xx 54
2102 _("ARPA"), // xx 55
2103 _("APRS"), // xx 56
2104 _("Buoy or similar") // xx 57
2105 };
2106 return short_ais_type[index];
2107}
Global state for AIS decoder.
AIS target definitions.
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.
Definition own_ship.cpp:34
Position, course, speed, etc.