2022-02-19 18:20:19 +08:00
|
|
|
|
import platform
|
|
|
|
|
|
from asyncio.exceptions import TimeoutError
|
|
|
|
|
|
from utils.utils import cn2py
|
2021-11-23 21:44:59 +08:00
|
|
|
|
from utils.http_utils import AsyncHttpx
|
2022-02-19 18:20:19 +08:00
|
|
|
|
from typing import List, Tuple, Union, Set
|
|
|
|
|
|
from .config import draw_config, DRAW_IMAGE_PATH
|
2021-05-20 19:23:32 +08:00
|
|
|
|
import nonebot
|
2022-02-19 18:20:19 +08:00
|
|
|
|
from PIL import UnidentifiedImageError
|
2021-12-16 11:16:28 +08:00
|
|
|
|
from utils.image_utils import BuildImage
|
2022-02-19 18:20:19 +08:00
|
|
|
|
from nonebot.adapters.onebot.v11 import MessageSegment
|
|
|
|
|
|
from nonebot.log import logger
|
2021-05-26 20:08:13 +08:00
|
|
|
|
import random
|
2021-05-20 19:23:32 +08:00
|
|
|
|
from dataclasses import dataclass
|
2021-06-04 18:01:33 +08:00
|
|
|
|
import os
|
|
|
|
|
|
import asyncio
|
2021-05-20 19:23:32 +08:00
|
|
|
|
|
|
|
|
|
|
|
2022-02-19 18:20:19 +08:00
|
|
|
|
driver = nonebot.get_driver()
|
2021-05-20 19:23:32 +08:00
|
|
|
|
|
|
|
|
|
|
|
2021-06-04 18:01:33 +08:00
|
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-05-20 19:23:32 +08:00
|
|
|
|
@dataclass
|
|
|
|
|
|
class BaseData:
|
|
|
|
|
|
name: str
|
|
|
|
|
|
star: int
|
|
|
|
|
|
limited: bool # 限定
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
|
|
class UpEvent:
|
|
|
|
|
|
star: int # 对应up星级
|
|
|
|
|
|
operators: List[BaseData] # 干员列表
|
|
|
|
|
|
zoom: float # up提升倍率
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def download_img(url: str, path: str, name: str) -> bool:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
path = path.split("_")[0]
|
2021-05-20 19:23:32 +08:00
|
|
|
|
codename = cn2py(name)
|
2022-02-19 18:20:19 +08:00
|
|
|
|
img_path = DRAW_IMAGE_PATH / f"{path}" / f"{codename}.png"
|
|
|
|
|
|
if not img_path.exists():
|
2021-05-20 19:23:32 +08:00
|
|
|
|
try:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
if await AsyncHttpx.download_file(url, img_path):
|
|
|
|
|
|
logger.info(
|
|
|
|
|
|
f"下载 {draw_config.path_dict[path]} 图片成功,名称:{name},url:{url}"
|
|
|
|
|
|
)
|
2021-11-23 21:44:59 +08:00
|
|
|
|
return True
|
2022-02-19 18:20:19 +08:00
|
|
|
|
except TimeoutError:
|
|
|
|
|
|
logger.warning(f"下载 {draw_config.path_dict[path]} 图片超时,名称:{name},url:{url}")
|
|
|
|
|
|
# logger.info(f'{path_dict[path]} 图片 {name} 已存在')
|
2021-11-23 21:44:59 +08:00
|
|
|
|
return False
|
2021-05-20 19:23:32 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@driver.on_startup
|
|
|
|
|
|
def _check_dir():
|
2022-02-19 18:20:19 +08:00
|
|
|
|
for dir_name in draw_config.path_dict.keys():
|
|
|
|
|
|
dir_path = DRAW_IMAGE_PATH / f"{dir_name}"
|
|
|
|
|
|
if not dir_path.exists():
|
|
|
|
|
|
dir_path.mkdir(parents=True, exist_ok=True)
|
2021-05-20 19:23:32 +08:00
|
|
|
|
|
|
|
|
|
|
|
2022-02-19 18:20:19 +08:00
|
|
|
|
async def generate_img(
|
|
|
|
|
|
card_set: Union[Set[BaseData], List[BaseData]], game_name: str, star_list: list
|
|
|
|
|
|
) -> str:
|
2021-05-20 19:23:32 +08:00
|
|
|
|
# try:
|
|
|
|
|
|
img_list = []
|
2021-06-04 18:01:33 +08:00
|
|
|
|
background_list = []
|
2021-05-20 19:23:32 +08:00
|
|
|
|
for x in card_set:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
if game_name == "prts":
|
2021-05-20 19:23:32 +08:00
|
|
|
|
if x.star == 6:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
background_list.append("#FFD700")
|
2021-05-20 19:23:32 +08:00
|
|
|
|
elif x.star == 5:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
background_list.append("#DAA520")
|
2021-05-20 19:23:32 +08:00
|
|
|
|
elif x.star == 4:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
background_list.append("#9370D8")
|
2021-05-20 19:23:32 +08:00
|
|
|
|
else:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
background_list.append("white")
|
|
|
|
|
|
img_path = DRAW_IMAGE_PATH / f"{game_name}" / f"{x.star}_star.png"
|
|
|
|
|
|
if game_name == "azur":
|
|
|
|
|
|
if img_path.exists():
|
|
|
|
|
|
background_list.append(str(img_path))
|
|
|
|
|
|
py_name = cn2py(x.name)
|
|
|
|
|
|
img_list.append(str(DRAW_IMAGE_PATH / f"{game_name}" / f"{py_name}.png"))
|
2021-05-20 19:23:32 +08:00
|
|
|
|
img_len = len(img_list)
|
|
|
|
|
|
w = 100 * 10
|
|
|
|
|
|
if img_len <= 10:
|
|
|
|
|
|
w = 100 * img_len
|
|
|
|
|
|
h = 100
|
|
|
|
|
|
elif img_len % 10 == 0:
|
|
|
|
|
|
h = 100 * int(img_len / 10)
|
|
|
|
|
|
else:
|
|
|
|
|
|
h = 100 * int(img_len / 10) + 100
|
2022-02-19 18:20:19 +08:00
|
|
|
|
card_img = await asyncio.get_event_loop().run_in_executor(
|
|
|
|
|
|
None, _pst, h, img_list, game_name, background_list
|
|
|
|
|
|
)
|
2021-05-20 19:23:32 +08:00
|
|
|
|
num = 0
|
|
|
|
|
|
for n in star_list:
|
|
|
|
|
|
num += n
|
2021-12-16 11:16:28 +08:00
|
|
|
|
A = BuildImage(w, h)
|
2021-05-20 19:23:32 +08:00
|
|
|
|
A.paste(card_img)
|
|
|
|
|
|
return A.pic2bs4()
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-06-04 18:01:33 +08:00
|
|
|
|
def _pst(h: int, img_list: list, game_name: str, background_list: list):
|
2021-12-16 11:16:28 +08:00
|
|
|
|
card_img = BuildImage(100 * 10, h, 100, 100)
|
2021-05-20 19:23:32 +08:00
|
|
|
|
idx = 0
|
|
|
|
|
|
for img in img_list:
|
|
|
|
|
|
try:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
if game_name == "prts":
|
2021-12-16 11:16:28 +08:00
|
|
|
|
bk = BuildImage(100, 100, color=background_list[idx])
|
|
|
|
|
|
b = BuildImage(94, 94, background=img)
|
2021-05-20 19:23:32 +08:00
|
|
|
|
bk.paste(b, (3, 3))
|
|
|
|
|
|
b = bk
|
2022-02-19 18:20:19 +08:00
|
|
|
|
elif game_name == "azur" and background_list:
|
2021-12-16 11:16:28 +08:00
|
|
|
|
bk = BuildImage(100, 100, background=background_list[idx])
|
|
|
|
|
|
b = BuildImage(98, 90, background=img)
|
2021-06-04 18:01:33 +08:00
|
|
|
|
bk.paste(b, (1, 5))
|
|
|
|
|
|
b = bk
|
2021-05-20 19:23:32 +08:00
|
|
|
|
else:
|
2021-06-17 09:43:03 +08:00
|
|
|
|
try:
|
2021-12-16 11:16:28 +08:00
|
|
|
|
b = BuildImage(100, 100, background=img)
|
2021-06-17 09:43:03 +08:00
|
|
|
|
except UnidentifiedImageError as e:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
logger.warning(f"无法识别图片 已删除图片,下次更新重新下载... e:{e}")
|
2021-06-17 09:43:03 +08:00
|
|
|
|
if os.path.exists(img):
|
|
|
|
|
|
os.remove(img)
|
2022-02-19 18:20:19 +08:00
|
|
|
|
b = BuildImage(100, 100, color="black")
|
2021-05-20 19:23:32 +08:00
|
|
|
|
except FileNotFoundError:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
logger.warning(f"{img} not exists")
|
|
|
|
|
|
b = BuildImage(100, 100, color="black")
|
2021-05-20 19:23:32 +08:00
|
|
|
|
card_img.paste(b)
|
2021-06-04 18:01:33 +08:00
|
|
|
|
idx += 1
|
2021-05-20 19:23:32 +08:00
|
|
|
|
return card_img
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-02-19 18:20:19 +08:00
|
|
|
|
# 初始化输出数据
|
|
|
|
|
|
def init_star_rst(
|
|
|
|
|
|
star_list: list,
|
|
|
|
|
|
cnlist: list,
|
|
|
|
|
|
max_star_list: list,
|
|
|
|
|
|
max_star_index_list: list,
|
|
|
|
|
|
up_list: list = None,
|
|
|
|
|
|
) -> str:
|
2021-05-20 19:23:32 +08:00
|
|
|
|
if not up_list:
|
|
|
|
|
|
up_list = []
|
2022-02-19 18:20:19 +08:00
|
|
|
|
rst = ""
|
2021-05-20 19:23:32 +08:00
|
|
|
|
for i in range(len(star_list)):
|
|
|
|
|
|
if star_list[i]:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
rst += f"[{cnlist[i]}×{star_list[i]}] "
|
|
|
|
|
|
rst += "\n"
|
2021-05-20 19:23:32 +08:00
|
|
|
|
for i in range(len(max_star_list)):
|
|
|
|
|
|
if max_star_list[i] in up_list:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
rst += f"第 {max_star_index_list[i]+1} 抽获取UP {max_star_list[i]}\n"
|
2021-05-20 19:23:32 +08:00
|
|
|
|
else:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
rst += f"第 {max_star_index_list[i]+1} 抽获取 {max_star_list[i]}\n"
|
2021-05-20 19:23:32 +08:00
|
|
|
|
return rst
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-02-19 18:20:19 +08:00
|
|
|
|
# 更好的初始化
|
|
|
|
|
|
def init_rst(
|
|
|
|
|
|
max_star_char_dict: dict,
|
|
|
|
|
|
star_num_list: List[int],
|
|
|
|
|
|
star: List[str],
|
|
|
|
|
|
up_list: list = None,
|
|
|
|
|
|
):
|
|
|
|
|
|
# print(max_star_char_dict)
|
|
|
|
|
|
# print(star_num_list)
|
|
|
|
|
|
# print(up_list)
|
|
|
|
|
|
up_list = up_list if up_list else []
|
|
|
|
|
|
rst = ""
|
|
|
|
|
|
for i in range(len(star_num_list)):
|
|
|
|
|
|
if star_num_list[i]:
|
|
|
|
|
|
rst += f"[{star[i]}×{star_num_list[i]}] "
|
|
|
|
|
|
rst += "\n"
|
|
|
|
|
|
_tmp = []
|
|
|
|
|
|
for name in max_star_char_dict.keys():
|
|
|
|
|
|
_tmp += max_star_char_dict[name]
|
|
|
|
|
|
for index in sorted(_tmp):
|
|
|
|
|
|
for name in max_star_char_dict.keys():
|
|
|
|
|
|
if index in max_star_char_dict[name]:
|
|
|
|
|
|
if name in up_list:
|
|
|
|
|
|
rst += f"第 {index} 抽获取UP {name}\n"
|
|
|
|
|
|
else:
|
|
|
|
|
|
rst += f"第 {index} 抽获取 {name}\n"
|
|
|
|
|
|
return rst[:-1] if rst else ""
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-05-20 19:23:32 +08:00
|
|
|
|
def max_card(_dict: dict):
|
|
|
|
|
|
_max_value = max(_dict.values())
|
|
|
|
|
|
_max_user = list(_dict.keys())[list(_dict.values()).index(_max_value)]
|
2022-02-19 18:20:19 +08:00
|
|
|
|
return f"抽取到最多的是{_max_user},共抽取了{_max_value}次"
|
2021-05-20 19:23:32 +08:00
|
|
|
|
# ThreeHighest = nlargest(3, operator_dict, key=operator_dict.get)
|
|
|
|
|
|
# rst = '最喜欢你的前三位是干员是:\n'
|
|
|
|
|
|
# for name in ThreeHighest:
|
|
|
|
|
|
# rst += f'{name} 共投了 {operator_dict[name]} 份简历\n'
|
|
|
|
|
|
# return rst[:-1]
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-02-19 18:20:19 +08:00
|
|
|
|
# 获取up和概率
|
|
|
|
|
|
async def init_up_char(announcement):
|
|
|
|
|
|
UP_CHAR = []
|
|
|
|
|
|
UP_ARMS = []
|
|
|
|
|
|
tmp = ""
|
|
|
|
|
|
up_char_dict = await announcement.update_up_char()
|
|
|
|
|
|
for x in list(up_char_dict.keys()):
|
|
|
|
|
|
tmp += up_char_dict[x]["title"] + "[\n]"
|
|
|
|
|
|
tmp = tmp.split("[\n]")
|
|
|
|
|
|
_CURRENT_CHAR_POOL_TITLE = tmp[0]
|
|
|
|
|
|
if len(up_char_dict) > 1:
|
|
|
|
|
|
_CURRENT_ARMS_POOL_TITLE = tmp[1]
|
|
|
|
|
|
else:
|
|
|
|
|
|
_CURRENT_ARMS_POOL_TITLE = ""
|
|
|
|
|
|
POOL_IMG = ""
|
|
|
|
|
|
x = [x for x in list(up_char_dict.keys())]
|
|
|
|
|
|
if _CURRENT_CHAR_POOL_TITLE:
|
|
|
|
|
|
POOL_IMG += MessageSegment.image(up_char_dict[x[0]]["pool_img"])
|
|
|
|
|
|
try:
|
|
|
|
|
|
if _CURRENT_ARMS_POOL_TITLE:
|
|
|
|
|
|
POOL_IMG += MessageSegment.image(up_char_dict[x[1]]["pool_img"])
|
|
|
|
|
|
except (IndexError, KeyError):
|
|
|
|
|
|
pass
|
|
|
|
|
|
logger.info(
|
|
|
|
|
|
f"成功获取{announcement.game_name}当前up信息...当前up池: {_CURRENT_CHAR_POOL_TITLE} & {_CURRENT_ARMS_POOL_TITLE}"
|
|
|
|
|
|
)
|
|
|
|
|
|
for key in up_char_dict.keys():
|
|
|
|
|
|
for star in up_char_dict[key]["up_char"].keys():
|
|
|
|
|
|
up_char_lst = []
|
|
|
|
|
|
for char in up_char_dict[key]["up_char"][star].keys():
|
|
|
|
|
|
up_char_lst.append(char)
|
|
|
|
|
|
if up_char_lst:
|
|
|
|
|
|
if key == "char":
|
|
|
|
|
|
UP_CHAR.append(
|
|
|
|
|
|
UpEvent(star=int(star), operators=up_char_lst, zoom=0)
|
|
|
|
|
|
)
|
|
|
|
|
|
else:
|
|
|
|
|
|
UP_ARMS.append(
|
|
|
|
|
|
UpEvent(star=int(star), operators=up_char_lst, zoom=0)
|
|
|
|
|
|
)
|
|
|
|
|
|
return (
|
|
|
|
|
|
_CURRENT_CHAR_POOL_TITLE,
|
|
|
|
|
|
_CURRENT_ARMS_POOL_TITLE,
|
|
|
|
|
|
POOL_IMG,
|
|
|
|
|
|
UP_CHAR,
|
|
|
|
|
|
UP_ARMS,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-05-26 20:08:13 +08:00
|
|
|
|
def is_number(s) -> bool:
|
|
|
|
|
|
try:
|
|
|
|
|
|
float(s)
|
|
|
|
|
|
return True
|
|
|
|
|
|
except ValueError:
|
|
|
|
|
|
pass
|
|
|
|
|
|
try:
|
|
|
|
|
|
import unicodedata
|
2022-02-19 18:20:19 +08:00
|
|
|
|
|
2021-05-26 20:08:13 +08:00
|
|
|
|
unicodedata.numeric(s)
|
|
|
|
|
|
return True
|
|
|
|
|
|
except (TypeError, ValueError):
|
|
|
|
|
|
pass
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-05-20 19:23:32 +08:00
|
|
|
|
def set_list(lst: List[BaseData]) -> list:
|
|
|
|
|
|
tmp = []
|
|
|
|
|
|
name_lst = []
|
|
|
|
|
|
for x in lst:
|
|
|
|
|
|
if x.name not in name_lst:
|
|
|
|
|
|
tmp.append(x)
|
|
|
|
|
|
name_lst.append(x.name)
|
|
|
|
|
|
return tmp
|
|
|
|
|
|
|
2021-05-26 20:08:13 +08:00
|
|
|
|
|
2022-02-19 18:20:19 +08:00
|
|
|
|
# 获取星级
|
2021-05-26 20:08:13 +08:00
|
|
|
|
def get_star(star_lst: List[int], probability_lst: List[float]) -> int:
|
|
|
|
|
|
rand = random.random()
|
|
|
|
|
|
add = 0
|
|
|
|
|
|
tmp_lst = [(0, probability_lst[0])]
|
|
|
|
|
|
for i in range(1, len(probability_lst) - 1):
|
|
|
|
|
|
add += probability_lst[i - 1]
|
|
|
|
|
|
tmp_lst.append((tmp_lst[i - 1][1], probability_lst[i] + add))
|
|
|
|
|
|
tmp_lst.append((tmp_lst[-1][1], 1))
|
|
|
|
|
|
for i in range(len(tmp_lst)):
|
|
|
|
|
|
if tmp_lst[i][0] <= rand <= tmp_lst[i][1]:
|
|
|
|
|
|
return star_lst[i]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 整理数据
|
2022-02-19 18:20:19 +08:00
|
|
|
|
def format_card_information(
|
|
|
|
|
|
count: int, star_list: List[int], func, pool_name: str = "", guaranteed: bool = True
|
|
|
|
|
|
):
|
|
|
|
|
|
max_star_lst = [] # 获取的最高星级角色列表
|
|
|
|
|
|
max_index_lst = [] # 获取最高星级角色的次数
|
|
|
|
|
|
obj_list = [] # 获取所有角色
|
|
|
|
|
|
obj_dict = {} # 获取角色次数字典
|
2021-06-24 15:32:06 +08:00
|
|
|
|
_count = -1
|
|
|
|
|
|
if guaranteed:
|
|
|
|
|
|
_count = 0
|
2021-05-26 20:08:13 +08:00
|
|
|
|
for i in range(count):
|
2021-06-24 15:32:06 +08:00
|
|
|
|
if guaranteed:
|
|
|
|
|
|
_count += 1
|
2021-05-26 20:08:13 +08:00
|
|
|
|
if pool_name:
|
2021-06-24 15:32:06 +08:00
|
|
|
|
if _count == 10:
|
|
|
|
|
|
obj, code = func(pool_name, 2)
|
|
|
|
|
|
_count = 0
|
|
|
|
|
|
else:
|
|
|
|
|
|
obj, code = func(pool_name)
|
2021-05-26 20:08:13 +08:00
|
|
|
|
else:
|
2021-06-24 15:32:06 +08:00
|
|
|
|
if _count == 10:
|
|
|
|
|
|
obj, code = func(mode=2)
|
|
|
|
|
|
_count = 0
|
|
|
|
|
|
else:
|
|
|
|
|
|
obj, code = func()
|
2021-05-26 20:08:13 +08:00
|
|
|
|
star_list[code] += 1
|
|
|
|
|
|
if code == 0:
|
|
|
|
|
|
max_star_lst.append(obj.name)
|
|
|
|
|
|
max_index_lst.append(i)
|
2021-06-24 15:32:06 +08:00
|
|
|
|
if guaranteed:
|
|
|
|
|
|
_count = 0
|
|
|
|
|
|
if code == 1:
|
|
|
|
|
|
if guaranteed:
|
|
|
|
|
|
_count = 0
|
2021-05-26 20:08:13 +08:00
|
|
|
|
try:
|
|
|
|
|
|
obj_dict[obj.name] += 1
|
|
|
|
|
|
except KeyError:
|
|
|
|
|
|
obj_dict[obj.name] = 1
|
|
|
|
|
|
obj_list.append(obj)
|
|
|
|
|
|
return obj_list, obj_dict, max_star_lst, star_list, max_index_lst
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 检测次数是否合法
|
2022-02-19 18:20:19 +08:00
|
|
|
|
def check_num(num: str, max_num: int) -> Tuple[str, bool]:
|
2021-05-26 20:08:13 +08:00
|
|
|
|
if is_number(num):
|
|
|
|
|
|
try:
|
|
|
|
|
|
num = int(num)
|
|
|
|
|
|
except ValueError:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
return "必!须!是!数!字!", False
|
2021-05-26 20:08:13 +08:00
|
|
|
|
if num > max_num:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
return "一井都满不足不了你嘛!快爬开!", False
|
2021-05-26 20:08:13 +08:00
|
|
|
|
if num < 1:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
return "虚空抽卡???", False
|
2021-05-26 20:08:13 +08:00
|
|
|
|
else:
|
|
|
|
|
|
return str(num), True
|
|
|
|
|
|
|
2021-06-04 18:01:33 +08:00
|
|
|
|
|
|
|
|
|
|
# 移除windows和linux下特殊字符
|
2022-02-19 18:20:19 +08:00
|
|
|
|
def remove_prohibited_str(name: str) -> str:
|
|
|
|
|
|
if platform.system().lower() == "windows":
|
|
|
|
|
|
tmp = ""
|
2021-06-04 18:01:33 +08:00
|
|
|
|
for i in name:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
if i not in ["\\", "/", ":", "*", "?", '"', "<", ">", "|"]:
|
2021-06-04 18:01:33 +08:00
|
|
|
|
tmp += i
|
|
|
|
|
|
name = tmp
|
|
|
|
|
|
else:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
name = name.replace("/", "\\")
|
2021-06-04 18:01:33 +08:00
|
|
|
|
return name
|