-
Notifications
You must be signed in to change notification settings - Fork 5
/
Constants.h
387 lines (315 loc) · 12 KB
/
Constants.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
#pragma once
#include "EuroScopePlugIn.h"
#define _USE_MATH_DEFINES
#include <math.h>
#include <string>
#include <sstream>
#include "nlohmann/json.hpp"
#define MY_PLUGIN_NAME "CoFrance"
#define MY_PLUGIN_VERSION "@appveyor_build"
#define MY_PLUGIN_DEVELOPER "Pierre Ferran"
#define MY_PLUGIN_COPYRIGHT "GPL v3"
#define CONFIG_ONLINE_URL_BASE "https://raw.githubusercontent.com"
#define CONFIG_ONLINE_URL_PATH "/vaccfr/CoFrance/master/config.toml"
#define API_URL_BASE "https://fire-ops.ew.r.appspot.com"
#define CONFIG_ONLINE_STAND_API_URL_PATH "/api/cfr/stand"
#define CONFIG_ONLINE_STAND_API_QUERY_URL_PATH "/api/cfr/stand/query"
using namespace std;
using namespace EuroScopePlugIn;
namespace CoFranceTags {
const int GS = 1;
const int VZ_INDICATOR = 2;
const int COPXN_POINT_REDUCED = 3;
const int COPXN_ALT_REDUCED = 4;
const int COPXN_ALT_FULL = 5;
const int DUMMY = 6;
const int DUMMY_TAGGED = 7;
const int SCRATCHPAD_INDIC = 8;
const int CONFLICT_GROUP_DETAIL = 9;
const int RFL = 10;
const int CONFLICT_GROUP_TAGGED = 11;
const int CFL = 12;
const int CFL_DETAILED = 13;
const int APP_INTENTION = 15;
const int VZ = 16;
const int STCA = 17;
const int CPDLC_STATUS = 18;
const int OCL_FLAG = 19;
const int ASSIGNED_SPEED = 20;
const int STAND = 21;
const int ANNOTATION_SPEED_SIGN = 2;
const int ANNOTATION_STAND = 3;
const int FUNCTION_CONFLICT_POPUP = 500;
const int FUNCTION_HANDLE_CONFLICT_GROUP = 501;
const int FUNCTION_SEP_TOOL = 502;
const int FUNCTION_OCL_TP = 503;
const int FUNCTION_OPEN_ASP = 504;
const int FUNCTION_ASP_TOOL_MIN = 901;
const int FUNCTION_ASP_TOOL_MAX = 902;
const int FUNCTION_ASP_TOOL_LIST = 903;
const int FUNCTION_ASP_TOOL_TOGGLE_M = 904;
const int FUNCTION_ASP_TOOL_RESUME = 905;
const int FUNCTION_ASP_TOOL_CANCEL = 906;
const int FUNCTION_STAND_MENU = 907;
const int FUNCTION_STAND_CLEAR = 908;
}
namespace CoFranceCharacters {
const string Moon = "±";
const string Star = "§";
const string Losange = "÷";
const string Pen = "µ";
const string ClearedVisualIndicator = "©";
const string ClearedAPPIndicator = "®";
const string DatalinkIndicator = "ß";
}
namespace StaticColours {
const Gdiplus::Color YellowHighlight(255, 255, 0);
const Gdiplus::Color DarkBlueMenu(0, 2, 48);
const Gdiplus::Color LightBlueMenu(23, 156, 155);
const Gdiplus::Color MenuButtonTop(165, 165, 165);
const Gdiplus::Color MenuButtonBottom(74, 74, 74);
const Gdiplus::Color GreyTextMenu(162, 162, 162);
const Gdiplus::Color SectorActive(4, 7, 14);
const Gdiplus::Color SectorInactive(22, 22, 22);
const Gdiplus::Color ListBackground(43, 51, 54);
const Gdiplus::Color ListForeground(0, 0, 0);
const Gdiplus::Color ListLightForeground(93, 103, 112);
const Gdiplus::Color SelectListBackground(32, 61, 64);
const Gdiplus::Color SelectActiveListBackground(105, 180, 211);
}
namespace SharedData {
static bool OCLEnabled = true;
static nlohmann::json OCLData;
static auto OCL_Tooltip_timer = std::chrono::system_clock::now();
static string OCL_Tooltip_string;
static POINT OCL_Tooltip_pt;
}
static bool HasOCL(string callsign) {
try {
for (auto d : SharedData::OCLData) {
if (d.contains("callsign") && d.contains("status")) {
if (d["callsign"] == callsign && d["status"] == "CLEARED")
return true;
}
}
}
catch (std::exception& exc) {
}
return false;
}
static int GetOCLLevel(string callsign) {
try {
for (auto d : SharedData::OCLData) {
if (d.contains("callsign") && d.contains("status") && d.contains("level")) {
if (d["callsign"] == callsign && d["status"] == "CLEARED")
return std::stoi(d["level"].get<std::string>())*100;
}
}
}
catch (std::exception& exc) {
}
return 0;
}
static string GetFullOCL(string callsign) {
try {
for (auto d : SharedData::OCLData) {
if (d.contains("callsign") && d.contains("status") && d.contains("level") && d.contains("fix") && d.contains("mach") && d.contains("extra_info")) {
if (d["callsign"] == callsign && d["status"] == "CLEARED")
return string("OCL ") + d["fix"].get<std::string>() + string(" ") + d["level"].get<std::string>() + string(" m")+ d["mach"].get<std::string>() + string(" ") + d["extra_info"].get<std::string>();
}
}
}
catch (std::exception& exc) {
return "";
}
return "";
}
const static int ButtonPaddingSides = 5;
const static int ButtonPaddingTop = 2;
const vector<string> Brest_Oceanic_Points = {"ETIKI", "UMLER", "SEPAL", "BUNAV", "SIVIR"};
inline static bool startsWith(const char* pre, const char* str)
{
size_t lenpre = strlen(pre), lenstr = strlen(str);
return lenstr < lenpre ? false : strncmp(pre, str, lenpre) == 0;
};
static bool StringContainsArray(string str, vector<string> possibilities) {
for (auto& c : str) c = toupper(c);
for (auto p : possibilities) {
if (str.find(p) != std::string::npos)
return true;
}
return false;
}
static Gdiplus::GraphicsPath* RoundedRect(Gdiplus::Rect bounds, int radius)
{
int diameter = radius * 2;
Gdiplus::Size size = Gdiplus::Size(diameter, diameter);
Gdiplus::Point pt;
bounds.GetLocation(&pt);
Gdiplus::Rect arc = Gdiplus::Rect(pt, size);
Gdiplus::GraphicsPath* path = new Gdiplus::GraphicsPath();
// top left arc
path->AddArc(arc, 180, 90);
// top right arc
arc.X = bounds.GetRight() - diameter;
path->AddArc(arc, 270, 90);
// bottom right arc
arc.Y = bounds.GetBottom() - diameter;
path->AddArc(arc, 0, 90);
// bottom left arc
arc.X = bounds.GetLeft();
path->AddArc(arc, 90, 90);
path->CloseFigure();
return path;
}
static int DrawCenteredText(CDC* dc, POINT Center, string s) {
CSize cs = dc->GetTextExtent(s.c_str());
dc->TextOutA(Center.x - cs.cx / 2, Center.y, s.c_str());
return cs.cy;
};
static int roundUp(int numToRound, int multiple)
{
if (multiple == 0)
return numToRound;
int remainder = numToRound % multiple;
if (remainder == 0)
return numToRound;
return numToRound + multiple - remainder;
}
inline static bool IsInRect(POINT pt, CRect rect) {
if (pt.x >= rect.left + 1 && pt.x <= rect.right - 1 && pt.y >= rect.top + 1 && pt.y <= rect.bottom - 1)
return true;
return false;
}
static int GetCoordinationTagColour(int CoordinationState) {
switch (CoordinationState) {
case EuroScopePlugIn::COORDINATION_STATE_REQUESTED_BY_ME:
return EuroScopePlugIn::TAG_COLOR_ONGOING_REQUEST_FROM_ME;
break;
case EuroScopePlugIn::COORDINATION_STATE_REQUESTED_BY_OTHER:
return EuroScopePlugIn::TAG_COLOR_ONGOING_REQUEST_TO_ME;
break;
case EuroScopePlugIn::COORDINATION_STATE_ACCEPTED:
return EuroScopePlugIn::TAG_COLOR_ONGOING_REQUEST_ACCEPTED;
break;
case EuroScopePlugIn::COORDINATION_STATE_MANUAL_ACCEPTED:
return EuroScopePlugIn::TAG_COLOR_ONGOING_REQUEST_ACCEPTED;
break;
case EuroScopePlugIn::COORDINATION_STATE_REFUSED:
return EuroScopePlugIn::TAG_COLOR_ONGOING_REQUEST_REFUSED;
break;
default:
return EuroScopePlugIn::TAG_COLOR_DEFAULT;
}
}
static Gdiplus::Color vectorToGdiplusColour(std::vector<int> input) {
if (input.size() == 3) {
return Gdiplus::Color(input.at(0), input.at(1), input.at(2));
}
if (input.size() == 4) {
return Gdiplus::Color(input.at(0), input.at(1), input.at(2), input.at(3));
}
return Gdiplus::Color(255, 0, 0);
}
static double DegToRad(const double degree) { return (degree * M_PI / 180.0); };
static double RadToDeg(const double radian) { return (radian * 180.0 / M_PI); };
static CPosition Extrapolate(CPosition init, double angle, double nm)
{
CPosition newPos;
double d = nm / 60 * M_PI / 180;
double trk = DegToRad(angle);
double lat0 = DegToRad(init.m_Latitude);
double lon0 = DegToRad(init.m_Longitude);
double lat = asin(sin(lat0) * cos(d) + cos(lat0) * sin(d) * cos(trk));
double lon = cos(lat) == 0 ? lon0 : fmod(lon0 + asin(sin(trk) * sin(d) / cos(lat)) + M_PI, 2 * M_PI) - M_PI;
newPos.m_Latitude = RadToDeg(lat);
newPos.m_Longitude = RadToDeg(lon);
return newPos;
}
static Gdiplus::Point rotatePoint(Gdiplus::Point center, float angle, Gdiplus::Point p)
{
float s = sin(angle);
float c = cos(angle);
// translate point back to origin:
p.X -= center.X;
p.Y -= center.Y;
// rotate point
float xnew = p.X * c - p.Y * s;
float ynew = p.X * s + p.Y * c;
// translate point back:
p.X = static_cast<int>(xnew) + center.X;
p.Y = static_cast<int>(ynew) + center.Y;
return p;
}
static string padWithZeros(int padding, int s)
{
stringstream ss;
ss << setfill('0') << setw(padding) << s;
return ss.str();
};
static COLORREF GetConflictGroupColor(toml::value Config, string ConflictGroup) {
if (ConflictGroup == CoFranceCharacters::Moon)
return vectorToGdiplusColour(toml::find<std::vector<int>>(Config, "colours", "conflict_group_moon")).ToCOLORREF();
if (ConflictGroup == CoFranceCharacters::Star)
return vectorToGdiplusColour(toml::find<std::vector<int>>(Config, "colours", "conflict_group_star")).ToCOLORREF();
if (ConflictGroup == CoFranceCharacters::Losange)
return vectorToGdiplusColour(toml::find<std::vector<int>>(Config, "colours", "conflict_group_losange")).ToCOLORREF();
return COLORREF();
}
inline static std::vector<std::string>& split(const std::string& s, char delim, std::vector<std::string>& elems) {
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim))
elems.push_back(item);
return elems;
};
inline static std::vector<std::string> split(const std::string& s, char delim) {
std::vector<std::string> elems;
split(s, delim, elems);
return elems;
};
inline static string join_vector(vector<string> v, string sep = ", ") {
std::string s;
for (const auto& piece : v) s += piece + sep;
return s;
}
// Liang-Barsky function by Daniel White @ http://www.skytopia.com/project/articles/compsci/clipping.html
// This function inputs 8 numbers, and outputs 4 new numbers (plus a boolean value to say whether the clipped line is drawn at all).
//
inline static bool LiangBarsky(RECT Area, POINT fromSrc, POINT toSrc, POINT& ClipFrom, POINT& ClipTo) // The output values, so declare these outside.
{
double edgeLeft, edgeRight, edgeBottom, edgeTop, x0src, y0src, x1src, y1src;
edgeLeft = Area.left;
edgeRight = Area.right;
edgeBottom = Area.top;
edgeTop = Area.bottom;
x0src = fromSrc.x;
y0src = fromSrc.y;
x1src = toSrc.x;
y1src = toSrc.y;
double t0 = 0.0; double t1 = 1.0;
double xdelta = x1src - x0src;
double ydelta = y1src - y0src;
double p = 0, q = 0, r;
for (int edge = 0; edge < 4; edge++) { // Traverse through left, right, bottom, top edges.
if (edge == 0) { p = -xdelta; q = -(edgeLeft - x0src); }
if (edge == 1) { p = xdelta; q = (edgeRight - x0src); }
if (edge == 2) { p = -ydelta; q = -(edgeBottom - y0src); }
if (edge == 3) { p = ydelta; q = (edgeTop - y0src); }
r = q / p;
if (p == 0 && q < 0) return false; // Don't draw line at all. (parallel line outside)
if (p < 0) {
if (r > t1) return false; // Don't draw line at all.
else if (r > t0) t0 = r; // Line is clipped!
}
else if (p > 0) {
if (r < t0) return false; // Don't draw line at all.
else if (r < t1) t1 = r; // Line is clipped!
}
}
ClipFrom.x = long(x0src + t0 * xdelta);
ClipFrom.y = long(y0src + t0 * ydelta);
ClipTo.x = long(x0src + t1 * xdelta);
ClipTo.y = long(y0src + t1 * ydelta);
return true; // (clipped) line is drawn
};