Skip to content

Instantly share code, notes, and snippets.

@bogkyu
Created January 28, 2019 23:02

Revisions

  1. bogkyu created this gist Jan 28, 2019.
    406 changes: 406 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,406 @@
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>JS Bin</title>
    </head>
    <body>

    <script id="jsbin-javascript">
    //KJS HA5

    // function generator, returns list of
    // boolean (check ok) and
    // string (current type, used if boolean were false)
    'use strict';

    var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })();

    var checktemplate = function checktemplate(ss) {
    return function (v) {
    return [typeof v == ss, typeof v, ss];
    };
    };
    var checkNumber = checktemplate('number'); // doesn't sense Nan-s
    var checkString = checktemplate('string');

    /*
    // TEST BED #1 see results from checking types
    [
    'string', 4, {}, '', undefined, NaN, true, [],
    ].forEach(x => {
    console.log(x + ': ' + checkString(x));
    console.log(x + ': ' + checkString(x));
    });
    */

    // declared order is important, strictly from largest to smallest
    var VALID_UNITS = ["day", "hour", "minute", "second"];

    // pure fun :)
    function checkPlurals(val, lab) {
    var startstop = ['^', '$'];
    var grouping = ['(', ')'];
    var re = new RegExp(startstop.join(grouping.join(VALID_UNITS.join("|")) + (Math.abs(val) == 1 ? "" : "s")));
    return re.exec(lab) == null ? [val, lab] : null;
    }
    /*
    // TEST BED #2 see results from checking types
    [
    [3, 'minutes'],
    [1, 'year'],
    [1, 'second'],
    [44, 'hours'],
    [44, 'hour'],
    ].forEach(([x, s]) => {
    console.log(x + ' ' + s + ": " + (checkPlurals(x, s) == null ? "OK" : "FAILED"));
    });
    */

    function checkTypes(val1, lab1, val2, lab2) {
    var error = '';
    [[val1, checkNumber], [lab1, checkString], [val2, checkNumber], [lab2, checkString]].forEach(function (_ref) {
    var _ref2 = _slicedToArray(_ref, 2);

    var v = _ref2[0];
    var f = _ref2[1];

    var _f = f(v);

    var _f2 = _slicedToArray(_f, 3);

    var isOk = _f2[0];
    var actualType = _f2[1];
    var requiredType = _f2[2];

    if (!isOk) {
    error += (error ? '\n' : '') + ' wrong type for value: ' + v + ', found ' + actualType + ', required ' + requiredType;
    }
    return error;
    });
    }
    /*
    // TEST BED #3 checkTypes
    [
    [[3, 'seconds', 5, 'minutes'], true],
    [[4555, 'second', 423, 'sedconde'], true],
    [[{}, 'seconds', 5, null], false],
    [[3,4,5,6], false],
    [['3','4','5','6'], false],
    ].forEach(([params, rightResult]) => {
    const [ v1, l1, v2, l2] = params;
    const realResult = checkTypes(v1, l1, v2, l2) == null ;
    console.log((realResult === rightResult ? "OK " : "FAILED" ) + ' testing value set:' + JSON.stringify(params));
    });
    */

    // HA5 Time adder.
    // Takes four mandatory parameters, grouped by pairs of time
    // descrpitors to be added, explained as below:
    // val1, val2 - the amounts of time
    // lab1, lab2 - the time units
    // time unit should be one of the following strings:
    // "seconds", "minutes", "hours", "days", "second", "minute", "hour", "day"
    // return value is the time we got by adding the two parameters, maintaining
    // or false if wrong parameters
    // extra credit for returning the largest label that can be used with
    // an integer value
    function timeAdder(val1, lab1, val2, lab2) {
    var retval = false;
    var error = checkTypes(val1, lab1, val2, lab2) || checkPlurals(val1, lab1) || checkPlurals(val2, lab2);

    if (!error) {
    // calculus and result
    var time1 = normalize(val1, lab1);
    var time2 = normalize(val2, lab2);
    var timef = time1 + time2;
    for (x in VALID_UNITS) {
    var unit = VALID_UNITS[x];
    var mult = multiplier(VALID_UNITS[x]);

    if (timef % mult === 0) {
    var newval = timef / multiplier(unit);
    retval = [newval, unit + (Math.abs(newval) === 1 ? "" : "s")];
    break;
    }
    }
    } else {
    console.log("Error: unexpected or incorrect parameters: " + error);
    }

    return retval;
    }

    // get the normalized (_in seconds_) time value
    function normalize(val, lab) {
    return val * multiplier(lab);
    }

    // returns the multiplier to seconds
    // Pirple require a switch statement
    // otherwise I would have implemented the functionality
    // augmenting the VALID_UNITS
    function multiplier(lab) {
    switch (lab) {

    case 'day':
    case 'days':
    return 60 * 60 * 24;

    case 'hour':
    case 'hours':
    return 60 * 60;

    case 'minute':
    case 'minutes':
    return 60;

    // assumes default seconds
    default:
    return 1;
    }
    }

    // TEST BED #4
    [[[23, 'minutes', 1, 'minute'], [24, 'minutes']], [[23, 'hours', 1, 'hour'], [1, 'day']], [[59, 'minutes', 2, 'minutes'], [61, 'minutes']], [[59, 'minutes', 2, 'seconds'], [3542, 'seconds']], [[3, 'days', 1, 'hour'], [73, 'hours']], [[0, 'hours', 0, 'hours'], [0, 'days']], [[23, 'seconds', -1, 'minute'], [-37, 'seconds']], [[23, 'second', -1, 'minute'], [-37, 'seconds']], // illustrates a failed test
    [[23, {}, -1, 'minute'], [-37, 'seconds']]]. // illustrates a failed test
    forEach(function (_ref3) {
    var _ref32 = _slicedToArray(_ref3, 2);

    var param = _ref32[0];
    var expectedResult = _ref32[1];

    function formatOutput(result, val1, lab1, val2, lab2, valf, labf) {
    var eqop = result ? '===' : '!==';
    return val1 + ' ' + lab1 + ' + ' + val2 + ' ' + lab2 + ' ' + eqop + ' ' + valf + ' ' + labf;
    }

    var _param = _slicedToArray(param, 4);

    var val1 = _param[0];
    var lab1 = _param[1];
    var val2 = _param[2];
    var lab2 = _param[3];

    var actualResult = timeAdder(val1, lab1, val2, lab2);
    if (actualResult) {
    var _actualResult = _slicedToArray(actualResult, 2);

    var actval = _actualResult[0];
    var actlab = _actualResult[1];

    var _expectedResult = _slicedToArray(expectedResult, 2);

    var expval = _expectedResult[0];
    var explab = _expectedResult[1];

    var testOK = actval === expval && actlab == explab;
    console.log("TEST " + (testOK ? 'OK: ' : 'FAILED:') + formatOutput(true, val1, lab1, val2, lab2, expval, explab));
    } else {
    console.log("TEST FAILED: incorrect input values");
    }
    });
    </script>



    <script id="jsbin-source-javascript" type="text/javascript">//KJS HA5


    // function generator, returns list of
    // boolean (check ok) and
    // string (current type, used if boolean were false)
    let checktemplate = ss => (v) => [typeof v == ss, typeof v, ss];
    let checkNumber = checktemplate('number'); // doesn't sense Nan-s
    let checkString = checktemplate('string');

    /*
    // TEST BED #1 see results from checking types
    [
    'string', 4, {}, '', undefined, NaN, true, [],
    ].forEach(x => {
    console.log(x + ': ' + checkString(x));
    console.log(x + ': ' + checkString(x));
    });
    */

    // declared order is important, strictly from largest to smallest
    const VALID_UNITS = [
    "day",
    "hour",
    "minute",
    "second",
    ];

    // pure fun :)
    function checkPlurals(val, lab) {
    const startstop = ['^', '$'];
    const grouping = ['(', ')'];
    const re = new RegExp(
    startstop.join(
    grouping.join(
    VALID_UNITS.join("|")
    )
    + (Math.abs(val) == 1 ? "" : "s")
    )
    );
    return re.exec(lab) == null ? [val, lab] : null;
    }
    /*
    // TEST BED #2 see results from checking types
    [
    [3, 'minutes'],
    [1, 'year'],
    [1, 'second'],
    [44, 'hours'],
    [44, 'hour'],
    ].forEach(([x, s]) => {
    console.log(x + ' ' + s + ": " + (checkPlurals(x, s) == null ? "OK" : "FAILED"));
    });
    */

    function checkTypes(val1, lab1, val2, lab2) {
    let error = '' ;
    [[val1, checkNumber],
    [lab1, checkString],
    [val2, checkNumber],
    [lab2, checkString],
    ].forEach(([v, f]) => {
    const [isOk, actualType, requiredType] = f(v);
    if( ! isOk ) {
    error += (error ? '\n' : '' )
    + ' wrong type for value: ' + v
    + ', found ' + actualType
    + ', required ' + requiredType;
    }
    return error;
    });
    }
    /*
    // TEST BED #3 checkTypes
    [
    [[3, 'seconds', 5, 'minutes'], true],
    [[4555, 'second', 423, 'sedconde'], true],
    [[{}, 'seconds', 5, null], false],
    [[3,4,5,6], false],
    [['3','4','5','6'], false],
    ].forEach(([params, rightResult]) => {
    const [ v1, l1, v2, l2] = params;
    const realResult = checkTypes(v1, l1, v2, l2) == null ;
    console.log((realResult === rightResult ? "OK " : "FAILED" ) + ' testing value set:' + JSON.stringify(params));
    });
    */


    // HA5 Time adder.
    // Takes four mandatory parameters, grouped by pairs of time
    // descrpitors to be added, explained as below:
    // val1, val2 - the amounts of time
    // lab1, lab2 - the time units
    // time unit should be one of the following strings:
    // "seconds", "minutes", "hours", "days", "second", "minute", "hour", "day"
    // return value is the time we got by adding the two parameters, maintaining
    // or false if wrong parameters
    // extra credit for returning the largest label that can be used with
    // an integer value
    function timeAdder(val1, lab1, val2, lab2){
    let retval = false;
    let error =
    checkTypes(val1, lab1, val2, lab2)
    || checkPlurals(val1, lab1)
    || checkPlurals(val2, lab2) ;

    if( !error ) {
    // calculus and result
    let time1 = normalize(val1, lab1);
    let time2 = normalize(val2, lab2);
    let timef = time1 + time2;
    for( x in VALID_UNITS) {
    let [unit, mult] = [VALID_UNITS[x], multiplier(VALID_UNITS[x])] ;
    if( timef % mult === 0 ) {
    const newval = timef / multiplier(unit);
    retval = [newval, unit + (Math.abs(newval) === 1 ? "" : "s") ];
    break;
    }
    }

    } else {
    console.log("Error: unexpected or incorrect parameters: " + error);
    }

    return retval;
    }

    // get the normalized (_in seconds_) time value
    function normalize(val, lab) {
    return val * multiplier(lab);
    }

    // returns the multiplier to seconds
    // Pirple require a switch statement
    // otherwise I would have implemented the functionality
    // augmenting the VALID_UNITS
    function multiplier(lab) {
    switch(lab) {

    case 'day':
    case 'days':
    return 60 * 60 * 24 ;

    case 'hour':
    case 'hours':
    return 60 * 60;

    case 'minute':
    case 'minutes':
    return 60;

    // assumes default seconds
    default:
    return 1;
    }
    }

    // TEST BED #4
    [
    [[23, 'minutes', 1, 'minute'], [24, 'minutes']],
    [[23, 'hours', 1, 'hour' ], [ 1, 'day']],
    [[59, 'minutes', 2, 'minutes'], [61, 'minutes']],
    [[59, 'minutes', 2, 'seconds'], [3542, 'seconds']],
    [[ 3, 'days', 1, 'hour'], [73, 'hours']],
    [[ 0, 'hours', 0, 'hours'], [0, 'days']],
    [[23, 'seconds',-1, 'minute'], [-37, 'seconds']],
    [[23, 'second',-1, 'minute'], [-37, 'seconds']], // illustrates a failed test
    [[23, {}, -1, 'minute'], [-37, 'seconds']], // illustrates a failed test
    ].forEach( ([param, expectedResult]) => {
    function formatOutput(result, val1, lab1, val2, lab2, valf, labf) {
    const eqop = result ? '===' : '!==';
    return val1 + ' ' + lab1
    + ' + ' + val2 + ' ' + lab2
    + ' ' + eqop
    + ' ' + valf + ' ' + labf;
    }
    const [val1, lab1, val2, lab2] = param;
    const actualResult = timeAdder(val1, lab1, val2, lab2);
    if( actualResult ) {
    const [actval, actlab] = actualResult;
    const [expval, explab] = expectedResult;
    const testOK = actval === expval && actlab == explab;
    console.log("TEST " + (testOK ? 'OK: ' : 'FAILED:')
    + formatOutput(true, val1, lab1, val2, lab2, expval, explab) );
    } else {
    console.log("TEST FAILED: incorrect input values");
    }
    });







    </script></body>
    </html>
    194 changes: 194 additions & 0 deletions jsbin.wihuhoc.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,194 @@
    //KJS HA5

    // function generator, returns list of
    // boolean (check ok) and
    // string (current type, used if boolean were false)
    'use strict';

    var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })();

    var checktemplate = function checktemplate(ss) {
    return function (v) {
    return [typeof v == ss, typeof v, ss];
    };
    };
    var checkNumber = checktemplate('number'); // doesn't sense Nan-s
    var checkString = checktemplate('string');

    /*
    // TEST BED #1 see results from checking types
    [
    'string', 4, {}, '', undefined, NaN, true, [],
    ].forEach(x => {
    console.log(x + ': ' + checkString(x));
    console.log(x + ': ' + checkString(x));
    });
    */

    // declared order is important, strictly from largest to smallest
    var VALID_UNITS = ["day", "hour", "minute", "second"];

    // pure fun :)
    function checkPlurals(val, lab) {
    var startstop = ['^', '$'];
    var grouping = ['(', ')'];
    var re = new RegExp(startstop.join(grouping.join(VALID_UNITS.join("|")) + (Math.abs(val) == 1 ? "" : "s")));
    return re.exec(lab) == null ? [val, lab] : null;
    }
    /*
    // TEST BED #2 see results from checking types
    [
    [3, 'minutes'],
    [1, 'year'],
    [1, 'second'],
    [44, 'hours'],
    [44, 'hour'],
    ].forEach(([x, s]) => {
    console.log(x + ' ' + s + ": " + (checkPlurals(x, s) == null ? "OK" : "FAILED"));
    });
    */

    function checkTypes(val1, lab1, val2, lab2) {
    var error = '';
    [[val1, checkNumber], [lab1, checkString], [val2, checkNumber], [lab2, checkString]].forEach(function (_ref) {
    var _ref2 = _slicedToArray(_ref, 2);

    var v = _ref2[0];
    var f = _ref2[1];

    var _f = f(v);

    var _f2 = _slicedToArray(_f, 3);

    var isOk = _f2[0];
    var actualType = _f2[1];
    var requiredType = _f2[2];

    if (!isOk) {
    error += (error ? '\n' : '') + ' wrong type for value: ' + v + ', found ' + actualType + ', required ' + requiredType;
    }
    return error;
    });
    }
    /*
    // TEST BED #3 checkTypes
    [
    [[3, 'seconds', 5, 'minutes'], true],
    [[4555, 'second', 423, 'sedconde'], true],
    [[{}, 'seconds', 5, null], false],
    [[3,4,5,6], false],
    [['3','4','5','6'], false],
    ].forEach(([params, rightResult]) => {
    const [ v1, l1, v2, l2] = params;
    const realResult = checkTypes(v1, l1, v2, l2) == null ;
    console.log((realResult === rightResult ? "OK " : "FAILED" ) + ' testing value set:' + JSON.stringify(params));
    });
    */

    // HA5 Time adder.
    // Takes four mandatory parameters, grouped by pairs of time
    // descrpitors to be added, explained as below:
    // val1, val2 - the amounts of time
    // lab1, lab2 - the time units
    // time unit should be one of the following strings:
    // "seconds", "minutes", "hours", "days", "second", "minute", "hour", "day"
    // return value is the time we got by adding the two parameters, maintaining
    // or false if wrong parameters
    // extra credit for returning the largest label that can be used with
    // an integer value
    function timeAdder(val1, lab1, val2, lab2) {
    var retval = false;
    var error = checkTypes(val1, lab1, val2, lab2) || checkPlurals(val1, lab1) || checkPlurals(val2, lab2);

    if (!error) {
    // calculus and result
    var time1 = normalize(val1, lab1);
    var time2 = normalize(val2, lab2);
    var timef = time1 + time2;
    for (x in VALID_UNITS) {
    var unit = VALID_UNITS[x];
    var mult = multiplier(VALID_UNITS[x]);

    if (timef % mult === 0) {
    var newval = timef / multiplier(unit);
    retval = [newval, unit + (Math.abs(newval) === 1 ? "" : "s")];
    break;
    }
    }
    } else {
    console.log("Error: unexpected or incorrect parameters: " + error);
    }

    return retval;
    }

    // get the normalized (_in seconds_) time value
    function normalize(val, lab) {
    return val * multiplier(lab);
    }

    // returns the multiplier to seconds
    // Pirple require a switch statement
    // otherwise I would have implemented the functionality
    // augmenting the VALID_UNITS
    function multiplier(lab) {
    switch (lab) {

    case 'day':
    case 'days':
    return 60 * 60 * 24;

    case 'hour':
    case 'hours':
    return 60 * 60;

    case 'minute':
    case 'minutes':
    return 60;

    // assumes default seconds
    default:
    return 1;
    }
    }

    // TEST BED #4
    [[[23, 'minutes', 1, 'minute'], [24, 'minutes']], [[23, 'hours', 1, 'hour'], [1, 'day']], [[59, 'minutes', 2, 'minutes'], [61, 'minutes']], [[59, 'minutes', 2, 'seconds'], [3542, 'seconds']], [[3, 'days', 1, 'hour'], [73, 'hours']], [[0, 'hours', 0, 'hours'], [0, 'days']], [[23, 'seconds', -1, 'minute'], [-37, 'seconds']], [[23, 'second', -1, 'minute'], [-37, 'seconds']], // illustrates a failed test
    [[23, {}, -1, 'minute'], [-37, 'seconds']]]. // illustrates a failed test
    forEach(function (_ref3) {
    var _ref32 = _slicedToArray(_ref3, 2);

    var param = _ref32[0];
    var expectedResult = _ref32[1];

    function formatOutput(result, val1, lab1, val2, lab2, valf, labf) {
    var eqop = result ? '===' : '!==';
    return val1 + ' ' + lab1 + ' + ' + val2 + ' ' + lab2 + ' ' + eqop + ' ' + valf + ' ' + labf;
    }

    var _param = _slicedToArray(param, 4);

    var val1 = _param[0];
    var lab1 = _param[1];
    var val2 = _param[2];
    var lab2 = _param[3];

    var actualResult = timeAdder(val1, lab1, val2, lab2);
    if (actualResult) {
    var _actualResult = _slicedToArray(actualResult, 2);

    var actval = _actualResult[0];
    var actlab = _actualResult[1];

    var _expectedResult = _slicedToArray(expectedResult, 2);

    var expval = _expectedResult[0];
    var explab = _expectedResult[1];

    var testOK = actval === expval && actlab == explab;
    console.log("TEST " + (testOK ? 'OK: ' : 'FAILED:') + formatOutput(true, val1, lab1, val2, lab2, expval, explab));
    } else {
    console.log("TEST FAILED: incorrect input values");
    }
    });