not1mm 25.1.6__py3-none-any.whl → 25.1.23__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/lib/database.py CHANGED
@@ -179,6 +179,7 @@ class DataBase:
179
179
  ");"
180
180
  )
181
181
  cursor.execute(sql_command)
182
+ cursor.execute("PRAGMA journal_mode=WAL")
182
183
  conn.commit()
183
184
  except sqlite3.OperationalError as exception:
184
185
  logger.debug("%s", exception)
@@ -222,6 +223,7 @@ class DataBase:
222
223
  ");"
223
224
  )
224
225
  cursor.execute(sql_command)
226
+ cursor.execute("PRAGMA journal_mode=WAL")
225
227
  conn.commit()
226
228
 
227
229
  sql_command = "select * from Contest;"
@@ -271,6 +273,7 @@ class DataBase:
271
273
  "TimeCategory NVARCHAR(20));"
272
274
  )
273
275
  cursor.execute(sql_command)
276
+ cursor.execute("PRAGMA journal_mode=WAL")
274
277
  conn.commit()
275
278
  except sqlite3.OperationalError as exception:
276
279
  logger.debug("%s", exception)
@@ -310,6 +313,7 @@ class DataBase:
310
313
  "PRIMARY KEY([Call]));"
311
314
  )
312
315
  cursor.execute(sql_command)
316
+ cursor.execute("PRAGMA journal_mode=WAL")
313
317
  conn.commit()
314
318
  except sqlite3.OperationalError as exception:
315
319
  logger.debug("%s", exception)
@@ -89,7 +89,7 @@ def gen_adif(self, cabrillo_name: str, contest_id=""):
89
89
  hisname = contact.get("Name", "")
90
90
  the_date_and_time = contact.get("TS", "")
91
91
  themode = contact.get("Mode", "")
92
- if themode == "CWR":
92
+ if themode in ("CWR", "CW-R"):
93
93
  themode = "CW"
94
94
  if cabrillo_name in ("CQ-WW-RTTY", "WEEKLY-RTTY"):
95
95
  themode = "RTTY"
not1mm/lib/version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """It's the version"""
2
2
 
3
- __version__ = "25.1.6"
3
+ __version__ = "25.1.23"
@@ -330,6 +330,8 @@ def cabrillo(self, file_encoding):
330
330
  themode = contact.get("Mode", "")
331
331
  if themode == "LSB" or themode == "USB":
332
332
  themode = "PH"
333
+ if themode == "RTTY":
334
+ themode = "DG"
333
335
  frequency = str(int(contact.get("Freq", "0"))).rjust(5)
334
336
 
335
337
  loggeddate = the_date_and_time[:10]
not1mm/ratewindow.py ADDED
@@ -0,0 +1,263 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ not1mm Contest logger
4
+ Email: michael.bridak@gmail.com
5
+ GPL V3
6
+ Class: RateWindow
7
+ Purpose: not sure yet
8
+ """
9
+ # pylint: disable=no-name-in-module, unused-import, no-member, invalid-name, c-extension-no-member
10
+ # pylint: disable=logging-fstring-interpolation, line-too-long
11
+
12
+ import datetime
13
+ import time
14
+ import logging
15
+ import os
16
+
17
+ from PyQt6 import uic
18
+ from PyQt6.QtWidgets import QLabel, QWidget, QDockWidget
19
+ from PyQt6.QtGui import QMouseEvent, QColorConstants, QPalette, QColor
20
+ from PyQt6.QtCore import pyqtSignal, QTimer
21
+
22
+ import not1mm.fsutils as fsutils
23
+ from not1mm.lib.database import DataBase
24
+
25
+ from json import loads
26
+ from json.decoder import JSONDecodeError
27
+ from pathlib import Path
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+
32
+ class RateWindow(QDockWidget):
33
+ """The rate window. Shows something important."""
34
+
35
+ message = pyqtSignal(dict)
36
+ dbname = None
37
+ pref = {}
38
+ poll_time = datetime.datetime.now() + datetime.timedelta(milliseconds=1000)
39
+
40
+ def __init__(self):
41
+ super().__init__()
42
+ self.active = False
43
+ self.load_pref()
44
+ self.dbname = fsutils.USER_DATA_PATH / self.pref.get(
45
+ "current_database", "ham.db"
46
+ )
47
+ self.database = DataBase(self.dbname, fsutils.APP_DATA_PATH)
48
+ self.database.current_contest = self.pref.get("contest", 0)
49
+
50
+ uic.loadUi(fsutils.APP_DATA_PATH / "ratewindow.ui", self)
51
+ self.hide_unused()
52
+ self.timer = QTimer()
53
+ self.timer.timeout.connect(self.get_run_and_total_qs)
54
+ self.timer.start(1000)
55
+
56
+ def msg_from_main(self, packet):
57
+ """"""
58
+ if packet.get("cmd", "") == "DARKMODE":
59
+ self.setDarkMode(packet.get("state", False))
60
+ return
61
+
62
+ if self.active is False:
63
+ return
64
+
65
+ if packet.get("cmd", "") == "NEWDB":
66
+ ...
67
+ # self.load_new_db()
68
+
69
+ def setActive(self, mode: bool):
70
+ self.active = bool(mode)
71
+
72
+ def setDarkMode(self, dark: bool) -> None:
73
+ """Forces a darkmode palette."""
74
+
75
+ if dark:
76
+ darkPalette = QPalette()
77
+ darkColor = QColor(56, 56, 56)
78
+ disabledColor = QColor(127, 127, 127)
79
+ darkPalette.setColor(QPalette.ColorRole.Window, darkColor)
80
+ darkPalette.setColor(QPalette.ColorRole.WindowText, QColorConstants.White)
81
+ darkPalette.setColor(QPalette.ColorRole.Base, QColor(45, 45, 45))
82
+ darkPalette.setColor(QPalette.ColorRole.AlternateBase, darkColor)
83
+ darkPalette.setColor(QPalette.ColorRole.Text, QColorConstants.White)
84
+ darkPalette.setColor(QPalette.ColorRole.Button, darkColor)
85
+ darkPalette.setColor(QPalette.ColorRole.ButtonText, QColorConstants.White)
86
+ darkPalette.setColor(QPalette.ColorRole.BrightText, QColorConstants.Red)
87
+ darkPalette.setColor(QPalette.ColorRole.Link, QColor(42, 130, 218))
88
+ darkPalette.setColor(QPalette.ColorRole.Highlight, QColor(42, 130, 218))
89
+ darkPalette.setColor(
90
+ QPalette.ColorRole.HighlightedText, QColorConstants.Black
91
+ )
92
+ darkPalette.setColor(
93
+ QPalette.ColorGroup.Disabled,
94
+ QPalette.ColorRole.ButtonText,
95
+ disabledColor,
96
+ )
97
+ darkPalette.setColor(
98
+ QPalette.ColorGroup.Disabled,
99
+ QPalette.ColorRole.HighlightedText,
100
+ disabledColor,
101
+ )
102
+ darkPalette.setColor(
103
+ QPalette.ColorGroup.Disabled,
104
+ QPalette.ColorRole.Text,
105
+ disabledColor,
106
+ )
107
+
108
+ self.setPalette(darkPalette)
109
+ else:
110
+ palette = self.style().standardPalette()
111
+ self.setPalette(palette)
112
+
113
+ def load_pref(self) -> None:
114
+ """
115
+ Load preference file to get current db filename and sets the initial darkmode state.
116
+
117
+ Parameters
118
+ ----------
119
+ None
120
+
121
+ Returns
122
+ -------
123
+ None
124
+ """
125
+ try:
126
+ if os.path.exists(fsutils.CONFIG_FILE):
127
+ with open(
128
+ fsutils.CONFIG_FILE, "rt", encoding="utf-8"
129
+ ) as file_descriptor:
130
+ self.pref = loads(file_descriptor.read())
131
+ logger.info(f"loaded config file from {fsutils.CONFIG_FILE}")
132
+ else:
133
+ self.pref["current_database"] = "ham.db"
134
+
135
+ except (IOError, JSONDecodeError) as exception:
136
+ logger.critical("Error: %s", exception)
137
+ self.setDarkMode(self.pref.get("darkmode", False))
138
+
139
+ def get_run_and_total_qs(self):
140
+ """get numbers"""
141
+
142
+ # last_hour
143
+ # 10_last_qso
144
+ # hundred_last_qso
145
+ # since_lasthour_label since_lasthour
146
+ # --------------------
147
+ # time_on
148
+ # time_off
149
+ # --------------------
150
+ # run_qso
151
+ # sandp_qso
152
+ # hour_run_qso
153
+ # hour_sandp_qso
154
+ # --------------------
155
+ # avg_km
156
+ # avg_pts
157
+ # --------------------
158
+ # time_by_mult
159
+ # qso_counts
160
+ # mult_counts
161
+ # mult_worth
162
+ # {'runs': 3, 'totalqs': 3}
163
+
164
+ # WHERE datetime(timestamp) > datetime(current_timestamp, '-60 minutes')
165
+
166
+ if not self.active:
167
+ return
168
+
169
+ # Get Q's in the 60 Minutes
170
+ query = f"select (julianday(MAX(ts)) - julianday(MIN(ts))) * 24 * 60 as timespan, count(*) as items from (select * from dxlog where ContestNR = {self.database.current_contest} and datetime(TS) > datetime(current_timestamp, '-60 minutes'));"
171
+ result = self.database.exec_sql(query)
172
+
173
+ if result.get("items", 0) < 1:
174
+ self.last_hour.setText("--- Q/h")
175
+ else:
176
+ try:
177
+ perhour = (60.0 / result.get("timespan", 60)) * result.get("items", 0)
178
+ self.last_hour.setText(str(f"{perhour:.2f} Q/h"))
179
+ except (ZeroDivisionError, TypeError):
180
+ ...
181
+
182
+ # Get Q's per hour rate of the last 10 QSO's
183
+ query = f"SELECT (julianday(MAX(ts)) - julianday(MIN(ts))) * 24 * 60 as timespan, count(*) as items FROM ( select * from DXLOG where ContestNR = {self.database.current_contest} ORDER by ts DESC limit 10);"
184
+ result = self.database.exec_sql(query)
185
+ if result.get("items", 0) < 10:
186
+ self.ten_last_qso.setText("--- Q/h")
187
+ else:
188
+ try:
189
+ perhour = (60.0 / result.get("timespan", 60)) * result.get("items", 0)
190
+ self.ten_last_qso.setText(str(f"{perhour:.2f} Q/h"))
191
+ except (ZeroDivisionError, TypeError):
192
+ ...
193
+
194
+ # Get Q's per hour rate of the last 100 QSO's
195
+ query = f"SELECT (julianday(MAX(ts)) - julianday(MIN(ts))) * 24 * 60 as timespan, count(*) as items FROM (select * from DXLOG where ContestNR = {self.database.current_contest} ORDER by ts DESC limit 100);"
196
+ result = self.database.exec_sql(query)
197
+ if result.get("items", 0) < 100:
198
+ self.hundred_last_qso.setText("--- Q/h")
199
+ else:
200
+ try:
201
+ perhour = (60.0 / result.get("timespan", 60)) * result.get("items", 0)
202
+ self.hundred_last_qso.setText(str(f"{perhour:.2f} Q/h"))
203
+ except (ZeroDivisionError, TypeError):
204
+ ...
205
+
206
+ # Get rate for the current hour
207
+ query = f"SELECT strftime('%Y-%m-%d %H:00:00','now') as limit_stamp, strftime('%H:00:00','now') as current_hour, count(*) as items FROM DXLOG where ContestNR = {self.database.current_contest} and datetime(TS) > limit_stamp;"
208
+ result = self.database.exec_sql(query)
209
+
210
+ self.since_lasthour_label.setText(
211
+ f"Since {result.get('current_hour', '00:00:00')}z:"
212
+ )
213
+ self.since_lasthour.setText(f"{result.get('items', '0')} QSO")
214
+
215
+ # Get Run QSO's and S&P QSO's
216
+ query = f"select sum(IsRunQSO) as runs, count(*) as totalqs from dxlog where ContestNR = {self.database.current_contest};"
217
+ result = self.database.exec_sql(query)
218
+ try:
219
+ sandp = result.get("totalqs", 0) - result.get("runs", 0)
220
+ self.run_qso.setText(f"{result.get("runs", 0)}")
221
+ self.sandp_qso.setText(f"{sandp}")
222
+ self.qso_counts.setText(f"{result.get("totalqs", 0)} pts")
223
+ except TypeError:
224
+ ...
225
+
226
+ # Get runs for the current hour
227
+ query = f"SELECT strftime('%Y-%m-%d %H:00:00','now') as limit_stamp, sum(IsRunQSO) as runs, count(*) as totalqs FROM DXLOG where ContestNR = {self.database.current_contest} and datetime(TS) > limit_stamp;"
228
+ result = self.database.exec_sql(query)
229
+ try:
230
+ sandp = result.get("totalqs", 0) - result.get("runs", 0)
231
+ self.hour_run_qso.setText(f"{result.get("runs", 0)}")
232
+ self.hour_sandp_qso.setText(f"{sandp}")
233
+ except TypeError:
234
+ ...
235
+
236
+ def hide_unused(self):
237
+ self.line.hide()
238
+ self.label_10.hide()
239
+ self.time_on.hide()
240
+ self.label_12.hide()
241
+ self.time_off.hide()
242
+
243
+ self.band_mode.hide()
244
+ self.label_23.hide()
245
+ self.avg_km.hide()
246
+ self.label_25.hide()
247
+ self.avg_pts.hide()
248
+ self.best_dx.hide()
249
+ self.label_26.hide()
250
+
251
+ self.line_5.hide()
252
+ self.label_29.hide()
253
+ self.label_30.hide()
254
+ self.time_by_mult.hide()
255
+ self.label_32.hide()
256
+ self.qso_counts.hide()
257
+ self.label_34.hide()
258
+ self.mult_counts.hide()
259
+ self.label_35.hide()
260
+ self.mult_worth.hide()
261
+
262
+ self.line_6.hide()
263
+ self.label_38.hide()
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: not1mm
3
- Version: 25.1.6
3
+ Version: 25.1.23
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
@@ -51,7 +51,6 @@ Requires-Dist: Levenshtein
51
51
  - [The What](#the-what)
52
52
  - [Target Environment](#target-environment)
53
53
  - [The Why](#the-why)
54
- - [General logging](#general-logging)
55
54
  - [Current state](#current-state)
56
55
  - [Code maturity](#code-maturity)
57
56
  - [Data and RTTY](#data-and-rtty)
@@ -115,6 +114,7 @@ Requires-Dist: Levenshtein
115
114
  - [Editing a contact](#editing-a-contact)
116
115
  - [The Bandmap Window](#the-bandmap-window)
117
116
  - [The Check Window](#the-check-window)
117
+ - [The Rate Window](#the-rate-window)
118
118
  - [The Remote VFO Window](#the-remote-vfo-window)
119
119
  - [Cabrillo](#cabrillo)
120
120
  - [ADIF](#adif)
@@ -164,11 +164,6 @@ I'm a casual contester and could not find any contesting software for Linux that
164
164
  I wanted to use. There is [Tucnak](http://tucnak.nagano.cz/) which is very robust
165
165
  and mature. It just wasn't for me.
166
166
 
167
- ### General logging
168
-
169
- In short... Don't. There are much better general purpose QSO logging programs.
170
- Try QLog or CQRLog.
171
-
172
167
  ## Current state
173
168
 
174
169
  ### Code maturity
@@ -240,6 +235,8 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
240
235
 
241
236
  ## Recent Changes (Polishing the Turd)
242
237
 
238
+ - [25-1-23] Added a basic rate window. Changed DB to WAL mode.
239
+ - [25-1-15] Fix bug in ADIF output where mode showed as CW-R and not CW.
243
240
  - [25-1-6] Altered RTTY RU UDP ADIF parse.
244
241
  - [25-1-1] Added ARRL RTTY RU.
245
242
 
@@ -247,7 +244,7 @@ See [CHANGELOG.md](CHANGELOG.md) for prior changes.
247
244
 
248
245
  ## Flatpak
249
246
 
250
- I've tried for a couple days to get not1mm to build as a flatpak. I've failed.
247
+ I've tried for a couple days to get Not1MM to build as a flatpak. I've failed.
251
248
  It keeps failing at building numpy. If you happen to be a flatpak savant, please
252
249
  feel free to look at com.github.mbridak.not1mm.yaml and python3-modules.yaml and
253
250
  clue me into the black magic needed to get it to work.
@@ -256,7 +253,7 @@ clue me into the black magic needed to get it to work.
256
253
 
257
254
  ### Prerequisites
258
255
 
259
- not1mm requires:
256
+ Not1MM requires:
260
257
 
261
258
  - Python 3.9+
262
259
  - PyQt6
@@ -268,7 +265,7 @@ You should install these through your distribution's package manager before cont
268
265
  ### Common installation recipes for Ubuntu and Fedora
269
266
 
270
267
  I've taken the time to install some common Linux distributions into a VM and
271
- noted the minimum steps needed to install not1mm.
268
+ noted the minimum steps needed to install Not1MM.
272
269
 
273
270
  <details>
274
271
 
@@ -392,14 +389,14 @@ python3 -m pipx ensurepath
392
389
 
393
390
  #### Installing with pipx
394
391
 
395
- Then installing not1mm is as simple as:
392
+ Then installing Not1MM is as simple as:
396
393
 
397
394
  ```bash
398
395
  # Install not1mm
399
396
  pipx install not1mm
400
397
  ```
401
398
 
402
- If you need to later update not1mm, you can do so with:
399
+ If you need to later update Not1MM, you can do so with:
403
400
 
404
401
  ```bash
405
402
  # Update not1mm
@@ -422,7 +419,7 @@ source rebuild.sh
422
419
  ```
423
420
 
424
421
  from the root directory. This installs a build chain and a local editable copy
425
- of not1mm.
422
+ of Not1MM.
426
423
 
427
424
  There's two ways to launch the program from the local editable copy.
428
425
 
@@ -625,14 +622,10 @@ On the Options TAB you can:
625
622
 
626
623
  ## Logging WSJT-X FT8/FT4/ETC and FLDIGI RTTY contacts
627
624
 
628
- not1mm listens for WSJT-X UDP traffic on the Multicast address 224.0.0.1:2237.
629
- No setup is needed to be done on not1mm's side. That's good because I'm lazy.
625
+ Not1MM listens for WSJT-X UDP traffic on the Multicast address 224.0.0.1:2237.
626
+ No setup is needed to be done on Not1MM's side. That's good because I'm lazy.
630
627
 
631
- ~~not1mm polls for fldigi QSOs via it's XMLRPC interface. It does this in a rather stupid
632
- way. It just keeps asking what was the last QSO and compares it to the previous response.
633
- If it's different, it's new.~~
634
-
635
- not1mm watches for fldigi qso's by watching for UDP traffic from fldigi on 127.0.0.1:9876.
628
+ Not1MM watches for fldigi qso's by watching for UDP traffic from fldigi on 127.0.0.1:9876.
636
629
 
637
630
  ![fldigi configuration dialog](https://github.com/mbridak/not1mm/blob/master/pic/fldigi_adif_udp.png?raw=true)
638
631
 
@@ -810,6 +803,14 @@ Clicking on any of these items will change the callsign field.
810
803
 
811
804
  ![Check Window](https://github.com/mbridak/not1mm/raw/master/pic/checkwindow.png)
812
805
 
806
+ ### The Rate Window
807
+
808
+ `Window`>`Rate Window`
809
+
810
+ This window contains QSO rates and counts.
811
+
812
+ ![Rate Window](https://github.com/mbridak/not1mm/raw/master/pic/rate_window.png)
813
+
813
814
  ### The Remote VFO Window
814
815
 
815
816
  You can control the VFO on a remote rig by following the directions listed in
@@ -1,11 +1,12 @@
1
1
  not1mm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- not1mm/__main__.py,sha256=mMKDAkCWN5gF4SM7-wod-njba7RDw2Zfr-pNI5q7FxY,144819
2
+ not1mm/__main__.py,sha256=4TslHv_xs1nYgUicgGvtK07oPvFYwtf0T6OHKsaytB8,146185
3
3
  not1mm/bandmap.py,sha256=zD3aUf36NVQCy0plAcZLNxYhSEM9xZ8J1Cu9vrcFPYA,31136
4
4
  not1mm/checkwindow.py,sha256=VFAcKYTcoWhmIf91chwY6tyao9FQMWPiUkgDDkkWaog,9670
5
5
  not1mm/fsutils.py,sha256=ukHKxKTeNKxKwqRaJjtzRShL4X5Xl0jRBbADyy3Ifp8,1701
6
6
  not1mm/logwindow.py,sha256=TvpzQTNB92hISlUO3iWBqtlPmlebdhOkAArx0DNGcOs,43966
7
7
  not1mm/lookupservice.py,sha256=GkY_qHZfrW6XHf8upIoaG4hCFqm0fg6Ganu9ConGrIc,2628
8
8
  not1mm/radio.py,sha256=c4m7Ci38uKGKxB0JUT5uOKalI_Mm8Vmixu5D_roN5z4,5400
9
+ not1mm/ratewindow.py,sha256=eAIjya6D83SAmXH7uBArUyZiMDSYNDoRzz3Y5UVzSy4,9623
9
10
  not1mm/rtc_service.py,sha256=axAwnCBuTr-QL0YwXtWvg9tjwhcFsiiEZFgFjOofX6k,2816
10
11
  not1mm/test.py,sha256=RN71m2S9MPIOJMaoCi0wZhwEhpEZunvtosZxaKahRB4,101
11
12
  not1mm/vfo.py,sha256=ggPyWtxMbdSE5RwdK0nDRwDNqOxdpb_pvnzZdbzZVQE,11136
@@ -31,7 +32,7 @@ not1mm/data/k6gte.not1mm-32.png,sha256=XdTsCa3xqwTfn26Ga7RwO_Vlbg_77RKkSc8bMxVcC
31
32
  not1mm/data/k6gte.not1mm-64.png,sha256=6ku45Gq1g5ezh04F07osoKRtanb3e4kbx5XdIEh3N90,2925
32
33
  not1mm/data/logwindow.ui,sha256=f7vULj96tHIQuR1nJMyvPHHcmVgzkhv9D1isyojsnFU,1458
33
34
  not1mm/data/logwindowx.ui,sha256=CwpI-h7cI1yqyldH9quKftsdHL5lTyL9ABOcf80nfqc,1632
34
- not1mm/data/main.ui,sha256=pI-70TYESe85ENkRH8l1DXnKDOkwYqKXUdMk6KYaN50,63193
35
+ not1mm/data/main.ui,sha256=LEziByl_8nNTBYR0Z-6CgqDcMbsvQVgfWOfF-B9z3MQ,63537
35
36
  not1mm/data/new_contest.ui,sha256=Sc8HquH7BK0bmkypeK_HbfhArE6yaw02WONOUlRdmuA,23953
36
37
  not1mm/data/not1mm.html,sha256=c9-mfjMwDt4f5pySUruz2gREW33CQ2_rCddM2z5CZQo,23273
37
38
  not1mm/data/opon.ui,sha256=QDicqAk2lORG2UWsHa6jHlsGn6uzrrI2R4HSAocpPes,2258
@@ -39,6 +40,7 @@ not1mm/data/pickcontest.ui,sha256=4hPBszCglObThx_eIWtmK9CEcbr7WBjbB1rKZdI-o3I,17
39
40
  not1mm/data/radio_green.png,sha256=PXlvRI2x0C8yLVkxRwrZe6tex8k9GtM-1Cj2Vy6KP7o,1234
40
41
  not1mm/data/radio_grey.png,sha256=9eOtMHDpQvRYY29D7_vPeacWbwotRXZTMm8EiHE9TW0,1258
41
42
  not1mm/data/radio_red.png,sha256=QvkMk7thd_hCEIyK5xGAG4xVVXivl39nwOfD8USDI20,957
43
+ not1mm/data/ratewindow.ui,sha256=yUi9PS0D96W3meNWsU1jg6vcSA_FC-1A2bInshJOTIQ,37369
42
44
  not1mm/data/reddot.png,sha256=M33jEMoU8W4rQ4_MVyzzKxDPDte1ypKBch5VnUMNLKE,565
43
45
  not1mm/data/rttymacros.txt,sha256=FQ2BnAChXF5w-tzmMnBOE8IgvviAEsd3cmmz4b8GOPk,467
44
46
  not1mm/data/settings.ui,sha256=NyHFUb3ZFEgZ4bYB3O7qlO_0TvZwcc9SFPr7z9nF6kk,40123
@@ -98,7 +100,7 @@ not1mm/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
98
100
  not1mm/lib/about.py,sha256=sWycfGcruN3SaEe4JmaJ61K6D8Itq0WxpUYT-lEcmYM,416
99
101
  not1mm/lib/cat_interface.py,sha256=weOH3Gds2ISEdZ2uZkHOv5tBZu-hoSwYKlrFUlg_KK4,25202
100
102
  not1mm/lib/cwinterface.py,sha256=yQL8Dif9oOIynaRItHgvcmu4mYv1TnTpqCHPtkeb09o,4472
101
- not1mm/lib/database.py,sha256=mm3vJgKmAQcUn4Ej--feR0yc_RhWTN01JIwMelI1EdI,48971
103
+ not1mm/lib/database.py,sha256=-9iAPTXDGVUc3OfnZNZCaWRxg3u-qdJyO5jvSvrJQSk,49203
102
104
  not1mm/lib/edit_contact.py,sha256=Ki9bGPpqyQQBB1cU8VIBDCal3lbXeQ6qxhzklmhE2_w,353
103
105
  not1mm/lib/edit_macro.py,sha256=raKWBwsHInj5EUKmvyLQ6gqc3ZFDlstsD3xqoM4PC8E,517
104
106
  not1mm/lib/edit_opon.py,sha256=j3qJ1aBsQoIOnQ9yiBl3lyeISvKTP0I_rtBYBPAfgeI,359
@@ -110,11 +112,11 @@ not1mm/lib/lookup.py,sha256=KECMDi9tflRDzgTLeDfDl7HGWWRHvW3HCjNHyyjoWaY,10835
110
112
  not1mm/lib/multicast.py,sha256=KJcruI-bOuHfHXPjl3SGQhL6I9sKrygy-sdFSvxffUM,3255
111
113
  not1mm/lib/n1mm.py,sha256=H54mpgJF0GAmKavM-nb5OAq2SJFWYkux4eMWWiSRxJc,6288
112
114
  not1mm/lib/new_contest.py,sha256=IznTDMq7yXHB6zBoGUEC_WDYPCPpsSZW4wwMJi16zK0,816
113
- not1mm/lib/plugin_common.py,sha256=-cvXtEAUgZ7GtxaNiwVdHbZ-7wEBeoMPRZXNdCxnPyA,13203
115
+ not1mm/lib/plugin_common.py,sha256=M5reDYM-v5IjAa2yTROvZTeTDkXYHb3U52W9mc9GxwA,13213
114
116
  not1mm/lib/select_contest.py,sha256=WsptLuwkouIHeocJL3oZ6-eUfEnhpwdc-x7eMZ_TIVM,359
115
117
  not1mm/lib/settings.py,sha256=j5lIMLHJ-eqIaVr_QhI82gkbOl17_C-5suRkWbHYET8,14717
116
118
  not1mm/lib/super_check_partial.py,sha256=hwT2NRwobu0PLDyw6ltmbmcAtGBD02CKGFbgGWjXMqA,2334
117
- not1mm/lib/version.py,sha256=iW32MIFaiAvBUPU7oYgyRhnGFlmeNjNzGML_oIFxa6s,47
119
+ not1mm/lib/version.py,sha256=DpSG7ODlKeORCWHhfP6siFU6x8qSgV-CRyUyC-zUp48,48
118
120
  not1mm/lib/versiontest.py,sha256=8vDNptuBBunn-1IGkjNaquehqBYUJyjrPSF8Igmd4_Y,1286
119
121
  not1mm/plugins/10_10_fall_cw.py,sha256=5QUyGMvGBC-HxcY_z9QbfuxSg3f7p6C9K4qhTxgZE7k,14719
120
122
  not1mm/plugins/10_10_spring_cw.py,sha256=XjYFM263WYyG6nVQzPObW4YC7Z9L93rixSOcVsxPvH4,14722
@@ -162,10 +164,10 @@ not1mm/plugins/ref_cw.py,sha256=sj69Jjtm1gA9juQTRVSe3BdcCqcQXMaJMD5D1kr5QOs,2072
162
164
  not1mm/plugins/ref_ssb.py,sha256=vfS9-mcnbw2znRvU4jh20JqI9BXap8jV65OV5mbCkCk,20939
163
165
  not1mm/plugins/stew_perry_topband.py,sha256=D1hekmMbx-i4BhaP2uzOK3OzaVVMMdgcN3RmfweNqHo,15341
164
166
  not1mm/plugins/weekly_rtty.py,sha256=huZszbZsIh4vF3cP80UyPzy3qxIoHdEiT1b6KuvwgYc,20083
165
- not1mm/plugins/winter_field_day.py,sha256=cSCFwy1LOoDDA9Zs1LHRG3r8spDMSKDisxyPxnVrLjw,15149
166
- not1mm-25.1.6.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
167
- not1mm-25.1.6.dist-info/METADATA,sha256=GQZzZaXZQcA238AIpNfqQXP4SYN2Xddwlvv2H6shzuE,35716
168
- not1mm-25.1.6.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
169
- not1mm-25.1.6.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
170
- not1mm-25.1.6.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
171
- not1mm-25.1.6.dist-info/RECORD,,
167
+ not1mm/plugins/winter_field_day.py,sha256=JK4r1vfxs7aADR7ZYbjZniz3f5s3_ipSQDZ0GRNWC7I,15222
168
+ not1mm-25.1.23.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
169
+ not1mm-25.1.23.dist-info/METADATA,sha256=lzLvwahSNXPAMD5QtDB906desmijbfpV8mItXBeknvA,35691
170
+ not1mm-25.1.23.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
171
+ not1mm-25.1.23.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
172
+ not1mm-25.1.23.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
173
+ not1mm-25.1.23.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.7.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5