not1mm 24.12.3__tar.gz → 24.12.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. {not1mm-24.12.3 → not1mm-24.12.3.1}/PKG-INFO +2 -1
  2. {not1mm-24.12.3 → not1mm-24.12.3.1}/README.md +1 -0
  3. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/new_contest.ui +5 -0
  4. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/database.py +17 -0
  5. not1mm-24.12.3.1/not1mm/lib/version.py +3 -0
  6. not1mm-24.12.3.1/not1mm/plugins/arrl_160m.py +543 -0
  7. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm.egg-info/PKG-INFO +2 -1
  8. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm.egg-info/SOURCES.txt +1 -0
  9. {not1mm-24.12.3 → not1mm-24.12.3.1}/pyproject.toml +1 -1
  10. not1mm-24.12.3/not1mm/lib/version.py +0 -3
  11. {not1mm-24.12.3 → not1mm-24.12.3.1}/LICENSE +0 -0
  12. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/__init__.py +0 -0
  13. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/__main__.py +0 -0
  14. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/bandmap.py +0 -0
  15. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/checkwindow.py +0 -0
  16. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/JetBrainsMono-ExtraLight.ttf +0 -0
  17. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/MASTER.SCP +0 -0
  18. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/about.ui +0 -0
  19. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/alpha bravo charlie delta.txt +0 -0
  20. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/bandmap.ui +0 -0
  21. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/check.png +0 -0
  22. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/checkwindow.ui +0 -0
  23. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/configuration.ui +0 -0
  24. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/contests.sql +0 -0
  25. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/cty.json +0 -0
  26. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/cwmacros.txt +0 -0
  27. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/donors.html +0 -0
  28. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/editcontact.ui +0 -0
  29. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/editmacro.ui +0 -0
  30. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/greendot.png +0 -0
  31. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/k6gte-not1mm.desktop +0 -0
  32. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/k6gte.not1mm-128.png +0 -0
  33. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/k6gte.not1mm-32.png +0 -0
  34. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/k6gte.not1mm-64.png +0 -0
  35. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/logwindow.ui +0 -0
  36. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/logwindowx.ui +0 -0
  37. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/main.ui +0 -0
  38. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/not1mm.html +0 -0
  39. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/opon.ui +0 -0
  40. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/0.wav +0 -0
  41. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/1.wav +0 -0
  42. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/2.wav +0 -0
  43. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/3.wav +0 -0
  44. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/4.wav +0 -0
  45. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/5.wav +0 -0
  46. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/6.wav +0 -0
  47. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/7.wav +0 -0
  48. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/73.wav +0 -0
  49. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/8.wav +0 -0
  50. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/9.wav +0 -0
  51. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/a.wav +0 -0
  52. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/again.wav +0 -0
  53. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/b.wav +0 -0
  54. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/c.wav +0 -0
  55. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/contest.wav +0 -0
  56. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/cq.wav +0 -0
  57. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/cq2.wav +0 -0
  58. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/d.wav +0 -0
  59. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/e.wav +0 -0
  60. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/f.wav +0 -0
  61. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/g.wav +0 -0
  62. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/h.wav +0 -0
  63. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/i.wav +0 -0
  64. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/j.wav +0 -0
  65. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/k.wav +0 -0
  66. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/k6gte.wav +0 -0
  67. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/l.wav +0 -0
  68. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/m.wav +0 -0
  69. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/mynumber.wav +0 -0
  70. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/n.wav +0 -0
  71. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/nil.wav +0 -0
  72. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/o.wav +0 -0
  73. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/p.wav +0 -0
  74. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/q.wav +0 -0
  75. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/r.wav +0 -0
  76. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/roger.wav +0 -0
  77. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/s.wav +0 -0
  78. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/space.wav +0 -0
  79. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/t.wav +0 -0
  80. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/thankyou.wav +0 -0
  81. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/thankyouqrz.wav +0 -0
  82. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/u.wav +0 -0
  83. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/v.wav +0 -0
  84. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/w.wav +0 -0
  85. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/x.wav +0 -0
  86. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/y.wav +0 -0
  87. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/yourcall.wav +0 -0
  88. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/phonetics/z.wav +0 -0
  89. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/pickcontest.ui +0 -0
  90. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/radio_green.png +0 -0
  91. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/radio_grey.png +0 -0
  92. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/radio_red.png +0 -0
  93. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/reddot.png +0 -0
  94. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/rttymacros.txt +0 -0
  95. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/settings.ui +0 -0
  96. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/splash.png +0 -0
  97. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/ssbmacros.txt +0 -0
  98. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/data/vfo.ui +0 -0
  99. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/fsutils.py +0 -0
  100. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/__init__.py +0 -0
  101. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/about.py +0 -0
  102. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/cat_interface.py +0 -0
  103. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/cwinterface.py +0 -0
  104. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/edit_contact.py +0 -0
  105. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/edit_macro.py +0 -0
  106. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/edit_opon.py +0 -0
  107. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/edit_station.py +0 -0
  108. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/fldigi_sendstring.py +0 -0
  109. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/fldigi_watcher.py +0 -0
  110. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/ft8_watcher.py +0 -0
  111. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/ham_utility.py +0 -0
  112. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/lookup.py +0 -0
  113. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/multicast.py +0 -0
  114. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/n1mm.py +0 -0
  115. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/new_contest.py +0 -0
  116. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/plugin_common.py +0 -0
  117. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/select_contest.py +0 -0
  118. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/settings.py +0 -0
  119. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/super_check_partial.py +0 -0
  120. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lib/versiontest.py +0 -0
  121. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/logwindow.py +0 -0
  122. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/lookupservice.py +0 -0
  123. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/10_10_fall_cw.py +0 -0
  124. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/10_10_spring_cw.py +0 -0
  125. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/10_10_summer_phone.py +0 -0
  126. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/10_10_winter_phone.py +0 -0
  127. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/__init__.py +0 -0
  128. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/arrl_10m.py +0 -0
  129. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/arrl_dx_cw.py +0 -0
  130. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/arrl_dx_ssb.py +0 -0
  131. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/arrl_field_day.py +0 -0
  132. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/arrl_rtty_ru.py +0 -0
  133. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/arrl_ss_cw.py +0 -0
  134. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/arrl_ss_phone.py +0 -0
  135. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/arrl_vhf_jan.py +0 -0
  136. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/arrl_vhf_jun.py +0 -0
  137. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/arrl_vhf_sep.py +0 -0
  138. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/canada_day.py +0 -0
  139. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/cq_160_cw.py +0 -0
  140. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/cq_160_ssb.py +0 -0
  141. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/cq_wpx_cw.py +0 -0
  142. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/cq_wpx_rtty.py +0 -0
  143. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/cq_wpx_ssb.py +0 -0
  144. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/cq_ww_cw.py +0 -0
  145. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/cq_ww_rtty.py +0 -0
  146. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/cq_ww_ssb.py +0 -0
  147. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/cwt.py +0 -0
  148. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/darc_xmas.py +0 -0
  149. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/general_logging.py +0 -0
  150. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/helvetia.py +0 -0
  151. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/iaru_fieldday_r1_cw.py +0 -0
  152. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/iaru_fieldday_r1_ssb.py +0 -0
  153. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/iaru_hf.py +0 -0
  154. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/icwc_mst.py +0 -0
  155. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/jidx_cw.py +0 -0
  156. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/jidx_ph.py +0 -0
  157. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/k1usn_sst.py +0 -0
  158. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/lz-dx.py +0 -0
  159. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/naqp_cw.py +0 -0
  160. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/naqp_rtty.py +0 -0
  161. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/naqp_ssb.py +0 -0
  162. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/phone_weekly_test.py +0 -0
  163. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/raem.py +0 -0
  164. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/ref_cw.py +0 -0
  165. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/ref_ssb.py +0 -0
  166. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/stew_perry_topband.py +0 -0
  167. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/weekly_rtty.py +0 -0
  168. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/plugins/winter_field_day.py +0 -0
  169. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/radio.py +0 -0
  170. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/test.py +0 -0
  171. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/vfo.py +0 -0
  172. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm/voice_keying.py +0 -0
  173. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm.egg-info/dependency_links.txt +0 -0
  174. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm.egg-info/entry_points.txt +0 -0
  175. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm.egg-info/requires.txt +0 -0
  176. {not1mm-24.12.3 → not1mm-24.12.3.1}/not1mm.egg-info/top_level.txt +0 -0
  177. {not1mm-24.12.3 → not1mm-24.12.3.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: not1mm
3
- Version: 24.12.3
3
+ Version: 24.12.3.1
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
@@ -238,6 +238,7 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
238
238
 
239
239
  ## Recent Changes (Polishing the Turd)
240
240
 
241
+ - [24-12-3-1] Adding ARRL 160
241
242
  - [24-12-3] Add button to bandmap to delete marked spots.
242
243
 
243
244
  See [CHANGELOG.md](CHANGELOG.md) for prior changes.
@@ -207,6 +207,7 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
207
207
 
208
208
  ## Recent Changes (Polishing the Turd)
209
209
 
210
+ - [24-12-3-1] Adding ARRL 160
210
211
  - [24-12-3] Add button to bandmap to delete marked spots.
211
212
 
212
213
  See [CHANGELOG.md](CHANGELOG.md) for prior changes.
@@ -217,6 +217,11 @@
217
217
  <string>ARRL 10M</string>
218
218
  </property>
219
219
  </item>
220
+ <item>
221
+ <property name="text">
222
+ <string>ARRL 160M</string>
223
+ </property>
224
+ </item>
220
225
  <item>
221
226
  <property name="text">
222
227
  <string>ARRL DX CW</string>
@@ -695,6 +695,23 @@ class DataBase:
695
695
  logger.debug("%s", exception)
696
696
  return {}
697
697
 
698
+ def fetch_exchange1_unique_count(self) -> dict:
699
+ """
700
+ Fetch count of unique countries
701
+ {exch1_count: count}
702
+ """
703
+ try:
704
+ with sqlite3.connect(self.database) as conn:
705
+ conn.row_factory = self.row_factory
706
+ cursor = conn.cursor()
707
+ cursor.execute(
708
+ f"select count(DISTINCT(Exchange1)) as exch1_count from dxlog where Exchange1 != '' and ContestNR = {self.current_contest};"
709
+ )
710
+ return cursor.fetchone()
711
+ except sqlite3.OperationalError as exception:
712
+ logger.debug("%s", exception)
713
+ return {}
714
+
698
715
  def fetch_arrldx_country_band_count(self) -> dict:
699
716
  """
700
717
  returns dict with count of unique NR.
@@ -0,0 +1,3 @@
1
+ """It's the version"""
2
+
3
+ __version__ = "24.12.3.1"
@@ -0,0 +1,543 @@
1
+ """ARRL 160 CW plugin"""
2
+
3
+ # pylint: disable=invalid-name, c-extension-no-member, unused-import, line-too-long
4
+
5
+ import datetime
6
+ import logging
7
+ import platform
8
+
9
+ from pathlib import Path
10
+
11
+ from PyQt6 import QtWidgets
12
+
13
+ from not1mm.lib.plugin_common import gen_adif
14
+ from not1mm.lib.version import __version__
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+ EXCHANGE_HINT = "ST/Prov or DX CQ Zone"
19
+
20
+ name = "ARRL 160-Meter"
21
+ cabrillo_name = "ARRL-160"
22
+ mode = "CW" # CW SSB BOTH RTTY
23
+
24
+ columns = [
25
+ "YYYY-MM-DD HH:MM:SS",
26
+ "Call",
27
+ "Freq",
28
+ "Snt",
29
+ "Rcv",
30
+ "PFX",
31
+ "Exchange1",
32
+ "PTS",
33
+ ]
34
+
35
+ advance_on_space = [True, True, True, True, True]
36
+
37
+ # 1 once per contest, 2 work each band, 3 each band/mode, 4 no dupe checking
38
+ dupe_type = 1
39
+
40
+
41
+ def init_contest(self):
42
+ """setup plugin"""
43
+ set_tab_next(self)
44
+ set_tab_prev(self)
45
+ interface(self)
46
+ self.next_field = self.other_2
47
+
48
+
49
+ def interface(self):
50
+ """Setup user interface"""
51
+ self.field1.show()
52
+ self.field2.show()
53
+ self.field3.hide()
54
+ self.field4.show()
55
+ self.snt_label.setText("SNT")
56
+ self.field1.setAccessibleName("RST Sent")
57
+ self.exch_label.setText("ARRL/RAC Section")
58
+ self.field4.setAccessibleName("Received Exchange")
59
+
60
+
61
+ def reset_label(self): # pylint: disable=unused-argument
62
+ """reset label after field cleared"""
63
+
64
+
65
+ def set_tab_next(self):
66
+ """Set TAB Advances"""
67
+ self.tab_next = {
68
+ self.callsign: self.sent,
69
+ self.sent: self.receive,
70
+ self.receive: self.other_2,
71
+ self.other_1: self.other_2,
72
+ self.other_2: self.callsign,
73
+ }
74
+
75
+
76
+ def set_tab_prev(self):
77
+ """Set TAB Advances"""
78
+ self.tab_prev = {
79
+ self.callsign: self.other_2,
80
+ self.sent: self.callsign,
81
+ self.receive: self.sent,
82
+ self.other_1: self.receive,
83
+ self.other_2: self.receive,
84
+ }
85
+
86
+
87
+ def set_contact_vars(self):
88
+ """Contest Specific"""
89
+ self.contact["SNT"] = self.sent.text()
90
+ self.contact["RCV"] = self.receive.text()
91
+ self.contact["SentNr"] = self.contest_settings.get("SentExchange", 0)
92
+ self.contact["Exchange1"] = self.other_2.text()
93
+
94
+
95
+ def predupe(self): # pylint: disable=unused-argument
96
+ """called after callsign entered"""
97
+
98
+
99
+ def prefill(self):
100
+ """Fill SentNR"""
101
+
102
+
103
+ def points(self):
104
+ """Calc point"""
105
+ # Each contact between W/VE stations counts for two (2) QSO points. Each contact with a DX station counts five (5) QSO points
106
+ call = self.contact.get("Call", "")
107
+ dupe_check = self.database.check_dupe(call)
108
+ if dupe_check.get("isdupe", 0) > 0:
109
+ return 0
110
+ result = self.cty_lookup(self.station.get("Call", ""))
111
+ if result:
112
+ for item in result.items():
113
+ mypfx = item[1].get("primary_pfx", "")
114
+ # mycountry = item[1].get("entity", "")
115
+ # mycontinent = item[1].get("continent", "")
116
+
117
+ result = self.cty_lookup(self.contact.get("Call", ""))
118
+ if result:
119
+ for item in result.items():
120
+ pfx = item[1].get("primary_pfx", "")
121
+ # entity = item[1].get("entity", "")
122
+ # continent = item[1].get("continent", "")
123
+
124
+ # Both in same country
125
+
126
+ if mypfx in ["K", "VE"] and pfx in ["K", "VE"]:
127
+ return 2
128
+
129
+ if mypfx.upper() != pfx.upper():
130
+ return 5
131
+
132
+ return 0
133
+
134
+
135
+ def show_mults(self):
136
+ """Return display string for mults"""
137
+ result = self.database.fetch_country_count()
138
+ mults = int(result.get("dxcc_count", 0))
139
+
140
+ result = self.database.fetch_exchange1_unique_count()
141
+ mults2 = int(result.get("exch1_count", 0))
142
+
143
+ return mults + mults2
144
+
145
+
146
+ def show_qso(self):
147
+ """Return qso count"""
148
+ result = self.database.fetch_qso_count()
149
+ if result:
150
+ return int(result.get("qsos", 0))
151
+ return 0
152
+
153
+
154
+ def calc_score(self):
155
+ """Return calculated score"""
156
+ result = self.database.fetch_points()
157
+ if result is not None:
158
+ score = result.get("Points", "0")
159
+ if score is None:
160
+ score = "0"
161
+ contest_points = int(score)
162
+
163
+ result = self.database.fetch_country_count()
164
+ mults = int(result.get("dxcc_count", 0))
165
+
166
+ result = self.database.fetch_exchange1_unique_count()
167
+ mults2 = int(result.get("exch1_count", 0))
168
+ return contest_points * (mults + mults2)
169
+ return 0
170
+
171
+
172
+ def adif(self):
173
+ """Call the generate ADIF function"""
174
+ gen_adif(self, cabrillo_name, "ARRL 160-Meter")
175
+
176
+
177
+ def output_cabrillo_line(line_to_output, ending, file_descriptor, file_encoding):
178
+ """"""
179
+ print(
180
+ line_to_output.encode(file_encoding, errors="ignore").decode(),
181
+ end=ending,
182
+ file=file_descriptor,
183
+ )
184
+
185
+
186
+ def cabrillo(self, file_encoding):
187
+ """Generates Cabrillo file. Maybe."""
188
+ # https://www.cw160.com/cabrillo.htm
189
+ logger.debug("******Cabrillo*****")
190
+ logger.debug("Station: %s", f"{self.station}")
191
+ logger.debug("Contest: %s", f"{self.contest_settings}")
192
+ now = datetime.datetime.now()
193
+ date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
194
+ filename = (
195
+ str(Path.home())
196
+ + "/"
197
+ + f"{self.station.get('Call', '').upper()}_{cabrillo_name}_{date_time}.log"
198
+ )
199
+ logger.debug("%s", filename)
200
+ log = self.database.fetch_all_contacts_asc()
201
+ try:
202
+ with open(filename, "w", encoding=file_encoding) as file_descriptor:
203
+ output_cabrillo_line(
204
+ "START-OF-LOG: 3.0",
205
+ "\r\n",
206
+ file_descriptor,
207
+ file_encoding,
208
+ )
209
+ output_cabrillo_line(
210
+ f"CREATED-BY: Not1MM v{__version__}",
211
+ "\r\n",
212
+ file_descriptor,
213
+ file_encoding,
214
+ )
215
+ output_cabrillo_line(
216
+ f"CONTEST: {cabrillo_name}",
217
+ "\r\n",
218
+ file_descriptor,
219
+ file_encoding,
220
+ )
221
+ if self.station.get("Club", ""):
222
+ output_cabrillo_line(
223
+ f"CLUB: {self.station.get('Club', '').upper()}",
224
+ "\r\n",
225
+ file_descriptor,
226
+ file_encoding,
227
+ )
228
+ output_cabrillo_line(
229
+ f"CALLSIGN: {self.station.get('Call','')}",
230
+ "\r\n",
231
+ file_descriptor,
232
+ file_encoding,
233
+ )
234
+ output_cabrillo_line(
235
+ f"LOCATION: {self.station.get('ARRLSection', '')}",
236
+ "\r\n",
237
+ file_descriptor,
238
+ file_encoding,
239
+ )
240
+ output_cabrillo_line(
241
+ f"CATEGORY-OPERATOR: {self.contest_settings.get('OperatorCategory','')}",
242
+ "\r\n",
243
+ file_descriptor,
244
+ file_encoding,
245
+ )
246
+ output_cabrillo_line(
247
+ f"CATEGORY-ASSISTED: {self.contest_settings.get('AssistedCategory','')}",
248
+ "\r\n",
249
+ file_descriptor,
250
+ file_encoding,
251
+ )
252
+ output_cabrillo_line(
253
+ f"CATEGORY-BAND: {self.contest_settings.get('BandCategory','')}",
254
+ "\r\n",
255
+ file_descriptor,
256
+ file_encoding,
257
+ )
258
+ output_cabrillo_line(
259
+ f"CATEGORY-MODE: {self.contest_settings.get('ModeCategory','')}",
260
+ "\r\n",
261
+ file_descriptor,
262
+ file_encoding,
263
+ )
264
+ output_cabrillo_line(
265
+ f"CATEGORY-TRANSMITTER: {self.contest_settings.get('TransmitterCategory','')}",
266
+ "\r\n",
267
+ file_descriptor,
268
+ file_encoding,
269
+ )
270
+ if self.contest_settings.get("OverlayCategory", "") != "N/A":
271
+ output_cabrillo_line(
272
+ f"CATEGORY-OVERLAY: {self.contest_settings.get('OverlayCategory','')}",
273
+ "\r\n",
274
+ file_descriptor,
275
+ file_encoding,
276
+ )
277
+ output_cabrillo_line(
278
+ f"GRID-LOCATOR: {self.station.get('GridSquare','')}",
279
+ "\r\n",
280
+ file_descriptor,
281
+ file_encoding,
282
+ )
283
+ output_cabrillo_line(
284
+ f"CATEGORY-POWER: {self.contest_settings.get('PowerCategory','')}",
285
+ "\r\n",
286
+ file_descriptor,
287
+ file_encoding,
288
+ )
289
+
290
+ output_cabrillo_line(
291
+ f"CLAIMED-SCORE: {calc_score(self)}",
292
+ "\r\n",
293
+ file_descriptor,
294
+ file_encoding,
295
+ )
296
+ ops = f"@{self.station.get('Call','')}"
297
+ list_of_ops = self.database.get_ops()
298
+ for op in list_of_ops:
299
+ ops += f", {op.get('Operator', '')}"
300
+ output_cabrillo_line(
301
+ f"OPERATORS: {ops}",
302
+ "\r\n",
303
+ file_descriptor,
304
+ file_encoding,
305
+ )
306
+ output_cabrillo_line(
307
+ f"NAME: {self.station.get('Name', '')}",
308
+ "\r\n",
309
+ file_descriptor,
310
+ file_encoding,
311
+ )
312
+ output_cabrillo_line(
313
+ f"ADDRESS: {self.station.get('Street1', '')}",
314
+ "\r\n",
315
+ file_descriptor,
316
+ file_encoding,
317
+ )
318
+ output_cabrillo_line(
319
+ f"ADDRESS-CITY: {self.station.get('City', '')}",
320
+ "\r\n",
321
+ file_descriptor,
322
+ file_encoding,
323
+ )
324
+ output_cabrillo_line(
325
+ f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
326
+ "\r\n",
327
+ file_descriptor,
328
+ file_encoding,
329
+ )
330
+ output_cabrillo_line(
331
+ f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
332
+ "\r\n",
333
+ file_descriptor,
334
+ file_encoding,
335
+ )
336
+ output_cabrillo_line(
337
+ f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
338
+ "\r\n",
339
+ file_descriptor,
340
+ file_encoding,
341
+ )
342
+ output_cabrillo_line(
343
+ f"EMAIL: {self.station.get('Email', '')}",
344
+ "\r\n",
345
+ file_descriptor,
346
+ file_encoding,
347
+ )
348
+ for contact in log:
349
+ the_date_and_time = contact.get("TS", "")
350
+ themode = contact.get("Mode", "")
351
+ if themode == "LSB" or themode == "USB":
352
+ themode = "PH"
353
+ frequency = str(int(contact.get("Freq", "0"))).rjust(5)
354
+
355
+ loggeddate = the_date_and_time[:10]
356
+ loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
357
+ thesentnr = contact.get("SentNr", "---")
358
+ if thesentnr == "":
359
+ thesentnr = "---"
360
+ theexch = contact.get("Exchange1", "---")
361
+ if theexch == "":
362
+ theexch = "---"
363
+
364
+ output_cabrillo_line(
365
+ f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
366
+ f"{contact.get('StationPrefix', '').ljust(13)} "
367
+ f"{str(contact.get('SNT', '')).ljust(3)} "
368
+ f"{str(thesentnr).ljust(6)} "
369
+ f"{contact.get('Call', '').ljust(13)} "
370
+ f"{str(contact.get('RCV', '')).ljust(3)} "
371
+ f"{str(theexch).ljust(6)}",
372
+ "\r\n",
373
+ file_descriptor,
374
+ file_encoding,
375
+ )
376
+ output_cabrillo_line("END-OF-LOG:", "\r\n", file_descriptor, file_encoding)
377
+ self.show_message_box(f"Cabrillo saved to: {filename}")
378
+ except IOError as exception:
379
+ logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
380
+ self.show_message_box(f"Error saving Cabrillo: {exception} {filename}")
381
+ return
382
+
383
+
384
+ # def trigger_update(self):
385
+ # """Triggers the log window to update."""
386
+ # cmd = {}
387
+ # cmd["cmd"] = "UPDATELOG"
388
+ # cmd["station"] = platform.node()
389
+ # self.multicast_interface.send_as_json(cmd)
390
+
391
+
392
+ def recalculate_mults(self):
393
+ """Recalculates multipliers after change in logged qso."""
394
+ # all_contacts = self.database.fetch_all_contacts_asc()
395
+ # for contact in all_contacts:
396
+ # time_stamp = contact.get("TS", "")
397
+ # if contact.get("CountryPrefix", "") == "K":
398
+ # query = f"select count(*) as count from dxlog where TS < '{time_stamp}' and CountryPrefix = 'K' and Exchange1 = '{contact.get('Exchange1', '')}' and ContestNR = '{self.pref.get('contest', '0')}'"
399
+ # result = self.database.exec_sql(query)
400
+ # if result.get("count", 0) == 0:
401
+ # contact["IsMultiplier1"] = 1
402
+ # else:
403
+ # contact["IsMultiplier1"] = 0
404
+ # self.database.change_contact(contact)
405
+ # continue
406
+ # if contact.get("CountryPrefix", "") == "VE":
407
+ # query = f"select count(*) as count from dxlog where TS < '{time_stamp}' and CountryPrefix = 'VE' and Exchange1 = '{contact.get('Exchange1', '')}' and ContestNR = '{self.pref.get('contest', '0')}'"
408
+ # result = self.database.exec_sql(query)
409
+ # if result.get("count", 0) == 0:
410
+ # contact["IsMultiplier1"] = 1
411
+ # else:
412
+ # contact["IsMultiplier1"] = 0
413
+ # self.database.change_contact(contact)
414
+ # continue
415
+ # query = f"select count(*) as count from dxlog where TS < '{time_stamp}' and CountryPrefix = '{contact.get('CountryPrefix', '')}' and ContestNR = '{self.pref.get('contest', '0')}'"
416
+ # result = self.database.exec_sql(query)
417
+ # if result.get("count", 0) == 0:
418
+ # contact["IsMultiplier1"] = 1
419
+ # else:
420
+ # contact["IsMultiplier1"] = 0
421
+ # self.database.change_contact(contact)
422
+ # trigger_update(self)
423
+
424
+
425
+ def process_esm(self, new_focused_widget=None, with_enter=False):
426
+ """ESM State Machine"""
427
+
428
+ # self.pref["run_state"]
429
+
430
+ # -----===== Assigned F-Keys =====-----
431
+ # self.esm_dict["CQ"]
432
+ # self.esm_dict["EXCH"]
433
+ # self.esm_dict["QRZ"]
434
+ # self.esm_dict["AGN"]
435
+ # self.esm_dict["HISCALL"]
436
+ # self.esm_dict["MYCALL"]
437
+ # self.esm_dict["QSOB4"]
438
+
439
+ # ----==== text fields ====----
440
+ # self.callsign
441
+ # self.sent
442
+ # self.receive
443
+ # self.other_1
444
+ # self.other_2
445
+
446
+ if new_focused_widget is not None:
447
+ self.current_widget = self.inputs_dict.get(new_focused_widget)
448
+
449
+ # print(f"checking esm {self.current_widget=} {with_enter=} {self.pref.get("run_state")=}")
450
+
451
+ for a_button in [
452
+ self.esm_dict["CQ"],
453
+ self.esm_dict["EXCH"],
454
+ self.esm_dict["QRZ"],
455
+ self.esm_dict["AGN"],
456
+ self.esm_dict["HISCALL"],
457
+ self.esm_dict["MYCALL"],
458
+ self.esm_dict["QSOB4"],
459
+ ]:
460
+ if a_button is not None:
461
+ self.restore_button_color(a_button)
462
+
463
+ buttons_to_send = []
464
+
465
+ if self.pref.get("run_state"):
466
+ if self.current_widget == "callsign":
467
+ if len(self.callsign.text()) < 3:
468
+ self.make_button_green(self.esm_dict["CQ"])
469
+ buttons_to_send.append(self.esm_dict["CQ"])
470
+ elif len(self.callsign.text()) > 2:
471
+ self.make_button_green(self.esm_dict["HISCALL"])
472
+ self.make_button_green(self.esm_dict["EXCH"])
473
+ buttons_to_send.append(self.esm_dict["HISCALL"])
474
+ buttons_to_send.append(self.esm_dict["EXCH"])
475
+
476
+ elif self.current_widget in ["other_2"]:
477
+ if self.contact.get("CountryPrefix", "") in ["K", "VE"]:
478
+ if self.other_2.text() == "":
479
+ self.make_button_green(self.esm_dict["AGN"])
480
+ buttons_to_send.append(self.esm_dict["AGN"])
481
+ else:
482
+ self.make_button_green(self.esm_dict["QRZ"])
483
+ buttons_to_send.append(self.esm_dict["QRZ"])
484
+ buttons_to_send.append("LOGIT")
485
+ else:
486
+ self.make_button_green(self.esm_dict["QRZ"])
487
+ buttons_to_send.append(self.esm_dict["QRZ"])
488
+ buttons_to_send.append("LOGIT")
489
+
490
+ if with_enter is True and bool(len(buttons_to_send)):
491
+ for button in buttons_to_send:
492
+ if button:
493
+ if button == "LOGIT":
494
+ self.save_contact()
495
+ continue
496
+ self.process_function_key(button)
497
+ else:
498
+ if self.current_widget == "callsign":
499
+ if len(self.callsign.text()) > 2:
500
+ self.make_button_green(self.esm_dict["MYCALL"])
501
+ buttons_to_send.append(self.esm_dict["MYCALL"])
502
+
503
+ elif self.current_widget in ["other_2"]:
504
+ if self.contact.get("CountryPrefix", "") in ["K", "VE"]:
505
+ if self.other_2.text() == "":
506
+ self.make_button_green(self.esm_dict["AGN"])
507
+ buttons_to_send.append(self.esm_dict["AGN"])
508
+ else:
509
+ self.make_button_green(self.esm_dict["EXCH"])
510
+ buttons_to_send.append(self.esm_dict["EXCH"])
511
+ buttons_to_send.append("LOGIT")
512
+
513
+ else:
514
+ self.make_button_green(self.esm_dict["EXCH"])
515
+ buttons_to_send.append(self.esm_dict["EXCH"])
516
+ buttons_to_send.append("LOGIT")
517
+
518
+ if with_enter is True and bool(len(buttons_to_send)):
519
+ for button in buttons_to_send:
520
+ if button:
521
+ if button == "LOGIT":
522
+ self.save_contact()
523
+ continue
524
+ self.process_function_key(button)
525
+
526
+
527
+ def populate_history_info_line(self):
528
+ result = self.database.fetch_call_history(self.callsign.text())
529
+ if result:
530
+ self.history_info.setText(
531
+ f"{result.get('Call', '')}, {result.get('Name', '')}, {result.get('Exch1', '')}, {result.get('UserText','...')}"
532
+ )
533
+ else:
534
+ self.history_info.setText("")
535
+
536
+
537
+ def check_call_history(self):
538
+ """"""
539
+ result = self.database.fetch_call_history(self.callsign.text())
540
+ if result:
541
+ self.history_info.setText(f"{result.get('UserText','')}")
542
+ if self.other_2.text() == "":
543
+ self.other_2.setText(f"{result.get('Exch1', '')}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: not1mm
3
- Version: 24.12.3
3
+ Version: 24.12.3.1
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
@@ -238,6 +238,7 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
238
238
 
239
239
  ## Recent Changes (Polishing the Turd)
240
240
 
241
+ - [24-12-3-1] Adding ARRL 160
241
242
  - [24-12-3] Add button to bandmap to delete marked spots.
242
243
 
243
244
  See [CHANGELOG.md](CHANGELOG.md) for prior changes.
@@ -131,6 +131,7 @@ not1mm/plugins/10_10_summer_phone.py
131
131
  not1mm/plugins/10_10_winter_phone.py
132
132
  not1mm/plugins/__init__.py
133
133
  not1mm/plugins/arrl_10m.py
134
+ not1mm/plugins/arrl_160m.py
134
135
  not1mm/plugins/arrl_dx_cw.py
135
136
  not1mm/plugins/arrl_dx_ssb.py
136
137
  not1mm/plugins/arrl_field_day.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "not1mm"
7
- version = "24.12.3"
7
+ version = "24.12.3.1"
8
8
  description = "NOT1MM Logger"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -1,3 +0,0 @@
1
- """It's the version"""
2
-
3
- __version__ = "24.12.3"
File without changes
File without changes
File without changes
File without changes