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