Source: sequence.js

const {Tab, Slot, None} = require('./insert');

/**
 * A function for generating {@link Insert}s sequentially
 *
 * @callback InsertsGenerator
 * @param {number} index the position of the element to be generated in the sequence
 * @returns {import('./insert').Insert}
 */

/**
 * This module exports several {@link Insert}s sequences strategies: {@link fixed}, {@link flipflop}, {@link twoAndTwo} and {@link random}
 *
 * @module sequence
 */

/**
 * @type {InsertsGenerator}
 */
function fixed(_n) {
  return Tab;
}

/**
 * Generates slots and tabs alternately
 *
 * @type {InsertsGenerator}
 */
function flipflop(n) {
  return n % 2 === 0 ? Tab : Slot;
}

/**
 * Generates sequences of two slots and then two tabs
 *
 * @type {InsertsGenerator}
 */
function twoAndTwo(n) {
  return n % 4 < 2 ? Tab : Slot;
}

/**
 * Generates tabs and slots in a psuedo-random way
 *
 * @type {InsertsGenerator}
 */
function random(_) {
  return Math.random() < 0.5 ? Tab : Slot;
}

/**
 * An InsertSequence is a statefull object that
 * allows to generate {@link Insert}s sequences using an {@link InsertsGenerator} as strategy
 */
class InsertSequence {
  /**
   * @param {InsertsGenerator} generator the generator used by this sequence to produce inserts
   */
  constructor(generator) {
    this.generator = generator;
    this.n = 0
    this._previous;
    this._current = None;
  }

  /**
   * The previously generated insert
   *
   * @returns {import('./insert').Insert}
   */
  previousComplement() {
    return this._previous.complement();
  }

  /**
   * Answers the last Insert generated by {@link InsertSequence#next}
   *
   * @returns {import('./insert').Insert}
   */
  current(max) {
    if (this.n == max) {
      return None
    }
    return this._current;
  }

  /**
   * @returns {import('./insert').Insert}
   **/
  next() {
    this._previous = this._current;
    this._current = this.generator(this.n++);
    return this._current;
  }
}

module.exports = {
  InsertSequence,
  fixed,
  flipflop,
  twoAndTwo,
  random
}