Source: hg/Player.js

// Copyright 2019 Campbell Crowley. All rights reserved.
// Author: Campbell Crowley (dev@campbellcrowley.com)
const Discord = require('discord.js');

/**
 * @description Serializable container for data pertaining to a single user.
 * @memberof HungryGames
 * @inner
 */
class Player {
  /**
   * @description Create a player object for a game. Requires a unique ID and a
   * username.
   * @param {string} id The id of the user this object is representing.
   * @param {string} username The name of the user to show in the game.
   * @param {string} avatarURL URL to avatar to show for the user in the game.
   * @param {?string} [nickname=null] The nickname for this user usually
   * assigned by the guild. If the user does not have a nickname, this will have
   * the same value as `name`.
   */
  constructor(id, username, avatarURL = '', nickname = null) {
    // Replace backtick with Unicode 1FEF Greek Varia because it looks the same,
    // but it wont ruin formatting.
    username = username.replace(/`/g, '`');
    if (typeof nickname === 'string') nickname = nickname.replace(/`/g, '`');
    /**
     * The id of the User this Player represents.
     *
     * @type {string}
     * @public
     */
    this.id = id;
    /**
     * The name of this Player.
     *
     * @type {string}
     * @public
     */
    this.name = username;
    /**
     * The URL to the discord avatar of the User.
     *
     * @type {string}
     * @public
     * @default ''
     */
    this.avatarURL = avatarURL || '';
    /**
     * The nickname for this user usually assigned by the guild. If the user
     * does
     * not have a nickname, this will have the same value as `name`.
     *
     * @type {string}
     */
    this.nickname = nickname || username;
    /**
     * Is the player still alive.
     *
     * @type {boolean}
     * @public
     * @default
     */
    this.living = true;
    /**
     * How many days has the player been wounded.
     *
     * @type {number}
     * @public
     * @default
     */
    this.bleeding = 0;
    /**
     * The current rank of the player in the game.
     *
     * @type {number}
     * @public
     * @default
     */
    this.rank = 1;
    /**
     * The current player state (normal, wounded, dead, zombie).
     *
     * @type {string}
     * @public
     * @default
     */
    this.state = 'normal';
    /**
     * The number of players this player has caused to die.
     *
     * @type {number}
     * @public
     * @default
     */
    this.kills = 0;
    /**
     * The weapons the player currently has and how many of each.
     *
     * @type {object.<number>}
     * @public
     * @default
     */
    this.weapons = {};
    /**
     * Custom settings for this user associated with the games.
     *
     * @type {object}
     * @public
     * @default
     */
    this.settings = {};
    /**
     * The day at which the player last died in the game. Only a valid number if
     * the player is currently dead. Otherwise a garbage value will be
     * available.
     *
     * @type {number}
     * @public
     * @default
     */
    this.dayOfDeath = -1;
  }
}

/**
 * @description Create a Player from a given Discord.User or Player-like Object.
 * Can be used as a copy-constructor.
 *
 * @public
 * @static
 * @param {
 * Discord~User|Discord~GuildMember|object
 * } member Object, User or GuildMember to make a Player from.
 * @returns {HungryGames~Player} Player object created.
 */
Player.from = function(member) {
  let player;
  if (typeof member === 'string') {
    player = new Player(member, member);
  } else {
    const isDiscord = (member instanceof Discord.GuildMember) ||
        (member instanceof Discord.User);
    const user = isDiscord ? member.user || member : member;
    const avatar =
        isDiscord ? user.displayAvatarURL({extension: 'png'}) : user.avatarURL;
    const name = isDiscord ? user.username : member.name;
    player = new Player(user.id, name, avatar, member.nickname);
    if (!isDiscord) {
      if (typeof player.living === 'boolean' || player.living === 'true' ||
          player.living === 'false') {
        if (typeof player.living !== 'boolean') {
          player.living = player.living === 'true' ? true : false;
        }
        player.living = member.living;
      }
      player.bleeding = member.bleeding || 0;
      player.rank = member.rank || 1;
      player.state = member.state || 'normal';
      player.kills = member.kills || 0;
      player.weapons = member.weapons || {};
      player.settings = member.settings || {};
      if (!isNaN(member.dayOfDeath)) {
        player.dayOfDeath = member.dayOfDeath;
      }
    }
  }
  return player;
};

module.exports = Player;