-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmortal_parse.py
111 lines (105 loc) · 4 KB
/
mortal_parse.py
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
import requests
import sys
import os
from joblib import Memory
import argparse
from bs4 import BeautifulSoup
import json
memory = Memory("cachedir", verbose=0)
@memory.cache
def get_html(url):
response = requests.get(url)
data = {}
data['soup'] = BeautifulSoup(response.content, 'html.parser')
return data
def parse_html(data):
pid = data['soup'].find(string='player id')
pid = int(pid.next.contents[0])
rating = data['soup'].find(string='rating')
rating = float(rating.next.contents[0])
dahaiDecisionCount = 0
notMatchMoveCount = 0
nagaRate = 0
badMoveCount = 0
RiichiState = None
details = data['soup'].find_all('details', {'class':'collapse entry'})
for d in details:
if "Turn 1 " in d.findChild('summary').contents[0]:
RiichiState = None # reset state
if RiichiState == 'complete':
# Skip if we riiched a previous turn
continue
roles = d.findChildren('span', {'class':'role'})
p_action = roles[0].nextSibling
if "Riichi" in p_action:
# Set flag so we process the Riichi discard next
RiichiState = 'discarding'
if not "Discard" in p_action:
# Only do stats on discards
continue
if RiichiState == "discarding":
# We are now processing the riichi discard set the state now
RiichiState = 'complete'
dahaiDecisionCount += 1
p_discard = roles[0].contents[0].find_next('use')['href']
m_discard = roles[1].contents[0].find_next('use')['href']
#print(p_discard, m_discard)
if p_discard != m_discard: notMatchMoveCount += 1
tbody = d.find('tbody')
for row in tbody.findChildren('tr'):
td = row.findChild('td')
if "Riichi" in td.contents[0]:
tile = None
else:
tile = td.contents[1].findChild('use')['href']
i = td.findChildren('span', {'class':'int'})
f = td.findChildren('span', {'class':'frac'})
Qval = float(f'{i[0].contents[0]}{f[0].contents[0]}')
Pval = float(f'{i[1].contents[0]}{f[1].contents[0]}')/100
if tile == m_discard:
m_Pval = Pval
if tile == p_discard:
p_Pval = Pval
if Pval < 0.05:
badMoveCount += 1
diff = m_Pval - p_Pval
nagaRate += diff
#print('count, match, score, bad')
details = data['soup'].find_all('textarea')
json_log = json.loads(details[-1].contents[0])
final_scores = json_log['log'][0][1]
final_diff = json_log['log'][0][16][1]
final_scores = [x+y for x,y in zip(final_scores, final_diff)]
# Hack to break ties. p0 = first dealer = wins ties so add the most
final_scores = [x+y for x,y in zip(final_scores, [3, 2, 1, 0])]
sorted_scores = sorted(final_scores)
placement = [4-sorted_scores.index(score) for score in final_scores]
final_scores = [x+y for x,y in zip(final_scores, [-3, -2, -1, 0])] #undo
print('{:1d}, {:s}, {:1d}, {:5d}, {:3d}, {:2.1f}, {:2.1f}, {:2.1f}, {:2.1f}'.format(
pid,
data['url'],
placement[pid],
final_scores[pid],
dahaiDecisionCount,
(dahaiDecisionCount - notMatchMoveCount)/dahaiDecisionCount*100,
(dahaiDecisionCount - nagaRate)/dahaiDecisionCount*100,
(badMoveCount/dahaiDecisionCount*100),
rating
))
def main():
parser = argparse.ArgumentParser(description="Naga log parser")
parser.add_argument('-u', '--url', help='URL')
parser.add_argument('-f', '--file', help='File with list of urls')
args = parser.parse_args()
if args.file:
with open(args.file, "r") as f:
url_list = f.read().splitlines()
url_list = [item.strip() for item in url_list if item.startswith("https://mjai")]
else:
url_list = [args.url]
for url in url_list:
data = get_html(url)
data['url'] = url
parse_html(data)
if __name__ == "__main__":
main()