Source: AlphaTab/Measure.js

/**
 * @class
 * @classdesc Encapsulates each measure in the music composed of string, int, bool attributes and an array of chords
 */
class Measure {
    /**
     * Constructs a new Measure
     */
    constructor() {
        this.attributesStr = new Map();
        this.attributesInt = new Map();
        this.attributesBool = new Set();
        this.chords = [];
    }
    
    /**
     * Sets string attribute
     * @param {string} attribute attribute of string to set
     * @param {string} value value of string to set
     */
    setStr(attribute, value) {
        this.attributesStr.set(attribute, value);
    }

    /**
     * Set int attribute
     * @param {string} attribute attribute of int to set
     * @param {number} value value of int to set
     */
    setInt(attribute, value) {
        this.attributesInt.set(attribute, value);
    }

    /**
     * Get int attribute
     * @param {string} attribute attribute of int to retrieve
     * @returns {number} The value for the asked attribute
     */
    getInt(attribute) { return this.attributesInt.get(attribute); }

    /**
     * Remove int attribute
     * @param {string} attribute attribute of int to remove
     */
    removeInt(attribute) { this.attributesInt.delete(attribute); }

    /**
     * Add bool attribute
     * @param {string} attribute attribute of bool to add
     */
    addBool(attribute) { this.attributesBool.add(attribute); }

    /**
     * Copies all string, int, and boolean attributes into this object
     * @param {object} source Source must have attributesStr, attributesInt, attributesBool
     * @property {Map} source.attributesStr Map relating String attributes to String values
     * @property {Map} source.attributesInt Map relating String attributes to Number values
     * @property {Set} source.attributesBool Set with String attributes
     */
    copyAttributes(source) {
        source.attributesStr.forEach((value, key, map) => {
            this.setStr(key, value);
        });

        source.attributesInt.forEach((value, key, map) => {
            this.setInt(key, value);
        });

        source.attributesBool.forEach((value1, value2, set) => {
            this.addBool(value1);
        });
    }

    /**
     * Adds chord to this array of chords
     * @param {Chord} chord Chord object to add to this array of chords
     */
    addChord(chord) {
        this.chords.push(chord);
    }

    /**
     * Copies source attributes and chords into this objects attributes and chords
     * @param {object} source Source object must have attributesStr, attributesInt, attributesBool, chords
     * @property {Map} source.attributesStr Map relating String attributes to String values
     * @property {Map} source.attributesInt Map relating String attributes to Number values
     * @property {Set} source.attributesBool Set with String attributes
     * @property {Chord[]} source.chords Array of Chord objects
     */
    copy(source) {
        this.copyAttributes(source);
        source.chords.forEach((element) => {
            this.addChord(element);
        });
    }

    /**
     * Converts Measure to a pretty string
     * @returns {string} The pretty string representation of the measure
     */
    toString() {
        let output = "";

        output += "Measure attributes: \n";
        this.attributesStr.forEach((value, key, map) => {
            output += "\t";
            output += key;
            output += " : ";
            output += value;
            output += "\n";
        });

        this.attributesInt.forEach((value, key, map) => {
            output += "\t";
            output += key;
            output += " : ";
            output += value;
            output += "\n";
        });

        output += "Chords: \n";

        this.chords.forEach((element) => {
            output += element.toString();
            output += "\n";
        });

        return output;
    }
}

module.exports = Measure;