db/rarity_database.js

import { random } from "../random_utils.js";
import { tagFilter } from "./database.js";
import Database from "./database.js";
import RarityTable from "../tables/rarity_table.js";

/**
 * Database that supports rarity-based item selection using frequency weighting.
 * @class RarityDatabase
 * @extends Database
 */
export default class RarityDatabase extends Database {
  /**
   * Creates a new RarityDatabase instance.
   * @constructor
   */
  constructor({ parser }) {
    super({ parser });
    this.table = new RarityTable();
    delete this.models;
  }
  add(...data) {
    for (let i = 0, len = data.length; i < len; i++) {
      var records = this.parser(data[i]);
      if (records instanceof Array) {
        records.forEach((r) => this.table.add(r.frequency, r));
      } else {
        this.table.add(records.frequency, records);
      }
    }
    return this;
  }
  get() {
    return this.table.get();
  }
  /**
   * This returns all items that match regardless of rarity, or an empty array
   * if none match.
   *
   * @param {*} param0
   * @returns {Model[]} all models that match
   */
  findAll({ tags } = {}) {
    return this.table.rows.filter((m) => tagFilter(m, tags));
  }
  /**
   * This returns one random item that matches, respecting rarity.
   * @param {*} param0
   * @returns {Model|null} a random matching model, or null if none found
   */
  findOne({ tags } = {}) {
    var freqs = this.table.weightedSort();
    while (freqs.length) {
      var freq = freqs.shift();
      var rows = this.table[freq].filter((m) => tagFilter(m, tags));
      if (rows.length) {
        return random(rows);
      }
    }
    return null;
  }
}