-
Notifications
You must be signed in to change notification settings - Fork 1
/
ContestParser.py
87 lines (78 loc) · 3.27 KB
/
ContestParser.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
import requests, hashlib, random, time
from requests.packages.urllib3.util.retry import Retry
from requests.adapters import HTTPAdapter
retry_strategy = Retry(
total=10, # Maximum number of retries
backoff_factor=2, # Exponential backoff factor (e.g., 2 means 1, 2, 4, 8 seconds, ...)
status_forcelist=[429, 500, 502, 503, 504, 522, 524, 401, 403, 404], # Status codes to retry
)
adapter = HTTPAdapter(max_retries=retry_strategy)
http = requests.Session()
http.mount("https://", adapter)
http.mount("http://", adapter)
class ContestParser:
def __init__(self, groupId, contestId, APIKey, APISecret) -> None:
self.groupId = groupId
self.contestId = contestId
self.apiKey = APIKey
self.apiSecret = APISecret
def __request(self, methodName, optionalMethod=""):
rand = random.randint(0, 100000)
rand = str(rand).zfill(6)
currentTime = str(int(time.time()))
apiSig = rand + "/" + methodName + "?apiKey=" + self.apiKey + \
"&contestId=" + self.contestId + "&groupCode=" + self.groupId + optionalMethod + \
"&time=" + currentTime + "#" + self.apiSecret
hash = hashlib.sha512(apiSig.encode()).hexdigest()
apiCommand = f"https://codeforces.com/api/{methodName}?groupCode={self.groupId}&contestId={self.contestId}{optionalMethod}&apiKey={self.apiKey}&time={currentTime}&apiSig={rand+hash}"
data = http.get(apiCommand).json()
return data["status"], data["result"]
def __getStandings(self):
status, data = self.__request("contest.standings")
problems = []
for problem in data["problems"]:
problems.append(problem["index"])
handles = []
for row in data["rows"]:
handles.append(row["party"]["members"][0]["handle"]) #index is 0 because there is only 1 member (not a team)
return problems, handles
def __getFirstAC(self, handle, problemList):
status, submissions = self.__request("contest.status", f"&handle={handle}")
ACSubs = {}
for problem in problemList:
ACSubs[problem] = 0;
for i in range(len(submissions)-1, -1, -1):
if submissions[i]["verdict"] == "OK":
problemId = submissions[i]["problem"]["index"] #in alphabet
subId = submissions[i]["id"]
if (ACSubs[problemId] == 0):
ACSubs[problemId] = subId
return ACSubs
def __getData(self):
problems, handles = self.__getStandings()
data = {
"groupId": self.groupId,
"contestId": self.contestId,
"problems": problems,
"handles": handles,
"solved": []
}
print("Start generating database...")
for handle in handles:
print(f"Analyzing {handle}...", end="")
time.sleep(1)
try:
subs = self.__getFirstAC(handle, problems)
print("done")
except:
print("failed")
finally:
userdata = {
"handle": handle,
"submission": subs
}
data["solved"].append(userdata)
print("Done.")
return data
def get(self):
return self.__getData()