<commit_before>(function( $ ) {

module( "tabs: options" );

test( "{ active: default }", function() {
	expect( 4 );

	var element = $( "#tabs1" ).tabs();
	equals( element.tabs( "option", "active" ), 0, "should be 0 by default" );
	tabs_state( element, 1, 0, 0 );
	element.tabs( "destroy" );

	location.hash = "#fragment-3";
	element = $( "#tabs1" ).tabs();
	equals( element.tabs( "option", "active" ), 2, "should be 2 based on URL" );
	tabs_state( element, 0, 0, 1 );
	element.tabs( "destroy" );
	location.hash = "#";
});

test( "{ active: false }", function() {
	expect( 7 );

	var element = $( "#tabs1" ).tabs({
		active: false,
		collapsible: true
	});
	tabs_state( element, 0, 0, 0 );
	equal( element.find( ".ui-tabs-nav .ui-state-active" ).size(), 0, "no tabs selected" );
	strictEqual( element.tabs( "option", "active" ), false );

	element.tabs( "option", "collapsible", false );
	tabs_state( element, 1, 0, 0 );
	equal( element.tabs( "option", "active" ), 0 );

	element.tabs( "destroy" );
	element.tabs({
		active: false
	});
	tabs_state( element, 1, 0, 0 );
	strictEqual( element.tabs( "option", "active" ), 0 );
});

test( "{ active: Number }", function() {
	expect( 8 );

	var element = $( "#tabs1" ).tabs({
		active: 2
	});
	equals( element.tabs( "option", "active" ), 2 );
	tabs_state( element, 0, 0, 1 );

	element.tabs( "option", "active", 0 );
	equals( element.tabs( "option", "active" ), 0 );
	tabs_state( element, 1, 0, 0 );

	element.find( ".ui-tabs-nav a" ).eq( 1 ).click();
	equals( element.tabs( "option", "active" ), 1 );
	tabs_state( element, 0, 1, 0 );

	element.tabs( "option", "active", 10 );
	equals( element.tabs( "option", "active" ), 1 );
	tabs_state( element, 0, 1, 0 );
});

if ( $.uiBackCompat === false ) {
	test( "{ active: -Number }", function() {
		var element = $( "#tabs1" ).tabs({
			active: -1
		});
		equals( element.tabs( "option", "active" ), 2 );
		tabs_state( element, 0, 0, 1 );

		element.tabs( "option", "active", -2 );
		equals( element.tabs( "option", "active" ), 1 );
		tabs_state( element, 0, 1, 0 );

		element.tabs( "option", "active", -10 );
		equals( element.tabs( "option", "active" ), 1 );
		tabs_state( element, 0, 1, 0 );

		element.tabs( "option", "active", -3 );
		equals( element.tabs( "option", "active" ), 0 );
		tabs_state( element, 1, 0, 0 );
	});
}

test( "active - mismatched tab/panel order", function() {
	expect( 3 );

	location.hash = "#tabs7-2";
	var element = $( "#tabs7" ).tabs();
	equals( element.tabs( "option", "active" ), 1, "should be 1 based on URL" );
	tabs_state( element, 0, 1 );
	element.tabs( "option", "active", 0 );
	tabs_state( element, 1, 0 );
	location.hash = "#";
});

test( "{ collapsible: false }", function() {
	expect( 4 );

	var element = $( "#tabs1" ).tabs({
		active: 1
	});
	element.tabs( "option", "active", false );
	equal( element.tabs( "option", "active" ), 1 );
	tabs_state( element, 0, 1, 0 );

	element.find( ".ui-state-active a" ).eq( 1 ).click();
	equal( element.tabs( "option", "active" ), 1 );
	tabs_state( element, 0, 1, 0 );
});

test( "{ collapsible: true }", function() {
	expect( 6 );

	var element = $( "#tabs1" ).tabs({
		active: 1,
		collapsible: true
	});

	element.tabs( "option", "active", false );
	equal( element.tabs( "option", "active" ), false );
	tabs_state( element, 0, 0, 0 );

	element.tabs( "option", "active", 1 );
	equal( element.tabs( "option", "active" ), 1 );
	tabs_state( element, 0, 1, 0 );

	element.find( ".ui-state-active a" ).click();
	equal( element.tabs( "option", "active" ), false );
	tabs_state( element, 0, 0, 0 );
});

test('disabled', function() {
	expect(4);

	el = $('#tabs1').tabs();
	same(el.tabs('option', 'disabled'), false, "should not disable any tab by default");

	el.tabs('option', 'disabled', [ 1 ]);
	same(el.tabs('option', 'disabled'), [ 1 ], "should set property"); // everything else is being tested in methods module...

	el.tabs('option', 'disabled', [ 0, 1 ]);
	same(el.tabs('option', 'disabled'), [ 0, 1 ], "should disable given tabs, even selected one"); // ...

	el.tabs('option', 'disabled', [ ]);
	same(el.tabs('option', 'disabled'), false, "should not disable any tab"); // ...
});

test('event', function() {
	ok(false, "missing test - untested code is broken code.");
});

test('fx', function() {
	ok(false, "missing test - untested code is broken code.");
});

})(jQuery);
<commit_msg>Tabs: Added tests for event option.<commit_after>(function( $ ) {

module( "tabs: options" );

test( "{ active: default }", function() {
	expect( 4 );

	var element = $( "#tabs1" ).tabs();
	equals( element.tabs( "option", "active" ), 0, "should be 0 by default" );
	tabs_state( element, 1, 0, 0 );
	element.tabs( "destroy" );

	location.hash = "#fragment-3";
	element = $( "#tabs1" ).tabs();
	equals( element.tabs( "option", "active" ), 2, "should be 2 based on URL" );
	tabs_state( element, 0, 0, 1 );
	element.tabs( "destroy" );
	location.hash = "#";
});

test( "{ active: false }", function() {
	expect( 7 );

	var element = $( "#tabs1" ).tabs({
		active: false,
		collapsible: true
	});
	tabs_state( element, 0, 0, 0 );
	equal( element.find( ".ui-tabs-nav .ui-state-active" ).size(), 0, "no tabs selected" );
	strictEqual( element.tabs( "option", "active" ), false );

	element.tabs( "option", "collapsible", false );
	tabs_state( element, 1, 0, 0 );
	equal( element.tabs( "option", "active" ), 0 );

	element.tabs( "destroy" );
	element.tabs({
		active: false
	});
	tabs_state( element, 1, 0, 0 );
	strictEqual( element.tabs( "option", "active" ), 0 );
});

test( "{ active: Number }", function() {
	expect( 8 );

	var element = $( "#tabs1" ).tabs({
		active: 2
	});
	equals( element.tabs( "option", "active" ), 2 );
	tabs_state( element, 0, 0, 1 );

	element.tabs( "option", "active", 0 );
	equals( element.tabs( "option", "active" ), 0 );
	tabs_state( element, 1, 0, 0 );

	element.find( ".ui-tabs-nav a" ).eq( 1 ).click();
	equals( element.tabs( "option", "active" ), 1 );
	tabs_state( element, 0, 1, 0 );

	element.tabs( "option", "active", 10 );
	equals( element.tabs( "option", "active" ), 1 );
	tabs_state( element, 0, 1, 0 );
});

if ( $.uiBackCompat === false ) {
	test( "{ active: -Number }", function() {
		var element = $( "#tabs1" ).tabs({
			active: -1
		});
		equals( element.tabs( "option", "active" ), 2 );
		tabs_state( element, 0, 0, 1 );

		element.tabs( "option", "active", -2 );
		equals( element.tabs( "option", "active" ), 1 );
		tabs_state( element, 0, 1, 0 );

		element.tabs( "option", "active", -10 );
		equals( element.tabs( "option", "active" ), 1 );
		tabs_state( element, 0, 1, 0 );

		element.tabs( "option", "active", -3 );
		equals( element.tabs( "option", "active" ), 0 );
		tabs_state( element, 1, 0, 0 );
	});
}

test( "active - mismatched tab/panel order", function() {
	expect( 3 );

	location.hash = "#tabs7-2";
	var element = $( "#tabs7" ).tabs();
	equals( element.tabs( "option", "active" ), 1, "should be 1 based on URL" );
	tabs_state( element, 0, 1 );
	element.tabs( "option", "active", 0 );
	tabs_state( element, 1, 0 );
	location.hash = "#";
});

test( "{ collapsible: false }", function() {
	expect( 4 );

	var element = $( "#tabs1" ).tabs({
		active: 1
	});
	element.tabs( "option", "active", false );
	equal( element.tabs( "option", "active" ), 1 );
	tabs_state( element, 0, 1, 0 );

	element.find( ".ui-state-active a" ).eq( 1 ).click();
	equal( element.tabs( "option", "active" ), 1 );
	tabs_state( element, 0, 1, 0 );
});

test( "{ collapsible: true }", function() {
	expect( 6 );

	var element = $( "#tabs1" ).tabs({
		active: 1,
		collapsible: true
	});

	element.tabs( "option", "active", false );
	equal( element.tabs( "option", "active" ), false );
	tabs_state( element, 0, 0, 0 );

	element.tabs( "option", "active", 1 );
	equal( element.tabs( "option", "active" ), 1 );
	tabs_state( element, 0, 1, 0 );

	element.find( ".ui-state-active a" ).click();
	equal( element.tabs( "option", "active" ), false );
	tabs_state( element, 0, 0, 0 );
});

test('disabled', function() {
	expect(4);

	el = $('#tabs1').tabs();
	same(el.tabs('option', 'disabled'), false, "should not disable any tab by default");

	el.tabs('option', 'disabled', [ 1 ]);
	same(el.tabs('option', 'disabled'), [ 1 ], "should set property"); // everything else is being tested in methods module...

	el.tabs('option', 'disabled', [ 0, 1 ]);
	same(el.tabs('option', 'disabled'), [ 0, 1 ], "should disable given tabs, even selected one"); // ...

	el.tabs('option', 'disabled', [ ]);
	same(el.tabs('option', 'disabled'), false, "should not disable any tab"); // ...
});

test( "{ event: null }", function() {
	expect( 5 );

	var element = $( "#tabs1" ).tabs({
		event: null
	});
	tabs_state( element, 1, 0, 0 );

	element.tabs( "option", "active", 1 );
	equal( element.tabs( "option", "active" ), 1 );
	tabs_state( element, 0, 1, 0 );

	// ensure default click handler isn't bound
	element.find( ".ui-tabs-nav a" ).eq( 2 ).click();
	equal( element.tabs( "option", "active" ), 1 );
	tabs_state( element, 0, 1, 0 );
});

test( "{ event: custom }", function() {
	expect( 11 );

	var element = $( "#tabs1" ).tabs({
		event: "custom1 custom2"
	});
	tabs_state( element, 1, 0, 0 );

	element.find( ".ui-tabs-nav a" ).eq( 1 ).trigger( "custom1" );
	equal( element.tabs( "option", "active" ), 1 );
	tabs_state( element, 0, 1, 0 );

	// ensure default click handler isn't bound
	element.find( ".ui-tabs-nav a" ).eq( 2 ).trigger( "click" );
	equal( element.tabs( "option", "active" ), 1 );
	tabs_state( element, 0, 1, 0 );

	element.find( ".ui-tabs-nav a" ).eq( 2 ).trigger( "custom2" );
	equal( element.tabs( "option", "active" ), 2 );
	tabs_state( element, 0, 0, 1 );

	element.tabs( "option", "event", "custom3" );

	// ensure old event handlers are unbound
	element.find( ".ui-tabs-nav a" ).eq( 1 ).trigger( "custom1" );
	equal( element.tabs( "option", "active" ), 2 );
	tabs_state( element, 0, 0, 1 );

	element.find( ".ui-tabs-nav a" ).eq( 1 ).trigger( "custom3" );
	equal( element.tabs( "option", "active" ), 1 );
	tabs_state( element, 0, 1, 0 );
});

test('fx', function() {
	ok(false, "missing test - untested code is broken code.");
});

})(jQuery);
<|endoftext|>


<commit_before>if (!String.fromCodePoint) {
  require('String.fromCodePoint');
}

// reference emoji
var emojiAt = function (order, block) {
  // emoji blocks, in order, with start, missing blocks, and symbol length
  var emojiBlocks = {
    "Miscellaneous Symbols and Pictographs": {
	   count: 766,
	   start: 0x1F300,
	   missing: [0x1F57A, 0x1F5A4]
     },
     "Emoticons": {
	   count: 80,
	   start: 0x1F600,
	   missing: []
     },
     "Transport and Map Symbols": {
	   count: 98,
	   start: 0x1F680,
	   missing: [0x1F6D1,0x1F6D2,0x1F6D3,0x1F6D4,0x1F6D5,0x1F6D6,0x1F6D7,0x1F6D8,0x1F6D9,0x1F6DA,0x1F6DB,0x1F6DC,0x1F6DD,0x1F6DE,0x1F6DF,0x1F6ED,0x1F6EE,0x1F6EF,0x1F6F4,0x1F6F5,0x1F6F6,0x1F6F7,0x1F6F8,0x1F6F9,0x1F6FA,0x1F6FB,0x1F6FC,0x1F6FD,0x1F6FE,0x1F6FF]
     },
     "Supplemental Symbols and Pictographs": {
	   count: 15,
	   start: 0x1F910,
	   missing: [
0x1F919,0x1F91A,0x1F91B,0x1F91C,0x1F91D,0x1F91E,0x1F91F,0x1F920,0x1F921,0x1F922,0x1F923,0x1F924,0x1F925,0x1F926,0x1F927,0x1F928,0x1F929,0x1F92A,0x1F92B,0x1F92C,0x1F92D,0x1F92E,0x1F92F,0x1F930,0x1F931,0x1F932,0x1F933,0x1F934,0x1F935,0x1F936,0x1F937,0x1F938,0x1F939,0x1F93A,0x1F93B,0x1F93C,0x1F93D,0x1F93E,0x1F93F,0x1F940,0x1F941,0x1F942,0x1F943,0x1F944,0x1F945,0x1F946,0x1F947,0x1F948,0x1F949,0x1F94A,0x1F94B,0x1F94C,0x1F94D,0x1F94E,0x1F94F,0x1F950,0x1F951,0x1F952,0x1F953,0x1F954,0x1F955,0x1F956,0x1F957,0x1F958,0x1F959,0x1F95A,0x1F95B,0x1F95C,0x1F95D,0x1F95E,0x1F95F,0x1F960,0x1F961,0x1F962,0x1F963,0x1F964,0x1F965,0x1F966,0x1F967,0x1F968,0x1F969,0x1F96A,0x1F96B,0x1F96C,0x1F96D,0x1F96E,0x1F96F,0x1F970,0x1F971,0x1F972,0x1F973,0x1F974,0x1F975,0x1F976,0x1F977,0x1F978,0x1F979,0x1F97A,0x1F97B,0x1F97C,0x1F97D,0x1F97E,0x1F97F,0x1F985,0x1F986,0x1F987,0x1F988,0x1F989,0x1F98A,0x1F98B,0x1F98C,0x1F98D,0x1F98E,0x1F98F,0x1F990,0x1F991,0x1F992,0x1F993,0x1F994,0x1F995,0x1F996,0x1F997,0x1F998,0x1F999,0x1F99A,0x1F99B,0x1F99C,0x1F99D,0x1F99E,0x1F99F,0x1F9A0,0x1F9A1,0x1F9A2,0x1F9A3,0x1F9A4,0x1F9A5,0x1F9A6,0x1F9A7,0x1F9A8,0x1F9A9,0x1F9AA,0x1F9AB,0x1F9AC,0x1F9AD,0x1F9AE,0x1F9AF,0x1F9B0,0x1F9B1,0x1F9B2,0x1F9B3,0x1F9B4,0x1F9B5,0x1F9B6,0x1F9B7,0x1F9B8,0x1F9B9,0x1F9BA,0x1F9BB,0x1F9BC,0x1F9BD,0x1F9BE,0x1F9BF
	   ]
     }
  };

  if (!block || !emojiBlocks[block]) {
    // determine overall Unicode order
    var bs = Object.keys(emojiBlocks);
    for (var b = 0; b < bs.length; b++) {
	  if (order < emojiBlocks[bs[b]].count) {
	    return emojiAt(order, bs[b]);
	  } else {
	    order -= emojiBlocks[bs[b]].count;
	  }
    }
  } else {
    // get nth valid character within block
    var nth = emojiBlocks[block].start + order;
    for (var m = 0; m < emojiBlocks[block].missing.length; m++) {
	  if (emojiBlocks[block].missing[m] <= nth) {
	    nth++;
	  } else {
	    break;
	  }
    }
    return String.fromCodePoint(nth);
  }
};

var coordAt = function(lat, lng, precision) {
  // emoji grid reference
  var emojiHeight = 30;
  var emojiWidth = 30;

  var substitutes = {};
  // love hotel replaced by walking person
  substitutes[String.fromCodePoint(127977)] = String.fromCodePoint(0x1F6B6);
  // pile of poo replaced by no-walking sign
  substitutes[String.fromCodePoint(128169)] = String.fromCodePoint(0x1F6B7);

  precision = precision || 3;
  var hash = "";
  var north = 90.0;
  var south = -90.0;
  var east = 180.0;
  var west = -180.0;

  for (var i = 0; i < precision; i++) {
    var latRatio = ((lat - south) / (north - south));
    var lngRatio = ((lng - west) / (east - west));
    var latRow = Math.floor(latRatio * emojiHeight);
    var lngColumn = Math.floor(lngRatio * emojiWidth);
    // console.log("zoom " + (i+1) + ": at " + (latRow+1) + "th row, " + (lngColumn+1) + "th column");

    // add appropriate emoji to hash
    var newc = emojiAt(emojiWidth * latRow + lngColumn);
    if (substitutes[newc]) {
      newc = substitutes[newc];
    }
    hash += newc;

    // calculate next box of the grid
    var gridHeight = (north - south) / emojiHeight;
    var gridWidth = (east - west) / emojiWidth;
    south += gridHeight * latRow;
    north = south + gridHeight;
    west += gridWidth * lngColumn;
    east = west + gridWidth;
  }
  return hash;
};

if (process.argv.length < 4) {
  console.log("use syntax: node geohash.js LATITUDE LONGITUDE");
} else {
  // retrieve arguments
  var lat = process.argv[2] * 1;
  var lng = process.argv[3] * 1;
  if (isNaN(lat) || isNaN(lng)) {
    return console.log("use syntax: node geohash.js LATITUDE LONGITUDE");
  }

  console.log( coordAt( lat, lng ) );
}

if (typeof exports !== "undefined") {
  exports.emojiAt = emojiAt;
  exports.coordAt = coordAt;
}<commit_msg>case-sensitive require for systems where that matters<commit_after>if (!String.fromCodePoint) {
  require('string.fromcodepoint');
}

// reference emoji
var emojiAt = function (order, block) {
  // emoji blocks, in order, with start, missing blocks, and symbol length
  var emojiBlocks = {
    "Miscellaneous Symbols and Pictographs": {
	   count: 766,
	   start: 0x1F300,
	   missing: [0x1F57A, 0x1F5A4]
     },
     "Emoticons": {
	   count: 80,
	   start: 0x1F600,
	   missing: []
     },
     "Transport and Map Symbols": {
	   count: 98,
	   start: 0x1F680,
	   missing: [0x1F6D1,0x1F6D2,0x1F6D3,0x1F6D4,0x1F6D5,0x1F6D6,0x1F6D7,0x1F6D8,0x1F6D9,0x1F6DA,0x1F6DB,0x1F6DC,0x1F6DD,0x1F6DE,0x1F6DF,0x1F6ED,0x1F6EE,0x1F6EF,0x1F6F4,0x1F6F5,0x1F6F6,0x1F6F7,0x1F6F8,0x1F6F9,0x1F6FA,0x1F6FB,0x1F6FC,0x1F6FD,0x1F6FE,0x1F6FF]
     },
     "Supplemental Symbols and Pictographs": {
	   count: 15,
	   start: 0x1F910,
	   missing: [
0x1F919,0x1F91A,0x1F91B,0x1F91C,0x1F91D,0x1F91E,0x1F91F,0x1F920,0x1F921,0x1F922,0x1F923,0x1F924,0x1F925,0x1F926,0x1F927,0x1F928,0x1F929,0x1F92A,0x1F92B,0x1F92C,0x1F92D,0x1F92E,0x1F92F,0x1F930,0x1F931,0x1F932,0x1F933,0x1F934,0x1F935,0x1F936,0x1F937,0x1F938,0x1F939,0x1F93A,0x1F93B,0x1F93C,0x1F93D,0x1F93E,0x1F93F,0x1F940,0x1F941,0x1F942,0x1F943,0x1F944,0x1F945,0x1F946,0x1F947,0x1F948,0x1F949,0x1F94A,0x1F94B,0x1F94C,0x1F94D,0x1F94E,0x1F94F,0x1F950,0x1F951,0x1F952,0x1F953,0x1F954,0x1F955,0x1F956,0x1F957,0x1F958,0x1F959,0x1F95A,0x1F95B,0x1F95C,0x1F95D,0x1F95E,0x1F95F,0x1F960,0x1F961,0x1F962,0x1F963,0x1F964,0x1F965,0x1F966,0x1F967,0x1F968,0x1F969,0x1F96A,0x1F96B,0x1F96C,0x1F96D,0x1F96E,0x1F96F,0x1F970,0x1F971,0x1F972,0x1F973,0x1F974,0x1F975,0x1F976,0x1F977,0x1F978,0x1F979,0x1F97A,0x1F97B,0x1F97C,0x1F97D,0x1F97E,0x1F97F,0x1F985,0x1F986,0x1F987,0x1F988,0x1F989,0x1F98A,0x1F98B,0x1F98C,0x1F98D,0x1F98E,0x1F98F,0x1F990,0x1F991,0x1F992,0x1F993,0x1F994,0x1F995,0x1F996,0x1F997,0x1F998,0x1F999,0x1F99A,0x1F99B,0x1F99C,0x1F99D,0x1F99E,0x1F99F,0x1F9A0,0x1F9A1,0x1F9A2,0x1F9A3,0x1F9A4,0x1F9A5,0x1F9A6,0x1F9A7,0x1F9A8,0x1F9A9,0x1F9AA,0x1F9AB,0x1F9AC,0x1F9AD,0x1F9AE,0x1F9AF,0x1F9B0,0x1F9B1,0x1F9B2,0x1F9B3,0x1F9B4,0x1F9B5,0x1F9B6,0x1F9B7,0x1F9B8,0x1F9B9,0x1F9BA,0x1F9BB,0x1F9BC,0x1F9BD,0x1F9BE,0x1F9BF
	   ]
     }
  };

  if (!block || !emojiBlocks[block]) {
    // determine overall Unicode order
    var bs = Object.keys(emojiBlocks);
    for (var b = 0; b < bs.length; b++) {
	  if (order < emojiBlocks[bs[b]].count) {
	    return emojiAt(order, bs[b]);
	  } else {
	    order -= emojiBlocks[bs[b]].count;
	  }
    }
  } else {
    // get nth valid character within block
    var nth = emojiBlocks[block].start + order;
    for (var m = 0; m < emojiBlocks[block].missing.length; m++) {
	  if (emojiBlocks[block].missing[m] <= nth) {
	    nth++;
	  } else {
	    break;
	  }
    }
    return String.fromCodePoint(nth);
  }
};

var coordAt = function(lat, lng, precision) {
  // emoji grid reference
  var emojiHeight = 30;
  var emojiWidth = 30;

  var substitutes = {};
  // love hotel replaced by walking person
  substitutes[String.fromCodePoint(127977)] = String.fromCodePoint(0x1F6B6);
  // pile of poo replaced by no-walking sign
  substitutes[String.fromCodePoint(128169)] = String.fromCodePoint(0x1F6B7);

  precision = precision || 3;
  var hash = "";
  var north = 90.0;
  var south = -90.0;
  var east = 180.0;
  var west = -180.0;

  for (var i = 0; i < precision; i++) {
    var latRatio = ((lat - south) / (north - south));
    var lngRatio = ((lng - west) / (east - west));
    var latRow = Math.floor(latRatio * emojiHeight);
    var lngColumn = Math.floor(lngRatio * emojiWidth);
    // console.log("zoom " + (i+1) + ": at " + (latRow+1) + "th row, " + (lngColumn+1) + "th column");

    // add appropriate emoji to hash
    var newc = emojiAt(emojiWidth * latRow + lngColumn);
    if (substitutes[newc]) {
      newc = substitutes[newc];
    }
    hash += newc;

    // calculate next box of the grid
    var gridHeight = (north - south) / emojiHeight;
    var gridWidth = (east - west) / emojiWidth;
    south += gridHeight * latRow;
    north = south + gridHeight;
    west += gridWidth * lngColumn;
    east = west + gridWidth;
  }
  return hash;
};

if (process.argv.length < 4) {
  console.log("use syntax: node geohash.js LATITUDE LONGITUDE");
} else {
  // retrieve arguments
  var lat = process.argv[2] * 1;
  var lng = process.argv[3] * 1;
  if (isNaN(lat) || isNaN(lng)) {
    return console.log("use syntax: node geohash.js LATITUDE LONGITUDE");
  }

  console.log( coordAt( lat, lng ) );
}

if (typeof exports !== "undefined") {
  exports.emojiAt = emojiAt;
  exports.coordAt = coordAt;
}
<|endoftext|>


<commit_before>function approx(actual, expected, message) {
    var diff = 0;
    for(var i=0, stop=actual.length; i<stop; i++) {
        diff = Math.abs(1 - actual[i]/expected[i]);
        if(diff > 0.1) {
            deepEqual(actual, expected, message);
            return;
        }
    }
    ok(true, message);
}

module('HSL conversion');

test("rgb <-> hsv", function() {
    var rgb_hsv = [
        [[0, 0, 0], [0, 0, 0]],
        [[0, 0, 255], [4/6, 1, 1]],
        [[0, 255, 0], [2/6, 1, 1]],
        [[0, 255, 255], [3/6, 1, 1]],
        [[255, 0, 0], [0, 1, 1]],
        [[255, 0, 255], [5/6, 1, 1]],
        [[255, 255, 0], [1/6, 1, 1]],
        [[255, 255, 255], [0, 0, 1]],
        [[255/2, 255/2, 255/2], [0, 0, 1/2]],
    ];
    for(var i=0, stop=rgb_hsv.length; i<stop; i++) {
        var current = rgb_hsv[i];
        var rgb = current[0], hsv = current[1];

        approx(rgb_to_hsv(rgb), hsv, 'rgb_to_hsv([' + rgb + ']) -> [' + hsv + ']');
        approx(hsv_to_rgb(hsv), rgb, 'hsv_to_rgb([' + hsv + ']) -> [' + rgb + ']');
    }
});

module('HSL conversion');

test("rgb <-> hsl", function() {
    var rgb_hsl = [
        [[0, 0, 0], [0, 0, 0]],
        [[0, 0, 255], [4/6, 1, 1/2]],
        [[0, 255, 0], [2/6, 1, 1/2]],
        [[0, 255, 255], [3/6, 1, 1/2]],
        [[255, 0, 0], [0, 1, 1/2]],
        [[255, 0, 255], [5/6, 1, 1/2]],
        [[255, 255, 0], [1/6, 1, 1/2]],
        [[255, 255, 255], [0, 0, 1]],
        [[255/2, 255/2, 255/2], [0, 0, 1/2]],
    ];

    for(var i=0, stop=rgb_hsl.length; i<stop; i++) {
        var current = rgb_hsl[i];
        var rgb = current[0], hsl = current[1];

        approx(rgb_to_hsl(rgb), hsl, 'rgb_to_hsl([' + rgb + ']) -> [' + hsl + ']');
        approx(hsl_to_rgb(hsl), rgb, 'hsl_to_rgb([' + hsl + ']) -> [' + rgb + ']');
    }
})

module('Blend Modes');

function run_blend_tests(data, mode) {
    for(var i=0, stop=data.length; i<stop; i++) {
        var current = data[i];
        var c1 = current[0], c2 = current[1], r = current[2];

        deepEqual(blend(mode, c1, c2), r, 'blend("' + mode + '", [' + c1 + '], [' + c2 + '] -> [' + r + ']');
    }
}

test("multiply", function() {
    var c1_c2_r = [
        [[50,100,150],[100,100,100],[20,39,59]],
        [[100,100,100],[50,100,150],[20,39,59]],
        [[123,234,12],[90,40,180],[43,37,8]],
        [[90,40,180],[123,234,12],[43,37,8]],
    ];
    run_blend_tests(c1_c2_r, 'multiply');
});

test("screen", function() {
    var c1_c2_r = [
        [[50,100,150],[100,100,100],[131,162,192]],
        [[100,100,100],[50,100,150],[131,162,192]],
        [[123,234,12],[90,40,180],[170,238,184]],
        [[90,40,180],[123,234,12],[170,238,184]],
    ];
    run_blend_tests(c1_c2_r, 'screen');
});

test("overlay", function() {

});

test("dodge", function() {

});

test("burn", function() {

});

test("negate", function() {

});
<commit_msg>Adding overlay tests.<commit_after>function approx(actual, expected, message) {
    var diff = 0;
    for(var i=0, stop=actual.length; i<stop; i++) {
        diff = Math.abs(1 - actual[i]/expected[i]);
        if(diff > 0.1) {
            deepEqual(actual, expected, message);
            return;
        }
    }
    ok(true, message);
}

module('HSL conversion');

test("rgb <-> hsv", function() {
    var rgb_hsv = [
        [[0, 0, 0], [0, 0, 0]],
        [[0, 0, 255], [4/6, 1, 1]],
        [[0, 255, 0], [2/6, 1, 1]],
        [[0, 255, 255], [3/6, 1, 1]],
        [[255, 0, 0], [0, 1, 1]],
        [[255, 0, 255], [5/6, 1, 1]],
        [[255, 255, 0], [1/6, 1, 1]],
        [[255, 255, 255], [0, 0, 1]],
        [[255/2, 255/2, 255/2], [0, 0, 1/2]],
    ];
    for(var i=0, stop=rgb_hsv.length; i<stop; i++) {
        var current = rgb_hsv[i];
        var rgb = current[0], hsv = current[1];

        approx(rgb_to_hsv(rgb), hsv, 'rgb_to_hsv([' + rgb + ']) -> [' + hsv + ']');
        approx(hsv_to_rgb(hsv), rgb, 'hsv_to_rgb([' + hsv + ']) -> [' + rgb + ']');
    }
});

module('HSL conversion');

test("rgb <-> hsl", function() {
    var rgb_hsl = [
        [[0, 0, 0], [0, 0, 0]],
        [[0, 0, 255], [4/6, 1, 1/2]],
        [[0, 255, 0], [2/6, 1, 1/2]],
        [[0, 255, 255], [3/6, 1, 1/2]],
        [[255, 0, 0], [0, 1, 1/2]],
        [[255, 0, 255], [5/6, 1, 1/2]],
        [[255, 255, 0], [1/6, 1, 1/2]],
        [[255, 255, 255], [0, 0, 1]],
        [[255/2, 255/2, 255/2], [0, 0, 1/2]],
    ];

    for(var i=0, stop=rgb_hsl.length; i<stop; i++) {
        var current = rgb_hsl[i];
        var rgb = current[0], hsl = current[1];

        approx(rgb_to_hsl(rgb), hsl, 'rgb_to_hsl([' + rgb + ']) -> [' + hsl + ']');
        approx(hsl_to_rgb(hsl), rgb, 'hsl_to_rgb([' + hsl + ']) -> [' + rgb + ']');
    }
})

module('Blend Modes');

function run_blend_tests(data, mode) {
    for(var i=0, stop=data.length; i<stop; i++) {
        var current = data[i];
        var c1 = current[0], c2 = current[1], r = current[2];

        deepEqual(blend(mode, c1, c2), r, 'blend("' + mode + '", [' + c1 + '], [' + c2 + '] -> [' + r + ']');
    }
}

test("multiply", function() {
    var c1_c2_r = [
        [[50,100,150],[100,100,100],[20,39,59]],
        [[100,100,100],[50,100,150],[20,39,59]],
        [[123,234,12],[90,40,180],[43,37,8]],
        [[90,40,180],[123,234,12],[43,37,8]],
    ];
    run_blend_tests(c1_c2_r, 'multiply');
});

test("screen", function() {
    var c1_c2_r = [
        [[50,100,150],[100,100,100],[131,162,192]],
        [[100,100,100],[50,100,150],[131,162,192]],
        [[123,234,12],[90,40,180],[170,238,184]],
        [[90,40,180],[123,234,12],[170,238,184]],
    ];
    run_blend_tests(c1_c2_r, 'screen');
});

test("overlay", function() {
    var c1_c2_r = [
        [[50,100,150],[100,100,100],[39,78,127]],
        [[100,100,100],[50,100,150],[39,78,118]],
        [[123,234,12],[90,40,180],[87,220,17]],
        [[90,40,180],[123,234,12],[87,73,112]],
    ];
    run_blend_tests(c1_c2_r, 'overlay');
});

test("dodge", function() {

});

test("burn", function() {

});

test("negate", function() {

});
<|endoftext|>


<commit_before>/**
 * Array.filter() shim by Trevor Menagh (https://github.com/trevmex) with some modifications
 */

if (!Array.prototype.filter) {
  Array.prototype.filter = function (fun, thisp) {
    "use strict";

    if (typeof this === "undefined" || this === null) {
      throw new TypeError();
    }
    if (typeof fun !== "function") {
      throw new TypeError();
    }

    thisp = thisp || this;

    var len = this.length,
      res = [],
      i,
      val;

    for (i = 0; i < len; i += 1) {
      if (this.hasOwnProperty(i)) {
        val = this[i]; // in case fun mutates this
        if (fun.call(thisp, val, i, this)) {
          res.push(val);
        }
      }
    }

    return res;
  };
}
<commit_msg>Bugfix #934. Fixed Array.filter shim. It now handles NodeList objects in IE8 correctly.<commit_after>/**
 * Array.filter() shim by Trevor Menagh (https://github.com/trevmex) with some modifications
 */

if (!Array.prototype.filter) {
  Array.prototype.filter = function (fun, thisp) {
    "use strict";

    if (typeof this === "undefined" || this === null) {
      throw new TypeError();
    }
    if (typeof fun !== "function") {
      throw new TypeError();
    }

    thisp = thisp || this;

    if (isNodeList(thisp)) {
      thisp = convertNodeListToArray(thisp);
    }

    var len = thisp.length,
      res = [],
      i,
      val;

    for (i = 0; i < len; i += 1) {
      if (thisp.hasOwnProperty(i)) {
        val = thisp[i]; // in case fun mutates this
        if (fun.call(thisp, val, i, thisp)) {
          res.push(val);
        }
      }
    }

    return res;

    function isNodeList(object) {
      return /NodeList/i.test(object.item);
    }

    function convertNodeListToArray(nodeList) {
      var array = [];

      for (var i = 0, len = nodeList.length; i < len; i++){
        array[i] = nodeList[i]
      }

      return array;
    }
  };
}
<|endoftext|>


<commit_before>import isMulti from '../utils/is-multi';
import actions from '../actions';

function createControlPropsMap() {
  function getTextValue(value) {
    if (typeof value === 'string' || typeof value === 'number') {
      return `${value}`;
    }

    return '';
  }

  function isChecked(props) {
    if (isMulti(props.model)) {
      if (!props.modelValue) return false;

      return props.modelValue.some((item) =>
        item === props.value);
    }

    return !!props.modelValue;
  }

  const textPropsMap = {
    value: (props) => ((!props.defaultValue && !props.hasOwnProperty('value'))
      ? getTextValue(props.viewValue)
      : props.value),
    name: (props) => props.name || props.model,
    onChange: ({ onChange }) => onChange,
    onBlur: ({ onBlur }) => onBlur,
    onFocus: ({ onFocus }) => onFocus,
    onKeyPress: ({ onKeyPress }) => onKeyPress,
  };

  return {
    default: textPropsMap,
    checkbox: {
      name: (props) => props.name || props.model,
      checked: (props) => (props.defaultChecked
        ? props.checked
        : isChecked(props)),
      onChange: ({ onChange }) => onChange,
      onBlur: ({ onBlur }) => onBlur,
      onFocus: ({ onFocus }) => onFocus,
      onKeyPress: ({ onKeyPress }) => onKeyPress,
    },
    radio: {
      name: (props) => props.name || props.model,
      checked: (props) => (props.defaultChecked
        ? props.checked
        : props.modelValue === props.value),
      value: (props) => props.value,
      onChange: ({ onChange }) => onChange,
      onBlur: ({ onBlur }) => onBlur,
      onFocus: ({ onFocus }) => onFocus,
      onKeyPress: ({ onKeyPress }) => onKeyPress,
    },
    select: {
      name: (props) => (props.name || props.model),
      value: (props) => (props.modelValue),
      onChange: ({ onChange }) => onChange,
      onBlur: ({ onBlur }) => onBlur,
      onFocus: ({ onFocus }) => onFocus,
      onKeyPress: ({ onKeyPress }) => onKeyPress,
    },
    text: textPropsMap,
    textarea: textPropsMap,
    file: {
      name: (props) => props.name || props.model,
      onChange: ({ onChange }) => onChange,
      onBlur: ({ onBlur }) => onBlur,
      onFocus: ({ onFocus }) => onFocus,
      onKeyPress: ({ onKeyPress }) => onKeyPress,
    },
    reset: {
      onClick: (props) => (event) => {
        event.preventDefault();
        props.dispatch(actions.reset(props.model));
      },
      onFocus: ({ onFocus }) => onFocus,
      onBlur: ({ onBlur }) => onBlur,
    },
  };
}

const controlPropsMap = createControlPropsMap();

export default controlPropsMap;
export {
  createControlPropsMap,
};
<commit_msg>Allowing numbers pass-thru. Fixes #487<commit_after>import isMulti from '../utils/is-multi';
import actions from '../actions';

function createControlPropsMap() {
  function getTextValue(value) {
    if (typeof value === 'string') {
      return `${value}`;
    } else if (typeof value === 'number') {
      return value;
    }

    return '';
  }

  function isChecked(props) {
    if (isMulti(props.model)) {
      if (!props.modelValue) return false;

      return props.modelValue.some((item) =>
        item === props.value);
    }

    return !!props.modelValue;
  }

  const textPropsMap = {
    value: (props) => ((!props.defaultValue && !props.hasOwnProperty('value'))
      ? getTextValue(props.viewValue)
      : props.value),
    name: (props) => props.name || props.model,
    onChange: ({ onChange }) => onChange,
    onBlur: ({ onBlur }) => onBlur,
    onFocus: ({ onFocus }) => onFocus,
    onKeyPress: ({ onKeyPress }) => onKeyPress,
  };

  return {
    default: textPropsMap,
    checkbox: {
      name: (props) => props.name || props.model,
      checked: (props) => (props.defaultChecked
        ? props.checked
        : isChecked(props)),
      onChange: ({ onChange }) => onChange,
      onBlur: ({ onBlur }) => onBlur,
      onFocus: ({ onFocus }) => onFocus,
      onKeyPress: ({ onKeyPress }) => onKeyPress,
    },
    radio: {
      name: (props) => props.name || props.model,
      checked: (props) => (props.defaultChecked
        ? props.checked
        : props.modelValue === props.value),
      value: (props) => props.value,
      onChange: ({ onChange }) => onChange,
      onBlur: ({ onBlur }) => onBlur,
      onFocus: ({ onFocus }) => onFocus,
      onKeyPress: ({ onKeyPress }) => onKeyPress,
    },
    select: {
      name: (props) => (props.name || props.model),
      value: (props) => (props.modelValue),
      onChange: ({ onChange }) => onChange,
      onBlur: ({ onBlur }) => onBlur,
      onFocus: ({ onFocus }) => onFocus,
      onKeyPress: ({ onKeyPress }) => onKeyPress,
    },
    text: textPropsMap,
    textarea: textPropsMap,
    file: {
      name: (props) => props.name || props.model,
      onChange: ({ onChange }) => onChange,
      onBlur: ({ onBlur }) => onBlur,
      onFocus: ({ onFocus }) => onFocus,
      onKeyPress: ({ onKeyPress }) => onKeyPress,
    },
    reset: {
      onClick: (props) => (event) => {
        event.preventDefault();
        props.dispatch(actions.reset(props.model));
      },
      onFocus: ({ onFocus }) => onFocus,
      onBlur: ({ onBlur }) => onBlur,
    },
  };
}

const controlPropsMap = createControlPropsMap();

export default controlPropsMap;
export {
  createControlPropsMap,
};
<|endoftext|>


<commit_before>import { lighten, darken } from 'polished';

const colorOffsetLight = 0.15;
const colorOffsetDark = 0.07;

export default {
  breakpoints: {
    mobile: '13.6em',
    mobileWide: '30.4em',
    tablet: '47.2em',
    desktop: '64em',
    desktopLarge: '97.6em'
  },
  gradient: {
    skyDew: 'linear-gradient(left, #76C4E2, #85CBA8)',
    twilightDew: 'linear-gradient(left, #8176B5, #85CBA8)',
    twilightSky: 'linear-gradient(left, #8176B5, #76C4E2)',
    twilightSunset: 'linear-gradient(left, #8176B5, #BA77B1)',
    twilightDawn: 'linear-gradient(left, #8176B5, #F16975)',
    dawnSunrise: 'linear-gradient(left, #F16975, #F69259)',
    sunriseLightning: 'linear-gradient(left, #F69259, #FFDB6F)',
    dewLightning: 'linear-gradient(left, #85CBA8, #FFDB6F)'
  },
  color: {
    //Style guide colors
    rain: '#408BC9',
    sky: '#76C4E2',
    dew: '#85CBA8',
    deepsea: '#1E4E79',
    twilight: '#8176B5',
    sunset: '#BA77B1',
    dawn: '#F16975',
    sunrise: '#F69259',
    lightning: '#FFDB6F',
    night: '#404041',
    dusk: '#4D4D4F',
    storm: '#808285',
    hail: '#BCBEC0',
    moonshine: '#F7F7F7',
    //current colors
    cement: '#7D7D7D',
    grass: '#9BCA3E',
    marine: '#2F7BBF',
    tangerine: '#FF7900',
    apple: '#BD2527',
    charcoal: '#333333',
    carrot: '#f56500',
    smoke: '#e0e0e0'
  },
  fontSize: '15px',
  boxShadow: '0 0 20px 0 rgba(136,136,136,0.50)',
  inputFontSize: '13px',
  lineHeight: 1.5,
  inputLineHeight: 1.4,
  em: '1em',
  rem: '1rem',
  fontFamily: '"Open Sans", Helvetica, Arial, sans-serif',
  weightLight: 300,
  weightNormal: 400,
  weightSemiBold: 600,
  weightBold: 700,
  fontWeight: 400,
  fontWeightLight: 300,
  fontColorHeadingCaption: '#888',
  borderRadius: '2px',
  arrowSize: '5px',
  disabledBackground: '#ededed',
  bodyBackground: '#ebebeb',
  bodyAccentColor: darken(0.8, '#fff'),
  bodyOffsetColor: darken(0.53, '#fff'),
  fontColor: darken(0.8, '#fff'),
  colorWhite: '#fff',
  colorBlack: '#000',
  colorOffsetLight,
  colorOffsetDark,
  colorInfo: '#00a9eb',
  colorSuccess: '#68970f',
  colorWarning: '#fca520',
  colorError: '#ff3100',
  colorMuted: darken(0.5125, '#fff'),
  colorSmoke: '#f2f2f2',
  colorBlue: '#2f7bbf',
  colorBlueLight: lighten(colorOffsetLight, '#2f7bbf'),
  colorBlueDark: darken(colorOffsetDark, '#2f7bbf'),
  colorOrange: '#ff7900',
  colorOrangeLight: lighten(colorOffsetLight, '#ff7900'),
  colorOrangeDark: darken(colorOffsetDark, '#ff7900'),
  colorGray: darken(0.5125, '#fff'),
  colorGrayLight: darken(0.13, '#fff'),
  colorGrayLightOnboarding: '#F7F7F7',
  colorGrayDark: darken(0.8, '#fff'),
  colorGrayBorder: '#666',
  colorGreen: '#9bca3e',
  colorGreenLight: lighten(colorOffsetLight, '#9bca3e'),
  colorGreenDark: darken(colorOffsetDark, '#9bca3e'),
  colorRed: '#bd2527',
  colorRedLight: lighten(colorOffsetLight, '#bd2527'),
  colorRedDark: darken(colorOffsetDark, '#bd2527'),
  colorYellow: '#ffd24d',
  colorYellowLight: lighten(colorOffsetLight, '#ffd24d'),
  colorYellowDark: darken(colorOffsetDark, '#ffd24d'),
  colorPink: '#d91698',
  colorPinkLight: lighten(colorOffsetLight, '#d91698'),
  colorPinkDark: darken(colorOffsetDark, '#d91698'),
  colorPurple: '#9545e5',
  colorPurpleLight: lighten(colorOffsetLight, '#d91698'),
  colorPurpleDark: darken(colorOffsetDark, '#d91698'),
  colorTwitterBlue: '#00aced',
  colorFacebookBlue: '#3b5998',
  colorMainBackground: '#e6e6e6',
  colorOverlay: 'rgba(0, 0, 0, .7)',
  colorImportantInformation: 'rgba(64,139,201,0.2)',
  zIndexMax: 1000
};
<commit_msg>feat(cf-style-const): Add new color called dust<commit_after>import { lighten, darken } from 'polished';

const colorOffsetLight = 0.15;
const colorOffsetDark = 0.07;

export default {
  breakpoints: {
    mobile: '13.6em',
    mobileWide: '30.4em',
    tablet: '47.2em',
    desktop: '64em',
    desktopLarge: '97.6em'
  },
  gradient: {
    skyDew: 'linear-gradient(left, #76C4E2, #85CBA8)',
    twilightDew: 'linear-gradient(left, #8176B5, #85CBA8)',
    twilightSky: 'linear-gradient(left, #8176B5, #76C4E2)',
    twilightSunset: 'linear-gradient(left, #8176B5, #BA77B1)',
    twilightDawn: 'linear-gradient(left, #8176B5, #F16975)',
    dawnSunrise: 'linear-gradient(left, #F16975, #F69259)',
    sunriseLightning: 'linear-gradient(left, #F69259, #FFDB6F)',
    dewLightning: 'linear-gradient(left, #85CBA8, #FFDB6F)'
  },
  color: {
    //Style guide colors
    rain: '#408BC9',
    sky: '#76C4E2',
    dew: '#85CBA8',
    deepsea: '#1E4E79',
    twilight: '#8176B5',
    sunset: '#BA77B1',
    dawn: '#F16975',
    sunrise: '#F69259',
    lightning: '#FFDB6F',
    night: '#404041',
    dusk: '#4D4D4F',
    storm: '#808285',
    hail: '#BCBEC0',
    moonshine: '#F7F7F7',
    //current colors
    cement: '#7D7D7D',
    grass: '#9BCA3E',
    marine: '#2F7BBF',
    tangerine: '#FF7900',
    apple: '#BD2527',
    charcoal: '#333333',
    carrot: '#f56500',
    smoke: '#e0e0e0',
    dust: '#ebebeb'
  },
  fontSize: '15px',
  boxShadow: '0 0 20px 0 rgba(136,136,136,0.50)',
  inputFontSize: '13px',
  lineHeight: 1.5,
  inputLineHeight: 1.4,
  em: '1em',
  rem: '1rem',
  fontFamily: '"Open Sans", Helvetica, Arial, sans-serif',
  weightLight: 300,
  weightNormal: 400,
  weightSemiBold: 600,
  weightBold: 700,
  fontWeight: 400,
  fontWeightLight: 300,
  fontColorHeadingCaption: '#888',
  borderRadius: '2px',
  arrowSize: '5px',
  disabledBackground: '#ededed',
  bodyBackground: '#ebebeb',
  bodyAccentColor: darken(0.8, '#fff'),
  bodyOffsetColor: darken(0.53, '#fff'),
  fontColor: darken(0.8, '#fff'),
  colorWhite: '#fff',
  colorBlack: '#000',
  colorOffsetLight,
  colorOffsetDark,
  colorInfo: '#00a9eb',
  colorSuccess: '#68970f',
  colorWarning: '#fca520',
  colorError: '#ff3100',
  colorMuted: darken(0.5125, '#fff'),
  colorSmoke: '#f2f2f2',
  colorBlue: '#2f7bbf',
  colorBlueLight: lighten(colorOffsetLight, '#2f7bbf'),
  colorBlueDark: darken(colorOffsetDark, '#2f7bbf'),
  colorOrange: '#ff7900',
  colorOrangeLight: lighten(colorOffsetLight, '#ff7900'),
  colorOrangeDark: darken(colorOffsetDark, '#ff7900'),
  colorGray: darken(0.5125, '#fff'),
  colorGrayLight: darken(0.13, '#fff'),
  colorGrayLightOnboarding: '#F7F7F7',
  colorGrayDark: darken(0.8, '#fff'),
  colorGrayBorder: '#666',
  colorGreen: '#9bca3e',
  colorGreenLight: lighten(colorOffsetLight, '#9bca3e'),
  colorGreenDark: darken(colorOffsetDark, '#9bca3e'),
  colorRed: '#bd2527',
  colorRedLight: lighten(colorOffsetLight, '#bd2527'),
  colorRedDark: darken(colorOffsetDark, '#bd2527'),
  colorYellow: '#ffd24d',
  colorYellowLight: lighten(colorOffsetLight, '#ffd24d'),
  colorYellowDark: darken(colorOffsetDark, '#ffd24d'),
  colorPink: '#d91698',
  colorPinkLight: lighten(colorOffsetLight, '#d91698'),
  colorPinkDark: darken(colorOffsetDark, '#d91698'),
  colorPurple: '#9545e5',
  colorPurpleLight: lighten(colorOffsetLight, '#d91698'),
  colorPurpleDark: darken(colorOffsetDark, '#d91698'),
  colorTwitterBlue: '#00aced',
  colorFacebookBlue: '#3b5998',
  colorMainBackground: '#e6e6e6',
  colorOverlay: 'rgba(0, 0, 0, .7)',
  colorImportantInformation: 'rgba(64,139,201,0.2)',
  zIndexMax: 1000
};
<|endoftext|>


<commit_before>const sharedUtils = require('./sharedUtils');
const gitCommands = require('./gitCommands');

function checkoutOrCreate(branchName) {
    try {
        gitCommands.checkout(branchName);
    } catch (e) {
        console.log(`Branch ${branchName} doesn't exist yet. Creating it now.`);
        gitCommands.createBranch(branchName);
    }
}

function isOutOfDate() {
    const fileStatus = gitCommands.getStatus().toString();
    const changesExist = fileStatus.includes('Changes');

    if (changesExist) {
        gitCommands.stash();
    }

    gitCommands.checkout('master');
    const status = gitCommands.getStatus();

    const outOfDateStatus = status.includes('up to date')
        || status.includes('is ahead of');

    gitCommands.checkout('workspace');

    if (changesExist) {
        gitCommands.popFromStash();
    }

    return !outOfDateStatus;
}

function setUpWorkspaceBranch() {
    let fileStashSuccessful = false;

    try {
        console.log('Setting up a working environment...');

        gitCommands.stash();
        fileStashSuccessful = true;
        checkoutOrCreate('workspace');
    } catch (e) {
        console.log('Uh oh! Something unexpected happened: ', e);
    }

    if (fileStashSuccessful) {
        gitCommands.popFromStash();
    }
}

function hasGitInstalled() {
    try {
        gitCommands.getStatus();
        return true;
    } catch (e) {
        return false;
    }
}

function checkOutBranch(branchName) {
    try {
        gitCommands.checkout(branchName);
    } catch (e) {
        sharedUtils.logSetupError(`It looks like ${branchName} is not set up yet.`);
        process.exit(1);
    }
}

function runIfGitIsInstalled(command) {
    return function (...args) {
        let result = false;

        if (hasGitInstalled()) {
            result = command(...args);
        }

        return result;
    }
}

module.exports = {
    checkOutBranch: runIfGitIsInstalled(checkOutBranch),
    hasGitInstalled,
    isOutOfDate: runIfGitIsInstalled(isOutOfDate),
    setUpWorkspaceBranch: runIfGitIsInstalled(setUpWorkspaceBranch)
}

<commit_msg>Moved pop to try/catch to avoid weird error states<commit_after>const sharedUtils = require('./sharedUtils');
const gitCommands = require('./gitCommands');

function checkoutOrCreate(branchName) {
    try {
        gitCommands.checkout(branchName);
    } catch (e) {
        console.log(`Branch ${branchName} doesn't exist yet. Creating it now.`);
        gitCommands.createBranch(branchName);
    }
}

function safePop() {
    try{
        gitCommands.popFromStash();
    } catch(e) {
        // do nothing and move along.
    }
}

function isOutOfDate() {
    const fileStatus = gitCommands.getStatus().toString();
    const changesExist = fileStatus.includes('Changes');

    if (changesExist) {
        gitCommands.stash();
    }

    gitCommands.checkout('master');
    const status = gitCommands.getStatus();

    const outOfDateStatus = status.includes('up to date')
        || status.includes('is ahead of');

    gitCommands.checkout('workspace');

    if (changesExist) {
        safePop();
    }

    return !outOfDateStatus;
}

function setUpWorkspaceBranch() {
    let fileStashSuccessful = false;

    try {
        console.log('Setting up a working environment...');

        gitCommands.stash();
        fileStashSuccessful = true;
        checkoutOrCreate('workspace');
    } catch (e) {
        console.log('Uh oh! Something unexpected happened: ', e);
    }

    if (fileStashSuccessful) {
        safePop();
    }
}

function hasGitInstalled() {
    try {
        gitCommands.getStatus();
        return true;
    } catch (e) {
        return false;
    }
}

function checkOutBranch(branchName) {
    try {
        gitCommands.checkout(branchName);
    } catch (e) {
        sharedUtils.logSetupError(`It looks like ${branchName} is not set up yet.`);
        process.exit(1);
    }
}

function runIfGitIsInstalled(command) {
    return function (...args) {
        let result = false;

        if (hasGitInstalled()) {
            result = command(...args);
        }

        return result;
    }
}

module.exports = {
    checkOutBranch: runIfGitIsInstalled(checkOutBranch),
    hasGitInstalled,
    isOutOfDate: runIfGitIsInstalled(isOutOfDate),
    setUpWorkspaceBranch: runIfGitIsInstalled(setUpWorkspaceBranch)
}

<|endoftext|>


<commit_before>var Swarm = require('bittorrent-swarm')
var TrackerGroup = require('bittorrent-tracker').TrackerGroup;
var MetadataDownload = require('./metadata_download');
var DataValidator = require('./data_validator');
var DataDownload = require('./data_download');
var infoToFiles = require('./info_files');
var FileStorage = require('./file_storage');
var RarityMap = require('./rarity_map');
var MIME = require('./mime');
var FileStream = require('./file_stream');

module.exports = TorrentContext;

function TorrentContext(infoHash, info) {
    /* TODO: generate: */
    this.peerId = generatePeerId();
    this.infoHash = infoHash;
    this.swarm = new Swarm(infoHash, this.peerId);

    var metadata = new MetadataDownload(infoHash, this.swarm, info);
    if (info) {
        this._onInfo(info);
    } else {
        metadata.on('complete', this._onInfo.bind(this));
    }

    this.swarm.on('wire', function(wire) {
        wire.setTimeout(3000);
        wire.on('extended', function(ext, info) {
            if (ext === 'handshake' &&
                Buffer.isBuffer(info.yourip) &&
                info.yourip.length === 4) {

                var myip = [0, 1, 2, 3].map(function(i) {
                    return info.yourip[i];
                }).join(".");
                // console.log(wire.remoteAddress, "says my IP is:", myip);
            }
        });
    });
}

TorrentContext.prototype.addTrackerGroup = function(urls) {
    var tg = new TrackerGroup(urls);
    tg.on('info', function(info) {
        info.infoHash = this.infoHash;
        info.peerId = this.peerId;
        // TODO
    }.bind(this));
    tg.on('peers', function(peers) {
        console.log('peers', peers);
        peers.forEach(function(peer) {
            /* TODO: fix for ipv6 */
            this.swarm.add(peer.ip + ":" + peer.port);
        }.bind(this));
    }.bind(this));
    tg.start();
};

TorrentContext.prototype._onInfo = function(info) {
    if (this.info) {
        /* Already set */
        return;
    }

    this.info = info;
    console.log("info", info);
    var sha1sums = [];
    for(var i = 0; i < info.pieces.length - 19; i += 20) {
        sha1sums.push(info.pieces.slice(i, i + 20));
    }
    this.pieceLength = info['piece length'];
    var files = infoToFiles(info, this.infoHash);
    this.totalLength = 0;
    files.forEach(function(file) {
        file.mime = MIME(file.name);
        this.totalLength += file.length;
    }.bind(this));
    console.log("files1", files);
    this.storage = new FileStorage(files);
    console.log("files2", files);

    this.download = new DataDownload(this.pieceLength, this.totalLength);
    this.validator = new DataValidator(sha1sums, this.pieceLength, this.totalLength);
    this.rarity = new RarityMap(this.swarm, this.validator.pieces.length);
    this.validator.on('read', function(index, offset, length) {
        var range = this.download.getValidateableRange(index, offset)
        if (range.length > 0) {
            // console.log("validatable range", index, ":", range);
            var totalOffset = index * this.pieceLength + range.offset;
            this.storage.read(totalOffset, range.length, function(err, data) {
                if (data) {
                    this.validator.onData(index, range.offset, data);
                }
            }.bind(this));
        }
    }.bind(this));
    this.validator.on('piece:complete', function(index) {
        console.warn("Piece", index, "complete, bitfield now:", this.validator.bitfield);
        this.download.removePiece(index);
        this.swarm.wires.forEach(function(wire) {
            wire.have(index);
            this._canInterest(wire);
        }.bind(this));
    }.bind(this));
    this.validator.on('piece:corrupt', function(index) {
        console.warn("Piece", index, "corrupt, must retry...");
        this.download.pieceCorrupted(index);
    }.bind(this));

    var setupWire = function(wire) {
        /* Send bitfield */
        wire.bitfield(this.validator.bitfield);
        /* Change interest status */
        wire.on('bitfield', function() {
            this._canInterest(wire);
        }.bind(this));
        wire.on('have', function() {
            this._canInterest(wire);
        }.bind(this));
        this._canInterest(wire);

        /* Start requesting */
        wire.on('unchoke', function() {
            this._canRequest(wire);
        }.bind(this));
        this._canRequest(wire);

        wire.on('interested', function() {
            console.log(wire.remoteAddress, "peer is interested");
            wire.unchoke();
        }.bind(this));
        wire.on('request', function(index, offset, length, respond) {
            if (this.validator.isPieceComplete(index)) {
                var totalOffset = index * this.pieceLength + offset;
                this.storage.read(totalOffset, length, respond);
            } else {
                respond(new Error("Peer requested incomplete piece " + index));
            }
        }.bind(this));

        wire.on('end', function() {
            wire.requests.forEach(function(req) {
                this.download.onError({
                    piece: req.index,
                    offset: req.offset,
                    length: req.length
                });
            });
        }.bind(this));
    }.bind(this);
    this.swarm.wires.forEach(setupWire);
    this.swarm.on('wire', setupWire);

    /* Stats print loop */
    setInterval(function() {
        this.download.pieces.forEach(function(piece) {
            var requested = 0, downloaded = 0, total = 0;
            piece.chunks.forEach(function(chunk) {
                total += chunk.length;
                if (chunk.state === 'requested')
                    requested += chunk.length;
                else if (chunk.state === 'downloaded')
                    downloaded += chunk.length;
            });
            function p(l) {
                return Math.floor(100 * l / total) + "%";
            }
            // console.log(piece.index + ":", p(requested), "requested", p(downloaded), "downloaded, since", Math.floor((Date.now() - piece.started) / 100) / 10, "rarity:", this.rarity.rarity[piece.index]);
        }.bind(this));
        var unchoked = this.swarm.wires.filter(function(wire) {
            return !wire.peerChoking;
        }).length;
        var interested = this.swarm.wires.filter(function(wire) {
            return wire.peerInterested;
        }).length;
        console.log(Math.floor(100 * (1 - this.validator.getBytesLeft() / this.totalLength)) + "% Interested in", this.download.pieces.length, "pieces with", this.swarm.wires.length, "peers,", unchoked, "unchoked", this.swarm.downloadSpeed(), "down", interested, "interested", this.swarm.uploadSpeed(), "up");
    }.bind(this), 1000);
};

TorrentContext.prototype._canInterest = function(wire) {
    var interested = false;
    var piecesAmount = this.validator.pieces.length;
    for(var i = 0; !interested && i < piecesAmount; i++) {
        interested =
            wire.peerPieces.get(i) &&
            !this.validator.isPieceComplete(i);
    }
    if (interested) {
        wire.interested();
    } else {
        wire.uninterested();
    }
};

TorrentContext.prototype._canRequestAll = function(wire) {
    this.swarm.wires.forEach(this._canRequest.bind(this));
};

TorrentContext.prototype._canRequest = function(wire) {
    /* Pieces per second */
    var rps = wire.downloadSpeed() / DataDownload.chunkSize;
    var minReqs = Math.max(2, Math.ceil(0.5 * rps));
    var maxReqs = Math.max(minReqs + 1, Math.ceil(1 * rps));
    // console.log("reqs:", minReqs, "..", maxReqs, "x", DataDownload.chunkSize, "@", wire.downloadSpeed());

    if (wire.peerChoking || wire.requests.length >= minReqs || wire._finished) {
        return;
    }

    var pieceFilter = function(index) {
        return wire.peerPieces.get(index) &&
            !this.validator.isPieceComplete(index) &&
            !this.download.isDownloadingPiece(index);
    }.bind(this);

    var needMore = true;
    while(needMore) {
        var chunks = this.download.nextToDownload(wire, maxReqs - wire.requests.length);
        // console.log(wire.remoteAddress, "will be requested with", chunks.length, "chunks for bandwidth:", wire.downloadSpeed());
        chunks.forEach(function(chunk) {
            // console.log(wire.remoteAddress, "request", chunk.index, ":", chunk.offset, "+", chunk.length);
            wire.request(chunk.index, chunk.offset, chunk.length, function(error, data) {
                if (error) {
                    // console.warn(wire.remoteAddress, "cb", error.message, { destroyed: wire.destroyed, _finished: wire._finished });
                    if (error.message == 'request has timed out') {
                        wire.cancel(chunk.index, chunk.offset, chunk.length);
                    }
                    this.download.onError(chunk);
                    this._canRequestAll();
                    return;
                }
                if (this.validator.isPieceComplete(chunk.index)) {
                    console.log("Waste of bandwidth,", chunk.index, "+", chunk.offset, "not needed");
                    return;
                }

                // console.warn(wire.remoteAddress, "cb", data.length);
                this.storage.write(chunk.index * this.pieceLength + chunk.offset, data, function(err) {
                    if (err) {
                        console.error(err.stack);
                        return;
                    }
                    this.download.onDownloaded(chunk);
                    console.log("downloaded", chunk.index, chunk.offset);
                    /* TODO: but it may be complete *now*, leading to an exception */
                    this.validator.onData(chunk.index, chunk.offset, data);
                    this._canRequest(wire);
                }.bind(this));
            }.bind(this));
        }.bind(this));

        needMore = wire.requests.length < maxReqs;
        if (needMore) {
            var index = this.rarity.findRarest(pieceFilter);
            if (typeof index === 'number') {
                if (this.download.addPiece(index)) {
                    // console.log("needed more, added piece", index);
                } else {
                    console.log("is already downloading", index, ":", this.download.getPiece(index));
                    needMore = false;
                }
            } else {
                /* Nothing left, TODO: go piece stealing */
                // console.log("needed more but nothing left");
                needMore = false;
            }
        }
    }
};

var STREAM_READAHEAD_TIME = 2000;

TorrentContext.prototype.streamFile = function(fileName, offset, length) {
    var file;
    if ((storage = this.storage)) {
        file = storage.files.filter(function(file) {
            return file.name === fileName;
        })[0];
    }

    if (file) {
        var torrentOffset = storage.fileToOffset(file.path, offset);
        console.log("length", length, "file.length", file.length, "offset", offset);
        if (!isNaN(length)) {
            length = Math.min(length, file.length - offset);
        } else {
            length = file.length - offset;
        }
        length = Math.min(length, file.length - offset);
        var stream = new FileStream(this.validator, this.storage, torrentOffset, length);
        stream.mime = file.mime;
        stream.fileLength = file.length;
        stream.on('priorize', function(index) {
            var piecesReadahead = Math.max(
                2,
                Math.ceil((STREAM_READAHEAD_TIME / 1000) * this.swarm.downloadSpeed() / this.pieceLength)
            );
            var indexes = [];
            var piecesAmount = this.validator.pieces.length;
            for(var i = index; i < piecesAmount && indexes.length < piecesReadahead; i++) {
                if (!this.validator.isPieceComplete(i)) {
                    indexes.push(i);
                }
            }
            this.download.priorizePieces(indexes);
        }.bind(this));
        return stream;
    } else {
        return null;
    }
};

function generatePeerId() {
    return new Buffer([
        0x2d, 0x41, 0x51, 0x32, 0x30,
        0x36, 0x30, 0x2d, 0, 0, 0,
        0, 0, 0, 0, 0,
        0, 0, 0, 0].map(function(ch) {
            return ch != 0 ? ch :
                Math.floor(32 + 95 * Math.random());
        })
    );
}
<commit_msg>torrent_context: require 'bittorent-tracker-client'<commit_after>var Swarm = require('bittorrent-swarm')
var TrackerGroup = require('bittorrent-tracker-client').TrackerGroup;
var MetadataDownload = require('./metadata_download');
var DataValidator = require('./data_validator');
var DataDownload = require('./data_download');
var infoToFiles = require('./info_files');
var FileStorage = require('./file_storage');
var RarityMap = require('./rarity_map');
var MIME = require('./mime');
var FileStream = require('./file_stream');

module.exports = TorrentContext;

function TorrentContext(infoHash, info) {
    /* TODO: generate: */
    this.peerId = generatePeerId();
    this.infoHash = infoHash;
    this.swarm = new Swarm(infoHash, this.peerId);

    var metadata = new MetadataDownload(infoHash, this.swarm, info);
    if (info) {
        this._onInfo(info);
    } else {
        metadata.on('complete', this._onInfo.bind(this));
    }

    this.swarm.on('wire', function(wire) {
        wire.setTimeout(3000);
        wire.on('extended', function(ext, info) {
            if (ext === 'handshake' &&
                Buffer.isBuffer(info.yourip) &&
                info.yourip.length === 4) {

                var myip = [0, 1, 2, 3].map(function(i) {
                    return info.yourip[i];
                }).join(".");
                // console.log(wire.remoteAddress, "says my IP is:", myip);
            }
        });
    });
}

TorrentContext.prototype.addTrackerGroup = function(urls) {
    var tg = new TrackerGroup(urls);
    tg.on('info', function(info) {
        info.infoHash = this.infoHash;
        info.peerId = this.peerId;
        // TODO
    }.bind(this));
    tg.on('peers', function(peers) {
        console.log('peers', peers);
        peers.forEach(function(peer) {
            /* TODO: fix for ipv6 */
            this.swarm.add(peer.ip + ":" + peer.port);
        }.bind(this));
    }.bind(this));
    tg.start();
};

TorrentContext.prototype._onInfo = function(info) {
    if (this.info) {
        /* Already set */
        return;
    }

    this.info = info;
    console.log("info", info);
    var sha1sums = [];
    for(var i = 0; i < info.pieces.length - 19; i += 20) {
        sha1sums.push(info.pieces.slice(i, i + 20));
    }
    this.pieceLength = info['piece length'];
    var files = infoToFiles(info, this.infoHash);
    this.totalLength = 0;
    files.forEach(function(file) {
        file.mime = MIME(file.name);
        this.totalLength += file.length;
    }.bind(this));
    console.log("files1", files);
    this.storage = new FileStorage(files);
    console.log("files2", files);

    this.download = new DataDownload(this.pieceLength, this.totalLength);
    this.validator = new DataValidator(sha1sums, this.pieceLength, this.totalLength);
    this.rarity = new RarityMap(this.swarm, this.validator.pieces.length);
    this.validator.on('read', function(index, offset, length) {
        var range = this.download.getValidateableRange(index, offset)
        if (range.length > 0) {
            // console.log("validatable range", index, ":", range);
            var totalOffset = index * this.pieceLength + range.offset;
            this.storage.read(totalOffset, range.length, function(err, data) {
                if (data) {
                    this.validator.onData(index, range.offset, data);
                }
            }.bind(this));
        }
    }.bind(this));
    this.validator.on('piece:complete', function(index) {
        console.warn("Piece", index, "complete, bitfield now:", this.validator.bitfield);
        this.download.removePiece(index);
        this.swarm.wires.forEach(function(wire) {
            wire.have(index);
            this._canInterest(wire);
        }.bind(this));
    }.bind(this));
    this.validator.on('piece:corrupt', function(index) {
        console.warn("Piece", index, "corrupt, must retry...");
        this.download.pieceCorrupted(index);
    }.bind(this));

    var setupWire = function(wire) {
        /* Send bitfield */
        wire.bitfield(this.validator.bitfield);
        /* Change interest status */
        wire.on('bitfield', function() {
            this._canInterest(wire);
        }.bind(this));
        wire.on('have', function() {
            this._canInterest(wire);
        }.bind(this));
        this._canInterest(wire);

        /* Start requesting */
        wire.on('unchoke', function() {
            this._canRequest(wire);
        }.bind(this));
        this._canRequest(wire);

        wire.on('interested', function() {
            console.log(wire.remoteAddress, "peer is interested");
            wire.unchoke();
        }.bind(this));
        wire.on('request', function(index, offset, length, respond) {
            if (this.validator.isPieceComplete(index)) {
                var totalOffset = index * this.pieceLength + offset;
                this.storage.read(totalOffset, length, respond);
            } else {
                respond(new Error("Peer requested incomplete piece " + index));
            }
        }.bind(this));

        wire.on('end', function() {
            wire.requests.forEach(function(req) {
                this.download.onError({
                    piece: req.index,
                    offset: req.offset,
                    length: req.length
                });
            });
        }.bind(this));
    }.bind(this);
    this.swarm.wires.forEach(setupWire);
    this.swarm.on('wire', setupWire);

    /* Stats print loop */
    setInterval(function() {
        this.download.pieces.forEach(function(piece) {
            var requested = 0, downloaded = 0, total = 0;
            piece.chunks.forEach(function(chunk) {
                total += chunk.length;
                if (chunk.state === 'requested')
                    requested += chunk.length;
                else if (chunk.state === 'downloaded')
                    downloaded += chunk.length;
            });
            function p(l) {
                return Math.floor(100 * l / total) + "%";
            }
            // console.log(piece.index + ":", p(requested), "requested", p(downloaded), "downloaded, since", Math.floor((Date.now() - piece.started) / 100) / 10, "rarity:", this.rarity.rarity[piece.index]);
        }.bind(this));
        var unchoked = this.swarm.wires.filter(function(wire) {
            return !wire.peerChoking;
        }).length;
        var interested = this.swarm.wires.filter(function(wire) {
            return wire.peerInterested;
        }).length;
        console.log(Math.floor(100 * (1 - this.validator.getBytesLeft() / this.totalLength)) + "% Interested in", this.download.pieces.length, "pieces with", this.swarm.wires.length, "peers,", unchoked, "unchoked", this.swarm.downloadSpeed(), "down", interested, "interested", this.swarm.uploadSpeed(), "up");
    }.bind(this), 1000);
};

TorrentContext.prototype._canInterest = function(wire) {
    var interested = false;
    var piecesAmount = this.validator.pieces.length;
    for(var i = 0; !interested && i < piecesAmount; i++) {
        interested =
            wire.peerPieces.get(i) &&
            !this.validator.isPieceComplete(i);
    }
    if (interested) {
        wire.interested();
    } else {
        wire.uninterested();
    }
};

TorrentContext.prototype._canRequestAll = function(wire) {
    this.swarm.wires.forEach(this._canRequest.bind(this));
};

TorrentContext.prototype._canRequest = function(wire) {
    /* Pieces per second */
    var rps = wire.downloadSpeed() / DataDownload.chunkSize;
    var minReqs = Math.max(2, Math.ceil(0.5 * rps));
    var maxReqs = Math.max(minReqs + 1, Math.ceil(1 * rps));
    // console.log("reqs:", minReqs, "..", maxReqs, "x", DataDownload.chunkSize, "@", wire.downloadSpeed());

    if (wire.peerChoking || wire.requests.length >= minReqs || wire._finished) {
        return;
    }

    var pieceFilter = function(index) {
        return wire.peerPieces.get(index) &&
            !this.validator.isPieceComplete(index) &&
            !this.download.isDownloadingPiece(index);
    }.bind(this);

    var needMore = true;
    while(needMore) {
        var chunks = this.download.nextToDownload(wire, maxReqs - wire.requests.length);
        // console.log(wire.remoteAddress, "will be requested with", chunks.length, "chunks for bandwidth:", wire.downloadSpeed());
        chunks.forEach(function(chunk) {
            // console.log(wire.remoteAddress, "request", chunk.index, ":", chunk.offset, "+", chunk.length);
            wire.request(chunk.index, chunk.offset, chunk.length, function(error, data) {
                if (error) {
                    // console.warn(wire.remoteAddress, "cb", error.message, { destroyed: wire.destroyed, _finished: wire._finished });
                    if (error.message == 'request has timed out') {
                        wire.cancel(chunk.index, chunk.offset, chunk.length);
                    }
                    this.download.onError(chunk);
                    this._canRequestAll();
                    return;
                }
                if (this.validator.isPieceComplete(chunk.index)) {
                    console.log("Waste of bandwidth,", chunk.index, "+", chunk.offset, "not needed");
                    return;
                }

                // console.warn(wire.remoteAddress, "cb", data.length);
                this.storage.write(chunk.index * this.pieceLength + chunk.offset, data, function(err) {
                    if (err) {
                        console.error(err.stack);
                        return;
                    }
                    this.download.onDownloaded(chunk);
                    console.log("downloaded", chunk.index, chunk.offset);
                    /* TODO: but it may be complete *now*, leading to an exception */
                    this.validator.onData(chunk.index, chunk.offset, data);
                    this._canRequest(wire);
                }.bind(this));
            }.bind(this));
        }.bind(this));

        needMore = wire.requests.length < maxReqs;
        if (needMore) {
            var index = this.rarity.findRarest(pieceFilter);
            if (typeof index === 'number') {
                if (this.download.addPiece(index)) {
                    // console.log("needed more, added piece", index);
                } else {
                    console.log("is already downloading", index, ":", this.download.getPiece(index));
                    needMore = false;
                }
            } else {
                /* Nothing left, TODO: go piece stealing */
                // console.log("needed more but nothing left");
                needMore = false;
            }
        }
    }
};

var STREAM_READAHEAD_TIME = 2000;

TorrentContext.prototype.streamFile = function(fileName, offset, length) {
    var file;
    if ((storage = this.storage)) {
        file = storage.files.filter(function(file) {
            return file.name === fileName;
        })[0];
    }

    if (file) {
        var torrentOffset = storage.fileToOffset(file.path, offset);
        console.log("length", length, "file.length", file.length, "offset", offset);
        if (!isNaN(length)) {
            length = Math.min(length, file.length - offset);
        } else {
            length = file.length - offset;
        }
        length = Math.min(length, file.length - offset);
        var stream = new FileStream(this.validator, this.storage, torrentOffset, length);
        stream.mime = file.mime;
        stream.fileLength = file.length;
        stream.on('priorize', function(index) {
            var piecesReadahead = Math.max(
                2,
                Math.ceil((STREAM_READAHEAD_TIME / 1000) * this.swarm.downloadSpeed() / this.pieceLength)
            );
            var indexes = [];
            var piecesAmount = this.validator.pieces.length;
            for(var i = index; i < piecesAmount && indexes.length < piecesReadahead; i++) {
                if (!this.validator.isPieceComplete(i)) {
                    indexes.push(i);
                }
            }
            this.download.priorizePieces(indexes);
        }.bind(this));
        return stream;
    } else {
        return null;
    }
};

function generatePeerId() {
    return new Buffer([
        0x2d, 0x41, 0x51, 0x32, 0x30,
        0x36, 0x30, 0x2d, 0, 0, 0,
        0, 0, 0, 0, 0,
        0, 0, 0, 0].map(function(ch) {
            return ch != 0 ? ch :
                Math.floor(32 + 95 * Math.random());
        })
    );
}
<|endoftext|>


<commit_before>/* global CustomEvent */

import { moduleFor, test } from 'ember-qunit';
import Ember from 'ember';
import sinon from 'sinon';

let service;
let sandbox;

moduleFor('service:unified-event-handler', 'Unit | Service | UnifiedEventHandler', {
  beforeEach() {
    service = this.subject();
    sandbox = sinon.sandbox.create();
  },
  afterEach() {
    sandbox.restore();
  }
});

/* register */

test('register binds callback to the event on the specified target', function(assert) {
  let callbackStub = sandbox.stub();
  service.register('window', 'scroll', callbackStub);
  window.dispatchEvent(new CustomEvent('scroll'));
  assert.ok(callbackStub.calledOnce);

  service.unregister('window', 'scroll', callbackStub);
});

test('unregisters event listeners when service is destroyed', function(assert) {
  let done = assert.async();
  let callbackStub = sandbox.stub();
  service.register('window', 'scroll', callbackStub);

  Ember.run(service, 'destroy');

  Ember.run(function() {
    window.dispatchEvent(new CustomEvent('scroll'));
    assert.ok(callbackStub.notCalled);
    done();
  });
});

test('unregisters multiple event listeners of same event type when service is destroyed', function(assert) {
  let done = assert.async();
  let callbackStub = sandbox.stub();
  let callbackBStub = sandbox.stub();
  service.register('window', 'scroll', callbackStub);
  service.register('window', 'scroll', callbackBStub);

  Ember.run(service, 'destroy');

  Ember.run(function() {
    window.dispatchEvent(new CustomEvent('scroll'));
    assert.ok(callbackStub.notCalled);
    assert.ok(callbackBStub.notCalled);
    done();
  });
});

test('unregisters multiple event listeners of different event types when service is destroyed', function(assert) {
  let done = assert.async();
  let callbackStub = sandbox.stub();
  let callbackBStub = sandbox.stub();
  service.register('window', 'scroll', callbackStub);
  service.register('window', 'resize', callbackBStub);

  Ember.run(service, 'destroy');

  Ember.run(function() {
    window.dispatchEvent(new CustomEvent('resize'));
    window.dispatchEvent(new CustomEvent('scroll'));
    assert.ok(callbackStub.notCalled);
    assert.ok(callbackBStub.notCalled);
    done();
  });
});

test('register binds multiple callbacks to the event on the specified target but only triggers once', function(assert) {
  assert.expect(3);

  let callback1Stub = sandbox.stub();
  let callback2Stub = sandbox.stub();
  let triggerSpy = sandbox.spy(service, 'triggerEvent');

  service.register('window', 'scroll', callback1Stub);
  service.register('window', 'scroll', callback2Stub);
  window.dispatchEvent(new CustomEvent('scroll'));
  assert.ok(callback1Stub.calledOnce);
  assert.ok(callback2Stub.calledOnce);
  assert.ok(triggerSpy.calledOnce);

  service.unregister('window', 'scroll', callback1Stub);
  service.unregister('window', 'scroll', callback2Stub);
});

test('register binds callbacks to multiple events on the specified target', function(assert) {
  assert.expect(4);

  let callback1Stub = sandbox.stub();
  let callback2Stub = sandbox.stub();

  service.register('window', 'resize', callback1Stub);
  service.register('window', 'scroll', callback2Stub);

  window.dispatchEvent(new CustomEvent('resize'));
  assert.ok(callback1Stub.calledOnce);
  assert.ok(callback2Stub.notCalled);

  window.dispatchEvent(new CustomEvent('scroll'));
  assert.ok(callback1Stub.calledOnce);
  assert.ok(callback2Stub.calledOnce);

  service.unregister('window', 'resize', callback1Stub);
  service.unregister('window', 'scroll', callback2Stub);
});

test('register binds callbacks to different events on multiple targets', function(assert) {
  assert.expect(4);

  let callback1Stub = sandbox.stub();
  let callback2Stub = sandbox.stub();

  service.register('window', 'resize', callback1Stub);
  service.register('document', 'scroll', callback2Stub);

  window.dispatchEvent(new CustomEvent('resize'));
  assert.ok(callback1Stub.calledOnce);
  assert.ok(callback2Stub.notCalled);

  document.dispatchEvent(new CustomEvent('scroll'));
  assert.ok(callback1Stub.calledOnce);
  assert.ok(callback2Stub.calledOnce);

  service.unregister('window', 'resize', callback1Stub);
  service.unregister('document', 'scroll', callback2Stub);
});

/* unregister */

test('unregister unbinds the callback from its event', function(assert) {
  let callbackSpy = sandbox.stub();

  service.register('window', 'scroll', callbackSpy);
  service.unregister('window', 'scroll', callbackSpy);
  window.dispatchEvent(new CustomEvent('scroll'));
  assert.ok(callbackSpy.notCalled);
});

test('unregister unbinds the callback from its event but leaves other callbacks for that event', function(assert) {
  assert.expect(2);

  let callback1Stub = sandbox.stub();
  let callback2Stub = sandbox.stub();

  service.register('window', 'scroll', callback1Stub);
  service.register('window', 'scroll', callback2Stub);
  service.unregister('window', 'scroll', callback2Stub);
  window.dispatchEvent(new CustomEvent('scroll'));

  assert.ok(callback1Stub.calledOnce);
  assert.ok(callback2Stub.notCalled);

  service.unregister('window', 'scroll', callback1Stub);
});

test('unregister destroys the DOM handler after all callbacks have been unbound', function(assert) {
  assert.expect(2);

  let callbackSpy = sandbox.stub();
  let triggerSpy = sandbox.spy(service, 'triggerEvent');

  service.register('window', 'scroll', callbackSpy);
  service.unregister('window', 'scroll', callbackSpy);
  window.dispatchEvent(new CustomEvent('scroll'));

  assert.ok(callbackSpy.notCalled);
  assert.ok(triggerSpy.notCalled);
});

test('unregister destroys the DOM handler for an event after all callbacks have been unbound but leaves other events', function(assert) {
  assert.expect(3);

  let callback1Spy = sandbox.stub();
  let callback2Spy = sandbox.stub();
  let triggerSpy = sandbox.spy(service, 'triggerEvent');

  service.register('window', 'scroll', callback1Spy);
  service.register('window', 'resize', callback2Spy);
  service.unregister('window', 'scroll', callback1Spy);
  window.dispatchEvent(new CustomEvent('resize'));

  assert.ok(callback1Spy.notCalled);
  assert.ok(callback2Spy.calledOnce);
  assert.ok(triggerSpy.calledOnce);

  service.unregister('window', 'resize', callback2Spy);
});

/* triggerEvent */

test('triggerEvent triggers the event at a throttled rate', function(assert) {
  assert.expect(2);

  let throttleSpy = sandbox.spy(Ember.run, 'throttle');
  let callbackStub = sandbox.stub();

  service.on('testing', callbackStub);
  service.triggerEvent('testing');

  assert.ok(throttleSpy.calledOnce);
  assert.ok(callbackStub.calledOnce);
});
<commit_msg>Test register method targeting element.class<commit_after>/* global CustomEvent */

import { moduleFor, test } from 'ember-qunit';
import Ember from 'ember';
import sinon from 'sinon';

let service;
let sandbox;

moduleFor('service:unified-event-handler', 'Unit | Service | UnifiedEventHandler', {
  beforeEach() {
    service = this.subject();
    sandbox = sinon.sandbox.create();
  },
  afterEach() {
    sandbox.restore();
  }
});

/* register */

test('register binds callback to the event on the specified target', function(assert) {
  let callbackStub = sandbox.stub();
  service.register('window', 'scroll', callbackStub);
  window.dispatchEvent(new CustomEvent('scroll'));
  assert.ok(callbackStub.calledOnce);

  service.unregister('window', 'scroll', callbackStub);
});

test('unregisters event listeners when service is destroyed', function(assert) {
  let done = assert.async();
  let callbackStub = sandbox.stub();
  service.register('window', 'scroll', callbackStub);

  Ember.run(service, 'destroy');

  Ember.run(function() {
    window.dispatchEvent(new CustomEvent('scroll'));
    assert.ok(callbackStub.notCalled);
    done();
  });
});

test('unregisters multiple event listeners of same event type when service is destroyed', function(assert) {
  let done = assert.async();
  let callbackStub = sandbox.stub();
  let callbackBStub = sandbox.stub();
  service.register('window', 'scroll', callbackStub);
  service.register('window', 'scroll', callbackBStub);

  Ember.run(service, 'destroy');

  Ember.run(function() {
    window.dispatchEvent(new CustomEvent('scroll'));
    assert.ok(callbackStub.notCalled);
    assert.ok(callbackBStub.notCalled);
    done();
  });
});

test('unregisters multiple event listeners of different event types when service is destroyed', function(assert) {
  let done = assert.async();
  let callbackStub = sandbox.stub();
  let callbackBStub = sandbox.stub();
  service.register('window', 'scroll', callbackStub);
  service.register('window', 'resize', callbackBStub);

  Ember.run(service, 'destroy');

  Ember.run(function() {
    window.dispatchEvent(new CustomEvent('resize'));
    window.dispatchEvent(new CustomEvent('scroll'));
    assert.ok(callbackStub.notCalled);
    assert.ok(callbackBStub.notCalled);
    done();
  });
});

test('register binds multiple callbacks to the event on the specified target but only triggers once', function(assert) {
  assert.expect(4);

  let callback1Stub = sandbox.stub();
  let callback2Stub = sandbox.stub();
  let triggerSpy = sandbox.spy(service, 'triggerEvent');

  let testContainer = document.getElementById('ember-testing');
  let element = document.createElement('p');
  element.classList.add('foo');
  testContainer.appendChild(element);
  let addEventListenerSpy = sandbox.spy(element, 'addEventListener');

  service.register('p.foo', 'scroll', callback1Stub);
  service.register('p.foo', 'scroll', callback2Stub);
  assert.ok(addEventListenerSpy.calledOnce, 'event listener added only once');

  element.dispatchEvent(new CustomEvent('scroll'));
  assert.ok(callback1Stub.calledOnce, 'first callback executed');
  assert.ok(callback2Stub.calledOnce, 'second callback executed');
  assert.ok(triggerSpy.calledOnce, 'trigger called only once');

  service.unregister('p.foo', 'scroll', callback1Stub);
  service.unregister('p.foo', 'scroll', callback2Stub);
  testContainer.removeChild(element);
});

test('register binds callbacks to multiple events on the specified target', function(assert) {
  assert.expect(4);

  let callback1Stub = sandbox.stub();
  let callback2Stub = sandbox.stub();

  service.register('window', 'resize', callback1Stub);
  service.register('window', 'scroll', callback2Stub);

  window.dispatchEvent(new CustomEvent('resize'));
  assert.ok(callback1Stub.calledOnce);
  assert.ok(callback2Stub.notCalled);

  window.dispatchEvent(new CustomEvent('scroll'));
  assert.ok(callback1Stub.calledOnce);
  assert.ok(callback2Stub.calledOnce);

  service.unregister('window', 'resize', callback1Stub);
  service.unregister('window', 'scroll', callback2Stub);
});

test('register binds callbacks to different events on multiple targets', function(assert) {
  assert.expect(4);

  let callback1Stub = sandbox.stub();
  let callback2Stub = sandbox.stub();

  service.register('window', 'resize', callback1Stub);
  service.register('document', 'scroll', callback2Stub);

  window.dispatchEvent(new CustomEvent('resize'));
  assert.ok(callback1Stub.calledOnce);
  assert.ok(callback2Stub.notCalled);

  document.dispatchEvent(new CustomEvent('scroll'));
  assert.ok(callback1Stub.calledOnce);
  assert.ok(callback2Stub.calledOnce);

  service.unregister('window', 'resize', callback1Stub);
  service.unregister('document', 'scroll', callback2Stub);
});

/* unregister */

test('unregister unbinds the callback from its event', function(assert) {
  let callbackSpy = sandbox.stub();

  service.register('window', 'scroll', callbackSpy);
  service.unregister('window', 'scroll', callbackSpy);
  window.dispatchEvent(new CustomEvent('scroll'));
  assert.ok(callbackSpy.notCalled);
});

test('unregister unbinds the callback from its event but leaves other callbacks for that event', function(assert) {
  assert.expect(2);

  let callback1Stub = sandbox.stub();
  let callback2Stub = sandbox.stub();

  service.register('window', 'scroll', callback1Stub);
  service.register('window', 'scroll', callback2Stub);
  service.unregister('window', 'scroll', callback2Stub);
  window.dispatchEvent(new CustomEvent('scroll'));

  assert.ok(callback1Stub.calledOnce);
  assert.ok(callback2Stub.notCalled);

  service.unregister('window', 'scroll', callback1Stub);
});

test('unregister destroys the DOM handler after all callbacks have been unbound', function(assert) {
  assert.expect(2);

  let callbackSpy = sandbox.stub();
  let triggerSpy = sandbox.spy(service, 'triggerEvent');

  service.register('window', 'scroll', callbackSpy);
  service.unregister('window', 'scroll', callbackSpy);
  window.dispatchEvent(new CustomEvent('scroll'));

  assert.ok(callbackSpy.notCalled);
  assert.ok(triggerSpy.notCalled);
});

test('unregister destroys the DOM handler for an event after all callbacks have been unbound but leaves other events', function(assert) {
  assert.expect(3);

  let callback1Spy = sandbox.stub();
  let callback2Spy = sandbox.stub();
  let triggerSpy = sandbox.spy(service, 'triggerEvent');

  service.register('window', 'scroll', callback1Spy);
  service.register('window', 'resize', callback2Spy);
  service.unregister('window', 'scroll', callback1Spy);
  window.dispatchEvent(new CustomEvent('resize'));

  assert.ok(callback1Spy.notCalled);
  assert.ok(callback2Spy.calledOnce);
  assert.ok(triggerSpy.calledOnce);

  service.unregister('window', 'resize', callback2Spy);
});

/* triggerEvent */

test('triggerEvent triggers the event at a throttled rate', function(assert) {
  assert.expect(2);

  let throttleSpy = sandbox.spy(Ember.run, 'throttle');
  let callbackStub = sandbox.stub();

  service.on('testing', callbackStub);
  service.triggerEvent('testing');

  assert.ok(throttleSpy.calledOnce);
  assert.ok(callbackStub.calledOnce);
});
<|endoftext|>


<commit_before>const mongoose = require('mongoose');
const Schema   = mongoose.Schema;

const userSchema = new Schema({
  name: { type: String, required: true },
  email: { type: String, required: true, unique: true },
  isOhafUser: { type: Boolean, required: false },
  userPhone: { type: Number, required: false },
  userType: { type: String, required: false },
  userStreetAddress: { type: String, required: false },
  userCity: { type: String, required: false },
  userState: { type: String, required: false },
  userZip: { type: String, required: false },
  userDetails:{ type: String, required: false },
  volTravelDistMiles: { type: Number, required: false },
  volCauses: { type: [String], required: false },
  volTalents: { type: [String], required: false },
  volWorkPrefs: { type: [String], required: false },
  volCauseOther:{ type: String, required: false },
  volTalentOther:{ type: String, required: false },
  volWorkOther:{ type: String, required: false }
});

module.exports = mongoose.model('User', userSchema);
<commit_msg>added userStatus<commit_after>const mongoose = require('mongoose');
const Schema   = mongoose.Schema;

const userSchema = new Schema({
  name: { type: String, required: true },
  email: { type: String, required: true, unique: true },
  isOhafUser: { type: Boolean, required: false },
  userPhone: { type: Number, required: false },
  userStatus: { type: String, required: false },
  userType: { type: String, required: false },
  userStreetAddress: { type: String, required: false },
  userCity: { type: String, required: false },
  userState: { type: String, required: false },
  userZip: { type: String, required: false },
  userDetails:{ type: String, required: false },
  volTravelDistMiles: { type: Number, required: false },
  volCauses: { type: [String], required: false },
  volTalents: { type: [String], required: false },
  volWorkPrefs: { type: [String], required: false },
  volCauseOther:{ type: String, required: false },
  volTalentOther:{ type: String, required: false },
  volWorkOther:{ type: String, required: false }
});

module.exports = mongoose.model('User', userSchema);
<|endoftext|>


<commit_before>module.exports = function (grunt) {

  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-recess');
  grunt.loadNpmTasks('grunt-karma');

  // Default task.
  grunt.registerTask('default', ['jshint','build','karma:unit']);
  grunt.registerTask('build', ['clean','concat','sass:build','copy:assets']);
  grunt.registerTask('release', ['clean','uglify','jshint','karma:unit','concat:index', 'sass:min','copy:assets']);
  grunt.registerTask('test-watch', ['karma:watch']);

  // Print a timestamp (useful for when watching)
  grunt.registerTask('timestamp', function() {
    grunt.log.subhead(Date());
  });

  var karmaConfig = function(configFile, customOptions) {
    var options = { configFile: configFile, keepalive: true };
    var travisOptions = process.env.TRAVIS && { browsers: ['Firefox'], reporters: 'dots' };
    return grunt.util._.extend(options, customOptions, travisOptions);
  };

  // Project configuration.
  grunt.initConfig({
    distdir: 'dist',
    pkg: grunt.file.readJSON('package.json'),
    banner:
    '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
    '<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' +
    ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>;\n' +
    ' * Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %>\n */\n',
    src: {
        js: ['src/**/*.js'],
        html: ['src/index.html'],
        sass: ['src/sass/main.scss'],
        sassWatch: ['src/sass/**.css'],
        bootstrapSass: ['vendor/bootstrap/**/*.scss']

    },
    dest: {
        css: '<%= distdir %>/<%= pkg.name %>.css'
    },
    clean: ['<%= distdir %>/*'],
    copy: {
      assets: {
        files: [{ dest: '<%= distdir %>', src : '**', expand: true, cwd: 'src/assets/' },
                { dest: '<%= distdir %>/fonts', src : '**', expand: true, cwd: 'vendor/bootstrap/fonts' }]
      }
    },
    karma: {
      unit: { options: karmaConfig('test/config/unit.js') },
      watch: { options: karmaConfig('test/config/unit.js', { singleRun:false, autoWatch: true}) }
    },
    concat:{
      dist:{
        options: {
          banner: "<%= banner %>"
        },
        src:['<%= src.js %>'],
        dest:'<%= distdir %>/<%= pkg.name %>.js'
      },
      index: {
        src: ['src/index.html'],
        dest: '<%= distdir %>/index.html',
        options: {
          process: true
        }
      },
      angular: {
        src:['vendor/angular/angular.js', 'vendor/angular/angular-*.js'],
        dest: '<%= distdir %>/angular.js'
      },
      bootstrap: {
        src:['vendor/angular-ui/bootstrap/*.js'],
        dest: '<%= distdir %>/bootstrap.js'
      }
    },
    uglify: {
      dist:{
        options: {
          banner: "<%= banner %>"
        },
        src:['<%= src.js %>' ,'<%= src.jsTpl %>'],
        dest:'<%= distdir %>/<%= pkg.name %>.js'
      },
      angular: {
        src:['<%= concat.angular.src %>'],
        dest: '<%= distdir %>/angular.js'
      },
      bootstrap: {
        src:['vendor/angular-ui/bootstrap/*.js'],
        dest: '<%= distdir %>/bootstrap.js'
      }
    },
    sass: {
        build: {
            options: {
                style: 'expanded'
            },
            files: {
                '<%= dest.css %>': '<%= src.sass %>',
                '<%= distdir %>/bootstrap.css': '<%= src.bootstrapSass %>'
            }
        },
        min: {
            options: {
                style: 'compressed'
            },
            files: {
                '<%= dest.css %>': '<%= src.sass %>',
                '<%= distdir %>/bootstrap.css': '<%= src.bootstrapSass %>'
            }
        }
    },
    watch:{
      all: {
        files:['<%= src.js %>', '<%= src.html %>', '<%= src.sassWatch %>'],
        tasks:['default','timestamp']
      },
      build: {
        files:['<%= src.js %>', '<%= src.html %>', '<%= src.sassWatch %>'],
        tasks:['build','timestamp']
      }
    },
    jshint:{
      files:['gruntFile.js', '<%= src.js %>'],
      options:{
        curly:true,
        eqeqeq:true,
        immed:true,
        latedef:true,
        newcap:true,
        noarg:true,
        sub:true,
        boss:true,
        eqnull:true,
        globals:{}
      }
    }
  });

};
<commit_msg>updated the client app's grunt file<commit_after>module.exports = function (grunt) {

  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-karma');

  // Default task.
  grunt.registerTask('default', ['jshint','build','karma:unit']);
  grunt.registerTask('build', ['clean','concat','sass:build','copy:assets']);
  grunt.registerTask('release', ['clean','uglify','jshint','karma:unit','concat:index', 'sass:min','copy:assets']);
  grunt.registerTask('test-watch', ['karma:watch']);

  // Print a timestamp (useful for when watching)
  grunt.registerTask('timestamp', function() {
    grunt.log.subhead(Date());
  });

  var karmaConfig = function(configFile, customOptions) {
    var options = { configFile: configFile, keepalive: true };
    var travisOptions = process.env.TRAVIS && { browsers: ['Firefox'], reporters: 'dots' };
    return grunt.util._.extend(options, customOptions, travisOptions);
  };

  // Project configuration.
  grunt.initConfig({
    distdir: 'dist',
    pkg: grunt.file.readJSON('package.json'),
    banner:
    '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
    '<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' +
    ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>;\n' +
    ' * Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %>\n */\n',
    src: {
        js: ['src/**/*.js'],
        html: ['src/index.html'],
        sass: ['src/sass/main.scss'],
        sassWatch: ['src/sass/**.css'],
        bootstrapSass: ['vendor/bootstrap/**/*.scss']

    },
    dest: {
        css: '<%= distdir %>/<%= pkg.name %>.css'
    },
    clean: ['<%= distdir %>/*'],
    copy: {
      assets: {
        files: [{ dest: '<%= distdir %>', src : '**', expand: true, cwd: 'src/assets/' },
                { dest: '<%= distdir %>/fonts', src : '**', expand: true, cwd: 'vendor/bootstrap/fonts' }]
      }
    },
    karma: {
      unit: { options: karmaConfig('test/config/unit.js') },
      watch: { options: karmaConfig('test/config/unit.js', { singleRun:false, autoWatch: true}) }
    },
    concat:{
      dist:{
        options: {
          banner: "<%= banner %>"
        },
        src:['<%= src.js %>'],
        dest:'<%= distdir %>/<%= pkg.name %>.js'
      },
      index: {
        src: ['src/index.html'],
        dest: '<%= distdir %>/index.html',
        options: {
          process: true
        }
      },
      angular: {
        src:['vendor/angular/angular.js', 'vendor/angular/angular-*.js'],
        dest: '<%= distdir %>/angular.js'
      },
      bootstrap: {
        src:['vendor/angular-ui/bootstrap/*.js'],
        dest: '<%= distdir %>/bootstrap.js'
      }
    },
    uglify: {
      dist:{
        options: {
          banner: "<%= banner %>"
        },
        src:['<%= src.js %>' ,'<%= src.jsTpl %>'],
        dest:'<%= distdir %>/<%= pkg.name %>.js'
      },
      angular: {
        src:['<%= concat.angular.src %>'],
        dest: '<%= distdir %>/angular.js'
      },
      bootstrap: {
        src:['vendor/angular-ui/bootstrap/*.js'],
        dest: '<%= distdir %>/bootstrap.js'
      }
    },
    sass: {
        build: {
            options: {
                style: 'expanded'
            },
            files: {
                '<%= dest.css %>': '<%= src.sass %>',
                '<%= distdir %>/bootstrap.css': '<%= src.bootstrapSass %>'
            }
        },
        min: {
            options: {
                style: 'compressed'
            },
            files: {
                '<%= dest.css %>': '<%= src.sass %>',
                '<%= distdir %>/bootstrap.css': '<%= src.bootstrapSass %>'
            }
        }
    },
    watch:{
      all: {
        files:['<%= src.js %>', '<%= src.html %>', '<%= src.sassWatch %>'],
        tasks:['default','timestamp']
      },
      build: {
        files:['<%= src.js %>', '<%= src.html %>', '<%= src.sassWatch %>'],
        tasks:['build','timestamp']
      }
    },
    jshint:{
      files:['gruntFile.js', '<%= src.js %>'],
      options:{
        curly:true,
        eqeqeq:true,
        immed:true,
        latedef:true,
        newcap:true,
        noarg:true,
        sub:true,
        boss:true,
        eqnull:true,
        globals:{}
      }
    }
  });

};
<|endoftext|>