深渊统计ui美化,补充新武器图鉴

This commit is contained in:
CMHopeSunshine 2022-09-27 22:42:04 +08:00
parent 7f9759dd8d
commit 18faeb17ae
3 changed files with 198 additions and 33 deletions

View File

@ -62,7 +62,8 @@
"10000102": ["散兵", "伞兵", "国崩", "卢本伟", "大炮", "sb"],
"10000103": ["迪希雅"],
"10000104": ["艾尔海森", "苏"],
"10000105": ["白术"]
"10000105": ["白术"],
"10000106": ["莱依拉"]
},
"武器": {
"磐岩结绿": [
@ -641,6 +642,19 @@
"西福斯的月光",
"西福斯",
"月光"
],
"赤沙之杖": [
"赤沙之杖",
"赤沙"
],
"风信之锋": [
"风信之锋",
"风信"
],
"玛海菈的水色": [
"玛海菈的水色",
"玛海菈",
"水色"
]
},
"圣遗物": {

View File

@ -1,45 +1,99 @@
import datetime
from typing import Dict, Any, Tuple
from collections import defaultdict
from nonebot import get_bot
from LittlePaimon.database.models import AbyssInfo
from LittlePaimon.utils.image import PMImage, font_manager as fm
from LittlePaimon.utils import aiorequests
from LittlePaimon.utils.files import load_image
from LittlePaimon.config import RESOURCE_BASE_PATH
from LittlePaimon.utils.image import PMImage, font_manager as fm, get_qq_avatar
from LittlePaimon.utils.message import MessageBuild
async def get_user_avatar(user_id: str, size: Tuple[int, int] = (60, 60)):
img = await get_qq_avatar(user_id)
await img.resize(size)
await img.to_circle('circle')
return img
async def get_group_avatar(group_id: str):
img = await aiorequests.get_img(f'https://p.qlogo.cn/gh/{group_id}/{group_id}/100', size=(110, 110))
img = PMImage(img)
await img.to_circle('circle')
return img
async def get_statistics(group_id: int):
if not (info_list := await AbyssInfo.all()):
return '本群还没有深渊战斗数据哦!'
member_list = await get_bot().get_group_member_list(group_id=group_id)
member_id_list = [str(member['user_id']) for member in member_list]
info_list = [info for info in info_list if info.user_id in member_id_list and info.total_battle and info.total_star and info.max_damage and info.max_take_damage]
info_list = [info for info in info_list if
info.user_id in member_id_list and info.total_battle and info.total_star and info.max_damage and info.max_take_damage]
now = datetime.datetime.now()
if 1 <= now.day < 15:
if now.day <= 15:
left_day = 1
right_day = 15
else:
left_day = 16
right_day = 31
info_list = [info for info in info_list if left_day <= info.update_time.day <= right_day]
info_list = [info for info in info_list if left_day <= info.update_time.day <= right_day and info.update_time.month == now.month]
if not info_list:
return '本群还没有深渊战斗数据哦!'
elif len(info_list) < 3:
return '本群深渊有效战斗数据不足3人无法生成统计图'
for info in info_list:
for member in member_list:
if info.user_id == str(member['user_id']):
info.nickname = member['card'] or member['nickname']
break
data = {
'群号': str(group_id),
'群名称': (await get_bot().get_group_info(group_id=group_id))['group_name'],
}
# 数据数
info_num = len(info_list)
data['总人数'] = info_num
# 满星人数
full_star_num = len([info for info in info_list if info.total_star >= 36])
data['满星人数'] = full_star_num
# 平均星数
average_star = round(sum(info.total_star for info in info_list) / info_num, 1)
data['平均星数'] = average_star
# 平均战斗次数
average_battle_num = round(sum(info.total_battle for info in info_list) / info_num, 1)
data['平均战斗次数'] = average_battle_num
# 最高伤害角色
max_damage = max(info_list, key=lambda x: x.max_damage.value)
# print(max_damage)
# return '123'
max_damage_user = [m for m in member_list if str(m['user_id']) == max_damage.user_id][0]
max_damage_user = max_damage_user['card'] or max_damage_user['nickname']
# max_damage = max(info_list, key=lambda x: x.max_damage.value)
max_damage = sorted(info_list, key=lambda x: x.max_damage.value, reverse=True)
data['最高伤害'] = [
{
'图标': info.max_damage.icon,
'稀有度': info.max_damage.rarity,
'等级': info.max_damage.level,
'数值': info.max_damage.value,
# '命座': (await Character.filter(user_id=info.user_id, uid=info.uid, character_id=info.max_damage.character_id).first()).constellation,
'用户名': info.nickname,
'qq号': info.user_id,
'uid': info.uid,
} for info in max_damage[:3]
]
# 最多承伤角色
max_take_damage = max(info_list, key=lambda x: x.max_take_damage.value)
max_take_damage_user = [m for m in member_list if str(m['user_id']) == max_take_damage.user_id][0]
max_take_damage_user = max_take_damage_user['card'] or max_take_damage_user['nickname']
max_take_damage = sorted(info_list, key=lambda x: x.max_take_damage.value, reverse=True)
data['最高承受伤害'] = [
{
'图标': info.max_take_damage.icon,
'稀有度': info.max_take_damage.rarity,
'等级': info.max_take_damage.level,
'数值': info.max_take_damage.value,
# '命座': (await Character.filter(user_id=info.user_id, uid=info.uid, character_id=info.max_damage.character_id).first()).constellation,
'用户名': info.nickname,
'qq号': info.user_id,
'uid': info.uid,
} for info in max_take_damage[:3]
]
# 11、12层阵容
battle_characters_up11 = defaultdict(lambda: 0)
battle_characters_down11 = defaultdict(lambda: 0)
@ -49,32 +103,127 @@ async def get_statistics(group_id: int):
if floor11 := info.floors.get(11):
for battles in floor11.battles_up:
for character in battles.characters:
battle_characters_up11[character.name] += 1
battle_characters_up11[f'{character.icon}-{character.rarity}'] += 1
for battles in floor11.battles_down:
for character in battles.characters:
battle_characters_down11[character.name] += 1
battle_characters_down11[f'{character.icon}-{character.rarity}'] += 1
if floor12 := info.floors.get(12):
for battles in floor12.battles_up:
for character in battles.characters:
battle_characters_up12[character.name] += 1
battle_characters_up12[f'{character.icon}-{character.rarity}'] += 1
for battles in floor12.battles_down:
for character in battles.characters:
battle_characters_down12[character.name] += 1
up_sort11 = [character[0] for character in
sorted(battle_characters_up11.items(), key=lambda x: x[1], reverse=True)[:4]]
down_sort11 = [character[0] for character in
sorted(battle_characters_down11.items(), key=lambda x: x[1], reverse=True)[:4]]
up_sort12 = [character[0] for character in
sorted(battle_characters_up12.items(), key=lambda x: x[1], reverse=True)[:4]]
down_sort12 = [character[0] for character in
sorted(battle_characters_down12.items(), key=lambda x: x[1], reverse=True)[:4]]
battle_characters_down12[f'{character.icon}-{character.rarity}'] += 1
data['11层上半'] = sorted(battle_characters_up11.items(), key=lambda x: x[1], reverse=True)[:4]
data['11层下半'] = sorted(battle_characters_down11.items(), key=lambda x: x[1], reverse=True)[:4]
data['12层上半'] = sorted(battle_characters_up12.items(), key=lambda x: x[1], reverse=True)[:4]
data['12层下半'] = sorted(battle_characters_down12.items(), key=lambda x: x[1], reverse=True)[:4]
return await draw_statistics_img(data)
async def draw_statistics_img(data: Dict[str, Any]):
img = PMImage(image=RESOURCE_BASE_PATH / 'abyss' / 'statistics_bg.png')
box = {
'4big': await load_image(RESOURCE_BASE_PATH / 'abyss' / '4bigbox.png'),
'4small': await load_image(RESOURCE_BASE_PATH / 'abyss' / '4smallbox.png'),
'5big': await load_image(RESOURCE_BASE_PATH / 'abyss' / '5bigbox.png'),
'5small': await load_image(RESOURCE_BASE_PATH / 'abyss' / '5smallbox.png'),
'4bg': await load_image(RESOURCE_BASE_PATH / 'icon' / 'star4_no_line.png', size=(95, 95)),
'5bg': await load_image(RESOURCE_BASE_PATH / 'icon' / 'star5_no_line.png', size=(95, 95))
}
avatar = await get_group_avatar(data['群号'])
await img.paste(avatar, (38, 47))
await img.text(data['群名称'], 162, 63, fm.get('hywh', 48), '#040404')
await img.text(data['群号'], 165, 116, fm.get('hywh', 36), '#040404')
await img.text(f'CREATED BY LITTLEPAIMON AT {datetime.datetime.now().strftime("%m-%d %H:%M")}',
1033, 194, fm.get('bahnschrift_regular.ttf', 30), '#8c4c2e', 'right')
await img.text(str(data['总人数']), (233, 352), 296, fm.get('bahnschrift_regular.ttf', 48), '#040404', 'center')
await img.text(str(data['平均星数']), (492, 586), 296, fm.get('bahnschrift_regular.ttf', 48), '#040404', 'center')
await img.text(str(data['平均战斗次数']), (698, 840), 296, fm.get('bahnschrift_regular.ttf', 48), '#040404', 'center')
# 满星人数
full_num = [data['满星人数'] / data['总人数'], 1 - data['满星人数'] / data['总人数']]
now_used_width = 36
if full_num[0] > 0.03:
await img.draw_rectangle((now_used_width, 402, now_used_width + int(1007 * full_num[0]), 449), '#b6d6f2')
await img.text(str(data['满星人数']), now_used_width + 18, 413, fm.get('bahnschrift_regular.ttf', 30), '#3d6e99')
now_used_width += int(1007 * full_num[0])
if full_num[1] > 0.03:
await img.draw_rectangle((now_used_width, 402, now_used_width + int(1007 * full_num[1]), 449), '#c8b6f2')
await img.text(str(data['总人数'] - data['满星人数']), now_used_width + 18, 413, fm.get('bahnschrift_regular.ttf', 30), '#593d99')
# 最高伤害
await img.paste(box[f'{data["最高伤害"][0]["稀有度"]}big'], (39, 512))
await img.paste(box[f'{data["最高伤害"][1]["稀有度"]}small'], (39, 664))
await img.paste(box[f'{data["最高伤害"][2]["稀有度"]}small'], (296, 664))
await img.paste(await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{data["最高伤害"][0]["图标"]}.png', size=(124, 124)),
(44, 525))
await img.paste(await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{data["最高伤害"][1]["图标"]}.png', size=(82, 82)),
(45, 673))
await img.paste(await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{data["最高伤害"][2]["图标"]}.png', size=(82, 82)),
(300, 673))
await img.paste(await get_user_avatar(data['最高伤害'][0]['qq号']), (112, 588))
await img.paste(await get_user_avatar(data['最高伤害'][1]['qq号'], (42, 42)), (87, 713))
await img.paste(await get_user_avatar(data['最高伤害'][2]['qq号'], (42, 42)), (344, 713))
await img.text('最强一击', 180, 515, fm.get('hywh', 30), '#040404')
await img.text('第二名', 139, 668, fm.get('hywh', 22), '#040404')
await img.text('第三名', 397, 668, fm.get('hywh', 22), '#040404')
await img.text(str(data['最高伤害'][0]['数值']), 180, 544, fm.get('bahnschrift_regular.ttf', 72), '#040404')
await img.text(str(data['最高伤害'][1]['数值']), 137, 690, fm.get('bahnschrift_regular.ttf', 44), '#040404')
await img.text(str(data['最高伤害'][1]['数值']), 395, 690, fm.get('bahnschrift_regular.ttf', 44), '#040404')
await img.text(data['最高伤害'][0]['用户名'][:11], 180, 610, fm.get('hywh', 30), '#040404')
await img.text(data['最高伤害'][1]['用户名'][:6], 137, 726, fm.get('hywh', 22), '#040404')
await img.text(data['最高伤害'][2]['用户名'][:6], 395, 726, fm.get('hywh', 22), '#040404')
# 最高承伤
await img.paste(box[f'{data["最高承受伤害"][0]["稀有度"]}big'], (554, 512))
await img.paste(box[f'{data["最高承受伤害"][1]["稀有度"]}small'], (552, 664))
await img.paste(box[f'{data["最高承受伤害"][2]["稀有度"]}small'], (808, 664))
await img.paste(await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{data["最高承受伤害"][0]["图标"]}.png', size=(124, 124)),
(560, 525))
await img.paste(await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{data["最高承受伤害"][1]["图标"]}.png', size=(82, 82)),
(557, 673))
await img.paste(await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{data["最高承受伤害"][2]["图标"]}.png', size=(82, 82)),
(815, 673))
await img.paste(await get_user_avatar(data['最高承受伤害'][0]['qq号']), (623, 588))
await img.paste(await get_user_avatar(data['最高承受伤害'][1]['qq号'], (42, 42)), (600, 713))
await img.paste(await get_user_avatar(data['最高承受伤害'][2]['qq号'], (42, 42)), (857, 713))
await img.text('最多承伤', 693, 515, fm.get('hywh', 30), '#040404')
await img.text('第二名', 652, 668, fm.get('hywh', 22), '#040404')
await img.text('第三名', 910, 668, fm.get('hywh', 22), '#040404')
await img.text(str(data['最高承受伤害'][0]['数值']), 693, 544, fm.get('bahnschrift_regular.ttf', 72), '#040404')
await img.text(str(data['最高承受伤害'][1]['数值']), 650, 690, fm.get('bahnschrift_regular.ttf', 44), '#040404')
await img.text(str(data['最高承受伤害'][2]['数值']), 908, 690, fm.get('bahnschrift_regular.ttf', 44), '#040404')
await img.text(data['最高承受伤害'][0]['用户名'][:11], 693, 610, fm.get('hywh', 30), '#040404')
await img.text(data['最高承受伤害'][1]['用户名'][:6], 650, 726, fm.get('hywh', 22), '#040404')
await img.text(data['最高承受伤害'][2]['用户名'][:6], 908, 726, fm.get('hywh', 22), '#040404')
tag = await load_image(RESOURCE_BASE_PATH / 'general' / 'tag.png')
# 角色出场率
for i in range(4):
icon, rarity, count = data['11层上半'][i][0].split('-')[0], data['11层上半'][i][0].split('-')[1], data['11层上半'][i][1]
await img.paste(box[f'{rarity}bg'], (182 + i * 101, 867))
await img.paste(await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{icon}.png', size=(95, 95)), (182 + i * 101, 867))
await img.paste(tag, (236 + i * 101, 942))
await img.text(str(count), (236 + i * 101, 277 + i * 101), 943, fm.get('bahnschrift_regular.ttf', 19), 'white', 'center')
icon, rarity, count = data['11层下半'][i][0].split('-')[0], data['11层下半'][i][0].split('-')[1], data['11层下半'][i][1]
await img.paste(box[f'{rarity}bg'], (642 + i * 101, 867))
await img.paste(await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{icon}.png', size=(95, 95)), (642 + i * 101, 867))
await img.paste(tag, (696 + i * 101, 942))
await img.text(str(count), (696 + i * 101, 737 + i * 101), 943, fm.get('bahnschrift_regular.ttf', 19), 'white', 'center')
icon, rarity, count = data['12层上半'][i][0].split('-')[0], data['12层上半'][i][0].split('-')[1], data['12层上半'][i][1]
await img.paste(box[f'{rarity}bg'], (182 + i * 101, 983))
await img.paste(await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{icon}.png', size=(95, 95)), (182 + i * 101, 983))
await img.paste(tag, (236 + i * 101, 1058))
await img.text(str(count), (236 + i * 101, 278 + i * 101), 1059, fm.get('bahnschrift_regular.ttf', 19), 'white', 'center')
icon, rarity, count = data['12层下半'][i][0].split('-')[0], data['12层下半'][i][0].split('-')[1], data['12层下半'][i][1]
await img.paste(box[f'{rarity}bg'], (642 + i * 101, 983))
await img.paste(await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{icon}.png', size=(95, 95)), (642 + i * 101, 983))
await img.paste(tag, (696 + i * 101, 1058))
await img.text(str(count), (696 + i * 101, 737 + i * 101), 1059, fm.get('bahnschrift_regular.ttf', 19), 'white', 'center')
i += 1
return MessageBuild.Image(img, mode='RGB', quality=80)
text = f'本群群友{now.strftime("%m月%d")}深渊统计情况:\n满星人数/总人数: {full_star_num}/{info_num}\n平均星数: {average_star}\n平均战斗次数: {average_battle_num}\n最高伤害角色: {max_damage_user}{max_damage.max_damage.name}({max_damage.max_damage.value})\n' \
f'最高承伤角色: {max_take_damage_user}{max_take_damage.max_take_damage.name}({max_take_damage.max_take_damage.value})\n' \
f'11层出场率最高角色\n 上半:{" ".join(up_sort11)}\n 下半:{" ".join(down_sort11)}\n' \
f'12层出场率最高角色\n 上半:{" ".join(up_sort12)}\n 下半:{" ".join(down_sort12)}\n' \
f'Created by LittlePaimon'
img = PMImage(size=(500, 33 * 15), color=(255, 255, 255, 255))
await img.text_box(text.replace('\n', '^'), (10, 490), (10, 33 * 15 - 10), fm.get('hywh', 25), 'black')
return MessageBuild.Image(img, mode='RGB')

View File

@ -135,6 +135,8 @@ class AsyncPlaywright:
path = Path(path)
try:
page = await cls.goto(url, wait_until=wait_until, **kwargs)
if page is None:
return MessageSegment.text('截图失败,无法访问网页,请稍候再试')
await page.set_viewport_size(viewport_size)
if element:
if isinstance(element, str):