1 /*
2 * Tlf - contest logging program for amateur radio operators
3 * Copyright (C) 2001-2002-2003 Rein Couperus <pa0rct@amsat.org>
4 * 2013 Ervin Hegedus <airween@gmail.com>
5 * 2013-2015 Thomas Beierlein <tb@forth-ev.de>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 /* ------------------------------------------------------------
23 * score
24 *
25 *--------------------------------------------------------------*/
26
27
28 #include <ctype.h>
29 #include <math.h>
30 #include <stdbool.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include "focm.h"
35 #include "getctydata.h"
36 #include "locator2longlat.h"
37 #include "qrb.h"
38 #include "tlf.h"
39
40 extern char countrylist[][6];
41 extern char continent_multiplier_list[7][3];
42
43 int calc_continent(int zone);
44
45 /* check if countrynr is in countrylist */
is_in_countrylist(int countrynr)46 bool is_in_countrylist(int countrynr) {
47 int i = 0;
48
49 while (strlen(countrylist[i]) != 0) {
50 if (getctynr(countrylist[i]) == countrynr) {
51 return true;
52 }
53 i++;
54 }
55 return false;
56 }
57
58
59 /* check if hiscall is in COUNTRY_LIST from logcfg.dat */
country_found(char prefix[])60 bool country_found(char prefix[]) {
61
62 extern int countrynr;
63 extern char hiscall[];
64 extern char call[];
65
66 char tmpcall[15];
67
68 if (strlen(hiscall) == 0) {
69 strcpy(tmpcall, call);
70 } else
71 strcpy(tmpcall, hiscall);
72
73 countrynr = getctydata(tmpcall);
74
75 return is_in_countrylist(countrynr);
76 }
77
exist_in_country_list()78 bool exist_in_country_list() {
79
80 extern char pxstr[];
81 char prefix[10];
82
83 strcpy(prefix, pxstr);
84
85 if (country_found(prefix)) {
86 return true;
87 }
88
89 if (!isdigit(prefix[strlen(prefix) - 1])) { /* last char '0'..'9' */
90 return false;
91 }
92
93 prefix[strlen(prefix) - 1] = '\0'; /* strip trailing digit */
94 if (country_found(prefix)) { /* and try again */
95 return true;
96 }
97
98 if (!isdigit(prefix[strlen(prefix) - 1])) {
99 return false;
100 }
101
102 prefix[strlen(prefix) - 1] = '\0'; /* last try */
103 return country_found(prefix);
104 }
105
106
107 /* HA2OS - check if continent is in CONTINENT_LIST from logcfg.dat */
is_in_continentlist(char * continent)108 bool is_in_continentlist(char *continent) {
109 int i = 0;
110
111 while (strlen(continent_multiplier_list[i]) != 0) {
112 if (strcmp(continent_multiplier_list[i], continent) == 0) {
113 return true;
114 }
115 i++;
116 }
117 return false;
118 }
119
120
121 /* apply bandweigth scoring *
122 * at the moment only LOWBAND_DOUBLES (<30m) can be active */
apply_bandweigth(int points)123 int apply_bandweigth(int points) {
124 extern int lowband_point_mult;
125 extern int bandinx;
126 extern int bandweight_points[];
127
128 if (lowband_point_mult != 0 && (bandinx < BANDINDEX_30))
129 points *= 2;
130
131 points *= bandweight_points[bandinx];
132
133 return points;
134 }
135
136
137 /* portable stations may count double
138 * see PORTABLE_X2 */
portable_doubles(int points)139 int portable_doubles(int points) {
140 extern int portable_x2;
141 extern char hiscall[];
142 char *loc;
143
144 if (portable_x2 == 1) { // portable x2
145 loc = strstr(hiscall, "/P");
146 if (loc == hiscall + strlen(hiscall) - 2) {
147 points *= 2;
148 }
149 }
150 return points;
151 }
152
153
154 /* apply points by mode */
scoreByMode()155 int scoreByMode() {
156 extern int cwpoints;
157 extern int ssbpoints;
158 extern int trxmode;
159
160 switch (trxmode) {
161 case CWMODE:
162 return cwpoints;
163 case SSBMODE:
164 return ssbpoints;
165 default:
166 return 0;
167 }
168 }
169
170
scoreByContinentOrCountry()171 int scoreByContinentOrCountry() {
172
173 extern char hiscall[];
174
175 extern int countrylist_points;
176 extern bool countrylist_only;
177
178 extern bool continentlist_only;
179 extern int continentlist_points;
180
181 extern int my_country_points;
182 extern int my_cont_points;
183 extern int dx_cont_points;
184
185 extern int countrynr;
186 extern int mycountrynr;
187 extern char continent[];
188 extern char mycontinent[];
189
190 int points = 0;
191 int inList = 0;
192
193 inList = exist_in_country_list();
194 if (countrylist_only) {
195 if (inList == 1 && countrylist_points != -1)
196 points = countrylist_points;
197 } else {
198
199 if (inList == 1) {
200 if (countrylist_points != -1)
201 points = countrylist_points;
202
203 if (countrynr == mycountrynr) {
204 if (my_country_points != -1)
205 points = my_country_points;
206 else if (my_cont_points != -1)
207 points = my_cont_points;
208 else
209 points = 0;
210 }
211
212 } else if (countrynr == mycountrynr) {
213 if (my_country_points != -1)
214 points = my_country_points;
215 else if (my_cont_points != -1)
216 points = my_cont_points;
217 } else if (strcmp(continent, mycontinent) == 0) {
218 if (my_cont_points != -1)
219 points = my_cont_points;
220 } else if (dx_cont_points != -1)
221 points = dx_cont_points;
222 }
223
224 /* HA2OS mods */
225 if (continentlist_only) {
226 // only continent list allowed
227 if (is_in_continentlist(continent)) {
228 // are we are on DX continent or not
229 if (strcmp(continent, mycontinent) == 0) {
230 points = my_cont_points;
231 } else if (continentlist_points != -1) {
232 points = continentlist_points;
233 }
234 } else {
235 points = 0;
236 }
237 }
238
239 return points;
240 }
241
242
243 /** default scoring code
244 *
245 * the default scoring rules will be applied if no contest specific rules
246 * are active
247 * \return points for QSO
248 */
scoreDefault()249 int scoreDefault() {
250
251 extern int cwpoints;
252 extern int ssbpoints;
253 extern int one_point;
254 extern int two_point;
255 extern int three_point;
256
257 int points;
258
259 if (one_point == 1) {
260 points = 1;
261 return points;
262 }
263
264 if (two_point == 1) {
265 points = 2;
266 return points;
267 }
268
269 if (three_point == 1) {
270 points = 3;
271 return points;
272 }
273
274 if (ssbpoints != 0 && cwpoints != 0) // e.g. arrl 10m contest
275 points = scoreByMode();
276 else
277 points = scoreByContinentOrCountry();
278
279 points = apply_bandweigth(points);
280 points = portable_doubles(points);
281
282 return points;
283 }
284
285
score()286 int score() {
287
288 extern int dupe;
289 extern int band_score[NBANDS];
290 extern int bandinx;
291 extern int focm;
292 extern int wpx;
293 extern int pfxmult;
294 extern int countrynr;
295 extern int mycountrynr;
296 extern char continent[];
297 extern char mycontinent[];
298 extern char comment[];
299 extern int cqww;
300 extern int arrl_fd;
301 extern int arrldx_usa;
302 extern int w_cty;
303 extern int ve_cty;
304 extern int trxmode;
305 extern char hiscall[];
306 extern char myqra[7];
307 extern int stewperry_flg;
308
309 int points;
310 int zone;
311
312 if (dupe == ISDUPE) {
313 points = 0;
314 dupe = NODUPE;
315 return points;
316 }
317
318 band_score[bandinx]++; /* qso's per band */
319
320 if ((arrldx_usa == 1)
321 && ((countrynr == w_cty) || (countrynr == ve_cty)))
322 band_score[bandinx]--;
323
324 if (focm == 1) {
325 points = foc_score(hiscall);
326
327 return points;
328 }
329
330 if (wpx == 1 && pfxmult == 0) {
331 if (countrynr == mycountrynr) {
332 points = 1;
333
334 return points;
335 }
336
337 if ((strcmp(continent, mycontinent) == 0)
338 && (bandinx > BANDINDEX_30)) {
339 if (strstr(mycontinent, "NA") != NULL) {
340 points = 2;
341 } else {
342 points = 1;
343 }
344
345 return points;
346 }
347
348 if ((strcmp(continent, mycontinent) == 0)
349 && (bandinx < BANDINDEX_30)) {
350 if (strstr(mycontinent, "NA") != NULL) {
351 points = 4;
352 } else {
353 points = 2;
354 }
355 return points;
356 }
357 if ((strcmp(continent, mycontinent) != 0)
358 && (bandinx > BANDINDEX_30)) {
359 points = 3;
360
361 return points;
362 }
363 if ((strcmp(continent, mycontinent) != 0)
364 && (bandinx < BANDINDEX_30)) {
365 points = 6;
366
367 return points;
368 }
369 } // end wpx
370
371 if (cqww == 1) {
372
373 if (countrynr == 0) {
374 zone = atoi(comment);
375 calc_continent(zone); // sets continent
376 }
377
378 if (countrynr == mycountrynr) {
379 points = 0;
380
381 return points;
382 }
383
384 if (strcmp(continent, mycontinent) == 0) {
385 if (strstr(mycontinent, "NA") != NULL) {
386 points = 2;
387 } else {
388 points = 1;
389 }
390
391 return points;
392 } else {
393 points = 3;
394
395 return points;
396 }
397
398 }
399
400 /* end cqww */
401 if (arrl_fd == 1) {
402
403 if (trxmode == SSBMODE) {
404 points = 1;
405 } else {
406 points = 2;
407
408 }
409 return points;
410
411 } // end arrl_fd
412
413 if (arrldx_usa == 1) {
414
415 if ((countrynr == w_cty) || (countrynr == ve_cty)) {
416 points = 0;
417
418 } else {
419 points = 3;
420 }
421
422 return points;
423 }
424
425 if (stewperry_flg == 1) {
426
427 double s1long, s1lat, s2long, s2lat, distance, azimuth;
428
429 points = 0;
430
431 if (strlen(comment) > 3) {
432 locator2longlat(&s1long, &s1lat, comment);
433 locator2longlat(&s2long, &s2lat, myqra);
434
435 qrb(s1long, s1lat, s2long, s2lat, &distance, &azimuth);
436
437 points = (int) ceil(distance / 500.0);
438 }
439
440 return points;
441 }
442
443 /* start of the universal scoring code */
444 return scoreDefault();
445 }
446
447
448 /* -----------------------------------------------------------------*/
score2(char * line)449 int score2(char *line) {
450 return atoi(line + 75);
451 }
452
453
454 /* ----------------------------------------------------------------- */
455 /* calculates continent from zone and sets 'continent' variable */
calc_continent(int zone)456 int calc_continent(int zone) {
457 extern char continent[];
458
459 switch (zone) {
460 case 1 ... 8:
461 strncpy(continent, "NA", 3);
462 break;
463 case 9 ... 13:
464 strncpy(continent, "SA", 3);
465 break;
466 case 14 ... 16:
467 strncpy(continent, "EU", 3);
468 break;
469 case 17 ... 26:
470 strncpy(continent, "AS", 3);
471 break;
472 case 27 ... 32:
473 strncpy(continent, "AS", 3);
474 break;
475 case 33 ... 39:
476 strncpy(continent, "AF", 3);
477 break;
478 case 40:
479 strncpy(continent, "EU", 3);
480 break;
481 default:
482 strncpy(continent, "??", 3);
483 }
484 return 0;
485 }
486
487