all files / js-range/ Range.js

100% Statements 33/33
100% Branches 21/21
100% Functions 4/4
100% Lines 33/33
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143                                                                                                                                                                                  200114× 200114×   200106×                                        
'use strict';
 
const util=require('util');
 
/**
 * Range Class
 */
class Range{
    /**
     * [constructor description]
     * @method constructor
     * @param  {Object}    range Object containing min max and step
     * @return {Range}          class to handle valid range and step for values
     */
    constructor(range){
        Object.defineProperties(
            this,
            {
                min:{
                    enumerable:true,
                    writable:true,
                    value:0
                },
                max:{
                    enumerable:true,
                    writable:true,
                    value:0
                },
                step:{
                    enumerable:true,
                    writable:true,
                    value:1e-2
                },
                stepNormalizer:{
                    enumerable:true,
                    writable:true,
                    value:1e10
                },
                isValid:{
                    enumerable:true,
                    writable:false,
                    value:checkValidValue
                },
                load:{
                    enumerable:true,
                    writable:false,
                    value:loadRange
                }
            }
        );
 
        if(range){
            this.load(range);
        }
 
        /**
         * converts an Object into a Range and checks validity
         * @method loadRange
         * @param  {Object}  range the range values
         * @return {Boolean}        success
         */
        function loadRange(range){
            let err;
            if(typeof range !== 'object' || Array.isArray(range)){
                err= new TypeError(
                    getTypeError({},range)
                );
                throw err;
            }
 
            if(typeof range.min !== 'number'){
                err= new TypeError(
                    getTypeError({},range.min,range)
                );
                throw err;
            }
 
            if(typeof range.max !== 'number'){
                err= new TypeError(
                    getTypeError({},range.max,range)
                );
                throw err;
            }
 
            if(typeof range.step !== 'number'){
                err= new TypeError(
                    getTypeError({},range.step,range)
                );
                throw err;
            }
 
            if(range.max<range.min){
                err= new TypeError(
                    `Expects min to be less than max
                        ${util.inspect(range,{depth:5, colors:true})}`
                );
                throw err;
            }
 
            this.min=range.min;
            this.max=range.max;
            this.step=range.step;
 
            return true;
        }
    }
}
 
/**
 * checks if value is valid for given range and step
 * @method checkValidValue
 * @param  {Number}        value proposed value
 * @return {Boolean}              value isValid
 */
function checkValidValue(value){
    let err;
    if(isNaN(value) || typeof value !== 'number'){
        return false;
    }
    return(
        value<=this.max
        && value>=this.min
        && (
            Math.round(value*this.stepNormalizer) - Math.round(this.min*this.stepNormalizer)
        ) % Math.round(this.step*this.stepNormalizer) == 0
    );
}
 
/**
 * [getTypeError description]
 * @method getTypeError
 * @param  {Any}     expects example expectation
 * @param  {Any}     value   offending value
 * @param  {Any}     from   offending values containing object
 * @return {String}             Error String
 */
function getTypeError(expects,value,from){
    return `Expects ${typeof expects} but got ${typeof value}
        ${util.inspect(from,{depth:5, colors:true})}`;
}
 
module.exports=Range;