elon_py/test/aola.py
2025-05-11 09:22:33 +08:00

310 lines
13 KiB
Python
Raw Permalink 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 sqlite3
import tkinter as tk
from tkinter import ttk
import os
import json
class TeamSwitchPacketGenerator:
def __init__(self):
# 检查数据库文件是否存在
db_file = 'aola.sqlite'
if not os.path.exists(db_file):
raise FileNotFoundError(f"数据库文件 {db_file} 未找到,请确保文件在 {os.getcwd()} 目录下!")
print(f"数据库文件路径: {os.path.abspath(db_file)}")
self.conn = sqlite3.connect(db_file)
self.cursor = self.conn.cursor()
self.root = tk.Tk()
self.root.title("阵容切换封包生成器")
# 获取所有阵容名称和 spell_code
self.team_data = self.get_team_data()
self.team_names = [item[0] for item in self.team_data]
self.last_filtered_teams = self.team_names
# 创建可搜索的下拉框
tk.Label(self.root, text="选择或搜索阵容(输入拼音缩写):").pack(anchor=tk.W, padx=5)
self.team_var = tk.StringVar(value="请选择阵容")
self.team_dropdown = ttk.Combobox(self.root, textvariable=self.team_var)
self.team_dropdown['values'] = self.team_names
self.team_dropdown.pack(pady=10)
# 防抖定时器和状态
self.debounce_timer = None
self.debounce_delay = 150
self.last_search_text = ""
self.has_typed = False
self.is_dropdown_open = False # 跟踪下拉框状态
# 绑定事件
self.team_dropdown.bind('<KeyRelease>', self.schedule_update_combobox)
self.team_dropdown.bind('<FocusIn>', self.clear_default_text)
self.team_dropdown.bind('<FocusOut>', self.close_dropdown)
self.team_dropdown.bind('<<ComboboxSelected>>', self.on_combobox_select)
# 获取 Combobox 的内部 Entry 控件
self.entry = self.team_dropdown # ttk.Combobox 本身支持 Entry 方法
# 绑定下拉框展开/收起事件
self.team_dropdown.bind('<Button-1>', self.toggle_dropdown_state)
# 创建按钮框架,包含“刷新”和“生成封包”按钮
button_frame = tk.Frame(self.root)
button_frame.pack(pady=5)
tk.Button(button_frame, text="Set1", command=self.set_1).pack(side=tk.LEFT, padx=5)
tk.Button(button_frame, text="刷新", command=self.refresh_dropdown).pack(side=tk.LEFT, padx=5)
tk.Button(button_frame, text="生成封包(第一次生成请先解锁二级密码)", command=self.generate_packets).pack(side=tk.LEFT, padx=5)
# 创建封包输出和复制按钮框架
output_frame = tk.Frame(self.root)
output_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
tk.Label(output_frame, text="封包输出:").pack(anchor=tk.W)
self.output_text = tk.Text(output_frame, height=15, width=60)
self.output_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
tk.Button(output_frame, text="复制脚本", command=self.copy_output).pack(side=tk.RIGHT, padx=5)
# 信息提示框
tk.Label(self.root, text="提示信息:").pack(anchor=tk.W)
self.info_text = tk.Text(self.root, height=5, width=80, fg="red")
self.info_text.pack(pady=5)
def set_1(self):
try:
self.cursor.execute("UPDATE aolaer_id SET is_set = 1")
self.conn.commit()
self.info_text.insert(tk.END, f"set1 ok\n")
return
except sqlite3.Error:
self.info_text.insert(tk.END, f"set1失败\n")
return
def get_team_data(self):
try:
self.cursor.execute("SELECT team_name, spell_code FROM aolaer_team ORDER BY team_name")
return [(row[0], row[1] or "") for row in self.cursor.fetchall()]
except sqlite3.Error as e:
self.info_text.insert(tk.END, f"获取阵容数据失败: {e}\n")
return []
def clear_default_text(self, event):
if self.team_var.get() == "请选择阵容":
self.team_var.set("")
self.has_typed = True
self.entry.focus_set()
self.entry.icursor(tk.END)
def schedule_update_combobox(self, event):
if event.keysym in ('Shift', 'Control', 'Alt', 'Return', 'Tab', 'Left', 'Right', 'Up', 'Down'):
return
self.has_typed = True
if self.debounce_timer is not None:
self.root.after_cancel(self.debounce_timer)
self.debounce_timer = self.root.after(self.debounce_delay, self.update_combobox)
def toggle_dropdown_state(self, event):
"""跟踪下拉框的展开/收起状态"""
# 简单假设点击切换状态(实际可能需要更复杂的状态检测)
self.is_dropdown_open = not self.is_dropdown_open
def update_combobox(self):
"""优化后的更新下拉框逻辑"""
search_text = self.team_var.get().strip().lower()
if search_text == self.last_search_text:
return
self.last_search_text = search_text
if not search_text or search_text == "请选择阵容":
filtered_teams = self.team_names
else:
filtered_teams = [
team_name for team_name, spell_code in self.team_data
if spell_code and search_text in spell_code.lower()
]
if not filtered_teams:
filtered_teams = ["无匹配阵容"]
# 更新下拉框选项
if filtered_teams != self.last_filtered_teams:
self.team_dropdown['values'] = filtered_teams
self.last_filtered_teams = filtered_teams
# 打开下拉框(仅在有输入且未打开时)
if self.has_typed and search_text and not self.is_dropdown_open:
self.team_dropdown.event_generate('<Down>')
self.is_dropdown_open = True
# 延迟设置焦点和光标位置
def set_focus_and_cursor():
self.entry.focus_set()
self.entry.icursor(tk.END)
# 调试日志
self.info_text.insert(tk.END, f"焦点设置: {self.root.focus_get() == self.entry}\n")
self.root.after(10, set_focus_and_cursor)
def close_dropdown(self, event):
self.has_typed = False
if self.is_dropdown_open:
self.team_dropdown.event_generate('<Up>')
self.is_dropdown_open = False
def on_combobox_select(self, event):
self.has_typed = False
self.is_dropdown_open = False
self.entry.focus_set()
self.entry.icursor(tk.END)
def refresh_dropdown(self):
self.team_data = self.get_team_data()
self.team_names = [item[0] for item in self.team_data]
self.team_dropdown['values'] = self.team_names
self.last_filtered_teams = self.team_names
self.team_var.set("请选择阵容")
self.last_search_text = ""
self.has_typed = False
self.is_dropdown_open = False
self.info_text.insert(tk.END, "下拉框数据已刷新!\n")
def copy_output(self):
content = self.output_text.get(1.0, tk.END).strip()
if content:
self.root.clipboard_clear()
self.root.clipboard_append(content)
self.info_text.insert(tk.END, "脚本内容已复制到剪贴板!\n")
else:
self.info_text.insert(tk.END, "脚本输出框为空,无法复制!\n")
def validate_ids(self, ids_str):
try:
ids = json.loads(ids_str)
if not isinstance(ids, list) or len(ids) != 5:
return False, "ids 必须是长度为 5 的数组"
for x in ids:
if not isinstance(x, int) or x < 0:
return False, "ids 中的值必须是非负整数"
return True, ids
except json.JSONDecodeError:
return False, "ids 格式不正确"
def generate_packets(self):
self.output_text.delete(1.0, tk.END)
self.info_text.delete(1.0, tk.END)
packets = []
selected_team = self.team_var.get()
if not selected_team or selected_team in ["请选择阵容", "无匹配阵容"]:
self.info_text.insert(tk.END, "请先选择一个有效阵容!\n")
return
try:
self.cursor.execute("SELECT team_code, team_set FROM aolaer_team WHERE team_name = ?", (selected_team,))
result = self.cursor.fetchone()
if not result:
self.info_text.insert(tk.END, f"未找到阵容 {selected_team} 的 team_code\n")
return
team_code, team_set = result
packets.append(f'|#send={{"id":13,"param":{{"pms":"{team_code}"}},"cmd":"1222"}}|')
self.cursor.execute("SELECT id FROM aolaer_id WHERE is_set = 1")
set_ids = [row[0] for row in self.cursor.fetchall()]
for set_id in set_ids:
packets.append(
f'|#send={{"id":42,"param":{{"bk":1,"petId":{set_id},"ids":[0,0,0,0,0]}},"cmd":"ASC221104_2"}}|#time=10|')
self.cursor.execute("UPDATE aolaer_id SET is_set = 0 WHERE id = ?", (set_id,))
self.conn.commit()
team_ids = team_code.split('#')
team_ids = [id for id in team_ids if id]
team_set_codes = None
if team_set:
team_set_codes = team_set.split('#')
if len(team_set_codes) != len(team_ids):
self.info_text.insert(tk.END,
f"警告team_set 的长度 ({len(team_set_codes)}) 与 team_code 的 ID 数量 ({len(team_ids)}) 不匹配!\n")
return
self.cursor.execute(
"SELECT id, div_weapon, aolaer_typecode FROM aolaer_id WHERE id IN ({})".format(
','.join('?' for _ in team_ids)
),
team_ids
)
id_to_typecode = {row[0]: row for row in self.cursor.fetchall()}
sub_pet_packets = []
soul_art_packets = []
soul_card_packets = []
for idx, id in enumerate(team_ids):
id = int(id)
if id not in id_to_typecode:
self.info_text.insert(tk.END, f"警告ID {id} 在 aolaer_id 表中不存在!\n")
continue
div_weapon = id_to_typecode[id][1]
typecode = id_to_typecode[id][2]
if team_set_codes and team_set_codes[idx] != '0':
typecode = team_set_codes[idx]
if div_weapon and str(div_weapon).strip():
sub_pet_packets.append(
f'|#send={{"id":42,"param":{{"subPetId":{id},"petId":{div_weapon}}},"cmd":"ASBS230623_con"}}|#time=10|')
else:
self.info_text.insert(tk.END, f"提示ID {id} 的 div_weapon 为空,跳过生成子宠物封包!\n")
self.cursor.execute("SELECT soul_art, soul_card FROM aolaer_type WHERE aolaer_typecode = ?",
(typecode,))
result = self.cursor.fetchone()
if not result:
self.info_text.insert(tk.END, f"警告typecode {typecode} 在 aolaer_type 表中不存在!\n")
continue
soul_art, soul_card = result
if soul_art and soul_art.strip():
try:
sid1, sid2 = soul_art.split(',')
soul_art_packets.append(
f'|#send={{"id":42,"param":{{"ui":{sid1},"petId":{id}}},"cmd":"ATT231229_1"}}|#time=10|')
soul_art_packets.append(
f'|#send={{"id":42,"param":{{"ui":{sid2},"petId":{id}}},"cmd":"ATT231229_1"}}|#time=10|')
except ValueError:
self.info_text.insert(tk.END, f"错误soul_art 格式不正确 for typecode {typecode}\n")
continue
else:
self.info_text.insert(tk.END,
f"提示typecode {typecode} 的 soul_art 为空,跳过生成魂艺封包!\n")
if soul_card and soul_card.strip():
is_valid, ids_or_error = self.validate_ids(soul_card)
if is_valid:
soul_card_packets.append(
f'|#send={{"id":42,"param":{{"bk":1,"petId":{id},"ids":{soul_card}}},"cmd":"ASC221104_2"}}|#time=10|')
self.cursor.execute("UPDATE aolaer_id SET is_set = 1 WHERE id = ?", (id,))
self.conn.commit()
else:
self.info_text.insert(tk.END,
f"警告typecode {typecode} 的 soul_card {soul_card} 无效({ids_or_error}),已跳过处理!\n")
else:
self.info_text.insert(tk.END, f"提示typecode {typecode} 的 soul_card 为空,已跳过处理!\n")
packets.extend(sub_pet_packets)
packets.extend(soul_art_packets)
packets.extend(soul_card_packets)
if packets:
self.output_text.insert(tk.END, '\n'.join(packets))
else:
self.info_text.insert(tk.END, "未生成任何封包,请检查数据!\n")
except sqlite3.Error as e:
self.info_text.insert(tk.END, f"数据库操作失败: {e}\n")
def run(self):
self.root.mainloop()
def __del__(self):
self.conn.close()
if __name__ == "__main__":
app = TeamSwitchPacketGenerator()
app.run()