not1mm 24.9.8__py3-none-any.whl → 24.9.10__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,421 @@
1
+ """IARU Region 1 Field Day"""
2
+
3
+ # pylint: disable=invalid-name, c-extension-no-member, unused-import
4
+
5
+ # Status: Active
6
+ # Geographic Focus: Europe
7
+ # Participation: Worldwide
8
+ # Mode: CW
9
+ # Bands: 160, 80, 40, 20, 15, 10m
10
+ # Classes: (see your national society rules)
11
+ # Exchange: RST + Serial No.
12
+ # E-mail logs to: (none)
13
+ # Upload log at: https://dxhf2.darc.de/~fdcwlog/upload.cgi?form=referat&lang=en
14
+ # Mail logs to: (none)
15
+ # Find rules at: https://www.darc.de/der-club/referate/conteste/iaru-region-1-fieldday/en/
16
+
17
+ # Scoring
18
+ # Fixed station to fixed station: 0 points
19
+
20
+ # For contacts with:
21
+
22
+ # fixed stations in Europe: 2 points
23
+ # fixed stations outside Europe: 3 points
24
+ # portable stations in Europe: 4 points
25
+ # portable stations outside Europe: 6 points
26
+
27
+ # Each station may be contacted only once per band.
28
+
29
+ # Portable stations only count as portable if they sign "/p", "/m", "/mm", or "/am",
30
+
31
+ # 10. Multipliers
32
+ # ONE for each WAE country / DXCC entity worked on each band
33
+
34
+
35
+ import datetime
36
+ import logging
37
+
38
+ from pathlib import Path
39
+
40
+ from PyQt6 import QtWidgets
41
+
42
+ from not1mm.lib.plugin_common import gen_adif, get_points
43
+ from not1mm.lib.version import __version__
44
+
45
+ logger = logging.getLogger(__name__)
46
+
47
+ EXCHANGE_HINT = "#"
48
+
49
+ name = "IARU FIELDDAY R1 DARC CW"
50
+ cabrillo_name = "IARU-FD-R1-DARC-CW"
51
+ mode = "CW" # CW SSB BOTH RTTY
52
+ # columns = [0, 1, 2, 3, 4, 5, 6, 9, 11, 15]
53
+ columns = [
54
+ "YYYY-MM-DD HH:MM:SS",
55
+ "Call",
56
+ "Freq",
57
+ "Snt",
58
+ "Rcv",
59
+ "SentNr",
60
+ "RcvNr",
61
+ "M1",
62
+ "PTS",
63
+ ]
64
+
65
+ advance_on_space = [True, True, True, True, True]
66
+
67
+ # 1 once per contest, 2 work each band, 3 each band/mode, 4 no dupe checking
68
+ dupe_type = 2
69
+
70
+
71
+ def init_contest(self):
72
+ """setup plugin"""
73
+ set_tab_next(self)
74
+ set_tab_prev(self)
75
+ interface(self)
76
+ self.next_field = self.other_2
77
+
78
+
79
+ def interface(self):
80
+ """Setup user interface"""
81
+ self.field1.show()
82
+ self.field2.show()
83
+ self.field3.show()
84
+ self.field4.show()
85
+ self.snt_label.setText("SNT")
86
+ self.field1.setAccessibleName("RST Sent")
87
+ self.other_label.setText("SentNR")
88
+ self.field3.setAccessibleName("Sent Number")
89
+ self.exch_label.setText("RcvNR")
90
+ self.field4.setAccessibleName("Received Number")
91
+
92
+
93
+ def reset_label(self): # pylint: disable=unused-argument
94
+ """reset label after field cleared"""
95
+
96
+
97
+ def set_tab_next(self):
98
+ """Set TAB Advances"""
99
+ self.tab_next = {
100
+ self.callsign: self.field1.findChild(QtWidgets.QLineEdit),
101
+ self.field1.findChild(QtWidgets.QLineEdit): self.field2.findChild(
102
+ QtWidgets.QLineEdit
103
+ ),
104
+ self.field2.findChild(QtWidgets.QLineEdit): self.field3.findChild(
105
+ QtWidgets.QLineEdit
106
+ ),
107
+ self.field3.findChild(QtWidgets.QLineEdit): self.field4.findChild(
108
+ QtWidgets.QLineEdit
109
+ ),
110
+ self.field4.findChild(QtWidgets.QLineEdit): self.callsign,
111
+ }
112
+
113
+
114
+ def set_tab_prev(self):
115
+ """Set TAB Advances"""
116
+ self.tab_prev = {
117
+ self.callsign: self.field4.findChild(QtWidgets.QLineEdit),
118
+ self.field1.findChild(QtWidgets.QLineEdit): self.callsign,
119
+ self.field2.findChild(QtWidgets.QLineEdit): self.field1.findChild(
120
+ QtWidgets.QLineEdit
121
+ ),
122
+ self.field3.findChild(QtWidgets.QLineEdit): self.field2.findChild(
123
+ QtWidgets.QLineEdit
124
+ ),
125
+ self.field4.findChild(QtWidgets.QLineEdit): self.field3.findChild(
126
+ QtWidgets.QLineEdit
127
+ ),
128
+ }
129
+
130
+
131
+ def set_contact_vars(self):
132
+ """Contest Specific"""
133
+ self.contact["SNT"] = self.sent.text()
134
+ self.contact["RCV"] = self.receive.text()
135
+ self.contact["SentNr"] = self.other_1.text()
136
+ self.contact["NR"] = self.other_2.text()
137
+ if self.contact.get("CountryPrefix", ""):
138
+ result = self.database.fetch_dxcc_exists(self.contact.get("CountryPrefix", ""))
139
+ if result.get("dxcc_count", ""):
140
+ self.contact["IsMultiplier1"] = 0
141
+ else:
142
+ self.contact["IsMultiplier1"] = 1
143
+
144
+
145
+ def predupe(self): # pylint: disable=unused-argument
146
+ """called after callsign entered"""
147
+
148
+
149
+ def prefill(self):
150
+ """Fill SentNR"""
151
+ result = self.database.get_serial()
152
+ serial_nr = str(result.get("serial_nr", "1")).zfill(3)
153
+ if serial_nr == "None":
154
+ serial_nr = "001"
155
+ field = self.field3.findChild(QtWidgets.QLineEdit)
156
+ if len(field.text()) == 0:
157
+ field.setText(serial_nr)
158
+
159
+
160
+ def points(self):
161
+ """
162
+ Calc point
163
+
164
+ # fixed stations in Europe: 2 points
165
+ # fixed stations outside Europe: 3 points
166
+ # portable stations in Europe: 4 points
167
+ # portable stations outside Europe: 6 points
168
+ """
169
+
170
+ their_portable = False
171
+ im_portable = False
172
+ their_continent = self.contact.get("Continent", "")
173
+ the_call = self.contact.get("Call", "").upper()
174
+
175
+ if the_call.endswith(("/P", "/M", "/MM", "/AM")):
176
+ their_portable = True
177
+ if self.station.get("Call", "").endswith(("/P", "/M", "/MM", "/AM")):
178
+ im_portable = True
179
+
180
+ if not im_portable and not their_portable:
181
+ return 0
182
+
183
+ if their_continent:
184
+ if their_portable:
185
+ if their_continent == "EU":
186
+ return 4
187
+ else:
188
+ return 6
189
+ else:
190
+ if their_continent == "EU":
191
+ return 2
192
+ else:
193
+ return 3
194
+
195
+ # Something wrong
196
+ return 0
197
+
198
+
199
+ def show_mults(self):
200
+ """Return display string for mults"""
201
+ result = self.database.fetch_mult_count(1)
202
+ if result:
203
+ return int(result.get("count", 0))
204
+ return 0
205
+
206
+
207
+ def show_qso(self):
208
+ """Return qso count"""
209
+ result = self.database.fetch_qso_count()
210
+ if result:
211
+ return int(result.get("qsos", 0))
212
+ return 0
213
+
214
+
215
+ def calc_score(self):
216
+ """Return calculated score"""
217
+ result = self.database.fetch_points()
218
+ if result is not None:
219
+ score = result.get("Points", "0")
220
+ if score is None:
221
+ score = "0"
222
+ contest_points = int(score)
223
+ result = self.database.fetch_mult_count(1)
224
+ mults = int(result.get("count", 0))
225
+ return contest_points * mults
226
+ return 0
227
+
228
+
229
+ def adif(self):
230
+ """Call the generate ADIF function"""
231
+ gen_adif(self, cabrillo_name, "IARU FIELDDAY R1 DARC CW")
232
+
233
+
234
+ def cabrillo(self):
235
+ """Generates Cabrillo file. Maybe."""
236
+ # https://www.cqwpx.com/cabrillo.htm
237
+ logger.debug("******Cabrillo*****")
238
+ logger.debug("Station: %s", f"{self.station}")
239
+ logger.debug("Contest: %s", f"{self.contest_settings}")
240
+ now = datetime.datetime.now()
241
+ date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
242
+ filename = (
243
+ str(Path.home())
244
+ + "/"
245
+ + f"{self.station.get('Call', '').upper()}_{cabrillo_name}_{date_time}.log"
246
+ )
247
+ logger.debug("%s", filename)
248
+ log = self.database.fetch_all_contacts_asc()
249
+ try:
250
+ with open(filename, "w", encoding="ascii") as file_descriptor:
251
+ print("START-OF-LOG: 3.0", end="\r\n", file=file_descriptor)
252
+ print(
253
+ f"CREATED-BY: Not1MM v{__version__}",
254
+ end="\r\n",
255
+ file=file_descriptor,
256
+ )
257
+ print(
258
+ f"CONTEST: {cabrillo_name}",
259
+ end="\r\n",
260
+ file=file_descriptor,
261
+ )
262
+ if self.station.get("Club", ""):
263
+ print(
264
+ f"CLUB: {self.station.get('Club', '').upper()}",
265
+ end="\r\n",
266
+ file=file_descriptor,
267
+ )
268
+ print(
269
+ f"CALLSIGN: {self.station.get('Call','')}",
270
+ end="\r\n",
271
+ file=file_descriptor,
272
+ )
273
+ print(
274
+ f"LOCATION: {self.station.get('ARRLSection', '')}",
275
+ end="\r\n",
276
+ file=file_descriptor,
277
+ )
278
+ # print(
279
+ # f"ARRL-SECTION: {self.pref.get('section', '')}",
280
+ # end="\r\n",
281
+ # file=file_descriptor,
282
+ # )
283
+ print(
284
+ f"CATEGORY-OPERATOR: {self.contest_settings.get('OperatorCategory','')}",
285
+ end="\r\n",
286
+ file=file_descriptor,
287
+ )
288
+ print(
289
+ f"CATEGORY-ASSISTED: {self.contest_settings.get('AssistedCategory','')}",
290
+ end="\r\n",
291
+ file=file_descriptor,
292
+ )
293
+ print(
294
+ f"CATEGORY-BAND: {self.contest_settings.get('BandCategory','')}",
295
+ end="\r\n",
296
+ file=file_descriptor,
297
+ )
298
+ print(
299
+ f"CATEGORY-MODE: {self.contest_settings.get('ModeCategory','')}",
300
+ end="\r\n",
301
+ file=file_descriptor,
302
+ )
303
+ print(
304
+ f"CATEGORY-TRANSMITTER: {self.contest_settings.get('TransmitterCategory','')}",
305
+ end="\r\n",
306
+ file=file_descriptor,
307
+ )
308
+ if self.contest_settings.get("OverlayCategory", "") != "N/A":
309
+ print(
310
+ f"CATEGORY-OVERLAY: {self.contest_settings.get('OverlayCategory','')}",
311
+ end="\r\n",
312
+ file=file_descriptor,
313
+ )
314
+ print(
315
+ f"GRID-LOCATOR: {self.station.get('GridSquare','')}",
316
+ end="\r\n",
317
+ file=file_descriptor,
318
+ )
319
+ # print(
320
+ # f"CATEGORY: {None}",
321
+ # end="\r\n",
322
+ # file=file_descriptor,
323
+ # )
324
+ print(
325
+ f"CATEGORY-POWER: {self.contest_settings.get('PowerCategory','')}",
326
+ end="\r\n",
327
+ file=file_descriptor,
328
+ )
329
+
330
+ print(
331
+ f"CLAIMED-SCORE: {calc_score(self)}",
332
+ end="\r\n",
333
+ file=file_descriptor,
334
+ )
335
+ ops = f"@{self.station.get('Call','')}"
336
+ list_of_ops = self.database.get_ops()
337
+ for op in list_of_ops:
338
+ ops += f", {op.get('Operator', '')}"
339
+ print(
340
+ f"OPERATORS: {ops}",
341
+ end="\r\n",
342
+ file=file_descriptor,
343
+ )
344
+ print(
345
+ f"NAME: {self.station.get('Name', '')}",
346
+ end="\r\n",
347
+ file=file_descriptor,
348
+ )
349
+ print(
350
+ f"ADDRESS: {self.station.get('Street1', '')}",
351
+ end="\r\n",
352
+ file=file_descriptor,
353
+ )
354
+ print(
355
+ f"ADDRESS-CITY: {self.station.get('City', '')}",
356
+ end="\r\n",
357
+ file=file_descriptor,
358
+ )
359
+ print(
360
+ f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
361
+ end="\r\n",
362
+ file=file_descriptor,
363
+ )
364
+ print(
365
+ f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
366
+ end="\r\n",
367
+ file=file_descriptor,
368
+ )
369
+ print(
370
+ f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
371
+ end="\r\n",
372
+ file=file_descriptor,
373
+ )
374
+ print(
375
+ f"EMAIL: {self.station.get('Email', '')}",
376
+ end="\r\n",
377
+ file=file_descriptor,
378
+ )
379
+ for contact in log:
380
+ the_date_and_time = contact.get("TS", "")
381
+ themode = contact.get("Mode", "")
382
+ if themode == "LSB" or themode == "USB":
383
+ themode = "PH"
384
+ frequency = str(int(contact.get("Freq", "0"))).rjust(5)
385
+
386
+ loggeddate = the_date_and_time[:10]
387
+ loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
388
+ print(
389
+ f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
390
+ f"{contact.get('StationPrefix', '').ljust(13)} "
391
+ f"{str(contact.get('SNT', '')).ljust(3)} "
392
+ f"{str(contact.get('SentNr', '')).ljust(6)} "
393
+ f"{contact.get('Call', '').ljust(13)} "
394
+ f"{str(contact.get('RCV', '')).ljust(3)} "
395
+ f"{str(contact.get('NR', '')).ljust(6)}",
396
+ end="\r\n",
397
+ file=file_descriptor,
398
+ )
399
+ print("END-OF-LOG:", end="\r\n", file=file_descriptor)
400
+ self.show_message_box(f"Cabrillo saved to: {filename}")
401
+ except IOError as exception:
402
+ logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
403
+ self.show_message_box(f"Error saving Cabrillo: {exception} {filename}")
404
+ return
405
+
406
+
407
+ def recalculate_mults(self):
408
+ """Recalculates multipliers after change in logged qso."""
409
+ all_contacts = self.database.fetch_all_contacts_asc()
410
+ for contact in all_contacts:
411
+ self.contact = contact
412
+ contact["Points"] = points(self)
413
+ time_stamp = contact.get("TS", "")
414
+ dxcc = contact.get("CountryPrefix", "")
415
+ result = self.database.fetch_dxcc_exists_before_me(dxcc, time_stamp)
416
+ dxcc_count = result.get("dxcc_count", 1)
417
+ if dxcc_count == 0:
418
+ contact["IsMultiplier1"] = 1
419
+ else:
420
+ contact["IsMultiplier1"] = 0
421
+ self.database.change_contact(contact)