diff --git a/GenshinUID/genshinuid_enka/__init__.py b/GenshinUID/genshinuid_enka/__init__.py index aa1b9014..b2c3adde 100644 --- a/GenshinUID/genshinuid_enka/__init__.py +++ b/GenshinUID/genshinuid_enka/__init__.py @@ -16,6 +16,7 @@ from ..utils.convert import get_uid from .get_akasha_data import get_rank from .start import refresh_player_list from .draw_artifacts_lib import draw_lib +from .draw_rank_list import draw_rank_img from ..utils.image.convert import convert_img from ..utils.map.GS_MAP_PATH import alias_data from .draw_char_rank import draw_cahrcard_list @@ -40,6 +41,16 @@ async def sned_rank_data(bot: Bot, ev: Event): await bot.send(await get_rank(uid)) +@sv_akasha.on_command('排名列表') +async def sned_rank_pic(bot: Bot, ev: Event): + # 获取uid + uid = await get_uid(bot, ev) + if uid is None: + return await bot.send(UID_HINT) + logger.info(f'[排名列表]uid: {uid}') + await bot.send(await draw_rank_img(ev.user_id, uid)) + + @sv_enka_admin.on_fullmatch('刷新全部圣遗物仓库') async def sned_fresh_all_list(bot: Bot, ev: Event): await bot.send('开始执行...可能时间较久, 执行完成会有提示, 请勿重复执行!') diff --git a/GenshinUID/genshinuid_enka/draw_rank_list.py b/GenshinUID/genshinuid_enka/draw_rank_list.py new file mode 100644 index 00000000..a334fc4f --- /dev/null +++ b/GenshinUID/genshinuid_enka/draw_rank_list.py @@ -0,0 +1,207 @@ +from typing import Dict, Union + +from PIL import Image, ImageDraw +from gsuid_core.utils.image.convert import convert_img +from gsuid_core.utils.image.image_tools import crop_center_img + +from .etc.etc import TEXT_PATH +from .get_akasha_data import _get_rank +from ..utils.map.name_covert import avatar_id_to_name +from .to_card import draw_char_card, draw_weapon_card +from ..utils.image.image_tools import get_qq_avatar, draw_pic_with_ring +from ..utils.fonts.genshin_fonts import ( + gs_font_15, + gs_font_22, + gs_font_26, + gs_font_32, + gs_font_44, +) + +RANK_TEXT = TEXT_PATH / 'rank_img' +BG_PATH = RANK_TEXT / 'dark_blue.jpg' +TITLE_PATH = RANK_TEXT / 'title.png' + +grey = (191, 191, 191) +COLOR_MAP = { + '1': (200, 12, 12), + '2': (200, 100, 12), + '3': (200, 12, 194), + '4': (33, 142, 212), + '5': (47, 107, 56), +} + + +async def draw_rank_img(user_id: str, uid: str) -> Union[bytes, str]: + rank_data = await _get_rank(uid) + if isinstance(rank_data, str): + return rank_data + + user_avatar = await get_qq_avatar(user_id) + user_pic = await draw_pic_with_ring(user_avatar, 314) + title = Image.open(TITLE_PATH) + title_draw = ImageDraw.Draw(title) + + title.paste(user_pic, (318, 57), user_pic) + title_draw.text((475, 425), f'UID {uid}', 'white', gs_font_26, 'mm') + + w, h = 950, 500 + len(rank_data) * 305 + 50 + img = crop_center_img(Image.open(BG_PATH), w, h) + + img.paste(title, (0, 0), title) + + for index, char in enumerate(rank_data): + raw_data = rank_data[char] + + time = raw_data['time'] + data = raw_data['calculations']['fit'] + stats: Dict = data['stats'] + char_name = await avatar_id_to_name(char) + result = '{:.2f}'.format(data['result']) + rank = data['ranking'] + if isinstance(rank, str): + rank = int(rank[1:]) + outof = data['outOf'] + _pc = float('{:.2f}'.format((rank / outof) * 100)) + + _hp = str(int(float(stats['maxHP']))) + _atk = str(int(float(stats['maxATK']))) + _def = str(int(float(stats['maxDEF']))) + _em = str(int(float(stats['elementalMastery']))) + _er = '{:.2f}%'.format(stats['energyRecharge']) + _cr = '{:.2f}%'.format(stats['critRate']) + _cd = '{:.2f}%'.format(stats['critDMG']) + _cv = int(float(stats['critValue'])) + _dmg = '{:.1f}%'.format(list(stats.values())[-1]) + + char_card = await draw_char_card(char) + weapon_card = await draw_weapon_card( + data['weapon']['icon'], data['weapon']['rarity'] + ) + weapon_card = weapon_card.resize((110, 110)) + + if _pc <= 10: + _color = COLOR_MAP['1'] + elif _pc <= 23: + _color = COLOR_MAP['2'] + elif _pc <= 35: + _color = COLOR_MAP['3'] + elif _pc <= 55: + _color = COLOR_MAP['4'] + else: + _color = COLOR_MAP['5'] + + if _cv >= 210: + cv_color = COLOR_MAP['1'] + elif _cv >= 185: + cv_color = COLOR_MAP['2'] + elif _cv >= 170: + cv_color = COLOR_MAP['3'] + elif _cv >= 150: + cv_color = COLOR_MAP['4'] + else: + cv_color = COLOR_MAP['5'] + + color = Image.new('RGBA', (950, 300), _color) + + tag_weapon = Image.open( + TEXT_PATH / f'char_card_{data["weapon"]["refinement"]}.png' + ).resize((40, 40)) + + if index % 2 == 0: + char_img = Image.open(RANK_TEXT / 'left.png') + bar = Image.open(RANK_TEXT / 'left_bar.png') + char_img.paste(color, (0, 0), bar) + char_img.paste(char_card, (-40, 1), char_card) + char_img.paste(weapon_card, (78, 166), weapon_card) + char_img.paste(tag_weapon, (140, 140), tag_weapon) + + char_draw = ImageDraw.Draw(char_img) + + char_draw.text( + (880, 39), f'数据最后更新于 {time}', grey, gs_font_15, 'rm' + ) + char_draw.text( + (174, 37), f'{char_name}', 'white', gs_font_32, 'lm' + ) + + char_draw.text( + (161, 161), + str(data["weapon"]["refinement"]), + 'white', + gs_font_26, + 'mm', + ) + + char_draw.text((361, 129), _hp, 'white', gs_font_26, 'lm') + char_draw.text((361, 169), _atk, 'white', gs_font_26, 'lm') + char_draw.text((361, 210), _def, 'white', gs_font_26, 'lm') + + char_draw.text((564, 129), _em, 'white', gs_font_26, 'lm') + char_draw.text((564, 169), _er, 'white', gs_font_26, 'lm') + char_draw.text((564, 210), _dmg, 'white', gs_font_26, 'lm') + + char_draw.text((791, 129), _cr, 'white', gs_font_26, 'lm') + char_draw.text((791, 169), _cd, 'white', gs_font_26, 'lm') + + char_draw.text((263, 260), '测试项目: 未知', grey, gs_font_22, 'lm') + char_draw.text( + (716, 257), str(int(float(result))), 'white', gs_font_44, 'lm' + ) + + char_draw.rounded_rectangle((258, 65, 384, 95), 20, cv_color) + char_draw.rounded_rectangle((389, 65, 547, 95), 20, _color) + char_draw.rounded_rectangle((552, 65, 710, 95), 20, _color) + + char_draw.text((321, 80), f'{_cv}分', 'white', gs_font_26, 'mm') + char_draw.text((467, 80), f'{rank}名', 'white', gs_font_26, 'mm') + char_draw.text((631, 80), f'前{_pc}%', 'white', gs_font_26, 'mm') + else: + char_img = Image.open(RANK_TEXT / 'right.png') + bar = Image.open(RANK_TEXT / 'right_bar.png') + char_img.paste(color, (0, 0), bar) + char_img.paste(char_card, (775, 1), char_card) + char_img.paste(weapon_card, (770, 166), weapon_card) + char_img.paste(tag_weapon, (768, 140), tag_weapon) + + char_draw = ImageDraw.Draw(char_img) + + char_draw.text((65, 39), f'数据最后更新于 {time}', grey, gs_font_15, 'lm') + char_draw.text( + (760, 37), f'{char_name}', 'white', gs_font_32, 'rm' + ) + + char_draw.text( + (789, 161), + str(data["weapon"]["refinement"]), + 'white', + gs_font_26, + 'mm', + ) + + char_draw.text((599, 129), _hp, 'white', gs_font_26, 'lm') + char_draw.text((599, 169), _atk, 'white', gs_font_26, 'lm') + char_draw.text((599, 210), _def, 'white', gs_font_26, 'lm') + + char_draw.text((386, 129), _em, 'white', gs_font_26, 'lm') + char_draw.text((386, 169), _er, 'white', gs_font_26, 'lm') + char_draw.text((386, 210), _dmg, 'white', gs_font_26, 'lm') + + char_draw.text((169, 129), _cr, 'white', gs_font_26, 'lm') + char_draw.text((169, 169), _cd, 'white', gs_font_26, 'lm') + + char_draw.text((669, 260), '测试项目: 未知', grey, gs_font_22, 'rm') + char_draw.text( + (237, 249), str(int(float(result))), 'white', gs_font_44, 'rm' + ) + + char_draw.rounded_rectangle((52, 65, 177, 95), 20, cv_color) + char_draw.rounded_rectangle((183, 65, 341, 95), 20, _color) + char_draw.rounded_rectangle((346, 65, 504, 95), 20, _color) + + char_draw.text((115, 80), f'{_cv}分', 'white', gs_font_26, 'mm') + char_draw.text((261, 80), f'{rank}名', 'white', gs_font_26, 'mm') + char_draw.text((425, 80), f'前{_pc}%', 'white', gs_font_26, 'mm') + + img.paste(char_img, (0, 485 + index * 305), char_img) + + return await convert_img(img) diff --git a/GenshinUID/genshinuid_enka/get_akasha_data.py b/GenshinUID/genshinuid_enka/get_akasha_data.py index 63a8f336..306747b6 100644 --- a/GenshinUID/genshinuid_enka/get_akasha_data.py +++ b/GenshinUID/genshinuid_enka/get_akasha_data.py @@ -1,4 +1,5 @@ import json +from typing import Dict, Union import aiofiles @@ -9,7 +10,7 @@ from ..utils.resource.RESOURCE_PATH import PLAYER_PATH is_enable_akasha = gsconfig.get_config('EnableAkasha').data -async def get_rank(uid: str) -> str: +async def _get_rank(uid: str) -> Union[Dict, str]: if not is_enable_akasha: return '未开启排名系统...' path = PLAYER_PATH / uid / 'rank.json' @@ -22,6 +23,14 @@ async def get_rank(uid: str) -> str: if len(rank_data) == 0: return '你还没有排名缓存, 请使用[强制刷新]生成/刷新数据!' + return rank_data + + +async def get_rank(uid: str) -> str: + rank_data = await _get_rank(uid) + if isinstance(rank_data, str): + return rank_data + im_list = [f'UID {uid}'] for char in rank_data: diff --git a/GenshinUID/genshinuid_enka/texture2D/char_card_1.png b/GenshinUID/genshinuid_enka/texture2D/char_card_1.png new file mode 100644 index 00000000..50b52ed2 Binary files /dev/null and b/GenshinUID/genshinuid_enka/texture2D/char_card_1.png differ diff --git a/GenshinUID/genshinuid_enka/texture2D/char_card_2.png b/GenshinUID/genshinuid_enka/texture2D/char_card_2.png new file mode 100644 index 00000000..034d9fa1 Binary files /dev/null and b/GenshinUID/genshinuid_enka/texture2D/char_card_2.png differ diff --git a/GenshinUID/genshinuid_enka/texture2D/char_card_3.png b/GenshinUID/genshinuid_enka/texture2D/char_card_3.png new file mode 100644 index 00000000..a3d64da0 Binary files /dev/null and b/GenshinUID/genshinuid_enka/texture2D/char_card_3.png differ diff --git a/GenshinUID/genshinuid_enka/texture2D/rank_img/dark_blue.jpg b/GenshinUID/genshinuid_enka/texture2D/rank_img/dark_blue.jpg new file mode 100644 index 00000000..6bafd25a Binary files /dev/null and b/GenshinUID/genshinuid_enka/texture2D/rank_img/dark_blue.jpg differ diff --git a/GenshinUID/genshinuid_enka/texture2D/rank_img/left.png b/GenshinUID/genshinuid_enka/texture2D/rank_img/left.png new file mode 100644 index 00000000..3bc5d4c6 Binary files /dev/null and b/GenshinUID/genshinuid_enka/texture2D/rank_img/left.png differ diff --git a/GenshinUID/genshinuid_enka/texture2D/rank_img/left_bar.png b/GenshinUID/genshinuid_enka/texture2D/rank_img/left_bar.png new file mode 100644 index 00000000..4bf72933 Binary files /dev/null and b/GenshinUID/genshinuid_enka/texture2D/rank_img/left_bar.png differ diff --git a/GenshinUID/genshinuid_enka/texture2D/rank_img/right.png b/GenshinUID/genshinuid_enka/texture2D/rank_img/right.png new file mode 100644 index 00000000..e3d99068 Binary files /dev/null and b/GenshinUID/genshinuid_enka/texture2D/rank_img/right.png differ diff --git a/GenshinUID/genshinuid_enka/texture2D/rank_img/right_bar.png b/GenshinUID/genshinuid_enka/texture2D/rank_img/right_bar.png new file mode 100644 index 00000000..5be9a90c Binary files /dev/null and b/GenshinUID/genshinuid_enka/texture2D/rank_img/right_bar.png differ diff --git a/GenshinUID/genshinuid_enka/texture2D/rank_img/title.png b/GenshinUID/genshinuid_enka/texture2D/rank_img/title.png new file mode 100644 index 00000000..ac4f9b28 Binary files /dev/null and b/GenshinUID/genshinuid_enka/texture2D/rank_img/title.png differ diff --git a/GenshinUID/genshinuid_enka/to_card.py b/GenshinUID/genshinuid_enka/to_card.py index 5e6e68b6..b4cd7428 100644 --- a/GenshinUID/genshinuid_enka/to_card.py +++ b/GenshinUID/genshinuid_enka/to_card.py @@ -7,8 +7,9 @@ from gsuid_core.utils.api.enka.models import EnkaData from .to_data import enka_to_dict from ..utils.image.convert import convert_img -from ..utils.resource.RESOURCE_PATH import CHAR_PATH +from ..utils.resource.download_url import download from ..utils.fonts.genshin_fonts import gs_font_18, gs_font_58 +from ..utils.resource.RESOURCE_PATH import CHAR_PATH, ICON_PATH from ..utils.map.name_covert import name_to_avatar_id, avatar_id_to_char_star half_color = (255, 255, 255, 120) @@ -100,18 +101,35 @@ async def draw_enka_card( return img -async def draw_enka_char(index: int, img: Image.Image, char_data: dict): - char_id = char_data['avatarId'] +async def draw_char_card(char_id: str) -> Image.Image: char_star = await avatar_id_to_char_star(str(char_id)) char_card = Image.open(TEXT_PATH / f'char_card_{char_star}.png') char_img = ( - Image.open(str(CHAR_PATH / f'{char_id}.png')) + Image.open(CHAR_PATH / f'{char_id}.png') .convert('RGBA') .resize((204, 204)) ) char_temp = Image.new('RGBA', (220, 220)) char_temp.paste(char_img, (8, 8), char_img) char_card.paste(char_temp, (0, 0), char_mask) + return char_card + + +async def draw_weapon_card(icon_url: str, rarity: str) -> Image.Image: + weapon_card = Image.open(TEXT_PATH / f'char_card_{rarity}.png') + weapon_icon_name = icon_url.split('/')[-1] + path = ICON_PATH / weapon_icon_name + if not path.exists(): + await download(icon_url, 8, weapon_icon_name) + weapon_img = Image.open(path).convert('RGBA').resize((204, 204)) + weapon_temp = Image.new('RGBA', (220, 220)) + weapon_temp.paste(weapon_img, (8, 8), weapon_img) + weapon_card.paste(weapon_temp, (0, 0), char_mask) + return weapon_card + + +async def draw_enka_char(index: int, img: Image.Image, char_data: dict): + char_card = await draw_char_card(char_data['avatarId']) if index <= 7: if img.size[0] <= 1100: x = 60 + (index % 4) * 220 diff --git a/GenshinUID/utils/image/bg/sp_bg/dark_blue.jpg b/GenshinUID/utils/image/bg/sp_bg/dark_blue.jpg new file mode 100644 index 00000000..6bafd25a Binary files /dev/null and b/GenshinUID/utils/image/bg/sp_bg/dark_blue.jpg differ