not1mm 24.8.27__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.
- not1mm/__main__.py +61 -35
- not1mm/lib/database.py +2 -16
- not1mm/lib/version.py +1 -1
- not1mm/plugins/arrl_field_day.py +14 -3
- not1mm/plugins/cq_160_cw.py +2 -2
- not1mm/plugins/cq_160_ssb.py +2 -2
- not1mm/plugins/helvetia.py +2 -2
- not1mm/plugins/ref_cw.py +502 -0
- not1mm/test.py +7 -10
- {not1mm-24.8.27.dist-info → not1mm-24.9.3.dist-info}/METADATA +12 -10
- {not1mm-24.8.27.dist-info → not1mm-24.9.3.dist-info}/RECORD +15 -14
- {not1mm-24.8.27.dist-info → not1mm-24.9.3.dist-info}/WHEEL +1 -1
- {not1mm-24.8.27.dist-info → not1mm-24.9.3.dist-info}/LICENSE +0 -0
- {not1mm-24.8.27.dist-info → not1mm-24.9.3.dist-info}/entry_points.txt +0 -0
- {not1mm-24.8.27.dist-info → not1mm-24.9.3.dist-info}/top_level.txt +0 -0
not1mm/__main__.py
CHANGED
@@ -23,6 +23,7 @@ import threading
|
|
23
23
|
import uuid
|
24
24
|
|
25
25
|
from json import dumps, loads
|
26
|
+
from json.decoder import JSONDecodeError
|
26
27
|
from pathlib import Path
|
27
28
|
from shutil import copyfile
|
28
29
|
|
@@ -186,8 +187,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
186
187
|
)
|
187
188
|
self.setCorner(Qt.Corner.TopLeftCorner, Qt.DockWidgetArea.LeftDockWidgetArea)
|
188
189
|
self.setCorner(Qt.Corner.BottomLeftCorner, Qt.DockWidgetArea.LeftDockWidgetArea)
|
189
|
-
|
190
|
-
uic.loadUi(data_path, self)
|
190
|
+
uic.loadUi(fsutils.APP_DATA_PATH / "main.ui", self)
|
191
191
|
self.cw_entry.hide()
|
192
192
|
self.leftdot.hide()
|
193
193
|
self.rightdot.hide()
|
@@ -459,8 +459,15 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
459
459
|
self.setWindowIcon(
|
460
460
|
QtGui.QIcon(str(fsutils.APP_DATA_PATH / "k6gte.not1mm-32.png"))
|
461
461
|
)
|
462
|
-
|
463
|
-
|
462
|
+
|
463
|
+
try:
|
464
|
+
with open(
|
465
|
+
fsutils.APP_DATA_PATH / "cty.json", "rt", encoding="utf-8"
|
466
|
+
) as c_file:
|
467
|
+
self.ctyfile = loads(c_file.read())
|
468
|
+
except (IOError, JSONDecodeError, TypeError):
|
469
|
+
logging.CRITICAL("There was an error parsing the BigCity file.")
|
470
|
+
|
464
471
|
self.readpreferences()
|
465
472
|
|
466
473
|
self.voice_process = Voice()
|
@@ -491,9 +498,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
491
498
|
self.make_op_dir()
|
492
499
|
|
493
500
|
self.clearinputs()
|
494
|
-
|
495
|
-
if self.pref.get("contest"):
|
496
|
-
self.load_contest()
|
501
|
+
self.load_contest()
|
497
502
|
self.read_cw_macros()
|
498
503
|
|
499
504
|
# Featureset for wayland
|
@@ -1287,10 +1292,15 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1287
1292
|
if updated:
|
1288
1293
|
cty.dump(fsutils.APP_DATA_PATH / "cty.json")
|
1289
1294
|
self.show_message_box("cty file updated.")
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1295
|
+
try:
|
1296
|
+
with open(
|
1297
|
+
fsutils.APP_DATA_PATH / "cty.json", "rt", encoding="utf-8"
|
1298
|
+
) as ctyfile:
|
1299
|
+
self.ctyfile = loads(ctyfile.read())
|
1300
|
+
except (IOError, JSONDecodeError, TypeError) as err:
|
1301
|
+
logging.CRITICAL(
|
1302
|
+
f"There was an error {err} parsing the BigCity file."
|
1303
|
+
)
|
1294
1304
|
else:
|
1295
1305
|
self.show_message_box("An Error occured updating file.")
|
1296
1306
|
else:
|
@@ -1898,11 +1908,14 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1898
1908
|
" "
|
1899
1909
|
)[:19]
|
1900
1910
|
self.contact["Call"] = self.callsign.text()
|
1901
|
-
self.contact
|
1902
|
-
|
1903
|
-
|
1904
|
-
|
1905
|
-
|
1911
|
+
if self.contact.get("Mode") not in ("FT8", "FT4"):
|
1912
|
+
self.contact["Freq"] = round(
|
1913
|
+
float(self.radio_state.get("vfoa", 0.0)) / 1000, 2
|
1914
|
+
)
|
1915
|
+
self.contact["QSXFreq"] = round(
|
1916
|
+
float(self.radio_state.get("vfoa", 0.0)) / 1000, 2
|
1917
|
+
)
|
1918
|
+
self.contact["Mode"] = self.radio_state.get("mode", "")
|
1906
1919
|
self.contact["ContestName"] = self.contest.cabrillo_name
|
1907
1920
|
self.contact["ContestNR"] = self.pref.get("contest", "0")
|
1908
1921
|
self.contact["StationPrefix"] = self.station.get("Call", "")
|
@@ -2093,7 +2106,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
2093
2106
|
|
2094
2107
|
def save_settings(self) -> None:
|
2095
2108
|
"""
|
2096
|
-
Save settings to database.
|
2109
|
+
Save Station settings to database.
|
2097
2110
|
|
2098
2111
|
Parameters
|
2099
2112
|
----------
|
@@ -2322,7 +2335,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
2322
2335
|
with open(fsutils.CONFIG_FILE, "wt", encoding="utf-8") as file_descriptor:
|
2323
2336
|
file_descriptor.write(dumps(self.pref, indent=4))
|
2324
2337
|
# logger.info("writing: %s", self.pref)
|
2325
|
-
except IOError as exception:
|
2338
|
+
except (IOError, TypeError, ValueError) as exception:
|
2326
2339
|
logger.critical("writepreferences: %s", exception)
|
2327
2340
|
|
2328
2341
|
def readpreferences(self) -> None:
|
@@ -2344,7 +2357,12 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
2344
2357
|
with open(
|
2345
2358
|
fsutils.CONFIG_FILE, "rt", encoding="utf-8"
|
2346
2359
|
) as file_descriptor:
|
2347
|
-
|
2360
|
+
try:
|
2361
|
+
self.pref = loads(file_descriptor.read())
|
2362
|
+
except (JSONDecodeError, TypeError):
|
2363
|
+
logging.CRITICAL(
|
2364
|
+
"There was an error parsing the preference file."
|
2365
|
+
)
|
2348
2366
|
logger.info("%s", self.pref)
|
2349
2367
|
else:
|
2350
2368
|
logger.info("No preference file. Writing preference.")
|
@@ -2354,7 +2372,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
2354
2372
|
self.pref = self.pref_ref.copy()
|
2355
2373
|
file_descriptor.write(dumps(self.pref, indent=4))
|
2356
2374
|
logger.info("%s", self.pref)
|
2357
|
-
except IOError as exception:
|
2375
|
+
except (IOError, TypeError, ValueError) as exception:
|
2358
2376
|
logger.critical("Error: %s", exception)
|
2359
2377
|
|
2360
2378
|
self.look_up = None
|
@@ -3197,10 +3215,14 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
3197
3215
|
else:
|
3198
3216
|
macro_file = "ssbmacros.txt"
|
3199
3217
|
if not (fsutils.USER_DATA_PATH / macro_file).exists():
|
3200
|
-
logger.debug("
|
3201
|
-
|
3202
|
-
|
3203
|
-
|
3218
|
+
logger.debug("copying default macro file.")
|
3219
|
+
try:
|
3220
|
+
copyfile(
|
3221
|
+
fsutils.APP_DATA_PATH / macro_file,
|
3222
|
+
fsutils.USER_DATA_PATH / macro_file,
|
3223
|
+
)
|
3224
|
+
except IOError as err:
|
3225
|
+
logger.critical(f"Error {err} copying macro file.")
|
3204
3226
|
try:
|
3205
3227
|
fsutils.openFileWithOS(fsutils.USER_DATA_PATH / macro_file)
|
3206
3228
|
except FileNotFoundError | PermissionError | OSError as err:
|
@@ -3221,22 +3243,26 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
3221
3243
|
macro_file = "ssbmacros.txt"
|
3222
3244
|
|
3223
3245
|
if not (fsutils.USER_DATA_PATH / macro_file).exists():
|
3224
|
-
logger.debug("
|
3225
|
-
|
3226
|
-
|
3227
|
-
|
3228
|
-
|
3229
|
-
|
3230
|
-
|
3231
|
-
|
3232
|
-
|
3246
|
+
logger.debug("copying default macro file.")
|
3247
|
+
try:
|
3248
|
+
copyfile(
|
3249
|
+
fsutils.APP_DATA_PATH / macro_file,
|
3250
|
+
fsutils.USER_DATA_PATH / macro_file,
|
3251
|
+
)
|
3252
|
+
except IOError as err:
|
3253
|
+
logger.critical(f"Error {err} copying macro file.")
|
3254
|
+
try:
|
3255
|
+
with open(
|
3256
|
+
fsutils.USER_DATA_PATH / macro_file, "r", encoding="utf-8"
|
3257
|
+
) as file_descriptor:
|
3258
|
+
for line in file_descriptor:
|
3233
3259
|
mode, fkey, buttonname, cwtext = line.split("|")
|
3234
3260
|
if mode.strip().upper() == "R" and self.pref.get("run_state"):
|
3235
3261
|
self.fkeys[fkey.strip()] = (buttonname.strip(), cwtext.strip())
|
3236
3262
|
if mode.strip().upper() != "R" and not self.pref.get("run_state"):
|
3237
3263
|
self.fkeys[fkey.strip()] = (buttonname.strip(), cwtext.strip())
|
3238
|
-
|
3239
|
-
|
3264
|
+
except (IOError, ValueError) as err:
|
3265
|
+
logger.info("read_cw_macros: %s", err)
|
3240
3266
|
keys = self.fkeys.keys()
|
3241
3267
|
if "F1" in keys:
|
3242
3268
|
self.F1.setText(f"F1: {self.fkeys['F1'][0]}")
|
not1mm/lib/database.py
CHANGED
@@ -886,28 +886,14 @@ class DataBase:
|
|
886
886
|
logger.debug("%s", exception)
|
887
887
|
return {}
|
888
888
|
|
889
|
-
def
|
889
|
+
def fetch_mult_count(self, mult: int) -> dict:
|
890
890
|
"""return QSO count"""
|
891
891
|
try:
|
892
892
|
with sqlite3.connect(self.database) as conn:
|
893
893
|
conn.row_factory = self.row_factory
|
894
894
|
cursor = conn.cursor()
|
895
895
|
cursor.execute(
|
896
|
-
f"select count(*) as count from dxlog where
|
897
|
-
)
|
898
|
-
return cursor.fetchone()
|
899
|
-
except sqlite3.OperationalError as exception:
|
900
|
-
logger.debug("%s", exception)
|
901
|
-
return {}
|
902
|
-
|
903
|
-
def fetch_mult2_count(self) -> dict:
|
904
|
-
"""return QSO count"""
|
905
|
-
try:
|
906
|
-
with sqlite3.connect(self.database) as conn:
|
907
|
-
conn.row_factory = self.row_factory
|
908
|
-
cursor = conn.cursor()
|
909
|
-
cursor.execute(
|
910
|
-
f"select count(*) as count from dxlog where IsMultiplier2 = 1 and ContestNR = {self.current_contest};"
|
896
|
+
f"select count(*) as count from dxlog where IsMultiplier{mult} = 1 and ContestNR = {self.current_contest};"
|
911
897
|
)
|
912
898
|
return cursor.fetchone()
|
913
899
|
except sqlite3.OperationalError as exception:
|
not1mm/lib/version.py
CHANGED
not1mm/plugins/arrl_field_day.py
CHANGED
@@ -8,6 +8,7 @@ import logging
|
|
8
8
|
from pathlib import Path
|
9
9
|
from PyQt6 import QtWidgets
|
10
10
|
|
11
|
+
from not1mm.lib.ham_utility import get_logged_band
|
11
12
|
from not1mm.lib.plugin_common import gen_adif, get_points
|
12
13
|
from not1mm.lib.version import __version__
|
13
14
|
|
@@ -114,7 +115,7 @@ def points(self):
|
|
114
115
|
_mode = self.contact.get("Mode", "")
|
115
116
|
if _mode in "SSB, USB, LSB, FM, AM":
|
116
117
|
return 1
|
117
|
-
if _mode in "CW, RTTY":
|
118
|
+
if _mode in "CW, RTTY, FT8":
|
118
119
|
return 2
|
119
120
|
return 0
|
120
121
|
|
@@ -295,8 +296,10 @@ def cabrillo(self):
|
|
295
296
|
for contact in log:
|
296
297
|
the_date_and_time = contact.get("TS", "")
|
297
298
|
themode = contact.get("Mode", "")
|
298
|
-
if themode
|
299
|
+
if themode in ("LSB", "USB"):
|
299
300
|
themode = "PH"
|
301
|
+
if themode in ("FT8", "FT4"):
|
302
|
+
themode = "DG"
|
300
303
|
frequency = str(int(contact.get("Freq", "0"))).rjust(5)
|
301
304
|
|
302
305
|
loggeddate = the_date_and_time[:10]
|
@@ -362,7 +365,15 @@ def ft8_handler(the_packet: dict):
|
|
362
365
|
ALTEREGO.contact["RCV"] = ALTEREGO.receive.text()
|
363
366
|
ALTEREGO.contact["Exchange1"] = the_packet.get("CLASS", "ERR")
|
364
367
|
ALTEREGO.contact["Sect"] = the_packet.get("ARRL_SECT", "ERR")
|
365
|
-
ALTEREGO.contact["Mode"] = "
|
368
|
+
ALTEREGO.contact["Mode"] = the_packet.get("MODE", "ERR")
|
369
|
+
ALTEREGO.contact["Freq"] = round(float(the_packet.get("FREQ", "0.0")) * 1000, 2)
|
370
|
+
ALTEREGO.contact["QSXFreq"] = round(
|
371
|
+
float(the_packet.get("FREQ", "0.0")) * 1000, 2
|
372
|
+
)
|
373
|
+
ALTEREGO.contact["Band"] = get_logged_band(
|
374
|
+
str(int(float(the_packet.get("FREQ", "0.0")) * 1000000))
|
375
|
+
)
|
366
376
|
ALTEREGO.other_1.setText(the_packet.get("CLASS", "ERR"))
|
367
377
|
ALTEREGO.other_2.setText(the_packet.get("ARRL_SECT", "ERR"))
|
368
378
|
print(f"\n{ALTEREGO.contact=}\n")
|
379
|
+
ALTEREGO.save_contact()
|
not1mm/plugins/cq_160_cw.py
CHANGED
@@ -177,7 +177,7 @@ def points(self):
|
|
177
177
|
|
178
178
|
def show_mults(self):
|
179
179
|
"""Return display string for mults"""
|
180
|
-
result = self.database.
|
180
|
+
result = self.database.fetch_mult_count(1)
|
181
181
|
count = result.get("count", 0)
|
182
182
|
return count
|
183
183
|
|
@@ -198,7 +198,7 @@ def calc_score(self):
|
|
198
198
|
if score is None:
|
199
199
|
score = "0"
|
200
200
|
contest_points = int(score)
|
201
|
-
result = self.database.
|
201
|
+
result = self.database.fetch_mult_count(1)
|
202
202
|
mults = int(result.get("count", 0))
|
203
203
|
return contest_points * mults
|
204
204
|
return 0
|
not1mm/plugins/cq_160_ssb.py
CHANGED
@@ -177,7 +177,7 @@ def points(self):
|
|
177
177
|
|
178
178
|
def show_mults(self):
|
179
179
|
"""Return display string for mults"""
|
180
|
-
result = self.database.
|
180
|
+
result = self.database.fetch_mult_count(1)
|
181
181
|
count = result.get("count", 0)
|
182
182
|
return count
|
183
183
|
|
@@ -198,7 +198,7 @@ def calc_score(self):
|
|
198
198
|
if score is None:
|
199
199
|
score = "0"
|
200
200
|
contest_points = int(score)
|
201
|
-
result = self.database.
|
201
|
+
result = self.database.fetch_mult_count(1)
|
202
202
|
mults = int(result.get("count", 0))
|
203
203
|
return contest_points * mults
|
204
204
|
return 0
|
not1mm/plugins/helvetia.py
CHANGED
@@ -250,8 +250,8 @@ def points(self):
|
|
250
250
|
|
251
251
|
def show_mults(self):
|
252
252
|
"""Return display string for mults"""
|
253
|
-
return int(self.database.
|
254
|
-
self.database.
|
253
|
+
return int(self.database.fetch_mult_count(1).get("count", 0)) + int(
|
254
|
+
self.database.fetch_mult_count(2).get("count", 0)
|
255
255
|
)
|
256
256
|
|
257
257
|
|
not1mm/plugins/ref_cw.py
ADDED
@@ -0,0 +1,502 @@
|
|
1
|
+
"""
|
2
|
+
REF Contest, CW
|
3
|
+
Status: Active
|
4
|
+
Geographic Focus: France + overseas territories
|
5
|
+
Participation: Worldwide
|
6
|
+
Awards: Worldwide
|
7
|
+
Mode: CW
|
8
|
+
Bands: 80, 40, 20, 15, 10m
|
9
|
+
Classes: Single Op All Band
|
10
|
+
Single Op Single Band
|
11
|
+
Multi-Single
|
12
|
+
Club
|
13
|
+
SWL
|
14
|
+
Max power: HP: >100 Watts
|
15
|
+
LP: 100 Watts
|
16
|
+
QRP: 5 Watts
|
17
|
+
|
18
|
+
Exchange: French: RST + Department/Prefix
|
19
|
+
non-French: RST + Serial No.
|
20
|
+
|
21
|
+
Work stations: Once per band
|
22
|
+
|
23
|
+
QSO Points: French: 6 points per QSO with French station same continent
|
24
|
+
French: 15 points per QSO with French station on different continent
|
25
|
+
French: 1 point per QSO with non-French station same continent
|
26
|
+
French: 2 points per QSO with non-French station on different continent
|
27
|
+
non-French: 1 point per QSO with French station same continent
|
28
|
+
non-French: 3 points per QSO with French station on different continent
|
29
|
+
|
30
|
+
Multipliers: French/Corsica departments once per band
|
31
|
+
French overseas prefixes once per band
|
32
|
+
non-French DXCC countries once per band (available only to French stations)
|
33
|
+
|
34
|
+
Score Calculation: Total score = total QSO points x total mults
|
35
|
+
|
36
|
+
Upload log at: https://concours.r-e-f.org/contest/logs/upload-form/
|
37
|
+
Find rules at: https://concours.r-e-f.org/reglements/actuels/reg_cdfhfdx.pdf
|
38
|
+
Cabrillo name: REF-CW
|
39
|
+
Cabrillo name aliases: REF
|
40
|
+
"""
|
41
|
+
|
42
|
+
import datetime
|
43
|
+
import logging
|
44
|
+
import platform
|
45
|
+
|
46
|
+
from pathlib import Path
|
47
|
+
|
48
|
+
from PyQt6 import QtWidgets
|
49
|
+
|
50
|
+
from not1mm.lib.plugin_common import gen_adif, get_points
|
51
|
+
|
52
|
+
from not1mm.lib.version import __version__
|
53
|
+
|
54
|
+
logger = logging.getLogger(__name__)
|
55
|
+
|
56
|
+
EXCHANGE_HINT = "Canton or #"
|
57
|
+
|
58
|
+
name = "French REF DX contest - CW"
|
59
|
+
cabrillo_name = "REF-CW"
|
60
|
+
mode = "CW" # CW SSB BOTH RTTY
|
61
|
+
|
62
|
+
columns = [
|
63
|
+
"YYYY-MM-DD HH:MM:SS",
|
64
|
+
"Call",
|
65
|
+
"Freq",
|
66
|
+
"Mode",
|
67
|
+
"Snt",
|
68
|
+
"Rcv",
|
69
|
+
"SentNr",
|
70
|
+
"RcvNr",
|
71
|
+
"M1",
|
72
|
+
"M2",
|
73
|
+
"PTS",
|
74
|
+
]
|
75
|
+
|
76
|
+
advance_on_space = [True, True, True, True, True]
|
77
|
+
|
78
|
+
# 1 once per contest, 2 work each band, 3 each band/mode, 4 no dupe checking
|
79
|
+
dupe_type = 2
|
80
|
+
|
81
|
+
|
82
|
+
def init_contest(self):
|
83
|
+
"""setup plugin"""
|
84
|
+
set_tab_next(self)
|
85
|
+
set_tab_prev(self)
|
86
|
+
interface(self)
|
87
|
+
self.next_field = self.other_2
|
88
|
+
|
89
|
+
|
90
|
+
def interface(self):
|
91
|
+
"""Setup user interface"""
|
92
|
+
self.field1.show()
|
93
|
+
self.field2.show()
|
94
|
+
self.field3.show()
|
95
|
+
self.field4.show()
|
96
|
+
label = self.field3.findChild(QtWidgets.QLabel)
|
97
|
+
label.setText("Sent")
|
98
|
+
self.field3.setAccessibleName("Sent")
|
99
|
+
label = self.field4.findChild(QtWidgets.QLabel)
|
100
|
+
label.setText("Dep/Pfx/SN")
|
101
|
+
self.field4.setAccessibleName("Department, Prefix or SN")
|
102
|
+
|
103
|
+
|
104
|
+
def reset_label(self):
|
105
|
+
"""reset label after field cleared"""
|
106
|
+
|
107
|
+
|
108
|
+
def set_tab_next(self):
|
109
|
+
"""Set TAB Advances"""
|
110
|
+
self.tab_next = {
|
111
|
+
self.callsign: self.field3.findChild(QtWidgets.QLineEdit),
|
112
|
+
self.field1.findChild(QtWidgets.QLineEdit): self.field3.findChild(
|
113
|
+
QtWidgets.QLineEdit
|
114
|
+
),
|
115
|
+
self.field2.findChild(QtWidgets.QLineEdit): self.field3.findChild(
|
116
|
+
QtWidgets.QLineEdit
|
117
|
+
),
|
118
|
+
self.field3.findChild(QtWidgets.QLineEdit): self.field4.findChild(
|
119
|
+
QtWidgets.QLineEdit
|
120
|
+
),
|
121
|
+
self.field4.findChild(QtWidgets.QLineEdit): self.callsign,
|
122
|
+
}
|
123
|
+
|
124
|
+
|
125
|
+
def set_tab_prev(self):
|
126
|
+
"""Set TAB Advances"""
|
127
|
+
self.tab_prev = {
|
128
|
+
self.callsign: self.field4.findChild(QtWidgets.QLineEdit),
|
129
|
+
self.field1.findChild(QtWidgets.QLineEdit): self.callsign,
|
130
|
+
self.field2.findChild(QtWidgets.QLineEdit): self.callsign,
|
131
|
+
self.field3.findChild(QtWidgets.QLineEdit): self.callsign,
|
132
|
+
self.field4.findChild(QtWidgets.QLineEdit): self.field3.findChild(
|
133
|
+
QtWidgets.QLineEdit
|
134
|
+
),
|
135
|
+
}
|
136
|
+
|
137
|
+
|
138
|
+
def set_contact_vars(self):
|
139
|
+
"""
|
140
|
+
Contest Specific
|
141
|
+
Multipliers:
|
142
|
+
French/Corsica departments once per band
|
143
|
+
French overseas prefixes once per band
|
144
|
+
non-French DXCC countries once per band (available only to French stations)
|
145
|
+
"""
|
146
|
+
self.contact["SNT"] = self.sent.text()
|
147
|
+
self.contact["RCV"] = self.receive.text()
|
148
|
+
self.contact["SentNr"] = self.other_1.text().upper()
|
149
|
+
self.contact["NR"] = self.other_2.text().upper()
|
150
|
+
|
151
|
+
self.contact["IsMultiplier1"] = 0
|
152
|
+
self.contact["IsMultiplier2"] = 0
|
153
|
+
|
154
|
+
if (
|
155
|
+
self.contact.get("CountryPrefix", "") == "F"
|
156
|
+
and self.contact.get("NR", "").isalpha()
|
157
|
+
):
|
158
|
+
canton = self.contact.get("NR", "").upper()
|
159
|
+
band = self.contact.get("Band", "")
|
160
|
+
query = (
|
161
|
+
f"select count(*) as canton_count from dxlog where "
|
162
|
+
f"NR = '{canton}' "
|
163
|
+
f"and Band = '{band}' "
|
164
|
+
f"and ContestNR = {self.pref.get('contest', '1')};"
|
165
|
+
)
|
166
|
+
result = self.database.exec_sql(query)
|
167
|
+
count = int(result.get("canton_count", 0))
|
168
|
+
if count == 0:
|
169
|
+
self.contact["IsMultiplier1"] = 1
|
170
|
+
|
171
|
+
if self.contact.get("CountryPrefix", ""):
|
172
|
+
dxcc = self.contact.get("CountryPrefix", "")
|
173
|
+
band = self.contact.get("Band", "")
|
174
|
+
query = (
|
175
|
+
f"select count(*) as dxcc_count from dxlog where "
|
176
|
+
f"CountryPrefix = '{dxcc}' "
|
177
|
+
f"and Band = '{band}' "
|
178
|
+
f"and ContestNR = {self.pref.get('contest', '1')};"
|
179
|
+
)
|
180
|
+
result = self.database.exec_sql(query)
|
181
|
+
if not result.get("dxcc_count", ""):
|
182
|
+
self.contact["IsMultiplier2"] = 1
|
183
|
+
|
184
|
+
|
185
|
+
def predupe(self):
|
186
|
+
"""called after callsign entered"""
|
187
|
+
|
188
|
+
|
189
|
+
def prefill(self):
|
190
|
+
"""Fill SentNR"""
|
191
|
+
field = self.field3.findChild(QtWidgets.QLineEdit)
|
192
|
+
sent_sxchange_setting = self.contest_settings.get("SentExchange", "")
|
193
|
+
if sent_sxchange_setting.strip() == "#":
|
194
|
+
result = self.database.get_serial()
|
195
|
+
serial_nr = str(result.get("serial_nr", "1")).zfill(3)
|
196
|
+
if serial_nr == "None":
|
197
|
+
serial_nr = "001"
|
198
|
+
if len(field.text()) == 0:
|
199
|
+
field.setText(serial_nr)
|
200
|
+
else:
|
201
|
+
field.setText(sent_sxchange_setting)
|
202
|
+
|
203
|
+
|
204
|
+
def points(self):
|
205
|
+
"""
|
206
|
+
Scoring:
|
207
|
+
French: 6 points per QSO with French station same continent
|
208
|
+
French: 15 points per QSO with French station on different continent
|
209
|
+
French: 1 point per QSO with non-French station same continent
|
210
|
+
French: 2 points per QSO with non-French station on different continent
|
211
|
+
non-French: 1 point per QSO with French station same continent
|
212
|
+
non-French: 3 points per QSO with French station on different continent
|
213
|
+
|
214
|
+
self.contact["CountryPrefix"]
|
215
|
+
self.contact["Continent"]
|
216
|
+
"""
|
217
|
+
|
218
|
+
# Just incase the cty lookup fails
|
219
|
+
my_country = None
|
220
|
+
my_continent = None
|
221
|
+
their_continent = None
|
222
|
+
their_country = None
|
223
|
+
|
224
|
+
result = self.cty_lookup(self.station.get("Call", ""))
|
225
|
+
if result:
|
226
|
+
for item in result.items():
|
227
|
+
my_country = item[1].get("entity", "")
|
228
|
+
my_continent = item[1].get("continent", "")
|
229
|
+
result = self.cty_lookup(self.contact.get("Call", ""))
|
230
|
+
if result:
|
231
|
+
for item in result.items():
|
232
|
+
their_country = item[1].get("entity", "")
|
233
|
+
their_continent = item[1].get("continent", "")
|
234
|
+
|
235
|
+
if my_country == "France":
|
236
|
+
if their_country == "France":
|
237
|
+
if my_continent == their_continent:
|
238
|
+
return 6
|
239
|
+
else:
|
240
|
+
return 15
|
241
|
+
else:
|
242
|
+
if my_continent == their_continent:
|
243
|
+
return 1
|
244
|
+
else:
|
245
|
+
return 2
|
246
|
+
else:
|
247
|
+
if their_country == "France":
|
248
|
+
if their_continent == my_continent:
|
249
|
+
return 1
|
250
|
+
else:
|
251
|
+
return 3
|
252
|
+
|
253
|
+
return 0
|
254
|
+
|
255
|
+
|
256
|
+
def show_mults(self):
|
257
|
+
"""Return display string for mults"""
|
258
|
+
return int(self.database.fetch_mult_count(1).get("count", 0)) + int(
|
259
|
+
self.database.fetch_mult_count(2).get("count", 0)
|
260
|
+
)
|
261
|
+
|
262
|
+
|
263
|
+
def show_qso(self):
|
264
|
+
"""Return qso count"""
|
265
|
+
result = self.database.fetch_qso_count()
|
266
|
+
if result:
|
267
|
+
return int(result.get("qsos", 0))
|
268
|
+
return 0
|
269
|
+
|
270
|
+
|
271
|
+
def calc_score(self):
|
272
|
+
"""Return calculated score"""
|
273
|
+
result = self.database.fetch_points()
|
274
|
+
if result is not None:
|
275
|
+
score = result.get("Points", "0")
|
276
|
+
if score is None:
|
277
|
+
score = "0"
|
278
|
+
contest_points = int(score)
|
279
|
+
mults = show_mults(self)
|
280
|
+
return contest_points * mults
|
281
|
+
return 0
|
282
|
+
|
283
|
+
|
284
|
+
def recalculate_mults(self):
|
285
|
+
"""Recalculates multipliers after change in logged qso."""
|
286
|
+
|
287
|
+
all_contacts = self.database.fetch_all_contacts_asc()
|
288
|
+
for contact in all_contacts:
|
289
|
+
|
290
|
+
contact["IsMultiplier1"] = 0
|
291
|
+
contact["IsMultiplier2"] = 0
|
292
|
+
|
293
|
+
time_stamp = contact.get("TS", "")
|
294
|
+
canton = contact.get("NR", "")
|
295
|
+
dxcc = contact.get("CountryPrefix", "")
|
296
|
+
band = contact.get("Band", "")
|
297
|
+
if dxcc == "HB" and canton.isalpha():
|
298
|
+
query = (
|
299
|
+
f"select count(*) as canton_count from dxlog where TS < '{time_stamp}' "
|
300
|
+
f"and NR = '{canton.upper()}' "
|
301
|
+
f"and Band = '{band}' "
|
302
|
+
f"and ContestNR = {self.pref.get('contest', '1')};"
|
303
|
+
)
|
304
|
+
result = self.database.exec_sql(query)
|
305
|
+
count = int(result.get("canton_count", 0))
|
306
|
+
if count == 0:
|
307
|
+
contact["IsMultiplier1"] = 1
|
308
|
+
|
309
|
+
if dxcc:
|
310
|
+
query = (
|
311
|
+
f"select count(*) as dxcc_count from dxlog where TS < '{time_stamp}' "
|
312
|
+
f"and CountryPrefix = '{dxcc}' "
|
313
|
+
f"and Band = '{band}' "
|
314
|
+
f"and ContestNR = {self.pref.get('contest', '1')};"
|
315
|
+
)
|
316
|
+
result = self.database.exec_sql(query)
|
317
|
+
if not result.get("dxcc_count", ""):
|
318
|
+
contact["IsMultiplier2"] = 1
|
319
|
+
|
320
|
+
self.database.change_contact(contact)
|
321
|
+
cmd = {}
|
322
|
+
cmd["cmd"] = "UPDATELOG"
|
323
|
+
cmd["station"] = platform.node()
|
324
|
+
self.multicast_interface.send_as_json(cmd)
|
325
|
+
|
326
|
+
|
327
|
+
def adif(self):
|
328
|
+
"""Call the generate ADIF function"""
|
329
|
+
gen_adif(self, cabrillo_name, "HELVETIA")
|
330
|
+
|
331
|
+
|
332
|
+
def cabrillo(self):
|
333
|
+
"""Generates Cabrillo file. Maybe."""
|
334
|
+
# https://www.cqwpx.com/cabrillo.htm
|
335
|
+
logger.debug("******Cabrillo*****")
|
336
|
+
logger.debug("Station: %s", f"{self.station}")
|
337
|
+
logger.debug("Contest: %s", f"{self.contest_settings}")
|
338
|
+
now = datetime.datetime.now()
|
339
|
+
date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
|
340
|
+
filename = (
|
341
|
+
str(Path.home())
|
342
|
+
+ "/"
|
343
|
+
+ f"{self.station.get('Call', '').upper()}_{cabrillo_name}_{date_time}.log"
|
344
|
+
)
|
345
|
+
logger.debug("%s", filename)
|
346
|
+
log = self.database.fetch_all_contacts_asc()
|
347
|
+
try:
|
348
|
+
with open(filename, "w", encoding="ascii") as file_descriptor:
|
349
|
+
print("START-OF-LOG: 3.0", end="\r\n", file=file_descriptor)
|
350
|
+
print(
|
351
|
+
f"CREATED-BY: Not1MM v{__version__}",
|
352
|
+
end="\r\n",
|
353
|
+
file=file_descriptor,
|
354
|
+
)
|
355
|
+
print(
|
356
|
+
f"CONTEST: {cabrillo_name}",
|
357
|
+
end="\r\n",
|
358
|
+
file=file_descriptor,
|
359
|
+
)
|
360
|
+
if self.station.get("Club", ""):
|
361
|
+
print(
|
362
|
+
f"CLUB: {self.station.get('Club', '').upper()}",
|
363
|
+
end="\r\n",
|
364
|
+
file=file_descriptor,
|
365
|
+
)
|
366
|
+
print(
|
367
|
+
f"CALLSIGN: {self.station.get('Call','')}",
|
368
|
+
end="\r\n",
|
369
|
+
file=file_descriptor,
|
370
|
+
)
|
371
|
+
print(
|
372
|
+
f"LOCATION: {self.station.get('ARRLSection', '')}",
|
373
|
+
end="\r\n",
|
374
|
+
file=file_descriptor,
|
375
|
+
)
|
376
|
+
# print(
|
377
|
+
# f"ARRL-SECTION: {self.pref.get('section', '')}",
|
378
|
+
# end="\r\n",
|
379
|
+
# file=file_descriptor,
|
380
|
+
# )
|
381
|
+
print(
|
382
|
+
f"CATEGORY-OPERATOR: {self.contest_settings.get('OperatorCategory','')}",
|
383
|
+
end="\r\n",
|
384
|
+
file=file_descriptor,
|
385
|
+
)
|
386
|
+
print(
|
387
|
+
f"CATEGORY-ASSISTED: {self.contest_settings.get('AssistedCategory','')}",
|
388
|
+
end="\r\n",
|
389
|
+
file=file_descriptor,
|
390
|
+
)
|
391
|
+
print(
|
392
|
+
f"CATEGORY-BAND: {self.contest_settings.get('BandCategory','')}",
|
393
|
+
end="\r\n",
|
394
|
+
file=file_descriptor,
|
395
|
+
)
|
396
|
+
print(
|
397
|
+
f"CATEGORY-MODE: {self.contest_settings.get('ModeCategory','')}",
|
398
|
+
end="\r\n",
|
399
|
+
file=file_descriptor,
|
400
|
+
)
|
401
|
+
print(
|
402
|
+
f"CATEGORY-TRANSMITTER: {self.contest_settings.get('TransmitterCategory','')}",
|
403
|
+
end="\r\n",
|
404
|
+
file=file_descriptor,
|
405
|
+
)
|
406
|
+
if self.contest_settings.get("OverlayCategory", "") != "N/A":
|
407
|
+
print(
|
408
|
+
f"CATEGORY-OVERLAY: {self.contest_settings.get('OverlayCategory','')}",
|
409
|
+
end="\r\n",
|
410
|
+
file=file_descriptor,
|
411
|
+
)
|
412
|
+
print(
|
413
|
+
f"GRID-LOCATOR: {self.station.get('GridSquare','')}",
|
414
|
+
end="\r\n",
|
415
|
+
file=file_descriptor,
|
416
|
+
)
|
417
|
+
# print(
|
418
|
+
# f"CATEGORY: {None}",
|
419
|
+
# end="\r\n",
|
420
|
+
# file=file_descriptor,
|
421
|
+
# )
|
422
|
+
print(
|
423
|
+
f"CATEGORY-POWER: {self.contest_settings.get('PowerCategory','')}",
|
424
|
+
end="\r\n",
|
425
|
+
file=file_descriptor,
|
426
|
+
)
|
427
|
+
|
428
|
+
print(
|
429
|
+
f"CLAIMED-SCORE: {calc_score(self)}",
|
430
|
+
end="\r\n",
|
431
|
+
file=file_descriptor,
|
432
|
+
)
|
433
|
+
ops = f"@{self.station.get('Call','')}"
|
434
|
+
list_of_ops = self.database.get_ops()
|
435
|
+
for op in list_of_ops:
|
436
|
+
ops += f", {op.get('Operator', '')}"
|
437
|
+
print(
|
438
|
+
f"OPERATORS: {ops}",
|
439
|
+
end="\r\n",
|
440
|
+
file=file_descriptor,
|
441
|
+
)
|
442
|
+
print(
|
443
|
+
f"NAME: {self.station.get('Name', '')}",
|
444
|
+
end="\r\n",
|
445
|
+
file=file_descriptor,
|
446
|
+
)
|
447
|
+
print(
|
448
|
+
f"ADDRESS: {self.station.get('Street1', '')}",
|
449
|
+
end="\r\n",
|
450
|
+
file=file_descriptor,
|
451
|
+
)
|
452
|
+
print(
|
453
|
+
f"ADDRESS-CITY: {self.station.get('City', '')}",
|
454
|
+
end="\r\n",
|
455
|
+
file=file_descriptor,
|
456
|
+
)
|
457
|
+
print(
|
458
|
+
f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
|
459
|
+
end="\r\n",
|
460
|
+
file=file_descriptor,
|
461
|
+
)
|
462
|
+
print(
|
463
|
+
f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
|
464
|
+
end="\r\n",
|
465
|
+
file=file_descriptor,
|
466
|
+
)
|
467
|
+
print(
|
468
|
+
f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
|
469
|
+
end="\r\n",
|
470
|
+
file=file_descriptor,
|
471
|
+
)
|
472
|
+
print(
|
473
|
+
f"EMAIL: {self.station.get('Email', '')}",
|
474
|
+
end="\r\n",
|
475
|
+
file=file_descriptor,
|
476
|
+
)
|
477
|
+
for contact in log:
|
478
|
+
the_date_and_time = contact.get("TS", "")
|
479
|
+
themode = contact.get("Mode", "")
|
480
|
+
if themode == "LSB" or themode == "USB":
|
481
|
+
themode = "PH"
|
482
|
+
frequency = str(int(contact.get("Freq", "0"))).rjust(5)
|
483
|
+
|
484
|
+
loggeddate = the_date_and_time[:10]
|
485
|
+
loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
|
486
|
+
print(
|
487
|
+
f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
|
488
|
+
f"{contact.get('StationPrefix', '').ljust(13)} "
|
489
|
+
f"{str(contact.get('SNT', '')).ljust(3)} "
|
490
|
+
f"{str(contact.get('SentNr', '')).ljust(6)} "
|
491
|
+
f"{contact.get('Call', '').ljust(13)} "
|
492
|
+
f"{str(contact.get('RCV', '')).ljust(3)} "
|
493
|
+
f"{str(contact.get('NR', '')).ljust(6)}",
|
494
|
+
end="\r\n",
|
495
|
+
file=file_descriptor,
|
496
|
+
)
|
497
|
+
print("END-OF-LOG:", end="\r\n", file=file_descriptor)
|
498
|
+
self.show_message_box(f"Cabrillo saved to: {filename}")
|
499
|
+
except IOError as exception:
|
500
|
+
logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
|
501
|
+
self.show_message_box(f"Error saving Cabrillo: {exception} {filename}")
|
502
|
+
return
|
not1mm/test.py
CHANGED
@@ -1,13 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
Purpose: test alternative sound playing interface
|
5
|
-
"""
|
6
|
-
# pylint: disable=unused-import, c-extension-no-member, no-member, invalid-name, too-many-lines, no-name-in-module
|
7
|
-
# pylint: disable=logging-fstring-interpolation, logging-not-lazy, line-too-long, bare-except
|
1
|
+
class Somefunc:
|
2
|
+
def __init__(self):
|
3
|
+
"""weee"""
|
8
4
|
|
9
|
-
|
5
|
+
def testfunc():
|
6
|
+
"""wooo"""
|
10
7
|
|
11
|
-
filename = "./testing/K1USNSSTOP.udc"
|
12
8
|
|
13
|
-
|
9
|
+
thetest = Somefunc()
|
10
|
+
print(f"{hasattr(thetest, "ft8_catcher")}")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: not1mm
|
3
|
-
Version: 24.
|
3
|
+
Version: 24.9.3
|
4
4
|
Summary: NOT1MM Logger
|
5
5
|
Author-email: Michael Bridak <michael.bridak@gmail.com>
|
6
6
|
Project-URL: Homepage, https://github.com/mbridak/not1mm
|
@@ -100,6 +100,7 @@ Requires-Dist: Levenshtein
|
|
100
100
|
- [Cluster](#cluster)
|
101
101
|
- [N1MM Packets](#n1mm-packets)
|
102
102
|
- [Bands](#bands)
|
103
|
+
- [Logging WSJT-X FT8/FT4 contacts](#logging-wsjt-x-ft8ft4-contacts)
|
103
104
|
- [Sending CW](#sending-cw)
|
104
105
|
- [Editing macro keys](#editing-macro-keys)
|
105
106
|
- [Macro substitutions](#macro-substitutions)
|
@@ -225,11 +226,7 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
|
|
225
226
|
|
226
227
|
## Recent Changes
|
227
228
|
|
228
|
-
- [24-
|
229
|
-
- [24-8-22] Add loading splash screen.
|
230
|
-
- [24-8-20] Added K1USN Slow Speed Test
|
231
|
-
- [24-8-17-1] Did an oops. Fixed the oops.
|
232
|
-
- [24-8-17] Removed some cruft. Made dockable widgets not floatable since Wayland breaks this.
|
229
|
+
- [24-9-3] Added WSJT-X FT8 mode contacts to ARRL Field Day.
|
233
230
|
|
234
231
|
See [CHANGELOG.md](CHANGELOG.md) for prior changes.
|
235
232
|
|
@@ -250,7 +247,7 @@ not1mm requires:
|
|
250
247
|
- PyQt6
|
251
248
|
- libportaudio2
|
252
249
|
- libxcb-cursor0 (maybe... Depends on the distro)
|
253
|
-
|
250
|
+
|
254
251
|
You should install these through your distribution's package manager before continuing.
|
255
252
|
|
256
253
|
### Common installation recipes for Ubuntu and Fedora
|
@@ -337,9 +334,7 @@ pamac build not1mm-git
|
|
337
334
|
#### Mint
|
338
335
|
|
339
336
|
```bash
|
340
|
-
sudo apt install python3-pip
|
341
|
-
sudo apt install pipx
|
342
|
-
sudo apt install libxcb-cursor0
|
337
|
+
sudo apt install python3-pip pipx libxcb-cursor0
|
343
338
|
pipx install not1mm
|
344
339
|
pipx ensurepath
|
345
340
|
```
|
@@ -608,6 +603,13 @@ appear. Those without will not.
|
|
608
603
|
|
609
604
|

|
610
605
|
|
606
|
+
## Logging WSJT-X FT8/FT4 contacts
|
607
|
+
|
608
|
+
**Currently only working for ARRL Field Day.**
|
609
|
+
|
610
|
+
not1mm listens for WSJT-X UDP traffic on the default localhost:2237. No setup is
|
611
|
+
needed to be done on not1mm's side.
|
612
|
+
|
611
613
|
## Sending CW
|
612
614
|
|
613
615
|
Other than sending CW by hand, you can also send predefined CW text messages by
|
@@ -1,11 +1,11 @@
|
|
1
1
|
not1mm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
not1mm/__main__.py,sha256=
|
2
|
+
not1mm/__main__.py,sha256=xmqEIER571T8ONHjL-65TCuQ-PnUpDqH-nQFIutvUOk,122905
|
3
3
|
not1mm/bandmap.py,sha256=1b5tXCfGTnpqqn6hPNt7zRA8SmuwSXzSwNHZXhCRt70,31434
|
4
4
|
not1mm/checkwindow.py,sha256=aI-nr8OF90IWV7R_XRdmitvBJ9M85evCs72HoU3Jnvc,10374
|
5
5
|
not1mm/fsutils.py,sha256=ukHKxKTeNKxKwqRaJjtzRShL4X5Xl0jRBbADyy3Ifp8,1701
|
6
6
|
not1mm/logwindow.py,sha256=pwhiwolmGnW01LF4sjlu3ywLsgfxL6KuGuKuYKYmgeY,44403
|
7
7
|
not1mm/radio.py,sha256=eiB04LPMPBeMrBRI021Z7VXth66EOYb0Ujh11T9877c,3362
|
8
|
-
not1mm/test.py,sha256=
|
8
|
+
not1mm/test.py,sha256=H_5hAobuNebV0-PZk_CeX0_MO2FgGhMiauVBfNhfNTg,166
|
9
9
|
not1mm/vfo.py,sha256=IvmUQYMIPzLJw_BHQGis4J_IEW-vlBtdfxZLXPh7OzI,12335
|
10
10
|
not1mm/voice_keying.py,sha256=sA3gw5_k7kShTg2qhG7HkKDM5M6KheJVRkAc_C7mxDk,3006
|
11
11
|
not1mm/data/JetBrainsMono-Regular.ttf,sha256=UOHctAKY_PzCGh7zy-6f6egnCcSK0wzmF0csBqO9lDY,203952
|
@@ -94,7 +94,7 @@ not1mm/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
94
94
|
not1mm/lib/about.py,sha256=sWycfGcruN3SaEe4JmaJ61K6D8Itq0WxpUYT-lEcmYM,416
|
95
95
|
not1mm/lib/cat_interface.py,sha256=aazvNTSeZAROq3KL8gPx-I95iVez2IiIOSk22qeqVCQ,19502
|
96
96
|
not1mm/lib/cwinterface.py,sha256=Q8p3pScOHczZ8ptICfH1Yu6rCEwQJLgrNwYMN76B2i8,3389
|
97
|
-
not1mm/lib/database.py,sha256=
|
97
|
+
not1mm/lib/database.py,sha256=0dx6SX40OiPFent2ePAGsFj_XmOVMNBHaqd0QtAiewY,43129
|
98
98
|
not1mm/lib/edit_contact.py,sha256=Ki9bGPpqyQQBB1cU8VIBDCal3lbXeQ6qxhzklmhE2_w,353
|
99
99
|
not1mm/lib/edit_macro.py,sha256=raKWBwsHInj5EUKmvyLQ6gqc3ZFDlstsD3xqoM4PC8E,517
|
100
100
|
not1mm/lib/edit_opon.py,sha256=j3qJ1aBsQoIOnQ9yiBl3lyeISvKTP0I_rtBYBPAfgeI,359
|
@@ -110,7 +110,7 @@ not1mm/lib/plugin_common.py,sha256=wuG7B0OJx9zYc5Gew3fdt_lNyan8Ul9KNlPQ7PDKGsU,9
|
|
110
110
|
not1mm/lib/select_contest.py,sha256=WsptLuwkouIHeocJL3oZ6-eUfEnhpwdc-x7eMZ_TIVM,359
|
111
111
|
not1mm/lib/settings.py,sha256=MWiKXbasaFbzeHTjfzTaTqbCBrIijudP_-0a5jNmUAA,9265
|
112
112
|
not1mm/lib/super_check_partial.py,sha256=p5l3u2ZOCBtlWgbvskC50FpuoaIpR07tfC6zTdRWbh4,2334
|
113
|
-
not1mm/lib/version.py,sha256=
|
113
|
+
not1mm/lib/version.py,sha256=3nHzm4TY2JdIkrbl-vZhxO25Akrnx3rGDTzqroFbYJg,47
|
114
114
|
not1mm/lib/versiontest.py,sha256=8vDNptuBBunn-1IGkjNaquehqBYUJyjrPSF8Igmd4_Y,1286
|
115
115
|
not1mm/plugins/10_10_fall_cw.py,sha256=IttjX1yy4nDdACGsiYlPteFG8eVseX_WtoFio6bqHE8,10953
|
116
116
|
not1mm/plugins/10_10_spring_cw.py,sha256=ThCptdM3dX4ywhoy2JRcOEyHSqcJolFaT7O_PYzM1Mg,10958
|
@@ -120,7 +120,7 @@ not1mm/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
120
120
|
not1mm/plugins/arrl_10m.py,sha256=EyNRb3Sm0Qb-GVm0p05EnadlHisVh7y-sKTBP2ddMLo,13768
|
121
121
|
not1mm/plugins/arrl_dx_cw.py,sha256=LVnYDNFEUiIpQ1TlhOCcRK7JNwH5XPO5WzUoApSUMTY,13802
|
122
122
|
not1mm/plugins/arrl_dx_ssb.py,sha256=fUFzuNbCAfA5sQSYm8ISV3P9Z_2xnuKeOdO6E66zn1k,13805
|
123
|
-
not1mm/plugins/arrl_field_day.py,sha256
|
123
|
+
not1mm/plugins/arrl_field_day.py,sha256=-HaAp14eHJsiwo1vNnHjVQ7cbDyZ7NYl0Z3SEUx0fek,11903
|
124
124
|
not1mm/plugins/arrl_rtty_ru.py,sha256=hKUS4isjdXo3EYxQrsqsDupPp2chW8fpoWj0T1pTgJ4,7994
|
125
125
|
not1mm/plugins/arrl_ss_cw.py,sha256=4yN68xZMuJRaSUfdiY4hafC07A3lifl5q6DEUZ-oYPQ,13080
|
126
126
|
not1mm/plugins/arrl_ss_phone.py,sha256=Yzc5sNjrY8TlnozbYF6k8hbEamyDuUAD_3-BNqHgXqY,13068
|
@@ -128,15 +128,15 @@ not1mm/plugins/arrl_vhf_jan.py,sha256=jkX9v2HHsjoawtTKiy8X0Td_HtfGQVT3MapJwpmM1q
|
|
128
128
|
not1mm/plugins/arrl_vhf_jun.py,sha256=_9h6joxVCRCoFuNnyTOlnonafvrMv7H0eBERhYCoGug,11591
|
129
129
|
not1mm/plugins/arrl_vhf_sep.py,sha256=XbS1OSAfGaYXFaTAP2HRyVvVeRD_Z6cefPc1_mOLJKw,11591
|
130
130
|
not1mm/plugins/canada_day.py,sha256=OVpcCl1Chse_zLHf6PayTrgawWM4W-pmrTw40Al-o9s,11998
|
131
|
-
not1mm/plugins/cq_160_cw.py,sha256=
|
132
|
-
not1mm/plugins/cq_160_ssb.py,sha256=
|
131
|
+
not1mm/plugins/cq_160_cw.py,sha256=5s6rIZdJEnmWe1SI06BEyz7p5vP0N2n9mI4l_mZ0icw,14139
|
132
|
+
not1mm/plugins/cq_160_ssb.py,sha256=zIwSMAjHSt6W2edrDzVbyTf860JowHoFkU9BKO8Enag,14182
|
133
133
|
not1mm/plugins/cq_wpx_cw.py,sha256=9aNzAR-KhznIwUlxUFjAi_hbiw_6RrCMwUBk9I2f6Hs,14037
|
134
134
|
not1mm/plugins/cq_wpx_ssb.py,sha256=-hGRovqHR9rfOUnG4LPOoABTb4heH8VAX6rYdJbCqsw,12687
|
135
135
|
not1mm/plugins/cq_ww_cw.py,sha256=ltXFnSXabCOuW70s-WOydgghZTNpztX8TKLpVIV50B4,11194
|
136
136
|
not1mm/plugins/cq_ww_ssb.py,sha256=kt-EQofmCbynX1iXFm9ehffi_TMW25ke8Qi9MiR69ZQ,11199
|
137
137
|
not1mm/plugins/cwt.py,sha256=4xdXN6ZJM5k-6gn0hJzNheWfFlGiqquC2p0ZMEe516M,12818
|
138
138
|
not1mm/plugins/general_logging.py,sha256=t02xtJs601qRICGdrvLs3G9y4GCG9H4AgQNkgA18CYs,3467
|
139
|
-
not1mm/plugins/helvetia.py,sha256=
|
139
|
+
not1mm/plugins/helvetia.py,sha256=6aOO4uiLzFFgHA-A3xz6IRdCJpqPOAm0egKxP5Y_Ie0,15432
|
140
140
|
not1mm/plugins/iaru_hf.py,sha256=-ROUo2gBkw3xB89t8bd-4f7_1hROw2VXZXVHLFdB62s,11541
|
141
141
|
not1mm/plugins/icwc_mst.py,sha256=BaUP2kzrT2D27un_WLGT4HCTTi1e7CNYC4NHcC_9r74,11842
|
142
142
|
not1mm/plugins/jidx_cw.py,sha256=9oV4hDxMiGXa9wuYUNYOCsr-mz8LYB-4WMHBN8u2dFk,12153
|
@@ -145,11 +145,12 @@ not1mm/plugins/k1usn_sst.py,sha256=2Nu7SRiQeUG3mL9CLKReRLh8vKsNbWcizMgv9MTLkrg,1
|
|
145
145
|
not1mm/plugins/naqp_cw.py,sha256=c0MuKqfkIxiYFvv2z7vqrBz3m9FSnSYkPK3f-DdkTIA,12632
|
146
146
|
not1mm/plugins/naqp_ssb.py,sha256=VLWVrSzI0UP1AhSXYn61eZ7or1rz6a_pS_xCKfgS4Jw,11595
|
147
147
|
not1mm/plugins/phone_weekly_test.py,sha256=fLpMe03WB9_KgRl6vMgQQt_aktFdqfNt2Sw81CTRAUs,12325
|
148
|
+
not1mm/plugins/ref_cw.py,sha256=aWjHHkqIKutjRUtzh09y5haFfnZK9poRQDWRQMDRxxU,16326
|
148
149
|
not1mm/plugins/stew_perry_topband.py,sha256=CKBQbYl4ETxhXJd2dma4fg_C5pag_s7Nf61SCztZtqE,10668
|
149
150
|
not1mm/plugins/winter_field_day.py,sha256=4rcfRtobwjHO6BNL3WOTHzBmyyeuX79BNGBG8PfjrI8,10238
|
150
|
-
not1mm-24.
|
151
|
-
not1mm-24.
|
152
|
-
not1mm-24.
|
153
|
-
not1mm-24.
|
154
|
-
not1mm-24.
|
155
|
-
not1mm-24.
|
151
|
+
not1mm-24.9.3.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
152
|
+
not1mm-24.9.3.dist-info/METADATA,sha256=11Kg9639B3UOSQ5rFKE5RgPZLY8Ww7rGP0hs4jW3QU8,29734
|
153
|
+
not1mm-24.9.3.dist-info/WHEEL,sha256=uCRv0ZEik_232NlR4YDw4Pv3Ajt5bKvMH13NUU7hFuI,91
|
154
|
+
not1mm-24.9.3.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
|
155
|
+
not1mm-24.9.3.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
|
156
|
+
not1mm-24.9.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|