<commit_before>var strResponse = undefined;
var searchResult = [];

var search_addr = "";
var search_detail_addr = "";
var search_type = "";

var numbers_of_result = {};
var searchAroundResult = [];
/*
item scheme of summary_of_result
{
	<year> : {
		<month>: <number>,
		...
	},
	...
}
*/
var summary_of_result = {};

function getData(trade_type, lawd_cd, addr, detail_addr) {
	search_type = trade_type;
	search_addr = addr;
	search_detail_addr = detail_addr;
	var yearStart = 2006;
	var ymEnd = "201705";
	var month = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]

	var dataHandler = require("./dataHandler.js");
	for(var i=yearStart;i<2017;i++) {
		for(var j=0;j<12;j++) {
			if(ymEnd == (i + month[j])) return;
			strResponse = dataHandler.readCachedData(trade_type, lawd_cd, i + month[j]);
			if(!strResponse) {
				dataHandler.getDataOfYear(trade_type, lawd_cd, i + month[j], parseResponse);
			} else {
				parseResponse();
			}
		}
	}

//	strResponse = dataHandler.readCachedData("11680", "201604");
//	if(!strResponse) {
//		getDataOfYear( "201612", parseResponse);
//	}
}

/*
 * <items>
<item>
<거래금액>32,000</거래금액>
<년>2017</년>
<대지권면적>33</대지권면적>
<법정동>방배동</법정동>
<연립다세대>(987-13)</연립다세대>
<월>5</월>
<일>1~10</일>
<전용면적>74.55</전용면적>
<지번>987-13</지번>
<지역코드>11650</지역코드>
<층>2</층>
</item>
</items> 테스트
 */
var xml;

function parseResponse() {
	var addr = search_detail_addr;
	var dong = search_addr;
	//var addr = "387-2";
	//var addr = "1170-3";

	var parser = new DOMParser();
	var xmlDoc = parser.parseFromString(strResponse,"text/xml");
	xml = xmlDoc;
	//console.log(xmlDoc.getElementsByTagName("items"));
	var itemArray = null;
	if(xmlDoc.getElementsByTagName("items")[0] != undefined ) {
		itemArray = xmlDoc.getElementsByTagName("items")[0].childNodes;
		for(var i = 0; i < itemArray.length; i++) {
			if( itemArray[i].getElementsByTagName("법정동")[0].innerHTML.trim() == dong) {
				// count volume of dong
				var year = itemArray[i].getElementsByTagName("년")[0].innerHTML.trim();
				var month = itemArray[i].getElementsByTagName("월")[0].innerHTML.trim();
				if(numbers_of_result[year] == undefined) numbers_of_result[year] = {};
				if(numbers_of_result[year][month] == undefined) numbers_of_result[year][month] = 0;
				numbers_of_result[year][month]++;
				// save record of full addr
				if( itemArray[i].getElementsByTagName("지번")[0].innerHTML == addr) {
					printItem(itemArray[i].childNodes);
					itemToJson(itemArray[i].childNodes);
				}
				// save record of same block
				if( itemArray[i].getElementsByTagName("지번")[0].innerHTML.split('-')[0] == addr.split('-')[0]) {
					var obj = {};
					var item = itemArray[i].childNodes;
					for(var j = 0; j < item.length; j++) {
						obj[item[j].tagName] = item[j].innerHTML.trim();
					}
					searchAroundResult.push(obj);
				}

			}
		}
	}
	makeTable();
	makeSummary();
	makeTableAround();
	//xml.getElementsByTagName("items")[0].childNodes[0].getElementsByTagName("지번")[0].innerHTML;
	//document.getElementById("demo").innerHTML = itemArray[0];
}

function itemToJson(item) {
	var obj = {};
	for(var j = 0; j < item.length; j++) {
		obj[item[j].tagName] = item[j].innerHTML.trim();
	}
	searchResult.push(obj);
}

function printItem(item) {
	var demo = document.getElementById("output");
	for(var j = 0; j < item.length; j++) {
		//demo.innerHTML += item[j].tagName + " : " + item[j].innerHTML.trim() + "
";
		console.log(item[j].tagName + " : " + item[j].innerHTML.trim());
	}
}

var trade_keys = ["년", "월", "거래금액", "층", "전용면적", "대지권면적", "법정동", "지번"];
var rent_keys = ["년", "월", "보증금액", "월세금액", "층", "전용면적", "법정동", "지번"];

function makeTable() {
	if(searchResult.length == 0) return;

	//var strOutput = document.getElementById("demo").innerHTML + "
";
	document.getElementById("table").innerHTML = "";
	var strHeader = "";
	var strOutput = "";
	var keys;
	if(search_type == "house_trade") keys = trade_keys;
	else if(search_type == "house_rent") keys = rent_keys;
	else {
		console.log("not implemented:" + search_type);
		return;
	}
	//alert(keys.toString());
	strOutput += "
";
	for(var j = 0; j < keys.length; j++) {
		strOutput += "
";
		strOutput += "" + keys[j] + "	";
		for(var i = 0; i < searchResult.length; i++) {
			strOutput += "" + searchResult[i][keys[j]] + "	";
		}
		strOutput += "
";
	}
	strOutput += "
";
	document.getElementById("table").innerHTML = strOutput;
};

function makeSummary() {
	var strOutput = "";
	strOutput += "
";

	if(Object.keys(numbers_of_result).length == 0) return;
	var yearList = Object.keys(numbers_of_result);

	strOutput += "
	";
	for(var j=0;j < Object.keys(numbers_of_result).length; j++) {
		strOutput += "" + Object.keys(numbers_of_result)[j] + "	";
	}
	strOutput += "
";

	for(var i=0; i<12; i++) {
		strOutput += "
";
		strOutput += "" + (i+1) + "	";
		for(var j=0;j < Object.keys(numbers_of_result).length; j++) {
			var value = numbers_of_result[yearList[j]][i+1];
			if(value)
				strOutput += "" + value + "	";
			else
				strOutput += "" + 0 + "	";
		}
		strOutput += "
";
	}
	strOutput += "
";
	document.getElementById("volume_table").innerHTML = strOutput;
};

function makeTableAround() {
	if(searchAroundResult.length == 0) return;

	//var strOutput = document.getElementById("demo").innerHTML + "
";
	document.getElementById("table_around").innerHTML = "";
	var strHeader = "";
	var strOutput = "";
	var keys;
	if(search_type == "house_trade") keys = trade_keys;
	else if(search_type == "house_rent") keys = rent_keys;
	else {
		console.log("not implemented:" + search_type);
		return;
	}
	//alert(keys.toString());
	strOutput += "
";
	for(var j = 0; j < keys.length; j++) {
		strOutput += "
";
		strOutput += "" + keys[j] + "	";
		for(var i = 0; i < searchAroundResult.length; i++) {
			strOutput += "" + searchAroundResult[i][keys[j]] + "	";
		}
		strOutput += "
";
	}
	strOutput += "
";
	document.getElementById("table_around").innerHTML = strOutput;
};

function clear() {
	delete searchResult;
	delete numbers_of_result;
	delete summary_of_result;
	searchResult = [];
	numbers_of_result = {};
	summary_of_result = {};
	searchAroundResult = [];
}<commit_msg>add chart for trade record<commit_after>var strResponse = undefined;
var searchResult = [];

var search_addr = "";
var search_detail_addr = "";
var search_type = "";

var numbers_of_result = {};
var searchAroundResult = [];
var chart = null;
/*
item scheme of summary_of_result
{
	<year> : {
		<month>: <number>,
		...
	},
	...
}
*/
var summary_of_result = {};

function getData(trade_type, lawd_cd, addr, detail_addr) {
	search_type = trade_type;
	search_addr = addr;
	search_detail_addr = detail_addr;
	var yearStart = 2006;
	var ymEnd = "201705";
	var month = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]

	var dataHandler = require("./dataHandler.js");
	for(var i=yearStart;i<2017;i++) {
		for(var j=0;j<12;j++) {
			if(ymEnd == (i + month[j])) return;
			strResponse = dataHandler.readCachedData(trade_type, lawd_cd, i + month[j]);
			if(!strResponse) {
				dataHandler.getDataOfYear(trade_type, lawd_cd, i + month[j], parseResponse);
			} else {
				parseResponse();
			}
		}
	}
	createChart();
	updateChart();
}

/*
 * <items>
<item>
<거래금액>32,000</거래금액>
<년>2017</년>
<대지권면적>33</대지권면적>
<법정동>방배동</법정동>
<연립다세대>(987-13)</연립다세대>
<월>5</월>
<일>1~10</일>
<전용면적>74.55</전용면적>
<지번>987-13</지번>
<지역코드>11650</지역코드>
<층>2</층>
</item>
</items> 테스트
 */
var xml;

function parseResponse() {
	var addr = search_detail_addr;
	var dong = search_addr;
	//var addr = "387-2";
	//var addr = "1170-3";

	var parser = new DOMParser();
	var xmlDoc = parser.parseFromString(strResponse,"text/xml");
	xml = xmlDoc;
	//console.log(xmlDoc.getElementsByTagName("items"));
	var itemArray = null;
	if(xmlDoc.getElementsByTagName("items")[0] != undefined ) {
		itemArray = xmlDoc.getElementsByTagName("items")[0].childNodes;
		for(var i = 0; i < itemArray.length; i++) {
			if( itemArray[i].getElementsByTagName("법정동")[0].innerHTML.trim() == dong) {
				// count volume of dong
				var year = itemArray[i].getElementsByTagName("년")[0].innerHTML.trim();
				var month = itemArray[i].getElementsByTagName("월")[0].innerHTML.trim();
				if(numbers_of_result[year] == undefined) numbers_of_result[year] = {};
				if(numbers_of_result[year][month] == undefined) numbers_of_result[year][month] = 0;
				numbers_of_result[year][month]++;
				// save record of full addr
				if( itemArray[i].getElementsByTagName("지번")[0].innerHTML == addr) {
					printItem(itemArray[i].childNodes);
					itemToJson(itemArray[i].childNodes);
				}
				// save record of same block
				if( itemArray[i].getElementsByTagName("지번")[0].innerHTML.split('-')[0] == addr.split('-')[0]) {
					var obj = {};
					var item = itemArray[i].childNodes;
					for(var j = 0; j < item.length; j++) {
						obj[item[j].tagName] = item[j].innerHTML.trim();
					}
					searchAroundResult.push(obj);
				}

			}
		}
	}
	makeTable();
	makeSummary();
	makeTableAround();
}

function itemToJson(item) {
	var obj = {};
	for(var j = 0; j < item.length; j++) {
		obj[item[j].tagName] = item[j].innerHTML.trim();
	}
	searchResult.push(obj);
}

function printItem(item) {
	var demo = document.getElementById("output");
	for(var j = 0; j < item.length; j++) {
		//demo.innerHTML += item[j].tagName + " : " + item[j].innerHTML.trim() + "
";
		console.log(item[j].tagName + " : " + item[j].innerHTML.trim());
	}
}

var trade_keys = ["년", "월", "거래금액", "층", "전용면적", "대지권면적", "법정동", "지번"];
var rent_keys = ["년", "월", "보증금액", "월세금액", "층", "전용면적", "법정동", "지번"];

function makeTable() {
	if(searchResult.length == 0) return;

	//var strOutput = document.getElementById("demo").innerHTML + "
";
	document.getElementById("table").innerHTML = "";
	var strHeader = "";
	var strOutput = "";
	var keys;
	if(search_type == "house_trade") keys = trade_keys;
	else if(search_type == "house_rent") keys = rent_keys;
	else {
		console.log("not implemented:" + search_type);
		return;
	}
	//alert(keys.toString());
	strOutput += "
";
	for(var j = 0; j < keys.length; j++) {
		strOutput += "
";
		strOutput += "" + keys[j] + "	";
		for(var i = 0; i < searchResult.length; i++) {
			strOutput += "" + searchResult[i][keys[j]] + "	";
		}
		strOutput += "
";
	}
	strOutput += "
";
	document.getElementById("table").innerHTML = strOutput;
};

function makeSummary() {
	var strOutput = "";
	strOutput += "
";

	if(Object.keys(numbers_of_result).length == 0) return;
	var yearList = Object.keys(numbers_of_result);

	strOutput += "
	";
	for(var j=0;j < Object.keys(numbers_of_result).length; j++) {
		strOutput += "" + Object.keys(numbers_of_result)[j] + "	";
	}
	strOutput += "
";

	for(var i=0; i<12; i++) {
		strOutput += "
";
		strOutput += "" + (i+1) + "	";
		for(var j=0;j < Object.keys(numbers_of_result).length; j++) {
			var value = numbers_of_result[yearList[j]][i+1];
			if(value)
				strOutput += "" + value + "	";
			else
				strOutput += "" + 0 + "	";
		}
		strOutput += "
";
	}
	strOutput += "
";
	document.getElementById("volume_table").innerHTML = strOutput;
};

function makeTableAround() {
	if(searchAroundResult.length == 0) return;

	//var strOutput = document.getElementById("demo").innerHTML + "
";
	document.getElementById("table_around").innerHTML = "";
	var strHeader = "";
	var strOutput = "";
	var keys;
	if(search_type == "house_trade") keys = trade_keys;
	else if(search_type == "house_rent") keys = rent_keys;
	else {
		console.log("not implemented:" + search_type);
		return;
	}
	//alert(keys.toString());
	strOutput += "
";
	for(var j = 0; j < keys.length; j++) {
		strOutput += "
";
		strOutput += "" + keys[j] + "	";
		for(var i = 0; i < searchAroundResult.length; i++) {
			strOutput += "" + searchAroundResult[i][keys[j]] + "	";
		}
		strOutput += "
";
	}
	strOutput += "
";
	document.getElementById("table_around").innerHTML = strOutput;
};

function clear() {
	delete searchResult;
	delete numbers_of_result;
	delete summary_of_result;
	searchResult = [];
	numbers_of_result = {};
	summary_of_result = {};
	searchAroundResult = [];
};

function createChart() {
	chart = Highcharts.chart('chart_container', {
    title: {
        text: 'Record of Trade'
    },

    yAxis: {
        title: {
            text: 'Number'
        }
    },
	xAxis: {
		type: 'datetime',
		labels: {
			format: '{value:%Y-%m}',
		}
	},
    legend: {
        layout: 'vertical',
        align: 'right',
        verticalAlign: 'middle'
    },
    series: []
});
};

function updateChart() {
	var series_list = {};

	if(searchResult.length == 0) return;
	var keys;
	var type;
	if(search_type == "house_trade") {
		keys = trade_keys;
		type = "매매";
	}
	else if(search_type == "house_rent") {
		keys = rent_keys;
		type = "전월세";
	}
	else {
		console.log("not implemented:" + search_type);
		return;
	}
	// trade recode
	for(var i = 0; i < searchResult.length; i++) {
		var size = type + " " + searchResult[i]["법정동"] + " " + searchResult[i]["전용면적"];
		if(!series_list[size]) {
			series_list[size] = chart.addSeries({
				name:size,
				data:[]
			});
		}
		var d = Date.UTC(parseInt(searchResult[i]["년"]), parseInt(searchResult[i]["월"]), 1);
		series_list[size].addPoint([d, parseInt(searchResult[i]["거래금액"].replace(",", ""))]);
	}
	// trade around
	for(var i = 0; i < searchAroundResult.length; i++) {
		var size = type + " " + searchResult[i]["법정동"] + " " + searchResult[i]["전용면적"];
		if(!series_list[size]) {
			series_list[size] = chart.addSeries({
				name:size,
				data:[]
			});
		}
		var d = Date.UTC(parseInt(searchAroundResult[i]["년"]), parseInt(searchAroundResult[i]["월"]), 1);
		series_list[size].addPoint([d, parseInt(searchAroundResult[i]["거래금액"].replace(",", ""))]);
	}

}<|endoftext|>


<commit_before>/* eslint-disable global-require */

'use strict'

module.exports = {
  api: require('./libs/api.js'),
  es: require('./libs/es.js'),
  ingest: require('./libs/ingest.js')
}
<commit_msg>do not export ingest module for now<commit_after>/* eslint-disable global-require */

'use strict'

module.exports = {
  api: require('./libs/api.js'),
  es: require('./libs/es.js')
  //ingest: require('./libs/ingest.js')
}
<|endoftext|>


<commit_before>(function() {
  "use strict";

  var buscaBR = {};

  // Exporta o objeto do buscaBR para o **Node.js**
  // com a compatibilidade para o browser definindo
  // buscaBR como um objeto global
  if (typeof exports !== 'undefined') {
    if (typeof module !== 'undefined' && module.exports) {
      exports = module.exports = buscaBR;
    }
    exports.buscaBR = buscaBR;
  } else {
    window.buscaBR = buscaBR;
  }

  var codes =  [
    [/BL|BR/, 'B'],
    ['PH', 'F'],
    [/GL|GR|MG|NG|RG/, 'G'],
    ['Y', 'I'],
    [/GE|GI|RJ|MJ/, 'J'],
    [/CA|CO|CU|CK|Q/, 'K'],
    ['N', 'M'],
    [/AO|AUM|GM|MD|OM|ON/, 'M'],
    ['PR', 'P'],
    ['L', 'R'],
    [/CE|CI|CH|CS|RS|TS|X|Z/, 'S'],
    [/TR|TL/, 'T'],
    [/CT|RT|ST|PT/, 'T'],
    [/\b[UW]/, 'V'],
    ['RM', 'SM'],
    [/[MRS]+\b/, ''],
    [/[AEIOUH]/, '']
  ];

  buscaBR.searchSync = function(str, array){
    var results = [];
    for(var i = 0 ; i < array.length; i++){
      if(this.encode(str) == this.encode(array[i])){
        results.push({termo:array[i], index: i})
      }
    }
    return (results.length>0) ? results : {erro:"Não há registros"};
  };

  buscaBR.search = function(str, array, callback){
    callback(this.searchSync(str, array));
  };

  buscaBR.encode = function (str) {
    str = removeAcento(str.toUpperCase());
    for(var i = 0; i < codes.length; i++){
      // str = str.replace(this.codes[i][0],this.codes[i][1]);
      str = str.split(codes[i][0]).join(codes[i][1])
    }

    str = squeeze(str);

    return str;
  };

  function squeeze(str){
    var cont = 0;
    var newString='';
    for(var i =  0 ; i < str.length; i++){
      if(str[i] != str[i+1]){
        newString +=str[i];
      }
    }
    return newString;
  }

  function removeAcento(strToReplace) {
    var str_acento = "ÁÀÃÂÄÉÈÊËÍÌÎÏÓÒÕÖÔÚÙÛÜÇ";
    var str_sem_acento = "AAAAAEEEEIIIIOOOOOUUUUC";
    var nova = "";
    for (var i = 0; i < strToReplace.length; i++) {
      if (str_acento.indexOf(strToReplace.charAt(i)) != -1) {
        nova += str_sem_acento.substr(str_acento.search(strToReplace.substr(i, 1)), 1);
      } else {
        nova += strToReplace.substr(i, 1);
      }
    }
    var nova = nova.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '');
    return nova;
  }

}());
<commit_msg>Adicionando uma convenção para constante do bloco de códigos<commit_after>(function() {
  "use strict";

  var buscaBR = {};

  // Exporta o objeto do buscaBR para o **Node.js**
  // com a compatibilidade para o browser definindo
  // buscaBR como um objeto global
  if (typeof exports !== 'undefined') {
    if (typeof module !== 'undefined' && module.exports) {
      exports = module.exports = buscaBR;
    }
    exports.buscaBR = buscaBR;
  } else {
    window.buscaBR = buscaBR;
  }

  var CODES =  [
    [/BL|BR/, 'B'],
    ['PH', 'F'],
    [/GL|GR|MG|NG|RG/, 'G'],
    ['Y', 'I'],
    [/GE|GI|RJ|MJ/, 'J'],
    [/CA|CO|CU|CK|Q/, 'K'],
    ['N', 'M'],
    [/AO|AUM|GM|MD|OM|ON/, 'M'],
    ['PR', 'P'],
    ['L', 'R'],
    [/CE|CI|CH|CS|RS|TS|X|Z/, 'S'],
    [/TR|TL/, 'T'],
    [/CT|RT|ST|PT/, 'T'],
    [/\b[UW]/, 'V'],
    ['RM', 'SM'],
    [/[MRS]+\b/, ''],
    [/[AEIOUH]/, '']
  ];

  buscaBR.searchSync = function(str, array){
    var results = [];
    for(var i = 0 ; i < array.length; i++){
      if(this.encode(str) == this.encode(array[i])){
        results.push({termo:array[i], index: i})
      }
    }
    return (results.length>0) ? results : {erro:"Não há registros"};
  };

  buscaBR.search = function(str, array, callback){
    callback(this.searchSync(str, array));
  };

  buscaBR.encode = function (str) {
    str = removeAcento(str.toUpperCase());
    for(var i = 0; i < CODES.length; i++){
      // str = str.replace(this.CODES[i][0],this.CODES[i][1]);
      str = str.split(CODES[i][0]).join(CODES[i][1])
    }

    str = squeeze(str);

    return str;
  };

  function squeeze(str){
    var cont = 0;
    var newString='';
    for(var i =  0 ; i < str.length; i++){
      if(str[i] != str[i+1]){
        newString +=str[i];
      }
    }
    return newString;
  }

  function removeAcento(strToReplace) {
    var str_acento = "ÁÀÃÂÄÉÈÊËÍÌÎÏÓÒÕÖÔÚÙÛÜÇ";
    var str_sem_acento = "AAAAAEEEEIIIIOOOOOUUUUC";
    var nova = "";
    for (var i = 0; i < strToReplace.length; i++) {
      if (str_acento.indexOf(strToReplace.charAt(i)) != -1) {
        nova += str_sem_acento.substr(str_acento.search(strToReplace.substr(i, 1)), 1);
      } else {
        nova += strToReplace.substr(i, 1);
      }
    }
    var nova = nova.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '');
    return nova;
  }

}());
<|endoftext|>


<commit_before>/*jshint esversion: 6 */

export const optionAtts = function () {
  const option = this;
  const atts = {
    value: option.value,
  };
  console.log('option:', option);

  if (option._id === 'AUTOFORM_EMPTY_FIRST_OPTION') {

    // change label to placeholder if it exists
    option.label = option.atts.placeholder?option.atts.placeholder:option.label;
  }

  if (option.selected) {
    atts.selected = '';
  }
  return atts;
};
<commit_msg>removed logging<commit_after>/*jshint esversion: 6 */

export const optionAtts = function () {
  const option = this;
  const atts = {
    value: option.value,
  };

  // if option is first empty option
  if (option._id === 'AUTOFORM_EMPTY_FIRST_OPTION') {

    // change label to placeholder if it exists
    option.label = option.atts.placeholder?option.atts.placeholder:option.label;
  }

  if (option.selected) {
    atts.selected = '';
  }
  return atts;
};
<|endoftext|>


<commit_before>'use strict'
var allProducts = [];
var counter = 0;
var randomTrio = [];
var allImgs = document.getElementById('imgs');

function Product(name, filePath) {
  this.name = name
  this.filePath = filePath
  this.votes = 0
  allProducts.push(this);
};
new Product('R2D2-bag','assets/bag.jpg');
new Product('banana slicer','assets/banana.jpg');
new Product('bathroom','assets/bathroom.jpg');
new Product('boots','assets/boots.jpg');
new Product('breakfast','assets/breakfast.jpg');
new Product('bubblegum', 'assets/bubblegum.jpg');
new Product('chair', 'assets/chair.jpg');
new Product('cthulhu', 'assets/cthulhu.jpg');
new Product('dog-duck', 'assets/dog-duck.jpg');
new Product('dragon', 'assets/dragon.jpg');
new Product('pen', 'assets/pen.jpg');
new Product('pet-sweep', 'assets/pet-sweep.jpg');
new Product('scissors', 'assets/scissors.jpg');
new Product('shark', 'assets/shark.jpg');
new Product('sweep', 'assets/sweep.png');
new Product('tauntaun', 'assets/tauntaun.jpg');
new Product('unicorn', 'assets/unicorn.jpg');
new Product('usb', 'assets/usb.gif');
new Product('water-can', 'assets/water-can.jpg');
new Product('wine-glass', 'assets/wine-glass.jpg');

function getRandom() {
  return Math.floor(Math.random() * allProducts.length);
}

function getRandomTrio() { //holds 3 items
  while (randomTrio.length < 3) {
    var randomNum = getRandom();
    while (randomTrio.indexOf(randomNum) > -1) {
      randomNum = getRandom();
    }
    randomTrio.push(randomNum);
  }
}
getRandomTrio();

var leftPic = document.getElementById('left');
var centerPic = document.getElementById('center');
var rightPic = document.getElementById('right');

function display(){
  leftPic.src = allProducts[randomTrio[0]].filePath;
  leftPic.name = allProducts[randomTrio[0]].name;
  centerPic.src = allProducts[randomTrio[1]].filePath;
  centerPic.name = allProducts[randomTrio[1]].name;
  rightPic.src = allProducts[randomTrio[2]].filePath;
  rightPic.name = allProducts[randomTrio[2]].name;
}
display();

function eventTally (pickedpic) {
  for (var i = 0; i < allProducts.length; i++){
    if(allProducts[i].name === pickedpic){
      allProducts[i].votes += 1;
    }
  }
}
function makeChart() {
  console.log(allProducts);
}
function clickEvent() {
  console.log('Clicked');
  if (event.target.name === leftPic.name || event.target.name === centerPic.name || event.target.name === rightPic.name) {
    eventTally(event.target.name);
    counter += 1;
    if (counter < 15) {
      randomTrio = [];
      getRandomTrio();
      display();
    } else {
      resultsButton();
      allImgs.removeEventListener('click',clickEvent);
      makeChart();
      localStorage.setItem('allProducts', JSON.stringify(allProducts));
    }

  } else {
    alert('Please click');
  }
}

allImgs.addEventListener('click', clickEvent);

function resultsButton() {
  var body = document.getElementById('button');
  var button = document.createElement('button');
  button.innerHTML = "Get Results";
  body.appendChild(button);
  button.addEventListener ('click', votes);
}

function createUl(products) {
  var allProducts = document.getElementById('allProducts');
  var ulEl = document.createElement('ul');
  document.getElementById('allProducts').appendChild(ulEl);

  var liEl = document.createElement('li');
  liEl.textContent = ('Product Name: ' + products.name + '(' + 'Times Voted: ' + products.votes + ')');
  ulEl.appendChild(liEl);

}

function votes() {
  for (var i = 0; i < allProducts.length; i++) {
    createUl(allProducts[i]);
  }
  createChart();
}
function checkStorage() {
  if ()
}
function refreshButton() {

}

function getVotes(){
  var chartVotes = [];
  for (var i = 0; i < allProducts.length; i ++) {
    chartVotes.push(allProducts[i].votes);
  }
  return chartVotes;
}
function getNames() {
  var chartNames = [];
  for (var i = 0; i < allProducts.length; i++) {
    chartNames.push(allProducts[i].name);
  }
  return chartNames;
}
function createChart(products) {
var canvas = document.getElementById('canvas');

var myChart = new Chart(canvas, {
  type: 'bar',
  data: {
    labels: getNames(),
    datasets: [{
      label: 'Consumer Choice Results',
      data: getVotes(),
      backgroundColor:'#000000 ',
      borderWidth: 1
    }]
  },
  options: {
    scales: {
      xAxes: [{
        scaleLabel: {
          display: true,
          labelString: 'Items'
        }
      }],
      yAxes: [{
        ticks: {
          max: 4,
          min: 0,
          stepSize: 1,
        }
      }]
    }
  }
});
}
checkStorage();
<commit_msg>finished busmall<commit_after>'use strict'
var allProducts = [];
var counter = 0;
var randomTrio = [];
var allImgs = document.getElementById('imgs');

function Product(name, filePath) {
  this.name = name
  this.filePath = filePath
  this.votes = 0
  allProducts.push(this);
};
new Product('R2D2-bag','assets/bag.jpg');
new Product('banana slicer','assets/banana.jpg');
new Product('bathroom','assets/bathroom.jpg');
new Product('boots','assets/boots.jpg');
new Product('breakfast','assets/breakfast.jpg');
new Product('bubblegum', 'assets/bubblegum.jpg');
new Product('chair', 'assets/chair.jpg');
new Product('cthulhu', 'assets/cthulhu.jpg');
new Product('dog-duck', 'assets/dog-duck.jpg');
new Product('dragon', 'assets/dragon.jpg');
new Product('pen', 'assets/pen.jpg');
new Product('pet-sweep', 'assets/pet-sweep.jpg');
new Product('scissors', 'assets/scissors.jpg');
new Product('shark', 'assets/shark.jpg');
new Product('sweep', 'assets/sweep.png');
new Product('tauntaun', 'assets/tauntaun.jpg');
new Product('unicorn', 'assets/unicorn.jpg');
new Product('usb', 'assets/usb.gif');
new Product('water-can', 'assets/water-can.jpg');
new Product('wine-glass', 'assets/wine-glass.jpg');

function getRandom() {
  return Math.floor(Math.random() * allProducts.length);
}

function getRandomTrio() { //holds 3 items
  while (randomTrio.length < 3) {
    var randomNum = getRandom();
    while (randomTrio.indexOf(randomNum) > -1) {
      randomNum = getRandom();
    }
    randomTrio.push(randomNum);
  }
}
getRandomTrio();

var leftPic = document.getElementById('left');
var centerPic = document.getElementById('center');
var rightPic = document.getElementById('right');

function display(){
  leftPic.src = allProducts[randomTrio[0]].filePath;
  leftPic.name = allProducts[randomTrio[0]].name;
  centerPic.src = allProducts[randomTrio[1]].filePath;
  centerPic.name = allProducts[randomTrio[1]].name;
  rightPic.src = allProducts[randomTrio[2]].filePath;
  rightPic.name = allProducts[randomTrio[2]].name;
}
display();

function eventTally (pickedpic) {
  for (var i = 0; i < allProducts.length; i++){
    if(allProducts[i].name === pickedpic){
      allProducts[i].votes += 1;
    }
  }
}
function makeChart() {
  console.log(allProducts);
}
function clickEvent() {
  console.log('Clicked');
  if (event.target.name === leftPic.name || event.target.name === centerPic.name || event.target.name === rightPic.name) {
    eventTally(event.target.name);
    counter += 1;
    if (counter < 15) {
      randomTrio = [];
      getRandomTrio();
      display();
    } else {
      resultsButton();
      allImgs.removeEventListener('click',clickEvent);
      makeChart();
      localStorage.setItem('allProducts', JSON.stringify(allProducts));
    }

  } else {
    alert('Please click');
  }
}

allImgs.addEventListener('click', clickEvent);

function resultsButton() {
  var body = document.getElementById('button');
  var button = document.createElement('button');
  button.innerHTML = "Get Results";
  body.appendChild(button);
  button.addEventListener ('click', votes);
}

function createUl(products) {
  var allProducts = document.getElementById('allProducts');
  var ulEl = document.createElement('ul');
  document.getElementById('allProducts').appendChild(ulEl);

  var liEl = document.createElement('li');
  liEl.textContent = ('Product Name: ' + products.name + '(' + 'Times Voted: ' + products.votes + ')');
  ulEl.appendChild(liEl);

}

function votes() {
  for (var i = 0; i < allProducts.length; i++) {
    createUl(allProducts[i]);
  }
  createChart();
}
function makeChart() {
  console.log(allProducts);
}

function refreshButton() {

}

function getVotes(){
  var chartVotes = [];
  for (var i = 0; i < allProducts.length; i ++) {
    chartVotes.push(allProducts[i].votes);
  }
  return chartVotes;
}
function getNames() {
  var chartNames = [];
  for (var i = 0; i < allProducts.length; i++) {
    chartNames.push(allProducts[i].name);
  }
  return chartNames;
}
function createChart(products) {
var canvas = document.getElementById('canvas');

var myChart = new Chart(canvas, {
  type: 'bar',
  data: {
    labels: getNames(),
    datasets: [{
      label: 'Consumer Choice Results',
      data: getVotes(),
      backgroundColor:'#000000 ',
      borderWidth: 1
    }]
  },
  options: {
    scales: {
      xAxes: [{
        scaleLabel: {
          display: true,
          labelString: 'Items'
        }
      }],
      yAxes: [{
        ticks: {
          max: 4,
          min: 0,
          stepSize: 1,
        }
      }]
    }
  }
});
}
<|endoftext|>


<commit_before>$(function()
  {

    window.Sip = Backbone.Model.extend({

      initialize: function()
        {
          this.loadJobs();
        },

      hasFinished: function()
        {
          return false == this.jobs.some(function(job)
            {
              return -1 < jQuery.inArray(job.get('currentstep'), ['Requires approval', 'Executing command(s)']);
            });
        },

      set: function(attributes, options)
        {
          Backbone.Model.prototype.set.call(this, attributes, options);

          if (undefined !== this.jobs && !this.hasFinished())
          {
            this.view.update();
          }
        },

      loadJobs: function()
        {
          // Nested collection
          this.jobs = new JobCollection(this.get('jobs'));

          var self = this;
          this.jobs.each(function(job)
            {
              job.sip = self;
            });
        }
    });

    window.SipCollection = Backbone.Collection.extend({

      model: Sip,

      url: '/sips/all/',

      initialize: function()
        {

        },

      comparator: function(sip)
        {
          return 0 - sip.get('timestamp');
        },

    });

    window.SipView = Backbone.View.extend({

      className: 'sip',

      template: _.template($('#sip-template').html()),

      events: {
        'click .sip-row > .sip-detail-jobs > a': 'toggleJobs',
      },

      initialize: function()
        {
          _.bindAll(this, 'render', 'update', 'add', 'updateIcon');
          this.model.view = this;
          this.model.bind('change:timestamp', this.update);
        },

      render: function()
        {
          $(this.el).html(this.template(this.model.toJSON())).attr('uuid', this.model.get('uuid'));

          this.$jobContainer = this.$('.sip-detail-job-container');

          return this;
        },

      update: function()
        {
          // Reload nested collection
          this.model.loadJobs(); // .refresh() shouldn't work here

          // Update timestamp
          this.$('.sip-detail-timestamp').html(
            new Date(this.model.get('timestamp') * 1000).getArchivematicaDateTime()
          );

          // Update icon
          this.updateIcon();

          if (this.$jobContainer.is(':visible'))
          {
            this.$jobContainer.empty();

            var self = this;

            this.model.jobs.each(function(job)
              {
                var view = new JobView({model: job});
                self.$jobContainer.append(view.render().el);
              });
          }
        },

      updateIcon: function()
        {
          this.$('.sip-detail-icon').html('');
        },

      toggleJobs: function(event)
        {
          if (event)
          {
            event.preventDefault();
          }

          if (this.$jobContainer.is(':visible'))
          {
            this.$jobContainer.slideUp('fast');
            $(this.el).removeClass('sip-selected');
            this.$('.sip-detail-jobs > a').text('Show micro-services');
          }
          else
          {
            this.$jobContainer.empty();

            var self = this;
            this.model.jobs.each(function(job)
              {
                var view = new JobView({model: job});
                self.$jobContainer.append(view.render().el);
              });

            this.$jobContainer.slideDown('fast');
            $(this.el).addClass('sip-selected');
            this.$('.sip-detail-jobs > a').text('Hide micro-services');
          }
        }
    });

    window.Job = Backbone.Model.extend({

    });

    window.JobCollection = Backbone.Collection.extend({

      model: Job,

      getIcon: function()
        {
          if (undefined !== this.find(function(job)
            {
              return 0 < job.get('status') || 'Requires approval' == job.get('currentstep');
            }))
          {
            return '/media/images/bell.png';
          }
          else if (undefined !== this.find(function(job)
            {
              return 'Failed' == job.get('currentstep');
            }))
          {
            return '/media/images/cancel.png';
          }
          else if (undefined !== this.find(function(job)
            {
              return 'Executing command(s)' == job.get('currentstep');
            }))
          {
            return '/media/images/icons/arrow_refresh.png';
          }
          else if (undefined !== this.find(function(job)
            {
              return 'Rejected' == job.get('currentstep');
            }))
          {
            return '/media/images/icons/control_stop_blue.png';
          }
          else
          {
            return '/media/images/accept.png';
          }
        }

    });

    window.JobView = Backbone.View.extend({

      className: 'job',

      events: {
        'click .btn_browse_job': 'browseJob',
        'click .btn_approve_job': 'approveJob',
        'click .btn_reject_job': 'rejectJob',
        'click .job-detail-microservice > a': 'toggleMicroserviceHelp',
      },

      template: _.template($('#job-template').html()),

      initialize: function()
        {
          _.bindAll(this, 'render', 'approveJob', 'rejectJob');
          this.model.bind('change', this.render);
          this.model.view = this;
        },

      render: function()
        {
          $(this.el).html(this.template(this.model.toJSON()));

          if (-1 < jQuery.inArray(this.model.get('currentstep'), ['Requires approval', 'Failed', 'Rejected', 'Executing command(s)']))
          {
            $(this.el).css('background-color', '#f2d8d8');
          }
          else
          {
            $(this.el).css('background-color', '#d8f2dc');
          }

          if (1 == this.model.get('status'))
          {
            this.$('.job-detail-currentstep')
              .append('

').children()
              .append('Browse')
              .append('Approve')
              .append('Reject')
          }

          return this;
        },

      toggleMicroserviceHelp: function(event)
        {
          event.preventDefault();

          $(event.target).siblings('p').toggle('blind', 500);
        },

      browseJob: function(event)
        {
          event.preventDefault();

          alert("browsejob " + this.model.get('uuid'));
        },

      approveJob: function(event)
        {
          event.preventDefault();

          $.ajax({
            context: this,
            data: { uuid: this.model.get('uuid') },
            type: 'POST',
            success: function(data)
              {
                this.model.set({
                  'currentstep': 'Executing command(s)',
                  'status': 0
                });

                this.model.sip.view.updateIcon();
              },
            url: '/mcp/approve-job/'
          });
        },

      rejectJob: function(event)
        {
          event.preventDefault();

          $.ajax({
            context: this,
            data: { uuid: this.model.get('uuid') },
            type: 'POST',
            success: function(data)
              {
                this.model.set({
                  'currentstep': 'Rejected',
                  'status': 0
                });

                this.model.sip.view.updateIcon();

                this.model.sip.view.toggleJobs();
              },
            url: '/mcp/reject-job/'
          });
        },

    });

    window.StatusView = Backbone.View.extend({

      id: 'status',

      template: _.template($('#status-template').html()),

      initialize: function()
        {

        },

      show: function(message, error)
        {
          this.text(message);

          if (true === error)
          {
            $(this.el).addClass('status-error');
          }
          else
          {
            $(this.el).removeClass('status-error');
          }

          $(this.el).show();
        },

      hide: function()
        {
          $(this.el).hide();
        },

      text: function(message)
        {
          $(this.el).find('span').html(message);
        }

    });

    window.AppView = Backbone.View.extend({

      el: $('#sip-container'),

      initialize: function()
        {
          _.bindAll(this, 'addOne', 'addAll', 'add');
          Sips.bind('refresh', this.addAll);
          Sips.bind('add', this.add);
          Sips.fetch();
        },

      add: function(sip)
        {
          var index = Sips.indexOf(sip);
          var view = new SipView({model: sip});

          var $new = $(view.render().el).hide();
          var $target = this.el.find('.sip').eq(index);

          if ($target.length)
          {
            $target.before($new);
          }
          else
          {
            this.el.children('#sip-body').append($new);
          }

          // Animation
          $new.addClass('sip-new').show('blind', {}, 500, function()
            {
              $(this).removeClass('sip-new', 2000);
            });
        },

      addOne: function(sip)
        {
          var view = new SipView({model: sip});
          this.el.children('#sip-body').append(view.render().el);
        },

      addAll: function()
        {
          Sips.each(this.addOne);

          var self = this;
          setTimeout(function()
            {
              self.poll();
            }, window.pollingInterval ? window.pollingInterval * 1000: 5000);
        },

      poll: function()
        {
          $.ajax({
            context: this,
            dataType: 'json',
            type: 'GET',
            url: '/sips/all/',
            error: function()
              {
                // Show warning
              },
            success: function(response)
              {
                for (var i in response)
                {
                  var sip = response[i];
                  var item = Sips.find(function(item) { return item.get('uuid') == sip.uuid; });

                  if (undefined === item)
                  {
                    // Add new sips
                    Sips.add(sip);
                  }
                  else
                  {
                    // Update sips
                    item.set(sip);
                  }

                  // Delete sips
                }
              },
            complete: function()
              {
                var self = this;
                setTimeout(function()
                  {
                    self.poll();
                  }, window.pollingInterval ? window.pollingInterval * 1000: 5000);
              }
          });
        },

    });

    Date.prototype.getArchivematicaDateTime = function()
      {
        pad = function (n)
          {
            return n < 10 ? '0' + n : n;
          }

        return this.getUTCFullYear() + '-' + pad(this.getUTCMonth() + 1) + '-' + pad(this.getUTCDate()) + ' ' + pad(this.getUTCHours()) + ':' + pad(this.getUTCMinutes()); // + ':' + pad(this.getUTCSeconds());
      };
  }
);<commit_msg>Fix status widget.<commit_after>$(function()
  {

    window.Sip = Backbone.Model.extend({

      initialize: function()
        {
          this.loadJobs();
        },

      hasFinished: function()
        {
          return false == this.jobs.some(function(job)
            {
              return -1 < jQuery.inArray(job.get('currentstep'), ['Requires approval', 'Executing command(s)']);
            });
        },

      set: function(attributes, options)
        {
          Backbone.Model.prototype.set.call(this, attributes, options);

          if (undefined !== this.jobs && !this.hasFinished())
          {
            this.view.update();
          }
        },

      loadJobs: function()
        {
          // Nested collection
          this.jobs = new JobCollection(this.get('jobs'));

          var self = this;
          this.jobs.each(function(job)
            {
              job.sip = self;
            });
        }
    });

    window.SipCollection = Backbone.Collection.extend({

      model: Sip,

      url: '/sips/all/',

      initialize: function()
        {

        },

      comparator: function(sip)
        {
          return 0 - sip.get('timestamp');
        },

    });

    window.SipView = Backbone.View.extend({

      className: 'sip',

      template: _.template($('#sip-template').html()),

      events: {
        'click .sip-row > .sip-detail-jobs > a': 'toggleJobs',
      },

      initialize: function()
        {
          _.bindAll(this, 'render', 'update', 'add', 'updateIcon');
          this.model.view = this;
          this.model.bind('change:timestamp', this.update);
        },

      render: function()
        {
          $(this.el).html(this.template(this.model.toJSON())).attr('uuid', this.model.get('uuid'));

          this.$jobContainer = this.$('.sip-detail-job-container');

          return this;
        },

      update: function()
        {
          // Reload nested collection
          this.model.loadJobs(); // .refresh() shouldn't work here

          // Update timestamp
          this.$('.sip-detail-timestamp').html(
            new Date(this.model.get('timestamp') * 1000).getArchivematicaDateTime()
          );

          // Update icon
          this.updateIcon();

          if (this.$jobContainer.is(':visible'))
          {
            this.$jobContainer.empty();

            var self = this;

            this.model.jobs.each(function(job)
              {
                var view = new JobView({model: job});
                self.$jobContainer.append(view.render().el);
              });
          }
        },

      updateIcon: function()
        {
          this.$('.sip-detail-icon').html('');
        },

      toggleJobs: function(event)
        {
          if (event)
          {
            event.preventDefault();
          }

          if (this.$jobContainer.is(':visible'))
          {
            this.$jobContainer.slideUp('fast');
            $(this.el).removeClass('sip-selected');
            this.$('.sip-detail-jobs > a').text('Show micro-services');
          }
          else
          {
            this.$jobContainer.empty();

            var self = this;
            this.model.jobs.each(function(job)
              {
                var view = new JobView({model: job});
                self.$jobContainer.append(view.render().el);
              });

            this.$jobContainer.slideDown('fast');
            $(this.el).addClass('sip-selected');
            this.$('.sip-detail-jobs > a').text('Hide micro-services');
          }
        }
    });

    window.Job = Backbone.Model.extend({

    });

    window.JobCollection = Backbone.Collection.extend({

      model: Job,

      getIcon: function()
        {
          if (undefined !== this.find(function(job)
            {
              return 0 < job.get('status') || 'Requires approval' == job.get('currentstep');
            }))
          {
            return '/media/images/bell.png';
          }
          else if (undefined !== this.find(function(job)
            {
              return 'Failed' == job.get('currentstep');
            }))
          {
            return '/media/images/cancel.png';
          }
          else if (undefined !== this.find(function(job)
            {
              return 'Executing command(s)' == job.get('currentstep');
            }))
          {
            return '/media/images/icons/arrow_refresh.png';
          }
          else if (undefined !== this.find(function(job)
            {
              return 'Rejected' == job.get('currentstep');
            }))
          {
            return '/media/images/icons/control_stop_blue.png';
          }
          else
          {
            return '/media/images/accept.png';
          }
        }

    });

    window.JobView = Backbone.View.extend({

      className: 'job',

      events: {
        'click .btn_browse_job': 'browseJob',
        'click .btn_approve_job': 'approveJob',
        'click .btn_reject_job': 'rejectJob',
        'click .job-detail-microservice > a': 'toggleMicroserviceHelp',
      },

      template: _.template($('#job-template').html()),

      initialize: function()
        {
          _.bindAll(this, 'render', 'approveJob', 'rejectJob');
          this.model.bind('change', this.render);
          this.model.view = this;
        },

      render: function()
        {
          $(this.el).html(this.template(this.model.toJSON()));

          if (-1 < jQuery.inArray(this.model.get('currentstep'), ['Requires approval', 'Failed', 'Rejected', 'Executing command(s)']))
          {
            $(this.el).css('background-color', '#f2d8d8');
          }
          else
          {
            $(this.el).css('background-color', '#d8f2dc');
          }

          if (1 == this.model.get('status'))
          {
            this.$('.job-detail-currentstep')
              .append('

').children()
              .append('Browse')
              .append('Approve')
              .append('Reject')
          }

          return this;
        },

      toggleMicroserviceHelp: function(event)
        {
          event.preventDefault();

          $(event.target).siblings('p').toggle('blind', 500);
        },

      browseJob: function(event)
        {
          event.preventDefault();

          alert("browsejob " + this.model.get('uuid'));
        },

      approveJob: function(event)
        {
          event.preventDefault();

          $.ajax({
            context: this,
            data: { uuid: this.model.get('uuid') },
            type: 'POST',
            success: function(data)
              {
                this.model.set({
                  'currentstep': 'Executing command(s)',
                  'status': 0
                });

                this.model.sip.view.updateIcon();
              },
            url: '/mcp/approve-job/'
          });
        },

      rejectJob: function(event)
        {
          event.preventDefault();

          $.ajax({
            context: this,
            data: { uuid: this.model.get('uuid') },
            type: 'POST',
            success: function(data)
              {
                this.model.set({
                  'currentstep': 'Rejected',
                  'status': 0
                });

                this.model.sip.view.updateIcon();

                this.model.sip.view.toggleJobs();
              },
            url: '/mcp/reject-job/'
          });
        },

    });

    window.StatusView = Backbone.View.extend({

      id: 'status',

      template: _.template($('#status-template').html()),

      initialize: function()
        {
          this.render();
        },

      render: function()
        {
          $(this.el).html(this.template()).hide().appendTo('body');

          return this;
        },

      hide: function()
        {
          $(this.el).fadeOut('fast');
        },

      text: function(message, error)
        {
          $(this.el).show().find('span').html(message);

          if (true === error)
          {
            $(this.el).addClass('status-error');
          }
          else
          {
            $(this.el).removeClass('status-error');
          }

          var self = this;
          setTimeout(function()
            {
              self.hide();
            }, 1000);
        }

    });

    window.AppView = Backbone.View.extend({

      el: $('#sip-container'),

      initialize: function()
        {
          _.bindAll(this, 'addOne', 'addAll', 'add');
          Sips.bind('refresh', this.addAll);
          Sips.bind('add', this.add);
          Sips.fetch();

          window.statusWidget = new window.StatusView();
        },

      add: function(sip)
        {
          var index = Sips.indexOf(sip);
          var view = new SipView({model: sip});

          var $new = $(view.render().el).hide();
          var $target = this.el.find('.sip').eq(index);

          if ($target.length)
          {
            $target.before($new);
          }
          else
          {
            this.el.children('#sip-body').append($new);
          }

          // Animation
          $new.addClass('sip-new').show('blind', {}, 500, function()
            {
              $(this).removeClass('sip-new', 2000);
            });
        },

      addOne: function(sip)
        {
          var view = new SipView({model: sip});
          this.el.children('#sip-body').append(view.render().el);
        },

      addAll: function()
        {
          Sips.each(this.addOne);

          var self = this;
          setTimeout(function()
            {
              self.poll();
            }, window.pollingInterval ? window.pollingInterval * 1000: 5000);
        },

      poll: function()
        {
          $.ajax({
            context: this,
            dataType: 'json',
            type: 'GET',
            url: '/sips/all/',
            beforeSend: function()
              {
                window.statusWidget.text('Refreshing...');
              },
            error: function()
              {
                // Show warning
              },
            success: function(response)
              {
                for (var i in response)
                {
                  var sip = response[i];
                  var item = Sips.find(function(item) { return item.get('uuid') == sip.uuid; });

                  if (undefined === item)
                  {
                    // Add new sips
                    Sips.add(sip);
                  }
                  else
                  {
                    // Update sips
                    item.set(sip);
                  }

                  // Delete sips
                }
              },
            complete: function()
              {
                var self = this;
                setTimeout(function()
                  {
                    self.poll();
                  }, window.pollingInterval ? window.pollingInterval * 1000: 5000);
              }
          });
        },

    });

    Date.prototype.getArchivematicaDateTime = function()
      {
        pad = function (n)
          {
            return n < 10 ? '0' + n : n;
          }

        return this.getUTCFullYear() + '-' + pad(this.getUTCMonth() + 1) + '-' + pad(this.getUTCDate()) + ' ' + pad(this.getUTCHours()) + ':' + pad(this.getUTCMinutes()); // + ':' + pad(this.getUTCSeconds());
      };
  }
);<|endoftext|>


<commit_before>const args = require('system').args
const async = require('async')
const page = require('webpage').create()

// Handle HTTP timeouts
page.settings.resourceTimeout = 60 * 1000 // 60 seconds
page.onResourceTimeout = function(request) {
  message = 'Timed out resource at ' + request.url + '. '
  message += 'Code: ' + request.errorCode + '. '
  message += 'Error: ' + request.errorString

  console.log(message)
  phantom.exit(1);
}

function delay(duration, callback) {
  setTimeout(callback, duration)
}

function waitUntil(conditionCallback, done) {
  if (conditionCallback()) {
    done()
  } else {
    delay(10, function() {
      waitUntil(conditionCallback, done)
    })
  }
}

// Rotation by calling the 3D Viewer through the DOM
function rotateY(y) {
  window.viewer.rotate(0, y, 0)
  window.viewer.update()
}

function rotationsByIncrement(increment) {
  const results = []
  for (var i = 0; i < 360; i += increment) {
    results.push(i)
  }
  return results
}

function isLoadingComplete() {
  return page.evaluate(function() {
    return window._loadingComplete
  })
}

function integers(total) {
  const results = []
  for (var i = 0; i < total; i += 1) {
    results.push(i)
  }
  return results
}

function capture(url, tmpDir, total, width, height) {
  const increment = 360 / total
  const rotations = rotationsByIncrement(increment)

  function imagePath(num) {
    return tmpDir + '/craster-' + num + '.png'
  }

  function rotator(index, callback) {
    const rotation = index * increment
    console.log(index + '/' + total + ': Rotate to ' + rotation)
    page.evaluate(rotateY, increment)
    delay(20, function() {
      page.render(imagePath(index))
      callback()
    })
  }

  function start() {
    console.log('Starting captures in ' + tmpDir + '...')
    page.evaluate(rotateY, 0)
    async.eachSeries(integers(total), rotator, function() {
      phantom.exit()
    })
  }

  page.viewportSize = { width: width, height: height }
  page.paperSize = { width: width, height: height }
  page.clipRect = { top: 0, left: 0, width: width, height: height }

  page.onConsoleMessage = function(msg) { console.log('console: ' + msg) }
  page.open(url, function() {
    console.log('Wait until loading complete...')
    waitUntil(isLoadingComplete, function() {
      delay(200, start)
    })
  })
}

if (args.length != 6) {
  console.log('Usage: phantomjs capture.js URL TMP_DIR TOTAL WIDTH HEIGHT')
  phantom.exit(1)
} else {
  const url = args[1]
  const tmpDir = args[2]
  const total = parseInt(args[3], 10)
  const width = parseInt(args[4], 10)
  const height = parseInt(args[5], 10)
  capture(url, tmpDir, total, width, height)
}
<commit_msg>Remove unused function<commit_after>const args = require('system').args
const async = require('async')
const page = require('webpage').create()

// Handle HTTP timeouts
page.settings.resourceTimeout = 60 * 1000 // 60 seconds
page.onResourceTimeout = function(request) {
  message = 'Timed out resource at ' + request.url + '. '
  message += 'Code: ' + request.errorCode + '. '
  message += 'Error: ' + request.errorString

  console.log(message)
  phantom.exit(1);
}

function delay(duration, callback) {
  setTimeout(callback, duration)
}

function waitUntil(conditionCallback, done) {
  if (conditionCallback()) {
    done()
  } else {
    delay(10, function() {
      waitUntil(conditionCallback, done)
    })
  }
}

// Rotation by calling the 3D Viewer through the DOM
function rotateY(y) {
  window.viewer.rotate(0, y, 0)
  window.viewer.update()
}

function isLoadingComplete() {
  return page.evaluate(function() {
    return window._loadingComplete
  })
}

function integers(total) {
  const results = []
  for (var i = 0; i < total; i += 1) {
    results.push(i)
  }
  return results
}

function capture(url, tmpDir, total, width, height) {
  const increment = 360 / total

  function imagePath(num) {
    return tmpDir + '/craster-' + num + '.png'
  }

  function rotator(index, callback) {
    const rotation = index * increment
    console.log(index + '/' + total + ': Rotate to ' + rotation)
    page.evaluate(rotateY, increment)
    delay(20, function() {
      page.render(imagePath(index))
      callback()
    })
  }

  function start() {
    console.log('Starting captures in ' + tmpDir + '...')
    page.evaluate(rotateY, 0)
    async.eachSeries(integers(total), rotator, function() {
      phantom.exit()
    })
  }

  page.viewportSize = { width: width, height: height }
  page.paperSize = { width: width, height: height }
  page.clipRect = { top: 0, left: 0, width: width, height: height }

  page.onConsoleMessage = function(msg) { console.log('console: ' + msg) }
  page.open(url, function() {
    console.log('Wait until loading complete...')
    waitUntil(isLoadingComplete, function() {
      delay(200, start)
    })
  })
}

if (args.length != 6) {
  console.log('Usage: phantomjs capture.js URL TMP_DIR TOTAL WIDTH HEIGHT')
  phantom.exit(1)
} else {
  const url = args[1]
  const tmpDir = args[2]
  const total = parseInt(args[3], 10)
  const width = parseInt(args[4], 10)
  const height = parseInt(args[5], 10)
  capture(url, tmpDir, total, width, height)
}
<|endoftext|>


<commit_before>// ==UserScript==
// @include http://youtube.com/*
// @include http://*.youtube.com/*
// @include https://youtube.com/*
// @include https://*.youtube.com/*
// @exclude http://youtube.com/html5
// @exclude http://*.youtube.com/html5
// @exclude https://youtube.com/html5
// @exclude https://*.youtube.com/html5
// ==/UserScript==

(function() {
{
  var requestedHtml5VideoStatus = false;

  window.addEventListener('load', function()
  {
    opera.extension.postMessage('requestHtml5VideoStatus');
    opera.extension.onmessage = function(event)
    {
      if (event.data === 'testHtml5VideoStatus' && !requestedHtml5VideoStatus)
      {
        loadHtml5VideoTestFrame();
      }
      if (event.data === 'goodHtml5VideoStatus')
      {
        reloadVideoPage(event.data);
      }
  }}, false);

  window.addEventListener('DOMContentLoaded', function()
  {
    if (widget.preferences.getItem('videoSaveButton') === 'true') downloadVideoButton();
    if (widget.preferences.getItem('filterSearch') === 'true') filterSearchResults();
    if (widget.preferences.getItem('hideFlashPromo') === 'true') removeElementById('flash10-promo-div');
    if (widget.preferences.getItem('hideFlashUpgrade') === 'true') setTimeout((function() { removeElementById('flash-upgrade'); }), 350);
    if (widget.preferences.getItem('preventFlash') === 'true') removeElementById('movie_player');
  }, false);

  function _(string)
  {
    if (typeof(oexWebMPlusi18n) != 'undefined' && oexWebMPlusi18n[string])
    {
      return oexWebMPlusi18n[string];
    }
    return string;
  }

  function loadHtml5VideoTestFrame()
  {
    requestedHtml5VideoStatus = true;
    var isHtml5VideoPlayer, videoPlayer = document.getElementById('watch-player');
    if (videoPlayer != null)
    {
      if (videoPlayer.class === 'html5-player') isHtml5VideoPlayer = true;
    }
    if (!isHtml5VideoPlayer)
    {
      var frame = document.createElement('iframe');
      frame.style.height = '1px';
      frame.style.width = '1px';
      frame.setAttribute('id', 'html5formframe');
      frame.setAttribute('src', window.location.protocol + '//' + window.location.hostname + '/html5');
      document.body.appendChild(frame);
  }}

  function reloadVideoPage()
  {
    var videoPage = window.location.pathname.indexOf('/watch'),
    html5Videos = document.getElementsByTagName('video').length;
    if (videoPage === 0 && html5Videos === 0)
    {
      window.location = window.location.href;
  }}

  function downloadVideoButton()
  {
    var text, video = document.getElementsByTagName('video'),
    container = document.getElementById('watch-actions-right'),
    button = document.createElement('button');
    if (video.length > 0 && container != undefined)
    {
      button.setAttribute('class', 'yt-uix-button yt-uix-tooltip yt-uix-tooltip-reverse');
      button.style.position = 'relative';
      button.style.top = '-4px';
      button.setAttribute('data-tooltip-text', _('Click, then press Ctrl+S to save.'));
      button.onclick = function() { window.location = video[0].src; }
      text = document.createTextNode(_('Download Video'));
      button.appendChild(text)
      container.appendChild(button);
  }}

  function removeElementById(id)
  {
    var element = document.getElementById(id);
    if (element != null) element.parentNode.removeChild(element);
  }

  function filterSearchResults()
  {
    var parameter, searchField = document.getElementById('masthead-search');
    if (searchField != null) {
      parameter = document.createElement('input');
      parameter.setAttribute('name', 'webm');
      parameter.setAttribute('type', 'hidden');
      parameter.setAttribute('value', '1');
      searchField.appendChild(parameter);
}}}}());<commit_msg>Dropped an extra pair of braces.<commit_after>// ==UserScript==
// @include http://youtube.com/*
// @include http://*.youtube.com/*
// @include https://youtube.com/*
// @include https://*.youtube.com/*
// @exclude http://youtube.com/html5
// @exclude http://*.youtube.com/html5
// @exclude https://youtube.com/html5
// @exclude https://*.youtube.com/html5
// ==/UserScript==

(function() {
  var requestedHtml5VideoStatus = false;

  window.addEventListener('load', function()
  {
    opera.extension.postMessage('requestHtml5VideoStatus');
    opera.extension.onmessage = function(event)
    {
      if (event.data === 'testHtml5VideoStatus' && !requestedHtml5VideoStatus)
      {
        loadHtml5VideoTestFrame();
      }
      if (event.data === 'goodHtml5VideoStatus')
      {
        reloadVideoPage(event.data);
      }
  }}, false);

  window.addEventListener('DOMContentLoaded', function()
  {
    if (widget.preferences.getItem('videoSaveButton') === 'true') downloadVideoButton();
    if (widget.preferences.getItem('filterSearch') === 'true') filterSearchResults();
    if (widget.preferences.getItem('hideFlashPromo') === 'true') removeElementById('flash10-promo-div');
    if (widget.preferences.getItem('hideFlashUpgrade') === 'true') setTimeout((function() { removeElementById('flash-upgrade'); }), 350);
    if (widget.preferences.getItem('preventFlash') === 'true') removeElementById('movie_player');
  }, false);

  function _(string)
  {
    if (typeof(oexWebMPlusi18n) != 'undefined' && oexWebMPlusi18n[string])
    {
      return oexWebMPlusi18n[string];
    }
    return string;
  }

  function loadHtml5VideoTestFrame()
  {
    requestedHtml5VideoStatus = true;
    var isHtml5VideoPlayer, videoPlayer = document.getElementById('watch-player');
    if (videoPlayer != null)
    {
      if (videoPlayer.class === 'html5-player') isHtml5VideoPlayer = true;
    }
    if (!isHtml5VideoPlayer)
    {
      var frame = document.createElement('iframe');
      frame.style.height = '1px';
      frame.style.width = '1px';
      frame.setAttribute('id', 'html5formframe');
      frame.setAttribute('src', window.location.protocol + '//' + window.location.hostname + '/html5');
      document.body.appendChild(frame);
  }}

  function reloadVideoPage()
  {
    var videoPage = window.location.pathname.indexOf('/watch'),
    html5Videos = document.getElementsByTagName('video').length;
    if (videoPage === 0 && html5Videos === 0)
    {
      window.location = window.location.href;
  }}

  function downloadVideoButton()
  {
    var text, video = document.getElementsByTagName('video'),
    container = document.getElementById('watch-actions-right'),
    button = document.createElement('button');
    if (video.length > 0 && container != undefined)
    {
      button.setAttribute('class', 'yt-uix-button yt-uix-tooltip yt-uix-tooltip-reverse');
      button.style.position = 'relative';
      button.style.top = '-4px';
      button.setAttribute('data-tooltip-text', _('Click, then press Ctrl+S to save.'));
      button.onclick = function() { window.location = video[0].src; }
      text = document.createTextNode(_('Download Video'));
      button.appendChild(text)
      container.appendChild(button);
  }}

  function removeElementById(id)
  {
    var element = document.getElementById(id);
    if (element != null) element.parentNode.removeChild(element);
  }

  function filterSearchResults()
  {
    var parameter, searchField = document.getElementById('masthead-search');
    if (searchField != null) {
      parameter = document.createElement('input');
      parameter.setAttribute('name', 'webm');
      parameter.setAttribute('type', 'hidden');
      parameter.setAttribute('value', '1');
      searchField.appendChild(parameter);
}}}());<|endoftext|>


<commit_before>// XXX We should revisit how we factor MongoDB support into (1) the
// server-side node.js driver [which you might use independently of
// livedata, after all], (2) minimongo [ditto], and (3) Collection,
// which is the class that glues the two of them to Livedata, but also
// is generally the "public interface for newbies" to Mongo in the
// Meteor universe. We want to allow the components to be used
// independently, but we don't want to overwhelm the user with
// minutiae.

Package.describe({
  summary: "Adaptor for using MongoDB and Minimongo over DDP",
  version: '1.5.1'
});

Npm.depends({
  "mongodb-uri": "0.9.7"
});

Npm.strip({
  mongodb: ["test/"]
});

Package.onUse(function (api) {
  api.use('npm-mongo', 'server');
  api.use('allow-deny');

  api.use([
    'random',
    'ejson',
    'minimongo',
    'ddp',
    'tracker',
    'diff-sequence',
    'mongo-id',
    'check',
    'ecmascript',
    'mongo-dev-server',
  ]);

  // Make weak use of Decimal type on client
  api.use('mongo-decimal', 'client', {weak: true});
  api.use('mongo-decimal', 'server');

  api.use('underscore', 'server');

  // Binary Heap data structure is used to optimize oplog observe driver
  // performance.
  api.use('binary-heap', 'server');

  // Allow us to detect 'insecure'.
  api.use('insecure', {weak: true});

  // Allow us to detect 'autopublish', and publish collections if it's loaded.
  api.use('autopublish', 'server', {weak: true});

  // Allow us to detect 'disable-oplog', which turns off oplog tailing for your
  // app even if it's configured in the environment. (This package will be
  // probably be removed before 1.0.)
  api.use('disable-oplog', 'server', {weak: true});

  // defaultRemoteCollectionDriver gets its deployConfig from something that is
  // (for questionable reasons) initialized by the webapp package.
  api.use('webapp', 'server', {weak: true});

  // If the facts package is loaded, publish some statistics.
  api.use('facts-base', 'server', {weak: true});

  api.use('callback-hook', 'server');

  // Stuff that should be exposed via a real API, but we haven't yet.
  api.export('MongoInternals', 'server');
  // For tests only.
  api.export('MongoTest', 'server', {testOnly: true});
  api.export("Mongo");

  api.addFiles(['mongo_driver.js', 'oplog_tailing.js',
                 'observe_multiplex.js', 'doc_fetcher.js',
                 'polling_observe_driver.js','oplog_observe_driver.js'],
                'server');
  api.addFiles('local_collection_driver.js', ['client', 'server']);
  api.addFiles('remote_collection_driver.js', 'server');
  api.addFiles('collection.js', ['client', 'server']);
  api.addFiles('connection_options.js', 'server');
});

Package.onTest(function (api) {
  api.use('mongo');
  api.use('check');
  api.use('ecmascript');
  api.use(['tinytest', 'underscore', 'test-helpers', 'ejson', 'random',
           'ddp', 'base64']);
  // XXX test order dependency: the allow_tests "partial allow" test
  // fails if it is run before mongo_livedata_tests.
  api.addFiles('mongo_livedata_tests.js', ['client', 'server']);
  api.addFiles('upsert_compatibility_test.js', 'server');
  api.addFiles('allow_tests.js', ['client', 'server']);
  api.addFiles('collection_tests.js', ['client', 'server']);
  api.addFiles('observe_changes_tests.js', ['client', 'server']);
  api.addFiles('oplog_tests.js', 'server');
  api.addFiles('doc_fetcher_tests.js', 'server');
});
<commit_msg>Bump minor version of mongo package to force useNewUrlParser fix.<commit_after>// XXX We should revisit how we factor MongoDB support into (1) the
// server-side node.js driver [which you might use independently of
// livedata, after all], (2) minimongo [ditto], and (3) Collection,
// which is the class that glues the two of them to Livedata, but also
// is generally the "public interface for newbies" to Mongo in the
// Meteor universe. We want to allow the components to be used
// independently, but we don't want to overwhelm the user with
// minutiae.

Package.describe({
  summary: "Adaptor for using MongoDB and Minimongo over DDP",
  version: '1.6.0'
});

Npm.depends({
  "mongodb-uri": "0.9.7"
});

Npm.strip({
  mongodb: ["test/"]
});

Package.onUse(function (api) {
  api.use('npm-mongo', 'server');
  api.use('allow-deny');

  api.use([
    'random',
    'ejson',
    'minimongo',
    'ddp',
    'tracker',
    'diff-sequence',
    'mongo-id',
    'check',
    'ecmascript',
    'mongo-dev-server',
  ]);

  // Make weak use of Decimal type on client
  api.use('mongo-decimal', 'client', {weak: true});
  api.use('mongo-decimal', 'server');

  api.use('underscore', 'server');

  // Binary Heap data structure is used to optimize oplog observe driver
  // performance.
  api.use('binary-heap', 'server');

  // Allow us to detect 'insecure'.
  api.use('insecure', {weak: true});

  // Allow us to detect 'autopublish', and publish collections if it's loaded.
  api.use('autopublish', 'server', {weak: true});

  // Allow us to detect 'disable-oplog', which turns off oplog tailing for your
  // app even if it's configured in the environment. (This package will be
  // probably be removed before 1.0.)
  api.use('disable-oplog', 'server', {weak: true});

  // defaultRemoteCollectionDriver gets its deployConfig from something that is
  // (for questionable reasons) initialized by the webapp package.
  api.use('webapp', 'server', {weak: true});

  // If the facts package is loaded, publish some statistics.
  api.use('facts-base', 'server', {weak: true});

  api.use('callback-hook', 'server');

  // Stuff that should be exposed via a real API, but we haven't yet.
  api.export('MongoInternals', 'server');
  // For tests only.
  api.export('MongoTest', 'server', {testOnly: true});
  api.export("Mongo");

  api.addFiles(['mongo_driver.js', 'oplog_tailing.js',
                 'observe_multiplex.js', 'doc_fetcher.js',
                 'polling_observe_driver.js','oplog_observe_driver.js'],
                'server');
  api.addFiles('local_collection_driver.js', ['client', 'server']);
  api.addFiles('remote_collection_driver.js', 'server');
  api.addFiles('collection.js', ['client', 'server']);
  api.addFiles('connection_options.js', 'server');
});

Package.onTest(function (api) {
  api.use('mongo');
  api.use('check');
  api.use('ecmascript');
  api.use(['tinytest', 'underscore', 'test-helpers', 'ejson', 'random',
           'ddp', 'base64']);
  // XXX test order dependency: the allow_tests "partial allow" test
  // fails if it is run before mongo_livedata_tests.
  api.addFiles('mongo_livedata_tests.js', ['client', 'server']);
  api.addFiles('upsert_compatibility_test.js', 'server');
  api.addFiles('allow_tests.js', ['client', 'server']);
  api.addFiles('collection_tests.js', ['client', 'server']);
  api.addFiles('observe_changes_tests.js', ['client', 'server']);
  api.addFiles('oplog_tests.js', 'server');
  api.addFiles('doc_fetcher_tests.js', 'server');
});
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var globalTimers = {
    setTimeout: require('timers').setTimeout,
    clearTimeout: require('timers').clearTimeout,
    now: Date.now
};
var globalRandom = Math.random;
var net = require('net');
var format = require('util').format;
var extend = require('xtend');

var inherits = require('util').inherits;
var EventEmitter = require('events').EventEmitter;

var nullLogger = require('./null-logger.js');
var EndpointHandler = require('./endpoint-handler.js');
var TChannelRequest = require('./request');
var TChannelServiceNameHandler = require('./service-name-handler');
var errors = require('./errors');

var TChannelConnection = require('./connection');
var TChannelPeers = require('./peers');

var TracingAgent = require('./trace/agent');

// TODO restore spying
// var Spy = require('./v2/spy');
// var dumpEnabled = /\btchannel_dump\b/.test(process.env.NODE_DEBUG || '');

function TChannel(options) {
    if (!(this instanceof TChannel)) {
        return new TChannel(options);
    }

    var self = this;
    EventEmitter.call(self);

    self.options = extend({
        timeoutCheckInterval: 1000,
        timeoutFuzz: 100,
        // TODO: maybe we should always add pid to user-supplied?
        processName: format('%s[%s]', process.title, process.pid)
    }, options);

    self.options.requestDefaults = extend({
        timeout: TChannelRequest.defaultTimeout
    }, self.options.requestDefaults);

    self.logger = self.options.logger || nullLogger;
    self.random = self.options.random || globalRandom;
    self.timers = self.options.timers || globalTimers;

    // Filled in by the listen call:
    self.host = null;
    self.requestedPort = null;

    // Filled in by listening event:
    self.hostPort = null;

    // name of the service running over this channel
    self.serviceName = '';
    if (self.options.serviceName) {
        self.serviceName = self.options.serviceName;
        self.options.requestDefaults.serviceName = self.serviceName;
        delete self.options.serviceName;
    }

    // populated by makeSubChannel
    self.topChannel = null;
    self.subChannels = self.serviceName ? null : {};

    // how to handle incoming requests
    if (!self.options.handler) {
        if (!self.serviceName) {
            self.handler = TChannelServiceNameHandler(self);
        } else {
            self.handler = EndpointHandler(self.serviceName);
        }
    } else {
        self.handler = self.options.handler;
        delete self.options.handler;
    }

    // populated by:
    // - manually api (.peers.add etc)
    // - incoming connections on any listening socket
    self.peers = TChannelPeers(self, self.options);

    // TChannel advances through the following states.
    self.listened = false;
    self.listening = false;
    self.destroyed = false;

    if (self.options.trace) {
        self.tracer = new TracingAgent({
            logger: self.logger,
            forceTrace: self.options.forceTrace,
            serviceName: self.options.tracingServiceName,
            reporter: self.options.traceReporter
        });

        if (self.options.requestDefaults !== false) {
            self.options.requestDefaults.trace = true;
        }
    }

    // lazily created by .getServer (usually from .listen)
    self.serverSocket = null;
    self.serverConnections = null;
}
inherits(TChannel, EventEmitter);

TChannel.prototype.getServer = function getServer() {
    var self = this;
    if (self.serverSocket) {
        return self.serverSocket;
    }

    self.serverConnections = Object.create(null);
    self.serverSocket = net.createServer(onServerSocketConnection);
    self.serverSocket.on('listening', onServerSocketListening);
    self.serverSocket.on('error', onServerSocketError);

    return self.serverSocket;

    function onServerSocketConnection(sock) {
        self.onServerSocketConnection(sock);
    }

    function onServerSocketListening() {
        self.onServerSocketListening();
    }

    function onServerSocketError(err) {
        self.onServerSocketError(err);
    }
};

TChannel.prototype.onServerSocketConnection = function onServerSocketConnection(sock) {
    var self = this;

    if (self.destroyed) {
        self.logger.error('got incoming socket whilst destroyed', {
            remoteAddr: sock.remoteAddr,
            remotePort: sock.remotePort,
            hostPort: self.hostPort
        });
        return;
    }

    var remoteAddr = sock.remoteAddress + ':' + sock.remotePort;
    var conn = new TChannelConnection(self, sock, 'in', remoteAddr);

    conn.on('span', function handleSpanFromConn(span) {
        self.tracer.report(span);
    });

    if (self.serverConnections[remoteAddr]) {
        var oldConn = self.serverConnections[remoteAddr];
        oldConn.resetAll(errors.SocketClosedError({
            reason: 'duplicate remoteAddr incoming conn'
        }));
        delete self.serverConnections[remoteAddr];
    }

    sock.on('close', onSocketClose);

    self.serverConnections[remoteAddr] = conn;
    self.emit('connection', conn);

    function onSocketClose() {
        delete self.serverConnections[remoteAddr];
    }
};

TChannel.prototype.onServerSocketListening = function onServerSocketListening() {
    var self = this;

    if (self.destroyed) {
        self.logger.error('got serverSocket listen whilst destroyed', {
            requestHostPort: self.host + ':' + self.requestedPort,
            hostPort: self.host + ':' + self.serverSocket.address().port
        });
        return;
    }

    var address = self.serverSocket.address();
    self.hostPort = self.host + ':' + address.port;
    self.listening = true;

    if (self.subChannels) {
        Object.keys(self.subChannels).forEach(function each(serviceName) {
            var chan = self.subChannels[serviceName];
            if (!chan.hostPort) {
                chan.hostPort = self.hostPort;
            }
        });
    }

    self.emit('listening');
};

TChannel.prototype.onServerSocketError = function onServerSocketError(err) {
    var self = this;

    if (err.code === 'EADDRINUSE') {
        err = errors.TChannelListenError(err, {
            requestedPort: self.requestedPort,
            host: self.host
        });
    }
    self.logger.error('server socket error', {
        err: err,
        requestedPort: self.requestedPort,
        host: self.host,
        hostPort: self.hostPort || null
    });
    self.emit('error', err);
};

TChannel.prototype.makeSubChannel = function makeSubChannel(options) {
    var self = this;
    if (!options) options = {};
    if (self.serviceName) {
        throw new Error('arbitrary-depth sub channels are unsupported'); // TODO typed error
    }
    if (!options.serviceName) {
        throw new Error('must specify serviceName'); // TODO typed error
    }
    if (self.subChannels[options.serviceName]) {
        throw new Error('sub channel already exists'); // TODO typed error
    }
    var opts = extend(self.options);
    var keys = Object.keys(options);
    for (var i = 0; i < keys.length; i++) {
        switch (keys[i]) {
            case 'peers':
                break;
            default:
                opts[keys[i]] = options[keys[i]];
        }
    }
    var chan = TChannel(opts);
    chan.topChannel = self;
    if (options.peers) {
        for (i = 0; i < options.peers.length; i++) {
            if (typeof options.peers[i] === 'string') {
                chan.peers.addPeer(self.peers.add(options.peers[i]));
            } else {
                chan.peers.addPeer(options.peers[i]);
            }
        }
    }
    self.subChannels[chan.serviceName] = chan;

    if (self.hostPort) {
        chan.hostPort = self.hostPort;
    }

    return chan;
};

TChannel.prototype.listen = function listen(port, host, callback) {
    var self = this;
    if (self.listened) {
        throw new Error('TChannel can only listen once'); // TODO typed error
    }
    if (typeof host !== 'string') {
        throw new Error('TChannel requires host argument'); // TODO typed error
    }
    if (typeof port !== 'number') {
        // Note that 0 is a valid port number, indicating that the system must
        // assign an available ephemeral port.
        throw new Error('TChannel must listen with numeric port'); // TODO typed error
    }
    // Does not expressly forbid 127.0.0.1 or localhost since these are valid
    // hosts for testing.
    if (host === '0.0.0.0') {
        throw new Error('TChannel must listen with externally visible host'); // TODO typed error
    }
    self.listened = true;
    self.requestedPort = port;
    self.host = host;
    self.getServer().listen(port, host, callback);
};

TChannel.prototype.register = function register(name, handler) {
    var self = this;

    var handlerType = self.handler && self.handler.type;

    switch (handlerType) {
        case 'tchannel.endpoint-handler':
            self.handler.register(name, handler);
            break;

        case 'tchannel.service-name-handler':
            throw errors.TopLevelRegisterError();

        default:
            throw errors.InvalidHandlerForRegister({
                handlerType: handlerType,
                handler: self.handler
            });
    }
};

TChannel.prototype.address = function address() {
    var self = this;
    if (self.serverSocket) {
        return self.serverSocket.address() || null;
    } else if (self.topChannel) {
        return self.topChannel.address();
    } else {
        return null;
    }
};

TChannel.prototype.request = function channelRequest(options) {
    var self = this;

    if (self.destroyed) {
        throw new Error('cannot request() to destroyed tchannel'); // TODO typed error
    }

    options = extend(self.options.requestDefaults, options);

    if (!options.service && options.serviceName) {
        options.service = options.serviceName;
    }

    if (!self.serviceName && !options.host) {
        if (options.service &&
            self.subChannels &&
            self.subChannels[options.service]) {
            return self.subChannels[options.service].request(options);
        } else {
            throw errors.TopLevelRequestError();
        }
    }

    var req = null;
    if (options.streamed) {
        req = self.peers.request(null, options);
    } else {
        req = new TChannelRequest(self, options);
    }
    self.emit('request', req);
    return req;
};

TChannel.prototype.quit = // to provide backward compatibility.
TChannel.prototype.close = function close(callback) {
    var self = this;

    if (self.destroyed) {
        throw new Error('double close'); // TODO typed error
    }

    self.destroyed = true;

    var counter = 1;

    if (self.serverSocket) {
        ++counter;
        if (self.serverSocket.address()) {
            closeServerSocket();
        } else {
            self.serverSocket.once('listening', closeServerSocket);
        }
    }

    if (self.serverConnections) {
        var incomingConns = Object.keys(self.serverConnections);
        for (var i = 0; i < incomingConns.length; i++) {
            ++counter;
            var incomingConn = self.serverConnections[incomingConns[i]];
            incomingConn.close(onClose);
        }
    }

    if (self.subChannels) {
        var serviceNames = Object.keys(self.subChannels);
        serviceNames.forEach(function each(serviceName) {
            var svcchan = self.subChannels[serviceName];
            if (!svcchan.destroyed) {
                counter++;
                svcchan.close(onClose);
            }
        });
    }

    self.peers.close(onClose);

    function closeServerSocket() {
        self.serverSocket.once('close', onClose);
        self.serverSocket.close();
    }

    function onClose() {
        if (--counter <= 0) {
            if (counter < 0) {
                self.logger.error('closed more channel sockets than expected', {
                    counter: counter
                });
            }
            if (typeof callback === 'function') {
                callback();
            }
        }
    }
};

module.exports = TChannel;
<commit_msg>TChannel: fix bug in trace request option defaulting<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var globalTimers = {
    setTimeout: require('timers').setTimeout,
    clearTimeout: require('timers').clearTimeout,
    now: Date.now
};
var globalRandom = Math.random;
var net = require('net');
var format = require('util').format;
var extend = require('xtend');

var inherits = require('util').inherits;
var EventEmitter = require('events').EventEmitter;

var nullLogger = require('./null-logger.js');
var EndpointHandler = require('./endpoint-handler.js');
var TChannelRequest = require('./request');
var TChannelServiceNameHandler = require('./service-name-handler');
var errors = require('./errors');

var TChannelConnection = require('./connection');
var TChannelPeers = require('./peers');

var TracingAgent = require('./trace/agent');

// TODO restore spying
// var Spy = require('./v2/spy');
// var dumpEnabled = /\btchannel_dump\b/.test(process.env.NODE_DEBUG || '');

function TChannel(options) {
    if (!(this instanceof TChannel)) {
        return new TChannel(options);
    }

    var self = this;
    EventEmitter.call(self);

    self.options = extend({
        timeoutCheckInterval: 1000,
        timeoutFuzz: 100,
        // TODO: maybe we should always add pid to user-supplied?
        processName: format('%s[%s]', process.title, process.pid)
    }, options);

    self.options.requestDefaults = extend({
        timeout: TChannelRequest.defaultTimeout
    }, self.options.requestDefaults);

    self.logger = self.options.logger || nullLogger;
    self.random = self.options.random || globalRandom;
    self.timers = self.options.timers || globalTimers;

    // Filled in by the listen call:
    self.host = null;
    self.requestedPort = null;

    // Filled in by listening event:
    self.hostPort = null;

    // name of the service running over this channel
    self.serviceName = '';
    if (self.options.serviceName) {
        self.serviceName = self.options.serviceName;
        self.options.requestDefaults.serviceName = self.serviceName;
        delete self.options.serviceName;
    }

    // populated by makeSubChannel
    self.topChannel = null;
    self.subChannels = self.serviceName ? null : {};

    // how to handle incoming requests
    if (!self.options.handler) {
        if (!self.serviceName) {
            self.handler = TChannelServiceNameHandler(self);
        } else {
            self.handler = EndpointHandler(self.serviceName);
        }
    } else {
        self.handler = self.options.handler;
        delete self.options.handler;
    }

    // populated by:
    // - manually api (.peers.add etc)
    // - incoming connections on any listening socket
    self.peers = TChannelPeers(self, self.options);

    // TChannel advances through the following states.
    self.listened = false;
    self.listening = false;
    self.destroyed = false;

    if (self.options.trace) {
        self.tracer = new TracingAgent({
            logger: self.logger,
            forceTrace: self.options.forceTrace,
            serviceName: self.options.tracingServiceName,
            reporter: self.options.traceReporter
        });

        if (self.options.requestDefaults.trace !== false) {
            self.options.requestDefaults.trace = true;
        }
    }

    // lazily created by .getServer (usually from .listen)
    self.serverSocket = null;
    self.serverConnections = null;
}
inherits(TChannel, EventEmitter);

TChannel.prototype.getServer = function getServer() {
    var self = this;
    if (self.serverSocket) {
        return self.serverSocket;
    }

    self.serverConnections = Object.create(null);
    self.serverSocket = net.createServer(onServerSocketConnection);
    self.serverSocket.on('listening', onServerSocketListening);
    self.serverSocket.on('error', onServerSocketError);

    return self.serverSocket;

    function onServerSocketConnection(sock) {
        self.onServerSocketConnection(sock);
    }

    function onServerSocketListening() {
        self.onServerSocketListening();
    }

    function onServerSocketError(err) {
        self.onServerSocketError(err);
    }
};

TChannel.prototype.onServerSocketConnection = function onServerSocketConnection(sock) {
    var self = this;

    if (self.destroyed) {
        self.logger.error('got incoming socket whilst destroyed', {
            remoteAddr: sock.remoteAddr,
            remotePort: sock.remotePort,
            hostPort: self.hostPort
        });
        return;
    }

    var remoteAddr = sock.remoteAddress + ':' + sock.remotePort;
    var conn = new TChannelConnection(self, sock, 'in', remoteAddr);

    conn.on('span', function handleSpanFromConn(span) {
        self.tracer.report(span);
    });

    if (self.serverConnections[remoteAddr]) {
        var oldConn = self.serverConnections[remoteAddr];
        oldConn.resetAll(errors.SocketClosedError({
            reason: 'duplicate remoteAddr incoming conn'
        }));
        delete self.serverConnections[remoteAddr];
    }

    sock.on('close', onSocketClose);

    self.serverConnections[remoteAddr] = conn;
    self.emit('connection', conn);

    function onSocketClose() {
        delete self.serverConnections[remoteAddr];
    }
};

TChannel.prototype.onServerSocketListening = function onServerSocketListening() {
    var self = this;

    if (self.destroyed) {
        self.logger.error('got serverSocket listen whilst destroyed', {
            requestHostPort: self.host + ':' + self.requestedPort,
            hostPort: self.host + ':' + self.serverSocket.address().port
        });
        return;
    }

    var address = self.serverSocket.address();
    self.hostPort = self.host + ':' + address.port;
    self.listening = true;

    if (self.subChannels) {
        Object.keys(self.subChannels).forEach(function each(serviceName) {
            var chan = self.subChannels[serviceName];
            if (!chan.hostPort) {
                chan.hostPort = self.hostPort;
            }
        });
    }

    self.emit('listening');
};

TChannel.prototype.onServerSocketError = function onServerSocketError(err) {
    var self = this;

    if (err.code === 'EADDRINUSE') {
        err = errors.TChannelListenError(err, {
            requestedPort: self.requestedPort,
            host: self.host
        });
    }
    self.logger.error('server socket error', {
        err: err,
        requestedPort: self.requestedPort,
        host: self.host,
        hostPort: self.hostPort || null
    });
    self.emit('error', err);
};

TChannel.prototype.makeSubChannel = function makeSubChannel(options) {
    var self = this;
    if (!options) options = {};
    if (self.serviceName) {
        throw new Error('arbitrary-depth sub channels are unsupported'); // TODO typed error
    }
    if (!options.serviceName) {
        throw new Error('must specify serviceName'); // TODO typed error
    }
    if (self.subChannels[options.serviceName]) {
        throw new Error('sub channel already exists'); // TODO typed error
    }
    var opts = extend(self.options);
    var keys = Object.keys(options);
    for (var i = 0; i < keys.length; i++) {
        switch (keys[i]) {
            case 'peers':
                break;
            default:
                opts[keys[i]] = options[keys[i]];
        }
    }
    var chan = TChannel(opts);
    chan.topChannel = self;
    if (options.peers) {
        for (i = 0; i < options.peers.length; i++) {
            if (typeof options.peers[i] === 'string') {
                chan.peers.addPeer(self.peers.add(options.peers[i]));
            } else {
                chan.peers.addPeer(options.peers[i]);
            }
        }
    }
    self.subChannels[chan.serviceName] = chan;

    if (self.hostPort) {
        chan.hostPort = self.hostPort;
    }

    return chan;
};

TChannel.prototype.listen = function listen(port, host, callback) {
    var self = this;
    if (self.listened) {
        throw new Error('TChannel can only listen once'); // TODO typed error
    }
    if (typeof host !== 'string') {
        throw new Error('TChannel requires host argument'); // TODO typed error
    }
    if (typeof port !== 'number') {
        // Note that 0 is a valid port number, indicating that the system must
        // assign an available ephemeral port.
        throw new Error('TChannel must listen with numeric port'); // TODO typed error
    }
    // Does not expressly forbid 127.0.0.1 or localhost since these are valid
    // hosts for testing.
    if (host === '0.0.0.0') {
        throw new Error('TChannel must listen with externally visible host'); // TODO typed error
    }
    self.listened = true;
    self.requestedPort = port;
    self.host = host;
    self.getServer().listen(port, host, callback);
};

TChannel.prototype.register = function register(name, handler) {
    var self = this;

    var handlerType = self.handler && self.handler.type;

    switch (handlerType) {
        case 'tchannel.endpoint-handler':
            self.handler.register(name, handler);
            break;

        case 'tchannel.service-name-handler':
            throw errors.TopLevelRegisterError();

        default:
            throw errors.InvalidHandlerForRegister({
                handlerType: handlerType,
                handler: self.handler
            });
    }
};

TChannel.prototype.address = function address() {
    var self = this;
    if (self.serverSocket) {
        return self.serverSocket.address() || null;
    } else if (self.topChannel) {
        return self.topChannel.address();
    } else {
        return null;
    }
};

TChannel.prototype.request = function channelRequest(options) {
    var self = this;

    if (self.destroyed) {
        throw new Error('cannot request() to destroyed tchannel'); // TODO typed error
    }

    options = extend(self.options.requestDefaults, options);

    if (!options.service && options.serviceName) {
        options.service = options.serviceName;
    }

    if (!self.serviceName && !options.host) {
        if (options.service &&
            self.subChannels &&
            self.subChannels[options.service]) {
            return self.subChannels[options.service].request(options);
        } else {
            throw errors.TopLevelRequestError();
        }
    }

    var req = null;
    if (options.streamed) {
        req = self.peers.request(null, options);
    } else {
        req = new TChannelRequest(self, options);
    }
    self.emit('request', req);
    return req;
};

TChannel.prototype.quit = // to provide backward compatibility.
TChannel.prototype.close = function close(callback) {
    var self = this;

    if (self.destroyed) {
        throw new Error('double close'); // TODO typed error
    }

    self.destroyed = true;

    var counter = 1;

    if (self.serverSocket) {
        ++counter;
        if (self.serverSocket.address()) {
            closeServerSocket();
        } else {
            self.serverSocket.once('listening', closeServerSocket);
        }
    }

    if (self.serverConnections) {
        var incomingConns = Object.keys(self.serverConnections);
        for (var i = 0; i < incomingConns.length; i++) {
            ++counter;
            var incomingConn = self.serverConnections[incomingConns[i]];
            incomingConn.close(onClose);
        }
    }

    if (self.subChannels) {
        var serviceNames = Object.keys(self.subChannels);
        serviceNames.forEach(function each(serviceName) {
            var svcchan = self.subChannels[serviceName];
            if (!svcchan.destroyed) {
                counter++;
                svcchan.close(onClose);
            }
        });
    }

    self.peers.close(onClose);

    function closeServerSocket() {
        self.serverSocket.once('close', onClose);
        self.serverSocket.close();
    }

    function onClose() {
        if (--counter <= 0) {
            if (counter < 0) {
                self.logger.error('closed more channel sockets than expected', {
                    counter: counter
                });
            }
            if (typeof callback === 'function') {
                callback();
            }
        }
    }
};

module.exports = TChannel;
<|endoftext|>