Files
abot/game_task/game_task_encyclopedia.py

481 lines
18 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import json
import random
import schedule
import time
from datetime import datetime
import pymysql
from game_task.game_chatgpt_qa import game_question_json, game_answer_json
# 数据库连接配置
db_config = {
'host': '192.168.2.32', # 替换为你的MariaDB服务器地址
'user': 'root', # 替换为你的MariaDB用户名
'password': 'lw123456', # 替换为你的MariaDB密码
'database': 'message_archive',
'charset': 'utf8mb4',
'cursorclass': pymysql.cursors.DictCursor
}
# 连接数据库
def get_db_connection():
return pymysql.connect(**db_config)
# 添加群聊
def add_group(group_id, player_id):
conn = get_db_connection()
cursor = conn.cursor()
try:
cursor.execute(
"INSERT INTO t_encyclopedia_groups (group_id) VALUES (%s)",
(group_id,)
)
conn.commit()
return (
f"🎉 好消息来啦!\n"
f"🌟 群 {group_id} 已成功加入\n"
f"🎈 大家快来一起玩吧!"
)
except pymysql.err.IntegrityError:
return (
f"😄 嘿,小伙伴\n"
f"🌈 群 {group_id} 已经在了\n"
f"🎶 快来一起开心吧!"
)
finally:
cursor.close()
conn.close()
# 获取所有群聊ID
def get_group_ids():
conn = get_db_connection()
cursor = conn.cursor()
try:
cursor.execute("SELECT group_id FROM t_encyclopedia_groups")
return [row['group_id'] for row in cursor.fetchall()]
finally:
cursor.close()
conn.close()
# 开始游戏(使用 player_id
def start_game(group_id, player_id, player_name="未知玩家"):
conn = get_db_connection()
cursor = conn.cursor()
try:
# 确保群聊存在
cursor.execute("SELECT group_id FROM t_encyclopedia_groups WHERE group_id = %s", (group_id,))
if not cursor.fetchone():
return (
f"😅 哎呀,小朋友\n"
f"🌼 群 {group_id} 还没准备好\n"
f"🎀 先用 /addgroup 添加哦!"
)
cursor.execute(
"INSERT INTO t_encyclopedia_players (player_id, group_id, player_name) VALUES (%s, %s, %s)",
(player_id, group_id, player_name)
)
conn.commit()
return (
f"🎉 欢迎加入,{player_name}\n"
f"🌟 已就位\n"
f"🎈 群 {group_id} 等你来玩\n"
f"🌈 快来接任务吧!指令: /gettask"
)
except pymysql.err.IntegrityError:
cursor.execute(
"SELECT player_name FROM t_encyclopedia_players WHERE group_id = %s AND player_id = %s",
(group_id, player_id)
)
existing_name = cursor.fetchone()['player_name']
return (
f"😄 你好呀,{existing_name}\n"
f"🌼 已加入游戏 {group_id}\n"
f"🎶 快来一起乐呵吧! \n"
f"🌈 快来接任务吧!指令: /gettask"
)
finally:
cursor.close()
conn.close()
# 随机分配任务(支持指定玩家)
def assign_random_task(group_id, player_id=None):
conn = get_db_connection()
cursor = conn.cursor()
try:
# 获取当前群聊的玩家列表
cursor.execute("SELECT player_id, player_name FROM t_encyclopedia_players WHERE group_id = %s", (group_id,))
players = cursor.fetchall()
if not players:
return (
f"😔 哎呀,群 {group_id} 好安静\n"
f"🌟 没有小伙伴加入\n"
f"🎈 快叫朋友来玩吧!"
)
# 如果指定了 player_id检查其是否在群聊中
if player_id:
player_dict = {p['player_id']: p['player_name'] for p in players}
if player_id not in player_dict:
return (
f"😅 嘿,小朋友\n"
f"🌟 ID: {player_id} 还没加入群 {group_id}\n"
f"🎈 用 /start 先报名吧!"
)
holder_id = player_id
holder_name = player_dict[player_id]
else:
# 未指定 player_id 时,随机选择
holder = random.choice(players)
holder_id = holder['player_id']
holder_name = holder['player_name']
# 使用内部方法获取任务
task = game_question_json("请从不同的学科领域(历史学:古代历史、近现代史、战争与政治、文化遗产与考古学;生物学:进化论、动植物学、基因与遗传学、生态学;化学:有机化学、无机化学、生物化学、环境化学;地理学:人文地理、自然地理、地质学、气候变化;文学:古典文学、现代文学、小说与戏剧、诗歌与散文;艺术:美术、音乐、戏剧与舞蹈、电影与媒体;哲学:西方哲学、东方哲学、道德与伦理学、逻辑与认识论;社会学:人类学、心理学、政治学、经济学;计算机科学:编程语言、人工智能、数据科学、网络与安全;工程学:机械工程、电气工程、化学工程、土木工程;医学:解剖学、生理学、临床医学、药学与护理;体育:球类运动、奥林匹克运动、运动心理学、健身与营养;宗教与神话:世界宗教、神话与民间故事、宗教哲学;语言学:语法与词汇、语言习得、方言与语言变异;经济学:宏观经济学、微观经济学、国际贸易、金融与投资;法律:民法与刑法、国际法、知识产权法、环境法)生成一个全新问题。")
question = task["question"]
answer = task["answer"]
score = int(task["score"])
description = task.get("description", "")
# 插入任务
cursor.execute(
"INSERT INTO t_encyclopedia_active_tasks (group_id, question, answer, score, description, holder_id) VALUES (%s, %s, %s, %s, %s, %s)",
(group_id, question, answer, score, description, holder_id)
)
conn.commit()
# 获取分配的任务ID
cursor.execute(
"SELECT active_task_id FROM t_encyclopedia_active_tasks WHERE group_id = %s AND question = %s AND holder_id = %s ORDER BY assigned_at DESC LIMIT 1",
(group_id, question, holder_id)
)
active_task_id = cursor.fetchone()['active_task_id']
# 根据是否指定玩家,返回不同消息
if player_id:
return (
f"🎁 {holder_name},你的新任务来啦!\n"
f"🎈 问题:{question}\n"
f"🌈 群 {group_id} 等你作答\n"
f"🎀 任务ID: task_{active_task_id}\n"
f"🌼 积分:{score}"
)
else:
return (
f"🎁 新任务来啦!\n"
f"🌟 幸运玩家:{holder_name} \n"
f"🎈 问题:{question}\n"
f"🌈 群 {group_id} 等你抢答\n"
f"🎀 任务ID: task_{active_task_id}\n"
f"🌼 积分:{score}"
)
finally:
cursor.close()
conn.close()
# 提交答案并计分错误扣1分
def submit_answer(group_id, player_id, task_id, answer):
conn = get_db_connection()
cursor = conn.cursor()
try:
# 检查玩家是否存在并获取名称
cursor.execute("SELECT player_name FROM t_encyclopedia_players WHERE group_id = %s AND player_id = %s",
(group_id, player_id))
player_row = cursor.fetchone()
if not player_row:
return (
f"😅 嘿,小朋友\n"
f"🌟 ID: {player_id} 还没加入群 {group_id}\n"
f"🎈 用 /start 先报名吧!"
)
player_name = player_row['player_name']
# 检查任务ID是否为纯数字
if not task_id.isdigit():
return (
f"😅 哎呀,小调皮\n"
f"🌟 任务ID格式不对哦\n"
f"🎈 应该是纯数字\n"
f"🌈 比如1\n"
f"🎀 再试一次吧!"
)
active_task_id = int(task_id)
# 检查任务是否存在并获取任务详情
cursor.execute(
"SELECT question, answer, score, holder_id, status FROM t_encyclopedia_active_tasks WHERE group_id = %s AND active_task_id = %s",
(group_id, active_task_id)
)
task_data = cursor.fetchone()
if not task_data:
return (
f"😔 哎呀,小伙伴\n"
f"🌼 群 {group_id} 的任务 task_{active_task_id} 不见了\n"
f"🎀 可能已经被抢答或过期啦!"
)
if task_data['status'] == 'completed':
return (
f"😄 哈哈,太慢啦!\n"
f"🌟 任务 task_{active_task_id} 已完成\n"
f"🎈 群 {group_id} 等你抢新任务哦!"
)
question, correct_answer_db, top_score, holder_id, _ = task_data['question'], task_data['answer'].lower(), \
task_data['score'], task_data['holder_id'], task_data['status']
# 获取持有者名称
cursor.execute("SELECT player_name FROM t_encyclopedia_players WHERE group_id = %s AND player_id = %s",
(group_id, holder_id))
holder_name = cursor.fetchone()['player_name']
# 调用内部方法校验答案
answer_json = {"question": question, "top_score": str(top_score), "answer": answer}
result = game_answer_json(answer_json)
points = int(result["score"])
description = result["description"]
is_correct = points > 0
# 处理答案提交逻辑
if is_correct:
# 答对 situation
cursor.execute(
"UPDATE t_encyclopedia_players SET points = points + %s WHERE group_id = %s AND player_id = %s",
(points, group_id, player_id)
)
cursor.execute(
"UPDATE t_encyclopedia_active_tasks SET status = 'completed' WHERE group_id = %s AND active_task_id = %s",
(group_id, active_task_id)
)
if player_id == holder_id:
message = (
f"🎉 {player_name} 太棒啦!\n"
f"🌟 任务:{question}\n"
f"🎈 答对了,真厉害!\n"
f"🌈 奖励:{points}\n"
f"🎀 提示:{description}"
)
else:
message = (
f"🎉 {player_name} 抢答成功!\n"
f"🌟 任务:{question}\n"
f"🎈 原主:{holder_name}\n"
f"🌈 获得 {points} 分,太棒了!\n"
f"🎀 提示:{description}"
)
else:
# 答错 situation任务保持 pending 状态,允许其他玩家继续抢答
cursor.execute(
"UPDATE t_encyclopedia_players SET points = GREATEST(points - 1, 0) WHERE group_id = %s AND player_id = %s",
(group_id, player_id)
)
points = -1 # 记录惩罚分
message = (
f"😅 {player_name} 有点小遗憾!\n"
f"🌼 任务:{question}\n"
f"🎈 你答:{answer}\n"
f"🌟 正确答案:{correct_answer_db}\n"
f"🌈 扣 1 分,别灰心!\n"
f"🎀 提示:{description}\n"
f"🌟 任务 task_{active_task_id} 仍可抢答哦!"
)
# 记录提交历史
cursor.execute(
"INSERT INTO t_encyclopedia_task_history (group_id, active_task_id, player_id, answer, is_correct, points_earned) VALUES (%s, %s, %s, %s, %s, %s)",
(group_id, active_task_id, player_id, answer, is_correct, points)
)
conn.commit()
return message
except ValueError:
return (
f"😅 哎呀,小调皮\n"
f"🌟 任务ID格式不对哦\n"
f"🎈 应该是纯数字\n"
f"🌈 比如1\n"
f"🎀 再试一次吧!"
)
except Exception as e :
print(f"submit_answer:{e}")
return (
f"😅 哎呀,小调皮\n"
f"🌟 任务ID格式不对哦\n"
f"🎈 应该是纯数字\n"
f"🌈 比如1\n"
f"🎀 再试一次吧!"
)
finally:
cursor.close()
conn.close()
# 显示排行榜
def show_rank(group_id, player_id):
conn = get_db_connection()
cursor = conn.cursor()
try:
cursor.execute(
"SELECT player_name, points FROM t_encyclopedia_players WHERE group_id = %s ORDER BY points DESC LIMIT 10",
(group_id,)
)
ranks = cursor.fetchall()
if not ranks:
return (
f"😔 群 {group_id} 好安静\n"
f"🌟 排行榜还没有人\n"
f"🎈 快来一起玩吧!"
)
rank_text = f"🎉 群 {group_id} 排行榜Top 10\n"
for i, row in enumerate(ranks, 1):
rank_text += f"🌈 {i}. {row['player_name']}: {row['points']}\n"
return rank_text
finally:
cursor.close()
conn.close()
# 显示当前活跃任务
def show_active_tasks(group_id, player_id):
conn = get_db_connection()
cursor = conn.cursor()
try:
cursor.execute("""
SELECT a.active_task_id, a.question, p.player_name, p.player_id
FROM t_encyclopedia_active_tasks a
JOIN t_encyclopedia_players p ON a.holder_id = p.player_id AND a.group_id = p.group_id
WHERE a.group_id = %s AND a.status = 'pending'
""", (group_id,))
tasks = cursor.fetchall()
if not tasks:
return (
f"😄 群 {group_id} 现在很平静\n"
f"🌟 没有活跃任务哦\n"
f"🎈 用 /gettask 拿一个吧!"
)
task_text = f"🎉 群 {group_id} 当前活跃任务:\n"
for task in tasks:
task_text += (
f"🌈 任务ID: task_{task['active_task_id']}\n"
f"🎀 问题:{task['question']}\n"
f"🌼 持有者:{task['player_name']} (ID: {task['player_id']})\n"
)
return task_text
finally:
cursor.close()
conn.close()
# 列举所有未完成任务及其所属者
def list_uncompleted_tasks(group_id, player_id):
conn = get_db_connection()
cursor = conn.cursor()
try:
cursor.execute("""
SELECT a.active_task_id, a.question, p.player_name, p.player_id
FROM t_encyclopedia_active_tasks a
JOIN t_encyclopedia_players p ON a.holder_id = p.player_id AND a.group_id = p.group_id
WHERE a.group_id = %s AND a.status = 'pending'
""", (group_id,))
tasks = cursor.fetchall()
if not tasks:
return (
f"😄 群 {group_id} 任务都完成啦\n"
f"🌟 目前没有未完成任务\n"
f"🎈 用 /gettask 再来一个吧!"
)
task_text = f"🎉 群 {group_id} 所有未完成任务列表:\n"
for task in tasks:
task_text += (
f"🌈 任务ID: task_{task['active_task_id']}\n"
f"🎀 问题:{task['question']}\n"
f"🌼 所属:{task['player_name']} (ID: {task['player_id']})\n"
)
return task_text
finally:
cursor.close()
conn.close()
# 定时任务整点触发排除23:00-08:00
def run_random_task_assignment(group_id):
current_hour = datetime.now().hour
if current_hour >= 23 or current_hour < 9: # 排除23:00-08:00
print(f"{datetime.now()}{group_id} 当前时间 {current_hour}:00 在23:00-08:00区间跳过任务发放")
return
result = assign_random_task(group_id) # 不传入 player_id保持随机
print(f"{datetime.now()} {result}")
# 处理群聊消息
def game_process_message(group_id, player_id, message, player_name="未知玩家"):
if message == "/start":
return start_game(group_id, player_id, player_name)
elif message == "/tasks":
return show_active_tasks(group_id, player_id)
elif message == "/list":
return list_uncompleted_tasks(group_id, player_id)
elif message.startswith("/answer"):
parts = message.split(" ", 2)
if len(parts) < 3:
return (
f"😅 哎呀,小朋友\n"
f"🌟 格式不对哦\n"
f"🎈 正确用法:/answer [任务ID] [答案]\n"
f"🌈 例如:/answer 1 钒Vanadium"
)
task_id, answer = parts[1], parts[2]
return submit_answer(group_id, player_id, task_id, answer)
elif message == "/rank":
return show_rank(group_id, player_id)
elif message.startswith("/addgroup"):
return add_group(group_id, player_id)
elif message == "/gettask":
current_hour = datetime.now().hour
if current_hour >= 23 or current_hour < 9:
return (
f"😴 现在是 {current_hour}:00\n"
f"🌙 太晚啦,小伙伴们休息中\n"
f"🌞 9点到22点再来玩吧"
)
return assign_random_task(group_id, player_id) # 传入 player_id
else:
return (
f"😄 嘿,小调皮\n"
f"🌟 指令不对哦\n"
f"🎈 可用指令:\n"
f"🌈 /start - 加入游戏\n"
f"🎀 /tasks - 查看活跃任务\n"
f"🌼 /list - 未完成任务\n"
f"🌟 /answer [任务ID] [答案] - 提交答案\n"
f"🎈 /addgroup - 添加群聊\n"
f"🌈 /gettask - 主动拿任务\n"
f"🎀 /rank - 查看排行榜"
)
# 设置定时任务
def setup_schedule():
group_ids = get_group_ids()
for gid in group_ids:
schedule.every().hour.at(":00").do(run_random_task_assignment, group_id=gid)
# 主程序
if __name__ == "__main__":
# 测试抢答功能
print(game_process_message("47530198896@chatroom", "player1001", "/start", "玩家1"))
print(game_process_message("47530198896@chatroom", "player1002", "/start", "玩家2"))
print(game_process_message("47530198896@chatroom", "player1001", "/gettask"))
# 玩家2 抢答玩家1的任务
print(game_process_message("47530198896@chatroom", "player1002", "/answer 1 珠穆朗玛峰"))