|
| 1 | +/* eslint-disable react/jsx-one-expression-per-line */ |
| 2 | +import React, { useContext } from 'react'; |
| 3 | +import CommunicationsContext from '../context/OverviewContext'; |
| 4 | +import '../stylesheets/routes.css'; |
| 5 | + |
| 6 | +const RouteLocations = (props) => { |
| 7 | + const communicationsData = useContext(CommunicationsContext).overviewData; |
| 8 | + // console.log('commData (from overviewContxt):', communicationsData); |
| 9 | + |
| 10 | + // initialize an empty object resObj. |
| 11 | + // This object will store the microservice names as values and its corresponding correlatingId or correlatingid as keys. |
| 12 | + // The microservice names will be stored in array within the order it was to the database. |
| 13 | + const resObj = {}; |
| 14 | + |
| 15 | + if (communicationsData.length > 0 && communicationsData[0]._id) { |
| 16 | + // Sort the communication array from OLDEST to NEWEST documents. |
| 17 | + communicationsData.sort((a, b) => { |
| 18 | + // Note that a newer date obj IS GREATER THAN an older date obj. |
| 19 | + if (new Date(a.timeSent) > new Date(b.timeSent)) return 1; |
| 20 | + if (new Date(a.timeSent) < new Date(b.timeSent)) return -1; |
| 21 | + return 0; |
| 22 | + }); |
| 23 | + // console.log('commData (AFTER sorting):', communicationsData); |
| 24 | + |
| 25 | + // Iterate over sorted array to build up resObj. |
| 26 | + for (let i = 0; i < communicationsData.length; i += 1) { |
| 27 | + // declare a constant element and initialize it as the object at index i of the communicationsData array |
| 28 | + const element = communicationsData[i]; |
| 29 | + // Pushes the microservice name & timeSent into the resObj. |
| 30 | + // Data objects w/ same corrId will be grouped in a same array. |
| 31 | + if (resObj[element.correlatingId]) { |
| 32 | + resObj[element.correlatingId].push({ |
| 33 | + microservice_name: element.currentMicroservice, |
| 34 | + timeSent: element.timeSent |
| 35 | + }); |
| 36 | + } else { |
| 37 | + // The value that corresp. to the correlationId key is an array of obj containing name and time data. |
| 38 | + // Each obj is a data point. |
| 39 | + resObj[element.correlatingId] = [{ |
| 40 | + microservice_name: element.currentMicroservice, |
| 41 | + timeSent: element.timeSent |
| 42 | + }]; |
| 43 | + } |
| 44 | + } |
| 45 | + } else { |
| 46 | + for (let i = communicationsData.length - 1; i >= 0; i--) { |
| 47 | + const element = communicationsData[i]; |
| 48 | + if (resObj[element.correlatingId]) { |
| 49 | + resObj[element.correlatingId].push({ |
| 50 | + microservice_name: element.currentMicroservice, |
| 51 | + timeSent: element.timeSent |
| 52 | + }); |
| 53 | + } else { |
| 54 | + // The value that corresp. to the correlationId key is an array of obj containing name and time data. |
| 55 | + // Each obj is a data point. |
| 56 | + resObj[element.correlatingId] = [{ |
| 57 | + microservice_name: element.currentMicroservice, |
| 58 | + timeSent: element.timeSent |
| 59 | + }]; |
| 60 | + } |
| 61 | + // initializing the object with the first microservice |
| 62 | + } |
| 63 | + } |
| 64 | + |
| 65 | + // use Object.values to destructure locations |
| 66 | + // Each elem in tracePoints is an array of arrays, which contain objects (each of which is a data point). |
| 67 | + // Filter the array so that only subarrays w/ len > 1 are kept. |
| 68 | + // (len == 1 means there's only one point in the route. There's no meaningful data to be gained from those.) |
| 69 | + const tracePoints = Object.values(resObj).filter(subArray => subArray.length > 1); |
| 70 | + // console.log('tracePoints arr:', tracePoints); |
| 71 | + |
| 72 | + |
| 73 | + // Construct an obj that stores data necessary for calculating avg speed of requests btw 2 pts. |
| 74 | + const avgDataObj = {}; |
| 75 | + /****** Build the object here w/ nested loops ************/ |
| 76 | + /****** WARNING: tracePoints arr can be very long (100+) ************/ |
| 77 | + for (let i = 0; i < tracePoints.length; i += 1) { |
| 78 | + let subArr = tracePoints[i]; |
| 79 | + for (let j = 0; j < subArr.length; j += 1) { |
| 80 | + let currDataObj = subArr[j]; |
| 81 | + if (j < subArr.length - 1) { |
| 82 | + let nextDataObj = subArr[j + 1]; |
| 83 | + let routeName = `${currDataObj.microservice_name}-${nextDataObj.microservice_name}`; |
| 84 | + // Key/value pair that keeps COUNT of two-point routes |
| 85 | + if (!avgDataObj[`${routeName}Count`]) avgDataObj[`${routeName}Count`] = 1; |
| 86 | + else avgDataObj[`${routeName}Count`] += 1; |
| 87 | + |
| 88 | + // Key/value that accumulates TOTAL TIME a req travels btw 2 certain points |
| 89 | + let timeDiff = new Date(nextDataObj.timeSent) - new Date(currDataObj.timeSent); |
| 90 | + if (!avgDataObj[`${routeName}TotalTime`]) { |
| 91 | + avgDataObj[`${routeName}TotalTime`] = timeDiff; |
| 92 | + } |
| 93 | + else avgDataObj[`${routeName}TotalTime`] += timeDiff; |
| 94 | + |
| 95 | + // Key/value that calculates AVG TIME of travel (dividing the 2 values above) |
| 96 | + let avgTime = avgDataObj[`${routeName}TotalTime`] / avgDataObj[`${routeName}Count`]; |
| 97 | + avgDataObj[`${routeName}AvgTime`] = avgTime; |
| 98 | + } |
| 99 | + } |
| 100 | + } |
| 101 | + /** End of nested loops */ |
| 102 | + console.log('avgDataObj:', avgDataObj); |
| 103 | + /****************************************/ |
| 104 | + |
| 105 | + // Array of <divs> to be rendered. Each <div> contains route name and time difference. |
| 106 | + const resArray = []; |
| 107 | + |
| 108 | + const position = communicationsData[0].correlatingid ? 0 : tracePoints.length - 1; |
| 109 | + console.log('position for tracePoints:', position); |
| 110 | + |
| 111 | + // iterate over ONE elem in tracePoints, creating a <div> for every data obj. |
| 112 | + for (let i = 0; i < tracePoints[position].length; i += 1) { |
| 113 | + if (i !== tracePoints[position].length - 1) { |
| 114 | + // Calc time difference (when not at the end of array): |
| 115 | + // Convert time str to Date obj w/ new Date(), then get the time difference. |
| 116 | + const timeDiff = new Date(tracePoints[position][i + 1].timeSent) - new Date(tracePoints[position][i].timeSent); |
| 117 | + resArray.push( |
| 118 | + <div className="RouteCircle" key={i}> |
| 119 | + {/* Altering this <p> so it displays only microsvc_name */} |
| 120 | + <p id="routeText"> |
| 121 | + Point {i + 1}: {tracePoints[position][i].microservice_name} |
| 122 | + </p> |
| 123 | + {/* Adding another <p> that displays time difference btw curr obj and next obj */} |
| 124 | + <p id="routeTimeDiff"> |
| 125 | + {/* Time: {tracePoints[position][i].timeSent} */} |
| 126 | + Time elapsed: {timeDiff} ms |
| 127 | + </p> |
| 128 | + </div>, |
| 129 | + ); |
| 130 | + } else { |
| 131 | + // If at the end of array, don't push the timeDiff <p> to resArray (only push a <p> w/ name). |
| 132 | + resArray.push( |
| 133 | + <div className="RouteCircle" key={i}> |
| 134 | + <p id="routeText"> |
| 135 | + Point {i + 1}: {tracePoints[position][i].microservice_name} |
| 136 | + </p> |
| 137 | + </div>, |
| 138 | + ); |
| 139 | + } |
| 140 | + } |
| 141 | + // console.log('resArray: ', resArray); |
| 142 | + |
| 143 | + /**** Making a list of avg speed-related data. ********/ |
| 144 | + // const avgData = []; |
| 145 | + // Object.entries(avgDataObj).forEach((el, i) => { |
| 146 | + // avgData.push( |
| 147 | + // <span className="avgDataDetails" key={`${i}+${el[0]}`}> |
| 148 | + // {el[0]}: {el[1]} |
| 149 | + // </span> |
| 150 | + // ) |
| 151 | + // }) |
| 152 | + // console.log('avgData (array):', avgData); |
| 153 | + |
| 154 | + /**** Making CATEGORIZED lists of avg speed-related data. ********/ |
| 155 | + const avgTime = [], totalTime = [], count = []; |
| 156 | + let i = 0; // For unique keys for each <span> // |
| 157 | + |
| 158 | + for (const key in avgDataObj) { |
| 159 | + i += 1; |
| 160 | + |
| 161 | + if (key.endsWith('AvgTime')) { |
| 162 | + avgTime.push( |
| 163 | + <span className="avgDataDetails" key={i}> |
| 164 | + {key.slice(0, -7)}: {avgDataObj[key]} ms |
| 165 | + </span> |
| 166 | + ) |
| 167 | + } |
| 168 | + if (key.endsWith('TotalTime')) { |
| 169 | + totalTime.push( |
| 170 | + <span className="avgDataDetails" key={i}> |
| 171 | + {key.slice(0, -9)}: {avgDataObj[key]} ms |
| 172 | + </span> |
| 173 | + ) |
| 174 | + } |
| 175 | + if (key.endsWith('Count')) { |
| 176 | + count.push( |
| 177 | + <span className="avgDataDetails" key={i}> |
| 178 | + {key.slice(0, -5)}: {avgDataObj[key]} |
| 179 | + </span> |
| 180 | + ) |
| 181 | + } |
| 182 | + } |
| 183 | + // console.log('avgTime:', avgTime); |
| 184 | + // console.log('totalTime:', totalTime); |
| 185 | + // console.log('count:', count); |
| 186 | + /****************/ |
| 187 | + |
| 188 | + return ( |
| 189 | + <div id="routeDataArea"> |
| 190 | + {/* Data on the lastest route */} |
| 191 | + {resArray} |
| 192 | + |
| 193 | + {/* Rendering avg-speed related data */} |
| 194 | + <div id="avgData"> |
| 195 | + {/* {avgData} */} |
| 196 | + <span className="avgData-titles">Average time between points:</span> |
| 197 | + {avgTime} |
| 198 | + <span className="avgData-titles">Total time between points:</span> |
| 199 | + {totalTime} |
| 200 | + <span className="avgData-titles">Number of trips between points:</span> |
| 201 | + {count} |
| 202 | + </div> |
| 203 | + </div> |
| 204 | + ); |
| 205 | +}; |
| 206 | + |
| 207 | +export default RouteLocations; |
0 commit comments