<commit_before>"use strict";

module.exports = function(imports) {

	let express = imports.modules.express;
	let ObjectId = imports.modules.mongoose.Types.ObjectId;
	let Promise = imports.modules.Promise;
	let util = imports.util;

	let requireLogin = util.requireLogin;
	let requireAdmin = util.requireAdmin;

	let Chat = imports.models.Chat;
	let User = imports.models.User;
	let Subdivision = imports.models.Subdivision;

	let router = express.Router();

	// TODO: separate this into separate requests for group and private chats
	router.post("/chats", requireLogin, Promise.coroutine(function*(req, res) {

		let subdivisionMembers = req.body.subdivisionMembers || [];
		let userMembers = req.body.userMembers || [];

		try {

			if (req.body.type == "private") {
				// private chat

				if((yield Chat.count({
					group: false,
					team: req.user.current_team._id,
					$or: [
						{ userMembers: [req.user._id, req.body.user2] },
						{ userMembers: [req.body.user2, req.user._id] }
					] // check to see if private convo already exists
				})) > 0) {
					return res.end("exists");
				}

				let chat = yield Chat.create({
					userMembers: userMembers,
					team: req.user.current_team._id,
					group: false
				});

				// get the user that is not the person making this request
				let user2Id = util.getUserOtherThanSelf(chat.userMembers, req.user._id.toString());
				let user = yield User.findOne({ _id: user2Id });

				res.json({
					_id: user._id,
					fn: user.firstname,
					ln: user.lastname,
					profpicpath: user.profpicpath,
					chat_id: chat._id
				});

			} else {
				// group chat

				if (req.body.name.length >= 20) { // name character limit
					return res.end("fail");
				}

				let chat = yield Chat.create({
					team: req.user.current_team._id,
					name: normalizeDisplayedText(req.body.name),
					userMembers: JSON.parse(userMembers),
					subdivisionMembers: JSON.parse(subdivisionMembers),
					group: true
				});

				res.json(chat);
			}
		} catch (err) {
			console.error(err);
			res.end("fail");
		}
	}));

	router.get("/chats", requireLogin, Promise.coroutine(function*(req, res) {
		// get an array of _ids of subdivisions of which the user is a member. (dat proper grammar doe)
		let userSubdivisionIds = util.activeSubdivisionIds(req.user.subdivisions);

		try {

			// find a chat in the current team that also has said user as a member or has a subdivision of which said user is a member.
			let chats = yield Chat.find({
				team: req.user.current_team._id,
				$or: [
					{
						userMembers: req.user._id
					}, {
						subdivisionMembers: {
							"$in": userSubdivisionIds
						}
					}
				]
			}, {
				_id: 1,
				name: 1,
				group: 1,
				userMembers: 1,
				subdivisionMembers: 1,
				updated_at: 1
			}).slice("messages", [0, 1])
				.populate("userMembers subdivisionMembers")
				.sort("-updated_at")
				.exec();
			// ^ the code above gets the latest message from the chat (for previews in iOS and Android) and orders the list by most recent.

			res.json(chats);

		} catch (err) {
			console.error(err);
			res.end("fail");
		}
	}));

	router.get("/chats/id/:chatId/messages", requireLogin, Promise.coroutine(function*(req, res) {
		// TODO: maybe in the future combine this with getUsersInChat to improve performance

		try {

			let skip = parseInt(req.query.skip);

			// loads 20 messages after skip many messages. example: if skip is 0, it loads messages 0-19, if it"s 20, loads 20-39, etc.
			let chat = yield Chat.findOne({ _id: req.params.chatId })
				.slice("messages", [skip, 20])
				.populate("messages.author")
				.exec();

			res.json(chat.messages);

		} catch (err) {
			console.error(err);
			res.end("fail");
		}
	}));

	router.get("/chats/id/:chatId/users", requireLogin, Promise.coroutine(function*(req, res) {
		// user members only, not subdivision members

		try {

			let chat = yield Chat.findOne({
				_id: req.params.chatId
			}, {
				userMembers: 1,
				subdivisionMembers: 1
			});

			let users = yield User.find({
				$or: [
					{
						_id: { "$in": chat.userMembers }
					}, {
						subdivisions: { $elemMatch: { _id: {"$in": chat.subdivisionMembers} } }
					}
				]
			});

			res.json(users);

		} catch (err) {
			console.error(err);
			res.end("fail");
		}
	}));

	router.get("/chats/id/:chatId/allMembers", requireLogin, Promise.coroutine(function*(req, res) {
		// both user members and subdivision members

		try {

			let chat = yield Chat.findOne({
				_id: req.params.chatId
			}, {
				userMembers: 1,
				subdivisionMembers: 1,
				group: 1
			});

			let userMembers = yield User.find({ _id: { "$in": chat.userMembers } });
			let subdivisionMembers = yield Subdivision.find({ _id: { "$in": chat.subdivisionMembers } });

			res.json({
				members: {
					userMembers: userMembers,
					subdivisionMembers: subdivisionMembers
				},
				group: chat.group
			});

		} catch (err) {
			console.error(err);
			res.end("fail");
		}
	}));

	router.put("/chats/group/id/:chatId/name", requireLogin, Promise.coroutine(function*(req, res) {

		if (req.body.newName.length >= 20) {
			return res.end("Name has to be 19 characters or fewer.");
		}

		try {

			yield Chat.update({
				_id: req.body.chat_id
			}, {
				name: util.normalizeDisplayedText(req.body.newName)
			});

			res.end("success");

		} catch (err) {
			console.error(err);
			res.end("fail");
		}
	}));

	router.delete("/chats/id/:chatId", requireAdmin, Promise.coroutine(function*(req, res) {
		try {

			yield Chat.findOneAndRemove({ _id: req.params.chatId });

			return res.end("success");

		} catch (err) {
			console.error(err);
			res.end("fail");
		}
	}));

	router.post("/chats/id/:chatId/messages", requireLogin, Promise.coroutine(function*(req, res) {
		try {

			yield Chat.update({ _id: req.params.chatId }, {
				"$push": {
					"messages": {
						"$each": [ {
							author: req.user._id,
				 			content: util.normalizeDisplayedText(req.body.content),
				  			timestamp: new Date()
						} ],
						"$position": 0
					}
				},
				updated_at: new Date()
			});

			res.end("success");

		} catch (err) {
			console.error(err);
			res.end("fail");
		}
	}));

	return router;

};
<commit_msg>Fix chat renaming<commit_after>"use strict";

module.exports = function(imports) {

	let express = imports.modules.express;
	let ObjectId = imports.modules.mongoose.Types.ObjectId;
	let Promise = imports.modules.Promise;
	let util = imports.util;

	let requireLogin = util.requireLogin;
	let requireAdmin = util.requireAdmin;

	let Chat = imports.models.Chat;
	let User = imports.models.User;
	let Subdivision = imports.models.Subdivision;

	let router = express.Router();

	// TODO: separate this into separate requests for group and private chats
	router.post("/chats", requireLogin, Promise.coroutine(function*(req, res) {

		let subdivisionMembers = req.body.subdivisionMembers || [];
		let userMembers = req.body.userMembers || [];

		try {

			if (req.body.type == "private") {
				// private chat

				if((yield Chat.count({
					group: false,
					team: req.user.current_team._id,
					$or: [
						{ userMembers: [req.user._id, req.body.user2] },
						{ userMembers: [req.body.user2, req.user._id] }
					] // check to see if private convo already exists
				})) > 0) {
					return res.end("exists");
				}

				let chat = yield Chat.create({
					userMembers: userMembers,
					team: req.user.current_team._id,
					group: false
				});

				// get the user that is not the person making this request
				let user2Id = util.getUserOtherThanSelf(chat.userMembers, req.user._id.toString());
				let user = yield User.findOne({ _id: user2Id });

				res.json({
					_id: user._id,
					fn: user.firstname,
					ln: user.lastname,
					profpicpath: user.profpicpath,
					chat_id: chat._id
				});

			} else {
				// group chat

				if (req.body.name.length >= 20) { // name character limit
					return res.end("fail");
				}

				let chat = yield Chat.create({
					team: req.user.current_team._id,
					name: normalizeDisplayedText(req.body.name),
					userMembers: JSON.parse(userMembers),
					subdivisionMembers: JSON.parse(subdivisionMembers),
					group: true
				});

				res.json(chat);
			}
		} catch (err) {
			console.error(err);
			res.end("fail");
		}
	}));

	router.get("/chats", requireLogin, Promise.coroutine(function*(req, res) {
		// get an array of _ids of subdivisions of which the user is a member. (dat proper grammar doe)
		let userSubdivisionIds = util.activeSubdivisionIds(req.user.subdivisions);

		try {

			// find a chat in the current team that also has said user as a member or has a subdivision of which said user is a member.
			let chats = yield Chat.find({
				team: req.user.current_team._id,
				$or: [
					{
						userMembers: req.user._id
					}, {
						subdivisionMembers: {
							"$in": userSubdivisionIds
						}
					}
				]
			}, {
				_id: 1,
				name: 1,
				group: 1,
				userMembers: 1,
				subdivisionMembers: 1,
				updated_at: 1
			}).slice("messages", [0, 1])
				.populate("userMembers subdivisionMembers")
				.sort("-updated_at")
				.exec();
			// ^ the code above gets the latest message from the chat (for previews in iOS and Android) and orders the list by most recent.

			res.json(chats);

		} catch (err) {
			console.error(err);
			res.end("fail");
		}
	}));

	router.get("/chats/id/:chatId/messages", requireLogin, Promise.coroutine(function*(req, res) {
		// TODO: maybe in the future combine this with getUsersInChat to improve performance

		try {

			let skip = parseInt(req.query.skip);

			// loads 20 messages after skip many messages. example: if skip is 0, it loads messages 0-19, if it"s 20, loads 20-39, etc.
			let chat = yield Chat.findOne({ _id: req.params.chatId })
				.slice("messages", [skip, 20])
				.populate("messages.author")
				.exec();

			res.json(chat.messages);

		} catch (err) {
			console.error(err);
			res.end("fail");
		}
	}));

	router.get("/chats/id/:chatId/users", requireLogin, Promise.coroutine(function*(req, res) {
		// user members only, not subdivision members

		try {

			let chat = yield Chat.findOne({
				_id: req.params.chatId
			}, {
				userMembers: 1,
				subdivisionMembers: 1
			});

			let users = yield User.find({
				$or: [
					{
						_id: { "$in": chat.userMembers }
					}, {
						subdivisions: { $elemMatch: { _id: {"$in": chat.subdivisionMembers} } }
					}
				]
			});

			res.json(users);

		} catch (err) {
			console.error(err);
			res.end("fail");
		}
	}));

	router.get("/chats/id/:chatId/allMembers", requireLogin, Promise.coroutine(function*(req, res) {
		// both user members and subdivision members

		try {

			let chat = yield Chat.findOne({
				_id: req.params.chatId
			}, {
				userMembers: 1,
				subdivisionMembers: 1,
				group: 1
			});

			let userMembers = yield User.find({ _id: { "$in": chat.userMembers } });
			let subdivisionMembers = yield Subdivision.find({ _id: { "$in": chat.subdivisionMembers } });

			res.json({
				members: {
					userMembers: userMembers,
					subdivisionMembers: subdivisionMembers
				},
				group: chat.group
			});

		} catch (err) {
			console.error(err);
			res.end("fail");
		}
	}));

	router.put("/chats/group/id/:chatId/name", requireLogin, Promise.coroutine(function*(req, res) {

		if (req.body.newName.length >= 20) {
			return res.end("Name has to be 19 characters or fewer.");
		}

		try {

			yield Chat.update({
				_id: req.params.chatId
			}, {
				name: util.normalizeDisplayedText(req.body.newName)
			});

			res.end("success");

		} catch (err) {
			console.error(err);
			res.end("fail");
		}
	}));

	router.delete("/chats/id/:chatId", requireAdmin, Promise.coroutine(function*(req, res) {
		try {

			yield Chat.findOneAndRemove({ _id: req.params.chatId });

			return res.end("success");

		} catch (err) {
			console.error(err);
			res.end("fail");
		}
	}));

	router.post("/chats/id/:chatId/messages", requireLogin, Promise.coroutine(function*(req, res) {
		try {

			yield Chat.update({ _id: req.params.chatId }, {
				"$push": {
					"messages": {
						"$each": [ {
							author: req.user._id,
				 			content: util.normalizeDisplayedText(req.body.content),
				  			timestamp: new Date()
						} ],
						"$position": 0
					}
				},
				updated_at: new Date()
			});

			res.end("success");

		} catch (err) {
			console.error(err);
			res.end("fail");
		}
	}));

	return router;

};
<|endoftext|>


<commit_before>//
// Copyright (c) Autodesk, Inc. All rights reserved
//
// Large Model Viewer Extractor
// by Cyrille Fauvel - Autodesk Developer Network (ADN)
// January 2015
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
var express =require ('express') ;
var request =require ('request') ;
var fs =require ('fs') ;
var multipart =require ('connect-multiparty') ;
var bodyParser =require ('body-parser') ;
var flow =require ('./flow-node.js') ('tmp') ;

var ACCESS_CONTROLL_ALLOW_ORIGIN =false ;

var router =express.Router () ;

var multipartMiddleware =multipart () ;
router.post ('/file', multipartMiddleware, function (req, res) {
	flow.post (req, function (status, filename, original_filename, identifier, totalSize) {
		console.log ('POST', status, original_filename, identifier) ;
		if ( status == 'done' ) {
			var data ={
				'key': identifier,
				'name': original_filename,
				'size': totalSize,
				'bytesRead': totalSize,
				'bytesPosted': 0
			} ;
			fs.writeFile ('data/' + identifier + '.json', JSON.stringify (data), function (err) {
				if ( err )
					console.log (err) ;
			}) ;
			var st =fs.createWriteStream ('./tmp/' + original_filename)
				.on ('finish', function () {}) ;
			flow.write (identifier, st, {
				end: true,
				onDone: function () {
					flow.clean (identifier) ;
				}
			}) ;
		}
		//if ( ACCESS_CONTROLL_ALLOW_ORIGIN )
		//	res.header ("Access-Control-Allow-Origin", "*") ;
		//res.status (status).send () ;
		res.status (200).end () ;
	}) ;
}) ;

router.options ('/file', function (req, res) {
	console.log ('OPTIONS') ;
	//if ( ACCESS_CONTROLL_ALLOW_ORIGIN )
	//	res.header ("Access-Control-Allow-Origin", "*") ;
	res.status (200).send () ;
}) ;

// Handle status checks on chunks through Flow.js
router.get ('/file', function (req, res) {
	flow.get (req, function (status, filename, original_filename, identifier, totalSize) {
		console.log ('GET', status) ;
		//if ( ACCESS_CONTROLL_ALLOW_ORIGIN )
		//	res.header("Access-Control-Allow-Origin", "*") ;
		res.status (status == 'found' ? 200 : 404).send () ; //- 404 Not Found
	}) ;
}) ;

router.get ('/file/*/details', function (req, res) {
	//console.log ('GET', req) ;
	var identifier =req.url.split ('/') [2] ;
	fs.readFile ('data/' + identifier + '.json', function (err, data) {
		if ( err )
			return (res.status (404).send ()) ; //- 404 Not Found
		data =JSON.parse (data) ;
		//res.setHeader ('Content-Type', 'application/json') ;
		res.json (data) ;
	}) ;
}) ;

router.get ('/file/*', function (req, res) {
	//console.log ('GET', req) ;
	var identifier =req.url.split ('/') [2] ;
	var data =fs.readFile ('data/' + identifier + '.json', function (err, data) {
		if ( err )
			throw err ;
		data =JSON.parse (data) ;
		//console.log (JSON.stringify (data)) ;
		var serverFile =__dirname + '/../tmp/' + data.name ;
		fs.exists (serverFile, function (exists) {
			if ( exists )
				res.download (serverFile, data.name) ;
			else
				res.status (404).end () ; //- 404 Not Found
		}) ;
	}) ;
}) ;

// http://murmuring-woodland-5218.herokuapp.com/samples/Seat.dwf (fails)
// http://dwf.blogs.com/residential/VizProject3d.DWF (succeed, but no head content-length)
router.post ('/uri', bodyParser.json (), function (req, res) {
	var uri =req.body.uri ;
	var identifier =req.body.identifier ;
	var original_filename =req.body.name || decodeURIComponent (uri).replace (/[\?#].*$/, "").replace (/.*\//, "") ;
	request.head (uri, function (err, headRes, body) {
		if ( err )
			return (res.status (500).end ()) ;
		if ( headRes.statusCode != 200 )
			return (res.status (headRes.statusCode).end (headRes.statusMessage)) ;
		//console.log ('content-type:', headRes.headers ['content-type']) ;
		//console.log ('content-length:', headRes.headers ['content-length']) ;
		var data ={
			"key": identifier,
			"name": original_filename,
			"uri": uri,
			"size": headRes.headers ['content-length'] || -1,
			"bytesRead": 0,
			"bytesPosted": 0
		} ;
		fs.writeFile ('data/' + identifier + '.json', JSON.stringify (data), function (err) {
			if ( err )
				return (res.status (500).end ()) ;
			var r =request (uri)
				//.on ('error', function (err) {
				//	console.log (err) ;
				//	console.log ('r error ' + original_filename) ;
				//})
				.on ('data', function (chunk) {
					data.bytesRead +=chunk.length ;
					fs.writeFile ('data/' + identifier + '.json', JSON.stringify (data), function (err) {}) ;
				})
				.pipe (fs.createWriteStream ('./tmp/' + original_filename)) ;
			r.on ('close', function () {
				if ( data.size !== -1 )
					data.bytesRead =data.size ;
				else
					data.size =data.bytesRead ;
				fs.writeFile ('data/' + identifier + '.json', JSON.stringify (data), function (err) {}) ;
			}) ;
			r.on ('error', function (message) {
				fs.unlink ('data/' + identifier + '.json', function (err) {}) ;
			}) ;
			res.json ({ 'status': identifier }) ;
		}) ;
	}) ;
}) ;

router.options ('/uri', bodyParser.json (), function (req, res) {
	var identifier =req.body.identifier ;
	fs.readFile ('data/' + identifier + '.json', function (err, data) {
		if ( err )
			return (res.status (500).end ()) ;
		try {
			data =JSON.parse (data) ;
			if ( data.size == -1 )
				throw "error" ;
		} catch ( e ) {
			return (res.json ({ 'status': identifier, 'progress': -1 })) ;
		}
		res.json ({ 'status': identifier, 'progress': Math.floor (100 * data.bytesRead / data.size) }) ;
	}) ;
}) ;

module.exports =router ;
<commit_msg>Update file.js<commit_after>//
// Copyright (c) Autodesk, Inc. All rights reserved
//
// Large Model Viewer Extractor
// by Cyrille Fauvel - Autodesk Developer Network (ADN)
// January 2015
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
var express =require ('express') ;
var request =require ('request') ;
var fs =require ('fs') ;
var multipart =require ('connect-multiparty') ;
var bodyParser =require ('body-parser') ;
var flow =require ('./flow-node.js') ('tmp') ;

var ACCESS_CONTROLL_ALLOW_ORIGIN =false ;

var router =express.Router () ;

var multipartMiddleware =multipart () ;
router.post ('/file', multipartMiddleware, function (req, res) {
	flow.post (req, function (status, filename, original_filename, identifier, totalSize) {
		console.log ('POST', status, original_filename, identifier) ;
		if ( status == 'done' ) {
			var data ={
				'key': identifier,
				'name': original_filename,
				'size': totalSize,
				'bytesRead': totalSize,
				'bytesPosted': 0
			} ;
			fs.writeFile (__dirname + '/../data/' + identifier + '.json', JSON.stringify (data), function (err) {
				if ( err )
					console.log (err) ;
			}) ;
			var st =fs.createWriteStream ('./tmp/' + original_filename)
				.on ('finish', function () {}) ;
			flow.write (identifier, st, {
				end: true,
				onDone: function () {
					flow.clean (identifier) ;
				}
			}) ;
		}
		//if ( ACCESS_CONTROLL_ALLOW_ORIGIN )
		//	res.header ("Access-Control-Allow-Origin", "*") ;
		//res.status (status).send () ;
		res.status (200).end () ;
	}) ;
}) ;

router.options ('/file', function (req, res) {
	console.log ('OPTIONS') ;
	//if ( ACCESS_CONTROLL_ALLOW_ORIGIN )
	//	res.header ("Access-Control-Allow-Origin", "*") ;
	res.status (200).send () ;
}) ;

// Handle status checks on chunks through Flow.js
router.get ('/file', function (req, res) {
	flow.get (req, function (status, filename, original_filename, identifier, totalSize) {
		console.log ('GET', status) ;
		//if ( ACCESS_CONTROLL_ALLOW_ORIGIN )
		//	res.header("Access-Control-Allow-Origin", "*") ;
		res.status (status == 'found' ? 200 : 404).send () ; //- 404 Not Found
	}) ;
}) ;

router.get ('/file/*/details', function (req, res) {
	//console.log ('GET', req) ;
	var identifier =req.url.split ('/') [2] ;
	fs.readFile (__dirname + '/../data/' + identifier + '.json', function (err, data) {
		if ( err )
			return (res.status (404).send ()) ; //- 404 Not Found
		data =JSON.parse (data) ;
		//res.setHeader ('Content-Type', 'application/json') ;
		res.json (data) ;
	}) ;
}) ;

router.get ('/file/*', function (req, res) {
	//console.log ('GET', req) ;
	var identifier =req.url.split ('/') [2] ;
	var data =fs.readFile (__dirname + '/../data/' + identifier + '.json', function (err, data) {
		if ( err )
			throw err ;
		data =JSON.parse (data) ;
		//console.log (JSON.stringify (data)) ;
		var serverFile =__dirname + '/../tmp/' + data.name ;
		fs.exists (serverFile, function (exists) {
			if ( exists )
				res.download (serverFile, data.name) ;
			else
				res.status (404).end () ; //- 404 Not Found
		}) ;
	}) ;
}) ;

// http://murmuring-woodland-5218.herokuapp.com/samples/Seat.dwf (fails)
// http://dwf.blogs.com/residential/VizProject3d.DWF (succeed, but no head content-length)
router.post ('/uri', bodyParser.json (), function (req, res) {
	var uri =req.body.uri ;
	var identifier =req.body.identifier ;
	var original_filename =req.body.name || decodeURIComponent (uri).replace (/[\?#].*$/, "").replace (/.*\//, "") ;
	request.head (uri, function (err, headRes, body) {
		if ( err )
			return (res.status (500).end ()) ;
		if ( headRes.statusCode != 200 )
			return (res.status (headRes.statusCode).end (headRes.statusMessage)) ;
		//console.log ('content-type:', headRes.headers ['content-type']) ;
		//console.log ('content-length:', headRes.headers ['content-length']) ;
		var data ={
			"key": identifier,
			"name": original_filename,
			"uri": uri,
			"size": headRes.headers ['content-length'] || -1,
			"bytesRead": 0,
			"bytesPosted": 0
		} ;
		fs.writeFile (__dirname + '/../data/' + identifier + '.json', JSON.stringify (data), function (err) {
			if ( err )
				return (res.status (500).end ()) ;
			var r =request (uri)
				//.on ('error', function (err) {
				//	console.log (err) ;
				//	console.log ('r error ' + original_filename) ;
				//})
				.on ('data', function (chunk) {
					data.bytesRead +=chunk.length ;
					fs.writeFile (__dirname + '/../data/' + identifier + '.json', JSON.stringify (data), function (err) {}) ;
				})
				.pipe (fs.createWriteStream (__dirname + '/../tmp/' + original_filename)) ;
			r.on ('close', function () {
				if ( data.size !== -1 )
					data.bytesRead =data.size ;
				else
					data.size =data.bytesRead ;
				fs.writeFile (__dirname + '/../data/' + identifier + '.json', JSON.stringify (data), function (err) {}) ;
			}) ;
			r.on ('error', function (message) {
				fs.unlink (__dirname + '/../data/' + identifier + '.json', function (err) {}) ;
			}) ;
			res.json ({ 'status': identifier }) ;
		}) ;
	}) ;
}) ;

router.options ('/uri', bodyParser.json (), function (req, res) {
	var identifier =req.body.identifier ;
	fs.readFile (__dirname + '/../data/' + identifier + '.json', function (err, data) {
		if ( err )
			return (res.status (500).end ()) ;
		try {
			data =JSON.parse (data) ;
			if ( data.size == -1 )
				throw "error" ;
		} catch ( e ) {
			return (res.json ({ 'status': identifier, 'progress': -1 })) ;
		}
		res.json ({ 'status': identifier, 'progress': Math.floor (100 * data.bytesRead / data.size) }) ;
	}) ;
}) ;

module.exports =router ;
<|endoftext|>


<commit_before>import { Meteor } from 'meteor/meteor';
import { loadFront } from 'yaml-front-matter';
import { GitHubConnector } from './github';
import { Tours, Pages } from '../collections';

function getFile(connector, repoFullName, path, ref) {
  let url = `/repos/${repoFullName}/contents/${path}`;

  if (ref) {
    url += `?ref=${ref}`;
  }

  return connector.get(url).then((data) => {
    return new Buffer(data.content, 'base64').toString();
  });
}

Meteor.methods({
  async importTour(tourRepository) {
    Tours.remove({ repository: tourRepository });
    Pages.remove({ routName: tourRepository });

    const connector = new GitHubConnector();

    const content = await getFile(connector, tourRepository, '.codetour.json');

    tour = JSON.parse(content);
    tour.repository = tourRepository;

    console.log(tour);

    Tours.insert(tour);

    tour.pages.forEach((pagePath) => {
      let page;

      getFile(connector, tour.repository, pagePath).then((content) => {
        page = {
          ...parseMD(content),
          tourName: tour.repository,
          slug: pagePath,
        };

        return getFile(connector, page.fullRepoName, page.filePath, page.commit);
      }).then((content) => {

        page = {
          ...page,
          code: content,
        };

        Pages.insert(page);
      }).catch((e) => {
        console.log(e);
      });
    });
  }
})

function parseMD(md) {
  const {
    title,
    code,
    __content: content,
  } = loadFront(md);

  const metadata = parseGitHubURL(code);

  const contentBlocks = parseContentBlocks(content, metadata);

  return {
    title,
    codeURL: code,
    content: contentBlocks,
    ...metadata,
  };
}

function parseGitHubURL(url) {
  // XXX this regex fails when there is only one line selected
  const re = /github\.com\/([^/]+)\/([^/]+)\/blob\/([^/]+)\/([^#]+)#L(\d+)-L(\d+)$/;
  const [
    str,
    user,
    repoName,
    commit,
    filePath,
    lineStart,
    lineEnd,
  ] = re.exec(url);

  const fileUrl = url.split('#')[0];

  return {
    user,
    repoName,
    fullRepoName: user + '/' + repoName,
    commit,
    filePath,
    lineStart,
    lineEnd,
    fileUrl,
  };
}

function parseContentBlocks(content, metadata) {
  const lines = content.split('\n');

  const segments = [];

  let currSegment = {
    slug: null,
    lineStart: null,
    lineEnd: null,
    content: '',
  };

  lines.forEach((line) => {
    if (line.indexOf(metadata.fileUrl) === -1) {
      currSegment.content += line + '\n';
      return;
    }

    // Close off current segment
    segments.push(currSegment);

    const re = /github\.com\/([^/]+)\/([^/]+)\/blob\/([^/]+)\/([^#]+)#L(\d+)(-L(\d+))?/;

    // This line contains a GitHub URL that points to the same file
    let [
      url,
      user,
      repoName,
      hash,
      path,
      lineStart,
      unused,
      lineEnd,
    ] = re.exec(line);

    if (!lineEnd) {
      lineEnd = lineStart;
    }

    const slug = /id="([^"]+)"/.exec(line)[1];
    const contentWithoutAnchorTag = /<a[^>]+>(.+)<\/a>/.exec(line)[1];

    currSegment = {
      slug,
      lineStart,
      lineEnd,
      content: contentWithoutAnchorTag,
    };
  });

  segments.push(currSegment);

  return segments;
}
<commit_msg>Remove stray console.log<commit_after>import { Meteor } from 'meteor/meteor';
import { loadFront } from 'yaml-front-matter';
import { GitHubConnector } from './github';
import { Tours, Pages } from '../collections';

function getFile(connector, repoFullName, path, ref) {
  let url = `/repos/${repoFullName}/contents/${path}`;

  if (ref) {
    url += `?ref=${ref}`;
  }

  return connector.get(url).then((data) => {
    return new Buffer(data.content, 'base64').toString();
  });
}

Meteor.methods({
  async importTour(tourRepository) {
    Tours.remove({ repository: tourRepository });
    Pages.remove({ routName: tourRepository });

    const connector = new GitHubConnector();

    const content = await getFile(connector, tourRepository, '.codetour.json');

    tour = JSON.parse(content);
    tour.repository = tourRepository;

    Tours.insert(tour);

    tour.pages.forEach((pagePath) => {
      let page;

      getFile(connector, tour.repository, pagePath).then((content) => {
        page = {
          ...parseMD(content),
          tourName: tour.repository,
          slug: pagePath,
        };

        return getFile(connector, page.fullRepoName, page.filePath, page.commit);
      }).then((content) => {

        page = {
          ...page,
          code: content,
        };

        Pages.insert(page);
      }).catch((e) => {
        console.log(e);
      });
    });
  }
})

function parseMD(md) {
  const {
    title,
    code,
    __content: content,
  } = loadFront(md);

  const metadata = parseGitHubURL(code);

  const contentBlocks = parseContentBlocks(content, metadata);

  return {
    title,
    codeURL: code,
    content: contentBlocks,
    ...metadata,
  };
}

function parseGitHubURL(url) {
  // XXX this regex fails when there is only one line selected
  const re = /github\.com\/([^/]+)\/([^/]+)\/blob\/([^/]+)\/([^#]+)#L(\d+)-L(\d+)$/;
  const [
    str,
    user,
    repoName,
    commit,
    filePath,
    lineStart,
    lineEnd,
  ] = re.exec(url);

  const fileUrl = url.split('#')[0];

  return {
    user,
    repoName,
    fullRepoName: user + '/' + repoName,
    commit,
    filePath,
    lineStart,
    lineEnd,
    fileUrl,
  };
}

function parseContentBlocks(content, metadata) {
  const lines = content.split('\n');

  const segments = [];

  let currSegment = {
    slug: null,
    lineStart: null,
    lineEnd: null,
    content: '',
  };

  lines.forEach((line) => {
    if (line.indexOf(metadata.fileUrl) === -1) {
      currSegment.content += line + '\n';
      return;
    }

    // Close off current segment
    segments.push(currSegment);

    const re = /github\.com\/([^/]+)\/([^/]+)\/blob\/([^/]+)\/([^#]+)#L(\d+)(-L(\d+))?/;

    // This line contains a GitHub URL that points to the same file
    let [
      url,
      user,
      repoName,
      hash,
      path,
      lineStart,
      unused,
      lineEnd,
    ] = re.exec(line);

    if (!lineEnd) {
      lineEnd = lineStart;
    }

    const slug = /id="([^"]+)"/.exec(line)[1];
    const contentWithoutAnchorTag = /<a[^>]+>(.+)<\/a>/.exec(line)[1];

    currSegment = {
      slug,
      lineStart,
      lineEnd,
      content: contentWithoutAnchorTag,
    };
  });

  segments.push(currSegment);

  return segments;
}
<|endoftext|>


<commit_before>const express = require('express')
const debug = require('debug')('app:server')
const path = require('path')
const webpack = require('webpack')
const webpackConfig = require('../config/webpack.config')
const project = require('../config/project.config')
const compress = require('compression')
const fs = require('fs-extra')

import '../config/mongo-connect'

const app = express()

app.set('port', (process.env.PORT || 3000));

//routes
require('./routes.js')(app);

// Apply gzip compression
app.use(compress())

// Serve static assets from ~/public since Webpack is unaware of
// these files. This middleware doesn't need to be enabled outside
// of development since this directory will be copied into ~/dist
// when the application is compiled.
app.use(express.static(project.paths.public()))

  const compiler = webpack(webpackConfig)

// ------------------------------------
// Apply Webpack HMR Middleware
// ------------------------------------
if (project.env === 'development') {

  debug('Enabling webpack dev and HMR middleware')
  app.use(require('webpack-dev-middleware')(compiler, {
    publicPath  : webpackConfig.output.publicPath,
    contentBase : project.paths.client(),
    hot         : true,
    quiet       : project.compiler_quiet,
    noInfo      : project.compiler_quiet,
    lazy        : false,
    stats       : project.compiler_stats
  }))
  app.use(require('webpack-hot-middleware')(compiler, {
    path: '/__webpack_hmr'
  }))

} else {
  debug(
    'Server is being run outside of live development mode, meaning it will ' +
    'only serve the compiled application bundle in ~/dist. Generally you ' +
    'do not need an application server for this and can instead use a web ' +
    'server such as nginx to serve your static files. See the "deployment" ' +
    'section in the README for more information on deployment strategies.'
  )

  // Serving ~/dist by default. Ideally these files should be served by
  // the web server and not the app server, but this helps to demo the
  // server in production.
}
  app.use(express.static(project.paths.dist()))

  // This rewrites all routes requests to the root /index.html file
  // (ignoring file requests). If you want to implement universal
  // rendering, you'll want to remove this middleware.

module.exports = app
<commit_msg>testing Heroky hosting...<commit_after>const express = require('express')
const debug = require('debug')('app:server')
const path = require('path')
const webpack = require('webpack')
const webpackConfig = require('../config/webpack.config')
const project = require('../config/project.config')
const compress = require('compression')
const fs = require('fs-extra')

import '../config/mongo-connect'

const app = express()

app.set('port', (process.env.PORT || 3000));

//routes
require('./routes.js')(app);

// Apply gzip compression
app.use(compress())

// Serve static assets from ~/public since Webpack is unaware of
// these files. This middleware doesn't need to be enabled outside
// of development since this directory will be copied into ~/dist
// when the application is compiled.
app.use(express.static(project.paths.public()))
app.use(express.static(project.paths.dist()))

  const compiler = webpack(webpackConfig)

// ------------------------------------
// Apply Webpack HMR Middleware
// ------------------------------------
if (project.env === 'development') {

  debug('Enabling webpack dev and HMR middleware')
  app.use(require('webpack-dev-middleware')(compiler, {
    publicPath  : webpackConfig.output.publicPath,
    contentBase : project.paths.client(),
    hot         : true,
    quiet       : project.compiler_quiet,
    noInfo      : project.compiler_quiet,
    lazy        : false,
    stats       : project.compiler_stats
  }))
  app.use(require('webpack-hot-middleware')(compiler, {
    path: '/__webpack_hmr'
  }))

} else {
  debug(
    'Server is being run outside of live development mode, meaning it will ' +
    'only serve the compiled application bundle in ~/dist. Generally you ' +
    'do not need an application server for this and can instead use a web ' +
    'server such as nginx to serve your static files. See the "deployment" ' +
    'section in the README for more information on deployment strategies.'
  )

  // Serving ~/dist by default. Ideally these files should be served by
  // the web server and not the app server, but this helps to demo the
  // server in production.
}

  // This rewrites all routes requests to the root /index.html file
  // (ignoring file requests). If you want to implement universal
  // rendering, you'll want to remove this middleware.

module.exports = app
<|endoftext|>


<commit_before>var http = require('http');
var net = require('net');
var os = require('os');
var fs = require('fs');
var util = require('util');

function getLocalIPAddress() {
  var interfaces = os.networkInterfaces();

  var ipAddress = "127.0.0.1";
  for (var interfaceName in interfaces) {
    for (var interfaceKey in interfaces[interfaceName]) {
      var interface = interfaces[interfaceName][interfaceKey];
      if ("IPv4" != interface.family || interface.internal != false)
        continue;
      ipAddress = interface.address;
      break;
    }
  }
  return ipAddress;
}

String.prototype.endsWith = function(str) {
  return this.indexOf(str, this.length - str.length) != -1;
}

function genMsg(command) {
  //var header = jspack.jspack.Pack('! 4s I I b 4b', 'ISCP', 16, command.length, 0x1, 0x0, 0x0, 0x0);
  //console.log("HEADER: " + header);
  var header = "ISCP\x00\x00\x00\x10\x00\x00\x00\x08\x01\x00\x00\x00";
  return header + command + '\r';
}

function writeHTMLHead(response) {
  response.writeHead(200, {"Content-Type": "text/html"});
}

function writeJSONHead(response) {
  response.writeHead(200, {"Content-Type": "application/json"});
}

function LutronOutput(id, integrationId, level) {
  this.type = "output";
  this.id = id;
  this.integrationId = integrationId;
  this.level = level;
}

function LutronDevice(id, integrationId, ledCount) {
  this.type = "device";
  this.id = id;
  this.integrationId = integrationId;
  this.leds = new Array(ledCount);
}

function LutronConnection(devices) {
  this.devices = devices !== undefined ? devices : {};
  // Build a reverse mapping so we can update our model from Lutron response
  // messages which are only in terms of integration ids.
  this.integrationIdToDevice = {};
  for (var deviceName in this.devices) {
    var key = "IntegrationID:" + this.devices[deviceName].integrationId;
    console.log("DEV:  "  + key);
    this.integrationIdToDevice[key] = deviceName;
  }

  this.connect();
}

LutronConnection.prototype.logDevice = function(device) {
  var str = util.format("Device=%s IntegrationId=%d Level=%d",
                        device.id, device.integrationId, device.level);
  console.log(str);
}

LutronConnection.prototype.connect = function() {
  this.client = net.connect(23, "10.1.10.32", function() {
    console.log("Connected to Lutron");
  });
  this.client.on("data", this.handleData.bind(this));
  this.client.on("end", this.handleError.bind(this));
  this.client.on("error", this.handleError.bind(this));
}

LutronConnection.prototype.reconnect = function() {
  setTimeout(this.connect.bind(this), 1000);
}

LutronConnection.prototype.parseData = function(data) {
  var data = data.split("\r\n").shift();
  console.log("Lutron: data = ||" + data + "||");
  var params = data.split(",");
  var prefix = params[0];
  var integrationId = params[1];
  switch (prefix) {
  case "~OUTPUT":
    var key = "IntegrationID:" + integrationId;
    if (key in this.integrationIdToDevice) {
      var deviceName = this.integrationIdToDevice[key];
      this.devices[deviceName].level = params[3];
      this.logDevice(this.devices[deviceName]);
    }
    break;
  case "~DEVICE":
    break;
  default:
    break;
  }
}

LutronConnection.prototype.command = function(id, level) {
  this.client.write("#DEVICE,60,1,3\r\n");
}

LutronConnection.prototype.handleConnected = function() {
  for (var deviceName in this.devices) {
    var device = this.devices[deviceName];
    switch (device.type) {
    case "output":
      this.client.write("?OUTPUT," + [device.integrationId, 1].join(","));
      break;
    case "device":
      for (var i = 0; i < device.leds.length; ++i)
        this.client.write("?DEVICE," + [device.integrationId, 81+i, 9].join(","));
      break;
    }
  }
}

LutronConnection.prototype.handleData = function(data) {
  // Coerce stringiness
  data += "";
  switch (data.trim()) {
  case "login:":
    console.log("Writing username...");
    this.client.write("lutron\r\n", "UTF8");
    break;
  case "password:":
    console.log("Writing password...");
    this.client.write("integration\r\n", "UTF8");
    this.handleConnected();
    break;
  default:
    this.parseData(data);
    break;
  }
}

LutronConnection.prototype.handleError = function() {
  console.log("Lutron: Connection Error");
  this.reconnect();
}

var gDevices = {};
gDevices["FrontPorch_Pendants"] = new LutronOutput("FrontPorch_Pendants", 14, 0);

var lutronConnection = new LutronConnection(gDevices);

http.createServer(function(request, response) {
  if (request.url.endsWith("/lutron/command")) {
    if (request.method == "POST" &&
        request.headers["content-type"] == "application/json") {
      var body = "";
      request.on("data", function(chunk) {
        body += chunk.toString();
      });
      request.on("end", function() {
        var command = JSON.parse(body);
        console.log("ID: " + command.id + " state: " + command.level);
      });
    }
  } else if (request.url.endsWith("/lutron/query")) {
    writeJSONHead(response);
    var queryResult = {};
    queryResult.id = "KitchenLightStatus";
    queryResult.system = "lutron";
    queryResult.type = "query";
    queryResult.level = 75.0;
    response.write(JSON.stringify(queryResult));
    response.end();
  } else if (request.url.endsWith("/lutron")) {
    fs.readFile("../fe/lutron.html", "utf8", function(error, data) {
      if (error)
        return console.log(error);
      writeHTMLHead(response);
      response.write(data);
      response.end();
    });
  } else if (request.url.endsWith("/receiverOn")) {
    response.writeHead(200, {'Content-Type': 'text/plain'})
    var client = net.connect(60128, "10.1.10.10", function () {
      console.log(genMsg("!1PWR01\r"));
      client.write(genMsg("!1PWR01\r"));
    });
    response.end('Turn receiver on\n');
  } else if (request.url.endsWith("/receiverOff")) {
    response.writeHead(200, {'Content-Type': 'text/plain'})
    var client2 = net.connect(60128, "10.1.10.10", function () {
      client2.write(genMsg("!1PWR00\r"));
    });
    response.end('Turn receiver off\n');
  } else {
    response.writeHead(200, {'Content-Type': 'text/plain'})
    response.end('Hello, World!\n');
  }
}).listen(80, getLocalIPAddress());
console.log('Server running @ http://' + getLocalIPAddress() + '/');
<commit_msg>Moar lutron<commit_after>var http = require('http');
var net = require('net');
var os = require('os');
var fs = require('fs');
var util = require('util');

function getLocalIPAddress() {
  var interfaces = os.networkInterfaces();

  var ipAddress = "127.0.0.1";
  for (var interfaceName in interfaces) {
    for (var interfaceKey in interfaces[interfaceName]) {
      var interface = interfaces[interfaceName][interfaceKey];
      if ("IPv4" != interface.family || interface.internal != false)
        continue;
      ipAddress = interface.address;
      break;
    }
  }
  return ipAddress;
}

String.prototype.endsWith = function(str) {
  return this.indexOf(str, this.length - str.length) != -1;
}

function genMsg(command) {
  //var header = jspack.jspack.Pack('! 4s I I b 4b', 'ISCP', 16, command.length, 0x1, 0x0, 0x0, 0x0);
  //console.log("HEADER: " + header);
  var header = "ISCP\x00\x00\x00\x10\x00\x00\x00\x08\x01\x00\x00\x00";
  return header + command + '\r';
}

function writeHTMLHead(response) {
  response.writeHead(200, {"Content-Type": "text/html"});
}

function writeJSONHead(response) {
  response.writeHead(200, {"Content-Type": "application/json"});
}

function LutronOutput(integrationId, level) {
  this.type = "output";
  this.integrationId = integrationId;
  this.level = level;
}

function LutronDevice(integrationId, ledCount) {
  this.type = "device";
  this.integrationId = integrationId;
  this.leds = new Array(ledCount);
}

function integrationIdKey(integrationId) {
  return "IntegrationId:" + integrationId;
}

function LutronConnection(devices) {
  this.devices = devices !== undefined ? devices : {};
  // Build a reverse mapping so we can update our model from Lutron response
  // messages which are only in terms of integration ids.
  this.integrationIdToDevice = {};
  for (var deviceName in this.devices) {
    var key = integrationIdKey(this.devices[deviceName].integrationId);
    this.integrationIdToDevice[key] = deviceName;
  }

  this.connect();
}

LutronConnection.prototype.logDevice = function(device) {
  var key = integrationIdKey(device.integrationId);
  var str = "";
  switch (device.type) {
    case "output":
      str = util.format("Device=%s IntegrationId=%d Level=%d",
                        this.integrationIdToDevice[key], device.integrationId,
                        device.level);
      break;
    case "device":
      var leds = device.leds.join(",");
      str = util.format("Device=%s IntegrationId=%d Leds=%s",
                        this.integrationIdToDevice[key], device.integrationId,
                        leds);
      break;
    default:
      break;
  }
  console.log(str);
}

LutronConnection.prototype.connect = function() {
  this.client = net.connect(23, "10.1.10.32", function() {
    console.log("Connected to Lutron");
  });
  this.client.on("data", this.handleData.bind(this));
  this.client.on("end", this.handleError.bind(this));
  this.client.on("error", this.handleError.bind(this));
}

LutronConnection.prototype.reconnect = function() {
  setTimeout(this.connect.bind(this), 1000);
}

LutronConnection.prototype.getDeviceForIntegrationId = function(integrationId) {
  var key = integrationIdKey(integrationId);
  if (key in this.integrationIdToDevice) {
    var deviceName = this.integrationIdToDevice[key];
    return this.devices[deviceName];
  }
  return null;
}

LutronConnection.prototype.parseData = function(data) {
  var data = data.split("\r\n").shift();
  if (data.substring(0, 5) == "QNET>")
    data = data.substring(5);
  data = data.trim();
  if (data == "")
    return;
  console.log("Lutron: data = |" + data + "|");
  var params = data.split(",");
  var device = this.getDeviceForIntegrationId(params[1]);
  if (device)
    this.logDevice(device);

  switch (params[0]) {
  case "~OUTPUT":
    if (device && (params[2] == 1))
      device.level = params[3];
    break;
  case "~DEVICE":
    if (device) {
      var ledIndex = params[3] - 81;
      if (ledIndex >= 0 && ledIndex < device.leds.length)
        device.leds[ledIndex] = params[4];
    }
    break;
  default:
    break;
  }
}

LutronConnection.prototype.command = function(id, level) {
  this.client.write("#DEVICE,60,1,3\r\n");
}

LutronConnection.prototype.handleConnected = function() {
  for (var deviceName in this.devices) {
    var device = this.devices[deviceName];
    switch (device.type) {
    case "output":
      var command = "?OUTPUT," + [device.integrationId, 1].join(",") + "\r\n";
      this.client.write(command);
      break;
    case "device":
      for (var i = 0; i < device.leds.length; ++i) {
        var command = "?DEVICE," + [device.integrationId, 81+i, 9].join(",") +
            "\r\n";
        this.client.write(command);
      }
      break;
    }
  }
}

LutronConnection.prototype.handleData = function(data) {
  // Coerce stringiness
  data += "";
  switch (data.trim()) {
  case "login:":
    this.client.write("lutron\r\n", "UTF8");
    break;
  case "password:":
    this.client.write("integration\r\n", "UTF8");
    this.handleConnected();
    break;
  default:
    this.parseData(data);
    break;
  }
}

LutronConnection.prototype.handleError = function() {
  console.log("Lutron: Connection Error");
  this.reconnect();
}

var gDevices = {};
gDevices["FrontPorch_Pendants"] = new LutronOutput(14, 0);
gDevices["FrontPorch_Sconces"] = new LutronOutput(15, 0);
gDevices["Kitchen_MudRoom_Switch"] = new LutronDevice(60, 6);
gDevices["MudRoom_Garage_Switch"] = new LutronDevice(49, 6);

var lutronConnection = new LutronConnection(gDevices);

http.createServer(function(request, response) {
  if (request.url.endsWith("/lutron/command")) {
    if (request.method == "POST" &&
        request.headers["content-type"] == "application/json") {
      var body = "";
      request.on("data", function(chunk) {
        body += chunk.toString();
      });
      request.on("end", function() {
        var command = JSON.parse(body);
        console.log("ID: " + command.id + " state: " + command.level);
      });
    }
  } else if (request.url.endsWith("/lutron/query")) {
    writeJSONHead(response);
    var queryResult = {};
    queryResult.id = "KitchenLightStatus";
    queryResult.system = "lutron";
    queryResult.type = "query";
    queryResult.level = 75.0;
    response.write(JSON.stringify(queryResult));
    response.end();
  } else if (request.url.endsWith("/lutron")) {
    fs.readFile("../fe/lutron.html", "utf8", function(error, data) {
      if (error)
        return console.log(error);
      writeHTMLHead(response);
      response.write(data);
      response.end();
    });
  } else if (request.url.endsWith("/receiverOn")) {
    response.writeHead(200, {'Content-Type': 'text/plain'})
    var client = net.connect(60128, "10.1.10.10", function () {
      console.log(genMsg("!1PWR01\r"));
      client.write(genMsg("!1PWR01\r"));
    });
    response.end('Turn receiver on\n');
  } else if (request.url.endsWith("/receiverOff")) {
    response.writeHead(200, {'Content-Type': 'text/plain'})
    var client2 = net.connect(60128, "10.1.10.10", function () {
      client2.write(genMsg("!1PWR00\r"));
    });
    response.end('Turn receiver off\n');
  } else {
    response.writeHead(200, {'Content-Type': 'text/plain'})
    response.end('Hello, World!\n');
  }
}).listen(80, getLocalIPAddress());
console.log('Server running @ http://' + getLocalIPAddress() + '/');
<|endoftext|>


<commit_before>/**
 * Watchdog.
 * @constructor
 */

function watchdog(){

    this.request_timeout = 30000;
    this.event_active_id = 0;
    this.reboot_after_ok = false;
}

watchdog.prototype.run = function(){

    var self = this;

    window.setInterval(function(){
        self.send_request();
    }, this.request_timeout);
}

watchdog.prototype.send_request = function(){

    var self = this;

    var cur_play_type = 0

    if (!stb.player.pause.on){
        cur_play_type = stb.get_current_place();
    }

    _debug('cur_play_type', cur_play_type);

    stb.load(
        {
            "type"            : "watchdog",
            "action"          : "get_events",
            "cur_play_type"   : cur_play_type,
            "event_active_id" : this.event_active_id
        },

        function(result){
            try{
                self.parse_result(result.data);
            }catch(e){
                _debug(e);
            }
        }
    );
}

watchdog.prototype.parse_result = function(data){

    _debug('watchdog.parse_result', data);

    module.curweather.set(data.cur_weather);

    if (typeof(data.id) != 'undefined'){

        _debug('data.id', data.id);

        switch(data.event){
            case 'reboot':
            {
                stb.ExecAction('reboot');
                break
            }
            case 'send_msg':
            {
                this.event_active_id = data.id

                var self = this;

                stb.msg.set_callback(
                    function(){
                        self.send_confirm();
                    });

                stb.msg.show(data.msg);

                this.reboot_after_ok = data.reboot_after_ok;

                break
            }
            case 'update_channels':
            {
                stb.load_channels();
                stb.load_fav_channels();
                stb.load_fav_itv();
                break
            }
            case 'update_subscription':
            {
                if (stb.cur_off_on){
                    stb.ExecAction('reboot');
                }else{
                    stb.load_channels();
                    stb.load_fav_channels();
                    stb.load_fav_itv();
                }
                break
            }
            case 'cut_off':
            {
                stb.cut_off();
                break
            }
            case 'cut_on':
            {
                stb.cut_on();
                break
            }
            case 'mount_all_storages':
            {
                stb.mount_home_dir(data.msg);
                break
            }
            case 'show_menu': // reset paused
            {
                keydown_observer.emulate_key(key.MENU);
                break
            }
            case 'play_channel':
            {
                keydown_observer.emulate_key(key.MENU);

                stb.user.fav_itv_on = 0;

                var ch_idx = stb.player.channels.getIdxByNumber(parseInt(data.msg));

                stb.player.ch_idx = ch_idx || 0;
                stb.player.cur_media_item = stb.player.channels[stb.player.ch_idx];
                stb.player.cur_tv_item = stb.player.channels[stb.player.ch_idx];

                keydown_observer.emulate_key(key.EXIT);
                break
            }
        }
    }
}

watchdog.prototype.send_confirm = function(){

    stb.load(
    {
        "type"   : "watchdog",
        "action" : "confirm_event",
        "event_active_id" : this.event_active_id
    },

    function(result){
        _debug(result);
    });

    this.event_active_id = 0;
}<commit_msg>"Modify parse_result"<commit_after>/**
 * Watchdog.
 * @constructor
 */

function watchdog(){

    this.request_timeout = 30000;
    this.event_active_id = 0;
    this.reboot_after_ok = false;
}

watchdog.prototype.run = function(){

    var self = this;

    window.setInterval(function(){
        self.send_request();
    }, this.request_timeout);
}

watchdog.prototype.send_request = function(){

    var self = this;

    var cur_play_type = 0

    if (!stb.player.pause.on){
        cur_play_type = stb.get_current_place();
    }

    _debug('cur_play_type', cur_play_type);

    stb.load(
        {
            "type"            : "watchdog",
            "action"          : "get_events",
            "cur_play_type"   : cur_play_type,
            "event_active_id" : this.event_active_id
        },

        function(result){
            try{
                self.parse_result(result.data);
            }catch(e){
                _debug(e);
            }
        }
    );
}

watchdog.prototype.parse_result = function(data){

    _debug('watchdog.parse_result', data);

    module.curweather && module.curweather.set && module.curweather.set(data.cur_weather);

    if (typeof(data.id) != 'undefined'){

        _debug('data.id', data.id);

        switch(data.event){
            case 'reboot':
            {
                stb.ExecAction('reboot');
                break
            }
            case 'send_msg':
            {
                this.event_active_id = data.id

                var self = this;

                stb.msg.set_callback(
                    function(){
                        self.send_confirm();
                    });

                stb.msg.show(data.msg);

                this.reboot_after_ok = data.reboot_after_ok;

                break
            }
            case 'update_channels':
            {
                stb.load_channels();
                stb.load_fav_channels();
                stb.load_fav_itv();
                break
            }
            case 'update_subscription':
            {
                if (stb.cur_off_on){
                    stb.ExecAction('reboot');
                }else{
                    stb.load_channels();
                    stb.load_fav_channels();
                    stb.load_fav_itv();
                }
                break
            }
            case 'cut_off':
            {
                stb.cut_off();
                break
            }
            case 'cut_on':
            {
                stb.cut_on();
                break
            }
            case 'mount_all_storages':
            {
                stb.mount_home_dir(data.msg);
                break
            }
            case 'show_menu': // reset paused
            {
                keydown_observer.emulate_key(key.MENU);
                break
            }
            case 'play_channel':
            {
                keydown_observer.emulate_key(key.MENU);

                stb.user.fav_itv_on = 0;

                var ch_idx = stb.player.channels.getIdxByNumber(parseInt(data.msg));

                stb.player.ch_idx = ch_idx || 0;
                stb.player.cur_media_item = stb.player.channels[stb.player.ch_idx];
                stb.player.cur_tv_item = stb.player.channels[stb.player.ch_idx];

                keydown_observer.emulate_key(key.EXIT);
                break
            }
        }
    }
}

watchdog.prototype.send_confirm = function(){

    stb.load(
    {
        "type"   : "watchdog",
        "action" : "confirm_event",
        "event_active_id" : this.event_active_id
    },

    function(result){
        _debug(result);
    });

    this.event_active_id = 0;
}<|endoftext|>


<commit_before>/* global math */
// Variables
var buttons = ['7', '8', '9', '+',
  '4', '5', '6', '-',
  '1', '2', '3', '*',
  '0', '.', '=', '/',
  'sin', 'cos', '^', '√',
  'tan', 'cot', '(', ')',
  'clr', '<-'
];

var lastNum = 'new';
var answer;

function renderContent() {
  // Create base elements for the page
  var container = createElement('div', '', {
    id: 'container'
  });
  var header = createElement('div', '', {
    id: 'header'
  });
  var nav = createElement('div', '', {
    id: 'nav'
  });
  var main = createElement('div', '', {
    id: 'main'
  });
  var aside = createElement('div', '', {
    id: 'aside'
  });
  var footer = createElement('div', '', {
    id: 'footer'
  });

  // Append main elements to container
  container.appendChild(header);
  container.appendChild(nav);
  container.appendChild(main);
  container.appendChild(aside);
  container.appendChild(footer);

  // Insert content
  header.appendChild(createElement('h1', 'Calculator', {
    className: 'title'
  }));
  main.appendChild(calculator());
  footer.appendChild(themeButton());
  footer.appendChild(about());

  // Add container to page
  document.body.appendChild(container);
  //document.getElementById('cal-box').focus();
}

function createElement(type, textContent, options) {
  var elem = document.createElement(type);
  elem.textContent = textContent;
  if (options) {
    for (var option in options) {
      elem[option] = options[option];
    }
  }
  return elem;
}

function calculator() {
  var calculatorWrap = createElement('div', '', {
    id: 'calculator'
  }); // Add calculator wrapper div
  calculatorWrap.appendChild(createElement('input', '', {
    className: 'cal-box',
    id: 'cal-box'
  })); // Add input box
  buttons.forEach(function(buttonContent) {
    var button = createElement('button', buttonContent, {
      className: 'cal-button',
      id: buttonContent
    });
    button.addEventListener('click', handleButton, false);
    calculatorWrap.appendChild(button);
  }); // Add calculator buttons
  return calculatorWrap;
}

function themeButton() {
  var themeWrapper = createElement('div', '');
  var toggle = createElement('button', 'Toggle Theme', {
    className: 'toggle',
    id: 'toggle'
  });
  toggle.addEventListener('click', switchTheme, false);
  themeWrapper.appendChild(toggle);
  return themeWrapper;
}

function switchTheme() {
  theme = document.body.className;
  if (theme == 'theme-light') {
    document.body.className = 'theme-dark';
  } else {
    document.body.className = 'theme-light';
  }
}

function about() {
  var about = createElement('div','');

  var math = createElement('p', 'Solutions calculated using ');
  math.appendChild(createElement('a', 'math.js', { href: 'http://mathjs.org/'} ));
  about.appendChild(math);

  var creator = createElement('p', 'Created by ');
  creator.appendChild(createElement('a', '@keawade', { href: 'https://github.com/keawade' }));
  about.appendChild(creator);

  return about;
}

// Need to rewrite keypress to be more efficient

// If Enter/Return is pressed, click '=' to evaluate
document.addEventListener('keypress', function(key) {
  console.log(key.keyCode);
  var keyString = String.fromCharCode(key.charCode);
  if (key.keyCode == 13) {
    document.getElementById('=').click();
  } else if (/[0-9]|[-/*+=.^()]/.test(keyString)) {
    document.getElementById(keyString).click();
  } else if (key.keyCode == 8) {
    var box = document.getElementById('cal-box')
    if (box === document.activeElement) {
      //
    } else {
      if (box.value == '') {
        // Do nothing
      } else {
        document.getElementById('<-').click();
      }
    }
  } // keyCode 46 is Delete
}, false);

function handleButton(event) {
  var box = document.getElementById('cal-box');

  if (!(box === document.activeElement)) {
    // Solve
    if (event.target.id == '=') {
      answer = math.eval(box.value);
      if (!isNaN(answer)) {
        box.value = answer;
        lastNum = answer;
      }
    // Clear
    } else if (event.target.id == 'clr') {
      box.value = '';
      lastNum = 'new';
    // Backspace
    } else if (event.target.id == '<-') {
      box.value = box.value.substring(0, box.value.length - 1);
      lastNum = box.value.charAt(box.value.length - 1);
    // Numbers
    } else if (/[0-9]/.test(event.target.id)) {
      if (!(/[)]/.test(lastNum))) {
        box.value = box.value + event.target.id;
        lastNum = event.target.id;
      }
    // Symbols
    } else if (/[-/*+.^()]/.test(event.target.id)) {
      if(!(/[new]|[-/*+.^()]/.test(lastNum))){
        box.value = box.value + event.target.id;
        lastNum = event.target.id;
      }
    // Trig Functions
    } else if (/[sin]|[cos]|[tan]|[cot]/.test(event.target.id)) {
      if (lastNum == answer) {
        box.value = event.target.id + '(';
      } else if (isNaN(lastNum)) {
        box.value = box.value + event.target.id + '('
        lastNum = '(';
      }
    }
    this.blur();
  }
}
/*

if(!isNaN(event.target.id)) {
  // If last operation was math.eval then start new string
  if(lastNum == 'new') {
    box.value = '';
  }
  // Append new value
  box.value = box.value + event.target.id;
  lastNum = event.target.id;
// If clicked button is not a number
} else {
  // If clicked button is '='
  if(event.target.id == '=') {
    // Evaluate current string
    answer = math.eval(box.value)
    if(isNaN(answer)){
      //
    } else {
      box.value = answer;
    }
    // Note that the last operation was an eval
    lastNum = 'new';
  // If clicked button is an operation
  } else {
    // If the last button clicked was a number, allow the operator to be appended
    if(!isNaN(lastNum)) {
      box.value = box.value + event.target.id;
      lastNum = event.target.id;
    }
  }
}
// Remove keyboard focus on button
this.blur();
} if(event.target.id == '=') {
// Evaluate current string
answer = math.eval(box.value)
if(isNaN(answer)){
  //
} else {
  box.value = answer;
}
// Note that the last operation was an eval
lastNum = 'new';
*/

renderContent();
<commit_msg>Fixed sqrt<commit_after>/* global math */
// Variables
var buttons = ['7', '8', '9', '+',
  '4', '5', '6', '-',
  '1', '2', '3', '*',
  '0', '.', '=', '/',
  'sin', 'cos', '^', 'sqrt',
  'tan', 'cot', '(', ')',
  'clr', '<-'
];

var lastNum = 'new';
var answer;

function renderContent() {
  // Create base elements for the page
  var container = createElement('div', '', {
    id: 'container'
  });
  var header = createElement('div', '', {
    id: 'header'
  });
  var nav = createElement('div', '', {
    id: 'nav'
  });
  var main = createElement('div', '', {
    id: 'main'
  });
  var aside = createElement('div', '', {
    id: 'aside'
  });
  var footer = createElement('div', '', {
    id: 'footer'
  });

  // Append main elements to container
  container.appendChild(header);
  container.appendChild(nav);
  container.appendChild(main);
  container.appendChild(aside);
  container.appendChild(footer);

  // Insert content
  header.appendChild(createElement('h1', 'Calculator', {
    className: 'title'
  }));
  main.appendChild(calculator());
  footer.appendChild(themeButton());
  footer.appendChild(about());

  // Add container to page
  document.body.appendChild(container);
  //document.getElementById('cal-box').focus();
}

function createElement(type, textContent, options) {
  var elem = document.createElement(type);
  elem.textContent = textContent;
  if (options) {
    for (var option in options) {
      elem[option] = options[option];
    }
  }
  return elem;
}

function calculator() {
  var calculatorWrap = createElement('div', '', {
    id: 'calculator'
  }); // Add calculator wrapper div
  calculatorWrap.appendChild(createElement('input', '', {
    className: 'cal-box',
    id: 'cal-box'
  })); // Add input box
  buttons.forEach(function(buttonContent) {
    var button = createElement('button', buttonContent, {
      className: 'cal-button',
      id: buttonContent
    });
    button.addEventListener('click', handleButton, false);
    calculatorWrap.appendChild(button);
  }); // Add calculator buttons
  return calculatorWrap;
}

function themeButton() {
  var themeWrapper = createElement('div', '');
  var toggle = createElement('button', 'Toggle Theme', {
    className: 'toggle',
    id: 'toggle'
  });
  toggle.addEventListener('click', switchTheme, false);
  themeWrapper.appendChild(toggle);
  return themeWrapper;
}

function switchTheme() {
  theme = document.body.className;
  if (theme == 'theme-light') {
    document.body.className = 'theme-dark';
  } else {
    document.body.className = 'theme-light';
  }
}

function about() {
  var about = createElement('div','');

  var math = createElement('p', 'Solutions calculated using ');
  math.appendChild(createElement('a', 'math.js', { href: 'http://mathjs.org/'} ));
  about.appendChild(math);

  var creator = createElement('p', 'Created by ');
  creator.appendChild(createElement('a', '@keawade', { href: 'https://github.com/keawade' }));
  about.appendChild(creator);

  return about;
}

// Need to rewrite keypress to be more efficient

// If Enter/Return is pressed, click '=' to evaluate
document.addEventListener('keypress', function(key) {
  console.log(key.keyCode);
  var keyString = String.fromCharCode(key.charCode);
  if (key.keyCode == 13) {
    document.getElementById('=').click();
  } else if (/[0-9]|[-/*+=.^()]/.test(keyString)) {
    document.getElementById(keyString).click();
  } else if (key.keyCode == 8) {
    var box = document.getElementById('cal-box')
    if (box === document.activeElement) {
      //
    } else {
      if (box.value == '') {
        // Do nothing
      } else {
        document.getElementById('<-').click();
      }
    }
  } // keyCode 46 is Delete
}, false);

function handleButton(event) {
  var box = document.getElementById('cal-box');

  if (!(box === document.activeElement)) {
    // Solve
    if (event.target.id == '=') {
      answer = math.eval(box.value);
      if (!isNaN(answer)) {
        box.value = answer;
        lastNum = answer;
      }
    // Clear
    } else if (event.target.id == 'clr') {
      box.value = '';
      lastNum = 'new';
    // Backspace
    } else if (event.target.id == '<-') {
      box.value = box.value.substring(0, box.value.length - 1);
      lastNum = box.value.charAt(box.value.length - 1);
    // Numbers
    } else if (/[0-9]/.test(event.target.id)) {
      if (!(/[)]/.test(lastNum))) {
        box.value = box.value + event.target.id;
        lastNum = event.target.id;
      }
    // Symbols
    } else if (/[-/*+.^()]/.test(event.target.id)) {
      if(!(/[new]|[-/*+.^()]/.test(lastNum))){
        box.value = box.value + event.target.id;
        lastNum = event.target.id;
      }
    // Trig Functions
  } else if (/[sin]|[cos]|[tan]|[cot]|[sqrt]/.test(event.target.id)) {
      if (lastNum == answer) {
        box.value = event.target.id + '(';
      } else if (isNaN(lastNum)) {
        box.value = box.value + event.target.id + '('
        lastNum = '(';
      }
    }
    this.blur();
  }
}
/*

if(!isNaN(event.target.id)) {
  // If last operation was math.eval then start new string
  if(lastNum == 'new') {
    box.value = '';
  }
  // Append new value
  box.value = box.value + event.target.id;
  lastNum = event.target.id;
// If clicked button is not a number
} else {
  // If clicked button is '='
  if(event.target.id == '=') {
    // Evaluate current string
    answer = math.eval(box.value)
    if(isNaN(answer)){
      //
    } else {
      box.value = answer;
    }
    // Note that the last operation was an eval
    lastNum = 'new';
  // If clicked button is an operation
  } else {
    // If the last button clicked was a number, allow the operator to be appended
    if(!isNaN(lastNum)) {
      box.value = box.value + event.target.id;
      lastNum = event.target.id;
    }
  }
}
// Remove keyboard focus on button
this.blur();
} if(event.target.id == '=') {
// Evaluate current string
answer = math.eval(box.value)
if(isNaN(answer)){
  //
} else {
  box.value = answer;
}
// Note that the last operation was an eval
lastNum = 'new';
*/

renderContent();
<|endoftext|>


<commit_before>var Ξ=[],//stack
		//I/O functions
		ô=i=>document.getElementById('o').value+=i!=[]._?i:(Ξ.shift(),Ξ.join`\n`),//output
		ℹ=i=>[i=i!=[]._?document.getElementById("c").value[i]:document.getElementById("c").value,Ξ.push(i)][0],//source

		//stack functions
		ᵖ=(i=0)=>{Array.prototype.slice.call(arguments).map(x=>Ξ.push(x))},
		ᵍ=i=>i!=[]._?Ξ[i<0?Ξ.length+i:i]:Ξ[Ξ.length-1],
		ʳ=(i=Ξ.length-1)=>Ξ.splice(i),
		ᶜ=i=>Ξ=[],

		//super-basic aliasing
		ī=Infinity,
		ü=[]._,
		М=math,
		Ϛ=String,
		Ѧ=Array,
		П=Number,
		Ø=Object,
		Ĵ=JSON,
		ɼ=RegExp,
		Ɗ=Date,
		ɘ=i=>LZString.decompress(i);
[Ϛ,Ѧ,П,Ø,ɼ,Ɗ].map(v=>Object.getOwnPropertyNames(v).map((x,y)=>v.prototype[String.fromCharCode(y+248)]=v.prototype[x]));
[М,Ϛ,Ѧ,П,Ø,Ĵ,ɼ,Ɗ].map(v=>Object.getOwnPropertyNames(v).map((x,y)=>v[String.fromCharCode(y+248)]=v[x]));
var Σ=(c,asdf=0)=>{
	//syntax from esmin to es6
	c=c
		.replace(/([ᵖᵍʳᶜôℹΣɘϚѦПØɼƊ])(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?|[A-Za-z]+)/g,'$1($2)')
		.replace(/([ᵖᵍʳᶜôℹΣɘϚѦПØɼƊ])(.+)⦆/g,'$1($2)')
		.replace(/ï(\d+)/g,'ï[$1]')
		.replace(/⬮/g,'()')
		.replace(/⬯/g,'(``)')
		.replace(/⇏/g,'(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z)=>')
		.replace(/↛/g,'=(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z)=>')
		.replace(/↪/g,'($,_,ã)=>')
		.replace(/⤤/g,'=($,_,ã)=>')
		.replace(/→/g,'=>')
		.replace(/“/g,'(`')
		.replace(/”/g,'`)')
		.replace(/‘/g,'(\\`')
		.replace(/’/g,'\\`)')
		.replace(/⸨/g,'((')
		.replace(/⸩/g,'))')
		.replace(/⎛/g,'(/')
		.replace(/⎞/g,'/)')
		.replace(/⦃/g,'${')
		.replace(/…/g,'...')
		.replace(/˖/g,'+=')
		.replace(/⧺/g,'++')
		.replace(/˗/g,'-=')
		.replace(/‡/g,'--')
		.replace(/×/g,'*=')
		.replace(/÷/g,'/=')
		.replace(/٪/g,'%=')
		.replace(/¡/g,'!!')
		.replace(/≔/g,'==')
		.replace(/≠/g,'!=')
		.replace(/≤/g,'<=')
		.replace(/≥/g,'>=')
		.replace(/⅋/g,'&&')
		.replace(/ǁ/g,'||')
		.replace(/↺/g,'for(')
		.replace(/Ʀ/g,'return ')
		.replace(/ŋ/g,'new ')
		.replace(/\((.+)\)²/g,'Math.pow($1,2)')
		.replace(/\((.+)\)³/g,'Math.pow($1,3)')
		.replace(/(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)²/g,'Math.pow($1,2)')
		.replace(/(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)³/g,'Math.pow($1,3)')
		.replace(/\((.+)\)ⁿ\((.+)\)/g,'Math.pow($1,$2)')
		.replace(/(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)ⁿ\((.+)\)/g,'Math.pow($1,$2)')
		.replace(/(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)ⁿ(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)/g,'Math.pow($1,$2)')
		.replace(/\((.+)\)ⁿ(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)/g,'Math.pow($1,$2)')
		.replace(/√\((.+)\)/g,'Math.sqrt($1)')
		.replace(/√(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)/g,'Math.sqrt($1)')
		.replace(/∛\((.+)\)/g,'Math.cbrt($1)')
		.replace(/∛(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)/g,'Math.cbrt($1)')
		.replace(/ɘ\(`(.+)`\)/g,(x,y)=>`\`${ɘ(y)}\``)
		.replace(/½/g,'0.5')
		.replace(/¼/g,'0.25')
		.replace(/¾/g,'0.75')
		.replace(/⅐/g,'(1/7)')
		.replace(/⅑/g,'(1/9)')
		.replace(/⅒/g,'0.1')
		.replace(/⅓/g,'(1/3)')
		.replace(/⅔/g,'(2/3)')
		.replace(/⅕/g,'0.2')
		.replace(/⅖/g,'0.4')
		.replace(/⅗/g,'0.6')
		.replace(/⅘/g,'0.8')
		.replace(/⅙/g,'(1/6)')
		.replace(/⅚/g,'(5/6)')
		.replace(/⅛/g,'(1/8)')
		.replace(/⅜/g,'(3/8)')
		.replace(/⅝/g,'(5/8)')
		.replace(/⅞/g,'(7/8)')
	;
	if(asdf==1e4&&!c.match(/ô/g))c+=';ô()';console.log(c);eval(c)
}

onload=function(){document.getElementById('c').value=decodeURIComponent((/code=(.+)/.exec(location.search)||[,""])[1]);document.getElementById('i').value=decodeURIComponent((/input=([^&]+)/.exec(location.search)||[,""])[1]);document.getElementById('e').checked=eval(decodeURIComponent((/eval=([^&]+)/.exec(location.search)||[,""])[1]))}<commit_msg>use multiline flag<commit_after>var Ξ=[],//stack
		//I/O functions
		ô=i=>document.getElementById('o').value+=i!=[]._?i:(Ξ.shift(),Ξ.join`\n`),//output
		ℹ=i=>[i=i!=[]._?document.getElementById("c").value[i]:document.getElementById("c").value,Ξ.push(i)][0],//source

		//stack functions
		ᵖ=(i=0)=>{Array.prototype.slice.call(arguments).map(x=>Ξ.push(x))},
		ᵍ=i=>i!=[]._?Ξ[i<0?Ξ.length+i:i]:Ξ[Ξ.length-1],
		ʳ=(i=Ξ.length-1)=>Ξ.splice(i),
		ᶜ=i=>Ξ=[],

		//super-basic aliasing
		ī=Infinity,
		ü=[]._,
		М=math,
		Ϛ=String,
		Ѧ=Array,
		П=Number,
		Ø=Object,
		Ĵ=JSON,
		ɼ=RegExp,
		Ɗ=Date,
		ɘ=i=>LZString.decompress(i);
[Ϛ,Ѧ,П,Ø,ɼ,Ɗ].map(v=>Object.getOwnPropertyNames(v).map((x,y)=>v.prototype[String.fromCharCode(y+248)]=v.prototype[x]));
[М,Ϛ,Ѧ,П,Ø,Ĵ,ɼ,Ɗ].map(v=>Object.getOwnPropertyNames(v).map((x,y)=>v[String.fromCharCode(y+248)]=v[x]));
var Σ=(c,asdf=0)=>{
	//syntax from esmin to es6
	c=c
		.replace(/([ᵖᵍʳᶜôℹΣɘϚѦПØɼƊ])(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?|[A-Za-z]+)/gm,'$1($2)')
		.replace(/([ᵖᵍʳᶜôℹΣɘϚѦПØɼƊ])(.+)⦆/gm,'$1($2)')
		.replace(/ï(\d+)/gm,'ï[$1]')
		.replace(/⬮/gm,'()')
		.replace(/⬯/gm,'(``)')
		.replace(/⇏/gm,'(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z)=>')
		.replace(/↛/gm,'=(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z)=>')
		.replace(/↪/gm,'($,_,ã)=>')
		.replace(/⤤/gm,'=($,_,ã)=>')
		.replace(/→/gm,'=>')
		.replace(/“/gm,'(`')
		.replace(/”/gm,'`)')
		.replace(/‘/gm,'(\\`')
		.replace(/’/gm,'\\`)')
		.replace(/⸨/gm,'((')
		.replace(/⸩/gm,'))')
		.replace(/⎛/gm,'(/')
		.replace(/⎞/gm,'/)')
		.replace(/⦃/gm,'${')
		.replace(/…/gm,'...')
		.replace(/˖/gm,'+=')
		.replace(/⧺/gm,'++')
		.replace(/˗/gm,'-=')
		.replace(/‡/gm,'--')
		.replace(/×/gm,'*=')
		.replace(/÷/gm,'/=')
		.replace(/٪/gm,'%=')
		.replace(/¡/gm,'!!')
		.replace(/≔/gm,'==')
		.replace(/≠/gm,'!=')
		.replace(/≤/gm,'<=')
		.replace(/≥/gm,'>=')
		.replace(/⅋/gm,'&&')
		.replace(/ǁ/gm,'||')
		.replace(/↺/gm,'for(')
		.replace(/Ʀ/gm,'return ')
		.replace(/ŋ/gm,'new ')
		.replace(/\((.+)\)²/gm,'Math.pow($1,2)')
		.replace(/\((.+)\)³/gm,'Math.pow($1,3)')
		.replace(/(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)²/gm,'Math.pow($1,2)')
		.replace(/(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)³/gm,'Math.pow($1,3)')
		.replace(/\((.+)\)ⁿ\((.+)\)/gm,'Math.pow($1,$2)')
		.replace(/(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)ⁿ\((.+)\)/gm,'Math.pow($1,$2)')
		.replace(/(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)ⁿ(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)/gm,'Math.pow($1,$2)')
		.replace(/\((.+)\)ⁿ(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)/gm,'Math.pow($1,$2)')
		.replace(/√\((.+)\)/gm,'Math.sqrt($1)')
		.replace(/√(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)/gm,'Math.sqrt($1)')
		.replace(/∛\((.+)\)/gm,'Math.cbrt($1)')
		.replace(/∛(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)/gm,'Math.cbrt($1)')
		.replace(/ɘ\(`(.+)`\)/gm,(x,y)=>`\`${ɘ(y)}\``)
		.replace(/½/gm,'0.5')
		.replace(/¼/gm,'0.25')
		.replace(/¾/gm,'0.75')
		.replace(/⅐/gm,'(1/7)')
		.replace(/⅑/gm,'(1/9)')
		.replace(/⅒/gm,'0.1')
		.replace(/⅓/gm,'(1/3)')
		.replace(/⅔/gm,'(2/3)')
		.replace(/⅕/gm,'0.2')
		.replace(/⅖/gm,'0.4')
		.replace(/⅗/gm,'0.6')
		.replace(/⅘/gm,'0.8')
		.replace(/⅙/gm,'(1/6)')
		.replace(/⅚/gm,'(5/6)')
		.replace(/⅛/gm,'(1/8)')
		.replace(/⅜/gm,'(3/8)')
		.replace(/⅝/gm,'(5/8)')
		.replace(/⅞/gm,'(7/8)')
	;
	if(asdf==1e4&&!c.match(/ô/gm))c+=';ô()';console.log(c);eval(c)
}

onload=function(){document.getElementById('c').value=decodeURIComponent((/code=(.+)/.exec(location.search)||[,""])[1]);document.getElementById('i').value=decodeURIComponent((/input=([^&]+)/.exec(location.search)||[,""])[1]);document.getElementById('e').checked=eval(decodeURIComponent((/eval=([^&]+)/.exec(location.search)||[,""])[1]))}<|endoftext|>


<commit_before>/*
	Scraper app. Only runs as child forked process.
*/

var	util 	= require('util'),
	http 	= require('http'),
	url 	= require('url'),
	mongoose= require('mongoose'),
	argv 	= require('named-argv'),
	jsdom	= require('jsdom');

mongoose.connect('mongodb://localhost/search_for_404_v4');

var scrapeHost = "", fullUrl = "", link, auth = {},
	Links404Model, LinksCheckModel, LinksGrabbedModel,
	requestsRunning = 0, requestsPerSecond = 0, maxThreads = 20;

process.on("message", function(data)
{
	switch (data.action)
	{
		case "setAuth":
			auth.user = data.auth_user;
			auth.pass = data.auth_pass;
			break;

		case "setMaxThreads":
			maxThreads = data.max_threads;
			break;

		case "start":
			fullUrl	   = data.url;
			scrapeHost = url.parse(data.url).host;

			Links404Model 	  = mongoose.model("links_404_" + scrapeHost, new mongoose.Schema({url:String, source:String}));
			LinksCheckModel   = mongoose.model("links_check_" + scrapeHost, new mongoose.Schema({ url: { type: String, index: { unique: true } }, source: String, from_redirect: {type: Boolean, default: false} }));
			LinksGrabbedModel = mongoose.model("links_grabbed_" + scrapeHost, new mongoose.Schema({url: { type: String, index: { unique: true }}, source: String }));

			if (data.clean) {
				Links404Model.find().remove();
				LinksCheckModel.find().remove();
				LinksGrabbedModel.find().remove();
			}

			(new LinksCheckModel({url: argv.opts.url})).save();
			util.log("Start scraping "+ scrapeHost +"...");

			setInterval(sendGeneralStats, 3000);
			setInterval(checkUrl, 10);
			break;
	}
})

function sendGeneralStats()
{
	LinksGrabbedModel.count({}, function(err, count_grabbed)
	{
		LinksCheckModel.count({}, function(err, count_check)
		{
			process.send(
			{
				message: 'general-stats',
				memory: bytesToSize(process.memoryUsage().rss),
				requests: requestsRunning,
				grabbed: count_grabbed,
				tocheck: count_check,
				max_threads: maxThreads,
				host: scrapeHost
			});
		});
	});
}

// setInterval(function()
// {
// 	io.sockets.emit("rps", {rps: requestsPerSecond});
// 	requestsPerSecond = 0;
// },
// 1000)

function checkUrl()
{
	LinksCheckModel.findOne({}, function(err, doc)
	{
		if( doc==null )
			return;

		if( requestsRunning > maxThreads )
			return;

		var source_link = doc.source;
		link = doc.url;
		doc.remove();

		LinksGrabbedModel.count({url: link}, function(err, count)
		{
			if( count == 0 ) {
				(new LinksGrabbedModel({url: link, source: source_link})).save();
			}
		});

		var urlObj = url.parse(link);
		requestsRunning++;

		process.send({message: "checking", url: urlObj.protocol+"//"+urlObj.host+urlObj.path})

		make_request(urlObj.protocol, urlObj.host, urlObj.path, function(statusCode, body, reqUrl, headers)
		{
			requestsPerSecond++;
			requestsRunning--;

			if( statusCode == 404 ) {
				LinksGrabbedModel.findOne({url: reqUrl}, function(err, doc) {
					if ( doc != null ) {
						(new Links404Model({url:reqUrl, source:doc.source})).save();
						process.send({message: "got-404", url: reqUrl, source: doc.source})
					}
				});

				return;
			}
			else if ( [301,302,303].indexOf(statusCode) > -1 ) {
				var redir_location = url.parse(headers.location);
				if (redir_location.host == undefined) {
					redir_location.host = url.parse(reqUrl).host;
				}

				(new LinksCheckModel({url:redir_location.href, source: reqUrl, from_redirect: true})).save();
				return;
			}

			jsdom.env({
				html: body,
				scripts: ["http://code.jquery.com/jquery.js"],
				done: function (errors, window)
				{
					if (window == undefined || window.$ == undefined) {
						if (window != undefined)
							window.close();
						return;
					}

					var $ = window.$;
					$("a").each(function()
					{
						var lnk = $(this).attr("href");

						if ((lnk = check_link(lnk)) == false)
							return;

						(function(add_link, source_link) {
							LinksGrabbedModel.findOne({url: add_link}, function(err, doc)
							{
								if( doc==null || doc.length==0 ) {
									LinksCheckModel.findOne({url: add_link}, function(err, doc)
									{
										if( doc==null || doc.length==0 ) {
											(new LinksCheckModel({url:add_link, source: source_link})).save();
										}
									});
								}
							});
						})(lnk, reqUrl);
					});

					window.close();
				}
			});
		});

		urlObj = null;
	});
};

function check_link(lnk)
{
	if( lnk.indexOf("/")==0 )
		lnk = "http://" + scrapeHost + lnk;

	if( lnk==undefined || ["#", ""].indexOf(lnk)!=-1 || (lnk.indexOf("http://" + scrapeHost)!=0 && lnk.indexOf("https://"+scrapeHost)!=0) ) {
		return false;
	}

	return lnk;
}

function make_request(protocol, host, path, callback)
{
	var opts = {
		host: host,
		port: 80,
		path: path,
		method: "GET"
	};

	if( Object.keys(auth).length )
		opts.auth = [auth.user, auth.pass].join(":");

	var req = http.request(opts, function(res)
	{
		var data = "";

		res.setEncoding('utf8');
		res.on('data', function (chunk) {
			if(res.statusCode==200)
				data += chunk;
		});

		res.on('end', function(){
			callback(res.statusCode, data, (protocol+"//"+host+path), res.headers);
		});
	});

	req.on('error', function(err) {
		console.log("ERR: %s", err, opts);
	});

	req.end();
}

function randomString(len)
{
	var vowels = ['a', 'e', 'i', 'o', 'u'];
	var consts =  ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'qu', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z', 'tt', 'ch', 'sh'];
	var word = '';

	var arr;
	var is_vowel = false;

	for (var i = 0; i < len; i++) {
	  if (is_vowel) arr = vowels
	  else arr = consts
	  is_vowel = !is_vowel;

	  word += arr[Math.round(Math.random()*(arr.length-1))];
	}

	return word;
}

function bytesToSize(bytes, precision)
{
    var kilobyte = 1024;
    var megabyte = kilobyte * 1024;
    var gigabyte = megabyte * 1024;
    var terabyte = gigabyte * 1024;

    if ((bytes >= 0) && (bytes < kilobyte)) {
        return bytes + ' B';

    } else if ((bytes >= kilobyte) && (bytes < megabyte)) {
        return (bytes / kilobyte).toFixed(precision) + ' KB';

    } else if ((bytes >= megabyte) && (bytes < gigabyte)) {
        return (bytes / megabyte).toFixed(precision) + ' MB';

    } else if ((bytes >= gigabyte) && (bytes < terabyte)) {
        return (bytes / gigabyte).toFixed(precision) + ' GB';

    } else if (bytes >= terabyte) {
        return (bytes / terabyte).toFixed(precision) + ' TB';

    } else {
        return bytes + ' B';
    }
}
<commit_msg>testing git name<commit_after>/*
	Scraper app. Only runs as child forked process.
*/

var	util 	= require('util'),
	http 	= require('http'),
	url 	= require('url'),
	mongoose= require('mongoose'),
	argv 	= require('named-argv'),
	jsdom	= require('jsdom');

mongoose.connect('mongodb://localhost/search_for_404_v4');

var scrapeHost = "", fullUrl = "", link, auth = {},
	Links404Model, LinksCheckModel, LinksGrabbedModel,
	requestsRunning = 0, requestsPerSecond = 0, maxThreads = 20;

process.on("message", function(data)
{
	switch (data.action)
	{
		case "setAuth":
			auth.user = data.auth_user;
			auth.pass = data.auth_pass;
			break;

		case "setMaxThreads":
			maxThreads = data.max_threads;
			break;

		case "start":
			fullUrl    = data.url;
			scrapeHost = url.parse(data.url).host;

			Links404Model 	  = mongoose.model("links_404_" + scrapeHost, new mongoose.Schema({url:String, source:String}));
			LinksCheckModel   = mongoose.model("links_check_" + scrapeHost, new mongoose.Schema({ url: { type: String, index: { unique: true } }, source: String, from_redirect: {type: Boolean, default: false} }));
			LinksGrabbedModel = mongoose.model("links_grabbed_" + scrapeHost, new mongoose.Schema({url: { type: String, index: { unique: true }}, source: String }));

			if (data.clean) {
				Links404Model.find().remove();
				LinksCheckModel.find().remove();
				LinksGrabbedModel.find().remove();
			}

			(new LinksCheckModel({url: argv.opts.url})).save();
			util.log("Start scraping "+ scrapeHost +"...");

			setInterval(sendGeneralStats, 3000);
			setInterval(checkUrl, 10);
			break;
	}
})

function sendGeneralStats()
{
	LinksGrabbedModel.count({}, function(err, count_grabbed)
	{
		LinksCheckModel.count({}, function(err, count_check)
		{
			process.send(
			{
				message: 'general-stats',
				memory: bytesToSize(process.memoryUsage().rss),
				requests: requestsRunning,
				grabbed: count_grabbed,
				tocheck: count_check,
				max_threads: maxThreads,
				host: scrapeHost
			});
		});
	});
}

// setInterval(function()
// {
// 	io.sockets.emit("rps", {rps: requestsPerSecond});
// 	requestsPerSecond = 0;
// },
// 1000)

function checkUrl()
{
	LinksCheckModel.findOne({}, function(err, doc)
	{
		if( doc==null )
			return;

		if( requestsRunning > maxThreads )
			return;

		var source_link = doc.source;
		link = doc.url;
		doc.remove();

		LinksGrabbedModel.count({url: link}, function(err, count)
		{
			if( count == 0 ) {
				(new LinksGrabbedModel({url: link, source: source_link})).save();
			}
		});

		var urlObj = url.parse(link);
		requestsRunning++;

		process.send({message: "checking", url: urlObj.protocol+"//"+urlObj.host+urlObj.path})

		make_request(urlObj.protocol, urlObj.host, urlObj.path, function(statusCode, body, reqUrl, headers)
		{
			requestsPerSecond++;
			requestsRunning--;

			if( statusCode == 404 ) {
				LinksGrabbedModel.findOne({url: reqUrl}, function(err, doc) {
					if ( doc != null ) {
						(new Links404Model({url:reqUrl, source:doc.source})).save();
						process.send({message: "got-404", url: reqUrl, source: doc.source})
					}
				});

				return;
			}
			else if ( [301,302,303].indexOf(statusCode) > -1 ) {
				var redir_location = url.parse(headers.location);
				if (redir_location.host == undefined) {
					redir_location.host = url.parse(reqUrl).host;
				}

				(new LinksCheckModel({url:redir_location.href, source: reqUrl, from_redirect: true})).save();
				return;
			}

			jsdom.env({
				html: body,
				scripts: ["http://code.jquery.com/jquery.js"],
				done: function (errors, window)
				{
					if (window == undefined || window.$ == undefined) {
						if (window != undefined)
							window.close();
						return;
					}

					var $ = window.$;
					$("a").each(function()
					{
						var lnk = $(this).attr("href");

						if ((lnk = check_link(lnk)) == false)
							return;

						(function(add_link, source_link) {
							LinksGrabbedModel.findOne({url: add_link}, function(err, doc)
							{
								if( doc==null || doc.length==0 ) {
									LinksCheckModel.findOne({url: add_link}, function(err, doc)
									{
										if( doc==null || doc.length==0 ) {
											(new LinksCheckModel({url:add_link, source: source_link})).save();
										}
									});
								}
							});
						})(lnk, reqUrl);
					});

					window.close();
				}
			});
		});

		urlObj = null;
	});
};

function check_link(lnk)
{
	if( lnk.indexOf("/")==0 )
		lnk = "http://" + scrapeHost + lnk;

	if( lnk==undefined || ["#", ""].indexOf(lnk)!=-1 || (lnk.indexOf("http://" + scrapeHost)!=0 && lnk.indexOf("https://"+scrapeHost)!=0) ) {
		return false;
	}

	return lnk;
}

function make_request(protocol, host, path, callback)
{
	var opts = {
		host: host,
		port: 80,
		path: path,
		method: "GET"
	};

	if( Object.keys(auth).length )
		opts.auth = [auth.user, auth.pass].join(":");

	var req = http.request(opts, function(res)
	{
		var data = "";

		res.setEncoding('utf8');
		res.on('data', function (chunk) {
			if(res.statusCode==200)
				data += chunk;
		});

		res.on('end', function(){
			callback(res.statusCode, data, (protocol+"//"+host+path), res.headers);
		});
	});

	req.on('error', function(err) {
		console.log("ERR: %s", err, opts);
	});

	req.end();
}

function randomString(len)
{
	var vowels = ['a', 'e', 'i', 'o', 'u'];
	var consts =  ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'qu', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z', 'tt', 'ch', 'sh'];
	var word = '';

	var arr;
	var is_vowel = false;

	for (var i = 0; i < len; i++) {
	  if (is_vowel) arr = vowels
	  else arr = consts
	  is_vowel = !is_vowel;

	  word += arr[Math.round(Math.random()*(arr.length-1))];
	}

	return word;
}

function bytesToSize(bytes, precision)
{
    var kilobyte = 1024;
    var megabyte = kilobyte * 1024;
    var gigabyte = megabyte * 1024;
    var terabyte = gigabyte * 1024;

    if ((bytes >= 0) && (bytes < kilobyte)) {
        return bytes + ' B';

    } else if ((bytes >= kilobyte) && (bytes < megabyte)) {
        return (bytes / kilobyte).toFixed(precision) + ' KB';

    } else if ((bytes >= megabyte) && (bytes < gigabyte)) {
        return (bytes / megabyte).toFixed(precision) + ' MB';

    } else if ((bytes >= gigabyte) && (bytes < terabyte)) {
        return (bytes / gigabyte).toFixed(precision) + ' GB';

    } else if (bytes >= terabyte) {
        return (bytes / terabyte).toFixed(precision) + ' TB';

    } else {
        return bytes + ' B';
    }
}
<|endoftext|>


<commit_before>function findElement(id, array) {
  return array.map(function(element) {
    return element.id
  }).indexOf(id);
}

//Reducer：更新state的函式
const todos = (state = { todos: [], filter: 'all', counter: 0 }, actions) => {
  switch(actions.type) {
    case 'ADD_TODO':
      state.todos.push({
        id: state.counter++,
        name: actions.name,
        completed: false
      });
      break;
    case 'DELETE_TODO':
      state = Object.assign({}, state, state.todos.splice(findElement(actions.id, state.todos), 1));
      break;
    case 'EDIT_TODO':
      state.todos[findElement(actions.id, state.todos)].name = actions.name;
      break;
    case 'COMPLETE_TODO':
      state.todos[findElement(actions.id, state.todos)].completed = actions.completed;
      break;
    case 'INCOMPLETE_TODO':
      state.todos[findElement(actions.id, state.todos)].completed = actions.completed;
      break;
    case 'FILTER_COMPLETED':
      state.filter = 'completed';
      break;
    case 'FILTER_ALL':
     state.filter = 'all'
      break;
    default:
      break;
  }

  return state;
}

//Store：儲存state的地方
const todosStore = Redux.createStore(todos);

//Action：使用todosStore.dispatch來通知有事情發生，必須更新state
$('.add').click(() => {
  var newValue = $('.input_new_item').val();
  if(newValue) {
    todosStore.dispatch({
      type: 'ADD_TODO',
      name: newValue
    });
  }

  $('.input_new_item').val('');
});

$('.list').on('click', '.delete', function() {
  todosStore.dispatch({
    type: 'DELETE_TODO',
    id: $(this).parents('.item').data('id')
  });
});

$('.list').on('click', '.edit', function() {
  $(this).hide();
  $(this).parents('.item').find('.edit-block').show();
});

$('.list').on('click', '.submit', function() {
  var $item = $(this).parents('.item');

  todosStore.dispatch({
    type: 'EDIT_TODO',
    id: $item.data('id'),
    name: $item.find('.input-edit').val()
  });

  $item.find('.edit').show();
  $item.find('.edit-block').hide();
});

$('.list').on('change', '.complete-status', function() {
  var isCompleted = $(this).prop('checked');
  var actionType = 'INCOMPLETE_TODO';

  if(isCompleted) {
    actionType = 'COMPLETE_TODO'
  }

  todosStore.dispatch({
    type: actionType,
    id: $(this).parents('.item').data('id'),
    completed: isCompleted
  });

});

$('.filter-complete').click(() => {
  todosStore.dispatch({
    type: 'FILTER_COMPLETED'
  });
});

$('.filter-all').click(() => {
  todosStore.dispatch({
    type: 'FILTER_ALL'
  });
});

//監聽，當dispatch action執行造成state改變時就去取目前state內容，用來更新UI
todosStore.subscribe(() => {
  var state = todosStore.getState();
  var ResultHTML = '';

  for(var i = 0; i < state.todos.length; i++) {
    let HTML = '';
    let item = state.todos[i];
    let status = item.completed ? 'checked' : '';
    let hide = (state.filter === 'completed' && !item.completed) ? 'hide' : '';

    HTML += [
      '
',
      '  <input type="checkbox" class="complete-status"' + status +'>',
      '  ' + item.name + '',
      '  ',
      '    <input class="input-edit" />',
      '    <button class="submit">submit</button>',
      '  ',
      '  <button class="edit">edit</button>',
      '  <button class="delete">delete</button>',
      '
'
    ].join('');
    ResultHTML += HTML;
  }

  $('#todoList .list').html(ResultHTML);
});<commit_msg>divide reducer into two parts: todos and filter<commit_after>const SHOW_ALL = 'SHOW_ALL';
const SHOW_COMPLETED = 'SHOW_COMPLETED';
var counter = 0;

function findElement(id, array) {
  return array.map(function(element) {
    return element.id
  }).indexOf(id);
}

//Reducer：更新state的函式
const filter = (state = SHOW_ALL, action) => {
  switch (action.type) {
    case SHOW_ALL:
      return action.type
    case SHOW_COMPLETED:
      return action.type
    default:
      return state
  }
}

const todos = (state = [], actions) => {
  switch(actions.type) {
    case 'ADD_TODO':
      state.push({
        id: counter++,
        name: actions.name,
        completed: false
      });
      break;
    case 'DELETE_TODO':
      state.splice(findElement(actions.id, state), 1);
      break;
    case 'EDIT_TODO':
      state[findElement(actions.id, state)].name = actions.name;
      break;
    case 'COMPLETE_TODO':
      state[findElement(actions.id, state)].completed = actions.completed;
      break;
    case 'INCOMPLETE_TODO':
      state.todos[findElement(actions.id, state)].completed = actions.completed;
      break;
    default:
      break;
  }

  return state;
}

//Store：儲存state的地方
const todoApp = Redux.combineReducers({
  filter,
  todos
});
var todosStore = Redux.createStore(todoApp)

//Action：使用todosStore.dispatch來通知有事情發生，必須更新state
$('.add').click(() => {
  var newValue = $('.input_new_item').val();
  if(newValue) {
    todosStore.dispatch({
      type: 'ADD_TODO',
      name: newValue
    });
  }

  $('.input_new_item').val('');
});

$('.list').on('click', '.delete', function() {
  todosStore.dispatch({
    type: 'DELETE_TODO',
    id: $(this).parents('.item').data('id')
  });
});

$('.list').on('click', '.edit', function() {
  $(this).hide();
  $(this).parents('.item').find('.edit-block').show();
});

$('.list').on('click', '.submit', function() {
  var $item = $(this).parents('.item');

  todosStore.dispatch({
    type: 'EDIT_TODO',
    id: $item.data('id'),
    name: $item.find('.input-edit').val()
  });

  $item.find('.edit').show();
  $item.find('.edit-block').hide();
});

$('.list').on('change', '.complete-status', function() {
  var isCompleted = $(this).prop('checked');
  var actionType = 'INCOMPLETE_TODO';

  if(isCompleted) {
    actionType = 'COMPLETE_TODO'
  }

  todosStore.dispatch({
    type: actionType,
    id: $(this).parents('.item').data('id'),
    completed: isCompleted
  });

});

$('.filter-complete').click(() => {
  todosStore.dispatch({
    type: SHOW_COMPLETED
  });
});

$('.filter-all').click(() => {
  todosStore.dispatch({
    type: SHOW_ALL
  });
});

//監聽，當dispatch action執行造成state改變時就去取目前state內容，用來更新UI
todosStore.subscribe(() => {
  var state = todosStore.getState();
  var ResultHTML = '';

  for(var i = 0; i < state.todos.length; i++) {
    let HTML = '';
    let item = state.todos[i];
    let status = item.completed ? 'checked' : '';
    let hide = (state.filter === SHOW_COMPLETED && !item.completed) ? 'hide' : '';

    HTML += [
      '
',
      '  <input type="checkbox" class="complete-status"' + status +'>',
      '  ' + item.name + '',
      '  ',
      '    <input class="input-edit" />',
      '    <button class="submit">submit</button>',
      '  ',
      '  <button class="edit">edit</button>',
      '  <button class="delete">delete</button>',
      '
'
    ].join('');
    ResultHTML += HTML;
  }

  $('#todoList .list').html(ResultHTML);
});<|endoftext|>