<commit_before>function createPopup(url, dialogTitle) {
		$.get( url, function(data) {
				var d= $( "
").html(data).dialog({
						width:"auto",
						height:"auto",
						title: dialogTitle,
						position: {
								my:"center bottom",
								at:"center top+50%",
								of:window
						}
				});
		});
}

function toggleVisibility(objId) {
		if ($( objId ).is(":visible")) {
				$( objId).hide();
		} else {
				$( objId).show();
		}
}

function create3DScatterPlot(coordinatesID, labelsID, targetDiv) {
		var lines= $( "#"+coordinatesID ).html().split("\n");
		var labels= $( "#"+labelsID ).html().split("\n");
		data = [];
		for(var i=0;i<lines.length;i++) {
				str = lines[i].split(",");
				var tuple = {};
				var defineTuple = false;
				if (str.length > 0){
						tuple.x = parseFloat(str[0]);
						if (!isNaN(tuple.x)){
								defineTuple = true;
						}
				} else {
						tuple.x = 0.0;
				}
				if (str.length > 1){
						tuple.y = parseFloat(str[1]);
						defineTuple = true;
				} else {
						tuple.y = 0.0;
				}
				if (str.length > 2){
						tuple.z = parseFloat(str[2]);
						defineTuple = true;
				} else {
						tuple.z = 0.0;
				}
				if (defineTuple) {
						tuple.name = labels[i];
						tuple.scoreval= -1.0;
						data.push(tuple);
				}
		}
		var maxElem={x:"",y:"",z:""}, minElem = {x:"", y:"", z:""};
		for(var i=0;i<data.length;i++) {
				o = data[i]
				if (maxElem.x == "" || maxElem.x < o.x) {
						maxElem.x = o.x;
				}
				if (maxElem.y == "" || maxElem.y < o.y) {
						maxElem.y = o.y;
				}
				if (maxElem.z == "" || maxElem.z < o.z) {
						maxElem.z = o.z;
				}
				if (minElem.x == "" || minElem.x > o.x) {
						minElem.x = o.x;
				}
				if (minElem.y == "" || minElem.y > o.y) {
						minElem.y = o.y;
				}
				if (minElem.z == "" || minElem.z > o.z) {
						minElem.z = o.z;
				}

		}
		// Give the points a 3D feel by adding a radial gradient
		Highcharts.getOptions().colors = $.map(Highcharts.getOptions().colors, function (color) {
				return {
						radialGradient: {
								cx: 0.4,
								cy: 0.3,
								r: 0.5
						},
						stops: [
								[0, color],
								[1, Highcharts.Color(color).brighten(-0.2).get('rgb')]
						]
				};
		});

		// Set up the chart
		chart = new Highcharts.Chart({
				chart: {
						renderTo: targetDiv,
						margin: 100,
						type: 'scatter',
						options3d: {
								enabled: true,
								alpha: 10,
								beta: 30,
								depth: 800,
								viewDistance: 5,
								fitToPlot: false,
								frame: {
										bottom: { size: 1, color: 'rgba(0,0,0,0.02)' },
										back: { size: 1, color: 'rgba(0,0,0,0.04)' },
										side: { size: 1, color: 'rgba(0,0,0,0.06)' }
								}
						},
				},
				title: {
						text: 'Dataset space'
				},
				subtitle: {
						text: 'Click and drag the plot area to rotate in space'
				},
				tooltip: {
						pointFormatter: function(){
								var message = this.name+"
(";
								message +=parseFloat(this.x)+","
								message +=parseFloat(this.y)+","
								message +=parseFloat(this.z)+")"
								if(scores!=undefined && scores[this.name]!=undefined) {
										message+="
Operator score:"+parseFloat(scores[this.name]);
								}
								return message
						}
				},
				plotOptions: {
						scatter: {
								width: 10,
								height: 10,
								depth: 10
						},
						series: {
							turboThreshold: 5000
						}
				},
				yAxis: {
						title: {
								text : "PC2"
						}
				},
				xAxis: {
						title: {
								text : "PC1"
						},
						gridLineWidth: 1
				},
				zAxis: {
						title: {
								text : "PC3"
						},
						showFirstLabel: false
				},
				legend: {
						enabled: false
				},
				series: [{
						name: 'Dataset',
						colorByPoint: false,
						data : data
				}]
		});

		// Add mouse events for rotation
		$(chart.container).on('mousedown.hc touchstart.hc', function (eStart) {
				eStart = chart.pointer.normalize(eStart);

				var posX = eStart.pageX,
						posY = eStart.pageY,
						alpha = chart.options.chart.options3d.alpha,
						beta = chart.options.chart.options3d.beta,
						newAlpha,
						newBeta,
						sensitivity = 6; // lower is more sensitive

				$(document).on({
						'mousemove.hc touchdrag.hc': function (e) {
								// Run beta
								newBeta = beta + (posX - e.pageX) / sensitivity;
								chart.options.chart.options3d.beta = newBeta;

								// Run alpha
								newAlpha = alpha + (e.pageY - posY) / sensitivity;
								chart.options.chart.options3d.alpha = newAlpha;

								chart.redraw(false);
						},
						'mouseup touchend': function () {
								$(document).off('.hc');
						}
				});
		});
};

function colorizePoints(obj) {
		colScales = [[2,0,0],[2,1,0],[2,2,0],[0,2,0],[0,2,2],[0,1,2],[0,0,2],[0,0,0]].reverse();
		colorStep = 100;
		id = obj.value;
		if (id == "none") {
				// do nothing
				scores={}
				for(i=0;i<data.length;i++) {
						data[i].color = ""
				}
				chart.series[0].update({data:data});
				console.log($("#legend").html())
				$("#legend").remove();

				return;
		}
		$.get("/scores/"+id+"/text", function(d){
				scores={};
				lines = d.split("\n");
				minElem = undefined, maxElem =undefined;
				for(i=0;i<lines.length;i++) {
						arr = lines[i].split(":")
						var v =parseFloat(arr[1])
						scores [arr[0]] = v
						if (minElem == undefined || minElem > v) {
								minElem = v
						}
						if (maxElem == undefined || maxElem < v) {
								maxElem = v
						}
				}
				data = chart.series[0].data;
				colorRegions = [];
				for(i=0;i<data.length;i++) {
						s = scores[data[i].name]
						v = (s - minElem)/(maxElem-minElem)
						idx = Math.round(v*(colScales.length-1))
						c = colScales[idx]
						if (colorRegions[idx] == undefined) {
								colorRegions[idx] = {min: s, max:s, count:0}
						}
						if (colorRegions[idx].min > s) {
								colorRegions[idx].min = s
						}
						if (colorRegions[idx].max < s) {
								colorRegions[idx].max = s
						}
						colorRegions[idx].count  =colorRegions[idx].count+1
						if (c!=undefined ){
								r= c[0]*colorStep, g = c[1]*colorStep, b=c[2]*colorStep
								rgbString = "rgb("+parseInt(r)+","+parseInt(g)+","+parseInt(b)+")"
								data[i].color = rgbString
						}
				}
				legendDiv = "
\n";
				legendDiv = legendDiv+"
#	min	max	#points
"
				for(var i=0;i<colScales.length;i++) {
						if (c!=undefined ){
								c = colScales[i]
								r= c[0]*colorStep, g = c[1]*colorStep, b=c[2]*colorStep
								rgbString = "rgb("+parseInt(r)+","+parseInt(g)+","+parseInt(b)+")"
								if (colorRegions[i] == undefined) {
										legendDiv = legendDiv +
												"
"+
												""+parseInt(i+1)+"	"+
												"-	"+
												"-	"+
												"0	"+
												"
 ";

								} else {
										legendDiv = legendDiv +
												"
"+
												""+parseInt(i+1)+"	"+
												""+colorRegions[i].min.toFixed(2)+"	"+
												""+colorRegions[i].max.toFixed(2)+"	"+
												""+colorRegions[i].count+"	"+
												"
 ";
								}
						}
				}
				legendDiv = legendDiv + "
";
				$("

").dialog({
						width:"auto",
						height:"auto",
						title:"Color Legend",
						position: {
								my:"left top",
								at:"right top",
								of:$("#main"),
						}
				}).html(legendDiv).attr("id", "legend");
				chart.series[0].update({data:data});
		});
}

function createHeatmap(smID) {
		$.get(smID, function(d) {
				lines = d.split("\n")
				var data = []
				idx={}
				labels=[]
				dict = {}
				minVal=1.0;
				for (i=1;i<lines.length;i++) {
						arr = lines[i].split(",")
						if (arr[0]!=undefined && idx[arr[0]] == undefined && arr[0]!="") {
								key = arr[0], ix = Object.keys(idx).length
								idx[key] = ix
								labels[ix] = key
						}
						if ( arr[1]!=undefined && idx[arr[1]] == undefined && arr[1]!="") {
								key = arr[1], ix = Object.keys(idx).length
								idx[key] = ix
								labels[ix] = key
						}
						v = parseFloat(arr[2]);
						if (minVal>v) {
								minVal = v;
						}
						if(idx[arr[0]]!=undefined && idx[arr[1]]!=undefined) {
								if(dict[arr[0]] == undefined) {
										dict[arr[0]] = {}
								}
								dict[arr[0]][arr[1]]=v
								data.push([idx[arr[0]], idx[arr[1]], v])
						}
				}
				chart = Highcharts.chart('container', {
						chart: {
								type: 'heatmap',
								margin: [60, 10, 80, 50]
						},

						boost: {
								useGPUTranslations: true
						},

						title: {
								text: 'Similarity Matrix as a heatmap',
								align: 'left',
								x: 40
						},

						subtitle: {
								text: 'Similarity Matrix',
								align: 'left',
								x: 40
						},
						tooltip: {
								pointFormatter: function() {
										return labels[this.x]+","+labels[this.y]+":"+this.value
								}
						},

						xAxis: {
								labels: {
										formatter: function() {return labels[this.x]}
								}
						},

						yAxis: {
								labels: {
										formatter: function() {return labels[this.y];}
								},
								tickLength: 20
						},

						colorAxis: {
								stops: [
										[0, '#3060cf'],
										[0.5, '#fffbbc'],
										[0.9, '#c4463a'],
										[1, '#c4463a']
								],
								min: minVal,
								max: 1.0,
								startOnTick: true,
								endOnTick: true
						},

						series: [{
								data: data
						}]

				});
		});
};

function changeOrdering(mainDataset) {
		mainDataset=mainDataset.value
		ordered = labels;
		if (mainDataset == "" ) {
				ordered.sort()
		}else {
				ordered.sort(function(a,b){return dict[mainDataset][a] - dict[mainDataset][b]}).reverse()
		}
		newData = []
		for(i=0;i<labels.length;i++) {
				for(j=0;j<labels.length;j++) {
						newData.push([i,j,dict[ordered[i]][ordered[j]]])
				}
		}
		chart.series[0].update({data:newData});
}

function trackDataset(option) {
		var obj;
		var data = chart.series[0].data;
		for(var i=0;i<data.length;i++) {
				obj = data[i];
				obj.marker = null;
				if (data[i].name == option.value) {
						obj.marker = {
								enabled:true,
								radius : 15,
								fillColor: obj.color
						};
				}
		}
		if (obj!=undefined) {
				chart.series[0].update({data:data});
		}
}
<commit_msg>color highchart points on operator select.<commit_after>function createPopup(url, dialogTitle) {
		$.get( url, function(data) {
				var d= $( "
").html(data).dialog({
						width:"auto",
						height:"auto",
						title: dialogTitle,
						position: {
								my:"center bottom",
								at:"center top+50%",
								of:window
						}
				});
		});
}

function toggleVisibility(objId) {
		if ($( objId ).is(":visible")) {
				$( objId).hide();
		} else {
				$( objId).show();
		}
}

function create3DScatterPlot(coordinatesID, labelsID, targetDiv) {
		var lines= $( "#"+coordinatesID ).html().split("\n");
		var labels= $( "#"+labelsID ).html().split("\n");
		data = [];
		for(var i=0;i<lines.length;i++) {
				str = lines[i].split(",");
				var tuple = {};
				var defineTuple = false;
				if (str.length > 0){
						tuple.x = parseFloat(str[0]);
						if (!isNaN(tuple.x)){
								defineTuple = true;
						}
				} else {
						tuple.x = 0.0;
				}
				if (str.length > 1){
						tuple.y = parseFloat(str[1]);
						defineTuple = true;
				} else {
						tuple.y = 0.0;
				}
				if (str.length > 2){
						tuple.z = parseFloat(str[2]);
						defineTuple = true;
				} else {
						tuple.z = 0.0;
				}
				if (defineTuple) {
						tuple.name = labels[i];
						tuple.scoreval= -1.0;
						data.push(tuple);
				}
		}
		var maxElem={x:"",y:"",z:""}, minElem = {x:"", y:"", z:""};
		for(var i=0;i<data.length;i++) {
				o = data[i]
				if (maxElem.x == "" || maxElem.x < o.x) {
						maxElem.x = o.x;
				}
				if (maxElem.y == "" || maxElem.y < o.y) {
						maxElem.y = o.y;
				}
				if (maxElem.z == "" || maxElem.z < o.z) {
						maxElem.z = o.z;
				}
				if (minElem.x == "" || minElem.x > o.x) {
						minElem.x = o.x;
				}
				if (minElem.y == "" || minElem.y > o.y) {
						minElem.y = o.y;
				}
				if (minElem.z == "" || minElem.z > o.z) {
						minElem.z = o.z;
				}

		}
		// Give the points a 3D feel by adding a radial gradient
		Highcharts.getOptions().colors = $.map(Highcharts.getOptions().colors, function (color) {
				return {
						radialGradient: {
								cx: 0.4,
								cy: 0.3,
								r: 0.5
						},
						stops: [
								[0, color],
								[1, Highcharts.Color(color).brighten(-0.2).get('rgb')]
						]
				};
		});

		// Set up the chart
		chart = new Highcharts.Chart({
				chart: {
						renderTo: targetDiv,
						margin: 100,
						type: 'scatter',
						options3d: {
								enabled: true,
								alpha: 10,
								beta: 30,
								depth: 800,
								viewDistance: 5,
								fitToPlot: false,
								frame: {
										bottom: { size: 1, color: 'rgba(0,0,0,0.02)' },
										back: { size: 1, color: 'rgba(0,0,0,0.04)' },
										side: { size: 1, color: 'rgba(0,0,0,0.06)' }
								}
						},
				},
				title: {
						text: 'Dataset space'
				},
				subtitle: {
						text: 'Click and drag the plot area to rotate in space'
				},
				tooltip: {
						pointFormatter: function(){
								var message = this.name+"
(";
								message +=parseFloat(this.x)+","
								message +=parseFloat(this.y)+","
								message +=parseFloat(this.z)+")"
								if(scores!=undefined && scores[this.name]!=undefined) {
										message+="
Operator score:"+parseFloat(scores[this.name]);
								}
								return message
						}
				},
				plotOptions: {
						scatter: {
								width: 10,
								height: 10,
								depth: 10
						},
						series: {
							turboThreshold: 5000
						}
				},
				yAxis: {
						title: {
								text : "PC2"
						}
				},
				xAxis: {
						title: {
								text : "PC1"
						},
						gridLineWidth: 1
				},
				zAxis: {
						title: {
								text : "PC3"
						},
						showFirstLabel: false
				},
				legend: {
						enabled: false
				},
				series: [{
						name: 'Dataset',
						colorByPoint: false,
						data : data
				}]
		});

		// Add mouse events for rotation
		$(chart.container).on('mousedown.hc touchstart.hc', function (eStart) {
				eStart = chart.pointer.normalize(eStart);

				var posX = eStart.pageX,
						posY = eStart.pageY,
						alpha = chart.options.chart.options3d.alpha,
						beta = chart.options.chart.options3d.beta,
						newAlpha,
						newBeta,
						sensitivity = 6; // lower is more sensitive

				$(document).on({
						'mousemove.hc touchdrag.hc': function (e) {
								// Run beta
								newBeta = beta + (posX - e.pageX) / sensitivity;
								chart.options.chart.options3d.beta = newBeta;

								// Run alpha
								newAlpha = alpha + (e.pageY - posY) / sensitivity;
								chart.options.chart.options3d.alpha = newAlpha;

								chart.redraw(false);
						},
						'mouseup touchend': function () {
								$(document).off('.hc');
						}
				});
		});
};

function colorizePoints(obj) {
		colScales = [[2,0,0],[2,1,0],[2,2,0],[0,2,0],[0,2,2],[0,1,2],[0,0,2],[0,0,0]].reverse();
		colorStep = 100;
		id = obj.value;
		if (id == "none") {
				// do nothing
				scores={}
				for(i=0;i<data.length;i++) {
						data[i].color = ""
				}
				chart.addSeries({data:data});
				chart.series[1].destroy();
				$("#legend").remove();

				return;
		}
		$.get("/scores/"+id+"/text", function(d){
				scores={};
				lines = d.split("\n");
				minElem = undefined, maxElem =undefined;
				for(i=0;i<lines.length;i++) {
						arr = lines[i].split(":")
						var v =parseFloat(arr[1])
						scores [arr[0]] = v
						if (minElem == undefined || minElem > v) {
								minElem = v
						}
						if (maxElem == undefined || maxElem < v) {
								maxElem = v
						}
				}
				data = chart.series[0].data;
				colorRegions = [];
				for(i=0;i<data.length;i++) {
						s = scores[data[i].name]
						v = (s - minElem)/(maxElem-minElem)
						idx = Math.round(v*(colScales.length-1))
						c = colScales[idx]
						if (colorRegions[idx] == undefined) {
								colorRegions[idx] = {min: s, max:s, count:0}
						}
						if (colorRegions[idx].min > s) {
								colorRegions[idx].min = s
						}
						if (colorRegions[idx].max < s) {
								colorRegions[idx].max = s
						}
						colorRegions[idx].count  =colorRegions[idx].count+1
						if (c!=undefined ){
								r= c[0]*colorStep, g = c[1]*colorStep, b=c[2]*colorStep
								rgbString = "rgb("+parseInt(r)+","+parseInt(g)+","+parseInt(b)+")"
								data[i].color = rgbString
						}
				}
				legendDiv = "
\n";
				legendDiv = legendDiv+"
#	min	max	#points
"
				for(var i=0;i<colScales.length;i++) {
						if (c!=undefined ){
								c = colScales[i]
								r= c[0]*colorStep, g = c[1]*colorStep, b=c[2]*colorStep
								rgbString = "rgb("+parseInt(r)+","+parseInt(g)+","+parseInt(b)+")"
								if (colorRegions[i] == undefined) {
										legendDiv = legendDiv +
												"
"+
												""+parseInt(i+1)+"	"+
												"-	"+
												"-	"+
												"0	"+
												"
 ";

								} else {
										legendDiv = legendDiv +
												"
"+
												""+parseInt(i+1)+"	"+
												""+colorRegions[i].min.toFixed(2)+"	"+
												""+colorRegions[i].max.toFixed(2)+"	"+
												""+colorRegions[i].count+"	"+
												"
 ";
								}
						}
				}
				legendDiv = legendDiv + "
";
				$("

").dialog({
						width:"auto",
						height:"auto",
						title:"Color Legend",
						position: {
								my:"left top",
								at:"right top",
								of:$("#main"),
						}
				}).html(legendDiv).attr("id", "legend");
				chart.addSeries({data:data});
				chart.series[1].destroy();
		});
}

function createHeatmap(smID) {
		$.get(smID, function(d) {
				lines = d.split("\n")
				var data = []
				idx={}
				labels=[]
				dict = {}
				minVal=1.0;
				for (i=1;i<lines.length;i++) {
						arr = lines[i].split(",")
						if (arr[0]!=undefined && idx[arr[0]] == undefined && arr[0]!="") {
								key = arr[0], ix = Object.keys(idx).length
								idx[key] = ix
								labels[ix] = key
						}
						if ( arr[1]!=undefined && idx[arr[1]] == undefined && arr[1]!="") {
								key = arr[1], ix = Object.keys(idx).length
								idx[key] = ix
								labels[ix] = key
						}
						v = parseFloat(arr[2]);
						if (minVal>v) {
								minVal = v;
						}
						if(idx[arr[0]]!=undefined && idx[arr[1]]!=undefined) {
								if(dict[arr[0]] == undefined) {
										dict[arr[0]] = {}
								}
								dict[arr[0]][arr[1]]=v
								data.push([idx[arr[0]], idx[arr[1]], v])
						}
				}
				chart = Highcharts.chart('container', {
						chart: {
								type: 'heatmap',
								margin: [60, 10, 80, 50]
						},

						boost: {
								useGPUTranslations: true
						},

						title: {
								text: 'Similarity Matrix as a heatmap',
								align: 'left',
								x: 40
						},

						subtitle: {
								text: 'Similarity Matrix',
								align: 'left',
								x: 40
						},
						tooltip: {
								pointFormatter: function() {
										return labels[this.x]+","+labels[this.y]+":"+this.value
								}
						},

						xAxis: {
								labels: {
										formatter: function() {return labels[this.x]}
								}
						},

						yAxis: {
								labels: {
										formatter: function() {return labels[this.y];}
								},
								tickLength: 20
						},

						colorAxis: {
								stops: [
										[0, '#3060cf'],
										[0.5, '#fffbbc'],
										[0.9, '#c4463a'],
										[1, '#c4463a']
								],
								min: minVal,
								max: 1.0,
								startOnTick: true,
								endOnTick: true
						},

						series: [{
								data: data
						}]

				});
		});
};

function changeOrdering(mainDataset) {
		mainDataset=mainDataset.value
		ordered = labels;
		if (mainDataset == "" ) {
				ordered.sort()
		}else {
				ordered.sort(function(a,b){return dict[mainDataset][a] - dict[mainDataset][b]}).reverse()
		}
		newData = []
		for(i=0;i<labels.length;i++) {
				for(j=0;j<labels.length;j++) {
						newData.push([i,j,dict[ordered[i]][ordered[j]]])
				}
		}
		chart.series[0].update({data:newData});
}

function trackDataset(option) {
		var obj;
		var data = chart.series[0].data;
		for(var i=0;i<data.length;i++) {
				obj = data[i];
				obj.marker = null;
				if (data[i].name == option.value) {
						obj.marker = {
								enabled:true,
								radius : 15,
								fillColor: obj.color
						};
				}
		}
		if (obj!=undefined) {
				chart.series[0].update({data:data});
		}
}
<|endoftext|>


<commit_before>function initTask (subTask) {
   var state = {};
   var level;
   var answer = null;
   var data = {
      easy: {
         nbCastors: 3,
         solution: [8, 1, 3]
      },
      medium: {
         nbCastors: 4,
         solution: [9, 7, 2, 12]
      },
      hard: {
         nbCastors: 5,
         solution: [18, 21, 7, 4, 10]
      }
   };
   var castors;
   var containers;
   var nbCastors;
   var nbCells;
   var animWidth = 650;
   var animHeight = 350;
   var tailleLettreCastor = 24;
   var yMargin = 15;
   var cellSide;
   var width;
   var xGrid;
   var dxText;
   var dyText;
   var beaverInCell = [];
   var solution;

   subTask.loadLevel = function(curLevel) {
      level = curLevel;
      nbCastors = data[level].nbCastors;
      solution = data[level].solution;
      nbCells = nbCastors * nbCastors;
   };

   subTask.getStateObject = function() {
      return state;
   };

   subTask.reloadAnswerObject = function(answerObj) {
      answer = answerObj;
      if(answer){
         innerReloadAnswer();
      }
   };

   subTask.resetDisplay = function() {
      initDim();
      drawPaper();
      reloadAnswer();
      drawSolution();
   };

   subTask.getAnswerObject = function() {
      return answer;
   };

   subTask.getDefaultAnswerObject = function() {
      var defaultAnswer = [];
      for (var iCastor = 0; iCastor < nbCastors; iCastor++) {
         defaultAnswer[iCastor] = nbCells + iCastor;
      }
      return defaultAnswer;
   };

   subTask.unloadLevel = function(callback) {
      stopAnimation();
      callback();
   };

   function getResultAndMessage() {
      var result;
      if (answer.length != nbCastors) {
         result = { successRate: 0, message: taskStrings.placeAllBeaversOnCells };
      }else{
         var correct = true;
         var allInGrid = true;
         for (var iCastor = 0; iCastor < nbCastors; iCastor++) {
            allInGrid &= (answer[iCastor] < nbCells);
            correct &= (answer[iCastor] == solution[iCastor]);
          }
         if (! allInGrid) {
            result = { successRate: 0, message: taskStrings.placeAllBeaversOnCells };
         } else if (correct) {
            result = { successRate: 1, message: taskStrings.success };
         } else {
            result = { successRate: 0, message: taskStrings.failure };
         }
      }
      return result;
   };

   subTask.getGrade = function(callback) {
      callback(getResultAndMessage());
   };

   function initDim() {
      cellSide = Math.min(1000, (animHeight-2*yMargin)/nbCastors);
      if (Beav.Navigator.isIE8()) {
         dxText = cellSide / 2;
         dyText = cellSide / 2;
         width = cellSide;
      } else {
         width = cellSide*150/220;
         dxText = width + 5;
         dyText = 3*cellSide/4;
      }
      xGrid = 170 + cellSide;
   };

   var animToContainer = function(castor, container) {
      var x = container.attrs.x;
      var y = container.attrs.y;
      var anim1 = new Raphael.animation({x : x, y : y, 'transform' : ''}, 100);
      var anim2 = new Raphael.animation({x : x + dxText, y : y + dyText, 'transform' : ''}, 100);
      subTask.raphaelFactory.animate("anim1r",castor.r,anim1);
      subTask.raphaelFactory.animate("anim1b",castor.b,anim1);
      subTask.raphaelFactory.animate("anim2",castor.t,anim2);
   }

   var initDragDrop = function(castor) {
      var r = castor.r;
      var t = castor.t;
      var b = castor.b;
      var drag_move  = function (dx, dy) {
         if (isNaN(dx) || isNaN(dy)) {
            return;
         }
         r.attr({x: r.ox + dx, y: r.oy + dy, transform:''});
         t.attr({x: t.ox + dx, y: t.oy + dy, transform:''});
         b.attr({x: r.ox + dx, y: r.oy + dy, transform:''});
      }

      var drag_start  = function () {
         r.sx = r.ox = r.attrs.x;
         r.sy = r.oy = r.attrs.y;
         t.sx = t.ox = t.attrs.x;
         t.sy = t.oy = t.attrs.y;
         r.toFront();
         t.toFront();
         b.toFront();
      }

      var drag_end = function () {
         var origContainer = containers[answer[r.id]];
         var origCell = answer[r.id];
         for (var i=0; i < nbCells + nbCastors; i++) {
            if (i < nbCastors*nbCastors || i == nbCastors*nbCastors+r.id) {
               var dropContainer = containers[i];
               if (dropContainer.isPointInside(r.attrs.x + r.attrs.width/2, r.attrs.y + r.attrs.height/2)) {
                  if (i == origCell) {
                     for(var iCastor = 0; iCastor < nbCastors; iCastor++){ // IE8 bug fix
                        initDragDrop(castors[iCastor]);
                     }
                     return;
                  }
                  if (beaverInCell[i] != -1) {
                     var iCastor = beaverInCell[i];
                     var returnPos = nbCells + iCastor;
                     var returnContainer = containers[returnPos];
                     beaverInCell[returnPos] = iCastor;
                     answer[iCastor] = returnPos;
                     animToContainer(castors[iCastor], returnContainer);
                  }

                  beaverInCell[i] = r.id;
                  beaverInCell[origCell] = -1;
                  answer[r.id] = i;
                  animToContainer(castor, dropContainer);
                  displayHelper.stopShowingResult();
                  for(var iCastor = 0; iCastor < nbCastors; iCastor++){ // IE8 bug fix
                     initDragDrop(castors[iCastor]);
                  }
                  return;
               }
            }
         }
         beaverInCell[origCell] = -1;
         var returnPos = nbCells + r.id;
         var returnContainer = containers[returnPos];
         beaverInCell[returnPos] = r.id;
         answer[r.id] = returnPos;
         animToContainer(castor, returnContainer);
         for(var iCastor = 0; iCastor < nbCastors; iCastor++){ // IE8 bug fix
            initDragDrop(castors[iCastor]);
         }
      }
      b.drag(drag_move, drag_start, drag_end);
   }

   var stopAnimation = function() {
      subTask.raphaelFactory.stopAnimate("anim1r");
      subTask.raphaelFactory.stopAnimate("anim1b");
      subTask.raphaelFactory.stopAnimate("anim2");
   };

   var drawSolution = function() {
      var paperSolution = subTask.raphaelFactory.create('animSolution','animSolution', animHeight, animHeight)
      paperSolution.rect(0, 0, animHeight, animHeight).attr('fill','#D5F2FE');;
      for (var iLin = 0; iLin < nbCastors; iLin++) {
         for (var iCol = 0; iCol < nbCastors; iCol++) {
            var x = yMargin + iCol*cellSide;
            var y = iLin*cellSide + yMargin;
            paperSolution.rect(x, y, cellSide, cellSide);
            var iCastor = -1;
            var iCell = iLin * nbCastors + iCol;
            $.each(solution, function(iCastorX, iCellX) {
               if (iCell == iCellX) {
                  iCastor = iCastorX;
               }
            });
            if (iCastor != -1) {
              paperSolution.image("castor2.png", x, y, width, cellSide).attr('fill','gray');
              drawCastor(paperSolution, iCastor, x, y);
            }
         }
      }
   };

   var drawCastor = function(paper, iCastor, x, y) {
      var r;
      var t;
      var name = String.fromCharCode(65+iCastor);
      if (Beav.Navigator.isIE8()) {
         r = paper.rect(x, y, cellSide, cellSide).attr('fill', '#C0C0C0');
         t = paper.text(x + dxText, y + dyText, name).attr({"font-size": 24, "font-weight": "bold"});
      } else {
         r = paper.image("castor2.png", x, y, width, cellSide).attr('fill','gray');
         t = paper.text(x + dxText, y + dyText, name).attr({"font-size": tailleLettreCastor, "font-weight": "bold"});
      }
      var b = paper.rect(x, y, cellSide, cellSide).attr({'fill': '#FFFFFF', 'opacity': 0});
      return {r: r, t: t, b:b};
   }

   var drawPaper = function() {
      paper = subTask.raphaelFactory.create('anim','anim', animWidth, animHeight);
      paper.rect(0, 0, animWidth, animHeight).attr('fill','#D5F2FE');;
      paper.image("montagne.png", 1, animHeight-301, 100, 300);

      containers = [];
      for (var iLin = 0; iLin < nbCastors; iLin++) {
         for (var iCol = 0; iCol < nbCastors; iCol++) {
            containers[iLin * nbCastors + iCol] = paper.rect(xGrid + iCol*cellSide, iLin*cellSide + yMargin, cellSide, cellSide);
            beaverInCell[iLin * nbCastors + iCol] = -1;
         }
      }

      castors = [];
      for (var iCastor=0; iCastor < nbCastors; iCastor++) {
         var x = 115;
         var y = iCastor*cellSide + yMargin;
         var castorElems = drawCastor(paper, iCastor, x, y);
         var r = castorElems.r;
         var t = castorElems.t;
         containers[nbCastors*nbCastors + iCastor] = paper.rect(x, y, cellSide, cellSide).attr("stroke-dasharray", ". ");
         beaverInCell[nbCastors*nbCastors + iCastor] = iCastor;
         $(t.node).css({
            "-webkit-touch-callout": "none",
            "-webkit-user-select": "none",
            "-khtml-user-select": "none",
            "-moz-user-select": "none",
            "-ms-user-select": "none",
            "user-select": "none",
            "cursor" : "default"
         });
         r.id = iCastor;
         castors[iCastor] = castorElems;
         initDragDrop(castors[iCastor]);
      }
   };

   var innerReloadAnswer = function() {
      for (var iContainer = 0; iContainer < nbCells + nbCastors; iContainer++) {
         beaverInCell[iContainer] = -1;
      }
      for (var iCastor = 0; iCastor < nbCastors; iCastor++) {
         beaverInCell[answer[iCastor]] = iCastor;
      }
   }

   var reloadAnswer = function() {
      for (var iCastor = 0; iCastor < nbCastors; iCastor++) {
         var container = containers[answer[iCastor]];
         var castor = castors[iCastor];
         var x = container.attrs.x;
         var y = container.attrs.y;
         castor.r.attr({"x": x, "y": y});
         castor.b.attr({"x": x, "y": y});
         castor.t.attr({"x": x+dxText, "y": y+dyText});
      }
   };
};
initWrapper(initTask, ["easy", "medium", "hard"]);
displayHelper.useFullWidth();

<commit_msg>2014-SE-04-height-game: bug fix<commit_after>function initTask (subTask) {
   var state = {};
   var level;
   var answer = null;
   var data = {
      easy: {
         nbCastors: 3,
         solution: [8, 1, 3]
      },
      medium: {
         nbCastors: 4,
         solution: [9, 7, 2, 12]
      },
      hard: {
         nbCastors: 5,
         solution: [18, 21, 7, 4, 10]
      }
   };
   var castors;
   var containers;
   var nbCastors;
   var nbCells;
   var animWidth = 650;
   var animHeight = 350;
   var tailleLettreCastor = 24;
   var yMargin = 15;
   var cellSide;
   var width;
   var xGrid;
   var dxText;
   var dyText;
   var beaverInCell = [];
   var solution;

   subTask.loadLevel = function(curLevel) {
      level = curLevel;
      nbCastors = data[level].nbCastors;
      solution = data[level].solution;
      nbCells = nbCastors * nbCastors;
   };

   subTask.getStateObject = function() {
      return state;
   };

   subTask.reloadAnswerObject = function(answerObj) {
      answer = answerObj;
      if(answer){
         innerReloadAnswer();
      }
   };

   subTask.resetDisplay = function() {
      initDim();
      drawPaper();
      reloadAnswer();
      // drawSolution();
   };

   subTask.getAnswerObject = function() {
      return answer;
   };

   subTask.getDefaultAnswerObject = function() {
      var defaultAnswer = [];
      for (var iCastor = 0; iCastor < nbCastors; iCastor++) {
         defaultAnswer[iCastor] = nbCells + iCastor;
      }
      return defaultAnswer;
   };

   subTask.unloadLevel = function(callback) {
      stopAnimation();
      callback();
   };

   function getResultAndMessage() {
      var result;
      if (answer.length != nbCastors) {
         result = { successRate: 0, message: taskStrings.placeAllBeaversOnCells };
      }else{
         var correct = true;
         var allInGrid = true;
         for (var iCastor = 0; iCastor < nbCastors; iCastor++) {
            allInGrid &= (answer[iCastor] < nbCells);
            correct &= (answer[iCastor] == solution[iCastor]);
          }
         if (! allInGrid) {
            result = { successRate: 0, message: taskStrings.placeAllBeaversOnCells };
         } else if (correct) {
            result = { successRate: 1, message: taskStrings.success };
         } else {
            result = { successRate: 0, message: taskStrings.failure };
         }
      }
      return result;
   };

   subTask.getGrade = function(callback) {
      callback(getResultAndMessage());
   };

   function initDim() {
      cellSide = Math.min(1000, (animHeight-2*yMargin)/nbCastors);
      if (Beav.Navigator.isIE8()) {
         dxText = cellSide / 2;
         dyText = cellSide / 2;
         width = cellSide;
      } else {
         width = cellSide*150/220;
         dxText = width + 5;
         dyText = 3*cellSide/4;
      }
      xGrid = 170 + cellSide;
   };

   var animToContainer = function(castor, container) {
      var x = container.attrs.x;
      var y = container.attrs.y;
      var anim1 = new Raphael.animation({x : x, y : y, 'transform' : ''}, 100);
      var anim2 = new Raphael.animation({x : x + dxText, y : y + dyText, 'transform' : ''}, 100);
      subTask.raphaelFactory.animate("anim1r",castor.r,anim1);
      subTask.raphaelFactory.animate("anim1b",castor.b,anim1);
      subTask.raphaelFactory.animate("anim2",castor.t,anim2);
   }

   var initDragDrop = function(castor) {
      var r = castor.r;
      var t = castor.t;
      var b = castor.b;
      var drag_move  = function (dx, dy) {
         if (isNaN(dx) || isNaN(dy)) {
            return;
         }
         r.attr({x: r.ox + dx, y: r.oy + dy, transform:''});
         t.attr({x: t.ox + dx, y: t.oy + dy, transform:''});
         b.attr({x: r.ox + dx, y: r.oy + dy, transform:''});
      }

      var drag_start  = function () {
         r.sx = r.ox = r.attrs.x;
         r.sy = r.oy = r.attrs.y;
         t.sx = t.ox = t.attrs.x;
         t.sy = t.oy = t.attrs.y;
         r.toFront();
         t.toFront();
         b.toFront();
      }

      var drag_end = function () {
         var origContainer = containers[answer[r.id]];
         var origCell = answer[r.id];
         for (var i=0; i < nbCells + nbCastors; i++) {
            if (i < nbCastors*nbCastors || i == nbCastors*nbCastors+r.id) {
               var dropContainer = containers[i];
               if (dropContainer.isPointInside(r.attrs.x + r.attrs.width/2, r.attrs.y + r.attrs.height/2)) {
                  if (i == origCell) {
                     reinitDragDrop(); // IE8 bug fix
                     return;
                  }
                  if (beaverInCell[i] != -1) {
                     var iCastor = beaverInCell[i];
                     var returnPos = nbCells + iCastor;
                     var returnContainer = containers[returnPos];
                     beaverInCell[returnPos] = iCastor;
                     answer[iCastor] = returnPos;
                     animToContainer(castors[iCastor], returnContainer);
                  }

                  beaverInCell[i] = r.id;
                  beaverInCell[origCell] = -1;
                  answer[r.id] = i;
                  animToContainer(castor, dropContainer);
                  displayHelper.stopShowingResult();
                  reinitDragDrop(); // IE8 bug fix
                  return;
               }
            }
         }
         beaverInCell[origCell] = -1;
         var returnPos = nbCells + r.id;
         var returnContainer = containers[returnPos];
         beaverInCell[returnPos] = r.id;
         answer[r.id] = returnPos;
         animToContainer(castor, returnContainer);
         reinitDragDrop(); // IE8 bug fix
      }
      b.undrag();
      b.drag(drag_move, drag_start, drag_end);
   }

   function reinitDragDrop() {
      for(var iCastor = 0; iCastor < nbCastors; iCastor++){
         initDragDrop(castors[iCastor]);
      }
   };

   var stopAnimation = function() {
      subTask.raphaelFactory.stopAnimate("anim1r");
      subTask.raphaelFactory.stopAnimate("anim1b");
      subTask.raphaelFactory.stopAnimate("anim2");
   };

   var drawSolution = function() {
      var paperSolution = subTask.raphaelFactory.create('animSolution','animSolution', animHeight, animHeight)
      paperSolution.rect(0, 0, animHeight, animHeight).attr('fill','#D5F2FE');;
      for (var iLin = 0; iLin < nbCastors; iLin++) {
         for (var iCol = 0; iCol < nbCastors; iCol++) {
            var x = yMargin + iCol*cellSide;
            var y = iLin*cellSide + yMargin;
            paperSolution.rect(x, y, cellSide, cellSide);
            var iCastor = -1;
            var iCell = iLin * nbCastors + iCol;
            $.each(solution, function(iCastorX, iCellX) {
               if (iCell == iCellX) {
                  iCastor = iCastorX;
               }
            });
            if (iCastor != -1) {
              paperSolution.image("castor2.png", x, y, width, cellSide).attr('fill','gray');
              drawCastor(paperSolution, iCastor, x, y);
            }
         }
      }
   };

   var drawCastor = function(paper, iCastor, x, y) {
      var r;
      var t;
      var name = String.fromCharCode(65+iCastor);
      if (Beav.Navigator.isIE8()) {
         r = paper.rect(x, y, cellSide, cellSide).attr('fill', '#C0C0C0');
         t = paper.text(x + dxText, y + dyText, name).attr({"font-size": 24, "font-weight": "bold"});
      } else {
         r = paper.image("castor2.png", x, y, width, cellSide).attr('fill','gray');
         t = paper.text(x + dxText, y + dyText, name).attr({"font-size": tailleLettreCastor, "font-weight": "bold"});
      }
      var b = paper.rect(x, y, cellSide, cellSide).attr({'fill': '#FFFFFF', 'opacity': 0});
      return {r: r, t: t, b:b};
   }

   var drawPaper = function() {
      paper = subTask.raphaelFactory.create('anim','anim', animWidth, animHeight);
      paper.rect(0, 0, animWidth, animHeight).attr('fill','#D5F2FE');;
      paper.image("montagne.png", 1, animHeight-301, 100, 300);

      containers = [];
      for (var iLin = 0; iLin < nbCastors; iLin++) {
         for (var iCol = 0; iCol < nbCastors; iCol++) {
            containers[iLin * nbCastors + iCol] = paper.rect(xGrid + iCol*cellSide, iLin*cellSide + yMargin, cellSide, cellSide);
            beaverInCell[iLin * nbCastors + iCol] = -1;
         }
      }

      castors = [];
      for (var iCastor=0; iCastor < nbCastors; iCastor++) {
         var x = 115;
         var y = iCastor*cellSide + yMargin;
         var castorElems = drawCastor(paper, iCastor, x, y);
         var r = castorElems.r;
         var t = castorElems.t;
         containers[nbCastors*nbCastors + iCastor] = paper.rect(x, y, cellSide, cellSide).attr("stroke-dasharray", ". ");
         beaverInCell[nbCastors*nbCastors + iCastor] = iCastor;
         $(t.node).css({
            "-webkit-touch-callout": "none",
            "-webkit-user-select": "none",
            "-khtml-user-select": "none",
            "-moz-user-select": "none",
            "-ms-user-select": "none",
            "user-select": "none",
            "cursor" : "default"
         });
         r.id = iCastor;
         castors[iCastor] = castorElems;
         initDragDrop(castors[iCastor]);
      }
   };

   var innerReloadAnswer = function() {
      for (var iContainer = 0; iContainer < nbCells + nbCastors; iContainer++) {
         beaverInCell[iContainer] = -1;
      }
      for (var iCastor = 0; iCastor < nbCastors; iCastor++) {
         beaverInCell[answer[iCastor]] = iCastor;
      }
   }

   var reloadAnswer = function() {
      for (var iCastor = 0; iCastor < nbCastors; iCastor++) {
         var container = containers[answer[iCastor]];
         var castor = castors[iCastor];
         var x = container.attrs.x;
         var y = container.attrs.y;
         castor.r.attr({"x": x, "y": y});
         castor.b.attr({"x": x, "y": y});
         castor.t.attr({"x": x+dxText, "y": y+dyText});
      }
   };
};
initWrapper(initTask, ["easy", "medium", "hard"]);
displayHelper.useFullWidth();

<|endoftext|>


<commit_before>var D2R = Math.PI / 180;
var R2D = 180 / Math.PI;

var Coord = function(lon,lat) {
    this.lon = lon;
    this.lat = lat;
    this.x = D2R * lon;
    this.y = D2R * lat;
};

Coord.prototype.view = function() {
    return String(this.lon).slice(0, 4) + ',' + String(this.lat).slice(0, 4);
};

Coord.prototype.antipode = function() {

    var anti_lat = -1 * this.lat;
    if (this.lon < 0) {
        var anti_lon = 180 + this.lon;
    } else {
        var anti_lon = (180 - this.lon) * -1;
    }
    return new Coord(anti_lon, anti_lat);
};

var LineString = function() {
    this.coords = [];
    this.length = 0;
};

LineString.prototype.move_to = function(coord) {
    this.length++;
    this.coords.push(coord);
};

var Arc = function(properties) {
    this.properties = properties || {};
    this.geometries = []
};

Arc.prototype.json = function() {
    if (this.geometries.length <= 0) {
        return {'geometry': { 'type': 'LineString', 'coordinates': null },
                'type': 'Feature', 'properties': this.properties
               };
    } else if (this.geometries.length == 1) {
        return {'geometry': { 'type': 'LineString', 'coordinates': this.geometries[0].coords },
                'type': 'Feature', 'properties': this.properties
               };
    } else {
        var multiline = []
        for (i = 0; i < this.geometries.length; i++) {
            multiline.push(this.geometries[i].coords);
        }
        return {'geometry': { 'type': 'MultiLineString', 'coordinates': multiline },
                'type': 'Feature', 'properties': this.properties
               };
    }
};

// TODO - output proper multilinestring
Arc.prototype.wkt = function() {
    var wkt_string = '';
    for (i = 0; i < this.geometries.length; i++) {
        if (this.geometries[i].coords.length === 0) {
            return 'LINESTRING(empty)';
        } else {
            var wkt = 'LINESTRING(';
            this.geometries[i].coords.forEach(function(c,idx) {
                wkt += c[0] + ' ' + c[1] + ',';
            });
            wkt_string += wkt.substring(0, wkt.length - 1) + ')';
        }
    }
    return wkt_string;
};

/*
 * http://en.wikipedia.org/wiki/Great-circle_distance
 *
 */
var GreatCircle = function(start,end,properties) {

    this.start = start;
    this.end = end;
    this.properties = properties || {};

    var w = this.start.x - this.end.x;
    var h = this.start.y - this.end.y;
    var z = Math.pow(Math.sin(h / 2.0), 2) +
                Math.cos(this.start.y) *
                   Math.cos(this.end.y) *
                     Math.pow(Math.sin(w / 2.0), 2);
    this.g = 2.0 * Math.asin(Math.sqrt(z));

    if (this.g == Math.PI) {
        throw new Error('it appears ' + start.view() + ' and ' + end.view() + " are 'antipodal', e.g diametrically opposite, thus there is no single route but rather infinite");
    } else if (isNaN(this.g)) {
        throw new Error('could not calculate great circle between ' + start + ' and ' + end);
    }
};

/*
 * http://williams.best.vwh.net/avform.htm#Intermediate
 */
GreatCircle.prototype.interpolate = function(f) {
    var A = Math.sin((1 - f) * this.g) / Math.sin(this.g);
    var B = Math.sin(f * this.g) / Math.sin(this.g);
    var x = A * Math.cos(this.start.y) * Math.cos(this.start.x) + B * Math.cos(this.end.y) * Math.cos(this.end.x);
    var y = A * Math.cos(this.start.y) * Math.sin(this.start.x) + B * Math.cos(this.end.y) * Math.sin(this.end.x);
    var z = A * Math.sin(this.start.y) + B * Math.sin(this.end.y);
    var lat = R2D * Math.atan2(z, Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
    var lon = R2D * Math.atan2(y, x);
    return [lon, lat];
};

/*
 * Generate points along the great circle
 */
GreatCircle.prototype.Arc = function(npoints,options) {
    var first_pass = [];
    //var minx = 0;
    //var maxx = 0;
    if (npoints <= 2) {
        first_pass.push([this.start.lon, this.start.lat]);
        first_pass.push([this.end.lon, this.end.lat]);
    } else {
        var delta = 1.0 / (npoints - 1);
        for (var i = 0; i < npoints; i++) {
            var step = delta * i;
            var pair = this.interpolate(step);
            //minx = Math.min(minx,pair[0]);
            //maxx = Math.max(maxx,pair[0]);
            first_pass.push(pair);
        }
    }
    /* partial port of dateline handling from:
      gdal/ogr/ogrgeometryfactory.cpp

      TODO - does not handle all wrapping scenarios yet
    */
    var bHasBigDiff = false;
    var dfMaxSmallDiffLong = 0;
    for (var i = 1; i < first_pass.length; i++) {
        //if (minx > 170 && maxx > 180) {
        // }
        var dfPrevX = first_pass[i-1][0];
        var dfX = first_pass[i][0];
        var dfDiffLong = Math.abs(dfX - dfPrevX);
        if (dfDiffLong > 350 &&
            ((dfX > 170 && dfPrevX < -170) || (dfPrevX > 170 && dfX < -170))) {
            bHasBigDiff = true;
        } else if (dfDiffLong > dfMaxSmallDiffLong) {
            dfMaxSmallDiffLong = dfDiffLong;
        }
    }

    var poMulti = []

    if (bHasBigDiff && dfMaxSmallDiffLong < 10) {
        var poNewLS = []
        poMulti.push(poNewLS);
        for (var i = 0; i < first_pass.length; i++) {
            var dfX = parseFloat(first_pass[i][0]);
            if (i > 0 &&  Math.abs(dfX - first_pass[i-1][0]) > 350) {
                var dfX1 = parseFloat(first_pass[i-1][0]);
                var dfY1 = parseFloat(first_pass[i-1][1]);
                var dfX2 = parseFloat(first_pass[i][0]);
                var dfY2 = parseFloat(first_pass[i][1]);
                if (dfX1 > -180 && dfX1 < -170 && dfX2 == 180 &&
                    i+1 < first_pass.length &&
                   first_pass[i-1][0] > -180 && first_pass[i-1][0] < -170)
                {
                     poNewLS.push([-180, first_pass[i][1]]);
                     i++;
                     poNewLS.push([first_pass[i][0], first_pass[i][1]]);
                     continue;
                } else if (dfX1 > 170 && dfX1 < 180 && dfX2 == -180 &&
                     i+1 < first_pass.length &&
                     first_pass[i-1][0] > 170 && first_pass[i-1][0] < 180)
                {
                     poNewLS.push([180, first_pass[i][1]]);
                     i++;
                     poNewLS.push([first_pass[i][0], first_pass[i][1]]);
                     continue;
                }

                if (dfX1 < -170 && dfX2 > 170)
                {
                    // swap dfX1, dfX2
                    var tmpX = dfX1;
                    dfX1 = dfX2;
                    dfX2 = tmpX;
                    // swap dfY1, dfY2
                    var tmpY = dfY1;
                    dfY1 = dfY2;
                    dfY2 = tmpY;
                }
                if (dfX1 > 170 && dfX2 < -170) {
                    dfX2 += 360;
                }

                if (dfX1 <= 180 && dfX2 >= 180 && dfX1 < dfX2)
                {
                    var dfRatio = (180 - dfX1) / (dfX2 - dfX1);
                    var dfY = dfRatio * dfY2 + (1 - dfRatio) * dfY1;
                    poNewLS.push([first_pass[i-1][0] > 170 ? 180 : -180, dfY]);
                    poNewLS = [];
                    poNewLS.push([first_pass[i-1][0] > 170 ? -180 : 180, dfY]);
                    poMulti.push(poNewLS);
                }
                else
                {
                    poNewLS = [];
                    poMulti.push(poNewLS);
                }
                poNewLS.push([dfX, first_pass[i][1]]);
            } else {
                poNewLS.push([first_pass[i][0], first_pass[i][1]]);
            }
        }
    } else {
       // add normally
        var poNewLS = []
        poMulti.push(poNewLS);
        for (var i = 0; i < first_pass.length; i++) {
            poNewLS.push([first_pass[i][0],first_pass[i][1]]);
        }
    }

    var arc = new Arc(this.properties);
    for (var i = 0; i < poMulti.length; i++) {
        var line = new LineString();
        arc.geometries.push(line);
        var points = poMulti[i];
        for (var j = 0; j < points.length; j++) {
            line.move_to(points[j]);
        }
    }
    return arc;
};

if (typeof window === 'undefined') {
  // nodejs
  module.exports.Coord = Coord;
  module.exports.Arc = Arc;
  module.exports.GreatCircle = GreatCircle;

} else {
  // browser
  var arc = {};
  arc.Coord = Coord;
  arc.Arc = Arc;
  arc.GreatCircle = GreatCircle;
}
<commit_msg>handle no npoints arg<commit_after>var D2R = Math.PI / 180;
var R2D = 180 / Math.PI;

var Coord = function(lon,lat) {
    this.lon = lon;
    this.lat = lat;
    this.x = D2R * lon;
    this.y = D2R * lat;
};

Coord.prototype.view = function() {
    return String(this.lon).slice(0, 4) + ',' + String(this.lat).slice(0, 4);
};

Coord.prototype.antipode = function() {

    var anti_lat = -1 * this.lat;
    if (this.lon < 0) {
        var anti_lon = 180 + this.lon;
    } else {
        var anti_lon = (180 - this.lon) * -1;
    }
    return new Coord(anti_lon, anti_lat);
};

var LineString = function() {
    this.coords = [];
    this.length = 0;
};

LineString.prototype.move_to = function(coord) {
    this.length++;
    this.coords.push(coord);
};

var Arc = function(properties) {
    this.properties = properties || {};
    this.geometries = []
};

Arc.prototype.json = function() {
    if (this.geometries.length <= 0) {
        return {'geometry': { 'type': 'LineString', 'coordinates': null },
                'type': 'Feature', 'properties': this.properties
               };
    } else if (this.geometries.length == 1) {
        return {'geometry': { 'type': 'LineString', 'coordinates': this.geometries[0].coords },
                'type': 'Feature', 'properties': this.properties
               };
    } else {
        var multiline = []
        for (i = 0; i < this.geometries.length; i++) {
            multiline.push(this.geometries[i].coords);
        }
        return {'geometry': { 'type': 'MultiLineString', 'coordinates': multiline },
                'type': 'Feature', 'properties': this.properties
               };
    }
};

// TODO - output proper multilinestring
Arc.prototype.wkt = function() {
    var wkt_string = '';
    for (i = 0; i < this.geometries.length; i++) {
        if (this.geometries[i].coords.length === 0) {
            return 'LINESTRING(empty)';
        } else {
            var wkt = 'LINESTRING(';
            this.geometries[i].coords.forEach(function(c,idx) {
                wkt += c[0] + ' ' + c[1] + ',';
            });
            wkt_string += wkt.substring(0, wkt.length - 1) + ')';
        }
    }
    return wkt_string;
};

/*
 * http://en.wikipedia.org/wiki/Great-circle_distance
 *
 */
var GreatCircle = function(start,end,properties) {

    this.start = start;
    this.end = end;
    this.properties = properties || {};

    var w = this.start.x - this.end.x;
    var h = this.start.y - this.end.y;
    var z = Math.pow(Math.sin(h / 2.0), 2) +
                Math.cos(this.start.y) *
                   Math.cos(this.end.y) *
                     Math.pow(Math.sin(w / 2.0), 2);
    this.g = 2.0 * Math.asin(Math.sqrt(z));

    if (this.g == Math.PI) {
        throw new Error('it appears ' + start.view() + ' and ' + end.view() + " are 'antipodal', e.g diametrically opposite, thus there is no single route but rather infinite");
    } else if (isNaN(this.g)) {
        throw new Error('could not calculate great circle between ' + start + ' and ' + end);
    }
};

/*
 * http://williams.best.vwh.net/avform.htm#Intermediate
 */
GreatCircle.prototype.interpolate = function(f) {
    var A = Math.sin((1 - f) * this.g) / Math.sin(this.g);
    var B = Math.sin(f * this.g) / Math.sin(this.g);
    var x = A * Math.cos(this.start.y) * Math.cos(this.start.x) + B * Math.cos(this.end.y) * Math.cos(this.end.x);
    var y = A * Math.cos(this.start.y) * Math.sin(this.start.x) + B * Math.cos(this.end.y) * Math.sin(this.end.x);
    var z = A * Math.sin(this.start.y) + B * Math.sin(this.end.y);
    var lat = R2D * Math.atan2(z, Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
    var lon = R2D * Math.atan2(y, x);
    return [lon, lat];
};

/*
 * Generate points along the great circle
 */
GreatCircle.prototype.Arc = function(npoints,options) {
    var first_pass = [];
    //var minx = 0;
    //var maxx = 0;
    if (!npoints || npoints <= 2) {
        first_pass.push([this.start.lon, this.start.lat]);
        first_pass.push([this.end.lon, this.end.lat]);
    } else {
        var delta = 1.0 / (npoints - 1);
        for (var i = 0; i < npoints; i++) {
            var step = delta * i;
            var pair = this.interpolate(step);
            //minx = Math.min(minx,pair[0]);
            //maxx = Math.max(maxx,pair[0]);
            first_pass.push(pair);
        }
    }
    /* partial port of dateline handling from:
      gdal/ogr/ogrgeometryfactory.cpp

      TODO - does not handle all wrapping scenarios yet
    */
    var bHasBigDiff = false;
    var dfMaxSmallDiffLong = 0;
    for (var i = 1; i < first_pass.length; i++) {
        //if (minx > 170 && maxx > 180) {
        // }
        var dfPrevX = first_pass[i-1][0];
        var dfX = first_pass[i][0];
        var dfDiffLong = Math.abs(dfX - dfPrevX);
        if (dfDiffLong > 350 &&
            ((dfX > 170 && dfPrevX < -170) || (dfPrevX > 170 && dfX < -170))) {
            bHasBigDiff = true;
        } else if (dfDiffLong > dfMaxSmallDiffLong) {
            dfMaxSmallDiffLong = dfDiffLong;
        }
    }

    var poMulti = []

    if (bHasBigDiff && dfMaxSmallDiffLong < 10) {
        var poNewLS = []
        poMulti.push(poNewLS);
        for (var i = 0; i < first_pass.length; i++) {
            var dfX = parseFloat(first_pass[i][0]);
            if (i > 0 &&  Math.abs(dfX - first_pass[i-1][0]) > 350) {
                var dfX1 = parseFloat(first_pass[i-1][0]);
                var dfY1 = parseFloat(first_pass[i-1][1]);
                var dfX2 = parseFloat(first_pass[i][0]);
                var dfY2 = parseFloat(first_pass[i][1]);
                if (dfX1 > -180 && dfX1 < -170 && dfX2 == 180 &&
                    i+1 < first_pass.length &&
                   first_pass[i-1][0] > -180 && first_pass[i-1][0] < -170)
                {
                     poNewLS.push([-180, first_pass[i][1]]);
                     i++;
                     poNewLS.push([first_pass[i][0], first_pass[i][1]]);
                     continue;
                } else if (dfX1 > 170 && dfX1 < 180 && dfX2 == -180 &&
                     i+1 < first_pass.length &&
                     first_pass[i-1][0] > 170 && first_pass[i-1][0] < 180)
                {
                     poNewLS.push([180, first_pass[i][1]]);
                     i++;
                     poNewLS.push([first_pass[i][0], first_pass[i][1]]);
                     continue;
                }

                if (dfX1 < -170 && dfX2 > 170)
                {
                    // swap dfX1, dfX2
                    var tmpX = dfX1;
                    dfX1 = dfX2;
                    dfX2 = tmpX;
                    // swap dfY1, dfY2
                    var tmpY = dfY1;
                    dfY1 = dfY2;
                    dfY2 = tmpY;
                }
                if (dfX1 > 170 && dfX2 < -170) {
                    dfX2 += 360;
                }

                if (dfX1 <= 180 && dfX2 >= 180 && dfX1 < dfX2)
                {
                    var dfRatio = (180 - dfX1) / (dfX2 - dfX1);
                    var dfY = dfRatio * dfY2 + (1 - dfRatio) * dfY1;
                    poNewLS.push([first_pass[i-1][0] > 170 ? 180 : -180, dfY]);
                    poNewLS = [];
                    poNewLS.push([first_pass[i-1][0] > 170 ? -180 : 180, dfY]);
                    poMulti.push(poNewLS);
                }
                else
                {
                    poNewLS = [];
                    poMulti.push(poNewLS);
                }
                poNewLS.push([dfX, first_pass[i][1]]);
            } else {
                poNewLS.push([first_pass[i][0], first_pass[i][1]]);
            }
        }
    } else {
       // add normally
        var poNewLS = []
        poMulti.push(poNewLS);
        for (var i = 0; i < first_pass.length; i++) {
            poNewLS.push([first_pass[i][0],first_pass[i][1]]);
        }
    }

    var arc = new Arc(this.properties);
    for (var i = 0; i < poMulti.length; i++) {
        var line = new LineString();
        arc.geometries.push(line);
        var points = poMulti[i];
        for (var j = 0; j < points.length; j++) {
            line.move_to(points[j]);
        }
    }
    return arc;
};

if (typeof window === 'undefined') {
  // nodejs
  module.exports.Coord = Coord;
  module.exports.Arc = Arc;
  module.exports.GreatCircle = GreatCircle;

} else {
  // browser
  var arc = {};
  arc.Coord = Coord;
  arc.Arc = Arc;
  arc.GreatCircle = GreatCircle;
}
<|endoftext|>


<commit_before>/*
==================================================================================================
  Jasy - JavaScript Tooling Refined
  Copyright 2010-2011 Sebastian Werner
==================================================================================================
*/

/**
 * Some utilities to work with properties
 */
Module("jasy.property.Util",
{
	/**
	 * Returns the definition of the given property. Returns null
	 * if the property does not exist.
	 *
	 * @param clazz {Class} class to check
	 * @param name {String} name of the event to check for
	 * @return {Map|null} whether the object support the given event.
	 */
	getPropertyDefinition : function(clazz, name)
	{
		var props;
		while (clazz)
		{
			props = clazz.$$properties;
			if (props && props[name]) {
				return props[name];
			}

			clazz = clazz.superclass;
		}

		return null;
	},

	/**
	 * Whether a class has the given property
	 *
	 * @param clazz {Class} class to check
	 * @param name {String} name of the property to check for
	 * @return {Boolean} whether the class includes the given property.
	 */
	hasProperty : function(clazz, name) {
		return !!this.getPropertyDefinition(clazz, name);
	},

	/**
	 * Returns a list of all properties supported by the given class
	 *
	 * @param clazz {Class} Class to query
	 * @return {String[]} List of all property names
	 */
	getProperties : function(clazz)
	{
		var list = [];

		while (clazz)
		{
			if (clazz.$$properties) {
				list.push.apply(list, qx.Bootstrap.getKeys(clazz.$$properties));
			}

			clazz = clazz.superclass;
		}

		return list;
	},

	/**
	 * Returns the class or one of its superclasses which contains the
	 * declaration for the given property in its class definition. Returns null
	 * if the property is not specified anywhere.
	 *
	 * @param clazz {Class} class to look for the property
	 * @param name {String} name of the property
	 * @return {Class | null} The class which includes the property
	 */
	getByProperty : function(clazz, name)
	{
		while (clazz)
		{
			if (clazz.$$properties && clazz.$$properties[name]) {
				return clazz;
			}

			clazz = clazz.superclass;
		}

		return null;
	}
});<commit_msg>Makes no sense in conjunction with other jasy stuff<commit_after><|endoftext|>


<commit_before>'use strict';

var User = require('../models/users');
var Poll = require('../models/polls');

//var path = __dirname;
var path = process.cwd();
//var ClickHandler = require(path + '/app/controllers/clickHandler.server.js');
var PollHandler = require(path + '/app/controllers/pollHandler.server.js');

module.exports = function (app, passport) {

	function isLoggedIn (req, res, next) {
		if (req.isAuthenticated()) {
			return next();
		} else {
			res.render('login');
		}
	}

	//var clickHandler = new ClickHandler();
	var pollHandler = new PollHandler();

	app.route('/')
		.get(function (req, res) {
			console.log(req.params);
			Poll.find({}, {}, { sort: { 'created_at' : -1 } }, function(err, poll) {
				console.log(poll);
				res.render('index',{poll:poll});
			})
		});

	app.route('/login')
		.get(function (req, res) {
			console.log(req.params);
			Poll.find({}, {}, { sort: { 'created_at' : -1 } }, function(err, poll) {
				console.log(poll);
			res.render('login',{poll:poll, layout:'loggedout'});
			})
		});

	/*app.route('/poll')
		.get(isLoggedIn, function (req, res) {
			console.log(req.params);
			User.findOne({"twitter.username":req.params.id}, function(err, user) {
				res.render('poll');
			})
		});*/

	app.route('/logout')
		.get(function (req, res) {
			req.logout();
			res.redirect('/login');
		});

	app.route('/profile/:id')
		.get(isLoggedIn, function (req, res) {
			console.log(req.params);
			User.findOne({"twitter.username":req.params.id}, function(err, user) {
				console.log(user);
				res.render('profile',{user:user, time:Date.now()});
			})
		});

	app.route('/createpoll')
		.get(isLoggedIn, function (req, res) {
			console.log(req.params);
			User.findOne({"twitter.username":req.params.id}, function(err, user) {
				res.render('createpoll');
			})
		});

	app.route('/profile')
		.get(isLoggedIn, function (req, res) {
			res.render("profile",{user:req.user});
		});

	app.route('/poll/:id')
		.get(function (req, res) {
			Poll.findOne({"_id":req.params.id}, function(err, poll){
				console.log(poll);
				res.render("poll",{poll:poll});
			})
		});

	app.route('/profile/:id')
		.delete(function (req, res) {
			Poll.findOne({"_id":req.params.id}, function(err, poll){
				poll.remove();
				res.render("profile",{user:req.user});
			})
		});

	app.route('/auth/github')
		.get(passport.authenticate('github'));

	app.route('/auth/github/callback')
		.get(passport.authenticate('github', {
			successRedirect: '/',
			failureRedirect: '/login'
		}));

	app.route('/auth/twitter')
		.get(passport.authenticate('twitter'));

	app.route('/auth/twitter/callback')
		.get(passport.authenticate('twitter', {
			successRedirect: '/',
			failureRedirect: '/login'
		}));

	/*app.route('/api/:id/clicks')
		.get(isLoggedIn, clickHandler.getClicks)
		.post(isLoggedIn, clickHandler.addClick)
		.delete(isLoggedIn, clickHandler.resetClicks);*/

	app.route('/createpoll')
		.post(pollHandler.addPoll);

	app.route('/success')
		.get(function (req, res) {
		//console.dir(req.body);
		res.render('success');
		});
//agasg

};
<commit_msg>displaying polls<commit_after>'use strict';

var User = require('../models/users');
var Poll = require('../models/polls');

//var path = __dirname;
var path = process.cwd();
//var ClickHandler = require(path + '/app/controllers/clickHandler.server.js');
var PollHandler = require(path + '/app/controllers/pollHandler.server.js');

module.exports = function (app, passport) {

	function isLoggedIn (req, res, next) {
		if (req.isAuthenticated()) {
			return next();
		} else {
			res.render('login');
		}
	}

	//var clickHandler = new ClickHandler();
	var pollHandler = new PollHandler();

	app.route('/')
		.get(function (req, res) {
			console.log(req.params);
			Poll.find({}, {}, { sort: { 'created_at' : -1 } }, function(err, poll) {
				console.log(poll);
				res.render('index',{poll:poll});
			})
		});

	app.route('/login')
		.get(function (req, res) {
			console.log(req.params);
			Poll.find({}, {}, { sort: { 'created_at' : -1 } }, function(err, poll) {
				console.log(poll);
			res.render('login',{poll:poll, layout:'loggedout'});
			})
		});

	/*app.route('/poll')
		.get(isLoggedIn, function (req, res) {
			console.log(req.params);
			User.findOne({"twitter.username":req.params.id}, function(err, user) {
				res.render('poll');
			})
		});*/

	app.route('/logout')
		.get(function (req, res) {
			req.logout();
			res.redirect('/login');
		});

	app.route('/profile/:id')
		.get(isLoggedIn, function (req, res) {
			console.log(req.params);
			User.findOne({"twitter.username":req.params.id}, function(err, user) {
				console.log(user);
				res.render('profile',{user:user, time:Date.now()});
			})
		});

	app.route('/createpoll')
		.get(isLoggedIn, function (req, res) {
			console.log(req.params);
			User.findOne({"twitter.username":req.params.id}, function(err, user) {
				res.render('createpoll');
			})
		});

	app.route('/profile')
		.get(isLoggedIn, function (req, res) {
			res.render("profile",{user:req.user});
		});

	app.route('/poll/:id')
		.get(function (req, res) {
			Poll.findOne({"_id":req.params.id}, function(err, poll){
				console.log(poll);
				res.render("poll",{poll:poll});
			})
		});

	app.route('/profile/:id')
		.delete(function (req, res) {
			console.log(req);
			Poll.findOne({"_id":req.params.id}, function(err, poll){
				poll.remove();
				res.render("profile",{user:req.user});
			})
		});

	app.route('/auth/github')
		.get(passport.authenticate('github'));

	app.route('/auth/github/callback')
		.get(passport.authenticate('github', {
			successRedirect: '/',
			failureRedirect: '/login'
		}));

	app.route('/auth/twitter')
		.get(passport.authenticate('twitter'));

	app.route('/auth/twitter/callback')
		.get(passport.authenticate('twitter', {
			successRedirect: '/',
			failureRedirect: '/login'
		}));

	/*app.route('/api/:id/clicks')
		.get(isLoggedIn, clickHandler.getClicks)
		.post(isLoggedIn, clickHandler.addClick)
		.delete(isLoggedIn, clickHandler.resetClicks);*/

	app.route('/createpoll')
		.post(pollHandler.addPoll);

	app.route('/success')
		.get(function (req, res) {
		//console.dir(req.body);
		res.render('success');
		});
//agasg

};
<|endoftext|>


<commit_before>'use babel';
'use strict';

import { Client } from 'discord.js';
import LocalStorage from '../storage/LocalStorage';
import GuildStorageLoader from '../storage/GuildStorageLoader';
import GuildStorageRegistry from '../storage/GuildStorageRegistry';
import CommandLoader from '../command/CommandLoader';
import CommandRegistry from '../command/CommandRegistry';
import CommandDispatcher from '../command/CommandDispatcher';

/**
 * The Discord.js Client instance. Contains bot-specific [storage]{@link Bot#storage},
 * guild specific [storages]{@link Bot#guildStorages}, and contains important
 * fields for access within commands
 * @class Bot
 * @extends {external:Client}
 * @param {BotOptions} botOptions - Object containing required bot properties
 * @param {external:ClientOptions} [clientOptions] - Discord.js ClientOptions
 */
export default class Bot extends Client
{
	constructor(botOptions = null, clientOptions)
	{
		super(clientOptions);

		/** @type {string} */
		this._token = botOptions.token;

		/**
		 * The name of the Bot
		 * @memberof Bot
		 * @type {string}
		 * @name name
		 * @instance
		 */
		this.name = botOptions.name || 'botname';

		/**
		 * Directory to find command class files. Optional
		 * if bot is passive. See: {@link Bot#passive}
		 * @memberof Bot
		 * @type {string}
		 * @name commandsDir
		 * @instance
		 */
		this.commandsDir = botOptions.commandsDir || null;

		/**
		 * Status text for the bot
		 * @memberof Bot
		 * @type {?string}
		 * @name statusText
		 * @instance
		 */
		this.statusText = botOptions.statusText || null;

		/**
		 * Text to output when the bot is ready
		 * @memberof Bot
		 * @type {string}
		 * @name readyText
		 * @instance
		 */
		this.readyText = botOptions.readyText || 'Ready!';

		/**
		 * Whether or not a generic 'command not found' message
		 * should be given in DMs to instruct the user to
		 * use the `help` command. Set to false to disable
		 * this message
		 * @name Bot#noCommandErr
		 * @type {string}
		 * @instance
		 */
		this.noCommandErr = botOptions.noCommandErr === undefined ? true : botOptions.noCommandErr;

		/**
		 * Whether or not the bot is a selfbot
		 * @memberof Bot
		 * @type {boolean}
		 * @name selfbot
		 * @instance
		 */
		this.selfbot = botOptions.selfbot || false;

		/**
		 * Whether or not this bot is passive. Passive bots
		 * will not register a command dispatcher or a message
		 * listener. This allows passive bots to be created that
		 * do not respond to any commands but are able to perform
		 * actions based on whatever the framework user wants
		 * @memberof Bot
		 * @type {boolean}
		 * @name passive
		 * @instance
		 */
		this.passive = botOptions.passive || false;

		/**
		 * Bot version, best taken from package.json
		 * @memberof Bot
		 * @type {string}
		 * @name version
		 * @instance
		 */
		this.version = botOptions.version || '0.0.0';

		/**
		 * Object containing token and owner ids
		 * @memberof Bot
		 * @type {Object}
		 * @name config
		 * @instance
		 * @property {string} token - Discord login token for the bot
		 * @property {string[]} owner - Array of owner id strings
		 */
		this.config = botOptions.config || null;

		/**
		 * Array of base command names to skip when loading commands. Base commands
		 * may only be disabled by name, not by alias
		 * @memberof Bot
		 * @type {string[]}
		 * @name disableBase
		 * @instance
		 */
		this.disableBase = botOptions.disableBase || [];

		/** @type {LocalStorage} */
		this._guildDataStorage = new LocalStorage('storage/guild-storage');

		/** @type {LocalStorage} */
		this._guildSettingStorage = new LocalStorage('storage/guild-settings');

		/** @type {GuildStorageLoader} */
		this._guildStorageLoader = new GuildStorageLoader(this);

		/** @type {CommandLoader} */
		this._commandLoader = new CommandLoader(this);

		/**
		 * Bot-specific storage
		 * @memberof Bot
		 * @type {LocalStorage}
		 * @name storage
		 * @instance
		 */
		this.storage = new LocalStorage('storage/bot-storage');

		/**
		 * [Collection]{@link external:Collection} containing all GuildStorage instances
		 * @memberof Bot
		 * @type {GuildStorageRegistry<string, GuildStorage>}
		 * @name guildStorages
		 * @instance
		 */
		this.guildStorages = new GuildStorageRegistry();

		/**
		 * [Collection]{@link external:Collection} containing all loaded commands
		 * @memberof Bot
		 * @type {CommandRegistry<string, Command>}
		 * @name commands
		 * @instance
		 */
		this.commands = new CommandRegistry();

		/**
		 * @typedef {Object} DefaultGuildSettings - The default settings to apply to new guilds.
		 * Stored under the key 'defaultGuildSettings' in {@link Bot#storage}
		 * @property {string} prefix='/' - Prefix to prepend commands
		 * @property {Array} [disabledGroups=[]] - Command groups to ignore
		 */

		// Load defaultGuildSettings into storage the first time the bot is run
		if (!this.storage.exists('defaultGuildSettings')) // eslint-disable-line curly
			this.storage.setItem('defaultGuildSettings',
				require('../storage/defaultGuildSettings.json'));

		/** @type {CommandDispatcher} */
		this._dispatcher = new CommandDispatcher(this);

		// Make some asserts
		if (!this._token) throw new Error('You must provide a token for the bot.');
		if (!this.commandsDir && !this.passive) throw new Error('You must provide a directory to load commands from via commandDir');
		if (!this.config) throw new Error('You must provide a config containing token and owner ids.');

		// Load commands
		if (!this.passive) this.loadCommand('all');
	}

	/**
	 * Loads/reloads all/specific commands
	 * @memberof Bot
	 * @instance
	 * @param {string} command - The name of a command to reload, or 'all' to load all commands
	 */
	loadCommand(command)
	{
		if (!command) throw new Error(`You must provide a command name to load, or 'all' to load all commands`);
		if (command === 'all') this._commandLoader.loadCommands();
		else this._commandLoader.reloadCommand(command);
	}

	/**
	 * Logs the Bot in and registers some event handlers
	 * @memberof Bot
	 * @instance
	 * @returns {Bot}
	 */
	start()
	{
		this.login(this._token);

		this.once('ready', () =>
		{
			console.log(this.readyText); // eslint-disable-line no-console
			this.user.setGame(this.statusText);

			// Load all guild storages
			this._guildStorageLoader.loadStorages(this._guildDataStorage, this._guildSettingStorage);
		});

		this.on('guildCreate', () =>
		{
			this._guildStorageLoader.initNewGuilds(this._guildDataStorage, this._guildSettingStorage);
		});

		this.on('guildDelete', (guild) =>
		{
			this.guildStorages.delete(guild.id);
			this._guildDataStorage.removeItem(guild.id);
			this._guildSettingStorage.removeItem(guild.id);
		});

		return this;
	}

	/**
	 * Set the value of a default setting key and push it to all guild
	 * setting storages. Will not overwrite a setting in guild settings
	 * storage if there is already an existing key with the given value
	 * @memberof Bot
	 * @instance
	 * @param {string} key - The key to use in settings storage
	 * @param {string} value - The value to use in settings storage
	 * @returns {Bot}
	 */
	setDefaultSetting(key, value)
	{
		this.storage.setItem(`defaultGuildSettings/${key}`, value);
		this.guildStorages.forEach(guild =>
		{
			if (!guild.settingExists(key)) guild.setSetting(key, value);
		});
		return this;
	}

	/**
	 * Remove a defaultGuildSettings item. Will not remove from ALL guild
	 * settings, but will prevent the item from being added to new guild
	 * settings storage upon creation
	 * @memberof Bot
	 * @instance
	 * @param {string} key - The key to use in settings storage
	 * @returns {Bot}
	 */
	removeDefaultSetting(key)
	{
		this.storage.removeItem(`defaultGuildSettings/${key}`);
		return this;
	}

	/**
	 * See if a guild default setting exists
	 * @memberof Bot
	 * @instance
	 * @param {string} key - The key in storage to check
	 * @returns {boolean}
	 */
	defaultSettingExists(key)
	{
		return !!this.storage.getItem('defaultGuildSettings')[key];
	}

	/**
	 * Shortcut to return the command prefix for the provided guild
	 * @memberof Bot
	 * @instance
	 * @param {(external:Guild|string)} guild - The guild or guild id to get the prefix of
	 * @returns {string|null}
	 */
	getPrefix(guild)
	{
		if (!guild) return null;
		return this.guildStorages.get(guild).getSetting('prefix') || null;
	}
}

/**
 * @typedef {Object} BotOptions Object containing required {@link Bot} properties to be
 * passed to a Bot on construction
 * @property {string} [name='botname'] - See: {@link Bot#name}
 * @property {string} token - See: {@link Bot#token}
 * @property {string} [commandsDir] - See: {@link Bot#commandsDir}
 * @property {string} [statusText=null] - See: {@link Bot#statusText}
 * @property {string} [readyText='Ready!'] - See: {@link Bot#readyText}
 * @property {boolean} [noCommandErr=true] - See: {@link Bot#noCommandErr}
 * @property {boolean} [selfbot=false] - See: {@link Bot#selfbot}
 * @property {boolean} [passive=false] - see {@link Bot#passive}
 * @property {string} [version='0.0.0'] - See: {@link Bot#version}
 * @property {Object} config - See: {@link Bot#config}
 * @property {string[]} [disableBase=[]] - See: {@link Bot#disableBase}
 */
<commit_msg>Add some errors for invalid config<commit_after>'use babel';
'use strict';

import { Client } from 'discord.js';
import LocalStorage from '../storage/LocalStorage';
import GuildStorageLoader from '../storage/GuildStorageLoader';
import GuildStorageRegistry from '../storage/GuildStorageRegistry';
import CommandLoader from '../command/CommandLoader';
import CommandRegistry from '../command/CommandRegistry';
import CommandDispatcher from '../command/CommandDispatcher';

/**
 * The Discord.js Client instance. Contains bot-specific [storage]{@link Bot#storage},
 * guild specific [storages]{@link Bot#guildStorages}, and contains important
 * fields for access within commands
 * @class Bot
 * @extends {external:Client}
 * @param {BotOptions} botOptions - Object containing required bot properties
 * @param {external:ClientOptions} [clientOptions] - Discord.js ClientOptions
 */
export default class Bot extends Client
{
	constructor(botOptions = null, clientOptions)
	{
		super(clientOptions);

		/** @type {string} */
		this._token = botOptions.token;

		/**
		 * The name of the Bot
		 * @memberof Bot
		 * @type {string}
		 * @name name
		 * @instance
		 */
		this.name = botOptions.name || 'botname';

		/**
		 * Directory to find command class files. Optional
		 * if bot is passive. See: {@link Bot#passive}
		 * @memberof Bot
		 * @type {string}
		 * @name commandsDir
		 * @instance
		 */
		this.commandsDir = botOptions.commandsDir || null;

		/**
		 * Status text for the bot
		 * @memberof Bot
		 * @type {?string}
		 * @name statusText
		 * @instance
		 */
		this.statusText = botOptions.statusText || null;

		/**
		 * Text to output when the bot is ready
		 * @memberof Bot
		 * @type {string}
		 * @name readyText
		 * @instance
		 */
		this.readyText = botOptions.readyText || 'Ready!';

		/**
		 * Whether or not a generic 'command not found' message
		 * should be given in DMs to instruct the user to
		 * use the `help` command. Set to false to disable
		 * this message
		 * @name Bot#noCommandErr
		 * @type {string}
		 * @instance
		 */
		this.noCommandErr = botOptions.noCommandErr === undefined ? true : botOptions.noCommandErr;

		/**
		 * Whether or not the bot is a selfbot
		 * @memberof Bot
		 * @type {boolean}
		 * @name selfbot
		 * @instance
		 */
		this.selfbot = botOptions.selfbot || false;

		/**
		 * Whether or not this bot is passive. Passive bots
		 * will not register a command dispatcher or a message
		 * listener. This allows passive bots to be created that
		 * do not respond to any commands but are able to perform
		 * actions based on whatever the framework user wants
		 * @memberof Bot
		 * @type {boolean}
		 * @name passive
		 * @instance
		 */
		this.passive = botOptions.passive || false;

		/**
		 * Bot version, best taken from package.json
		 * @memberof Bot
		 * @type {string}
		 * @name version
		 * @instance
		 */
		this.version = botOptions.version || '0.0.0';

		/**
		 * Object containing token and owner ids
		 * @memberof Bot
		 * @type {Object}
		 * @name config
		 * @instance
		 * @property {string} token - Discord login token for the bot
		 * @property {string[]} owner - Array of owner id strings
		 */
		this.config = botOptions.config || null;

		/**
		 * Array of base command names to skip when loading commands. Base commands
		 * may only be disabled by name, not by alias
		 * @memberof Bot
		 * @type {string[]}
		 * @name disableBase
		 * @instance
		 */
		this.disableBase = botOptions.disableBase || [];

		/** @type {LocalStorage} */
		this._guildDataStorage = new LocalStorage('storage/guild-storage');

		/** @type {LocalStorage} */
		this._guildSettingStorage = new LocalStorage('storage/guild-settings');

		/** @type {GuildStorageLoader} */
		this._guildStorageLoader = new GuildStorageLoader(this);

		/** @type {CommandLoader} */
		this._commandLoader = new CommandLoader(this);

		/**
		 * Bot-specific storage
		 * @memberof Bot
		 * @type {LocalStorage}
		 * @name storage
		 * @instance
		 */
		this.storage = new LocalStorage('storage/bot-storage');

		/**
		 * [Collection]{@link external:Collection} containing all GuildStorage instances
		 * @memberof Bot
		 * @type {GuildStorageRegistry<string, GuildStorage>}
		 * @name guildStorages
		 * @instance
		 */
		this.guildStorages = new GuildStorageRegistry();

		/**
		 * [Collection]{@link external:Collection} containing all loaded commands
		 * @memberof Bot
		 * @type {CommandRegistry<string, Command>}
		 * @name commands
		 * @instance
		 */
		this.commands = new CommandRegistry();

		/**
		 * @typedef {Object} DefaultGuildSettings - The default settings to apply to new guilds.
		 * Stored under the key 'defaultGuildSettings' in {@link Bot#storage}
		 * @property {string} prefix='/' - Prefix to prepend commands
		 * @property {Array} [disabledGroups=[]] - Command groups to ignore
		 */

		// Load defaultGuildSettings into storage the first time the bot is run
		if (!this.storage.exists('defaultGuildSettings')) // eslint-disable-line curly
			this.storage.setItem('defaultGuildSettings',
				require('../storage/defaultGuildSettings.json'));

		/** @type {CommandDispatcher} */
		this._dispatcher = new CommandDispatcher(this);

		// Make some asserts
		if (!this._token) throw new Error('You must provide a token for the bot.');
		if (!this.commandsDir && !this.passive) throw new Error('You must provide a directory to load commands from via commandDir');
		if (!this.config) throw new Error('You must provide a config containing token and owner ids.');
		if (!this.config.owner) throw new Error('You must provide config array of owner ids.');
		if (typeof this.config.owner !== 'array') throw new Error('Config owner option must be an arrray of user ids.');

		// Load commands
		if (!this.passive) this.loadCommand('all');
	}

	/**
	 * Loads/reloads all/specific commands
	 * @memberof Bot
	 * @instance
	 * @param {string} command - The name of a command to reload, or 'all' to load all commands
	 */
	loadCommand(command)
	{
		if (!command) throw new Error(`You must provide a command name to load, or 'all' to load all commands`);
		if (command === 'all') this._commandLoader.loadCommands();
		else this._commandLoader.reloadCommand(command);
	}

	/**
	 * Logs the Bot in and registers some event handlers
	 * @memberof Bot
	 * @instance
	 * @returns {Bot}
	 */
	start()
	{
		this.login(this._token);

		this.once('ready', () =>
		{
			console.log(this.readyText); // eslint-disable-line no-console
			this.user.setGame(this.statusText);

			// Load all guild storages
			this._guildStorageLoader.loadStorages(this._guildDataStorage, this._guildSettingStorage);
		});

		this.on('guildCreate', () =>
		{
			this._guildStorageLoader.initNewGuilds(this._guildDataStorage, this._guildSettingStorage);
		});

		this.on('guildDelete', (guild) =>
		{
			this.guildStorages.delete(guild.id);
			this._guildDataStorage.removeItem(guild.id);
			this._guildSettingStorage.removeItem(guild.id);
		});

		return this;
	}

	/**
	 * Set the value of a default setting key and push it to all guild
	 * setting storages. Will not overwrite a setting in guild settings
	 * storage if there is already an existing key with the given value
	 * @memberof Bot
	 * @instance
	 * @param {string} key - The key to use in settings storage
	 * @param {string} value - The value to use in settings storage
	 * @returns {Bot}
	 */
	setDefaultSetting(key, value)
	{
		this.storage.setItem(`defaultGuildSettings/${key}`, value);
		this.guildStorages.forEach(guild =>
		{
			if (!guild.settingExists(key)) guild.setSetting(key, value);
		});
		return this;
	}

	/**
	 * Remove a defaultGuildSettings item. Will not remove from ALL guild
	 * settings, but will prevent the item from being added to new guild
	 * settings storage upon creation
	 * @memberof Bot
	 * @instance
	 * @param {string} key - The key to use in settings storage
	 * @returns {Bot}
	 */
	removeDefaultSetting(key)
	{
		this.storage.removeItem(`defaultGuildSettings/${key}`);
		return this;
	}

	/**
	 * See if a guild default setting exists
	 * @memberof Bot
	 * @instance
	 * @param {string} key - The key in storage to check
	 * @returns {boolean}
	 */
	defaultSettingExists(key)
	{
		return !!this.storage.getItem('defaultGuildSettings')[key];
	}

	/**
	 * Shortcut to return the command prefix for the provided guild
	 * @memberof Bot
	 * @instance
	 * @param {(external:Guild|string)} guild - The guild or guild id to get the prefix of
	 * @returns {string|null}
	 */
	getPrefix(guild)
	{
		if (!guild) return null;
		return this.guildStorages.get(guild).getSetting('prefix') || null;
	}
}

/**
 * @typedef {Object} BotOptions Object containing required {@link Bot} properties to be
 * passed to a Bot on construction
 * @property {string} [name='botname'] - See: {@link Bot#name}
 * @property {string} token - See: {@link Bot#token}
 * @property {string} [commandsDir] - See: {@link Bot#commandsDir}
 * @property {string} [statusText=null] - See: {@link Bot#statusText}
 * @property {string} [readyText='Ready!'] - See: {@link Bot#readyText}
 * @property {boolean} [noCommandErr=true] - See: {@link Bot#noCommandErr}
 * @property {boolean} [selfbot=false] - See: {@link Bot#selfbot}
 * @property {boolean} [passive=false] - see {@link Bot#passive}
 * @property {string} [version='0.0.0'] - See: {@link Bot#version}
 * @property {Object} config - See: {@link Bot#config}
 * @property {string[]} [disableBase=[]] - See: {@link Bot#disableBase}
 */
<|endoftext|>


<commit_before>'use strict';

var path = process.cwd();
var ClickHandler = require(path + '/app/controllers/clickHandler.server.js');
var index = path + '/public/index.html';

module.exports = function (app, passport) {

	function isLoggedIn (req, res, next) {
		// console.log('starting isAuthenticated');
		// console.log('req.session');
		// console.log(req.session);
		// console.log('req.user');
		// console.log(req.user.username);
		// console.log('req.rawHeaders');
		// console.log(req.rawHeaders);
		// console.log('req.url');
		// console.log(req.url);
		// console.log('req.path');
		// console.log(req.path);
		if (req.isAuthenticated()) {
			// console.log('isAuthenticated true');
			var hour = 36000000
			req.session.cookie.expires = new Date(Date.now() + hour)
			req.session.cookie.maxAge = hour
			return next();
		}	else {
			// console.log('isAuthenticated false');
			// console.log(req.url);
			res.json({id: false});
		}
	}

	var clickHandler = new ClickHandler();
	clickHandler.addDefault();

	app.route('/')
		.get(function (req, res) {
			// console.log(req.params);
			res.sendFile(index);
		});

	app.route('/login')
		.get(function (req, res) {
			res.sendFile(path + '/public/login.html');
		});

	app.route('/logout')
		.get(function (req, res) {
			req.logout();
			res.redirect('/');
		});

	// get and take a poll
	app.route('/api/poll/:id')
		.get(clickHandler.getPoll)
		.put(clickHandler.takePoll)

	// get all polls
	app.route('/api/allPolls')
		.get(clickHandler.getAllPolls)

	// get user info
	app.route('/api/:id')
		.get(isLoggedIn, function (req, res) {
			console.log('/api/:id');
			console.log('user info');
			console.log(req.user);
			// console.log('github');
			// console.log(req.user.github.id);
			res.json(req.user)

		});

	app.route('/auth/github')
		.get(passport.authenticate('github'));

	app.route('/auth/github/callback')
		.get(passport.authenticate('github', {
			successRedirect: '/',
			failureRedirect: '/'
		}));

	app.route('/auth/twitter')
		.get(passport.authenticate('twitter'));

	app.route('/auth/twitter/callback')
		.get(passport.authenticate('twitter', {
			successRedirect: '/',
			failureRedirect: '/'
		}));

	// add, get, edit, delete the user poll data
	// must be authenticated
	app.route('/api/:id/:poll')
		.get(isLoggedIn, clickHandler.getPolls)
		.put(isLoggedIn, clickHandler.editPoll)
		.post(isLoggedIn, clickHandler.addPoll)
		.delete(isLoggedIn, clickHandler.delPoll)

};
<commit_msg>removed con.log causing heroku to crash<commit_after>'use strict';

var path = process.cwd();
var ClickHandler = require(path + '/app/controllers/clickHandler.server.js');
var index = path + '/public/index.html';

module.exports = function (app, passport) {

	function isLoggedIn (req, res, next) {
		// console.log('starting isAuthenticated');
		// console.log('req.session');
		// console.log(req.session);
		// console.log('req.user');
		// console.log(req.user.username);
		// console.log('req.rawHeaders');
		// console.log(req.rawHeaders);
		// console.log('req.url');
		// console.log(req.url);
		// console.log('req.path');
		// console.log(req.path);
		if (req.isAuthenticated()) {
			// console.log('isAuthenticated true');
			var hour = 36000000
			req.session.cookie.expires = new Date(Date.now() + hour)
			req.session.cookie.maxAge = hour
			return next();
		}	else {
			// console.log('isAuthenticated false');
			// console.log(req.url);
			res.json({id: false});
		}
	}

	var clickHandler = new ClickHandler();
	clickHandler.addDefault();

	app.route('/')
		.get(function (req, res) {
			// console.log(req.params);
			res.sendFile(index);
		});

	app.route('/login')
		.get(function (req, res) {
			res.sendFile(path + '/public/login.html');
		});

	app.route('/logout')
		.get(function (req, res) {
			req.logout();
			res.redirect('/');
		});

	// get and take a poll
	app.route('/api/poll/:id')
		.get(clickHandler.getPoll)
		.put(clickHandler.takePoll)

	// get all polls
	app.route('/api/allPolls')
		.get(clickHandler.getAllPolls)

	// get user info
	app.route('/api/:id')
		.get(isLoggedIn, function (req, res) {
			console.log('/api/:id');
			console.log('user info');
			// console.log(req.user);
			// console.log('github');
			// console.log(req.user.github.id);
			res.json(req.user)

		});

	app.route('/auth/github')
		.get(passport.authenticate('github'));

	app.route('/auth/github/callback')
		.get(passport.authenticate('github', {
			successRedirect: '/',
			failureRedirect: '/'
		}));

	app.route('/auth/twitter')
		.get(passport.authenticate('twitter'));

	app.route('/auth/twitter/callback')
		.get(passport.authenticate('twitter', {
			successRedirect: '/',
			failureRedirect: '/'
		}));

	// add, get, edit, delete the user poll data
	// must be authenticated
	app.route('/api/:id/:poll')
		.get(isLoggedIn, clickHandler.getPolls)
		.put(isLoggedIn, clickHandler.editPoll)
		.post(isLoggedIn, clickHandler.addPoll)
		.delete(isLoggedIn, clickHandler.delPoll)

};
<|endoftext|>


<commit_before>import React from 'react';
import { Route, IndexRoute } from 'react-router';
import try from 'try';

import App from 'containers/App/';
import Main from 'containers/Main/';

const routes = (
  <Route path="/" component={ App } >
    <IndexRoute component={ Main } />
    <Route path="/main" component={ Main } />
  </Route>
);

export default routes;
<commit_msg>Remove malformed import<commit_after>import React from 'react';
import { Route, IndexRoute } from 'react-router';

import App from 'containers/App/';
import Main from 'containers/Main/';

const routes = (
  <Route path="/" component={ App } >
    <IndexRoute component={ Main } />
    <Route path="/main" component={ Main } />
  </Route>
);

export default routes;
<|endoftext|>