<commit_before>"use strinct";
var gRoutes = require("json!./routes.json");
function is(val){return typeof val !== "undefined";};
var chk = {
	"token":function(contexts){
		Object.keys(contexts).forEach(function(domain){
			if (!contexts[domain].token)
				delete contexts[domain];
		});
		return  Object.keys(contexts).length?null:"token";
	}
	,"leadContext":function(contexts){
		if (Object.keys(contexts).length > 1){
			var leadContext = new Object();
			leadContext[gConfig.leadDomain] = contexts[gConfig.leadDomain];
			contexts = leadContext;
		}
		return null;
	}
}
function mixedTimelines (cView, contexts, prAllT,prAllC){
	return cView.Utils._Promise.all([prAllT,prAllC]).then( function (res){
		var domains = Object.keys(contexts);
		var posts = new Array();
		cView.doc.getElementById("loading-msg").innerHTML = "Building page";
		res[0].forEach(function(data,idx){
			var context = contexts[domains[idx]];
			cView.Common.loadGlobals( data, context);
			if(typeof data.posts !== "undefined" ){
				data.posts.forEach(function(post){
					post.domain = domains[idx];
				});
				posts = posts.concat(data.posts);
			}
			context.timelineId = data.timelines.id;
			if(JSON.parse(cView.localStorage.getItem("rt")))
				context.rtSubTimeline(data);
		});
		posts = undup(cView, posts);
		posts.sort(function(a,b){return b.updatedAt - a.updatedAt;});
		cView.Drawer.drawTimeline(posts,contexts);
		cView.Drawer.updateReqs();
	});
}
function undup (cView, posts){
	posts.forEach(function(post,idx){
		post.sign = cView.hasher.of(post.body);
	});
	//var hashes = posts.map(function(post){return hash.of(post.body);});
	var duplicates = new Object();
	for(var idx = 0; idx < posts.length-1; idx++){
		if(posts[idx].body.length < cView.minBody) continue;
		for(var v = idx+1; v < posts.length; v++){
			if(posts[v].body.length < cView.minBody) continue;
			if( cView.hasher.similarity(posts[idx].sign,posts[v].sign)>cView.threshold){
				var dups;
				if (is(duplicates[idx]))dups = duplicates[idx];
				else if (is(duplicates[v]))dups = duplicates[v];
				else dups = new Object();
				dups[idx] = true;
				dups[v] = true;
				duplicates[idx] = duplicates[v] = dups;
			}
		}
	}
	Object.keys(duplicates).forEach(function(idx){
		idx = parseInt(idx);
		if (!is(duplicates[idx]))return;
		posts.push(
			cView.Common.metapost(
				Object.keys( duplicates[idx]).map(function(v){
					return posts[parseInt(v)];
				})
			)
		);
		Object.keys(duplicates[idx])
		.forEach(function(v){
			v = parseInt(v);
			delete duplicates[v];
			posts[v] = null;
		});
	});
	posts = posts.filter(function(post){return post != null;});
	return posts;

}
define("./router",[],function(){
	function _Router(v){
		this.cView = v;
	};
	_Router.prototype = {
		"route":function(contexts, path){
			var cView = this.cView;
			if (cView.doc.title == "") cView.doc.title = "Feeds";
			if (path.indexOf("#") != -1 )
				var arrPath = path.substr(0,path.indexOf("#")).split("/");
			else var arrPath = path.split("/");
			var step = gRoutes;
			for(var idx = 0; idx < arrPath.length; idx++){
				var txtStep = arrPath[idx];
				if (txtStep == "")continue;
				if (is(step.req) && chk[step.req](contexts))
					return new cView.Utils._Promise.reject(chk[step.req](contexts));

				if(is(step.reroute))
					return cView[step.reroute[0]][step.reroute[1]](contexts, path);
				if (is(step.vals) && is(step.vals[txtStep]))
					step = step.vals[txtStep];
				else if (is(step.default)) step = step.default;
			}
			if (is(step.default)) step = step.default;
			if(is(step.dest)){
				cView.doc.getElementById("loading-msg").innerHTML = "Loading content";
				if((step.dest.length == 3)&& chk[step.dest[2]](contexts) )
					return new cView.Utils._Promise.reject(chk[step.dest[2]](contexts));
				return cView[step.dest[0]][step.dest[1]](contexts, path);
			}
			return new cView.Utils._Promise.reject();
		}
		,"directs":function(contexts){
			var cView = this.cView;
			return new cView.Utils._Promise(function(resolve,reject){
				var nodeAddPost = cView.gNodes["new-post"].cloneAll();
				var body = cView.doc.getElementById("container");
				body.appendChild(nodeAddPost);
				var domains = Object.keys(contexts);
				var context = contexts[gConfig.leadDomain];
				if (!is(context))context = contexts[domains[0]];
				context.p.then(function () {
					cView.Drawer.genDirectTo(nodeAddPost
						,context.gMe);
				});
				cView.Router.timeline(contexts, "filter/directs").then(function(){
					body.cNodes["pagetitle"].innerHTML = "Direct messages";
					cView.doc.title += ": Direct messages";
					resolve();
				},reject);
			});
		}
		,"routeContext":function(contexts, path){
			var cView = this.cView;
			var arrPath = path.split("/");
			var singleContext = new Object();
			singleContext[arrPath[1]] = contexts[arrPath[1]];
			cView.doc.title = arrPath[1];
			var newPath = arrPath.slice(2).join("/");
			return this.route(singleContext, (newPath != "")?newPath:"home");
		}
		,"routeHome":function(contexts){
			var cView = this.cView;
			return new cView.Utils._Promise(function(resolve,reject){
				var nodeAddPost = cView.gNodes["new-post"].cloneAll();
				var body = cView.doc.getElementById("container");
				body.appendChild(nodeAddPost);
				var domains = Object.keys(contexts);
				var mainContext = (domains.indexOf(gConfig.leadDomain) != -1)?
					contexts[gConfig.leadDomain]:contexts[domains[0]];
				mainContext.p.then(function () {
					cView.Drawer.genPostTo(nodeAddPost
						,null
						,mainContext.gMe);
				});
				cView.Router.timeline(contexts, "home" ).then(resolve,reject);
			});
		}
		,"routeMe": function(contexts, path){
			var cView = this.cView;
			var nodeAddPost = cView.gNodes["new-post"].cloneAll();
			var domains = Object.keys(contexts);
			var body = cView.doc.getElementById("container");
			var mainContext = (domains.indexOf(gConfig.leadDomain) != -1)?
				contexts[gConfig.leadDomain]:contexts[domains[0]];
			mainContext.p.then(function () {
				cView.Drawer.genPostTo(nodeAddPost
					,null
					,mainContext.gMe);
			});
			body.appendChild(nodeAddPost);
			cView.doc.getElementById("container").cNodes["pagetitle"].innerHTML = path;
			cView.doc.title +=": " + path;
			var prContxt = new Array();
			var prConts = new Array();
			domains.forEach(function(domain){
				var context = contexts[domain];
				prContxt.push(context.p);
				prConts.push(context.api.getTimeline(
					context.token
					,context.gMe.users.username
					,cView.skip
				));
			});
			var prAllT = cView.Utils._Promise.all(prConts);
			var prAllC = cView.Utils._Promise.all(prContxt);
			return mixedTimelines (cView, contexts, prAllT,prAllC);
		}
		,"subscribers":function(contexts, path){
			var cView = this.cView;
			return cView.Router.subs(contexts, path, cView.Drawer.drawSubs);
		}
		,"subscriptions":function(contexts, path){
			var cView = this.cView;
			return cView.Router.subs(contexts, path, cView.Drawer.drawFriends);
		}
		,"subs":function(contexts, path, fn){
			var cView = this.cView;
			var context = contexts[Object.keys(contexts)[0]];
			return cView.Utils._Promise.all([ context.api.getSubs(context.token,path),context.p ])
			.then(function(res){
				cView.Common.loadGlobals(res[0], context);
				var body = cView.doc.getElementById("container");
				body.cNodes["pagetitle"].innerHTML = path;
				cView.doc.title = "@"+path.split("/")[0]+ "'s  " + path.split("/")[1] + " ("+context.domain+")";
				fn.call(cView, res[0],context);
			});
		}
		,"groups":function(contexts, path){
			var cView = this.cView;
			return cView.Utils._Promise.all(Object.keys(contexts).map(function(domain){
				return contexts[domain].p;
			})).then(function(res){
				var body = cView.doc.getElementById("container");
				body.cNodes["pagetitle"].innerHTML = path;
				cView.doc.title = "My groups";
				cView.Drawer.drawGroups();
			});
		}
		,"unmixed":function(contexts, path){
			var cView = this.cView;
			return new cView.Utils._Promise(function(resolve,reject){
				var body = cView.doc.getElementById("container");
				var nodeDummy = body.appendChild(cView.doc.createElement("div"));
				var domains = Object.keys(contexts);
				var domain = (domains.indexOf(gConfig.leadDomain) != -1)?  gConfig.leadDomain :domains[0];
				var cs = new Object();
				cs[domain] = contexts[domain];
				var context = cs[domain];
				var username = path.split("/")[0];
				cView.Router.timeline(cs, path).then(function(){
					var feed =  context.gUsers.byName[username];
					if(feed.type == "user")cView.noBlocks = true;
					//cView.Common.addUser.call(context, feed);
					cView.doc.title = "@"+feed.username + ", a " + context.domain + " feed.";
					cView.Utils.setChild(body, "details", cView.Drawer.genUserDetails(feed.username, context));
					if (context.ids)
						cView.Utils.setChild(body, "up-controls", cView.Drawer.genUpControls(feed));
					var names = new Array();
					context.ids.forEach( function(id){
						names.push(context.gUsers[id].username);
					});
					if (names.indexOf(feed.username)!= -1) {
						var nodeAddPost = cView.gNodes["new-post"].cloneAll();
						body.replaceChild(nodeAddPost, nodeDummy);
						cView.Drawer.genPostTo(
							nodeAddPost
							,null
							,context.logins[context.gUsers.byName[feed.username].id].data
						);
					}
					if ((feed.type == "group") && feed.friend){
						var nodeAddPost = cView.gNodes["new-post"].cloneAll();
						body.replaceChild(nodeAddPost, nodeDummy);
						cView.Drawer.genPostTo(
							nodeAddPost
							,feed.username
							,context.gMe
						);
					}
					resolve();
				},reject);
			});
		}
		,"singlePost":function(contexts,path){
			var cView = this.cView;
			cView.noBlocks = true;
			var context = Object.keys(contexts).map(function(d){ return contexts[d];})[0];
			return cView.Utils._Promise.all( [
				context.api.getPost(context.token, path, ["comments"])
				,context.p
			]).then( function (res){
				cView.doc.getElementById("loading-msg").innerHTML = "Building page";
				cView.Common.loadGlobals(res[0], context);
				var post = res[0].posts;
				if(Array.isArray(post))post = post[0];
				post.domain = context.domain;
				cView.Drawer.drawPost(post,context);
				if(JSON.parse(cView.localStorage.getItem("rt"))) context.rtSubPost(res[0]) ;
				if(is(res[0].timelines))
					context.timelineId = res[0].timelines.id;
			});
		}
		,"routeSearch":function(contexts){
			var cView = this.cView;
			var search = cView.search.match(/qs=([^&]+)/);

			if(!search){
				cView.Drawer.drawSearch("");
				return cView.Utils._Promise.resolve();
			}
			return this.timeline(
				contexts
				,search[1]
				,"getSearch"
			).then(function(){
				cView.Drawer.drawSearch(decodeURIComponent(search[1].replace("+", " ")));
			});
		}
		,"timeline":function(contexts, path, source ){
			var cView = this.cView;
			source = (typeof source !== "undefined")?source:"getTimeline";
			var arrContent = new Array();
			var prConts = new Array();
			var prContxt = new Array();
			var domains = Object.keys(contexts);
			domains.forEach(function(domain){
				var context = contexts[domain];
				prContxt.push(context.p);
				prConts.push(context.api[source](context.token,path, cView.skip));
			});
			var prAllT = cView.Utils._Promise.all(prConts);
			var prAllC = cView.Utils._Promise.all(prContxt);
			cView.doc.getElementById("container").cNodes["pagetitle"].innerHTML = path;
			cView.doc.title +=": " + path;
			return mixedTimelines(cView, contexts, prAllT,prAllC);
		}
	}
return _Router;
});

<commit_msg>Ignore failed requests if not failed to all backends<commit_after>"use strinct";
var gRoutes = require("json!./routes.json");
function is(val){return typeof val !== "undefined";};
var chk = {
	"token":function(contexts){
		Object.keys(contexts).forEach(function(domain){
			if (!contexts[domain].token)
				delete contexts[domain];
		});
		return  Object.keys(contexts).length?null:"token";
	}
	,"leadContext":function(contexts){
		if (Object.keys(contexts).length > 1){
			var leadContext = new Object();
			leadContext[gConfig.leadDomain] = contexts[gConfig.leadDomain];
			contexts = leadContext;
		}
		return null;
	}
}
function some(_Promise,arr ){
	return new _Promise(function(resolve, reject){
		var count = arr.length;
		var failed = true;
		if(!count)resolve();
		var reses = new Array(count);
		var failes = new Array(count);
		function alldone(ok, data,idx){
			if (ok) {
				failed = false;
				reses[idx] = data;
			}else failes[idx] = data;
			if (--count)return;
			(!failed)?resolve(reses):reject(failes);
		}

		arr.forEach(function(item, idx){
			function success(res){alldone(true, res,idx);};
			function fail(res){alldone(false, res ,idx);};
			if( typeof item.then !== "function")item = _Promise.resolve(item);
			item.then(success, fail);
		});

	});
}

function mixedTimelines (cView, contexts, prAllT,prAllC){
	return cView.Utils._Promise.all([prAllT,prAllC]).then( function (res){
		var domains = Object.keys(contexts);
		var posts = new Array();
		cView.doc.getElementById("loading-msg").innerHTML = "Building page";
		res[0].forEach(function(data,idx){
			if(typeof data === "undefined" )return;
			var context = contexts[domains[idx]];
			cView.Common.loadGlobals( data, context);
			if(typeof data.posts !== "undefined" ){
				data.posts.forEach(function(post){
					post.domain = domains[idx];
				});
				posts = posts.concat(data.posts);
			}
			context.timelineId = data.timelines.id;
			if(JSON.parse(cView.localStorage.getItem("rt")))
				context.rtSubTimeline(data);
		});
		posts = undup(cView, posts);
		posts.sort(function(a,b){return b.updatedAt - a.updatedAt;});
		cView.Drawer.drawTimeline(posts,contexts);
		cView.Drawer.updateReqs();
	});
}
function undup (cView, posts){
	posts.forEach(function(post,idx){
		post.sign = cView.hasher.of(post.body);
	});
	//var hashes = posts.map(function(post){return hash.of(post.body);});
	var duplicates = new Object();
	for(var idx = 0; idx < posts.length-1; idx++){
		if(posts[idx].body.length < cView.minBody) continue;
		for(var v = idx+1; v < posts.length; v++){
			if(posts[v].body.length < cView.minBody) continue;
			if( cView.hasher.similarity(posts[idx].sign,posts[v].sign)>cView.threshold){
				var dups;
				if (is(duplicates[idx]))dups = duplicates[idx];
				else if (is(duplicates[v]))dups = duplicates[v];
				else dups = new Object();
				dups[idx] = true;
				dups[v] = true;
				duplicates[idx] = duplicates[v] = dups;
			}
		}
	}
	Object.keys(duplicates).forEach(function(idx){
		idx = parseInt(idx);
		if (!is(duplicates[idx]))return;
		posts.push(
			cView.Common.metapost(
				Object.keys( duplicates[idx]).map(function(v){
					return posts[parseInt(v)];
				})
			)
		);
		Object.keys(duplicates[idx])
		.forEach(function(v){
			v = parseInt(v);
			delete duplicates[v];
			posts[v] = null;
		});
	});
	posts = posts.filter(function(post){return post != null;});
	return posts;

}
define("./router",[],function(){
	function _Router(v){
		this.cView = v;
	};
	_Router.prototype = {
		"route":function(contexts, path){
			var cView = this.cView;
			if (cView.doc.title == "") cView.doc.title = "Feeds";
			if (path.indexOf("#") != -1 )
				var arrPath = path.substr(0,path.indexOf("#")).split("/");
			else var arrPath = path.split("/");
			var step = gRoutes;
			for(var idx = 0; idx < arrPath.length; idx++){
				var txtStep = arrPath[idx];
				if (txtStep == "")continue;
				if (is(step.req) && chk[step.req](contexts))
					return new cView.Utils._Promise.reject(chk[step.req](contexts));

				if(is(step.reroute))
					return cView[step.reroute[0]][step.reroute[1]](contexts, path);
				if (is(step.vals) && is(step.vals[txtStep]))
					step = step.vals[txtStep];
				else if (is(step.default)) step = step.default;
			}
			if (is(step.default)) step = step.default;
			if(is(step.dest)){
				cView.doc.getElementById("loading-msg").innerHTML = "Loading content";
				if((step.dest.length == 3)&& chk[step.dest[2]](contexts) )
					return new cView.Utils._Promise.reject(chk[step.dest[2]](contexts));
				return cView[step.dest[0]][step.dest[1]](contexts, path);
			}
			return new cView.Utils._Promise.reject();
		}
		,"directs":function(contexts){
			var cView = this.cView;
			return new cView.Utils._Promise(function(resolve,reject){
				var nodeAddPost = cView.gNodes["new-post"].cloneAll();
				var body = cView.doc.getElementById("container");
				body.appendChild(nodeAddPost);
				var domains = Object.keys(contexts);
				var context = contexts[gConfig.leadDomain];
				if (!is(context))context = contexts[domains[0]];
				context.p.then(function () {
					cView.Drawer.genDirectTo(nodeAddPost
						,context.gMe);
				});
				cView.Router.timeline(contexts, "filter/directs").then(function(){
					body.cNodes["pagetitle"].innerHTML = "Direct messages";
					cView.doc.title += ": Direct messages";
					resolve();
				},reject);
			});
		}
		,"routeContext":function(contexts, path){
			var cView = this.cView;
			var arrPath = path.split("/");
			var singleContext = new Object();
			singleContext[arrPath[1]] = contexts[arrPath[1]];
			cView.doc.title = arrPath[1];
			var newPath = arrPath.slice(2).join("/");
			return this.route(singleContext, (newPath != "")?newPath:"home");
		}
		,"routeHome":function(contexts){
			var cView = this.cView;
			return new cView.Utils._Promise(function(resolve,reject){
				var nodeAddPost = cView.gNodes["new-post"].cloneAll();
				var body = cView.doc.getElementById("container");
				body.appendChild(nodeAddPost);
				var domains = Object.keys(contexts);
				var mainContext = (domains.indexOf(gConfig.leadDomain) != -1)?
					contexts[gConfig.leadDomain]:contexts[domains[0]];
				mainContext.p.then(function () {
					cView.Drawer.genPostTo(nodeAddPost
						,null
						,mainContext.gMe);
				});
				cView.Router.timeline(contexts, "home" ).then(resolve,reject);
			});
		}
		,"routeMe": function(contexts, path){
			var cView = this.cView;
			var nodeAddPost = cView.gNodes["new-post"].cloneAll();
			var domains = Object.keys(contexts);
			var body = cView.doc.getElementById("container");
			var mainContext = (domains.indexOf(gConfig.leadDomain) != -1)?
				contexts[gConfig.leadDomain]:contexts[domains[0]];
			mainContext.p.then(function () {
				cView.Drawer.genPostTo(nodeAddPost
					,null
					,mainContext.gMe);
			});
			body.appendChild(nodeAddPost);
			cView.doc.getElementById("container").cNodes["pagetitle"].innerHTML = path;
			cView.doc.title +=": " + path;
			var prContxt = new Array();
			var prConts = new Array();
			domains.forEach(function(domain){
				var context = contexts[domain];
				prContxt.push(context.p);
				prConts.push(context.api.getTimeline(
					context.token
					,context.gMe.users.username
					,cView.skip
				));
			});
			var prAllT = cView.Utils._Promise.all(prConts);
			var prAllC = cView.Utils._Promise.all(prContxt);
			return mixedTimelines (cView, contexts, prAllT,prAllC);
		}
		,"subscribers":function(contexts, path){
			var cView = this.cView;
			return cView.Router.subs(contexts, path, cView.Drawer.drawSubs);
		}
		,"subscriptions":function(contexts, path){
			var cView = this.cView;
			return cView.Router.subs(contexts, path, cView.Drawer.drawFriends);
		}
		,"subs":function(contexts, path, fn){
			var cView = this.cView;
			var context = contexts[Object.keys(contexts)[0]];
			return cView.Utils._Promise.all([ context.api.getSubs(context.token,path),context.p ])
			.then(function(res){
				cView.Common.loadGlobals(res[0], context);
				var body = cView.doc.getElementById("container");
				body.cNodes["pagetitle"].innerHTML = path;
				cView.doc.title = "@"+path.split("/")[0]+ "'s  " + path.split("/")[1] + " ("+context.domain+")";
				fn.call(cView, res[0],context);
			});
		}
		,"groups":function(contexts, path){
			var cView = this.cView;
			return cView.Utils._Promise.all(Object.keys(contexts).map(function(domain){
				return contexts[domain].p;
			})).then(function(res){
				var body = cView.doc.getElementById("container");
				body.cNodes["pagetitle"].innerHTML = path;
				cView.doc.title = "My groups";
				cView.Drawer.drawGroups();
			});
		}
		,"unmixed":function(contexts, path){
			var cView = this.cView;
			return new cView.Utils._Promise(function(resolve,reject){
				var body = cView.doc.getElementById("container");
				var nodeDummy = body.appendChild(cView.doc.createElement("div"));
				var domains = Object.keys(contexts);
				var domain = (domains.indexOf(gConfig.leadDomain) != -1)?  gConfig.leadDomain :domains[0];
				var cs = new Object();
				cs[domain] = contexts[domain];
				var context = cs[domain];
				var username = path.split("/")[0];
				cView.Router.timeline(cs, path).then(function(){
					var feed =  context.gUsers.byName[username];
					if(feed.type == "user")cView.noBlocks = true;
					//cView.Common.addUser.call(context, feed);
					cView.doc.title = "@"+feed.username + ", a " + context.domain + " feed.";
					cView.Utils.setChild(body, "details", cView.Drawer.genUserDetails(feed.username, context));
					if (context.ids)
						cView.Utils.setChild(body, "up-controls", cView.Drawer.genUpControls(feed));
					var names = new Array();
					context.ids.forEach( function(id){
						names.push(context.gUsers[id].username);
					});
					if (names.indexOf(feed.username)!= -1) {
						var nodeAddPost = cView.gNodes["new-post"].cloneAll();
						body.replaceChild(nodeAddPost, nodeDummy);
						cView.Drawer.genPostTo(
							nodeAddPost
							,null
							,context.logins[context.gUsers.byName[feed.username].id].data
						);
					}
					if ((feed.type == "group") && feed.friend){
						var nodeAddPost = cView.gNodes["new-post"].cloneAll();
						body.replaceChild(nodeAddPost, nodeDummy);
						cView.Drawer.genPostTo(
							nodeAddPost
							,feed.username
							,context.gMe
						);
					}
					resolve();
				},reject);
			});
		}
		,"singlePost":function(contexts,path){
			var cView = this.cView;
			cView.noBlocks = true;
			var context = Object.keys(contexts).map(function(d){ return contexts[d];})[0];
			return cView.Utils._Promise.all( [
				context.api.getPost(context.token, path, ["comments"])
				,context.p
			]).then( function (res){
				cView.doc.getElementById("loading-msg").innerHTML = "Building page";
				cView.Common.loadGlobals(res[0], context);
				var post = res[0].posts;
				if(Array.isArray(post))post = post[0];
				post.domain = context.domain;
				cView.Drawer.drawPost(post,context);
				if(JSON.parse(cView.localStorage.getItem("rt"))) context.rtSubPost(res[0]) ;
				if(is(res[0].timelines))
					context.timelineId = res[0].timelines.id;
			});
		}
		,"routeSearch":function(contexts){
			var cView = this.cView;
			var search = cView.search.match(/qs=([^&]+)/);

			if(!search){
				cView.Drawer.drawSearch("");
				return cView.Utils._Promise.resolve();
			}
			return this.timeline(
				contexts
				,search[1]
				,"getSearch"
			).then(function(){
				cView.Drawer.drawSearch(decodeURIComponent(search[1].replace("+", " ")));
			});
		}
		,"timeline":function(contexts, path, source ){
			var cView = this.cView;
			source = (typeof source !== "undefined")?source:"getTimeline";
			var arrContent = new Array();
			var prConts = new Array();
			var prContxt = new Array();
			var domains = Object.keys(contexts);
			domains.forEach(function(domain){
				var context = contexts[domain];
				prContxt.push(context.p);
				prConts.push(context.api[source](context.token,path, cView.skip));
			});
			var prAllT = some(cView.Utils._Promise, prConts);
			var prAllC = cView.Utils._Promise.all(prContxt);
			cView.doc.getElementById("container").cNodes["pagetitle"].innerHTML = path;
			cView.doc.title +=": " + path;
			return mixedTimelines(cView, contexts, prAllT,prAllC);
		}
	}
return _Router;
});

<|endoftext|>


<commit_before>/**
 * Determines how to play the given notes based on their type and quality, then loads
 * the corresponding audio files and plays them.
 *
 * @class MusicSnippet
 * @constructor
 * @param {String} type Type of the sonority
 * @param {String} quality Quality of the sonority
 * @param {String} category Category of the sonority
 * @param {String Array} notes Array of notes
 */
function MusicSnippet(type, quality, notes, category) {
	/* Constants */
	const CHORD = "chord";
	const SCALE = "scale";
	const INTERVAL = "interval";
	const TWENTIETH = "20th Century";
	const JAZZ = "jazz";

	const BPM = 80; 				//Beats per minute
	var bps = BPM/60; 				//Beats per second

	/* Variables */
	var baseNotes = notes;			//Store the base notes to transpose from
	var type = type;				//Chord, scale, or interval
	var quality = quality;			//Answer
	var category = category;		//Category
	var numNotes = notes.length;	//Number of notes

	var tempSounds = [];			//Holds current sound
	var numLoaded = 0;				//Number of loaded files
	var timeouts = [];				//Timeout objects to keep track of when playing broken

	/**
	 * Plays the loaded files:
	 *  - Chords are played broken then blocked
	 *  - Scales are played broken
	 *  - Intervals are played broken
	 *
	 * @method play
	 * @param {String} style How to play the notes. No argument means play it quiz style
	 */
	this.play = function(style) {
		stop();
		clear();
		if(style == undefined) {
			//Play arpegiated and then play block
			if(type == CHORD) {
				if(category == TWENTIETH) {
					playBlock();
				}
				else {
					playBlock();
					timeouts.push(setTimeout(function() {playBroken();}, (1/bps)*2000));
				}
			}
			//Play broken
			else if(type == SCALE) {
				playBroken();
			}
			else if(type == INTERVAL) {
				playBroken();
			}
			else {
				playBroken();
			}
		}
	}

	/**
	 * Randomly transposes the notes given from the CSV file and gives them a random octave.
	 * Then loads the corresponding audio files.
	 *
	 * @method generate
	 */
	this.generate = function() {
		tempSounds = generateTransposition();
	}

	/**
	 * Returns the type and quality
	 *
	 * @method answer
	 * @return {String} quality + type
	 */
	this.answer = function() {
		return quality+" "+type;
	}

	/**
	 * Stops all sound
	 *
	 * @method stopSound
	 */
	this.stopSound = function() {
		stop();
		clear();
	}

	/**
	 * Transposes and sets octave of the notes from the CSV file randomly, then loads the
	 * corresponding files
	 *
	 * @method generateTransposition
	 * @return {Howl Array} An array of Howl objects that have the loaded audio files
	 * @private
	 */
	function generateTransposition() {
		var randKey = Math.floor(Math.random()*13)-6;	//Get Random key between -7 and 7
		var tempNotes = setNotes(randKey);		//Array of transposed keys
		tempNotes = setOctave(tempNotes);		//Set a random octave
		return loadFiles(tempNotes);			//Load the corresponding files
	}

	/**
	 * Tranposes the notes from the CSV file a given number of sharps or flats
	 *
	 * @method setNotes
	 * @param {Integer} shift How much to transpose the notes by
	 * @return {String Array} Array of the notes after transposition
	 * @private
	 */
	function setNotes(shift) {
		return transpose(baseNotes, shift);
	}

	/**
	 * Plays the note at the given index in the loaded files array
	 *
	 * @method playNote
	 * @param {Integer} i Index of the note to be played
	 * @private
	 */
	function playNote(i) {
		tempSounds[i].play();

		//Don't let notes bleed if playing a scale
		if(type == SCALE) {
			stop();
		}
	}

	/**
	 * Plays all notes at the same time
	 *
	 * @method playBlock
	 * @private
	 */
	function playBlock() {
		for(i = 0; i < numNotes; i++) {
			tempSounds[i].play();
		}
	}

	/*
	 * Plays all notes in sequence with timing based on bpm
	 *
	 * @method playBroken
	 * @private
	 */
	function playBroken() {
		//Play first note instantly
		timeouts.push(setTimeout(function() {
			playNote(0);
			playBrokenHelp(1);		//Play rest of notes
		}, 0));
	}

	/*
	 * Recursive helper for playBroken()
	 *
	 * @method playBrokenHelp
	 * @param {Integer} note An index representing the note to be played
	 * @private
	 */
	function playBrokenHelp(note) {
		if(note < numNotes) {
			timeouts.push(setTimeout(function() {
				playNote(note);
				playBrokenHelp(note+1);
			}, (1/bps)*1000)); //How many seconds per note given the bpm
		}
	}

	/*
	 * Stops all sound immediately
	 *
	 * @method stop
	 * @private
	 */
	function stop() {
		for(i = 0; i < tempSounds.length; i++) {
			tempSounds[i].stop();
		}
	}

	/*
	 * Clears all timeouts (delayed sounds)
	 *
	 * @method clear
	 * @private
	 */
	function clear() {
		var initLength = timeouts.length;
		for(i = 0; i < initLength; i++) {
			clearTimeout(timeouts[timeouts.length-1]);
			timeouts.pop();
		}
	}

	/*
	 * Takes the notes and converts them into Howl objects with the appropriate
	 * sound files.
	 *
	 * @method loadFiles
	 * @param {String Array} notes Array of notes to be loaded
	 * @return {Howl Array} Array of Howl objects containing the corresponding audio files
	 * @private
	 */
	function loadFiles(notes) {
		var midi = [];		//Store notes as midi numbers
		var files = [];		//Store file paths to corresponding files
		var sounds = [];	//Howl objects of files

		//Get midi numbers of given notes
		for(i = 0; i < numNotes; i++) {
			midi.push(noteToFileNum[notes[i]]);
			//Error checking
			if(midi[i] == undefined) {
				console.log("Error: Check notation for "+quality+" "+type);
			}
		}

		//Convert midi numbers to their corresponding file names
		files = convMidiToFile(midi);

		//Load sound files
		for(i = 0; i < numNotes; i++) {
			sounds.push(new Howl({
				urls : [files[i]],
				onload : function() {
					numLoaded++;
					console.log("Loaded note "+numLoaded);
					if(numLoaded == numNotes) {
						document.getElementById("loading").style.display = "none";
						document.getElementById("allbuttons").style.display = "block";
						numLoaded = 0;
					}
				},
				onloaderror : function() {console.log(quality+" "+type+" "+i+" loading error")}
			}));
		}
		return sounds;
	}

	/*
 	 * Converts midi numbers to their corresponding file names
 	 *
 	 * @method convMidiToFile
 	 * @param {Integer Array} midi Array of midi numbers to be converted into files
 	 * @return {String Array} Array of strings containing the proper file paths to the audio files
 	 * @private
 	 */
	function convMidiToFile(midi) {
		var files = [];
		for(i = 0; i < numNotes; i++) {
			files.push("audio/piano/piano"+midi[i]+".wav");
		}
		return files;
	}
}
<commit_msg>dbueeing<commit_after>/**
 * Determines how to play the given notes based on their type and quality, then loads
 * the corresponding audio files and plays them.
 *
 * @class MusicSnippet
 * @constructor
 * @param {String} type Type of the sonority
 * @param {String} quality Quality of the sonority
 * @param {String} category Category of the sonority
 * @param {String Array} notes Array of notes
 */
function MusicSnippet(type, quality, notes, category) {
	/* Constants */
	const CHORD = "chord";
	const SCALE = "scale";
	const INTERVAL = "interval";
	const TWENTIETH = "20th Century";
	const JAZZ = "jazz";

	const BPM = 80; 				//Beats per minute
	var bps = BPM/60; 				//Beats per second

	/* Variables */
	var baseNotes = notes;			//Store the base notes to transpose from
	var type = type;				//Chord, scale, or interval
	var quality = quality;			//Answer
	var category = category;		//Category
	var numNotes = notes.length;	//Number of notes

	var tempSounds = [];			//Holds current sound
	var numLoaded = 0;				//Number of loaded files
	var timeouts = [];				//Timeout objects to keep track of when playing broken

	/**
	 * Plays the loaded files:
	 *  - Chords are played broken then blocked
	 *  - Scales are played broken
	 *  - Intervals are played broken
	 *
	 * @method play
	 * @param {String} style How to play the notes. No argument means play it quiz style
	 */
	this.play = function(style) {
		stop();
		clear();
		if(style == undefined) {
			//Play arpegiated and then play block
			if(type == CHORD) {
				if(category == TWENTIETH) {
					playBlock();
				}
				else {
					playBlock();
					timeouts.push(setTimeout(function() {playBroken();}, (1/bps)*2000));
				}
			}
			//Play broken
			else if(type == SCALE) {
				playBroken();
			}
			else if(type == INTERVAL) {
				playBroken();
			}
			else {
				playBroken();
			}
		}
	}

	/**
	 * Randomly transposes the notes given from the CSV file and gives them a random octave.
	 * Then loads the corresponding audio files.
	 *
	 * @method generate
	 */
	this.generate = function() {
		tempSounds = generateTransposition();
	}

	/**
	 * Returns the type and quality
	 *
	 * @method answer
	 * @return {String} quality + type
	 */
	this.answer = function() {
		return quality+" "+type;
	}

	/**
	 * Stops all sound
	 *
	 * @method stopSound
	 */
	this.stopSound = function() {
		stop();
		clear();
	}

	/**
	 * Transposes and sets octave of the notes from the CSV file randomly, then loads the
	 * corresponding files
	 *
	 * @method generateTransposition
	 * @return {Howl Array} An array of Howl objects that have the loaded audio files
	 * @private
	 */
	function generateTransposition() {
		var randKey = Math.floor(Math.random()*13)-6;	//Get Random key between -7 and 7
		var tempNotes = setNotes(randKey);		//Array of transposed keys
		tempNotes = setOctave(tempNotes);		//Set a random octave
		return loadFiles(tempNotes);			//Load the corresponding files
	}

	/**
	 * Tranposes the notes from the CSV file a given number of sharps or flats
	 *
	 * @method setNotes
	 * @param {Integer} shift How much to transpose the notes by
	 * @return {String Array} Array of the notes after transposition
	 * @private
	 */
	function setNotes(shift) {
		return transpose(baseNotes, shift);
	}

	/**
	 * Plays the note at the given index in the loaded files array
	 *
	 * @method playNote
	 * @param {Integer} i Index of the note to be played
	 * @private
	 */
	function playNote(i) {
		//Don't let notes bleed if playing a scale
		if(type == SCALE) {
			stop();
		}

		tempSounds[i].play();
	}

	/**
	 * Plays all notes at the same time
	 *
	 * @method playBlock
	 * @private
	 */
	function playBlock() {
		for(i = 0; i < numNotes; i++) {
			tempSounds[i].play();
		}
	}

	/*
	 * Plays all notes in sequence with timing based on bpm
	 *
	 * @method playBroken
	 * @private
	 */
	function playBroken() {
		//Play first note instantly
		timeouts.push(setTimeout(function() {
			playNote(0);
			playBrokenHelp(1);		//Play rest of notes
		}, 0));
	}

	/*
	 * Recursive helper for playBroken()
	 *
	 * @method playBrokenHelp
	 * @param {Integer} note An index representing the note to be played
	 * @private
	 */
	function playBrokenHelp(note) {
		if(note < numNotes) {
			timeouts.push(setTimeout(function() {
				playNote(note);
				playBrokenHelp(note+1);
			}, (1/bps)*1000)); //How many seconds per note given the bpm
		}
	}

	/*
	 * Stops all sound immediately
	 *
	 * @method stop
	 * @private
	 */
	function stop() {
		for(i = 0; i < tempSounds.length; i++) {
			tempSounds[i].stop();
		}
	}

	/*
	 * Clears all timeouts (delayed sounds)
	 *
	 * @method clear
	 * @private
	 */
	function clear() {
		var initLength = timeouts.length;
		for(i = 0; i < initLength; i++) {
			clearTimeout(timeouts[timeouts.length-1]);
			timeouts.pop();
		}
	}

	/*
	 * Takes the notes and converts them into Howl objects with the appropriate
	 * sound files.
	 *
	 * @method loadFiles
	 * @param {String Array} notes Array of notes to be loaded
	 * @return {Howl Array} Array of Howl objects containing the corresponding audio files
	 * @private
	 */
	function loadFiles(notes) {
		var midi = [];		//Store notes as midi numbers
		var files = [];		//Store file paths to corresponding files
		var sounds = [];	//Howl objects of files

		//Get midi numbers of given notes
		for(i = 0; i < numNotes; i++) {
			midi.push(noteToFileNum[notes[i]]);
			//Error checking
			if(midi[i] == undefined) {
				console.log("Error: Check notation for "+quality+" "+type);
			}
		}

		//Convert midi numbers to their corresponding file names
		files = convMidiToFile(midi);

		//Load sound files
		for(i = 0; i < numNotes; i++) {
			sounds.push(new Howl({
				urls : [files[i]],
				onload : function() {
					numLoaded++;
					console.log("Loaded note "+numLoaded);
					if(numLoaded == numNotes) {
						document.getElementById("loading").style.display = "none";
						document.getElementById("allbuttons").style.display = "block";
						numLoaded = 0;
					}
				},
				onloaderror : function() {console.log(quality+" "+type+" "+i+" loading error")}
			}));
		}
		return sounds;
	}

	/*
 	 * Converts midi numbers to their corresponding file names
 	 *
 	 * @method convMidiToFile
 	 * @param {Integer Array} midi Array of midi numbers to be converted into files
 	 * @return {String Array} Array of strings containing the proper file paths to the audio files
 	 * @private
 	 */
	function convMidiToFile(midi) {
		var files = [];
		for(i = 0; i < numNotes; i++) {
			files.push("audio/piano/piano"+midi[i]+".wav");
		}
		return files;
	}
}
<|endoftext|>


<commit_before>"use strict";

var util = require('util');
var binding = require('./incremental');
var algorithms = {};

exports.getHashes = function() {
  return Object.keys(binding)
        .filter(function(name) {
          return 'function' === typeof binding[name];
        })
        .map(function(name) { return name.toLowerCase(); });
};

Object.keys(binding).forEach(function(name) {
  if (binding.hasOwnProperty(name) && 'function' === typeof binding[name]) {
    algorithms[name.toLowerCase()] = binding[name];
  }
});

algorithms.murmurhash3a = algorithms.murmurhash32 = algorithms.murmurhash32x86 = algorithms.murmurhash;

/* from nodejs lib/crypto.js */

var LazyTransform = require('./lazy_transform');

/**
 * Creates and returns a MurmurHash object that can be used to generate murmurhash digests.
 *
 * Except murmur's `seed` option, the rest of the options are passed to
 * stream.Transform constructor.
 *
 * @param {string|MurmurHash} algorithm|hasher - one of available algorithms
 *                            or a murmur hasher instance
 * @param {number|object} seed|options - hasher options
 **/
exports.createHash = exports.MurmurHash = MurmurHash;
function MurmurHash(algorithm, options) {
  var seed;

  if (!(this instanceof MurmurHash))
    return new MurmurHash(algorithm, options);

  if (options && 'object' === typeof options) {
    seed = options.seed;
  } else {
    seed = options; options = undefined;
  }

  if (algorithm instanceof MurmurHash) {
    this._handle = new algorithm._handle.constructor(algorithm._handle);
  } else if (algorithm) {
    // handle object from json
    if ('object' === typeof algorithm) {
      seed = algorithm.seed;
      algorithm = algorithm.type;
    }
    var Handle = algorithms[algorithm.toLowerCase()];
    if (Handle) {
      this._handle = new Handle(seed);
    } else {
      throw new Error("Algorithm not supported");
    }
  } else {
    throw new TypeError("Must give algorithm string or MurmurHash instance");
  }

  LazyTransform.call(this, options);
}

util.inherits(MurmurHash, LazyTransform);

MurmurHash.prototype._transform = function(chunk, encoding, callback) {
  if (chunk.length < 8192) { // this constant was chosen experimentally
    this._handle.update(chunk, encoding);
    callback();
  } else {
    this._handle.update(chunk, encoding, callback);
  }
};

MurmurHash.prototype._flush = function(callback) {
  this.push(this._handle.digest());
  callback();
};

MurmurHash.prototype.update = function() {
  var handle = this._handle;
  return handle.update.apply(handle, arguments) && this;
};

MurmurHash.prototype.digest = function() {
  var handle = this._handle;
  return handle.digest.apply(handle, arguments);
};

MurmurHash.prototype.serialize = function(type, offset) {
  return this._handle.serialize(type, offset);
};

MurmurHash.prototype.copy = function(target) {
  this._handle.copy(target && target._handle);
  return target;
};

MurmurHash.prototype.toJSON = function() {
  var handle = this._handle;
  return {
    type: handle.constructor.name,
    seed: handle.toJSON()
  };
};

Object.defineProperty(MurmurHash.prototype, 'isBusy', {
  get: function() {
    return this._handle.isBusy;
  },
  enumerable: false,
  configurable: false
});

Object.defineProperty(MurmurHash.prototype, 'total', {
  get: function() {
    return this._handle.total;
  },
  enumerable: true,
  configurable: true
});

Object.defineProperty(MurmurHash.prototype, 'endianness', {
  get: function() {
    return this._handle.endianness;
  },
  enumerable: true,
  configurable: false
});

Object.defineProperty(MurmurHash.prototype, 'SERIAL_BYTE_LENGTH', {
  get: function() {
    Object.defineProperty(this, 'SERIAL_BYTE_LENGTH', {
      enumerable: true,
      writable: true,
      configurable: true,
      value: this._handle.SERIAL_BYTE_LENGTH
    });
    return this.SERIAL_BYTE_LENGTH;
  },
  enumerable: true,
  configurable: true,
});
<commit_msg>stream: endianness option and setter<commit_after>"use strict";

var util = require('util');
var binding = require('./incremental');
var algorithms = {};

exports.getHashes = function() {
  return Object.keys(binding)
        .filter(function(name) {
          return 'function' === typeof binding[name];
        })
        .map(function(name) { return name.toLowerCase(); });
};

Object.keys(binding).forEach(function(name) {
  if (binding.hasOwnProperty(name) && 'function' === typeof binding[name]) {
    algorithms[name.toLowerCase()] = binding[name];
  }
});

algorithms.murmurhash3a = algorithms.murmurhash32 = algorithms.murmurhash32x86 = algorithms.murmurhash;

/* from nodejs lib/crypto.js */

var LazyTransform = require('./lazy_transform');

/**
 * Creates and returns a MurmurHash object that can be used to generate murmurhash digests.
 *
 * Except murmur's `seed` and `endianness` options, the rest of the options are passed to
 * stream.Transform constructor.
 *
 * @param {string|MurmurHash} algorithm|hasher - one of available algorithms
 *                            or a murmur hasher instance
 * @param {number|object} seed|options - hasher options
 **/
exports.createHash = exports.MurmurHash = MurmurHash;
function MurmurHash(algorithm, options) {
  var seed, endianness;

  if (!(this instanceof MurmurHash))
    return new MurmurHash(algorithm, options);

  if (options && 'object' === typeof options) {
    seed = options.seed;
    endianness = options.endianness;
  } else {
    seed = options; options = undefined;
  }

  if (algorithm instanceof MurmurHash) {
    this._handle = new algorithm._handle.constructor(algorithm._handle, endianness);
  } else if (algorithm) {
    // handle object from json
    if ('object' === typeof algorithm) {
      seed = algorithm.seed;
      algorithm = algorithm.type;
    }
    var Handle = algorithms[algorithm.toLowerCase()];
    if (Handle) {
      this._handle = new Handle(seed, endianness);
    } else {
      throw new Error("Algorithm not supported");
    }
  } else {
    throw new TypeError("Must give algorithm string or MurmurHash instance");
  }

  LazyTransform.call(this, options);
}

util.inherits(MurmurHash, LazyTransform);

MurmurHash.prototype._transform = function(chunk, encoding, callback) {
  if (chunk.length < 8192) { // this constant was chosen experimentally
    this._handle.update(chunk, encoding);
    callback();
  } else {
    this._handle.update(chunk, encoding, callback);
  }
};

MurmurHash.prototype._flush = function(callback) {
  this.push(this._handle.digest());
  callback();
};

MurmurHash.prototype.update = function() {
  var handle = this._handle;
  return handle.update.apply(handle, arguments) && this;
};

MurmurHash.prototype.digest = function() {
  var handle = this._handle;
  return handle.digest.apply(handle, arguments);
};

MurmurHash.prototype.serialize = function(type, offset) {
  return this._handle.serialize(type, offset);
};

MurmurHash.prototype.copy = function(target) {
  this._handle.copy(target && target._handle);
  return target;
};

MurmurHash.prototype.toJSON = function() {
  var handle = this._handle;
  return {
    type: handle.constructor.name,
    seed: handle.toJSON()
  };
};

Object.defineProperty(MurmurHash.prototype, 'isBusy', {
  get: function() {
    return this._handle.isBusy;
  },
  enumerable: false,
  configurable: false
});

Object.defineProperty(MurmurHash.prototype, 'total', {
  get: function() {
    return this._handle.total;
  },
  enumerable: true,
  configurable: true
});

Object.defineProperty(MurmurHash.prototype, 'endianness', {
  get: function() {
    return this._handle.endianness;
  },
  set: function(value) {
    this._handle.endianness = value;
  },
  enumerable: true,
  configurable: false
});

Object.defineProperty(MurmurHash.prototype, 'SERIAL_BYTE_LENGTH', {
  get: function() {
    Object.defineProperty(this, 'SERIAL_BYTE_LENGTH', {
      enumerable: true,
      writable: true,
      configurable: true,
      value: this._handle.SERIAL_BYTE_LENGTH
    });
    return this.SERIAL_BYTE_LENGTH;
  },
  enumerable: true,
  configurable: true,
});
<|endoftext|>


<commit_before>const MBContract      = require('./mb_contract');
const MBDefaults      = require('./mb_defaults');
const MBNotifications = require('./mb_notifications');
const TradingAnalysis = require('../trade/analysis');
const redrawChart     = require('../trade/charts/webtrader_chart').redrawChart;
const ViewPopup       = require('../user/view_popup/view_popup');
const Client          = require('../../base/client');
const GTM             = require('../../base/gtm');
const BinarySocket    = require('../../base/socket');
const jpClient        = require('../../common/country_base').jpClient;
const formatMoney     = require('../../common/currency').formatMoney;
const localize        = require('../../../_common/localize').localize;
const isEmptyObject   = require('../../../_common/utility').isEmptyObject;

/*
 * Price object handles all the functions we need to display prices
 *
 * We create Price proposal that we need to send to server to get price,
 * longcode and all other information that we need to get the price for
 * current contract
 *
 */

const MBPrice = (() => {
    const price_selector = '.prices-wrapper .price-rows';
    const is_japan       = jpClient();

    let prices         = {};
    let contract_types = {};
    let el_rows        = {};
    let barriers       = [];
    let req_id         = 0;
    let is_displayed   = false;
    let is_unwelcome   = false;

    let $table;

    const addPriceObj = (req) => {
        req.barriers.forEach((barrier_obj) => {
            const barrier = makeBarrier(barrier_obj);
            if (!prices[barrier]) {
                prices[barrier] = {};
            }
            req.contract_type.forEach((c_type) => {
                prices[barrier][c_type] = {};
                if (!contract_types[c_type]) {
                    contract_types[c_type] = MBContract.getTemplate(c_type);
                }
            });
        });
    };

    const updateTabsAndChart = () => {
        TradingAnalysis.bindAnalysisTabEvent();
        TradingAnalysis.request();
        redrawChart();
    };

    const makeBarrier = (barrier_object) => {
        if (!barrier_object.barrier && barrier_object.error) {
            // error.details will include the barrier value in case of error
            // it is intended to change the original object as we need the barrier value
            barrier_object = barrier_object.error.details; // eslint-disable-line no-param-reassign
        }
        return (barrier_object.barrier2 ? `${barrier_object.barrier2}_` : '') + barrier_object.barrier;
    };

    const display = (response) => {
        if (isEmptyObject(response.proposal_array.proposals)) { // ignore invalid responses
            updateTabsAndChart();
            return;
        }
        Object.keys(response.proposal_array.proposals).forEach((contract_type) => {
            response.proposal_array.proposals[contract_type].forEach((proposal) => {
                const barrier                  = makeBarrier(proposal);
                const prev_proposal            = $.extend({}, prices[barrier][contract_type]);
                prices[barrier][contract_type] = $.extend({ echo_req: response.echo_req }, proposal);

                // update previous ask_price to use in price movement
                if (!isEmptyObject(prev_proposal) && !prev_proposal.error) {
                    prices[barrier][contract_type].prev_price = prev_proposal.ask_price;
                }
            });
        });

        if (!is_displayed) {
            populateTable();
        }
        updatePrices();
    };

    const populateTable = () => {
        if (!$table) {
            $table = $(price_selector);
        }
        $table.off('click', 'button.price-button').on('click', 'button.price-button', processBuy);

        BinarySocket.wait('get_account_status').then((response) => {
            is_unwelcome = /unwelcome/.test(response.get_account_status.status);
            if (is_unwelcome) {
                MBNotifications.show({
                    text       : localize('Sorry, your account is not authorised for any further contract purchases.'),
                    uid        : 'UNWELCOME',
                    dismissible: false,
                });
            }
        });

        if (!barriers.length) {
            barriers = Object.keys(prices).sort((a, b) => +b.split('_')[0] - (+a.split('_')[0]));
        }

        const el_price_row = document.querySelector('#templates .price-row');
        if (is_japan) {
            el_price_row.querySelectorAll('.base-value').forEach((el) => {
                el.classList.remove('invisible');
            });
        }
        barriers.forEach((barrier) => {
            el_rows[barrier] = {};
            const el_row = el_price_row.cloneNode(true);
            el_row.setAttribute('data-barrier', barrier);
            el_row.querySelector('.barrier').innerHTML = barrier.replace(/_/g, '
');
            Object.keys(contract_types).forEach((contract_type) => {
                if (!el_rows[barrier][contract_type]) {
                    el_rows[barrier][contract_type] = {};
                }

                const order = contract_types[contract_type].order;
                const el_buy  = el_row.querySelectorAll('.buy-price button')[order];
                const el_sell = el_row.querySelectorAll('.sell-price .price-wrapper')[order];

                el_buy.setAttribute('data-barrier', barrier);
                el_buy.setAttribute('data-contract_type', contract_type);

                el_rows[barrier][contract_type].buy = {
                    btn: el_buy,
                    dyn: el_buy.getElementsByClassName('dynamics')[0],
                    val: el_buy.getElementsByClassName('value')[0],
                };
                el_rows[barrier][contract_type].sell = {
                    sell: el_sell,
                    val : el_sell.getElementsByClassName('value')[0],
                };

                if (is_japan) {
                    el_rows[barrier][contract_type].buy.base_value  = el_buy.getElementsByClassName('base-value')[0];
                    el_rows[barrier][contract_type].sell.base_value = el_sell.getElementsByClassName('base-value')[0];
                }

                updatePriceRow(getValues(prices[barrier][contract_type], contract_type));
            });
            $table.append(el_row);
        });

        hidePriceOverlay();
        MBNotifications.hideSpinnerShowTrading();
        is_displayed = true;

        // Analysis should be initialised after contents being displayed,
        // so the chart is able to get the proper container width/height
        updateTabsAndChart();
    };

    const updatePrices = () => {
        Object.keys(contract_types).forEach((contract_type) => {
            barriers.forEach((barrier) => {
                const proposal   = prices[barrier][contract_type];
                const price_rows = document.querySelectorAll(`${price_selector} div[data-barrier="${makeBarrier(proposal)}"]`);

                if (!price_rows.length) return;

                const contract_type_opp = contract_types[contract_type].opposite;

                updatePriceRow(getValues(proposal, contract_type));
                updatePriceRow(getValues(prices[barrier][contract_type_opp], contract_type_opp));
            });
        });
    };

    const getValues = (proposal, contract_type) => {
        const barrier      = makeBarrier(proposal);
        const payout       = proposal.echo_req.amount;
        const proposal_opp = prices[barrier][contract_types[contract_type].opposite];
        const time_left    = MBContract.getRemainingTime();
        return {
            contract_type,
            barrier,
            payout             : payout / 1000,
            is_active          : !proposal.error && proposal.ask_price && !is_unwelcome && time_left > 120,
            message            : proposal.error && proposal.error.code !== 'RateLimit' ? proposal.error.message : '',
            ask_price          : getAskPrice(proposal),
            sell_price         : payout - getAskPrice(proposal_opp),
            ask_price_movement : !proposal.error ? getMovementDirection(proposal.prev_price, proposal.ask_price) : '',
            sell_price_movement: proposal_opp && !proposal_opp.error ? getMovementDirection(proposal_opp.ask_price, proposal_opp.prev_price) : '',
        };
    };

    const getAskPrice = proposal => (
        // In case of RateLimit error, there is no display_value, so we display the request amount
        (proposal.error || +proposal.ask_price === 0) ? proposal.echo_req.amount : proposal.ask_price
    );

    const getMovementDirection = (prev, current) => {
        let movement = '';
        if (prev !== current) {
            movement = current > prev ? 'up' : 'down';
        }
        return movement;
    };

    const updatePriceRow = (values) => {
        const el_buy  = el_rows[values.barrier][values.contract_type].buy;
        const el_sell = el_rows[values.barrier][values.contract_type].sell;

        el_buy.btn.classList[values.is_active ? 'remove' : 'add']('inactive');
        el_buy.btn[values.message ? 'setAttribute' : 'removeAttribute']('data-balloon', values.message);
        el_buy.btn[values.message ? 'setAttribute' : 'removeAttribute']('data-balloon-length', 'large');
        el_buy.dyn.setAttribute('class', `dynamics ${values.ask_price_movement || ''}`);
        el_buy.val.textContent = formatPrice(values.ask_price);

        el_sell.sell.classList[values.sell_price ? 'remove' : 'add']('inactive');
        el_sell.val.textContent = formatPrice(values.sell_price);

        if (is_japan) {
            el_buy.base_value.textContent  = formatPrice(values.ask_price / values.payout);
            el_sell.base_value.textContent = formatPrice(values.sell_price / values.payout);
        }
    };

    const processBuy = (e) => {
        e.preventDefault();

        if (!Client.isLoggedIn()) {
            MBNotifications.show({ text: localize('Please log in.'), uid: 'LOGIN_ERROR', dismissible: true });
            return;
        }

        let $btn = $(e.target);
        if ($btn.prop('tagName').toLowerCase() !== 'button') {
            $btn = $btn.parents('button.price-button');
        }

        if ($btn.hasClass('inactive')) return;

        const barrier       = $btn.attr('data-barrier');
        const contract_type = $btn.attr('data-contract_type');
        if (!barrier || !contract_type) return;

        showPriceOverlay();
        sendBuyRequest(barrier, contract_type);
    };

    const formatPrice = price => formatMoney(MBContract.getCurrency(), price, 1);

    const cleanup = () => {
        prices         = {};
        contract_types = {};
        barriers       = [];
        is_displayed   = false;
        el_rows        = {};
        // display loading
        if ($(price_selector).html()) {
            $('#loading-overlay').height($(price_selector).height()).setVisibility(1);
        }
        $(price_selector).html('');
    };

    const sendBuyRequest = (barrier, contract_type) => {
        if (MBDefaults.get('disable_trading')) {
            MBNotifications.show({ text: 'You have disabled the trading.', uid: 'TRADING_DISABLED', dismissible: true });
            return;
        }
        MBNotifications.hide('TRADING_DISABLED');

        const proposal = prices[barrier][contract_type];
        if (!proposal || proposal.error) return;

        const req = {
            buy       : 1,
            price     : proposal.ask_price,
            parameters: {
                contract_type,
                amount               : proposal.echo_req.amount,
                barrier              : proposal.barrier,
                basis                : 'payout',
                currency             : MBContract.getCurrency(),
                symbol               : proposal.echo_req.symbol,
                date_expiry          : proposal.echo_req.date_expiry,
                trading_period_start : proposal.echo_req.trading_period_start,
                product_type         : 'multi_barrier',
                app_markup_percentage: '0',
            },
        };

        if (proposal.barrier2) {
            req.parameters.barrier2 = proposal.barrier2;
        }

        BinarySocket.send(req).then((response) => {
            if (response.error) {
                hidePriceOverlay();
                MBNotifications.show({ text: response.error.message, uid: 'BUY_ERROR', dismissible: true });
            } else {
                MBNotifications.hide('BUY_ERROR');
                ViewPopup.init($('
', { contract_id: response.buy.contract_id }).get(0));
                GTM.pushPurchaseData(response);
            }
        });
    };

    const showPriceOverlay = () => {
        $('#disable-overlay').setVisibility(1);
        $('#loading-overlay').setVisibility(0);
    };

    const hidePriceOverlay = () => {
        if (!MBDefaults.get('disable_trading')) {
            $('#disable-overlay').setVisibility(0);
        }
        $('#loading-overlay').setVisibility(0);
    };

    return {
        display,
        addPriceObj,
        cleanup,
        showPriceOverlay,
        hidePriceOverlay,

        getReqId     : () => req_id,
        increaseReqId: () => { req_id++; cleanup(); },
        getPrices    : () => prices,
        onUnload     : () => { cleanup(); req_id = 0; $table = undefined; },
    };
})();

module.exports = MBPrice;
<commit_msg>make container of error message smaller<commit_after>const MBContract      = require('./mb_contract');
const MBDefaults      = require('./mb_defaults');
const MBNotifications = require('./mb_notifications');
const TradingAnalysis = require('../trade/analysis');
const redrawChart     = require('../trade/charts/webtrader_chart').redrawChart;
const ViewPopup       = require('../user/view_popup/view_popup');
const Client          = require('../../base/client');
const GTM             = require('../../base/gtm');
const BinarySocket    = require('../../base/socket');
const jpClient        = require('../../common/country_base').jpClient;
const formatMoney     = require('../../common/currency').formatMoney;
const localize        = require('../../../_common/localize').localize;
const isEmptyObject   = require('../../../_common/utility').isEmptyObject;

/*
 * Price object handles all the functions we need to display prices
 *
 * We create Price proposal that we need to send to server to get price,
 * longcode and all other information that we need to get the price for
 * current contract
 *
 */

const MBPrice = (() => {
    const price_selector = '.prices-wrapper .price-rows';
    const is_japan       = jpClient();

    let prices         = {};
    let contract_types = {};
    let el_rows        = {};
    let barriers       = [];
    let req_id         = 0;
    let is_displayed   = false;
    let is_unwelcome   = false;

    let $table;

    const addPriceObj = (req) => {
        req.barriers.forEach((barrier_obj) => {
            const barrier = makeBarrier(barrier_obj);
            if (!prices[barrier]) {
                prices[barrier] = {};
            }
            req.contract_type.forEach((c_type) => {
                prices[barrier][c_type] = {};
                if (!contract_types[c_type]) {
                    contract_types[c_type] = MBContract.getTemplate(c_type);
                }
            });
        });
    };

    const updateTabsAndChart = () => {
        TradingAnalysis.bindAnalysisTabEvent();
        TradingAnalysis.request();
        redrawChart();
    };

    const makeBarrier = (barrier_object) => {
        if (!barrier_object.barrier && barrier_object.error) {
            // error.details will include the barrier value in case of error
            // it is intended to change the original object as we need the barrier value
            barrier_object = barrier_object.error.details; // eslint-disable-line no-param-reassign
        }
        return (barrier_object.barrier2 ? `${barrier_object.barrier2}_` : '') + barrier_object.barrier;
    };

    const display = (response) => {
        if (isEmptyObject(response.proposal_array.proposals)) { // ignore invalid responses
            updateTabsAndChart();
            return;
        }
        Object.keys(response.proposal_array.proposals).forEach((contract_type) => {
            response.proposal_array.proposals[contract_type].forEach((proposal) => {
                const barrier                  = makeBarrier(proposal);
                const prev_proposal            = $.extend({}, prices[barrier][contract_type]);
                prices[barrier][contract_type] = $.extend({ echo_req: response.echo_req }, proposal);

                // update previous ask_price to use in price movement
                if (!isEmptyObject(prev_proposal) && !prev_proposal.error) {
                    prices[barrier][contract_type].prev_price = prev_proposal.ask_price;
                }
            });
        });

        if (!is_displayed) {
            populateTable();
        }
        updatePrices();
    };

    const populateTable = () => {
        if (!$table) {
            $table = $(price_selector);
        }
        $table.off('click', 'button.price-button').on('click', 'button.price-button', processBuy);

        BinarySocket.wait('get_account_status').then((response) => {
            is_unwelcome = /unwelcome/.test(response.get_account_status.status);
            if (is_unwelcome) {
                MBNotifications.show({
                    text       : localize('Sorry, your account is not authorised for any further contract purchases.'),
                    uid        : 'UNWELCOME',
                    dismissible: false,
                });
            }
        });

        if (!barriers.length) {
            barriers = Object.keys(prices).sort((a, b) => +b.split('_')[0] - (+a.split('_')[0]));
        }

        const el_price_row = document.querySelector('#templates .price-row');
        if (is_japan) {
            el_price_row.querySelectorAll('.base-value').forEach((el) => {
                el.classList.remove('invisible');
            });
        }
        barriers.forEach((barrier) => {
            el_rows[barrier] = {};
            const el_row = el_price_row.cloneNode(true);
            el_row.setAttribute('data-barrier', barrier);
            el_row.querySelector('.barrier').innerHTML = barrier.replace(/_/g, '
');
            Object.keys(contract_types).forEach((contract_type) => {
                if (!el_rows[barrier][contract_type]) {
                    el_rows[barrier][contract_type] = {};
                }

                const order = contract_types[contract_type].order;
                const el_buy  = el_row.querySelectorAll('.buy-price button')[order];
                const el_sell = el_row.querySelectorAll('.sell-price .price-wrapper')[order];

                el_buy.setAttribute('data-barrier', barrier);
                el_buy.setAttribute('data-contract_type', contract_type);

                el_rows[barrier][contract_type].buy = {
                    btn: el_buy,
                    dyn: el_buy.getElementsByClassName('dynamics')[0],
                    val: el_buy.getElementsByClassName('value')[0],
                };
                el_rows[barrier][contract_type].sell = {
                    sell: el_sell,
                    val : el_sell.getElementsByClassName('value')[0],
                };

                if (is_japan) {
                    el_rows[barrier][contract_type].buy.base_value  = el_buy.getElementsByClassName('base-value')[0];
                    el_rows[barrier][contract_type].sell.base_value = el_sell.getElementsByClassName('base-value')[0];
                }

                updatePriceRow(getValues(prices[barrier][contract_type], contract_type));
            });
            $table.append(el_row);
        });

        hidePriceOverlay();
        MBNotifications.hideSpinnerShowTrading();
        is_displayed = true;

        // Analysis should be initialised after contents being displayed,
        // so the chart is able to get the proper container width/height
        updateTabsAndChart();
    };

    const updatePrices = () => {
        Object.keys(contract_types).forEach((contract_type) => {
            barriers.forEach((barrier) => {
                const proposal   = prices[barrier][contract_type];
                const price_rows = document.querySelectorAll(`${price_selector} div[data-barrier="${makeBarrier(proposal)}"]`);

                if (!price_rows.length) return;

                const contract_type_opp = contract_types[contract_type].opposite;

                updatePriceRow(getValues(proposal, contract_type));
                updatePriceRow(getValues(prices[barrier][contract_type_opp], contract_type_opp));
            });
        });
    };

    const getValues = (proposal, contract_type) => {
        const barrier      = makeBarrier(proposal);
        const payout       = proposal.echo_req.amount;
        const proposal_opp = prices[barrier][contract_types[contract_type].opposite];
        const time_left    = MBContract.getRemainingTime();
        return {
            contract_type,
            barrier,
            payout             : payout / 1000,
            is_active          : !proposal.error && proposal.ask_price && !is_unwelcome && time_left > 120,
            message            : proposal.error && proposal.error.code !== 'RateLimit' ? proposal.error.message : '',
            ask_price          : getAskPrice(proposal),
            sell_price         : payout - getAskPrice(proposal_opp),
            ask_price_movement : !proposal.error ? getMovementDirection(proposal.prev_price, proposal.ask_price) : '',
            sell_price_movement: proposal_opp && !proposal_opp.error ? getMovementDirection(proposal_opp.ask_price, proposal_opp.prev_price) : '',
        };
    };

    const getAskPrice = proposal => (
        // In case of RateLimit error, there is no display_value, so we display the request amount
        (proposal.error || +proposal.ask_price === 0) ? proposal.echo_req.amount : proposal.ask_price
    );

    const getMovementDirection = (prev, current) => {
        let movement = '';
        if (prev !== current) {
            movement = current > prev ? 'up' : 'down';
        }
        return movement;
    };

    const updatePriceRow = (values) => {
        const el_buy  = el_rows[values.barrier][values.contract_type].buy;
        const el_sell = el_rows[values.barrier][values.contract_type].sell;

        el_buy.btn.classList[values.is_active ? 'remove' : 'add']('inactive');
        el_buy.btn[values.message ? 'setAttribute' : 'removeAttribute']('data-balloon', values.message);
        el_buy.btn[values.message ? 'setAttribute' : 'removeAttribute']('data-balloon-length', 'medium');
        el_buy.dyn.setAttribute('class', `dynamics ${values.ask_price_movement || ''}`);
        el_buy.val.textContent = formatPrice(values.ask_price);

        el_sell.sell.classList[values.sell_price ? 'remove' : 'add']('inactive');
        el_sell.val.textContent = formatPrice(values.sell_price);

        if (is_japan) {
            el_buy.base_value.textContent  = formatPrice(values.ask_price / values.payout);
            el_sell.base_value.textContent = formatPrice(values.sell_price / values.payout);
        }
    };

    const processBuy = (e) => {
        e.preventDefault();

        if (!Client.isLoggedIn()) {
            MBNotifications.show({ text: localize('Please log in.'), uid: 'LOGIN_ERROR', dismissible: true });
            return;
        }

        let $btn = $(e.target);
        if ($btn.prop('tagName').toLowerCase() !== 'button') {
            $btn = $btn.parents('button.price-button');
        }

        if ($btn.hasClass('inactive')) return;

        const barrier       = $btn.attr('data-barrier');
        const contract_type = $btn.attr('data-contract_type');
        if (!barrier || !contract_type) return;

        showPriceOverlay();
        sendBuyRequest(barrier, contract_type);
    };

    const formatPrice = price => formatMoney(MBContract.getCurrency(), price, 1);

    const cleanup = () => {
        prices         = {};
        contract_types = {};
        barriers       = [];
        is_displayed   = false;
        el_rows        = {};
        // display loading
        if ($(price_selector).html()) {
            $('#loading-overlay').height($(price_selector).height()).setVisibility(1);
        }
        $(price_selector).html('');
    };

    const sendBuyRequest = (barrier, contract_type) => {
        if (MBDefaults.get('disable_trading')) {
            MBNotifications.show({ text: 'You have disabled the trading.', uid: 'TRADING_DISABLED', dismissible: true });
            return;
        }
        MBNotifications.hide('TRADING_DISABLED');

        const proposal = prices[barrier][contract_type];
        if (!proposal || proposal.error) return;

        const req = {
            buy       : 1,
            price     : proposal.ask_price,
            parameters: {
                contract_type,
                amount               : proposal.echo_req.amount,
                barrier              : proposal.barrier,
                basis                : 'payout',
                currency             : MBContract.getCurrency(),
                symbol               : proposal.echo_req.symbol,
                date_expiry          : proposal.echo_req.date_expiry,
                trading_period_start : proposal.echo_req.trading_period_start,
                product_type         : 'multi_barrier',
                app_markup_percentage: '0',
            },
        };

        if (proposal.barrier2) {
            req.parameters.barrier2 = proposal.barrier2;
        }

        BinarySocket.send(req).then((response) => {
            if (response.error) {
                hidePriceOverlay();
                MBNotifications.show({ text: response.error.message, uid: 'BUY_ERROR', dismissible: true });
            } else {
                MBNotifications.hide('BUY_ERROR');
                ViewPopup.init($('
', { contract_id: response.buy.contract_id }).get(0));
                GTM.pushPurchaseData(response);
            }
        });
    };

    const showPriceOverlay = () => {
        $('#disable-overlay').setVisibility(1);
        $('#loading-overlay').setVisibility(0);
    };

    const hidePriceOverlay = () => {
        if (!MBDefaults.get('disable_trading')) {
            $('#disable-overlay').setVisibility(0);
        }
        $('#loading-overlay').setVisibility(0);
    };

    return {
        display,
        addPriceObj,
        cleanup,
        showPriceOverlay,
        hidePriceOverlay,

        getReqId     : () => req_id,
        increaseReqId: () => { req_id++; cleanup(); },
        getPrices    : () => prices,
        onUnload     : () => { cleanup(); req_id = 0; $table = undefined; },
    };
})();

module.exports = MBPrice;
<|endoftext|>


<commit_before>const superagent = require('superagent')
const logger = require('./Logger/winston.js')
const config = require('./config.js')[process.env.NODE_ENV]

logger.info('Initialising the routes for the server')
logger.info(config)

let internals = {}
let clients = []

internals.serveHomePage = function (request, reply) {
  logger.info('serveHomePage | Serve Home')
  reply.file('views/home.html')
}

internals.serveFavicon = function (request, reply) {
  logger.info('serveFavicon | Serve Favicon')
  reply('success')
}

internals.serveResultPage = function (request, reply) {
  const remote = request.params.repoName
  const API_BASE_URL = config.API_BASE_URL
  const CALLBACK_URL = config.FRONT_URL + '/callback'

  const redisClient = request.server.plugins['hapi-redis'].client

  redisClient.get(remote, function(err, res) {
    if(err) {
      logger.error('Redis Connection failed : ', err)
    }
    if (res === null) {
      logger.warn('Redis Cache missed. ', res)
    }
    logger.info('Data found in cache', res)
  })

  logger.info('serveResultPage', '|', 'callback url:', CALLBACK_URL, 'api base url: ', API_BASE_URL)

  superagent
    .get(API_BASE_URL + '/badges')
      .query({ download: 'git', remote: remote, callback: CALLBACK_URL }) // query string
      .end(function (err, res) {
        // Do something
        if (err) {
          const errorMsg = 'Error in posting to API: '
          logger.error(errorMsg, err)
          reply(errorMsg).code(404)
        }
        logger.info('POST /badges')
        reply.file('views/result.html')
      })
}

internals.handleCallback = function (request, reply) {
  const badges = request.payload.badges
  const remote = request.payload.remote
  const error = request.payload.error
  const redisClient = request.server.plugins['hapi-redis'].client

  redisClient.set(remote, badges, function(err, res) {
    if(err) {
      logger.warn('Redis connection screwed', err)
    }
    if(res == 'OK') {
      logger.info('Successfully cached for remote: ', remote)
    }
  })

  logger.info('In handleCallback | ', 'Remote: ', remote)

  if (error) {
    logger.error('handleCallback', error)
    reply('Error', error).code(404)
    return
  }

  global.io.sockets.on('connection', function (socket) {
    // Socket connected
    logger.info('Socket connected| (New client id=' + socket.id + ').')

    // Save the socket id to redis store
    clients.push(socket)

    // Send an event once socket is connected
    logger.info('Data emitted: | (New client id=' + socket.id + ').')

    // Remove the socket on disconnection
    socket.on('disconnect', function () {
      var socketIndex = clients.indexOf(socket)
      if (socketIndex !== -1) {
        clients.splice(socketIndex, 1)
        logger.info('Client gone (id=' + socket.id + ').')
      }
    })
  })
  reply('success')
}

module.exports = [
  {
    method: 'GET',
    path: '/',
    handler: internals.serveHomePage
  },
  // Serve static routes
  {
    method: 'GET',
    path: '/{param*}',
    handler: {
      directory: {
        path: '.',
        redirectToSlash: true,
        index: true
      }
    }
  },
  {
    method: 'GET',
    path: '/favicon.ico',
    handler: internals.serveFavicon
  },
  {
    method: 'POST',
    path: '/callback',
    handler: internals.handleCallback
  },
  {
    method: 'GET',
    path: '/w/{repoName*}',
    handler: internals.serveResultPage
  }
]
<commit_msg>add back emitter<commit_after>const superagent = require('superagent')
const logger = require('./Logger/winston.js')
const config = require('./config.js')[process.env.NODE_ENV]

logger.info('Initialising the routes for the server')
logger.info(config)

let internals = {}
let clients = []

internals.serveHomePage = function (request, reply) {
  logger.info('serveHomePage | Serve Home')
  reply.file('views/home.html')
}

internals.serveFavicon = function (request, reply) {
  logger.info('serveFavicon | Serve Favicon')
  reply('success')
}

internals.serveResultPage = function (request, reply) {
  const remote = request.params.repoName
  const API_BASE_URL = config.API_BASE_URL
  const CALLBACK_URL = config.FRONT_URL + '/callback'

  const redisClient = request.server.plugins['hapi-redis'].client

  reply.file('views/result.html')

  redisClient.get(remote, function(err, res) {
    if(err) {
      logger.error('Redis Connection failed : ', err)
    }
    if (res === null) {
      logger.warn('Redis Cache missed. ', res)
    }
    logger.info('Data found in cache', res)

  })

  logger.info('serveResultPage', '|', 'callback url:', CALLBACK_URL, 'api base url: ', API_BASE_URL)

  superagent
    .get(API_BASE_URL + '/badges')
      .query({ download: 'git', remote: remote, callback: CALLBACK_URL }) // query string
      .end(function (err, res) {
        // Do something
        if (err) {
          const errorMsg = 'Error in posting to API: '
          logger.error(errorMsg, err)
          reply(errorMsg).code(404)
        }
        logger.info('POST /badges')
      })
}

internals.handleCallback = function (request, reply) {
  const badges = request.payload.badges
  const remote = request.payload.remote
  const error = request.payload.error
  const redisClient = request.server.plugins['hapi-redis'].client

  redisClient.set(remote, badges, function(err, res) {
    if(err) {
      logger.warn('Redis connection screwed', err)
    }
    if(res == 'OK') {
      logger.info('Successfully cached for remote: ', remote)
    }
  })

  logger.info('In handleCallback | ', 'Remote: ', remote)

  if (error) {
    logger.error('handleCallback', error)
    reply('Error', error).code(404)
    return
  }

  global.io.sockets.on('connection', function (socket) {
    // Socket connected
    logger.info('Socket connected| (New client id=' + socket.id + ').')

    // Save the socket id to redis store
    clients.push(socket)

    // Send an event once socket is connected
    logger.info('Data emitted: | (New client id=' + socket.id + ').')

    socket.emit('news', { reqData: badges })
    // Remove the socket on disconnection
    socket.on('disconnect', function () {
      var socketIndex = clients.indexOf(socket)
      if (socketIndex !== -1) {
        clients.splice(socketIndex, 1)
        logger.info('Client gone (id=' + socket.id + ').')
      }
    })
  })
  reply('success')
}

module.exports = [
  {
    method: 'GET',
    path: '/',
    handler: internals.serveHomePage
  },
  // Serve static routes
  {
    method: 'GET',
    path: '/{param*}',
    handler: {
      directory: {
        path: '.',
        redirectToSlash: true,
        index: true
      }
    }
  },
  {
    method: 'GET',
    path: '/favicon.ico',
    handler: internals.serveFavicon
  },
  {
    method: 'POST',
    path: '/callback',
    handler: internals.handleCallback
  },
  {
    method: 'GET',
    path: '/w/{repoName*}',
    handler: internals.serveResultPage
  }
]
<|endoftext|>


<commit_before>var logger = require('./logger');
var juego = require('./juego');
var errorHandler = require('./errorHandler');
var loginModule = require('./loginModule');

var messageHandler = (function(){

    return {
        procesar: function(msj, client){

            switch(msj.operacion){
                case "iniciarJuego":
                    logger.log("El cliente "+ msj.session.username + " empezo la partida");
                    juego.iniciarJuego();
                    break;
                case "conectarJugador":
                    //logger.log("Jugador identificado como: "+ JSON.stringify(msj.datosLoginJugador) + " se conecto! ");

                    var jugador = loginModule.login(msj.datosLoginJugador, client);
                    if(jugador)
                        juego.agregarJugador(jugador);
                    break;
                case "robarCartas":
                    logger.log("El cliente "+ msj.session.username + " quiere robar "+ msj.cantidad + " cartas.");

                    juego.robarCartas(msj.session, msj.cantidad);
                    break;
                default:
                    errorHandler.error("Llego un msj equivocado: '"+msj.operacion+"'.");
            }
        }
    }

})();

module.exports = messageHandler;<commit_msg>Reestructurado el handler para que sea mas cohesivo y claro el manejo de cada mensaje distinto. Separado el metodo de identificacion del cliente, con el procesamiento de su pedido.<commit_after>var logger = require('./logger');
var juego = require('./juego');
var errorHandler = require('./errorHandler');
var loginModule = require('./loginModule');
var jugadoresRepository = require('./jugadoresRepository');

var messageHandler = (function(){

    //private
    var loginJugador = function (msj, client) {

        var jugadorLogueado = null;

        try{
             jugadorLogueado = loginModule.login(msj.datosLoginJugador, client);

        }catch(e){
            logger.logError(e);
            if(e.name === "JugadorLoginError") {
                client.send(messageFactory.msjErrorLogin(e));
                throw e;
            }
        } finally {
            return jugadorLogueado;
        }
    }

    //private
    var identificarJugador = function (msj) {

        var conectados = jugadoresRepository.getJugadoresConectados();

        var jugador = jugadoresRepository.getJugador(msj.session);
        if(!jugador)
            throw {
                name: "JugadorNoIdentificadoError",
                message: "No se pudo identificar al jugador: "+ msj.session.username+", que mando msj: "+msj
            }

        return jugador;
    }

    var identificarOLoggear = function(msj, client) {
        var jugador = null;

        if(msj.operacion==="conectarJugador")
            jugador = loginJugador(msj, client);

        if(!jugador) {
            jugador = identificarJugador(msj);

        }

        return jugador;
    }

    var iniciarJuego = function (jugador) {
        logger.log("El jugador "+ jugador.getUsername() + " empezo la partida");
        juego.iniciarJuego();
    }

    var conectarJugador = function (jugadorLogueado) {
        juego.agregarJugador(jugadorLogueado);

    }

    var robarCartas = function (jugador, msj) {

        logger.log("El jugador "+ jugador.getUsername() + " quiere robar "+ msj.cantidad + " cartas.");

        juego.robarCartas(jugador, msj.cantidad);
    }

    var bajarCarta = function (jugador, msj) {

        var cartaInfo = Carta(msj.cartaId);
        logger.log("El jugador "+  jugador.getUsername() + " bajo carta "+ cartaInfo.nombre);
        juego.bajarCarta(jugador, cartaInfo);
    }

    var resolver = {
        iniciarJuego: iniciarJuego,
        conectarJugador: conectarJugador,
        robarCartas: robarCartas,
        bajarCarta: bajarCarta
    }
    return {
        procesar: function (msj, client) {
            try{
                var jugador = identificarOLoggear(msj, client);
                logger.log("Se logidentifico al jug: " + jugador.getUsername() +" op: "+msj.operacion);
                resolver[msj.operacion](jugador, msj);
            }
            catch(e) {
                if(e.name === "ErrorIdentificacion" )
                    logger.logError(e);
                else
                    throw e;
            }
        },
        /*
        procesar2: function(msj, client){

            switch(msj.operacion){
                case "iniciarJuego":
                    logger.log("El jugador "+ msj.session.username + " empezo la partida");
                    juego.iniciarJuego();
                    break;
                case "conectarJugador":
                    //logger.log("Jugador identificado como: "+ JSON.stringify(msj.datosLoginJugador) + " se conecto! ");

                    var jugador = loginModule.login(msj.datosLoginJugador, client);
                    if(jugador)
                        juego.agregarJugador(jugador);
                    break;
                case "robarCartas":
                    var jugador = identificarJugador(sessionJugador);

                    logger.log("El jugador "+ jugador.getUsername() + " quiere robar "+ msj.cantidad + " cartas.");

                    if(!jugador){
                        errorHandler.error("Jugador no identificado correctamente! No puede robar cartas.");
                        return;
                    }
                    juego.robarCartas(jugador, msj.cantidad);
                    break;

                case "bajarCarta":
                    var cartaInfo = Carta(msj.cartaId);
                    logger.log("El jugador "+  msj.session.username + " bajo carta "+ cartaInfo.nombre);
                    juego.bajarCarta();
                default:
                    errorHandler.error("Llego un msj equivocado: '"+msj.operacion+"'.");
            }
        }*/
    }

})();

module.exports = messageHandler;

/*
var operacionesAccionesMap = (function(){
    return {
        iniciarJuego: [
            LogAction(logger, "El cliente "+ msj.session.username + " empezo la partida"),
            IniciarJuego(juego)],
        conectarJugador: [
            ]

    }
})

var LogAction = function(logger, msgLog){
    return function log_posta(){
        logger.log("Hola "+msgLog);
    };
}

var IniciarJuego = function (juego) {
    return function iniciar_posta(){
        juego.iniciarJuego();
    }
}

var RobarCartas = function(juego, jugador, cantidad){
    return function robar_posta(){
        juego.robarCartas(jugador, cantidad);
    }
}

var LoginJugador = function (loginModule, jugador) {
    return function login_posta(){

    }
}
*/<|endoftext|>


<commit_before>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

const
	path = require('path'),
	webpack = require('webpack'),
	config = require('config');

const
	HardSourceWebpackPlugin = require('hard-source-webpack-plugin');

const
	{buildCache} = include('build/build.webpack');

/**
 * Returns a list of webpack plugins
 *
 * @param {(number|string)} buildId - build id
 * @returns {Map}
 */
module.exports = async function ({buildId}) {
	const
		build = await include('build/entities.webpack');

	const plugins = new Map([
		['globals', new webpack.DefinePlugin(include('build/globals.webpack'))],
		['dependencies', include('build/dependencies.webpack')({build})]
	]);

	if (!isProd) {
		plugins.set('buildCache', new HardSourceWebpackPlugin({
			environmentHash: {files: ['package-lock.json', 'yarn.lock']},
			cacheDirectory: path.join(buildCache, buildId, config.webpack.cacheDir()),
			configHash: () => require('node-object-hash')().hash(global.WEBPACK_CONFIG)
		}));
	}

	return plugins;
};
<commit_msg>:wrench:<commit_after>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

const
	path = require('path'),
	webpack = require('webpack'),
	config = require('config');

const
	HardSourceWebpackPlugin = require('hard-source-webpack-plugin');

const
	{buildCache} = include('build/build.webpack');

/**
 * Returns a list of webpack plugins
 *
 * @param {(number|string)} buildId - build id
 * @returns {Map}
 */
module.exports = async function ({buildId}) {
	const
		build = await include('build/entities.webpack');

	const plugins = new Map([
		['globals', new webpack.DefinePlugin(include('build/globals.webpack'))],
		['dependencies', include('build/dependencies.webpack')({build})]
	]);

	if (!isProd) {
		plugins.set('buildCache', new HardSourceWebpackPlugin({
			environmentHash: {files: ['package-lock.json', 'yarn.lock']},
			cacheDirectory: path.join(buildCache, String(buildId), config.webpack.cacheDir()),
			configHash: () => require('node-object-hash')().hash(global.WEBPACK_CONFIG)
		}));
	}

	return plugins;
};
<|endoftext|>


<commit_before>const electronScreen = require('electron').screen

const screenInfoBtn = document.getElementById('screen-info')
const size = electronScreen.getPrimaryDisplay().size

screenInfoBtn.addEventListener('click', function () {
  const message = `Your screen is: ${size.width} px x ${size.height} px`
  document.getElementById('got-screen-info').innerHTML = message
})
<commit_msg>:fire: spaces<commit_after>const electronScreen = require('electron').screen

const screenInfoBtn = document.getElementById('screen-info')
const size = electronScreen.getPrimaryDisplay().size

screenInfoBtn.addEventListener('click', function () {
  const message = `Your screen is: ${size.width}px x ${size.height}px`
  document.getElementById('got-screen-info').innerHTML = message
})
<|endoftext|>


<commit_before>module.exports = [
  {
    test: /\.svg$/,
    loader: 'svg-sprite-loader',
    exclude: /fonts/,
  }, {
    test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
    loader: 'url-loader?limit=60000&mimetype=application/font-woff',
  }, {
    test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
    loader: 'url-loader?limit=60000',
    include: /fonts/,
  }, {
    test: /\.(png|jpg)$/,
    loader: 'url-loader?limit=8192',
  }, {
    test: /\.css$/,
    loader: 'style-loader!css-loader!postcss-loader',
  }, {
    test: /\.mcss$/,
    loader: 'style-loader!css-loader?modules&importLoaders=1&localIdentName=[name]_[local]_[hash:base64:5]!postcss-loader',
  }, {
    test: /\.c$/i,
    loader: 'shader-loader',
  }, {
    test: /\.json$/,
    loader: 'json-loader',
  }, {
    test: /\.html$/,
    loader: 'html-loader',
  }, {
    test: /\.isvg$/,
    loader: 'html-loader?attrs=false',
  }, {
    test: /\.js$/,
    include: /node_modules(\/|\\)paraviewweb(\/|\\)/,
    loader: 'babel-loader?presets[]=es2015,presets[]=react',
  }, {
    test: /\.js$/,
    include: /node_modules(\/|\\)vtk.js(\/|\\)/,
    loader: 'babel-loader?presets[]=es2015,presets[]=react',
  }, {
    test: /\.js$/,
    include: /node_modules(\/|\\)wslink(\/|\\)/,
    loader: 'babel-loader?presets[]=es2015',
  }, {
    test: /\.glsl$/,
    loader: 'shader-loader',
  }, {
    test: /\.js$/,
    exclude: /node_modules/,
    loader: 'babel-loader?presets[]=es2015,presets[]=react',
  },
];
<commit_msg>fix(webpack): loader tweak for svg-sprite-loader v2.0+<commit_after>module.exports = [
  {
    test: /\.svg$/,
    loader: 'svg-sprite-loader?runtimeCompat=true',
    exclude: /fonts/,
  }, {
    test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
    loader: 'url-loader?limit=60000&mimetype=application/font-woff',
  }, {
    test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
    loader: 'url-loader?limit=60000',
    include: /fonts/,
  }, {
    test: /\.(png|jpg)$/,
    loader: 'url-loader?limit=8192',
  }, {
    test: /\.css$/,
    loader: 'style-loader!css-loader!postcss-loader',
  }, {
    test: /\.mcss$/,
    loader: 'style-loader!css-loader?modules&importLoaders=1&localIdentName=[name]_[local]_[hash:base64:5]!postcss-loader',
  }, {
    test: /\.c$/i,
    loader: 'shader-loader',
  }, {
    test: /\.json$/,
    loader: 'json-loader',
  }, {
    test: /\.html$/,
    loader: 'html-loader',
  }, {
    test: /\.isvg$/,
    loader: 'html-loader?attrs=false',
  }, {
    test: /\.js$/,
    include: /node_modules(\/|\\)paraviewweb(\/|\\)/,
    loader: 'babel-loader?presets[]=es2015,presets[]=react',
  }, {
    test: /\.js$/,
    include: /node_modules(\/|\\)vtk.js(\/|\\)/,
    loader: 'babel-loader?presets[]=es2015,presets[]=react',
  }, {
    test: /\.js$/,
    include: /node_modules(\/|\\)wslink(\/|\\)/,
    loader: 'babel-loader?presets[]=es2015',
  }, {
    test: /\.glsl$/,
    loader: 'shader-loader',
  }, {
    test: /\.js$/,
    exclude: /node_modules/,
    loader: 'babel-loader?presets[]=es2015,presets[]=react',
  },
];
<|endoftext|>