<commit_before>var qid;  // id of the last posed question
var gen_sources, gen_answers;  // when this number changes, re-render

/* Create a fancy score bar representing confidence of an answer. */
function score_bar(score) {
	var green = Math.round(200 * score + 25);
	var red = Math.round(200 * (1-score) + 25);
	return '
 ';
}

/* Create a box with question summary. */
function showSummary(container, summary) {
	container.empty();
	container.append("
Answer type: " + summary.lats.join(', ') + "
");
	summary.concepts.forEach(function(c) {
		container.append('
'
				+ ''
				+ ' '
				+ c.title + '
'); // TODO also include the first sentence?
	});
}

/* Create a box with answer sources. */
function showSources(container, sources) {
	container.empty();
        $.each(sources, function(sid, source) {
		var state_stags = ['', '', ''];
		var state_etags = ['', '', ''];
        if (source.type == "enwiki" && source.origin != "document title") {
            container.append('
'
                + ''
                + ' '
                + state_stags[source.state] + source.title + state_etags[source.state]
                + ' (' + source.origin + ')
'); // TODO also include the first sentence?
        }
	});
}

/* Create a table with answers. */
function showAnswers(container, answers, snippets, sources) {
	container.empty();
	var i = 1;
	answers.forEach(function(a) {
		// FIXME: also deal with < > &
		text = a.text.replace(/"/g, """);
        var str="";

        for(var index = 0; index< a.snippetIDs.length; index++) {
            //origin is (fulltext)/(title-in-clue)/(documented search)
	    source = sources[snippets[a.snippetIDs[index]].sourceID]
            str += "(" + source.type + " " + source.origin + ") \n";
            str += source.title + " \n";

            //add either wikipedia document ID or source URL
	    if (source.type == "enwiki") {
		    str += source.pageId + "\n";
	    } else {
		    str += source.URL + "\n";
	    }

            //add either passage text or property label
            if (!(typeof (snippets[a.snippetIDs[index]].passageText) ==="undefined")) {
                str += snippets[a.snippetIDs[index]].passageText.replace(/"/g, """) + "\n";
            }
            else if (!(typeof (snippets[a.snippetIDs[index]].propertyLabel) ==="undefined")) {
                str += snippets[a.snippetIDs[index]].propertyLabel + "\n";
            }
        }
		container.append('
'+i+'.	'
				+ ''+text+'	'
				+ ''+score_bar(a.confidence)+'	'
				+ ''+(a.confidence*100).toFixed(1)+'%
');
		i++;
	});
}

/* Retrieve, process and display json question information. */
function getQuestionJson() {
	$.get("/q/"+qid, function(r) {
		$('input[name="text"]').val(r.text);

		if (r.summary) {
			/* Show the question summary. */
			container = $("#summary");
			if (!container.length) {
				container = $('

');
				$("#metadata_area").prepend(container);
				showSummary(container, r.summary);
			}
		}

		if (!$.isEmptyObject(r.sources) && gen_sources != r.gen_sources) {
			/* Show the answer sources. */
			container = $("#sources");
			if (!container.length) {
				container = $('

');
				$("#metadata_area").prepend(container);
			}
			showSources(container, r.sources);
			gen_sources = r.gen_sources;
		}

		if (r.answers && gen_answers != r.gen_answers) {
			/* Show the list of answers. */
			container = $("#answers");
			if (!container.length) {
				container = $('

');
				$("#answers_area").prepend(container);
			}
			showAnswers(container, r.answers, r.snippets, r.sources);
			gen_answers = r.gen_answers;
		}

		if (r.finished) {
			$("#spinner").hide();
		} else {
			// keep watching
			setTimeout(getQuestionJson, 500);
		}
	});
}

/* Create a titled listing of questions. */
function showQuestionList(container, title, list) {
	container.empty();
	container.append('
' + title + '
');
	list.forEach(function(q) {
		container.append('
'+q.text+'
');
	});
}

/* Retrieve, process and display json question list. */
function getToAnswerJson() {
	$.get("/q/?toAnswer", function(r) { showQuestionList($("#toAnswer"), "Question Queue", r); });
}
function getInProgressJson() {
	$.get("/q/?inProgress", function(r) { showQuestionList($("#inProgress"), "In Progress", r); });
}
function getAnsweredJson() {
	$.get("/q/?answered", function(r) { showQuestionList($("#answered"), "Answered", r); });
}

function loadQuestion(q) {
	$("#metadata_area").empty();
	$("#answers_area").empty();
	$("#spinner").show();
	qid = q;
	gen_sources = 0;
	gen_answers = 0;
	getQuestionJson();
}

$(function() {
$("#ask").ajaxForm({
	success: function(response) {
		setTimeout(function() { loadQuestion(JSON.parse(response).id) }, 500);
	}});

getToAnswerJson(); setInterval(getToAnswerJson, 3100);
getInProgressJson(); setInterval(getInProgressJson, 3000);
getAnsweredJson(); setInterval(getAnsweredJson, 2900);
});
<commit_msg>webpublic showSources(): Show all sources but 'document title', even structured, and source type<commit_after>var qid;  // id of the last posed question
var gen_sources, gen_answers;  // when this number changes, re-render

/* Create a fancy score bar representing confidence of an answer. */
function score_bar(score) {
	var green = Math.round(200 * score + 25);
	var red = Math.round(200 * (1-score) + 25);
	return '
 ';
}

/* Create a box with question summary. */
function showSummary(container, summary) {
	container.empty();
	container.append("
Answer type: " + summary.lats.join(', ') + "
");
	summary.concepts.forEach(function(c) {
		container.append('
'
				+ ''
				+ ' '
				+ c.title + '
'); // TODO also include the first sentence?
	});
}

/* Create a box with answer sources. */
function showSources(container, sources) {
	container.empty();
        $.each(sources, function(sid, source) {
		var state_stags = ['', '', ''];
		var state_etags = ['', '', ''];
        if (source.origin != "document title") {
		if (source.type == "enwiki") {
			url = 'http://en.wikipedia.org/?curid=' + source.pageId;
		} else {
			url = source.URL;
		}
            container.append('
'
                + ''
                + ' '
                + state_stags[source.state] + source.title + state_etags[source.state]
                + ' (' + source.type + ' ' + source.origin + ')
'); // TODO also include the first sentence?
        }
	});
}

/* Create a table with answers. */
function showAnswers(container, answers, snippets, sources) {
	container.empty();
	var i = 1;
	answers.forEach(function(a) {
		// FIXME: also deal with < > &
		text = a.text.replace(/"/g, """);
        var str="";

        for(var index = 0; index< a.snippetIDs.length; index++) {
            //origin is (fulltext)/(title-in-clue)/(documented search)
	    source = sources[snippets[a.snippetIDs[index]].sourceID]
            str += "(" + source.type + " " + source.origin + ") \n";
            str += source.title + " \n";

            //add either wikipedia document ID or source URL
	    if (source.type == "enwiki") {
		    str += source.pageId + "\n";
	    } else {
		    str += source.URL + "\n";
	    }

            //add either passage text or property label
            if (!(typeof (snippets[a.snippetIDs[index]].passageText) ==="undefined")) {
                str += snippets[a.snippetIDs[index]].passageText.replace(/"/g, """) + "\n";
            }
            else if (!(typeof (snippets[a.snippetIDs[index]].propertyLabel) ==="undefined")) {
                str += snippets[a.snippetIDs[index]].propertyLabel + "\n";
            }
        }
		container.append('
'+i+'.	'
				+ ''+text+'	'
				+ ''+score_bar(a.confidence)+'	'
				+ ''+(a.confidence*100).toFixed(1)+'%
');
		i++;
	});
}

/* Retrieve, process and display json question information. */
function getQuestionJson() {
	$.get("/q/"+qid, function(r) {
		$('input[name="text"]').val(r.text);

		if (r.summary) {
			/* Show the question summary. */
			container = $("#summary");
			if (!container.length) {
				container = $('

');
				$("#metadata_area").prepend(container);
				showSummary(container, r.summary);
			}
		}

		if (!$.isEmptyObject(r.sources) && gen_sources != r.gen_sources) {
			/* Show the answer sources. */
			container = $("#sources");
			if (!container.length) {
				container = $('

');
				$("#metadata_area").prepend(container);
			}
			showSources(container, r.sources);
			gen_sources = r.gen_sources;
		}

		if (r.answers && gen_answers != r.gen_answers) {
			/* Show the list of answers. */
			container = $("#answers");
			if (!container.length) {
				container = $('

');
				$("#answers_area").prepend(container);
			}
			showAnswers(container, r.answers, r.snippets, r.sources);
			gen_answers = r.gen_answers;
		}

		if (r.finished) {
			$("#spinner").hide();
		} else {
			// keep watching
			setTimeout(getQuestionJson, 500);
		}
	});
}

/* Create a titled listing of questions. */
function showQuestionList(container, title, list) {
	container.empty();
	container.append('
' + title + '
');
	list.forEach(function(q) {
		container.append('
'+q.text+'
');
	});
}

/* Retrieve, process and display json question list. */
function getToAnswerJson() {
	$.get("/q/?toAnswer", function(r) { showQuestionList($("#toAnswer"), "Question Queue", r); });
}
function getInProgressJson() {
	$.get("/q/?inProgress", function(r) { showQuestionList($("#inProgress"), "In Progress", r); });
}
function getAnsweredJson() {
	$.get("/q/?answered", function(r) { showQuestionList($("#answered"), "Answered", r); });
}

function loadQuestion(q) {
	$("#metadata_area").empty();
	$("#answers_area").empty();
	$("#spinner").show();
	qid = q;
	gen_sources = 0;
	gen_answers = 0;
	getQuestionJson();
}

$(function() {
$("#ask").ajaxForm({
	success: function(response) {
		setTimeout(function() { loadQuestion(JSON.parse(response).id) }, 500);
	}});

getToAnswerJson(); setInterval(getToAnswerJson, 3100);
getInProgressJson(); setInterval(getInProgressJson, 3000);
getAnsweredJson(); setInterval(getAnsweredJson, 2900);
});
<|endoftext|>


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

/**
 * Monitors the memory usage over time.
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
define( require => {
  'use strict';

  // modules
  const joist = require( 'JOIST/joist' );
  const RunningAverage = require( 'DOT/RunningAverage' );

  // constants
  const MB = 1024 * 1024;

  // globals
  let hadMemoryFailure = false;

  class MemoryMonitor {
    /**
     * @param {Object} [options]
     */
    constructor( options ) {
      options = _.extend( {
        // {number} - Quantity of measurements in the running average
        windowSize: 2000,

        // {number} - Number of megabytes before operations will throw an error
        memoryLimit: phet.chipper.queryParameters.memoryLimit
      }, options );

      // @private {number}
      this.memoryLimit = options.memoryLimit * MB;

      // @public {RunningAverage}
      this.runningAverage = new RunningAverage( options.windowSize );

      // @public {number}
      this.lastMemory = 0;
    }

    /**
     * Records a memory measurement.
     * @public
     */
    measure() {
      if ( !window.performance || !window.performance.memory || !window.performance.memory.usedJSHeapSize ) {
        return;
      }

      const currentMemory = window.performance.memory.usedJSHeapSize;
      this.lastMemory = currentMemory;
      const averageMemory = this.runningAverage.updateRunningAverage( currentMemory );

      if ( this.memoryLimit &&
           this.runningAverage.isSaturated() &&
           !hadMemoryFailure &&
           averageMemory > this.memoryLimit &&
           currentMemory > this.memoryLimit * 0.5 ) {
        hadMemoryFailure = true;
        throw new Error( 'Average memory used (' + MemoryMonitor.memoryString( averageMemory ) + ') is above our memoryLimit (' + MemoryMonitor.memoryString( this.memoryLimit ) + '). Current memory: ' + MemoryMonitor.memoryString( currentMemory ) + '.' );
      }
    }

    /**
     * Convers a number of bytes into a quick-to-read memory string.
     * @public
     *
     * @param {number} bytes
     * @returns {string}
     */
    static memoryString( bytes ) {
      return Math.ceil( bytes / MB ) + 'MB';
    }
  }

  return joist.register( 'MemoryMonitor', MemoryMonitor );
} );<commit_msg>update copyright dates from daily grunt work<commit_after>// Copyright 2018-2019, University of Colorado Boulder

/**
 * Monitors the memory usage over time.
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
define( require => {
  'use strict';

  // modules
  const joist = require( 'JOIST/joist' );
  const RunningAverage = require( 'DOT/RunningAverage' );

  // constants
  const MB = 1024 * 1024;

  // globals
  let hadMemoryFailure = false;

  class MemoryMonitor {
    /**
     * @param {Object} [options]
     */
    constructor( options ) {
      options = _.extend( {
        // {number} - Quantity of measurements in the running average
        windowSize: 2000,

        // {number} - Number of megabytes before operations will throw an error
        memoryLimit: phet.chipper.queryParameters.memoryLimit
      }, options );

      // @private {number}
      this.memoryLimit = options.memoryLimit * MB;

      // @public {RunningAverage}
      this.runningAverage = new RunningAverage( options.windowSize );

      // @public {number}
      this.lastMemory = 0;
    }

    /**
     * Records a memory measurement.
     * @public
     */
    measure() {
      if ( !window.performance || !window.performance.memory || !window.performance.memory.usedJSHeapSize ) {
        return;
      }

      const currentMemory = window.performance.memory.usedJSHeapSize;
      this.lastMemory = currentMemory;
      const averageMemory = this.runningAverage.updateRunningAverage( currentMemory );

      if ( this.memoryLimit &&
           this.runningAverage.isSaturated() &&
           !hadMemoryFailure &&
           averageMemory > this.memoryLimit &&
           currentMemory > this.memoryLimit * 0.5 ) {
        hadMemoryFailure = true;
        throw new Error( 'Average memory used (' + MemoryMonitor.memoryString( averageMemory ) + ') is above our memoryLimit (' + MemoryMonitor.memoryString( this.memoryLimit ) + '). Current memory: ' + MemoryMonitor.memoryString( currentMemory ) + '.' );
      }
    }

    /**
     * Convers a number of bytes into a quick-to-read memory string.
     * @public
     *
     * @param {number} bytes
     * @returns {string}
     */
    static memoryString( bytes ) {
      return Math.ceil( bytes / MB ) + 'MB';
    }
  }

  return joist.register( 'MemoryMonitor', MemoryMonitor );
} );<|endoftext|>


<commit_before>// Copyright 2002-2013, University of Colorado Boulder

/**
 * The navigation bar at the bottom of the screen.
 * For a single-tab sim, it shows the name of the sim at the left and the PhET Logo and options menu at the right.
 * For a multi-tab sim, it shows icons for all of the other tabs, with the tab name at the left and the PhET Logo and options menu at the right.
 *
 * @author Sam Reid
 */
define( function( require ) {
  'use strict';

  var Node = require( 'SCENERY/nodes/Node' );
  var Path = require( 'SCENERY/nodes/Path' );
  var HBox = require( 'SCENERY/nodes/HBox' );
  var VBox = require( 'SCENERY/nodes/VBox' );
  var Text = require( 'SCENERY/nodes/Text' );
  var FontAwesomeNode = require( 'SUN/FontAwesomeNode' );
  var Panel = require( 'SUN/Panel' );
  var HomeButton = require( 'SCENERY_PHET/HomeButton' );
  var Rectangle = require( 'SCENERY/nodes/Rectangle' );
  var inherit = require( 'PHET_CORE/inherit' );
  var PhetMenu = require( 'JOIST/PhetMenu' );
  var Font = require( 'SCENERY/util/Font' );
  var Shape = require( 'KITE/Shape' );
  var LinearGradient = require( 'SCENERY/util/LinearGradient' );
  var PhetButton = require( 'JOIST/PhetButton' );
  var ButtonListener = require( 'SCENERY/input/ButtonListener' );
  var Highlight = require( 'JOIST/Highlight' );

  /**
   * Create a nav bar.  Layout assumes all of the tab widths are the same.
   * @param {Sim} sim
   * @param {Array<Tab>} tabs
   * @param {PropertySet} model see joist.Sim
   * @constructor
   */
  function NavigationBar( sim, tabs, model ) {
    this.tabs = tabs;

    this.navBarHeight = 40;
    this.navBarScale = 1;
    this.navBarWidth = 768;

    Node.call( this, {renderer: 'svg'} );
    this.background = new Rectangle( 0, 0, 0, 0, {fill: 'black'} );
    this.addChild( this.background );

    this.hbox = new PhetButton( sim );
    this.addChild( this.hbox );

    this.titleLabel = new Text( sim.name, {fontSize: 18, fill: 'white'} );

    //Create the nodes to be used for the tab icons
    var index = 0;

    var selectedFont = new Font( { size: 10, weight: 'bold'} );
    var normalFont = new Font( { size: 10 } );

    this.addChild( this.titleLabel );

    if ( tabs.length > 1 ) {

      var iconAndTextArray = _.map( tabs, function( tab ) {
        var icon = new Node( {children: [tab.icon], scale: 25 / tab.icon.height} );
        var text = new Text( tab.name, { fill: 'white', visible: true} );

        //Put a panel around it to extend it horizontally so there is some distance from the highlight region to the text and some distance between adjacent texts.
        var textPanel = new Panel( text, {
          fill: null,
          stroke: null,
          lineWidth: 1, // width of the background border
          xMargin: 4,
          yMargin: 0,
          cornerRadius: 0, // radius of the rounded corners on the background
          resize: false // dynamically resize when content bounds change?
        } );
        var iconAndText = new VBox( {children: [icon, textPanel]} );
        iconAndText.icon = icon;
        iconAndText.text = text;
        iconAndText.textPanel = textPanel;
        iconAndText.index = index++;
        iconAndText.tab = tab;

        //On initialization and when the tab changes, update the size of the icons and the layout of the icons and text
        model.tabIndexProperty.link( function( tabIndex ) {
          var selected = iconAndText.index === tabIndex;
          iconAndText.text.fill = selected ? 'yellow' : 'white';
          iconAndText.text.font = selected ? selectedFont : normalFont;
          iconAndText.opacity = selected ? 1.0 : 0.5;
        } );

        return iconAndText;
      } );

      //Make all of the icons the same size so they will have equal hit areas and equal spacing
      var maxWidth = _.max( iconAndTextArray,function( iconAndText ) {return iconAndText.width;} ).width;
      var maxHeight = _.max( iconAndTextArray,function( iconAndText ) {return iconAndText.height;} ).height;

      this.buttonArray = iconAndTextArray.map( function( iconAndText ) {
        //Background area for layout and hit region
        var rectangle = new Rectangle( 0, 0, maxWidth, maxHeight );
        var highlight = Highlight.createHighlight( maxWidth, maxHeight );
        iconAndText.centerX = maxWidth / 2;
        iconAndText.top = 0;
        var button = new Node( {children: [ rectangle, highlight, iconAndText]} );

        //In the nav bar, don't show highlight or cursor pointer when over a tab icon that is already selected
        model.tabIndexProperty.link( function( tabIndex ) { button.cursor = tabIndex === iconAndText.index ? 'default' : 'pointer'; } );

        var pressListener = function() {
          model.tabIndex = iconAndText.index;
          model.showHomeScreen = false;
        };
        button.addInputListener( new ButtonListener( {fire: pressListener} ) );

        //TODO: Move the over/out listener into ButtonListener when it is working better. Currently 'out' is not being fired
        button.addInputListener( {
          //Highlight a button when mousing over it
          over: function( event ) {
            if ( event.pointer.isMouse ) {
              highlight.visible = true;
            }
          },
          out: function( event ) {
            if ( event.pointer.isMouse ) {
              highlight.visible = false;
            }
          }
        } );

        button.addPeer( '<input type="button" aria-label="Switch to the ' + iconAndText.tab.name + ' Tab">', {click: pressListener, tabIndex: 99} );
        return  button;
      } );

      //TODO: This spacing is not always necessary, it depends on the relative width
      //TODO:   of the icon vs the text, if all of the buttons have the same dimensions.
      //TODO:   Currently this solves the simple case where all of the text is shorter than all of the icons (like in Build an Atom)
      var maxIconWidth = _.max( iconAndTextArray,function( i ) {return i.icon.width;} ).icon.width;
      var maxTextWidth = _.max( iconAndTextArray,function( i ) {return i.text.width;} ).text.width;

      this.buttonHBox = new HBox( {spacing: maxTextWidth <= maxIconWidth ? 20 : 0, children: this.buttonArray} );
      this.addChild( this.buttonHBox );

      //add the home icon
      this.homeIcon = new HomeButton();
      var homeHighlight = Highlight.createHighlight( this.homeIcon.width + 10, this.homeIcon.height + 5 );
      homeHighlight.bottom = this.homeIcon.bottom + 3;
      homeHighlight.x = -5;
      this.homeIcon.addChild( homeHighlight );

      //Hide the highlight on the home icon if the home icon is pressed
      model.showHomeScreenProperty.link( function( showHomeScreen ) { if ( showHomeScreen ) { homeHighlight.visible = false; } } );
      this.homeIcon.addInputListener( { down: function() { model.showHomeScreen = true; }} );
      this.homeIcon.addInputListener( Highlight.createHighlightListener( homeHighlight ) );
      this.homeIcon.addPeer( '<input type="button" aria-label="Home Screen">', {click: function() {model.showHomeScreen = true;}, tabIndex: 100} );
      this.addChild( this.homeIcon );
    }
  }

  return inherit( Node, NavigationBar, {
    relayout: function() {
      var navigationBar = this;
      navigationBar.background.rectHeight = this.navBarHeight;
      navigationBar.background.rectWidth = this.navBarWidth;
      var tabIndex = navigationBar.tabIndex;

      if ( this.buttonHBox ) {
        this.buttonHBox.setScaleMagnitude( navigationBar.navBarScale );
      }

      this.titleLabel.setScaleMagnitude( this.navBarScale );
      this.titleLabel.centerY = this.navBarHeight / 2;
      this.titleLabel.left = 10;

      //Lay out the components from left to right
      if ( this.tabs.length !== 1 ) {

        //put the center right in the middle
        this.buttonHBox.centerX = this.navBarWidth / 2;
        this.buttonHBox.top = 2;

        navigationBar.homeIcon.setScaleMagnitude( this.navBarScale );
        navigationBar.homeIcon.top = 2;
        navigationBar.homeIcon.left = navigationBar.buttonHBox.right + 15;
      }
      this.hbox.setScaleMagnitude( this.navBarScale );
      this.hbox.right = this.navBarWidth - 5;
      this.hbox.centerY = this.navBarHeight / 2;
    },
    layout: function( scale, width, height, windowHeight ) {
      this.navBarScale = scale;
      this.navBarWidth = width;
      this.navBarHeight = height;
      this.relayout();
    }} );
} );<commit_msg>Fixed navbar icon spacing for short tab names on firefox, see #28<commit_after>// Copyright 2002-2013, University of Colorado Boulder

/**
 * The navigation bar at the bottom of the screen.
 * For a single-tab sim, it shows the name of the sim at the left and the PhET Logo and options menu at the right.
 * For a multi-tab sim, it shows icons for all of the other tabs, with the tab name at the left and the PhET Logo and options menu at the right.
 *
 * @author Sam Reid
 */
define( function( require ) {
  'use strict';

  var Node = require( 'SCENERY/nodes/Node' );
  var Path = require( 'SCENERY/nodes/Path' );
  var HBox = require( 'SCENERY/nodes/HBox' );
  var VBox = require( 'SCENERY/nodes/VBox' );
  var Text = require( 'SCENERY/nodes/Text' );
  var FontAwesomeNode = require( 'SUN/FontAwesomeNode' );
  var Panel = require( 'SUN/Panel' );
  var HomeButton = require( 'SCENERY_PHET/HomeButton' );
  var Rectangle = require( 'SCENERY/nodes/Rectangle' );
  var inherit = require( 'PHET_CORE/inherit' );
  var PhetMenu = require( 'JOIST/PhetMenu' );
  var Font = require( 'SCENERY/util/Font' );
  var Shape = require( 'KITE/Shape' );
  var LinearGradient = require( 'SCENERY/util/LinearGradient' );
  var PhetButton = require( 'JOIST/PhetButton' );
  var ButtonListener = require( 'SCENERY/input/ButtonListener' );
  var Highlight = require( 'JOIST/Highlight' );

  /**
   * Create a nav bar.  Layout assumes all of the tab widths are the same.
   * @param {Sim} sim
   * @param {Array<Tab>} tabs
   * @param {PropertySet} model see joist.Sim
   * @constructor
   */
  function NavigationBar( sim, tabs, model ) {
    this.tabs = tabs;

    this.navBarHeight = 40;
    this.navBarScale = 1;
    this.navBarWidth = 768;

    Node.call( this, {renderer: 'svg'} );
    this.background = new Rectangle( 0, 0, 0, 0, {fill: 'black'} );
    this.addChild( this.background );

    this.hbox = new PhetButton( sim );
    this.addChild( this.hbox );

    this.titleLabel = new Text( sim.name, {fontSize: 18, fill: 'white'} );

    //Create the nodes to be used for the tab icons
    var index = 0;

    var selectedFont = new Font( { size: 10, weight: 'bold'} );
    var normalFont = new Font( { size: 10 } );

    this.addChild( this.titleLabel );

    if ( tabs.length > 1 ) {

      var iconAndTextArray = _.map( tabs, function( tab ) {
        var icon = new Node( {children: [tab.icon], scale: 25 / tab.icon.height} );
        var text = new Text( tab.name, { fill: 'white', visible: true} );

        //Put a panel around it to extend it horizontally so there is some distance from the highlight region to the text and some distance between adjacent texts.
        var textPanel = new Panel( text, {
          fill: null,
          stroke: null,
          lineWidth: 1, // width of the background border
          xMargin: 4,
          yMargin: 0,
          cornerRadius: 0, // radius of the rounded corners on the background
          resize: false // dynamically resize when content bounds change?
        } );
        var iconAndText = new VBox( {children: [icon, textPanel]} );
        iconAndText.icon = icon;
        iconAndText.text = text;
        iconAndText.textPanel = textPanel;
        iconAndText.index = index++;
        iconAndText.tab = tab;

        //On initialization and when the tab changes, update the size of the icons and the layout of the icons and text
        model.tabIndexProperty.link( function( tabIndex ) {
          var selected = iconAndText.index === tabIndex;
          iconAndText.text.fill = selected ? 'yellow' : 'white';
          iconAndText.text.font = selected ? selectedFont : normalFont;
          iconAndText.opacity = selected ? 1.0 : 0.5;
        } );

        return iconAndText;
      } );

      //Make all of the icons the same size so they will have equal hit areas and equal spacing
      var maxWidth = _.max( iconAndTextArray,function( iconAndText ) {return iconAndText.width;} ).width;
      var maxHeight = _.max( iconAndTextArray,function( iconAndText ) {return iconAndText.height;} ).height;

      this.buttonArray = iconAndTextArray.map( function( iconAndText ) {
        //Background area for layout and hit region
        var rectangle = new Rectangle( 0, 0, maxWidth, maxHeight );
        var highlight = Highlight.createHighlight( maxWidth, maxHeight );
        iconAndText.centerX = maxWidth / 2;
        iconAndText.top = 0;
        var button = new Node( {children: [ rectangle, highlight, iconAndText]} );

        //In the nav bar, don't show highlight or cursor pointer when over a tab icon that is already selected
        model.tabIndexProperty.link( function( tabIndex ) { button.cursor = tabIndex === iconAndText.index ? 'default' : 'pointer'; } );

        var pressListener = function() {
          model.tabIndex = iconAndText.index;
          model.showHomeScreen = false;
        };
        button.addInputListener( new ButtonListener( {fire: pressListener} ) );

        //TODO: Move the over/out listener into ButtonListener when it is working better. Currently 'out' is not being fired
        button.addInputListener( {
          //Highlight a button when mousing over it
          over: function( event ) {
            if ( event.pointer.isMouse ) {
              highlight.visible = true;
            }
          },
          out: function( event ) {
            if ( event.pointer.isMouse ) {
              highlight.visible = false;
            }
          }
        } );

        button.addPeer( '<input type="button" aria-label="Switch to the ' + iconAndText.tab.name + ' Tab">', {click: pressListener, tabIndex: 99} );
        return  button;
      } );

      //TODO: This spacing is not always necessary, it depends on the relative width
      //TODO:   of the icon vs the text, if all of the buttons have the same dimensions.
      //TODO:   Currently this solves the simple case where all of the text is shorter than all of the icons (like in Build an Atom)
      //TODO: A better strategy may be to use a linear function to space them based on how far it is from the criterion maxTextWidth<=maxIconWidth+2
      //See Joist #28 https://github.com/phetsims/joist/issues/28
      var maxIconWidth = _.max( iconAndTextArray,function( i ) {return i.icon.width;} ).icon.width;
      var maxTextWidth = _.max( iconAndTextArray,function( i ) {return i.text.width;} ).text.width;

      this.buttonHBox = new HBox( {spacing: maxTextWidth <= maxIconWidth + 2 ? 20 : 0, children: this.buttonArray} );
      this.addChild( this.buttonHBox );

      //add the home icon
      this.homeIcon = new HomeButton();
      var homeHighlight = Highlight.createHighlight( this.homeIcon.width + 10, this.homeIcon.height + 5 );
      homeHighlight.bottom = this.homeIcon.bottom + 3;
      homeHighlight.x = -5;
      this.homeIcon.addChild( homeHighlight );

      //Hide the highlight on the home icon if the home icon is pressed
      model.showHomeScreenProperty.link( function( showHomeScreen ) { if ( showHomeScreen ) { homeHighlight.visible = false; } } );
      this.homeIcon.addInputListener( { down: function() { model.showHomeScreen = true; }} );
      this.homeIcon.addInputListener( Highlight.createHighlightListener( homeHighlight ) );
      this.homeIcon.addPeer( '<input type="button" aria-label="Home Screen">', {click: function() {model.showHomeScreen = true;}, tabIndex: 100} );
      this.addChild( this.homeIcon );
    }
  }

  return inherit( Node, NavigationBar, {
    relayout: function() {
      var navigationBar = this;
      navigationBar.background.rectHeight = this.navBarHeight;
      navigationBar.background.rectWidth = this.navBarWidth;
      var tabIndex = navigationBar.tabIndex;

      if ( this.buttonHBox ) {
        this.buttonHBox.setScaleMagnitude( navigationBar.navBarScale );
      }

      this.titleLabel.setScaleMagnitude( this.navBarScale );
      this.titleLabel.centerY = this.navBarHeight / 2;
      this.titleLabel.left = 10;

      //Lay out the components from left to right
      if ( this.tabs.length !== 1 ) {

        //put the center right in the middle
        this.buttonHBox.centerX = this.navBarWidth / 2;
        this.buttonHBox.top = 2;

        navigationBar.homeIcon.setScaleMagnitude( this.navBarScale );
        navigationBar.homeIcon.top = 2;
        navigationBar.homeIcon.left = navigationBar.buttonHBox.right + 15;
      }
      this.hbox.setScaleMagnitude( this.navBarScale );
      this.hbox.right = this.navBarWidth - 5;
      this.hbox.centerY = this.navBarHeight / 2;
    },
    layout: function( scale, width, height, windowHeight ) {
      this.navBarScale = scale;
      this.navBarWidth = width;
      this.navBarHeight = height;
      this.relayout();
    }} );
} );<|endoftext|>


<commit_before>(function($){
  $.fn.accordionize = function(options) {
    function AccordionizeNode(accordionizeNode) {
      $.extend(this, accordionizeNode);
    }

    var propTagName = "tagName";
    var attrSrc = "src";
    var attrAlt = "alt";
    var tagImg = "img";
    var attrClass = "class";

    var core = {
      defaultOptions: $.extend({
        tabWidth: 80,
        scroll: {
          timeout: 7000,
          auto: true
        },
        classPrefix: 'accordionized'
      }, options),

      data: {
        containerClassName: '',
        instanceClassName: ''
      },

      elements: [],

      writeContainerNamesData: function($container){
        core.data.containerClassName = $container.attr(attrClass);
        core.data.instanceClassName = core.buildInstanceClassName($container);
      },

      grayscale: {
        createCanvas: function($container) {
          var $images = $container.find(tagImg);

          $images.each(function(){
            var $image = $(this),
              imgWidth = $image.width(),
              imgHeight = $image.height(),
              imgName = $image.attr('alt'),
              $canvas = $('<canvas />')
                .attr({
                  'width': imgWidth,
                  'height': imgHeight,
                  'data-rel': imgName
                })
                .css({
                  position: 'absolute'
                });

            var context = $canvas.get(0).getContext('2d');

            context.drawImage($image.get(0), 0, 0);

            var imageData = context.getImageData(0, 0, imgWidth, imgHeight),
              pix = imageData.data;

            for (var i = 0; i < pix.length; i += 4) {
              var grayscale = pix[i] * .3 + pix[i + 1] * .59 + pix[i + 2] * .11;
              pix[i] = grayscale;
              pix[i + 1] = grayscale;
              pix[i + 2] = grayscale;
            }

            context.putImageData(imageData, 0, 0);
            $canvas.insertAfter($image);
          });
        }
      },

      buildInstanceClassName: function($container) {
        var className = {
            prefix: core.defaultOptions.classPrefix,
            id: core.generateInstanceId(),
            postfix: '__' + $container.attr(attrClass)
          }

        return className.prefix + className.id + className.postfix;
      },

      generateInstanceId: function() {
        return Math.floor(Math.random() * (99999 - 0 + 1)) + 0;
      },

      setLoop: function($container) {
        if(core.defaultOptions.scroll.auto) {
          clearInterval(window.interval);

          window.interval = setInterval(function() {
            var $activeElement = $container.children('.active');
            if($activeElement.is(':last-child')) {
              $container.children('.banner-item:first-child').trigger('mousedown');
            } else {
              $activeElement.next().trigger('mousedown');
            }
          }, core.defaultOptions.scroll.timeout);
        }
      },

      init: function($container, defaultOptions, externalOptions) {
        core.writeContainerNamesData($container);
        core.findAndConvertBaseNode($container);
        core.buildDOM($container);
        core.grayscale.createCanvas($container);
        core.setEvents($container);
        $container.children('.banner-item').first().trigger('mousedown');
      },

      convertBaseNodeToAccordionizeNode: function(baseNodeArray) {
        for (var index in baseNodeArray) {
          var node = $(baseNodeArray[index]);

          var accordionizeNode = new AccordionizeNode({tagName: node.prop(propTagName),
            src: node.attr(attrSrc),
            alt: node.attr(attrAlt)});
          core.elements.push(accordionizeNode);
        }
      },

      findAndConvertBaseNode: function($container) {
        var objImages = $container.find(tagImg);
        var imageArray = objImages.toArray();

        core.convertBaseNodeToAccordionizeNode(imageArray);
        objImages.remove();
      },

      buildDOM: function($container) {
        var builtElements = [];
        for(var i = 0; i < core.elements.length; i++) {
          var title = core.elements[i].alt
            src = core.elements[i].src,
            tagName = core.elements[i].tagName,
            $wrapper = $('<div />',{
              'class': 'banner-item',
              'data-title': title
            }),
            $overlay = $('<div />', {
              'class': 'banner-item-overlay',
              'html': title
            }),
            $label = $('<div />', {
              'class': 'banner-item-label',
              'html': title
            }),
            $image = $('<img />', {
              'src': src,
              'alt': title
            });

          $image.css({
            'position': 'absolute',
            'display': 'none',
            'z-index': '1'
          });

          $wrapper
            .append($overlay)
            .append($label)
            .append($image);

          builtElements.push($wrapper);
        }
        $container.append(builtElements);
      },

      setEvents: function($container) {
        var $elements = $container.find('.banner-item'),
          slideWidth = $container.width() - (core.defaultOptions.tabWidth + 1) * (core.elements.length - 1) - 1;

        $elements.each(function(){
          $(this).on('mousedown', function(){
            var $this = $(this);
            if(!$this.is('.active')) {
              if($container.attr('data-animated') != 'true') {
                $container.attr('data-animated', 'true');
                core.wrap($container, $this.siblings('.active'));
                core.unwrap($container, $this, slideWidth);
                core.setLoop($container);
              }
            } else {
              return false;
            }
          });
        });
      },

      unwrap: function($container, $slide, slideWidth) {
        setTimeout(function(){
          $slide
            .animate({
              'width': slideWidth + 'px'
            }, 400, function(){
              $container.attr('data-animated', 'false');
            })
            .addClass('active');

          $slide
            .find('.banner-item-overlay')
            .fadeOut(400);

          setTimeout(function(){
            $slide
              .find('.banner-item-label')
              .fadeIn(300);
            $slide
              .find(tagImg)
              .fadeIn(300);
          }, 400)
        }, 300);

      },

      wrap: function($container, $slide) {
        setTimeout(function(){
          $slide
            .animate({
              'width': core.defaultOptions.tabWidth + 'px'
            }, 400, function(){
              $container.attr('data-animated', 'false');
            })
            .removeClass('active');

          setTimeout(function(){
            $slide
              .find(tagImg)
              .fadeOut(300);

            $slide
              .find('.banner-item-overlay')
              .fadeIn(400);
          }, 400);

        }, 300);

        $slide
          .find('.banner-item-label')
          .fadeOut(300);
      }
     }

    core.init(this, core.defaultOptions, options);
  }
})(jQuery);
<commit_msg>Use attrAlt<commit_after>(function($){
  $.fn.accordionize = function(options) {
    function AccordionizeNode(accordionizeNode) {
      $.extend(this, accordionizeNode);
    }

    var propTagName = "tagName";
    var attrSrc = "src";
    var attrAlt = "alt";
    var tagImg = "img";
    var attrClass = "class";

    var core = {
      defaultOptions: $.extend({
        tabWidth: 80,
        scroll: {
          timeout: 7000,
          auto: true
        },
        classPrefix: 'accordionized'
      }, options),

      data: {
        containerClassName: '',
        instanceClassName: ''
      },

      elements: [],

      writeContainerNamesData: function($container){
        core.data.containerClassName = $container.attr(attrClass);
        core.data.instanceClassName = core.buildInstanceClassName($container);
      },

      grayscale: {
        createCanvas: function($container) {
          var $images = $container.find(tagImg);

          $images.each(function(){
            var $image = $(this),
              imgWidth = $image.width(),
              imgHeight = $image.height(),
              imgName = $image.attr(attrAlt),
              $canvas = $('<canvas />')
                .attr({
                  'width': imgWidth,
                  'height': imgHeight,
                  'data-rel': imgName
                })
                .css({
                  position: 'absolute'
                });

            var context = $canvas.get(0).getContext('2d');

            context.drawImage($image.get(0), 0, 0);

            var imageData = context.getImageData(0, 0, imgWidth, imgHeight),
              pix = imageData.data;

            for (var i = 0; i < pix.length; i += 4) {
              var grayscale = pix[i] * .3 + pix[i + 1] * .59 + pix[i + 2] * .11;
              pix[i] = grayscale;
              pix[i + 1] = grayscale;
              pix[i + 2] = grayscale;
            }

            context.putImageData(imageData, 0, 0);
            $canvas.insertAfter($image);
          });
        }
      },

      buildInstanceClassName: function($container) {
        var className = {
            prefix: core.defaultOptions.classPrefix,
            id: core.generateInstanceId(),
            postfix: '__' + $container.attr(attrClass)
          }

        return className.prefix + className.id + className.postfix;
      },

      generateInstanceId: function() {
        return Math.floor(Math.random() * (99999 - 0 + 1)) + 0;
      },

      setLoop: function($container) {
        if(core.defaultOptions.scroll.auto) {
          clearInterval(window.interval);

          window.interval = setInterval(function() {
            var $activeElement = $container.children('.active');
            if($activeElement.is(':last-child')) {
              $container.children('.banner-item:first-child').trigger('mousedown');
            } else {
              $activeElement.next().trigger('mousedown');
            }
          }, core.defaultOptions.scroll.timeout);
        }
      },

      init: function($container, defaultOptions, externalOptions) {
        core.writeContainerNamesData($container);
        core.findAndConvertBaseNode($container);
        core.buildDOM($container);
        core.grayscale.createCanvas($container);
        core.setEvents($container);
        $container.children('.banner-item').first().trigger('mousedown');
      },

      convertBaseNodeToAccordionizeNode: function(baseNodeArray) {
        for (var index in baseNodeArray) {
          var node = $(baseNodeArray[index]);

          var accordionizeNode = new AccordionizeNode({tagName: node.prop(propTagName),
            src: node.attr(attrSrc),
            alt: node.attr(attrAlt)});
          core.elements.push(accordionizeNode);
        }
      },

      findAndConvertBaseNode: function($container) {
        var objImages = $container.find(tagImg);
        var imageArray = objImages.toArray();

        core.convertBaseNodeToAccordionizeNode(imageArray);
        objImages.remove();
      },

      buildDOM: function($container) {
        var builtElements = [];
        for(var i = 0; i < core.elements.length; i++) {
          var title = core.elements[i].alt
            src = core.elements[i].src,
            tagName = core.elements[i].tagName,
            $wrapper = $('<div />',{
              'class': 'banner-item',
              'data-title': title
            }),
            $overlay = $('<div />', {
              'class': 'banner-item-overlay',
              'html': title
            }),
            $label = $('<div />', {
              'class': 'banner-item-label',
              'html': title
            }),
            $image = $('<img />', {
              'src': src,
              attrAlt: title
            });

          $image.css({
            'position': 'absolute',
            'display': 'none',
            'z-index': '1'
          });

          $wrapper
            .append($overlay)
            .append($label)
            .append($image);

          builtElements.push($wrapper);
        }
        $container.append(builtElements);
      },

      setEvents: function($container) {
        var $elements = $container.find('.banner-item'),
          slideWidth = $container.width() - (core.defaultOptions.tabWidth + 1) * (core.elements.length - 1) - 1;

        $elements.each(function(){
          $(this).on('mousedown', function(){
            var $this = $(this);
            if(!$this.is('.active')) {
              if($container.attr('data-animated') != 'true') {
                $container.attr('data-animated', 'true');
                core.wrap($container, $this.siblings('.active'));
                core.unwrap($container, $this, slideWidth);
                core.setLoop($container);
              }
            } else {
              return false;
            }
          });
        });
      },

      unwrap: function($container, $slide, slideWidth) {
        setTimeout(function(){
          $slide
            .animate({
              'width': slideWidth + 'px'
            }, 400, function(){
              $container.attr('data-animated', 'false');
            })
            .addClass('active');

          $slide
            .find('.banner-item-overlay')
            .fadeOut(400);

          setTimeout(function(){
            $slide
              .find('.banner-item-label')
              .fadeIn(300);
            $slide
              .find(tagImg)
              .fadeIn(300);
          }, 400)
        }, 300);

      },

      wrap: function($container, $slide) {
        setTimeout(function(){
          $slide
            .animate({
              'width': core.defaultOptions.tabWidth + 'px'
            }, 400, function(){
              $container.attr('data-animated', 'false');
            })
            .removeClass('active');

          setTimeout(function(){
            $slide
              .find(tagImg)
              .fadeOut(300);

            $slide
              .find('.banner-item-overlay')
              .fadeIn(400);
          }, 400);

        }, 300);

        $slide
          .find('.banner-item-label')
          .fadeOut(300);
      }
     }

    core.init(this, core.defaultOptions, options);
  }
})(jQuery);
<|endoftext|>


<commit_before>/*globals alert*/
var $        = require('jquery'),
    _        = require('underscore'),
    Facility = require('cloud/models/facility');

var location = function() {
  var lat, lon;

  if ( navigator.geolocation ) {
    navigator.geolocation.getCurrentPosition(function(position) {
      lat = position.coords.latitude;
      lon = position.coords.longitude;
    }, function(error) {
      console.log(error);
    });
  }

  console.log(lat, lon);

  if (!(lat && lon)) {
    alert("lat: " + lat + " lon: " + lon);
    lat = 37.782355;
    lon = -122.409825;
  }

  console.log(lat, lon);
  return {lat: lat, lon: lon};
};

var queryFunction = function(runWhere) {
  if ( runWhere === 'cloud' ) {
    return _.partial(Parse.Cloud.run, "browse");
  } else {
    return require('cloud/lib/browse');
  }
};

var submit = function(params) {
  // to keep track of when it finishes
  var deferred = $.Deferred();

  // choose where to run the query
  // var query = queryFunction(params.runwhere);
  var query = queryFunction('browser');

  // add location if proximity sorting
  if ( params.sort === 'near' ) {
    $.extend(params, location());
  }

  query(params, {
    success: function(result) {
      deferred.resolve(result);
      // dumpToDOM(result);
    },

    error: function(err) {
      deferred.reject(err);
    }
  });

  return deferred.promise();
};

// TODO -- hoist this up a layer into "browse" -- or wherever we keep the direct parse communication lib.
var getByID = function(id) {
  var deferred = $.Deferred();

  var q = new Parse.Query(Facility);
  q.include("services");
  q.get(id, {
    success: function(result) {
      deferred.resolve(result);
    },
    error: function(err) {
      deferred.reject(err);
    }
  });

  return deferred.promise();
};

module.exports = { submit: submit, getByID: getByID };
<commit_msg>remove testing statements<commit_after>/*globals alert*/
var $        = require('jquery'),
    _        = require('underscore'),
    Facility = require('cloud/models/facility');

var location = function() {
  var lat, lon;

  if ( navigator.geolocation ) {
    navigator.geolocation.getCurrentPosition(function(position) {
      lat = position.coords.latitude;
      lon = position.coords.longitude;
    }, function(error) {
      console.log(error);
    });
  }

  if (!(lat && lon)) {
    lat = 37.782355;
    lon = -122.409825;
  }

  return {lat: lat, lon: lon};
};

var queryFunction = function(runWhere) {
  if ( runWhere === 'cloud' ) {
    return _.partial(Parse.Cloud.run, "browse");
  } else {
    return require('cloud/lib/browse');
  }
};

var submit = function(params) {
  // to keep track of when it finishes
  var deferred = $.Deferred();

  // choose where to run the query
  // var query = queryFunction(params.runwhere);
  var query = queryFunction('browser');

  // add location if proximity sorting
  if ( params.sort === 'near' ) {
    $.extend(params, location());
  }

  query(params, {
    success: function(result) {
      deferred.resolve(result);
      // dumpToDOM(result);
    },

    error: function(err) {
      deferred.reject(err);
    }
  });

  return deferred.promise();
};

// TODO -- hoist this up a layer into "browse" -- or wherever we keep the direct parse communication lib.
var getByID = function(id) {
  var deferred = $.Deferred();

  var q = new Parse.Query(Facility);
  q.include("services");
  q.get(id, {
    success: function(result) {
      deferred.resolve(result);
    },
    error: function(err) {
      deferred.reject(err);
    }
  });

  return deferred.promise();
};

module.exports = { submit: submit, getByID: getByID };
<|endoftext|>


<commit_before>"use strict";

const ccxt = require ('ccxt')
    , WsClient = require ('./WsClient')
    , {
        OrderBook,
        IndexedOrderBook,
        CountedOrderBook,
    } = require ('./OrderBook')

module.exports = class Exchange extends ccxt.Exchange {

    orderBook (snapshot = {}, depth = Number.MAX_SAFE_INTEGER) {
        return new OrderBook (snapshot, depth)
    }

    indexedOrderBook (snapshot = {}, depth = Number.MAX_SAFE_INTEGER) {
        return new IndexedOrderBook (snapshot, depth)
    }

    countedOrderBook (snapshot = {}, depth = Number.MAX_SAFE_INTEGER) {
        return new CountedOrderBook (snapshot, depth)
    }

    client (url) {
        this.clients = this.clients || {}
        if (!this.clients[url]) {
            const onMessage = this.handleMessage.bind (this)
            const onError = this.onError.bind (this)
            const onClose = this.onClose.bind (this)
            // decide client type here: ws / signalr / socketio
            const options = this.extend (this.streaming, {
                'ping': this.ping ? this.ping.bind (this) : this.ping,
            })
            this.clients[url] = new WsClient (url, onMessage, onError, onClose, options)
        }
        return this.clients[url]
    }

    async after (future, method, ... args) {
        const result = await future
        // call it as an instance method on this
        return method.call (this, result, ... args)
    }

    async afterDropped (future, method, ... args) {
        // same as above, drop the result
        if (future) {
            await future
        }
        return await method.apply (this, args)
    }

    spawn (method, ... args) {
        (method.apply (this, args)).catch ((e) => {
            // todo: handle spawned errors
        })
    }

    watch (url, messageHash, message = undefined, subscribeHash = undefined, subscription = undefined) {
        //
        // Without comments the code of this method is short and easy:
        //
        //     const client = this.client (url)
        //     const backoffDelay = 0
        //     const future = client.future (messageHash)
        //     const connected = client.connect (backoffDelay)
        //     connected.then (() => {
        //         if (message && !client.subscriptions[subscribeHash]) {
        //             client.subscriptions[subscribeHash] = true
        //             message = this.signMessage (client, messageHash, message)
        //             client.send (message)
        //         }
        //     }).catch ((error) => {})
        //     return future
        //
        // The following is a longer version of this method with comments
        //
        const client = this.client (url)
        // todo: calculate the backoff using the clients cache
        const backoffDelay = 0
        //
        //  watchOrderBook ---- future ----+---------------+----→ user
        //                                 |               |
        //                                 ↓               ↑
        //                                 |               |
        //                              connect ......→ resolve
        //                                 |               |
        //                                 ↓               ↑
        //                                 |               |
        //                             subscribe -----→ receive
        //
        const future = client.future (messageHash)
        // we intentionally do not use await here to avoid unhandled exceptions
        // the policy is to make sure that 100% of promises are resolved or rejected
        // either with a call to client.resolve or client.reject with
        //  a proper exception class instance
        if (client.isOpen ()) {
            if (message && !client.subscriptions[subscribeHash]) {
                client.subscriptions[subscribeHash] = subscription || true
                message = this.signMessage (client, messageHash, message)
                client.send (message)
            }
            return future
        }
        const connected = client.connect (backoffDelay)
        // the following is executed only if the catch-clause does not
        // catch any connection-level exceptions from the client
        // (connection established successfully)
        connected.then (() => {
            if (message && !client.subscriptions[subscribeHash]) {
                client.subscriptions[subscribeHash] = subscription || true
                // todo: decouple signing from subscriptions
                message = this.signMessage (client, messageHash, message)
                client.send (message)
            }
        }).catch ((error) => {
            // we do nothing and don't return a resolvable value from here
            // we leave it in a rejected state to avoid triggering the
            // then-clauses that will follow (if any)
            // removing this catch will raise UnhandledPromiseRejection in JS
            // upon connection failure
        })
        return future
    }

    onError (client, error) {
        if ((client.url in this.clients) && (this.clients[client.url].error)) {
            delete this.clients[client.url]
        }
    }

    onClose (client, error) {
        if (client.error) {
            // connection closed due to an error, do nothing
        } else {
            // server disconnected a working connection
            if (this.clients[client.url]) {
                delete this.clients[client.url]
            }
        }
    }

    async close () {
        const clients = Object.values (this.clients || {})
        for (let i = 0; i < clients.length; i++) {
            const client = clients[i]
            delete this.clients[client.url]
            await client.close ()
        }
    }

    signMessage (client, messageHash, message, params = {}) {
        throw new ccxt.NotSupported (this.id + ' signMessage () not implemented yet')
    }
}
<commit_msg>remove unnecessary check<commit_after>"use strict";

const ccxt = require ('ccxt')
    , WsClient = require ('./WsClient')
    , {
        OrderBook,
        IndexedOrderBook,
        CountedOrderBook,
    } = require ('./OrderBook')

module.exports = class Exchange extends ccxt.Exchange {

    orderBook (snapshot = {}, depth = Number.MAX_SAFE_INTEGER) {
        return new OrderBook (snapshot, depth)
    }

    indexedOrderBook (snapshot = {}, depth = Number.MAX_SAFE_INTEGER) {
        return new IndexedOrderBook (snapshot, depth)
    }

    countedOrderBook (snapshot = {}, depth = Number.MAX_SAFE_INTEGER) {
        return new CountedOrderBook (snapshot, depth)
    }

    client (url) {
        this.clients = this.clients || {}
        if (!this.clients[url]) {
            const onMessage = this.handleMessage.bind (this)
            const onError = this.onError.bind (this)
            const onClose = this.onClose.bind (this)
            // decide client type here: ws / signalr / socketio
            const options = this.extend (this.streaming, {
                'ping': this.ping ? this.ping.bind (this) : this.ping,
            })
            this.clients[url] = new WsClient (url, onMessage, onError, onClose, options)
        }
        return this.clients[url]
    }

    async after (future, method, ... args) {
        const result = await future
        // call it as an instance method on this
        return method.call (this, result, ... args)
    }

    async afterDropped (future, method, ... args) {
        // same as above, drop the result
        if (future) {
            await future
        }
        return await method.apply (this, args)
    }

    spawn (method, ... args) {
        (method.apply (this, args)).catch ((e) => {
            // todo: handle spawned errors
        })
    }

    watch (url, messageHash, message = undefined, subscribeHash = undefined, subscription = undefined) {
        //
        // Without comments the code of this method is short and easy:
        //
        //     const client = this.client (url)
        //     const backoffDelay = 0
        //     const future = client.future (messageHash)
        //     const connected = client.connect (backoffDelay)
        //     connected.then (() => {
        //         if (message && !client.subscriptions[subscribeHash]) {
        //             client.subscriptions[subscribeHash] = true
        //             message = this.signMessage (client, messageHash, message)
        //             client.send (message)
        //         }
        //     }).catch ((error) => {})
        //     return future
        //
        // The following is a longer version of this method with comments
        //
        const client = this.client (url)
        // todo: calculate the backoff using the clients cache
        const backoffDelay = 0
        //
        //  watchOrderBook ---- future ----+---------------+----→ user
        //                                 |               |
        //                                 ↓               ↑
        //                                 |               |
        //                              connect ......→ resolve
        //                                 |               |
        //                                 ↓               ↑
        //                                 |               |
        //                             subscribe -----→ receive
        //
        const future = client.future (messageHash)
        // we intentionally do not use await here to avoid unhandled exceptions
        // the policy is to make sure that 100% of promises are resolved or rejected
        // either with a call to client.resolve or client.reject with
        //  a proper exception class instance
        const connected = client.connect (backoffDelay)
        // the following is executed only if the catch-clause does not
        // catch any connection-level exceptions from the client
        // (connection established successfully)
        connected.then (() => {
            if (message && !client.subscriptions[subscribeHash]) {
                client.subscriptions[subscribeHash] = subscription || true
                // todo: decouple signing from subscriptions
                message = this.signMessage (client, messageHash, message)
                client.send (message)
            }
        }).catch ((error) => {
            // we do nothing and don't return a resolvable value from here
            // we leave it in a rejected state to avoid triggering the
            // then-clauses that will follow (if any)
            // removing this catch will raise UnhandledPromiseRejection in JS
            // upon connection failure
        })
        return future
    }

    onError (client, error) {
        if ((client.url in this.clients) && (this.clients[client.url].error)) {
            delete this.clients[client.url]
        }
    }

    onClose (client, error) {
        if (client.error) {
            // connection closed due to an error, do nothing
        } else {
            // server disconnected a working connection
            if (this.clients[client.url]) {
                delete this.clients[client.url]
            }
        }
    }

    async close () {
        const clients = Object.values (this.clients || {})
        for (let i = 0; i < clients.length; i++) {
            const client = clients[i]
            delete this.clients[client.url]
            await client.close ()
        }
    }

    signMessage (client, messageHash, message, params = {}) {
        throw new ccxt.NotSupported (this.id + ' signMessage () not implemented yet')
    }
}
<|endoftext|>


<commit_before>/*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, vars: true, white: true, plusplus: true */
/*global require */

////////////////////////////////////////////////////////////////////////////////
/// @brief ArangoShell client API
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Achim Brandt
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                                  public functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ArangoShell
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief start paging
////////////////////////////////////////////////////////////////////////////////

function start_pager () {
  var internal = require("internal");
  internal.startPager();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief stop paging
////////////////////////////////////////////////////////////////////////////////

function stop_pager () {
  var internal = require("internal");
  internal.stopPager();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief print the overall help
////////////////////////////////////////////////////////////////////////////////

function help () {
  var internal = require("internal");
  var arangodb = require("org/arangodb");
  var client = require("org/arangodb/arangosh");

  internal.print(client.HELP);
  internal.print(arangodb.ArangoStatement.prototype._help());
  internal.print(arangodb.ArangoDatabase.prototype._help());
  internal.print(arangodb.ArangoCollection.prototype._help());
  internal.print(arangodb.ArangoQueryCursor.prototype._help());
  internal.print(client.helpExtended);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief clear screen (poor man's way)
////////////////////////////////////////////////////////////////////////////////

function clear () {
  var internal = require("internal");
  var i;

  for (i = 0; i < 100; ++i) {
    internal.print('\n');
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief prints help
////////////////////////////////////////////////////////////////////////////////

(function() {
  var internal = require("internal");
  var arangosh = require("org/arangodb/arangosh");

  if (internal.arango !== undefined) {
    if (typeof internal.arango.isConnected !== "undefined") {
      if (internal.arango.isConnected()) {
        internal.print(arangosh.HELP);
      }
    }
  }
}());

////////////////////////////////////////////////////////////////////////////////
/// @brief global 'db'
////////////////////////////////////////////////////////////////////////////////

var db = require("org/arangodb").db;

////////////////////////////////////////////////////////////////////////////////
/// @brief global 'arango'
////////////////////////////////////////////////////////////////////////////////

var arango = require("org/arangodb").arango;

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @}\\|/\\*jslint"
// End:
<commit_msg>preload collections<commit_after>/*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, vars: true, white: true, plusplus: true */
/*global require */

////////////////////////////////////////////////////////////////////////////////
/// @brief ArangoShell client API
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Achim Brandt
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                                  public functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ArangoShell
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief start paging
////////////////////////////////////////////////////////////////////////////////

function start_pager () {
  var internal = require("internal");
  internal.startPager();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief stop paging
////////////////////////////////////////////////////////////////////////////////

function stop_pager () {
  var internal = require("internal");
  internal.stopPager();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief print the overall help
////////////////////////////////////////////////////////////////////////////////

function help () {
  var internal = require("internal");
  var arangodb = require("org/arangodb");
  var client = require("org/arangodb/arangosh");

  internal.print(client.HELP);
  internal.print(arangodb.ArangoStatement.prototype._help());
  internal.print(arangodb.ArangoDatabase.prototype._help());
  internal.print(arangodb.ArangoCollection.prototype._help());
  internal.print(arangodb.ArangoQueryCursor.prototype._help());
  internal.print(client.helpExtended);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief clear screen (poor man's way)
////////////////////////////////////////////////////////////////////////////////

function clear () {
  var internal = require("internal");
  var i;

  for (i = 0; i < 100; ++i) {
    internal.print('\n');
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief prints help
////////////////////////////////////////////////////////////////////////////////

(function() {
  var internal = require("internal");
  var arangosh = require("org/arangodb/arangosh");

  if (internal.db !== undefined) {
    try {
      internal.db._collections();
    }
    catch (err) {
    }
  }

  if (internal.arango !== undefined) {
    if (typeof internal.arango.isConnected !== "undefined") {
      if (internal.arango.isConnected()) {
        internal.print(arangosh.HELP);
      }
    }
  }
}());

////////////////////////////////////////////////////////////////////////////////
/// @brief global 'db'
////////////////////////////////////////////////////////////////////////////////

var db = require("org/arangodb").db;

////////////////////////////////////////////////////////////////////////////////
/// @brief global 'arango'
////////////////////////////////////////////////////////////////////////////////

var arango = require("org/arangodb").arango;

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @}\\|/\\*jslint"
// End:
<|endoftext|>


<commit_before>"use strict";

var expect = require('expect.js');
var __ = require('../lib/kansuu.js');
var base = require('../lib/kansuu-base.js');
var med = require('../examples/medical.js');

describe("'medical' example", () => {
  it('BMI', (next) => {
    expect(
      med.BMI(75, 175)
    ).to.be.within(24.0, 25.0)
    next();
  });
  describe('person', () => {
	var male = med.algebraic.male({
	  weight: 72,
	  height: 175
	});
	var female = med.algebraic.female({
	  weight: 54,
	  height: 160
	});
	it('BMI', (next) => {
      expect(
		med.algebraic.evaluate.call(med,male).BMI
      ).to.be(23.510204081632654)
      next();
	});
	it('TBW', (next) => {
      expect(
		med.algebraic.evaluate.call(med,female).TBW
      ).to.be(27)
      next();
	});
  });
  describe('case', () => {
	var male = med.algebraic.male({
	  weight: 62.9,
	  height: 174
	});
	it('BMI', (next) => {
      expect(
		med.algebraic.evaluate.call(med,male).BMI
      ).to.be(23.510204081632654)
      next();
	});
	it('TBW', (next) => {
      expect(
		med.algebraic.evaluate.call(med,male).TBW
      ).to.be(27)
      next();
	});
  });
});
<commit_msg>all test passed<commit_after>"use strict";

var expect = require('expect.js');
var __ = require('../lib/kansuu.js');
var base = require('../lib/kansuu-base.js');
var med = require('../examples/medical.js');

describe("'medical' example", () => {
  it('BMI', (next) => {
    expect(
      med.BMI(75, 175)
    ).to.be.within(24.0, 25.0)
    next();
  });
  describe('person', () => {
	var male = med.algebraic.male({
	  weight: 72,
	  height: 175
	});
	var female = med.algebraic.female({
	  weight: 54,
	  height: 160
	});
	it('BMI', (next) => {
      expect(
		med.algebraic.evaluate.call(med,male).BMI
      ).to.be(23.510204081632654)
      next();
	});
	it('TBW', (next) => {
      expect(
		med.algebraic.evaluate.call(med,female).TBW
      ).to.be(29.783085)
      next();
	});
  });
  describe('case', () => {
	var male = med.algebraic.male({
	  weight: 62.9,
	  height: 174
	});
	it('BMI', (next) => {
      expect(
		med.algebraic.evaluate.call(med,male).BMI
      ).to.be(20.775531774342713)
      next();
	});
	it('TBW', (next) => {
      expect(
		med.algebraic.evaluate.call(med,male).TBW
      ).to.be(38.5476065)
      next();
	});
  });
});
<|endoftext|>


<commit_before>/* global using */

using("WSE.tools::getSerializedNodes", "WSE.tools::warn").
define("WSE.commands.line", function (getSerializedNodes, warn) {

    "use strict";

    function line (command, interpreter) {

        var speakerId, speakerName, textboxName, i, len, current;
        var assetElements, text, doNext, bus = interpreter.bus, next;

        next = {doNext: true};

        bus.trigger(
            "wse.interpreter.commands.line",
            {
                interpreter: interpreter,
                command: command
            },
            false
        );

        speakerId = command.getAttribute("s");
        doNext = command.getAttribute("stop") === "false" ? true : false;

        if (speakerId === null) {
            warn(bus, "Element 'line' requires attribute 's'.", command);
            return next;
        }

        assetElements = interpreter.story.getElementsByTagName("character");
        len = assetElements.length;

        for (i = 0; i < len; i += 1) {

            current = assetElements[i];

            if (current.getAttribute("name") === speakerId) {

                textboxName = current.getAttribute("textbox");

                if (typeof textboxName === "undefined" || textboxName === null) {
                    warn(bus, "No textbox defined for character '" + speakerId + "'.", command);
                    return next;
                }

                try {
                    speakerName =
                        getSerializedNodes(current.getElementsByTagName("displayname")[0]);
                }
                catch (e) {}

                break;
            }
        }

        if (typeof interpreter.assets[textboxName] === "undefined") {
            warn(bus, "Trying to use an unknown textbox or character.", command);
            return next;
        }

        text = getSerializedNodes(command);

        interpreter.log.push({speaker: speakerId, text: text});
        interpreter.assets[textboxName].put(text, speakerName, speakerId);

        return {
            doNext: doNext,
            wait: true
        };
    }

    return line;

});<commit_msg>A character's displayname is now trimmed.<commit_after>/* global using */

using("WSE.tools::getSerializedNodes", "WSE.tools::warn").
define("WSE.commands.line", function (getSerializedNodes, warn) {

    "use strict";

    function line (command, interpreter) {

        var speakerId, speakerName, textboxName, i, len, current;
        var assetElements, text, doNext, bus = interpreter.bus, next;

        next = {doNext: true};

        bus.trigger(
            "wse.interpreter.commands.line",
            {
                interpreter: interpreter,
                command: command
            },
            false
        );

        speakerId = command.getAttribute("s");
        doNext = command.getAttribute("stop") === "false" ? true : false;

        if (speakerId === null) {
            warn(bus, "Element 'line' requires attribute 's'.", command);
            return next;
        }

        assetElements = interpreter.story.getElementsByTagName("character");
        len = assetElements.length;

        for (i = 0; i < len; i += 1) {

            current = assetElements[i];

            if (current.getAttribute("name") === speakerId) {

                textboxName = current.getAttribute("textbox");

                if (typeof textboxName === "undefined" || textboxName === null) {
                    warn(bus, "No textbox defined for character '" + speakerId + "'.", command);
                    return next;
                }

                try {
                    speakerName =
                        getSerializedNodes(current.getElementsByTagName("displayname")[0]).trim();
                }
                catch (e) {}

                break;
            }
        }

        if (typeof interpreter.assets[textboxName] === "undefined") {
            warn(bus, "Trying to use an unknown textbox or character.", command);
            return next;
        }

        text = getSerializedNodes(command);

        interpreter.log.push({speaker: speakerId, text: text});
        interpreter.assets[textboxName].put(text, speakerName, speakerId);

        return {
            doNext: doNext,
            wait: true
        };
    }

    return line;

});<|endoftext|>


<commit_before>var assert = require('chai').assert;
var should = require('chai').should();
var sinon = require('sinon');
var async = require('async');
var featureThrottle = require('../feature-throttle');

describe('feature-throttle', function() {
	var dataSource = null;

	beforeEach(function() {
		dataSource = {
			"set" : sinon.stub(),
			"get" : sinon.stub()
		};
		featureThrottle.setDataSource(dataSource);
	});

	describe('#setThrottles', function() {
		it('should pass given throttles to data source', function(done) {
			var throttles = {"foo" : 1, "bar" : .5};
			featureThrottle.setThrottles(throttles, done);
			dataSource.set.calledWith(throttles, done);
			done();
		});
	});

	describe('#listThrottles', function() {
		it('should return throttles from data source', function(done) {
			var expected = {"bing" : .25, "baz" : .125};
			dataSource.get.callsArgWith(0, null, expected);
			featureThrottle.listThrottles(function(err, actual) {
				if (err)
					throw err;
				actual.should.equal(expected);
				done();
			});
		});
	});

	describe('#removeThrottle', function() {
		it('sets existing throttle data after deleting specified throttle', function(done) {
			var original = {"feature1" : .5, "feature2" : .6};
			dataSource.get.callsArgWith(0, null, original);
			dataSource.set.callsArg(1);
			featureThrottle.removeThrottle("feature2", function(err) {
				if (err)
					throw err;
				dataSource.set.calledWith({"feature1" : .5});
				done();
			});
		});

		it('does not throw when asked to remove non-existent throttle', function(done) {
			var original = {"feature1" : .5};
			dataSource.get.callsArgWith(0, null, original);
			dataSource.set.callsArg(1);
			featureThrottle.removeThrottle("feature2", function(err) {
				if (err)
					throw err;
				dataSource.set.calledWith(original);
				done();
			});
		});
	});

	describe('#updateThrottles', function() {
		it('adds and updates throttles without removing any', function(done){
			var original = {'feature1' : .25, 'feature2' : .5};
			var additional = {'feature1' : .35, 'feature3' : .45};
			dataSource.get.callsArgWith(0, null, original);
			dataSource.set.callsArg(1);
			featureThrottle.updateThrottles(additional, function(err){
				if (err)
					throw err;
				var combined = {'feature1' : .35, 'feature2' : .5, 'feature3' : .45};
				dataSource.set.calledWith(combined);
				done();
			});
		});
	});

	describe('#checkThrottle', function() {
		it('returns false when throttle is set to zero', function(done) {
			var throttles = {'feature' : 0};
			dataSource.get.callsArgWith(0, null, throttles);
			featureThrottle.checkThrottle('feature', 'userId', function(err, didPass) {
				didPass.should.be.false;
				done();
			});
		});

		it('returns true when throttle is set to one', function(done) {
			var throttles = {'feature' : 1};
			dataSource.get.callsArgWith(0, null, throttles);
			featureThrottle.checkThrottle('feature', 'userId', function(err, didPass) {
				didPass.should.be.true;
				done();
			});
		});

		it('returns expected value when throttle is set to fraction', function(done) {
			var throttles = {'feature' : .5};
			var passes = 0;
			var fails = 0;
			var userIds = [];
			dataSource.get.callsArgWith(0, null, throttles);
			for (var i = 0; i < 1000; i++)
				userIds.push("user" + (Math.random() * 10000));
			async.each(userIds, function(userId, itComplete){
				featureThrottle.checkThrottle('feature', userId, function(err, didPass) {
					if (err)
						throw err;
					if (didPass)
						passes++;
					else
						fails++;
					itComplete();
				});
			}, function(err) {
				if (err)
					throw err;
				var percentPassed = passes / (passes + fails);
				percentPassed.should.be.above(.4).and.below(.6);
				done();
			});
		});
	});
});<commit_msg>Moved some stub training into setup function.<commit_after>var assert = require('chai').assert;
var should = require('chai').should();
var sinon = require('sinon');
var async = require('async');
var featureThrottle = require('../feature-throttle');

describe('feature-throttle', function() {
	var dataSource = null;

	beforeEach(function() {
		dataSource = {
			"set" : sinon.stub(),
			"get" : sinon.stub()
		};
		dataSource.set.callsArg(1);
		featureThrottle.setDataSource(dataSource);
	});

	describe('#setThrottles', function() {
		it('should pass given throttles to data source', function(done) {
			var throttles = {"foo" : 1, "bar" : .5};
			featureThrottle.setThrottles(throttles, function(err) {
				if (err)
					throw err;
				dataSource.set.calledWith(throttles);
				done();
			});
		});
	});

	describe('#listThrottles', function() {
		it('should return throttles from data source', function(done) {
			var expected = {"bing" : .25, "baz" : .125};
			dataSource.get.callsArgWith(0, null, expected);
			featureThrottle.listThrottles(function(err, actual) {
				if (err)
					throw err;
				actual.should.equal(expected);
				done();
			});
		});
	});

	describe('#removeThrottle', function() {
		it('sets existing throttle data after deleting specified throttle', function(done) {
			var original = {"feature1" : .5, "feature2" : .6};
			dataSource.get.callsArgWith(0, null, original);
			featureThrottle.removeThrottle("feature2", function(err) {
				if (err)
					throw err;
				dataSource.set.calledWith({"feature1" : .5});
				done();
			});
		});

		it('does not throw when asked to remove non-existent throttle', function(done) {
			var original = {"feature1" : .5};
			dataSource.get.callsArgWith(0, null, original);
			featureThrottle.removeThrottle("feature2", function(err) {
				if (err)
					throw err;
				dataSource.set.calledWith(original);
				done();
			});
		});
	});

	describe('#updateThrottles', function() {
		it('adds and updates throttles without removing any', function(done){
			var original = {'feature1' : .25, 'feature2' : .5};
			var additional = {'feature1' : .35, 'feature3' : .45};
			dataSource.get.callsArgWith(0, null, original);
			featureThrottle.updateThrottles(additional, function(err){
				if (err)
					throw err;
				var combined = {'feature1' : .35, 'feature2' : .5, 'feature3' : .45};
				dataSource.set.calledWith(combined);
				done();
			});
		});
	});

	describe('#checkThrottle', function() {
		it('returns false when throttle is set to zero', function(done) {
			var throttles = {'feature' : 0};
			dataSource.get.callsArgWith(0, null, throttles);
			featureThrottle.checkThrottle('feature', 'userId', function(err, didPass) {
				didPass.should.be.false;
				done();
			});
		});

		it('returns true when throttle is set to one', function(done) {
			var throttles = {'feature' : 1};
			dataSource.get.callsArgWith(0, null, throttles);
			featureThrottle.checkThrottle('feature', 'userId', function(err, didPass) {
				didPass.should.be.true;
				done();
			});
		});

		it('returns expected value when throttle is set to fraction', function(done) {
			var throttles = {'feature' : .5};
			var passes = 0;
			var fails = 0;
			var userIds = [];
			dataSource.get.callsArgWith(0, null, throttles);
			for (var i = 0; i < 1000; i++)
				userIds.push("user" + (Math.random() * 10000));
			async.each(userIds, function(userId, itComplete){
				featureThrottle.checkThrottle('feature', userId, function(err, didPass) {
					if (err)
						throw err;
					if (didPass)
						passes++;
					else
						fails++;
					itComplete();
				});
			}, function(err) {
				if (err)
					throw err;
				var percentPassed = passes / (passes + fails);
				percentPassed.should.be.above(.4).and.below(.6);
				done();
			});
		});
	});
});<|endoftext|>


<commit_before>import React from 'react';
import cx from 'classnames';

import Row from './Row';
import Col from './Col';

class Tabs extends React.Component {

  componentDidMount() {
    if (typeof $ !== 'undefined') {
      $(this.tabsEl).tabs()
    }
  }

  _onSelect(idx, e) {
    if (this.props.hasOwnProperty('onChange')) {
      this.props.onChange(idx, e)
    }
  }

  render() {
    let {children, className, defaultValue, ...props} = this.props;
    return (
      <Row>
        <Col s={12}>

 this.tabsEl = ref}>
            {
              React.Children.map(children, (child, idx) => {
                let {title, tabWidth, className, active, disabled} = child.props;
                //if (!tabWidth) {
                //  tabWidth = Math.floor(12 / count);
                //}
                let classes = {
                  tab: true,
                  disabled,
                  col: true
                };
                if (tabWidth) classes['s' + tabWidth] = true;
                let target = '#tab_' + idx;
                return (

                    {title}

                );
              })
            }

        </Col>
        {
          React.Children.map(children, (child, idx) => {
            return <Col id={'tab_' + idx} s={12} key={'tab' + idx}>{child.props.children}</Col>;
          })
        }
      </Row>
    );
  }
}

export default Tabs;
<commit_msg>Disabled tabs does not handle events anymore<commit_after>import React from 'react';
import cx from 'classnames';

import Row from './Row';
import Col from './Col';

class Tabs extends React.Component {

  componentDidMount() {
    if (typeof $ !== 'undefined') {
      $(this.tabsEl).tabs()
    }
  }

  _onSelect(idx, e) {
    if (this.props.hasOwnProperty('onChange')) {
      this.props.onChange(idx, e)
    }
  }

  render() {
    let {children, className, defaultValue, ...props} = this.props;
    return (
      <Row>
        <Col s={12}>

 this.tabsEl = ref}>
            {
              React.Children.map(children, (child, idx) => {
                let {title, tabWidth, className, active, disabled} = child.props;
                //if (!tabWidth) {
                //  tabWidth = Math.floor(12 / count);
                //}
                let classes = {
                  tab: true,
                  disabled,
                  col: true
                };
                if (tabWidth) classes['s' + tabWidth] = true;
                let target = '#tab_' + idx;
                return (

                    {title}

                );
              })
            }

        </Col>
        {
          React.Children.map(children, (child, idx) => {
            return <Col id={'tab_' + idx} s={12} key={'tab' + idx}>{child.props.children}</Col>;
          })
        }
      </Row>
    );
  }
}

export default Tabs;
<|endoftext|>


<commit_before>var resulttable = function (resultobj) {
    "use strict";
    if (resultobj === 'no results') {
        return "
No results
";
    }
    if (resultobj.results.bindings && resultobj.results.bindings.length > 0) {
        var result, i, j, binding, fieldtype;
        result = "
\n";
        result = result + "
\n";
        for (i = 0; i < resultobj.head.vars.length; i += 1) {
            fieldtype = resultobj.head.vars[i];
            result = result + "  " + fieldtype + "	\n";
        }
        result = result + "
\n";
        for (j = 0; j < resultobj.results.bindings.length; j += 1) {
            binding = resultobj.results.bindings[j];
            result = result + "
\n";
            for (i = 0; i < resultobj.head.vars.length; i += 1) {
                fieldtype = resultobj.head.vars[i];
                //may want to call decodeURIComponent somewhere around here
                //fielddatatype = binding[fieldtype].type;
                result = result + "    " + binding[fieldtype].value + "	\n";
            }
            result = result + "
\n";
        }
        result = result + "
";
        return result;
    }
    return "
No results
";
};
<commit_msg>implement uri links to text in previous column<commit_after>var uricolumn = function (resultobj, column) {
    "use strict";
    var i, binding, celltype;
    for (i = 0; i < resultobj.results.bindings.length; i += 1) {
        binding = resultobj.results.bindings[i];
        celltype = binding[column].type;
        if (celltype !== 'uri') {
            return false;
        }
    }
    return true;
};

var resulttable = function (resultobj) {
    "use strict";
    if (resultobj === 'no results') {
        return "
No results
";
    }
    if (resultobj.results.bindings && resultobj.results.bindings.length > 0) {
        var result, i, j, binding, fieldtype, fieldname, nextfieldname, fielddatatype, nextfielddatatype;
        result = "
\n";
        result = result + "
\n";
        for (i = 0; i < resultobj.head.vars.length; i += 1) {
            fieldtype = resultobj.head.vars[i];
            if (!uricolumn(resultobj, fieldtype)) {
                result = result + "  " + fieldtype + "	\n";
            }
        }
        result = result + "
\n";
        for (j = 0; j < resultobj.results.bindings.length; j += 1) {
            binding = resultobj.results.bindings[j];
            result = result + "
\n";
            for (i = 0; i < resultobj.head.vars.length; i += 1) {
                fieldname = resultobj.head.vars[i];
                fielddatatype = binding[fieldname].type;
                if (i < resultobj.head.vars.length - 1) {
                    nextfielddatatype = binding[resultobj.head.vars[i + 1]].type;
                } else {
                    nextfielddatatype = '';
                }
                if (nextfielddatatype === 'uri') {
                    nextfieldname = resultobj.head.vars[i + 1];
                    result = result + "     " + binding[fieldname].value + "	\n";
                } else {
                    if (fielddatatype !== 'uri') {
                        result = result + "    " + binding[fieldname].value + "	\n";
                    }
                }
            }
            result = result + "
\n";
        }
        result = result + "
";
        return result;
    }
    return "
No results
";
};

<|endoftext|>