not1mm 24.10.27.2__py3-none-any.whl → 24.11.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/plugins/raem.py ADDED
@@ -0,0 +1,592 @@
1
+ """Ernst Krenkel Memorial"""
2
+
3
+ # pylint: disable=invalid-name, c-extension-no-member, unused-import
4
+
5
+
6
+ # RAEM Contest
7
+ # Status: Active
8
+ # Geographic Focus: Worldwide
9
+ # Participation: Worldwide
10
+ # Mode: CW
11
+ # Bands: 80, 40, 20, 15, 10m
12
+ # Classes: Single Op All Band (Low/High)
13
+ # Single Op Single Band
14
+ # Multi-Single
15
+ # Max power: HP: >100 watts
16
+ # LP: 100 watts
17
+ # Exchange: Serial No. + latitude (degs only) + hemisphere + longitude (degs only) + hemisphere (see rules)
18
+ # N=North, S=South, W=West, O=East (e.g. 57N 85O)
19
+ # Work stations: Once per band
20
+ # QSO Points: 50 points + 1 point for every degree difference in geo location, both latitude and longitude
21
+ # QSO with Polar station: 100 points additional
22
+ # QSO with RAEM Memorial Station: 300 points additional
23
+ # Multipliers: Polar stations multiply total QSO points by 1.1
24
+ # Score Calculation: Total score = total QSO points
25
+ # E-mail logs to: raem[at]srr[dot]ru
26
+ # Upload log at: http://ua9qcq.com/
27
+ # Mail logs to: (none)
28
+ # Find rules at: https://raem.srr.ru/rules/
29
+ # Cabrillo name: RAEM
30
+
31
+ import datetime
32
+ import logging
33
+
34
+ from pathlib import Path
35
+
36
+ from PyQt6 import QtWidgets
37
+
38
+ from not1mm.lib.plugin_common import gen_adif, get_points
39
+ from not1mm.lib.version import __version__
40
+
41
+ logger = logging.getLogger(__name__)
42
+
43
+ EXCHANGE_HINT = "33N117W"
44
+
45
+ name = "RAEM"
46
+ cabrillo_name = "RAEM"
47
+ mode = "CW" # CW SSB BOTH RTTY
48
+
49
+ columns = [
50
+ "YYYY-MM-DD HH:MM:SS",
51
+ "Call",
52
+ "Freq",
53
+ "SentNr",
54
+ "RcvNr",
55
+ "Exchange1",
56
+ "PTS",
57
+ ]
58
+
59
+ advance_on_space = [True, True, True, True, True]
60
+
61
+ # 1 once per contest, 2 work each band, 3 each band/mode, 4 no dupe checking
62
+ dupe_type = 2
63
+
64
+
65
+ def init_contest(self):
66
+ """setup plugin"""
67
+ set_tab_next(self)
68
+ set_tab_prev(self)
69
+ interface(self)
70
+ self.next_field = self.other_1
71
+
72
+
73
+ def interface(self):
74
+ """Setup user interface"""
75
+ self.field1.show()
76
+ self.field2.hide()
77
+ self.field3.show()
78
+ self.field4.show()
79
+ self.snt_label.setText("Sent S/N")
80
+ self.field1.setAccessibleName("Sent Serial Number")
81
+ self.other_label.setText("Rcv S/N")
82
+ self.field3.setAccessibleName("Serial Number")
83
+ self.exch_label.setText("Exchange")
84
+ self.field4.setAccessibleName("Exchange")
85
+ self.sent.setText("")
86
+
87
+
88
+ def reset_label(self): # pylint: disable=unused-argument
89
+ """reset label after field cleared"""
90
+
91
+
92
+ def set_tab_next(self):
93
+ """Set TAB Advances"""
94
+ self.tab_next = {
95
+ self.callsign: self.field1.findChild(QtWidgets.QLineEdit),
96
+ self.field1.findChild(QtWidgets.QLineEdit): self.field3.findChild(
97
+ QtWidgets.QLineEdit
98
+ ),
99
+ # self.field2.findChild(QtWidgets.QLineEdit): self.field3.findChild(
100
+ # QtWidgets.QLineEdit
101
+ # ),
102
+ self.field3.findChild(QtWidgets.QLineEdit): self.field4.findChild(
103
+ QtWidgets.QLineEdit
104
+ ),
105
+ self.field4.findChild(QtWidgets.QLineEdit): self.callsign,
106
+ }
107
+
108
+
109
+ def set_tab_prev(self):
110
+ """Set TAB Advances"""
111
+ self.tab_prev = {
112
+ self.callsign: self.field4.findChild(QtWidgets.QLineEdit),
113
+ self.field1.findChild(QtWidgets.QLineEdit): self.callsign,
114
+ # self.field2.findChild(QtWidgets.QLineEdit): self.field1.findChild(
115
+ # QtWidgets.QLineEdit
116
+ # ),
117
+ self.field3.findChild(QtWidgets.QLineEdit): self.field1.findChild(
118
+ QtWidgets.QLineEdit
119
+ ),
120
+ self.field4.findChild(QtWidgets.QLineEdit): self.field3.findChild(
121
+ QtWidgets.QLineEdit
122
+ ),
123
+ }
124
+
125
+
126
+ def set_contact_vars(self):
127
+ """Contest Specific"""
128
+ self.contact["SNT"] = "599"
129
+ self.contact["RCV"] = "599"
130
+ self.contact["SentNr"] = self.sent.text()
131
+ self.contact["NR"] = self.other_1.text()
132
+ self.contact["Exchange1"] = self.other_2.text()
133
+
134
+
135
+ def predupe(self): # pylint: disable=unused-argument
136
+ """called after callsign entered"""
137
+
138
+
139
+ def prefill(self):
140
+ """Fill SentNR"""
141
+ field = self.sent
142
+ result = self.database.get_serial()
143
+ serial_nr = str(result.get("serial_nr", "1")).zfill(3)
144
+ if serial_nr == "None":
145
+ serial_nr = "001"
146
+ if len(field.text()) == 0:
147
+ field.setText(serial_nr)
148
+
149
+
150
+ def latlondif(self, exchange1: str):
151
+ """"""
152
+ ourexchange = self.contest_settings.get("SentExchange", None)
153
+ if ourexchange is None:
154
+ return 0, False
155
+ ourexchange = ourexchange.upper()
156
+ if len(exchange1) < 4:
157
+ return 0, False
158
+ exchange1 = exchange1.upper()
159
+
160
+ latindex = None
161
+ ourlat = None
162
+ ourlon = None
163
+ if "N" in ourexchange:
164
+ latindex = ourexchange.index("N")
165
+ lat = ourexchange[:latindex]
166
+ if lat.isnumeric():
167
+ ourlat = int(lat)
168
+ if "S" in ourexchange:
169
+ latindex = ourexchange.index("S")
170
+ lat = ourexchange[:latindex]
171
+ if lat.isnumeric():
172
+ ourlat = int(lat)
173
+ if "W" in ourexchange:
174
+ lon = ourexchange[latindex + 1 : ourexchange.index("W")]
175
+ if lon.isnumeric():
176
+ ourlon = int(lon)
177
+ if "O" in ourexchange:
178
+ lon = ourexchange[latindex + 1 : ourexchange.index("O")]
179
+ if lon.isnumeric():
180
+ ourlon = int(lon)
181
+ if ourlat is None or ourlon is None:
182
+ return 0, False
183
+
184
+ hislat = None
185
+ hislon = None
186
+ if "N" in exchange1:
187
+ latindex = exchange1.index("N")
188
+ lat = exchange1[:latindex]
189
+ if lat.isnumeric():
190
+ hislat = int(lat)
191
+ if "S" in exchange1:
192
+ latindex = exchange1.index("S")
193
+ lat = exchange1[:latindex]
194
+ if lat.isnumeric():
195
+ hislat = int(lat)
196
+ if "W" in exchange1:
197
+ lon = exchange1[latindex + 1 : exchange1.index("W")]
198
+ if lon.isnumeric():
199
+ hislon = int(lon)
200
+ if "O" in exchange1:
201
+ lon = exchange1[latindex + 1 : exchange1.index("O")]
202
+ if lon.isnumeric():
203
+ hislon = int(lon)
204
+ if hislat is None or hislon is None:
205
+ return 0, False
206
+
207
+ return abs(ourlat - hislat) + abs(ourlon - hislon), hislat >= 66
208
+
209
+
210
+ def points(self):
211
+ """Calc point"""
212
+ # 50 points + 1 point for every degree difference in geo location, both latitude and longitude
213
+ # QSO with Polar station: 100 points additional
214
+ # QSO with RAEM Memorial Station: 300 points additional
215
+
216
+ points = 50
217
+ morepoints, ispolar = latlondif(self, self.other_2.text())
218
+ points += morepoints
219
+ if ispolar is not False:
220
+ points += 100
221
+ if self.callsign.text() == "RAEM":
222
+ points += 300
223
+
224
+ return points
225
+
226
+
227
+ def show_mults(self):
228
+ """Return display string for mults"""
229
+ ourexchange = self.contest_settings.get("SentExchange", None)
230
+ if ourexchange is None:
231
+ return 0, False
232
+ ourexchange = ourexchange.upper()
233
+
234
+ latindex = None
235
+ ourlat = None
236
+ if "N" in ourexchange:
237
+ latindex = ourexchange.index("N")
238
+ lat = ourexchange[:latindex]
239
+ if lat.isnumeric():
240
+ ourlat = int(lat)
241
+ if "S" in ourexchange:
242
+ latindex = ourexchange.index("S")
243
+ lat = ourexchange[:latindex]
244
+ if lat.isnumeric():
245
+ ourlat = int(lat)
246
+
247
+ if ourlat is not None:
248
+ if ourlat >= 66:
249
+ return 1.1
250
+
251
+ return 1
252
+
253
+
254
+ def show_qso(self):
255
+ """Return qso count"""
256
+ result = self.database.fetch_qso_count()
257
+ if result:
258
+ return int(result.get("qsos", 0))
259
+ return 0
260
+
261
+
262
+ def calc_score(self):
263
+ """Return calculated score"""
264
+ result = self.database.fetch_points()
265
+ if result is not None:
266
+ score = result.get("Points", "0")
267
+ if score is None:
268
+ score = "0"
269
+ contest_points = int(score)
270
+ mults = show_mults(self)
271
+ return contest_points * mults
272
+ return 0
273
+
274
+
275
+ def adif(self):
276
+ """Call the generate ADIF function"""
277
+ gen_adif(self, cabrillo_name, "RAEM")
278
+
279
+
280
+ def output_cabrillo_line(line_to_output, ending, file_descriptor, file_encoding):
281
+ """"""
282
+ print(
283
+ line_to_output.encode(file_encoding, errors="ignore").decode(),
284
+ end=ending,
285
+ file=file_descriptor,
286
+ )
287
+
288
+
289
+ def cabrillo(self, file_encoding):
290
+ """Generates Cabrillo file. Maybe."""
291
+ logger.debug("******Cabrillo*****")
292
+ logger.debug("Station: %s", f"{self.station}")
293
+ logger.debug("Contest: %s", f"{self.contest_settings}")
294
+ now = datetime.datetime.now()
295
+ date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
296
+ filename = (
297
+ str(Path.home())
298
+ + "/"
299
+ + f"{self.station.get('Call', '').upper()}_{cabrillo_name}_{date_time}.log"
300
+ )
301
+ logger.debug("%s", filename)
302
+ log = self.database.fetch_all_contacts_asc()
303
+ try:
304
+ with open(filename, "w", encoding=file_encoding) as file_descriptor:
305
+ output_cabrillo_line(
306
+ "START-OF-LOG: 3.0",
307
+ "\r\n",
308
+ file_descriptor,
309
+ file_encoding,
310
+ )
311
+ output_cabrillo_line(
312
+ f"CREATED-BY: Not1MM v{__version__}",
313
+ "\r\n",
314
+ file_descriptor,
315
+ file_encoding,
316
+ )
317
+ output_cabrillo_line(
318
+ f"CONTEST: {cabrillo_name}",
319
+ "\r\n",
320
+ file_descriptor,
321
+ file_encoding,
322
+ )
323
+ if self.station.get("Club", ""):
324
+ output_cabrillo_line(
325
+ f"CLUB: {self.station.get('Club', '').upper()}",
326
+ "\r\n",
327
+ file_descriptor,
328
+ file_encoding,
329
+ )
330
+ output_cabrillo_line(
331
+ f"CALLSIGN: {self.station.get('Call','')}",
332
+ "\r\n",
333
+ file_descriptor,
334
+ file_encoding,
335
+ )
336
+ output_cabrillo_line(
337
+ f"LOCATION: {self.station.get('ARRLSection', '')}",
338
+ "\r\n",
339
+ file_descriptor,
340
+ file_encoding,
341
+ )
342
+ output_cabrillo_line(
343
+ f"CATEGORY-OPERATOR: {self.contest_settings.get('OperatorCategory','')}",
344
+ "\r\n",
345
+ file_descriptor,
346
+ file_encoding,
347
+ )
348
+ output_cabrillo_line(
349
+ f"CATEGORY-ASSISTED: {self.contest_settings.get('AssistedCategory','')}",
350
+ "\r\n",
351
+ file_descriptor,
352
+ file_encoding,
353
+ )
354
+ output_cabrillo_line(
355
+ f"CATEGORY-BAND: {self.contest_settings.get('BandCategory','')}",
356
+ "\r\n",
357
+ file_descriptor,
358
+ file_encoding,
359
+ )
360
+ output_cabrillo_line(
361
+ f"CATEGORY-MODE: {self.contest_settings.get('ModeCategory','')}",
362
+ "\r\n",
363
+ file_descriptor,
364
+ file_encoding,
365
+ )
366
+ output_cabrillo_line(
367
+ f"CATEGORY-TRANSMITTER: {self.contest_settings.get('TransmitterCategory','')}",
368
+ "\r\n",
369
+ file_descriptor,
370
+ file_encoding,
371
+ )
372
+ if self.contest_settings.get("OverlayCategory", "") != "N/A":
373
+ output_cabrillo_line(
374
+ f"CATEGORY-OVERLAY: {self.contest_settings.get('OverlayCategory','')}",
375
+ "\r\n",
376
+ file_descriptor,
377
+ file_encoding,
378
+ )
379
+ output_cabrillo_line(
380
+ f"GRID-LOCATOR: {self.station.get('GridSquare','')}",
381
+ "\r\n",
382
+ file_descriptor,
383
+ file_encoding,
384
+ )
385
+ output_cabrillo_line(
386
+ f"CATEGORY-POWER: {self.contest_settings.get('PowerCategory','')}",
387
+ "\r\n",
388
+ file_descriptor,
389
+ file_encoding,
390
+ )
391
+
392
+ output_cabrillo_line(
393
+ f"CLAIMED-SCORE: {calc_score(self)}",
394
+ "\r\n",
395
+ file_descriptor,
396
+ file_encoding,
397
+ )
398
+ ops = f"@{self.station.get('Call','')}"
399
+ list_of_ops = self.database.get_ops()
400
+ for op in list_of_ops:
401
+ ops += f", {op.get('Operator', '')}"
402
+ output_cabrillo_line(
403
+ f"OPERATORS: {ops}",
404
+ "\r\n",
405
+ file_descriptor,
406
+ file_encoding,
407
+ )
408
+ output_cabrillo_line(
409
+ f"NAME: {self.station.get('Name', '')}",
410
+ "\r\n",
411
+ file_descriptor,
412
+ file_encoding,
413
+ )
414
+ output_cabrillo_line(
415
+ f"ADDRESS: {self.station.get('Street1', '')}",
416
+ "\r\n",
417
+ file_descriptor,
418
+ file_encoding,
419
+ )
420
+ output_cabrillo_line(
421
+ f"ADDRESS-CITY: {self.station.get('City', '')}",
422
+ "\r\n",
423
+ file_descriptor,
424
+ file_encoding,
425
+ )
426
+ output_cabrillo_line(
427
+ f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
428
+ "\r\n",
429
+ file_descriptor,
430
+ file_encoding,
431
+ )
432
+ output_cabrillo_line(
433
+ f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
434
+ "\r\n",
435
+ file_descriptor,
436
+ file_encoding,
437
+ )
438
+ output_cabrillo_line(
439
+ f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
440
+ "\r\n",
441
+ file_descriptor,
442
+ file_encoding,
443
+ )
444
+ output_cabrillo_line(
445
+ f"EMAIL: {self.station.get('Email', '')}",
446
+ "\r\n",
447
+ file_descriptor,
448
+ file_encoding,
449
+ )
450
+ for contact in log:
451
+ the_date_and_time = contact.get("TS", "")
452
+ themode = contact.get("Mode", "")
453
+ if themode == "LSB" or themode == "USB":
454
+ themode = "PH"
455
+ frequency = str(int(contact.get("Freq", "0"))).rjust(5)
456
+
457
+ loggeddate = the_date_and_time[:10]
458
+ loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
459
+ output_cabrillo_line(
460
+ f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
461
+ f"{contact.get('StationPrefix', '').ljust(13)} "
462
+ f"{str(contact.get('SentNr', '')).ljust(6)} "
463
+ f"{self.contest_settings.get('SentExchange', '').ljust(14).upper()}"
464
+ f"{contact.get('Call', '').ljust(13)} "
465
+ f"{str(contact.get('NR', '')).ljust(6)}"
466
+ f"{str(contact.get('Exchange1', '')).ljust(14)} ",
467
+ "\r\n",
468
+ file_descriptor,
469
+ file_encoding,
470
+ )
471
+ output_cabrillo_line("END-OF-LOG:", "\r\n", file_descriptor, file_encoding)
472
+ self.show_message_box(f"Cabrillo saved to: {filename}")
473
+ except IOError as exception:
474
+ logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
475
+ self.show_message_box(f"Error saving Cabrillo: {exception} {filename}")
476
+ return
477
+
478
+
479
+ def recalculate_mults(self):
480
+ """Recalculates multipliers after change in logged qso."""
481
+ # all_contacts = self.database.fetch_all_contacts_asc()
482
+ # for contact in all_contacts:
483
+ # time_stamp = contact.get("TS", "")
484
+ # wpx = contact.get("WPXPrefix", "")
485
+ # result = self.database.fetch_wpx_exists_before_me(wpx, time_stamp)
486
+ # wpx_count = result.get("wpx_count", 1)
487
+ # if wpx_count == 0:
488
+ # contact["IsMultiplier1"] = 1
489
+ # else:
490
+ # contact["IsMultiplier1"] = 0
491
+ # self.database.change_contact(contact)
492
+
493
+
494
+ def check_call_history(self):
495
+ """"""
496
+ result = self.database.fetch_call_history(self.callsign.text())
497
+ print(f"{result=}")
498
+ if result:
499
+ self.history_info.setText(f"{result.get('UserText','')}")
500
+ if self.other_2.text() == "":
501
+ self.other_2.setText(f"{result.get('Exch1', '')}")
502
+
503
+
504
+ def process_esm(self, new_focused_widget=None, with_enter=False):
505
+ """ESM State Machine"""
506
+
507
+ # self.pref["run_state"]
508
+
509
+ # -----===== Assigned F-Keys =====-----
510
+ # self.esm_dict["CQ"]
511
+ # self.esm_dict["EXCH"]
512
+ # self.esm_dict["QRZ"]
513
+ # self.esm_dict["AGN"]
514
+ # self.esm_dict["HISCALL"]
515
+ # self.esm_dict["MYCALL"]
516
+ # self.esm_dict["QSOB4"]
517
+
518
+ # ----==== text fields ====----
519
+ # self.callsign
520
+ # self.sent
521
+ # self.receive
522
+ # self.other_1
523
+ # self.other_2
524
+
525
+ if new_focused_widget is not None:
526
+ self.current_widget = self.inputs_dict.get(new_focused_widget)
527
+
528
+ # print(f"checking esm {self.current_widget=} {with_enter=} {self.pref.get("run_state")=}")
529
+
530
+ for a_button in [
531
+ self.esm_dict["CQ"],
532
+ self.esm_dict["EXCH"],
533
+ self.esm_dict["QRZ"],
534
+ self.esm_dict["AGN"],
535
+ self.esm_dict["HISCALL"],
536
+ self.esm_dict["MYCALL"],
537
+ self.esm_dict["QSOB4"],
538
+ ]:
539
+ if a_button is not None:
540
+ self.restore_button_color(a_button)
541
+
542
+ buttons_to_send = []
543
+
544
+ if self.pref.get("run_state"):
545
+ if self.current_widget == "callsign":
546
+ if len(self.callsign.text()) < 3:
547
+ self.make_button_green(self.esm_dict["CQ"])
548
+ buttons_to_send.append(self.esm_dict["CQ"])
549
+ elif len(self.callsign.text()) > 2:
550
+ self.make_button_green(self.esm_dict["HISCALL"])
551
+ self.make_button_green(self.esm_dict["EXCH"])
552
+ buttons_to_send.append(self.esm_dict["HISCALL"])
553
+ buttons_to_send.append(self.esm_dict["EXCH"])
554
+
555
+ elif self.current_widget == "other_1" or self.current_widget == "other_2":
556
+ if self.other_2.text() == "" or self.other_1.text() == "":
557
+ self.make_button_green(self.esm_dict["AGN"])
558
+ buttons_to_send.append(self.esm_dict["AGN"])
559
+ else:
560
+ self.make_button_green(self.esm_dict["QRZ"])
561
+ buttons_to_send.append(self.esm_dict["QRZ"])
562
+ buttons_to_send.append("LOGIT")
563
+
564
+ if with_enter is True and bool(len(buttons_to_send)):
565
+ for button in buttons_to_send:
566
+ if button:
567
+ if button == "LOGIT":
568
+ self.save_contact()
569
+ continue
570
+ self.process_function_key(button)
571
+ else:
572
+ if self.current_widget == "callsign":
573
+ if len(self.callsign.text()) > 2:
574
+ self.make_button_green(self.esm_dict["MYCALL"])
575
+ buttons_to_send.append(self.esm_dict["MYCALL"])
576
+
577
+ elif self.current_widget == "other_1" or self.current_widget == "other_2":
578
+ if self.other_2.text() == "" or self.other_1.text() == "":
579
+ self.make_button_green(self.esm_dict["AGN"])
580
+ buttons_to_send.append(self.esm_dict["AGN"])
581
+ else:
582
+ self.make_button_green(self.esm_dict["EXCH"])
583
+ buttons_to_send.append(self.esm_dict["EXCH"])
584
+ buttons_to_send.append("LOGIT")
585
+
586
+ if with_enter is True and bool(len(buttons_to_send)):
587
+ for button in buttons_to_send:
588
+ if button:
589
+ if button == "LOGIT":
590
+ self.save_contact()
591
+ continue
592
+ self.process_function_key(button)
not1mm/test.py CHANGED
@@ -1,11 +1,61 @@
1
- from dasbus.connection import SessionMessageBus
1
+ from not1mm.lib.database import DataBase
2
+ from json import loads
3
+ import not1mm.fsutils as fsutils
4
+ import os
2
5
 
3
- bus = SessionMessageBus()
6
+ dbname = None
7
+ pref = {}
4
8
 
5
- proxy = bus.get_proxy("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
6
9
 
7
- id = proxy.Notify(
8
- "weenes", 0, "face-smile", "My notification", "Hello World!", [], {}, 0
9
- )
10
+ def load_pref():
11
+ try:
12
+ if os.path.exists(fsutils.CONFIG_FILE):
13
+ with open(fsutils.CONFIG_FILE, "rt", encoding="utf-8") as file_descriptor:
14
+ pref = loads(file_descriptor.read())
15
+ else:
16
+ pref["current_database"] = "ham.db"
10
17
 
11
- print("The notification {} was sent.".format(id))
18
+ except IOError:
19
+ ...
20
+
21
+
22
+ load_pref()
23
+ dbname = fsutils.USER_DATA_PATH / pref.get("current_database", "ham.db")
24
+ database = DataBase(dbname, fsutils.USER_DATA_PATH)
25
+
26
+ database.create_callhistory_table()
27
+ database.delete_callhistory()
28
+
29
+ try:
30
+ with open(
31
+ "/home/mbridak/call_history/CWOPS_3634-AAA.txt", "rt", encoding="utf-8"
32
+ ) as file_descriptor:
33
+ lines = file_descriptor.readlines()
34
+ if "!!Order!!" in lines[0]:
35
+ item_names = lines[0].strip().split(",")
36
+ # ['!!Order!!', 'Call', 'Sect', 'State', 'CK', 'UserText', '']
37
+ item_names = item_names[1:-1]
38
+ # ['Call', 'Sect', 'State', 'CK', 'UserText']
39
+ lines = lines[1:]
40
+ group_list = []
41
+ for line in lines:
42
+ if line.startswith("#"):
43
+ continue
44
+ group = {}
45
+ fields = line.strip().split(",")
46
+ # ['4U1WB','MDC','DC','89','']
47
+ count = 0
48
+ try:
49
+ for item in item_names:
50
+ if item == "":
51
+ continue
52
+ group[item] = fields[count]
53
+ count += 1
54
+ group_list.append(group)
55
+ # database.add_callhistory_item(group)
56
+ # print(f"{group=}")
57
+ except IndexError:
58
+ ...
59
+ database.add_callhistory_items(group_list)
60
+ except FileNotFoundError:
61
+ print("error")