feat: panel

This commit is contained in:
bietiaop 2024-07-13 17:52:31 +08:00
parent 35c8c95b80
commit 27171c5727
77 changed files with 2126 additions and 312 deletions

View file

@ -96,10 +96,11 @@ export function getPanelList(uid) {
* @returns {ZZZAvatarInfo | null}
*/
export function getPanel(uid, name) {
logger.debug('获取面板数据', uid, name);
const data = getPanelData(uid).map(item => new ZZZAvatarInfo(item));
const _data = getPanelData(uid);
const data = _data.map(item => new ZZZAvatarInfo(item));
const id = char.atlasToID(name);
logger.debug('获取角色ID', id);
if (!id) return null;
return data.find(item => item.id === id) || null;
const result = data.find(item => item.id === id);
if (!result) return null;
return result;
}

View file

@ -3,3 +3,9 @@ export * as element from './convert/element.js';
export * as char from './convert/char.js';
export * as weapon from './convert/weapon.js';
export * as equip from './convert/equip.js';
export * as rank from './convert/rank.js';
export * as property from './convert/property.js';

View file

@ -27,7 +27,7 @@ export const IDToCharName = (id, full = true, en = false) => {
export const IDToCharSprite = id => {
const data = PartnerId2SpriteId?.[id];
if (!data) return null;
return data?.['sprite'];
return data?.['sprite_id'];
};
/**

19
lib/convert/equip.js Normal file
View file

@ -0,0 +1,19 @@
import { getMapData } from '../../utils/file.js';
const equipData = getMapData('EquipId2Data');
/**
* 获取驱动盘装备的图片
* @param {string | number} equipId
* @returns {string | null}
*/
export function equipIdToSprite(equipId) {
equipId = equipId.toString();
if (equipId.length === 5) {
const suitId = equipId.slice(0, 3) + '00';
if (equipData.hasOwnProperty(suitId)) {
return equipData[suitId]['sprite_file'].replace('3D', '');
}
}
return null;
}

41
lib/convert/property.js Normal file
View file

@ -0,0 +1,41 @@
const prop_id = {
111: 'hpmax',
121: 'attack',
131: 'def',
122: 'breakstun',
201: 'crit',
211: 'critdam',
314: 'elementabnormalpower',
312: 'elementmystery',
231: 'penratio',
232: 'penvalue',
305: 'sprecover',
310: 'spgetratio',
115: 'spmax',
315: 'physdmg',
316: 'fire',
317: 'ice',
318: 'thunder',
319: 'dungeonbuffether',
};
const pro_id = {
1: 'attack',
2: 'stun',
3: 'anomaly',
4: 'support',
5: 'defense',
};
/**
* 获取属性css类名
* @param {string} _id 属性id
* @returns {string | null}
*/
export function idToClassName(_id) {
let propId = _id.toString();
propId = propId.slice(0, 3);
const propIcon = prop_id[propId];
if (!propIcon) return null;
return propIcon;
}

14
lib/convert/rank.js Normal file
View file

@ -0,0 +1,14 @@
const RANK_MAP = {
4: 'S',
3: 'A',
2: 'B',
};
/**
* 获取星级对应的字母
* @param {string | number} id
* @returns {string}
*/
export function getRankChar(id) {
return RANK_MAP[id] || '';
}

View file

@ -2,7 +2,7 @@ import path from 'path';
import fs from 'fs';
import { ZZZ_SQUARE_AVATAR, ZZZ_SQUARE_BANGBOO } from './mysapi/api.js';
import { imageResourcesPath } from './path.js';
import { weapon } from './convert.js';
import { char, equip, weapon } from './convert.js';
import { getResourceRemotePath } from './assets.js';
const ZZZ_SQUARE_AVATAR_PATH = path.join(imageResourcesPath, 'square_avatar');
@ -11,9 +11,18 @@ const ZZZ_SQUARE_BANGBOO_PATH = path.join(
'bangboo_square_avatar'
);
const ZZZ_WEAPON_PATH = path.join(imageResourcesPath, 'weapon');
const ZZZ_GUIDES_PATH = path.join(imageResourcesPath, 'guides');
const ZZZ_ROLE_PATH = path.join(imageResourcesPath, 'role');
const ZZZ_ROLE_CIRCLE_PATH = path.join(imageResourcesPath, 'role_circle');
const ZZZ_SUIT_3D_PATH = path.join(imageResourcesPath, 'suit_3d');
const ZZZ_SUIT_PATH = path.join(imageResourcesPath, 'suit');
// const ZZZ_GUIDES_PATH = path.join(imageResourcesPath, 'guides');
// 将下面的下载封装起来支持错误重试5次
/**
* 下载文件
* @param {string} url 下载地址
* @param {string} savePath 保存路径
* @returns
*/
const downloadFile = async (url, savePath) => {
const _download = async (url, savePath, retry = 0) => {
if (retry > 5) {
@ -36,7 +45,7 @@ const downloadFile = async (url, savePath) => {
};
/**
*
* 获取角色头像方形
* @param {string | number} charID
* @returns Promise<string>
*/
@ -51,7 +60,7 @@ export const getSquareAvatar = async charID => {
};
/**
*
* 获取邦布头像方形
* @param {string | number} bangbooId
* @returns Promise<string>
*/
@ -66,7 +75,7 @@ export const getSquareBangboo = async bangbooId => {
};
/**
* Get weapon image path
* 获取武器图片
* @param {string} id
* @returns Promise<string>
*/
@ -80,6 +89,72 @@ export const getWeaponImage = async id => {
const url = await getResourceRemotePath('weapon', filename);
const savePath = weaponPath;
const download = await downloadFile(url, savePath);
logger.mark('getWeaponImage', download);
logger.debug('getWeaponImage', download);
return download;
};
/**
* 获取角色图片
* @param {string | number} id
* @returns Promise<string>
*/
export const getRoleImage = async id => {
const sprite = char.IDToCharSprite(id);
if (sprite === null) return null;
const filename = `IconRole${sprite}.png`;
const rolePath = path.join(ZZZ_ROLE_PATH, filename);
if (fs.existsSync(rolePath)) return rolePath;
const url = await getResourceRemotePath('role', filename);
const savePath = rolePath;
const download = await downloadFile(url, savePath);
return download;
};
/**
* 获取角色圆形图片
* @param {string | number} id
* @returns Promise<string>
*/
export const getRoleCircleImage = async id => {
const sprite = char.IDToCharSprite(id);
if (sprite === null) return null;
const filename = `IconRoleCircle${sprite}.png`;
const roleCirclePath = path.join(ZZZ_ROLE_CIRCLE_PATH, filename);
if (fs.existsSync(roleCirclePath)) return roleCirclePath;
const url = await getResourceRemotePath('role_circle', filename);
const savePath = roleCirclePath;
const download = await downloadFile(url, savePath);
return download;
};
/**
* 获取套装图片
* @param {string | number} suitId
* @returns Promise<string>
*/
export const getSuitImage = async suitId => {
const suitName = equip.equipIdToSprite(suitId);
const filename = `${suitName}.png`;
const suitPath = path.join(ZZZ_SUIT_PATH, filename);
if (fs.existsSync(suitPath)) return suitPath;
const url = await getResourceRemotePath('suit', filename);
const savePath = suitPath;
const download = await downloadFile(url, savePath);
return download;
};
/**
* 获取3D套装图片
* @param {string | number} suitId
* @returns Promise<string>
*/
export const getSuit3DImage = async suitId => {
const suitName = equip.equipIdToSprite(suitId);
const filename = `${suitName}_3d.png`;
const suitPath = path.join(ZZZ_SUIT_3D_PATH, filename);
if (fs.existsSync(suitPath)) return suitPath;
const url = await getResourceRemotePath('suit_3d', filename);
const savePath = suitPath;
const download = await downloadFile(url, savePath);
return download;
};

View file

@ -1,5 +1,6 @@
import { SingleGachaLog, ZZZGachaLogResp } from '../model/gacha.js';
import { sleep } from '../utils/time.js';
import { rank } from './convert.js';
import { getGachaLog, saveGachaLog } from './db.js';
import { ZZZ_GET_GACHA_LOG_API } from './mysapi/api.js';
@ -96,7 +97,12 @@ export async function getZZZGachaLogByAuthkey(
* @param {string} authKey
* @param {string} uid
* @returns {Promise<{
* [x: string]: SingleGachaLog[];
* data: {
* [x: string]: SingleGachaLog[];
* },
* count: {
* [x: string]: number;
* }
* }>}
*/
export async function updateGachaLog(authKey, uid) {
@ -104,26 +110,13 @@ export async function updateGachaLog(authKey, uid) {
if (!previousLog) {
previousLog = {};
}
let newCount = {};
for (const name in gacha_type_meta_data) {
if (!previousLog[name]) {
previousLog[name] = [];
}
previousLog[name] = previousLog[name].map(
i =>
new SingleGachaLog(
i.uid,
i.gacha_id,
i.gacha_type,
i.item_id,
i.count,
i.time,
i.name,
i.lang,
i.item_type,
i.rank_type,
i.id
)
);
newCount[name] = 0;
previousLog[name] = previousLog[name].map(i => new SingleGachaLog(i));
const lastSaved = previousLog[name]?.[0];
let page = 1;
let endId = '0';
@ -145,6 +138,7 @@ export async function updateGachaLog(authKey, uid) {
break queryLabel;
}
newData.push(item);
newCount[name]++;
}
endId = log.list[log.list.length - 1]?.id || endId;
page++;
@ -154,14 +148,12 @@ export async function updateGachaLog(authKey, uid) {
previousLog[name] = [...newData, ...previousLog[name]];
}
saveGachaLog(uid, previousLog);
return previousLog;
return {
data: previousLog,
count: newCount,
};
}
const RANK_MAP = {
4: 'S',
3: 'A',
2: 'B',
};
const HOMO_TAG = ['非到极致', '运气不好', '平稳保底', '小欧一把', '欧狗在此'];
const EMOJI = [
[4, 8, 13],
@ -186,10 +178,10 @@ const NORMAL_LIST = [
];
const FLOORS_MAP = {
'邦布频段': [50, 70],
'音擎频段': [50, 70],
'独家频段': [60, 80],
'常驻频段': [60, 80],
邦布频段: [50, 70],
音擎频段: [50, 70],
独家频段: [60, 80],
常驻频段: [60, 80],
};
function getLevelFromList(ast, lst) {
@ -214,22 +206,7 @@ export async function anaylizeGachaLog(uid) {
}
const result = [];
for (const name in savedData) {
const data = savedData[name].map(
item =>
new SingleGachaLog(
item.uid,
item.gacha_id,
item.gacha_type,
item.item_id,
item.count,
item.time,
item.name,
item.lang,
item.item_type,
item.rank_type,
item.id
)
);
const data = savedData[name].map(item => new SingleGachaLog(item));
const earliest = data[data.length - 1];
const latest = data[0];
const list = [];
@ -256,7 +233,7 @@ export async function anaylizeGachaLog(uid) {
}
list.push({
...item,
rank_type_label: RANK_MAP[item.rank_type],
rank_type_label: rank.getRankChar(item.rank_type),
isUp: isUp,
totalCount: '-',
color: 'white',

View file

@ -47,6 +47,7 @@ function render(e, renderPath, renderData = {}, cfg = {}) {
resourcesPath: resPath,
currentPath: renderPathFull,
playerInfo: path.join(layoutPathFull, 'playerinfo.html'),
specialTitle: path.join(layoutPathFull, 'specialtitle.html'),
copyright: `Created By ${version.name}<span class="version">${version.yunzai}</span> & ${pluginName}<span class="version">${version.version}</span>`,
createdby: `Created By <span class="highlight">${pluginName}</span> & Powered By <span class="highlight">ZZZure</span>`,
},