<commit_before>/* written in ECMAscript 6 */
/**
 * @fileoverview WAVE scheduler singleton based on audio time (time-engine master)
 * @author Nor<EMAIL>, <EMAIL>, <EMAIL>
 */
'use strict';

var audioContext = require("audio-context");
var PriorityQueue = require("priority-queue");
var TimeEngine = require("time-engine");

function arrayRemove(array, value) {
  var index = array.indexOf(value);

  if (index >= 0) {
    array.splice(index, 1);
    return true;
  }

  return false;
}

class Scheduler {
  constructor() {
    this.__queue = new PriorityQueue();
    this.__engines = [];

    this.__currentTime = null;
    this.__nextTime = Infinity;
    this.__timeout = null;

    /**
     * scheduler (setTimeout) period
     * @type {Number}
     */
    this.period = 0.025;

    /**
     * scheduler lookahead time (> period)
     * @type {Number}
     */
    this.lookahead = 0.1;
  }

  // setTimeout scheduling loop
  __tick() {
    var nextTime = this.__nextTime;

    this.__timeout = null;

    while (nextTime <= audioContext.currentTime + this.lookahead) {
      this.__currentTime = nextTime;

      var engine = this.__queue.head;
      var time = engine.advanceTime(this.__currentTime);

      if (time && time < Infinity) {
        nextTime = this.__queue.move(engine, Math.max(time, this.__currentTime));
      } else {
        nextTime = this.__queue.remove(engine);

        // remove engine from scheduler
        if(!time && arrayRemove(this.__engines, engine))
          TimeEngine.resetInterface(engine);
      }
    }

    this.__currentTime = null;
    this.__reschedule(nextTime);
  }

  __reschedule(nextTime) {
    if (this.__timeout) {
      clearTimeout(this.__timeout);
      this.__timeout = null;
    }

    if (nextTime !== Infinity) {
      this.__nextTime = nextTime;

      var timeOutDelay = Math.max((nextTime - audioContext.currentTime - this.lookahead), this.period);

      this.__timeout = setTimeout(() => {
        this.__tick();
      }, timeOutDelay * 1000);
    }
  }

  /**
   * Get scheduler time
   * @return {Number} current scheduler time including lookahead
   */
  get currentTime() {
    return this.__currentTime || audioContext.currentTime + this.lookahead;
  }

  /**
   * Add a callback to the scheduler
   * @param {Function} callbackFunction callback function(time) to be called
   * @param {Number} time time of first callback (default is 0)
   * @return {Object} scheduled object that can be used to call remove and reset
   */
  callback(callbackFunction, time = this.currentTime) {
    var engine = {
      advanceTime: callbackFunction
    };

    var nextTime = this.__queue.insert(engine, this.currentTime + time);
    this.__reschedule(nextTime);

    return engine;
  }

  /**<commit_msg>fixed time in callback method<commit_after>/* written in ECMAscript 6 */
/**
 * @fileoverview WAVE scheduler singleton based on audio time (time-engine master)
 * @author Norbert.Schnell<EMAIL>, <EMAIL>, <EMAIL>
 */
'use strict';

var audioContext = require("audio-context");
var PriorityQueue = require("priority-queue");
var TimeEngine = require("time-engine");

function arrayRemove(array, value) {
  var index = array.indexOf(value);

  if (index >= 0) {
    array.splice(index, 1);
    return true;
  }

  return false;
}

class Scheduler {
  constructor() {
    this.__queue = new PriorityQueue();
    this.__engines = [];

    this.__currentTime = null;
    this.__nextTime = Infinity;
    this.__timeout = null;

    /**
     * scheduler (setTimeout) period
     * @type {Number}
     */
    this.period = 0.025;

    /**
     * scheduler lookahead time (> period)
     * @type {Number}
     */
    this.lookahead = 0.1;
  }

  // setTimeout scheduling loop
  __tick() {
    var nextTime = this.__nextTime;

    this.__timeout = null;

    while (nextTime <= audioContext.currentTime + this.lookahead) {
      this.__currentTime = nextTime;

      var engine = this.__queue.head;
      var time = engine.advanceTime(this.__currentTime);

      if (time && time < Infinity) {
        nextTime = this.__queue.move(engine, Math.max(time, this.__currentTime));
      } else {
        nextTime = this.__queue.remove(engine);

        // remove engine from scheduler
        if(!time && arrayRemove(this.__engines, engine))
          TimeEngine.resetInterface(engine);
      }
    }

    this.__currentTime = null;
    this.__reschedule(nextTime);
  }

  __reschedule(nextTime) {
    if (this.__timeout) {
      clearTimeout(this.__timeout);
      this.__timeout = null;
    }

    if (nextTime !== Infinity) {
      this.__nextTime = nextTime;

      var timeOutDelay = Math.max((nextTime - audioContext.currentTime - this.lookahead), this.period);

      this.__timeout = setTimeout(() => {
        this.__tick();
      }, timeOutDelay * 1000);
    }
  }

  /**
   * Get scheduler time
   * @return {Number} current scheduler time including lookahead
   */
  get currentTime() {
    return this.__currentTime || audioContext.currentTime + this.lookahead;
  }

  /**
   * Add a callback to the scheduler
   * @param {Function} callbackFunction callback function(time) to be called
   * @param {Number} time time of first callback (default is 0)
   * @return {Object} scheduled object that can be used to call remove and reset
   */
  callback(callbackFunction, time = this.currentTime) {
    var engine = {
      advanceTime: callbackFunction
    };

    var nextTime = this.__queue.insert(engine, time);
    this.__reschedule(nextTime);

    return engine;
  }

  /**
{'fraction_non_alphanumeric': 0.12344117115488885, 'fraction_numerical': 0.005060545816013013, 'mean_word_length': 2.8034364261168383, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6048278', 'n_tokens_mistral': 1713, 'n_tokens_neox': 1628, 'n_words': 415}