<commit_before>var http = require('http');
var fs   = require('fs');
var url  = require('url');
var TicketQ = require('./ticketq.js');
var spawn = require('child_process').spawn;

var settingsPath='settings2.json';

var Server = function(path){
	this.readSettings(path);
}

Server.prototype.readSettings = function(path){
	fs.readFile(path, 'utf8', function(err,data){
		if(err) throw err;
		Server.prototype.parseSettings(data);
	})
}

Server.prototype.parseSettings = function(data){
	this.options=JSON.parse(data);

	if(!this.options.downloadPath) throw new Error('downloadPath is not set in settings file');
	if(this.options.downloadPath.substring(this.options.downloadPath.length-1,1)!='/') this.options.downloadPath+'/';

	this.options.cssName = this.options.cssName || 'bauerj.css';
	if(this.options.cssName.substring(this.options.cssName.length-1,1)!='/') this.options.cssName

	this.createServer();
	this.files={};
	this.findFiles();
	setInterval((this.findFiles).bind(this),3000);
}

Server.prototype.createServer = function(){
	this.http = http.createServer(this.onRequest.bind(this)).listen(this.options.port);
	this.views = require('./views.js');
	this.ticketq = new TicketQ();
	this.totalTraffic=0;
	this.trafficMonitor = setInterval((this.statsTick).bind(this),1000);
}

Server.prototype.findFiles = function(){
	fs.readdir(this.options.downloadPath,(function(err,files){
		if(err) throw err;

		for(var f in files){
			if(! this.files[files[f]])
				this.addFile(files[f]);
		}
	}).bind(this))
}
Server.prototype.addFile = function(filename){
	fs.stat(this.options.downloadPath+filename, (function(err, stats){
		var matches;
		if(!stats.isFile() || !( matches= filename.match(/^([a-zA-Z0-9_]+)_([0-9]+).([0-9]+).([0-9]+)_([0-9]+)-([0-9]+)_([a-z0-9]+)_(\d+)_TVOON_DE\.mpg(((\.avi)|(\.otrkey)|(\.cut)|(\.HD)|(\.mp4)|(\.HQ)|(\.ac3))+)$/))) return;

		//console.log(matches[1].replace(/\_/g,"$"));

		this.files[filename]={filename: filename, status: 'pre-stat',
			title: matches[1].replace(/\_/g," "),
			starttime: new Date(2000+parseInt(matches[2]), parseInt(matches[3]), parseInt(matches[4]), parseInt(matches[5]), parseInt(matches[6])),
			station: matches[7],
			duration: matches[8],
			flags: function(flagstring){
				var split = flagstring.split('.');
				var flags = {};
				for (var i in split){
					if(split[i].length>0)
						flags[split[i]] = true;
				}
				return flags;
			}(matches[9]),
			md5: null
		};

		var m = {};
		for (var i in matches)
			m[i.toString()]=matches[i] || "empty";

		//console.log(JSON.stringify(m));

		//console.log(JSON.stringify(this.files[filename]));

		console.log('+ '+filename);
		if(err) throw err;
		this.files[filename].size=stats.size;
		this.files[filename].status='ready';
		fs.watchFile(this.options.downloadPath+filename, (function(curr,prev){this.onFileChange(filename,curr,prev);}).bind(this));
		this.getMd5(filename);
	}).bind(this));
}

Server.prototype.saveMd5 = function(filename,sigma){
	var hex = parseInt((sigma.match(/^[0-9a-f]+/))[0],16);
	var b = new Buffer(hex.toString());
	this.files[filename].md5 = b.toString('base64');
}

Server.prototype.getMd5 = function(filename){
	fs.readFile(this.options.downloadPath+filename+'.md5','utf8',(function(err,sigma){
		if(err) return this.makeMd5(filename)
		else this.saveMd5(filename,sigma)
	}).bind(this))
}

Server.prototype.makeMd5 = function(filename){
	var sigma = '';
	var proc = spawn('md5sum',[this.options.downloadPath+filename])
	proc.stdout.setEncoding('utf8');
	proc.stdout.on('data',function(chunk){
		sigma += chunk;
	});
	proc.on('exit',(function(code,signal){
		if(code != 0) return console.log('md5sum of ' + filename + ' failed, exit code: ' + code);
		this.saveMd5(filename,sigma);
		fs.writeFile(this.options.downloadPath+filename+'.md5',sigma);
	}).bind(this));
}

Server.prototype.onFileChange = function(filename,curr,prev){
	if(curr.nlink){
		if(filename in this.files)
			this.files[filename].size = curr.size;
		else
			this.addFile(filename)
		this.files[filename].md5 = null;
		this.getMd5(filename);
	}
	else{
		console.log('- '+filename);
		delete this.files[filename];
	}
}

Server.prototype.onRequest = function(req,res){
	var u = url.parse(req.url)
	var matches;
	if(u.pathname == "/" || (matches = u.pathname.match(/^\/index(\/([a-zA-Z0-9_.-]*)\/?)?$/i)))
		(this.views.index).bind(this)(req,res,matches);
	else if(matches=u.pathname.match(/^\/createticketfor\/([a-zA-Z0-9_.-]+)/i))
		this.createTicket(req,res,matches);
	else if(matches=u.pathname.match(/^\/download\/([0-9]+)\/?/i))
		this.download(req,res,matches);
	else if(u.pathname.match(/^\/thankyou\/?/i))
		this.sendStatic(req,res, 'thankyou.html');
	  else if(u.pathname.match(/^\/faq\/?/i))
                this.sendStatic(req,res,'faq.html');
	  else if(u.pathname.match(/^\/imprint\/?/i))
                this.sendStatic(req,res, 'imprint.html');
        else if(matches=u.pathname.match(/.*(jpg|png|ico)/i))
		this.sendStatic(req, res, '.'+  u.pathname, {});
	else if(u.pathname.match(/^\/style.css\/?/i))
		this.sendStatic(req, res, this.options.cssName, {'Content-Type': 'text/css'});
	else if(u.pathname.match(/^\/linklist\/?/i))
		(this.views.linklist).bind(this)(req,res);
	else{
		this.views.send404(req,res);
	}
}

Server.prototype.sendStatic = function(req,res,path,httpOptions){
	res.writeHead(200,httpOptions || {'Content-Type': 'text/html; charset=utf-8'})
	fs.createReadStream('./static/'+path).pipe(res)
}

Server.prototype.showTemplate = function(req,res,textfnc,mimeType){
	res.writeHead(200, {'Content-Type': mimeType || 'text/html; charset=utf-8'});
	res.end(textfnc());
}

Server.prototype.createTicket = function(req,res,matches){
	var filename=matches[1];
	if(filename in this.files){
		var t = this.ticketq.append(filename)
		res.writeHead(302, {location: 'http://' + this.options.fqdn+'/download/' + t.id});
		res.end();
	}
	else{
		res.writeHead(404, {'Content-Type': 'text/html; charset=utf-8'});
		res.write('
file not found

available files:

')
		for (var f in this.files){
			res.write("
"+f+"
\n");
		}
		res.end("
");
	}
}

Server.prototype.download = function(req,res,matches){

	var ticket=this.ticketq.tickets[matches[1]];
	if(ticket){
		if( ! (ticket.filename in this.files) ){
			console.log('404 gelöscht');
			res.writeHead(404)
			console.log(2);
			res.end('file not found');
			return;
		}

		var call = {res: res}
		if(req.headers.range){
			var range=req.headers.range.match(/^bytes=([0-9]*)-([0-9]*)/)
			call.start = parseInt(range[1]) || 0;
			call.end = parseInt(range[2]) || this.files[ticket.filename].size-1;
		}

		if( call.end && call.start>call.end){
			res.writeHead(416);
			res.end('requested range not satisfiable');
			return;
		}

		var options = {'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename='+ticket.filename, 'Content-Length': this.files[ticket.filename].size,'Content-MD5': this.files[ticket.filename].md5};
		if(call.end){
			options['Content-Range'] = 'bytes ' + call.start + '-' + call.end + '/' + this.files[ticket.filename].size;
		}
		if(call.end  && (call.end!=this.files[ticket.filename].size || call.start!= 0) )
			res.writeHead(206,options);
		else{
			console.log(this.files[ticket.filename].md5);
			res.writeHead(200,options)
		}

		ticket.res.push(call);

		if(ticket.ready) this.pushDownload(ticket);
	}
	else{
		this.views.send404(req,res);
	}
}

Server.prototype.pushDownload = function(ticket){
	if(ticket.filename in this.files){
		var call;
		while( call = ticket.res.pop() ){
			call.rs = fs.createReadStream(this.options.downloadPath+ticket.filename,{start: call.start, end: call.end});
			call.rs.pipe(call.res);
			call.rs.on('data', (function(chunk){this.totalTraffic+=chunk.length;}).bind(this));
		}
	}
	else{ //file has been deleted in the meantime
		ticket.res.end();
	}
}

Server.prototype.statsTick = function(){
	if (this.ticketq.head!== null && this.totalTraffic < (this.options.maintainTraffic || Number.POSITIVE_INFINITY)){
		var t;
 		while(this.ticketq.head !== null && (null == (t = this.ticketq.shift()))){} //some entries in tickets may be null due to premature deletion
		if( t ){ // the last item might be null as well
			t.ready = true;
			if( t.res.length>0 ){
				this.pushDownload(t);
			}
		}
	}
	this.totalTraffic = 0;
}

var s=new Server(settingsPath);
<commit_msg>md5 working, missing view<commit_after>var http = require('http');
var fs   = require('fs');
var url  = require('url');
var TicketQ = require('./ticketq.js');
var spawn = require('child_process').spawn;

var settingsPath='settings2.json';

var Server = function(path){
	this.readSettings(path);
}

Server.prototype.readSettings = function(path){
	fs.readFile(path, 'utf8', function(err,data){
		if(err) throw err;
		Server.prototype.parseSettings(data);
	})
}

Server.prototype.parseSettings = function(data){
	this.options=JSON.parse(data);

	if(!this.options.downloadPath) throw new Error('downloadPath is not set in settings file');
	if(this.options.downloadPath.substring(this.options.downloadPath.length-1,1)!='/') this.options.downloadPath+'/';

	this.options.cssName = this.options.cssName || 'bauerj.css';
	if(this.options.cssName.substring(this.options.cssName.length-1,1)!='/') this.options.cssName

	this.createServer();
	this.files={};
	this.findFiles();
	setInterval((this.findFiles).bind(this),3000);
}

Server.prototype.createServer = function(){
	this.http = http.createServer(this.onRequest.bind(this)).listen(this.options.port);
	this.views = require('./views.js');
	this.ticketq = new TicketQ();
	this.totalTraffic=0;
	this.trafficMonitor = setInterval((this.statsTick).bind(this),1000);
}

Server.prototype.findFiles = function(){
	fs.readdir(this.options.downloadPath,(function(err,files){
		if(err) throw err;

		for(var f in files){
			if(! this.files[files[f]])
				this.addFile(files[f]);
		}
	}).bind(this))
}
Server.prototype.addFile = function(filename){
	fs.stat(this.options.downloadPath+filename, (function(err, stats){
		var matches;
		if(!stats.isFile() || !( matches= filename.match(/^([a-zA-Z0-9_]+)_([0-9]+).([0-9]+).([0-9]+)_([0-9]+)-([0-9]+)_([a-z0-9]+)_(\d+)_TVOON_DE\.mpg(((\.avi)|(\.otrkey)|(\.cut)|(\.HD)|(\.mp4)|(\.HQ)|(\.ac3))+)$/))) return;

		//console.log(matches[1].replace(/\_/g,"$"));

		this.files[filename]={filename: filename, status: 'pre-stat',
			title: matches[1].replace(/\_/g," "),
			starttime: new Date(2000+parseInt(matches[2]), parseInt(matches[3]), parseInt(matches[4]), parseInt(matches[5]), parseInt(matches[6])),
			station: matches[7],
			duration: matches[8],
			flags: function(flagstring){
				var split = flagstring.split('.');
				var flags = {};
				for (var i in split){
					if(split[i].length>0)
						flags[split[i]] = true;
				}
				return flags;
			}(matches[9]),
			md5: false
		};

		var m = {};
		for (var i in matches)
			m[i.toString()]=matches[i] || "empty";

		//console.log(JSON.stringify(m));

		//console.log(JSON.stringify(this.files[filename]));

		console.log('+ '+filename);
		if(err) throw err;
		this.files[filename].size=stats.size;
		this.files[filename].status='ready';
		fs.watchFile(this.options.downloadPath+filename, (function(curr,prev){this.onFileChange(filename,curr,prev);}).bind(this));
		if(this.options.md5) this.getMd5(filename);
	}).bind(this));
}

Server.prototype.getMd5 = function(filename){
	fs.readFile(this.options.downloadPath+filename+'.md5','utf8',(function(err,sigma){
		if(err) return this.makeMd5(filename)
		var hex = sigma.match(/^[0-9a-f]+/i)[0]
		this.files[filename].md5 = hex;
	}).bind(this))
}

Server.prototype.makeMd5 = function(filename){
	var sigma = '';
	var proc = spawn('md5sum',[this.options.downloadPath+filename])
	proc.stdout.setEncoding('utf8');
	proc.stdout.on('data',function(chunk){
		sigma += chunk;
	});
	proc.on('exit',(function(code,signal){
		if(code != 0) return console.log('md5sum of ' + filename + ' failed, exit code: ' + code);
		var hex = sigma.match(/^[0-9a-f]+/i)[0]
		this.files[filename].md5 = hex;
		fs.writeFile(this.options.downloadPath+filename+'.md5',hex);
	}).bind(this));
}

Server.prototype.onFileChange = function(filename,curr,prev){
	if(curr.nlink){
		if(filename in this.files)
			this.files[filename].size = curr.size;
		else
			this.addFile(filename)
		this.files[filename].md5 = null;
		if(this.options.md5) this.getMd5(filename);
	}
	else{
		console.log('- '+filename);
		delete this.files[filename];
	}
}

Server.prototype.onRequest = function(req,res){
	var u = url.parse(req.url)
	var matches;
	if(u.pathname == "/" || (matches = u.pathname.match(/^\/index(\/([a-zA-Z0-9_.-]*)\/?)?$/i)))
		(this.views.index).bind(this)(req,res,matches);
	else if(matches=u.pathname.match(/^\/createticketfor\/([a-zA-Z0-9_.-]+)/i))
		this.createTicket(req,res,matches);
	else if(matches=u.pathname.match(/^\/download\/([0-9]+)\/?/i))
		this.download(req,res,matches);
	else if(matches=u.pathname.match(/^\/md5\/([a-zA-Z0-9_.-]*)\/?$/))
		this.sendMd5(req,res,matches);
	else if(u.pathname.match(/^\/thankyou\/?/i))
		this.sendStatic(req,res, 'thankyou.html');
	else if(u.pathname.match(/^\/faq\/?/i))
                this.sendStatic(req,res,'faq.html');
	else if(u.pathname.match(/^\/imprint\/?/i))
                this.sendStatic(req,res, 'imprint.html');
        else if(matches=u.pathname.match(/.*(jpg|png|ico)/i))
		this.sendStatic(req, res, '.'+  u.pathname, {});
	else if(u.pathname.match(/^\/style.css\/?/i))
		this.sendStatic(req, res, this.options.cssName, {'Content-Type': 'text/css'});
	else if(u.pathname.match(/^\/linklist\/?/i))
		(this.views.linklist).bind(this)(req,res);
	else{
		this.views.send404(req,res);
	}
}

Server.prototype.sendStatic = function(req,res,path,httpOptions){
	res.writeHead(200,httpOptions || {'Content-Type': 'text/html; charset=utf-8'})
	fs.createReadStream('./static/'+path).pipe(res)
}

Server.prototype.showTemplate = function(req,res,textfnc,mimeType){
	res.writeHead(200, {'Content-Type': mimeType || 'text/html; charset=utf-8'});
	res.end(textfnc());
}

Server.prototype.sendMd5 = function(req,res,matches){
	var f = this.files[matches[1]];
	if(!f || !f.md5) return this.views.send404(req,res)
	res.writeHead(200,{'Content-Type': 'text/plain'})
	res.end(f.md5);
}

Server.prototype.createTicket = function(req,res,matches){
	var filename=matches[1];
	if(filename in this.files){
		var t = this.ticketq.append(filename)
		res.writeHead(302, {location: 'http://' + this.options.fqdn+'/download/' + t.id});
		res.end();
	}
	else{
		res.writeHead(404, {'Content-Type': 'text/html; charset=utf-8'});
		res.write('
file not found

available files:

')
		for (var f in this.files){
			res.write("
"+f+"
\n");
		}
		res.end("
");
	}
}

Server.prototype.download = function(req,res,matches){

	var ticket=this.ticketq.tickets[matches[1]];
	if(ticket){
		if( ! (ticket.filename in this.files) ){
			console.log('404 gelöscht');
			res.writeHead(404)
			res.end('file not found');
			return;
		}

		var call = {res: res}
		if(req.headers.range){
			var range=req.headers.range.match(/^bytes=([0-9]*)-([0-9]*)/)
			call.start = parseInt(range[1]) || 0;
			call.end = parseInt(range[2]) || this.files[ticket.filename].size-1;
		}

		if( call.end && call.start>call.end){
			res.writeHead(416);
			res.end('requested range not satisfiable');
			return;
		}

		var options = {'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename='+ticket.filename, 'Content-Length': this.files[ticket.filename].size};
		if(call.end){
			options['Content-Range'] = 'bytes ' + call.start + '-' + call.end + '/' + this.files[ticket.filename].size;
		}
		if(call.end  && (call.end!=this.files[ticket.filename].size || call.start!= 0) )
			res.writeHead(206,options);
		else{
			res.writeHead(200,options)
		}

		ticket.res.push(call);

		if(ticket.ready) this.pushDownload(ticket);
	}
	else{
		this.views.send404(req,res);
	}
}

Server.prototype.pushDownload = function(ticket){
	if(ticket.filename in this.files){
		var call;
		while( call = ticket.res.pop() ){
			call.rs = fs.createReadStream(this.options.downloadPath+ticket.filename,{start: call.start, end: call.end});
			call.rs.pipe(call.res);
			call.rs.on('data', (function(chunk){this.totalTraffic+=chunk.length;}).bind(this));
		}
	}
	else{ //file has been deleted in the meantime
		ticket.res.end();
	}
}

Server.prototype.statsTick = function(){
	if (this.ticketq.head!== null && this.totalTraffic < (this.options.maintainTraffic || Number.POSITIVE_INFINITY)){
		var t;
 		while(this.ticketq.head !== null && (null == (t = this.ticketq.shift()))){} //some entries in tickets may be null due to premature deletion
		if( t ){ // the last item might be null as well
			t.ready = true;
			if( t.res.length>0 ){
				this.pushDownload(t);
			}
		}
	}
	this.totalTraffic = 0;
}

var s=new Server(settingsPath);
<|endoftext|>


<commit_before>// //Chris Samuel
// //Github: Alayode
// //2015-3-12
//
// // Code School: Changing Declarations to Expressions
//
// // Developers for the Forest of Function Expressions
// // Theme Park have created a function declaration named forestFright,
// // but they’ve decided not to keep the function in memory.
// // Convert the function from a named function
// // declaration to an anonymous function
// // expression and assign it to a variable called runAway.
//
//
// function forestFright() {
//   var toAlert = "";
//   for (var i = 0; i < 5; i++) {
//     toAlert = toAlert + "Lions, Tigers, and Bears, Oh My!!\n";
//   }
//   alert(toAlert);
// }
//
//
// // First lets create a variable called runAway
// var runAway;
//
// //Next lets try remeber that when a function expression is added to a
// //variable we can remove the name of the function from the "()"
// // this will make it become an anonymous function.
//
// function() {
//   var toAlert = "";
//   for (var i = 0; i < 5; i++) {
//     toAlert = toAlert + "Lions, Tigers, and Bears, Oh My!!\n";
//   }
//   alert(toAlert);
// }
//
//
// // now that it has no name it can called by assiging it to a
// // variable. lets use the variable runAway
//
// //this is another to use this function.
// var runAway = function() {
//   var toAlert = "";
//   for (var i = 0; i < 5; i++) {
//     toAlert = toAlert + "Lions, Tigers, and Bears, Oh My!!\n";
//   }
//   alert(toAlert);
// };
//
//
// //Finally we will callback the function by adding the name of the variable plus the paraentheses
// //to call back the function.
// //callback
// // runAway();

//Using Function Expressions with Parameters

// The devs at the Death-Defying Dogwoods have determined
// a specific formula for the quantifiable amount of fear
// generated at the theme park. Their formula is based
// on the amount of people, the amount of rain, and
// the amount of sharks. Yes. Sharks.

// If the math is troubling, try to work backwards
// from an ideal number in the accepted range of 100 to 400.
//
// var people = 5;
// var rain = 6;
// var sharks = 6;
//
//
// var fearGenerated = function(numPeeps, rainInInches, numSharks) {
//   var rainFear = numPeeps * rainInInches;
//   var sharkFear = numSharks * numSharks * numSharks;
//   var totalFear = sharkFear + rainFear;
//   return totalFear;
// };
//
// Test Your Code!!!!
// Call the function and ensure that your parameters are
// being passed in the right order, and only by variable name.

// Displaying Functions contents
// Periodically, the devs at the Haunted Hickory
// House need to be reminded of their formula.
// They would like to view the contents of the function,
// rather than executing it.
//
// Write one line of code to alert the contents of the
// variable that stores the function to the screen.
// Here is the fearGenerated function expression assignment for reference:

//
// var fearGenerated = function(numPeeps, rainInInches, numSharks) {
//   var rainFear = numPeeps * rainInInches;
//   var sharkFear = numSharks * numSharks * numSharks;
//   var totalFear = sharkFear + rainFear;
//   return totalFear;
// };
//
//
// //Note if you are using NodeJS you will not be able to use alert method.
// // That method is a apart of the window object in the browser.
//
// alert(fearGenerated);

// Functions as parameters, arguments and Return Values

// Well, it stands to reason that some people might not want to experience the Haunted Hickory House if the fear is significantly elevated on that day.
//
//     Inside the fearMessage function expression, use conditional statements to check the already-generated fear value, and decide whether it is LOW or MEDIUM.
//     Inside each conditional statement, return a specific confirm message in the following formats:
//
// For fear levels less than 200:
//
// Fear Level: LOW
// Still wanna ride?
//
// For fear levels 200 through and including 300:
//
// Fear Level: MEDIUM
// Think you'll make it?
//
// Lastly, call the confirmRide function and pass in the fearMessage variable. Then assign the results of that function in a new variable called startRide.
//
// Note: You do not need to change the existing code that’s provided for you in the challenge editor.

var fear = fearGenerated(numPeeps, rainInInches, numSharks);

var fearMessage = function() {
  // Insert conditional statements here

};

function confirmRide(confirmToGo) {
  return confirmToGo();
}

// Call confirmRide here
<commit_msg> updated question<commit_after>// //Chris Samuel
// //Github: Alayode
// //2015-3-12
//
// // Code School: Changing Declarations to Expressions
//
// // Developers for the Forest of Function Expressions
// // Theme Park have created a function declaration named forestFright,
// // but they’ve decided not to keep the function in memory.
// // Convert the function from a named function
// // declaration to an anonymous function
// // expression and assign it to a variable called runAway.
//
//
// function forestFright() {
//   var toAlert = "";
//   for (var i = 0; i < 5; i++) {
//     toAlert = toAlert + "Lions, Tigers, and Bears, Oh My!!\n";
//   }
//   alert(toAlert);
// }
//
//
// // First lets create a variable called runAway
// var runAway;
//
// //Next lets try remeber that when a function expression is added to a
// //variable we can remove the name of the function from the "()"
// // this will make it become an anonymous function.
//
// function() {
//   var toAlert = "";
//   for (var i = 0; i < 5; i++) {
//     toAlert = toAlert + "Lions, Tigers, and Bears, Oh My!!\n";
//   }
//   alert(toAlert);
// }
//
//
// // now that it has no name it can called by assiging it to a
// // variable. lets use the variable runAway
//
// //this is another to use this function.
// var runAway = function() {
//   var toAlert = "";
//   for (var i = 0; i < 5; i++) {
//     toAlert = toAlert + "Lions, Tigers, and Bears, Oh My!!\n";
//   }
//   alert(toAlert);
// };
//
//
// //Finally we will callback the function by adding the name of the variable plus the paraentheses
// //to call back the function.
// //callback
// // runAway();

//Using Function Expressions with Parameters

// The devs at the Death-Defying Dogwoods have determined
// a specific formula for the quantifiable amount of fear
// generated at the theme park. Their formula is based
// on the amount of people, the amount of rain, and
// the amount of sharks. Yes. Sharks.

// If the math is troubling, try to work backwards
// from an ideal number in the accepted range of 100 to 400.
//
// var people = 5;
// var rain = 6;
// var sharks = 6;
//
//
// var fearGenerated = function(numPeeps, rainInInches, numSharks) {
//   var rainFear = numPeeps * rainInInches;
//   var sharkFear = numSharks * numSharks * numSharks;
//   var totalFear = sharkFear + rainFear;
//   return totalFear;
// };
//
// Test Your Code!!!!
// Call the function and ensure that your parameters are
// being passed in the right order, and only by variable name.

// Displaying Functions contents
// Periodically, the devs at the Haunted Hickory
// House need to be reminded of their formula.
// They would like to view the contents of the function,
// rather than executing it.
//
// Write one line of code to alert the contents of the
// variable that stores the function to the screen.
// Here is the fearGenerated function expression assignment for reference:

//
// var fearGenerated = function(numPeeps, rainInInches, numSharks) {
//   var rainFear = numPeeps * rainInInches;
//   var sharkFear = numSharks * numSharks * numSharks;
//   var totalFear = sharkFear + rainFear;
//   return totalFear;
// };
//
//
// //Note if you are using NodeJS you will not be able to use alert method.
// // That method is a apart of the window object in the browser.
//
// alert(fearGenerated);

// Functions as parameters, arguments and Return Values

// Well, it stands to reason that some people might not want to experience the Haunted Hickory House if the fear is significantly elevated on that day.
//
//     Inside the fearMessage function expression, use conditional statements to check the already-generated fear value, and decide whether it is LOW or MEDIUM.
//     Inside each conditional statement, return a specific confirm message in the following formats:
//
// For fear levels less than 200:
//
// Fear Level: LOW
// Still wanna ride?
//
// For fear levels 200 through and including 300:
//
// Fear Level: MEDIUM
// Think you'll make it?
//
// Lastly, call the confirmRide function and pass in the fearMessage variable. Then assign the results of that function in a new variable called startRide.
//

// Note: You do not need to change the existing code that’s provided for you!!!!
var fear = fearGenerated(numPeeps, rainInInches, numSharks);

var fearMessage = function() {
  // Insert conditional statements here

};

function confirmRide(confirmToGo) {
  return confirmToGo();
}

// Call confirmRide here
<|endoftext|>


<commit_before>const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const ObjectID = require('mongodb').ObjectID;
const MongoClient = require('mongodb').MongoClient;
require('dotenv').config();
const connectionString = process.env.DB_TYPE + process.env.DB_USER + ':' + process.env.DB_PSW + process.env.DB_PATH;

const Event = require('./models/event');
const Volunteer = require('./models/volunteer');
const mongoose = require('mongoose');

app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, HEAD, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  next();
});

app.use(bodyParser.json());

var options = {
  useMongoClient: true,
  autoIndex: false, // Don't build indexes
  reconnectTries: 10, // Never stop trying to reconnect
  reconnectInterval: 500, // Reconnect every 500ms
  poolSize: 10, // Maintain up to 10 socket connections
  // If not connected, return errors immediately rather than waiting for reconnect
  bufferMaxEntries: 0
};

mongoose.connect(connectionString, options);

Event.find({}, function(err, events) {
  console.log('is this running');
  if (err) {
    console.log('error: ', err);
  }
  // test connection
  console.log('All Events', events);
});

app.get('/events', function(req, res) {
  Event.find({}, function(err, events) {
    if (err) {
      console.log('error: ', err);
    }

    // object of all the users
    console.log('All Events', events);
    res.send(events);
  });
});

app.get('/volunteers', function(req, res) {
  MongoClient.connect(connectionString, function(err, db) {
    console.log('Connected correctly to server');
    if (err) {
      console.log('error occurred:', err);
    }

    var collection = db.collection('volunteers');
    collection.find().toArray(function(err, volunteers) {
      if (err) {
        console.log('error in retrieving volunteers');
      }
      res.send(volunteers);
    });
    db.close();
  });
});

app.post('/events', function(req, res) {
  // create a new user
  var newEvent = Event({
    name: req.body.name,
    date: req.body.date,
    currentVolunteers: req.body.currentVolunteers,
    maxVolunteers: req.body.maxVolunteers
  });

  // save the user
  newEvent.save(function(err) {
    if (err) throw err;

    console.log('Event created!');
    res.send('New Event Added');
  });
});

//creates new volunteer
app.post('/register', function(req, res) {
  MongoClient.connect(connectionString, function(err, db) {
    console.log('Connected correctly to server');
    if (err) {
      console.log('error occurred:', err);
    }
    console.log('post data - register', req);
    var collection = db.collection('volunteers');
    collection
      .insertOne({
        name: req.body.name,
        email: req.body.email,
        age: req.body.age,
        eventsJoined: 0,
        futureEvents: []
      })
      .then(function(result) {
        console.log('New Event Saved to MongoDb');
        res.send('New Event Added.');
      });
    db.close();
  });
});

app.put('/events/joinEvent', function(req, res) {
  MongoClient.connect(connectionString, function(err, db) {
    console.log('Connected correctly to server');
    if (err) {
      console.log('error occurred:', err);
    }

    var collection = db.collection('events');
    collection
      .update(
        { name: req.body.eventName },
        { $push: { currentVolunteers: { name: req.body.username, email: req.body.email } } }
      )
      .then(function(result) {
        console.log('User added to Event', result);
        res.send('User joined event.');
      });
    db.close();
  });
});

app.put('/volunteers/joinEvent', function(req, res) {
  MongoClient.connect(connectionString, function(err, db) {
    console.log('Connected correctly to server');
    if (err) {
      console.log('error occurred:', err);
    }

    var collection = db.collection('volunteers');
    collection
      .update(
        { name: req.body.username },
        {
          $inc: { eventsJoined: 1 },
          $push: { futureEvents: { name: req.body.eventName } }
        }
      )
      .then(function(result) {
        console.log('Event added to User', result);
        res.send('Event added to User.');
      });
    db.close();
  });
});

app.delete('/events/:id', function(req, res) {
  MongoClient.connect(connectionString, function(err, db) {
    console.log('Connected correctly to server');
    if (err) {
      console.log('error occurred:', err);
    }

    var collection = db.collection('events');
    collection
      .deleteOne({
        _id: ObjectID(req.params.id)
      })
      .then(function(result) {
        console.log('Event removed from MongoDb', result);
        res.send('Event Removed.');
      });
    db.close();
  });
});

app.delete('/volunteers/:id', function(req, res) {
  // MongoClient.connect(connectionString, function(err, db) {
  //   console.log('Connected correctly to server');
  //   if (err) {
  //     console.log('error occurred:', err);
  //   }

  //   var collection = db.collection('volunteers');
  //   collection
  //     .deleteOne({
  //       _id: ObjectID(req.params.id)
  //     })
  //     .then(function(result) {
  //       console.log('Volunteer removed from MongoDb', result);
  //       res.send('Volunteer Removed.');
  //     });
  //   db.close();
  // });

  // find the user with id
  Volunteer.findByIdAndRemove(ObjectID(req.params.id), function(err) {
    if (err) throw err;

    // user deleted
    console.log('User deleted!');
    res.send('Volunteer Removed');
  });
});

app.listen(process.env.DB_PORT, function() {
  console.log('listening on 3000');
});
<commit_msg>refactored server routes to use mongoose instead of mongo<commit_after>const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const ObjectID = require('mongodb').ObjectID;
const MongoClient = require('mongodb').MongoClient;
require('dotenv').config();
const connectionString = process.env.DB_TYPE + process.env.DB_USER + ':' + process.env.DB_PSW + process.env.DB_PATH;

const Event = require('./models/event');
const Volunteer = require('./models/volunteer');
const mongoose = require('mongoose');

app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, HEAD, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  next();
});

app.use(bodyParser.json());

var options = {
  useMongoClient: true,
  autoIndex: false, // Don't build indexes
  reconnectTries: 10, // Never stop trying to reconnect
  reconnectInterval: 500, // Reconnect every 500ms
  poolSize: 10, // Maintain up to 10 socket connections
  // If not connected, return errors immediately rather than waiting for reconnect
  bufferMaxEntries: 0
};

mongoose.connect(connectionString, options);

app.get('/events', function(req, res) {
  Event.find({}, function(err, events) {
    if (err) {
      console.log('error: ', err);
    }

    console.log('All events', events);
    res.send(events);
  });
});

app.get('/volunteers', function(req, res) {
  Volunteer.find({}, function(err, volunteers) {
    if (err) {
      console.log('error: ', err);
    }

    // object of all the users
    console.log('All volunteers', volunteers);
    res.send(volunteers);
  });
});
// create a new user
app.post('/events', function(req, res) {
  var newEvent = Event({
    name: req.body.name,
    date: req.body.date,
    currentVolunteers: req.body.currentVolunteers,
    maxVolunteers: req.body.maxVolunteers
  });

  newEvent.save(function(err) {
    if (err) throw err;

    console.log('Event created!');
    res.send('New Event Added');
  });
});

//creates new volunteer
app.post('/register', function(req, res) {
  var newVolunteer = Volunteer({
    name: req.body.name,
    email: req.body.email,
    age: req.body.age,
    eventsJoined: 0,
    futureEvents: []
  });

  // save the user
  newVolunteer.save(function(err) {
    if (err) throw err;

    console.log('Volunteer created!');
    res.send('New Volunteer Added');
  });
});
//find event & push volunteer into event's array
app.put('/events/joinEvent', function(req, res) {
  var eventObj = { name: req.body.eventName };
  var userJoinEvent = { $push: { currentVolunteers: { name: req.body.username, email: req.body.email } } };

  Event.findOneAndUpdate(eventObj, userJoinEvent, function(err, user) {
    if (err) throw err;

    console.log('User added to event list', user);
    res.send('User joined event.');
  });
});
//find user & push event into user's array
app.put('/volunteers/joinEvent', function(req, res) {
  var userObj = { name: req.body.username };
  var addEventToUser = { $push: { futureEvents: { name: req.body.eventName } } };
  var incrementEventsJoined = { $inc: { eventsJoined: 1 } };

  Volunteer.findOneAndUpdate(userObj, addEventToUser, incrementEventsJoined, function(err, volunteer) {
    if (err) throw err;

    console.log('Event added to user list', volunteer);
    res.send('Event added to User.');
  });
});

app.delete('/events/:id', function(req, res) {
  // find the event with id
  Event.findByIdAndRemove(ObjectID(req.params.id), function(err) {
    if (err) throw err;

    // user deleted
    console.log('Event deleted!');
    res.send('Event Removed');
  });
});

app.delete('/volunteers/:id', function(req, res) {
  // find the user with id
  Volunteer.findByIdAndRemove(ObjectID(req.params.id), function(err) {
    if (err) throw err;

    // user deleted
    console.log('User deleted!');
    res.send('Volunteer Removed');
  });
});

app.listen(process.env.DB_PORT, function() {
  console.log('listening on 3000');
});
<|endoftext|>


<commit_before>var WelcomeCard = {
    name: 'WelcomeCard',
    dom_target: undefined,

    render_init: function() {
        if (window.user.applicant && !window.user.student) {
            this._render();
        } else {
            return;
        }
    },

    render_upon_data: function () {
        WelcomeCard._render();
    },

    _render: function () {
        var student_info = {};
        var source = $("#welcome_card").html();
        var template = Handlebars.compile(source);

        WelcomeCard.dom_target.html(template(student_info));
        LogUtils.cardLoaded(WelcomeCard.name, WelcomeCard.dom_target);
    },

    _has_all_data: function () {
        return true;
    },

    render_error: function () {
        $("#WelcomeCard").hide();
    }
};

/* node.js exports */
if (typeof exports == "undefined") {
    var exports = {};
}
exports.WelcomeCard = WelcomeCard;
<commit_msg>Fixing Welcome card<commit_after>var WelcomeCard = {
    name: 'WelcomeCard',
    dom_target: undefined,

    render_init: function() {
        if (window.user.applicant && !window.user.student) {
            this._render();
        } else {
            this.render_error();
        }
    },

    render_upon_data: function () {
        WelcomeCard._render();
    },

    _render: function () {
        var student_info = {};
        var source = $("#welcome_card").html();
        var template = Handlebars.compile(source);

        WelcomeCard.dom_target.html(template(student_info));
        LogUtils.cardLoaded(WelcomeCard.name, WelcomeCard.dom_target);
    },

    _has_all_data: function () {
        return true;
    },

    render_error: function () {
        $("#WelcomeCard").hide();
    }
};

/* node.js exports */
if (typeof exports == "undefined") {
    var exports = {};
}
exports.WelcomeCard = WelcomeCard;
<|endoftext|>


<commit_before>/*
 * Copyright 2016 SimplifyOps, Inc. (http://simplifyops.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//= require knockout.min
//= require knockout-mapping
//= require knockout-onenter
//= require ko/binding-url-path-param
//= require ko/binding-message-template
//= require jquery.waypoints.min
//= require menu/project-model

function HomeData(data) {
    var self = this;
    self.baseUrl = data.baseUrl;
    self.summaryUrl = data.summaryUrl;
    self.projectNamesUrl = data.projectNamesUrl;
    self.loaded = ko.observable(data.loaded?true:false);
    self.jobCount = ko.observable(0);
    self.execCount = ko.observable(data.execCount||0);
    self.totalFailedCount = ko.observable(data.totalFailedCount||0);
    self.projectNames = ko.observableArray(data.projectNames || []);
    self.projectNamesTotal = ko.observable(data.projectNamesTotal || 0);
    self.loadedProjectNames = ko.observable(false);
    self.projects = ko.observableArray([]);
    self.projects.extend({rateLimit: 500});

    self.recentUsers = ko.observableArray(data.recentUsers||[]);
    self.recentProjects = ko.observableArray(data.recentProjects||[]);
    self.frameworkNodeName = ko.observable(null);
    self.doRefresh = ko.observable(false);
    self.doPaging = ko.observable(false);
    self.pagingMax = ko.observable(20);
    self.pagingRepeatMax = ko.observable(20);
    self.pagingDelay = ko.observable(2000);
    self.pagingOffset = ko.observable(0);
    self.refreshDelay = ko.observable(30000);
    self.search=ko.observable(null);

    //batch of project data to load
    self.batchList=ko.observableArray([]);
    self.batchList.extend({ rateLimit: 500 });
    self.batches=ko.observableArray([]);

    self.recentUsersCount = ko.pureComputed(function () {
        return self.recentUsers().length;
    });
    self.recentProjectsCount = ko.pureComputed(function () {
        return self.recentProjects().length;
    });
    self.searchedProjects=ko.pureComputed(function(){
        "use strict";
        var search=self.search();
        var names=self.projectNames();
        if(null==search){
            return names;
        }
        var regex;
        if (search.charAt(0) === '/' && search.charAt(search.length - 1) === '/') {
            regex = new RegExp(search.substring(1, search.length - 1),'i');
        }else{
            //simple match which is case-insensitive, escaping special regex chars
            regex = new RegExp(search.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'),'i');
        }
        return ko.utils.arrayFilter(names,function(val,ndx){
            var proj = self.projectForName(val);
            var label = proj.label();
            if (regex) {
                return val.match(regex) || label && label.match(regex);
            }
            return val.indexOf(search) >= 0 || label && label.indexOf(search) >= 0;
        });
    });
    self.searchedProjectsCount = ko.pureComputed(function () {
        return self.searchedProjects().length;
    });
    self.projectCount = ko.pureComputed(function () {
        return self.projectNames().length;
    });
    self.projectsByName = ko.pureComputed(function () {
        var obj = {};
        ko.utils.arrayForEach(self.projects(), function (elem, ndx) {
            obj[ko.unwrap(elem.name)] = elem;
        });
        return obj;
    });
    self.searchProjectsByName = ko.pureComputed(function () {
        var obj = {};
        ko.utils.arrayForEach(self.searchedProjects(), function (elem, ndx) {
            obj[ko.unwrap(elem.name)] = elem;
        });
        return obj;
    });
    self.projectInSearch=function(name){
        "use strict";
        return !self.search() || self.searchProjectsByName()[name]!=null;
    };
    self.prototypeProject = new Project({page: 'projectList'});
    self.projectForName = function (name) {
        var projectsByName = self.projectsByName()[name];
        if(null==projectsByName){
            return self.prototypeProject;
        }
        return projectsByName;
    };
    self.mapping = {
        'projects': {
            key: function (data) {
                return ko.utils.unwrapObservable(data.name);
            },
            create: function (data) {
                "use strict";
                return new Project(options.data);
            },
            update: function (options) {
                var updateArray = [];
                var found = options.parent.projectForName(options.data.name);
                if (found) {
                    return ko.mapping.fromJS(options.data, {}, found);
                } else {
                    return ko.mapping.fromJS(options.data, {}, {});
                }
            }
        }
    };
    self.loadSummary = function () {
        return jQuery.ajax({
            type: 'GET',
            contentType: 'json',
            headers: {'x-rundeck-ajax': 'true'},
            url: _genUrl(self.summaryUrl, {}),
            success: function (data, status, jqxhr) {

                ko.mapping.fromJS(data, self.mapping, self);
                self.loaded(true);

                if (self.doRefresh()) {
                    setTimeout(self.loadSummary, self.refreshDelay());
                }
            }
        });
    };
    self.loadProjects = function (projs) {
        for (var i = 0; i < projs.length; i++) {
            var newproj = projs[i];
            var found = self.projectForName(newproj.name);
            if (found && found.name()==newproj.name) {
                ko.mapping.fromJS(newproj, null, found);
                found.loaded(true);
            } else {
                self.projects.push(
                    new Project(jQuery.extend(newproj, {loaded: true, page: 'projectList'}))
                );
            }
        }
    };
    self.load = function (refresh) {
        var params = {};//refresh?{refresh:true}:{};
        if (self.doPaging()) {
            jQuery.extend(params, {
                offset: self.pagingOffset(),
                max: self.pagingMax()
            });
            self.pagingMax(self.pagingRepeatMax());
        }
        return jQuery.ajax({
            type: 'GET',
            contentType: 'json',
            headers: {'x-rundeck-ajax': 'true'},
            url: _genUrl(self.baseUrl, params),
            success: function (data, status, jqxhr) {
                if (data.projects) {
                    self.loadProjects(data.projects);
                }
                // ko.mapping.fromJS(data, self.mapping, self);
                if (self.doPaging() && data.nextoffset) {
                    self.pagingOffset(data.nextoffset);
                    if (self.pagingOffset() === -1) {
                        self.pagingOffset(0);
                    } else {
                        setTimeout(self.load.curry(true), self.pagingDelay());
                        return;
                    }
                }
            }
        });
    };
    self.pullBatch=function(){
        "use strict";
        //pull up to max number of items from batchList
        var items=self.batchList.splice(0,self.pagingMax());
        if(items.length>0) {
            self.batches.push(items);
        }
    };
    self.batchList.subscribe(function(newValue){
        "use strict";
        if(newValue.length>0){
            setTimeout(self.pullBatch,100);
        }
    });
    self.batches.subscribe(function(newValue){
        if(!self.batchLoading && newValue.length>0){
            self.batchLoading=true;
            setTimeout(self.loadBatch,100);
        }
    });
    self.clearBatchLoad=function(){
        "use strict";

        self.batchList([]);
        self.batches([]);
    };
    self.search.subscribe(self.clearBatchLoad);
    self.batchLoading=false;
    self.loadBatch = function () {
        self.batchLoading=true;
        var projects=self.batches.shift();
        if(null==projects || projects.length<1){
            self.batchLoading=false;
            return;
        }
        var params = {projects:projects.join(',')};//refresh?{refresh:true}:{};
        return jQuery.ajax({
            type: 'GET',
            contentType: 'json',
            headers: {'x-rundeck-ajax': 'true'},
            url: _genUrl(self.baseUrl, params),
            success: function (data, status, jqxhr) {
                if (data.projects) {
                    self.loadProjects(data.projects);
                }
                //...
                if(self.batches().length>0){
                    self.loadBatch();
                }else{
                    self.batchLoading=false;
                }
            }
        });
    };

    /**
     * bound via the ko/binding-waypoints knockout binding
     * example:
     * <span data-bind="waypoints: $root.waypointHandler" >
     */
    self.waypointHandler=function(){
        "use strict";
        var projectName = jQuery(this.element).data('project');
        if(!self.projectForName(projectName).loaded()) {
            self.batchList.push(projectName);
        }

        this.destroy();
    };
    //initial setup
    self.beginLoad = function () {

        if (self.doRefresh()) {
            setTimeout(self.loadSummary, self.refreshDelay());
        }
    };
    self.loadProjectNames = function () {
        return jQuery.ajax({
            type: 'GET',
            contentType: 'json',
            headers: {'x-rundeck-ajax': 'true'},
            url: _genUrl(self.projectNamesUrl, {}),
            success: function (data, status, jqxhr) {
                self.projectNames(data.projectNames);
                self.projectNamesTotal(data.projectNames.length);
                self.loadedProjectNames(true);
            }
        });
    };
    self.init = function () {
        self.beginLoad();
        if (self.projectCount() != self.projectNamesTotal()) {
            self.loadProjectNames();
        }
    };
}
var _waypointBatchTimer;
function batchInitWaypoints(arr,handler,count){
    "use strict";
    var arr2=arr.splice(0,count);
    if(arr2.length>0) {
        jQuery(arr2).waypoint(handler, {offset: '100%'});
        if (arr.length > 0) {
            _waypointBatchTimer=setTimeout(batchInitWaypoints.curry(arr, handler,count), 1500);
        }
    }
}
function initWaypoints(homedata,reset){
    "use strict";
    if(reset){
        if(_waypointBatchTimer){
            clearTimeout(_waypointBatchTimer);
            _waypointBatchTimer=null;
        }
        Waypoint.destroyAll();
    }

    batchInitWaypoints(jQuery('.project_list_item[data-project]'),homedata.waypointHandler,50);
}

/**
 * START page init
 */
var homedata;
function init() {
    // ko.options.deferUpdates = true;
    var pageparams = loadJsonData('homeDataPagingParams') || {};
    var projectNamesData = loadJsonData('projectNamesData');
    if (projectNamesData.projectNames == null) {
        projectNamesData.projectNames = [];
    }
    var statsdata = loadJsonData('statsData') || {};
    homedata = new HomeData(jQuery.extend({
        baseUrl: appLinks.menuHomeAjax,
        summaryUrl: appLinks.menuHomeSummaryAjax,
        projectNamesUrl: appLinks.menuProjectNamesAjax,
        projectNames: projectNamesData.projectNames.sort(),
        projectNamesTotal: projectNamesData.projectNamesTotal || 0
    },statsdata));
    homedata.loadedProjectNames(projectNamesData.projectNames.length == projectNamesData.projectNamesTotal);
    ko.applyBindings(homedata);

    homedata.pagingMax(pageparams.pagingInitialMax || 15);
    homedata.pagingRepeatMax(pageparams.pagingRepeatMax || 50);
    homedata.doRefresh(pageparams.summaryRefresh != null ? pageparams.summaryRefresh : true);
    homedata.refreshDelay(pageparams.refreshDelay || 60000);
    homedata.doPaging(pageparams.doPaging != null ? pageparams.doPaging : true);
    homedata.pagingDelay(pageparams.pagingDelay || 2000);
    homedata.searchedProjects.subscribe(function(val){
        "use strict";
        //when search results change, refresh waypoints
        ko.tasks.schedule(initWaypoints.curry(homedata,true));
    });
    if(homedata.loadedProjectNames()){
        //load waypoints manually
        initWaypoints(homedata);
    }
    homedata.loaded.subscribe(Waypoint.refreshAll);
    homedata.projects.subscribe(Waypoint.refreshAll);
    homedata.init();
}
jQuery(init);
<commit_msg>cleanup<commit_after>/*
 * Copyright 2016 SimplifyOps, Inc. (http://simplifyops.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//= require knockout.min
//= require knockout-mapping
//= require knockout-onenter
//= require ko/binding-url-path-param
//= require ko/binding-message-template
//= require jquery.waypoints.min
//= require menu/project-model

function HomeData(data) {
    var self = this;
    self.baseUrl = data.baseUrl;
    self.summaryUrl = data.summaryUrl;
    self.projectNamesUrl = data.projectNamesUrl;
    self.loaded = ko.observable(data.loaded?true:false);
    self.jobCount = ko.observable(0);
    self.execCount = ko.observable(data.execCount||0);
    self.totalFailedCount = ko.observable(data.totalFailedCount||0);
    self.projectNames = ko.observableArray(data.projectNames || []);
    self.projectNamesTotal = ko.observable(data.projectNamesTotal || 0);
    self.loadedProjectNames = ko.observable(false);
    self.projects = ko.observableArray([]);
    self.projects.extend({rateLimit: 500});

    self.recentUsers = ko.observableArray(data.recentUsers||[]);
    self.recentProjects = ko.observableArray(data.recentProjects||[]);
    self.frameworkNodeName = ko.observable(null);
    self.doRefresh = ko.observable(false);
    self.doPaging = ko.observable(false);
    self.pagingMax = ko.observable(20);
    self.pagingRepeatMax = ko.observable(20);
    self.pagingDelay = ko.observable(2000);
    self.pagingOffset = ko.observable(0);
    self.refreshDelay = ko.observable(30000);
    self.search=ko.observable(null);

    //batch of project data to load
    self.batchList=ko.observableArray([]);
    self.batchList.extend({ rateLimit: 500 });
    self.batches=ko.observableArray([]);

    self.recentUsersCount = ko.pureComputed(function () {
        return self.recentUsers().length;
    });
    self.recentProjectsCount = ko.pureComputed(function () {
        return self.recentProjects().length;
    });
    self.searchedProjects=ko.pureComputed(function(){
        "use strict";
        var search=self.search();
        var names=self.projectNames();
        if(null==search){
            return names;
        }
        var regex;
        if (search.charAt(0) === '/' && search.charAt(search.length - 1) === '/') {
            regex = new RegExp(search.substring(1, search.length - 1),'i');
        }else{
            //simple match which is case-insensitive, escaping special regex chars
            regex = new RegExp(search.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'),'i');
        }
        return ko.utils.arrayFilter(names,function(val,ndx){
            var proj = self.projectForName(val);
            var label = proj.label();
            return val.match(regex) || label && label.match(regex);
        });
    });
    self.searchedProjectsCount = ko.pureComputed(function () {
        return self.searchedProjects().length;
    });
    self.projectCount = ko.pureComputed(function () {
        return self.projectNames().length;
    });
    self.projectsByName = ko.pureComputed(function () {
        var obj = {};
        ko.utils.arrayForEach(self.projects(), function (elem, ndx) {
            obj[ko.unwrap(elem.name)] = elem;
        });
        return obj;
    });
    self.searchProjectsByName = ko.pureComputed(function () {
        var obj = {};
        ko.utils.arrayForEach(self.searchedProjects(), function (elem, ndx) {
            obj[ko.unwrap(elem.name)] = elem;
        });
        return obj;
    });
    self.projectInSearch=function(name){
        "use strict";
        return !self.search() || self.searchProjectsByName()[name]!=null;
    };
    self.prototypeProject = new Project({page: 'projectList'});
    self.projectForName = function (name) {
        var projectsByName = self.projectsByName()[name];
        if(null==projectsByName){
            return self.prototypeProject;
        }
        return projectsByName;
    };
    self.mapping = {
        'projects': {
            key: function (data) {
                return ko.utils.unwrapObservable(data.name);
            },
            create: function (data) {
                "use strict";
                return new Project(options.data);
            },
            update: function (options) {
                var updateArray = [];
                var found = options.parent.projectForName(options.data.name);
                if (found) {
                    return ko.mapping.fromJS(options.data, {}, found);
                } else {
                    return ko.mapping.fromJS(options.data, {}, {});
                }
            }
        }
    };
    self.loadSummary = function () {
        return jQuery.ajax({
            type: 'GET',
            contentType: 'json',
            headers: {'x-rundeck-ajax': 'true'},
            url: _genUrl(self.summaryUrl, {}),
            success: function (data, status, jqxhr) {

                ko.mapping.fromJS(data, self.mapping, self);
                self.loaded(true);

                if (self.doRefresh()) {
                    setTimeout(self.loadSummary, self.refreshDelay());
                }
            }
        });
    };
    self.loadProjects = function (projs) {
        for (var i = 0; i < projs.length; i++) {
            var newproj = projs[i];
            var found = self.projectForName(newproj.name);
            if (found && found.name()==newproj.name) {
                ko.mapping.fromJS(newproj, null, found);
                found.loaded(true);
            } else {
                self.projects.push(
                    new Project(jQuery.extend(newproj, {loaded: true, page: 'projectList'}))
                );
            }
        }
    };
    self.load = function (refresh) {
        var params = {};//refresh?{refresh:true}:{};
        if (self.doPaging()) {
            jQuery.extend(params, {
                offset: self.pagingOffset(),
                max: self.pagingMax()
            });
            self.pagingMax(self.pagingRepeatMax());
        }
        return jQuery.ajax({
            type: 'GET',
            contentType: 'json',
            headers: {'x-rundeck-ajax': 'true'},
            url: _genUrl(self.baseUrl, params),
            success: function (data, status, jqxhr) {
                if (data.projects) {
                    self.loadProjects(data.projects);
                }
                // ko.mapping.fromJS(data, self.mapping, self);
                if (self.doPaging() && data.nextoffset) {
                    self.pagingOffset(data.nextoffset);
                    if (self.pagingOffset() === -1) {
                        self.pagingOffset(0);
                    } else {
                        setTimeout(self.load.curry(true), self.pagingDelay());
                        return;
                    }
                }
            }
        });
    };
    self.pullBatch=function(){
        "use strict";
        //pull up to max number of items from batchList
        var items=self.batchList.splice(0,self.pagingMax());
        if(items.length>0) {
            self.batches.push(items);
        }
    };
    self.batchList.subscribe(function(newValue){
        "use strict";
        if(newValue.length>0){
            setTimeout(self.pullBatch,100);
        }
    });
    self.batches.subscribe(function(newValue){
        if(!self.batchLoading && newValue.length>0){
            self.batchLoading=true;
            setTimeout(self.loadBatch,100);
        }
    });
    self.clearBatchLoad=function(){
        "use strict";

        self.batchList([]);
        self.batches([]);
    };
    self.search.subscribe(self.clearBatchLoad);
    self.batchLoading=false;
    self.loadBatch = function () {
        self.batchLoading=true;
        var projects=self.batches.shift();
        if(null==projects || projects.length<1){
            self.batchLoading=false;
            return;
        }
        var params = {projects:projects.join(',')};//refresh?{refresh:true}:{};
        return jQuery.ajax({
            type: 'GET',
            contentType: 'json',
            headers: {'x-rundeck-ajax': 'true'},
            url: _genUrl(self.baseUrl, params),
            success: function (data, status, jqxhr) {
                if (data.projects) {
                    self.loadProjects(data.projects);
                }
                //...
                if(self.batches().length>0){
                    self.loadBatch();
                }else{
                    self.batchLoading=false;
                }
            }
        });
    };

    /**
     * bound via the ko/binding-waypoints knockout binding
     * example:
     * <span data-bind="waypoints: $root.waypointHandler" >
     */
    self.waypointHandler=function(){
        "use strict";
        var projectName = jQuery(this.element).data('project');
        if(!self.projectForName(projectName).loaded()) {
            self.batchList.push(projectName);
        }

        this.destroy();
    };
    //initial setup
    self.beginLoad = function () {

        if (self.doRefresh()) {
            setTimeout(self.loadSummary, self.refreshDelay());
        }
    };
    self.loadProjectNames = function () {
        return jQuery.ajax({
            type: 'GET',
            contentType: 'json',
            headers: {'x-rundeck-ajax': 'true'},
            url: _genUrl(self.projectNamesUrl, {}),
            success: function (data, status, jqxhr) {
                self.projectNames(data.projectNames);
                self.projectNamesTotal(data.projectNames.length);
                self.loadedProjectNames(true);
            }
        });
    };
    self.init = function () {
        self.beginLoad();
        if (self.projectCount() != self.projectNamesTotal()) {
            self.loadProjectNames();
        }
    };
}
var _waypointBatchTimer;
function batchInitWaypoints(arr,handler,count){
    "use strict";
    var arr2=arr.splice(0,count);
    if(arr2.length>0) {
        jQuery(arr2).waypoint(handler, {offset: '100%'});
        if (arr.length > 0) {
            _waypointBatchTimer=setTimeout(batchInitWaypoints.curry(arr, handler,count), 1500);
        }
    }
}
function initWaypoints(homedata,reset){
    "use strict";
    if(reset){
        if(_waypointBatchTimer){
            clearTimeout(_waypointBatchTimer);
            _waypointBatchTimer=null;
        }
        Waypoint.destroyAll();
    }

    batchInitWaypoints(jQuery('.project_list_item[data-project]'),homedata.waypointHandler,50);
}

/**
 * START page init
 */
var homedata;
function init() {
    // ko.options.deferUpdates = true;
    var pageparams = loadJsonData('homeDataPagingParams') || {};
    var projectNamesData = loadJsonData('projectNamesData');
    if (projectNamesData.projectNames == null) {
        projectNamesData.projectNames = [];
    }
    var statsdata = loadJsonData('statsData') || {};
    homedata = new HomeData(jQuery.extend({
        baseUrl: appLinks.menuHomeAjax,
        summaryUrl: appLinks.menuHomeSummaryAjax,
        projectNamesUrl: appLinks.menuProjectNamesAjax,
        projectNames: projectNamesData.projectNames.sort(),
        projectNamesTotal: projectNamesData.projectNamesTotal || 0
    },statsdata));
    homedata.loadedProjectNames(projectNamesData.projectNames.length == projectNamesData.projectNamesTotal);
    ko.applyBindings(homedata);

    homedata.pagingMax(pageparams.pagingInitialMax || 15);
    homedata.pagingRepeatMax(pageparams.pagingRepeatMax || 50);
    homedata.doRefresh(pageparams.summaryRefresh != null ? pageparams.summaryRefresh : true);
    homedata.refreshDelay(pageparams.refreshDelay || 60000);
    homedata.doPaging(pageparams.doPaging != null ? pageparams.doPaging : true);
    homedata.pagingDelay(pageparams.pagingDelay || 2000);
    homedata.searchedProjects.subscribe(function(val){
        "use strict";
        //when search results change, refresh waypoints
        ko.tasks.schedule(initWaypoints.curry(homedata,true));
    });
    if(homedata.loadedProjectNames()){
        //load waypoints manually
        initWaypoints(homedata);
    }
    homedata.loaded.subscribe(Waypoint.refreshAll);
    homedata.projects.subscribe(Waypoint.refreshAll);
    homedata.init();
}
jQuery(init);
<|endoftext|>


<commit_before>//Block of constants used to name classes of HTML elements created, if change needed change the constant's value

const processDivClassName = "processes";
const frameDivClassName = "frame";
const frameTitleClassName = "frameTitle";
const lifelines = "lifeLine";
const arrowDivClassNameL2R = "arrowLtoR";
const arrowDivClassNameR2L = "arrowRtoL";
const messageDivClassName = "messages";
//const activatorClassName = "activator";

var animator = JSON.parse(localStorage.getItem('stringJSON'));
var mainDiv = document.getElementById("outputJSON");

window.onload = function animateJSON() {

    //Selects the processes array in JSON File and iterates for every element

    for (var i = 0; i < animator.processes.length; i++) {

        createObject(animator, i);

        //Similar behavior as in the previous block, but this time the lifelines are given a unique ID, are appended to the <div> created in the previous block
        //and the activators are appended to the lifeline divs.

        createLifeline(animator, i);

        // var activatorDiv = document.createElement("div");
        // activatorDiv.className = activatorClassName;
        // lifeLineDiv.appendChild(activatorDiv);
    }

    var animatorDiagramArray = Object.keys(animator.diagram); //In order to check whether or not the JSON element is a node, we must select the diagram object's keys.
    //if (animatorDiagramArray.hasOwnProperty('node'))
    for (var i = 0; i < animatorDiagramArray.length; i++) {   //loop through the array of Keys created above
        if (animatorDiagramArray[i] === 'node') {             //we check wether the JSON element is a node here
             frameDiv = document.createElement("div");
            frameDiv.className = frameDivClassName;
            frameDiv.id = animator.diagram.node.toString();
            mainDiv.appendChild(frameDiv);

            var frameTitle = document.createElement("div");
            frameTitle.className = frameTitleClassName;
            frameTitle.id = animator.diagram.node.toString() + "Title";
            frameTitle.innerHTML = animator.diagram.node.toString();
            frameDiv.appendChild(frameTitle);
        }
    }

    createArrow(animator, 0, 0, frameDiv, mainDiv);
    createLog(animator, 0, 0, 0);

};

/*
* This function creates arrows based on the direction of the arrow by using the functions arrowL2R and arrowR2L.
* It checks the start and end position of each arrow in the content of the diagram section provided in the JSON file.
* The function is set to a timeout in order to generate the arrows one by one with a timeout of one second.
 */

function createArrow(animator, j, i, mainDiv) {

    // resets the i and increment j as for loop inside a for loop  to get all messages.
    if (animator.diagram.content[j].content.length === i) {

        i = 0;
        j++;

        var lineBreak = document.createElement('hr');

        if (frameDiv != undefined) {
            frameDiv.appendChild(lineBreak);
        }
    }

    var startPosition = getPosition(document.querySelector("#" + animator.diagram.content[j].content[i].from.toString()));
    var endPosition = getPosition(document.querySelector("#" + animator.diagram.content[j].content[i].to.toString()));

    // decides what direction the arrow will go, and makes the length of the arrows

    if (startPosition.x > endPosition.x) {

        arrowR2L(startPosition, endPosition, j, i);
    }
    else {

        arrowL2R(startPosition, endPosition, j, i);
    }

    // base case of the recursive loop

    if (animator.diagram.content[j].content[i + 1] === undefined && j + 1 === animator.diagram.content.length) {}

    // the recursive call of the loop and the incrementing of var i

    else {
        setTimeout(function () {
            i++;
            createArrow(animator, j, i, mainDiv);
        }, 1000);
    }
}

function createLog(animator, i, e, total) {
    var ul = document.getElementById("logList");

    // resets the i and increment e as for loop inside a for loop to get all messages.

    if (animator.diagram.content[e].content.length === i) {
        i = 0;
        e++;
    }

    var li = document.createElement("li");
    li.setAttribute('id', ((total + 1) + ": Sending message From: " +
        animator.diagram.content[e].content[i].from.toString() + " To: " +
        animator.diagram.content[e].content[i].to.toString() + " || Message: " +
        animator.diagram.content[e].content[i].message.toString()));
    li.appendChild(document.createTextNode((total + 1) + ": Sending message From: " +
        animator.diagram.content[e].content[i].from.toString() + " To: " +
        animator.diagram.content[e].content[i].to.toString() + " || Message: " +
        animator.diagram.content[e].content[i].message.toString()));
    ul.appendChild(li);

    if (animator.diagram.content.length > e) {

        // base case of the recursive loop

        if (animator.diagram.content[e].content[i + 1] === undefined && e + 1 === animator.diagram.content.length) {
        }

        // the recursive call of the loop and the incrementing of var i

        else {
            setTimeout(function () {
                i++;
                total++;
                createLog(animator, i, e, total);
            }, 1000);
        }

    }

}

/*
 * This function generates an arrow with the specific direction of left to right. It also generates the div related to
 * the message that each arrow carries. As stated in the function, arrows are children of frameDiv.
 */

function arrowL2R(from, to, j, i) {

    var arrow = document.createElement("div");
    var svg = document.createElementNS('http://www.w3.org/2000/svg', "svg");
    var polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
    var message = document.createElement("div");

    arrow.className = arrowDivClassNameL2R;
    var arrowLengthL2R = to.x - from.x;
    arrow.style.maxWidth = arrowLengthL2R + 'px';

    svg.setAttribute("preserveAspectRatio", "xMaxYMid slice");
    svg.setAttribute("viewBox", "0 0 1400 14");
    svg.setAttribute("width", "100%");
    svg.setAttribute("height", "14");
    polygon.setAttribute("points", "1400,7 1385,1 1390,6 0,6 0,8 1390,8 1385,13 1400,7");

    arrow.style.left = from.x - 30 + 'px';

    message.className = messageDivClassName;
    message.innerHTML = animator.diagram.content[j].content[i].message.toString();

    arrow.appendChild(message);
    svg.appendChild(polygon);
    arrow.appendChild(svg);

    if (frameDiv === undefined) {
        mainDiv.appendChild(arrow);
    }
    else {
        frameDiv.appendChild(arrow);
    }

}

/*
 * This function generates an arrow with the specific direction of right to left. It also generates the div related to
 * the message that each arrow carries. As stated in the function, arrows are children of frameDiv.
 */

function arrowR2L(from, to, j, i) {

    var arrow = document.createElement("div");
    var svg = document.createElementNS('http://www.w3.org/2000/svg', "svg");
    var polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
    var message = document.createElement("div");

    arrow.className = arrowDivClassNameR2L;
    var arrowLengthR2L = from.x - to.x;
    arrow.style.maxWidth = arrowLengthR2L + 'px';

    svg.setAttribute("preserveAspectRatio", "xMinYMid slice");
    svg.setAttribute("viewBox", "0 0 1400 14");
    svg.setAttribute("width", "100%");
    svg.setAttribute("height", "14");
    polygon.setAttribute("points", "0,7 15,1 10,6 1400,6 1400,8 10,8 15,13 0,7");

    arrow.style.left =  to.x - 30 + 'px';

    message.className = messageDivClassName;
    message.innerHTML = animator.diagram.content[j].content[i].message.toString();

    arrow.appendChild(message);
    svg.appendChild(polygon);
    arrow.appendChild(svg);

    if (frameDiv === undefined) {
        mainDiv.appendChild(arrow);
    }
    else {
        frameDiv.appendChild(arrow);
    }
}

/*
 * Helper function that gets an arrow's exact position by using its dedicated id
 */

function getPosition(el) {
    var xPos = 0;
    var yPos = 0;
    while (el) {
        if (el.tagName == "BODY") {
            // deal with browser quirks with body/window/document and page scroll
            var xScroll = el.scrollLeft || document.documentElement.scrollLeft;
            var yScroll = el.scrollTop || document.documentElement.scrollTop;

            xPos += (el.offsetLeft - xScroll + el.clientLeft);
            yPos += (el.offsetTop - yScroll + el.clientTop);
        } else {
            // for all other non-BODY elements
            xPos += (el.offsetLeft - el.scrollLeft + el.clientLeft);
            yPos += (el.offsetTop - el.scrollTop + el.clientTop);
        }

        el = el.offsetParent;
    }
    return {
        x: xPos,
        y: yPos
    };
}

/*
 * This function creates an object (process) in the SSD diagram from the list of processes in the JSON file provided.
 */

function createObject(animator, i) {

    div = document.createElement("div");            //Creates an HTML <div> element
    div.className = processDivClassName;                //assigns it a class
    div.innerHTML =
        animator.processes[i].name.toString() + ": " +  //Gives it a text output as specified in the JSON file, here the class and name of the object
        animator.processes[i].class.toString();         //here it is the class and name of the SSD object
    mainDiv.appendChild(div);                           //Places the new <div> element under the mainDiv, as specified in the variable declaration in l.4

}

/*
 * This function creates the lifeline related to each object (process) in the SSD diagram. It also assigns an id to
 * each lifeline including the name of its object's name. This id is used later in locating the start and end position
 * of the arrows.
 */

function createLifeline(animator, i) {

    var lifeLineDiv = document.createElement("div");
    lifeLineDiv.className = lifelines;
    lifeLineDiv.id = animator.processes[i].name.toString();
    div.appendChild(lifeLineDiv);

}

    // Get a reference to the div you want to auto-scroll.
    var mainDivElement = document.querySelector("outputJSON");
    // Create an observer and pass it a callback.
    var observer = new MutationObserver(scrollToBottom);
    // Tell it to look for new children that will change the height.
    var config = {attributes:true,characterData:true,childList: true};
    observer.observe(mainDivElement, config);

// First, define a helper function.
function animateScroll(duration) {
    var start = mainDivElement.scrollTop;
    var end = mainDivElement.scrollHeight;
    var change = end - start;
    var increment = 20;
    function easeInOut(currentTime, start, change, duration) {
      // by Robert Penner  Easing Functions
      currentTime /= duration / 2;
      if (currentTime < 1) {
        return change / 2 * currentTime * currentTime + start;
      }
      currentTime -= 1;
      return -change / 2 * (currentTime * (currentTime - 2) - 1) + start;
    }

    function animate(elapsedTime) {
      elapsedTime += increment;
      var position = easeInOut(elapsedTime, start, change, duration);
      mainDivElement.scrollTop = position;
      if (elapsedTime < duration) {
        setTimeout(function() {
          animate(elapsedTime);
        }, increment)
      }
    }
    animate(0);
  }

  // Here's our main callback function we passed to the observer
  function scrollToBottom() {
    var duration = 1000 // Or however many milliseconds you want to scroll to last
    animateScroll(duration);
  }<commit_msg>fixed the smooth scroll of the mainDIV every time there is change occured in the div height<commit_after>//Block of constants used to name classes of HTML elements created, if change needed change the constant's value

const processDivClassName = "processes";
const frameDivClassName = "frame";
const frameTitleClassName = "frameTitle";
const lifelines = "lifeLine";
const arrowDivClassNameL2R = "arrowLtoR";
const arrowDivClassNameR2L = "arrowRtoL";
const messageDivClassName = "messages";
//const activatorClassName = "activator";

var animator = JSON.parse(localStorage.getItem('stringJSON'));
var mainDiv = document.getElementById("outputJSON");

window.onload = function animateJSON() {

    //Selects the processes array in JSON File and iterates for every element

    for (var i = 0; i < animator.processes.length; i++) {

        createObject(animator, i);

        //Similar behavior as in the previous block, but this time the lifelines are given a unique ID, are appended to the <div> created in the previous block
        //and the activators are appended to the lifeline divs.

        createLifeline(animator, i);

        // var activatorDiv = document.createElement("div");
        // activatorDiv.className = activatorClassName;
        // lifeLineDiv.appendChild(activatorDiv);
    }

    var animatorDiagramArray = Object.keys(animator.diagram); //In order to check whether or not the JSON element is a node, we must select the diagram object's keys.
    //if (animatorDiagramArray.hasOwnProperty('node'))
    for (var i = 0; i < animatorDiagramArray.length; i++) {   //loop through the array of Keys created above
        if (animatorDiagramArray[i] === 'node') {             //we check wether the JSON element is a node here
             frameDiv = document.createElement("div");
            frameDiv.className = frameDivClassName;
            frameDiv.id = animator.diagram.node.toString();
            mainDiv.appendChild(frameDiv);

            var frameTitle = document.createElement("div");
            frameTitle.className = frameTitleClassName;
            frameTitle.id = animator.diagram.node.toString() + "Title";
            frameTitle.innerHTML = animator.diagram.node.toString();
            frameDiv.appendChild(frameTitle);
        }
    }

    createArrow(animator, 0, 0, frameDiv, mainDiv);
    createLog(animator, 0, 0, 0);

};

/*
* This function creates arrows based on the direction of the arrow by using the functions arrowL2R and arrowR2L.
* It checks the start and end position of each arrow in the content of the diagram section provided in the JSON file.
* The function is set to a timeout in order to generate the arrows one by one with a timeout of one second.
 */

function createArrow(animator, j, i, mainDiv) {

    // resets the i and increment j as for loop inside a for loop  to get all messages.
    if (animator.diagram.content[j].content.length === i) {

        i = 0;
        j++;

        var lineBreak = document.createElement('hr');

        if (frameDiv != undefined) {
            frameDiv.appendChild(lineBreak);
        }
    }

    var startPosition = getPosition(document.querySelector("#" + animator.diagram.content[j].content[i].from.toString()));
    var endPosition = getPosition(document.querySelector("#" + animator.diagram.content[j].content[i].to.toString()));

    // decides what direction the arrow will go, and makes the length of the arrows

    if (startPosition.x > endPosition.x) {

        arrowR2L(startPosition, endPosition, j, i);
    }
    else {

        arrowL2R(startPosition, endPosition, j, i);
    }

    // base case of the recursive loop

    if (animator.diagram.content[j].content[i + 1] === undefined && j + 1 === animator.diagram.content.length) {}

    // the recursive call of the loop and the incrementing of var i

    else {
        setTimeout(function () {
            i++;
            createArrow(animator, j, i, mainDiv);
        }, 1000);
    }
}

function createLog(animator, i, e, total) {
    var ul = document.getElementById("logList");

    // resets the i and increment e as for loop inside a for loop to get all messages.

    if (animator.diagram.content[e].content.length === i) {
        i = 0;
        e++;
    }

    var li = document.createElement("li");
    li.setAttribute('id', ((total + 1) + ": Sending message From: " +
        animator.diagram.content[e].content[i].from.toString() + " To: " +
        animator.diagram.content[e].content[i].to.toString() + " || Message: " +
        animator.diagram.content[e].content[i].message.toString()));
    li.appendChild(document.createTextNode((total + 1) + ": Sending message From: " +
        animator.diagram.content[e].content[i].from.toString() + " To: " +
        animator.diagram.content[e].content[i].to.toString() + " || Message: " +
        animator.diagram.content[e].content[i].message.toString()));
    ul.appendChild(li);

    if (animator.diagram.content.length > e) {

        // base case of the recursive loop

        if (animator.diagram.content[e].content[i + 1] === undefined && e + 1 === animator.diagram.content.length) {
        }

        // the recursive call of the loop and the incrementing of var i

        else {
            setTimeout(function () {
                i++;
                total++;
                createLog(animator, i, e, total);
            }, 1000);
        }

    }

}

/*
 * This function generates an arrow with the specific direction of left to right. It also generates the div related to
 * the message that each arrow carries. As stated in the function, arrows are children of frameDiv.
 */

function arrowL2R(from, to, j, i) {

    var arrow = document.createElement("div");
    var svg = document.createElementNS('http://www.w3.org/2000/svg', "svg");
    var polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
    var message = document.createElement("div");

    arrow.className = arrowDivClassNameL2R;
    var arrowLengthL2R = to.x - from.x;
    arrow.style.maxWidth = arrowLengthL2R + 'px';

    svg.setAttribute("preserveAspectRatio", "xMaxYMid slice");
    svg.setAttribute("viewBox", "0 0 1400 14");
    svg.setAttribute("width", "100%");
    svg.setAttribute("height", "14");
    polygon.setAttribute("points", "1400,7 1385,1 1390,6 0,6 0,8 1390,8 1385,13 1400,7");

    arrow.style.left = from.x - 30 + 'px';

    message.className = messageDivClassName;
    message.innerHTML = animator.diagram.content[j].content[i].message.toString();

    arrow.appendChild(message);
    svg.appendChild(polygon);
    arrow.appendChild(svg);

    if (frameDiv === undefined) {
        mainDiv.appendChild(arrow);
    }
    else {
        frameDiv.appendChild(arrow);
    }

}

/*
 * This function generates an arrow with the specific direction of right to left. It also generates the div related to
 * the message that each arrow carries. As stated in the function, arrows are children of frameDiv.
 */

function arrowR2L(from, to, j, i) {

    var arrow = document.createElement("div");
    var svg = document.createElementNS('http://www.w3.org/2000/svg', "svg");
    var polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
    var message = document.createElement("div");

    arrow.className = arrowDivClassNameR2L;
    var arrowLengthR2L = from.x - to.x;
    arrow.style.maxWidth = arrowLengthR2L + 'px';

    svg.setAttribute("preserveAspectRatio", "xMinYMid slice");
    svg.setAttribute("viewBox", "0 0 1400 14");
    svg.setAttribute("width", "100%");
    svg.setAttribute("height", "14");
    polygon.setAttribute("points", "0,7 15,1 10,6 1400,6 1400,8 10,8 15,13 0,7");

    arrow.style.left =  to.x - 30 + 'px';

    message.className = messageDivClassName;
    message.innerHTML = animator.diagram.content[j].content[i].message.toString();

    arrow.appendChild(message);
    svg.appendChild(polygon);
    arrow.appendChild(svg);

    if (frameDiv === undefined) {
        mainDiv.appendChild(arrow);
    }
    else {
        frameDiv.appendChild(arrow);
    }
}

/*
 * Helper function that gets an arrow's exact position by using its dedicated id
 */

function getPosition(el) {
    var xPos = 0;
    var yPos = 0;
    while (el) {
        if (el.tagName == "BODY") {
            // deal with browser quirks with body/window/document and page scroll
            var xScroll = el.scrollLeft || document.documentElement.scrollLeft;
            var yScroll = el.scrollTop || document.documentElement.scrollTop;

            xPos += (el.offsetLeft - xScroll + el.clientLeft);
            yPos += (el.offsetTop - yScroll + el.clientTop);
        } else {
            // for all other non-BODY elements
            xPos += (el.offsetLeft - el.scrollLeft + el.clientLeft);
            yPos += (el.offsetTop - el.scrollTop + el.clientTop);
        }

        el = el.offsetParent;
    }
    return {
        x: xPos,
        y: yPos
    };
}

/*
 * This function creates an object (process) in the SSD diagram from the list of processes in the JSON file provided.
 */

function createObject(animator, i) {

    div = document.createElement("div");            //Creates an HTML <div> element
    div.className = processDivClassName;                //assigns it a class
    div.innerHTML =
        animator.processes[i].name.toString() + ": " +  //Gives it a text output as specified in the JSON file, here the class and name of the object
        animator.processes[i].class.toString();         //here it is the class and name of the SSD object
    mainDiv.appendChild(div);                           //Places the new <div> element under the mainDiv, as specified in the variable declaration in l.4

}

/*
 * This function creates the lifeline related to each object (process) in the SSD diagram. It also assigns an id to
 * each lifeline including the name of its object's name. This id is used later in locating the start and end position
 * of the arrows.
 */

function createLifeline(animator, i) {

    var lifeLineDiv = document.createElement("div");
    lifeLineDiv.className = lifelines;
    lifeLineDiv.id = animator.processes[i].name.toString();
    div.appendChild(lifeLineDiv);

}

    // Get a reference to the div you want to auto-scroll.
    var mainDivElement = document.querySelector("#outputJSON");
    // Create an observer and pass it a callback.
    var observer = new MutationObserver(scrollToBottom);
    // Tell it to look for new children that will change the height.
    var config = {attributes:true,characterData:true,childList: true,attributeFilter: ["id"]};
    observer.observe(mainDivElement, config);
    // later, you can stop observing
    //observer.disconnect();

// First, define a helper function.
function animateScroll(duration) {
    var start = mainDivElement.scrollTop;
    var end = mainDivElement.scrollHeight;
    var change = end - start;
    var increment = 15;
    function easeInOut(currentTime, start, change, duration) {
      // by Robert Penner  Easing Functions
      currentTime /= duration / 2;
      if (currentTime < 1) {
        return change / 2 * currentTime * currentTime + start;
      }
      currentTime -= 1;
      return -change / 2 * (currentTime * (currentTime - 2) - 1) + start;
    }

    function animate(elapsedTime) {
      elapsedTime += increment;
      var position = easeInOut(elapsedTime, start, change, duration);
      mainDivElement.scrollTop = position;
      if (elapsedTime < duration) {
        setTimeout(function() {
          animate(elapsedTime);
        }, increment)
      }
    }
    animate(0);
  }

  // Here's our main callback function we passed to the observer
  function scrollToBottom() {
    var duration = 11600 // Or however many milliseconds you want to scroll to last
    animateScroll(duration);
  }<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011  JTalks.org Team
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
var Utils = {};

function quote(postId) {
    var callback = function (text) {
        console.log(text);
        var answer = $('#postBody');
        if (answer) {
            answer.val(answer.val() + text);
        }
    }

    $.ajax({
        url: baseUrl + '/posts/' + postId + '/ajax_quote',
        type: 'GET',
        data: {
            selection: getSelectedPostText()
        },
        success: function (data) {
            callback(data.result);
        },
        error: function () {
            callback('');
        }
    });

}

function getSelectedPostText() {
    var txt = '';
    if (document.getSelection) {
        txt = document.getSelection().toString();
    }
    else if (window.getSelection) {
        txt = window.getSelection().toString();
    }
    else if (document.selection) {
        txt = document.selection.createRange().text;
    }
    return txt;
}

/**
 * Encodes given string by escaping special HTML characters
 *
 * @param s string to be encoded
 */
Utils.htmlEncode = function (s) {
    return s
    .replace(/&/g, "&")
    .replace(/</g, "<")
    .replace(/>/g, ">")
    .replace(/"/g, """)
    .replace(/'/g, "'");
};

/**
 * Do focus to element
 *
 * @param target selector of element to focus
 */
Utils.focusFirstEl = function (target) {
    $(target).focus();
}

/**
 * Replaces all \n characters by
 tags. Used for review comments.
 *
 * @param s string where perform replacing
 */
Utils.lf2br = function (s) {
    return s.replace(/\n/g, "
");
}

/**
 * Replaces all \
 tags by \n characters. Used for review comments.
 *
 * @param s string where perform replacing
 */
Utils.br2lf = function (s) {
    return s.replace(/
/gi, "\n");
}

/**
 * Create form field with given label(placeholder), id, type
 */
Utils.createFormElement = function (label, id, type, cls) {
    var elementHtml = ' \

 \

 \
                <input type="' + type + '" id="' + id + '" name="' + id + '" placeholder="' + label + '" class="input-xlarge ' + cls + '" /> \

 \

 \
    ';

    return elementHtml;
}
<commit_msg>#JC-1706 small fix to encode html<commit_after>/*
 * Copyright (C) 2011  JTalks.org Team
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
var Utils = {};

function quote(postId) {
    var callback = function (text) {
        console.log(text);
        var answer = $('#postBody');
        if (answer) {
            answer.val(answer.val() + text);
        }
    }

    $.ajax({
        url: baseUrl + '/posts/' + postId + '/ajax_quote',
        type: 'GET',
        data: {
            selection: getSelectedPostText()
        },
        success: function (data) {
            callback(data.result);
        },
        error: function () {
            callback('');
        }
    });

}

function getSelectedPostText() {
    var txt = '';
    if (document.getSelection) {
        txt = document.getSelection().toString();
    }
    else if (window.getSelection) {
        txt = window.getSelection().toString();
    }
    else if (document.selection) {
        txt = document.selection.createRange().text;
    }
    return txt;
}

/**
 * Encodes given string by escaping special HTML characters
 *
 * @param s string to be encoded
 */
Utils.htmlEncode = function (s) {
    return $('
').text(s).html();
};

/**
 * Do focus to element
 *
 * @param target selector of element to focus
 */
Utils.focusFirstEl = function (target) {
    $(target).focus();
}

/**
 * Replaces all \n characters by
 tags. Used for review comments.
 *
 * @param s string where perform replacing
 */
Utils.lf2br = function (s) {
    return s.replace(/\n/g, "
");
}

/**
 * Replaces all \
 tags by \n characters. Used for review comments.
 *
 * @param s string where perform replacing
 */
Utils.br2lf = function (s) {
    return s.replace(/
/gi, "\n");
}

/**
 * Create form field with given label(placeholder), id, type
 */
Utils.createFormElement = function (label, id, type, cls) {
    var elementHtml = ' \

 \

 \
                <input type="' + type + '" id="' + id + '" name="' + id + '" placeholder="' + label + '" class="input-xlarge ' + cls + '" /> \

 \

 \
    ';

    return elementHtml;
}
<|endoftext|>


<commit_before>var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {
	req.getCredentials(function(error, credentials){
		if(error) res.status(500).json({ error: "Not Authenticated" });
		// Add better error handling here
		req.database.models.mail.find().where({ receiver: credentials.email }).exec(function(error, mails){
			if(error) res.status(500).json({ error: "Not Authenticated" });
			if((!mails)||(mails.length < 1)) mails = [];
			res.render('mailbox', { mails: mails });
<<<<<<< HEAD
			res.set("Connection", "close");
=======
>>>>>>> parent of 4a39943... Added connection close
		});
	});
});

module.exports = router;<commit_msg>Fixed Git revert error<commit_after>var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {
	req.getCredentials(function(error, credentials){
		if(error) res.status(500).json({ error: "Not Authenticated" });
		// Add better error handling here
		req.database.models.mail.find().where({ receiver: credentials.email }).exec(function(error, mails){
			if(error) res.status(500).json({ error: "Not Authenticated" });
			if((!mails)||(mails.length < 1)) mails = [];
			res.render('mailbox', { mails: mails });
		});
	});
});

module.exports = router;<|endoftext|>


<commit_before>var path = require('path')

const downgraded = [
  'array-callback-return',
  'class-methods-use-this',
  'consistent-return',
  'eqeqeq',
  'no-async-promise-executor',
  'no-await-in-loop',
  'no-self-compare',
  'no-shadow',
  'no-underscore-dangle',
  'no-use-before-define',
]

module.exports = {
  extends: '@ln-zap',
  rules: downgraded.reduce(
    (acc, next) => {
      acc[next] = 'warn'
      return acc
    },
    {
      'no-unused-expressions': ['error', { allowShortCircuit: true, allowTernary: true }],
      'no-plusplus': ['error', { allowForLoopAfterthoughts: true }],
      'no-restricted-syntax': 'off',
    }
  ),
  settings: {
    'import/resolver': {
      'babel-module': {},
    },
    node: {
      moduleDirectory: ['renderer', 'node_modules'],
    },
    webpack: {
      config: path.resolve(__dirname, 'webpack', 'webpack.config.eslint.js'),
    },
  },
}
<commit_msg>style(lint): upgrade array-callback-return lint rule from warn to error<commit_after>var path = require('path')

const downgraded = [
  'class-methods-use-this',
  'consistent-return',
  'eqeqeq',
  'no-async-promise-executor',
  'no-await-in-loop',
  'no-self-compare',
  'no-shadow',
  'no-underscore-dangle',
  'no-use-before-define',
]

module.exports = {
  extends: '@ln-zap',
  rules: downgraded.reduce(
    (acc, next) => {
      acc[next] = 'warn'
      return acc
    },
    {
      'no-unused-expressions': ['error', { allowShortCircuit: true, allowTernary: true }],
      'no-plusplus': ['error', { allowForLoopAfterthoughts: true }],
      'no-restricted-syntax': 'off',
    }
  ),
  settings: {
    'import/resolver': {
      'babel-module': {},
    },
    node: {
      moduleDirectory: ['renderer', 'node_modules'],
    },
    webpack: {
      config: path.resolve(__dirname, 'webpack', 'webpack.config.eslint.js'),
    },
  },
}
<|endoftext|>