pokemon-quiz / app.py
Yoon-gu Hwang
typo
cd601c3
raw
history blame
9.57 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)
return q, a
initial_info = {"done" : True,
"score": 0, "count": 0,
"best_score": 0, "best_time": float("inf"),
"time": 0.0, "comment": ""}
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="문제 μŠ€ν‚΅")
stop = 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"])
msg = gr.Textbox(placeholder="문제의 닡을 μž…λ ₯ν•˜μ„Έμš”.", label="λ‹΅")
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 = 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 = 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}+{types}"
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)
chat_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[['이름', '졜고점수', 'μ‹œκ°„κΈ°λ‘', 'ν€΄μ¦ˆμœ ν˜•']]
return "", chat_history, md
play.click(respond,
inputs=[play, chatbot, user, quiz_count, generation, poke_types],
outputs=[msg, chatbot, leader_board])
skip.click(respond,
inputs=[skip, chatbot, user, quiz_count, generation, poke_types],
outputs=[msg, chatbot, leader_board])
stop.click(respond,
inputs=[stop, chatbot, user, quiz_count, generation, poke_types],
outputs=[msg, chatbot, leader_board])
def rs_change(rs):
global USERS
if rs not in USERS:
USERS += [rs]
return gr.update(choices=sorted(USERS), value=rs)
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
print(len(lbdf))
md = lbdf[['이름', '졜고점수', 'μ‹œκ°„κΈ°λ‘', 'ν€΄μ¦ˆμœ ν˜•']]
return md, gr.Dropdown(USERS, value=user, label="μ‚¬μš©μž", info="당신은 λˆ„κ΅¬μ‹ κ°€μš”?", allow_custom_value=True)
demo.load(update_table,
inputs=user,
outputs=[leader_board, user])
msg.submit(respond, [msg, chatbot, user, quiz_count, generation, poke_types], [msg, chatbot, leader_board])
demo.queue(concurrency_count=1)
demo.launch()