✨ 初步支持排名列表
(#493)
@ -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('开始执行...可能时间较久, 执行完成会有提示, 请勿重复执行!')
|
||||
|
207
GenshinUID/genshinuid_enka/draw_rank_list.py
Normal file
@ -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)
|
@ -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:
|
||||
|
BIN
GenshinUID/genshinuid_enka/texture2D/char_card_1.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
GenshinUID/genshinuid_enka/texture2D/char_card_2.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
GenshinUID/genshinuid_enka/texture2D/char_card_3.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
GenshinUID/genshinuid_enka/texture2D/rank_img/dark_blue.jpg
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
GenshinUID/genshinuid_enka/texture2D/rank_img/left.png
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
GenshinUID/genshinuid_enka/texture2D/rank_img/left_bar.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
GenshinUID/genshinuid_enka/texture2D/rank_img/right.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
GenshinUID/genshinuid_enka/texture2D/rank_img/right_bar.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
GenshinUID/genshinuid_enka/texture2D/rank_img/title.png
Normal file
After Width: | Height: | Size: 241 KiB |
@ -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
|
||||
|
BIN
GenshinUID/utils/image/bg/sp_bg/dark_blue.jpg
Normal file
After Width: | Height: | Size: 44 KiB |