Pre-release
AdventureJS Docs Downloads
Score: 0 Moves: 0
// ParsedNoun.js
(function () {
  /* global AdventureJS A */

  /**
   * @class AdventureJS.Parser.ParsedNoun
   * @param {Object|AdventureJS.Assets.Asset} asset
   * @ajsinternal
   * @ajsnavheading ParserClasses
   * @summary Special class used to store metadata about an asset
   * and lists of all possible matches for that asset.
   * @classdesc
   * <p>
   * <strong>ParsedNoun</strong> is a special class constructed by
   * {@link AdventureJS.Parser#parseNoun|Parser.parseNoun()},
   * and used to store metadata about an asset and lists of all
   * possible matches for that asset. This is an internal class
   * that authors should not need to construct.
   * </p>
   */
  class ParsedNoun {
    constructor(asset) {
      if (!asset || !asset.id) asset = null;

      /**
       *
       * @var {String} AdventureJS.Parser.ParsedNoun#
       * @default
       */
      this.class = "ParsedNoun";

      /**
       *
       * @var {Boolean} AdventureJS.Parser.ParsedNoun#exclude
       * @default false
       */
      this.exclude = false;

      /**
       *
       * @var {String} AdventureJS.Parser.ParsedNoun#plural
       * @default ""
       */
      this.plural = "";

      /**
       *
       * @var {Boolean} AdventureJS.Parser.ParsedNoun#is_plural
       * @default false
       */
      this.is_plural = false;

      /**
       *
       * @var {Boolean} AdventureJS.Parser.ParsedNoun#is_all
       * @default false
       */
      this.is_all = false;

      /**
       *
       * @var {Boolean} AdventureJS.Parser.ParsedNoun#is_group
       * @default false
       */
      this.is_group = false;

      /**
       *
       * @var {String} AdventureJS.Parser.ParsedNoun#singular
       * @default ""
       */
      this.singular = "";

      /**
       *
       * @var {String} AdventureJS.Parser.ParsedNoun#type
       * @default ""
       */
      this.type = "";

      /**
       * The asset name found in user input, though that may already have been
       * replaced with an asset ID by the time this noun gets parsed.
       * @var {String} AdventureJS.Parser.ParsedNoun#input
       * @default ""
       */
      this.input = asset === null ? "" : asset.name;

      /**
       * Serializing input changes to lowercase, replaces spaces with underscores.
       * @var {String} AdventureJS.Parser.ParsedNoun#normalized_input
       * @default ""
       */
      this.normalized_input = asset === null ? "" : asset.id;

      /**
       * During parsing we may replace the original input string with
       * the ID of a found asset. Ensure that we keep the original.
       * @var {String} AdventureJS.Parser.ParsedNoun#original_input
       * @default ""
       */
      this.original_input = asset === null ? "" : asset.name;

      /**
       * If a singular asset was found that matched the input, store its ID here.
       * @var {String} AdventureJS.Parser.ParsedNoun#is_qualified
       * @default ""
       */
      this.is_qualified = asset === null ? "" : asset.id;

      /**
       * Save a variety of information about assets that matched the input.
       * @var {Object} AdventureJS.Parser.ParsedNoun#matches
       * @default { all:[], qualified:[], qindex:0 }
       */
      this.matches = {
        all: [],

        qualified: [],

        // qindex exists because there is a scenario where
        // a verb can act without disambiguation upon one
        // qualified asset out of a group returned by the parser
        qindex: 0,

        // matches.qualified can be set from many places.
        // setby is a debug code used to trace where it was set.
        setby: "",
      };

      /**
       * matches.qualified can be set from many places.
       * matchcode is a code used to debug where it was set.
       * @var {Object} AdventureJS.Parser.ParsedNoun#matchcode
       * @default ""
       */
      this.matchcode = "";

      if (asset !== null) {
        this.matches.all = [asset.id];
        this.matches.qualified = [asset.id];
        this.matches.qindex = 0;
      }

      /**
       * If a singular asset was found that matched the input, store its ID here.
       * We only use this in support of setting is_qualified, the ultimate arbiter.
       *
       * we set unambiguous but never really rely on it due to the
       * scenario described above - safer to use ParsedNoun.asset_id
       * it also causes an issue with substances in handleSentence where
       * substance is unambiguous though multiple substance containers are found
       *
       * @var {String} AdventureJS.Parser.ParsedNoun#is_unambiguous
       * @default ""
       */
      this.is_unambiguous = asset === null ? "" : asset.id;

      /**
       *
       * @var {String} AdventureJS.Parser.ParsedNoun#preposition
       * @default ""
       */
      this.preposition = "";

      /**
       *
       * @var {Boolean} AdventureJS.Parser.ParsedNoun#is_assumed
       * @default false
       */
      this.is_assumed = false;

      /**
       *
       * @var {Boolean} AdventureJS.Parser.ParsedNoun#is_platonic
       * @default false
       */
      this.is_platonic = false;

      /**
       *
       * @var {String} AdventureJS.Parser.ParsedNoun#is_direction
       * @default ""
       */
      this.is_direction = false;

      /**
       *
       * @var {String} AdventureJS.Parser.ParsedNoun#is_substance
       * @default ""
       */
      this.is_substance = false;

      /**
       *
       * @var {Boolean} AdventureJS.Parser.ParsedNoun#is_dispenser
       * @default false
       */
      this.is_dispenser = false;

      /**
       *
       * @var {Boolean} AdventureJS.Parser.ParsedNoun#is_fungible
       * @default false
       */
      this.is_fungible = false;

      return this;
    }

    /**
     * Getter function looks for a qualified asset id, and if it
     * doesn't find one, it returns the first qualified match.
     * @var {Getter} AdventureJS.Parser.ParsedNoun#asset_id
     * @returns {String}
     * @TODO returning this.is_unambiguous breaks with platonics
     * because you wind up with this:
     *
     * is_unambiguous: "platonic_pistachio"
     * matches:
     *  all: ['platonic_pistachio']
     *  qindex: 0
     *  qualified:['pistachio_0']
     *
     */
    get asset_id() {
      return (
        /* this.is_unambiguous || */
        this.is_qualified || this.matches.qualified[this.matches.qindex] || null
      );
    }

    /**
     * Provides a chainable shortcut method for setting a number of properties on the instance.
     * @method AdventureJS.Atom#set
     * @memberOf AdventureJS.Atom
     * @param {Object} props A generic object containing properties to copy to the Object instance.
     * @returns {Object} Returns the instance the method is called on (useful for chaining calls.)
     * @chainable
     */
    set(props) {
      return A.FX.deepSet.call(this.game, props, this);
    }
  }

  AdventureJS.Parser.ParsedNoun = ParsedNoun;
})();