not1mm 25.6.16.1__py3-none-any.whl → 25.6.18.1__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 CHANGED
@@ -3399,7 +3399,7 @@ class MainWindow(QtWidgets.QMainWindow):
3399
3399
  return
3400
3400
  self.cw.sendcw(self.process_macro(function_key.toolTip()))
3401
3401
  # if self.pref.get("cwtype") == 2:
3402
- time.sleep(0.3)
3402
+ # time.sleep(0.3)
3403
3403
  # return
3404
3404
 
3405
3405
  def toggle_run_sp(self) -> None:
@@ -367,6 +367,11 @@
367
367
  <string>ES FIELD DAY</string>
368
368
  </property>
369
369
  </item>
370
+ <item>
371
+ <property name="text">
372
+ <string>ES MANUAL KEY</string>
373
+ </property>
374
+ </item>
370
375
  <item>
371
376
  <property name="text">
372
377
  <string>HELVETIA</string>
not1mm/lib/lookup.py CHANGED
@@ -74,27 +74,30 @@ class HamDBlookup:
74
74
  if root:
75
75
  messages = root.get("messages")
76
76
  callsign = root.get("callsign")
77
- if messages:
78
- error_text = messages.get("status")
79
- logger.debug("HamDB: %s", error_text)
80
- if error_text != "OK":
81
- self.error = False
82
- if callsign:
83
- logger.debug("HamDB: found callsign field")
84
- if callsign.get("grid"):
85
- grid = callsign.get("grid")
86
- if callsign.get("fname"):
87
- name = callsign.get("fname")
88
- if callsign.get("name"):
89
- if not name:
90
- name = callsign.get("name")
91
- else:
92
- name = f"{name} {callsign.get('name')}"
93
- if callsign.get("nickname"):
94
- nickname = callsign.get("nickname")
77
+ if messages is not None:
78
+ error_text = messages.get("status")
79
+ logger.debug("HamDB: %s", error_text)
80
+ if error_text != "OK":
81
+ self.error = False
82
+ if callsign is not None:
83
+ logger.debug("HamDB: found callsign field")
84
+ if callsign.get("grid"):
85
+ grid = callsign.get("grid")
86
+ if callsign.get("fname"):
87
+ name = callsign.get("fname")
88
+ if callsign.get("name"):
89
+ if not name:
90
+ name = callsign.get("name")
91
+ else:
92
+ name = f"{name} {callsign.get('name')}"
93
+ if callsign.get("nickname"):
94
+ nickname = callsign.get("nickname")
95
95
  else:
96
96
  self.error = True
97
97
  error_text = str(query_result.status_code)
98
+ logger.critical(
99
+ "HamDB-lookup: %s %s %s %s", grid, name, nickname, error_text
100
+ )
98
101
  logger.info("HamDB-lookup: %s %s %s %s", grid, name, nickname, error_text)
99
102
  return grid, name, nickname, error_text
100
103
 
@@ -166,12 +169,20 @@ class QRZlookup:
166
169
  )
167
170
 
168
171
  logger.info("\n\n%s\n\n", root)
169
- logger.info(
170
- "key:%s error:%s message:%s",
171
- self.session,
172
- self.error,
173
- self.message,
174
- )
172
+ if self.error:
173
+ logger.critical(
174
+ "key:%s error:%s message:%s",
175
+ self.session,
176
+ self.error,
177
+ self.message,
178
+ )
179
+ else:
180
+ logger.info(
181
+ "key:%s error:%s message:%s",
182
+ self.session,
183
+ self.error,
184
+ self.message,
185
+ )
175
186
  except requests.exceptions.RequestException as exception:
176
187
  logger.info("%s", exception)
177
188
  self.session = False
@@ -209,7 +220,7 @@ class QRZlookup:
209
220
  )
210
221
  baseroot = xmltodict.parse(query_result.text)
211
222
  root = baseroot.get("QRZDatabase", {})
212
- return root.get("Callsign")
223
+ return root.get("Callsign", {})
213
224
 
214
225
 
215
226
  class HamQTH:
@@ -338,22 +338,23 @@ def gen_adif(self, cabrillo_name: str, contest_id=""):
338
338
  self.show_message_box(f"Error saving ADIF file: {error}")
339
339
 
340
340
 
341
- def get_station_arrlsection_code(self):
342
- # get the station ARRL Section in station settings
343
- query = f"SELECT ARRLSection as arrlsection from Station;"
344
- # run query
345
- result = self.database.exec_sql(query)
346
- if result:
347
- arrlsection = result.get("arrlsection", "")
348
- return arrlsection
349
- return ""
341
+ # def get_station_arrlsection_code(self):
342
+ # # get the station ARRL Section in station settings
343
+ # query = f"SELECT ARRLSection as arrlsection from Station;"
344
+ # # run query
345
+ # result = self.database.exec_sql(query)
346
+ # if result:
347
+ # arrlsection = result.get("arrlsection", "")
348
+ # return arrlsection
349
+ # return ""
350
350
 
351
- def get_station_state_code(self):
352
- # get the station state code in station settings
353
- query = f"SELECT state as state from Station;"
354
- # run query
355
- result = self.database.exec_sql(query)
356
- if result:
357
- state = result.get("state", "")
358
- return state
359
- return ""
351
+
352
+ # def get_station_state_code(self):
353
+ # # get the station state code in station settings
354
+ # query = f"SELECT state as state from Station;"
355
+ # # run query
356
+ # result = self.database.exec_sql(query)
357
+ # if result:
358
+ # state = result.get("state", "")
359
+ # return state
360
+ # return ""
not1mm/lib/version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """It's the version"""
2
2
 
3
- __version__ = "25.6.16.1"
3
+ __version__ = "25.6.18.1"
not1mm/lookupservice.py CHANGED
@@ -40,14 +40,14 @@ class LookupService(QDockWidget):
40
40
 
41
41
  if self.settings.get("useqrz"):
42
42
  self.look_up = QRZlookup(
43
- self.settings.get("lookupusername"),
44
- self.settings.get("lookuppassword"),
43
+ self.settings.get("lookupusername", ""),
44
+ self.settings.get("lookuppassword", ""),
45
45
  )
46
46
 
47
47
  if self.settings.get("usehamqth"):
48
48
  self.look_up = HamQTH(
49
- self.settings.get("lookupusername"),
50
- self.settings.get("lookuppassword"),
49
+ self.settings.get("lookupusername", ""),
50
+ self.settings.get("lookuppassword", ""),
51
51
  )
52
52
 
53
53
  def get_settings(self) -> dict:
@@ -55,6 +55,7 @@ class LookupService(QDockWidget):
55
55
  if os.path.exists(fsutils.CONFIG_FILE):
56
56
  with open(fsutils.CONFIG_FILE, "rt", encoding="utf-8") as file_descriptor:
57
57
  return loads(file_descriptor.read())
58
+ return {}
58
59
 
59
60
  def msg_from_main(self, packet):
60
61
  """"""
@@ -74,12 +75,12 @@ class LookupService(QDockWidget):
74
75
  self.look_up = None
75
76
  if self.settings.get("useqrz"):
76
77
  self.look_up = QRZlookup(
77
- self.settings.get("lookupusername"),
78
- self.settings.get("lookuppassword"),
78
+ self.settings.get("lookupusername", ""),
79
+ self.settings.get("lookuppassword", ""),
79
80
  )
80
81
 
81
82
  if self.settings.get("usehamqth"):
82
83
  self.look_up = HamQTH(
83
- self.settings.get("lookupusername"),
84
- self.settings.get("lookuppassword"),
84
+ self.settings.get("lookupusername", ""),
85
+ self.settings.get("lookuppassword", ""),
85
86
  )
@@ -10,9 +10,11 @@ from pathlib import Path
10
10
 
11
11
  from PyQt6 import QtWidgets
12
12
 
13
- from not1mm.lib.plugin_common import gen_adif, get_points, get_station_state_code, get_station_arrlsection_code
13
+ from not1mm.lib.plugin_common import (
14
+ gen_adif,
15
+ get_points,
16
+ )
14
17
 
15
- from not1mm.lib.ham_utility import calculate_wpx_prefix
16
18
  from not1mm.lib.version import __version__
17
19
 
18
20
  logger = logging.getLogger(__name__)
@@ -56,9 +58,10 @@ estonian_regions = [
56
58
  "TL",
57
59
  "VC",
58
60
  "VO",
59
- "VP"
61
+ "VP",
60
62
  ]
61
63
 
64
+
62
65
  def specific_contest_check_dupe(self, call):
63
66
  """"""
64
67
  # get mode from radio state
@@ -85,7 +88,7 @@ def specific_contest_check_dupe(self, call):
85
88
  time_period_1 = time_periods[0] if len(time_periods) > 0 else None
86
89
  time_period_2 = time_periods[1] if len(time_periods) > 1 else None
87
90
  time_period_3 = time_periods[2] if len(time_periods) > 2 else None
88
-
91
+
89
92
  # get current time in UTC
90
93
  iso_current_time = datetime.now(timezone.utc)
91
94
  current_time = iso_current_time.replace(tzinfo=None)
@@ -93,7 +96,11 @@ def specific_contest_check_dupe(self, call):
93
96
  result = {}
94
97
  result["isdupe"] = False
95
98
 
96
- if current_time < time_period_1 and current_time >= start_date_init_date:
99
+ if (
100
+ time_period_1 is not None
101
+ and current_time < time_period_1
102
+ and current_time >= start_date_init_date
103
+ ):
97
104
 
98
105
  result = self.database.check_dupe_on_period_mode(
99
106
  call,
@@ -103,7 +110,12 @@ def specific_contest_check_dupe(self, call):
103
110
  time_period_1.strftime("%Y-%m-%d %H:%M:%S"),
104
111
  )
105
112
 
106
- if current_time < time_period_2 and current_time >= time_period_1:
113
+ if (
114
+ time_period_1 is not None
115
+ and time_period_2 is not None
116
+ and current_time < time_period_2
117
+ and current_time >= time_period_1
118
+ ):
107
119
 
108
120
  result = self.database.check_dupe_on_period_mode(
109
121
  call,
@@ -113,7 +125,12 @@ def specific_contest_check_dupe(self, call):
113
125
  time_period_2.strftime("%Y-%m-%d %H:%M:%S"),
114
126
  )
115
127
 
116
- if current_time < time_period_3 and current_time >= time_period_2:
128
+ if (
129
+ time_period_2 is not None
130
+ and time_period_3 is not None
131
+ and current_time < time_period_3
132
+ and current_time >= time_period_2
133
+ ):
117
134
 
118
135
  result = self.database.check_dupe_on_period_mode(
119
136
  call,
@@ -131,6 +148,7 @@ def specific_contest_check_dupe(self, call):
131
148
 
132
149
  return result
133
150
 
151
+
134
152
  def init_contest(self):
135
153
  """setup plugin"""
136
154
  set_tab_next(self)
@@ -195,13 +213,13 @@ def predupe(self):
195
213
 
196
214
  def prefill(self):
197
215
  """Fill SentNR"""
198
-
216
+
199
217
  sent_sxchange_setting = self.contest_settings.get("SentExchange", "")
200
218
  if sent_sxchange_setting.strip() == "#":
201
219
  result = self.database.get_serial()
202
220
  serial_nr = str(result.get("serial_nr", "1")).zfill(3)
203
221
  # get station region code from setup ARRLSection field
204
- serial_nr = serial_nr + " " + get_station_state_code(self)
222
+ serial_nr = serial_nr + " " + self.station.get("State", "")
205
223
 
206
224
  if serial_nr == "None":
207
225
  serial_nr = "001"
@@ -228,15 +246,17 @@ def points(self):
228
246
  else:
229
247
  return 1
230
248
 
249
+
231
250
  def show_mults(self, rtc=None):
232
251
  """Return display string for mults"""
233
252
 
234
253
  # implement here multipliers checks
235
254
  # get received number and region code
236
255
 
237
- call_result = str(self.contact.get("NR", ""))
256
+ # call_result never used, so commenting it out.
257
+ # call_result = str(self.contact.get("NR", ""))
238
258
  # create placeholders
239
- placeholders = ','.join(['?'] * len(estonian_regions))
259
+ placeholders = ",".join(["?"] * len(estonian_regions))
240
260
  # main query to filter by regions
241
261
  query = f"SELECT count(distinct(SUBSTR(NR, -2)) || ':' || Band || ':' || Mode) as mults from DXLOG where ContestNR = {self.pref.get('contest', '1')} AND CountryPrefix = 'ES' AND NR GLOB '*[A-Z]*' AND substr(NR,-2) IN ({placeholders});"
242
262
  # apply params
@@ -248,6 +268,7 @@ def show_mults(self, rtc=None):
248
268
  return mult_count
249
269
  return 0
250
270
 
271
+
251
272
  def show_qso(self):
252
273
  """Return qso count"""
253
274
  result = self.database.fetch_qso_count()
@@ -592,13 +613,13 @@ def process_esm(self, new_focused_widget=None, with_enter=False):
592
613
  self.process_function_key(button)
593
614
 
594
615
 
595
- def get_mults(self):
596
- """Get mults for RTC XML"""
597
- mults = {}
598
- mults["country"], mults["state"] = show_mults(self, rtc=True)
599
- return mults
616
+ # def get_mults(self):
617
+ # """Get mults for RTC XML"""
618
+ # mults = {}
619
+ # mults["country"], mults["state"] = show_mults(self, rtc=True)
620
+ # return mults
600
621
 
601
622
 
602
- def just_points(self):
603
- """Get points for RTC XML"""
604
- return get_points(self)
623
+ # def just_points(self):
624
+ # """Get points for RTC XML"""
625
+ # return get_points(self)
@@ -0,0 +1,651 @@
1
+ """ """
2
+
3
+ import logging
4
+ import platform
5
+ import datetime
6
+
7
+
8
+ from pathlib import Path
9
+
10
+ from PyQt6 import QtWidgets
11
+
12
+ from not1mm.lib.plugin_common import gen_adif, get_points
13
+
14
+ from not1mm.lib.ham_utility import calculate_wpx_prefix
15
+ from not1mm.lib.version import __version__
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+ EXCHANGE_HINT = "#"
20
+
21
+
22
+ name = "ES MANUAL KEY"
23
+ cabrillo_name = "ES-MANUAL-KEY"
24
+ mode = "CW" # CW SSB BOTH RTTY
25
+
26
+ columns = [
27
+ "YYYY-MM-DD HH:MM:SS",
28
+ "Call",
29
+ "Freq",
30
+ "Mode",
31
+ "Snt",
32
+ "Rcv",
33
+ "SentNr",
34
+ "RcvNr",
35
+ "PTS",
36
+ ]
37
+
38
+ advance_on_space = [True, True, True, True, True]
39
+
40
+ # 5 Contest specific dupe check.
41
+ dupe_type = 5
42
+
43
+
44
+ def specific_contest_check_dupe(self, call):
45
+ """"""
46
+ # get mode from radio state
47
+ mode = self.radio_state.get("mode", "")
48
+ """Dupe checking specific to just this contest."""
49
+ # constant to split the contest - correct ES Open Contest length is 4 hours
50
+ contest_length_in_minutes = 45
51
+ split_contest_by_minutes = 15
52
+
53
+ period_count = int(contest_length_in_minutes / split_contest_by_minutes)
54
+
55
+ # think about generic solution by splitting the contest to n different periods
56
+ start_date_init = self.contest_settings.get("StartDate", "")
57
+ start_date_init_date = datetime.datetime.strptime(
58
+ start_date_init, "%Y-%m-%d %H:%M:%S"
59
+ )
60
+
61
+ # Create time periods dynamically based on period count
62
+ time_periods = []
63
+ for i in range(period_count):
64
+ minutes_to_add = split_contest_by_minutes * (i + 1)
65
+ time_period = start_date_init_date + datetime.timedelta(minutes=minutes_to_add)
66
+ time_periods.append(time_period)
67
+
68
+ # Assign to variables for backwards compatibility
69
+ time_period_1 = time_periods[0] if len(time_periods) > 0 else None
70
+ time_period_2 = time_periods[1] if len(time_periods) > 1 else None
71
+ time_period_3 = time_periods[2] if len(time_periods) > 2 else None
72
+
73
+ # get current time in UTC
74
+ iso_current_time = datetime.datetime.now(datetime.timezone.utc)
75
+ current_time = iso_current_time.replace(tzinfo=None)
76
+
77
+ result = {}
78
+ result["isdupe"] = False
79
+
80
+ if (
81
+ time_period_1 is not None
82
+ and current_time < time_period_1
83
+ and current_time >= start_date_init_date
84
+ ):
85
+
86
+ result = self.database.check_dupe_on_period_mode(
87
+ call,
88
+ self.contact.get("Band", ""),
89
+ mode,
90
+ start_date_init_date,
91
+ time_period_1.strftime("%Y-%m-%d %H:%M:%S"),
92
+ )
93
+
94
+ if (
95
+ time_period_2 is not None
96
+ and time_period_1 is not None
97
+ and current_time < time_period_2
98
+ and current_time >= time_period_1
99
+ ):
100
+
101
+ result = self.database.check_dupe_on_period_mode(
102
+ call,
103
+ self.contact.get("Band", ""),
104
+ mode,
105
+ time_period_1.strftime("%Y-%m-%d %H:%M:%S"),
106
+ time_period_2.strftime("%Y-%m-%d %H:%M:%S"),
107
+ )
108
+
109
+ if (
110
+ time_period_3 is not None
111
+ and time_period_2 is not None
112
+ and current_time < time_period_3
113
+ and current_time >= time_period_2
114
+ ):
115
+
116
+ result = self.database.check_dupe_on_period_mode(
117
+ call,
118
+ self.contact.get("Band", ""),
119
+ mode,
120
+ time_period_2.strftime("%Y-%m-%d %H:%M:%S"),
121
+ time_period_3.strftime("%Y-%m-%d %H:%M:%S"),
122
+ )
123
+
124
+ # just for band and mode if outside of time period
125
+ else:
126
+ result = self.database.check_dupe_on_band_mode(
127
+ call, self.contact.get("Band", ""), mode
128
+ )
129
+
130
+ return result
131
+
132
+
133
+ def init_contest(self):
134
+ """setup plugin"""
135
+ set_tab_next(self)
136
+ set_tab_prev(self)
137
+ interface(self)
138
+ self.next_field = self.other_2
139
+
140
+
141
+ def interface(self):
142
+ """Setup user interface"""
143
+ self.field1.show()
144
+ self.field2.show()
145
+ self.field3.show()
146
+ self.field4.show()
147
+ self.other_label.setText("Sent")
148
+ self.field3.setAccessibleName("Sent")
149
+ self.exch_label.setText("SN")
150
+ self.field4.setAccessibleName("SN")
151
+
152
+
153
+ def reset_label(self):
154
+ """reset label after field cleared"""
155
+
156
+
157
+ def set_tab_next(self):
158
+ """Set TAB Advances"""
159
+ self.tab_next = {
160
+ self.callsign: self.other_1,
161
+ self.sent: self.other_1,
162
+ self.receive: self.other_1,
163
+ self.other_1: self.other_2,
164
+ self.other_2: self.callsign,
165
+ }
166
+
167
+
168
+ def set_tab_prev(self):
169
+ """Set TAB Advances"""
170
+ self.tab_prev = {
171
+ self.callsign: self.other_2,
172
+ self.sent: self.callsign,
173
+ self.receive: self.callsign,
174
+ self.other_1: self.callsign,
175
+ self.other_2: self.other_1,
176
+ }
177
+
178
+
179
+ def set_contact_vars(self):
180
+ """Contest Specific"""
181
+ self.contact["SNT"] = self.sent.text()
182
+ self.contact["RCV"] = self.receive.text()
183
+ self.contact["SentNr"] = self.other_1.text().upper()
184
+ self.contact["NR"] = self.other_2.text().upper()
185
+
186
+ self.contact["IsMultiplier1"] = 0
187
+ self.contact["IsMultiplier2"] = 0
188
+
189
+
190
+ def predupe(self):
191
+ """called after callsign entered"""
192
+
193
+
194
+ def prefill(self):
195
+ """Fill SentNR"""
196
+ sent_sxchange_setting = self.contest_settings.get("SentExchange", "")
197
+ if sent_sxchange_setting.strip() == "#":
198
+ result = self.database.get_serial()
199
+ serial_nr = str(result.get("serial_nr", "1"))
200
+ serial_nr_last3 = serial_nr[-3:].zfill(3)
201
+ if serial_nr_last3 == "None":
202
+ serial_nr_last3 = "001"
203
+ # get station license class from setup LicenseClass field - use it for seniority
204
+ # how many years from the first QSO using club station or individual station
205
+
206
+ # The LicenseClass should already be available in the self.station object
207
+ # serial_nr = get_station_license_class(self) + serial_nr_last3
208
+ serial_nr = self.station.get("LicenseClass", "") + serial_nr_last3
209
+
210
+ if len(self.other_1.text()) == 0:
211
+ self.other_1.setText(serial_nr)
212
+ else:
213
+ self.other_1.setText(sent_sxchange_setting)
214
+
215
+
216
+ # Points are awarded for each communication/qso according to the correspondent's broadcasting
217
+ # experience/seniority
218
+ # (i.e. the first two numbers of the received report).
219
+ # To obtain the total number of points, the experience/seniority points for all communications/qsos
220
+ # (including repeated communications) are added together,
221
+ # to which the competitor's own experience/seniority points
222
+ # for each period worked are added, i.e. 3 times.
223
+ # To motivate competitors with less experience, operators with up to 10 years of experience
224
+ # (inclusive) are awarded an additional 20 points for each communication/qso,
225
+ # and for operators with an experience range of 11-20 years, an additional 10 points.
226
+ # The competitor must also add the same points 3 times to his/her total to obtain the final result.
227
+
228
+
229
+ def points(self):
230
+ """ """
231
+ if self.contact_is_dupe > 0:
232
+ return 0
233
+
234
+ _mode = self.contact.get("Mode", "")
235
+
236
+ if _mode in "CW":
237
+
238
+ call_result = str(self.contact.get("NR", "")).strip()
239
+
240
+ # get call seniority
241
+ try:
242
+ seniority = int(call_result[:2])
243
+ except ValueError:
244
+ seniority = 0
245
+
246
+ # get call age (this is not used, so commenting out)
247
+ # age = call_result[2:4]
248
+
249
+ # get call serial number (this is not used, so commenting out)
250
+ # call_serial_nr = call_result[4:6]
251
+
252
+ if seniority < 10:
253
+ points = seniority + 20
254
+ elif seniority > 10 and seniority <= 20:
255
+ points = seniority + 10
256
+ else:
257
+ points = seniority
258
+ return points
259
+
260
+ return 0
261
+
262
+
263
+ def show_mults(self, rtc=None):
264
+ """Return display string for mults"""
265
+ our_prefix = calculate_wpx_prefix(self.station.get("Call", ""))
266
+ query = f"SELECT count(DISTINCT(substr(WPXPrefix,3,1) || ':' || Band || ':' || Mode)) as mults from DXLOG where ContestNR = {self.pref.get('contest', '1')} AND CountryPrefix = 'ES' AND WPXPrefix != '{our_prefix}';"
267
+ result = self.database.exec_sql(query)
268
+ if result:
269
+ mult_count = result.get("mults", 0)
270
+ return mult_count
271
+ return 0
272
+
273
+
274
+ def show_qso(self):
275
+ """Return qso count"""
276
+ result = self.database.fetch_qso_count()
277
+ if result:
278
+ return int(result.get("qsos", 0))
279
+ return 0
280
+
281
+
282
+ # Points are awarded for each communication/qso according to the correspondent's broadcasting experience/seniority
283
+ # (i.e. the first two numbers of the received report).
284
+ # To obtain the total number of points, the experience/seniority points for all communications/qsos
285
+ # (including repeated communications) are added together,
286
+ # to which the competitor's own experience/seniority points
287
+ # for each period worked are added, i.e. 3 times.
288
+ # To motivate competitors with less experience, operators with up to 10 years of experience
289
+ # (inclusive) are awarded an additional 20 points for each communication/qso,
290
+ # and for operators with an experience range of 11-20 years, an additional 10 points.
291
+ # The competitor must also add the same points 3 times to his/her total to obtain the final result.
292
+
293
+
294
+ def calc_score(self):
295
+ """Return calculated score"""
296
+ result = self.database.fetch_points()
297
+ if result is not None:
298
+ score = result.get("Points", "0")
299
+ if score is None:
300
+ score = "0"
301
+ contest_points = int(score)
302
+
303
+ # egt station seniority number
304
+ station_seniority = self.station.get("LicenseClass", "")
305
+ # calc station seniority
306
+ try:
307
+ station_seniority_multiplier = 3 * int(station_seniority.strip()[:2])
308
+ except ValueError:
309
+ station_seniority_multiplier = 3
310
+
311
+ # always add 3 times your own seniority to the overall score
312
+ contest_points = contest_points + station_seniority_multiplier
313
+
314
+ mults = show_mults(self)
315
+ return contest_points * (mults + 1)
316
+ return 0
317
+
318
+
319
+ def recalculate_mults(self):
320
+ """Recalculates multipliers after change in logged qso."""
321
+
322
+
323
+ def adif(self):
324
+ """Call the generate ADIF function"""
325
+ gen_adif(self, cabrillo_name, "ES OPEN")
326
+
327
+
328
+ def output_cabrillo_line(line_to_output, ending, file_descriptor, file_encoding):
329
+ """"""
330
+ print(
331
+ line_to_output.encode(file_encoding, errors="ignore").decode(),
332
+ end=ending,
333
+ file=file_descriptor,
334
+ )
335
+
336
+
337
+ def cabrillo(self, file_encoding):
338
+ """Generates Cabrillo file. Maybe."""
339
+ # https://www.cqwpx.com/cabrillo.htm
340
+ logger.debug("******Cabrillo*****")
341
+ logger.debug("Station: %s", f"{self.station}")
342
+ logger.debug("Contest: %s", f"{self.contest_settings}")
343
+ now = datetime.datetime.now()
344
+ date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
345
+ filename = (
346
+ str(Path.home())
347
+ + "/"
348
+ + f"{self.station.get('Call', '').upper()}_{cabrillo_name}_{date_time}.log"
349
+ )
350
+ logger.debug("%s", filename)
351
+ log = self.database.fetch_all_contacts_asc()
352
+ try:
353
+ with open(filename, "w", encoding=file_encoding, newline="") as file_descriptor:
354
+ output_cabrillo_line(
355
+ "START-OF-LOG: 3.0",
356
+ "\r\n",
357
+ file_descriptor,
358
+ file_encoding,
359
+ )
360
+ output_cabrillo_line(
361
+ f"CREATED-BY: Not1MM v{__version__}",
362
+ "\r\n",
363
+ file_descriptor,
364
+ file_encoding,
365
+ )
366
+ output_cabrillo_line(
367
+ f"CONTEST: {cabrillo_name}",
368
+ "\r\n",
369
+ file_descriptor,
370
+ file_encoding,
371
+ )
372
+ if self.station.get("Club", ""):
373
+ output_cabrillo_line(
374
+ f"CLUB: {self.station.get('Club', '').upper()}",
375
+ "\r\n",
376
+ file_descriptor,
377
+ file_encoding,
378
+ )
379
+ output_cabrillo_line(
380
+ f"CALLSIGN: {self.station.get('Call','')}",
381
+ "\r\n",
382
+ file_descriptor,
383
+ file_encoding,
384
+ )
385
+ output_cabrillo_line(
386
+ f"LOCATION: {self.station.get('ARRLSection', '')}",
387
+ "\r\n",
388
+ file_descriptor,
389
+ file_encoding,
390
+ )
391
+ output_cabrillo_line(
392
+ f"CATEGORY-OPERATOR: {self.contest_settings.get('OperatorCategory','')}",
393
+ "\r\n",
394
+ file_descriptor,
395
+ file_encoding,
396
+ )
397
+ output_cabrillo_line(
398
+ f"CATEGORY-ASSISTED: {self.contest_settings.get('AssistedCategory','')}",
399
+ "\r\n",
400
+ file_descriptor,
401
+ file_encoding,
402
+ )
403
+ output_cabrillo_line(
404
+ f"CATEGORY-BAND: {self.contest_settings.get('BandCategory','')}",
405
+ "\r\n",
406
+ file_descriptor,
407
+ file_encoding,
408
+ )
409
+ mode = self.contest_settings.get("ModeCategory", "")
410
+ if mode in ["SSB+CW", "SSB+CW+DIGITAL"]:
411
+ mode = "MIXED"
412
+ output_cabrillo_line(
413
+ f"CATEGORY-MODE: {mode}",
414
+ "\r\n",
415
+ file_descriptor,
416
+ file_encoding,
417
+ )
418
+ output_cabrillo_line(
419
+ f"CATEGORY-TRANSMITTER: {self.contest_settings.get('TransmitterCategory','')}",
420
+ "\r\n",
421
+ file_descriptor,
422
+ file_encoding,
423
+ )
424
+ if self.contest_settings.get("OverlayCategory", "") != "N/A":
425
+ output_cabrillo_line(
426
+ f"CATEGORY-OVERLAY: {self.contest_settings.get('OverlayCategory','')}",
427
+ "\r\n",
428
+ file_descriptor,
429
+ file_encoding,
430
+ )
431
+ output_cabrillo_line(
432
+ f"GRID-LOCATOR: {self.station.get('GridSquare','')}",
433
+ "\r\n",
434
+ file_descriptor,
435
+ file_encoding,
436
+ )
437
+ output_cabrillo_line(
438
+ f"CATEGORY-POWER: {self.contest_settings.get('PowerCategory','')}",
439
+ "\r\n",
440
+ file_descriptor,
441
+ file_encoding,
442
+ )
443
+
444
+ output_cabrillo_line(
445
+ f"CLAIMED-SCORE: {calc_score(self)}",
446
+ "\r\n",
447
+ file_descriptor,
448
+ file_encoding,
449
+ )
450
+ ops = f"@{self.station.get('Call','')}"
451
+ list_of_ops = self.database.get_ops()
452
+ for op in list_of_ops:
453
+ ops += f", {op.get('Operator', '')}"
454
+ output_cabrillo_line(
455
+ f"OPERATORS: {ops}",
456
+ "\r\n",
457
+ file_descriptor,
458
+ file_encoding,
459
+ )
460
+ output_cabrillo_line(
461
+ f"NAME: {self.station.get('Name', '')}",
462
+ "\r\n",
463
+ file_descriptor,
464
+ file_encoding,
465
+ )
466
+ output_cabrillo_line(
467
+ f"ADDRESS: {self.station.get('Street1', '')}",
468
+ "\r\n",
469
+ file_descriptor,
470
+ file_encoding,
471
+ )
472
+ output_cabrillo_line(
473
+ f"ADDRESS-CITY: {self.station.get('City', '')}",
474
+ "\r\n",
475
+ file_descriptor,
476
+ file_encoding,
477
+ )
478
+ output_cabrillo_line(
479
+ f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
480
+ "\r\n",
481
+ file_descriptor,
482
+ file_encoding,
483
+ )
484
+ output_cabrillo_line(
485
+ f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
486
+ "\r\n",
487
+ file_descriptor,
488
+ file_encoding,
489
+ )
490
+ output_cabrillo_line(
491
+ f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
492
+ "\r\n",
493
+ file_descriptor,
494
+ file_encoding,
495
+ )
496
+ output_cabrillo_line(
497
+ f"EMAIL: {self.station.get('Email', '')}",
498
+ "\r\n",
499
+ file_descriptor,
500
+ file_encoding,
501
+ )
502
+ for contact in log:
503
+ the_date_and_time = contact.get("TS", "")
504
+ themode = contact.get("Mode", "")
505
+ if themode == "LSB" or themode == "USB":
506
+ themode = "PH"
507
+ frequency = str(int(contact.get("Freq", "0"))).rjust(5)
508
+
509
+ loggeddate = the_date_and_time[:10]
510
+ loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
511
+ output_cabrillo_line(
512
+ f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
513
+ f"{contact.get('StationPrefix', '').ljust(13)} "
514
+ f"{str(contact.get('SNT', '')).ljust(3)} "
515
+ f"{str(contact.get('SentNr', '')).ljust(6)} "
516
+ f"{contact.get('Call', '').ljust(13)} "
517
+ f"{str(contact.get('RCV', '')).ljust(3)} "
518
+ f"{str(contact.get('NR', '')).ljust(6)}",
519
+ "\r\n",
520
+ file_descriptor,
521
+ file_encoding,
522
+ )
523
+ output_cabrillo_line("END-OF-LOG:", "\r\n", file_descriptor, file_encoding)
524
+ self.show_message_box(f"Cabrillo saved to: {filename}")
525
+ except IOError as exception:
526
+ logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
527
+ self.show_message_box(f"Error saving Cabrillo: {exception} {filename}")
528
+ return
529
+
530
+
531
+ # def populate_history_info_line(self):
532
+ # result = self.database.fetch_call_history(self.callsign.text())
533
+ # if result:
534
+ # self.history_info.setText(
535
+ # f"{result.get('Call', '')}, {result.get('Exch1', '')}, {result.get('UserText','...')}"
536
+ # )
537
+ # else:
538
+ # self.history_info.setText("")
539
+
540
+
541
+ # def check_call_history(self):
542
+ # """"""
543
+ # result = self.database.fetch_call_history(self.callsign.text())
544
+ # print(f"{result=}")
545
+ # if result:
546
+ # self.history_info.setText(f"{result.get('UserText','')}")
547
+ # if self.other_2.text() == "":
548
+ # self.other_2.setText(f"{result.get('Exch1', '')}")
549
+
550
+
551
+ def process_esm(self, new_focused_widget=None, with_enter=False):
552
+ """ESM State Machine"""
553
+
554
+ # self.pref["run_state"]
555
+
556
+ # -----===== Assigned F-Keys =====-----
557
+ # self.esm_dict["CQ"]
558
+ # self.esm_dict["EXCH"]
559
+ # self.esm_dict["QRZ"]
560
+ # self.esm_dict["AGN"]
561
+ # self.esm_dict["HISCALL"]
562
+ # self.esm_dict["MYCALL"]
563
+ # self.esm_dict["QSOB4"]
564
+
565
+ # ----==== text fields ====----
566
+ # self.callsign
567
+ # self.sent
568
+ # self.receive
569
+ # self.other_1
570
+ # self.other_2
571
+
572
+ if new_focused_widget is not None:
573
+ self.current_widget = self.inputs_dict.get(new_focused_widget)
574
+
575
+ # print(f"checking esm {self.current_widget=} {with_enter=} {self.pref.get("run_state")=}")
576
+
577
+ for a_button in [
578
+ self.esm_dict["CQ"],
579
+ self.esm_dict["EXCH"],
580
+ self.esm_dict["QRZ"],
581
+ self.esm_dict["AGN"],
582
+ self.esm_dict["HISCALL"],
583
+ self.esm_dict["MYCALL"],
584
+ self.esm_dict["QSOB4"],
585
+ ]:
586
+ if a_button is not None:
587
+ self.restore_button_color(a_button)
588
+
589
+ buttons_to_send = []
590
+
591
+ if self.pref.get("run_state"):
592
+ if self.current_widget == "callsign":
593
+ if len(self.callsign.text()) < 3:
594
+ self.make_button_green(self.esm_dict["CQ"])
595
+ buttons_to_send.append(self.esm_dict["CQ"])
596
+ elif len(self.callsign.text()) > 2:
597
+ self.make_button_green(self.esm_dict["HISCALL"])
598
+ self.make_button_green(self.esm_dict["EXCH"])
599
+ buttons_to_send.append(self.esm_dict["HISCALL"])
600
+ buttons_to_send.append(self.esm_dict["EXCH"])
601
+
602
+ elif self.current_widget == "other_2":
603
+ if self.other_2.text() == "":
604
+ self.make_button_green(self.esm_dict["AGN"])
605
+ buttons_to_send.append(self.esm_dict["AGN"])
606
+ else:
607
+ self.make_button_green(self.esm_dict["QRZ"])
608
+ buttons_to_send.append(self.esm_dict["QRZ"])
609
+ buttons_to_send.append("LOGIT")
610
+
611
+ if with_enter is True and bool(len(buttons_to_send)):
612
+ for button in buttons_to_send:
613
+ if button:
614
+ if button == "LOGIT":
615
+ self.save_contact()
616
+ continue
617
+ self.process_function_key(button)
618
+ else:
619
+ if self.current_widget == "callsign":
620
+ if len(self.callsign.text()) > 2:
621
+ self.make_button_green(self.esm_dict["MYCALL"])
622
+ buttons_to_send.append(self.esm_dict["MYCALL"])
623
+
624
+ elif self.current_widget == "other_2":
625
+ if self.other_2.text() == "":
626
+ self.make_button_green(self.esm_dict["AGN"])
627
+ buttons_to_send.append(self.esm_dict["AGN"])
628
+ else:
629
+ self.make_button_green(self.esm_dict["EXCH"])
630
+ buttons_to_send.append(self.esm_dict["EXCH"])
631
+ buttons_to_send.append("LOGIT")
632
+
633
+ if with_enter is True and bool(len(buttons_to_send)):
634
+ for button in buttons_to_send:
635
+ if button:
636
+ if button == "LOGIT":
637
+ self.save_contact()
638
+ continue
639
+ self.process_function_key(button)
640
+
641
+
642
+ # def get_mults(self):
643
+ # """Get mults for RTC XML"""
644
+ # mults = {}
645
+ # mults["country"], mults["state"] = show_mults(self, rtc=True)
646
+ # return mults
647
+
648
+
649
+ # def just_points(self):
650
+ # """Get points for RTC XML"""
651
+ # return get_points(self)
not1mm/plugins/es_open.py CHANGED
@@ -78,7 +78,11 @@ def specific_contest_check_dupe(self, call):
78
78
  result = {}
79
79
  result["isdupe"] = False
80
80
 
81
- if current_time < time_period_1 and current_time >= start_date_init_date:
81
+ if (
82
+ time_period_1 is not None
83
+ and current_time < time_period_1
84
+ and current_time >= start_date_init_date
85
+ ):
82
86
 
83
87
  result = self.database.check_dupe_on_period_mode(
84
88
  call,
@@ -88,7 +92,12 @@ def specific_contest_check_dupe(self, call):
88
92
  time_period_1.strftime("%Y-%m-%d %H:%M:%S"),
89
93
  )
90
94
 
91
- if current_time < time_period_2 and current_time >= time_period_1:
95
+ if (
96
+ time_period_1 is not None
97
+ and time_period_2 is not None
98
+ and current_time < time_period_2
99
+ and current_time >= time_period_1
100
+ ):
92
101
 
93
102
  result = self.database.check_dupe_on_period_mode(
94
103
  call,
@@ -98,7 +107,12 @@ def specific_contest_check_dupe(self, call):
98
107
  time_period_2.strftime("%Y-%m-%d %H:%M:%S"),
99
108
  )
100
109
 
101
- if current_time < time_period_3 and current_time >= time_period_2:
110
+ if (
111
+ time_period_2 is not None
112
+ and time_period_3 is not None
113
+ and current_time < time_period_3
114
+ and current_time >= time_period_2
115
+ ):
102
116
 
103
117
  result = self.database.check_dupe_on_period_mode(
104
118
  call,
@@ -108,7 +122,12 @@ def specific_contest_check_dupe(self, call):
108
122
  time_period_3.strftime("%Y-%m-%d %H:%M:%S"),
109
123
  )
110
124
 
111
- if current_time < time_period_4 and current_time >= time_period_3:
125
+ if (
126
+ time_period_3 is not None
127
+ and time_period_4 is not None
128
+ and current_time < time_period_4
129
+ and current_time >= time_period_3
130
+ ):
112
131
 
113
132
  result = self.database.check_dupe_on_period_mode(
114
133
  call,
@@ -125,6 +144,7 @@ def specific_contest_check_dupe(self, call):
125
144
 
126
145
  return result
127
146
 
147
+
128
148
  def init_contest(self):
129
149
  """setup plugin"""
130
150
  set_tab_next(self)
@@ -270,7 +290,7 @@ def cabrillo(self, file_encoding):
270
290
  logger.debug("******Cabrillo*****")
271
291
  logger.debug("Station: %s", f"{self.station}")
272
292
  logger.debug("Contest: %s", f"{self.contest_settings}")
273
- now = datetime.datetime.now()
293
+ now = datetime.now()
274
294
  date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
275
295
  filename = (
276
296
  str(Path.home())
@@ -569,13 +589,13 @@ def process_esm(self, new_focused_widget=None, with_enter=False):
569
589
  self.process_function_key(button)
570
590
 
571
591
 
572
- def get_mults(self):
573
- """Get mults for RTC XML"""
574
- mults = {}
575
- mults["country"], mults["state"] = show_mults(self, rtc=True)
576
- return mults
592
+ # def get_mults(self):
593
+ # """Get mults for RTC XML"""
594
+ # mults = {}
595
+ # mults["country"], mults["state"] = show_mults(self, rtc=True)
596
+ # return mults
577
597
 
578
598
 
579
- def just_points(self):
580
- """Get points for RTC XML"""
581
- return get_points(self)
599
+ # def just_points(self):
600
+ # """Get points for RTC XML"""
601
+ # return get_points(self)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: not1mm
3
- Version: 25.6.16.1
3
+ Version: 25.6.18.1
4
4
  Summary: NOT1MM Logger
5
5
  Author-email: Michael Bridak <michael.bridak@gmail.com>
6
6
  License: GPL-3.0-or-later
@@ -246,6 +246,7 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
246
246
 
247
247
  ## Recent Changes
248
248
 
249
+ - [25-6-18] Merged changes from @term73, Adding ES Manual Key contest.
249
250
  - [25-6-16] Merged PR from @awandahl SM0HPL, adding ESM buttons to General DX Logging plugin.
250
251
  - [25-6-15] Corrected tab focus of rotator windows buttons.
251
252
  - [25-6-13] Polished up the Rotator window. Adding Stop and Park. Made the NSWE buttons smaller.
@@ -1,11 +1,11 @@
1
1
  not1mm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- not1mm/__main__.py,sha256=SgbLlUVWGbXy00ThKA_61ApJobDaazLfGabsfo3Mpkg,174828
2
+ not1mm/__main__.py,sha256=x-MFQjObG-GRtx3OrTLvdqUtj6qCQhGfw69myPdWZVU,174830
3
3
  not1mm/bandmap.py,sha256=PpoZIuJ8dTj9erW0xYqbyneZrSQ-CEqbpek5jTlc6PQ,31173
4
4
  not1mm/checkwindow.py,sha256=zEHlw40j6Wr3rvKbCQf2lcezCoiZqaBqEvBjQU5aKW0,7630
5
5
  not1mm/dxcc_tracker.py,sha256=px1m6wcFv-ZDBDKyqSa0IcgAfE9GmQ5mptJHBbnWTcA,4379
6
6
  not1mm/fsutils.py,sha256=ukHKxKTeNKxKwqRaJjtzRShL4X5Xl0jRBbADyy3Ifp8,1701
7
7
  not1mm/logwindow.py,sha256=O2dMaT_BYWsXA_dxsEHN92JwN-qVGy9nmH0MCMaG9gY,42830
8
- not1mm/lookupservice.py,sha256=GkY_qHZfrW6XHf8upIoaG4hCFqm0fg6Ganu9ConGrIc,2628
8
+ not1mm/lookupservice.py,sha256=WyLp1m4XPxK0Nk7FH8IKA8jjAs25UcEMrwpCsHmW1fY,2678
9
9
  not1mm/radio.py,sha256=4Lysf9BY3vdtYCHwKfzO5WN7IGyh4_lKSVuQ6F4Z08g,5536
10
10
  not1mm/ratewindow.py,sha256=iBjqdOetIEX0wSwdGM89Ibt4gVlFdE-K8HQPnkVPVOg,6965
11
11
  not1mm/rotator.py,sha256=jrAqO3IkeuZcOgsYFKvEv6DY2ccV85wg0o5sdJa_EUo,12760
@@ -40,7 +40,7 @@ not1mm/data/logwindow.ui,sha256=vfkNdzJgFs3tTOBKLDavF2zVMvNHWOZ82fAErRi6pQY,1436
40
40
  not1mm/data/logwindowx.ui,sha256=9FzDJtLRpagvAWcDjFdB9NnvNZ4bVxdTNHy1Jit2ido,1610
41
41
  not1mm/data/main.ui,sha256=2cGrhepmcTylTWJ2LwisW6q9nZsReOH38yThvUn_31g,65717
42
42
  not1mm/data/map3.png,sha256=EJqHeFp0ys6Vb1oKkjL4m0v8i3uWXtIgRrxzi0ETUHM,40704
43
- not1mm/data/new_contest.ui,sha256=i-WThxa9IBstyAMCRtNMB4NVPpV3fekUIX1YDYPyuOQ,25521
43
+ not1mm/data/new_contest.ui,sha256=dobgydE_RBaQ2YGJ_8FGR8NHYteztOsLmdwq4Wfm1HQ,25631
44
44
  not1mm/data/not1mm.html,sha256=c9-mfjMwDt4f5pySUruz2gREW33CQ2_rCddM2z5CZQo,23273
45
45
  not1mm/data/opon.ui,sha256=mC4OhoVIfR1H9IqHAKXliPMm8VOVmxSEadpsFQ7XnS4,2247
46
46
  not1mm/data/pickcontest.ui,sha256=Pbb_YEOzQfacyhIRkx-M3ZGugIIPL1KPztdwVv5c_q0,1696
@@ -117,16 +117,16 @@ not1mm/lib/edit_station.py,sha256=hUpqNgboNqhpFzHzjQI0FI8GId6muECRsaXaphN02kQ,19
117
117
  not1mm/lib/fldigi_sendstring.py,sha256=EeXSBRKgyUEzNyHBjMtHiFe-iOU3TcWcCCX77t0ur_I,602
118
118
  not1mm/lib/ft8_watcher.py,sha256=BFmVIsnbwuRMWoe-dIBybuCgi0WFmr8Km0O9l4eiwMM,4624
119
119
  not1mm/lib/ham_utility.py,sha256=7vsnk_nPAOHoP5XhMCDX6ll0F8Sm9XOI-DFMjB80ZFI,12105
120
- not1mm/lib/lookup.py,sha256=KECMDi9tflRDzgTLeDfDl7HGWWRHvW3HCjNHyyjoWaY,10835
120
+ not1mm/lib/lookup.py,sha256=k-BctngA0QEvMo5cPDB9UkUnQvIk69LnJ8bJek2So4U,11326
121
121
  not1mm/lib/multicast.py,sha256=KJcruI-bOuHfHXPjl3SGQhL6I9sKrygy-sdFSvxffUM,3255
122
122
  not1mm/lib/n1mm.py,sha256=H54mpgJF0GAmKavM-nb5OAq2SJFWYkux4eMWWiSRxJc,6288
123
123
  not1mm/lib/new_contest.py,sha256=IznTDMq7yXHB6zBoGUEC_WDYPCPpsSZW4wwMJi16zK0,816
124
- not1mm/lib/plugin_common.py,sha256=nqiUq11T9Wz8RDrRen4Zvp-KXVWUYcIp5JPZwqmu2Oo,13913
124
+ not1mm/lib/plugin_common.py,sha256=4M5CqBXPVvqiakmCEV_SvcRHAZrlwYgGRZwfxAw2e9U,13951
125
125
  not1mm/lib/rot_interface.py,sha256=bOyxpV9pQHORUY5qfNZE2QAV1V71QEG2jooiI2p9AwE,3744
126
126
  not1mm/lib/select_contest.py,sha256=WsptLuwkouIHeocJL3oZ6-eUfEnhpwdc-x7eMZ_TIVM,359
127
127
  not1mm/lib/settings.py,sha256=5xnsagH48qGeCDhfxPWW9yaXtv8wT13yoIVvYt8h_Qs,16023
128
128
  not1mm/lib/super_check_partial.py,sha256=jX7DjHesEV4KNVQbddJui0wAsYHerikH7W0iPv7PXQw,3110
129
- not1mm/lib/version.py,sha256=BXK9rv-j6m1DJFcBBrHMRMEUyr4cZvhrOSpryaAtg4w,50
129
+ not1mm/lib/version.py,sha256=6vtRvmqFiXcSqD6LJaNhFmapnntAFFNtZCCGJh245_I,50
130
130
  not1mm/lib/versiontest.py,sha256=8vDNptuBBunn-1IGkjNaquehqBYUJyjrPSF8Igmd4_Y,1286
131
131
  not1mm/plugins/10_10_fall_cw.py,sha256=oJh3JKqjOpnWElSlZpiQ631UnaOd8qra5s9bl_QoInk,14783
132
132
  not1mm/plugins/10_10_spring_cw.py,sha256=p7dSDtbFK0e6Xouw2V6swYn3VFVgHKyx4IfRWyBjMZY,14786
@@ -161,8 +161,9 @@ not1mm/plugins/darc_xmas.py,sha256=p5UNYLdtylsC_sSlxT8NvXXL1oSW0KyUhIN-rJonHgI,1
161
161
  not1mm/plugins/ea_majistad_cw.py,sha256=O-GLcW0tMAesw7Ow01M3i6MirbGFXwTcwrY7xJdCYDA,23382
162
162
  not1mm/plugins/ea_majistad_ssb.py,sha256=kZoFknVkslHAEjvleV8shsJEwk12Q3aU6qcmBXzVojo,22976
163
163
  not1mm/plugins/ea_rtty.py,sha256=r6c85eyGHbx_ZLBIqKI96vIMqCGH0KCZq2pd-GQt_Dg,23259
164
- not1mm/plugins/es_field_day.py,sha256=neBPerH9TSnVhBFB0bCXVfjBBAYwlDZgcZjqFbmGvNE,19166
165
- not1mm/plugins/es_open.py,sha256=xFp7fdMMdEZyey99Qws5gd7S5HRiF_gAk7qz4AyWneE,18719
164
+ not1mm/plugins/es_field_day.py,sha256=SMzkLHRbFqUM3VZ5-8KxqOcakSqlusGnLUhtZ4FXrww,19403
165
+ not1mm/plugins/es_manual_key.py,sha256=pnc5Wm5xb10ue5rFfBQ4-YDRd-dSnYJ_-aecLxYVobI,21639
166
+ not1mm/plugins/es_open.py,sha256=SkvweNe0nNoeUFODkC2bwyQMRSm-bK7pidk-6H5C6iY,19089
166
167
  not1mm/plugins/general_logging.py,sha256=qon9snE369TC0DUQYH7dezENQ-vl7BH0j3w_Cb0LyU0,8796
167
168
  not1mm/plugins/helvetia.py,sha256=nvgFjCq-_5XF0cLiCVFFwAS8NtIIFPDptr8eLsoprGE,20082
168
169
  not1mm/plugins/iaru_fieldday_r1_cw.py,sha256=1AVyZFi3ri2zqaNJY181Wtyz74fai8QLoi7PoyXpfaY,17218
@@ -190,9 +191,9 @@ not1mm/plugins/ukeidx.py,sha256=ZsIFXgOSwjuKNmN4W_C0TAgGqgnabJGNLMHwGkl3_bk,1910
190
191
  not1mm/plugins/vhf_sprint.py,sha256=a9QFTpv8XUbZ_GLjdVCh7svykFa-gXOWwKFZ6MD3uQM,19289
191
192
  not1mm/plugins/weekly_rtty.py,sha256=C8Xs3Q5UgSYx-mFFar8BVARWtmqlyrbeC98Ubzb4UN8,20128
192
193
  not1mm/plugins/winter_field_day.py,sha256=hmAMgkdqIXtnCNyUp8J9Bb8liN8wj10wps6ROuG-Bok,15284
193
- not1mm-25.6.16.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
194
- not1mm-25.6.16.1.dist-info/METADATA,sha256=TbPB3A5sopjzK7eOR4K0wDJO3lZSvBi6K5YCzFIg15A,36874
195
- not1mm-25.6.16.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
196
- not1mm-25.6.16.1.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
197
- not1mm-25.6.16.1.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
198
- not1mm-25.6.16.1.dist-info/RECORD,,
194
+ not1mm-25.6.18.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
195
+ not1mm-25.6.18.1.dist-info/METADATA,sha256=Siv6s5xx3WIWa4SDjncdlmZmDEsKfOt1QuxpBPM-rT4,36945
196
+ not1mm-25.6.18.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
197
+ not1mm-25.6.18.1.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
198
+ not1mm-25.6.18.1.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
199
+ not1mm-25.6.18.1.dist-info/RECORD,,