Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 753fd68

Browse files
first commit
0 parents commit 753fd68

File tree

10 files changed

+1972
-0
lines changed

10 files changed

+1972
-0
lines changed

‎.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules/
2+
.env

‎config/DBConnect.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const mongoose = require('mongoose')
2+
const path = require('path')
3+
require('dotenv').config({path: path.resolve(__dirname, '../.env')})
4+
5+
6+
const connectDB= async ()=>{
7+
try{
8+
const client=await mongoose.connect(process.env.MONGO_URI, {
9+
useNewUrlParser:true,
10+
useUnifiedTopology:true,
11+
})
12+
console.log(`MongoDB connected :${client.connection.host}`)
13+
}catch(err){
14+
console.log(`error:${err.message}`)
15+
process.exit()
16+
}
17+
}
18+
19+
module.exports={
20+
connectDB
21+
}

‎controller.js

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
const csvParser = require('csv-parser');
2+
const fs = require('fs');
3+
const {connectDB} = require('./config/DBConnect')
4+
const {Event} = require('./models/EventModel');
5+
const { log } = require('console');
6+
7+
8+
9+
async function dataIngestHandler(req, res){
10+
await connectDB().catch(error=>res.status(500).json({error:'connection falied with mongoDB...'}))
11+
12+
// Check if file exists
13+
if (!req.file) {
14+
return res.status(400).send('No file uploaded.');
15+
}
16+
17+
// Read the CSV file and process its contents
18+
const results = [];
19+
fs.createReadStream(req.file.path)
20+
.pipe(csvParser())
21+
.on('data', (data) => results.push(data))
22+
.on('end', async() => {
23+
24+
try{
25+
const result = await Event.insertMany(results)
26+
27+
return res.status(201).json({result: `${result.length} events inserted into database....`})
28+
29+
}catch(err){
30+
return res.status(404).json({error: 'Insertion failed!'})
31+
}
32+
33+
});
34+
}
35+
36+
37+
async function dataQueryHandler(req, res){
38+
await connectDB().catch(error=>res.status(500).json({error:'connection falied with mongoDB...'}))
39+
40+
const user_longitude = req.query.longitude.toString()
41+
const user_latitude = req.query.latitude.toString()
42+
const search_date = req.query.date.toString()
43+
44+
try{
45+
const end_date = incrementDate(search_date, 15)
46+
//this will return events occurring within the next 14 days from the search_date
47+
const result = await Event.find({date:{$gte:search_date, $lt:end_date}})
48+
49+
//using Promise.all() we making concurrent API calls to the external Weather and Distance Calculation APIs to minimize response times
50+
try{
51+
const events = await Promise.all(
52+
result.map((event) => executeDistanceAndWeatherAPICallTask(event, user_latitude, user_longitude))
53+
)
54+
55+
//process the responce with 10 events each page.
56+
const pages = []
57+
const pageSize = 10;
58+
const totalPages = Math.ceil(events.length / pageSize);
59+
60+
// Generate responses for each page
61+
for (let pageNumber = 1; pageNumber <= totalPages; pageNumber++) {
62+
const pageResponse = generateResponcePage(pageNumber, pageSize, events);
63+
pages.push(pageResponse)
64+
}
65+
66+
return res.status(200).json(pages)
67+
68+
}catch(err){
69+
console.log(err)
70+
return res.status(200).json({error: 'Promises to external APIs failed!'})
71+
}
72+
73+
}catch(err){
74+
console.log(err)
75+
return res.status(404).json({error: 'Searching of events failed!'})
76+
}
77+
}
78+
79+
async function dataDeleteHandler(req, res){
80+
await connectDB().catch(error=>res.status(500).json({error:'connection falied with mongoDB...'}))
81+
82+
try{
83+
const result = await Event.deleteMany({})
84+
return res.status(404).json(result)
85+
}catch(err){
86+
return res.status(404).json({error: 'Insertion failed!'})
87+
}
88+
}
89+
90+
91+
const executeDistanceAndWeatherAPICallTask = async(event, user_latitude, user_longitude) => {
92+
let city_name = event.city_name.replaceAll(' ', '%20')
93+
const distance_api_url = `https://gg-backend-assignment.azurewebsites.net/api/Distance?code=IAKvV2EvJa6Z6dEIUqqd7yGAu7IZ8gaH-a0QO6btjRc1AzFu8Y3IcQ==&latitude1=${user_latitude}&longitude1=${user_longitude}&latitude2=${event.latitude}&longitude2=${event.longitude}`
94+
const weather_api_url = `https://gg-backend-assignment.azurewebsites.net/api/Weather?code=KfQnTWHJbg1giyB_Q9Ih3Xu3L9QOBDTuU5zwqVikZepCAzFut3rqsg==&city=${city_name}&date=${event.date}`
95+
96+
try{
97+
const distance_res = await fetch(distance_api_url)
98+
const distance_res_json = await distance_res.json()
99+
try{
100+
const weather_res = await fetch(weather_api_url)
101+
const weather_res_json = await weather_res.json()
102+
103+
return {
104+
event_name: event.event_name,
105+
city_name: event.city_name,
106+
date: event.date,
107+
distance: distance_res_json.distance,
108+
weather: weather_res_json.weather
109+
}
110+
111+
}catch(err){
112+
throw err
113+
}
114+
115+
}catch(err){
116+
throw err
117+
}
118+
}
119+
120+
function incrementDate(date_str, incrementor) {
121+
var parts = date_str.split("-");
122+
var dt = new Date(
123+
parseInt(parts[0], 10), // year
124+
parseInt(parts[1], 10) - 1, // month (starts with 0)
125+
parseInt(parts[2], 10) // date
126+
);
127+
dt.setTime(dt.getTime() + incrementor * 86400000);
128+
parts[0] = "" + dt.getFullYear();
129+
parts[1] = "" + (dt.getMonth() + 1);
130+
if (parts[1].length < 2) {
131+
parts[1] = "0" + parts[1];
132+
}
133+
parts[2] = "" + dt.getDate();
134+
if (parts[2].length < 2) {
135+
parts[2] = "0" + parts[2];
136+
}
137+
return parts.join("-");
138+
}
139+
140+
141+
function generateResponcePage(pageNumber, pageSize, events) {
142+
// Calculate the start index and end index based on page number and page size
143+
const startIndex = (pageNumber - 1) * pageSize;
144+
const endIndex = Math.min(startIndex + pageSize, events.length);
145+
146+
// Get the events for the current page
147+
const eventsForPage = events.slice(startIndex, endIndex);
148+
149+
// Total events and pages
150+
const totalEvents = events.length;
151+
const totalPages = Math.ceil(totalEvents / pageSize);
152+
153+
// Create the page object
154+
const page = {
155+
events: eventsForPage,
156+
page: pageNumber,
157+
pageSize: pageSize,
158+
totalEvents: totalEvents,
159+
totalPages: totalPages
160+
};
161+
return page
162+
}
163+
164+
165+
166+
module.exports = {
167+
dataIngestHandler,
168+
dataQueryHandler,
169+
dataDeleteHandler,
170+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /