-
Notifications
You must be signed in to change notification settings - Fork 0
/
badgemaker.py
168 lines (139 loc) · 6.04 KB
/
badgemaker.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
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
from PIL import Image, ImageDraw, ImageFont
import matplotlib.pyplot as plt
import time
import sqlite3
import requests
import json
class BadgeMakerDatabaseLink:
def __init__(self):
self.dbFile = 'lcbadge.db'
self.dbConnection = sqlite3.connect(self.dbFile, check_same_thread=False)
self.dbCursor = self.dbConnection.cursor()
def makeRecord(self, username, easy, medium, hard):
self.dbCursor.execute(f"""
INSERT INTO scores VALUES ('{username}', {easy}, {medium}, {hard}, DATE('now'))
""")
def recordExists(self, username):
res = self.dbCursor.execute(f"""
SELECT easy, medium, hard FROM scores WHERE date LIKE DATE('now') AND username LIKE '{username}'
""")
fetch = res.fetchone()
if fetch is not None:
return fetch
else:
return None
class BadgeMaker:
def __init__(self):
self.dbLink = BadgeMakerDatabaseLink()
def draw_shadow(self, draw, text, font, pos):
x, y = pos
shadowcolor = (0, 0, 0)
draw.text((x-1, y-1), text, font=font, fill=shadowcolor)
draw.text((x+1, y-1), text, font=font, fill=shadowcolor)
draw.text((x-1, y+1), text, font=font, fill=shadowcolor)
draw.text((x+1, y+1), text, font=font, fill=shadowcolor)
def getTotalProblems(self, username="awmc2000"):
if self.cachedResponse is None:
# GraphQL query
query = """
query getUserProfile($username: String!) {
allQuestionsCount {
difficulty
count
}
matchedUser(username: $username) {
username
submitStats {
acSubmissionNum {
difficulty
count
}
}
}
}
"""
# Prepare GraphQL POST request
variables = {"username": username}
response = requests.post('https://leetcode.com/graphql',
json={"query": query, "variables": variables})
deserialize = json.loads(response.text)
else:
deserialize = self.cachedResponse
counts = deserialize['data']['allQuestionsCount']
return (counts[1]['count'], counts[2]['count'], counts[3]['count'])
def getSolved(self, username):
# Check if we already fetched their data today before fetching it again.
exists = self.dbLink.recordExists(username)
if exists:
return exists
# GraphQL query
query = """
query getUserProfile($username: String!) {
allQuestionsCount {
difficulty
count
}
matchedUser(username: $username) {
username
submitStats {
acSubmissionNum {
difficulty
count
}
}
}
}
"""
# Prepare GraphQL POST request
variables = {"username": username}
response = requests.post('https://leetcode.com/graphql',
json={"query": query, "variables": variables})
deserialize = json.loads(response.text)
# Update the cached response each time,
# in case there are new problems added
self.cachedResponse = deserialize
# If that username does not exist, this key will exist
if 'errors' in deserialize.keys():
return (0, 0, 0)
# Extract the number of each problem type solved
submissions = deserialize['data']['matchedUser']['submitStats']['acSubmissionNum']
easySolved = int(submissions[1]['count'])
medSolved = int(submissions[2]['count'])
hardSolved = int(submissions[3]['count'])
# Make a record so they cannot request a new image in the same day.
self.dbLink.makeRecord(username, easySolved, medSolved, hardSolved)
return (easySolved, medSolved, hardSolved)
def createBadge(self, username):
easySolved, medSolved, hardSolved = self.getSolved(username)
filename = f'pngs/lcbadge-{username}-{time.asctime()}.png'
with Image.open('template-retro.png') as im:
font = ImageFont.truetype('univers.ttf', 8)
font2 = ImageFont.truetype('univers.ttf', 10)
easyFill = (28, 186, 186)
medFill = (255, 183, 0)
hardFill = (246, 55, 55)
draw = ImageDraw.Draw(im)
positions = {'username': (2, 0), 'easy': (4, 10), 'medium': (35, 10),
'hard': (70, 10), 'join me': (2, 20)}
draw.text(positions['username'], f'{username} solved', (0,0,0), font=font)
self.draw_shadow(draw, f'{easySolved}', font2, positions['easy'])
draw.text(positions['easy'], f'{easySolved}', easyFill, font=font2)
self.draw_shadow(draw, f'{medSolved}', font2, positions['medium'])
draw.text(positions['medium'], f'{medSolved}', medFill, font=font2)
self.draw_shadow(draw, f'{hardSolved}', font2, positions['hard'])
draw.text(positions['hard'], f'{hardSolved}', hardFill, font=font2)
draw.text(positions['join me'], f'Join me on LeetCode!', (0,0,0), font=font)
im.save(filename)
return filename
def createPieChart(self, username):
easySolved, medSolved, hardSolved = self.getSolved(username)
easyTotal, medTotal, hardTotal = self.getTotalProblems(username)
solved = easySolved + medSolved + hardSolved
unsolved = easyTotal + medTotal + hardTotal - solved
labels = ["Easy", "Medium", "Hard", "Unsolved"]
fig, ax = plt.subplots()
ax.pie([easySolved, medSolved, hardSolved, unsolved], labels=labels,
colors=['green', 'yellow', 'red', 'gray'])
filename = f'pngs/lcpie-{username}-{time.asctime()}.png'
plt.savefig(filename, bbox_inches='tight')
return filename