units.mjs

export { WorkflowUnits, WorkflowUnitsCombobox };

/**
 * Helper functions to get factors to convert between unit systems
 */
class WorkflowUnits {
    /**
     * Get the length unit for the given unit system
     * @param {number} unit_system Workflow unit system, e.g. Workflow.UNIT_SYSTEM_U1
     * @returns {string}
     * @example
     * let u = WorkflowUnits.LengthUnit(Workflow.UNIT_SYSTEM_U1);
     */
    static LengthUnit(unit_system) {
        switch (unit_system) {
            case Workflow.UNIT_SYSTEM_U1:
                return "m";
            case Workflow.UNIT_SYSTEM_U2:
                return "mm";
            case Workflow.UNIT_SYSTEM_U3:
                return "mm";
            case Workflow.UNIT_SYSTEM_U4:
                return "mm";
            case Workflow.UNIT_SYSTEM_U5:
                return "ft";
            case Workflow.UNIT_SYSTEM_U6:
                return "m";

            default:
                return "";
        }
    }

    /**
     * Get the mass unit for the given unit system
     * @param {number} unit_system Workflow unit system, e.g. Workflow.UNIT_SYSTEM_U1
     * @returns {string}
     * @example
     * let u = WorkflowUnits.MassUnit(Workflow.UNIT_SYSTEM_U1);
     */
    static MassUnit(unit_system) {
        switch (unit_system) {
            case Workflow.UNIT_SYSTEM_U1:
                return "kg";
            case Workflow.UNIT_SYSTEM_U2:
                return "tonne";
            case Workflow.UNIT_SYSTEM_U3:
                return "kg";
            case Workflow.UNIT_SYSTEM_U4:
                return "gm";
            case Workflow.UNIT_SYSTEM_U5:
                return "slug";
            case Workflow.UNIT_SYSTEM_U6:
                return "tonne";

            default:
                return "";
        }
    }

    /**
     * Get the time unit for the given unit system
     * @param {number} unit_system Workflow unit system, e.g. Workflow.UNIT_SYSTEM_U1
     * @returns {string}
     * @example
     * let u = WorkflowUnits.TimeUnit(Workflow.UNIT_SYSTEM_U1);
     */
    static TimeUnit(unit_system) {
        switch (unit_system) {
            case Workflow.UNIT_SYSTEM_U1:
                return "s";
            case Workflow.UNIT_SYSTEM_U2:
                return "s";
            case Workflow.UNIT_SYSTEM_U3:
                return "ms";
            case Workflow.UNIT_SYSTEM_U4:
                return "ms";
            case Workflow.UNIT_SYSTEM_U5:
                return "s";
            case Workflow.UNIT_SYSTEM_U6:
                return "s";

            default:
                return "";
        }
    }

    /**
     * Returns a factor to divide a length value by to convert it from the given unit system to metres
     * (or multiply by to convert from metres to the given unit system)
     * @param {number} unit_system Workflow unit system, e.g. Workflow.UNIT_SYSTEM_U1
     * @returns {number}
     * @example
     * let mm = 1500;  // 1500mm
     * let f = WorkflowUnits.LengthToMetresFactor(Workflow.UNIT_SYSTEM_U2);
     * let metres = mm / f;  // metres = 1500 / 1000 = 1.5
     */
    static LengthToMetresFactor(unit_system) {
        switch (unit_system) {
            case Workflow.UNIT_SYSTEM_U1:
                return 1.0;
            case Workflow.UNIT_SYSTEM_U2:
                return 1000;
            case Workflow.UNIT_SYSTEM_U3:
                return 1000;
            case Workflow.UNIT_SYSTEM_U4:
                return 1000;
            case Workflow.UNIT_SYSTEM_U5:
                return 3.28084;
            case Workflow.UNIT_SYSTEM_U6:
                return 1.0;

            default:
                return 1.0;
        }
    }

    /**
     * Returns a factor to divide a length value by to convert it from the given unit system to millimetres
     * (or multiply by to convert from millimetres to the given unit system)
     * @param {number} unit_system Workflow unit system, e.g. Workflow.UNIT_SYSTEM_U1
     * @returns {number}
     * @example
     * let mm = 1500;  // 1500mm
     * let f = WorkflowUnits.LengthToMillimetresFactor(Workflow.UNIT_SYSTEM_U2);
     * let metres = mm / f;  // metres = 1500 / 1000 = 1.5
     */
    static LengthToMillimetresFactor(unit_system) {
        switch (unit_system) {
            case Workflow.UNIT_SYSTEM_U1:
                return 0.001;
            case Workflow.UNIT_SYSTEM_U2:
                return 1.0;
            case Workflow.UNIT_SYSTEM_U3:
                return 1.0;
            case Workflow.UNIT_SYSTEM_U4:
                return 1.0;
            case Workflow.UNIT_SYSTEM_U5:
                return 0.00328084;
            case Workflow.UNIT_SYSTEM_U6:
                return 0.001;

            default:
                return 1.0;
        }
    }

    /**
     * Returns a factor to divide a mass value by to convert it from the given unit system to kilograms
     * (or multiply by to convert from kilograms to the given unit system)
     * @param {number} unit_system Workflow unit system, e.g. Workflow.UNIT_SYSTEM_U1
     * @returns {number}
     * @example
     * let tonne = 1.0;  // 1 tonne
     * let f = WorkflowUnits.MassToKilogramFactor(Workflow.UNIT_SYSTEM_U2);
     * let kg = tonne / f;  // kg = 1.0 / 0.001 = 1000
     */
    static MassToKilogramsFactor(unit_system) {
        switch (unit_system) {
            case Workflow.UNIT_SYSTEM_U1:
                return 1.0;
            case Workflow.UNIT_SYSTEM_U2:
                return 0.001;
            case Workflow.UNIT_SYSTEM_U3:
                return 1.0;
            case Workflow.UNIT_SYSTEM_U4:
                return 1000.0;
            case Workflow.UNIT_SYSTEM_U5:
                return 0.06852178;
            case Workflow.UNIT_SYSTEM_U6:
                return 0.001;

            default:
                return 1.0;
        }
    }

    /**
     * Returns a factor to divide a time value by to convert it from the given unit system to seconds
     * (or multiply by to convert from seconds to the given unit system)
     * @param {number} unit_system Workflow unit system, e.g. Workflow.UNIT_SYSTEM_U1
     * @returns {number}
     * @example
     * let ms = 1000;  // 1000ms
     * let f = WorkflowUnits.TimeToSecondsFactor(Workflow.UNIT_SYSTEM_U3);
     * let s = ms / f;  // s = 1000 / 1000 = 1.0
     */
    static TimeToSecondsFactor(unit_system) {
        switch (unit_system) {
            case Workflow.UNIT_SYSTEM_U1:
                return 1.0;
            case Workflow.UNIT_SYSTEM_U2:
                return 1.0;
            case Workflow.UNIT_SYSTEM_U3:
                return 1000.0;
            case Workflow.UNIT_SYSTEM_U4:
                return 1000.0;
            case Workflow.UNIT_SYSTEM_U5:
                return 1.0;
            case Workflow.UNIT_SYSTEM_U6:
                return 1.0;

            default:
                return 1.0;
        }
    }

    /**
     * Returns a factor to divide a force value by to convert it from the given unit system to kN
     * (or multiply by to convert from kN to the given unit system)
     * @param {number} unit_system Workflow unit system, e.g. Workflow.UNIT_SYSTEM_U1
     * @returns {number}
     * @example
     * let force = 1000.0;  // 1000 N
     * let f = WorkflowUnits.ForceToKiloNewtonFactor(Workflow.UNIT_SYSTEM_U1);
     * let kn = force / f;  // kn = 1000 / 1000 = 1
     */
    static ForceToKiloNewtonFactor(unit_system) {
        let mass_factor = WorkflowUnits.MassToKilogramsFactor(unit_system);
        let length_factor = WorkflowUnits.LengthToMetresFactor(unit_system);
        let time_factor = WorkflowUnits.TimeToSecondsFactor(unit_system);

        return 1000 * ((mass_factor * length_factor) / (time_factor * time_factor));
    }

    /**
     * Returns a factor to divide a moment value by to convert it from the given unit system to Nm
     * (or multiply by to convert from Nm to the given unit system)
     * @param {number} unit_system Workflow unit system, e.g. Workflow.UNIT_SYSTEM_U1
     * @returns {number}
     * @example
     * let moment = 1000.0;  // 1000 Nmm
     * let f = WorkflowUnits.MomentToNewtonMetreFactor(Workflow.UNIT_SYSTEM_U2);
     * let kNm = moment / f;  // Nm = 1000 / 1000 = 1
     */
    static MomentToNewtonMetreFactor(unit_system) {
        let mass_factor = WorkflowUnits.MassToKilogramsFactor(unit_system);
        let length_factor = WorkflowUnits.LengthToMetresFactor(unit_system);
        let time_factor = WorkflowUnits.TimeToSecondsFactor(unit_system);

        return (mass_factor * length_factor * length_factor) / (time_factor * time_factor);
    }

    /**
     * Return the gravity constant for the given unit system
     * @param {number} unit_system Workflow unit system, e.g. Workflow.UNIT_SYSTEM_U1
     * @returns {number}
     * @example
     * let g = WorkflowUnits.GravityConstant(Workflow.UNIT_SYSTEM_U1);
     */
    static GravityConstant(unit_system) {
        let length_factor = WorkflowUnits.LengthToMetresFactor(unit_system);
        let time_factor = WorkflowUnits.TimeToSecondsFactor(unit_system);

        return (9.81 * length_factor) / (time_factor * time_factor);
    }
}

class WorkflowUnitsCombobox {
    /**
     *
     * @param {Widget} combobox Combobox Widget to add items to
     * @example
     * let units_combobox = new WorkflowUnitsCombobox(combobox);
     */
    constructor(combobox) {
        this.combobox = combobox;

        this.u1 = new WidgetItem(this.combobox, "U1 (m,kg,s)");
        this.u2 = new WidgetItem(this.combobox, "U2 (mm,T,s)");
        this.u3 = new WidgetItem(this.combobox, "U3 (mm,kg,ms)");
        this.u4 = new WidgetItem(this.combobox, "U4 (mm,gm,ms)");
        this.u5 = new WidgetItem(this.combobox, "U5 (ft,slug,s)");
        this.u6 = new WidgetItem(this.combobox, "U6 (m,T,s)");
    }

    /**
     * Combobox
     * @type {Widget} */
    get combobox() {
        return this._combobox;
    }
    set combobox(new_combobox) {
        if (!(new_combobox instanceof Widget)) {
            throw new Error("combobox is not a Widget");
        }

        if (new_combobox.type != Widget.COMBOBOX) {
            throw new Error("combobox is not a Widget.COMBOBOX");
        }

        this._combobox = new_combobox;
    }

    /**
     * U1 WidgetItem
     * @type {WidgetItem} */
    get u1() {
        return this._u1;
    }
    set u1(new_u1) {
        if (!(new_u1 instanceof WidgetItem)) {
            throw new Error("u1 is not a WidgetItem");
        }

        this._u1 = new_u1;
    }

    /**
     * U2 WidgetItem
     * @type {WidgetItem} */
    get u2() {
        return this._u2;
    }
    set u2(new_u2) {
        if (!(new_u2 instanceof WidgetItem)) {
            throw new Error("u2 is not a WidgetItem");
        }

        this._u2 = new_u2;
    }

    /**
     * U3 WidgetItem
     * @type {WidgetItem} */
    get u3() {
        return this._u3;
    }
    set u3(new_u3) {
        if (!(new_u3 instanceof WidgetItem)) {
            throw new Error("u3 is not a WidgetItem");
        }

        this._u3 = new_u3;
    }

    /**
     * U4 WidgetItem
     * @type {WidgetItem} */
    get u4() {
        return this._u4;
    }
    set u4(new_u4) {
        if (!(new_u4 instanceof WidgetItem)) {
            throw new Error("u4 is not a WidgetItem");
        }

        this._u4 = new_u4;
    }

    /**
     * U5 WidgetItem
     * @type {WidgetItem} */
    get u5() {
        return this._u5;
    }
    set u5(new_u5) {
        if (!(new_u5 instanceof WidgetItem)) {
            throw new Error("u5 is not a WidgetItem");
        }

        this._u5 = new_u5;
    }

    /**
     * U6 WidgetItem
     * @type {WidgetItem} */
    get u6() {
        return this._u6;
    }
    set u6(new_u6) {
        if (!(new_u6 instanceof WidgetItem)) {
            throw new Error("u6 is not a WidgetItem");
        }

        this._u6 = new_u6;
    }

    /**
     * Set the selected widget item on the unit combobox
     * @param {number} unit_system Unit system, e.g. Workflow.UNIT_SYSTEM_U1
     * @example
     * let units_combobox = new WorkflowUnitsCombobox(combobox);
     *
     * units_combobox.SetSelectedUnitSystem(Workflow.UNIT_SYSTEM_U4);
     */
    SetSelectedUnitSystem(unit_system) {
        let selected_item = this.u1;

        switch (unit_system) {
            case Workflow.UNIT_SYSTEM_U1:
                selected_item = this.u1;
                break;
            case Workflow.UNIT_SYSTEM_U2:
                selected_item = this.u2;
                break;
            case Workflow.UNIT_SYSTEM_U3:
                selected_item = this.u3;
                break;
            case Workflow.UNIT_SYSTEM_U4:
                selected_item = this.u4;
                break;
            case Workflow.UNIT_SYSTEM_U5:
                selected_item = this.u5;
                break;
            case Workflow.UNIT_SYSTEM_U6:
                selected_item = this.u6;
                break;
            default:
                ErrorMessage(
                    `Unknown unit system: ${unit_system} in WorkflowUnitsCombobox.SetSelectedUnitSystem. Setting it to U1.`
                );
        }

        this.combobox.selectedItem = selected_item;
    }

    /**
     * Returns the selected unit system
     * @returns {number} Unit system, e.g. Workflow.UNIT_SYSTEM_U1
     * @example
     * let unit_system = units_combobox.GetSelectedUnitSystem();
     */
    GetSelectedUnitSystem() {
        let selected_item = this.combobox.selectedItem;

        if (selected_item == this.u1) {
            return Workflow.UNIT_SYSTEM_U1;
        } else if (selected_item == this.u2) {
            return Workflow.UNIT_SYSTEM_U2;
        } else if (selected_item == this.u3) {
            return Workflow.UNIT_SYSTEM_U3;
        } else if (selected_item == this.u4) {
            return Workflow.UNIT_SYSTEM_U4;
        } else if (selected_item == this.u5) {
            return Workflow.UNIT_SYSTEM_U5;
        } else if (selected_item == this.u6) {
            return Workflow.UNIT_SYSTEM_U6;
        } else {
            return Workflow.UNIT_SYSTEM_U1;
        }
    }
}