162 lines
4.9 KiB
Python
162 lines
4.9 KiB
Python
import tkinter as tk
|
|
from tkinter import messagebox, simpledialog
|
|
import time
|
|
import requests
|
|
|
|
API_URL = "http://47.80.30.142:6364" # Flask 接口地址
|
|
|
|
# 读取排行榜数据(从 Flask 获取)
|
|
def load_leaderboard():
|
|
try:
|
|
resp = requests.get(f"{API_URL}/get_board")
|
|
if resp.status_code == 200:
|
|
return resp.json()
|
|
else:
|
|
return []
|
|
except Exception as e:
|
|
messagebox.showerror("错误", f"无法加载排行榜数据:{e}")
|
|
return []
|
|
|
|
# 获取参赛者姓名
|
|
def get_player_name():
|
|
name = simpledialog.askstring("参赛者姓名", "请输入您的姓名:")
|
|
if not name:
|
|
messagebox.showwarning("警告", "姓名不能为空,请重新输入。")
|
|
return get_player_name()
|
|
return name
|
|
|
|
# 上传成绩并刷新排行榜
|
|
def submit_result(name, error):
|
|
try:
|
|
# 先下载当前排行榜
|
|
leaderboard = load_leaderboard()
|
|
|
|
# 查找或更新当前用户成绩(误差更小的)
|
|
found = False
|
|
for entry in leaderboard:
|
|
if entry["name"] == name:
|
|
found = True
|
|
if abs(error) < entry["error"]:
|
|
entry["error"] = round(abs(error), 3)
|
|
break
|
|
if not found:
|
|
leaderboard.append({"name": name, "error": round(abs(error), 3)})
|
|
|
|
# 按误差升序排序
|
|
leaderboard.sort(key=lambda x: x["error"])
|
|
|
|
# 提交新的排行榜到服务器
|
|
resp = requests.post(f"{API_URL}/set_board", json=leaderboard)
|
|
if resp.status_code == 200:
|
|
update_rank_display(leaderboard)
|
|
else:
|
|
messagebox.showerror("提交失败", "提交成绩失败,请稍后再试。")
|
|
except Exception as e:
|
|
messagebox.showerror("错误", f"提交成绩时出错:{e}")
|
|
|
|
|
|
# 显示排行榜
|
|
def update_rank_display(leaderboard):
|
|
rank_listbox.delete(0, tk.END)
|
|
for i, entry in enumerate(leaderboard, 1):
|
|
n, e = entry["name"], entry["error"]
|
|
rank_listbox.insert(tk.END, f"{i}. {n:<8} 误差: {e:.3f}s")
|
|
|
|
# 更新时间函数
|
|
def update_time():
|
|
if flag:
|
|
now = time.time()
|
|
timex = now - start_time
|
|
timex_label.config(text=f"⏱ 时间:{timex:.3f} 秒")
|
|
root.after(10, update_time)
|
|
|
|
def show_win_animation():
|
|
anim = tk.Toplevel(root)
|
|
anim.geometry("320x200")
|
|
anim.title("🎉 胜利动画")
|
|
anim.configure(bg="#ffffff")
|
|
anim.attributes("-topmost", True)
|
|
|
|
label = tk.Label(anim, text="🎉 完美掌控时间!🎉", font=("微软雅黑", 18, "bold"), bg="#ffffff")
|
|
label.pack(expand=True)
|
|
|
|
colors = ["#ff6666", "#66cc66", "#3399ff", "#ffcc00", "#cc66ff"]
|
|
sizes = [18, 22, 26, 30, 26, 22, 18]
|
|
|
|
def animate(i=0):
|
|
if i < len(sizes):
|
|
label.config(font=("微软雅黑", sizes[i], "bold"), fg=colors[i % len(colors)])
|
|
anim.after(150, animate, i + 1)
|
|
else:
|
|
anim.destroy()
|
|
|
|
animate()
|
|
|
|
# 控制开始/停止
|
|
def change():
|
|
global flag, start_time
|
|
|
|
if not flag:
|
|
flag = True
|
|
start_time = time.time()
|
|
update_time()
|
|
else:
|
|
flag = False
|
|
end_time = time.time()
|
|
timex = end_time - start_time
|
|
error = timex - 10
|
|
|
|
timex_label.config(text=f"✅ 实际时间:{timex:.3f} 秒\n误差:{error:.3f} 秒")
|
|
|
|
name = get_player_name()
|
|
submit_result(name, error)
|
|
|
|
if abs(error) < 0.01:
|
|
show_win_animation()
|
|
else:
|
|
messagebox.showinfo("结果", "还差一点点,再接再厉吧!")
|
|
|
|
# ================================
|
|
# 主窗口
|
|
# ================================
|
|
|
|
root = tk.Tk()
|
|
root.geometry("340x500")
|
|
root.title("10秒挑战")
|
|
root.configure(bg="#f0faff")
|
|
|
|
# 标题
|
|
title_label = tk.Label(root, text="🎯 10 秒挑战 🎯", font=("微软雅黑", 18, "bold"), fg="#004466", bg="#f0faff")
|
|
title_label.pack(pady=15)
|
|
|
|
# 排行榜框
|
|
rank_frame = tk.Frame(root, bg="#ffffff", bd=2, relief="groove")
|
|
rank_frame.pack(pady=10)
|
|
|
|
rank_title = tk.Label(rank_frame, text="🏆 排行榜(误差越小越靠前)", font=("微软雅黑", 10, "bold"), bg="#ffffff", fg="#333333")
|
|
rank_title.pack(pady=(5, 0))
|
|
|
|
rank_listbox = tk.Listbox(rank_frame, font=("Courier", 10), height=5, width=35, bg="#f9f9f9")
|
|
rank_listbox.pack(padx=10, pady=5)
|
|
|
|
# 初始显示排行榜
|
|
leaderboard = load_leaderboard()
|
|
update_rank_display(leaderboard)
|
|
|
|
# 时间标签
|
|
timex_label = tk.Label(root, text="点击按钮开始挑战", font=("微软雅黑", 12), bg="#f0faff", fg="#333333")
|
|
timex_label.pack(pady=20)
|
|
|
|
# 按钮
|
|
start_button = tk.Button(root, text="🎮 开始 / 停止", font=("微软雅黑", 12, "bold"),
|
|
bg="#66ccff", fg="white", activebackground="#3399cc",
|
|
width=20, height=2, command=change, relief="raised", bd=3)
|
|
start_button.pack(pady=30)
|
|
|
|
# 控制变量
|
|
flag = False
|
|
start_time = 0
|
|
|
|
# 启动主循环
|
|
root.mainloop()
|