wwvb 4.0.0a0__py3-none-any.whl → 5.0.0__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.
uwwvb.py CHANGED
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: 2021 Jeff Epler
1
+ # SPDX-FileCopyrightText: 2021-2024 Jeff Epler
2
2
  #
3
3
  # SPDX-License-Identifier: GPL-3.0-only
4
4
 
wwvb/__init__.py CHANGED
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/python3
2
2
  """A library for WWVB timecodes"""
3
3
 
4
- # Copyright (C) 2011-2020 Jeff Epler <jepler@gmail.com>
5
- # SPDX-FileCopyrightText: 2021 Jeff Epler
4
+ # SPDX-FileCopyrightText: 2011-2024 Jeff Epler
6
5
  #
7
6
  # SPDX-License-Identifier: GPL-3.0-only
8
7
 
@@ -12,11 +11,14 @@ import datetime
12
11
  import enum
13
12
  import json
14
13
  import warnings
15
- from typing import Any, Generator, NamedTuple, TextIO, TypeVar
14
+ from typing import TYPE_CHECKING, Any, NamedTuple, TextIO, TypeVar
16
15
 
17
16
  from . import iersdata
18
17
  from .tz import Mountain
19
18
 
19
+ if TYPE_CHECKING:
20
+ from collections.abc import Generator
21
+
20
22
  HOUR = datetime.timedelta(seconds=3600)
21
23
  SECOND = datetime.timedelta(seconds=1)
22
24
  T = TypeVar("T")
@@ -871,6 +873,8 @@ def print_timecodes(
871
873
  style_chars = styles.get(style, ["0", "1", "2"])
872
874
  first = True
873
875
  for _ in range(minutes):
876
+ if not first and channel == "both":
877
+ print(file=file)
874
878
  if first or all_timecodes:
875
879
  if not first:
876
880
  print(file=file)
@@ -888,8 +892,6 @@ def print_timecodes(
888
892
  pfx = " " * len(pfx)
889
893
  if channel in ("phase", "both"):
890
894
  print(f"{pfx} {tc.to_pm_string(style_chars)}", file=file)
891
- if channel == "both":
892
- print(file=file)
893
895
  w = w.next_minute()
894
896
 
895
897
 
wwvb/__version__.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '4.0.0a0'
16
- __version_tuple__ = version_tuple = (4, 0, 0)
15
+ __version__ = version = '5.0.0'
16
+ __version_tuple__ = version_tuple = (5, 0, 0)
wwvb/decode.py CHANGED
@@ -6,10 +6,13 @@
6
6
  from __future__ import annotations
7
7
 
8
8
  import sys
9
- from typing import Generator
9
+ from typing import TYPE_CHECKING
10
10
 
11
11
  import wwvb
12
12
 
13
+ if TYPE_CHECKING:
14
+ from collections.abc import Generator
15
+
13
16
  # State 1: Unsync'd
14
17
  # Marker: State 2
15
18
  # Other: State 1
@@ -86,5 +89,5 @@ def main() -> None:
86
89
  print(w)
87
90
 
88
91
 
89
- if __name__ == "__main__": # pragma no cover
92
+ if __name__ == "__main__":
90
93
  main()
wwvb/dut1table.py CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
- # SPDX-FileCopyrightText: 2021 Jeff Epler
3
+ # SPDX-FileCopyrightText: 2021-2024 Jeff Epler
4
4
  #
5
5
  # SPDX-License-Identifier: GPL-3.0-only
6
6
 
@@ -28,5 +28,5 @@ def main() -> None:
28
28
  print(date)
29
29
 
30
30
 
31
- if __name__ == "__main__": # pragma no branch
31
+ if __name__ == "__main__":
32
32
  main()
wwvb/gen.py CHANGED
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/python3
2
2
  """A command-line program for generating wwvb timecodes"""
3
3
 
4
- # Copyright (C) 2011-2020 Jeff Epler <jepler@gmail.com>
5
- # SPDX-FileCopyrightText: 2021 Jeff Epler
4
+ # SPDX-FileCopyrightText: 2011-2024 Jeff Epler
6
5
  #
7
6
  # SPDX-License-Identifier: GPL-3.0-only
8
7
 
@@ -124,5 +123,5 @@ def main(
124
123
  print_timecodes(w, minutes, channel, style, all_timecodes=all_timecodes, file=sys.stdout)
125
124
 
126
125
 
127
- if __name__ == "__main__": # pragma no branch
126
+ if __name__ == "__main__":
128
127
  main()
wwvb/iersdata.json ADDED
@@ -0,0 +1 @@
1
+ {"START": "1972-01-01", "OFFSETS_GZ": "H4sIAFEb/WYC/+2aa3LDMAiEL5uHLDuxnN5/pn/aTmfSSiAWhGR9J8gsywJylqVHPtqxZuH/7leeI0fKsGd5EngQ2WisJWKegrThDa6aJFnL0u4wYZkCE2UmSF0U+13vCveStC6JTfQyW3O86HLJf0SvDgy5u4FCI+WVKRuy0KMjJeXoULIvMDmEWgeRxAJtwXquPCIBqbLh/gbfv0mcxk3mHV9tYiATZP8W/zgw2wd5LpJnY+WErI8abJ3opaIW6592+YMbjSsNWQFlNVVtuhjhtQzSUh4MEpOdDrSW6qsUv+O+Dt+XkIONSrUwvWmTsmq5LO9xsZ+EgcDK+MIESDaYmxSxGlgbGOFjBXMjbV7lc6zlmQ0i48oH5P4+vK7i/AHc7tfTXDtffqFi3m6WhApPSTyDvArU5vUDhm7YaNQYGASVbbwLUBtI2PrhSiZNbvCRrtGUGu0GbjDhJ3aLCx5dQFjt0LFovmWB96e6tktqMenoULXajVS3asBibP3kYXrpmZxnsS2Yf2xRPrHbvQ2D9wjfL4C6b4PWV4otW0vWUYkeWE5M8M594oLbxP77xcl4NuBkG0dfM3xOUf/T0GF+ur+J5pljcODEUZkXg6vIdLYy7g3oZU3bPNDnc8qwGdJZMmAurUsRj6tOo95zP6fb9YPWp5OuZ5X7q2DrmsG/VCyTyaREnDRhnUxOjcmKM9b/R7R0+gQ5cs/LtEwAAA=="}
@@ -0,0 +1,2 @@
1
+ SPDX-FileCopyrightText: Public domain
2
+ SPDX-License-Identifier: CC0-1.0
wwvb/iersdata.py CHANGED
@@ -1,28 +1,37 @@
1
1
  # -*- python3 -*-
2
2
  """Retrieve iers data, possibly from user or site data or from the wwvbpy distribution"""
3
3
 
4
- # Copyright (C) 2021 Jeff Epler <jepler@gmail.com>
5
- # SPDX-FileCopyrightText: 2021 Jeff Epler
4
+ # SPDX-FileCopyrightText: 2011-2024 Jeff Epler
6
5
  #
7
6
  # SPDX-License-Identifier: GPL-3.0-only
8
7
 
8
+ import binascii
9
9
  import datetime
10
- import pathlib
10
+ import gzip
11
+ import importlib.resources
12
+ import json
11
13
 
12
14
  import platformdirs
13
15
 
14
16
  __all__ = ["DUT1_DATA_START", "DUT1_OFFSETS", "start", "span", "end"]
15
- from .iersdata_dist import DUT1_DATA_START, DUT1_OFFSETS
16
17
 
17
- for location in [
18
- platformdirs.user_data_dir("wwvbpy", "unpythonic.net"),
19
- platformdirs.site_data_dir("wwvbpy", "unpythonic.net"),
20
- ]: # pragma no cover
21
- path = pathlib.Path(location) / "wwvbpy_iersdata.py"
18
+ content: dict[str, str] = {"START": "1970-01-01", "OFFSETS_GZ": "H4sIAFNx1mYC/wMAAAAAAAAAAAA="}
19
+
20
+ path = importlib.resources.files("wwvb") / "iersdata.json"
21
+ content = json.loads(path.read_text(encoding="utf-8"))
22
+
23
+ for location in [ # pragma no cover
24
+ platformdirs.user_data_path("wwvbpy", "unpythonic.net"),
25
+ platformdirs.site_data_path("wwvbpy", "unpythonic.net"),
26
+ ]:
27
+ path = location / "iersdata.json"
22
28
  if path.exists():
23
- exec(path.read_text(encoding="utf-8"), globals(), globals())
29
+ content = json.loads(path.read_text(encoding="utf-8"))
24
30
  break
25
31
 
26
- start = datetime.datetime.combine(DUT1_DATA_START, datetime.time()).replace(tzinfo=datetime.timezone.utc)
32
+ DUT1_DATA_START = datetime.date.fromisoformat(content["START"])
33
+ DUT1_OFFSETS = gzip.decompress(binascii.a2b_base64(content["OFFSETS_GZ"])).decode("ascii")
34
+
35
+ start = datetime.datetime.combine(DUT1_DATA_START, datetime.time(), tzinfo=datetime.timezone.utc)
27
36
  span = datetime.timedelta(days=len(DUT1_OFFSETS))
28
37
  end = start + span
wwvb/tz.py CHANGED
@@ -1,8 +1,7 @@
1
1
  # -*- python -*-
2
2
  """A library for WWVB timecodes"""
3
3
 
4
- # Copyright (C) 2011-2020 Jeff Epler <jepler@gmail.com>
5
- # SPDX-FileCopyrightText: 2021 Jeff Epler
4
+ # SPDX-FileCopyrightText: 2021-2024 Jeff Epler
6
5
  #
7
6
  # SPDX-License-Identifier: GPL-3.0-only
8
7
 
wwvb/updateiers.py CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/python3
2
2
 
3
- # SPDX-FileCopyrightText: 2021 Jeff Epler
3
+ # SPDX-FileCopyrightText: 2021-2024 Jeff Epler
4
4
  #
5
5
  # SPDX-License-Identifier: GPL-3.0-only
6
6
 
@@ -8,10 +8,12 @@
8
8
 
9
9
  from __future__ import annotations
10
10
 
11
+ import binascii
11
12
  import csv
12
13
  import datetime
14
+ import gzip
13
15
  import io
14
- import itertools
16
+ import json
15
17
  import pathlib
16
18
  from typing import Callable
17
19
 
@@ -20,15 +22,7 @@ import click
20
22
  import platformdirs
21
23
  import requests
22
24
 
23
- DIST_PATH = pathlib.Path(__file__).parent / "iersdata_dist.py"
24
-
25
- OLD_TABLE_START: datetime.date | None = None
26
- OLD_TABLE_END: datetime.date | None = None
27
- if DIST_PATH.exists():
28
- import wwvb.iersdata_dist
29
-
30
- OLD_TABLE_START = wwvb.iersdata_dist.DUT1_DATA_START
31
- OLD_TABLE_END = OLD_TABLE_START + datetime.timedelta(days=len(wwvb.iersdata_dist.DUT1_OFFSETS) - 1)
25
+ DIST_PATH = pathlib.Path(__file__).parent / "iersdata.json"
32
26
 
33
27
  IERS_URL = "https://datacenter.iers.org/data/csv/finals2000A.all.csv"
34
28
  IERS_PATH = pathlib.Path("finals2000A.all.csv")
@@ -47,7 +41,7 @@ def _get_text(url: str) -> str:
47
41
  return pathlib.Path(url).read_text(encoding="utf-8")
48
42
 
49
43
 
50
- def update_iersdata( # noqa: PLR0915, PLR0912
44
+ def update_iersdata( # noqa: PLR0915
51
45
  target_path: pathlib.Path,
52
46
  ) -> None:
53
47
  """Update iersdata.py"""
@@ -124,57 +118,25 @@ def update_iersdata( # noqa: PLR0915, PLR0912
124
118
  assert wwvb_start is not None
125
119
  patch(wwvb_start, wwvb_data_stamp + datetime.timedelta(days=1), wwvb_dut1)
126
120
 
127
- with target_path.open("w", encoding="utf-8") as output:
128
-
129
- def code(*args: str) -> None:
130
- """Print to the output file"""
131
- print(*args, file=output)
132
-
133
- code("# -*- python3 -*-")
134
- code("# fmt: off")
135
- code('"""File generated from public data - not subject to copyright"""')
136
- code("# SPDX" + "-FileCopyrightText: Public domain")
137
- code("# SPDX" + "-License-Identifier: CC0-1.0")
138
- code("# isort: skip_file")
139
- code("import datetime")
140
-
141
- code("__all__ = ['DUT1_DATA_START', 'DUT1_OFFSETS']")
142
- code(f"DUT1_DATA_START = {table_start!r}")
143
- c = sorted(chr(ord("a") + ch + 10) for ch in set(offsets))
144
- code(f"{','.join(c)} = tuple({''.join(c)!r})")
145
- code(f"DUT1_OFFSETS = str( # {table_start.year:04d}{table_start.month:02d}{table_start.day:02d}")
146
- line = ""
147
- j = 0
148
-
149
- for val, it in itertools.groupby(offsets):
150
- part = ""
151
- ch = chr(ord("a") + val + 10)
152
- sz = len(list(it))
153
- if j:
154
- part = part + "+"
155
- part = part + ch if sz < 2 else part + f"{ch}*{sz}"
156
- j += sz
157
- if len(line + part) > 60:
158
- d = table_start + datetime.timedelta(j - 1)
159
- code(f" {line:<60s} # {d.year:04d}{d.month:02d}{d.day:02d}")
160
- line = part
161
- else:
162
- line = line + part
163
- d = table_start + datetime.timedelta(j - 1)
164
- code(f" {line:<60s} # {d.year:04d}{d.month:02d}{d.day:02d}")
165
- code(")")
166
121
  table_end = table_start + datetime.timedelta(len(offsets) - 1)
167
- if OLD_TABLE_START:
168
- print(f"old iersdata covered {OLD_TABLE_START} .. {OLD_TABLE_END}")
122
+ base = ord("a") + 10
123
+ offsets_bin = bytes(base + ch for ch in offsets)
124
+
125
+ target_path.write_text(
126
+ json.dumps(
127
+ {
128
+ "START": table_start.isoformat(),
129
+ "OFFSETS_GZ": binascii.b2a_base64(gzip.compress(offsets_bin)).decode("ascii").strip(),
130
+ },
131
+ ),
132
+ )
133
+
169
134
  print(f"iersdata covers {table_start} .. {table_end}")
170
135
 
171
136
 
172
137
  def iersdata_path(callback: Callable[[str, str], pathlib.Path]) -> pathlib.Path:
173
138
  """Find out the path for this directory"""
174
- print("iersdata_path", callback)
175
- r = callback("wwvbpy", "unpythonic.net") / "wwvb_iersdata.py"
176
- print(f"iersdata_path {r=!r}")
177
- return r
139
+ return callback("wwvbpy", "unpythonic.net") / "iersdata.json"
178
140
 
179
141
 
180
142
  @click.command()
wwvb/wwvbtk.py CHANGED
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/python3
2
2
  """Visualize the WWVB signal in realtime"""
3
3
 
4
- # Copyright (C) 2011-2020 Jeff Epler <jepler@gmail.com>
5
- # SPDX-FileCopyrightText: 2021 Jeff Epler
4
+ # SPDX-FileCopyrightText: 2021-2024 Jeff Epler
6
5
  #
7
6
  # SPDX-License-Identifier: GPL-3.0-only
8
7
  from __future__ import annotations
@@ -11,12 +10,15 @@ import functools
11
10
  import threading
12
11
  import time
13
12
  from tkinter import Canvas, TclError, Tk
14
- from typing import Any, Generator
13
+ from typing import TYPE_CHECKING, Any
15
14
 
16
15
  import click
17
16
 
18
17
  import wwvb
19
18
 
19
+ if TYPE_CHECKING:
20
+ from collections.abc import Generator
21
+
20
22
 
21
23
  @functools.cache
22
24
  def _app() -> Tk:
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wwvb
3
- Version: 4.0.0a0
3
+ Version: 5.0.0
4
4
  Summary: Generate WWVB timecodes for any desired time
5
- Home-page: https://github.com/jepler/wwvbpy
6
- Author: Jeff Epler
7
- Author-email: jepler@gmail.com
5
+ Author-email: Jeff Epler <jepler@gmail.com>
6
+ Project-URL: Source, https://github.com/jepler/wwvbpy
7
+ Project-URL: Documentation, https://github.com/jepler/wwvbpy
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Programming Language :: Python :: 3.9
10
10
  Classifier: Programming Language :: Python :: 3.10
@@ -22,9 +22,10 @@ Requires-Dist: leapseconddata
22
22
  Requires-Dist: platformdirs
23
23
  Requires-Dist: python-dateutil
24
24
  Requires-Dist: requests
25
+ Requires-Dist: tzdata
25
26
 
26
27
  <!--
27
- SPDX-FileCopyrightText: 2021 Jeff Epler
28
+ SPDX-FileCopyrightText: 2021-2024 Jeff Epler
28
29
 
29
30
  SPDX-License-Identifier: GPL-3.0-only
30
31
  -->
@@ -0,0 +1,18 @@
1
+ uwwvb.py,sha256=dyYlxZ6tIlcbKsWExNHKA8OtRfbziaCy5Xcj_97bGtA,5737
2
+ wwvb/__init__.py,sha256=rDpr-XLoMld473qP-ufDunQxiDbLQDeS6eN7NOBtW84,30790
3
+ wwvb/__version__.py,sha256=U7HnWMtKn0QTFHRJAzsVjr4cELMq3Toi6P5afKP6ah0,411
4
+ wwvb/decode.py,sha256=llTLKBW49nl6COheM90NsyMnTNeVApl2oeCHtl6Tf3w,2759
5
+ wwvb/dut1table.py,sha256=HVX1338RlQzAQ-bsMPEdmCqoyIxSWoJSoRu1YGyaJO4,875
6
+ wwvb/gen.py,sha256=_fpUypu_2nZfG5Vjnya0B8C26nk1WOhnLMTCXwskAHs,3720
7
+ wwvb/iersdata.json,sha256=cutY_J5jElAyLBsxfcDnP0eHY5fkQQ8Y1nDO77uEU4I,770
8
+ wwvb/iersdata.json.license,sha256=1k5fhRCuOn0yXbwHtB21G0Nntnf0qMxstflMHuK3-Js,71
9
+ wwvb/iersdata.py,sha256=_PSnGhNS5QU4AAk_aFbmR4Jru0pK_y-5JtNL6pAwtT8,1210
10
+ wwvb/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ wwvb/tz.py,sha256=nlxKnzFPmqLLtC-cEDhWaJ3v3GCSPfqzVtUMf8EEdZ0,248
12
+ wwvb/updateiers.py,sha256=2kIzgLD_109EpapdscZj7dGt8z-KzE7Yp4LhRi5NW7Q,5671
13
+ wwvb/wwvbtk.py,sha256=QBJntkgLJPPjsxYC0szDZZXajijUbuwEmU_mjGEJ4GI,4599
14
+ wwvb-5.0.0.dist-info/METADATA,sha256=nOmRifOcCGG1uEgKgr607Fxw-9vB8osk8IL1VBSQwug,10382
15
+ wwvb-5.0.0.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
16
+ wwvb-5.0.0.dist-info/entry_points.txt,sha256=KSevvHWLEKxOxUQ-L-OQidD4Sj2BPEfhZ2TQhOgyys4,179
17
+ wwvb-5.0.0.dist-info/top_level.txt,sha256=0IYdkhEAMgurpv_F-76rlyn4GdxepGFzG99tivVdQVU,11
18
+ wwvb-5.0.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.3.0)
2
+ Generator: setuptools (75.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
wwvb/iersdata_dist.py DELETED
@@ -1,38 +0,0 @@
1
- # -*- python3 -*-
2
- # fmt: off
3
- """File generated from public data - not subject to copyright"""
4
- # SPDX-FileCopyrightText: Public domain
5
- # SPDX-License-Identifier: CC0-1.0
6
- # isort: skip_file
7
- import datetime
8
- __all__ = ["DUT1_DATA_START", "DUT1_OFFSETS"]
9
- DUT1_DATA_START = datetime.date(1972, 1, 1)
10
- d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s = tuple("defghijklmnopqrs")
11
- DUT1_OFFSETS = str( # 19720101
12
- i*182+s*123+k*30+i*31+s*19+r*31+q*29+p*28+o*30+n*36+m*40 # 19730909
13
- +l*39+k*33+j*31+i*31+h*18+r*19+q*38+p*32+o*31+n*33+m*48+l*45 # 19741010
14
- +k*37+j*33+i*34+h*15+r*22+q*34+p*33+o*34+n*37+m*49+l*45+k*36 # 19751118
15
- +j*32+i*36+h*7+r*28+q*33+p*32+o*30+n*33+m*42+l*42+k*34+j*29 # 19761201
16
- +i*33+h*30+r*6+q*36+p*34+o*31+n*32+m*42+l*51+k*37+j*32+i*33 # 19771231
17
- +h*31+q*32+p*29+o*29+n*30+m*32+l*47+k*47+j*36+i*33+h*32+g*18 # 19790116
18
- +q*16+p*35+o*33+n*32+m*35+l*45+k*51+j*39+i*39+h*38+g*2+q*40 # 19800319
19
- +p*39+o*38+n*43+m*57+l*50+k*39+j*42+i*41+h*43+g*37+f*39+e*39 # 19810719
20
- +o*19+n*62+m*43+l*45+k*48+j*44+i*39+h*44+g*21+q*44+p*48+o*43 # 19821223
21
- +n*41+m*36+l*34+k*34+j*38+i*47+s+r*64+q*50+p*42+o*56+n*57 # 19840517
22
- +m*52+l*100+k*61+j*62+i*66+h*52+g*67+f+p*103+o*56+n*68+m*69 # 19860807
23
- +l*107+k*82+j*72+i*67+h*63+g*113+f*63+e*51+o*11+n*60+m*59 # 19880907
24
- +l*121+k*71+j*71+i*67+h*57+g*93+f*61+e*48+d*12+n*41+m*44 # 19900511
25
- +l*46+k*61+j*66+i*47+h*45+g*15+q*32+p*44+o*41+n*48+m*74+l*49 # 19911129
26
- +k*45+j*44+i*40+h*37+g*38+f*50+e*5+o*60+n*49+m*40+l*40+k*38 # 19930322
27
- +j*38+i*36+h*39+g*25+q*31+p*50+o*41+n*41+m*43+l*41+k*39+j*40 # 19940630
28
- +i*39+s*24+r*57+q*43+p*41+o*39+n*38+m*35+l*37+k*43+j*69+i*44 # 19951124
29
- +h*42+g*37+q*4+p*51+o*45+n*44+m*69+l*70+k*50+j*54+i*53+h*40 # 19970612
30
- +g*49+f*18+p*59+o*53+n*52+m*57+l*48+k*53+j*127+i*70+h*30 # 19990303
31
- +r*62+q*79+p*152+o*82+n*106+m*184+l*125+k*217+j*133+i*252 # 20030402
32
- +h*161+g*392+f*322+e*290+n*116+m*154+l*85+k*83+j*91+i*168 # 20080312
33
- +h*105+g*147+f*105+e*42+o*70+n*91+m*154+l*119+k*84+j*217 # 20110511
34
- +i*126+h*176+g*97+f*91+e*52+o*116+n*98+m*70+l*133+k*91+j*91 # 20140507
35
- +i*77+h*140+g*91+f*84+e*70+d*34+n*72+m*76+l*66+k*53+j*56 # 20160831
36
- +i*105+h*77+g*45+q*25+p*63+o*91+n*154+m*105+l*190+k*118 # 20190501
37
- +j*105+i*807+j*376+k*768+l*47+k*3+l*4+k*252, # 20250705
38
- )