Files
@ c234eb08d816
Branch filter:
Location: Rank-Progress/rank_progress.py - annotation
c234eb08d816
5.2 KiB
text/x-python
fixed wrong rating reset
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | f16ea61e1ace ddeb551e1404 0e7c4e24c743 ddeb551e1404 ddeb551e1404 455d2af528a8 ddeb551e1404 b9be6aa9ece0 f16ea61e1ace 0e7c4e24c743 f16ea61e1ace b9be6aa9ece0 ddeb551e1404 ddeb551e1404 3d0ab62fd174 3d0ab62fd174 2156c5a17dfe 2156c5a17dfe 3d0ab62fd174 3d0ab62fd174 3d0ab62fd174 3d0ab62fd174 3d0ab62fd174 3d0ab62fd174 3d0ab62fd174 3d0ab62fd174 068be3e00177 3d0ab62fd174 3d0ab62fd174 3d0ab62fd174 3d0ab62fd174 3d0ab62fd174 3d0ab62fd174 3d0ab62fd174 3d0ab62fd174 3d0ab62fd174 3d0ab62fd174 3d0ab62fd174 2156c5a17dfe 2156c5a17dfe 3d0ab62fd174 3d0ab62fd174 d908ea134adb d908ea134adb 6644c5267fb5 c234eb08d816 d908ea134adb 2a3c04d47300 d908ea134adb d908ea134adb d908ea134adb d908ea134adb d908ea134adb 068be3e00177 068be3e00177 068be3e00177 068be3e00177 c234eb08d816 c234eb08d816 c234eb08d816 c234eb08d816 d908ea134adb 6644c5267fb5 d908ea134adb 6644c5267fb5 d908ea134adb c234eb08d816 c234eb08d816 d908ea134adb 6644c5267fb5 d908ea134adb 2a3c04d47300 2a3c04d47300 2a3c04d47300 2a3c04d47300 2a3c04d47300 d908ea134adb 2a3c04d47300 6644c5267fb5 d908ea134adb 2a3c04d47300 d908ea134adb d908ea134adb d908ea134adb 6644c5267fb5 6644c5267fb5 9598ea1d80e2 9598ea1d80e2 9598ea1d80e2 9598ea1d80e2 9598ea1d80e2 d908ea134adb d908ea134adb ddeb551e1404 ddeb551e1404 ddeb551e1404 ddeb551e1404 ddeb551e1404 ddeb551e1404 ddeb551e1404 ddeb551e1404 ddeb551e1404 ddeb551e1404 2156c5a17dfe 2156c5a17dfe 2156c5a17dfe 2156c5a17dfe 2156c5a17dfe 2156c5a17dfe 4ade6373edba d908ea134adb d908ea134adb d908ea134adb d908ea134adb 0e7c4e24c743 455d2af528a8 455d2af528a8 455d2af528a8 ddeb551e1404 d908ea134adb d908ea134adb 068be3e00177 d908ea134adb d908ea134adb d908ea134adb d908ea134adb c234eb08d816 068be3e00177 ddeb551e1404 068be3e00177 068be3e00177 068be3e00177 068be3e00177 d908ea134adb ddeb551e1404 d908ea134adb d908ea134adb d908ea134adb 455d2af528a8 455d2af528a8 455d2af528a8 455d2af528a8 455d2af528a8 4ade6373edba 4ade6373edba 4ade6373edba b9be6aa9ece0 b9be6aa9ece0 b9be6aa9ece0 4ade6373edba 4ade6373edba 4ade6373edba 0e7c4e24c743 4ade6373edba 4ade6373edba 4ade6373edba 4ade6373edba 4ade6373edba 4ade6373edba 0e7c4e24c743 0e7c4e24c743 0e7c4e24c743 882866aa38f6 0e7c4e24c743 0e7c4e24c743 0e7c4e24c743 f16ea61e1ace f16ea61e1ace f16ea61e1ace f16ea61e1ace 882866aa38f6 f16ea61e1ace f16ea61e1ace f16ea61e1ace f16ea61e1ace f16ea61e1ace f16ea61e1ace f16ea61e1ace 4ade6373edba 0e7c4e24c743 0e7c4e24c743 0e7c4e24c743 455d2af528a8 | import sys
import re
import io
from itertools import groupby
from datetime import datetime
import shutil
import argparse
import zlib
from zipfile import ZipFile
import urllib.request
from urllib.error import URLError
from base64 import b64decode
class Record:
def __init__(self, tokens, source):
self.source = source
self.pin = int(tokens[0])
self.country_code = tokens[2]
self.rating_before = int(tokens[8])
self.rating_after = int(tokens[9])
tournament_code = tokens[5]
self.date = datetime.strptime(tournament_code[1:7], "%y%m%d")
self.rank_change = ("", "")
@classmethod
def parse(cls, line):
tokens = re.split(r" {2,}", line.strip())
if len(tokens) != 10:
return None
return cls(tokens, line)
def __str__(self):
s = self.source + " {} -> {}".format(*self.rank_change)
return s
class RankTracker:
def __init__(self, rating):
assert rating >= -900
self._precise_rating = rating
self._rounded_rating = round_rating(rating)
self._best = self._rounded_rating
@property
def rank(self):
return rating_to_rank(self._rounded_rating)
@property
def rounded_rating(self):
return self._rounded_rating
@property
def precise_rating(self):
return self._precise_rating
def update(self, rating):
assert rating >= -900
rounded_rating = round_rating(rating)
old_rank = self.rank
self._precise_rating = rating
if rounded_rating == self._rounded_rating:
pass
elif rounded_rating > self._rounded_rating: # promotion
# when pushing the best by 2 and more ranks you have to cross the hundred, not just the fifty
if rounded_rating >= self._best+200 and rating < rounded_rating:
self._rounded_rating = rounded_rating-100
else:
self._rounded_rating = rounded_rating
else: # demotion
# 100 points for 5k and better
if self._rounded_rating >= 1600 and self._rounded_rating - rating > 100:
self._rounded_rating = rounded_rating
# 150 points for the others
elif self._rounded_rating - rating > 150:
self._rounded_rating = rounded_rating+100
else:
pass
if self._rounded_rating > self._best and self.rank != old_rank:
self._best = self._rounded_rating
return self.rank
else:
return False
def parse_record(record):
types = [int, str, str, str, str, str, int, int, int, int]
columns = [f(token) for (f, token) in zip(types, record)] + [datetime.strptime(record[5][1:7], "%y%m%d")]
return tuple(columns)
def round_rating(r):
return (r+50)//100*100
def rating_to_rank(rating):
rank_list = [str(i)+"k" for i in range(30, 0, -1)] + [str(i)+"d" for i in range(1, 8)]
key = round_rating(rating)//100
return rank_list[min(key+9, 36)]
def main(s, since, to, args):
records = [Record.parse(line) for line in s.splitlines()]
records = filter(lambda rec: rec is not None, records)
national_records = filter(lambda rec: rec.country_code == args.country_code, records)
player_records = groupby(national_records, lambda rec: rec.pin)
print("Detecting rank changes...")
hr = "=" * shutil.get_terminal_size().columns
found_anything = False
print(hr)
for (pin, recs) in player_records:
tourneys = list(recs)
tracker = RankTracker(tourneys[0].rating_before)
steps = []
for r in tourneys:
# omit reset ratings
if tracker.precise_rating != r.rating_before:
tracker = RankTracker(r.rating_before)
old_rank = tracker.rank
new_rank = tracker.update(r.rating_after)
if new_rank is not False:
r.rank_change = (old_rank, new_rank)
steps.append(r)
steps = [r for r in steps if since <= r.date <= to]
if steps:
print("\n".join(map(str, steps)))
found_anything = True
if not found_anything:
print("Nothing found.")
print(hr)
if __name__ == "__main__":
copyright_notice = str(zlib.decompress(b64decode(b'eJw1zk0OgjAUBOCrzAUsIa5wZdiwMYYYiOvSPoEALXl9+HcbzmK8lzXGzazmy8yZexFyaB6otKXX+l6REw+TdtDOYuwNuUAWi7PEKI41ivKA6xae4ehGrFB1hOAXNgTjbYxoG8LFRwMt6ETmsEsSptmrNLunmTLP5KTdsCnZt0whQCFf2vCn3yZLXBUPUc3vz54m3Y+RfgDMjz+e')), encoding="utf-8")
parser = argparse.ArgumentParser(epilog=copyright_notice)
parser.add_argument("since", help="a date in YYYYMMDD format")
parser.add_argument("to", nargs="?", help="a date in YYYYMMDD format")
parser.add_argument("-c", "--country-code", default="CZ", help="a two letter country code, default=CZ")
parser.add_argument("-f", "--file", help="a path to the rating history file")
args = parser.parse_args()
since = datetime.strptime(args.since, "%Y%m%d")
to = datetime.strptime(args.to, "%Y%m%d") if args.to else datetime.now()
if args.file:
print("Reading {} ...".format(args.file))
with ZipFile(args.file) as f:
s = f.read("all.hst").decode("iso8859")
else:
url = "https://europeangodatabase.eu/EGD/EGD_2_0/downloads/hisgor.zip"
print("Downloading data from {} ...".format(url))
try:
with urllib.request.urlopen(url) as f:
compressed_data = f.read()
with ZipFile(io.BytesIO(compressed_data)) as g:
s = g.read("all.hst").decode("iso8859")
except URLError as e:
print(
"* Failed to connect to the server. "
"You can try again later or download {} and run the program with the -f parameter.\n"
"The error message:\n{}".format(url, e)
)
sys.exit(1)
print("Processing...")
main(s, since, to, args)
print("Done.")
|