Repository navigation
Expand file tree
/
Copy pathserver.js
More file actions
129 lines (119 loc) · 4.58 KB
/
Copy pathserver.js
File metadata and controls
129 lines (119 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Installed packages
import path from 'path';
import { Server } from 'http';
import Express from 'express';
import React from 'react';
import { renderToString } from 'react-dom/server';
import stream from "express-stream";
import updateJsonFile from "update-json-file";
// React components
import PickupArrived from "./components/PickupArrived";
import Assigned from "./components/Assigned";
import RideCompleted from "./components/RideCompleted";
import NoCabs from "./components/NoCabs";
// Local APIs
const getNearestCab = require("./api/getNearestCab");
const moveCabForTime = require("./api/moveCabForTime");
const calculateDistance = require("./api/calculateDistance");
const getRideTimeByDistance = require("./api/getRideTimeByDistance");
const calculateFareForRide = require("./api/calculateFareForRide");
// List of cabs json
const filePath = './data/cabs.json';
let cabs = require(filePath)["data"];
// initialize the server and configure support for ejs templates
const app = new Express();
const server = new Server(app);
// Set the view engine
app.set('view engine', "ejs");
app.set('views', path.join(__dirname, 'views'));
// API to find idle cab
app.get("/findCab/:sourceLat/:sourceLng/:destLat/:destLng/:wantPink", stream.pipe(), ( async function (req, res) {
// Parameter validation
const sourceLat = Number(req.params.sourceLat);
if (isNaN(sourceLat)) {
throw new Error("Source latitude must be a number");
}
const sourceLng = Number(req.params.sourceLng);
if (isNaN(sourceLng)) {
throw new Error("Source longitude must be a number");
}
const destLat = Number(req.params.destLat);
if (isNaN(destLat)) {
throw new Error("Destination latitude must be a number");
}
const destLng = Number(req.params.destLng);
if (isNaN(destLng)) {
throw new Error("Destination longitude must be a number");
}
let wantPink;
try {
wantPink = JSON.parse(req.params.wantPink);
} catch (e) {
throw new Error("wantPink should be a boolean");
}
if (typeof wantPink !== "boolean") {
throw new Error("wantPink should be a boolean");
}
// Prepare location objects
const sourceLocation = {lat: sourceLat, lng: sourceLng};
const destLocation = {lat: destLat, lng: destLng};
// Get the nearest available cab
const nearestCab = getNearestCab(wantPink, sourceLocation);
if (nearestCab !== null) {
// If cab available
cabs.forEach((cab) => {
if (cab.id === nearestCab.id) {
cab.idle = false; // Unset this cab from idle so that it doesn't get assigned to someone else
}
});
// Update the json file
updateJsonFile(filePath, (data) => {
data.data = cabs;
return data;
});
// Wait for time till cab arrives to pickup location
let markup;
const pickupTime = getRideTimeByDistance(nearestCab.distanceToPickup);
markup = renderToString(<Assigned time={pickupTime}/>);
res.stream('index', { markup });
await moveCabForTime(pickupTime);
// Start the ride and wait for cab to reach the drop location
const commuteDistance = calculateDistance(sourceLocation, destLocation);
const rideTime = getRideTimeByDistance(commuteDistance);
markup = renderToString(<PickupArrived time={rideTime}/>);
res.stream('index', { markup });
await moveCabForTime(rideTime);
// Calculate ride fare
const rideFare = calculateFareForRide(commuteDistance, rideTime, wantPink);
cabs.forEach((cab) => {
if (cab.id === nearestCab.id) {
// Update the json file with cab's new location and status to idle so that new customer can access it.
cab.idle = true;
cab.lat = destLocation.lat;
cab.lng = destLocation.lng;
}
});
// Update the json file
updateJsonFile(filePath, (data) => {
data.data = cabs;
return data;
});
// Show ride completed message on UI with total fare
markup = renderToString(<RideCompleted rideFare={rideFare}/>);
res.stream('index', { markup });
res.close();
} else {
// If cab not available
let markup = renderToString(<NoCabs/>);
res.stream('index', { markup });
}
}));
// Start the server
const port = process.env.PORT || 3000;
server.listen(port, err => {
if (err) {
return console.error(err);
}
console.info(`Server running on http://localhost:${port}`);
});
global.navigator = { userAgent: 'all' };