mirror of
https://github.com/PaiGramTeam/PaiGram.git
synced 2024-11-25 09:37:30 +00:00
✨ Support Akasha System
This commit is contained in:
parent
144bd22359
commit
cf478b3b49
138
modules/apihelper/client/components/akasha.py
Normal file
138
modules/apihelper/client/components/akasha.py
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
from types import TracebackType
|
||||||
|
from typing import Optional, Type, List
|
||||||
|
from urllib.parse import unquote
|
||||||
|
|
||||||
|
import httpx
|
||||||
|
|
||||||
|
from modules.apihelper.models.genshin.akasha import (
|
||||||
|
AkashaRank,
|
||||||
|
AkashaLeaderboardCategory,
|
||||||
|
AkashaLeaderboard,
|
||||||
|
AkashaSubStat,
|
||||||
|
AkashaArtifact,
|
||||||
|
)
|
||||||
|
|
||||||
|
BASE_URL = "https://akasha.cv/api"
|
||||||
|
MAIN_API = BASE_URL + "/filters/accounts/"
|
||||||
|
RANK_API = BASE_URL + "/getCalculationsForUser/"
|
||||||
|
DATA_API = BASE_URL + "/user/"
|
||||||
|
REFRESH_API = BASE_URL + "/user/refresh/"
|
||||||
|
LEADERBOARD_API = BASE_URL + "/leaderboards"
|
||||||
|
LEADERBOARD_CATEGORY_API = BASE_URL + "/v2/leaderboards/categories"
|
||||||
|
ARTIFACTS_API = BASE_URL + "/artifacts"
|
||||||
|
|
||||||
|
|
||||||
|
class Akasha:
|
||||||
|
SUB_STAT_MAP = {
|
||||||
|
AkashaSubStat.CRR: "critValue",
|
||||||
|
AkashaSubStat.ATK: "substats.ATK%",
|
||||||
|
AkashaSubStat.HP: "substats.HP%",
|
||||||
|
AkashaSubStat.DEF: "substats.DEF%",
|
||||||
|
AkashaSubStat.ATKF: "substats.Flat ATK",
|
||||||
|
AkashaSubStat.HPF: "substats.Flat HP",
|
||||||
|
AkashaSubStat.DEFF: "substats.Flat DEF",
|
||||||
|
AkashaSubStat.EM: "substats.Elemental Mastery",
|
||||||
|
AkashaSubStat.ER: "substats.Energy Recharge",
|
||||||
|
AkashaSubStat.CR: "substats.Crit RATE",
|
||||||
|
AkashaSubStat.CD: "substats.Crit DMG",
|
||||||
|
}
|
||||||
|
SUB_STAT_NAME_MAP = {
|
||||||
|
"Flat ATK": "攻击力",
|
||||||
|
"Flat HP": "血量",
|
||||||
|
"Flat DEF": "防御力",
|
||||||
|
"ATK%": "百分比攻击力",
|
||||||
|
"HP%": "百分比血量",
|
||||||
|
"DEF%": "百分比防御",
|
||||||
|
"Elemental Mastery": "元素精通",
|
||||||
|
"Energy Recharge": "元素充能效率",
|
||||||
|
"Crit RATE": "暴击率",
|
||||||
|
"Crit DMG": "暴击伤害",
|
||||||
|
"Cryo DMG Bonus": "冰元素伤害加成",
|
||||||
|
"Pyro DMG Bonus": "火元素伤害加成",
|
||||||
|
"Hydro DMG Bonus": "水元素伤害加成",
|
||||||
|
"Electro DMG Bonus": "雷元素伤害加成",
|
||||||
|
"Anemo DMG Bonus": "风元素伤害加成",
|
||||||
|
"Geo DMG Bonus": "岩元素伤害加成",
|
||||||
|
"Dendro DMG Bonus": "草元素伤害加成",
|
||||||
|
"Healing Bonus": "治疗加成",
|
||||||
|
"Physical Bonus": "物理伤害加成",
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.client = httpx.AsyncClient(timeout=60)
|
||||||
|
self.session_id = None
|
||||||
|
|
||||||
|
async def get_session_id(self) -> Optional[str]:
|
||||||
|
if self.session_id is None:
|
||||||
|
resp = await self.client.get(MAIN_API)
|
||||||
|
sid = resp.cookies.get("connect.sid", "")
|
||||||
|
sid = unquote(str(sid))
|
||||||
|
self.session_id = sid.split(".")[0].split(":")[-1]
|
||||||
|
return self.session_id
|
||||||
|
|
||||||
|
async def refresh_user_data(self, uid: int) -> None:
|
||||||
|
session_id = await self.get_session_id()
|
||||||
|
params = {"sessionID": session_id}
|
||||||
|
await self.client.get(DATA_API + str(uid), params=params)
|
||||||
|
await self.client.get(REFRESH_API + str(uid), params=params)
|
||||||
|
|
||||||
|
async def get_rank_data(self, uid: int) -> List[AkashaRank]:
|
||||||
|
await self.refresh_user_data(uid)
|
||||||
|
try:
|
||||||
|
resp = await self.client.get(RANK_API + str(uid))
|
||||||
|
data = resp.json()["data"]
|
||||||
|
except KeyError:
|
||||||
|
return []
|
||||||
|
return [AkashaRank(**i) for i in data]
|
||||||
|
|
||||||
|
async def get_leaderboard_categories(self, character_id: int) -> List[AkashaLeaderboardCategory]:
|
||||||
|
params = {"characterId": character_id}
|
||||||
|
try:
|
||||||
|
resp = await self.client.get(LEADERBOARD_CATEGORY_API, params=params)
|
||||||
|
data = resp.json()["data"]
|
||||||
|
except KeyError:
|
||||||
|
return []
|
||||||
|
return [AkashaLeaderboardCategory(**i) for i in data]
|
||||||
|
|
||||||
|
async def get_leaderboard(self, calculation_id: str, uid: int = None) -> List[AkashaLeaderboard]:
|
||||||
|
params = {
|
||||||
|
"sort": "calculation.result",
|
||||||
|
"p": "",
|
||||||
|
"calculationId": calculation_id,
|
||||||
|
"order": -1,
|
||||||
|
"size": 20,
|
||||||
|
"page": 1,
|
||||||
|
"filter": "",
|
||||||
|
"uids": "",
|
||||||
|
"fromId": "",
|
||||||
|
}
|
||||||
|
if uid:
|
||||||
|
params["uids"] = f"[uid]{uid}"
|
||||||
|
try:
|
||||||
|
resp = await self.client.get(LEADERBOARD_API, params=params)
|
||||||
|
data = resp.json()["data"]
|
||||||
|
except KeyError:
|
||||||
|
return []
|
||||||
|
return [AkashaLeaderboard(**i) for i in data]
|
||||||
|
|
||||||
|
async def get_artifacts_list(self, sort_by: AkashaSubStat = AkashaSubStat.CRR) -> List[AkashaArtifact]:
|
||||||
|
params = {
|
||||||
|
"sort": self.SUB_STAT_MAP[sort_by],
|
||||||
|
"p": "",
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
resp = await self.client.get(ARTIFACTS_API, params=params)
|
||||||
|
data = resp.json()["data"]
|
||||||
|
except KeyError:
|
||||||
|
return []
|
||||||
|
return [AkashaArtifact(**i) for i in data]
|
||||||
|
|
||||||
|
async def __aenter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
async def __aexit__(
|
||||||
|
self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType]
|
||||||
|
):
|
||||||
|
if self.client.is_closed:
|
||||||
|
return
|
||||||
|
await self.client.aclose()
|
212
modules/apihelper/models/genshin/akasha.py
Normal file
212
modules/apihelper/models/genshin/akasha.py
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
from enum import Enum
|
||||||
|
from typing import Dict, List, Any, Optional
|
||||||
|
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaSubStat(str, Enum):
|
||||||
|
CRR = "双暴"
|
||||||
|
ATK = "百分比攻击力"
|
||||||
|
HP = "百分比生命值"
|
||||||
|
DEF = "百分比防御力"
|
||||||
|
ATKF = "固定攻击力"
|
||||||
|
HPF = "固定生命值"
|
||||||
|
DEFF = "固定防御力"
|
||||||
|
EM = "元素精通"
|
||||||
|
ER = "元素充能效率"
|
||||||
|
CR = "暴击率"
|
||||||
|
CD = "暴击伤害"
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaRankCalFit(BaseModel):
|
||||||
|
calculationId: str
|
||||||
|
short: str
|
||||||
|
name: str
|
||||||
|
details: str
|
||||||
|
result: float
|
||||||
|
ranking: str
|
||||||
|
outOf: int
|
||||||
|
priority: int
|
||||||
|
type: str
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaRankCal(BaseModel):
|
||||||
|
fit: AkashaRankCalFit
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaRank(BaseModel):
|
||||||
|
_id: str
|
||||||
|
characterId: int
|
||||||
|
uid = int
|
||||||
|
constellation: int
|
||||||
|
icon: str
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaLeaderboardCategoryWeapon(BaseModel):
|
||||||
|
name: str
|
||||||
|
icon: str
|
||||||
|
substat: str
|
||||||
|
type: str
|
||||||
|
rarity: str
|
||||||
|
refinement: int
|
||||||
|
calculationId: str
|
||||||
|
details: str
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaLeaderboardCategory(BaseModel):
|
||||||
|
_id: str
|
||||||
|
name: str
|
||||||
|
addDate: datetime
|
||||||
|
c6: str
|
||||||
|
characterId: int
|
||||||
|
characterName: str
|
||||||
|
count: int
|
||||||
|
details: str
|
||||||
|
element: str
|
||||||
|
new: int
|
||||||
|
rarity: int
|
||||||
|
short: str
|
||||||
|
weapons: List[AkashaLeaderboardCategoryWeapon]
|
||||||
|
weaponsCount: int
|
||||||
|
characterIcon: str
|
||||||
|
index: int
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaLeaderboardCalculation(BaseModel):
|
||||||
|
id: str
|
||||||
|
result: float
|
||||||
|
|
||||||
|
@property
|
||||||
|
def int(self) -> int:
|
||||||
|
return int(self.result)
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaLeaderboardArtifactSet(BaseModel):
|
||||||
|
icon: str
|
||||||
|
count: int
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaLeaderboardOwner(BaseModel):
|
||||||
|
nickname: str
|
||||||
|
adventureRank: float
|
||||||
|
profilePicture: Any
|
||||||
|
nameCard: str
|
||||||
|
patreon: Dict[str, Any]
|
||||||
|
region: str
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaLeaderboardStatsValue(BaseModel):
|
||||||
|
value: float
|
||||||
|
|
||||||
|
@property
|
||||||
|
def int(self) -> int:
|
||||||
|
return int(self.value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def percent(self) -> str:
|
||||||
|
return f"{self.value * 100:.1f}"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def web_value(self) -> str:
|
||||||
|
return f"{self.value:.2f}"
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaLeaderboardStats(BaseModel):
|
||||||
|
maxHp: AkashaLeaderboardStatsValue
|
||||||
|
atk: AkashaLeaderboardStatsValue
|
||||||
|
def_: AkashaLeaderboardStatsValue = Field(..., alias="def")
|
||||||
|
elementalMastery: AkashaLeaderboardStatsValue
|
||||||
|
energyRecharge: AkashaLeaderboardStatsValue
|
||||||
|
healingBonus: AkashaLeaderboardStatsValue
|
||||||
|
critRate: AkashaLeaderboardStatsValue
|
||||||
|
critDamage: AkashaLeaderboardStatsValue
|
||||||
|
electroDamageBonus: Optional[AkashaLeaderboardStatsValue]
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaLeaderboardWeaponInfo(BaseModel):
|
||||||
|
level: int
|
||||||
|
promoteLevel: int
|
||||||
|
refinementLevel: AkashaLeaderboardStatsValue
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaLeaderboardWeapon(BaseModel):
|
||||||
|
weaponInfo: AkashaLeaderboardWeaponInfo
|
||||||
|
flat: Dict[str, Any]
|
||||||
|
name: str
|
||||||
|
icon: str
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaLeaderboardCharacterMetadata(BaseModel):
|
||||||
|
element: str
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaLeaderboard(BaseModel):
|
||||||
|
_id: str
|
||||||
|
calculation: AkashaLeaderboardCalculation
|
||||||
|
characterId: int
|
||||||
|
type: str
|
||||||
|
uid: str
|
||||||
|
artifactObjects: Dict[str, Any]
|
||||||
|
artifactSets: Dict[str, AkashaLeaderboardArtifactSet]
|
||||||
|
calculations: Dict[str, Any]
|
||||||
|
constellation: int
|
||||||
|
costumeId: str
|
||||||
|
critValue: float
|
||||||
|
md5: str
|
||||||
|
name: str
|
||||||
|
owner: AkashaLeaderboardOwner
|
||||||
|
propMap: Dict[str, Any]
|
||||||
|
proudSkillExtraLevelMap: Dict[str, Any]
|
||||||
|
stats: AkashaLeaderboardStats
|
||||||
|
talentsLevelMap: Dict[str, Any]
|
||||||
|
weapon: AkashaLeaderboardWeapon
|
||||||
|
icon: str
|
||||||
|
index: str
|
||||||
|
nameCardLink: str
|
||||||
|
profilePictureLink: str
|
||||||
|
characterMetadata: AkashaLeaderboardCharacterMetadata
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaArtifactType(str, Enum):
|
||||||
|
BRACER = "EQUIP_BRACER"
|
||||||
|
"""生之花"""
|
||||||
|
NECKLACE = "EQUIP_NECKLACE"
|
||||||
|
"""死之羽"""
|
||||||
|
SHOES = "EQUIP_SHOES"
|
||||||
|
"""时之沙"""
|
||||||
|
RING = "EQUIP_RING"
|
||||||
|
"""空之杯"""
|
||||||
|
DRESS = "EQUIP_DRESS"
|
||||||
|
"""理之冠"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def real_name(self):
|
||||||
|
name_map = {
|
||||||
|
"EQUIP_BRACER": "生之花",
|
||||||
|
"EQUIP_NECKLACE": "死之羽",
|
||||||
|
"EQUIP_SHOES": "时之沙",
|
||||||
|
"EQUIP_RING": "空之杯",
|
||||||
|
"EQUIP_DRESS": "理之冠",
|
||||||
|
}
|
||||||
|
return name_map[self.value]
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaArtifact(BaseModel):
|
||||||
|
_id: str
|
||||||
|
uid: int
|
||||||
|
critValue: float
|
||||||
|
equipType: AkashaArtifactType
|
||||||
|
icon: str
|
||||||
|
level: int
|
||||||
|
mainStatKey: str
|
||||||
|
mainStatValue: float
|
||||||
|
name: str
|
||||||
|
owner: AkashaLeaderboardOwner
|
||||||
|
setName: str
|
||||||
|
stars: int
|
||||||
|
substats: Dict[str, float]
|
||||||
|
substatsIdList: List[int]
|
||||||
|
index: int
|
||||||
|
nameCardLink: str
|
||||||
|
profilePictureLink: str
|
112
plugins/genshin/akasha.py
Normal file
112
plugins/genshin/akasha.py
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
from typing import TYPE_CHECKING, Optional
|
||||||
|
|
||||||
|
from telegram.constants import ChatAction
|
||||||
|
from telegram.ext import filters
|
||||||
|
|
||||||
|
from core.dependence.assets import AssetsService
|
||||||
|
from core.plugin import Plugin, handler
|
||||||
|
from core.services.template.models import FileType
|
||||||
|
from core.services.template.services import TemplateService
|
||||||
|
from gram_core.services.players import PlayersService
|
||||||
|
from metadata.genshin import AVATAR_DATA
|
||||||
|
from metadata.shortname import roleToName, roleToId
|
||||||
|
from modules.apihelper.client.components.akasha import Akasha
|
||||||
|
from utils.log import logger
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from telegram import Update
|
||||||
|
from telegram.ext import ContextTypes
|
||||||
|
|
||||||
|
|
||||||
|
class AkashaPlugin(Plugin):
|
||||||
|
"""Akasha 数据排行"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
assets_service: AssetsService = None,
|
||||||
|
template_service: TemplateService = None,
|
||||||
|
player_service: PlayersService = None,
|
||||||
|
) -> None:
|
||||||
|
self.assets_service = assets_service
|
||||||
|
self.template_service = template_service
|
||||||
|
self.player_service = player_service
|
||||||
|
|
||||||
|
async def get_user_uid(self, user_id: int) -> Optional[int]:
|
||||||
|
player = await self.player_service.get(user_id)
|
||||||
|
if player is None:
|
||||||
|
return None
|
||||||
|
return player.player_id
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def get_leaderboard_data(character_id: int, uid: int = None):
|
||||||
|
akasha = Akasha()
|
||||||
|
categories = await akasha.get_leaderboard_categories(character_id)
|
||||||
|
if len(categories) == 0 or len(categories[0].weapons) == 0:
|
||||||
|
raise NotImplementedError
|
||||||
|
calculation_id = categories[0].weapons[0].calculationId
|
||||||
|
count = categories[0].count
|
||||||
|
data = await akasha.get_leaderboard(calculation_id)
|
||||||
|
if len(data) == 0:
|
||||||
|
raise NotImplementedError
|
||||||
|
user_data = []
|
||||||
|
if uid:
|
||||||
|
user_data = await akasha.get_leaderboard(calculation_id, uid)
|
||||||
|
if len(user_data) == 0:
|
||||||
|
data = [data]
|
||||||
|
else:
|
||||||
|
data = [user_data, data]
|
||||||
|
return data, count
|
||||||
|
|
||||||
|
async def get_avatar_board_render_data(self, character: str, uid: int):
|
||||||
|
character_id = roleToId(character)
|
||||||
|
name_card = (await self.assets_service.namecard(character_id).navbar()).as_uri()
|
||||||
|
avatar = (await self.assets_service.avatar(character_id).icon()).as_uri()
|
||||||
|
rarity = 5
|
||||||
|
try:
|
||||||
|
rarity = {k: v["rank"] for k, v in AVATAR_DATA.items()}[str(character_id)]
|
||||||
|
except KeyError:
|
||||||
|
logger.warning("未找到角色 %s 的星级", character_id)
|
||||||
|
akasha_data, count = await self.get_leaderboard_data(character_id, uid)
|
||||||
|
return {
|
||||||
|
"character": character, # 角色名
|
||||||
|
"avatar": avatar, # 角色头像
|
||||||
|
"namecard": name_card, # 角色名片
|
||||||
|
"rarity": rarity, # 角色稀有度
|
||||||
|
"count": count,
|
||||||
|
"all_data": akasha_data,
|
||||||
|
}
|
||||||
|
|
||||||
|
@handler.command("avatar_board", block=False)
|
||||||
|
@handler.message(filters.Regex(r"^角色排名(.*)$"), block=False)
|
||||||
|
async def avatar_board(self, update: "Update", context: "ContextTypes.DEFAULT_TYPE"):
|
||||||
|
user = update.effective_user
|
||||||
|
message = update.effective_message
|
||||||
|
args = self.get_args(context)
|
||||||
|
if len(args) == 0:
|
||||||
|
reply_message = await message.reply_text("请指定要查询的角色")
|
||||||
|
if filters.ChatType.GROUPS.filter(reply_message):
|
||||||
|
self.add_delete_message_job(message)
|
||||||
|
self.add_delete_message_job(reply_message)
|
||||||
|
return
|
||||||
|
avatar_name = roleToName(args[0])
|
||||||
|
uid = await self.get_user_uid(user.id)
|
||||||
|
try:
|
||||||
|
render_data = await self.get_avatar_board_render_data(avatar_name, uid)
|
||||||
|
except NotImplementedError:
|
||||||
|
reply_message = await message.reply_text("暂不支持该角色")
|
||||||
|
if filters.ChatType.GROUPS.filter(reply_message):
|
||||||
|
self.add_delete_message_job(message)
|
||||||
|
self.add_delete_message_job(reply_message)
|
||||||
|
return
|
||||||
|
await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
|
||||||
|
|
||||||
|
image = await self.template_service.render(
|
||||||
|
"genshin/akasha/char_rank.jinja2",
|
||||||
|
render_data,
|
||||||
|
viewport={"width": 1040, "height": 500},
|
||||||
|
full_page=True,
|
||||||
|
query_selector=".container",
|
||||||
|
file_type=FileType.PHOTO,
|
||||||
|
ttl=24 * 60 * 60,
|
||||||
|
)
|
||||||
|
await image.reply_photo(message)
|
72
resources/genshin/akasha/char_rank.jinja2
Normal file
72
resources/genshin/akasha/char_rank.jinja2
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Avatar List</title>
|
||||||
|
<link type="text/css" href="./style.css" rel="stylesheet"/>
|
||||||
|
<link type="text/css" href="../avatar_list/style.css" rel="stylesheet"/>
|
||||||
|
<link type="text/css" href="../../styles/public.css" rel="stylesheet"/>
|
||||||
|
<style>
|
||||||
|
.avatar > div::after {
|
||||||
|
background-position: center center;
|
||||||
|
background-size: cover;
|
||||||
|
background-image: url("../../background/rarity/half/{{ rarity }}.png");
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="head" style="background-image: url('{{ namecard }}')">
|
||||||
|
<div class="avatar">
|
||||||
|
<div><img src="{{ avatar }}" alt="avatar"></div>
|
||||||
|
</div>
|
||||||
|
<div class="player">
|
||||||
|
<div>
|
||||||
|
<div class="nickname">{{ character }}</div>
|
||||||
|
<div class="uid">角色排行 共 {{ count }} 条数据</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="logo"></div>
|
||||||
|
</div>
|
||||||
|
{% for akasha_data in all_data %}
|
||||||
|
<div class="content">
|
||||||
|
<div class="row">
|
||||||
|
<div>#</div>
|
||||||
|
<div style="flex: 3">UID</div>
|
||||||
|
<div style="flex: 3">昵称</div>
|
||||||
|
<div style="flex: 3">暴击 : 暴伤</div>
|
||||||
|
<div style="flex: 2">生命</div>
|
||||||
|
<div style="flex: 2">攻击</div>
|
||||||
|
<div style="flex: 2">防御</div>
|
||||||
|
<div style="flex: 2">精通</div>
|
||||||
|
<div style="flex: 2">充能</div>
|
||||||
|
<div style="flex: 2">HYPER</div>
|
||||||
|
</div>
|
||||||
|
{% for data in akasha_data %}
|
||||||
|
<div
|
||||||
|
{% if loop.index is even %}
|
||||||
|
class="row second-row"
|
||||||
|
{% else %}
|
||||||
|
class="row"
|
||||||
|
{% endif %}
|
||||||
|
>
|
||||||
|
<div>{{ data.index }}</div>
|
||||||
|
<div style="flex: 3">{{ data.uid }}</div>
|
||||||
|
<div style="flex: 3" class="username">{{ data.owner.nickname }}</div>
|
||||||
|
<div style="flex: 3">{{ data.stats.critRate.percent }} : {{ data.stats.critDamage.percent }}</div>
|
||||||
|
<div style="flex: 2">{{ data.stats.maxHp.int }}</div>
|
||||||
|
<div style="flex: 2">{{ data.stats.atk.int }}</div>
|
||||||
|
<div style="flex: 2">{{ data.stats.def_.int }}</div>
|
||||||
|
<div style="flex: 2">{{ data.stats.elementalMastery.int }}</div>
|
||||||
|
<div style="flex: 2">{{ data.stats.energyRecharge.percent }}%</div>
|
||||||
|
<div style="flex: 2; background-color: rgb(229 171 229/70%)">{{ data.calculation.int }}</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% if loop.index == 1 %}
|
||||||
|
<div style="height: 50px"></div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
128
resources/genshin/akasha/char_rank_example.html
Normal file
128
resources/genshin/akasha/char_rank_example.html
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Avatar List</title>
|
||||||
|
<link type="text/css" href="./style.css" rel="stylesheet"/>
|
||||||
|
<link type="text/css" href="../avatar_list/style.css" rel="stylesheet"/>
|
||||||
|
<link type="text/css" href="../../styles/public.css" rel="stylesheet"/>
|
||||||
|
<style>
|
||||||
|
.avatar > div::after {
|
||||||
|
background-position: center center;
|
||||||
|
background-size: cover;
|
||||||
|
background-image: url("../../background/rarity/half/5.png");
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="head" style="background-image: url('../../assets/namecard/210081/navbar.png')">
|
||||||
|
<div class="avatar">
|
||||||
|
<div><img src="../../assets/avatar/10000002/icon.png" alt="avatar"></div>
|
||||||
|
</div>
|
||||||
|
<div class="player">
|
||||||
|
<div>
|
||||||
|
<div class="nickname">神里绫华</div>
|
||||||
|
<div class="uid">角色排行 共 199999 条数据</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="logo"></div>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="row">
|
||||||
|
<div>#</div>
|
||||||
|
<div style="flex: 3">UID</div>
|
||||||
|
<div style="flex: 3">昵称</div>
|
||||||
|
<div style="flex: 3">暴击 : 暴伤</div>
|
||||||
|
<div style="flex: 2">生命值</div>
|
||||||
|
<div style="flex: 2">攻击力</div>
|
||||||
|
<div style="flex: 2">防御力</div>
|
||||||
|
<div style="flex: 2">精通</div>
|
||||||
|
<div style="flex: 2">充能</div>
|
||||||
|
<div style="flex: 2">HYPER</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div>1</div>
|
||||||
|
|
||||||
|
<div style="flex: 3">2222222</div>
|
||||||
|
<div style="flex: 3" class="username">
|
||||||
|
得得得得得得得得得
|
||||||
|
</div>
|
||||||
|
<div style="flex: 3">7.7 : 50.0</div>
|
||||||
|
<div style="flex: 2">20000</div>
|
||||||
|
<div style="flex: 2">2000</div>
|
||||||
|
<div style="flex: 2">2000</div>
|
||||||
|
<div style="flex: 2">1000</div>
|
||||||
|
<div style="flex: 2">300.0%</div>
|
||||||
|
<div style="flex: 2; background-color: rgb(229 171 229/70%)">451399</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="height: 50px"></div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="row">
|
||||||
|
<div>#</div>
|
||||||
|
<div style="flex: 3">UID</div>
|
||||||
|
<div style="flex: 3">昵称</div>
|
||||||
|
<div style="flex: 3">暴击 : 暴伤</div>
|
||||||
|
<div style="flex: 2">生命值</div>
|
||||||
|
<div style="flex: 2">攻击力</div>
|
||||||
|
<div style="flex: 2">防御力</div>
|
||||||
|
<div style="flex: 2">精通</div>
|
||||||
|
<div style="flex: 2">充能</div>
|
||||||
|
<div style="flex: 2">HYPER</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div>1</div>
|
||||||
|
|
||||||
|
<div style="flex: 3">2222222</div>
|
||||||
|
<div style="flex: 3" class="username">
|
||||||
|
得得得得得得得得得
|
||||||
|
</div>
|
||||||
|
<div style="flex: 3">7.7 : 50.0</div>
|
||||||
|
<div style="flex: 2">20000</div>
|
||||||
|
<div style="flex: 2">2000</div>
|
||||||
|
<div style="flex: 2">2000</div>
|
||||||
|
<div style="flex: 2">1000</div>
|
||||||
|
<div style="flex: 2">300.0%</div>
|
||||||
|
<div style="flex: 2; background-color: rgb(229 171 229/70%)">451399</div>
|
||||||
|
</div>
|
||||||
|
<div class="row second-row">
|
||||||
|
<div>2</div>
|
||||||
|
|
||||||
|
<div style="flex: 3">
|
||||||
|
<div>11111111</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="flex: 3" class="username">
|
||||||
|
啊啊啊啊啊啊啊啊啊啊啊啊
|
||||||
|
</div>
|
||||||
|
<div style="flex: 3">7.7 : 50.0</div>
|
||||||
|
<div style="flex: 2">20000</div>
|
||||||
|
<div style="flex: 2">2000</div>
|
||||||
|
<div style="flex: 2">2000</div>
|
||||||
|
<div style="flex: 2">1000</div>
|
||||||
|
<div style="flex: 2">300.0%</div>
|
||||||
|
<div style="flex: 2">451398</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div>3</div>
|
||||||
|
|
||||||
|
<div style="flex: 3">
|
||||||
|
<div>3333333</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="flex: 3" class="username">
|
||||||
|
姑姑姑姑姑姑过过过过
|
||||||
|
</div>
|
||||||
|
<div style="flex: 3">7.7 : 50.0</div>
|
||||||
|
<div style="flex: 2">20000</div>
|
||||||
|
<div style="flex: 2">2000</div>
|
||||||
|
<div style="flex: 2">2000</div>
|
||||||
|
<div style="flex: 2">1000</div>
|
||||||
|
<div style="flex: 2">300.0%</div>
|
||||||
|
<div style="flex: 2">451399</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
5
resources/genshin/akasha/style.css
Normal file
5
resources/genshin/akasha/style.css
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.username {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user