Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support several multipliers for a QSO #442

Merged
merged 2 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions rules/eudx/eudx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
########################
# EU-DX contest #
########################
# https://www.eudx-contest.com/rules/
#
# Provided by: HA5CQZ
#
CONTEST_MODE
LOGFILE=eudx.log

CABRILLO=UNIVERSAL
CABRILLO-CONTEST=EUDXC

#================================
# Select one of following blocks:
#--------------------------------
#
# non-EU stations send ITU zone
#
#CABRILLO-EXCHANGE=00
#F3=@ ++5NN-- 00
#S&P_TU_MSG=TU ++5NN-- 00
#PLUGIN_CONFIG=DX
#--------------------------------
#
# EU stations send region code
#
CABRILLO-EXCHANGE=XX00
F3=@ ++5NN-- XX00
S&P_TU_MSG=TU ++5NN-- XX00
PLUGIN_CONFIG=IT
#================================

MIXED

# Scoring:
# (handled by eudx.py)


# Multipliers:
# EU regions and DXCC countries per band
# (handled by eudx.py)
GENERIC_MULT=BAND

87 changes: 87 additions & 0 deletions rules/eudx/eudx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"""
EU-DX contest
https://www.eudx-contest.com/
"""
import re

MY_COUNTRY = None
MY_PREFIX = None
MY_CONTINENT = None

EU_REGION_PATTERN = re.compile('([A-Z]{2})\d{2}') # two letters and two numbers

EU_COUNTRIES = ['AT', 'BE', 'BG', 'CZ', 'CY', 'HR', 'DK', 'EE',
'FI', 'FR', 'DE', 'GR', 'HU', 'IE', 'IT', 'LV',
'LT', 'LX', 'MT', 'NL', 'PL', 'PT', 'RO', 'SK',
'SI', 'ES', 'SE']

#
# - EU stations shall provide their ISO_3166-1_alpha-2 country code
# as used in the contest (NOT the DXCC country code)
# - non-EU stations shall use simply DX
#
def init(cfg):
global MY_COUNTRY
if cfg in EU_COUNTRIES:
MY_COUNTRY = cfg
else:
MY_COUNTRY = 'DX' # normalize to DX

dxcc = tlf.get_dxcc(tlf.MY_CALL)
global MY_PREFIX
MY_PREFIX = dxcc.main_prefix
global MY_CONTINENT
MY_CONTINENT = dxcc.continent


# a. European Union stations:
# - your own country 2 points,
# - another European Union country 10 points,
# - with a non-European Union country in your continent 3 points,
# - another continent 5 points.
# b. Non- European Union stations:
# - European Union 10 points,
# - your own country 2 points,
# - a different country in your continent 3 points,
# - another continent 5 points.
def score(qso):
xchg = qso.exchange.strip()

m = EU_REGION_PATTERN.match(xchg)
if m:
eu_country = m.group(1)
else:
eu_country = None

if MY_COUNTRY != 'DX':
if eu_country == MY_COUNTRY:
return 2
if eu_country:
return 10
dxcc = tlf.get_dxcc(qso.call)
if dxcc.continent == MY_CONTINENT:
return 3
else:
return 5
else:
if eu_country:
return 10
dxcc = tlf.get_dxcc(qso.call)
if dxcc.main_prefix == MY_PREFIX:
return 2
if dxcc.continent == MY_CONTINENT:
return 3
else:
return 5



def check_exchange(qso):
xchg = qso.exchange.strip()
dxcc = tlf.get_dxcc(qso.call)
mult = dxcc.main_prefix

if EU_REGION_PATTERN.match(xchg):
mult += ' ' + xchg

return {'mult1_value': mult}
47 changes: 44 additions & 3 deletions src/addmult.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,49 @@

GPtrArray *mults_possible;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe locate function near related remember_multi()?

/*
* process a space separated list of multipliers from qso->mult1_value.
* qso->mult1_value is updated with the list of actually applied new multipliers.
* if none could be applied then it contains an empty string.
*/
static void remember_generic_mult(struct qso_t *qso, bool check_only) {
static GRegex *regex = NULL;
if (regex == NULL) {
// words with trailing space(s) or at the end of string
regex = g_regex_new("(\\S+(\\s+|$))", 0, 0, NULL);
}

GMatchInfo *match_info;
g_regex_match(regex, qso->mult1_value, 0, &match_info);

GString *applied_mults = g_string_new(NULL);

while (g_match_info_matches(match_info)) {
gchar *word = g_match_info_fetch(match_info, 0);

gchar *mult = g_strdup(word);
g_strchomp(mult); // remove trailing whitespace for mult check

int mult_index = remember_multi(mult, qso->bandindex, generic_mult, check_only);

if (mult_index >= 0) {
// aggregate the original value incl. whitespace
g_string_append(applied_mults, word);
}

g_free(mult);
g_free(word);
g_match_info_next(match_info, NULL);
}

g_match_info_free(match_info);

// copy applied_mults to mult1_value
g_free(qso->mult1_value);
qso->mult1_value = g_string_free(applied_mults, FALSE);

}

/*
* \return - index in mults[] array if new mult or new on band
* -1 if not a (new) mult
Expand Down Expand Up @@ -74,7 +117,6 @@ static int addmult_internal(struct qso_t *qso, bool check_only) {

// --------------------------- section_mult_once--------------------------
else if (sectn_mult_once) {

/* is it a mult? */
idx = get_exact_mult_index(qso->mult1_value);
if (idx >= 0) {
Expand Down Expand Up @@ -118,8 +160,7 @@ static int addmult_internal(struct qso_t *qso, bool check_only) {

// ----------- generic: use mult1 -----------
else if (generic_mult != MULT_NONE) {
mult_index = remember_multi(qso->mult1_value, qso->bandindex, generic_mult,
check_only);
remember_generic_mult(qso, check_only);
}

free(stripped_comment);
Expand Down
5 changes: 4 additions & 1 deletion src/makelogline.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,9 +290,12 @@ void prepare_specific_part(char *logline, struct qso_t *qso) {
new_cty = 0;
}

} else if (generic_mult != MULT_NONE) {

strncat(logline, qso->mult1_value, 9);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if we have >=10 points? We get no space between multi and points.

Or should we drop one more character from the combined multi field ... That would allow only 7 characters. I fear we must live with the missing separating space here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we have to live with the missing separator. A wider terminal screen could solve this, but also introduce a bunch of other problems.

} else if (wysiwyg_multi
|| unique_call_multi != MULT_NONE
|| generic_mult != MULT_NONE
|| serial_section_mult
|| sectn_mult
|| sectn_mult_once
Expand Down
1 change: 0 additions & 1 deletion src/parse_logcfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,6 @@ static int cfg_countrylist(const cfg_arg_t arg) {
g_strlcpy(buffer, parameter, buffer_len);
g_strchomp(buffer); /* drop trailing whitespace */

printf("%s\n", buffer);
if ((fp = fopen(buffer, "r")) != NULL) {
char *prefix = g_strdup_printf("%s:", whichcontest);

Expand Down
7 changes: 7 additions & 0 deletions test/rules/cqp_dx/cqp.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
40CW 21-Nov-23 22:34 0001 AB1AAA --- --- 4ELDO ELDO 3
40CW 21-Nov-23 22:34 0002 AB1BBB --- --- 007 ELDO 3
40CW 21-Nov-23 22:35 0003 AB1CCC --- --- 123 KING TULA KING TUL 3
40CW 21-Nov-23 22:36 0004 AB1DDD --- --- 27TULA 3
40CW 21-Nov-23 22:36 0005 AB1EEE --- --- 64ORAN ORAN 3
40SSB 21-Nov-23 22:37 0006 AB1FFF --- --- 8 BUTT BUTT 2
40SSB 21-Nov-23 22:38 0007 AB1GGG --- --- 5 TULA KERN KERN 2
2 changes: 2 additions & 0 deletions test/rules/cqp_dx/logcfg.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
RULES=cqp
CALL=AB6AAA
64 changes: 64 additions & 0 deletions test/rules/cqp_dx/rules/cqp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
########################
#
#
#
########################
#
CONTEST_MODE
LOGFILE=cqp.log
CABRILLO=UNIVERSAL
GENERIC_MULT=BAND
NO_RST
PLUGIN_CONFIG=FL
SSBPOINTS=2
CWPOINTS=3
#
##################################
# #
# Messages F1= to F12= #
# Message CQ_TU_MSG= #
# Message S&P_TU_MSG= #
# #
# % = call #
# @ = hiscall #
# # = serial #
# [ = RST #
# + = increase cw speed #
# - = decrease cw speed #
# #
##################################
#
F1=cq cqp %
F2=@ DE %
F3=# FL
F4=TU
F5=@
F6=%
F7=@ SRI QSO B4 GL
F8=AGN
F9= ?
F10= QRZ?
F11= PSE K
F12=cq cqp %
#
CQ_TU_MSG=TU %
S&P_TU_MSG=# FL
#
#ALT_0=
#ALT_1=
#ALT_2=
#ALT_3=
#ALT_4=
#ALT_5=
#ALT_6=
#ALT_7=
#ALT_8=
#ALT_9=
#
#SEND_DE
#
CABRILLO-QSO-FORMAT=CQP
CABRILLO-EXCHANGE=# FL
CABRILLO-CONTEST=
####### END #####################

63 changes: 63 additions & 0 deletions test/rules/cqp_dx/rules/cqp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""
CQP contest
https://www.cqp.org/
"""
import re

MY_STATE = None

CA_COUNTIES = ['ALAM', 'ALPI', 'AMAD', 'BUTT', 'CALA', 'COLU', 'CCOS', 'DELN',
'ELDO', 'FRES', 'GLEN', 'HUMB', 'IMPE', 'INYO', 'KERN', 'KING', 'LAKE',
'LASS', 'LANG', 'MADE', 'MARN', 'MARP', 'MEND', 'MERC', 'MODO', 'MONO',
'MONT', 'NAPA', 'NEVA', 'ORAN', 'PLAC', 'PLUM', 'RIVE', 'SACR', 'SBEN',
'SBER', 'SDIE', 'SFRA', 'SJOA', 'SLUI', 'SMAT', 'SBAR', 'SCLA', 'SCRU',
'SHAS', 'SIER', 'SISK', 'SOLA', 'SONO', 'STAN', 'SUTT', 'TEHA', 'TRIN',
'TULA', 'TUOL', 'VENT', 'YOLO', 'YUBA']

STATES = ['AL', 'AK', 'AZ', 'AR',
# 'CA' -- The first valid QSO logged with 4-letter county abbreviation will count as the multiplier for California.
'CO', 'CT', 'DE', 'FL', 'GA', 'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY',
'LA', 'ME', 'MD', 'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH',
'NJ', 'NM', 'NY', 'NC', 'ND', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD',
'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV', 'WI', 'WY',
# Canada
'AB', 'BC', 'MB', 'NB', 'NL', 'NT', 'NS', 'NU', 'ON', 'PE', 'QC', 'SK', 'YT'
]

MULT_PATTERN = re.compile('[A-Z\s]+$') # trailing block of letters and spaces

def init(cfg):
global MY_STATE
MY_STATE = cfg

def check_exchange(qso):
m = MULT_PATTERN.search(qso.exchange)
if m:
parts = m.group(0).split()
else:
parts = []

mult = ''

if MY_STATE == 'CA':
if len(parts) == 0: # no value
pass
elif len(parts) == 1: # single value
part = parts[0]
if part in STATES:
mult = part
elif part in CA_COUNTIES:
mult = 'CA'
else: # multiple values, all must be valid CA counties
ok = True
for part in parts:
if part not in CA_COUNTIES:
ok = False
if ok:
mult = 'CA'
else: # Non-California Station
for part in parts:
if part in CA_COUNTIES:
mult += part + ' '

return {'mult1_value': mult}
11 changes: 11 additions & 0 deletions test/rules/eudx/eudx.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
40CW 31-Jan-24 19:53 0001 OE1AAA 599 599 AT03 OE AT03 10
40CW 31-Jan-24 19:53 0002 OE3BBB 599 599 AT04 AT04 10
40CW 31-Jan-24 19:54 0003 OE5CCC 599 599 AT03 10
40CW 31-Jan-24 19:54 0004 LZ1DDD 599 599 BG01 LZ BG01 10
20CW 31-Jan-24 19:54 0005 LZ2EEE 599 599 BG01 LZ BG01 10
40SSB 31-Jan-24 19:56 0006 LZ1DDD 599 599 BG01 10
40CW 31-Jan-24 19:57 0007 IS9FFF 599 599 IT15 IS IT15 2
40CW 31-Jan-24 19:58 0008 IG9X 599 599 IT17 IG9 IT17 2
40CW 31-Jan-24 19:59 0009 I9QQQ 599 599 IT04 I IT04 2
40CW 31-Jan-24 20:00 0010 K1WWW 599 599 07 K 5
40CW 31-Jan-24 20:01 0011 ER9RRR 599 599 29 ER 3
2 changes: 2 additions & 0 deletions test/rules/eudx/logcfg.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
RULES=eudx
CALL=IK1AAA
1 change: 1 addition & 0 deletions test/rules/eudx/rules/eudx
1 change: 1 addition & 0 deletions test/rules/eudx/rules/eudx.py