models/gang.js

import Model from "./model.js";
import { article, sentenceCase, numberWord, Builder } from "../string_utils.js";
import { COMBAT_TRAITS } from "../constants.js";

function combatantString(character) {
  const traits = {};
  Object.values(COMBAT_TRAITS).forEach(function (traitName) {
    if (character.trait(traitName) > 0) {
      traits[traitName] = character.trait(traitName);
    }
  });
  // This is destructive, which is not great
  character.traits = traits;
  character.description = [];
  return character.toString();
}

/**
 * Represents a Gang, which is a set of characters of a specific kind or purpose. Could
 * also be called a “party”.
 *
 * @class
 * @extends Model
 *
 * @property {Array<Character>} members - The members of the gang.
 * @property {String} kind - The kind or type of the gang.
 * @property {String} [name] - The name of the gang.
 *
 * @example
 * const gang = new Gang({
 *   name: 'Oakley Boys',
 *   kind: 'Cowboy Posse',
 *   members: [pa, littleJohn, billy]
 * });
 */
class Gang extends Model {
  /**
   * Create a Gang.
   * @param [params] {Object}
   * @param {String} params.kind - The kind/type of the gang.
   * @param {String} [params.name] - The name of the gang.
   * @param {Array} [params.members=[]] - The members of the gang.
   * @param {Array} [params.tags=[]] - Tags associated with the gang.
   */
  constructor({ kind, name, members = [], tags = [], guid } = {}) {
    super({ tags, guid });
    this.name = name;
    this.kind = kind;
    this.members = members;
    this._class = "Gang";
  }
  add(character) {
    this.members.push(character);
  }
  roster() {
    return this.members.map((m) => `<p>${m.toString()}</p>`).join("");
  }
  gangName(lowercase = false) {
    let len = numberWord(this.members.length);
    let type = `${article(len)} member ${this.kind.toLowerCase()}`;
    let str = !!this.name ? `the ${this.name} (${type})` : type;
    return lowercase ? str : sentenceCase(str);
  }
  toTitleString() {
    return this.name || this.kind;
  }
  getDisplayProps() {
    if (this.name) {
      return { _kind: this.kind, __members: this.members.length };
    }
    return { __members: this.members.length };
  }
  toDetailHtml() {
    return this.members.map((m) => `<p>${m.toString()}</p>`).join("");
  }
  toString() {
    const b = new Builder();
    b.append(this.gangName(false));
    b.append(": \n\n");
    b.append(this.roster());
    return b.toString();
  }
}

export default Gang;