pokemon-quiz / app.py
Yoon-gu Hwang
κ°κ΄€μ‹μœΌλ‘œ λ³€κ²½
ccdda9e
raw
history blame
10.6 kB
import os
import gradio as gr
import pandas as pd
import random
import json
import time
import wandb
from copy import deepcopy
from collections import defaultdict
wandb.login(key=os.environ['WANDB_KEY'])
run = wandb.init(project="pokemon-quiz", entity="yoon-gu")
with open('pokemon.json', 'r') as f:
pokemons = json.load(f)
pokemons_types = ["λͺ¨λ“  νƒ€μž…"] + sorted(set([t for poke in pokemons for t in poke['types']]))
df = pd.DataFrame(pokemons)
GEN_RANGE = {
"λͺ¨λ“  μ„ΈλŒ€": [1, 1017],
"1μ„ΈλŒ€": [1, 151],
"2μ„ΈλŒ€": [152, 251],
"3μ„ΈλŒ€": [252, 386],
"4μ„ΈλŒ€": [387, 493],
"5μ„ΈλŒ€": [494, 649],
"6μ„ΈλŒ€": [650, 721],
"7μ„ΈλŒ€": [722, 809],
"8μ„ΈλŒ€": [810, 905],
"9μ„ΈλŒ€": [906, 1017]
}
QUESTION_TEMPLATE = {"question": "λ‹€μŒ 포켓λͺ¬μ˜ 이름은 λ­˜κΉŒμš”?![]({img_url})", "answer": "{name}"}
def get_question_answer(pokemons_set):
chosen = random.choice(pokemons_set)
name = chosen['name'].replace("♀", "μ•”μ»·").replace("β™‚", "수컷")
image_path = chosen['image_path']
img_url = f"https://huggingface.co/spaces/yoon-gu/pokemon/resolve/main/{image_path}"
q = QUESTION_TEMPLATE["question"].format(img_url=img_url)
a = QUESTION_TEMPLATE['answer'].format(name=name)
candidates = random.choices([poke['name'] for poke in pokemons_set], k=3)
candidates.append(a)
random.shuffle(candidates)
random_buttons = [gr.Button(value=f"{name}") for name in candidates]
return q, a, random_buttons
initial_info = {"done" : True,
"score": 0, "count": 0,
"best_score": 0, "best_time": float("inf"),
"time": 0.0, "comment": "",
"history": []}
try:
folder = run.use_artifact("settings:latest").download()
with open(os.path.join(folder, "users.json"), "r") as f:
USERS = json.load(f)
with open(os.path.join(folder, "info.json"), "r") as f:
info = json.load(f)
except:
info = defaultdict(lambda : deepcopy(initial_info))
USERS = ["κΉ€μ„œν˜„", "κΉ€μš°μ£Ό", "Anonymous"]
for user in USERS:
print(info[user])
MD = """# 포켓λͺ¬ ν€΄μ¦ˆ
## 곡뢀 방법
μ•„λž˜ 포켓λͺ¬ 도감을 보고 κ³΅λΆ€ν•˜λ©΄ 도움이 λ©λ‹ˆλ‹€.
- https://huggingface.co/spaces/yoon-gu/pokemon
## μ‚¬μš©λ°©λ²•
1. μ‚¬μš©μžλ₯Ό μ„ νƒν•˜μ„Έμš”.
2. 총 ν€΄μ¦ˆ 개수λ₯Ό μ„ νƒν•˜μ„Έμš”.
3. 포켓λͺ¬ μ„ΈλŒ€λ₯Ό μ„ νƒν•˜μ„Έμš”.
4. 포켓λͺ¬ νƒ€μž…μ„ μ„ νƒν•˜μ„Έμš”.
## 점수판
"""
with gr.Blocks() as demo:
with gr.Row():
with gr.Column():
markdown = gr.Markdown(MD.format(content=''))
leader_board = gr.DataFrame(wrap=True, row_count=10)
user = gr.Dropdown(USERS, value="Anonymous", label="μ‚¬μš©μž", info="당신은 λˆ„κ΅¬μ‹ κ°€μš”?", allow_custom_value=True)
quiz_count = gr.Radio([10, 20, 30], value=10, label="총 ν€΄μ¦ˆ 개수", info="ν€΄μ¦ˆλ₯Ό λͺ‡ 개 ν’€ μ˜ˆμ •μΈκ°€μš”?")
with gr.Column():
with gr.Row():
generation = gr.Dropdown(
[f"{k}μ„ΈλŒ€" for k in range(1, 10)] + ["λͺ¨λ“  μ„ΈλŒ€"],
value="λͺ¨λ“  μ„ΈλŒ€",
label="포켓λͺ¬ μ„ΈλŒ€",
info="μ›ν•˜λŠ” 포켓λͺ¬ μ„ΈλŒ€λ₯Ό μ„ νƒν•˜μ„Έμš”."
)
poke_types = gr.Dropdown(
pokemons_types, value="λͺ¨λ“  νƒ€μž…",
label="포켓λͺ¬ νƒ€μž…",
info="μ›ν•˜λŠ” 포켓λͺ¬ νƒ€μž…μ„ μ„ νƒν•˜μ„Έμš”."
)
with gr.Row():
play = gr.Button(value="ν€΄μ¦ˆ μ‹œμž‘", label="ν€΄μ¦ˆ μ‹œμž‘")
skip = gr.Button(value="문제 λ„˜μ–΄κ°€κΈ°", label="문제 μŠ€ν‚΅")
chatbot = gr.Chatbot(bubble_full_width=False,
avatar_images=["https://huggingface.co/spaces/yoon-gu/pokemon/resolve/main/images/No_0001_이상해씨.png",
"https://huggingface.co/spaces/yoon-gu/pokemon/resolve/main/images/No_0155_λΈŒμΌ€μΈ.png"])
with gr.Row():
button1 = gr.Button(value="1번")
button2 = gr.Button(value="2번")
button3 = gr.Button(value="3번")
button4 = gr.Button(value="4번")
def respond(message, chat_history, user, quiz_count, gen, types, request: gr.Request):
message = message.strip()
done = info[user]['done']
start, end = GEN_RANGE[gen]
sdf = df[start:end]
pokemons_set = sdf[sdf['types'].apply(lambda x: (types in x)) | (types == "λͺ¨λ“  νƒ€μž…")]
pokemons_set = pokemons_set.to_dict("records")
if done:
if "ν€΄μ¦ˆμ‹œμž‘" == message.replace(" ", ""):
q, a, random_buttons = get_question_answer(pokemons_set)
bot_message = f"ν€΄μ¦ˆλ₯Ό μ‹œμž‘ν•©λ‹ˆλ‹€.\n{q}"
info[user]['answer'] = a
info[user]['done'] = False
info[user]['score'] = 0
info[user]['count'] = 0
info[user]['time'] = time.time()
else:
bot_message = "ν€΄μ¦ˆλ₯Ό μ‹œμž‘ν•˜κ³  μ‹ΆμœΌμ‹œλ©΄, **ν€΄μ¦ˆ μ‹œμž‘** λ²„νŠΌμ„ λˆ„λ₯΄μ„Έμš”."
else:
if info[user]['answer'] == message:
q, a, random_buttons = get_question_answer(pokemons_set)
info[user]['answer'] = a
info[user]['score'] += 1
info[user]['count'] += 1
bot_message = f"πŸŽ‰μ •λ‹΅μž…λ‹ˆλ‹€! λ‹€μŒ λ¬Έμ œμž…λ‹ˆλ‹€.\n{q}\n- ν˜„μž¬ 점수: {info[user]['score']}점\n- μ†Œμš” μ‹œκ°„: {time.time() - info[user]['time']:4.3f}초"
elif "ν¬κΈ°ν•˜κΈ°" == message.replace(" ", ""):
bot_message = f"ν€΄μ¦ˆλ₯Ό κ°•μ œ μ’…λ£Œν•©λ‹ˆλ‹€."
info[user]['done'] = True
elif "문제 λ„˜μ–΄κ°€κΈ°" == message:
info[user]['count'] += 1
q, a = get_question_answer(pokemons_set)
info[user]['answer'] = a
bot_message = f"문제λ₯Ό λ„˜μ–΄κ°‘λ‹ˆλ‹€. λ‹€μŒλ¬Έμ œμž…λ‹ˆλ‹€.\n{q}"
else:
hint1 = ""
for i, y in enumerate(info[user]['answer']):
if i < len(message):
if message[i] == y:
hint1 += y
else:
hint1 += "X"
else:
hint1 += "X"
bot_message = f"***{message}***!? 🧐 λ‹€μ‹œ ν•œλ²ˆ μƒκ°ν•΄λ³΄μ„Έμš”.\n힌트: {hint1}"
info[user]['score'] -= 0.1
bot_message += f"\n\n총 {quiz_count}개 문제 쀑 {info[user]['count']+1}번째 문제 진행 μ€‘μž…λ‹ˆλ‹€."
if quiz_count == info[user]['count']:
bot_message = f"λͺ¨λ“  ν€΄μ¦ˆλ₯Ό λ‹€ ν’€μ—ˆμŠ΅λ‹ˆλ‹€. μ μˆ˜λŠ” {info[user]['score']:3.1f}점 μž…λ‹ˆλ‹€."
info[user]['done'] = True
if info[user]['score'] >= info[user]['best_score']:
info[user]['best_score'] = info[user]['score']
info[user]['best_time'] = min(time.time() - info[user]['time'], info[user]['best_time'])
info[user]['best_time'] = round(info[user]['best_time'], 2)
info[user]['comment'] = f"{gen.replace(' ', '')}+{types.replace(' ', '')}"
with open("info.json", "w") as f:
json.dump(info, f, indent=4)
with open("users.json", "w") as f:
json.dump(USERS, f, indent=4)
artifact = wandb.Artifact("settings", type="info")
artifact.add_file("info.json")
artifact.add_file("users.json")
run.log_artifact(artifact)
info[user]['history'].append((message, bot_message))
leader_board = sorted(info.items(), key=lambda x: (x[1]['best_score'], -x[1]['best_time']), reverse=True)
lbdf = pd.DataFrame([dict(**a[1], name=a[0]) for a in leader_board])
lbdf.rename(columns={'name': "이름", 'best_score': "졜고점수", 'best_time': "μ‹œκ°„κΈ°λ‘", 'comment': "ν€΄μ¦ˆμœ ν˜•"}, inplace=True)
lbdf.index += 1
md = lbdf[['이름', '졜고점수', 'μ‹œκ°„κΈ°λ‘', 'ν€΄μ¦ˆμœ ν˜•']]
if info[user]['done']:
btn = gr.Button(value="ν€΄μ¦ˆ μ‹œμž‘", label="ν€΄μ¦ˆ μ‹œμž‘")
else:
btn = gr.Button(value="ν¬κΈ°ν•˜κΈ°", label="ν€΄μ¦ˆ 쀑단")
return btn, info[user]['history'], md, *random_buttons
play.click(respond,
inputs=[play, chatbot, user, quiz_count, generation, poke_types],
outputs=[play, chatbot, leader_board, button1, button2, button3, button4])
skip.click(respond,
inputs=[skip, chatbot, user, quiz_count, generation, poke_types],
outputs=[play, chatbot, leader_board, button1, button2, button3, button4])
for btn in [button1, button2, button3, button4]:
btn.click(respond,
inputs=[btn, chatbot, user, quiz_count, generation, poke_types],
outputs=[play, chatbot, leader_board, button1, button2, button3, button4])
def rs_change(rs):
global USERS
if rs not in USERS:
USERS += [rs]
new_dropdown = gr.Dropdown(sorted(USERS), value=rs, label="μ‚¬μš©μž", info="당신은 λˆ„κ΅¬μ‹ κ°€μš”?", allow_custom_value=True)
return new_dropdown
user.blur(rs_change, user, user)
def update_table(user):
leader_board = sorted(info.items(), key=lambda x: (x[1]['best_score'], -x[1]['best_time']), reverse=True)
lbdf = pd.DataFrame([dict(**a[1], name=a[0]) for a in leader_board])
lbdf.rename(columns={'name': "이름", 'best_score': "졜고점수", 'best_time': "μ‹œκ°„κΈ°λ‘", 'comment': "ν€΄μ¦ˆμœ ν˜•"}, inplace=True)
lbdf.index += 1
md = lbdf[['이름', '졜고점수', 'μ‹œκ°„κΈ°λ‘', 'ν€΄μ¦ˆμœ ν˜•']]
if info[user]['done']:
btn = gr.Button(value="ν€΄μ¦ˆ μ‹œμž‘", label="ν€΄μ¦ˆ μ‹œμž‘")
else:
btn = gr.Button(value="ν¬κΈ°ν•˜κΈ°", label="ν€΄μ¦ˆ 쀑단")
return btn, md, gr.Dropdown(USERS, value=user, label="μ‚¬μš©μž", info="당신은 λˆ„κ΅¬μ‹ κ°€μš”?", allow_custom_value=True), info[user]['history']
demo.load(update_table,
inputs=user,
outputs=[play, leader_board, user, chatbot])
demo.queue(concurrency_count=3)
demo.launch()