warframe-worldstate-parser
Version:
An Open parser for Warframe's Worldstate in Javascript
184 lines (160 loc) • 5.48 kB
JavaScript
import { parseDate, timeDeltaToString, toNow, node, languageString, faction } from 'warframe-worldstate-data/utilities';
import mdConfig from '../supporting/MarkdownSettings.js';
import Reward from './Reward.js';
import WorldstateObject from './WorldstateObject.js';
/**
* An invasion participant
* @typedef {object} InvasionParticipant
* @property {string} reward Reward for supporting this participant in the invasion
* @property {string} faction Faction of this participant (localized)
* @property {string} factionKey Faction of this participant (always English)
*/
/**
* Represents an invasion
*/
export default class Invasion extends WorldstateObject {
/**
* @param {object} data The invasion data
* @param {Dependency} deps The dependencies object
* @param {string} deps.locale Locale to use for translations
*/
constructor(data, { locale = 'en' } = { locale: 'en' }) {
super(data);
const opts = {
locale,
};
/**
* The node where the invasion is taking place
* @type {string}
*/
this.node = node(data.Node, locale);
/**
* The node key where the invasion is taking place
* @type {string}
*/
this.nodeKey = node(data.Node);
/**
* The invasion's description
* @type {string}
*/
this.desc = languageString(data.LocTag, locale);
/**
* The attacking faction
* @type {string}
*/
this.attackingFaction = faction(data.DefenderMissionInfo.faction, locale);
/**
* Invasion attacker
* @type {InvasionParticipant}
*/
this.attacker = {
reward: Object.keys(data?.AttackerReward || {})?.length ? new Reward(data.AttackerReward, opts) : undefined,
faction: faction(data.DefenderMissionInfo.faction, locale),
factionKey: faction(data.DefenderMissionInfo.faction, 'en'),
};
/**
* Invasion defender
* @type {InvasionParticipant}
*/
this.defender = {
reward: Object.keys(data?.DefenderReward || {})?.length ? new Reward(data.DefenderReward, opts) : undefined,
faction: faction(data.AttackerMissionInfo.faction, locale),
factionKey: faction(data.AttackerMissionInfo.faction, 'en'),
};
/**
* Whether this invasion is against the infestation
* @type {boolean}
*/
this.vsInfestation = /infest/i.test(data.DefenderMissionInfo.faction);
/**
* The time at which the invasion starts
* @type {Date}
*/
this.activation = parseDate(data.Activation);
/**
* The signed count of completed runs. Supporting the attackers makes the count go up,
* supporting the defenders makes it go down
* @type {number}
*/
this.count = data.Count;
/**
* The number of runs that one side needs to win
* @type {number}
*/
this.requiredRuns = data.Goal;
/**
* The invasion's completion percentage. Defenders win if it gets to 0
* Grineer vs. Corpus invasions start at 50, Infested invasions start at 100
* @type {number}
*/
this.completion = (1 + data.Count / data.Goal) * (this.vsInfestation ? 100 : 50);
/**
* Whether the invasion has finished
* @type {boolean}
*/
this.completed = data.Completed;
/**
* ETA string (at time of object creation)
* @type {string}
*/
this.eta = this.getETAString();
/**
* An array containing the types of all of the invasions's rewards
* @type {Array.<string>}
*/
this.rewardTypes = this.getRewardTypes();
}
/**
* Whether or not the attackers are winning.
* This is always false when the infestation is attacking
* @returns {boolean} whether the attacker is winning
*/
isAttackerWinning() {
return this.count > 0;
}
/**
* Get an estimation of how much time is left before the invasion ends in milliseconds
* @returns {number} remaining time in ms
*/
getRemainingTime() {
const completedRuns = Math.abs(this.count);
const elapsedMillis = toNow(this.activation);
const remainingRuns = this.requiredRuns - completedRuns;
return remainingRuns * (elapsedMillis / completedRuns);
}
/**
* Get a string estimating how much time is left before the invasion ends
* @returns {string} time delta string from now to the end
*/
getETAString() {
return timeDeltaToString(this.getRemainingTime());
}
/**
* Get the types of the items being rewarded in the invasion
* @returns {Array<string>} types of items being rewarded
*/
getRewardTypes() {
return [...(this.attacker.reward?.getTypes() ?? []), ...(this.defender.reward?.getTypes() ?? [])];
}
/**
* The invasion's string representation
* @returns {string} string representation of the invasion
*/
toString() {
let lines = [];
if (this.vsInfestation) {
lines = [
this.defender.reward?.toString(),
`${this.desc} on ${this.node}`,
`${Math.round(this.completion * 100) / 100}% - ETA: ${this.getETAString()}`,
].filter(Boolean);
} else {
lines = [
`${this.attackingFaction} (${this.attacker.reward}) vs. ${this.defender.faction} (${this.defender.reward})`,
`${this.node} - ${this.desc}`,
`${Math.round(this.completion * 100) / 100}% - ETA: ${this.getETAString()}`,
];
}
return `${mdConfig.codeBlock}${lines.join(mdConfig.lineEnd)}${mdConfig.blockEnd}`;
}
}