1
0
Fork 0
liza/src/calc/Calc.js

655 lines
13 KiB
JavaScript

/**
* Contains calculation methods
*
* Copyright (C) 2017 R-T Specialty, LLC.
*
* This file is part of the Liza Data Collection Framework.
*
* liza is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
function _each( data, value, callback )
{
var data_len = data.length,
result = [],
cur_val = null;
for ( var i = 0; i < data_len; i++ )
{
cur_val = ( value[ i ] !== undefined ) ? value[ i ] : cur_val;
result.push( callback( data[ i ], cur_val, i ) );
}
return result;
}
exports.append = function( data, value )
{
return _each( data, value, function( arr1, arr2 )
{
if( !( arr1 instanceof Array ) )
{
arr1 = [ arr1 ];
}
return arr1.concat( arr2 );
});
};
exports.join = function( data, value )
{
return _each( data, value, function( arr, delimiter )
{
return arr.join( delimiter );
});
};
exports[ 'if' ] = function( data, value )
{
var result = [];
for ( var i = 0; i < data.length; i++ )
{
result.push( ( ( data[ i ] === "1" ) ? value[ i ] : '' ) );
}
return result;
};
exports.sum = function( data )
{
var data_len = data.length;
// calculate and return the sum
for ( var i = 0, sum = 0; i < data_len; sum += +data[i++] );
return [ sum ];
};
/**
* Return an object containing a range of elements
*
* @param data The first value of the sequence of numbers
* @param value The ending value of the sequence
*
* @example range( 1, 3 ) will yield [ "1", "2", "3" ]
* range( 5, 2 ) will yield [ "5", "4", "3", "2" ]
*/
exports.range = function( data, value )
{
var result = [],
range_from = data[ 0 ],
range_to = value[ 0 ],
low = Math.min( range_from, range_to ),
high = Math.max( range_from, range_to ),
index = 0;
for ( var i = low; i < high; i++ )
{
result[ index ] = ( ''+i );
index++;
}
return ( range_from < range_to )
? result
: result.reverse();
};
exports.length = function( data )
{
var result = [],
item = '',
i = 0;
while ( true )
{
item = data[ i++ ];
if ( ( item === null ) || ( item === undefined ) )
{
break;
}
result.push( item.length );
}
return result;
};
/**
* Return the number of elements in the set that optionally match the given
* value
*/
exports.count = function( data, value )
{
var len = data.length;
if ( !( value ) || value.length === 0 )
{
return [ ''+( len ) ];
}
var count = 0;
for ( var i = 0; i < len; i++ )
{
// intentional lazy cmp
if ( data[ i ] == value[ 0 ] )
{
count++;
}
}
return [ ''+( count ) ];
};
exports.countNonEmpty = function( data, value )
{
var count = 0;
for ( var i in data )
{
if ( data[ i ] !== '' )
{
count++;
}
}
return [ ''+count ];
};
exports.divide = function( data, value )
{
return _each( data, value, function( val1, val2 )
{
return ( +val1 / +val2 );
} );
};
exports.multiply = function( data, value )
{
return _each( data, value, function( val1, val2 )
{
return ( +val1 * +val2 );
} );
};
exports.add = function( data, value )
{
return _each( data, value, function( val1, val2 )
{
return ( +val1 + +val2 );
} );
};
exports.subtract = function( data, value )
{
return _each( data, value, function( val1, val2 )
{
return ( +val1 - +val2 );
} );
};
exports.date = function()
{
var now = new Date();
// return in the YYYY-MM-DD format, since that's what our fields are
// formatted as
return [
now.getFullYear() + '-'
+ ( now.getMonth() + 1 ) + '-'
+ now.getDate()
];
};
exports.userAgent = function()
{
return ( typeof window !== 'undefined' )
? [ window.navigator.userAgent ]
: [ '' ];
};
exports.relativeDate = function( data, value )
{
return _each( data, value, function( curdate, format )
{
var type = format.substr( -1 ),
tval = format.substr( 0, format.length - 1 ),
ms = 0;
var now = ( curdate ) ? new Date( curdate ) : new Date(),
now_year = now.getUTCFullYear(),
now_month = now.getUTCMonth() + 1,
now_day = now.getUTCDate(),
date_new = null;
switch ( type )
{
// years
case 'y':
date_new = new Date(
( now_year + +tval ) + '/' + now_month + '/' + now_day
);
break;
// months
case 'm':
date_new = new Date(
now_year + '/' + ( now_month + +tval ) + '/' + now_day
);
break;
// days
case 'd':
date_new = new Date(
now_year + '/' + now_month + '/' + ( now_day + +tval )
);
break;
// seconds
case 's':
date_new = new Date( now.getTime() + ( tval * 1000 ) );
break;
default:
return '';
}
// return in the YYYY-MM-DD format, since that's what our fields are
// formatted as
return date_new.getFullYear() + '-'
+ ( date_new.getMonth() + 1 ) + '-'
+ date_new.getDate();
} );
};
exports.copy = function( data )
{
return data;
};
exports.month = function( data )
{
// if no reference was provided, return the current month
if ( data.length === 0 )
{
return [ new Date().getMonth() + 1 ];
}
// otherwise, get the month from each of the provided dates
var len = data.length,
result = [];
for ( var i = 0; i < len; i++ )
{
result.push(
new Date(
Date.parse( data[i].replace( /-/g, '/' ) )
).getMonth() + 1
);
}
return result;
};
exports.year = function( data )
{
// if no reference was provided, return the current year
if ( data.length === 0 )
{
return [ new Date().getFullYear() ];
}
// otherwise, get the year from each of the provided dates
var len = data.length,
result = [];
for ( var i = 0; i < len; i++ )
{
if ( data[ i ] === '' )
{
result.push( new Date().getFullYear() );
continue;
}
result.push(
new Date(
Date.parse( data[i].replace( /-/g, '/' ) )
).getFullYear()
);
}
return result;
};
// tests if a value(s) exists in data
exports.isIn = function( data, value )
{
var all_values_found = false;
for ( var v_key = 0; v_key < value.length; v_key++ )
{
var value_found = false;
for ( var d_key = 0; d_key < data.length; d_key++ )
{
// check to see if this value has a match
if ( +value[ v_key ] === +data[ d_key ] )
{
value_found = true;
}
}
// all values sent in must have a match for isIn to be true
all_values_found = ( value_found )
? true
: all_values_found;
}
return ( all_values_found === true )
? [ '1' ]
: [ '0' ];
};
exports.identical = function( data, value )
{
// true if all values in data are the same
var len = data.length,
cmp_val = data[ 0 ];
for ( var i = 0; i < len; i++ )
{
// null indicates that the location is marked for deletion
if ( data[ i ] !== cmp_val && data[ i ] !== null )
{
// something doesn't match
return [ '0' ];
}
}
return [ '1' ];
};
exports.dateDiff = function( data, value )
{
var data_len = data.length,
result = [],
cmp_ts = 0;
for ( var i = 0; i < data_len; i++ )
{
// use the last available value for comparison
if ( value[i] )
{
// convert it to a timestamp
cmp_ts = ( Date.parse( value[i].replace( /-/g, '/' ) ) / 1000 );
}
// convert data to timestamp
var data_ts = ( Date.parse( data[i].replace( /-/g, '/' ) ) / 1000 );
// if the given date is higher than the comparison value, then a
// positive number will result, otherwise a negative
var diff = data_ts - cmp_ts;
result.push( isNaN( diff ) ? 0 : diff );
}
return result;
};
exports.split = function( data, value )
{
return _each( data, value, function( item, delim )
{
// split using the provided delimiter
return ( ( ''+( item ) ).split( delim ) );
});
};
exports.keyValue = function( data, value )
{
return _each( data, value, function( item, index )
{
if ( !( item instanceof Array ) )
{
return null;
}
// return requested index
return item[ index ];
});
};
exports.match = function( data, value )
{
return _each( data, value, function( item, regex )
{
return ( ( ''+item ).match( new RegExp( regex ) ) );
});
};
/**
* Return min numeric value in data set
*/
exports.min = function( data )
{
var min_val = +data[ 0 ],
i = data.length;
while ( i-- )
{
var cur_val = +data[ i ];
min_val = ( min_val < cur_val ) ? min_val : cur_val;
}
return [ ''+( min_val ) ];
};
/**
* Finds min numeric value in data set and
* returns its position
*/
exports.minPos = function( data )
{
var min_val = +data[ 0 ],
min_pos = 0;
for ( var i = 0; i < data.length; i++ )
{
var cur_val = +data[ i ];
if ( cur_val < min_val )
{
min_val = cur_val;
min_pos = i;
}
}
return [ ''+min_pos ];
};
/**
* Finds max numeric value in data set and
* returns its position
*/
exports.maxPos = function( data )
{
var max_val = +data[ 0 ],
max_pos = 0;
for ( var i = 0; i < data.length; i++ )
{
var cur_val = +data[ i ];
if ( cur_val > max_val )
{
max_val = cur_val;
max_pos = i;
}
}
return [ ''+max_pos ];
};
/**
* Return max numeric value in data set
*/
exports.max = function( data )
{
var max_val = +data[ 0 ],
i = data.length,
result = [];
while ( i-- )
{
var cur_val = +data[ i ];
max_val = ( max_val > cur_val ) ? max_val : cur_val;
}
return [ ''+( max_val ) ];
};
/**
* Return array of each unique element in the data set
*/
exports.uniq = function( data )
{
var found = {},
uniq = [],
i = data.length;
while ( i-- )
{
var val = data[ i ];
if ( found[ val ] )
{
continue;
}
found[ val ] = true;
uniq.push( val );
}
return uniq;
};
/**
* Join array of elements with a delimiter
*
* @param data The array of values to join
* @param value The delimiter
*
* @example implode( [ "foo", "bar" ], "," ) will yield [ "foo,bar" ]
*/
exports.implode = function( data, value )
{
return [ ( data.join( value || '' ) ) ];
};
/**
* Given a regular expression, returns '1' for positive test and '0' for
* negative.
*/
exports.test = function( data, value )
{
return _each( data, value, function( item, regex )
{
// return '1' for true, '0' for false
return ''+( +( ( new RegExp( regex ) ).test( item ) ) );
} );
};
/**
* Opposite of test
*/
exports.testNot = function( data, value )
{
return _each( data, value, function( item, regex )
{
// return '1' for true, '0' for false
return ''+( +( !( ( new RegExp( regex ) ).test( item ) ) ) );
} );
};
/**
* N-based index
*/
exports.position = function( data, value )
{
return _each( data, value, function( item, offset, i )
{
return +i + ( +offset || 0 );
} );
};
/**
* Given a set of indexes, return array of values
*/
exports.value = function( data, indexes )
{
var len = indexes.length,
values = [],
key = 0;
for ( var i = 0; i < len; i++ )
{
key = indexes[ i ];
if ( data[ key ] !== null )
{
// found a value
values.push( data[ key ] );
}
else
{
values.push( null );
}
}
return values;
};
exports[ 'void' ] = function()
{
return [];
};