<commit_before>var m = require('mithril');
var k = Mousetrap;
var merge = require('merge');
var last = require('lodash/array/last');
var chessground = require('chessground');
var partial = chessground.util.partial;
var data = require('./data');
var chess = require('./chess');
var puzzle = require('./puzzle');
var xhr = require('./xhr');

module.exports = function(cfg, router, i18n) {

  this.vm = {
    loading: false
  };

  this.data = data(cfg);

  var userMove = function(orig, dest) {
    var res = puzzle.tryMove(this.data, [orig, dest]);
    var newProgress = res[0];
    var newLines = res[1];
    var lastMove = last(newProgress);
    var promotion = lastMove ? lastMove[4] : undefined;
    m.startComputation();
    switch (newLines) {
      case 'retry':
        setTimeout(partial(this.revert, this.data.puzzle.id), 500);
        this.data.comment = 'retry';
        break;
      case 'fail':
        setTimeout(function() {
          if (this.data.mode == 'play') {
            this.chessground.stop();
            xhr.attempt(this, false);
          } else this.revert(this.data.puzzle.id);
        }.bind(this), 500);
        this.data.comment = 'fail';
        break;
      default:
        this.userFinalizeMove([orig, dest, promotion], newProgress);
        if (newLines == 'win') {
          this.chessground.stop();
          xhr.attempt(this, true);
        } else setTimeout(partial(this.playOpponentNextMove, this.data.puzzle.id), 1000);
        break;
    }
    m.endComputation(); // give feedback ASAP, don't wait for delayed action
  }.bind(this);

  var onMove = function(orig, dest, captured) {
    if (captured) {
      $.sound.capture();
    } else $.sound.move();
  }.bind(this);

  this.revert = function(id) {
    if (id != this.data.puzzle.id) return;
    this.chessground.set({
      fen: this.data.chess.fen(),
      lastMove: chess.lastMove(this.data.chess),
      turnColor: this.data.puzzle.color,
      check: null,
      movable: {
        dests: this.data.chess.dests()
      }
    });
    m.redraw();
    if (this.data.chess.in_check()) this.chessground.setCheck();
  }.bind(this);

  this.userFinalizeMove = function(move, newProgress) {
    chess.move(this.data.chess, move);
    this.data.comment = 'great';
    this.data.progress = newProgress;
    this.chessground.set({
      fen: this.data.chess.fen(),
      lastMove: move,
      turnColor: this.data.puzzle.opponentColor,
      check: null
    });
    if (this.data.chess.in_check()) this.chessground.setCheck();
  }.bind(this);

  this.chessground = new chessground.controller(merge.recursive({
    fen: cfg.puzzle.fen,
    orientation: this.data.puzzle.color,
    turnColor: this.data.puzzle.opponentColor,
    movable: {
      free: false,
      color: cfg.mode !== 'view' ? cfg.puzzle.color : null,
      events: {
        after: userMove
      },
    },
    events: {
      move: onMove
    },
    animation: {
      enabled: true,
      duration: this.data.animation.duration
    },
    premovable: {
      enabled: true
    },
    drawable: {
      enabled: true
    },
    disableContextMenu: true
  }, this.data.chessground));

  k.bind(['esc'], this.chessground.cancelMove);

  this.initiate = function() {
    if (this.data.mode !== 'view')
      setTimeout(partial(this.playInitialMove, this.data.puzzle.id), 1000);
  }.bind(this);

  this.reload = function(cfg) {
    this.vm.loading = false;
    this.data = data(cfg);
    chessground.board.reset(this.chessground.data);
    chessground.anim(puzzle.reload, this.chessground.data)(this.data, cfg);
    this.initiate();
  }.bind(this);

  this.pushState = function(cfg) {
    if (window.history.pushState)
      window.history.pushState(cfg, null, router.Puzzle.show(cfg.puzzle.id).url);
  }.bind(this);

  window.onpopstate = function(cfg) {
    if (cfg.state) this.reload(cfg.state);
    m.redraw();
  }.bind(this);

  this.playOpponentMove = function(move) {
    onMove(move[0], move[1], this.chessground.data.pieces[move[1]]);
    m.startComputation();
    chess.move(this.data.chess, move);
    this.chessground.set({
      fen: this.data.chess.fen(),
      lastMove: move,
      movable: {
        dests: this.data.chess.dests()
      },
      turnColor: this.data.puzzle.color,
      check: null
    });
    if (this.data.chess.in_check()) this.chessground.setCheck();
    setTimeout(this.chessground.playPremove, this.chessground.data.animation.duration);
    m.endComputation();
  }.bind(this);

  this.playOpponentNextMove = function(id) {
    if (id != this.data.puzzle.id) return;
    var move = puzzle.getOpponentNextMove(this.data);
    this.playOpponentMove(puzzle.str2move(move));
    this.data.progress.push(move);
    if (puzzle.getCurrentLines(this.data) == 'win') xhr.attempt(this, true);
  }.bind(this);

  this.playInitialMove = function(id) {
    if (id != this.data.puzzle.id) return;
    this.playOpponentMove(this.data.puzzle.initialMove);
    this.data.startedAt = new Date();
  }.bind(this);

  this.jump = function(to) {
    chessground.anim(puzzle.jump, this.chessground.data)(this.data, to);
  }.bind(this);

  this.router = router;

  this.trans = function(key) {
    var str = i18n[key] || key;
    Array.prototype.slice.call(arguments, 1).forEach(function(arg) {
      str = str.replace('%s', arg);
    });
    return str;
  };
};
<commit_msg>add sounds to puzzle replay<commit_after>var m = require('mithril');
var k = Mousetrap;
var merge = require('merge');
var last = require('lodash/array/last');
var chessground = require('chessground');
var partial = chessground.util.partial;
var data = require('./data');
var chess = require('./chess');
var puzzle = require('./puzzle');
var xhr = require('./xhr');

module.exports = function(cfg, router, i18n) {

  this.vm = {
    loading: false
  };

  this.data = data(cfg);

  var userMove = function(orig, dest) {
    var res = puzzle.tryMove(this.data, [orig, dest]);
    var newProgress = res[0];
    var newLines = res[1];
    var lastMove = last(newProgress);
    var promotion = lastMove ? lastMove[4] : undefined;
    m.startComputation();
    switch (newLines) {
      case 'retry':
        setTimeout(partial(this.revert, this.data.puzzle.id), 500);
        this.data.comment = 'retry';
        break;
      case 'fail':
        setTimeout(function() {
          if (this.data.mode == 'play') {
            this.chessground.stop();
            xhr.attempt(this, false);
          } else this.revert(this.data.puzzle.id);
        }.bind(this), 500);
        this.data.comment = 'fail';
        break;
      default:
        this.userFinalizeMove([orig, dest, promotion], newProgress);
        if (newLines == 'win') {
          this.chessground.stop();
          xhr.attempt(this, true);
        } else setTimeout(partial(this.playOpponentNextMove, this.data.puzzle.id), 1000);
        break;
    }
    m.endComputation(); // give feedback ASAP, don't wait for delayed action
  }.bind(this);

  var onMove = function(orig, dest, captured) {
    $.sound[captured ? 'capture' : 'move']();
  }.bind(this);

  this.revert = function(id) {
    if (id != this.data.puzzle.id) return;
    this.chessground.set({
      fen: this.data.chess.fen(),
      lastMove: chess.lastMove(this.data.chess),
      turnColor: this.data.puzzle.color,
      check: null,
      movable: {
        dests: this.data.chess.dests()
      }
    });
    m.redraw();
    if (this.data.chess.in_check()) this.chessground.setCheck();
  }.bind(this);

  this.userFinalizeMove = function(move, newProgress) {
    chess.move(this.data.chess, move);
    this.data.comment = 'great';
    this.data.progress = newProgress;
    this.chessground.set({
      fen: this.data.chess.fen(),
      lastMove: move,
      turnColor: this.data.puzzle.opponentColor,
      check: null
    });
    if (this.data.chess.in_check()) this.chessground.setCheck();
  }.bind(this);

  this.chessground = new chessground.controller(merge.recursive({
    fen: cfg.puzzle.fen,
    orientation: this.data.puzzle.color,
    turnColor: this.data.puzzle.opponentColor,
    movable: {
      free: false,
      color: cfg.mode !== 'view' ? cfg.puzzle.color : null,
      events: {
        after: userMove
      },
    },
    events: {
      move: onMove
    },
    animation: {
      enabled: true,
      duration: this.data.animation.duration
    },
    premovable: {
      enabled: true
    },
    drawable: {
      enabled: true
    },
    disableContextMenu: true
  }, this.data.chessground));

  k.bind(['esc'], this.chessground.cancelMove);

  this.initiate = function() {
    if (this.data.mode !== 'view')
      setTimeout(partial(this.playInitialMove, this.data.puzzle.id), 1000);
  }.bind(this);

  this.reload = function(cfg) {
    this.vm.loading = false;
    this.data = data(cfg);
    chessground.board.reset(this.chessground.data);
    chessground.anim(puzzle.reload, this.chessground.data)(this.data, cfg);
    this.initiate();
  }.bind(this);

  this.pushState = function(cfg) {
    if (window.history.pushState)
      window.history.pushState(cfg, null, router.Puzzle.show(cfg.puzzle.id).url);
  }.bind(this);

  window.onpopstate = function(cfg) {
    if (cfg.state) this.reload(cfg.state);
    m.redraw();
  }.bind(this);

  this.playOpponentMove = function(move) {
    onMove(move[0], move[1], this.chessground.data.pieces[move[1]]);
    m.startComputation();
    chess.move(this.data.chess, move);
    this.chessground.set({
      fen: this.data.chess.fen(),
      lastMove: move,
      movable: {
        dests: this.data.chess.dests()
      },
      turnColor: this.data.puzzle.color,
      check: null
    });
    if (this.data.chess.in_check()) this.chessground.setCheck();
    setTimeout(this.chessground.playPremove, this.chessground.data.animation.duration);
    m.endComputation();
  }.bind(this);

  this.playOpponentNextMove = function(id) {
    if (id != this.data.puzzle.id) return;
    var move = puzzle.getOpponentNextMove(this.data);
    this.playOpponentMove(puzzle.str2move(move));
    this.data.progress.push(move);
    if (puzzle.getCurrentLines(this.data) == 'win') xhr.attempt(this, true);
  }.bind(this);

  this.playInitialMove = function(id) {
    if (id != this.data.puzzle.id) return;
    this.playOpponentMove(this.data.puzzle.initialMove);
    this.data.startedAt = new Date();
  }.bind(this);

  this.jump = function(to) {
    chessground.anim(puzzle.jump, this.chessground.data)(this.data, to);
    $.sound.move();
  }.bind(this);

  this.router = router;

  this.trans = function(key) {
    var str = i18n[key] || key;
    Array.prototype.slice.call(arguments, 1).forEach(function(arg) {
      str = str.replace('%s', arg);
    });
    return str;
  };
};
<|endoftext|>


<commit_before>/**
* selection index form, calculation and presentation
* @author Isaak Y Tecle <iyt2@cornell.edu>
*
*/

JSAN.use('jquery.blockUI');

jQuery(document).ready( function () {
        listSelectionIndexPopulations();
});

jQuery("#rank_genotypes").live("click", function() {
    var modelId        = jQuery("#model_id").val();
    var selectionPopId = jQuery("#selected_population_id").val();
    var popType        = jQuery("#selected_population_type").val();

    selectionIndex(modelId, selectionPopId);
});

function listSelectionIndexPopulations ()  {

    var modelData = getTrainingPopulationData();
    var trainingPopIdName = JSON.stringify(modelData);

    var  popsList =  '
'
        + '
 Choose a population
'
        + '
'
        + '
'
        + '
'
        + '' + modelData.name + '' + trainingPopIdName + ''
        + '
';

    popsList += '

';

    jQuery("#select_a_population_div").empty().append(popsList).show();

    var dbSelPopsList;
    if( modelData.id.match(/uploaded/) == null) {
        dbSelPopsList = addSelectionPopulations();
    }

    if (dbSelPopsList) {
            jQuery("#select_a_population_div ul").append(dbSelPopsList);
    }

    var userUploadedSelExists = jQuery("#uploaded_selection_pops_table").doesExist();
    if( userUploadedSelExists == true) {
        var userSelPops = listUploadedSelPopulations();
        if (userSelPops) {

            jQuery("#select_a_population_div ul").append(userSelPops);
        }
    }

    getSelectionPopTraits(modelData.id, modelData.id);

   jQuery(".si_dropdown dt a").click(function() {
            jQuery(".si_dropdown dd ul").toggle();
        });

    jQuery(".si_dropdown dd ul li a").click(function() {

        var text = jQuery(this).html();

        jQuery(".si_dropdown dt a span").html(text);
        jQuery(".si_dropdown dd ul").hide();

        var idPopName = jQuery("#selected_population").find("dt a span.value").html();
        idPopName     = JSON.parse(idPopName);
        modelId = jQuery("#model_id").val();

        selectedPopId   = idPopName.id;
        selectedPopName = idPopName.name;
        selectedPopType = idPopName.pop_type;

        jQuery("#selected_population_name").val(selectedPopName);
        jQuery("#selected_population_id").val(selectedPopId);
        jQuery("#selected_population_type").val(selectedPopType);

        getSelectionPopTraits(modelId, selectedPopId);

    });

    jQuery(".si_dropdown").bind('click', function(e) {
        var clicked = jQuery(e.target);

        if (! clicked.parents().hasClass("si_dropdown"))
            jQuery(".si_dropdown dd ul").hide();

        e.preventDefault();
    });
}

function addSelectionPopulations(){

    var selPopsTable = jQuery("#selection_populations table").html();
    var selPopsRows  = jQuery(selPopsTable).find("tr");

    var predictedPop = [];
    var popsList = '';

    for (var i = 1; i < selPopsRows.length; i++) {
        var row    = selPopsRows[i];
        var popRow = row.innerHTML;

        predictedPop = popRow.match(/\/solgs\/selection\//g);

        if (predictedPop) {
            if (predictedPop.length > 1) {
                var selPopsInput  = row.getElementsByTagName("input")[0];
                var idPopName     = selPopsInput.value;
                var idPopNameCopy = idPopName;
                idPopNameCopy     = JSON.parse(idPopNameCopy);
                var popName       = idPopNameCopy.name;

                popsList += '
'
                    + '' + popName + '' + idPopName + ''
                    + '
';
            }
        }
    }

    return popsList;
}

function getSelectionPopTraits (modelId, selectedPopId) {

    if (modelId === selectedPopId) {selectedPopId=undefined;}

    jQuery.ajax({
        type: 'POST',
        dataType: "json",
        url: '/solgs/selection/index/form',
        data: {'pred_pop_id': selectedPopId, 'training_pop_id': modelId},
        success: function(res) {

            if (res.status == 'success') {
                var table;
                var traits = res.traits;

                if (traits.length > 1) {
                    table  = selectionIndexForm(traits);
                } else {
                    var msg = 'There is only one trait with valid GEBV predictions.';
                    jQuery("#select_a_population_div").empty();
                    jQuery("#select_a_population_div_text").empty().append(msg);
                }

                jQuery('#selection_index_form').empty().append(table);

            }
        }
    });
}

function  selectionIndexForm(predictedTraits) {
    var cnt = 1;
    var row = '';
    var totalCount = 1;

    for (var i=0; i < predictedTraits.length; i++) {
        var tdCell  = '' + predictedTraits[i]  + ':	';
        var rowTag  = '';

        if ( cnt === 3 ) {
            rowTag = '

';
        }

        row += tdCell
            + '<input type="text" name=' +  predictedTraits[i]
            + ' size = 5px '
            + '>	'
            + rowTag;

        if (cnt === 3 ) { cnt=0;}
        cnt++;
        totalCount++;
    }

    var rankButton =  '
'
        +  '<input style="position:relative;" " class="button" type="submit" value="Calculate" name= "rank" id="rank_genotypes"'
        +  '
';

    var table = '

'
        +  row + '
'
        + rankButton
        + '
';

    return table;
}

function applySelectionIndex(params, legend, trainingPopId, predictionPopId) {

    if (params) {
        jQuery.blockUI.defaults.applyPlatformOpacityRules = false;
        jQuery.blockUI({message: 'Please wait..'});

        var action;

        if (!predictionPopId) {
            predictionPopId = 'undef';
        }

        var action = '/solgs/calculate/selection/index/' + trainingPopId +  '/' + predictionPopId;

        jQuery.ajax({
            type: 'POST',
            dataType: "json",
            url: action,
            data: params,
            success: function(res){
                var suc = res.status;
                var table;
                if (suc == 'success' ) {

                    var genos = new Object();

                    genos = res.genotypes;
                    var download_link = res.link;
                    var indexFile     = res.index_file;

                    table = '
';
                    table += '
Genotypes	Selection indices
';

                    var sorted = [];
                    for (var geno in genos) {
                        sorted.push([geno, genos[geno]]);
                        sorted = sorted.sort(function(a, b) {return b[1] - a[1]});
                    }

                    for (var i=0; i<sorted.length; i++) {
                        table += '
';
                        table += ''
                            + sorted[i][0] + '	' + ''
                            + sorted[i][1] + '	';
                        table += '
';
                    }

                    table += '
';
                    table += '
[ ' + download_link + ' ]';
                    table += '
' + legend + '

';
                } else {
                    table = res.status + ' Ranking the genotypes failed..Please report the problem.';
                }

                jQuery('#top_genotypes').append(table).show();
                jQuery('#selected_pop').val('');

                var popId;
                var type;
                if (predictionPopId && predictionPopId !== trainingPopId) {
                    popId = predictionPopId;
                    type  = 'selection';
                } else {
                    popId = trainingPopId;
                    type  = 'training';
                }

                formatGenCorInputData(popId, type, indexFile);

                jQuery("#si_correlation_message")
                    .css({"padding-left": '0px'})
                    .html("Running correlation analysis...");

            },
            error: function(res){
                alert('error occured calculating selection index.');
                jQuery.unblockUI();
            }
        });
    }
}

function validateRelativeWts(nm, val) {
     // alert(val + ' : ' + nm);
     if (isNaN(val) && nm != 'all') {
         alert('the relative weight of trait '+nm+
               ' must be a number.'
               );
         return;
     } else if (!val && nm != 'all') {
         alert('You need to assign a relative weight to trait '+nm+'.'
               +' If you want to exclude the trait assign 0 to it.'
               );
         return;
     } else if (val < 0 && nm != 'all') {
         alert('The relative weight to trait '+nm+
               ' must be a positive number.'
               );
         return;
     } else if (nm == 'all' && val == 0) {
         alert('At least two traits must be assigned relative weight.');
         return;
     } else {
         return true;
     }
 }

function sumElements (elements) {
    var sum = 0;
    for (var i=0; i<elements.length; i++) {
        if (!isNaN(elements[i])) {
                sum +=  elements[i];
        }
    }
    return sum;
}

function selectionIndex ( trainingPopId, predictionPopId ) {

    if (!predictionPopId) {
        predictionPopId = jQuery("#default_selected_population_id").val();
    }

    var legendValues = legendParams();

    var legend   = legendValues.legend;
    var params   = legendValues.params;
    var validate = legendValues.validate;

    if (params && validate) {
        applySelectionIndex(legendValues.params, legendValues.legend, trainingPopId, predictionPopId);
    }
}

function legendParams () {

    var predPopName   = jQuery("#selected_population_name").val();

    if (!predPopName) {
        predPopName = jQuery("#default_selected_population_name").val();
    }

    var rel_form = document.getElementById('selection_index_form');
    var all = rel_form.getElementsByTagName('input');
    var params, validate;
    var allValues = [];

    var legend =  "
";

    legend += 'Relative weights:';

     for (var i = 0; i < all.length; i++) {
         var nm = all[i].name;
         var val = all[i].value;

         if (val != 'Calculate')  {
             if (nm != 'prediction_pop_name') {

                 allValues.push(val);
                 validate = validateRelativeWts(nm, val);

                 if (validate) {
                     if (i == 0) {
                         params = nm+'='+val;
                     } else {
                         params = params +'&'+ nm + '=' + val;
                     }
                     legend += ' ' + nm + '' + ': '+ val;
                 }
             }
         }
     }

     var sum = sumElements(allValues);
     validate = validateRelativeWts('all', sum);

     for (var i=0;  i<allValues.length; i++)  {
         if (isNaN(allValues[i]) || allValues[i] < 0) {
             params = undefined;
         }
     }

     if (predPopName) {
         legend += '
Name: ' + predPopName + '
</div';
     }

    return {'legend' : legend,
            'params': params,
            'validate' : validate
           };
}

function listUploadedSelPopulations ()  {

    var selPopsDivUploaded   = document.getElementById("uploaded_selection_populations");
    var selPopsTableUploaded = selPopsDivUploaded.getElementsByTagName("table");
    var selPopsRowsUploaded  = selPopsTableUploaded[0].rows;
    var predictedPopUploaded = [];

    var popsList ='';
    for (var i = 1; i < selPopsRowsUploaded.length; i++) {
        var row    = selPopsRowsUploaded[i];
        var popRow = row.innerHTML;

        predictedPopUploaded = popRow.match(/\/solgs\/selection\//g);

        if (predictedPopUploaded) {
            var selPopsInput  = row.getElementsByTagName("input")[0];
            var idPopName     = selPopsInput.value;
            var idPopNameCopy = idPopName;
            idPopNameCopy     = JSON.parse(idPopNameCopy);
            var popName       = idPopNameCopy.name;

            popsList += '
'
                + '' + popName + '' + idPopName + ''
                + '
';
        } else {
            popsList = undefined;
        }
    }

   return popsList;
}

function getTrainingPopulationData () {

    var modelId   = jQuery("#model_id").val();
    var modelName = jQuery("#model_name").val();
    var popType   = jQuery("#default_selected_population_type").val();

    return {'id' : modelId, 'name' : modelName, 'pop_type': popType};
}

<commit_msg>allow negative relative weight in selection index..<commit_after>/**
* selection index form, calculation and presentation
* @author Isaak Y Tecle <iyt2@cornell.edu>
*
*/

JSAN.use('jquery.blockUI');

jQuery(document).ready( function () {
        listSelectionIndexPopulations();
});

jQuery("#rank_genotypes").live("click", function() {
    var modelId        = jQuery("#model_id").val();
    var selectionPopId = jQuery("#selected_population_id").val();
    var popType        = jQuery("#selected_population_type").val();

    selectionIndex(modelId, selectionPopId);
});

function listSelectionIndexPopulations ()  {

    var modelData = getTrainingPopulationData();
    var trainingPopIdName = JSON.stringify(modelData);

    var  popsList =  '
'
        + '
 Choose a population
'
        + '
'
        + '
'
        + '
'
        + '' + modelData.name + '' + trainingPopIdName + ''
        + '
';

    popsList += '

';

    jQuery("#select_a_population_div").empty().append(popsList).show();

    var dbSelPopsList;
    if( modelData.id.match(/uploaded/) == null) {
        dbSelPopsList = addSelectionPopulations();
    }

    if (dbSelPopsList) {
            jQuery("#select_a_population_div ul").append(dbSelPopsList);
    }

    var userUploadedSelExists = jQuery("#uploaded_selection_pops_table").doesExist();
    if( userUploadedSelExists == true) {
        var userSelPops = listUploadedSelPopulations();
        if (userSelPops) {

            jQuery("#select_a_population_div ul").append(userSelPops);
        }
    }

    getSelectionPopTraits(modelData.id, modelData.id);

   jQuery(".si_dropdown dt a").click(function() {
            jQuery(".si_dropdown dd ul").toggle();
        });

    jQuery(".si_dropdown dd ul li a").click(function() {

        var text = jQuery(this).html();

        jQuery(".si_dropdown dt a span").html(text);
        jQuery(".si_dropdown dd ul").hide();

        var idPopName = jQuery("#selected_population").find("dt a span.value").html();
        idPopName     = JSON.parse(idPopName);
        modelId = jQuery("#model_id").val();

        selectedPopId   = idPopName.id;
        selectedPopName = idPopName.name;
        selectedPopType = idPopName.pop_type;

        jQuery("#selected_population_name").val(selectedPopName);
        jQuery("#selected_population_id").val(selectedPopId);
        jQuery("#selected_population_type").val(selectedPopType);

        getSelectionPopTraits(modelId, selectedPopId);

    });

    jQuery(".si_dropdown").bind('click', function(e) {
        var clicked = jQuery(e.target);

        if (! clicked.parents().hasClass("si_dropdown"))
            jQuery(".si_dropdown dd ul").hide();

        e.preventDefault();
    });
}

function addSelectionPopulations(){

    var selPopsTable = jQuery("#selection_populations table").html();
    var selPopsRows  = jQuery(selPopsTable).find("tr");

    var predictedPop = [];
    var popsList = '';

    for (var i = 1; i < selPopsRows.length; i++) {
        var row    = selPopsRows[i];
        var popRow = row.innerHTML;

        predictedPop = popRow.match(/\/solgs\/selection\//g);

        if (predictedPop) {
            if (predictedPop.length > 1) {
                var selPopsInput  = row.getElementsByTagName("input")[0];
                var idPopName     = selPopsInput.value;
                var idPopNameCopy = idPopName;
                idPopNameCopy     = JSON.parse(idPopNameCopy);
                var popName       = idPopNameCopy.name;

                popsList += '
'
                    + '' + popName + '' + idPopName + ''
                    + '
';
            }
        }
    }

    return popsList;
}

function getSelectionPopTraits (modelId, selectedPopId) {

    if (modelId === selectedPopId) {selectedPopId=undefined;}

    jQuery.ajax({
        type: 'POST',
        dataType: "json",
        url: '/solgs/selection/index/form',
        data: {'pred_pop_id': selectedPopId, 'training_pop_id': modelId},
        success: function(res) {

            if (res.status == 'success') {
                var table;
                var traits = res.traits;

                if (traits.length > 1) {
                    table  = selectionIndexForm(traits);
                } else {
                    var msg = 'There is only one trait with valid GEBV predictions.';
                    jQuery("#select_a_population_div").empty();
                    jQuery("#select_a_population_div_text").empty().append(msg);
                }

                jQuery('#selection_index_form').empty().append(table);

            }
        }
    });
}

function  selectionIndexForm(predictedTraits) {
    var cnt = 1;
    var row = '';
    var totalCount = 1;

    for (var i=0; i < predictedTraits.length; i++) {
        var tdCell  = '' + predictedTraits[i]  + ':	';
        var rowTag  = '';

        if ( cnt === 3 ) {
            rowTag = '

';
        }

        row += tdCell
            + '<input type="text" name=' +  predictedTraits[i]
            + ' size = 5px '
            + '>	'
            + rowTag;

        if (cnt === 3 ) { cnt=0;}
        cnt++;
        totalCount++;
    }

    var rankButton =  '
'
        +  '<input style="position:relative;" " class="button" type="submit" value="Calculate" name= "rank" id="rank_genotypes"'
        +  '
';

    var table = '

'
        +  row + '
'
        + rankButton
        + '
';

    return table;
}

function applySelectionIndex(params, legend, trainingPopId, predictionPopId) {

    if (params) {
        jQuery.blockUI.defaults.applyPlatformOpacityRules = false;
        jQuery.blockUI({message: 'Please wait..'});

        var action;

        if (!predictionPopId) {
            predictionPopId = 'undef';
        }

        var action = '/solgs/calculate/selection/index/' + trainingPopId +  '/' + predictionPopId;

        jQuery.ajax({
            type: 'POST',
            dataType: "json",
            url: action,
            data: params,
            success: function(res){
                var suc = res.status;
                var table;
                if (suc == 'success' ) {

                    var genos = new Object();

                    genos = res.genotypes;
                    var download_link = res.link;
                    var indexFile     = res.index_file;

                    table = '
';
                    table += '
Genotypes	Selection indices
';

                    var sorted = [];
                    for (var geno in genos) {
                        sorted.push([geno, genos[geno]]);
                        sorted = sorted.sort(function(a, b) {return b[1] - a[1]});
                    }

                    for (var i=0; i<sorted.length; i++) {
                        table += '
';
                        table += ''
                            + sorted[i][0] + '	' + ''
                            + sorted[i][1] + '	';
                        table += '
';
                    }

                    table += '
';
                    table += '
[ ' + download_link + ' ]';
                    table += '
' + legend + '

';
                } else {
                    table = res.status + ' Ranking the genotypes failed..Please report the problem.';
                }

                jQuery('#top_genotypes').append(table).show();
                jQuery('#selected_pop').val('');

                var popId;
                var type;
                if (predictionPopId && predictionPopId !== trainingPopId) {
                    popId = predictionPopId;
                    type  = 'selection';
                } else {
                    popId = trainingPopId;
                    type  = 'training';
                }

                formatGenCorInputData(popId, type, indexFile);

                jQuery("#si_correlation_message")
                    .css({"padding-left": '0px'})
                    .html("Running correlation analysis...");

            },
            error: function(res){
                alert('error occured calculating selection index.');
                jQuery.unblockUI();
            }
        });
    }
}

function validateRelativeWts(nm, val) {

     if (isNaN(val) && nm != 'all') {
         alert('the relative weight of trait '+nm+
               ' must be a number.'
               );
         return;
     } else if (!val && nm != 'all') {
         alert('You need to assign a relative weight to trait '+nm+'.'
               +' If you want to exclude the trait assign 0 to it.'
               );
         return;
    // }// else if (val < 0 && nm != 'all') {
      //   alert('The relative weight to trait '+nm+
      //         ' must be a positive number.'
      //         );
     //    return;
     } else if (nm == 'all' && val == 0) {
         alert('At least two traits must be assigned relative weight.');
         return;
     } else {
         return true;
     }
 }

function sumElements (elements) {
    var sum = 0;
    for (var i=0; i<elements.length; i++) {
        if (!isNaN(elements[i])) {
            sum = parseFloat(sum) +  parseFloat(elements[i]);
        }
    }
    return sum;
}

function selectionIndex ( trainingPopId, predictionPopId ) {

    if (!predictionPopId) {
        predictionPopId = jQuery("#default_selected_population_id").val();
    }

    var legendValues = legendParams();

    var legend   = legendValues.legend;
    var params   = legendValues.params;
    var validate = legendValues.validate;

    if (params && validate) {
        applySelectionIndex(legendValues.params, legendValues.legend, trainingPopId, predictionPopId);
    }
}

function legendParams () {

    var predPopName   = jQuery("#selected_population_name").val();

    if (!predPopName) {
        predPopName = jQuery("#default_selected_population_name").val();
    }

    var rel_form = document.getElementById('selection_index_form');
    var all = rel_form.getElementsByTagName('input');
    var params, validate;
    var allValues = [];

    var legend =  "
";

    legend += 'Relative weights:';

     for (var i = 0; i < all.length; i++) {
         var nm = all[i].name;
         var val = all[i].value;

         if (val != 'Calculate')  {
             if (nm != 'prediction_pop_name') {

                 allValues.push(val);
                 validate = validateRelativeWts(nm, val);

                 if (validate) {
                     if (i == 0) {
                         params = nm+'='+val;
                     } else {
                         params = params +'&'+ nm + '=' + val;
                     }
                     legend += ' ' + nm + '' + ': '+ val;
                 }
             }
         }
     }

     var sum = sumElements(allValues);
     validate = validateRelativeWts('all', sum);

     for (var i=0;  i<allValues.length; i++)  {
	// (isNaN(allValues[i]) || allValues[i] < 0)
         if (isNaN(allValues[i])) {
             params = undefined;
         }
     }

     if (predPopName) {
         legend += '
Name: ' + predPopName + '
</div';
     }

    return {'legend' : legend,
            'params': params,
            'validate' : validate
           };
}

function listUploadedSelPopulations ()  {

    var selPopsDivUploaded   = document.getElementById("uploaded_selection_populations");
    var selPopsTableUploaded = selPopsDivUploaded.getElementsByTagName("table");
    var selPopsRowsUploaded  = selPopsTableUploaded[0].rows;
    var predictedPopUploaded = [];

    var popsList ='';
    for (var i = 1; i < selPopsRowsUploaded.length; i++) {
        var row    = selPopsRowsUploaded[i];
        var popRow = row.innerHTML;

        predictedPopUploaded = popRow.match(/\/solgs\/selection\//g);

        if (predictedPopUploaded) {
            var selPopsInput  = row.getElementsByTagName("input")[0];
            var idPopName     = selPopsInput.value;
            var idPopNameCopy = idPopName;
            idPopNameCopy     = JSON.parse(idPopNameCopy);
            var popName       = idPopNameCopy.name;

            popsList += '
'
                + '' + popName + '' + idPopName + ''
                + '
';
        } else {
            popsList = undefined;
        }
    }

   return popsList;
}

function getTrainingPopulationData () {

    var modelId   = jQuery("#model_id").val();
    var modelName = jQuery("#model_name").val();
    var popType   = jQuery("#default_selected_population_type").val();

    return {'id' : modelId, 'name' : modelName, 'pop_type': popType};
}

<|endoftext|>


<commit_before>#!/usr/bin/env node
/* eslint-disable */
/* Adapted from nodemon's postinstall: https://github.com/remy/nodemon/blob/master/package.json */

var msg = 'Take a look at https://opencollective.com/styled-components/donate to help out styled-components’ maintainers';

console.log(msg);
<commit_msg>Remove "/donate" from opencollective link<commit_after>#!/usr/bin/env node
/* eslint-disable */
/* Adapted from nodemon's postinstall: https://github.com/remy/nodemon/blob/master/package.json */

var msg = 'Take a look at https://opencollective.com/styled-components to help out styled-components’ maintainers';

console.log(msg);
<|endoftext|>


<commit_before>'use strict';

var async = require('async');

var debug = require('./util/debug')('analysis');

var Factory = require('./workflow/factory');
var toposort = require('../lib/dag/toposort');
var validator = require('../lib/dag/validator');

var DatabaseService = require('./service/database');
var Requirements = require('./service/requirements');

var AnalysisLogger = require('./logging/logger');

function Analysis(rootNode) {
    this.rootNode = rootNode;
}

Analysis.prototype.id = function() {
    return this.rootNode.id();
};

Analysis.prototype.getQuery = function() {
    return this.rootNode.getQuery();
};

Analysis.prototype.getRoot = function() {
    return this.rootNode;
};

Analysis.prototype.getNodes = function() {
    function buildList(node, nodesList) {
        nodesList = nodesList || [node];

        node.getInputNodes().forEach(function(inputNode) {
            nodesList.push(inputNode);

            buildList(inputNode, nodesList);
        });

        return nodesList;
    }

    return buildList(this.rootNode);
};

Analysis.prototype.getSortedNodes = function() {
    return toposort(this.rootNode);
};

function AnalysisFactory(DatabaseServiceClass) {
    this.DatabaseServiceClass = DatabaseServiceClass;
}

AnalysisFactory.prototype.create = function(configuration, definition, callback) {
    debug(configuration.user, configuration.db, configuration.batch);
    var databaseService = new this.DatabaseServiceClass(
        configuration.user,
        configuration.db,
        configuration.batch,
        configuration.limits
    );
    var requirements = new Requirements(databaseService, configuration.limits);
    var logger = configuration.logger ? new AnalysisLogger(configuration.logger.stream, configuration.user) : undefined;

    async.waterfall(
        [
            function analysis$createWithFactory(done) {
                var factory = new Factory(configuration.user, databaseService);
                factory.create(JSON.parse(JSON.stringify(definition)), done);
            },
            function analysis$validate(rootNode, done) {
                if (!validator.isValid(rootNode)) {
                    return done(new Error('Invalid analysis, cycle found'));
                }

                return done(null, new Analysis(rootNode));
            },
            function analysis$register(analysis, done) {
                databaseService.registerAnalysisInCatalog(analysis, function(err) {
                    return done(err, analysis);
                });
            },
            function analysis$checkLimits(analysis, done) {
                requirements.checkLimits(analysis, function(err) {
                    return done(err, analysis);
                });
            },
            function analysis$queueOperations(analysis, done) {
                databaseService.queueAnalysisOperations(analysis, function(err) {
                    return done(err, analysis);
                });
            },
            function analysis$track(analysis, done) {
                if (logger) {
                    logger.log(analysis);
                }

                databaseService.trackAnalysis(analysis, function(err) {
                    return done(err, analysis);
                });
            }
        ],
        function analysis$finish(err, analysis) {
            if (err) {
                if (err && err.message && err.message.match(/permission denied/i)) {
                    err = new Error('Analysis requires authentication with API key: permission denied.');
                }
                return callback(err);
            }
            return callback(null, analysis);
        }
    );
};

module.exports = AnalysisFactory;
var analysisFactory = new AnalysisFactory(DatabaseService);
module.exports.create = analysisFactory.create.bind(analysisFactory);
module.exports.reference = require('../reference');
module.exports.version = require('../package.json').version;
<commit_msg>Perform limit-checking before registering the analysis<commit_after>'use strict';

var async = require('async');

var debug = require('./util/debug')('analysis');

var Factory = require('./workflow/factory');
var toposort = require('../lib/dag/toposort');
var validator = require('../lib/dag/validator');

var DatabaseService = require('./service/database');
var Requirements = require('./service/requirements');

var AnalysisLogger = require('./logging/logger');

function Analysis(rootNode) {
    this.rootNode = rootNode;
}

Analysis.prototype.id = function() {
    return this.rootNode.id();
};

Analysis.prototype.getQuery = function() {
    return this.rootNode.getQuery();
};

Analysis.prototype.getRoot = function() {
    return this.rootNode;
};

Analysis.prototype.getNodes = function() {
    function buildList(node, nodesList) {
        nodesList = nodesList || [node];

        node.getInputNodes().forEach(function(inputNode) {
            nodesList.push(inputNode);

            buildList(inputNode, nodesList);
        });

        return nodesList;
    }

    return buildList(this.rootNode);
};

Analysis.prototype.getSortedNodes = function() {
    return toposort(this.rootNode);
};

function AnalysisFactory(DatabaseServiceClass) {
    this.DatabaseServiceClass = DatabaseServiceClass;
}

AnalysisFactory.prototype.create = function(configuration, definition, callback) {
    debug(configuration.user, configuration.db, configuration.batch);
    var databaseService = new this.DatabaseServiceClass(
        configuration.user,
        configuration.db,
        configuration.batch,
        configuration.limits
    );
    var requirements = new Requirements(databaseService, configuration.limits);
    var logger = configuration.logger ? new AnalysisLogger(configuration.logger.stream, configuration.user) : undefined;

    async.waterfall(
        [
            function analysis$createWithFactory(done) {
                var factory = new Factory(configuration.user, databaseService);
                factory.create(JSON.parse(JSON.stringify(definition)), done);
            },
            function analysis$validate(rootNode, done) {
                if (!validator.isValid(rootNode)) {
                    return done(new Error('Invalid analysis, cycle found'));
                }

                return done(null, new Analysis(rootNode));
            },
            function analysis$checkLimits(analysis, done) {
                requirements.checkLimits(analysis, function(err) {
                    return done(err, analysis);
                });
            },
            function analysis$register(analysis, done) {
                databaseService.registerAnalysisInCatalog(analysis, function(err) {
                    return done(err, analysis);
                });
            },
            function analysis$queueOperations(analysis, done) {
                databaseService.queueAnalysisOperations(analysis, function(err) {
                    return done(err, analysis);
                });
            },
            function analysis$track(analysis, done) {
                if (logger) {
                    logger.log(analysis);
                }

                databaseService.trackAnalysis(analysis, function(err) {
                    return done(err, analysis);
                });
            }
        ],
        function analysis$finish(err, analysis) {
            if (err) {
                if (err && err.message && err.message.match(/permission denied/i)) {
                    err = new Error('Analysis requires authentication with API key: permission denied.');
                }
                return callback(err);
            }
            return callback(null, analysis);
        }
    );
};

module.exports = AnalysisFactory;
var analysisFactory = new AnalysisFactory(DatabaseService);
module.exports.create = analysisFactory.create.bind(analysisFactory);
module.exports.reference = require('../reference');
module.exports.version = require('../package.json').version;
<|endoftext|>


<commit_before>// Copyright 2018-2019, University of Colorado Boulder

/**
 * IO type for JS's built-in Float64Array type
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 * @author Chris Klusendorf
 */
define( require => {
  'use strict';

  // modules
  const ObjectIO = require( 'TANDEM/types/ObjectIO' );
  const tandemNamespace = require( 'TANDEM/tandemNamespace' );

  class Float64ArrayIO extends ObjectIO {
    /**
     * Serialize an array by serializing each element
     * @public
     * @override
     *
     * @param {Float64ArrayIO} array
     * @returns {Array.<number>}
     */
    static toStateObject( array ) {
      assert && assert( array instanceof Float64Array, 'Float64ArrayIO should wrap array instances' );

      const result = [];
      array.forEach( float => result.push( float ) );
      return result;
    }

    /**
     * Deserialize from a serialized state.
     * @public
     * @override
     *
     * @param {Array.<number>} stateObject - from toStateObject
     * @returns {Float64Array}
     */
    static fromStateObject( stateObject ) {
      return new Float64Array( stateObject );
    }

    /**
     * Sets the value of the entire typed array.
     * @public
     * @override
     *
     * @param {Float64Array} array
     * @param {Array.<number>}
     */
    static setValue( array, fromStateObject ) {
      assert && assert( array instanceof Float64Array, 'Float64ArrayIO should wrap array instances' );
      array.set( fromStateObject );
    }
  }

  return tandemNamespace.register( 'Float64ArrayIO', Float64ArrayIO );
} );
<commit_msg>Improving documentation and variable names<commit_after>// Copyright 2018-2019, University of Colorado Boulder

/**
 * IO type for JS's built-in Float64Array type
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 * @author Chris Klusendorf
 */
define( require => {
  'use strict';

  // modules
  const ObjectIO = require( 'TANDEM/types/ObjectIO' );
  const tandemNamespace = require( 'TANDEM/tandemNamespace' );

  class Float64ArrayIO extends ObjectIO {

    /**
     * Serialize an array by serializing each element
     * @public
     * @override
     *
     * @param {Float64ArrayIO} array
     * @returns {Array.<number>}
     */
    static toStateObject( array ) {
      assert && assert( array instanceof Float64Array, 'Float64ArrayIO should wrap array instances' );

      const result = [];
      array.forEach( float => result.push( float ) );
      return result;
    }

    /**
     * Deserialize from a serialized state.
     * @public
     * @override
     *
     * @param {Array.<number>} stateObject - from toStateObject
     * @returns {Float64Array}
     */
    static fromStateObject( stateObject ) {
      return new Float64Array( stateObject );
    }

    /**
     * Sets the value of the entire typed array.
     * @public
     * @override
     *
     * @param {Float64Array} array
     * @param {Float64Array} stateObject
     */
    static setValue( array, stateObject ) {
      assert && assert( array instanceof Float64Array, 'Float64ArrayIO should wrap array instances' );
      array.set( stateObject );
    }
  }

  return tandemNamespace.register( 'Float64ArrayIO', Float64ArrayIO );
} );
<|endoftext|>


<commit_before>exports.transports = {
	tcp    : require("./transport/tcp"),
	ascii  : require("./transport/ascii"),
	serial : require("./transport/serial")
};

exports.drivers = {
	serial : require("./driver/serial"),
	tcp    : require("./driver/tcp"),
	udp    : require("./driver/udp")
};

exports.stream = require("./stream");
exports.pdu    = require("modbus-pdu");

exports.tcp = {
	connect : function () {
		var port    = 502;
		var host    = "localhost";
		var options = {};
		var next    = noop;

		Array.prototype.slice.apply(arguments).map(function (arg) {
			switch (typeof arg) {
				case "number":
					port = arg;
					break;
				case "string":
					host = arg;
					break;
				case "object":
					options = arg;
					break;
				case "function":
					next = arg;
					break;
			}
		});

		if (typeof options.retry == "undefined") {
			options.retry = 30000;
		}

		var socket = exports.drivers.tcp.connect(port, host, options);

		socket.attach(exports.transports.tcp.prepare(options), next);
	},
	server : function () {
		var options = {};
		var next    = noop;

		Array.prototype.slice.apply(arguments).map(function (arg) {
			switch (typeof arg) {
				case "object":
					options = arg;
					break;
				case "function":
					next = arg;
					break;
			}
		});

		if (typeof options.retry == "undefined") {
			options.retry = 30000;
		}

		return exports.drivers.tcp.server(options).attach(exports.transports.tcp.prepare(options), next);
	}
};

exports.udp = {
	connect : function () {
		var port    = 502;
		var host    = "localhost";
		var options = {};
		var next    = noop;

		Array.prototype.slice.apply(arguments).map(function (arg) {
			switch (typeof arg) {
				case "number":
					port = arg;
					break;
				case "string":
					host = arg;
					break;
				case "object":
					options = arg;
					break;
				case "function":
					next = arg;
					break;
			}
		});

		if (typeof options.retry == "undefined") {
			options.retry = 3000;
		}

		var socket = exports.drivers.udp.connect(port, host, options);

		socket.attach(exports.transports.tcp.prepare(options), next);
	},
	server : function () {
		var options = {};
		var next    = noop;

		Array.prototype.slice.apply(arguments).map(function (arg) {
			switch (typeof arg) {
				case "object":
					options = arg;
					break;
				case "function":
					next = arg;
					break;
			}
		});

		if (typeof options.retry == "undefined") {
			options.retry = 3000;
		}

		return exports.drivers.udp.server(options).attach(exports.transports.tcp.prepare(options), next);
	}
};

exports.serial = {
	connect : function () {
		var possible_options = [ "retries", "retry", "beforerequest", "afterrequest", "mutex", "maxDataInterval" ];
		var device           = "/dev/ttyS0";
		var options          = {};
		var serial_options   = {};
		var next             = noop;

		Array.prototype.slice.apply(arguments).map(function (arg) {
			switch (typeof arg) {
				case "string":
					device = arg;
					break;
				case "object":
					options = arg;
					break;
				case "function":
					next = arg;
					break;
			}
		});

		possible_options.map(function (option) {
			if (typeof options[option] != "undefined") {
				serial_options[option] = options[option];
				delete options[option];
			}
		});

		var stream = exports.drivers.serial.connect(device, options);

		stream.attach(exports.transports.serial.prepare(serial_options), next);
	}
};

function noop() {}
<commit_msg>added a mode parameter to select ascii mode for a serial modbus slave<commit_after>exports.transports = {
	tcp    : require("./transport/tcp"),
	ascii  : require("./transport/ascii"),
	serial : require("./transport/serial")
};

exports.drivers = {
	serial : require("./driver/serial"),
	tcp    : require("./driver/tcp"),
	udp    : require("./driver/udp")
};

exports.stream = require("./stream");
exports.pdu    = require("modbus-pdu");

exports.tcp = {
	connect : function () {
		var port    = 502;
		var host    = "localhost";
		var options = {};
		var next    = noop;

		Array.prototype.slice.apply(arguments).map(function (arg) {
			switch (typeof arg) {
				case "number":
					port = arg;
					break;
				case "string":
					host = arg;
					break;
				case "object":
					options = arg;
					break;
				case "function":
					next = arg;
					break;
			}
		});

		if (typeof options.retry == "undefined") {
			options.retry = 30000;
		}

		var socket = exports.drivers.tcp.connect(port, host, options);

		socket.attach(exports.transports.tcp.prepare(options), next);
	},
	server : function () {
		var options = {};
		var next    = noop;

		Array.prototype.slice.apply(arguments).map(function (arg) {
			switch (typeof arg) {
				case "object":
					options = arg;
					break;
				case "function":
					next = arg;
					break;
			}
		});

		if (typeof options.retry == "undefined") {
			options.retry = 30000;
		}

		return exports.drivers.tcp.server(options).attach(exports.transports.tcp.prepare(options), next);
	}
};

exports.udp = {
	connect : function () {
		var port    = 502;
		var host    = "localhost";
		var options = {};
		var next    = noop;

		Array.prototype.slice.apply(arguments).map(function (arg) {
			switch (typeof arg) {
				case "number":
					port = arg;
					break;
				case "string":
					host = arg;
					break;
				case "object":
					options = arg;
					break;
				case "function":
					next = arg;
					break;
			}
		});

		if (typeof options.retry == "undefined") {
			options.retry = 3000;
		}

		var socket = exports.drivers.udp.connect(port, host, options);

		socket.attach(exports.transports.tcp.prepare(options), next);
	},
	server : function () {
		var options = {};
		var next    = noop;

		Array.prototype.slice.apply(arguments).map(function (arg) {
			switch (typeof arg) {
				case "object":
					options = arg;
					break;
				case "function":
					next = arg;
					break;
			}
		});

		if (typeof options.retry == "undefined") {
			options.retry = 3000;
		}

		return exports.drivers.udp.server(options).attach(exports.transports.tcp.prepare(options), next);
	}
};

exports.serial = {
	connect : function () {
		var possible_options = [ "retries", "retry", "beforerequest", "afterrequest", "mutex", "maxDataInterval" ];
		var device           = "/dev/ttyS0";
		var options          = {};
		var serial_options   = {};
		var next             = noop;

		Array.prototype.slice.apply(arguments).map(function (arg) {
			switch (typeof arg) {
				case "string":
					device = arg;
					break;
				case "object":
					options = arg;
					break;
				case "function":
					next = arg;
					break;
			}
		});

		possible_options.map(function (option) {
			if (typeof options[option] != "undefined") {
				serial_options[option] = options[option];
				delete options[option];
			}
		});

		var stream = exports.drivers.serial.connect(device, options);
		if (options.mode !== undefined) {
			switch (options.mode){
				case "rtu":
					stream.attach(exports.transports.serial.prepare(serial_options), next);
					break;
				case "ascii":
					stream.attach(exports.transports.ascii.prepare(serial_options), next);
					break;
				default:
					stream.attach(exports.transports.serial.prepare(serial_options), next);
			}
		}
		else {
			stream.attach(exports.transports.serial.prepare(serial_options), next);
		}

	}
};

function noop() {}
<|endoftext|>


<commit_before>
/*!
 * Connect - router
 * Copyright(c) 2010 Sencha Inc.
 * Copyright(c) 2011 TJ Holowaychuk
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var utils = require('../node_modules/connect/lib/utils')
  , parse = require('url').parse;

/**
 * Expose router.
 */

exports = module.exports = router;

/**
 * Supported HTTP / WebDAV methods.
 */

var _methods = exports.methods = [
    'get'
  , 'post'
  , 'put'
  , 'delete'
  , 'connect'
  , 'options'
  , 'trace'
  , 'copy'
  , 'lock'
  , 'mkcol'
  , 'move'
  , 'propfind'
  , 'proppatch'
  , 'unlock'
  , 'report'
  , 'mkactivity'
  , 'checkout'
  , 'merge'
];

/**
 * Provides Sinatra and Express-like routing capabilities.
 *
 * Examples:
 *
 *     connect.router(function(app){
 *       app.get('/user/:id', function(req, res, next){
 *         // populates req.params.id
 *       });
 *       app.put('/user/:id', function(req, res, next){
 *         // populates req.params.id
 *       });
 *     })
 *
 * @param {Function} fn
 * @return {Function}
 * @api public
 */

function router(fn){
  var self = this
    , methods = {}
    , routes = {}
    , params = {};

  if (!fn) throw new Error('router provider requires a callback function');

  // Generate method functions
  _methods.forEach(function(method){
    methods[method] = generateMethodFunction(method.toUpperCase());
  });

  // Alias del -> delete
  methods.del = methods.delete;

  // Apply callback to all methods
  methods.all = function(){
    var args = arguments;
    _methods.forEach(function(name){
      methods[name].apply(this, args);
    });
    return self;
  };

  // Register param callback
  methods.param = function(name, fn){
    params[name] = fn;
  };

  fn.call(this, methods);

  function generateMethodFunction(name) {
    var localRoutes = routes[name] = routes[name] || [];
    var ret = function(path, fn){
      var keys = []
        , middleware = [];

      // slice middleware
      if (arguments.length > 2) {
        middleware = Array.prototype.slice.call(arguments, 1, arguments.length);
        fn = middleware.pop();
        middleware = utils.flatten(middleware);
      }

      fn.middleware = middleware;

      if (!path) throw new Error(name + ' route requires a path');
      if (!fn) throw new Error(name + ' route ' + path + ' requires a callback');
      var regexp = path instanceof RegExp
        ? path
        : normalizePath(path, keys);
      localRoutes.push({
          fn: fn
        , path: regexp
        , keys: keys
        , orig: path
        , method: name
      });
      console.trace("Added route " + path + " for verb " + name);
      return self;
    };
    return ret;
  }

  function router(req, res, next){
    var route
      , self = this;

    (function pass(i){
      if (route = match(req, routes, i)) {
        var i = 0
          , keys = route.keys;

        req.params = route.params;

        // Param preconditions
        (function param(err) {
          try {
            var key = keys[i++]
              , val = req.params[key]
              , fn = params[key];

            if ('route' == err) {
              pass(req._route_index + 1);
            // Error
            } else if (err) {
              next(err);
            // Param has callback
            } else if (fn) {
              // Return style
              if (1 == fn.length) {
                req.params[key] = fn(val);
                param();
              // Middleware style
              } else {
                fn(req, res, param, val);
              }
            // Finished processing params
            } else if (!key) {
              // route middleware
              i = 0;
              (function nextMiddleware(err){
                var fn = route.middleware[i++];
                if ('route' == err) {
                  pass(req._route_index + 1);
                } else if (err) {
                  next(err);
                } else if (fn) {
                  fn(req, res, nextMiddleware);
                } else {
                  route.call(self, req, res, function(err){
                    if (err) {
                      next(err);
                    } else {
                      pass(req._route_index + 1);
                    }
                  });
                }
              })();
            // More params
            } else {
              param();
            }
          } catch (err) {
            next(err);
          }
        })();
      } else if ('OPTIONS' == req.method) {
        options(req, res, routes);
      } else {
        next();
      }
    })();
  };

  router.remove = function(path, method){
    var fns = router.lookup(path, method);
    fns.forEach(function(fn){
      routes[fn.method].splice(fn.index, 1);
    });
  };

  router.lookup = function(path, method, ret){
    ret = ret || [];

    // method specific lookup
    if (method) {
      method = method.toUpperCase();
      if (routes[method]) {
        routes[method].forEach(function(route, i){
          if (path == route.orig) {
            var fn = route.fn;
            fn.regexp = route.path;
            fn.keys = route.keys;
            fn.path = route.orig;
            fn.method = route.method;
            fn.index = i;
            ret.push(fn);
          }
        });
      }
    // global lookup
    } else {
      _methods.forEach(function(method){
        router.lookup(path, method, ret);
      });
    }

    return ret;
  };

  router.match = function(url, method, ret){
    var ret = ret || []
      , i = 0
      , fn
      , req;

    // method specific matches
    if (method) {
      method = method.toUpperCase();
      req = { url: url, method: method };
      while (fn = match(req, routes, i)) {
        i = req._route_index + 1;
        ret.push(fn);
      }
    // global matches
    } else {
      _methods.forEach(function(method){
        router.match(url, method, ret);
      });
    }

    return ret;
  };

  return router;
}

/**
 * Respond to OPTIONS.
 *
 * @param {ServerRequest} req
 * @param {ServerResponse} req
 * @param {Array} routes
 * @api private
 */

function options(req, res, routes) {
  var pathname = parse(req.url).pathname
    , body = optionsFor(pathname, routes).join(',');
  res.writeHead(200, {
      'Content-Length': body.length
    , 'Allow': body
  });
  res.end(body);
}

/**
 * Return OPTIONS array for the given `path`, matching `routes`.
 *
 * @param {String} path
 * @param {Array} routes
 * @return {Array}
 * @api private
 */

function optionsFor(path, routes) {
  return _methods.filter(function(method){
    var arr = routes[method.toUpperCase()];
    for (var i = 0, len = arr.length; i < len; ++i) {
      if (arr[i].path.test(path)) return true;
    }
  }).map(function(method){
    return method.toUpperCase();
  });
}

/**
 * Normalize the given path string,
 * returning a regular expression.
 *
 * An empty array should be passed,
 * which will contain the placeholder
 * key names. For example "/user/:id" will
 * then contain ["id"].
 *
 * @param  {String} path
 * @param  {Array} keys
 * @return {RegExp}
 * @api private
 */

function normalizePath(path, keys) {
  path = path
    .concat('/?')
    .replace(/\/\(/g, '(?:/')
    .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?/g, function(_, slash, format, key, capture, optional){
      keys.push(key);
      slash = slash || '';
      return ''
        + (optional ? '' : slash)
        + '(?:'
        + (optional ? slash : '')
        + (format || '') + (capture || '([^/]+?)') + ')'
        + (optional || '');
    })
    .replace(/([\/.])/g, '\\$1')
    .replace(/\*/g, '(.+)');
  return new RegExp('^' + path + '$', 'i');
}

/**
 * Attempt to match the given request to
 * one of the routes. When successful
 * a route function is returned.
 *
 * @param  {ServerRequest} req
 * @param  {Object} routes
 * @return {Function}
 * @api private
 */

function match(req, routes, i) {
  var captures
    , method = req.method
    , i = i || 0;
  if ('HEAD' == method.toUpperCase()) method = 'GET';
  if (routes = routes[method]) {
    var url = parse(req.url)
      , pathname = url.pathname;
    for (var len = routes.length; i < len; ++i) {
      var route = routes[i]
        , fn = route.fn
        , path = route.path
        , keys = fn.keys = route.keys;
      if (captures = path.exec(pathname)) {
        fn.method = method;
        fn.params = [];
        for (var j = 1, len = captures.length; j < len; ++j) {
          var key = keys[j-1],
            val = typeof captures[j] === 'string'
              ? decodeURIComponent(captures[j])
              : captures[j];
          if (key) {
            fn.params[key] = val;
          } else {
            fn.params.push(val);
          }
        }
        req._route_index = i;
        return fn;
      }
    }
  }
}
<commit_msg>Removed a trace console log.<commit_after>
/*!
 * Connect - router
 * Copyright(c) 2010 Sencha Inc.
 * Copyright(c) 2011 TJ Holowaychuk
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var utils = require('../node_modules/connect/lib/utils')
  , parse = require('url').parse;

/**
 * Expose router.
 */

exports = module.exports = router;

/**
 * Supported HTTP / WebDAV methods.
 */

var _methods = exports.methods = [
    'get'
  , 'post'
  , 'put'
  , 'delete'
  , 'connect'
  , 'options'
  , 'trace'
  , 'copy'
  , 'lock'
  , 'mkcol'
  , 'move'
  , 'propfind'
  , 'proppatch'
  , 'unlock'
  , 'report'
  , 'mkactivity'
  , 'checkout'
  , 'merge'
];

/**
 * Provides Sinatra and Express-like routing capabilities.
 *
 * Examples:
 *
 *     connect.router(function(app){
 *       app.get('/user/:id', function(req, res, next){
 *         // populates req.params.id
 *       });
 *       app.put('/user/:id', function(req, res, next){
 *         // populates req.params.id
 *       });
 *     })
 *
 * @param {Function} fn
 * @return {Function}
 * @api public
 */

function router(fn){
  var self = this
    , methods = {}
    , routes = {}
    , params = {};

  if (!fn) throw new Error('router provider requires a callback function');

  // Generate method functions
  _methods.forEach(function(method){
    methods[method] = generateMethodFunction(method.toUpperCase());
  });

  // Alias del -> delete
  methods.del = methods.delete;

  // Apply callback to all methods
  methods.all = function(){
    var args = arguments;
    _methods.forEach(function(name){
      methods[name].apply(this, args);
    });
    return self;
  };

  // Register param callback
  methods.param = function(name, fn){
    params[name] = fn;
  };

  fn.call(this, methods);

  function generateMethodFunction(name) {
    var localRoutes = routes[name] = routes[name] || [];
    var ret = function(path, fn){
      var keys = []
        , middleware = [];

      // slice middleware
      if (arguments.length > 2) {
        middleware = Array.prototype.slice.call(arguments, 1, arguments.length);
        fn = middleware.pop();
        middleware = utils.flatten(middleware);
      }

      fn.middleware = middleware;

      if (!path) throw new Error(name + ' route requires a path');
      if (!fn) throw new Error(name + ' route ' + path + ' requires a callback');
      var regexp = path instanceof RegExp
        ? path
        : normalizePath(path, keys);
      localRoutes.push({
          fn: fn
        , path: regexp
        , keys: keys
        , orig: path
        , method: name
      });
      //console.trace("Added route " + path + " for verb " + name);
      return self;
    };
    return ret;
  }

  function router(req, res, next){
    var route
      , self = this;

    (function pass(i){
      if (route = match(req, routes, i)) {
        var i = 0
          , keys = route.keys;

        req.params = route.params;

        // Param preconditions
        (function param(err) {
          try {
            var key = keys[i++]
              , val = req.params[key]
              , fn = params[key];

            if ('route' == err) {
              pass(req._route_index + 1);
            // Error
            } else if (err) {
              next(err);
            // Param has callback
            } else if (fn) {
              // Return style
              if (1 == fn.length) {
                req.params[key] = fn(val);
                param();
              // Middleware style
              } else {
                fn(req, res, param, val);
              }
            // Finished processing params
            } else if (!key) {
              // route middleware
              i = 0;
              (function nextMiddleware(err){
                var fn = route.middleware[i++];
                if ('route' == err) {
                  pass(req._route_index + 1);
                } else if (err) {
                  next(err);
                } else if (fn) {
                  fn(req, res, nextMiddleware);
                } else {
                  route.call(self, req, res, function(err){
                    if (err) {
                      next(err);
                    } else {
                      pass(req._route_index + 1);
                    }
                  });
                }
              })();
            // More params
            } else {
              param();
            }
          } catch (err) {
            next(err);
          }
        })();
      } else if ('OPTIONS' == req.method) {
        options(req, res, routes);
      } else {
        next();
      }
    })();
  };

  router.remove = function(path, method){
    var fns = router.lookup(path, method);
    fns.forEach(function(fn){
      routes[fn.method].splice(fn.index, 1);
    });
  };

  router.lookup = function(path, method, ret){
    ret = ret || [];

    // method specific lookup
    if (method) {
      method = method.toUpperCase();
      if (routes[method]) {
        routes[method].forEach(function(route, i){
          if (path == route.orig) {
            var fn = route.fn;
            fn.regexp = route.path;
            fn.keys = route.keys;
            fn.path = route.orig;
            fn.method = route.method;
            fn.index = i;
            ret.push(fn);
          }
        });
      }
    // global lookup
    } else {
      _methods.forEach(function(method){
        router.lookup(path, method, ret);
      });
    }

    return ret;
  };

  router.match = function(url, method, ret){
    var ret = ret || []
      , i = 0
      , fn
      , req;

    // method specific matches
    if (method) {
      method = method.toUpperCase();
      req = { url: url, method: method };
      while (fn = match(req, routes, i)) {
        i = req._route_index + 1;
        ret.push(fn);
      }
    // global matches
    } else {
      _methods.forEach(function(method){
        router.match(url, method, ret);
      });
    }

    return ret;
  };

  return router;
}

/**
 * Respond to OPTIONS.
 *
 * @param {ServerRequest} req
 * @param {ServerResponse} req
 * @param {Array} routes
 * @api private
 */

function options(req, res, routes) {
  var pathname = parse(req.url).pathname
    , body = optionsFor(pathname, routes).join(',');
  res.writeHead(200, {
      'Content-Length': body.length
    , 'Allow': body
  });
  res.end(body);
}

/**
 * Return OPTIONS array for the given `path`, matching `routes`.
 *
 * @param {String} path
 * @param {Array} routes
 * @return {Array}
 * @api private
 */

function optionsFor(path, routes) {
  return _methods.filter(function(method){
    var arr = routes[method.toUpperCase()];
    for (var i = 0, len = arr.length; i < len; ++i) {
      if (arr[i].path.test(path)) return true;
    }
  }).map(function(method){
    return method.toUpperCase();
  });
}

/**
 * Normalize the given path string,
 * returning a regular expression.
 *
 * An empty array should be passed,
 * which will contain the placeholder
 * key names. For example "/user/:id" will
 * then contain ["id"].
 *
 * @param  {String} path
 * @param  {Array} keys
 * @return {RegExp}
 * @api private
 */

function normalizePath(path, keys) {
  path = path
    .concat('/?')
    .replace(/\/\(/g, '(?:/')
    .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?/g, function(_, slash, format, key, capture, optional){
      keys.push(key);
      slash = slash || '';
      return ''
        + (optional ? '' : slash)
        + '(?:'
        + (optional ? slash : '')
        + (format || '') + (capture || '([^/]+?)') + ')'
        + (optional || '');
    })
    .replace(/([\/.])/g, '\\$1')
    .replace(/\*/g, '(.+)');
  return new RegExp('^' + path + '$', 'i');
}

/**
 * Attempt to match the given request to
 * one of the routes. When successful
 * a route function is returned.
 *
 * @param  {ServerRequest} req
 * @param  {Object} routes
 * @return {Function}
 * @api private
 */

function match(req, routes, i) {
  var captures
    , method = req.method
    , i = i || 0;
  if ('HEAD' == method.toUpperCase()) method = 'GET';
  if (routes = routes[method]) {
    var url = parse(req.url)
      , pathname = url.pathname;
    for (var len = routes.length; i < len; ++i) {
      var route = routes[i]
        , fn = route.fn
        , path = route.path
        , keys = fn.keys = route.keys;
      if (captures = path.exec(pathname)) {
        fn.method = method;
        fn.params = [];
        for (var j = 1, len = captures.length; j < len; ++j) {
          var key = keys[j-1],
            val = typeof captures[j] === 'string'
              ? decodeURIComponent(captures[j])
              : captures[j];
          if (key) {
            fn.params[key] = val;
          } else {
            fn.params.push(val);
          }
        }
        req._route_index = i;
        return fn;
      }
    }
  }
}
<|endoftext|>


<commit_before>// Copyright 2017, University of Colorado Boulder

/**
 * IO type for SimIframeAPI
 *
 * @author - Michael Kauzmann (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var ObjectIO = require( 'PHET_IO/types/ObjectIO' );
  var phetioInherit = require( 'PHET_IO/phetioInherit' );
  var phetioNamespace = require( 'PHET_IO/phetioNamespace' );

  /**
   * @param {SimIFrameAPI} instance
   * @param {string} phetioID
   * @constructor
   */
  function SimIFrameAPIIO( instance, phetioID ) {
    // assert && assertInstanceOf( instance, phet.phetIo.SimIFrameAPI ); // TODO: enable this line
    ObjectIO.call( this, instance, phetioID );
  }

  phetioInherit( ObjectIO, 'SimIFrameAPIIO', SimIFrameAPIIO,

    // Instance methods
    {},

    // Static methods
    {
      events: [ 'invoked' ],
      documentation: 'Instance of a SimIFrameAPI.'
    }
  );

  phetioNamespace.register( 'SimIFrameAPIIO', SimIFrameAPIIO );

  return SimIFrameAPIIO;
} );<commit_msg>Standardized header JSDoc around author annotations<commit_after>// Copyright 2017, University of Colorado Boulder

/**
 * IO type for SimIframeAPI
 *
 * @author Michael Kauzmann (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var ObjectIO = require( 'PHET_IO/types/ObjectIO' );
  var phetioInherit = require( 'PHET_IO/phetioInherit' );
  var phetioNamespace = require( 'PHET_IO/phetioNamespace' );

  /**
   * @param {SimIFrameAPI} instance
   * @param {string} phetioID
   * @constructor
   */
  function SimIFrameAPIIO( instance, phetioID ) {
    // assert && assertInstanceOf( instance, phet.phetIo.SimIFrameAPI ); // TODO: enable this line
    ObjectIO.call( this, instance, phetioID );
  }

  phetioInherit( ObjectIO, 'SimIFrameAPIIO', SimIFrameAPIIO,

    // Instance methods
    {},

    // Static methods
    {
      events: [ 'invoked' ],
      documentation: 'Instance of a SimIFrameAPI.'
    }
  );

  phetioNamespace.register( 'SimIFrameAPIIO', SimIFrameAPIIO );

  return SimIFrameAPIIO;
} );<|endoftext|>


<commit_before>// Copyright 2014 Globo.com Player authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

import {seekStringToSeconds} from 'base/utils'

import Playback from 'base/playback'
import template from 'base/template'
import Styler from 'base/styler'
import Browser from 'components/browser'
import Events from 'base/events'
import tagStyle from './public/style.scss'
import sourceHTML from './public/index.html'
import find from 'lodash.find'

const MIMETYPES = {
  'mp4': ["avc1.42E01E", "avc1.58A01E", "avc1.4D401E", "avc1.64001E", "mp4v.20.8", "mp4v.20.240", "mp4a.40.2"].map(
    (codec) => { return 'video/mp4; codecs="' + codec + ', mp4a.40.2"'}),
  'ogg': ['video/ogg; codecs="theora, vorbis"', 'video/ogg; codecs="dirac"', 'video/ogg; codecs="theora, speex"'],
  '3gpp': ['video/3gpp; codecs="mp4v.20.8, samr"'],
  'webm': ['video/webm; codecs="vp8, vorbis"'],
  'mkv': ['video/x-matroska; codecs="theora, vorbis"'],
  'm3u8': ['application/x-mpegurl']
}
MIMETYPES['ogv'] = MIMETYPES['ogg']
MIMETYPES['3gp'] = MIMETYPES['3gpp']

export default class HTML5Video extends Playback {
  get name() { return 'html5_video' }
  get tagName() { return 'video' }
  get template() { return template(sourceHTML) }

  get attributes() {
    return {
      'data-html5-video': ''
    }
  }

  get events() {
    return {
      'canplay': 'handleBufferingEvents',
      'canplaythrough': 'handleBufferingEvents',
      'durationchange': 'onDurationChange',
      'ended': 'onEnded',
      'error': 'onError',
      'loadedmetadata': 'onLoadedMetadata',
      'loadstart': 'onLoadStart',
      'pause': 'onPause',
      'playing': 'onPlaying',
      'progress': 'onProgress',
      'seeked': 'handleBufferingEvents',
      'seeking': 'handleBufferingEvents',
      'stalled': 'handleBufferingEvents',
      'timeupdate': 'onTimeUpdate',
      'waiting': 'handleBufferingEvents'
    }
  }

  /**
   * Determine if the playback has ended.
   * @property ended
   * @type Boolean
   */
  get ended() {
    return this.el.ended
  }

  /**
   * Determine if the playback is having to buffer in order for
   * playback to be smooth.
   * This is related to the PLAYBACK_BUFFERING and PLAYBACK_BUFFERFULL events
   * @property buffering
   * @type Boolean
   */
  get buffering() {
    return this.bufferingState
  }

  constructor(options) {
    super(options)
    this.loadStarted = false
    this.playheadMoving = false
    this.playheadMovingTimeOnCheck = null
    this.playheadMovingTimer = setInterval(this.determineIfPlayheadMoving.bind(this), 500)
    this.options = options
    this.setupSrc(options.src)
    this.el.loop = options.loop
    if (options.poster) {
      this.$el.attr("poster", options.poster)
    }
    this.el.autoplay = options.autoPlay
    if (Browser.isSafari) {
      this.setupSafari()
    } else {
      this.el.preload = options.preload ? options.preload: 'metadata'
      this.settings.seekEnabled = true
    }
    this.settings = {default: ['seekbar']}
    this.settings.left = ["playpause", "position", "duration"]
    this.settings.right = ["fullscreen", "volume", "hd-indicator"]
  }

  /**
   * Sets the source url on the <video> element, and also the 'src' property.
   * @method setupSrc
   * @param {String} srcUrl The source URL.
   */
  setupSrc(srcUrl) {
    this.src = srcUrl
    this.el.src = srcUrl
  }

  setupSafari() {
    this.el.preload = 'auto'
  }

  onLoadedMetadata(e) {
    this.handleBufferingEvents()
    this.trigger(Events.PLAYBACK_LOADEDMETADATA, {duration: e.target.duration, data: e})
    this.updateSettings()
    var autoSeekFromUrl = typeof(this.options.autoSeekFromUrl) === "undefined" || this.options.autoSeekFromUrl
    if (this.getPlaybackType() !== Playback.LIVE && autoSeekFromUrl) {
      this.checkInitialSeek()
    }
  }

  onDurationChange() {
    this.updateSettings()
    this.onTimeUpdate()
  }

  updateSettings() {
    // we can't figure out if hls resource is VoD or not until it is being loaded or duration has changed.
    // that's why we check it again and update media control accordingly.
    if (this.getPlaybackType() === Playback.VOD) {
      this.settings.left = ["playpause", "position", "duration"]
    } else {
      this.settings.left = ["playstop"]
    }
    this.settings.seekEnabled = this.isSeekEnabled()
    this.trigger(Events.PLAYBACK_SETTINGSUPDATE)
  }

  isSeekEnabled() {
    return isFinite(this.getDuration())
  }

  getPlaybackType() {
    return [0, undefined, Infinity].indexOf(this.el.duration) >= 0 ? Playback.LIVE : Playback.VOD
  }

  isHighDefinitionInUse() {
    return false
  }

  play() {
    if (!this.loadStarted && this.el.preload === 'none') {
      this.loadStarted = true
      this.handleBufferingEvents()
    }
    this.el.play()
  }

  pause() {
    this.el.pause()
  }

  stop() {
    this.pause()
    this.el.currentTime = 0
    this.handleBufferingEvents()
    this.trigger(Events.PLAYBACK_STOP)
  }

  volume(value) {
    this.el.volume = value / 100
  }

  mute() {
    this.el.volume = 0
  }

  unmute() {
    this.el.volume = 1
  }

  isMuted() {
    return !!this.el.volume
  }

  isPlaying() {
    return !this.el.paused && !this.el.ended
  }

  get isReady() {
    return this.isReadyState
  }

  determineIfPlayheadMoving() {
    var before = this.playheadMovingTimeOnCheck
    var now = this.el.currentTime
    this.playheadMoving = before !== now
    this.playheadMovingTimeOnCheck = now
    this.handleBufferingEvents()
  }

  onLoadStart() {
    if (this.el.preload !== 'none') {
      // when preload is none the onLoadStart event is still fired
      // immediately. Pretend that load starts in play()
      this.loadStarted = true
      this.handleBufferingEvents()
    }
  }

  onPlaying() {
    this.handleBufferingEvents()
    this.trigger(Events.PLAYBACK_PLAY)
  }

  onPause() {
    this.handleBufferingEvents()
    this.trigger(Events.PLAYBACK_PAUSE)
  }

  onEnded() {
    this.handleBufferingEvents()
    this.trigger(Events.PLAYBACK_ENDED, this.name)
  }

  // The playback should be classed as buffering if the following are true:
  // - the ready state is less then HAVE_FUTURE_DATA or the playhead isn't moving and it should be
  // - the media hasn't "ended"
  // - loading has started
  handleBufferingEvents() {
    var playheadShouldBeMoving = !this.el.ended && !this.el.paused
    var buffering = this.loadStarted && !this.el.ended && ((playheadShouldBeMoving && !this.playheadMoving) || this.el.readyState < this.el.HAVE_FUTURE_DATA)
    if (this.bufferingState !== buffering) {
      this.bufferingState = buffering
      if (buffering) {
        this.trigger(Events.PLAYBACK_BUFFERING, this.name)
      }
      else {
        this.trigger(Events.PLAYBACK_BUFFERFULL, this.name)
      }
    }
  }

  onError(event) {
    this.trigger(Events.PLAYBACK_ERROR, this.el.error, this.name)
  }

  destroy() {
    this.stop()
    this.el.src = ''
    this.src = ''
    clearInterval(this.playheadMovingTimer)
    this.$el.remove()
  }

  seek(time) {
    this.el.currentTime = time
  }

  seekPercentage(percentage) {
    var time = this.el.duration * (percentage / 100)
    this.seek(time)
  }

  checkInitialSeek() {
    var seekTime = seekStringToSeconds(window.location.href)
    if (seekTime !== 0) {
      this.seek(seekTime)
    }
  }

  getCurrentTime() {
    return this.el.currentTime
  }

  getDuration() {
    return this.el.duration
  }

  onTimeUpdate() {
    this.handleBufferingEvents()
    if (this.getPlaybackType() === Playback.LIVE) {
      this.trigger(Events.PLAYBACK_TIMEUPDATE, {current: 1, total: 1}, this.name)
    } else {
      this.trigger(Events.PLAYBACK_TIMEUPDATE, {current: this.el.currentTime, total: this.el.duration}, this.name)
    }
  }

  onProgress() {
    if (!this.el.buffered.length) {
      return
    }
    var bufferedPos = 0
    for (var i = 0;  i < this.el.buffered.length; i++) {
      if (this.el.currentTime >= this.el.buffered.start(i) && this.el.currentTime <= this.el.buffered.end(i)) {
        bufferedPos = i
        break
      }
    }
    this.trigger(Events.PLAYBACK_PROGRESS, {
      start: this.el.buffered.start(bufferedPos),
      current: this.el.buffered.end(bufferedPos),
      total: this.el.duration
    })
  }

  typeFor(src) {
    return 'video/mp4'
  }

  ready() {
    if (this.isReadyState) {
      return
    }
    this.isReadyState = true
    this.trigger(Events.PLAYBACK_READY, this.name)
  }

  render() {
    var style = Styler.getStyleFor(tagStyle)

    this.src && this.$el.html(this.template({ src: this.src, type: this.typeFor(this.src) }))

    if (this.options.useVideoTagDefaultControls) {
      this.$el.attr('controls', 'controls')
    }

    if (this.options.disableVideoTagContextMenu) {
      this.$el.on("contextmenu", () => {
        return false
      })
    }

    this.$el.append(style)
    this.ready()
    return this
  }
}

HTML5Video._canPlay = function(type, mimeTypesByExtension, resourceUrl, mimeType) {
  var extension = (resourceUrl.split('?')[0].match(/.*\.(.*)$/) || [])[1]
  var mimeTypes = mimeType || mimeTypesByExtension[extension] || []
  mimeTypes = (mimeTypes.constructor === Array) ? mimeTypes : [mimeTypes]

  var media = document.createElement(type)
  return !!find(mimeTypes, (mediaType) => !!media.canPlayType(mediaType).replace(/no/, ''))
}

HTML5Video.canPlay = function(resourceUrl, mimeType) {
  return HTML5Video._canPlay('video', MIMETYPES, resourceUrl, mimeType)
}

module.exports = HTML5Video
<commit_msg>set 'src' back to null to match the initial value<commit_after>// Copyright 2014 Globo.com Player authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

import {seekStringToSeconds} from 'base/utils'

import Playback from 'base/playback'
import template from 'base/template'
import Styler from 'base/styler'
import Browser from 'components/browser'
import Events from 'base/events'
import tagStyle from './public/style.scss'
import sourceHTML from './public/index.html'
import find from 'lodash.find'

const MIMETYPES = {
  'mp4': ["avc1.42E01E", "avc1.58A01E", "avc1.4D401E", "avc1.64001E", "mp4v.20.8", "mp4v.20.240", "mp4a.40.2"].map(
    (codec) => { return 'video/mp4; codecs="' + codec + ', mp4a.40.2"'}),
  'ogg': ['video/ogg; codecs="theora, vorbis"', 'video/ogg; codecs="dirac"', 'video/ogg; codecs="theora, speex"'],
  '3gpp': ['video/3gpp; codecs="mp4v.20.8, samr"'],
  'webm': ['video/webm; codecs="vp8, vorbis"'],
  'mkv': ['video/x-matroska; codecs="theora, vorbis"'],
  'm3u8': ['application/x-mpegurl']
}
MIMETYPES['ogv'] = MIMETYPES['ogg']
MIMETYPES['3gp'] = MIMETYPES['3gpp']

export default class HTML5Video extends Playback {
  get name() { return 'html5_video' }
  get tagName() { return 'video' }
  get template() { return template(sourceHTML) }

  get attributes() {
    return {
      'data-html5-video': ''
    }
  }

  get events() {
    return {
      'canplay': 'handleBufferingEvents',
      'canplaythrough': 'handleBufferingEvents',
      'durationchange': 'onDurationChange',
      'ended': 'onEnded',
      'error': 'onError',
      'loadedmetadata': 'onLoadedMetadata',
      'loadstart': 'onLoadStart',
      'pause': 'onPause',
      'playing': 'onPlaying',
      'progress': 'onProgress',
      'seeked': 'handleBufferingEvents',
      'seeking': 'handleBufferingEvents',
      'stalled': 'handleBufferingEvents',
      'timeupdate': 'onTimeUpdate',
      'waiting': 'handleBufferingEvents'
    }
  }

  /**
   * Determine if the playback has ended.
   * @property ended
   * @type Boolean
   */
  get ended() {
    return this.el.ended
  }

  /**
   * Determine if the playback is having to buffer in order for
   * playback to be smooth.
   * This is related to the PLAYBACK_BUFFERING and PLAYBACK_BUFFERFULL events
   * @property buffering
   * @type Boolean
   */
  get buffering() {
    return this.bufferingState
  }

  constructor(options) {
    super(options)
    this.loadStarted = false
    this.playheadMoving = false
    this.playheadMovingTimeOnCheck = null
    this.playheadMovingTimer = setInterval(this.determineIfPlayheadMoving.bind(this), 500)
    this.options = options
    this.setupSrc(options.src)
    this.el.loop = options.loop
    if (options.poster) {
      this.$el.attr("poster", options.poster)
    }
    this.el.autoplay = options.autoPlay
    if (Browser.isSafari) {
      this.setupSafari()
    } else {
      this.el.preload = options.preload ? options.preload: 'metadata'
      this.settings.seekEnabled = true
    }
    this.settings = {default: ['seekbar']}
    this.settings.left = ["playpause", "position", "duration"]
    this.settings.right = ["fullscreen", "volume", "hd-indicator"]
  }

  /**
   * Sets the source url on the <video> element, and also the 'src' property.
   * @method setupSrc
   * @param {String} srcUrl The source URL.
   */
  setupSrc(srcUrl) {
    this.src = srcUrl
    this.el.src = srcUrl
  }

  setupSafari() {
    this.el.preload = 'auto'
  }

  onLoadedMetadata(e) {
    this.handleBufferingEvents()
    this.trigger(Events.PLAYBACK_LOADEDMETADATA, {duration: e.target.duration, data: e})
    this.updateSettings()
    var autoSeekFromUrl = typeof(this.options.autoSeekFromUrl) === "undefined" || this.options.autoSeekFromUrl
    if (this.getPlaybackType() !== Playback.LIVE && autoSeekFromUrl) {
      this.checkInitialSeek()
    }
  }

  onDurationChange() {
    this.updateSettings()
    this.onTimeUpdate()
  }

  updateSettings() {
    // we can't figure out if hls resource is VoD or not until it is being loaded or duration has changed.
    // that's why we check it again and update media control accordingly.
    if (this.getPlaybackType() === Playback.VOD) {
      this.settings.left = ["playpause", "position", "duration"]
    } else {
      this.settings.left = ["playstop"]
    }
    this.settings.seekEnabled = this.isSeekEnabled()
    this.trigger(Events.PLAYBACK_SETTINGSUPDATE)
  }

  isSeekEnabled() {
    return isFinite(this.getDuration())
  }

  getPlaybackType() {
    return [0, undefined, Infinity].indexOf(this.el.duration) >= 0 ? Playback.LIVE : Playback.VOD
  }

  isHighDefinitionInUse() {
    return false
  }

  play() {
    if (!this.loadStarted && this.el.preload === 'none') {
      this.loadStarted = true
      this.handleBufferingEvents()
    }
    this.el.play()
  }

  pause() {
    this.el.pause()
  }

  stop() {
    this.pause()
    this.el.currentTime = 0
    this.handleBufferingEvents()
    this.trigger(Events.PLAYBACK_STOP)
  }

  volume(value) {
    this.el.volume = value / 100
  }

  mute() {
    this.el.volume = 0
  }

  unmute() {
    this.el.volume = 1
  }

  isMuted() {
    return !!this.el.volume
  }

  isPlaying() {
    return !this.el.paused && !this.el.ended
  }

  get isReady() {
    return this.isReadyState
  }

  determineIfPlayheadMoving() {
    var before = this.playheadMovingTimeOnCheck
    var now = this.el.currentTime
    this.playheadMoving = before !== now
    this.playheadMovingTimeOnCheck = now
    this.handleBufferingEvents()
  }

  onLoadStart() {
    if (this.el.preload !== 'none') {
      // when preload is none the onLoadStart event is still fired
      // immediately. Pretend that load starts in play()
      this.loadStarted = true
      this.handleBufferingEvents()
    }
  }

  onPlaying() {
    this.handleBufferingEvents()
    this.trigger(Events.PLAYBACK_PLAY)
  }

  onPause() {
    this.handleBufferingEvents()
    this.trigger(Events.PLAYBACK_PAUSE)
  }

  onEnded() {
    this.handleBufferingEvents()
    this.trigger(Events.PLAYBACK_ENDED, this.name)
  }

  // The playback should be classed as buffering if the following are true:
  // - the ready state is less then HAVE_FUTURE_DATA or the playhead isn't moving and it should be
  // - the media hasn't "ended"
  // - loading has started
  handleBufferingEvents() {
    var playheadShouldBeMoving = !this.el.ended && !this.el.paused
    var buffering = this.loadStarted && !this.el.ended && ((playheadShouldBeMoving && !this.playheadMoving) || this.el.readyState < this.el.HAVE_FUTURE_DATA)
    if (this.bufferingState !== buffering) {
      this.bufferingState = buffering
      if (buffering) {
        this.trigger(Events.PLAYBACK_BUFFERING, this.name)
      }
      else {
        this.trigger(Events.PLAYBACK_BUFFERFULL, this.name)
      }
    }
  }

  onError(event) {
    this.trigger(Events.PLAYBACK_ERROR, this.el.error, this.name)
  }

  destroy() {
    this.stop()
    this.el.src = ''
    this.src = null
    clearInterval(this.playheadMovingTimer)
    this.$el.remove()
  }

  seek(time) {
    this.el.currentTime = time
  }

  seekPercentage(percentage) {
    var time = this.el.duration * (percentage / 100)
    this.seek(time)
  }

  checkInitialSeek() {
    var seekTime = seekStringToSeconds(window.location.href)
    if (seekTime !== 0) {
      this.seek(seekTime)
    }
  }

  getCurrentTime() {
    return this.el.currentTime
  }

  getDuration() {
    return this.el.duration
  }

  onTimeUpdate() {
    this.handleBufferingEvents()
    if (this.getPlaybackType() === Playback.LIVE) {
      this.trigger(Events.PLAYBACK_TIMEUPDATE, {current: 1, total: 1}, this.name)
    } else {
      this.trigger(Events.PLAYBACK_TIMEUPDATE, {current: this.el.currentTime, total: this.el.duration}, this.name)
    }
  }

  onProgress() {
    if (!this.el.buffered.length) {
      return
    }
    var bufferedPos = 0
    for (var i = 0;  i < this.el.buffered.length; i++) {
      if (this.el.currentTime >= this.el.buffered.start(i) && this.el.currentTime <= this.el.buffered.end(i)) {
        bufferedPos = i
        break
      }
    }
    this.trigger(Events.PLAYBACK_PROGRESS, {
      start: this.el.buffered.start(bufferedPos),
      current: this.el.buffered.end(bufferedPos),
      total: this.el.duration
    })
  }

  typeFor(src) {
    return 'video/mp4'
  }

  ready() {
    if (this.isReadyState) {
      return
    }
    this.isReadyState = true
    this.trigger(Events.PLAYBACK_READY, this.name)
  }

  render() {
    var style = Styler.getStyleFor(tagStyle)

    this.src && this.$el.html(this.template({ src: this.src, type: this.typeFor(this.src) }))

    if (this.options.useVideoTagDefaultControls) {
      this.$el.attr('controls', 'controls')
    }

    if (this.options.disableVideoTagContextMenu) {
      this.$el.on("contextmenu", () => {
        return false
      })
    }

    this.$el.append(style)
    this.ready()
    return this
  }
}

HTML5Video._canPlay = function(type, mimeTypesByExtension, resourceUrl, mimeType) {
  var extension = (resourceUrl.split('?')[0].match(/.*\.(.*)$/) || [])[1]
  var mimeTypes = mimeType || mimeTypesByExtension[extension] || []
  mimeTypes = (mimeTypes.constructor === Array) ? mimeTypes : [mimeTypes]

  var media = document.createElement(type)
  return !!find(mimeTypes, (mediaType) => !!media.canPlayType(mediaType).replace(/no/, ''))
}

HTML5Video.canPlay = function(resourceUrl, mimeType) {
  return HTML5Video._canPlay('video', MIMETYPES, resourceUrl, mimeType)
}

module.exports = HTML5Video
<|endoftext|>