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,413 @@
1
+ """
2
+ ARRL 10-Meter Contest
3
+ Status: Active
4
+ Geographic Focus: Worldwide
5
+ Participation: Worldwide
6
+ Mode: CW, Phone
7
+ Bands: 10m Only
8
+ Classes: Single Op (QRP/Low/High)(CW/Phone/Mixed)
9
+ Single Op Unlimited (QRP/Low/High)(CW/Phone/Mixed)
10
+ Single Op Overlay: (Limited Antennas)
11
+ Multi-Single (Low/High)
12
+ Max operating hours: 36 hours
13
+ Max power: HP: 1500 watts
14
+ LP: 100 watts
15
+ QRP: 5 watts
16
+ Exchange: W/VE: RST + State/Province
17
+ XE: RST + State
18
+ DX: RST + Serial No.
19
+ MM: RST + ITU Region
20
+ QSO Points: 2 points per Phone QSO
21
+ 4 points per CW QSO
22
+ Multipliers: Each US State + DC once per mode
23
+ Each VE Province/Territory once per mode
24
+ Each XE State once per mode
25
+ Each DXCC Country once per mode
26
+ Each ITU Region (MM only) once per mode
27
+ Score Calculation: Total score = total QSO points x total mults
28
+ Find rules at: <http://www.arrl.org/10-meter>
29
+ Cabrillo name: ARRL-10
30
+
31
+
32
+ Scoring: Each phone contact counts for two (2) QSO points. Each CW contact counts for four (4) QSO
33
+ points. To calculate your final score, multiply the total QSO points by the number of US states (plus the
34
+ District of Columbia), Canadian Provinces and Territories, Mexican states, DXCC entities, and ITU
35
+ regions you contacted. Each multiplier counts once on phone and once on CW
36
+
37
+ Scoring Example: KA1RWY makes 2235 contacts including 1305 phone QSOs, and 930 CW QSOs, for
38
+ a total of 6330 QSO points. On phone, she works 49 states, 10 Canadian provinces, 3 Mexican states, 20
39
+ DXCC entities and a maritime mobile station in Region 2 for a total of 49+10+3+20+1 = 83 phone
40
+ multipliers. On CW she works 30 states, 8 Canadian provinces, 1 Mexican state, and 18 DXCC entities
41
+ for a total of 30+8+1+18 = 57 CW multipliers. Her final score = 6330 QSO points x (83+57) multipliers =
42
+ 6330 x 140 = 886,200 points.
43
+
44
+
45
+ """
46
+
47
+ # pylint: disable=invalid-name, unused-argument, unused-variable, c-extension-no-member
48
+
49
+ import datetime
50
+ import logging
51
+
52
+ from pathlib import Path
53
+ from PyQt5 import QtWidgets
54
+
55
+ from not1mm.lib.plugin_common import gen_adif, get_points
56
+ from not1mm.lib.version import __version__
57
+
58
+ logger = logging.getLogger("__main__")
59
+
60
+ name = "ARRL 10M"
61
+ mode = "BOTH" # CW SSB BOTH RTTY
62
+ cabrillo_name = "ARRL-10"
63
+
64
+ columns = [
65
+ "YYYY-MM-DD HH:MM:SS",
66
+ "Call",
67
+ "Freq",
68
+ "Snt",
69
+ "Rcv",
70
+ "SentNr",
71
+ "RcvNr",
72
+ "PTS",
73
+ ]
74
+
75
+ advance_on_space = [True, True, True, True, True]
76
+
77
+ # 1 once per contest, 2 work each band, 3 each band/mode, 4 no dupe checking
78
+ dupe_type = 3
79
+
80
+
81
+ def init_contest(self):
82
+ """setup plugin"""
83
+ set_tab_next(self)
84
+ set_tab_prev(self)
85
+ interface(self)
86
+ self.next_field = self.other_2
87
+
88
+
89
+ def interface(self):
90
+ """Setup user interface"""
91
+ self.field1.show()
92
+ self.field2.show()
93
+ self.field3.show()
94
+ self.field4.show()
95
+ label = self.field3.findChild(QtWidgets.QLabel)
96
+ label.setText("SentNR")
97
+ self.field3.setAccessibleName("Sent Number")
98
+ label = self.field4.findChild(QtWidgets.QLabel)
99
+ label.setText("State|Prov|SN|ITU")
100
+ self.field4.setAccessibleName("State Province Serial Number or I T U Section")
101
+
102
+
103
+ def reset_label(self):
104
+ """reset label after field cleared"""
105
+
106
+
107
+ def set_tab_next(self):
108
+ """Set TAB Advances"""
109
+ self.tab_next = {
110
+ self.callsign: self.field1.findChild(QtWidgets.QLineEdit),
111
+ self.field1.findChild(QtWidgets.QLineEdit): self.field2.findChild(
112
+ QtWidgets.QLineEdit
113
+ ),
114
+ self.field2.findChild(QtWidgets.QLineEdit): self.field3.findChild(
115
+ QtWidgets.QLineEdit
116
+ ),
117
+ self.field3.findChild(QtWidgets.QLineEdit): self.field4.findChild(
118
+ QtWidgets.QLineEdit
119
+ ),
120
+ self.field4.findChild(QtWidgets.QLineEdit): self.callsign,
121
+ }
122
+
123
+
124
+ def set_tab_prev(self):
125
+ """Set TAB Advances"""
126
+ self.tab_prev = {
127
+ self.callsign: self.field4.findChild(QtWidgets.QLineEdit),
128
+ self.field1.findChild(QtWidgets.QLineEdit): self.callsign,
129
+ self.field2.findChild(QtWidgets.QLineEdit): self.field1.findChild(
130
+ QtWidgets.QLineEdit
131
+ ),
132
+ self.field3.findChild(QtWidgets.QLineEdit): self.field2.findChild(
133
+ QtWidgets.QLineEdit
134
+ ),
135
+ self.field4.findChild(QtWidgets.QLineEdit): self.field3.findChild(
136
+ QtWidgets.QLineEdit
137
+ ),
138
+ }
139
+
140
+
141
+ def validate(self):
142
+ """doc"""
143
+ # exchange = self.other_2.text().upper().split()
144
+ # if len(exchange) == 3:
145
+ # if exchange[0].isalpha() and exchange[1].isdigit() and exchange[2].isalpha():
146
+ # return True
147
+ # return False
148
+ return True
149
+
150
+
151
+ def set_contact_vars(self):
152
+ """Contest Specific"""
153
+ self.contact["SNT"] = self.sent.text()
154
+ self.contact["RCV"] = self.receive.text()
155
+ self.contact["NR"] = self.other_2.text().upper()
156
+ self.contact["SentNr"] = self.other_1.text()
157
+
158
+
159
+ def predupe(self):
160
+ """called after callsign entered"""
161
+
162
+
163
+ def prefill(self):
164
+ """Fill sentnr"""
165
+ result = self.database.get_serial()
166
+ serial_nr = str(result.get("serial_nr", "1"))
167
+ if serial_nr == "None":
168
+ serial_nr = "1"
169
+
170
+ exchange = self.contest_settings.get("SentExchange", "").replace("#", serial_nr)
171
+ field = self.field3.findChild(QtWidgets.QLineEdit)
172
+ if len(field.text()) == 0:
173
+ field.setText(exchange)
174
+
175
+
176
+ def points(self):
177
+ """Calc point"""
178
+ _mode = self.contact.get("Mode", "")
179
+ if _mode in "SSB, USB, LSB, FM, AM":
180
+ return 2
181
+ if _mode in "CW":
182
+ return 4
183
+ return 0
184
+
185
+
186
+ def show_mults(self):
187
+ """Return display string for mults"""
188
+ # CountryPrefix, integer
189
+
190
+ us_ve_mx = 0
191
+ mm = 0
192
+ dx = 0
193
+
194
+ sql = (
195
+ "select count(DISTINCT(NR || ':' || Mode)) as mult_count "
196
+ f"from dxlog where ContestNR = {self.database.current_contest} and typeof(NR) = 'text';"
197
+ )
198
+ result = self.database.exec_sql(sql)
199
+ if result:
200
+ us_ve_mx = result.get("mult_count", 0)
201
+
202
+ # MM
203
+ sql = (
204
+ "select count(DISTINCT(NR || ':' || Mode)) as mult_count "
205
+ f"from dxlog where ContestNR = {self.database.current_contest} "
206
+ "and typeof(NR) = 'integer' "
207
+ "and call like '%/MM';"
208
+ )
209
+ result = self.database.exec_sql(sql)
210
+ if result:
211
+ mm = result.get("mult_count", 0)
212
+
213
+ # DX
214
+ sql = (
215
+ "select count(DISTINCT(CountryPrefix || ':' || Mode)) as mult_count "
216
+ f"from dxlog where ContestNR = {self.database.current_contest} "
217
+ "and typeof(NR) = 'integer' "
218
+ "and call not like '%/MM';"
219
+ )
220
+ result = self.database.exec_sql(sql)
221
+ if result:
222
+ dx = result.get("mult_count", 0)
223
+
224
+ return us_ve_mx + mm + dx
225
+
226
+
227
+ def show_qso(self):
228
+ """Return qso count"""
229
+ result = self.database.fetch_qso_count()
230
+ if result:
231
+ return int(result.get("qsos", 0))
232
+ return 0
233
+
234
+
235
+ def calc_score(self):
236
+ """Return calculated score"""
237
+ # Multipliers: Each US State + DC once per mode
238
+ _points = get_points(self)
239
+ _mults = show_mults(self)
240
+ _power_mult = 1
241
+ # if self.contest_settings.get("PowerCategory", "") == "QRP":
242
+ # _power_mult = 2
243
+ return _points * _power_mult * _mults
244
+
245
+
246
+ def adif(self):
247
+ """Call the generate ADIF function"""
248
+ gen_adif(self, cabrillo_name)
249
+
250
+
251
+ def cabrillo(self):
252
+ """Generates Cabrillo file. Maybe."""
253
+ # https://www.cqwpx.com/cabrillo.htm
254
+ logger.debug("******Cabrillo*****")
255
+ logger.debug("Station: %s", f"{self.station}")
256
+ logger.debug("Contest: %s", f"{self.contest_settings}")
257
+ now = datetime.datetime.now()
258
+ date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
259
+ filename = (
260
+ str(Path.home())
261
+ + "/"
262
+ + f"{self.station.get('Call').upper()}_{cabrillo_name}_{date_time}.log"
263
+ )
264
+ logger.debug("%s", filename)
265
+ log = self.database.fetch_all_contacts_asc()
266
+ try:
267
+ with open(filename, "w", encoding="ascii") as file_descriptor:
268
+ print("START-OF-LOG: 3.0", end="\r\n", file=file_descriptor)
269
+ print(
270
+ f"CREATED-BY: Not1MM v{__version__}",
271
+ end="\r\n",
272
+ file=file_descriptor,
273
+ )
274
+ print(
275
+ f"CONTEST: {cabrillo_name}",
276
+ end="\r\n",
277
+ file=file_descriptor,
278
+ )
279
+ print(
280
+ f"CALLSIGN: {self.station.get('Call','')}",
281
+ end="\r\n",
282
+ file=file_descriptor,
283
+ )
284
+ print(
285
+ f"LOCATION: {self.station.get('ARRLSection', '')}",
286
+ end="\r\n",
287
+ file=file_descriptor,
288
+ )
289
+ # print(
290
+ # f"ARRL-SECTION: {self.pref.get('section', '')}",
291
+ # end="\r\n",
292
+ # file=file_descriptor,
293
+ # )
294
+ print(
295
+ f"CATEGORY-OPERATOR: {self.contest_settings.get('OperatorCategory','')}",
296
+ end="\r\n",
297
+ file=file_descriptor,
298
+ )
299
+ print(
300
+ f"CATEGORY-ASSISTED: {self.contest_settings.get('AssistedCategory','')}",
301
+ end="\r\n",
302
+ file=file_descriptor,
303
+ )
304
+ print(
305
+ f"CATEGORY-BAND: {self.contest_settings.get('BandCategory','')}",
306
+ end="\r\n",
307
+ file=file_descriptor,
308
+ )
309
+ print(
310
+ f"CATEGORY-MODE: {self.contest_settings.get('ModeCategory','')}",
311
+ end="\r\n",
312
+ file=file_descriptor,
313
+ )
314
+ print(
315
+ f"CATEGORY-TRANSMITTER: {self.contest_settings.get('TransmitterCategory','')}",
316
+ end="\r\n",
317
+ file=file_descriptor,
318
+ )
319
+ if self.contest_settings.get("OverlayCategory", "") != "N/A":
320
+ print(
321
+ f"CATEGORY-OVERLAY: {self.contest_settings.get('OverlayCategory','')}",
322
+ end="\r\n",
323
+ file=file_descriptor,
324
+ )
325
+ print(
326
+ f"GRID-LOCATOR: {self.station.get('GridSquare','')}",
327
+ end="\r\n",
328
+ file=file_descriptor,
329
+ )
330
+ # print(
331
+ # f"CATEGORY: {None}",
332
+ # end="\r\n",
333
+ # file=file_descriptor,
334
+ # )
335
+ print(
336
+ f"CATEGORY-POWER: {self.contest_settings.get('PowerCategory','')}",
337
+ end="\r\n",
338
+ file=file_descriptor,
339
+ )
340
+
341
+ print(
342
+ f"CLAIMED-SCORE: {calc_score(self)}",
343
+ end="\r\n",
344
+ file=file_descriptor,
345
+ )
346
+ print(
347
+ f"OPERATORS: {self.contest_settings.get('Operators','')}",
348
+ end="\r\n",
349
+ file=file_descriptor,
350
+ )
351
+ print(
352
+ f"NAME: {self.station.get('Name', '')}",
353
+ end="\r\n",
354
+ file=file_descriptor,
355
+ )
356
+ print(
357
+ f"ADDRESS: {self.station.get('Street1', '')}",
358
+ end="\r\n",
359
+ file=file_descriptor,
360
+ )
361
+ print(
362
+ f"ADDRESS-CITY: {self.station.get('City', '')}",
363
+ end="\r\n",
364
+ file=file_descriptor,
365
+ )
366
+ print(
367
+ f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
368
+ end="\r\n",
369
+ file=file_descriptor,
370
+ )
371
+ print(
372
+ f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
373
+ end="\r\n",
374
+ file=file_descriptor,
375
+ )
376
+ print(
377
+ f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
378
+ end="\r\n",
379
+ file=file_descriptor,
380
+ )
381
+ print(
382
+ f"EMAIL: {self.station.get('Email', '')}",
383
+ end="\r\n",
384
+ file=file_descriptor,
385
+ )
386
+ for contact in log:
387
+ the_date_and_time = contact.get("TS", "")
388
+ themode = contact.get("Mode", "")
389
+ if themode == "LSB" or themode == "USB":
390
+ themode = "PH"
391
+ frequency = str(int(contact.get("Freq", "0"))).rjust(5)
392
+
393
+ loggeddate = the_date_and_time[:10]
394
+ loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
395
+ print(
396
+ f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
397
+ f"{contact.get('StationPrefix', '').ljust(13)} "
398
+ f"{str(contact.get('SNT', '')).ljust(3)} "
399
+ f"{str(contact.get('SentNr', '')).ljust(6)} "
400
+ f"{contact.get('Call', '').ljust(13)} "
401
+ f"{str(contact.get('RCV', '')).ljust(3)} "
402
+ f"{str(contact.get('NR', '')).ljust(6)}",
403
+ end="\r\n",
404
+ file=file_descriptor,
405
+ )
406
+ print("END-OF-LOG:", end="\r\n", file=file_descriptor)
407
+ except IOError as exception:
408
+ logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
409
+ return
410
+
411
+
412
+ def recalculate_mults(self):
413
+ """Recalculates multipliers after change in logged qso."""
@@ -1,6 +1,6 @@
1
1
  """ARRL plugin"""
2
2
 
3
- # pylint: disable=invalid-name, unused-argument, unused-variable, c-extension-no-member
3
+ # pylint: disable=invalid-name, unused-argument, unused-variable, c-extension-no-member, unused-import
4
4
 
5
5
  import datetime
6
6
  import logging
@@ -1,6 +1,6 @@
1
1
  """ARRL plugin"""
2
2
 
3
- # pylint: disable=invalid-name, unused-argument, unused-variable, c-extension-no-member
3
+ # pylint: disable=invalid-name, unused-argument, unused-variable, c-extension-no-member, unused-import
4
4
 
5
5
  import datetime
6
6
  import logging
@@ -137,7 +137,10 @@ def points(self):
137
137
 
138
138
  def show_mults(self):
139
139
  """Return display string for mults"""
140
- sql = f"select count(DISTINCT(Sect)) as mults from dxlog where ContestNR = {self.database.current_contest};"
140
+ sql = (
141
+ "select count(DISTINCT(Sect)) as mults from dxlog ",
142
+ f"where ContestNR = {self.database.current_contest};",
143
+ )
141
144
  result = self.database.exec_sql(sql)
142
145
  return int(result.get("mults", 0))
143
146
 
@@ -137,7 +137,10 @@ def points(self):
137
137
 
138
138
  def show_mults(self):
139
139
  """Return display string for mults"""
140
- sql = f"select count(DISTINCT(Sect)) as mults from dxlog where ContestNR = {self.database.current_contest};"
140
+ sql = (
141
+ "select count(DISTINCT(Sect)) as mults from dxlog ",
142
+ f"where ContestNR = {self.database.current_contest};",
143
+ )
141
144
  result = self.database.exec_sql(sql)
142
145
  return int(result.get("mults", 0))
143
146