ZZZ-Plugin/model/abyss.js
2025-04-26 01:27:13 +08:00

380 lines
8.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { element } from '../lib/convert.js';
import { getSquareAvatar, getSquareBangboo } from '../lib/download.js';
/**
* @typedef {Object} IChallengeAvatar
* @property {number} id
* @property {number} level
* @property {string} rarity
* @property {number} element_type
*/
/**
* @typedef {Object} IChallengeBangboo
* @property {number} id
* @property {string} rarity
* @property {number} level
*/
/**
* @typedef {Object} IHadalTime
* @property {number} year
* @property {number} month
* @property {number} day
* @property {number} hour
* @property {number} minute
* @property {number} second
*/
/**
* @typedef {Object} IMonsterInfo
* @property {number} id
* @property {string} name
* @property {number} weak_element_type
*/
/**
* @typedef {Object} IBuff
* @property {string} title
* @property {string} text
*/
/**
* @typedef {Object} IChallengeNode
* @property {IChallengeAvatar[]} avatars
* @property {IChallengeBangboo} buddy
* @property {number[]} element_type_list
* @property {IMonsterInfo} monster_info
*/
/**
* @typedef {Object} IFloorChallengeTime
* @property {number} year
* @property {number} month
* @property {number} day
* @property {number} hour
* @property {number} minute
* @property {number} second
*/
/**
* @typedef {Object} IFloorDetail
* @property {number} layer_index
* @property {string} rating
* @property {number} layer_id
* @property {IBuff[]} buffs
* @property {IChallengeNode} node_1
* @property {IChallengeNode} node_2
* @property {number} challenge_time
* @property {string} zone_name
* @property {IFloorChallengeTime} floor_challenge_time
*/
/**
* @typedef {Object} IRating
* @property {number} times
* @property {string} rating
*/
/**
* @typedef {Object} IZZZChallenge
* @property {number} schedule_id
* @property {number} begin_time
* @property {number} end_time
* @property {IRating[]} rating_list
* @property {boolean} has_data
* @property {IFloorDetail[]} all_floor_detail
* @property {number} fast_layer_time
* @property {number} max_layer
* @property {IHadalTime} hadal_begin_time
* @property {IHadalTime} hadal_end_time
*/
/**
* @class ChallengeAvatar.
*/
export class ChallengeAvatar {
/**
* @param {IChallengeAvatar} data
*/
constructor(data) {
this.id = data.id;
this.level = data.level;
this.rarity = data.rarity;
this.element_type = data.element_type;
this.rank = data.rank;
}
async get_assets() {
const result = await getSquareAvatar(this.id);
this.square_icon = result;
}
get element() {
return element.IDToElement(this.element_type);
}
}
/**
* @class ChallengeBangboo.
*/
export class ChallengeBangboo {
/**
* @param {IChallengeBangboo} data
*/
constructor(data) {
this.id = data.id;
this.rarity = data.rarity;
this.level = data.level;
}
async get_assets() {
const result = await getSquareBangboo(this.id);
this.square_icon = result;
}
}
/**
* @class MonsterInfo.
*/
export class MonsterInfo {
/**
* @param {IMonsterInfo} data
*/
constructor(data) {
this.id = data.id;
this.name = data.name;
this.weak_element_type = data.weak_element_type;
}
}
/**
* @class Buff.
*/
export class Buff {
/**
* @param {IBuff} data
*/
constructor(data) {
this.title = data.title;
this.text = data.text;
}
}
/**
* @class ChallengeNode.
*/
export class ChallengeNode {
/**
* @param {IChallengeNode} data
*/
constructor(data) {
/** @type {IChallengeAvatar[]} */
this.avatars = data?.avatars?.map(avatar => new ChallengeAvatar(avatar));
/** @type {IChallengeBangboo} */
this.buddy = data?.buddy && new ChallengeBangboo(data.buddy);
/** @type {number[]} */
this.element_type_list = data.element_type_list;
/** @type {MonsterInfo} */
this.monster_info =
data?.monster_info && new MonsterInfo(data.monster_info);
/** @type {number} */
this.battle_time = data.battle_time;
}
async get_assets() {
if (this.avatars) {
await Promise.all(this.avatars.map(avatar => avatar.get_assets()));
}
if (this.buddy) {
await this.buddy.get_assets();
}
}
get elements() {
return this.element_type_list.map(type => {
return element.IDToElement(type);
});
}
get formattedTime() {
const seconds = this.battle_time % 60;
const minutes = Math.floor(this.battle_time / 60);
return `${minutes ? minutes + '分' : ''}${seconds + '秒'}`;
}
}
/**
* @class FloorChallengeTime.
*/
export class FloorChallengeTime {
/**
* @param {IFloorChallengeTime} data
*/
constructor(data) {
/** @type {number} */
this.year = data.year;
/** @type {number} */
this.month = data.month;
/** @type {number} */
this.day = data.day;
/** @type {number} */
this.hour = data.hour;
/** @type {number} */
this.minute = data.minute;
/** @type {number} */
this.second = data.second;
}
/** @type {string} */
get formattedTime() {
return `${this.year}/${this.month}/${this.day} ${this.hour}:${this.minute}:${this.second}`;
}
}
/**
* @class FloorDetail.
*/
export class FloorDetail {
/**
* @param {IFloorDetail} data
*/
constructor(data) {
/** @type {number} */
this.layer_index = data.layer_index;
/** @type {string} */
this.rating = data.rating;
/** @type {number} */
this.layer_id = data.layer_id;
/** @type {IBuff[]} */
this.buffs = data.buffs.map(buff => new Buff(buff));
/** @type {IChallengeNode} */
this.node_1 = data?.node_1 && new ChallengeNode(data.node_1);
/** @type {IChallengeNode} */
this.node_2 = data?.node_2 && new ChallengeNode(data.node_2);
/** @type {number} */
this.challenge_time = data.challenge_time;
/** @type {string} */
this.zone_name = data.zone_name;
/** @type {IFloorChallengeTime} */
this.floor_challenge_time = new FloorChallengeTime(
data.floor_challenge_time
);
}
async get_assets() {
if (this.node_1) {
await this.node_1.get_assets();
}
if (this.node_2) {
await this.node_2.get_assets();
}
}
/** @type {string} */
get formattedTime() {
return (
this.floor_challenge_time.year +
'年' +
this.floor_challenge_time.month +
'月' +
this.floor_challenge_time.day +
'日 ' +
this.floor_challenge_time.hour.toString().padStart(2, '0') +
':' +
this.floor_challenge_time.minute.toString().padStart(2, '0') +
':' +
this.floor_challenge_time.second.toString().padStart(2, '0')
);
}
}
/**
* @class Rating.
*/
export class Rating {
/**
* @param {IRating} data
*/
constructor(data) {
this.times = data.times;
this.rating = data.rating;
}
}
/**
* @class ZZZChallenge.
*/
export class ZZZChallenge {
/**
* @param {IZZZChallenge} data
*/
constructor(data) {
// 类型标注
/** @type {number} */
this.schedule_id = data.schedule_id;
/** @type {number} */
this._begin_time = data.begin_time;
/** @type {number} */
this._end_time = data.end_time;
/** @type {IRating[]} */
this.rating_list = data.rating_list.map(rating => new Rating(rating));
/** @type {boolean} */
this.has_data = data.has_data;
/** @type {IFloorDetail[]} */
this.all_floor_detail = data.all_floor_detail.map(
floorDetail => new FloorDetail(floorDetail)
);
/** @type {number} */
this.fast_layer_time = data.fast_layer_time;
/** @type {number} */
this.max_layer = data.max_layer;
/** @type {IHadalTime} */
this.hadal_begin_time = data.hadal_begin_time;
/** @type {IHadalTime} */
this.hadal_end_time = data.hadal_end_time;
/** @type {{
* S: number;
* A: number;
* B: number;
* }} */
this.rate_count = {
S: this.rating_list.find(rating => rating.rating === 'S')?.times || 0,
A: this.rating_list.find(rating => rating.rating === 'A')?.times || 0,
B: this.rating_list.find(rating => rating.rating === 'B')?.times || 0,
};
}
async get_assets() {
await Promise.all(this.all_floor_detail.map(floor => floor.get_assets()));
}
get fast_layer_time_str() {
// 将秒数转换为 xx小时xx分钟xx秒 的格式例如234 -> 3分钟54秒
const seconds = this.fast_layer_time % 60;
const minutes = Math.floor(this.fast_layer_time / 60) % 60;
const hours = Math.floor(this.fast_layer_time / 3600);
return `${hours ? hours + '小时' : ''}${minutes ? minutes + '分钟' : ''}${
seconds ? seconds + '秒' : ''
}`;
}
/** @type {string} */
get begin_time() {
return new Date(Number(this._begin_time) * 1000).toLocaleDateString(
'en-US',
{
month: '2-digit',
day: '2-digit',
}
);
}
/** @type {string} */
get end_time() {
return new Date(Number(this._end_time) * 1000).toLocaleDateString('en-US', {
month: '2-digit',
day: '2-digit',
});
}
}