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