not1mm 24.8.20__py3-none-any.whl → 24.9.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,497 @@
1
+ """
2
+ Helvetica
3
+ -------------------------------------------------
4
+ Status: Active
5
+ Geographic Focus: Switzerland
6
+ Participation: Worldwide
7
+ Mode: CW, SSB, Digital
8
+ Bands: 160, 80, 40, 20, 15, 10m
9
+ Classes: Single Op (CW/SSB) High
10
+ Single Op Mixed (QRP/Low/High)
11
+ Multi-Op (CW/SSB/Mixed) High
12
+ SWL
13
+ Max operating hours: 18 with a maximum of two rest periods of any length
14
+ Max power: HP: >100 watts
15
+ LP: 100 watts
16
+ QRP: 5 watts (CW/Digital) or 10 watts (SSB)
17
+ Exchange: HB: RS(T) + 2-letter canton
18
+ non-HB: RS(T) + Serial No.
19
+ Work stations: Once per band per mode
20
+
21
+ Scoring:
22
+ Contact with a station in Switzerland: 10 points
23
+ Contact with a station within the same continent: 1 point
24
+ Contact with a station outside the operator’s continent: 3 points
25
+
26
+ Multipliers: Canton and DXCC country (including Switzerland) per band: 1 point
27
+
28
+ Score Calculation: Total score = total QSO points x total mults
29
+ E-mail logs to: contest[at]uska[dot]ch
30
+ Mail logs to: (none)
31
+ Find rules at: https://www.uska.ch/events/uska-helvetia-contest-concours-helvetia-hf/
32
+ Cabrillo name: HELVETIA
33
+ """
34
+
35
+ import datetime
36
+ import logging
37
+ import platform
38
+
39
+ from pathlib import Path
40
+
41
+ from PyQt6 import QtWidgets
42
+
43
+ from not1mm.lib.plugin_common import gen_adif, get_points
44
+
45
+ from not1mm.lib.version import __version__
46
+
47
+ logger = logging.getLogger(__name__)
48
+
49
+ EXCHANGE_HINT = "Canton or #"
50
+
51
+ name = "HELVETIA"
52
+ cabrillo_name = "HELVETIA"
53
+ mode = "BOTH" # CW SSB BOTH RTTY
54
+
55
+ columns = [
56
+ "YYYY-MM-DD HH:MM:SS",
57
+ "Call",
58
+ "Freq",
59
+ "Mode",
60
+ "Snt",
61
+ "Rcv",
62
+ "SentNr",
63
+ "RcvNr",
64
+ "M1",
65
+ "M2",
66
+ "PTS",
67
+ ]
68
+
69
+ advance_on_space = [True, True, True, True, True]
70
+
71
+ # 1 once per contest, 2 work each band, 3 each band/mode, 4 no dupe checking
72
+ dupe_type = 3
73
+
74
+ cantons = [
75
+ "AG",
76
+ "AI",
77
+ "AR",
78
+ "BE",
79
+ "BL",
80
+ "BS",
81
+ "CH",
82
+ "FR",
83
+ "GE",
84
+ "GL",
85
+ "GR",
86
+ "JU",
87
+ "LU",
88
+ "NE",
89
+ "NW",
90
+ "OW",
91
+ "SG",
92
+ "SH",
93
+ "SO",
94
+ "SZ",
95
+ "TG",
96
+ "TI",
97
+ "UR",
98
+ "VD",
99
+ "VS",
100
+ "ZG",
101
+ "ZH",
102
+ ]
103
+
104
+
105
+ def init_contest(self):
106
+ """setup plugin"""
107
+ set_tab_next(self)
108
+ set_tab_prev(self)
109
+ interface(self)
110
+ self.next_field = self.other_2
111
+
112
+
113
+ def interface(self):
114
+ """Setup user interface"""
115
+ self.field1.show()
116
+ self.field2.show()
117
+ self.field3.show()
118
+ self.field4.show()
119
+ label = self.field3.findChild(QtWidgets.QLabel)
120
+ label.setText("Sent")
121
+ self.field3.setAccessibleName("Sent")
122
+ label = self.field4.findChild(QtWidgets.QLabel)
123
+ label.setText("Canton/SN")
124
+ self.field4.setAccessibleName("Canton or SN")
125
+
126
+
127
+ def reset_label(self):
128
+ """reset label after field cleared"""
129
+
130
+
131
+ def set_tab_next(self):
132
+ """Set TAB Advances"""
133
+ self.tab_next = {
134
+ self.callsign: self.field3.findChild(QtWidgets.QLineEdit),
135
+ self.field1.findChild(QtWidgets.QLineEdit): self.field3.findChild(
136
+ QtWidgets.QLineEdit
137
+ ),
138
+ self.field2.findChild(QtWidgets.QLineEdit): self.field3.findChild(
139
+ QtWidgets.QLineEdit
140
+ ),
141
+ self.field3.findChild(QtWidgets.QLineEdit): self.field4.findChild(
142
+ QtWidgets.QLineEdit
143
+ ),
144
+ self.field4.findChild(QtWidgets.QLineEdit): self.callsign,
145
+ }
146
+
147
+
148
+ def set_tab_prev(self):
149
+ """Set TAB Advances"""
150
+ self.tab_prev = {
151
+ self.callsign: self.field4.findChild(QtWidgets.QLineEdit),
152
+ self.field1.findChild(QtWidgets.QLineEdit): self.callsign,
153
+ self.field2.findChild(QtWidgets.QLineEdit): self.callsign,
154
+ self.field3.findChild(QtWidgets.QLineEdit): self.callsign,
155
+ self.field4.findChild(QtWidgets.QLineEdit): self.field3.findChild(
156
+ QtWidgets.QLineEdit
157
+ ),
158
+ }
159
+
160
+
161
+ def set_contact_vars(self):
162
+ """Contest Specific"""
163
+ self.contact["SNT"] = self.sent.text()
164
+ self.contact["RCV"] = self.receive.text()
165
+ self.contact["SentNr"] = self.other_1.text().upper()
166
+ self.contact["NR"] = self.other_2.text().upper()
167
+
168
+ self.contact["IsMultiplier1"] = 0
169
+ self.contact["IsMultiplier2"] = 0
170
+
171
+ if (
172
+ self.contact.get("CountryPrefix", "") == "HB"
173
+ and self.contact.get("NR", "").isalpha()
174
+ ):
175
+ canton = self.contact.get("NR", "").upper()
176
+ band = self.contact.get("Band", "")
177
+ query = (
178
+ f"select count(*) as canton_count from dxlog where "
179
+ f"NR = '{canton}' "
180
+ f"and Band = '{band}' "
181
+ f"and ContestNR = {self.pref.get('contest', '1')};"
182
+ )
183
+ result = self.database.exec_sql(query)
184
+ count = int(result.get("canton_count", 0))
185
+ if count == 0:
186
+ self.contact["IsMultiplier1"] = 1
187
+
188
+ if self.contact.get("CountryPrefix", ""):
189
+ dxcc = self.contact.get("CountryPrefix", "")
190
+ band = self.contact.get("Band", "")
191
+ query = (
192
+ f"select count(*) as dxcc_count from dxlog where "
193
+ f"CountryPrefix = '{dxcc}' "
194
+ f"and Band = '{band}' "
195
+ f"and ContestNR = {self.pref.get('contest', '1')};"
196
+ )
197
+ result = self.database.exec_sql(query)
198
+ if not result.get("dxcc_count", ""):
199
+ self.contact["IsMultiplier2"] = 1
200
+
201
+
202
+ def predupe(self):
203
+ """called after callsign entered"""
204
+
205
+
206
+ def prefill(self):
207
+ """Fill SentNR"""
208
+ field = self.field3.findChild(QtWidgets.QLineEdit)
209
+ sent_sxchange_setting = self.contest_settings.get("SentExchange", "")
210
+ if sent_sxchange_setting.strip() == "#":
211
+ result = self.database.get_serial()
212
+ serial_nr = str(result.get("serial_nr", "1")).zfill(3)
213
+ if serial_nr == "None":
214
+ serial_nr = "001"
215
+ if len(field.text()) == 0:
216
+ field.setText(serial_nr)
217
+ else:
218
+ field.setText(sent_sxchange_setting)
219
+
220
+
221
+ def points(self):
222
+ """
223
+ Scoring:
224
+ Contact with a station within the same continent: 1 point
225
+ Contact with a station outside the operator’s continent: 3 points
226
+ Contact with a station in Switzerland: 10 points
227
+ self.contact["CountryPrefix"]
228
+ self.contact["Continent"]
229
+ """
230
+ result = self.cty_lookup(self.station.get("Call", ""))
231
+ if result:
232
+ for item in result.items():
233
+ my_continent = item[1].get("continent", "")
234
+ result = self.cty_lookup(self.contact.get("Call", ""))
235
+ if result:
236
+ for item in result.items():
237
+ their_country = item[1].get("entity", "")
238
+ their_continent = item[1].get("continent", "")
239
+
240
+ if their_country == "Switzerland":
241
+ return 10
242
+
243
+ if my_continent != their_continent:
244
+ return 3
245
+
246
+ return 1
247
+ # Something wrong
248
+ return 0
249
+
250
+
251
+ def show_mults(self):
252
+ """Return display string for mults"""
253
+ return int(self.database.fetch_mult_count(1).get("count", 0)) + int(
254
+ self.database.fetch_mult_count(2).get("count", 0)
255
+ )
256
+
257
+
258
+ def show_qso(self):
259
+ """Return qso count"""
260
+ result = self.database.fetch_qso_count()
261
+ if result:
262
+ return int(result.get("qsos", 0))
263
+ return 0
264
+
265
+
266
+ def calc_score(self):
267
+ """Return calculated score"""
268
+ result = self.database.fetch_points()
269
+ if result is not None:
270
+ score = result.get("Points", "0")
271
+ if score is None:
272
+ score = "0"
273
+ contest_points = int(score)
274
+ mults = show_mults(self)
275
+ return contest_points * mults
276
+ return 0
277
+
278
+
279
+ def recalculate_mults(self):
280
+ """Recalculates multipliers after change in logged qso."""
281
+
282
+ all_contacts = self.database.fetch_all_contacts_asc()
283
+ for contact in all_contacts:
284
+
285
+ contact["IsMultiplier1"] = 0
286
+ contact["IsMultiplier2"] = 0
287
+
288
+ time_stamp = contact.get("TS", "")
289
+ canton = contact.get("NR", "")
290
+ dxcc = contact.get("CountryPrefix", "")
291
+ band = contact.get("Band", "")
292
+ if dxcc == "HB" and canton.isalpha():
293
+ query = (
294
+ f"select count(*) as canton_count from dxlog where TS < '{time_stamp}' "
295
+ f"and NR = '{canton.upper()}' "
296
+ f"and Band = '{band}' "
297
+ f"and ContestNR = {self.pref.get('contest', '1')};"
298
+ )
299
+ result = self.database.exec_sql(query)
300
+ count = int(result.get("canton_count", 0))
301
+ if count == 0:
302
+ contact["IsMultiplier1"] = 1
303
+
304
+ if dxcc:
305
+ query = (
306
+ f"select count(*) as dxcc_count from dxlog where TS < '{time_stamp}' "
307
+ f"and CountryPrefix = '{dxcc}' "
308
+ f"and Band = '{band}' "
309
+ f"and ContestNR = {self.pref.get('contest', '1')};"
310
+ )
311
+ result = self.database.exec_sql(query)
312
+ if not result.get("dxcc_count", ""):
313
+ contact["IsMultiplier2"] = 1
314
+
315
+ self.database.change_contact(contact)
316
+ cmd = {}
317
+ cmd["cmd"] = "UPDATELOG"
318
+ cmd["station"] = platform.node()
319
+ self.multicast_interface.send_as_json(cmd)
320
+
321
+
322
+ def adif(self):
323
+ """Call the generate ADIF function"""
324
+ gen_adif(self, cabrillo_name, "HELVETIA")
325
+
326
+
327
+ def cabrillo(self):
328
+ """Generates Cabrillo file. Maybe."""
329
+ # https://www.cqwpx.com/cabrillo.htm
330
+ logger.debug("******Cabrillo*****")
331
+ logger.debug("Station: %s", f"{self.station}")
332
+ logger.debug("Contest: %s", f"{self.contest_settings}")
333
+ now = datetime.datetime.now()
334
+ date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
335
+ filename = (
336
+ str(Path.home())
337
+ + "/"
338
+ + f"{self.station.get('Call', '').upper()}_{cabrillo_name}_{date_time}.log"
339
+ )
340
+ logger.debug("%s", filename)
341
+ log = self.database.fetch_all_contacts_asc()
342
+ try:
343
+ with open(filename, "w", encoding="ascii") as file_descriptor:
344
+ print("START-OF-LOG: 3.0", end="\r\n", file=file_descriptor)
345
+ print(
346
+ f"CREATED-BY: Not1MM v{__version__}",
347
+ end="\r\n",
348
+ file=file_descriptor,
349
+ )
350
+ print(
351
+ f"CONTEST: {cabrillo_name}",
352
+ end="\r\n",
353
+ file=file_descriptor,
354
+ )
355
+ if self.station.get("Club", ""):
356
+ print(
357
+ f"CLUB: {self.station.get('Club', '').upper()}",
358
+ end="\r\n",
359
+ file=file_descriptor,
360
+ )
361
+ print(
362
+ f"CALLSIGN: {self.station.get('Call','')}",
363
+ end="\r\n",
364
+ file=file_descriptor,
365
+ )
366
+ print(
367
+ f"LOCATION: {self.station.get('ARRLSection', '')}",
368
+ end="\r\n",
369
+ file=file_descriptor,
370
+ )
371
+ # print(
372
+ # f"ARRL-SECTION: {self.pref.get('section', '')}",
373
+ # end="\r\n",
374
+ # file=file_descriptor,
375
+ # )
376
+ print(
377
+ f"CATEGORY-OPERATOR: {self.contest_settings.get('OperatorCategory','')}",
378
+ end="\r\n",
379
+ file=file_descriptor,
380
+ )
381
+ print(
382
+ f"CATEGORY-ASSISTED: {self.contest_settings.get('AssistedCategory','')}",
383
+ end="\r\n",
384
+ file=file_descriptor,
385
+ )
386
+ print(
387
+ f"CATEGORY-BAND: {self.contest_settings.get('BandCategory','')}",
388
+ end="\r\n",
389
+ file=file_descriptor,
390
+ )
391
+ print(
392
+ f"CATEGORY-MODE: {self.contest_settings.get('ModeCategory','')}",
393
+ end="\r\n",
394
+ file=file_descriptor,
395
+ )
396
+ print(
397
+ f"CATEGORY-TRANSMITTER: {self.contest_settings.get('TransmitterCategory','')}",
398
+ end="\r\n",
399
+ file=file_descriptor,
400
+ )
401
+ if self.contest_settings.get("OverlayCategory", "") != "N/A":
402
+ print(
403
+ f"CATEGORY-OVERLAY: {self.contest_settings.get('OverlayCategory','')}",
404
+ end="\r\n",
405
+ file=file_descriptor,
406
+ )
407
+ print(
408
+ f"GRID-LOCATOR: {self.station.get('GridSquare','')}",
409
+ end="\r\n",
410
+ file=file_descriptor,
411
+ )
412
+ # print(
413
+ # f"CATEGORY: {None}",
414
+ # end="\r\n",
415
+ # file=file_descriptor,
416
+ # )
417
+ print(
418
+ f"CATEGORY-POWER: {self.contest_settings.get('PowerCategory','')}",
419
+ end="\r\n",
420
+ file=file_descriptor,
421
+ )
422
+
423
+ print(
424
+ f"CLAIMED-SCORE: {calc_score(self)}",
425
+ end="\r\n",
426
+ file=file_descriptor,
427
+ )
428
+ ops = f"@{self.station.get('Call','')}"
429
+ list_of_ops = self.database.get_ops()
430
+ for op in list_of_ops:
431
+ ops += f", {op.get('Operator', '')}"
432
+ print(
433
+ f"OPERATORS: {ops}",
434
+ end="\r\n",
435
+ file=file_descriptor,
436
+ )
437
+ print(
438
+ f"NAME: {self.station.get('Name', '')}",
439
+ end="\r\n",
440
+ file=file_descriptor,
441
+ )
442
+ print(
443
+ f"ADDRESS: {self.station.get('Street1', '')}",
444
+ end="\r\n",
445
+ file=file_descriptor,
446
+ )
447
+ print(
448
+ f"ADDRESS-CITY: {self.station.get('City', '')}",
449
+ end="\r\n",
450
+ file=file_descriptor,
451
+ )
452
+ print(
453
+ f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
454
+ end="\r\n",
455
+ file=file_descriptor,
456
+ )
457
+ print(
458
+ f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
459
+ end="\r\n",
460
+ file=file_descriptor,
461
+ )
462
+ print(
463
+ f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
464
+ end="\r\n",
465
+ file=file_descriptor,
466
+ )
467
+ print(
468
+ f"EMAIL: {self.station.get('Email', '')}",
469
+ end="\r\n",
470
+ file=file_descriptor,
471
+ )
472
+ for contact in log:
473
+ the_date_and_time = contact.get("TS", "")
474
+ themode = contact.get("Mode", "")
475
+ if themode == "LSB" or themode == "USB":
476
+ themode = "PH"
477
+ frequency = str(int(contact.get("Freq", "0"))).rjust(5)
478
+
479
+ loggeddate = the_date_and_time[:10]
480
+ loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
481
+ print(
482
+ f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
483
+ f"{contact.get('StationPrefix', '').ljust(13)} "
484
+ f"{str(contact.get('SNT', '')).ljust(3)} "
485
+ f"{str(contact.get('SentNr', '')).ljust(6)} "
486
+ f"{contact.get('Call', '').ljust(13)} "
487
+ f"{str(contact.get('RCV', '')).ljust(3)} "
488
+ f"{str(contact.get('NR', '')).ljust(6)}",
489
+ end="\r\n",
490
+ file=file_descriptor,
491
+ )
492
+ print("END-OF-LOG:", end="\r\n", file=file_descriptor)
493
+ self.show_message_box(f"Cabrillo saved to: {filename}")
494
+ except IOError as exception:
495
+ logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
496
+ self.show_message_box(f"Error saving Cabrillo: {exception} {filename}")
497
+ return