db/item_database.js

import { calculateEncumbrance } from "../tag_utils.js";
import { random } from "../random_utils.js";
import { tagFilter } from "./database.js";
import { toTag } from "../string_utils.js";
import Item from "../models/item.js";
import RarityDatabase from "./rarity_database.js";

/**
 * Register one or more items (via a short, string-based item specification format)
 * with this database.
 *
 * Specification
 *
 * `name1; name2!value!tags`
 *
 * The first tag must always be 'common', 'uncommon' or 'rare'. If a 'br' tag is
 * included, this indicates that the item can be found broken, and it will be added
 * to the database twice (once intact, and once broken).
 *
 * @param {*} line
 * @returns {array} results
 */
function parser(line) {
  let parts = line.split("!");
  let names = parts[0].trim().split(/\s*;\s*/);
  let [all, value, freq, enc] = parts[1].match(/(.*)([ruc])(.*)/);
  let tagArray = parts[2]
    .trim()
    .split(/\s+/)
    .filter((s) => s !== "");
  let frequency = freq === "c" ? "common" : freq === "u" ? "uncommon" : "rare";
  let tags = new Set(tagArray);
  let results = [];
  let params = {
    value: parseFloat(value),
    enc: enc,
    frequency,
    tags,
  };
  names.forEach((name) => {
    params.name = name;
    add(results, params);
  });
  return results;
}

function add(array, params) {
  let item = new Item(params);
  item.tags.add(toTag(params.name)); // add name in tag form
  array.push(item);
}

class ItemDatabase extends RarityDatabase {
  constructor() {
    super({ parser });
  }
  findAll({
    name,
    tags,
    minValue = 0,
    maxValue = Number.MAX_VALUE,
    minEnc = 0,
    maxEnc = Number.MAX_VALUE,
  } = {}) {
    return this.table.rows
      .filter(
        (model) =>
          model.name.indexOf(name) > -1 ||
          (model.value >= minValue &&
            model.value <= maxValue &&
            model.enc >= minEnc &&
            model.enc <= maxEnc &&
            tagFilter(model, tags))
      )
      .map((item) => new Item(item));
  }
  findOne({
    name,
    tags,
    minValue = 0,
    maxValue = Number.MAX_VALUE,
    minEnc = 0,
    maxEnc = Number.MAX_VALUE,
  } = {}) {
    var freqs = this.table.weightedSort();
    while (freqs.length) {
      var freq = freqs.shift();
      var rows = this.table[freq].filter(
        (model) =>
          model.name.indexOf(name) > -1 ||
          (model.value >= minValue &&
            model.value <= maxValue &&
            model.enc >= minEnc &&
            model.enc <= maxEnc &&
            tagFilter(model, tags))
      );
      if (rows.length) {
        return new Item(random(rows));
      }
    }
    return null;
  }
}

export default ItemDatabase;