Skip to content

Commit 038b7c7

Browse files
committedDec 11, 2016
initial commit
0 parents  commit 038b7c7

11 files changed

+2971
-0
lines changed
 

‎.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
cops.json
2+
.vscode/
3+
node_modules/

‎app.js

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
var http = require("http");
2+
var express = require("express");
3+
var consolidate = require("consolidate");//1
4+
var _ = require("lodash");
5+
var bodyParser = require('body-parser');
6+
var socket_io = require('socket.io'); //Creating a new socket.io instance by passing the HTTP server object
7+
8+
var routes = require('./routes'); //File that contains our endpoints
9+
var mongoClient = require("mongodb").MongoClient;
10+
11+
var app = express();
12+
app.use(bodyParser.urlencoded({
13+
extended: true,
14+
}));
15+
16+
app.use(bodyParser.json({ limit: '5mb' }));
17+
18+
app.set('views', 'views'); //Set the folder-name from where you serve the html page.
19+
app.use(express.static('./public')); //setting the folder name (public) where all the static files like css, js, images etc are made available
20+
21+
app.set('view engine', 'html');
22+
app.engine('html', consolidate.underscore);
23+
var server = http.createServer(app);
24+
var io = socket_io(server);
25+
var portNumber = 8000; //for locahost:8000
26+
27+
server.listen(portNumber, function () { //creating the server which is listening to the port number:8000, and calls a function within in which calls the initialize(app) function in the router module
28+
console.log('Server listening at port ' + portNumber);
29+
30+
var url = 'mongodb://localhost:27017/myUberApp';
31+
mongoClient.connect(url, function (err, db) { //a connection with the mongodb is established here.
32+
console.log("Connected to Database");
33+
34+
app.get('/citizen.html', function (req, res) {
35+
res.render('citizen.html', {
36+
userId: req.query.userId
37+
});
38+
});
39+
40+
app.get('/cop.html', function (req, res) {
41+
res.render('cop.html', {
42+
userId: req.query.userId
43+
});
44+
});
45+
46+
app.get('/data.html', function (req, res) {
47+
res.render('data.html');
48+
});
49+
50+
io.on('connection', function (socket) { //Listen on the 'connection' event for incoming sockets
51+
console.log('A user just connected');
52+
53+
socket.on('join', function (data) { //Listen to any join event from connected users
54+
socket.join(data.userId); //User joins a unique room/channel that's named after the userId
55+
console.log("User joined room: " + data.userId);
56+
});
57+
58+
routes.initialize(app, db, socket, io); //Pass socket and io objects that we could use at different parts of our app
59+
});
60+
});
61+
});
62+
63+
/* 1. Not all the template engines work uniformly with express, hence this library in js, (consolidate), is used to make the template engines work uniformly. Altough it doesn't have any
64+
modules of its own and any template engine to be used should be seprately installed!*/

‎db-operations.js

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
function fetchNearestCops(db, coordinates, callback) {
2+
db.collection('policeData').createIndex({
3+
"location": "2dsphere"
4+
}, function () {
5+
db.collection("policeData").find({
6+
location: {
7+
$near: {
8+
$geometry: {
9+
type: "Point",
10+
coordinates: coordinates
11+
},
12+
$maxDistance: 2000
13+
}
14+
}
15+
}).toArray(function (err, results) {
16+
if (err) {
17+
console.log(err)
18+
} else {
19+
callback(results);
20+
}
21+
});
22+
});
23+
}
24+
25+
function fetchCopDetails(db, userId, callback) {
26+
db.collection('policeData').findOne({
27+
userId: userId,
28+
}, function (err, results) {
29+
if (err) return console.log(err);
30+
callback({
31+
copId: results.userId,
32+
displayName: results.displayName,
33+
phone: results.phone,
34+
location: results.location,
35+
});
36+
})
37+
}
38+
39+
function saveRequest(db, issueId, requestTime, location, citizenId, status, callback) {
40+
db.collection('requestsData').insert({
41+
"_id": issueId,
42+
"requestTime": requestTime,
43+
"location": location,
44+
"citizenId": citizenId,
45+
"status": status
46+
}, function (err, results) {
47+
if (err) {
48+
console.log(err);
49+
} else {
50+
callback(results);
51+
}
52+
});
53+
}
54+
55+
function updateRequest(db, requestId, copId, status, callback) {
56+
db.collection('requestsData').update({
57+
"_id": requestId //Perform update for the given requestId
58+
}, {
59+
$set: {
60+
"status": status, //Update status to 'engaged'
61+
"copId": copId //save cop's userId
62+
}
63+
}, function (err, results) {
64+
if (err) {
65+
console.log(err);
66+
} else {
67+
callback("Issue updated")
68+
}
69+
});
70+
}
71+
72+
function fetchRequests(db, callback) {
73+
db.collection('requestsData').find({}, {
74+
requestTime: true,
75+
status: true,
76+
location: true
77+
}).toArray(function (err, results) {
78+
if (err) {
79+
console.log(err)
80+
} else {
81+
callback(results);
82+
}
83+
});
84+
}
85+
86+
exports.fetchRequests = fetchRequests;
87+
exports.updateRequest = updateRequest;
88+
exports.saveRequest = saveRequest;
89+
exports.fetchNearestCops = fetchNearestCops;
90+
exports.fetchCopDetails = fetchCopDetails;

‎package.json

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "myapp",
3+
"version": "0.0.1",
4+
"private": true,
5+
"dependencies": {
6+
"async": "*",
7+
"bcrypt": "*",
8+
"body-parser": "*",
9+
"connect-redis": "*",
10+
"consolidate": "*",
11+
"cookie-parser": "*",
12+
"debug": "*",
13+
"express": "*",
14+
"express-session": "*",
15+
"googlemaps": "*",
16+
"jsx-loader": "*",
17+
"lodash": "*",
18+
"mongodb": "^2.2.14",
19+
"nodemailer": "^2.7.0",
20+
"react": "*",
21+
"redis": "*",
22+
"serve-favicon": "*",
23+
"socket.io": "*"
24+
},
25+
"devDependencies": {
26+
"eslint": "^3.11.1"
27+
}
28+
}

‎public/citizen.png

30.1 KB
Loading

‎routes.js

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
var dbOperations = require('./db-operations');
2+
function initialize(app, db, socket, io) {
3+
4+
//A GET request to /cops should return back the nearest cops in the vicinity.
5+
app.get('/cops', function (req, res) {
6+
var latitude = Number(req.query.lat);
7+
var longitude = Number(req.query.long);
8+
9+
dbOperations.fetchNearestCops(db, [longitude, latitude], function (results) {
10+
res.json({ cops: results });
11+
});
12+
});
13+
14+
app.get('/cops/info', function (req, res) {
15+
var userId = req.query.userId;
16+
dbOperations.fetchCopDetails(db, userId, function (results) {
17+
res.json({
18+
copDetails: results,
19+
});
20+
});
21+
});
22+
23+
app.get('/requests/info', function (req, res) {
24+
dbOperations.fetchRequests(db, function (results) {
25+
var features = results.map(function (row) {
26+
return {
27+
type: 'Feature',
28+
geometry: {
29+
type: 'Point',
30+
coordinates: row.location.coordinates
31+
},
32+
properties: {
33+
status: row.status,
34+
requestTime: row.requestTime,
35+
address: row.location.address
36+
}
37+
};
38+
});
39+
var geoJsonData = {
40+
type: 'FeatureCollection',
41+
features: features
42+
}
43+
44+
res.json(geoJsonData);
45+
})
46+
});
47+
48+
//Listen to a 'request-for-help' event from connected citizens
49+
socket.on('request-for-help', function (eventData) {
50+
/*
51+
eventData contains userId and location
52+
1. First save the request details inside a table requestsData
53+
2. AFTER saving, fetch nearby cops from citizen’s location
54+
3. Fire a request-for-help event to each of the cop’s room
55+
*/
56+
57+
var requestTime = new Date(); //Time of the request
58+
59+
var ObjectID = require('mongodb').ObjectID;
60+
var requestId = new ObjectID; //Generate unique ID for the request
61+
62+
//1. First save the request details inside a table requestsData.
63+
//Convert latitude and longitude to [longitude, latitude]
64+
var location = {
65+
coordinates: [
66+
eventData.location.longitude,
67+
eventData.location.latitude
68+
],
69+
address: eventData.location.address
70+
};
71+
dbOperations.saveRequest(db, requestId, requestTime, location, eventData.citizenId, 'waiting', function (results) {
72+
73+
//2. AFTER saving, fetch nearby cops from citizen’s location
74+
dbOperations.fetchNearestCops(db, location.coordinates, function (results) {
75+
eventData.requestId = requestId;
76+
//3. After fetching nearest cops, fire a 'request-for-help' event to each of them
77+
for (var i = 0; i < results.length; i++) {
78+
io.sockets.in(results[i].userId).emit('request-for-help', eventData);
79+
}
80+
});
81+
});
82+
});
83+
84+
//Listen to a 'request-accepted' event from connected cops
85+
socket.on('request-accepted', function (eventData) {
86+
//Convert string to MongoDb's ObjectId data-type
87+
var ObjectID = require('mongodb').ObjectID;
88+
var requestId = new ObjectID(eventData.requestDetails.requestId);
89+
90+
//For the request with requestId, update request details
91+
dbOperations.updateRequest(db, requestId, eventData.copDetails.copId, 'engaged', function (results) {
92+
//Fire a 'request-accepted' event to the citizen and send cop details
93+
io.sockets.in(eventData.requestDetails.citizenId).emit('request-accepted', eventData.copDetails);
94+
});
95+
});
96+
}
97+
98+
exports.initialize = initialize;

‎views/abc.html

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset='utf-8' />
6+
<title></title>
7+
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
8+
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.28.0/mapbox-gl.js'></script>
9+
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.28.0/mapbox-gl.css' rel='stylesheet' />
10+
<style>
11+
body { margin:0; padding:0; }
12+
#map { position:absolute; top:0; bottom:0; width:100%; }
13+
</style>
14+
</head>
15+
16+
<body>
17+
18+
<div id='map'></div>
19+
<div class="marker mapboxgl-marker" style="background-image: url(&quot;https://raw.githubusercontent.com/booleanhunter/code-samples/master/blog-posts/how-to-build-your-own-uber-for-x-app/public/images/citizen.png&quot;); width: 50px; height: 50px; transform: translate(720px, 185px);"></div>
20+
<script>
21+
mapboxgl.accessToken = 'pk.eyJ1IjoiYXl1c2gwMDAiLCJhIjoiY2l3aTZpZTh2MDFmaTJ6cG94ZzZ4dnE3eSJ9.9zdaXHeiwS5WiXD_aAb_ig';
22+
var map = new mapboxgl.Map({
23+
container: 'map', // container id
24+
style: 'mapbox://styles/mapbox/streets-v9', //stylesheet location
25+
center: [-74.50, 40], // starting position
26+
zoom: 9 // starting zoom
27+
});
28+
</script>
29+
30+
</body>
31+
32+
</html>

‎views/citizen.html

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="utf-8" />
6+
<title>Citizen
7+
<%= userId %>
8+
</title>
9+
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.28.0/mapbox-gl.js'></script>
10+
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.28.0/mapbox-gl.css' rel='stylesheet' />
11+
<script src='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v2.0.1/mapbox-gl-geocoder.js'></script>
12+
<link rel='stylesheet' href='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v2.0.1/mapbox-gl-geocoder.css'
13+
type='text/css' />
14+
<style>
15+
#map { position:absolute; top:200px; bottom:0; width:100%; }
16+
.marker {
17+
display: block;
18+
border: none;
19+
border-radius: 50%;
20+
cursor: pointer;
21+
padding: 0;
22+
}
23+
</style>
24+
</head>
25+
26+
<body data-userId="<%= userId %>">
27+
<h1>Hello Citizen
28+
<%= userId %>
29+
</h1>
30+
<button onclick="requestForHelp()"> Request for help
31+
</button>
32+
<h4 id="notification">
33+
<!-- Some info will be displayed here-->
34+
</h4>
35+
36+
<div id='map'>
37+
<!-- We will load a map here later-->
38+
</div>
39+
40+
<!--Load JavaScripts -->
41+
42+
<!-- Load socket.io client library -->
43+
<script src="/socket.io/socket.io.js"></script>
44+
<!-- Load JQuery from a CDN -->
45+
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
46+
47+
<!-- load libraries before your JS code
48+
Write rest of your JS code here -->
49+
50+
<script type="text/javascript">
51+
var socket = io();
52+
//Fetch userId from the data-atribute of the body tag
53+
var userId = document.body.getAttribute("data-userId");
54+
55+
/*Fire a 'join' event and send your userId to the server, to join a room - room-name will be the userId itself!
56+
*/
57+
socket.emit('join', { userId: userId });
58+
59+
//Declare variables, this will be used later
60+
var requestDetails = {};
61+
var copDetails = {};
62+
var map, marker;
63+
64+
//Citizen's info
65+
requestDetails = {
66+
citizenId: userId,
67+
location: {
68+
address: "Indiranagar, Bengaluru, Karnataka 560038, India",
69+
latitude: 12.9718915,
70+
longitude: 77.64115449999997
71+
}
72+
}
73+
74+
//When button is clicked, fire request-for-help and send citizen's userId and location
75+
function requestForHelp() {
76+
socket.emit("request-for-help", requestDetails);
77+
}
78+
79+
//Listen for a "request-accepted" event
80+
socket.on("request-accepted", function (eventData) {
81+
copDetails = eventData; //Save cop details
82+
83+
//Display Cop details
84+
document.getElementById("notification").innerHTML = "A cop is coming to your rescue! \n" + JSON.stringify(copDetails);
85+
});
86+
87+
mapboxgl.accessToken = "pk.eyJ1IjoiYXl1c2gwMDAiLCJhIjoiY2l3aTZpZTh2MDFmaTJ6cG94ZzZ4dnE3eSJ9.9zdaXHeiwS5WiXD_aAb_ig";
88+
map = new mapboxgl.Map({
89+
container: 'map', // container id
90+
style: 'mapbox://styles/mapbox/streets-v10', //stylesheet location
91+
center: [77.64115449999997, 12.9718915], // starting position
92+
zoom: 9 // starting zoom
93+
});
94+
// Create marker
95+
var el = document.createElement("img");
96+
el.className = 'marker';
97+
el.setAttribute('src','https://raw.githubusercontent.com/booleanhunter/code-samples/master/blog-posts/how-to-build-your-own-uber-for-x-app/public/images/citizen.png');
98+
el.style.width = '50px';
99+
el.style.height = '50px';
100+
marker = new mapboxgl.Marker(el)
101+
.setLngLat([77.64115449999997, 12.9718915])
102+
.addTo(map);
103+
map.addControl(new MapboxGeocoder({
104+
accessToken: mapboxgl.accessToken
105+
}).on('result', function (data) {
106+
console.log(data);
107+
//Extract address and coordinates from the results and save it
108+
requestDetails.location = {
109+
address: data.result['place_name'],
110+
latitude: data.result.center[1],
111+
longitude: data.result.center[0],
112+
};
113+
marker.setLngLat([data.result.center[0], data.result.center[1]]);
114+
115+
}));
116+
117+
//Load the map and give it a default style
118+
// map = L.mapbox.map("map", "mapbox.streets");
119+
//set it to a given lat-lng and zoom level
120+
// map.setView([12.9718915, 77.64115449999997], 9);
121+
//Display a default marker
122+
// marker = L.marker([12.9718915, 77.64115449999997]).addTo(map);
123+
124+
</script>
125+
</body>
126+
127+
</html>

‎views/cop.html

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="utf-8" />
6+
<title>Cop
7+
<%= userId %>
8+
</title>
9+
<link href="https://api.mapbox.com/mapbox.js/v2.4.0/mapbox.css" rel="stylesheet" />
10+
</head>
11+
12+
<body data-userId="<%= userId %>">
13+
<h1>Hello Cop
14+
<%= userId %>
15+
</h1>
16+
<h2>Cop details: </h2>
17+
<div id="copDetails"></div>
18+
<h4 id="notification">
19+
<!-- Some info will be displayed here-->
20+
</h4>
21+
<button onclick="helpCitizen()"> Help Citizen
22+
</button>
23+
24+
<div id="map">
25+
<!-- We will load a map here later-->
26+
</div>
27+
28+
<!--Load JavaScripts -->
29+
<!-- Load socket.io client library -->
30+
<script src="/socket.io/socket.io.js"></script>
31+
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.28.0/mapbox-gl.js'></script>
32+
<!-- Load JQuery from a CDN -->
33+
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
34+
35+
<!-- load libraries before your JS code
36+
Write rest of your JS code here -->
37+
38+
<script type="text/javascript">
39+
var socket = io();
40+
41+
//Fetch userId from the data-atribute of the body tag
42+
var userId = document.body.getAttribute("data-userId");
43+
44+
/*Fire a 'join' event and send your userId to the server, to join a room
45+
- room-name will be the userId itself!*/
46+
socket.emit('join', { userId: userId });
47+
48+
//Declare variables, this will be used later
49+
var requestDetails = {};
50+
var copDetails = {};
51+
var map, marker;
52+
//First send a GET request using JQuery AJAX and get the cop's details and save it
53+
$.ajax({
54+
url: "/cops/info?userId=" + userId,
55+
type: "GET",
56+
dataType: "json",
57+
success: function (data) { //Once response is successful
58+
copDetails = data.copDetails; //Save the cop details
59+
copDetails.location = {
60+
longitude: copDetails.location.coordinates[0],
61+
latitude: copDetails.location.coordinates[1],
62+
address: copDetails.location.address,
63+
};
64+
document.getElementById("copDetails").innerHTML = JSON.stringify(data.copDetails);
65+
},
66+
error: function (httpRequest, status, error) {
67+
console.log(error);
68+
}
69+
});
70+
71+
//Listen for a "request-for-help" event
72+
socket.on("request-for-help", function (eventData) {
73+
//Once request is received, do this:
74+
75+
//Save request details
76+
requestDetails = eventData; //Contains info of citizen
77+
78+
//display the data received from the event
79+
document.getElementById("notification").innerHTML = "Someone's being attacked by a wildling! \n" + JSON.stringify(requestDetails);
80+
});
81+
function helpCitizen() {
82+
//Fire a "request-accepted" event/signal and send relevant info back to server
83+
socket.emit("request-accepted", {
84+
requestDetails: requestDetails,
85+
copDetails: copDetails
86+
});
87+
}
88+
89+
</script>
90+
</body>
91+
92+
</html>

‎views/data.html

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="utf-8" />
6+
<title>Visualize Data</title>
7+
<link href="https://api.tiles.mapbox.com/mapbox-gl-js/v0.28.0/mapbox-gl.css" rel="stylesheet" />
8+
</head>
9+
10+
<body>
11+
12+
<div id="map" style="position:absolute; top:0; bottom: 0; width: 100%;">
13+
<!--Load the map here -->
14+
</div>
15+
16+
<!-- Load socket.io client library -->
17+
<script src="/socket.io/socket.io.js"></script>
18+
19+
<!-- Load JQuery from a CDN -->
20+
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
21+
22+
<!-- Load Mapbox GL Library -->
23+
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v0.28.0/mapbox-gl.js"></script>
24+
25+
<!-- load libraries before your JS code
26+
Write rest of your JS code here -->
27+
28+
<script type="text/javascript">
29+
var socket = io();
30+
var map, sdata;
31+
mapboxgl.accessToken = "pk.eyJ1IjoiYXl1c2gwMDAiLCJhIjoiY2l3aTZpZTh2MDFmaTJ6cG94ZzZ4dnE3eSJ9.9zdaXHeiwS5WiXD_aAb_ig";
32+
33+
$.ajax({
34+
url: "/requests/info",
35+
type: "GET",
36+
dataType: "json",
37+
success: function (data) {
38+
sdata = data;
39+
console.log(data);
40+
},
41+
error: function (httpRequest, status, error) {
42+
console.log(error);
43+
}
44+
});
45+
map = new mapboxgl.Map({
46+
container: "map",
47+
style: "mapbox://styles/mapbox/dark-v9",
48+
center: [77.64115449999997, 12.9718915],
49+
zoom: 10
50+
});
51+
52+
map.on("load", function () {
53+
54+
//Add a new source from our GeoJSON data
55+
map.addSource("help-requests", {
56+
type: "geojson",
57+
data: sdata
58+
});
59+
60+
//we can specify different color and styling formats by adding different layers
61+
62+
map.addLayer({
63+
"id": "help-requests",
64+
"type": "circle",
65+
"source": "help-requests",
66+
"paint": {
67+
//Apply a different color to different status fields
68+
"circle-color": {
69+
property: "status",
70+
type: "categorical",
71+
stops: [
72+
//For waiting, show in red
73+
["waiting", "rgba(255,0,0,0.5)"],
74+
75+
//For engaged, show in green
76+
["engaged", "rgba(0,255,0,0.5)"]
77+
]
78+
},
79+
"circle-radius": 20, //Radius of the circle
80+
"circle-blur": 1 //Amount of blur
81+
}
82+
});
83+
});
84+
85+
</script>
86+
</body>
87+
88+
</html>

‎yarn.lock

+2,349
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.