Pre-release
AdventureJS Docs Downloads Devlog
Score: 0 Moves: 0
// numberToWords.js

(function () {
  /* global AdventureJS A */

  var p = AdventureJS.Dictionary.prototype;

  /**
   * numberToWords converts integers to written words
   * such as "10 pistachios" to "ten pistachios".
   * @method AdventureJS.Dictionary#numberToWords
   * @memberOf AdventureJS
   * @param {String} text
   * @returns {String}
   */
  p.numberToWords = function Dictionary_numberToWords(num, british = true) {
    const ONES = [
      "no",
      /* "zero", */
      /* "a", */ /* "a" breaks on "a hundred and a" */
      "one",
      "two",
      "three",
      "four",
      "five",
      "six",
      "seven",
      "eight",
      "nine",
      "ten",
      "eleven",
      "twelve",
      "thirteen",
      "fourteen",
      "fifteen",
      "sixteen",
      "seventeen",
      "eighteen",
      "nineteen",
    ];

    const TENS = [
      "",
      "",
      "twenty",
      "thirty",
      "forty",
      "fifty",
      "sixty",
      "seventy",
      "eighty",
      "ninety",
    ];

    const THOUSANDS = ["", "thousand", "million", "billion", "trillion"];

    const chunkToWords = function (n, british) {
      const parts = [];

      if (n >= 100) {
        parts.push(ONES[Math.floor(n / 100)]);
        parts.push("hundred");
        n %= 100;

        if (british) {
          if (n > 0) {
            parts.push("and");
          }
        }
      }

      if (n >= 20) {
        const tens = Math.floor(n / 10);
        const ones = n % 10;

        parts.push(ones ? `${TENS[tens]}-${ONES[ones]}` : TENS[tens]);
      } else if (n > 0) {
        parts.push(ONES[n]);
      }

      return parts.join(" ");
    };

    if (!Number.isInteger(num)) {
      return "NaN";
    }

    if (num === -1) return "infinite";

    if (num === 0) return "zero";

    if (num < 0) {
      return `minus ${this.numberToWords(-num)}`;
    }

    const parts = [];
    let group = 0;

    while (num > 0) {
      const chunk = num % 1000;

      if (chunk) {
        let text = chunkToWords(chunk, british);

        if (THOUSANDS[group]) {
          text += ` ${THOUSANDS[group]}`;
        }

        parts.unshift(text);
      }

      num = Math.floor(num / 1000);
      group++;
    }

    return parts.join(" ");
  };
})();