Source: hg/FinalEvent.js

// Copyright 2019 Campbell Crowley. All rights reserved.
// Author: Campbell Crowley (dev@campbellcrowley.com)
const UserIconUrl = require('./UserIconUrl.js');
const Grammar = require('./Grammar.js');
const funTranslator = require('../lib/funTranslators.js');

/**
 * @description Finalized event ready for display to users.
 * @memberof HungryGames
 * @inner
 */
class FinalEvent {
  /**
   * @description Create an event ready for display.
   * @param {HungryGames~NormalEvent} evt Event to finalize.
   * @param {HungryGames~GuildGame} game Game context.
   * @param {HungryGames~Player[]} affected An array of all players affected by
   * this event.
   */
  constructor(evt, game, affected) {
    const useNickname = game.options.useNicknames ? 'nickname' : 'username';
    const mention = game.options.mentionAll;
    const vO = evt.victim.outcome;
    const aO = evt.attacker.outcome;
    const nV = evt.victim.count;
    const nA = evt.attacker.count;
    /**
     * @description String to send to mention users.
     * @public
     * @type {string}
     */
    this.mentionString = '';
    let translator = null;
    for (let i = 0; i < affected.length; i++) {
      if (!affected[i]) {
        console.log('BAD AFFECTED', affected);
        continue;
      }
      if (!affected[i].isNPC && mention == 'all' ||
          (mention == 'death' &&
           ((vO == 'dies' && i < nV) || (aO == 'dies' && i >= nV)))) {
        this.mentionString += `<@${affected[i].id}>`;
      }
      if (affected[i].settings &&
          affected[i].settings['hg:fun_translators'] &&
          affected[i].settings['hg:fun_translators'] !== 'disabled') {
        translator = affected[i].settings['hg:fun_translators'];
      }
    }
    const affectedVictims = affected.slice(0, nV);
    const affectedAttackers = affected.slice(nV, nA + nV);
    let finalMessage =
        evt.message
            .replace(
                /\[V([^|]*)\|([^\]]*)\]/g,
                affectedVictims.length > 1 ? '$2' : '$1')
            .replace(
                /\[A([^|]*)\|([^\]]*)\]/g,
                affectedAttackers.length > 1 ? '$2' : '$1');
    let deadUsers = [];
    if (finalMessage.indexOf('{dead}') > -1) {
      const deadList = game.currentGame.includedUsers.filter(
          (obj) => !obj.living && !affected.find((u) => u.id == obj.id));
      if (deadList.length > 0) {
        const index = Math.floor(Math.random() * deadList.length);
        deadUsers = deadList.slice(index, index + 1);
      }
      finalMessage = finalMessage.replace(
          /\[D([^|]*)\|([^\]]*)\]/g, deadUsers.length <= 1 ? '$1' : '$2');
    }
    finalMessage =
        finalMessage.replace(/\{(victim|attacker|dead)\}/g, (match, tag) => {
          switch (tag) {
            case 'victim':
              return Grammar.formatMultiNames(affectedVictims, useNickname);
            case 'attacker':
              return Grammar.formatMultiNames(affectedAttackers, useNickname);
            case 'dead':
              if (deadUsers.length > 0) {
                return Grammar.formatMultiNames(deadUsers, useNickname);
              } else {
                return 'an animal';
              }
          }
        });
    finalMessage = funTranslator.to(translator, finalMessage);

    /**
     * @description Message to show to user.
     * @public
     * @type {string}
     */
    this.message = finalMessage;
    /**
     * @description The icons to show in the message.
     * @public
     * @type {HungryGames~UserIconUrl[]}
     */
    this.icons = UserIconUrl.from(affectedVictims, affectedAttackers);

    /**
     * @description Amount of weapons this consumes.
     * @public
     * @type {Array.<{name: string, count: number}>}
     */
    this.consumes = evt.consumes;
    if (!evt.consumes || typeof evt.consumes === 'number' ||
        (typeof evt.consumes === 'string' && evt.consumes.match(/^\d+$/))) {
      if (evt.consumes != null) {
        this.consumes = [evt.consumes * 1];
      } else {
        this.consumes = [];
      }
    } else if (!Array.isArray(this.consumes)) {
      throw new TypeError('Consumes is not an array: ' + evt.consumes);
    }
    /**
     * @description The ID of the player that will be consuming weapons.
     * @public
     * @type {string}
     */
    this.consumer = evt.consumer;

    const vW = evt.victim.weapon &&
        [{id: evt.victim.weapon.id, count: evt.victim.weapon.count}];
    const aW = evt.attacker.weapon &&
        [{id: evt.attacker.weapon.id, count: evt.attacker.weapon.count}];

    /**
     * @description Information about the victims as a result of this event.
     * Weapon count is amount gained.
     * @public
     * @type {{
     *   outcome: string,
     *   count: number,
     *   killer: boolean,
     *   weapons: Array.<{name: string, count: number}>
     * }}
     */
    this.victim = {
      outcome: vO,
      count: nV,
      killer: evt.victim.killer,
      weapons: vW || [],
    };
    /**
     * @description Information about the attackers as a result of this event.
     * Weapon count is amount gained.
     * @public
     * @type {{
     *   outcome: string,
     *   count: number,
     *   killer: boolean,
     *   weapons: Array.<{name: string, count: number}>
     * }}
     */
    this.attacker = {
      outcome: aO,
      count: nA,
      killer: evt.attacker.killer,
      weapons: aW || [],
    };

    /**
     * @description Additional message text to display.
     * @public
     * @type {string}
     */
    this.subMessage = evt.subMessage || '';
  }
}

module.exports = FinalEvent;