GenshinUID/genshinuid_gachalog/draw_gachalogs.py
2022-08-29 23:12:44 +08:00

267 lines
8.4 KiB
Python

import json
import time
import asyncio
from pathlib import Path
from typing import List, Tuple, Union, Optional
from nonebot.log import logger
from PIL import Image, ImageDraw
from ..utils.get_cookies.get_cookies import GetCookies
from ..utils.draw_image_tools.send_image_tool import convert_img
from ..utils.draw_image_tools.draw_image_tool import get_simple_bg
from ..utils.genshin_fonts.genshin_fonts import genshin_font_origin
from ..utils.alias.avatarId_and_name_covert import name_to_avatar_id
TEXT_PATH = Path(__file__).parent / 'texture2d'
PLAYER_PATH = Path(__file__).parents[1] / 'player'
RESOURCE_PATH = Path(__file__).parents[1] / 'resource'
CHAR_PATH = RESOURCE_PATH / 'chars'
STAND_PATH = RESOURCE_PATH / 'char_stand'
WEAPON_PATH = RESOURCE_PATH / 'weapon'
title_mask = Image.open(TEXT_PATH / 'title_mask.png')
gs_font_16 = genshin_font_origin(16)
gs_font_23 = genshin_font_origin(23)
gs_font_26 = genshin_font_origin(26)
gs_font_28 = genshin_font_origin(28)
gs_font_40 = genshin_font_origin(40)
first_color = (29, 29, 29)
brown_color = (41, 25, 0)
red_color = (255, 66, 66)
green_color = (74, 189, 119)
CHANGE_MAP = {'常驻祈愿': 'normal', '角色祈愿': 'char', '武器祈愿': 'weapon'}
async def _get_tag(level: int) -> Image.Image:
return Image.open(TEXT_PATH / f'tag_{level}.png')
async def _draw_card(
img: Image.Image,
xy_point: Tuple[int, int],
type: str,
name: str,
gacha_num: int,
):
card_img = Image.open(TEXT_PATH / 'item_bg.png')
card_img_draw = ImageDraw.Draw(card_img)
point = (1, 0)
text_point = (55, 124)
if type == '角色':
name = await name_to_avatar_id(name)
item_pic = (
Image.open(CHAR_PATH / f'{name}.png')
.convert('RGBA')
.resize((108, 108))
)
else:
item_pic = (
Image.open(WEAPON_PATH / f'{name}.png')
.convert('RGBA')
.resize((108, 108))
)
card_img.paste(item_pic, point, item_pic)
if gacha_num >= 81:
text_color = red_color
elif gacha_num <= 55:
text_color = green_color
else:
text_color = brown_color
card_img_draw.text(
text_point, f'{gacha_num}', text_color, gs_font_23, 'mm'
)
img.paste(card_img, xy_point, card_img)
async def draw_gachalogs_img(uid: str) -> Union[bytes, str]:
path = PLAYER_PATH / str(uid) / 'gacha_logs.json'
if not path.exists():
return '你还没有祈愿数据噢~\n请添加Stoken后使用命令`刷新抽卡记录`更新祈愿数据~'
with open(path, 'r', encoding='UTF-8') as f:
gacha_data = json.load(f)
# 数据初始化
total_data = {}
for i in ['常驻祈愿', '角色祈愿', '武器祈愿']:
total_data[i] = {
'total': 0,
'avg': 0,
'remain': 0,
'item': '',
'list': [],
}
data_list = gacha_data['data'][i]
is_not_first = False
num_temp = []
num = 1
for data in data_list[::-1]:
if data['rank_type'] == '5':
data['gacha_num'] = num
# 排除第一个
if is_not_first:
num_temp.append(num)
if num_temp == []:
is_not_first = True
total_data[i]['list'].append(data)
num = 1
total_data[i]['total'] += 1
else:
num += 1
if i == '武器祈愿':
total_data[i]['item'] = '班尼特'
elif i == '常驻祈愿':
total_data[i]['item'] = '刻晴'
else:
g = {}
for k in total_data[i]['list']:
if k['name'] in g:
g[k['name']] += 1
else:
g[k['name']] = 1
total_data[i]['item'] = max(g, key=lambda x: g[x])
total_data[i]['item'] = await name_to_avatar_id(total_data[i]['item'])
total_data[i]['remain'] = num - 1
if len(num_temp) == 0:
total_data[i]['avg'] = 0
else:
total_data[i]['avg'] = float(
'{:.2f}'.format(sum(num_temp) / len(num_temp))
)
# 常量偏移数据
single_y = 150
title_y = 300
# 计算图片尺寸
normal_y = (
1 + ((total_data['常驻祈愿']['total'] - 1) // 6)
) * single_y + title_y
char_y = (
1 + ((total_data['角色祈愿']['total'] - 1) // 6)
) * single_y + title_y
weapon_y = (
1 + ((total_data['武器祈愿']['total'] - 1) // 6)
) * single_y + title_y
# 获取背景图片各项参数
based_w = 800
based_h = normal_y + char_y + weapon_y + 200
white_overlay = Image.new('RGBA', (based_w, based_h), (255, 255, 255, 220))
bg_img = await get_simple_bg(based_w, based_h)
bg_img.paste(white_overlay, (0, 0), white_overlay)
# 总标题
all_title = Image.open(TEXT_PATH / 'all_title.png')
all_title_draw = ImageDraw.Draw(all_title)
# 写UID
all_title_draw.text((47, 181), f'{uid}', first_color, gs_font_26, 'lm')
bg_img.paste(all_title, (0, 0), all_title)
# 处理title
# {'total': 0, 'avg': 0, 'remain': 0, 'list': []}
type_list = ['常驻祈愿', '角色祈愿', '武器祈愿']
y_extend = 0
for index, i in enumerate(type_list):
title = Image.open(TEXT_PATH / 'gahca_title.png')
title_pic = (
Image.open(STAND_PATH / f'{total_data[i]["item"]}.png')
.convert('RGBA')
.resize((1292, 792))
)
temp_pic = Image.new('RGBA', (800, 300), (0, 0, 0, 0))
temp_pic.paste(title_pic, (-70, -56), title_pic)
temp_mask = Image.new('RGBA', (800, 300), (0, 0, 0, 0))
temp_mask.paste(temp_pic, (0, 0), title_mask)
temp_mask.putalpha(
temp_mask.getchannel('A').point(
lambda x: round(x * 0.6) if x > 0 else 0
)
)
title = Image.alpha_composite(title, temp_mask)
if total_data[i]['avg'] == 0:
level = 3
else:
# 非酋 <= 90
# 小非 <= 80
# 稳定 <= 72
# 小欧 <= 60
# 欧皇 <= 43
# 武器统一减10
for num_index, num in enumerate([42, 58, 68, 75, 90]):
if i == '武器祈愿':
num -= 10
if total_data[i]['avg'] <= num:
level = 5 - num_index
break
else:
level = 3
tag_pic = await _get_tag(level)
tag_pic = tag_pic.resize((208, 88))
title.paste(tag_pic, (35, 54), tag_pic)
title_draw = ImageDraw.Draw(title)
# 卡池
title_draw.text((245, 86), i, first_color, gs_font_40, 'lm')
# 抽卡时间
if gacha_data['data'][i]:
first_time = gacha_data['data'][i][0]['time'].split(' ')[0]
else:
first_time = '暂未抽过卡!'
title_draw.text((245, 123), first_time, first_color, gs_font_28, 'lm')
# 平均抽卡数量
title_draw.text(
(108, 209),
str(total_data[i]['avg']),
first_color,
gs_font_40,
'mm',
)
title_draw.text(
(261, 209),
str(gacha_data[f'{CHANGE_MAP[i]}_gacha_num']),
first_color,
gs_font_40,
'mm',
)
title_draw.text(
(104, 160),
str(total_data[i]['remain']),
red_color,
gs_font_28,
'mm',
)
y_extend += (
(1 + ((total_data[type_list[index - 1]]['total'] - 1) // 6)) * 150
if index != 0
else 0
)
y = index * title_y + y_extend + 200
bg_img.paste(title, (0, y), title)
tasks = []
for item_index, item in enumerate(total_data[i]['list']):
item_x = (item_index % 6) * 129 + 20
item_y = (item_index // 6) * 150 + y + title_y
xy_point = (item_x, item_y)
tasks.append(
_draw_card(
bg_img,
xy_point,
item['item_type'],
item['name'],
item['gacha_num'],
)
)
await asyncio.gather(*tasks)
tasks.clear()
# 发送图片
res = await convert_img(bg_img)
logger.info('[查询抽卡]绘图已完成,等待发送!')
return res