<commit_before>var Bounds = require('../util/Bounds'),
    canvas = require('../util/canvas'),
    svg = require('../util/svg'),
    font = require('./font'),
    paths = require('../path'),
    parse = paths.parse,
    boundPath = paths.bounds,
    areaPath = svg.path.area,
    linePath = svg.path.line,
    halfpi = Math.PI / 2,
    sqrt3 = Math.sqrt(3),
    tan30 = Math.tan(30 * Math.PI / 180),
    g2D = null;

function context() {
  return g2D || (g2D = canvas.instance(1,1).getContext('2d'));
}

function strokeBounds(o, bounds) {
  if (o.stroke && o.opacity !== 0 && o.stokeOpacity !== 0) {
    bounds.expand(o.strokeWidth != null ? o.strokeWidth : 1);
  }
  return bounds;
}

function pathBounds(o, path, bounds) {
  if (path == null) {
    bounds.set(0, 0, 0, 0);
  } else {
    boundPath(path, bounds);
    strokeBounds(o, bounds);
  }
  return bounds;
}

function path(o, bounds) {
  var p = o.path ? o.pathCache || (o.pathCache = parse(o.path)) : null;
  return pathBounds(o, p, bounds).translate(o.x || 0, o.y || 0);
}

function area(mark, bounds) {
  if (mark.items.length === 0) return bounds;
  var items = mark.items,
      item = items[0],
      p = item.pathCache || (item.pathCache = parse(areaPath(items)));
  return pathBounds(item, p, bounds);
}

function line(mark, bounds) {
  if (mark.items.length === 0) return bounds;
  var items = mark.items,
      item = items[0],
      p = item.pathCache || (item.pathCache = parse(linePath(items)));
  return pathBounds(item, p, bounds);
}

function rect(o, bounds) {
  var x, y;
  return strokeBounds(o, bounds.set(
    x = o.x || 0,
    y = o.y || 0,
    (x + o.width) || 0,
    (y + o.height) || 0
  ));
}

function image(o, bounds) {
  var x = o.x || 0,
      y = o.y || 0,
      w = o.width || 0,
      h = o.height || 0;
  x = x - (o.align === 'center' ? w/2 : (o.align === 'right' ? w : 0));
  y = y - (o.baseline === 'middle' ? h/2 : (o.baseline === 'bottom' ? h : 0));
  return bounds.set(x, y, x+w, y+h);
}

function rule(o, bounds) {
  var x1, y1;
  return strokeBounds(o, bounds.set(
    x1 = o.x || 0,
    y1 = o.y || 0,
    o.x2 != null ? o.x2 : x1,
    o.y2 != null ? o.y2 : y1
  ));
}

function arc(o, bounds) {
  var cx = o.x || 0,
      cy = o.y || 0,
      ir = o.innerRadius || 0,
      or = o.outerRadius || 0,
      sa = (o.startAngle || 0) - halfpi,
      ea = (o.endAngle || 0) - halfpi,
      xmin = Infinity, xmax = -Infinity,
      ymin = Infinity, ymax = -Infinity,
      a, i, n, x, y, ix, iy, ox, oy;

  var angles = [sa, ea],
      s = sa - (sa % halfpi);
  for (i=0; i<4 && s<ea; ++i, s+=halfpi) {
    angles.push(s);
  }

  for (i=0, n=angles.length; i<n; ++i) {
    a = angles[i];
    x = Math.cos(a); ix = ir*x; ox = or*x;
    y = Math.sin(a); iy = ir*y; oy = or*y;
    xmin = Math.min(xmin, ix, ox);
    xmax = Math.max(xmax, ix, ox);
    ymin = Math.min(ymin, iy, oy);
    ymax = Math.max(ymax, iy, oy);
  }

  return strokeBounds(o, bounds.set(
    cx + xmin,
    cy + ymin,
    cx + xmax,
    cy + ymax
  ));
}

function symbol(o, bounds) {
  var size = o.size != null ? o.size : 100,
      x = o.x || 0,
      y = o.y || 0,
      r, t, rx, ry;

  switch (o.shape) {
    case 'cross':
      r = Math.sqrt(size / 5) / 2;
      t = 3*r;
      bounds.set(x-t, y-r, x+t, y+r);
      break;

    case 'diamond':
      ry = Math.sqrt(size / (2 * tan30));
      rx = ry * tan30;
      bounds.set(x-rx, y-ry, x+rx, y+ry);
      break;

    case 'square':
      t = Math.sqrt(size);
      r = t / 2;
      bounds.set(x-r, y-r, x+r, y+r);
      break;

    case 'triangle-down':
      rx = Math.sqrt(size / sqrt3);
      ry = rx * sqrt3 / 2;
      bounds.set(x-rx, y-ry, x+rx, y+ry);
      break;

    case 'triangle-up':
      rx = Math.sqrt(size / sqrt3);
      ry = rx * sqrt3 / 2;
      bounds.set(x-rx, y-ry, x+rx, y+ry);
      break;

    default:
      r = Math.sqrt(size/Math.PI);
      bounds.set(x-r, y-r, x+r, y+r);
  }

  return strokeBounds(o, bounds);
}

function text(o, bounds, noRotate) {
  var x = (o.x || 0) + (o.dx || 0),
      y = (o.y || 0) + (o.dy || 0),
      h = font.size(o),
      a = o.align,
      r = o.radius || 0,
      g = context(), w, t;

  g.font = font.string(o);
  w = g.measureText(o.text || '').width;

  if (r) {
    t = (o.theta || 0) - Math.PI/2;
    x += r * Math.cos(t);
    y += r * Math.sin(t);
  }

  // horizontal
  if (a === 'center') {
    x = x - (w / 2);
  } else if (a === 'right') {
    x = x - w;
  } else {
    // left by default, do nothing
  }

  // vertical
  y += font.offset(o) - Math.round(0.8*h);

  bounds.set(x, y, x+w, y+h);
  if (o.angle && !noRotate) {
    bounds.rotate(o.angle*Math.PI/180, o.x||0, o.y||0);
  }
  return bounds.expand(noRotate ? 0 : 1);
}

function group(g, bounds, includeLegends) {
  var axes = g.axisItems || [],
      items = g.items || [],
      legends = g.legendItems || [],
      j, m;

  for (j=0, m=axes.length; j<m; ++j) {
    bounds.union(axes[j].bounds);
  }
  for (j=0, m=items.length; j<m; ++j) {
    bounds.union(items[j].bounds);
  }
  if (includeLegends) {
    for (j=0, m=legends.length; j<m; ++j) {
      bounds.union(legends[j].bounds);
    }
  }
  if (g.width != null && g.height != null) {
    bounds.add(g.width, g.height);
  }
  if (g.x != null && g.y != null) {
    bounds.add(0, 0);
  }
  return bounds.translate(g.x || 0, g.y || 0);
}

var methods = {
  group:  group,
  symbol: symbol,
  image:  image,
  rect:   rect,
  rule:   rule,
  arc:    arc,
  text:   text,
  path:   path,
  area:   area,
  line:   line
};
methods.area.nest = true;
methods.line.nest = true;

function itemBounds(item, func, opt) {
  var type = item.mark.marktype;
  func = func || methods[type];
  if (func.nest) item = item.mark;

  var curr = item.bounds,
      prev = item['bounds:prev'] || (item['bounds:prev'] = new Bounds());

  if (curr) {
    prev.clear().union(curr);
    curr.clear();
  } else {
    item.bounds = new Bounds();
  }
  func(item, item.bounds, opt);
  if (!curr) prev.clear().union(item.bounds);
  return item.bounds;
}

var DUMMY_ITEM = {mark: null};

function markBounds(mark, bounds, opt) {
  var type  = mark.marktype,
      func  = methods[type],
      items = mark.items,
      hasi  = items && items.length,
      i, n, o, b;

  if (func.nest) {
    o = hasi ? items[0]
      : (DUMMY_ITEM.mark = mark, DUMMY_ITEM); // no items, so fake it
    b = itemBounds(o, func, opt);
    bounds = bounds && bounds.union(b) || b;
    return bounds;
  }

  bounds = bounds || mark.bounds && mark.bounds.clear() || new Bounds();
  if (hasi) {
    for (i=0, n=items.length; i<n; ++i) {
      bounds.union(itemBounds(items[i], func, opt));
    }
  }
  return (mark.bounds = bounds);
}

module.exports = {
  mark:  markBounds,
  item:  itemBounds,
  text:  text,
  group: group
};
<commit_msg>Fix cross bounds calculation error.<commit_after>var Bounds = require('../util/Bounds'),
    canvas = require('../util/canvas'),
    svg = require('../util/svg'),
    font = require('./font'),
    paths = require('../path'),
    parse = paths.parse,
    boundPath = paths.bounds,
    areaPath = svg.path.area,
    linePath = svg.path.line,
    halfpi = Math.PI / 2,
    sqrt3 = Math.sqrt(3),
    tan30 = Math.tan(30 * Math.PI / 180),
    g2D = null;

function context() {
  return g2D || (g2D = canvas.instance(1,1).getContext('2d'));
}

function strokeBounds(o, bounds) {
  if (o.stroke && o.opacity !== 0 && o.stokeOpacity !== 0) {
    bounds.expand(o.strokeWidth != null ? o.strokeWidth : 1);
  }
  return bounds;
}

function pathBounds(o, path, bounds) {
  if (path == null) {
    bounds.set(0, 0, 0, 0);
  } else {
    boundPath(path, bounds);
    strokeBounds(o, bounds);
  }
  return bounds;
}

function path(o, bounds) {
  var p = o.path ? o.pathCache || (o.pathCache = parse(o.path)) : null;
  return pathBounds(o, p, bounds).translate(o.x || 0, o.y || 0);
}

function area(mark, bounds) {
  if (mark.items.length === 0) return bounds;
  var items = mark.items,
      item = items[0],
      p = item.pathCache || (item.pathCache = parse(areaPath(items)));
  return pathBounds(item, p, bounds);
}

function line(mark, bounds) {
  if (mark.items.length === 0) return bounds;
  var items = mark.items,
      item = items[0],
      p = item.pathCache || (item.pathCache = parse(linePath(items)));
  return pathBounds(item, p, bounds);
}

function rect(o, bounds) {
  var x, y;
  return strokeBounds(o, bounds.set(
    x = o.x || 0,
    y = o.y || 0,
    (x + o.width) || 0,
    (y + o.height) || 0
  ));
}

function image(o, bounds) {
  var x = o.x || 0,
      y = o.y || 0,
      w = o.width || 0,
      h = o.height || 0;
  x = x - (o.align === 'center' ? w/2 : (o.align === 'right' ? w : 0));
  y = y - (o.baseline === 'middle' ? h/2 : (o.baseline === 'bottom' ? h : 0));
  return bounds.set(x, y, x+w, y+h);
}

function rule(o, bounds) {
  var x1, y1;
  return strokeBounds(o, bounds.set(
    x1 = o.x || 0,
    y1 = o.y || 0,
    o.x2 != null ? o.x2 : x1,
    o.y2 != null ? o.y2 : y1
  ));
}

function arc(o, bounds) {
  var cx = o.x || 0,
      cy = o.y || 0,
      ir = o.innerRadius || 0,
      or = o.outerRadius || 0,
      sa = (o.startAngle || 0) - halfpi,
      ea = (o.endAngle || 0) - halfpi,
      xmin = Infinity, xmax = -Infinity,
      ymin = Infinity, ymax = -Infinity,
      a, i, n, x, y, ix, iy, ox, oy;

  var angles = [sa, ea],
      s = sa - (sa % halfpi);
  for (i=0; i<4 && s<ea; ++i, s+=halfpi) {
    angles.push(s);
  }

  for (i=0, n=angles.length; i<n; ++i) {
    a = angles[i];
    x = Math.cos(a); ix = ir*x; ox = or*x;
    y = Math.sin(a); iy = ir*y; oy = or*y;
    xmin = Math.min(xmin, ix, ox);
    xmax = Math.max(xmax, ix, ox);
    ymin = Math.min(ymin, iy, oy);
    ymax = Math.max(ymax, iy, oy);
  }

  return strokeBounds(o, bounds.set(
    cx + xmin,
    cy + ymin,
    cx + xmax,
    cy + ymax
  ));
}

function symbol(o, bounds) {
  var size = o.size != null ? o.size : 100,
      x = o.x || 0,
      y = o.y || 0,
      r, t, rx, ry;

  switch (o.shape) {
    case 'cross':
      t = 3 * Math.sqrt(size / 5) / 2;
      bounds.set(x-t, y-t, x+t, y+t);
      break;

    case 'diamond':
      ry = Math.sqrt(size / (2 * tan30));
      rx = ry * tan30;
      bounds.set(x-rx, y-ry, x+rx, y+ry);
      break;

    case 'square':
      t = Math.sqrt(size);
      r = t / 2;
      bounds.set(x-r, y-r, x+r, y+r);
      break;

    case 'triangle-down':
      rx = Math.sqrt(size / sqrt3);
      ry = rx * sqrt3 / 2;
      bounds.set(x-rx, y-ry, x+rx, y+ry);
      break;

    case 'triangle-up':
      rx = Math.sqrt(size / sqrt3);
      ry = rx * sqrt3 / 2;
      bounds.set(x-rx, y-ry, x+rx, y+ry);
      break;

    default:
      r = Math.sqrt(size/Math.PI);
      bounds.set(x-r, y-r, x+r, y+r);
  }

  return strokeBounds(o, bounds);
}

function text(o, bounds, noRotate) {
  var x = (o.x || 0) + (o.dx || 0),
      y = (o.y || 0) + (o.dy || 0),
      h = font.size(o),
      a = o.align,
      r = o.radius || 0,
      g = context(), w, t;

  g.font = font.string(o);
  w = g.measureText(o.text || '').width;

  if (r) {
    t = (o.theta || 0) - Math.PI/2;
    x += r * Math.cos(t);
    y += r * Math.sin(t);
  }

  // horizontal
  if (a === 'center') {
    x = x - (w / 2);
  } else if (a === 'right') {
    x = x - w;
  } else {
    // left by default, do nothing
  }

  // vertical
  y += font.offset(o) - Math.round(0.8*h);

  bounds.set(x, y, x+w, y+h);
  if (o.angle && !noRotate) {
    bounds.rotate(o.angle*Math.PI/180, o.x||0, o.y||0);
  }
  return bounds.expand(noRotate ? 0 : 1);
}

function group(g, bounds, includeLegends) {
  var axes = g.axisItems || [],
      items = g.items || [],
      legends = g.legendItems || [],
      j, m;

  for (j=0, m=axes.length; j<m; ++j) {
    bounds.union(axes[j].bounds);
  }
  for (j=0, m=items.length; j<m; ++j) {
    bounds.union(items[j].bounds);
  }
  if (includeLegends) {
    for (j=0, m=legends.length; j<m; ++j) {
      bounds.union(legends[j].bounds);
    }
  }
  if (g.width != null && g.height != null) {
    bounds.add(g.width, g.height);
  }
  if (g.x != null && g.y != null) {
    bounds.add(0, 0);
  }
  return bounds.translate(g.x || 0, g.y || 0);
}

var methods = {
  group:  group,
  symbol: symbol,
  image:  image,
  rect:   rect,
  rule:   rule,
  arc:    arc,
  text:   text,
  path:   path,
  area:   area,
  line:   line
};
methods.area.nest = true;
methods.line.nest = true;

function itemBounds(item, func, opt) {
  var type = item.mark.marktype;
  func = func || methods[type];
  if (func.nest) item = item.mark;

  var curr = item.bounds,
      prev = item['bounds:prev'] || (item['bounds:prev'] = new Bounds());

  if (curr) {
    prev.clear().union(curr);
    curr.clear();
  } else {
    item.bounds = new Bounds();
  }
  func(item, item.bounds, opt);
  if (!curr) prev.clear().union(item.bounds);
  return item.bounds;
}

var DUMMY_ITEM = {mark: null};

function markBounds(mark, bounds, opt) {
  var type  = mark.marktype,
      func  = methods[type],
      items = mark.items,
      hasi  = items && items.length,
      i, n, o, b;

  if (func.nest) {
    o = hasi ? items[0]
      : (DUMMY_ITEM.mark = mark, DUMMY_ITEM); // no items, so fake it
    b = itemBounds(o, func, opt);
    bounds = bounds && bounds.union(b) || b;
    return bounds;
  }

  bounds = bounds || mark.bounds && mark.bounds.clear() || new Bounds();
  if (hasi) {
    for (i=0, n=items.length; i<n; ++i) {
      bounds.union(itemBounds(items[i], func, opt));
    }
  }
  return (mark.bounds = bounds);
}

module.exports = {
  mark:  markBounds,
  item:  itemBounds,
  text:  text,
  group: group
};
<|endoftext|>


<commit_before>var http = require("http");
var fs = require("fs");
var url = require("url");
var qs = require("querystring");
//var io = require("socket.io");
var sqlite = require("sqlite3");
var db = new sqlite.Database("data.db");

function parseJSON(str) {
	try {
		return JSON.parse(str);
	}
	catch(ex) {}
}

var server = http.createServer(function(req, res) {
	var path = url.parse(req.url).pathname;
	var get = qs.parse(url.parse(req.url).querystring);
	var any = false;
	for(var i = 0; i < actions.length; i++) {
		if(path.toLowerCase() == ("/f/" + actions[i].path).toLowerCase()) {
			if(actions[i].method.toLowerCase() == "post") {
				(function() {
					var action = actions[i];
					var data = new Buffer(0);
					req.on("data", function(chunk) {
						data = Buffer.concat([data, chunk]);
					});
					req.on("end", function() {
						action.cb(req, res, get, String(data));
					});
				})();
			}
			else if(actions[i].method.toLowerCase() == "get") {
				actions[i].cb(req, res, get);
			}
			any = true;
			break;
		}
	}
	var found = true;
	var hidden = [".git", ".DS_Store", "LICENSE", "README.md"];
	for(var i = 0; i < hidden.length; i++) {
		if(~path.toLowerCase().indexOf(hidden[i].toLowerCase())) {
			found = false;
			break;
		}
	}
	if(!any && found) {
		path = path.replace(/\.+/, ".");
		if(path == "/") {
			path = "/index.html";
		}
		else if(!~path.indexOf(".")) {
			path += ".html";
		}
		fs.readFile("../Morganizer-website" + path, function(err, data) {
			if(err) {
				found = false;
			}
			else {
				res.end(data);
			}
		});
	}
	if(!found) {
		res.end("404");
	}
});

var port = process.argv[2] || 8080;
server.listen(port);

var actions = [];
function addAction(path, method, cb) {
	actions.push({
		path: path,
		method: method,
		cb: cb
	});
}

addAction("createUser", "POST", function(req, res, get, post) {
	var data = parseJSON(post);
	var user = data.user;
	var pass = data.pass;
	var email = data.email;
	var subdivision = data.subdivision;
	var phone = data.phone;
	var firstName = data.firstName;
	var lastName = data.lastName;
	var token = randomStr();

	db.serialize(function() {
		db.run("CREATE TABLE IF NOT EXISTS Users (user TEXT, pass TEXT, email TEXT, first TEXT, last TEXT, subdivision TEXT, phone TEXT)");
		db.run("INSERT INTO Users VALUES ('" + [user, pass, email, firstName, lastName, subdivision, phone].join("','") + "')");

		db.run("CREATE TABLE IF NOT EXISTS Sessions (user TEXT, token TEXT)");
		db.run("INSERT INTO Sessions VALUES ('" + [user, token].join("','") + "')");
	});
	res.end(JSON.stringify({"user":user,"token":token}));
});

addAction("loginUser", "POST", function(req, res, get, post) {
 	var data = parseJSON(post);
 	var pass = data.pass;
 	var user = data.user;
 	db.serialize(function() {
 		db.run("CREATE TABLE IF NOT EXISTS Sessions (user TEXT, token TEXT)");
 		db.all("SELECT * FROM Users WHERE user = '" + user + "' AND pass = '" + pass + "'", function(err, results) {
 			if (typeof(results) != "undefined" && results.length > 0){
 				var token = randomStr();
 				db.run("INSERT INTO Sessions VALUES ('" + [user, token].join("','") + "')");
				res.end(JSON.stringify({"user" : user, "token" : token}));
 			}
 			else {
 				res.end("invalid login");
 			}
 		});
 	});
});

addAction("addEvent", "POST", function(req, res, get, post) {
	var user = get.user;
	var data = parseJSON(post);
	validateSession(user, get.token, function(valid) {
		if(valid) {
			db.serialize(function() {
				db.run("CREATE TABLE IF NOT EXISTS " + user + "_Calendar (month INTEGER, day INTEGER, year INTEGER, time TEXT, event TEXT)");
				var insert = getInsertSql(user + "_Calendar", [data.month, data.day, data.year, data.time, data.event]);
				db.run(insert);
			});
			res.end("success");
		}
		else {
			res.end("invalid session");
		}
	});
});

addAction("getEvents", "GET", function(req, res, get) {
	var user = get.user;
	validateSession(user, get.token, function(valid) {
		if(valid) {
			db.serialize(function() {
				db.run("CREATE TABLE IF NOT EXISTS " + user + "_Calendar (month INTEGER, day INTEGER, year INTEGER, time TEXT, event TEXT)");
				db.all("SELECT * FROM " + user + "_Calendar", function(err, events) {
					res.end(JSON.stringify(events));
				});
			});
		}
		else {
			res.end("invalid session");
		}
	});
});
//Consider post data for token and search item (spaces)
addAction("searchUsers", "GET", function(req, res, get) {
	var searchItem = get.item;
	var results = [];
	db.serialize(function() {
 		db.each("SELECT first, last FROM Users", function(err, user) {
  			var name = user.first + " " + user.last;
  			if(~name.toLowerCase().indexOf(searchItem.toLowerCase())) {
  	 			results.push(name);
  			}
 		}, function() {
  				res.end(JSON.stringify(results));
		});
	});
});

addAction("searchEvents", "GET", function(req, res, get) {
	var searchItem = get.item;
	var user = get.user;
	var results = [];
	validateSession(user, get.token, function(valid) {
		if(valid) {
			db.serialize(function() {
				db.run("CREATE TABLE IF NOT EXISTS " + user + "_Calendar (month INTEGER, day INTEGER, year INTEGER, time TEXT, event TEXT)");
 				db.all("SELECT * FROM "+ user + "_Calendar WHERE event LIKE '%" + searchItem + "%'", function(err, events) {
  					if (typeof(events) != "undefined"&&events.length > 0){
  						results = events;
  					}
  					res.end(JSON.stringify(results));
				});
			});
		}
		else {
			res.end("invalid session");
		}
	});
});

function validateSession(user, token, cb){
	db.all("SELECT * FROM Sessions WHERE user = '" + user + "' AND token = '" + token + "'", function(err, results) {
		cb(typeof(results) != "undefined" && results.length > 0);
	});
}

function randomStr() {
	var str = "";
	for(var i = 0; i < 32; i++) {
		var rand = Math.floor(Math.random() * 62);
		str += String.fromCharCode(rand + ((rand < 26) ? 97 : ((rand < 52) ? 39 : -4)));
	}
	return str;
}

function getInsertSql(table, arr) {
	if(!isValidInput(table)) {
		return null;
	}
	var strs = []
	for(var i = 0; i < arr.length; i++) {
		if(typeof(arr[i]) == "string") {
			strs.push("\"" + arr[i] + "\"");
		}
		else {
			strs.push(String(arr[i]));
		}
		if(!isValid(arr[i])) {
			return null;
		}
	}
	return "INSERT INTO " + table + " VALUES (" + strs.join(",") + ")";
}

function isValidInput(str) {
	for(var i = 0; i < str.length; i++) {
		var char = str.charAt(i);
		switch(true) {
			 case "0" <= char && char <= "9":
			 case "a" <= char && char <= "z":
			 case "A" <= char && char <= "Z":
			 case char == "_":
			 	break;
			 default:
			 	return false;
		}
	}
	return true;
}

/*
io.listen(server).on("connection", function(socket) {

	socket.on("disconnect", function() {

	});

});
*/<commit_msg>Sends more info to client on login<commit_after>var http = require("http");
var fs = require("fs");
var url = require("url");
var qs = require("querystring");
//var io = require("socket.io");
var sqlite = require("sqlite3");
var db = new sqlite.Database("data.db");

function parseJSON(str) {
	try {
		return JSON.parse(str);
	}
	catch(ex) {}
}

var server = http.createServer(function(req, res) {
	var path = url.parse(req.url).pathname;
	var get = qs.parse(url.parse(req.url).querystring);
	var any = false;
	for(var i = 0; i < actions.length; i++) {
		if(path.toLowerCase() == ("/f/" + actions[i].path).toLowerCase()) {
			if(actions[i].method.toLowerCase() == "post") {
				(function() {
					var action = actions[i];
					var data = new Buffer(0);
					req.on("data", function(chunk) {
						data = Buffer.concat([data, chunk]);
					});
					req.on("end", function() {
						action.cb(req, res, get, String(data));
					});
				})();
			}
			else if(actions[i].method.toLowerCase() == "get") {
				actions[i].cb(req, res, get);
			}
			any = true;
			break;
		}
	}
	var found = true;
	var hidden = [".git", ".DS_Store", "LICENSE", "README.md"];
	for(var i = 0; i < hidden.length; i++) {
		if(~path.toLowerCase().indexOf(hidden[i].toLowerCase())) {
			found = false;
			break;
		}
	}
	if(!any && found) {
		path = path.replace(/\.+/, ".");
		if(path == "/") {
			path = "/index.html";
		}
		else if(!~path.indexOf(".")) {
			path += ".html";
		}
		fs.readFile("../Morganizer-website" + path, function(err, data) {
			if(err) {
				found = false;
			}
			else {
				res.end(data);
			}
		});
	}
	if(!found) {
		res.end("404");
	}
});

var port = process.argv[2] || 8080;
server.listen(port);

var actions = [];
function addAction(path, method, cb) {
	actions.push({
		path: path,
		method: method,
		cb: cb
	});
}

addAction("createUser", "POST", function(req, res, get, post) {
	var data = parseJSON(post);
	var user = data.user;
	var pass = data.pass;
	var email = data.email;
	var subdivision = data.subdivision;
	var phone = data.phone;
	var firstName = data.firstName;
	var lastName = data.lastName;
	var token = randomStr();
	console.log("Ran2");
	console.log(user);
	console.log(pass);
	db.serialize(function() {
		db.run("CREATE TABLE IF NOT EXISTS Users (user TEXT, pass TEXT, email TEXT, first TEXT, last TEXT, subdivision TEXT, phone TEXT)");
		db.run("INSERT INTO Users VALUES ('" + [user, pass, email, firstName, lastName, subdivision, phone].join("','") + "')");

		db.run("CREATE TABLE IF NOT EXISTS Sessions (user TEXT, token TEXT)");
		db.run("INSERT INTO Sessions VALUES ('" + [user, token].join("','") + "')");
	});
	res.end(JSON.stringify({"user":user,"token":token,"email":email,"subdivision":subdivision,"phone":phone,"first":firstName,"last":lastName}));
});

addAction("loginUser", "POST", function(req, res, get, post) {
 	var data = parseJSON(post);
 	var pass = data.pass;
 	var user = data.user;
 	console.log(user);
 	console.log(pass);
 	console.log("Ran3");
 	db.serialize(function() {
 		db.run("CREATE TABLE IF NOT EXISTS Sessions (user TEXT, token TEXT)");
 		db.all("SELECT * FROM Users WHERE user = '" + user + "' AND pass = '" + pass + "'", function(err, results) {
 			if (typeof(results) != "undefined" && results.length > 0){
 				var token = randomStr();
 				var email = results[0].email;
 				var subdivision = results[0].subdivision;
 				var phone = results[0].phone;
 				var firstName = results[0].first;
 				var lastName = results[0].last;
 				db.run("INSERT INTO Sessions VALUES ('" + [user, token].join("','") + "')");
				res.end(JSON.stringify({"user":user,"token":token,"email":email,"subdivision":subdivision,"phone":phone,"first":firstName,"last":lastName}));
 			}
 			else {
 				res.end("invalid login");
 			}
 		});
 	});
});

addAction("addEvent", "POST", function(req, res, get, post) {
	var user = get.user;
	var data = parseJSON(post);
	validateSession(user, get.token, function(valid) {
		if(valid) {
			db.serialize(function() {
				db.run("CREATE TABLE IF NOT EXISTS " + user + "_Calendar (month INTEGER, day INTEGER, year INTEGER, time TEXT, event TEXT)");
				var insert = getInsertSql(user + "_Calendar", [data.month, data.day, data.year, data.time, data.event]);
				db.run(insert);
			});
			res.end("success");
		}
		else {
			res.end("invalid session");
		}
	});
});

addAction("getEvents", "GET", function(req, res, get) {
	var user = get.user;
	validateSession(user, get.token, function(valid) {
		if(valid) {
			db.serialize(function() {
				db.run("CREATE TABLE IF NOT EXISTS " + user + "_Calendar (month INTEGER, day INTEGER, year INTEGER, time TEXT, event TEXT)");
				db.all("SELECT * FROM " + user + "_Calendar", function(err, events) {
					res.end(JSON.stringify(events));
				});
			});
		}
		else {
			res.end("invalid session");
		}
	});
});
//Consider post data for token and search item (spaces)
addAction("searchUsers", "GET", function(req, res, get) {
	var searchItem = get.item;
	var results = [];
	db.serialize(function() {
 		db.each("SELECT first, last FROM Users", function(err, user) {
  			var name = user.first + " " + user.last;
  			if(~name.toLowerCase().indexOf(searchItem.toLowerCase())) {
  	 			results.push(name);
  			}
 		}, function() {
  				res.end(JSON.stringify(results));
		});
	});
});

addAction("searchEvents", "GET", function(req, res, get) {
	var searchItem = get.item;
	var user = get.user;
	var results = [];
	validateSession(user, get.token, function(valid) {
		if(valid) {
			db.serialize(function() {
				db.run("CREATE TABLE IF NOT EXISTS " + user + "_Calendar (month INTEGER, day INTEGER, year INTEGER, time TEXT, event TEXT)");
 				db.all("SELECT * FROM "+ user + "_Calendar WHERE event LIKE '%" + searchItem + "%'", function(err, events) {
  					if (typeof(events) != "undefined"&&events.length > 0){
  						results = events;
  					}
  					res.end(JSON.stringify(results));
				});
			});
		}
		else {
			res.end("invalid session");
		}
	});
});

function validateSession(user, token, cb){
	db.all("SELECT * FROM Sessions WHERE user = '" + user + "' AND token = '" + token + "'", function(err, results) {
		cb(typeof(results) != "undefined" && results.length > 0);
	});
}

function randomStr() {
	var str = "";
	for(var i = 0; i < 32; i++) {
		var rand = Math.floor(Math.random() * 62);
		str += String.fromCharCode(rand + ((rand < 26) ? 97 : ((rand < 52) ? 39 : -4)));
	}
	return str;
}

function getInsertSql(table, arr) {
	if(!isValidInput(table)) {
		return null;
	}
	var strs = []
	for(var i = 0; i < arr.length; i++) {
		if(typeof(arr[i]) == "string") {
			strs.push("\"" + arr[i] + "\"");
		}
		else {
			strs.push(String(arr[i]));
		}
		if(!isValid(arr[i])) {
			return null;
		}
	}
	return "INSERT INTO " + table + " VALUES (" + strs.join(",") + ")";
}

function isValidInput(str) {
	for(var i = 0; i < str.length; i++) {
		var char = str.charAt(i);
		switch(true) {
			 case "0" <= char && char <= "9":
			 case "a" <= char && char <= "z":
			 case "A" <= char && char <= "Z":
			 case char == "_":
			 	break;
			 default:
			 	return false;
		}
	}
	return true;
}

/*
io.listen(server).on("connection", function(socket) {

	socket.on("disconnect", function() {

	});

});
*/<|endoftext|>


<commit_before>var mqWebApp = angular.module('mqWebApp');

mqWebApp.directive('mqEventQtip', function($http, $compile, $templateCache) {
	return {
		restrict: 'A',
		scope : {
			mqWebURL : '@mqEventQtip'
		},
		link : function(scope, element, attrs) {
			$(element).qtip({
				position: {
					my: 'bottom left',
					at: 'top right'
				},
				content: {
					text: function(event, api) {
						$http.get(scope.mqWebURL, { cache: false })
						.success(function(content, status) {
							// Set the tooltip content upon successful retrieval
							var contentDOM = $(content);
							// When a title id is found, use it as qtip title and make
							// the title invisible.
							var titleElement = contentDOM.find("#eventTitle");
							if ( titleElement )
							{
								titleElement.hide();
								api.set('content.title', titleElement.text());
							}
							api.set('content.text', contentDOM.html());
						}).error(function(xhr, status, error) {
							// Upon failure... set the tooltip content to the status and error value
							api.set('content.text', status + ': ' + error);
						});

						return 'Loading...'; // Set some initial text
					}
				}
			});
		}
	}
});

mqWebApp.controller('QmgrController', ['$scope', '$http', 'MQWEB_CONFIG', function($scope, $http, config) {
	$scope.loading = false;
	$scope.mqweb = null;
	$scope.qmgr = null;
	$scope.error = null;

	$scope.load = function() {
		$scope.loading = true;
		$http.get('/qmgr/view.json/' + config.qmgrName, { cache: false })
			.success(function(data, status) {
				$scope.loading = false;
				$scope.mqweb = data.mqweb;
				$scope.qmgr = data.qmgr;
				$scope.error = data.error;
			}).error(function(data, status) {
				$scope.loading = false;
		});
	};

	$scope.load();
}]);

mqWebApp.controller('LocalQueueController', ['$scope', '$http', 'MQWEB_CONFIG', function($scope, $http, config) {
	$scope.loading = false;
	$scope.mqweb = null;
	$scope.queues = null;
	$scope.error = null;
	$scope.http_rc = 0;

	$scope.load = function() {
		$scope.loading = true;
		$http.get('/queue/inquire/' + config.qmgrName, {
			cache: false,
			params : {
				queueDepth : 1,
				queueExcludeSystem: 'true',
				queueUsage : "normal",
				queueExcludeTemp : 'true'
			}
		}).success(function(data, status) {
			$scope.loading = false;
			$scope.mqweb = data.mqweb;
			$scope.queues = data.queues;
			$scope.error = data.error;
		}).error(function(data, status) {
			$scope.loading = false;
			$scope.http_rc = status;
		});
	};

	$scope.load();
}]);

mqWebApp.controller('XmitQueueController', ['$scope', '$http', 'MQWEB_CONFIG', function($scope, $http, config) {
	$scope.loading = false;
	$scope.mqweb = null;
	$scope.queues = null;
	$scope.error = null;
	$scope.http_rc = 0;

	$scope.load = function() {
		$scope.loading = true;
		$http.get('/queue/inquire/' + config.qmgrName, {
			cache : false,
			params : {
				queueDepth : 1,
				queueExcludeSystem: 'false',
				queueUsage : "xmitq"
			}
		}).success(function(data, status) {
			$scope.loading = false;
			$scope.mqweb = data.mqweb;
			$scope.queues = data.queues;
			$scope.error = data.error;
		}).error(function(data, status) {
			$scope.loading = false;
			$scope.http_rc = status;
		});
	};

	$scope.load();
}]);

mqWebApp.controller('ChannelStatusController', ['$scope', '$http', 'MQWEB_CONFIG', function($scope, $http, config) {
	$scope.loading = false;
	$scope.mqweb = null;
	$scope.channels = null;
	$scope.error = null;
	$scope.http_rc = 0;

	$scope.load = function() {
		$scope.loading = true;
		$http.get('/chs/list.json/' + config.qmgrName, { cache: false })
			.success(function(data, status) {
				$scope.loading = false;
				$scope.mqweb = data.mqweb;
				$scope.channels = data.channels;
				$scope.error = data.error;
				})
			.error(function(data, status) {
				$scope.loading = false;
				$scope.http_rc = status;
			});
		};
	$scope.load();
}]);

mqWebApp.controller('EventMessageController', ['$scope', '$http', 'MQWEB_CONFIG', function($scope, $http, config) {

	$scope.loading = false;
	$scope.events = null;
	$scope.error = null;
	$scope.curdepth = 0;
	$scope.http_rc = 0;

	$scope.load = function() {
		$scope.loading = true;
		$http.get("/message/event.json/" + config.qmgrName + "/SYSTEM.ADMIN.QMGR.EVENT", {
			cache: false,
			params : {
				limit : 3
				}
			}).success(function(data, status) {
				$scope.loading = false;
				$scope.error = data.error;
				$scope.events = data.events;
				$scope.curdepth = data.queue.curdepth;
			}).error(function(data, status) {
				$scope.loading = false;
				$scope.http_rc = status;
			});
		};
	$scope.load();
}]);

$(document).ready(function()
{
	$("[data-qtip]").qtip({
		content : {
			text: function(event, api) {
				return $(this).attr('data-qtip');
			},
			title: function(event, api) {
				return $(this).text();
			}
		},
		position: {
			my: 'bottom center',
			at: 'top center'
		}
	});
	$(".imgtip").qtip({
		content : {
			attr: 'alt'
		}
	});
});<commit_msg>chs/list renamed into chstatus/inquire<commit_after>var mqWebApp = angular.module('mqWebApp');

mqWebApp.directive('mqEventQtip', function($http, $compile, $templateCache) {
	return {
		restrict: 'A',
		scope : {
			mqWebURL : '@mqEventQtip'
		},
		link : function(scope, element, attrs) {
			$(element).qtip({
				position: {
					my: 'bottom left',
					at: 'top right'
				},
				content: {
					text: function(event, api) {
						$http.get(scope.mqWebURL, { cache: false })
						.success(function(content, status) {
							// Set the tooltip content upon successful retrieval
							var contentDOM = $(content);
							// When a title id is found, use it as qtip title and make
							// the title invisible.
							var titleElement = contentDOM.find("#eventTitle");
							if ( titleElement )
							{
								titleElement.hide();
								api.set('content.title', titleElement.text());
							}
							api.set('content.text', contentDOM.html());
						}).error(function(xhr, status, error) {
							// Upon failure... set the tooltip content to the status and error value
							api.set('content.text', status + ': ' + error);
						});

						return 'Loading...'; // Set some initial text
					}
				}
			});
		}
	}
});

mqWebApp.controller('QmgrController', ['$scope', '$http', 'MQWEB_CONFIG', function($scope, $http, config) {
	$scope.loading = false;
	$scope.mqweb = null;
	$scope.qmgr = null;
	$scope.error = null;

	$scope.load = function() {
		$scope.loading = true;
		$http.get('/qmgr/view.json/' + config.qmgrName, { cache: false })
			.success(function(data, status) {
				$scope.loading = false;
				$scope.mqweb = data.mqweb;
				$scope.qmgr = data.qmgr;
				$scope.error = data.error;
			}).error(function(data, status) {
				$scope.loading = false;
		});
	};

	$scope.load();
}]);

mqWebApp.controller('LocalQueueController', ['$scope', '$http', 'MQWEB_CONFIG', function($scope, $http, config) {
	$scope.loading = false;
	$scope.mqweb = null;
	$scope.queues = null;
	$scope.error = null;
	$scope.http_rc = 0;

	$scope.load = function() {
		$scope.loading = true;
		$http.get('/queue/inquire/' + config.qmgrName, {
			cache: false,
			params : {
				queueDepth : 1,
				queueExcludeSystem: 'true',
				queueUsage : "normal",
				queueExcludeTemp : 'true'
			}
		}).success(function(data, status) {
			$scope.loading = false;
			$scope.mqweb = data.mqweb;
			$scope.queues = data.queues;
			$scope.error = data.error;
		}).error(function(data, status) {
			$scope.loading = false;
			$scope.http_rc = status;
		});
	};

	$scope.load();
}]);

mqWebApp.controller('XmitQueueController', ['$scope', '$http', 'MQWEB_CONFIG', function($scope, $http, config) {
	$scope.loading = false;
	$scope.mqweb = null;
	$scope.queues = null;
	$scope.error = null;
	$scope.http_rc = 0;

	$scope.load = function() {
		$scope.loading = true;
		$http.get('/queue/inquire/' + config.qmgrName, {
			cache : false,
			params : {
				queueDepth : 1,
				queueExcludeSystem: 'false',
				queueUsage : "xmitq"
			}
		}).success(function(data, status) {
			$scope.loading = false;
			$scope.mqweb = data.mqweb;
			$scope.queues = data.queues;
			$scope.error = data.error;
		}).error(function(data, status) {
			$scope.loading = false;
			$scope.http_rc = status;
		});
	};

	$scope.load();
}]);

mqWebApp.controller('ChannelStatusController', ['$scope', '$http', 'MQWEB_CONFIG', function($scope, $http, config) {
	$scope.loading = false;
	$scope.mqweb = null;
	$scope.channels = null;
	$scope.error = null;
	$scope.http_rc = 0;

	$scope.load = function() {
		$scope.loading = true;
		$http.get('/chstatus/inquire.json/' + config.qmgrName, { cache: false })
			.success(function(data, status) {
				$scope.loading = false;
				$scope.mqweb = data.mqweb;
				$scope.channels = data.statuses;
				$scope.error = data.error;
				})
			.error(function(data, status) {
				$scope.loading = false;
				$scope.http_rc = status;
			});
		};
	$scope.load();
}]);

mqWebApp.controller('EventMessageController', ['$scope', '$http', 'MQWEB_CONFIG', function($scope, $http, config) {

	$scope.loading = false;
	$scope.events = null;
	$scope.error = null;
	$scope.curdepth = 0;
	$scope.http_rc = 0;

	$scope.load = function() {
		$scope.loading = true;
		$http.get("/message/event.json/" + config.qmgrName + "/SYSTEM.ADMIN.QMGR.EVENT", {
			cache: false,
			params : {
				limit : 3
				}
			}).success(function(data, status) {
				$scope.loading = false;
				$scope.error = data.error;
				$scope.events = data.events;
				$scope.curdepth = data.queue.curdepth;
			}).error(function(data, status) {
				$scope.loading = false;
				$scope.http_rc = status;
			});
		};
	$scope.load();
}]);

$(document).ready(function()
{
	$("[data-qtip]").qtip({
		content : {
			text: function(event, api) {
				return $(this).attr('data-qtip');
			},
			title: function(event, api) {
				return $(this).text();
			}
		},
		position: {
			my: 'bottom center',
			at: 'top center'
		}
	});
	$(".imgtip").qtip({
		content : {
			attr: 'alt'
		}
	});
});<|endoftext|>


<commit_before>window.semaUtils = (function () {

    var utils = {};

    /**
     *
     */
    utils.log = (traceMessage, level) => {
        if(window.semaDebugMode) {
            switch(level) {
                case 'error':
                    console.error('[SIP] ' + traceMessage);
                    break;
                case 'info':
                    console.info('[SIP] ' + traceMessage);
                    break;
                case 'warn':
                    console.warn('[SIP] ' + traceMessage);
                    break;
                default:
                    console.log('[SIP] ' + traceMessage);
            }
        }
    };

    /**
     *
     */
    utils.getSettings = (callback) => {
        $.ajax({
            url: '/settings',
            success: function(data) {
                callback(data);
            },
            cache: false
        });
    };

    /**
     *
     */
    /*utils.requestSensorState = (sensor, callback) => {
        $.ajax({
            url: '/sensor/' + sensor,
            success: function(data) {
                callback(data);
            },
            cache: false
        });
    };*/
    utils.requestSensorState = (sensor, callback) => {
        var promise = new Promise((resolve, reject) => {
            $.ajax({
                url: '/sensor/' + sensor,
                success: (data) => {
                    resolve(data);
                },
                error: (err) => {
                    reject(err);
                },
                cache: false
            });
        });
        return promise;
    };

    /**
     *
     */
    utils.requestSensorData = (endpoint, chart, callback) => {
        utils.log('Calling to ' + endpoint);

        // "Sanitize" the input
        if(endpoint.charAt(0) === '/') {
            endpoint = endpoint.slice(1);
        }

        $.ajax({
            url: endpoint,
            success: function(data) {
                var series = chart.series[0],
                    shift = series.data.length > 20;

                // add the points
                for(let i=0; i<data.lastValues.length; i++) {
                    chart.series[0].addPoint(data.lastValues[i], true, shift);
                }

                callback();
            },
            cache: false
        });
    };

    /**
     *
     */
    utils.sendX10Command = (device, action, callback) => {
        $.ajax({
            type: 'post',
            url: 'http://192.168.12.70:3000/x10',
            data: {
                device: device,
                action: action
            },
            success: function() {
                callback();
            },
            cache: false
        });
    };

    /**
     *
     */
    utils.getSongList = (callback) => {
        $.ajax({
            url: 'http://192.168.12.70:3000/library',
            success: function(data) {
                callback(data);
            },
            cache: false
        });
    };

    /**
     *
     */
    utils.playSong = (song) => {
        $.ajax({
            type: 'post',
            data: { song: song },
            url: 'http://192.168.12.70:3000/library/play',
            success: function() { },
            error: function() {
                // Check if there was an error (erro handler)
            },
            cache: false
        });
    };

    /**
     *
     */
    utils.stopPlaying = () => {
        $.ajax({
            url: 'http://192.168.12.70:3000/library/stop',
            success: function(data) {
            },
            cache: false
        });
    };

    /**
     *
     */
    utils.forwardPlaying = () => {
        $.ajax({
            url: 'http://192.168.12.70:3000/library/forward',
            success: function(data) {
            },
            cache: false
        });
    };

    /**
     *
     */
    utils.connectToBulb = () => {
        if(navigator.bluetooth) {
            navigator.bluetooth.requestDevice({
                filters: [{ services: [0xffe5] }]
            })
            .then(function(device) {
                // Step 2: Connect to it
                console.log('setp2: ', device);
                return device.gatt.connect();
            })
            .then(function(server) {
                // Step 3: Get the Service
                console.log('setp3: ', server);
                return server.getPrimaryService(0xffe5);
            })
            .then(function(service) {
                // Step 4: get the Characteristic
                console.log('setp4: ', service);
                return service.getCharacteristic(0xffe9);
            })
            .then(function(characteristic) {
                // Step 5: Write to the characteristic
                console.log('setp5: ', characteristic);
                var data = new Uint8Array([0xbb, 0x25, 0x05, 0x44]);
                return characteristic.writeValue(data);
            })
            .catch(function(error) {
                // And of course: error handling!
                console.error('Connection failed! ', error);
            });
        } else {
            alert('Error, bluetooth not supported or disconnected');
        }
    };

    /**
     *
     */
    utils.setBulbColor = (r, g, b) => {

    };

    return utils;
}($));<commit_msg>Refactored media server IPs and implemented setBulbColor function<commit_after>window.semaUtils = (function () {

    var utils = {};

    /**
     *
     */
    utils.serverMediaIP = '192.168.1.3:3000';

    /**
     *
     */
    utils.log = (traceMessage, level) => {
        if(window.semaDebugMode) {
            switch(level) {
                case 'error':
                    console.error('[SIP] ' + traceMessage);
                    break;
                case 'info':
                    console.info('[SIP] ' + traceMessage);
                    break;
                case 'warn':
                    console.warn('[SIP] ' + traceMessage);
                    break;
                default:
                    console.log('[SIP] ' + traceMessage);
            }
        }
    };

    /**
     *
     */
    utils.getSettings = (callback) => {
        $.ajax({
            url: '/settings',
            success: function(data) {
                callback(data);
            },
            cache: false
        });
    };

    /**
     * (Implementation through a promise instead of callbacks)
     */
    utils.requestSensorState = (sensor) => {
        var promise = new Promise((resolve, reject) => {
            $.ajax({
                url: '/sensor/' + sensor,
                success: (data) => {
                    resolve(data);
                },
                error: (err) => {
                    reject(err);
                },
                cache: false
            });
        });
        return promise;
    };

    /**
     *
     */
    utils.requestSensorData = (endpoint, chart, callback) => {
        utils.log('Calling to ' + endpoint);

        // "Sanitize" the input
        if(endpoint.charAt(0) === '/') {
            endpoint = endpoint.slice(1);
        }

        $.ajax({
            url: endpoint,
            success: function(data) {
                var series = chart.series[0],
                    shift = series.data.length > 20;

                // add the points
                for(let i=0; i<data.lastValues.length; i++) {
                    chart.series[0].addPoint(data.lastValues[i], true, shift);
                }

                callback();
            },
            cache: false
        });
    };

    /**
     *
     */
    utils.sendX10Command = (device, action, callback) => {
        $.ajax({
            type: 'post',
            url: `${utils.serverMediaIP}/x10`,
            data: {
                device: device,
                action: action
            },
            success: function() {
                callback();
            },
            cache: false
        });
    };

    /**
     *
     */
    utils.getSongList = (callback) => {
        $.ajax({
            url: `${utils.serverMediaIP}/library`,
            success: function(data) {
                callback(data);
            },
            cache: false
        });
    };

    /**
     *
     */
    utils.playSong = (song) => {
        $.ajax({
            type: 'post',
            data: { song: song },
            url: `${utils.serverMediaIP}/library/play`,
            success: function() { },
            error: function() {
                // Check if there was an error (erro handler)
            },
            cache: false
        });
    };

    /**
     *
     */
    utils.stopPlaying = () => {
        $.ajax({
            url: `${utils.serverMediaIP}/library/stop`,
            success: function(data) {
            },
            cache: false
        });
    };

    /**
     *
     */
    utils.forwardPlaying = () => {
        $.ajax({
            url: `${utils.serverMediaIP}/library/forward`,
            success: function(data) {
            },
            cache: false
        });
    };

    /**
     *
     */
    utils.connectToBulb = () => {
        if(navigator.bluetooth) {
            navigator.bluetooth.requestDevice({
                filters: [{ services: [0xffe5] }]
            })
            .then(function(device) {
                // Step 2: Connect to it
                console.log('setp2: ', device);
                return device.gatt.connect();
            })
            .then(function(server) {
                // Step 3: Get the Service
                console.log('setp3: ', server);
                return server.getPrimaryService(0xffe5);
            })
            .then(function(service) {
                // Step 4: get the Characteristic
                console.log('setp4: ', service);
                return service.getCharacteristic(0xffe9);
            })
            .then(function(characteristic) {
                // Step 5: Write to the characteristic
                console.log('setp5: ', characteristic);
                utils.ledCharacteristic = characteristic;
                var data = new Uint8Array([0xbb, 0x25, 0x05, 0x44]);
                return characteristic.writeValue(data);
            })
            .catch(function(error) {
                // And of course: error handling!
                console.error('Connection failed! ', error);
            });
        } else {
            alert('Error, bluetooth not supported or disconnected');
        }
    };

    /**
     *
     */
    utils.setBulbColor = (r, g, b) => {
        if(utils.ledCharacteristic) {
            let data = new Uint8Array([0x56, r, g, b, 0x00, 0xf0, 0xaa]);
            return utils.ledCharacteristic.writeValue(data)
                .catch(err => console.log('Error when writing value! ', err));
        }
    };

    return utils;
}($));<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Blackmoon Info Tech Services
 *
 * 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.
 */
var BaseClass = StdClass.extend({
	onCreate: function() {
		//defined just to avoid a crash if you call _super() during onCreate
	}
});

/**
 * Since JS cannot handle default values in the function definition,
 * this function will return the arg or the default if arg is undefined.
 * @param aArg - the argument
 * @param aDef - the default
 * @returns Arg unless it is undefined, else Default.
 */
BaseClass.prototype.argOrDefault = function(aArg, aDef) {
	return ((typeof aArg) !== 'undefined') ? aArg : aDef;
};

/**
 * Helper function to bind methods as callback functions.
 * @param aMethodName - name of method to call
 * @returns {Function} Returns the anonymous function used as a callback.
 */
BaseClass.prototype.asCB = function(aMethodName) {
	var thisone = this;
	return function() {
		return thisone[aMethodName].apply(thisone,arguments);
	};
};

/**
 * Pseudo-UUID, random + time "version 4" generated UUID.
 * @param {string} aGlue - (optional) defaults to "-".
 * @returns {String} v4 UUID.
 * @see http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
 */
BaseClass.prototype.createUUID = function(aGlue) {
	var g = this.argOrDefault(aGlue,'-');
	var d = new Date().getTime();
	var s = 'xxxxxxxx'+g+'xxxx'+g+'4xxx'+g+'yxxx'+g+'xxxxxxxxxxxx';
	var uuid = s.replace(/[xy]/g, function(c) {
		var r = (d + Math.random()*16)%16 | 0;
		d = Math.floor(d/16);
		return (c==='x' ? r : (r&0x7|0x8)).toString(16);
	});
	return uuid;
};
<commit_msg>BaseClass.js improved asCB() to accept function and string; also added asCB() to Function.prototype.<commit_after>/*
 * Copyright (C) 2014 Blackmoon Info Tech Services
 *
 * 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.
 */
var BaseClass = StdClass.extend({
	onCreate: function() {
		//defined just to avoid a crash if you call _super() during onCreate
	}
});

/**
 * Since JS cannot handle default values in the function definition,
 * this function will return the arg or the default if arg is undefined.
 * @param aArg - the argument
 * @param aDef - the default
 * @returns Arg unless it is undefined, else Default.
 */
BaseClass.prototype.argOrDefault = function(aArg, aDef) {
	return ((typeof aArg) !== 'undefined') ? aArg : aDef;
};

/**
 * Helper function to bind methods as callback functions.
 * @param aMethod - name of method to call, or function itself
 * @returns {Function} Returns the anonymous function used as a callback.
 */
BaseClass.prototype.asCB = function(aMethod) {
	var thisone = this;
	var theFn = ((typeof aMethod) === 'function') ? aMethod : this[aMethod];
	return function() {
		return theFn.apply(thisone,arguments);
	};
};
BaseClass.prototype.bind = BaseClass.prototype.asCB; //alias

/**
 * Helper function to bind methods as callback functions.
 * @param aContext - the "this" var the method needs.
 * @returns {Function} Returns the anonymous function used as a callback.
 */
Function.prototype.asCB = function(aContext) {
	var theFn = this;
	return function() {
		return theFn.apply(aContext,arguments);
	};
};

/**
 * Pseudo-UUID, random + time "version 4" generated UUID.
 * @param {string} aGlue - (optional) defaults to "-".
 * @returns {String} v4 UUID.
 * @see http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
 */
BaseClass.prototype.createUUID = function(aGlue) {
	var g = this.argOrDefault(aGlue,'-');
	var d = new Date().getTime();
	var s = 'xxxxxxxx'+g+'xxxx'+g+'4xxx'+g+'yxxx'+g+'xxxxxxxxxxxx';
	var uuid = s.replace(/[xy]/g, function(c) {
		var r = (d + Math.random()*16)%16 | 0;
		d = Math.floor(d/16);
		return (c==='x' ? r : (r&0x7|0x8)).toString(16);
	});
	return uuid;
};
<|endoftext|>


<commit_before>var locastyle = locastyle || {};

locastyle.popover = (function() {
  'use strict';

  var config = {
    module       : '[data-ls-module="popover"]',
    idPopover    : '#ls-popover-',
    popoverClass : '.ls-popover',
    trigger      : 'click',
    events: {
      opened: 'popover:opened',
      closed: 'popover:closed',
      destroyed: 'popover:destroyed'
    }
  }

  function init() {
    buildPopover();
    bindPopover();
  }

  // When click or hover elements, show the popovers
  function bindPopover() {
    $(config.module).each(function(index, popoverTrigger) {
      var trigger = $(popoverTrigger).attr('data-trigger') === 'hover' ? 'mouseover' : config.trigger;

      $(popoverTrigger).on(trigger, function() {
        var popoverTarget = $(popoverTrigger).data('target');

        if ($(popoverTarget).hasClass('ls-active')) {
          hide(popoverTarget);
        } else {
          setTimeout(function(){
            show(popoverTarget)
          },100);
          clickAnywhereClose(popoverTarget);
        }
        if (trigger === 'mouseover') {
          $(popoverTrigger).on('mouseout', function() {
            hide(popoverTarget);
          });
        }

      });
    });

  }

  // If popover was not created, we build the HTML using a template
  function buildPopover() {
    $(config.module).each(function(index, popoverTrigger) {

      // Add attr data-target to popover triggers
      $(popoverTrigger).attr('data-target', config.idPopover+index);

      if (!$(config.idPopover+index).length) {
        var data = {
          index        : index,
          title        : $(popoverTrigger).data('title'),
          content      : $(popoverTrigger).data('content'),
          placement    : $(popoverTrigger).data('placement'),
          customClasses: $(popoverTrigger).data('custom-class')
        }

        $('body').append(locastyle.templates.popover(data));

        // Define position of popovers based on his triggers
        setPosition(popoverTrigger);
      }
    });
  }

  // Define position of popovers
  function setPosition(popoverTrigger) {
    var data = {
        target    : $(popoverTrigger).data('target'),
        top       : $(popoverTrigger).offset().top,
        left      : $(popoverTrigger).offset().left,
        width     : $(popoverTrigger).outerWidth(),
        height    : $(popoverTrigger).outerHeight(),
        placement : $(popoverTrigger).data('placement')
    }

    // Define the position of popovers and your elements triggers
    switch (data.placement) {
      case 'top':
        $(data.target).css({
          top : data.top  -=  12,
          left: data.left += (data.width/2 + 4)
        });
        break;
      case 'right':
        $(data.target).css({
          top : data.top  += (data.height/2 -2),
          left: data.left += (data.width + 12)
        });
        break;
      case 'bottom':
        $(data.target).css({
          top : data.top  += (data.height + 12),
          left: data.left += (data.width/2 + 4)
        });
        break;
      case 'left':
        $(data.target).css({
          top : data.top  += (data.height/2 -2 ),
          left: data.left -= 12
        });
    }

  }

  function clickAnywhereClose(popoverTarget) {
    $(document).on('click.ls', function(evt){
      if ($(popoverTarget).is(':visible') && !$(evt.target).parents(popoverTarget).length) {
        hide('.ls-popover.ls-active');
      }
    });
  }

  // Show called popover
  function show(target) {
    $(target).addClass('ls-active');
    $(target).trigger(config.events.opened);
  }

  // Hide all or visible popovers
  function hide(target) {
    $(target || config.popoverClass+':visible').removeClass('ls-active');
    $(target).trigger(config.events.closed).unbind(config.events.opened);
  }

  // Destroy all created popovers
  function destroy() {
    $(config.popoverClass).remove();

    // Unbind all events.
    $.each(config.events, function(index, event) {
      $(document).unbind(event);
    });

    $(document).trigger(config.events.destroyed);
  }

  return {
    init   : init,
    show   : show,
    hide   : hide,
    destroy: destroy
  };

}());
<commit_msg>When click anywhere, we close all popovers opened.<commit_after>var locastyle = locastyle || {};

locastyle.popover = (function() {
  'use strict';

  var config = {
    module       : '[data-ls-module="popover"]',
    idPopover    : '#ls-popover-',
    popoverClass : '.ls-popover',
    trigger      : 'click',
    events: {
      clickAnywhere: 'click.clickanywhere',
      opened: 'popover:opened',
      closed: 'popover:closed',
      destroyed: 'popover:destroyed'
    }
  }

  function init() {
    clickAnywhereClose();
    buildPopover();
    bindPopover();
  }

  // When click or hover elements, show the popovers
  function bindPopover() {
    $(config.module).each(function(index, popoverTrigger) {
      var trigger = $(popoverTrigger).attr('data-trigger') === 'hover' ? 'mouseover' : config.trigger;

      $(popoverTrigger).on(trigger, function(event) {
        event.preventDefault();
        event.stopPropagation();

        var popoverTarget = $(popoverTrigger).data('target');

        if ($(popoverTarget).hasClass('ls-active')) {
          hide(popoverTarget);
        } else {
          show(popoverTarget);
          clickAnywhereClose(popoverTarget)
        }

        if (trigger === 'mouseover') {
          $(popoverTrigger).on('mouseout', function() {
            hide(popoverTarget);
          });
        }

      });
    });

  }

  function clickAnywhereClose(target) {
    $(document).on(config.events.clickAnywhere, function(event){
      if(!$(event.target).parents('.ls-popover').length){
        hide(target);
      }
    });
  }

  // If popover was not created, we build the HTML using a template
  function buildPopover() {
    $(config.module).each(function(index, popoverTrigger) {

      // Add attr data-target to popover triggers
      $(popoverTrigger).attr('data-target', config.idPopover+index);

      if (!$(config.idPopover+index).length) {
        var data = {
          index        : index,
          title        : $(popoverTrigger).data('title'),
          content      : $(popoverTrigger).data('content'),
          placement    : $(popoverTrigger).data('placement'),
          customClasses: $(popoverTrigger).data('custom-class')
        }

        $('body').append(locastyle.templates.popover(data));

        // Define position of popovers based on his triggers
        setPosition(popoverTrigger);
      }
    });
  }

  // Define position of popovers
  function setPosition(popoverTrigger) {
    var data = {
        target    : $(popoverTrigger).data('target'),
        top       : $(popoverTrigger).offset().top,
        left      : $(popoverTrigger).offset().left,
        width     : $(popoverTrigger).outerWidth(),
        height    : $(popoverTrigger).outerHeight(),
        placement : $(popoverTrigger).data('placement')
    }

    // Define the position of popovers and your elements triggers
    switch (data.placement) {
      case 'top':
        $(data.target).css({
          top : data.top  -=  12,
          left: data.left += (data.width/2 + 4)
        });
        break;
      case 'right':
        $(data.target).css({
          top : data.top  += (data.height/2 -2),
          left: data.left += (data.width + 12)
        });
        break;
      case 'bottom':
        $(data.target).css({
          top : data.top  += (data.height + 12),
          left: data.left += (data.width/2 + 4)
        });
        break;
      case 'left':
        $(data.target).css({
          top : data.top  += (data.height/2 -2 ),
          left: data.left -= 12
        });
    }

  }

  // Show called popover
  function show(target) {
    $(target).on(config.events.opened, function(){
      console.log('opened', target)
    });
    $(target).addClass('ls-active');
    $(target).off(config.events.closed).trigger(config.events.opened);
  }

  // Hide all or visible popovers
  function hide(target) {
    $(target).on(config.events.closed, function(){
      console.log('closed', target)
    });
    $(target || '.ls-popover.ls-active').removeClass('ls-active');
    $(target).trigger(config.events.closed).off(config.events.opened)
    $(document).off(config.events.clickAnywhere)
  }

  // Destroy all created popovers
  function destroy() {
    $(config.popoverClass).remove();

    // Unbind all events.
    $.each(config.events, function(index, event) {
      $(document).unbind(event);
    });

    $(document).trigger(config.events.destroyed);
  }

  return {
    init   : init,
    show   : show,
    hide   : hide,
    destroy: destroy
  };

}());
<|endoftext|>


<commit_before>
(function(global){
  var ChatWork = (function() {

    function ChatWork(config)
    {
      this.base_url = 'https://api.chatwork.com/v1';
      this.headers  = {'X-ChatWorkToken': config.token};
    };

    /**
    * メッセージ送信
    */
    ChatWork.prototype.sendMessage = function(params) {
      var post_data = {
        'body': params.body
      }

      return this.post('/rooms/'+ params.room_id +'/messages', post_data);
    };

    /**
    * マイチャットへのメッセージを送信
    */
    ChatWork.prototype.sendMessageToMyChat = function(message) {
      var mydata = this.get('/me');

      return this.sendMessage({
        'body': message,
        'room_id': mydata.room_id
      });
    };

    /**
    * タスク追加
    */
    ChatWork.prototype.sendTask = function(params) {
      var to_ids = params.to_id_list.join(',');
      var post_data = {
        'body': params.body,
        'to_ids': to_ids,
        'limit': (new Number(params.limit)).toFixed() // 指数表記で来ることがあるので、intにする
      };

      return this.post('/rooms/'+ params.room_id +'/tasks', post_data);
    };

    /**
     * 指定したチャットのタスク一覧を取得
     */
    ChatWork.prototype.getRoomTasks = function(room_id, params) {
      return this.get('/rooms/' + room_id + '/tasks', params);
    };

    /**
    * 自分のタスク一覧を取得
    */
    ChatWork.prototype.getMyTasks = function(params) {
      return this.get('/my/tasks', params);
    };

    ChatWork.prototype._sendRequest = function(params)
    {
      var url = this.base_url + params.path;
      var options = {
        'method': params.method,
        'headers': this.headers,
        'payload': params.payload || {}
      };
      result = UrlFetchApp.fetch(url, options);

      // リクエストに成功していたら結果を解析して返す
      if (result.getResponseCode() == 200) {
        return JSON.parse(result.getContentText())
      }

      return false;
    };

    ChatWork.prototype.post = function(endpoint, post_data) {
      return this._sendRequest({
        'method': 'post',
        'path': endpoint,
        'payload': post_data
      });
    };

    ChatWork.prototype.put = function(endpoint, put_data) {
      return this._sendRequest({
        'method': 'put',
        'path': endpoint,
        'payload': put_data
      });
    };

    ChatWork.prototype.get = function(endpoint, get_data) {
      get_data = get_data || {};

      var path = endpoint

      // get_dataがあればクエリーを生成する
      // かなり簡易的なので必要に応じて拡張する
      var query_string_list = [];
      for (var key in get_data) {
        query_string_list.push(encodeURIComponent(key) + '=' + encodeURIComponent(get_data[key]));
      }

      if (query_string_list.length > 0) {
        path += '?' + query_string_list.join('&');
      }

      return this._sendRequest({
        'method': 'get',
        'path': path
      });
    };

    return ChatWork;
  })();

  global.ChatWork = ChatWork;

})(this);

/**
 * ChatWorkClientの作成
 *
 *
利用例

 *

 * var cw = ChatWorkClient.factory({token: xxx});
 * cw.sendMessage({room_id: xx, body: xx});
 *

 * @param {assoc} config
 */
function factory(config) {
  return new ChatWork(config);
};
<commit_msg>Update API version<commit_after>
(function(global){
  var ChatWork = (function() {

    function ChatWork(config)
    {
      this.base_url = 'https://api.chatwork.com/v2';
      this.headers  = {'X-ChatWorkToken': config.token};
    };

    /**
    * メッセージ送信
    */
    ChatWork.prototype.sendMessage = function(params) {
      var post_data = {
        'body': params.body
      }

      return this.post('/rooms/'+ params.room_id +'/messages', post_data);
    };

    /**
    * マイチャットへのメッセージを送信
    */
    ChatWork.prototype.sendMessageToMyChat = function(message) {
      var mydata = this.get('/me');

      return this.sendMessage({
        'body': message,
        'room_id': mydata.room_id
      });
    };

    /**
    * タスク追加
    */
    ChatWork.prototype.sendTask = function(params) {
      var to_ids = params.to_id_list.join(',');
      var post_data = {
        'body': params.body,
        'to_ids': to_ids,
        'limit': (new Number(params.limit)).toFixed() // 指数表記で来ることがあるので、intにする
      };

      return this.post('/rooms/'+ params.room_id +'/tasks', post_data);
    };

    /**
     * 指定したチャットのタスク一覧を取得
     */
    ChatWork.prototype.getRoomTasks = function(room_id, params) {
      return this.get('/rooms/' + room_id + '/tasks', params);
    };

    /**
    * 自分のタスク一覧を取得
    */
    ChatWork.prototype.getMyTasks = function(params) {
      return this.get('/my/tasks', params);
    };

    ChatWork.prototype._sendRequest = function(params)
    {
      var url = this.base_url + params.path;
      var options = {
        'method': params.method,
        'headers': this.headers,
        'payload': params.payload || {}
      };
      result = UrlFetchApp.fetch(url, options);

      // リクエストに成功していたら結果を解析して返す
      if (result.getResponseCode() == 200) {
        return JSON.parse(result.getContentText())
      }

      return false;
    };

    ChatWork.prototype.post = function(endpoint, post_data) {
      return this._sendRequest({
        'method': 'post',
        'path': endpoint,
        'payload': post_data
      });
    };

    ChatWork.prototype.put = function(endpoint, put_data) {
      return this._sendRequest({
        'method': 'put',
        'path': endpoint,
        'payload': put_data
      });
    };

    ChatWork.prototype.get = function(endpoint, get_data) {
      get_data = get_data || {};

      var path = endpoint

      // get_dataがあればクエリーを生成する
      // かなり簡易的なので必要に応じて拡張する
      var query_string_list = [];
      for (var key in get_data) {
        query_string_list.push(encodeURIComponent(key) + '=' + encodeURIComponent(get_data[key]));
      }

      if (query_string_list.length > 0) {
        path += '?' + query_string_list.join('&');
      }

      return this._sendRequest({
        'method': 'get',
        'path': path
      });
    };

    return ChatWork;
  })();

  global.ChatWork = ChatWork;

})(this);

/**
 * ChatWorkClientの作成
 *
 *
利用例

 *

 * var cw = ChatWorkClient.factory({token: xxx});
 * cw.sendMessage({room_id: xx, body: xx});
 *

 * @param {assoc} config
 */
function factory(config) {
  return new ChatWork(config);
};
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	errorHandler = require('./errors'),
	Story = mongoose.model('Story'),
	nodemailer = require('nodemailer'),

	_ = require('lodash');

var transporter = nodemailer.createTransport({
    service: 'Gmail',
    auth: {
        user: 'aacase@gmail.com',
        pass: 'W%skippy1738'
    }
});

/**
 * Create a Story
 */
exports.create = function(req, res) {
	var story = new Story(req.body);
	story.user = req.user;

	story.save(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(story);
		}
	});

	var mailOptions = {
	    from: 'Aaron Case ✔ <aacase@gmail.com>', // sender address
	    to: 'Aaron Case ✔ <aacase@gmail.com>', // list of receivers
	    subject: 'Hello ✔', // Subject line
	    text: 'Hello world ✔', // plaintext body
	    html: 'Hello world ✔' // html body
	};

	// send mail with defined transport object
	transporter.sendMail(mailOptions, function(error, info){
	    if(error){
	        console.log(error);
	    }else{
	        console.log('Message sent: ' + info.response);
	    }
	});
};

/**
 * Show the current Story
 */
exports.read = function(req, res) {
	res.jsonp(req.story);
};

/**
 * Update a Story
 */
exports.update = function(req, res) {
	var story = req.story ;

	story = _.extend(story , req.body);

	story.save(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(story);
		}
	});
};

/**
 * Delete an Story
 */
exports.delete = function(req, res) {
	var story = req.story ;

	story.remove(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(story);
		}
	});
};

/**
 * List of Stories
 */
exports.list = function(req, res) { Story.find().sort('-created').populate('user', 'displayName').exec(function(err, stories) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(stories);
		}
	});
};

/**
 * Story middleware
 */
exports.storyByID = function(req, res, next, id) { Story.findById(id).populate('user', 'displayName').exec(function(err, story) {
		if (err) return next(err);
		if (! story) return next(new Error('Failed to load Story ' + id));
		req.story = story ;
		next();
	});
};

/**
 * Story authorization middleware
 */
exports.hasAuthorization = function(req, res, next) {
	if (req.story.user.id !== req.user.id) {
		return res.status(403).send('User is not authorized');
	}
	next();
};<commit_msg>mailer working, but sending twice<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	errorHandler = require('./errors'),
	Story = mongoose.model('Story'),
	nodemailer = require('nodemailer'),

	_ = require('lodash');

var transporter = nodemailer.createTransport({
    service: 'Gmail',
    auth: {
        user: 'aacase@gmail.com',
        pass: 'W%skippy1738'
    }
});

/**
 * Create a Story
 */
exports.create = function(req, res) {
	var story = new Story(req.body);
	story.user = req.user;

	story.save(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(story);
		}
	});

	var mailOptions = {
	    from: 'Aaron Case ✔ <aacase@gmail.com>', // sender address
	    to: req.user.email, // list of receivers
	    subject: 'Hello ✔', // Subject line
	    text: 'Hello world ✔', // plaintext body
	    html: "
Here's that kickass story you made on Keystoke Storytime!
\

"+story.content+"
\

"+story.content2+"
\

"+story.content3+"
"// html body
	};

	// send mail with defined transport object
	transporter.sendMail(mailOptions, function(error, info){
	    if(error){
	        console.log(error);
	    }else{
	        console.log('Message sent: ' + info.response);
	    }
	});
};

/**
 * Show the current Story
 */
exports.read = function(req, res) {
	res.jsonp(req.story);
};

/**
 * Update a Story
 */
exports.update = function(req, res) {
	var story = req.story ;

	story = _.extend(story , req.body);

	story.save(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(story);
		}
	});
};

/**
 * Delete an Story
 */
exports.delete = function(req, res) {
	var story = req.story ;

	story.remove(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(story);
		}
	});
};

/**
 * List of Stories
 */
exports.list = function(req, res) { Story.find().sort('-created').populate('user', 'displayName').exec(function(err, stories) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(stories);
		}
	});
};

/**
 * Story middleware
 */
exports.storyByID = function(req, res, next, id) { Story.findById(id).populate('user', 'displayName').exec(function(err, story) {
		if (err) return next(err);
		if (! story) return next(new Error('Failed to load Story ' + id));
		req.story = story ;
		next();
	});
};

/**
 * Story authorization middleware
 */
exports.hasAuthorization = function(req, res, next) {
	if (req.story.user.id !== req.user.id) {
		return res.status(403).send('User is not authorized');
	}
	next();
};<|endoftext|>


<commit_before>function GameManager(size, InputManager, Actuator) {
  this.size         = size; // Size of the grid
  this.inputManager = new InputManager;
  this.actuator     = new Actuator;
  this.running      = false;

  this.inputManager.on("move", this.move.bind(this));
  this.inputManager.on("restart", this.restart.bind(this));

  this.inputManager.on('think', function() {
    var best = this.ai.getBest({
		score: this.score,
		grid: this.grid
	});
    this.actuator.showHint(best.move);
  }.bind(this));

  this.inputManager.on('run', function() {
    if (this.running) {
      this.running = false;
      this.actuator.setRunButton('Auto-run');
    } else {
      this.running = true;
      this.run()
      this.actuator.setRunButton('Stop');
    }
  }.bind(this));

  this.setup();
}

// Restart the game
GameManager.prototype.restart = function () {
  this.actuator.restart();
 // this.running = false;
 // this.actuator.setRunButton('Auto-run');
  this.setup();
};

// Set up the game
GameManager.prototype.setup = function () {
  this.grid         = new Grid(this.size);
  this.grid.addStartTiles();

  this.ai           = this.ai || new AI();

  this.score        = 0;
  this.over         = false;
  this.won          = false;
  this.timesMoved   = 0;
  // Update the actuator
  this.actuate();
};

// Sends the updated grid to the actuator
GameManager.prototype.actuate = function () {

	this.actuator.actuate(this.grid, {
		score: this.score,
		over:  this.over,
		won:   this.won
	});

	if(this.over){
		this.logResults();
	}

};

GameManager.prototype.logResults = function() {
	var GM = this;

	if( !this.win ){
		setTimeout( function() {

			GM.actuator.restart();
			GM.setup();
			document.getElementsByClassName("ai-button")[1].click();
			document.getElementsByClassName("ai-button")[1].click();

		}, 2000 );
	}

};

// makes a given move and updates state
GameManager.prototype.move = function(direction) {
  var result = this.grid.move(direction);
  this.score += result.score;
	if( this.previousMove )
		this.previousMove.moved = result.moved;
	else
		this.previousMove = { moved: result.moved, move: 0 };

  if (!result.won) {
    if (result.moved) {
      this.grid.computerMove();
    }
  } else {
    this.won = true;
  }

  //console.log(this.grid.valueSum());

  if (!this.grid.movesAvailable()) {
	jQuery('#scoreHistory').append('
 Ending Score: ' + this.score + ' - Total Moves: ' + (this.timesMoved+1) + '
');
    this.over = true; // Game over!
  }

  this.actuate();
}

// moves continuously until game is over
GameManager.prototype.run = function() {
	console.log(this.previousMove);
	var best = this.ai.getBest({
		score: this.score,
		moved: ( ( this.previousMove ) ? this.previousMove.moved : false ),
		previousMove: ( ( this.previousMove ) ? this.previousMove.move : 0 ),
		timesMoved: this.timesMoved,
		grid: this.grid
	});
	this.previousScore = this.score;
	this.move(best.move);
	console.log(this.previousMove);
	this.previousMove = best;
	this.timesMoved++;
	this.ai.reward({
			score: this.score,
			previous: this.previousScore,
			won: this.won,
			over: this.over,
			timesMoved: this.timesMoved,
			empty: this.ai.getEmptyCount()
		});
  var timeout = animationDelay;
  if (this.running && !this.over && !this.won) {
    var self = this;
    setTimeout(function(){
      self.run();
    }, timeout);
  }
}
<commit_msg>jsonify the play history<commit_after>function GameManager(size, InputManager, Actuator) {
  this.size         = size; // Size of the grid
  this.inputManager = new InputManager;
  this.actuator     = new Actuator;
  this.running      = false;
	this.history = [];
  this.inputManager.on("move", this.move.bind(this));
  this.inputManager.on("restart", this.restart.bind(this));

  this.inputManager.on('think', function() {
    var best = this.ai.getBest({
		score: this.score,
		grid: this.grid
	});
    this.actuator.showHint(best.move);
  }.bind(this));

  this.inputManager.on('run', function() {
    if (this.running) {
      this.running = false;
      this.actuator.setRunButton('Auto-run');
    } else {
      this.running = true;
      this.run()
      this.actuator.setRunButton('Stop');
    }
  }.bind(this));

  this.setup();
}

// Restart the game
GameManager.prototype.restart = function () {
  this.actuator.restart();
 // this.running = false;
 // this.actuator.setRunButton('Auto-run');
  this.setup();
};

// Set up the game
GameManager.prototype.setup = function () {
  this.grid         = new Grid(this.size);
  this.grid.addStartTiles();

  this.ai           = this.ai || new AI();

  this.score        = 0;
  this.over         = false;
  this.won          = false;
  this.timesMoved   = 0;
  // Update the actuator
  this.actuate();
};

// Sends the updated grid to the actuator
GameManager.prototype.actuate = function () {

	this.actuator.actuate(this.grid, {
		score: this.score,
		over:  this.over,
		won:   this.won
	});

	if(this.over){
		this.logResults();
	}

};

GameManager.prototype.logResults = function() {
	var GM = this;

	if( !this.win ){
		setTimeout( function() {

			GM.actuator.restart();
			GM.setup();
			document.getElementsByClassName("ai-button")[1].click();
			document.getElementsByClassName("ai-button")[1].click();

		}, 2000 );
	}

};

// makes a given move and updates state
GameManager.prototype.move = function(direction) {
  var result = this.grid.move(direction);
  this.score += result.score;
	if( this.previousMove )
		this.previousMove.moved = result.moved;
	else
		this.previousMove = { moved: result.moved, move: 0 };

  if (!result.won) {
    if (result.moved) {
      this.grid.computerMove();
    }
  } else {
    this.won = true;
  }

  //console.log(this.grid.valueSum());

  if (!this.grid.movesAvailable()) {
	this.history.push({ ending: this.score, moves: (this.timesMoved+1)});
	jQuery('#scoreHistory').append('
'.JSON.stringify(this.history).'
');
    this.over = true; // Game over!
  }

  this.actuate();
}

// moves continuously until game is over
GameManager.prototype.run = function() {
	console.log(this.previousMove);
	var best = this.ai.getBest({
		score: this.score,
		moved: ( ( this.previousMove ) ? this.previousMove.moved : false ),
		previousMove: ( ( this.previousMove ) ? this.previousMove.move : 0 ),
		timesMoved: this.timesMoved,
		grid: this.grid
	});
	this.previousScore = this.score;
	this.move(best.move);
	console.log(this.previousMove);
	this.previousMove = best;
	this.timesMoved++;
	this.ai.reward({
			score: this.score,
			previous: this.previousScore,
			won: this.won,
			over: this.over,
			timesMoved: this.timesMoved,
			empty: this.ai.getEmptyCount()
		});
  var timeout = animationDelay;
  if (this.running && !this.over && !this.won) {
    var self = this;
    setTimeout(function(){
      self.run();
    }, timeout);
  }
}
<|endoftext|>


<commit_before>let Application = require('spectron').Application
let chai = require('chai')
let chaiAsPromised = require('chai-as-promised')
let path = require('path')
let glob = require("glob")

let appPath;
if (process.platform === 'win32') {
  appPath = path.resolve(
    __dirname,
    '../node_modules/electron-prebuilt/dist/Electron.exe'
  );
} else if (process.platform === 'darwin') {
  appPath = path.resolve(
    __dirname,
    '../node_modules/electron-prebuilt/dist/Electron.app/Contents/MacOS/Electron'
  );
} else {
  appPath = path.resolve(
    __dirname,
    '../node_modules/electron-prebuilt/dist/electron'
  );
}

chai.should()
chai.use(chaiAsPromised)

describe('application launch', function () {
  beforeEach(function () {
    this.app = new Application({
      path: appPath,
      args: ['./app']
    })
    return this.app.start()
  })

  beforeEach(function () {
    chaiAsPromised.transferPromiseness = this.app.transferPromiseness
  })

  afterEach(function () {
    if (this.app && this.app.isRunning()) {
      return this.app.stop()
    }
  })

  it('opens a window', function () {
    return this.app.client.waitUntilWindowLoaded(31950)
      .getWindowCount().should.eventually.equal(1)
      .browserWindow.isMinimized().should.eventually.be.false
      .browserWindow.isDevToolsOpened().should.eventually.be.false
      .browserWindow.isVisible().should.eventually.be.true
      .browserWindow.isFocused().should.eventually.be.true
      .browserWindow.getBounds().should.eventually.have.property('width').and.be.above(0)
      .browserWindow.getBounds().should.eventually.have.property('height').and.be.above(0)
  })

  it('runs a protocol', function () {
    let file = path.join(__dirname, '..', 'server', 'tests', 'data', '/simple_protocol.py')
    let pauseTime = process.env.PAUSE_TIME || 0
    let connectDropDown = '//*[@id="connections"]'
    let virtualSmoothie = connectDropDown + '/option[3]'
    let uploadXpath = '/html/body/div/section/form/div/input'
    let saveButton = '//*[@id="task"]/button[1]'
    let platePath = '//*[@id="step-list"]/div/span/div/ul/li[2]/a'
    let plungerPath = '//*[@id="step-list"]/div/span/div/ul/li[3]/a'
    let top = '//*[@id="task-pipette"]/span/div[1]/section[1]/button[1]'
    let bottom = '//*[@id="task-pipette"]/span/div[1]/section[2]/button[1]'
    let dropTip = '//*[@id="task-pipette"]/span/div[1]/section[3]/button[1]'
    let blowOut = '//*[@id="task-pipette"]/span/div[1]/section[4]/button[1]'
    let plungerDown = '//*[@id="jog-controls"]/span[3]/button[2]'
    let run = '//*[@id="run"]/button'

    return this.app.client.waitUntilWindowLoaded(31950)
      .click(connectDropDown)
      .pause(pauseTime)
      .click(virtualSmoothie)
      .pause(pauseTime)
      .chooseFile(uploadXpath, file)
      .pause(1000)
      .pause(pauseTime)
      .waitForText('.toast-message-text', 'Successfully uploaded simple_protocol.py')
      .click(saveButton)
      .pause(pauseTime)
      .click(platePath)
      .pause(pauseTime)
      .click(saveButton)
      .pause(pauseTime)
      .click(plungerPath)
      .pause(pauseTime)
      .click(top)
      .pause(pauseTime)
      .click(plungerDown)
      .pause(pauseTime)
      .click(bottom)
      .pause(pauseTime)
      .click(plungerDown)
      .pause(pauseTime)
      .click(dropTip)
      .pause(pauseTime)
      .click(blowOut)
      .pause(pauseTime)
      .click(run)
      .pause(2000)
      .waitForText(".toast-message-text", "Run complete")
  })
})
<commit_msg>fix integration test xpath<commit_after>let Application = require('spectron').Application
let chai = require('chai')
let chaiAsPromised = require('chai-as-promised')
let path = require('path')
let glob = require("glob")

let appPath;
if (process.platform === 'win32') {
  appPath = path.resolve(
    __dirname,
    '../node_modules/electron-prebuilt/dist/Electron.exe'
  );
} else if (process.platform === 'darwin') {
  appPath = path.resolve(
    __dirname,
    '../node_modules/electron-prebuilt/dist/Electron.app/Contents/MacOS/Electron'
  );
} else {
  appPath = path.resolve(
    __dirname,
    '../node_modules/electron-prebuilt/dist/electron'
  );
}

chai.should()
chai.use(chaiAsPromised)

describe('application launch', function () {
  beforeEach(function () {
    this.app = new Application({
      path: appPath,
      args: ['./app']
    })
    return this.app.start()
  })

  beforeEach(function () {
    chaiAsPromised.transferPromiseness = this.app.transferPromiseness
  })

  afterEach(function () {
    if (this.app && this.app.isRunning()) {
      return this.app.stop()
    }
  })

  it('opens a window', function () {
    return this.app.client.waitUntilWindowLoaded(31950)
      .getWindowCount().should.eventually.equal(1)
      .browserWindow.isMinimized().should.eventually.be.false
      .browserWindow.isDevToolsOpened().should.eventually.be.false
      .browserWindow.isVisible().should.eventually.be.true
      .browserWindow.isFocused().should.eventually.be.true
      .browserWindow.getBounds().should.eventually.have.property('width').and.be.above(0)
      .browserWindow.getBounds().should.eventually.have.property('height').and.be.above(0)
  })

  it('runs a protocol', function () {
    let file = path.join(__dirname, '..', 'server', 'tests', 'data', '/simple_protocol.py')
    let pauseTime = process.env.PAUSE_TIME || 0
    let connectDropDown = '//*[@id="connections"]'
    let virtualSmoothie = connectDropDown + '/option[3]'
    let uploadXpath = '/html/body/div/section/span/form/div/input'
    let saveButton = '//*[@id="task"]/button[1]'
    let platePath = '//*[@id="step-list"]/div/span/div/ul/li[2]/a'
    let plungerPath = '//*[@id="step-list"]/div/span/div/ul/li[3]/a'
    let top = '//*[@id="task-pipette"]/span/div[1]/section[1]/button[1]'
    let bottom = '//*[@id="task-pipette"]/span/div[1]/section[2]/button[1]'
    let dropTip = '//*[@id="task-pipette"]/span/div[1]/section[3]/button[1]'
    let blowOut = '//*[@id="task-pipette"]/span/div[1]/section[4]/button[1]'
    let plungerDown = '//*[@id="jog-controls"]/span[3]/button[2]'
    let run = '//*[@id="run"]/button'

    return this.app.client.waitUntilWindowLoaded(31950)
      .click(connectDropDown)
      .pause(pauseTime)
      .click(virtualSmoothie)
      .pause(pauseTime)
      .pause(1000)
      .chooseFile(uploadXpath, file)
      .pause(1000)
      .pause(pauseTime)
      .waitForText('.toast-message-text', 'Successfully uploaded simple_protocol.py')
      .click(saveButton)
      .pause(pauseTime)
      .click(platePath)
      .pause(pauseTime)
      .click(saveButton)
      .pause(pauseTime)
      .click(plungerPath)
      .pause(pauseTime)
      .click(top)
      .pause(pauseTime)
      .click(plungerDown)
      .pause(pauseTime)
      .click(bottom)
      .pause(pauseTime)
      .click(plungerDown)
      .pause(pauseTime)
      .click(dropTip)
      .pause(pauseTime)
      .click(blowOut)
      .pause(pauseTime)
      .click(run)
      .pause(2000)
      .waitForText(".toast-message-text", "Run complete")
  })
})
<|endoftext|>


<commit_before>var proj4 = require('proj4');
var webmercatorProj = new proj4.Proj('EPSG:3857');

function transform(point, scale) {
    var a = 0.5 / (Math.PI * proj4.WGS84.a),
        b = 0.5,
        c = -a,
        d = b;

    return {
        x: scale * (a * point.x + b),
        y: scale * (c * point.y + d)
    };
}

function project(latlng, zoom) {
    var projectedPoint = proj4(webmercatorProj, proj4.toPoint([latlng.lng, latlng.lat]));
    return transform(projectedPoint, 256 * Math.pow(2, zoom));
}

function subtract(pointA, pointB) {
    return {
        x: pointA.x - pointB.x,
        y: pointA.y - pointB.y
    };
}

function contains(pointA, pointB) {
    return Math.abs(pointB.x) <= Math.abs(pointA.x) && Math.abs(pointB.y) <= Math.abs(pointA.y);
}

function floorPoint(point) {
    return {
        x: Math.floor(point.x),
        y: Math.floor(point.y)
    };
}

function boundsZoom(bounds, size) {

    size = {
        x: size.width,
        y: size.height
    };

    var west = Math.min(bounds.lng1, bounds.lng2),
        south = Math.min(bounds.lat1, bounds.lat2),
        east = Math.max(bounds.lng1, bounds.lng2),
        north = Math.max(bounds.lat1, bounds.lat2),

        zoom = 0,
        maxZoom = 18,

        nw = {lat: north, lng: west},
        se = {lat: south, lng: east},

        zoomNotFound = true,
        boundsSize;

    do {
        zoom++;
        boundsSize = floorPoint(subtract(project(se, zoom), project(nw, zoom)));
        zoomNotFound = contains(size, boundsSize);
    } while (zoomNotFound && zoom <= maxZoom);

    console.log(project(se, zoom-1));
    console.log(project(nw, zoom-1));

    return zoom - 1;
}
console.log(boundsZoom({lat1: 49, lng1: 6, lat2: 52, lng2: 9}, {width: 256, height: 256}));
<commit_msg>Removes example file created while developing boundZoom<commit_after><|endoftext|>


<commit_before>import copy from './copy';
import { clipboard } from 'electron';
// const { clipboard } = require('electron');

jest.mock('electron', () => ({
  clipboard: {
    writeText: jest.fn(),
  },
}));

describe('app/main/actions/copy', () => {
  let message;
  let arg;
  beforeEach(() => {
    message = 'foo';
    arg = 'bar';
  });
  describe('with arg', () => {
    beforeEach(() => {
      copy(message, arg);
    });
    it('should call `writeText`', () => {
      expect(clipboard.writeText).toHaveBeenCalledTimes(1);
    });
    it('should call `writeText` with `bar`', () => {
      expect(clipboard.writeText).toHaveBeenCalledWith('bar');
    });
  });
  describe('without arg', () => {
    beforeEach(() => {
      arg = undefined;
      copy(message, arg);
    });
    it('should not call `writeText`', () => {
      expect(clipboard.writeText).not.toHaveBeenCalled();
    });
  });
  afterEach(() => {
    clipboard.writeText.mockClear();
  });
});
<commit_msg>refactor(app/main): remove commented import<commit_after>import copy from './copy';
import { clipboard } from 'electron';

jest.mock('electron', () => ({
  clipboard: {
    writeText: jest.fn(),
  },
}));

describe('app/main/actions/copy', () => {
  let message;
  let arg;
  beforeEach(() => {
    message = 'foo';
    arg = 'bar';
  });
  describe('with arg', () => {
    beforeEach(() => {
      copy(message, arg);
    });
    it('should call `writeText`', () => {
      expect(clipboard.writeText).toHaveBeenCalledTimes(1);
    });
    it('should call `writeText` with `bar`', () => {
      expect(clipboard.writeText).toHaveBeenCalledWith('bar');
    });
  });
  describe('without arg', () => {
    beforeEach(() => {
      arg = undefined;
      copy(message, arg);
    });
    it('should not call `writeText`', () => {
      expect(clipboard.writeText).not.toHaveBeenCalled();
    });
  });
  afterEach(() => {
    clipboard.writeText.mockClear();
  });
});
<|endoftext|>


<commit_before>var o2 = {
  version : _o2Version,
};

// Can require both javascript and css files.
o2.require = function(url, onLoadCallback, isJson) {
  var urlWithoutVersion = o2.getUrlWithoutVersion(url);
  var urlWithVersion    = o2.getUrlWithVersion(urlWithoutVersion);
  if (!window.includedUrls) {
    window.includedUrls = new Array();
  }
  if (o2.hasBeenRequired(urlWithoutVersion)) {
    o2._executeRequireCallback(onLoadCallback, urlWithoutVersion);
    return;
  }

  var newNode;
  if (urlWithoutVersion.match(/\.css([?]|$)/i)) { // It's a css file
    if (!o2._validateBrowser(urlWithoutVersion)) {
      return;
    }
    newNode = document.createElement("link");
    newNode.setAttribute( "rel",  "stylesheet"   );
    newNode.setAttribute( "type", "text/css"     );
    newNode.setAttribute( "href", urlWithVersion );
    document.getElementsByTagName("head").item(0).appendChild(newNode);
  }
  else {
    $.ajaxSetup({async:false});
    if (isJson) {
      $.getScript(urlWithoutVersion);
    }
    else { // Let's just assume it's a javascript file
      $.getScript(url);
    }
    $.ajaxSetup({async:true});
    includedUrls[urlWithoutVersion] = true;
  }
  if (o2.isJqueryUrl(urlWithoutVersion)) {
    includedUrls.jquery = true;
  }
  else if (o2.isJqueryUiUrl(urlWithoutVersion)) {
    includedUrls.jqueryUi = true;
  }
  o2._executeRequireCallback(onLoadCallback, url);
}

o2.requireJs = function(file, onLoadCallback) {
  o2._requireJsOrCss("js", file, onLoadCallback);
}

o2.requireJson = function(file, onLoadCallback) {
  o2._requireJsOrCss("json", file, onLoadCallback);
}

o2.requireCss = function(file, onLoadCallback) {
  o2._requireJsOrCss("css", file, onLoadCallback);
}

o2._requireJsOrCss = function(type, file, onLoadCallback) {
  if (file.match(/^\//)) { // Starts with a slash
    return o2.require(file, onLoadCallback);
  }

  var isJson = type === "json";
  if (isJson) {
    type = "js";
  }
  var url = "/" + type + "/" + file + "." + type;
  return o2.require(url, onLoadCallback, isJson);
}

o2.hasBeenRequired = function(url) {
  var urlWithoutVersion = o2.getUrlWithoutVersion(url);
  if (o2.isJqueryUrl(urlWithoutVersion)) {
    return includedUrls.jquery;
  }
  if (o2.isJqueryUiUrl(urlWithoutVersion)) {
    return includedUrls.jqueryUi;
  }
  return includedUrls[urlWithoutVersion];
}

o2.isJqueryUrl = function(url) {
  return url.match(/\bjquery(-\d+[.]\d+[.]\d+)?([.]min)?[.]js\b/);
}

o2.isJqueryUiUrl = function(url) {
  return url.match(/\bjquery-ui(-\d+[.]\d+[.]\d+)?([.]\w+)?([.]min)?[.]js\b/);
}

o2.hasBeenRequiredAndLoaded = function(url) {
  var urlWithoutVersion = o2.getUrlWithoutVersion(url);
  return o2.hasBeenRequired(urlWithoutVersion);
}

o2._executeRequireCallback = function(onLoadCallback, url) {
  if (onLoadCallback) {
    onLoadCallback.call(this, url);
  }
}

o2._getXmlHttpRequest = function() {
  var xmlHttp;
  if (window.XMLHttpRequest) {
    xmlHttp = new XMLHttpRequest();
  }
  else if (window.ActiveXObject) { // branch for IE/Windows ActiveX version
    try {
      xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (e) {
      xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
  }
  return xmlHttp;
}

o2._validateBrowser = function(url) {
  if (url.match(/^[^.]+([.]min)?[.]css$/)) {
    return true;
  }
  var userAgent = navigator.userAgent.toLowerCase();
  var isIe      = userAgent.indexOf("msie")  !== -1  &&  userAgent.indexOf("opera") === -1  &&  userAgent.indexOf("webtv") === -1;
  if (!isIe) {
    return false;
  }
  var allowedIeVersion = url.replace(/^.*[.]ie(\d*)[.]css$/, "$1");
  if (!allowedIeVersion) {
    return true;
  }
  var ieVersion = parseFloat( userAgent.replace(/^.*msie ([\d.]+).*$/, "$1") );
  return parseFloat(allowedIeVersion) === ieVersion;
}

o2.getUrlWithVersion = function(url) {
  if (url.match(/[&?]v=\d+/)) {
    return url; // Already contains version (v) attribute
  }
  var urlWithoutVersion = o2.getUrlWithoutVersion(url);
  return urlWithoutVersion + (urlWithoutVersion.match(/[?]/) ? "&" : "?") + "v=" + o2.version;
}

o2.getUrlWithoutVersion = function(url) {
  return url.replace(/([&?])v=\d+(&|$)/, "$1").replace(/[?]$/, ""); // Remove v (version) attribute from url
}
<commit_msg>Things should work even if v-parameter (version) is missing.<commit_after>var o2 = {
  version : _o2Version,
};

// Can require both javascript and css files.
o2.require = function(url, onLoadCallback, isJson) {
  var urlWithoutVersion = o2.getUrlWithoutVersion(url);
  var urlWithVersion    = o2.getUrlWithVersion(urlWithoutVersion);
  if (!window.includedUrls) {
    window.includedUrls = new Array();
  }
  if (o2.hasBeenRequired(urlWithoutVersion)) {
    o2._executeRequireCallback(onLoadCallback, urlWithoutVersion);
    return;
  }

  var newNode;
  if (urlWithoutVersion.match(/\.css([?]|$)/i)) { // It's a css file
    if (!o2._validateBrowser(urlWithoutVersion)) {
      return;
    }
    newNode = document.createElement("link");
    newNode.setAttribute( "rel",  "stylesheet"   );
    newNode.setAttribute( "type", "text/css"     );
    newNode.setAttribute( "href", urlWithVersion );
    document.getElementsByTagName("head").item(0).appendChild(newNode);
  }
  else {
    $.ajaxSetup({async:false});
    if (isJson) {
      $.getScript(urlWithoutVersion);
    }
    else { // Let's just assume it's a javascript file
      $.getScript(url);
    }
    $.ajaxSetup({async:true});
    includedUrls[urlWithoutVersion] = true;
  }
  if (o2.isJqueryUrl(urlWithoutVersion)) {
    includedUrls.jquery = true;
  }
  else if (o2.isJqueryUiUrl(urlWithoutVersion)) {
    includedUrls.jqueryUi = true;
  }
  o2._executeRequireCallback(onLoadCallback, url);
}

o2.requireJs = function(file, onLoadCallback) {
  o2._requireJsOrCss("js", file, onLoadCallback);
}

o2.requireJson = function(file, onLoadCallback) {
  o2._requireJsOrCss("json", file, onLoadCallback);
}

o2.requireCss = function(file, onLoadCallback) {
  o2._requireJsOrCss("css", file, onLoadCallback);
}

o2._requireJsOrCss = function(type, file, onLoadCallback) {
  if (file.match(/^\//)) { // Starts with a slash
    return o2.require(file, onLoadCallback);
  }

  var isJson = type === "json";
  if (isJson) {
    type = "js";
  }
  var url = "/" + type + "/" + file + "." + type;
  return o2.require(url, onLoadCallback, isJson);
}

o2.hasBeenRequired = function(url) {
  var urlWithoutVersion = o2.getUrlWithoutVersion(url);
  if (o2.isJqueryUrl(urlWithoutVersion)) {
    return includedUrls.jquery;
  }
  if (o2.isJqueryUiUrl(urlWithoutVersion)) {
    return includedUrls.jqueryUi;
  }
  return includedUrls[urlWithoutVersion];
}

o2.isJqueryUrl = function(url) {
  return url.match(/\bjquery(-\d+[.]\d+[.]\d+)?([.]min)?[.]js\b/);
}

o2.isJqueryUiUrl = function(url) {
  return url.match(/\bjquery-ui(-\d+[.]\d+[.]\d+)?([.]\w+)?([.]min)?[.]js\b/);
}

o2.hasBeenRequiredAndLoaded = function(url) {
  var urlWithoutVersion = o2.getUrlWithoutVersion(url);
  return o2.hasBeenRequired(urlWithoutVersion);
}

o2._executeRequireCallback = function(onLoadCallback, url) {
  if (onLoadCallback) {
    onLoadCallback.call(this, url);
  }
}

o2._getXmlHttpRequest = function() {
  var xmlHttp;
  if (window.XMLHttpRequest) {
    xmlHttp = new XMLHttpRequest();
  }
  else if (window.ActiveXObject) { // branch for IE/Windows ActiveX version
    try {
      xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (e) {
      xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
  }
  return xmlHttp;
}

o2._validateBrowser = function(url) {
  if (url.match(/^[^.]+([.]min)?[.]css$/)) {
    return true;
  }
  var userAgent = navigator.userAgent.toLowerCase();
  var isIe      = userAgent.indexOf("msie")  !== -1  &&  userAgent.indexOf("opera") === -1  &&  userAgent.indexOf("webtv") === -1;
  if (!isIe) {
    return false;
  }
  var allowedIeVersion = url.replace(/^.*[.]ie(\d*)[.]css$/, "$1");
  if (!allowedIeVersion) {
    return true;
  }
  var ieVersion = parseFloat( userAgent.replace(/^.*msie ([\d.]+).*$/, "$1") );
  return parseFloat(allowedIeVersion) === ieVersion;
}

o2.getUrlWithVersion = function(url) {
  if (url.match(/[&?]v=\d*/)) {
    return url; // Already contains version (v) attribute
  }
  var urlWithoutVersion = o2.getUrlWithoutVersion(url);
  return urlWithoutVersion + (urlWithoutVersion.match(/[?]/) ? "&" : "?") + "v=" + o2.version;
}

o2.getUrlWithoutVersion = function(url) {
  return url.replace(/([&?])v=\d*(&|$)/, "$1").replace(/[?]$/, ""); // Remove v (version) attribute from url
}
<|endoftext|>