歷史分?jǐn)?shù) (最近三次結(jié)算)
日期 (G / K / A) | Guardian | Knight |
---|---|---|
2022/1/26 794 / 3970 / 15881 |
最高: 3489.204 int65536 最低: 2204.994 jelly97 |
最高: 2204.888 zhao-yang-24 最低: 1855.839 tan-ya-wen |
2022/1/18 780 / 3902 / 15611 |
最高: 3489.204 int65536 最低: 2202.661 Raymond_YP |
最高: 2202.449 tangyao0792 最低: 1854.801 yongyongyong |
2022/1/13 775 / 3876 / 15507 |
最高: 3489.204 int65536 最低: 2201.923 charleswang2001 |
最高: 2201.813 love-a-wild-horse 最低: 1854.794 blue_k |
計(jì)算方式
力扣競(jìng)賽 - 勛章及成就規(guī)則
簡(jiǎn)而言之就是:
Guardian
為 1600
分以上的所有參與競(jìng)賽人員的前 5%
Knight
為 1600
分以上的所有參與競(jìng)賽人員的前 25%
代碼
import re
import sys
from functools import cache
import requests as req
url = 'https://leetcode-cn.com/graphql'
# 分頁加載排名列表
@cache
def loadPage(page):
query = "{\nlocalRanking(page:" + str(page) + ") {\nrankingNodes {\ncurrentRating\nuser {\nusername\n}\n}\n}\n}\n"
retry = 0
while retry < 3:
resp = req.post(url=url, json={'query': query})
if resp.status_code == 200:
nodes = resp.json()['data']['localRanking']['rankingNodes']
return [(int(nd['currentRating']), nd['user']['username']) for nd in nodes]
else:
retry += 1
return None
# 根據(jù)用戶名獲取其個(gè)人主頁顯示的真實(shí)排名
# 排行榜上部分coder沒有真實(shí)排名幔翰,導(dǎo)致排行榜上的排名與個(gè)人主頁排名并不一致
# 實(shí)測(cè)LC的計(jì)算使用的排名是個(gè)人主頁的排名
@cache
def getUserRank(uid):
operationName = "userContest"
query = "query userContest($userSlug: String!){\n userContestRanking(userSlug: $userSlug){" \
"\ncurrentRatingRanking\nratingHistory\n}\n}\n "
variables = {'userSlug': uid}
retry = 0
while retry < 3:
resp = req.post(url=url, json={
'operationName': operationName,
'query': query,
'variables': variables
})
if resp.status_code == 200:
ranking = resp.json()['data']['userContestRanking']
score = None
if ranking and 'ratingHistory' in ranking:
s = ranking['ratingHistory']
mth = re.search(r'(\d+(?:\.\d+)?)(?:, null)*]$', s)
if mth:
score = mth.group(1)
return (ranking['currentRatingRanking'], score) if ranking else (None, None)
else:
retry += 1
return None, None
# 使用二分的方式獲取1600分以上的人數(shù)酣难,并使用 getUserRank 方法校準(zhǔn)
def get1600Count() -> int:
l, r = 1, 1000
while l < r:
mid = (l + r) // 2
scores = loadPage(mid)
print(f'第 {mid} 頁:', scores)
if not scores:
return 0
if scores[-1][0] < 1600:
r = mid
else:
l = mid + 1
scores = loadPage(l)
print('校準(zhǔn)中...')
while True:
for (score, uid) in scores[::-1]:
if score >= 1600:
if ret := (getUserRank(uid)[0]):
return ret
l -= 1
scores = loadPage(l)
# 獲取指定排名的用戶,并使用 getUserRank 方法校準(zhǔn)
@cache
def getUser(rank):
if rank <= 0:
raise Exception('無效的排名')
p = (rank - 1) // 25 + 1
of = (rank - 1) % 25
scores = loadPage(p)
if of >= len(scores):
raise Exception('無效的排名')
while True:
ranking = getUserRank(scores[of][1])[0]
if ranking == rank:
uid = scores[of][1]
return getUserRank(uid)[1], uid
if ranking > rank:
# 特殊情況,排名很靠后時(shí)哟冬,順序是亂的
for i in [0, 1, -1]:
if i != 0:
scores = loadPage(p + i)
for _, uid in scores:
r, s = getUserRank(uid)
if r == rank:
return s, uid
raise Exception('校準(zhǔn)失敗')
if not ranking or ranking < rank:
of += 1 if not ranking else rank - ranking
if of >= len(scores):
p += of // len(scores)
of %= len(scores)
scores = loadPage(p)
total = get1600Count()
if not total:
print('網(wǎng)絡(luò)故障')
sys.exit()
print(f'1600 分以上共計(jì) {total} 人')
guardian = int(total * 0.05)
knight = int(total * 0.25)
g_first, g_last = getUser(1), getUser(guardian)
print(f'Guardian(top 5%): 共 {guardian} 名撇他,守門員 {g_last[0]} 分(uid: {g_last[1]}),最高 {g_first[0]} 分(uid: {g_first[1]})')
k_first, k_last = getUser(guardian + 1), getUser(knight)
print(f'Knight(top 25%): 共 {knight} 名识椰,守門員 {k_last[0]} 分(uid: {k_last[1]})入愧,最高 {k_first[0]} 分(uid: {k_first[1]})')