Home Reference Source

src/network/rps/cyclon/partialview.js

class PartialView extends Map {
  /**
     * Get the oldest peer in the partial view.
     * @returns {string} The oldest peer in the array.
     */
  get oldest () {
    if (this.size <= 0) { throw new Error('oldest peer not found') };
    let oldestPeer = null
    let oldestAge = 0
    this.forEach((ages, peerId) => {
      if (oldestAge <= ages[ages.length - 1]) {
        oldestPeer = peerId
        oldestAge = ages[ages.length - 1]
      };
    })
    return oldestPeer
  };

  /**
     * Increment the age of the whole partial view
     */
  increment () {
    this.forEach((ages, peerId) => {
      this.set(peerId, ages.map((age) => { return age + 1 }))
    })
  };

  /**
     * Add the peer to the partial view with an age of 0.
     * @param {string} peerId The identifier of the peer added to the partial
     * view.
     */
  add (peerId) {
    (!this.has(peerId)) && this.set(peerId, [])
    this.get(peerId).unshift(0) // add 0 in front of the array
  };

  /**
     * Remove the newest entry of the peer from the partial view.
     * @param {string} peerId The identifier of the peer to remove from the
     * partial view.
     */
  removeYoungest (peerId) {
    if (!this.has(peerId)) {
      throw new Error('removeYoungest, peer not found' + peerId)
    };
    this.get(peerId).shift();
    (this.get(peerId).length === 0) && this.delete(peerId)
  };

  /**
     * Remove the oldest entry of the peer from the partial view.
     * @param {string} peerId The identifier of the peer to remove from the
     * partial view.
     */
  removeOldest (peerId) {
    if (!this.has(peerId)) {
      throw new Error('removeOldest, peer not found:' + peerId)
    };
    this.get(peerId).pop();
    (this.get(peerId).length === 0) && this.delete(peerId)
  };

  /**
     * Remove all entries of the peer from the partial view.
     * @param {string} peerId The identifier of the peer to remove from the
     * partial view.
     * @returns {number} The number of occurrences of peerId removed.
     */
  removeAll (peerId) {
    if (!this.has(peerId)) {
      throw new Error('removeAll, peer not found: ' + peerId)
    };
    const occ = this.get(peerId).length
    this.delete(peerId)
    return occ
  };

  /**
     * Get the least frequent peer. If multiple peers have the same number of
     * occurrences, it chooses one among them at random.
     * @returns {string} The identifier of a least frequent peer.
     */
  get leastFrequent () {
    let leastFrequent = []
    let frequency = Infinity
    this.forEach((ages, peerId) => {
      if (ages.length < frequency) {
        leastFrequent = []
        frequency = ages.length
      };
      (ages.length === frequency) && leastFrequent.push(peerId)
    })
    return leastFrequent[Math.floor(Math.random() * leastFrequent.length)]
  };
}

module.exports = PartialView