-
Notifications
You must be signed in to change notification settings - Fork 1
/
algoalgo_member.py
371 lines (307 loc) · 12.6 KB
/
algoalgo_member.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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
import unicodedata
import requests
from bs4 import BeautifulSoup
from random import randint
import algoalgo_bj_crawling
import algoalgo_sql
def adduser(author, cmd):
args = cmd.split()
if author == "admin" and len(args) != 5:
return "[!] Usage : !adduser <name> <student_id> <baekjoon_id> <discord_id>"
elif author != "admin" and len(args) != 4:
return "[!] Usage : !adduser <name> <student_id> <baekjoon_id>"
# !adduser <이름> <학번> <백준 아이디>
dc_id = author if author != "admin" else args[4]
name = args[1]
s_id = args[2]
bj_id = args[3]
bj_solved = algoalgo_bj_crawling.getBJSolved(bj_id)
sql = "insert into member (discord_id, student_id, name, baekjoon_id, bj_solved) value (%s, %s, %s, %s, %s);"
try:
algoalgo_sql.sql_update(sql, dc_id, s_id, name, bj_id, bj_solved)
except Exception as ex:
return f"[!] An error occurs while adding user({author}) into db....\n[INFO] error : {ex}"
return f"[+] success adding user into db...{author}"
def showuserinfo(author):
sql = f"select * from member where discord_id='{str(author)}';"
try:
sql_result = algoalgo_sql.sql_exe(sql)
item_dir = show_items(sql_result[0]['items'])
# status : 1, 2, 3에 맞는 값을 각각 문자열로 풀어서 출력
# items : 아이템 보유 개수 정리해서 출력
userinfo = f"""discord_id : {sql_result[0]['discord_id']}
name : {sql_result[0]['name']}
**- GAME INFO**
status : {sql_result[0]['status']}
your steps on today : {sql_result[0]['daily_steps']}
your point : {sql_result[0]['point']}
your location : {sql_result[0]['map_location']}
**- items**
```
STEP | {item_dir['STEP']}
SNAKE | {item_dir['SNAKE']}
STUN | {item_dir['STUN']}
ASSASSIN | {item_dir['ASSASSIN']}
REDEMPTION | {item_dir['REDEMPTION']} ```
**- BAEKJOON INFO**
baekjoon id : {sql_result[0]['baekjoon_id']}
Continuous Days of Mission : {sql_result[0]['bj_solv_contd']}
"""
return f"[*] Successfully Inquires data about {author}", userinfo
except Exception as ex:
return f"[!] An error occurs while finding user({author}) in db....\n[INFO] error : {ex}", None
def fill_str_with_space(input_s="", max_size=27, fill_char=" "):
l = 0
for c in input_s:
if unicodedata.east_asian_width(c) in ['F', 'W']:
l+=2
else:
l+=1
return input_s+fill_char*(max_size-l)
def addpoint(cmd):
args = cmd.split(' ')
if len(args) != 3:
return "[!] Usage : !addpoint <archivement id> <student_id or discord_id>"
# !addpoint <업적 번호> <학번 또는 디스코드 닉네임>
# 업적 정보 확인
try:
result = algoalgo_sql.sql_exe("SELECT points, achive_name FROM achievement WHERE id = %s", args[1])[0]
except Exception as ex:
return f"[!] An error occurs while check the db....\n[INFO] error : {ex}"
point = result['points']
achname = result['achive_name']
# 포인트 업데이트
if args[2].find('#') == -1: # 학번 입력시
sql = "UPDATE member SET point = point+%s WHERE student_id = %s;"
try:
algoalgo_sql.sql_update(sql, point, args[2])
name = algoalgo_sql.sql_exe("SELECT discord_id FROM member WHERE student_id = %s", args[2])[0]['discord_id']
except Exception as ex:
return f"[!] An error occurs while update the point into db....\n[INFO] error : {ex}"
else: # 디스코드 닉네임 입력시
name = args[2]
try:
sql = "UPDATE member SET point = point+%s WHERE discord_id = %s;"
algoalgo_sql.sql_update(sql, point, name)
except Exception as ex:
return f"[!] An error occurs while update the point into db....\n[INFO] error : {ex}"
return f"[+] Mission Accomplished: {achname} by {name}"
def refresh():
try:
algoalgo_sql.sql_update("UPDATE member SET daily_steps = 0") # 일일 문제풀이 가능 횟수
algoalgo_sql.sql_update("UPDATE member SET status = 0 WHERE status = -1") # Stun 초기화
# 연속 업적 달성 확인
algoalgo_sql.sql_update("UPDATE member SET bj_solv_contd = bj_solv_contd+1 WHERE bj_today <> 0")
algoalgo_sql.sql_update("UPDATE member SET bj_solv_contd = 0 WHERE bj_today = 0")
algoalgo_sql.sql_update("UPDATE member SET bj_today = 0")
# 연속 업적 달성자 업적 반영
sids = algoalgo_sql.sql_exe("SELECT student_id, bj_solv_contd FROM member WHERE bj_solv_contd IN (5, 14, 30)")
for sid in sids:
# 달성 업적 확인
if sid['bj_solv_contd'] == 5:
aid = 12
elif sid['bj_solv_contd'] == 14:
aid = 13
else:
aid = 14
addpoint(f"!addpoint {aid} {sid['student_id']}")
except Exception as ex:
return f"[!] An error occurs while refresh db....\n[INFO] error : {ex}"
print('refresh done')
return f"[+] Refresh Done"
def list_achievement():
# DB에서 업적 목록 확인
try:
achlist = algoalgo_sql.sql_exe("SELECT description, points FROM achievement WHERE is_hidden = 0")
except Exception as ex:
return f"[!] An error occurs while check db....\n[INFO] error : {ex}"
# 업적 목록 만들기
printlist = []
for ach in achlist:
printlist.append(f"{fill_str_with_space(ach['description'])}{ach['points']} 포인트")
return "\n".join(printlist)
"""printlist = []
printlist.append("| Title | Points |")
printlist.append("| :-----: | ----: |")
for ach in achlist:
printlist.append(f"| {ach['description']} | {ach['points']} |")"""
def problem_rank_update():
# solved.ac 크롤러
def crawler(url):
soup = BeautifulSoup(requests.get(url).text, 'html.parser')
text = soup.select('a.gLFkLK > span')
if len(text) == 0:
return 0
else:
qids = []
for item in text:
qids.append(int(item.text))
return qids
# 해당 랭크 문제 목록 가져오기
def get_problem_list(rank):
problemsbyrank = []
page = 1
while page != 0:
ids = crawler(f'https://solved.ac/problems/level/{rank}?sort=id&direction=ascending&page={page}')
if ids == 0:
page = 0
else:
problemsbyrank += ids
page += 1
return problemsbyrank
# 해당 랭크 문제 목록 DB 저장
def save_problem_list(rank):
sql = "insert into solved_rank (id, rank) values (%s, %s);"
vals = []
for problem in get_problem_list(rank):
vals.append([problem, rank])
try:
algoalgo_sql.sql_update_many(sql, vals)
except Exception as ex:
print(ex)
return f"[!] An error occurs while updating problem ranks into db....\n[INFO] error : {ex}"
# Bronze 5 ~ Ruby 1 업데이트
print("starting update")
for rank in range(1, 31):
save_problem_list(rank)
print(rank)
print('done')
return f"[+] Successfully Updated Rank & Problem Table"
# BOJ 푼 문제 목록 크롤러
def get_solved(bojid):
soup = BeautifulSoup(requests.get(f'https://www.acmicpc.net/user/{bojid}').text, 'html.parser')
text = soup.select_one('div.panel-body')
solved = text.text.split('\n')[1:-1]
return solved
def random_bj(author, cmd):
args = cmd.split()
if len(args) != 2:
return "[!] Usage : !random_bj <tier>"
tier = args[1]
# 요청자 BOJ id 및 푼 문제 목록 확인
try:
bojid = algoalgo_sql.sql_exe("SELECT baekjoon_id FROM member WHERE discord_id = %s", author)[0]['baekjoon_id']
except Exception as ex:
return f"[!] An error occurs while check db....\n[INFO] error : {ex}"
solved = get_solved(bojid)
# 티어별 시작점 설정
if tier == 'bronze':
startfrom = 1
elif tier == 'silver':
startfrom = 6
elif tier == 'gold':
startfrom = 11
elif tier == 'platinum':
startfrom = 16
elif tier == 'diamond':
startfrom = 21
elif tier == 'ruby':
startfrom = 26
else:
return "[!] There is no such tier in solved.ac."
# DB에서 해당 티어 문제 목록 가져오기
sql = "SELECT id FROM solved_rank WHERE rank >= %s and rank < %s;"
try:
result = algoalgo_sql.sql_exe(sql, startfrom, startfrom+5)
except Exception as ex:
return f"[!] An error occurs while check db....\n[INFO] error : {ex}"
candidate = []
for item in result:
candidate.append(item['id'])
# 푼 적 없는 랜덤 문제 추천
count = 0
while count != len(candidate):
rbj = candidate[randint(0, len(candidate))]
if rbj not in solved:
break;
# 결과 반환
if count == len(candidate):
return "[!] You've Solved All Problems."
else:
return f'https://www.acmicpc.net/problem/{rbj}'
def daily_baekjoon(author, cmd):
args = cmd.split()
if len(args) != 2:
return "[!] Usage : !daily_baekjoon <Problem id>"
# 입력된 문제 번호
pid = args[1]
# 인증된 푼 문제 목록
try:
solvedlist = algoalgo_sql.sql_exe("SELECT bj_solved FROM member WHERE discord_id = %s", author)[0]['bj_solved']
except Exception as ex:
return f"[!] An error occurs while check db....\n[INFO] error : {ex}"
if solvedlist == None:
solvedlist = ""
# 이미 인증된 문제
if pid in solvedlist.split(';')[:-1]:
return "[!] Already Registered Problem"
# 아직 풀지 않은 문제
try:
solvedlist_db = get_solved(algoalgo_sql.sql_exe("SELECT baekjoon_id FROM member WHERE discord_id = %s", author)[0]['baekjoon_id'])
except Exception as ex:
return f"[!] An error occurs while check db....\n[INFO] error : {ex}"
if pid not in solvedlist_db:
return "[!] You Haven't Solved the Problem Yet."
# 신규 1일 1백준 인증 및 add point
solvedlist += (str(pid) + ';')
try:
algoalgo_sql.sql_update("UPDATE member SET bj_solved = %s WHERE discord_id = %s", solvedlist, author)
addpoint(f"!addpoint 11 {author}")
algoalgo_sql.sql_update("UPDATE member SET bj_today = 1 WHERE discord_id = %s", author)
except Exception as ex:
return f"[!] An error occurs while update certification into db....\n[INFO] error : {ex}"
return "[+] Successfully Certified."
def unlock(author):
try:
memberinfo = algoalgo_sql.sql_exe("SELECT status, map_location, baekjoon_id, bj_solved FROM member WHERE discord_id = %s", author)[0]
except Exception as ex:
return f"[!] An error occurs while check db....\n[INFO] error : {ex}"
# 이미 잠금 해제된 경우
if memberinfo['status'] == 1:
return "[!] Already Unlocked."
# 스턴에 걸린 경우
if memberinfo['status'] == -1:
return "[!] You've got Stunned. Try Again Tomorrow."
if memberinfo['status'] == 0:
# 풀어야 하는 문제 확인
try:
pid = algoalgo_sql.sql_exe("SELECT baekjoon_no FROM map WHERE id = %s", memberinfo['map_location'])[0]['baekjoon_no']
except Exception as ex:
return f"[!] An error occurs while check db....\n[INFO] error : {ex}"
# 정상 해제 시도
if pid in get_solved(memberinfo['baekjoon_id']):
try:
algoalgo_sql.sql_update("UPDATE member SET status = 1 WHERE baekjoon_id = %s", memberinfo['baekjoon_id'])
except Exception as ex:
return f"[!] An error occurs while update status into db....\n[INFO] error : {ex}"
# DB에 인증되지 않았을 경우 인증 진행
if pid not in memberinfo['bj_solved'].split(';')[:-1]:
memberinfo['bj_solved'] += (str(pid) + ';')
return "[*] Successfully Unlocked."
# 문제를 풀지 않은 경우
else:
return "[!] You haven't Solved The Problem."
# 그 외의 에러
else:
return "[!] Status Error: Call the Admins"
def show_items(items_list):
try:
item_dir = {"STEP" : 0,
"SNAKE" : 0,
"STUN" : 0,
"ASSASSIN" : 0,
"REDEMPTION" : 0,
"CAFFEINE" : 0,
"BOMB" : 0,
"RED BULL" : 0
}
if items_list != None:
items_list = items_list.rstrip(';')
items = items_list.split(';')
for item in items:
if len(item) == 0:
continue
item_dir[item] += 1
return item_dir
except Exception as ex:
raise ex