tango-app-api-analysis-zone 3.0.0-alpha.14 → 3.0.0-alpha.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import { analysisZoneRouter } from './src/routes/analysisZone.js';
|
|
4
4
|
import { analysisZoneV2Router } from './src/routes/analysisZoneV2.js';
|
|
5
|
-
|
|
6
|
-
export { analysisZoneRouter, analysisZoneV2Router };
|
|
5
|
+
import { mobileAnalysisZoneV2Router } from './src/routes/mobileAnalysisZoneV2.js';
|
|
6
|
+
export { analysisZoneRouter, analysisZoneV2Router, mobileAnalysisZoneV2Router };
|
|
7
7
|
|
package/package.json
CHANGED
|
@@ -80,7 +80,6 @@ export const topPerformingStoresV1 = async ( req, res ) => {
|
|
|
80
80
|
'Zone Name': element.zoneName,
|
|
81
81
|
'Concentration': element.concentrationRate,
|
|
82
82
|
'AVG DwellTime': element.avgDwellTime,
|
|
83
|
-
'Overall Footfall': element.overallFootfall,
|
|
84
83
|
'Zone Footfall': element.zoneFootfall,
|
|
85
84
|
} );
|
|
86
85
|
} );
|
|
@@ -130,12 +129,11 @@ export const zoneSummaryTableV1 = async ( req, res ) => {
|
|
|
130
129
|
'Age Below 12': element.below12,
|
|
131
130
|
'Age 13-19': element['13-19'],
|
|
132
131
|
'Age 20-30': element['20-30'],
|
|
133
|
-
'Age 31-
|
|
134
|
-
'Age
|
|
135
|
-
'Age 51-60': element['51-60'],
|
|
132
|
+
'Age 31-45': element['31-45'],
|
|
133
|
+
'Age 46-59': element['46-59'],
|
|
136
134
|
'Age 60+': element['60 above'],
|
|
137
|
-
'Male': element.
|
|
138
|
-
'Female': element.
|
|
135
|
+
'Male': element.maleCount,
|
|
136
|
+
'Female': element.femaleCount,
|
|
139
137
|
} );
|
|
140
138
|
} );
|
|
141
139
|
return await download( exportdata, res );
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { logger } from 'tango-app-api-middleware';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export const zonecards = async ( req, res ) => {
|
|
5
|
+
try {
|
|
6
|
+
let reqestData = req.body;
|
|
7
|
+
let checkNoData = await returnNoData( reqestData.storeId );
|
|
8
|
+
if ( checkNoData ) {
|
|
9
|
+
return res.sendError( { error: 'No Data Found' }, 204 );
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
|
|
13
|
+
if ( checkInvalidRequest ) {
|
|
14
|
+
return res.sendError( { error: 'Invalid Date' }, 400 );
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let checkServerError = await returnServerError( reqestData.storeId );
|
|
18
|
+
if ( checkServerError ) {
|
|
19
|
+
return res.sendError( { error: 'Server Error' }, 500 );
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let result = {
|
|
23
|
+
'card': {
|
|
24
|
+
'footfall': {
|
|
25
|
+
'count': 100, // Store Footfall Count
|
|
26
|
+
'zoneName': 'Entry', // highest Zone Footfall
|
|
27
|
+
'zoneFootfallCount': 40,
|
|
28
|
+
},
|
|
29
|
+
'impression': {
|
|
30
|
+
'rate': 89.5, // Store impression rate
|
|
31
|
+
'zoneName': 'EXit', // highest Impression(Concentration)
|
|
32
|
+
'zoneImpressionRate': 40.0,
|
|
33
|
+
},
|
|
34
|
+
'bounced': {
|
|
35
|
+
'rate': 89.5, // Store bounced rate
|
|
36
|
+
'zoneName': 'EXit', // highest Bounced
|
|
37
|
+
},
|
|
38
|
+
'engagers': {
|
|
39
|
+
'rate': 89.5, // Store engagers rate
|
|
40
|
+
'zoneName': 'EXit', // highest Engagers
|
|
41
|
+
},
|
|
42
|
+
'avgDwellTime': {
|
|
43
|
+
'rate': 89.5, // Store avgDwellTime rate
|
|
44
|
+
'zoneName': 'EXit', // highest Average Dwell Time
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
return res.sendSuccess( result );
|
|
49
|
+
} catch ( error ) {
|
|
50
|
+
logger.error( { error: error, message: req.query, function: 'zonecards' } );
|
|
51
|
+
return res.sendError( { error: error }, 500 );
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
export const topPerformingZones = async ( req, res ) => {
|
|
55
|
+
try {
|
|
56
|
+
let reqestData = req.body;
|
|
57
|
+
let checkNoData = await returnNoData( reqestData.storeId );
|
|
58
|
+
if ( checkNoData ) {
|
|
59
|
+
return res.sendError( { error: 'No Data Found' }, 204 );
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
|
|
63
|
+
if ( checkInvalidRequest ) {
|
|
64
|
+
return res.sendError( { error: 'Invalid Date' }, 400 );
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let checkServerError = await returnServerError( reqestData.storeId );
|
|
68
|
+
if ( checkServerError ) {
|
|
69
|
+
return res.sendError( { error: 'Server Error' }, 500 );
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let result = {
|
|
73
|
+
'topPerformingZones': [
|
|
74
|
+
{ 'zoneName': 'zone-0', 'footfallCount': 100, 'bouncedCount': 40, 'engagersCount': 30, 'impressionRate': 50.0 },
|
|
75
|
+
{ 'zoneName': 'zone-0', 'footfallCount': 98, 'bouncedCount': 38, 'engagersCount': 28, 'impressionRate': 48.5 },
|
|
76
|
+
{ 'zoneName': 'zone-0', 'footfallCount': 96, 'bouncedCount': 36, 'engagersCount': 26, 'impressionRate': 46.5 },
|
|
77
|
+
{ 'zoneName': 'zone-0', 'footfallCount': 94, 'bouncedCount': 34, 'engagersCount': 24, 'impressionRate': 44.5 },
|
|
78
|
+
{ 'zoneName': 'zone-0', 'footfallCount': 92, 'bouncedCount': 32, 'engagersCount': 22, 'impressionRate': 42.5 },
|
|
79
|
+
],
|
|
80
|
+
};
|
|
81
|
+
return res.sendSuccess( result );
|
|
82
|
+
} catch ( error ) {
|
|
83
|
+
logger.error( { error: error, message: req.query, function: 'topPerformingZones' } );
|
|
84
|
+
return res.sendError( { error: error }, 500 );
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
export const topPerformingStores = async ( req, res ) => {
|
|
88
|
+
try {
|
|
89
|
+
let reqestData = req.body;
|
|
90
|
+
let checkNoData = await returnNoData( reqestData.storeId );
|
|
91
|
+
if ( checkNoData ) {
|
|
92
|
+
return res.sendError( { error: 'No Data Found' }, 204 );
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
|
|
96
|
+
if ( checkInvalidRequest ) {
|
|
97
|
+
return res.sendError( { error: 'Invalid Date' }, 400 );
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let checkServerError = await returnServerError( reqestData.storeId );
|
|
101
|
+
if ( checkServerError ) {
|
|
102
|
+
return res.sendError( { error: 'Server Error' }, 500 );
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let result = {
|
|
106
|
+
'topPerformingStores': [
|
|
107
|
+
{ 'storeName': 'LKST11-300', 'storeId': '11-300', 'zoneName': 'zone-0', 'zoneFootfallCount': 90, 'impressionRate': 40.4, 'avgDwellTime': 39.9 },
|
|
108
|
+
{ 'storeName': 'LKST11-301', 'storeId': '11-301', 'zoneName': 'zone-1', 'zoneFootfallCount': 90, 'impressionRate': 40.4, 'avgDwellTime': 39.9 },
|
|
109
|
+
{ 'storeName': 'LKST11-302', 'storeId': '11-302', 'zoneName': 'zone-2', 'zoneFootfallCount': 90, 'impressionRate': 40.4, 'avgDwellTime': 39.9 },
|
|
110
|
+
{ 'storeName': 'LKST11-303', 'storeId': '11-303', 'zoneName': 'zone-3', 'zoneFootfallCount': 90, 'impressionRate': 40.4, 'avgDwellTime': 39.9 },
|
|
111
|
+
{ 'storeName': 'LKST11-304', 'storeId': '11-304', 'zoneName': 'zone-4', 'zoneFootfallCount': 90, 'impressionRate': 40.4, 'avgDwellTime': 39.9 },
|
|
112
|
+
],
|
|
113
|
+
};
|
|
114
|
+
return res.sendSuccess( result );
|
|
115
|
+
} catch ( error ) {
|
|
116
|
+
logger.error( { error: error, message: req.query, function: 'topPerformingStores' } );
|
|
117
|
+
return res.sendError( { error: error }, 500 );
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export const zoneConcentrationSummary = async ( req, res ) => {
|
|
122
|
+
try {
|
|
123
|
+
let reqestData = req.body;
|
|
124
|
+
let checkNoData = await returnNoData( reqestData.storeId );
|
|
125
|
+
if ( checkNoData ) {
|
|
126
|
+
return res.sendError( { error: 'No Data Found' }, 204 );
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
|
|
130
|
+
if ( checkInvalidRequest ) {
|
|
131
|
+
return res.sendError( { error: 'Invalid Date' }, 400 );
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
let checkServerError = await returnServerError( reqestData.storeId );
|
|
135
|
+
if ( checkServerError ) {
|
|
136
|
+
return res.sendError( { error: 'Server Error' }, 500 );
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
let result = {
|
|
140
|
+
'zoneConcentrationData': [
|
|
141
|
+
{
|
|
142
|
+
'zoneName': 'zone-1',
|
|
143
|
+
'footfall': {
|
|
144
|
+
'zoneCount': 10,
|
|
145
|
+
'storeRate': 65.0,
|
|
146
|
+
},
|
|
147
|
+
'impression': {
|
|
148
|
+
'zoneRate': 10.0,
|
|
149
|
+
'storeRate': 65.0,
|
|
150
|
+
},
|
|
151
|
+
'bounced': {
|
|
152
|
+
'zoneCount': 10,
|
|
153
|
+
'storeRate': 65.0,
|
|
154
|
+
},
|
|
155
|
+
'engagers': {
|
|
156
|
+
'zoneCount': 10,
|
|
157
|
+
'storeRate': 65.0,
|
|
158
|
+
},
|
|
159
|
+
'avgDwellTime': {
|
|
160
|
+
'zoneAvgDwellTime': 10,
|
|
161
|
+
'storeAvgDwellTime': 65,
|
|
162
|
+
},
|
|
163
|
+
'ageAnalysis': [
|
|
164
|
+
{
|
|
165
|
+
'category': 'Below 12',
|
|
166
|
+
'value': 1,
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
'category': 'Age 13-19',
|
|
170
|
+
'value': 1,
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
'category': 'Age 20-30',
|
|
174
|
+
'value': 39,
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
'category': 'Age 31-45',
|
|
178
|
+
'value': 40,
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
'category': 'Age 46-59',
|
|
182
|
+
'value': 10,
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
'category': 'Above 60',
|
|
186
|
+
'value': 8,
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
'genderAnalysis': [
|
|
190
|
+
{
|
|
191
|
+
'category': 'Male',
|
|
192
|
+
'value': 50,
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
'category': 'Female',
|
|
196
|
+
'value': 50,
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
};
|
|
202
|
+
return res.sendSuccess( result );
|
|
203
|
+
} catch ( error ) {
|
|
204
|
+
logger.error( { error: error, message: req.query, function: 'zoneConcentrationSummary' } );
|
|
205
|
+
return res.sendError( { error: error }, 500 );
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
export const overallStoreConcentrationDates = async ( req, res ) => {
|
|
209
|
+
try {
|
|
210
|
+
let reqestData = req.body;
|
|
211
|
+
let checkNoData = await returnNoData( reqestData.storeId );
|
|
212
|
+
if ( checkNoData ) {
|
|
213
|
+
return res.sendError( { error: 'No Data Found' }, 204 );
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
|
|
217
|
+
if ( checkInvalidRequest ) {
|
|
218
|
+
return res.sendError( { error: 'Invalid Date' }, 400 );
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
let checkServerError = await returnServerError( reqestData.storeId );
|
|
222
|
+
if ( checkServerError ) {
|
|
223
|
+
return res.sendError( { error: 'Server Error' }, 500 );
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
let result = {
|
|
227
|
+
'overallStoreConcentrationDates': [
|
|
228
|
+
{ 'zoneDate': 'Jan 01-30' },
|
|
229
|
+
{ 'zoneDate': 'Feb 01-07' },
|
|
230
|
+
{ 'zoneDate': 'Feb 08' },
|
|
231
|
+
],
|
|
232
|
+
};
|
|
233
|
+
return res.sendSuccess( result );
|
|
234
|
+
} catch ( error ) {
|
|
235
|
+
logger.error( { error: error, message: req.query, function: 'overallStoreConcentrationDates' } );
|
|
236
|
+
return res.sendError( { error: error }, 500 );
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
export const overallStoreConcentrationHeatmap = async ( req, res ) => {
|
|
240
|
+
try {
|
|
241
|
+
let reqestData = req.body;
|
|
242
|
+
let checkNoData = await returnNoData( reqestData.storeId );
|
|
243
|
+
if ( checkNoData ) {
|
|
244
|
+
return res.sendError( { error: 'No Data Found' }, 204 );
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
|
|
248
|
+
if ( checkInvalidRequest ) {
|
|
249
|
+
return res.sendError( { error: 'Invalid Date' }, 400 );
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
let checkServerError = await returnServerError( reqestData.storeId );
|
|
253
|
+
if ( checkServerError ) {
|
|
254
|
+
return res.sendError( { error: 'Server Error' }, 500 );
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
let result = {
|
|
258
|
+
'overallStoreConcentrationData': {
|
|
259
|
+
'ImageURLs': [
|
|
260
|
+
{
|
|
261
|
+
'streamName': 'cam1',
|
|
262
|
+
'URL': 'https://devtangoretail-api.tangoeye.ai/heatmapimg1.jpeg',
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
'streamName': 'cam2',
|
|
266
|
+
'URL': 'https://devtangoretail-api.tangoeye.ai/heatmapimg2.jpeg',
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
'streamName': 'cam3',
|
|
270
|
+
'URL': 'https://devtangoretail-api.tangoeye.ai/heatmapimg3.jpeg',
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
'streamName': 'cam4',
|
|
274
|
+
'URL': 'https://devtangoretail-api.tangoeye.ai/heatmapimg4.jpeg',
|
|
275
|
+
},
|
|
276
|
+
],
|
|
277
|
+
},
|
|
278
|
+
};
|
|
279
|
+
return res.sendSuccess( result );
|
|
280
|
+
} catch ( error ) {
|
|
281
|
+
logger.error( { error: error, message: req.query, function: 'overallStoreConcentrationHeatmap' } );
|
|
282
|
+
return res.sendError( { error: error }, 500 );
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
async function returnNoData( requestData ) {
|
|
287
|
+
try {
|
|
288
|
+
if ( requestData && requestData.includes( '204' ) ) {
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
} catch ( error ) {
|
|
292
|
+
logger.error( { error: error, message: data, function: 'returnNoData' } );
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
async function returnInvalidRequest( requestData ) {
|
|
297
|
+
try {
|
|
298
|
+
if ( requestData && requestData.includes( '400' ) ) {
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
} catch ( error ) {
|
|
302
|
+
logger.error( { error: error, message: data, function: 'returnInvalidRequest' } );
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
async function returnServerError( requestData ) {
|
|
307
|
+
try {
|
|
308
|
+
if ( requestData && requestData.includes( '500' ) ) {
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
} catch ( error ) {
|
|
312
|
+
logger.error( { error: error, message: data, function: 'returnServerError' } );
|
|
313
|
+
}
|
|
314
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
// import { validate, isAllowedSessionHandler, authorize } from 'tango-app-api-middleware';
|
|
3
|
+
// import * as validationDtos from '../dtos/validation.dtos.js';
|
|
4
|
+
|
|
5
|
+
export const mobileAnalysisZoneV2Router = express.Router();
|
|
6
|
+
import {
|
|
7
|
+
zonecards,
|
|
8
|
+
topPerformingZones,
|
|
9
|
+
topPerformingStores,
|
|
10
|
+
zoneConcentrationSummary,
|
|
11
|
+
overallStoreConcentrationDates,
|
|
12
|
+
overallStoreConcentrationHeatmap,
|
|
13
|
+
} from '../controllers/mobileAnalysisZoneSampleDataV2.controllers.js';
|
|
14
|
+
|
|
15
|
+
mobileAnalysisZoneV2Router
|
|
16
|
+
.post( '/zonecards', zonecards )
|
|
17
|
+
.post( '/topPerformingZones', topPerformingZones )
|
|
18
|
+
.post( '/topPerformingStores', topPerformingStores )
|
|
19
|
+
.post( '/zoneConcentrationSummary', zoneConcentrationSummary )
|
|
20
|
+
.post( '/overallStoreConcentrationDates', overallStoreConcentrationDates )
|
|
21
|
+
.post( '/overallStoreConcentrationHeatmap', overallStoreConcentrationHeatmap );
|
|
22
|
+
export default mobileAnalysisZoneV2Router;
|