not1mm 23.12.5__py3-none-any.whl → 24.1.15__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.
Files changed (42) hide show
  1. not1mm/__main__.py +249 -399
  2. not1mm/data/MASTER.SCP +1056 -48577
  3. not1mm/data/configuration.ui +93 -2
  4. not1mm/data/cty.json +1 -1
  5. not1mm/data/main.ui +186 -3
  6. not1mm/data/new_contest.ui +26 -1
  7. not1mm/lib/ham_utility.py +16 -4
  8. not1mm/lib/settings.py +40 -0
  9. not1mm/lib/version.py +1 -1
  10. not1mm/plugins/10_10_fall_cw.py +1 -1
  11. not1mm/plugins/10_10_spring_cw.py +1 -1
  12. not1mm/plugins/10_10_summer_phone.py +1 -1
  13. not1mm/plugins/10_10_winter_phone.py +1 -1
  14. not1mm/plugins/arrl_10m.py +413 -0
  15. not1mm/plugins/arrl_dx_cw.py +1 -1
  16. not1mm/plugins/arrl_dx_ssb.py +1 -1
  17. not1mm/plugins/arrl_ss_cw.py +4 -1
  18. not1mm/plugins/arrl_ss_phone.py +4 -1
  19. not1mm/plugins/arrl_vhf_jan.py +390 -0
  20. not1mm/plugins/arrl_vhf_jun.py +358 -0
  21. not1mm/plugins/arrl_vhf_sep.py +357 -0
  22. not1mm/plugins/canada_day.py +5 -2
  23. not1mm/plugins/cq_wpx_cw.py +1 -1
  24. not1mm/plugins/cq_wpx_ssb.py +1 -1
  25. not1mm/plugins/cq_ww_cw.py +1 -1
  26. not1mm/plugins/cq_ww_ssb.py +1 -1
  27. not1mm/plugins/cwt.py +5 -2
  28. not1mm/plugins/general_logging.py +1 -1
  29. not1mm/plugins/iaru_hf.py +1 -1
  30. not1mm/plugins/jidx_cw.py +2 -1
  31. not1mm/plugins/jidx_ph.py +2 -1
  32. not1mm/plugins/naqp_cw.py +1 -2
  33. not1mm/plugins/naqp_ssb.py +1 -2
  34. not1mm/plugins/phone_weekly_test.py +372 -0
  35. not1mm/plugins/stew_perry_topband.py +336 -0
  36. not1mm/weee.py +10 -0
  37. {not1mm-23.12.5.dist-info → not1mm-24.1.15.dist-info}/METADATA +19 -7
  38. {not1mm-23.12.5.dist-info → not1mm-24.1.15.dist-info}/RECORD +42 -35
  39. {not1mm-23.12.5.dist-info → not1mm-24.1.15.dist-info}/LICENSE +0 -0
  40. {not1mm-23.12.5.dist-info → not1mm-24.1.15.dist-info}/WHEEL +0 -0
  41. {not1mm-23.12.5.dist-info → not1mm-24.1.15.dist-info}/entry_points.txt +0 -0
  42. {not1mm-23.12.5.dist-info → not1mm-24.1.15.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,390 @@
1
+ """ARRL Jan VHF"""
2
+
3
+
4
+ # Status: Active
5
+ # Geographic Focus: United States/Canada
6
+ # Participation: Worldwide
7
+ # Mode: Any
8
+ # Bands: 50 MHz and up
9
+ # Classes: Single Op All Band (All Modes/Analog Modes)(Low/High)
10
+ # Single Op Portable (All Modes/Analog Modes)
11
+ # Single Op 3-Band (All Modes/Analog Modes)
12
+ # Single Op FM
13
+ # Rover
14
+ # Limited Rover
15
+ # Unlimited Rover
16
+ # Multi-Op
17
+ # Limited Multi-Op
18
+ # Max power: (see rules)
19
+ # Exchange: 4-character grid square
20
+ # Work stations: Once per band
21
+ # QSO Points: 1 point per 50 or 144 MHz QSO
22
+ # 2 points per 222 or 432 MHz QSO
23
+ # 4 points per 902 or 1296 MHz QSO
24
+ # 8 points per 2.3 GHz or higher QSO
25
+ # Multipliers: Grid squares once per band
26
+ # Rovers: grid squares operated from once regardless of band
27
+ # Score Calculation: Total score = total QSO points x total mults
28
+ # E-mail logs to: (none)
29
+ # Upload log at: http://contest-log-submission.arrl.org
30
+ # Mail logs to: January VHF
31
+ # ARRL
32
+ # 225 Main St.
33
+ # Newington, CT 06111
34
+ # USA
35
+ # Find rules at: http://www.arrl.org/january-vhf
36
+ # Cabrillo name: ARRL-VHF-JAN
37
+ # Cabrillo name aliases: ARRL-VHF
38
+
39
+ # pylint: disable=invalid-name, unused-argument, unused-variable, c-extension-no-member
40
+
41
+ import datetime
42
+ import logging
43
+
44
+ from pathlib import Path
45
+ from PyQt5 import QtWidgets
46
+
47
+ from not1mm.lib.plugin_common import gen_adif, get_points
48
+ from not1mm.lib.version import __version__
49
+
50
+ logger = logging.getLogger("__main__")
51
+
52
+ name = "ARRL VHF JAN"
53
+ mode = "BOTH" # CW SSB BOTH RTTY
54
+ cabrillo_name = "ARRL-VHF-JAN"
55
+
56
+ columns = [
57
+ "YYYY-MM-DD HH:MM:SS",
58
+ "Call",
59
+ "Freq",
60
+ "SentNr",
61
+ "RcvNr",
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
+ label = self.field3.findChild(QtWidgets.QLabel)
86
+ label.setText("SentNR")
87
+ self.field3.setAccessibleName("Sent Grid")
88
+ label = self.field4.findChild(QtWidgets.QLabel)
89
+ label.setText("Grid")
90
+ self.field4.setAccessibleName("Gridsquare")
91
+
92
+
93
+ def reset_label(self):
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 validate(self):
132
+ """doc"""
133
+ # exchange = self.other_2.text().upper().split()
134
+ # if len(exchange) == 3:
135
+ # if exchange[0].isalpha() and exchange[1].isdigit() and exchange[2].isalpha():
136
+ # return True
137
+ # return False
138
+ return True
139
+
140
+
141
+ def set_contact_vars(self):
142
+ """Contest Specific"""
143
+ self.contact["SNT"] = self.sent.text()
144
+ self.contact["RCV"] = self.receive.text()
145
+ self.contact["NR"] = self.other_2.text().upper()
146
+ self.contact["SentNr"] = self.other_1.text()
147
+
148
+
149
+ def predupe(self):
150
+ """called after callsign entered"""
151
+
152
+
153
+ def prefill(self):
154
+ """Fill sentnr"""
155
+ result = self.database.get_serial()
156
+ serial_nr = str(result.get("serial_nr", "1"))
157
+ if serial_nr == "None":
158
+ serial_nr = "1"
159
+
160
+ exchange = self.contest_settings.get("SentExchange", "").replace("#", serial_nr)
161
+ field = self.field3.findChild(QtWidgets.QLineEdit)
162
+ if len(field.text()) == 0:
163
+ field.setText(exchange)
164
+
165
+
166
+ def points(self):
167
+ """Calc point"""
168
+
169
+ # QSO Points: 1 point per 50 or 144 MHz QSO
170
+ # 2 points per 222 or 432 MHz QSO
171
+ # 4 points per 902 or 1296 MHz QSO
172
+ # 8 points per 2.3 GHz or higher QSO
173
+
174
+ _band = self.contact.get("Band", "")
175
+ if _band in ["50", "144"]:
176
+ return 1
177
+ if _band in ["222", "432"]:
178
+ return 2
179
+ if _band in ["902", "1296"]:
180
+ return 4
181
+ if _band in ["2300+"]:
182
+ return 8
183
+ return 0
184
+
185
+
186
+ def show_mults(self):
187
+ """Return display string for mults"""
188
+ # Multipliers: Grid squares once per band
189
+
190
+ dx = 0
191
+
192
+ sql = (
193
+ "select count(DISTINCT(NR || ':' || Band)) as mult_count "
194
+ f"from dxlog where ContestNR = {self.database.current_contest} and typeof(NR) = 'text';"
195
+ )
196
+ result = self.database.exec_sql(sql)
197
+
198
+ if result:
199
+ dx = result.get("mult_count", 0)
200
+
201
+ return dx
202
+
203
+
204
+ def show_qso(self):
205
+ """Return qso count"""
206
+ result = self.database.fetch_qso_count()
207
+ if result:
208
+ return int(result.get("qsos", 0))
209
+ return 0
210
+
211
+
212
+ def calc_score(self):
213
+ """Return calculated score"""
214
+ # Multipliers: Each US State + DC once per mode
215
+ _points = get_points(self)
216
+ _mults = show_mults(self)
217
+ _power_mult = 1
218
+ # if self.contest_settings.get("PowerCategory", "") == "QRP":
219
+ # _power_mult = 2
220
+ return _points * _power_mult * _mults
221
+
222
+
223
+ def adif(self):
224
+ """Call the generate ADIF function"""
225
+ gen_adif(self, cabrillo_name)
226
+
227
+
228
+ def cabrillo(self):
229
+ """Generates Cabrillo file. Maybe."""
230
+ # https://www.cqwpx.com/cabrillo.htm
231
+ logger.debug("******Cabrillo*****")
232
+ logger.debug("Station: %s", f"{self.station}")
233
+ logger.debug("Contest: %s", f"{self.contest_settings}")
234
+ now = datetime.datetime.now()
235
+ date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
236
+ filename = (
237
+ str(Path.home())
238
+ + "/"
239
+ + f"{self.station.get('Call').upper()}_{cabrillo_name}_{date_time}.log"
240
+ )
241
+ logger.debug("%s", filename)
242
+ log = self.database.fetch_all_contacts_asc()
243
+ try:
244
+ with open(filename, "w", encoding="ascii") as file_descriptor:
245
+ print("START-OF-LOG: 3.0", end="\r\n", file=file_descriptor)
246
+ print(
247
+ f"CREATED-BY: Not1MM v{__version__}",
248
+ end="\r\n",
249
+ file=file_descriptor,
250
+ )
251
+ print(
252
+ f"CONTEST: {cabrillo_name}",
253
+ end="\r\n",
254
+ file=file_descriptor,
255
+ )
256
+ print(
257
+ f"CALLSIGN: {self.station.get('Call','')}",
258
+ end="\r\n",
259
+ file=file_descriptor,
260
+ )
261
+ print(
262
+ f"LOCATION: {self.station.get('ARRLSection', '')}",
263
+ end="\r\n",
264
+ file=file_descriptor,
265
+ )
266
+ # print(
267
+ # f"ARRL-SECTION: {self.pref.get('section', '')}",
268
+ # end="\r\n",
269
+ # file=file_descriptor,
270
+ # )
271
+ print(
272
+ f"CATEGORY-OPERATOR: {self.contest_settings.get('OperatorCategory','')}",
273
+ end="\r\n",
274
+ file=file_descriptor,
275
+ )
276
+ print(
277
+ f"CATEGORY-ASSISTED: {self.contest_settings.get('AssistedCategory','')}",
278
+ end="\r\n",
279
+ file=file_descriptor,
280
+ )
281
+ print(
282
+ f"CATEGORY-BAND: {self.contest_settings.get('BandCategory','')}",
283
+ end="\r\n",
284
+ file=file_descriptor,
285
+ )
286
+ print(
287
+ f"CATEGORY-MODE: {self.contest_settings.get('ModeCategory','')}",
288
+ end="\r\n",
289
+ file=file_descriptor,
290
+ )
291
+ print(
292
+ f"CATEGORY-TRANSMITTER: {self.contest_settings.get('TransmitterCategory','')}",
293
+ end="\r\n",
294
+ file=file_descriptor,
295
+ )
296
+ if self.contest_settings.get("OverlayCategory", "") != "N/A":
297
+ print(
298
+ f"CATEGORY-OVERLAY: {self.contest_settings.get('OverlayCategory','')}",
299
+ end="\r\n",
300
+ file=file_descriptor,
301
+ )
302
+ print(
303
+ f"GRID-LOCATOR: {self.station.get('GridSquare','')}",
304
+ end="\r\n",
305
+ file=file_descriptor,
306
+ )
307
+ # print(
308
+ # f"CATEGORY: {None}",
309
+ # end="\r\n",
310
+ # file=file_descriptor,
311
+ # )
312
+ print(
313
+ f"CATEGORY-POWER: {self.contest_settings.get('PowerCategory','')}",
314
+ end="\r\n",
315
+ file=file_descriptor,
316
+ )
317
+
318
+ print(
319
+ f"CLAIMED-SCORE: {calc_score(self)}",
320
+ end="\r\n",
321
+ file=file_descriptor,
322
+ )
323
+ print(
324
+ f"OPERATORS: {self.contest_settings.get('Operators','')}",
325
+ end="\r\n",
326
+ file=file_descriptor,
327
+ )
328
+ print(
329
+ f"NAME: {self.station.get('Name', '')}",
330
+ end="\r\n",
331
+ file=file_descriptor,
332
+ )
333
+ print(
334
+ f"ADDRESS: {self.station.get('Street1', '')}",
335
+ end="\r\n",
336
+ file=file_descriptor,
337
+ )
338
+ print(
339
+ f"ADDRESS-CITY: {self.station.get('City', '')}",
340
+ end="\r\n",
341
+ file=file_descriptor,
342
+ )
343
+ print(
344
+ f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
345
+ end="\r\n",
346
+ file=file_descriptor,
347
+ )
348
+ print(
349
+ f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
350
+ end="\r\n",
351
+ file=file_descriptor,
352
+ )
353
+ print(
354
+ f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
355
+ end="\r\n",
356
+ file=file_descriptor,
357
+ )
358
+ print(
359
+ f"EMAIL: {self.station.get('Email', '')}",
360
+ end="\r\n",
361
+ file=file_descriptor,
362
+ )
363
+ for contact in log:
364
+ the_date_and_time = contact.get("TS", "")
365
+ themode = contact.get("Mode", "")
366
+ if themode == "LSB" or themode == "USB":
367
+ themode = "PH"
368
+ frequency = str(int(contact.get("Freq", "0"))).rjust(5)
369
+
370
+ loggeddate = the_date_and_time[:10]
371
+ loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
372
+ print(
373
+ f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
374
+ f"{contact.get('StationPrefix', '').ljust(13)} "
375
+ f"{str(contact.get('SNT', '')).ljust(3)} "
376
+ f"{str(contact.get('SentNr', '')).ljust(6)} "
377
+ f"{contact.get('Call', '').ljust(13)} "
378
+ f"{str(contact.get('RCV', '')).ljust(3)} "
379
+ f"{str(contact.get('NR', '')).ljust(6)}",
380
+ end="\r\n",
381
+ file=file_descriptor,
382
+ )
383
+ print("END-OF-LOG:", end="\r\n", file=file_descriptor)
384
+ except IOError as exception:
385
+ logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
386
+ return
387
+
388
+
389
+ def recalculate_mults(self):
390
+ """Recalculates multipliers after change in logged qso."""