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 +1 -1
- wwvb/__init__.py +7 -5
- wwvb/__version__.py +2 -2
- wwvb/decode.py +5 -2
- wwvb/dut1table.py +2 -2
- wwvb/gen.py +2 -3
- wwvb/iersdata.json +1 -0
- wwvb/iersdata.json.license +2 -0
- wwvb/iersdata.py +20 -11
- wwvb/tz.py +1 -2
- wwvb/updateiers.py +19 -57
- wwvb/wwvbtk.py +5 -3
- {wwvb-4.0.0a0.dist-info → wwvb-5.0.0.dist-info}/METADATA +6 -5
- wwvb-5.0.0.dist-info/RECORD +18 -0
- {wwvb-4.0.0a0.dist-info → wwvb-5.0.0.dist-info}/WHEEL +1 -1
- wwvb/iersdata_dist.py +0 -38
- wwvb/testcli.py +0 -291
- wwvb/testdaylight.py +0 -60
- wwvb/testls.py +0 -63
- wwvb/testpm.py +0 -33
- wwvb/testuwwvb.py +0 -221
- wwvb/testwwvb.py +0 -403
- wwvb-4.0.0a0.dist-info/RECORD +0 -23
- {wwvb-4.0.0a0.dist-info → wwvb-5.0.0.dist-info}/entry_points.txt +0 -0
- {wwvb-4.0.0a0.dist-info → wwvb-5.0.0.dist-info}/top_level.txt +0 -0
uwwvb.py
CHANGED
wwvb/__init__.py
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
#!/usr/bin/python3
|
2
2
|
"""A library for WWVB timecodes"""
|
3
3
|
|
4
|
-
#
|
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
|
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
wwvb/decode.py
CHANGED
@@ -6,10 +6,13 @@
|
|
6
6
|
from __future__ import annotations
|
7
7
|
|
8
8
|
import sys
|
9
|
-
from typing import
|
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__":
|
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__":
|
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
|
-
#
|
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__":
|
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=="}
|
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
|
-
#
|
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
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
29
|
+
content = json.loads(path.read_text(encoding="utf-8"))
|
24
30
|
break
|
25
31
|
|
26
|
-
|
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
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
|
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 / "
|
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
|
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
|
-
|
168
|
-
|
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
|
-
|
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
|
-
#
|
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
|
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:
|
3
|
+
Version: 5.0.0
|
4
4
|
Summary: Generate WWVB timecodes for any desired time
|
5
|
-
|
6
|
-
|
7
|
-
|
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,,
|
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
|
-
)
|