{"version":3,"sources":["contexts/ConfigurationContext.js","contexts/TestsContext.js","contexts/TargetsContext.js","apis/configuration.js","contexts/LocationContext.js","contexts/ApplicationStateContext.js","utilities/gtm.js","hooks/UseCounter.js","hooks/index.js","hooks/UseTesting.js","components/footer/Link.js","components/footer/Footer.js","components/header/NavBar.js","assets/img/thumbs.png","components/header/Header.js","assets/img/powered-by.jpg","components/common/About.js","components/common/AboutLink.js","components/common/Ad.js","components/common/Box.js","components/common/JitterChart.js","components/common/LatencyChart.js","components/common/Location.js","components/common/ShadowBox.js","components/common/Stat.js","components/PageTracking.js","App.js","reportWebVitals.js","hooks/UseAds.js","assets/img/start.gif","components/home/Home.js","components/global-tests/LatencyChart.js","components/global-tests/Test.js","components/global-tests/AboutAverageLatency.js","components/global-tests/AboutMaximumLatency.js","components/global-tests/AboutMinimumLatency.js","components/global-tests/Stats.js","components/global-tests/Tests.js","components/detail-test/LatencyDetail.js","components/detail-test/JitterDetail.js","components/detail-test/AboutLatency.js","components/detail-test/AboutJitter.js","components/detail-test/AboutLatencyChart.js","components/detail-test/AboutJitterChart.js","components/detail-test/Detail.js","components/detail-testing/JitterDetail.js","components/detail-testing/LatencyDetail.js","components/detail-testing/Status.js","components/detail-testing/DetailTesting.js","components/global-testing/LatencyChart.js","components/global-testing/Test.js","components/global-testing/Status.js","assets/video/as.mp4","assets/video/af.mp4","assets/video/eu.mp4","assets/video/na.mp4","assets/video/sa.mp4","assets/video/an.mp4","assets/video/oc.mp4","components/global-testing/Video.js","components/global-testing/GlobalTesting.js","index.js","utilities/latency.js","utilities/stats.js","utilities/localstorage.js","utilities/conversion.js"],"names":["ConfigurationContext","React","createContext","ConfigurationContextProvider","props","useState","targets","state","Provider","value","children","storageKey","initialState","times","testCount","averageLatency","maximumLatency","minimumLatency","calculateStats","sum","count","minimum","maximum","forEach","tests","Array","isArray","test","reducer","action","newState","type","index","resetOne","replace","setStorage","TestsContext","TestsContextProvider","useReducer","getStorage","initState","dispatch","TargetsContext","TargetsContextProvider","getConfiguration","a","json","fetch","process","response","LocationContext","initialContext","country","countryName","continent","ip","LocationContextProvider","setState","useEffect","get","Promise","all","c","configuration","sourceCountry","sourceContinent","loadedAds","ApplicationStateContext","ApplicationStateContextProvider","applicationState","applicationStateDispatch","pushPageViewEvent","path","title","window","dataLayer","push","event","pagePath","pageTitle","useCounter","minCount","maxCount","interval","onDone","setCount","intervalId","useRef","current","clearInterval","startCounter","useCallback","setInterval","UseTesting","maxTestTime","maxTests","targetDescriptions","useContext","running","setRunning","singleTest","min","max","onDoneCounting","onDoneTesting","startTesting","saveResults","results","testLatencyAsync","url","start","Link","href","className","target","rel","Footer","useLocation","pathname","includes","Fragment","style","backgroundColor","Date","getFullYear","NavBar","id","Header","src","thumbs","width","alt","fontSize","About","tooltip","Tooltip","OverlayTrigger","placement","overlay","AboutLink","label","Ad","height","Box","classes","styles","JitterChart","chartData","setChartData","j","n","length","Math","trunc","abs","data","chartType","options","legend","pointSize","series","color","hAxis","textPosition","gridlines","vAxis","format","minValue","xcount","LatencyChart","theme","position","slantedText","maxAlternation","Location","area","flag","ShadowBox","Stat","size","info","fontWeight","PageTracking","location","ads","toLowerCase","App","showAdColumn","Container","fluid","zIndex","Row","Col","top","left","reportWebVitals","onPerfEntry","Function","then","getCLS","getFID","getFCP","getLCP","getTTFB","useAds","w","d","s","l","i","getTime","f","getElementsByTagName","createElement","async","parentNode","insertBefore","document","e","XMLHttpRequest","open","onreadystatechange","t","readyState","status","text","responseText","head","appendChild","send","Home","getTargetOrdinal","to","toUpperCase","found","find","countryCode","continentCode","getTarget","getBestTarget","Accordion","Item","eventKey","Body","setData","targetIndex","Test","latency","setLatency","jitter","setJitter","hasData","calculateAverage","loc","generateID","AboutAverageLatency","AboutMaximumLatency","AboutMinimumLatency","Stats","Tests","Button","map","item","show","reverse","LatencyDetail","avg","setAverage","setMinimum","setMaximum","calculateMinimum","calculateMaximum","JitterDetail","initJitter","AboutLatency","AboutJitter","AboutLatencyChart","AboutJitterChart","Detail","useParams","class","Status","localTestTime","now","startTime","setStartTime","percent","elapsedTime","p","ProgressBar","striped","variant","DetailTesting","params","navigate","useNavigate","toInt","localTestLimit","reload","Video","autoPlay","afVideo","asVideo","euVideo","naVideo","saVideo","ocVideo","anVideo","video","GlobalTesting","activeSlide","setActiveSlide","globalTestTime","globalTestLimit","setTimeout","Carousel","indicators","controls","activeIndex","CarouselItem","baseUrl","getAttribute","history","createBrowserHistory","basename","TagManager","initialize","gtmId","ReactDOM","render","StrictMode","element","getElementById","pingAsync","performance","method","headers","Accept","end","ok","testTime","setResults","latencies","stopTime","stats","key","JSON","stringify","localStorage","setItem","getItem","parse","parsed","parseInt","isNaN"],"mappings":"oeAKaA,EAAuBC,IAAMC,cAAc,MAM3CC,EAA+B,SAACC,GAC3C,MAAgBC,mBAASC,GAAlBC,EAAP,oBAGA,OAAO,cAACP,EAAqBQ,SAAtB,CAA+BC,MAAOF,EAAtC,SAA8CH,EAAMM,Y,sBCZvDC,EAAa,gBAGbC,EAAe,CACnBC,MAAO,KACPC,UAAW,EACXC,eAAgB,EAChBC,eAAgB,EAChBC,eAAgB,GAmBZC,EAAiB,SAACX,GACtB,IAAIY,EAAM,EACNC,EAAQ,EACRC,EAAU,EACVC,EAAU,EA4Bd,OA1BAf,EAAMM,MAAMU,SAAQ,SAACC,GACfA,GAASC,MAAMC,QAAQF,IACzBA,EAAMD,SAAQ,SAACI,GACC,IAAVP,GAEFC,EAAUM,EACVL,EAAUK,IAGNA,EAAOL,IAASA,EAAUK,GAC1BA,EAAON,IAASA,EAAUM,IAEhCR,GAAOQ,EACPP,UAKNb,EAAMO,UAAYM,EAEdA,EAAQ,IACVb,EAAMQ,eAAiBI,EAAMC,GAE/Bb,EAAMU,eAAiBI,EACvBd,EAAMS,eAAiBM,EAEhBf,GAmCHqB,EAAU,SAACrB,EAAOsB,GACtB,IAAIC,EAAQ,eAAQlB,GAEpB,IAAKiB,EACH,OAAOtB,EAGT,OAAQsB,EAAOE,MACb,IAAK,QAIDD,EAF0B,kBAAjBD,EAAOG,MAhCP,SAACzB,EAAOyB,GAEvB,IAAIF,EAAWvB,EAWf,OAPKuB,EAASjB,QACZiB,EAASjB,MAAQ,IAGnBiB,EAASjB,MAAMmB,GAAS,GAGjBd,EAAeY,GAqBLG,CAAS1B,EAAOsB,EAAOG,OAxCjCpB,EA6CH,MAEF,IAAK,SACHkB,EAAQ,eAAQlB,GAEZL,EAAMM,MACRiB,EAASjB,MAAT,YAAqBN,EAAMM,OAE3BiB,EAASjB,MAAQ,GAGdY,MAAMC,QAAQI,EAASjB,MAAMgB,EAAOG,UACvCF,EAASjB,MAAMgB,EAAOG,OAAS,IAG7BH,EAAOK,QACLT,MAAMC,QAAQG,EAAOL,OACvBM,EAASjB,MAAMgB,EAAOG,OAAtB,YAAmCH,EAAOL,OAE1CM,EAASjB,MAAMgB,EAAOG,OAAS,CAACH,EAAOL,OAGrCC,MAAMC,QAAQG,EAAOL,OACvBM,EAASjB,MAAMgB,EAAOG,OAAtB,sBAAmCF,EAASjB,MAAMgB,EAAOG,QAAzD,YAAoEH,EAAOL,QAE3EM,EAASjB,MAAMgB,EAAOG,OAAtB,sBAAmCF,EAASjB,MAAMgB,EAAOG,QAAzD,CAAiEH,EAAOL,QAI5EM,EAAWZ,EAAeY,GAC1B,MAEF,QACEA,EAAWvB,EAMf,OAFA4B,YAAWxB,EAAYmB,GAEhBA,GAKIM,EAAenC,IAAMC,gBAMrBmC,EAAuB,SAACjC,GACnC,MAA0BkC,qBAAWV,EApJrB,WAEhB,IAAIrB,EAAQgC,YAAW5B,GAKvB,OAJKJ,IACHA,EAAK,eAAQK,IAGRL,EA6IuCiC,IAA9C,mBAAOhB,EAAP,KAAciB,EAAd,KACA,OAAO,cAACL,EAAa5B,SAAd,CAAuBC,MAAO,CAAEe,QAAOiB,YAAvC,SAAoDrC,EAAMM,Y,QCjKtDgC,EAAiBzC,IAAMC,cAAc,MAMrCyC,EAAyB,SAACvC,GACrC,MAAgBC,mBAASC,GAAlBC,EAAP,oBAGA,OAAO,cAACmC,EAAelC,SAAhB,CAAyBC,MAAOF,EAAhC,SAAwCH,EAAMM,Y,yBCf1CkC,EAAgB,uCAAG,8BAAAC,EAAA,6DAC1BC,EAAO,KADmB,kBAILC,MAAM,GAAD,OAAIC,eAAJ,sBAJA,cAItBC,EAJsB,gBAKfA,EAASH,OALM,OAK5BA,EAL4B,0FAUvBA,GAVuB,0DAAH,qDCMhBI,EAAkBjD,IAAMC,cAAc,MAE7CiD,EAAiB,CACrBC,QAAS,GACTC,YAAa,GACbC,UAAW,GACXC,GAAI,IAQOC,EAA0B,SAACpD,GACtC,MAA0BH,IAAMI,SAAS8C,GAAzC,mBAAO5C,EAAP,KAAckD,EAAd,KAuBA,OApBAC,qBAAU,WAER,IAAIC,EAAG,uCAAG,8BAAAd,EAAA,sEACMe,QAAQC,IAAI,CAACjB,MADnB,OACJkB,EADI,QAEJC,EAAgBD,EAAE,KAGpBL,EAAS,CACPL,QAASW,EAAcC,cACvBV,UAAWS,EAAcE,gBACzBV,GAAIQ,EAAcR,KARd,2CAAH,qDAcPI,MACC,IAGI,cAACT,EAAgB1C,SAAjB,CAA0BC,MAAOF,EAAjC,SAAyCH,EAAMM,YCxClDE,EAAe,CACnBsD,WAAW,GAUPtC,EAAU,SAACrB,EAAOsB,GACtB,IAAKA,EACH,OAAOtB,EAGT,OAAQsB,EAAOE,MACb,IAAK,MACH,IAAID,EAAQ,eAAQvB,GAEpB,OADAuB,EAASoC,WAAY,EACdpC,EAET,IAAK,QAEH,OAnBG,eAAKlB,GAqBV,QACE,OAAOL,IAMA4D,EAA0BlE,IAAMC,gBAMhCkE,EAAkC,SAAChE,GAC9C,MAAqDkC,qBAAWV,EAAShB,GAAzE,mBAAOyD,EAAP,KAAyBC,EAAzB,KACA,OACE,cAACH,EAAwB3D,SAAzB,CAAkCC,MAAO,CAAE4D,mBAAkBC,4BAA7D,SACGlE,EAAMM,a,gCC/Cb,kCAGO,IAAM6D,EAAoB,SAACC,EAAMC,GACpCC,OAAOC,UAAUC,KAAK,CAClBC,MAAO,WACPC,SAAUN,EACVO,UAAWN,M,oFCDNO,EAAa,SAACC,EAAUC,EAAUC,EAAUC,GACvD,MAA0B/E,mBAAS4E,GAAnC,mBAAO7D,EAAP,KAAciE,EAAd,KACMC,EAAaC,iBAAO,MAmC1B,OA/BA7B,qBAAU,WAEJtC,GAAS8D,GAAmC,OAAvBI,EAAWE,UAClCC,cAAcH,EAAWE,SACrBJ,GAEFA,OAGH,CAAChE,EAAO8D,EAAUC,EAAUC,IAI/B1B,qBAAU,WAGR,OAAO,WACsB,OAAvB4B,EAAWE,SACbC,cAAcH,EAAWE,YAG5B,IAUI,CACLE,aAPYC,uBAAY,WACxBL,EAAWE,QAAUI,aAAY,WAC/BP,GAAS,SAACvB,GAAD,OAAOA,EAAI,OACnBqB,KACF,CAACA,IAIF/D,MAAOA,K,gCC7CX,sE,wJCaayE,EAAa,SAACvF,EAASwF,EAAaC,EAAUX,GACzD,IAAMY,EAAqBC,qBAAWvD,KAC9BD,EAAawD,qBAAW7D,KAAxBK,SACR,EAA8BpC,oBAAS,GAAvC,mBAAO6F,EAAP,KAAgBC,EAAhB,KAIMC,EAAa9F,EAAQ+F,MAAQ/F,EAAQgG,IAIrCC,EAAiBZ,uBAAY,YAC5BS,GAAchB,GACjBA,MAED,CAACA,EAAQgB,IAINI,EAAgBb,uBAAY,WAC5BS,GAAchB,GAChBA,MAED,CAACA,EAAQgB,IAEZ,EAAgCpB,YAAW1E,EAAQ+F,IAAK/F,EAAQgG,IAAK,KAAMC,GAAnEb,EAAR,EAAQA,aAActE,EAAtB,EAAsBA,MAIhBqF,EAAed,uBAAY,WAC1BS,GACHV,IAEFS,GAAW,KACV,CAACT,EAAcU,IAclB,OAVA1C,qBAAU,WACR,IAAMgD,EAAW,uCAAG,WAAOC,GAAP,SAAA9D,EAAA,sEACZJ,EAAS,CAAEV,KAAM,SAAUC,MAAOZ,EAAOI,MAAO,CAACmF,KADrC,2CAAH,sDAIbT,GACFU,YAAiBZ,EAAmB5E,GAAOyF,IAAKd,EAAUD,EAAaY,EAAaF,KAErF,CAACpF,EAAO8E,EAASzD,EAAUsD,EAAUD,EAAaU,EAAeR,IAE7D,CACLc,MAAOL,EACPrF,MAAOA,K,s4FC7DE2F,EAAO,SAAC3G,GACnB,IAAM4G,EAAO5G,EAAM4G,KAEnB,OACE,mCACE,mBAAGC,UAAU,eAAeD,KAAMA,EAAME,OAAO,SAASC,IAAI,sBAA5D,SACG/G,EAAMM,cCJF0G,EAAS,WASpB,OARiBC,cAQJC,SAASC,SAAS,WACtB,KAIP,cAAC,IAAMC,SAAP,UACE,yBAAQP,UAAU,4BAA4BQ,MAAO,CAAEC,gBAAiB,WAAxE,UACE,gCACE,cAAC,EAAD,CAAMV,KAAK,gEAAX,4BACA,sBAAMC,UAAU,OAAhB,eACA,cAAC,EAAD,CAAMD,KAAK,6DAAX,iCAEF,8CACc,IACZ,cAAC,EAAD,CAAMA,KAAK,4DAAX,sDAIF,qGACA,mDAxBK,IAAIW,MACHC,cAuBN,+CC7BKC,G,MAAS,WACpB,OACE,mCACE,qBAAKZ,UAAU,gDAAf,SACE,sBAAKA,UAAU,kBAAf,UACE,wBACEA,UAAU,iBACVlF,KAAK,SACL,iBAAe,WACf,iBAAe,aACf,gBAAc,YACd,gBAAc,QACd,aAAW,oBAPb,SAQE,sBAAMkF,UAAU,0BAElB,qBAAKA,UAAU,2BAA2Ba,GAAG,YAA7C,SACE,qBAAIb,UAAU,aAAd,UACE,oBAAIA,UAAU,WAAd,SACE,mBAAGA,UAAU,WAAWD,KAAK,QAA7B,8BAIF,oBAAIC,UAAU,qBAAd,SACE,mBAAGA,UAAU,WAAWD,KAAK,cAA7B,0BAIF,oBAAIC,UAAU,WAAd,SACE,mBAAGA,UAAU,WAAWD,KAAK,uBAA7B,mCAIF,oBAAIC,UAAU,WAAd,SACE,mBAAGA,UAAU,WAAWD,KAAK,oBAA7B,0BAIF,oBAAIC,UAAU,WAAd,SACE,mBAAGA,UAAU,WAAWD,KAAK,aAA7B,gCAKF,oBAAIC,UAAU,WAAd,SACE,mBAAGA,UAAU,WAAWD,KAAK,eAA7B,2BAKF,oBAAIC,UAAU,WAAd,SACE,mBAAGA,UAAU,kBAAkB,eAAa,OAAOD,KAAK,IAAxD,wCCrDD,MAA0B,mCCK5Be,EAAS,WACpB,OACE,qCACE,sBAAKd,UAAU,uCAAf,UACE,8BACE,qBAAKe,IAAKC,EAAQhB,UAAU,YAAYQ,MAAO,CAAES,MAAO,QAAUC,IAAI,UAExE,qBAAKlB,UAAU,0BAA0BQ,MAAO,CAAEW,SAAU,UAA5D,6BAGA,qBAAKnB,UAAU,UAAf,SACE,qBAAKe,IChBA,8mPDgBgBf,UAAU,YAAYkB,IAAI,aAGnD,qBAAKlB,UAAU,oBAAf,SACE,cAAC,EAAD,U,wCEhBKoB,EAAQ,SAACjI,GACEA,EAAd6G,UAAR,IACMa,EAAK1H,EAAM0H,GAAK,WAEhBQ,EACJ,cAACC,EAAA,EAAD,CAAST,GAAIA,EAAb,SACE,qBAAKb,UAAU,aAAf,SAA6B7G,EAAMM,aAIvC,OACE,mCACE,cAAC8H,EAAA,EAAD,CAAyBC,UAAU,MAAMC,QAASJ,EAAlD,SACE,mBAAGtB,KAAK,qBAAR,SACE,mBAAGC,UAAU,yBAFIa,MCZda,EAAY,SAACvI,GACFA,EAAd6G,UAAR,IACMa,EAAK1H,EAAM0H,GAAK,WACdc,EAAUxI,EAAVwI,MAEFN,EACJ,cAACC,EAAA,EAAD,CAAST,GAAIA,EAAb,SACE,qBAAKb,UAAU,aAAf,SAA6B7G,EAAMM,aAIvC,OACE,mCACE,cAAC8H,EAAA,EAAD,CAAyBC,UAAU,MAAMC,QAASJ,EAAlD,SACE,mBAAGtB,KAAK,qBAAR,SAA8B4B,KADXd,MCfde,EAAK,SAACzI,GACjB,OAAO,qBAAK0H,GAAI1H,EAAM0H,GAAIL,MAAO,CAAES,MAAO,QAASY,OAAQ,YCDhDC,EAAM,SAAC3I,GAAW,IAAD,EACtB4I,EAAO,mCAA+B5I,EAAM6G,WAC5CgC,EAAM,UAAG7I,EAAMqH,aAAT,QAAkB,GAE9B,OACE,qBAAKR,UAAW+B,EAASvB,MAAOwB,EAAhC,SACG7I,EAAMM,Y,eCJAwI,EAAc,SAAC9I,GAC1B,IAAQ4B,EAAU5B,EAAV4B,MACAR,EAAUyE,qBAAW7D,KAArBZ,MACR,EAAkCnB,mBAAS,MAA3C,mBAAO8I,EAAP,KAAkBC,EAAlB,KAEA1F,qBAAU,WACR,GAAc,OAAVlC,GAAkBC,MAAMC,QAAQF,EAAMX,QAAUY,MAAMC,QAAQF,EAAMX,MAAMmB,IAAS,CAErF,IADA,IAAIqH,EAAI,GACCC,EAAI,EAAGA,EAAI9H,EAAMX,MAAMmB,GAAOuH,OAAS,IAAKD,EACnDD,EAAEzE,KAAK4E,KAAKC,MAAMD,KAAKE,IAAIlI,EAAMX,MAAMmB,GAAOsH,GAAK9H,EAAMX,MAAMmB,GAAOsH,EAAI,MAG5E,IAAIK,EAAO,CAAC,CAAC,GAAI,KACjB,IAAKL,EAAI,EAAGA,EAAID,EAAEE,SAAUD,EAC1BK,EAAK/E,KAAK,CAAC0E,EAAI,EAAGD,EAAEC,KAEtBF,EAAaO,MAEd,CAAC3H,EAAOR,IAsBX,OACE,mCACG2H,GAAaA,EAAUI,OAAS,EAC/B,cAAC,IAAD,CAAOK,UAAU,YAAY1B,MAAM,OAAOY,OAAO,OAAOa,KAAMR,EAAWU,QAvBjE,CACZC,OAAQ,OACRC,UAAW,EACXC,OAAQ,CAAC,CAAEC,MAAO,SAElBC,MAAO,CACLC,aAAc,OACdC,UAAW,CACThJ,MAAO,IAGXiJ,MAAO,CACLC,OAAQ,OACRC,SAAU,EACVH,UAAW,CACTI,OAAQ,OASN,QC5CGC,EAAe,SAACrK,GAC3B,IAAQ4B,EAAU5B,EAAV4B,MACAR,EAAUyE,qBAAW7D,KAArBZ,MACR,EAAkCnB,mBAAS,MAA3C,mBAAO8I,EAAP,KAAkBC,EAAlB,KAEA1F,qBAAU,WACR,GAAc,OAAVlC,GAAkBC,MAAMC,QAAQF,EAAMX,QAAUY,MAAMC,QAAQF,EAAMX,MAAMmB,IAAS,CAErF,IADA,IAAI2H,EAAO,CAAC,CAAC,GAAI,KACRL,EAAI,EAAGA,EAAI9H,EAAMX,MAAMmB,GAAOuH,SAAUD,EAC/CK,EAAK/E,KAAK,CAAC,GAAD,OAAI0E,EAAI,GAAK9H,EAAMX,MAAMmB,GAAOsH,KAE5CF,EAAaO,MAEd,CAAC3H,EAAOR,IAmBX,OACE,mCACG2H,GAAaA,EAAUI,OAAS,EAC/B,cAAC,IAAD,CAAOK,UAAU,cAAc1B,MAAM,OAAOY,OAAO,OAAOa,KAAMR,EAAWU,QApBnE,CACZa,MAAO,WACPZ,OAAQ,CACNa,SAAU,QAEZZ,UAAW,EACXC,OAAQ,CAAC,CAAEC,MAAO,SAClBC,MAAO,CACLU,aAAa,EACbC,eAAgB,GAElBR,MAAO,CACLC,OAAQ,OACRC,SAAU,MAQN,QClCGO,EAAW,SAAC1K,GACvB,IAEA,EAFgB6F,qBAAWvD,KACTtC,EAAV4B,OACA+I,EAAR,EAAQA,KAAM3H,EAAd,EAAcA,QAAS4H,EAAvB,EAAuBA,KAEvB,OACE,mCACE,sBAAK/D,UAAU,iCAAf,UACE,qBAAKA,UAAU,SAAf,SACE,qBAAKiB,MAAM,OAAOF,IAAG,UAAKgD,OAE5B,sBAAK/D,UAAU,qCAAf,UACE,qBAAKA,UAAU,8BAAf,SAA8C8D,IAC9C,qBAAK9D,UAAU,2BAAf,SAA2C7D,aCjBxC6H,EAAY,SAAC7K,GACxB,IAAM4I,EAAO,kCAA8B5I,EAAM6G,WACjD,OAAO,qBAAKA,UAAW+B,EAAhB,SAA0B5I,EAAMM,YCF5BwK,EAAO,SAAC9K,GACnB,IAAQqE,EAA6BrE,EAA7BqE,MAAOhE,EAAsBL,EAAtBK,MAAO0K,EAAe/K,EAAf+K,KAAMC,EAAShL,EAATgL,KAExB3D,EAAQ,GAMZ,OALI0D,GAAiB,OAATA,IACV1D,EAAQ,CAAEW,SAAU,SAKpB,sBAAKnB,UAAU,cAAcQ,MAAOA,EAApC,UACE,sBAAKR,UAAU,gCAAf,UACE,qBAAKA,UAAW,aAAcQ,MAAO,CAAEW,SAAU,OAAQiD,WAAY,QAArE,SACG5G,IAEF2G,EAAO,qBAAKnE,UAAU,OAAf,SAAuBmE,IAAc,QAE/C,sBAAKnE,UAAW,YAAaQ,MAAO,CAAEW,SAAU,SAAhD,UACGoB,KAAKC,MAAMhJ,GADd,a,QC4BO6K,EAAe,SAAClL,GAC3B,IAAImL,EAAWlE,cACPhD,EAAqB4B,qBAAW9B,KAAhCE,iBAQR,OANAX,qBAAU,WAAO,IAAD,EAxBIc,EAAMgH,EAANhH,EAyBD+G,EAASjE,SAASmE,cAzBXD,EAyBR,iBAAkCnH,QAAlC,IAAkCA,OAAlC,EAAkCA,EAAkBH,iBAApD,UAvBdM,EAAK+C,SAAS,aAAeiE,IAK5BhH,EAAK+C,SAAS,aAmBfhD,YATGG,OAAO6G,SAASjE,SArCP,SAAC9C,GACjB,OAAIA,EAAK+C,SAAS,kBACT,iBAEL/C,EAAK+C,SAAS,gBACT,sBAEL/C,EAAK+C,SAAS,kBACT,iBAEL/C,EAAK+C,SAAS,eACT,sBAGF,OAgC2BxC,CAAUwG,EAASjE,SAASmE,kBAE3D,CAACF,IAEGnL,EAAMM,UC4BAgL,EAlEI,WACjB,IAAMH,EAAWlE,cAKXsE,EAAe,WACnB,OAAIJ,EAASjE,SAASC,SAAS,YAQjC,OACE,sBAAKN,UAAU,MAAf,UACE,cAAC,IAAD,UACE,cAAC,IAAD,UACE,cAAC,IAAD,UACE,cAAC,IAAD,UACE,cAAC,IAAD,UACE,eAAC,EAAD,WACE,eAAC2E,EAAA,EAAD,CAAWC,OAAK,EAACpE,MAAO,CAAEqE,OAAQ,OAAlC,UACE,cAACC,EAAA,EAAD,CAAK9E,UAAU,yBAAf,SACE,cAAC+E,EAAA,EAAD,CAAK/E,UAAU,gBAAgBQ,MAAO,CAAEC,gBAAiB,SAAzD,SACE,sBAAKD,MAAO,CAAES,MAAO,UAArB,UACE,cAAC,EAAD,IACA,eAAC6D,EAAA,EAAD,CAAK9E,UAAU,0BAAf,UACE,cAAC+E,EAAA,EAAD,CAAK/E,UAAW0E,IAAiB,OAAS,OAA1C,SAEE,cAAC,IAAD,MAGDA,IACC,eAACK,EAAA,EAAD,CAAK/E,UAAU,WAAf,UACE,cAAC,EAAD,CAAIa,GAAG,qBACP,cAAC,EAAD,CAAIA,GAAG,wBAEP,eAKZ,cAACiE,EAAA,EAAD,UACE,cAAC,EAAD,SAGJ,qBACEjE,GAAG,mBACHL,MAAO,CACLqE,OAAQ,OACRnB,SAAU,WACVsB,IAAK,MACLC,KAAM,sBAOU,QCpEvBC,EAZS,SAAAC,GAClBA,GAAeA,aAAuBC,UACxC,6BAAqBC,MAAK,YAAkD,IAA/CC,EAA8C,EAA9CA,OAAQC,EAAsC,EAAtCA,OAAQC,EAA8B,EAA9BA,OAAQC,EAAsB,EAAtBA,OAAQC,EAAc,EAAdA,QAC3DJ,EAAOH,GACPI,EAAOJ,GACPK,EAAOL,GACPM,EAAON,GACPO,EAAQP,O,gBCmDCQ,EAtDA,WACb,IAAMrB,EAAWlE,cACjB,EAAuDpB,qBAAW9B,KAA1DE,EAAR,EAAQA,iBAAkBC,EAA1B,EAA0BA,yBAI1BZ,qBAAU,WAEJ6H,EAASjE,SAASC,SAAS,YAK3BlD,EAAiBH,aAKrB,SAAW2I,EAAGC,EAAGC,EAAGC,EAAGC,GACrBJ,EAAEG,GAAKH,EAAEG,IAAM,GACfH,EAAEG,GAAGpI,KAAK,CAAE,aAAa,IAAI+C,MAAOuF,UAAWrI,MAAO,WACtD,IAAIsI,EAAIL,EAAEM,qBAAqBL,GAAG,GAChC1D,EAAIyD,EAAEO,cAAcN,GAEtB1D,EAAEiE,OAAQ,EACVjE,EAAErB,IAAM,yDACRmF,EAAEI,WAAWC,aAAanE,EAAG8D,GAR/B,CASGzI,OAAQ+I,SAAU,SAAU,aAG/B,SAAWZ,EAAGa,GACZ,IAAIX,EAAI,IAAIY,eACZZ,EAAEa,KACA,MACA,qJACA,GAEFb,EAAEc,mBAAqB,WACrB,IAAIC,EAEF,GAAKf,EAAEgB,aACL,KAAOhB,EAAEiB,QAAUjB,EAAEiB,OAAS,KAAQ,KAAOjB,EAAEiB,WAC9CF,EAAIJ,EAAEL,cAAc,WAAWtL,KAAO,kBACxC+L,EAAEG,KAAOlB,EAAEmB,aACZR,EAAES,KAAKC,YAAYN,KAEvBf,EAAEsB,KAAK,MAhBT,CAiBG3J,OAAQ+I,UAGXnJ,EAAyB,CAAEvC,KAAM,WAChC,CAACsC,EAAiBH,UAAWI,EAA0BiH,EAASjE,YCvDtD,MAA0B,kCCQ5BgH,EAAO,WAClB1B,IACA,IAAMrB,EAAWtF,qBAAW/C,KACtB5C,EAAU2F,qBAAWvD,KAErB6L,EAAmB,SAACzG,GACxB,IAAK,IAAIwB,EAAI,EAAGA,EAAIhJ,EAAQiJ,SAAUD,EACpC,GAAIhJ,EAAQgJ,GAAGxB,KAAOA,EAAI,OAAOwB,GAgDrC,OACE,qCACE,oBAAIrC,UAAU,OAAd,yBAEA,qBAAKA,UAAU,MAAf,gFAEA,qBAAKA,UAAU,qCAAf,SACE,cAAC,IAAD,CAAMa,GAAG,mBAAmB0G,GAAE,0BAnCd,WACpB,IAAIvK,EAAkBsH,EAASjI,UAAUmL,cACrCzK,EAAgBuH,EAASnI,QAAQqL,cAErC,OAAQxK,GACN,IAAK,KAML,IAAK,GACHA,EAAkB,KAClB,MALF,IAAK,KACHA,EAAkB,KActB,OANKD,GAAmC,KAAlBA,IACpBA,EAAgB,MAlCF,SAACA,EAAeC,GAEhC,IAAIyK,EAAQpO,EAAQqO,MAAK,SAACzH,GAAD,OAAYA,EAAO0H,YAAYH,gBAAkBzK,KAC1E,OAAI0K,IAKJA,EAAQpO,EAAQqO,MAAK,SAACzH,GAAD,OAAYA,EAAO2H,cAAcJ,gBAAkBxK,MAJ/DsK,EAAiBG,EAAM5G,IASzB,EA0BAgH,CAAU9K,EAAeC,GAYuB8K,IAAnD,SACE,qBAAK/G,IAAKlB,EAAOG,UAAU,YAAYkB,IAAI,YAI/C,eAAC6G,EAAA,EAAD,CAAW/H,UAAU,aAArB,UACE,eAAC+H,EAAA,EAAUC,KAAX,CAAgBC,SAAS,IAAzB,UACE,cAACF,EAAA,EAAUjH,OAAX,oCACA,cAACiH,EAAA,EAAUG,KAAX,2xBAWF,eAACH,EAAA,EAAUC,KAAX,CAAgBC,SAAS,IAAzB,UACE,cAACF,EAAA,EAAUjH,OAAX,qBACA,cAACiH,EAAA,EAAUG,KAAX,+gBAQF,eAACH,EAAA,EAAUC,KAAX,CAAgBC,SAAS,IAAzB,UACE,cAACF,EAAA,EAAUjH,OAAX,mBACA,cAACiH,EAAA,EAAUG,KAAX,sVCjGG1E,EAAe,SAACrK,GAC3B,IAAQoB,EAAUyE,qBAAW7D,KAArBZ,MACR,EAA6BnB,mBAAS,MAAtC,mBAAO8I,EAAP,KAAkBiG,EAAlB,KACMC,EAAcjP,EAAM4B,MAI1B0B,qBAAU,WACR,GAAIlC,EAAMX,OAASW,EAAMX,MAAMwO,GAAc,CAI3C,IAFA,IAAIvC,EAAI,CAAC,CAAC,GAAI,KAELxD,EAAI,EAAGA,EAAI9H,EAAMX,MAAMwO,GAAa9F,SAAUD,EACrDwD,EAAElI,KAAK,CAAC0E,EAAI,EAAG9H,EAAMX,MAAMwO,GAAa/F,KAE1C8F,EAAQtC,MAET,CAACtL,EAAO6N,IA8BX,OACE,mCA1BO7N,EAAMX,OAASW,EAAMX,MAAMwO,IAAgBlG,GA4B9C,cAAC,IAAD,CAAOS,UAAU,cAAc1B,MAAM,OAAOY,OAAO,OAAOa,KAAMR,EAAWU,QAxB9D,CACjBC,OAAQ,OACRC,UAAW,EACXG,MAAO,CACLC,aAAc,OACdC,UAAW,CACThJ,MAAO,IAGXiJ,MAAO,CACLC,OAAQ,OACRC,SAAU,EACVH,UAAW,CACTI,OAAQ,IAGZR,OAAQ,CAAC,CAAEC,MAAO,e,OChCTqF,EAAO,SAAClP,GACnB,IAAIE,EAAU2F,qBAAWvD,KACnBlB,EAAUyE,qBAAW7D,KAArBZ,MACEQ,EAAU5B,EAAV4B,MACR,EAA8B3B,mBAAS,GAAvC,mBAAOkP,EAAP,KAAgBC,EAAhB,KACA,EAA4BnP,mBAAS,GAArC,mBAAOoP,EAAP,KAAeC,EAAf,KACA,EAA0BpP,EAAQ0B,GAE5B2N,GAFN,EAAQ5E,KAAR,EAAc3H,QAEY,OAAV5B,GAAkBC,MAAMC,QAAQF,EAAMX,QAAUY,MAAMC,QAAQF,EAAMX,MAAMmB,KAI1F0B,qBAAU,WACR,GAAIiM,EAAS,CAGX,IADA,IAAIF,EAAS,GACJnG,EAAI,EAAGA,EAAI9H,EAAMX,MAAMmB,GAAOuH,OAAS,IAAKD,EACnDmG,EAAO7K,KAAK4E,KAAKC,MAAMD,KAAKE,IAAIlI,EAAMX,MAAMmB,GAAOsH,GAAK9H,EAAMX,MAAMmB,GAAOsH,EAAI,MAIjFkG,EAAWhG,KAAKC,MAAMmG,YAAiBpO,EAAMX,MAAMmB,MACnD0N,EAAUlG,KAAKC,MAAMmG,YAAiBH,QAEvC,CAACjO,EAAOQ,EAAO2N,IASlB,OACE,qCACE,qBAAK1I,UAAU,QAAf,SACE,cAAC,EAAD,CAAUjF,MAAOA,MAEnB,cAAC,EAAD,CAAKiF,UAAU,MAAf,SACE,eAAC8E,EAAA,EAAD,WACE,cAACC,EAAA,EAAD,CAAK/E,UAAU,QAAf,SACE,cAAC,EAAD,CAAcjF,MAAOA,MAEvB,eAACgK,EAAA,EAAD,WACE,eAACD,EAAA,EAAD,WACE,cAACC,EAAA,EAAD,UACE,cAAC,EAAD,CAAMvH,MAAM,UAAUhE,MAAO8O,MAE/B,cAACvD,EAAA,EAAD,UACE,cAAC,EAAD,CAAMvH,MAAM,SAAShE,MAAOgP,SAGhC,cAAC,IAAD,CAAM3H,GAxBG,WACjB,IAAM+H,EAAMvP,EAAQ0B,GAAO8F,GAC3B,MAAM,UAAN,OAAiB+H,EAAIpE,eAsBHqE,GAActB,GAAE,0BAAqBxM,GAA/C,sCC/DC+N,EAAsB,SAAC3P,GAClC,OACE,mCACE,qBAAK6G,UAAW7G,EAAM6G,UAAtB,SACE,cAAC,EAAD,CAAOa,GAAG,gBAAV,sGCJKkI,EAAsB,SAAC5P,GAClC,OACE,mCACE,qBAAK6G,UAAW7G,EAAM6G,UAAtB,SACE,cAAC,EAAD,CAAOa,GAAG,gBAAV,wHCJKmI,EAAsB,SAAC7P,GAClC,OACE,mCACE,qBAAK6G,UAAW7G,EAAM6G,UAAtB,SACE,cAAC,EAAD,CAAOa,GAAG,gBAAV,wHCDKoI,EAAQ,SAAC9P,GACEA,EAAd6G,UAAR,IACQzF,EAAUyE,qBAAW7D,KAArBZ,MACAT,EAAmDS,EAAnDT,eAAgBE,EAAmCO,EAAnCP,eAAgBD,EAAmBQ,EAAnBR,eAExC,OACE,mCACE,eAAC+K,EAAA,EAAD,WACE,cAACC,EAAA,EAAD,UACE,cAAC,EAAD,CAAW/E,UAAU,MAArB,SACE,cAAC,EAAD,CAAMxC,MAAM,kBAAkBhE,MAAOM,EAAgBqK,KAAM,cAAC,EAAD,UAG/D,cAACY,EAAA,EAAD,UACE,cAAC,EAAD,CAAW/E,UAAU,MAArB,SACE,cAAC,EAAD,CAAMxC,MAAM,kBAAkBhE,MAAOQ,EAAgBmK,KAAM,cAAC,EAAD,UAG/D,cAACY,EAAA,EAAD,UACE,cAAC,EAAD,CAAW/E,UAAU,MAArB,SACE,cAAC,EAAD,CAAMxC,MAAM,kBAAkBhE,MAAOO,EAAgBoK,KAAM,cAAC,EAAD,gB,QClB1D+E,EAAQ,WAAO,IAAD,EACnB7P,EAAU2F,qBAAWvD,KAE3BkK,IAcA,OACE,qCACE,qBAAK3F,UAAU,kBAAf,SACE,qBAAKA,UAAU,qCAAf,SACE,cAAC,IAAD,CAAMuH,GAAE,kBAAR,SACE,eAAC4B,EAAA,EAAD,CAAQtI,GAAG,kBAAkBmC,MAAM,UAAUkB,KAAK,KAAlD,6BACkB,mBAAGlE,UAAU,+BAKrC,cAAC,EAAD,CAAOA,UAAU,SACjB,wCArBO3G,EAAQ+P,KAAI,SAACC,EAAMtO,GAAP,OACnB,qBAAiBiF,UAAU,QAA3B,SACE,cAAC,EAAD,CAAkBjF,MAAOA,EAAOuJ,SAAU,MAAOgF,MAAM,GAA5CvO,IADHA,MAKFwO,iBAeR,QAAkB,SC/BXC,EAAgB,SAACrQ,GAG5B,MAA0BC,mBAAS,GAAnC,mBAAOqQ,EAAP,KAAYC,EAAZ,KACA,EAA0BtQ,mBAAS,GAAnC,mBAAOgG,EAAP,KAAYuK,EAAZ,KACA,EAA0BvQ,mBAAS,GAAnC,mBAAOiG,EAAP,KAAYuK,EAAZ,KACQrP,EAAUyE,qBAAW7D,KAArBZ,MACAQ,EAAU5B,EAAV4B,MAmBR,OAdA0B,qBAAU,WAAO,IAAD,EAKd,IAJgB,SAAC1B,GACf,OAAiB,OAAVR,GAAkBC,MAAMC,QAAQF,EAAMX,QAAUY,MAAMC,QAAQF,EAAMX,MAAMmB,IAG9E2N,CAAQ3N,GAAQ,OAAO,KAE5B,IAAI8K,EAAC,iBAAGtL,QAAH,IAAGA,OAAH,EAAGA,EAAOX,MAAMmB,UAAhB,QAA0B,GAE/B2O,GAAW,kBAAMnH,KAAKC,MAAMmG,YAAiB9C,OAC7C8D,GAAW,kBAAMpH,KAAKC,MAAMqH,YAAiBhE,OAC7C+D,GAAW,kBAAMrH,KAAKC,MAAMsH,YAAiBjE,SAC5C,CAACtL,EAAOQ,IAGT,sBAAKiF,UAAU,sCAAf,UACE,qBAAKA,UAAU,OAAf,SACE,cAAC,EAAD,CAAMxC,MAAM,UAAUhE,MAAOiQ,EAAKvF,KAAK,SAEzC,qBAAKlE,UAAU,OAAf,SACE,cAAC,EAAD,CAAMxC,MAAM,UAAUhE,MAAO4F,EAAK8E,KAAK,SAEzC,qBAAKlE,UAAU,OAAf,SACE,cAAC,EAAD,CAAMxC,MAAM,UAAUhE,MAAO6F,EAAK6E,KAAK,aC3BlC6F,EAAe,SAAC5Q,GAG3B,MAA0BC,mBAAS,GAAnC,mBAAOqQ,EAAP,KAAYC,EAAZ,KACA,EAA0BtQ,mBAAS,GAAnC,mBAAOgG,EAAP,KAAYuK,EAAZ,KACA,EAA0BvQ,mBAAS,GAAnC,mBAAOiG,EAAP,KAAYuK,EAAZ,KACQrP,EAAUyE,qBAAW7D,KAArBZ,MACAQ,EAAU5B,EAAV4B,MAqBR,OAhBA0B,qBAAU,WAAO,IAAD,EAOd,GANgB,SAAC1B,GACf,OAAiB,OAAVR,GAAkBC,MAAMC,QAAQF,EAAMX,QAAUY,MAAMC,QAAQF,EAAMX,MAAMmB,IAK9E2N,CAAQ3N,GAAb,CAEA,IAAIyN,EA7BW,SAACjO,GAElB,IADA,IAAI6H,EAAI,GACCC,EAAI,EAAGA,EAAI9H,EAAM+H,OAAS,IAAKD,EACtCD,EAAEzE,KAAK4E,KAAKC,MAAMD,KAAKE,IAAIlI,EAAM8H,GAAK9H,EAAM8H,EAAI,MAElD,OAAOD,EAwBQ4H,CAAU,iBAACzP,QAAD,IAACA,OAAD,EAACA,EAAOX,MAAMmB,UAAd,QAAwB,IAE/C2O,GAAW,kBAAMnH,KAAKC,MAAMmG,YAAiBH,OAC7CmB,GAAW,kBAAMpH,KAAKC,MAAMqH,YAAiBrB,OAC7CoB,GAAW,kBAAMrH,KAAKC,MAAMsH,YAAiBtB,UAC5C,CAACjO,EAAOQ,IAGT,sBAAKiF,UAAU,sCAAf,UACE,qBAAKA,UAAU,OAAf,SACE,cAAC,EAAD,CAAMxC,MAAM,UAAUhE,MAAOiQ,EAAKvF,KAAK,SAEzC,qBAAKlE,UAAU,OAAf,SACE,cAAC,EAAD,CAAMxC,MAAM,UAAUhE,MAAO4F,EAAK8E,KAAK,SAEzC,qBAAKlE,UAAU,OAAf,SACE,cAAC,EAAD,CAAMxC,MAAM,UAAUhE,MAAO6F,EAAK6E,KAAK,aChDlC+F,EAAe,SAAC9Q,GAC3B,OACE,mCACE,qBAAK6G,UAAW7G,EAAM6G,UAAtB,SACE,cAAC,EAAD,CAAOa,GAAG,gBAAV,uGCJKqJ,EAAc,SAAC/Q,GAC1B,OACE,mCACE,qBAAK6G,UAAW7G,EAAM6G,UAAtB,SACE,cAAC,EAAD,CAAOa,GAAG,eAAV,oHCHKsJ,EAAoB,SAAChR,GAChC,IAAQ6G,EAA2B7G,EAA3B6G,UAAWoI,EAAgBjP,EAAhBiP,YACX7N,EAAUyE,qBAAW7D,KAArBZ,MAER,EADgByE,qBAAWvD,KACO2M,GAA1BtE,EAAR,EAAQA,KAAM3H,EAAd,EAAcA,QAEd,OACE,mCACE,qBAAK6D,UAAWA,EAAhB,SACE,cAAC,EAAD,CAAWa,GAAG,sBAAsBc,MAAM,mBAA1C,oCACuBpH,EAAMX,MAAMwO,GAAa9F,OADhD,6DAC2GwB,EAD3G,aACoH3H,UCV/GiO,GAAmB,SAACjR,GAC/B,IAAQ6G,EAA2B7G,EAA3B6G,UAAWoI,EAAgBjP,EAAhBiP,YACX7N,EAAUyE,qBAAW7D,KAArBZ,MAER,EADgByE,qBAAWvD,KACO2M,GAA1BtE,EAAR,EAAQA,KAAM3H,EAAd,EAAcA,QAEd,OACE,mCACE,qBAAK6D,UAAWA,EAAhB,SACE,cAAC,EAAD,CAAWa,GAAG,qBAAqBc,MAAM,mBAAzC,gDACmCpH,EAAMX,MAAMwO,GAAa9F,OAD5D,6DACuHwB,EADvH,aACgI3H,UCG3HkO,GAAS,WACpB,IAAQtP,EAAUuP,cAAVvP,MACJ1B,EAAU2F,qBAAWvD,KAGzB,OAFAkK,IAEKtM,GAAYA,EAAQ0B,GAMvB,qCACE,cAAC+J,EAAA,EAAD,CAAK9E,UAAU,kDAAf,SACE,cAAC+E,EAAA,EAAD,UACE,cAAC,EAAD,CAAUhK,MAAOA,QAMrB,eAAC+J,EAAA,EAAD,WACE,eAACC,EAAA,EAAD,WACE,eAACD,EAAA,EAAD,CAAK9E,UAAU,WAAf,UACE,cAAC+E,EAAA,EAAD,CAAK/E,UAAU,WAAf,SACE,sBAAMA,UAAU,oBAAhB,uBAEF,cAAC+E,EAAA,EAAD,CAAK/E,UAAU,WAAf,SACE,cAAC,EAAD,SAGJ,eAAC,EAAD,CAAWA,UAAU,MAArB,UACE,8BACE,cAAC,EAAD,CAAejF,MAAOA,MAExB,8BACE,cAAC,EAAD,CAAcA,MAAOA,MAEvB,cAAC,EAAD,CAAmBiF,UAAU,OAAOoI,YAAarN,UAGrD,eAACgK,EAAA,EAAD,WACE,eAACD,EAAA,EAAD,CAAK9E,UAAU,YAAf,UACE,cAAC+E,EAAA,EAAD,CAAK/E,UAAU,WAAf,SACE,sBAAMA,UAAU,oBAAhB,sBAEF,cAAC+E,EAAA,EAAD,CAAK/E,UAAU,WAAf,SACE,cAAC,EAAD,SAGJ,eAAC,EAAD,CAAWA,UAAU,MAArB,UACE,8BACE,cAAC,EAAD,CAAcjF,MAAOA,MAEvB,8BACE,cAAC,EAAD,CAAaA,MAAOA,MAEtB,cAAC,GAAD,CAAkBiF,UAAU,OAAOoI,YAAarN,aAItD,qBAAKwP,MAAM,2CACX,eAACzF,EAAA,EAAD,CAAK9E,UAAU,OAAf,UACE,yEACA,sDAEA,cAAC,IAAD,CAAMa,GAAG,0BAA0B0G,GAAE,kBAArC,SACE,qBAAKxG,IAAKlB,EAAOG,UAAU,YAAYkB,IAAI,gBA7DX,MCR7B6I,GAAe,SAAC5Q,GAG3B,MAA0BC,mBAAS,GAAnC,mBAAOqQ,EAAP,KAAYC,EAAZ,KACA,EAA0BtQ,mBAAS,GAAnC,mBAAOgG,EAAP,KAAYuK,EAAZ,KACA,EAA0BvQ,mBAAS,GAAnC,mBAAOiG,EAAP,KAAYuK,EAAZ,KACQrP,EAAUyE,qBAAW7D,KAArBZ,MACAQ,EAAU5B,EAAV4B,MAqBR,OAhBA0B,qBAAU,WAAO,IAAD,EAOd,GANgB,SAAC1B,GACf,OAAiB,OAAVR,GAAkBC,MAAMC,QAAQF,EAAMX,QAAUY,MAAMC,QAAQF,EAAMX,MAAMmB,IAK9E2N,CAAQ3N,GAAb,CAEA,IAAIyN,EA7BW,SAACjO,GAElB,IADA,IAAI6H,EAAI,GACCC,EAAI,EAAGA,EAAI9H,EAAM+H,OAAS,IAAKD,EACtCD,EAAEzE,KAAK4E,KAAKC,MAAMD,KAAKE,IAAIlI,EAAM8H,GAAK9H,EAAM8H,EAAI,MAElD,OAAOD,EAwBQ4H,CAAU,iBAACzP,QAAD,IAACA,OAAD,EAACA,EAAOX,MAAMmB,UAAd,QAAwB,IAE/C2O,GAAW,kBAAMnH,KAAKC,MAAMmG,YAAiBH,OAC7CmB,GAAW,kBAAMpH,KAAKC,MAAMqH,YAAiBrB,OAC7CoB,GAAW,kBAAMrH,KAAKC,MAAMsH,YAAiBtB,UAC5C,CAACjO,EAAOQ,IAGT,qBAAKiF,UAAU,MAAf,SACE,eAAC8E,EAAA,EAAD,CAAK9E,UAAU,cAAf,UACE,cAAC+E,EAAA,EAAD,CAAK/E,UAAU,qBAAf,SACE,cAAC,EAAD,CAAMxC,MAAM,UAAUhE,MAAOiQ,EAAKvF,KAAK,SAEzC,cAACa,EAAA,EAAD,CAAK/E,UAAU,qBAAf,SACE,cAAC,EAAD,CAAMxC,MAAM,UAAUhE,MAAO4F,EAAK8E,KAAK,SAEzC,cAACa,EAAA,EAAD,CAAK/E,UAAU,qBAAf,SACE,cAAC,EAAD,CAAMxC,MAAM,UAAUhE,MAAO6F,EAAK6E,KAAK,eC9CpCsF,GAAgB,SAACrQ,GAG5B,MAA0BC,mBAAS,GAAnC,mBAAOqQ,EAAP,KAAYC,EAAZ,KACA,EAA0BtQ,mBAAS,GAAnC,mBAAOgG,EAAP,KAAYuK,EAAZ,KACA,EAA0BvQ,mBAAS,GAAnC,mBAAOiG,EAAP,KAAYuK,EAAZ,KACQrP,EAAUyE,qBAAW7D,KAArBZ,MACAQ,EAAU5B,EAAV4B,MAqBR,OAhBA0B,qBAAU,WAAO,IAAD,EAOd,GAJgB,SAAC1B,GACf,OAAiB,OAAVR,GAAkBC,MAAMC,QAAQF,EAAMX,QAAUY,MAAMC,QAAQF,EAAMX,MAAMmB,IAG9E2N,CAAQ3N,GAAb,CAEA,IAAI8K,EAAC,iBAAGtL,QAAH,IAAGA,OAAH,EAAGA,EAAOX,MAAMmB,UAAhB,QAA0B,GAE/B2O,GAAW,kBAAMnH,KAAKC,MAAMmG,YAAiB9C,OAC7C8D,GAAW,kBAAMpH,KAAKC,MAAMqH,YAAiBhE,OAC7C+D,GAAW,kBAAMrH,KAAKC,MAAMsH,YAAiBjE,UAC5C,CAACtL,EAAOQ,IAGT,qBAAKiF,UAAU,MAAf,SACE,eAAC8E,EAAA,EAAD,CAAK9E,UAAU,cAAf,UACE,cAAC+E,EAAA,EAAD,CAAK/E,UAAU,qBAAf,SACE,cAAC,EAAD,CAAMxC,MAAM,UAAUhE,MAAOiQ,EAAKvF,KAAK,SAEzC,cAACa,EAAA,EAAD,CAAK/E,UAAU,qBAAf,SACE,cAAC,EAAD,CAAMxC,MAAM,UAAUhE,MAAO4F,EAAK8E,KAAK,SAEzC,cAACa,EAAA,EAAD,CAAK/E,UAAU,qBAAf,SACE,cAAC,EAAD,CAAMxC,MAAM,UAAUhE,MAAO6F,EAAK6E,KAAK,e,kBCrCpCsG,GAAS,SAACrR,GAIrB,IAAQsR,EAAkBzL,qBAAWjG,KAA7B0R,cACR,EAAkCrR,mBAASsH,KAAKgK,OAAhD,mBAAOC,EAAP,KAAkBC,EAAlB,KAEAnO,qBAAU,WAERmO,EAAalK,KAAKgK,SACjB,IAIH,IAAMG,EAAU,WACd,IAAMC,EAAcpK,KAAKgK,MAAQC,EAE7BI,EAAIxI,KAAKC,MAAOsI,EAAcL,EAAiB,KACnD,OAAOM,EAAI,GAAK,IAAMA,GAMxB,OACE,mCACE,cAACC,GAAA,EAAD,CAAaC,SAAO,EAACC,QAAQ,UAAUR,IAAKG,IAAWlJ,MAAK,UAAKkJ,IAAL,UCfrDM,GAAgB,WAC3B,IAAMC,EAASd,cACTe,EAAWC,cACTlO,EAAqB4B,qBAAW9B,KAAhCE,iBACF/D,EAAU2F,qBAAWvD,KACnBD,EAAawD,qBAAW7D,KAAxBK,SACF4M,EAAcmD,YAAMH,EAAOrQ,OACjC,EAA0CiE,qBAAWjG,KAA7C0R,EAAR,EAAQA,cAAee,EAAvB,EAAuBA,eAIjBjM,EAAgBb,uBAAY,WAEhC2M,EAAS,gBAAD,OAAiBjD,MACxB,CAACA,EAAaiD,IAETxL,EAAUjB,sBAAW,CAAEQ,IAAKgJ,EAAa/I,IAAK+I,GAAeqC,EAAee,EAAgBjM,GAA5FM,MAIFL,EAAed,uBAAY,WAC/BlD,EAAS,CAAEV,KAAM,QAASC,MAAOqN,IACjCvI,EAAMN,KACL,CAAC/D,EAAU4M,EAAavI,EAAON,IAIlC9C,qBAAU,WAEJW,EAAiBH,WACnBQ,OAAO6G,SAASmH,QAAO,KAGxB,CAACrO,EAAiBH,YAIrBR,qBAAU,WAEHW,EAAiBH,WACpBuC,MAED,CAACpC,EAAiBH,UAAWuC,IAWhC,OALUpC,EAAiBH,WAAa5D,GAAWA,EAAQ+O,GAWzD,mCACE,gCACE,qBAAKpI,UAAU,OAAf,SACE,cAAC,EAAD,CAAUjF,MAAOqN,MAEnB,eAACtD,EAAA,EAAD,WACE,eAACC,EAAA,EAAD,WACE,qBAAK/E,UAAU,+BAAf,qBACA,eAAC,EAAD,CAAWA,UAAU,MAArB,UACE,8BACE,cAAC,GAAD,CAAejF,MAAOqN,MAExB,8BACE,cAAC,EAAD,CAAcrN,MAAOqN,YAI3B,eAACrD,EAAA,EAAD,WACE,qBAAK/E,UAAU,+BAAf,oBACA,eAAC,EAAD,CAAWA,UAAU,MAArB,UACE,8BACE,cAAC,GAAD,CAAcjF,MAAOqN,MAEvB,8BACE,cAAC,EAAD,CAAarN,MAAOqN,eAK5B,qBAAKpI,UAAU,MAAf,SACE,cAAC,GAAD,CAAQoI,YAAaA,MAChB,SAnCJ,M,uDCrEE5E,GAAe,SAACrK,GAC3B,IAAQoB,EAAUyE,qBAAW7D,KAArBZ,MACR,EAA6BnB,mBAAS,MAAtC,mBAAO8I,EAAP,KAAkBiG,EAAlB,KAEA1L,qBAAU,WACR,GAAIlC,EAAMX,OAASW,EAAMX,MAAMT,EAAM4B,OAAQ,CAI3C,IAFA,IAAI8K,EAAI,CAAC,CAAC,GAAI,KAELxD,EAAI,EAAGA,EAAI9H,EAAMX,MAAMT,EAAM4B,OAAOuH,SAAUD,EACrDwD,EAAElI,KAAK,CAAC0E,EAAI,EAAG9H,EAAMX,MAAMT,EAAM4B,OAAOsH,KAE1C8F,EAAQtC,MAET,CAACtL,EAAOpB,EAAM4B,QAyBjB,OACE,mCAvBOR,EAAMX,OAASW,EAAMX,MAAMT,EAAM4B,QAuBxB,cAAC,IAAD,CAAO4H,UAAU,cAAc1B,MAAM,OAAOY,OAAO,OAAOa,KAAMR,EAAWU,QApB/E,CACZC,OAAQ,OACRC,UAAW,EACXC,OAAQ,CAAC,CAAEC,MAAO,SAClBC,MAAO,CACLC,aAAc,OACdC,UAAW,CACThJ,MAAO,IAGXiJ,MAAO,CACLC,OAAQ,OACRC,SAAU,EACVH,UAAW,CACTI,OAAQ,UC9BH8E,GAAO,SAAClP,GACnB,IAAMoB,EAAUyE,qBAAW7D,KAArBZ,MACEQ,EAAU5B,EAAV4B,MACR,EAA8B3B,mBAAS,GAAvC,mBAAOkP,EAAP,KAAgBC,EAAhB,KACA,EAA4BnP,mBAAS,GAArC,mBAAOoP,EAAP,KAAeC,EAAf,KACMC,EAAoB,OAAVnO,GAAkBC,MAAMC,QAAQF,EAAMX,QAAUY,MAAMC,QAAQF,EAAMX,MAAMmB,IAkB1F,OAdA0B,qBAAU,WACR,GAAIiM,EAAS,CAGX,IADA,IAAIF,EAAS,GACJnG,EAAI,EAAGA,EAAI9H,EAAMX,MAAMmB,GAAOuH,OAAS,IAAKD,EACnDmG,EAAO7K,KAAK4E,KAAKC,MAAMD,KAAKE,IAAIlI,EAAMX,MAAMmB,GAAOsH,GAAK9H,EAAMX,MAAMmB,GAAOsH,EAAI,MAIjFkG,EAAWhG,KAAKC,MAAMmG,YAAiBpO,EAAMX,MAAMmB,MACnD0N,EAAUlG,KAAKC,MAAMmG,YAAiBH,QAEvC,CAACjO,EAAOQ,EAAO2N,IAGhB,cAAC,EAAD,UACE,cAAC,EAAD,CAAK1I,UAAU,MAAf,SACE,eAAC8E,EAAA,EAAD,WACE,cAACC,EAAA,EAAD,CAAK/E,UAAU,GAAf,SACE,cAAC,EAAD,CAAUjF,MAAOA,MAEnB,cAACgK,EAAA,EAAD,CAAK/E,UAAU,GAAf,SACE,cAAC,GAAD,CAAcjF,MAAOA,MAEvB,cAACgK,EAAA,EAAD,CAAK/E,UAAU,QAAf,SACE,eAAC8E,EAAA,EAAD,WACE,cAACC,EAAA,EAAD,UACE,cAAC,EAAD,CAAMvH,MAAM,UAAUhE,MAAO8O,MAE/B,cAACvD,EAAA,EAAD,UACE,cAAC,EAAD,CAAMvH,MAAM,SAAShE,MAAOgP,mBCxC/BgC,GAAS,WACpB,IACQ3Q,EADUmF,qBAAW7D,KAArBZ,MACAV,UAIFgR,EAAU,WACd,IAAIE,EAAIxI,KAAKC,MAAO3I,EAAY,GAAM,KACtC,OAAOkR,EAAI,IAAM,IAAMA,GAKzB,OACE,mCACE,cAACC,GAAA,EAAD,CAAaC,SAAO,EAACC,QAAQ,UAAUR,IAAKG,IAAWlJ,MAAK,UAAKkJ,IAAL,UCtBnD,OAA0B,+BCA1B,OAA0B,+BCA1B,OAA0B,+BCA1B,OAA0B,+BCA1B,OAA0B,+BCA1B,OAA0B,+BCA1B,OAA0B,+BCW5Ba,GAAQ,SAACvS,GACpB,IAAMmL,EAAWtF,qBAAW/C,KA0B5B,OACE,mCACE,qBAAK+D,UAAU,4BAAf,UACW,OAARsE,QAAQ,IAARA,OAAA,EAAAA,EAAUjI,YACT,wBAAOwE,GAAG,aAAaI,MAAM,OAAO0K,UAAU,EAA9C,UACE,wBAAQ5K,IA7BJ,WACZ,OAAQuD,EAASjI,UAAUmL,eACzB,IAAK,KACH,OAAOoE,GACT,IAAK,KACH,OAAOC,GACT,IAAK,KACH,OAAOC,GACT,IAAK,KAQL,QACE,OAAOC,GAPT,IAAK,KACH,OAAOC,GACT,IAAK,KACH,OAAOC,GACT,IAAK,KACH,OAAOC,IAcUC,KADf,+DC3BGC,GAAgB,WAC3B,IAAM/S,EAAU2F,qBAAWvD,KACnB2B,EAAqB4B,qBAAW9B,KAAhCE,iBACR,EAA4B4B,qBAAW7D,KAA/BZ,EAAR,EAAQA,MAAOiB,EAAf,EAAeA,SACf,EAAsCpC,mBAAS,GAA/C,mBAAOiT,EAAP,KAAoBC,EAApB,KACQxS,EAAmDS,EAAnDT,eAAgBE,EAAmCO,EAAnCP,eAAgBD,EAAmBQ,EAAnBR,eAClCsR,EAAWC,cACjB,EAA4CtM,qBAAWjG,KAA/CwT,EAAR,EAAQA,eAAgBC,EAAxB,EAAwBA,gBAIlBrO,EAASO,uBAAY,WAEzB+N,YAAW,WACTpB,EAAS,mBACR,OACF,CAACA,IAEJ,EAAyBzM,sBAAW,CAAEQ,IAAK,EAAGC,IAAKhG,EAAQiJ,OAAS,GAAKiK,EAAgBC,EAAiBrO,GAAlG0B,EAAR,EAAQA,MAAO1F,EAAf,EAAeA,MAIfsC,qBAAU,WACR6P,EAAenS,KACd,CAACA,IAIJsC,qBAAU,WAEJW,EAAiBH,WACnBQ,OAAO6G,SAASmH,QAAO,MAO3BhP,qBAAU,WAER,IAAIW,EAAiBH,UAArB,CAMEzB,EAAS,CAAEV,KAAM,UAGjB2R,YAAW,WACT5M,MACC,QAIJ,CAACzC,EAAiBH,UAAWzB,EAAUqE,IAiB1C,OAAIzC,EAAiBH,UACZ,KAIP,qCACE,qBAAK+C,UAAU,OAAf,SACE,cAAC0M,GAAA,EAAD,CAAUC,YAAY,EAAOC,UAAU,EAAOC,YAAaR,EAA3D,SAnBKhT,EAAQ+P,KAAI,SAACC,EAAMtO,GAAP,OACnB,cAAC+R,GAAA,EAAD,UACE,cAAC,GAAD,CAAkB/R,MAAOA,EAAOuJ,SAAU,MAAOgF,MAAM,GAA5CvO,IADMA,UAsBnB,eAAC+J,EAAA,EAAD,CAAK9E,UAAU,OAAf,UACE,eAAC+E,EAAA,EAAD,CAAK/E,UAAU,QAAf,UACE,cAAC,GAAD,IACA,cAAC,GAAD,OAEF,eAAC+E,EAAA,EAAD,CAAK/E,UAAU,oBAAf,UACE,cAAC,EAAD,CAAWA,UAAU,OAArB,SACE,cAAC,EAAD,CAAMxC,MAAM,kBAAkBhE,MAAOM,MAGvC,cAAC,EAAD,CAAWkG,UAAU,OAArB,SACE,cAAC,EAAD,CAAMxC,MAAM,kBAAkBhE,MAAOQ,MAGvC,cAAC,EAAD,CAAWgG,UAAU,OAArB,SACE,cAAC,EAAD,CAAMxC,MAAM,kBAAkBhE,MAAOO,gBCtF3CgT,GAAUvG,SAASL,qBAAqB,QAAQ,GAAG6G,aAAa,QAEzDC,GAAUC,aAAqB,CAC1CC,SAAUpR,gBAGZqR,KAAWC,WAAW,CACpBC,MAAO,gBAGTC,IAASC,OACP,cAAC,IAAMC,WAAP,UACE,cAAC,IAAD,CAAeN,SAAQ,UAAKJ,GAAL,KAAvB,SACE,cAAC,IAAD,UACE,eAAC,IAAD,CAAOxP,KAAK,IAAImQ,QAAS,cAAC,EAAD,IAAzB,UACE,cAAC,IAAD,CAAO3S,OAAK,EAAC2S,QAAS,cAAC,EAAD,MACtB,cAAC,IAAD,CAAOnQ,KAAK,eAAemQ,QAAS,cAAC,EAAD,MACpC,cAAC,IAAD,CAAOnQ,KAAK,iBAAiBmQ,QAAS,cAAC,GAAD,MACtC,cAAC,IAAD,CAAOnQ,KAAK,qBAAqBmQ,QAAS,cAAC,GAAD,MAC1C,cAAC,IAAD,CAAOnQ,KAAK,wBAAwBmQ,QAAS,cAAC,GAAD,eAKrDlH,SAASmH,eAAe,SAG1BzI,K,0SCjDM0I,EAAS,uCAAG,WAAOhO,GAAP,mBAAAhE,EAAA,6DAEViE,EAAQgO,YAAYnD,MAFV,kBAKW5O,MAAM,WAAa8D,EAAb,uBAAmCc,KAAKgK,OAAS,CACxEoD,OAAQ,MAERC,QAAS,CAELC,OAAQ,gBAVN,cAKNhS,EALM,gBAcJA,EAASgL,OAdL,UAgBNiH,EAAMJ,YAAYnD,OAElB1O,EAASkS,GAlBH,0CAmBCD,EAAMpO,GAnBP,2FA2BP,GA3BO,0DAAH,sDAsCFF,EAAgB,uCAAG,WAC5BM,EACApG,EACAsU,EACAC,EACAjQ,GAL4B,qBAAAvC,EAAA,6DAOxByS,EAAY,GACZC,EAAW5N,KAAKgK,MAAQyD,EARA,SAWtBP,EAAU3N,GAXY,OAgBnBoC,EAAI,EAhBe,YAgBZA,EAAIxI,GAAa6G,KAAKgK,MAAQ4D,GAhBlB,iCAiBJV,EAAU3N,GAjBN,QAiBpBqI,EAjBoB,WAoBpBA,GAAWA,EAAU,IAAM,IACZ,IAAGA,EAAU,IAC5B+F,EAAU1Q,KAAK2K,GACf8F,EAAW9F,IAvBS,UAgB8BjG,EAhB9B,8BA6BxBlE,GAEAA,IA/BwB,kBAkCrBkQ,GAlCqB,4CAAH,8DCxChB1F,EAAmB,SAAC4F,GAC/B,IAAKA,IAAUA,EAAMjM,OACnB,OAAO,EAKT,IAFA,IAAIpI,EAAM,EACNC,EAAQ,EACHkI,EAAI,EAAGA,EAAIkM,EAAMjM,SAAUD,EAC9BkM,EAAMlM,KACRnI,GAAOqU,EAAMlM,GACblI,KAIJ,OAAiB,IAAVA,EAAcD,EAAMC,EAAQ,GAMxB0P,EAAmB,SAAC0E,GAC/B,IAAKA,IAAUA,EAAMjM,OACnB,OAAO,EAIT,IADA,IAAIlD,EAAMmP,EAAM,GACPlM,EAAI,EAAGA,EAAIkM,EAAMjM,SAAUD,EAC9BkM,EAAMlM,GAAKjD,IAAKA,EAAMmP,EAAMlM,IAElC,OAAOjD,GAMI0K,EAAmB,SAACyE,GAC/B,IAAKA,IAAUA,EAAMjM,OACnB,OAAO,EAIT,IADA,IAAIjD,EAAMkP,EAAM,GACPlM,EAAI,EAAGA,EAAIkM,EAAMjM,SAAUD,EAC9BkM,EAAMlM,GAAKhD,IAAKA,EAAMkP,EAAMlM,IAElC,OAAOhD,GC5CInE,EAAa,SAACsT,EAAKhV,GACvBgV,GAAQhV,IAIQ,kBAAVA,IACPA,EAAQiV,KAAKC,UAAUlV,IAE3BmV,aAAaC,QAAQJ,EAAKhV,KAMjB8B,EAAa,SAACkT,GACvB,IAAIhV,EAAQmV,aAAaE,QAAQL,GAEjC,GAAKhV,EASL,MAJiB,MAAbA,EAAM,KACNA,EAAQiV,KAAKK,MAAMtV,IAGhBA,GC7BE+R,EAAQ,SAACzF,GAClB,IAAMiJ,EAASC,SAASlJ,GACxB,OAAImJ,MAAMF,GACC,KAEJA,G","file":"static/js/main.ce0e8e7c.chunk.js","sourcesContent":["import React, { useState } from \"react\";\r\nimport targets from \"../data/config.json\";\r\n\r\n/** The context.\r\n */\r\nexport const ConfigurationContext = React.createContext(null);\r\n\r\n/** The Context Provider.\r\n *\r\n * @param {} props\r\n */\r\nexport const ConfigurationContextProvider = (props) => {\r\n const [state] = useState(targets);\r\n\r\n // Render.\r\n return {props.children};\r\n};\r\n","import React, { useReducer } from \"react\";\r\nimport { setStorage, getStorage } from \"../utilities\";\r\n\r\nconst storageKey = \"latency-tests\";\r\n\r\n// The initial state settings.\r\nconst initialState = {\r\n times: null, // Array of test times.\r\n testCount: 0,\r\n averageLatency: 0,\r\n maximumLatency: 0,\r\n minimumLatency: 0,\r\n};\r\n\r\n/** Initialize state.\r\n *\r\n */\r\nconst initState = () => {\r\n // Load from local storage if any.\r\n let state = getStorage(storageKey);\r\n if (!state) {\r\n state = { ...initialState };\r\n }\r\n\r\n return state;\r\n};\r\n\r\n/** Calculate the stats.\r\n *\r\n */\r\nconst calculateStats = (state) => {\r\n let sum = 0;\r\n let count = 0;\r\n let minimum = 0;\r\n let maximum = 0;\r\n\r\n state.times.forEach((tests) => {\r\n if (tests && Array.isArray(tests)) {\r\n tests.forEach((test) => {\r\n if (count === 0) {\r\n // First time so set initial stats.\r\n minimum = test;\r\n maximum = test;\r\n } else {\r\n // Not first so test for max and min.\r\n if (test > maximum) maximum = test;\r\n if (test < minimum) minimum = test;\r\n }\r\n sum += test;\r\n count++;\r\n });\r\n }\r\n });\r\n\r\n state.testCount = count;\r\n\r\n if (count > 0) {\r\n state.averageLatency = sum / count;\r\n }\r\n state.minimumLatency = minimum;\r\n state.maximumLatency = maximum;\r\n\r\n return state;\r\n};\r\n\r\n/** Reset the entire state.\r\n *\r\n */\r\nconst resetAll = (state) => {\r\n return initialState;\r\n};\r\n\r\n/** Reset one test set.\r\n *\r\n */\r\nconst resetOne = (state, index) => {\r\n // console.log(`resetting one ${index}`);\r\n let newState = state;\r\n\r\n //newState.times = [...state.times];\r\n\r\n if (!newState.times) {\r\n newState.times = [];\r\n }\r\n\r\n newState.times[index] = [];\r\n\r\n // Recalculate all the stats.\r\n return calculateStats(newState);\r\n};\r\n\r\n// The Reducer ---------------------------------------------------------------------------------------------------------\r\n\r\n// Action\r\n// type = \"reset\", \"append\"\r\n// payload = { index, test, tests }\r\n\r\nconst reducer = (state, action) => {\r\n let newState = { ...initialState };\r\n\r\n if (!action) {\r\n return state;\r\n }\r\n\r\n switch (action.type) {\r\n case \"reset\":\r\n // Reset one or all tests depending on whether an index is passed.\r\n if (typeof action.index === \"number\") {\r\n // Reset one.\r\n newState = resetOne(state, action.index);\r\n } else {\r\n // Reset all.\r\n newState = resetAll(state);\r\n }\r\n break;\r\n\r\n case \"append\":\r\n newState = { ...initialState };\r\n\r\n if (state.times) {\r\n newState.times = [...state.times];\r\n } else {\r\n newState.times = [];\r\n }\r\n\r\n if (!Array.isArray(newState.times[action.index])) {\r\n newState.times[action.index] = [];\r\n }\r\n\r\n if (action.replace) {\r\n if (Array.isArray(action.tests)) {\r\n newState.times[action.index] = [...action.tests];\r\n } else {\r\n newState.times[action.index] = [action.tests];\r\n }\r\n } else {\r\n if (Array.isArray(action.tests)) {\r\n newState.times[action.index] = [...newState.times[action.index], ...action.tests];\r\n } else {\r\n newState.times[action.index] = [...newState.times[action.index], action.tests];\r\n }\r\n }\r\n // Calculate the stats on the new tests.\r\n newState = calculateStats(newState);\r\n break;\r\n\r\n default:\r\n newState = state;\r\n // return state;\r\n }\r\n\r\n setStorage(storageKey, newState);\r\n\r\n return newState;\r\n};\r\n\r\n// The Context ---------------------------------------------------------------------------------------------------------\r\n\r\nexport const TestsContext = React.createContext();\r\n\r\n/** The Context Provider.\r\n *\r\n * @param {} props\r\n */\r\nexport const TestsContextProvider = (props) => {\r\n const [tests, dispatch] = useReducer(reducer, initState());\r\n return {props.children};\r\n};\r\n","import React, { useState } from \"react\";\r\nimport targets from \"../data/targets.json\";\r\n\r\n/** The context.\r\n */\r\nexport const TargetsContext = React.createContext(null);\r\n\r\n/** The Context Provider.\r\n *\r\n * @param {} props\r\n */\r\nexport const TargetsContextProvider = (props) => {\r\n const [state] = useState(targets);\r\n\r\n // Render.\r\n return {props.children};\r\n};\r\n","export const getConfiguration = async () => {\r\n let json = null;\r\n\r\n try {\r\n const response = await fetch(`${process.env.REACT_APP_BASE_URL}api/configuration`);\r\n json = await response.json();\r\n } catch (err) {\r\n // // console.log(\"Exception: \" + err);\r\n }\r\n\r\n return json;\r\n};\r\n","import React, { useEffect } from \"react\";\r\nimport { getConfiguration } from \"../apis\";\r\n\r\n/**\r\n * The context.\r\n */\r\nexport const LocationContext = React.createContext(null);\r\n\r\nconst initialContext = {\r\n country: \"\",\r\n countryName: \"\",\r\n continent: \"\",\r\n ip: \"\",\r\n};\r\n\r\n/**\r\n * The Context Provider.\r\n *\r\n * @param {} props\r\n */\r\nexport const LocationContextProvider = (props) => {\r\n const [state, setState] = React.useState(initialContext);\r\n\r\n /** Effect to get the configuration from the back-end. */\r\n useEffect(() => {\r\n // Local function to absorb async.\r\n let get = async () => {\r\n var c = await Promise.all([getConfiguration()]);\r\n let configuration = c[0];\r\n\r\n if (configuration) {\r\n setState({\r\n country: configuration.sourceCountry,\r\n continent: configuration.sourceContinent,\r\n ip: configuration.ip,\r\n });\r\n }\r\n };\r\n\r\n // Get the configuration.\r\n get();\r\n }, []);\r\n\r\n // Render.\r\n return {props.children};\r\n};\r\n","import React, { useReducer } from \"react\";\r\n\r\n// The Reducer ---------------------------------------------------------------------------------------------------------\r\n\r\nconst initialState = {\r\n loadedAds: false,\r\n};\r\n\r\nconst initState = () => {\r\n return { ...initialState };\r\n};\r\n\r\n// Action\r\n// type = \"set\", \"clear\"\r\n// payload = { index, test, tests }\r\nconst reducer = (state, action) => {\r\n if (!action) {\r\n return state;\r\n }\r\n\r\n switch (action.type) {\r\n case \"set\": {\r\n let newState = { ...state };\r\n newState.loadedAds = true;\r\n return newState;\r\n }\r\n case \"clear\": {\r\n let newState = initState();\r\n return newState;\r\n }\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\n// The Context ---------------------------------------------------------------------------------------------------------\r\n\r\nexport const ApplicationStateContext = React.createContext();\r\n\r\n/** The Context Provider.\r\n *\r\n * @param {} props\r\n */\r\nexport const ApplicationStateContextProvider = (props) => {\r\n const [applicationState, applicationStateDispatch] = useReducer(reducer, initialState);\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};\r\n","/** Push a page view event to the GTM data layer.\r\n *\r\n */\r\nexport const pushPageViewEvent = (path, title) => {\r\n window.dataLayer.push({\r\n event: \"pageview\",\r\n pagePath: path,\r\n pageTitle: title,\r\n });\r\n};\r\n","import { useEffect, useRef, useState, useCallback } from \"react\";\r\n\r\n/**\r\n * Hook to run a counter with an interval and end count.\r\n *\r\n */\r\nexport const useCounter = (minCount, maxCount, interval, onDone) => {\r\n const [count, setCount] = useState(minCount);\r\n const intervalId = useRef(null);\r\n\r\n /** Effect to watch for end of count.\r\n */\r\n useEffect(() => {\r\n // Clear interval when done counting.\r\n if (count >= maxCount && intervalId.current !== null) {\r\n clearInterval(intervalId.current);\r\n if (onDone) {\r\n // Call the done handler.\r\n onDone();\r\n }\r\n }\r\n }, [count, maxCount, interval, onDone]);\r\n\r\n /** Effect to clean up the interval on unmount.\r\n */\r\n useEffect(() => {\r\n // console.log(`counting ${minCount} to ${maxCount}`);\r\n\r\n return () => {\r\n if (intervalId.current !== null) {\r\n clearInterval(intervalId.current);\r\n }\r\n };\r\n }, []);\r\n\r\n /** Start the counter.\r\n */\r\n const start = useCallback(() => {\r\n intervalId.current = setInterval(() => {\r\n setCount((c) => c + 1);\r\n }, interval);\r\n }, [interval]);\r\n\r\n return {\r\n startCounter: start,\r\n count: count,\r\n };\r\n};\r\n","//export * from \"./UseLogger.js\";\r\nexport * from \"./UseCounter.js\";\r\nexport * from \"./UseTesting.js\";\r\nexport * from \"./xxUsePageTracking.js\";\r\n\r\n//export * from \"./UseTesting.js\";\r\n","import { useContext, useEffect, useState, useCallback } from \"react\";\r\nimport { TargetsContext, TestsContext } from \"../contexts\";\r\nimport { testLatencyAsync } from \"../utilities\";\r\nimport { useCounter } from \"./UseCounter\";\r\n\r\n//const defaultMaxTime = 2500; // The default time for all the tests for each target.\r\n//const defaultMaxTests = 8; // The default number of tests to run for each target.\r\n\r\n/**\r\n * Hook to run a series of latency tests against several targets.\r\n *\r\n */\r\n\r\nexport const UseTesting = (targets, maxTestTime, maxTests, onDone) => {\r\n const targetDescriptions = useContext(TargetsContext);\r\n const { dispatch } = useContext(TestsContext);\r\n const [running, setRunning] = useState(false);\r\n\r\n // console.log(`min and max: ${targets.min} ${targets.max}`);\r\n\r\n const singleTest = targets.min === targets.max; // Is this used for tests against single or multiple targets.\r\n\r\n /** Function: Handle done counting event.\r\n */\r\n const onDoneCounting = useCallback(() => {\r\n if (!singleTest && onDone) {\r\n onDone();\r\n }\r\n }, [onDone, singleTest]);\r\n\r\n /** Function: Handle done testing event.\r\n */\r\n const onDoneTesting = useCallback(() => {\r\n if (singleTest && onDone) {\r\n onDone();\r\n }\r\n }, [onDone, singleTest]);\r\n\r\n const { startCounter, count } = useCounter(targets.min, targets.max, 3300, onDoneCounting);\r\n\r\n /** Function: Start the testing.\r\n */\r\n const startTesting = useCallback(() => {\r\n if (!singleTest) {\r\n startCounter();\r\n }\r\n setRunning(true);\r\n }, [startCounter, singleTest]);\r\n\r\n /** Effect: Call the latency testing.\r\n */\r\n useEffect(() => {\r\n const saveResults = async (results) => {\r\n await dispatch({ type: \"append\", index: count, tests: [results] });\r\n };\r\n\r\n if (running) {\r\n testLatencyAsync(targetDescriptions[count].url, maxTests, maxTestTime, saveResults, onDoneTesting);\r\n }\r\n }, [count, running, dispatch, maxTests, maxTestTime, onDoneTesting, targetDescriptions]);\r\n\r\n return {\r\n start: startTesting,\r\n count: count,\r\n };\r\n};\r\n","import React from \"react\";\r\n\r\nexport const Link = (props) => {\r\n const href = props.href;\r\n\r\n return (\r\n <>\r\n \r\n {props.children}\r\n \r\n \r\n );\r\n};\r\n","import React from \"react\";\r\nimport { Link } from \"./Link\";\r\nimport { useLocation } from \"react-router-dom\";\r\n\r\nexport const Footer = () => {\r\n const location = useLocation();\r\n\r\n const year = () => {\r\n var dt = new Date();\r\n return dt.getFullYear();\r\n };\r\n\r\n // Don't show if we're showing the testing view.\r\n if (location.pathname.includes(\"testing\")) {\r\n return null;\r\n }\r\n\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n","import React from \"react\";\r\nimport \"./navbar.css\";\r\n\r\nexport const NavBar = () => {\r\n return (\r\n <>\r\n \r\n \r\n );\r\n};\r\n","export default __webpack_public_path__ + \"static/media/thumbs.aad2fa99.png\";","import React from \"react\";\r\nimport { NavBar } from \"./NavBar\";\r\nimport thumbs from \"../../assets/img/thumbs.png\";\r\nimport poweredBy from \"../../assets/img/powered-by.jpg\";\r\n\r\nexport const Header = () => {\r\n return (\r\n <>\r\n
\r\n
\r\n ...\r\n
\r\n
\r\n Speed Test BETA\r\n
\r\n
\r\n ...\r\n
\r\n
\r\n
\r\n \r\n
\r\n \r\n );\r\n};\r\n","export default \"data:image/jpeg;base64,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\"","import React from \"react\";\r\nimport OverlayTrigger from \"react-bootstrap/OverlayTrigger\";\r\nimport Tooltip from \"react-bootstrap/Tooltip\";\r\n\r\nexport const About = (props) => {\r\n const { className } = props;\r\n const id = props.id + \"-tooltip\";\r\n\r\n const tooltip = (\r\n \r\n
{props.children}
\r\n
\r\n );\r\n\r\n return (\r\n <>\r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n","import React from \"react\";\r\nimport OverlayTrigger from \"react-bootstrap/OverlayTrigger\";\r\nimport Tooltip from \"react-bootstrap/Tooltip\";\r\n\r\nexport const AboutLink = (props) => {\r\n const { className } = props;\r\n const id = props.id + \"-tooltip\";\r\n const { label } = props;\r\n\r\n const tooltip = (\r\n \r\n
{props.children}
\r\n
\r\n );\r\n\r\n return (\r\n <>\r\n \r\n {label}\r\n \r\n \r\n );\r\n};\r\n\r\n// import React from \"react\";\r\n\r\n// export const AboutLink = (props) => {\r\n// const { className } = props;\r\n// const id = props.id + \"-about-link\";\r\n\r\n// return (\r\n// <>\r\n{\r\n /*
\r\n \r\n About this chart\r\n \r\n \r\n \r\n
{props.children}
\r\n
\r\n
*/\r\n}\r\n// \r\n// );\r\n// };\r\n","import React from \"react\";\r\n\r\nexport const Ad = (props) => {\r\n return
;\r\n};\r\n","import React from \"react\";\r\n\r\nexport const Box = (props) => {\r\n const classes = ` bg-white rounded border ${props.className}`;\r\n const styles = props.style ?? {};\r\n\r\n return (\r\n
\r\n {props.children}\r\n
\r\n );\r\n};\r\n","import React, { useEffect, useContext, useState } from \"react\";\r\nimport { Chart } from \"react-google-charts\";\r\nimport { TestsContext } from \"../../contexts\";\r\n\r\nexport const JitterChart = (props) => {\r\n const { index } = props;\r\n const { tests } = useContext(TestsContext);\r\n const [chartData, setChartData] = useState(null);\r\n\r\n useEffect(() => {\r\n if (tests !== null && Array.isArray(tests.times) && Array.isArray(tests.times[index])) {\r\n let j = [];\r\n for (var n = 0; n < tests.times[index].length - 1; ++n) {\r\n j.push(Math.trunc(Math.abs(tests.times[index][n] - tests.times[index][n + 1])));\r\n }\r\n\r\n var data = [[\"\", \"\"]];\r\n for (n = 0; n < j.length; ++n) {\r\n data.push([n + 1, j[n]]);\r\n }\r\n setChartData(data);\r\n }\r\n }, [index, tests]);\r\n\r\n var options = {\r\n legend: \"none\",\r\n pointSize: 3,\r\n series: [{ color: \"grey\" }],\r\n\r\n hAxis: {\r\n textPosition: \"none\",\r\n gridlines: {\r\n count: 1,\r\n },\r\n },\r\n vAxis: {\r\n format: \"# ms\",\r\n minValue: 0,\r\n gridlines: {\r\n xcount: 1,\r\n },\r\n },\r\n };\r\n\r\n return (\r\n <>\r\n {chartData && chartData.length > 1 ? (\r\n \r\n ) : null}\r\n \r\n );\r\n};\r\n","import React, { useEffect, useContext, useState } from \"react\";\r\nimport { Chart } from \"react-google-charts\";\r\nimport { TestsContext } from \"../../contexts\";\r\n\r\nexport const LatencyChart = (props) => {\r\n const { index } = props;\r\n const { tests } = useContext(TestsContext);\r\n const [chartData, setChartData] = useState(null);\r\n\r\n useEffect(() => {\r\n if (tests !== null && Array.isArray(tests.times) && Array.isArray(tests.times[index])) {\r\n var data = [[\"\", \"\"]];\r\n for (var n = 0; n < tests.times[index].length; ++n) {\r\n data.push([`${n + 1}`, tests.times[index][n]]);\r\n }\r\n setChartData(data);\r\n }\r\n }, [index, tests]);\r\n\r\n var options = {\r\n theme: \"material\",\r\n legend: {\r\n position: \"none\",\r\n },\r\n pointSize: 3,\r\n series: [{ color: \"grey\" }],\r\n hAxis: {\r\n slantedText: false,\r\n maxAlternation: 1,\r\n },\r\n vAxis: {\r\n format: \"# ms\",\r\n minValue: 0,\r\n },\r\n };\r\n\r\n return (\r\n <>\r\n {chartData && chartData.length > 1 ? (\r\n \r\n ) : null}\r\n \r\n );\r\n};\r\n","import React, { useContext } from \"react\";\r\nimport { TargetsContext } from \"../../contexts\";\r\n\r\n/** Init the data for the chart.\r\n *\r\n */\r\nexport const Location = (props) => {\r\n const targets = useContext(TargetsContext);\r\n const { index } = props;\r\n const { area, country, flag } = targets[index];\r\n\r\n return (\r\n <>\r\n
\r\n
\r\n \r\n
\r\n
\r\n
{area}
\r\n
{country}
\r\n
\r\n
\r\n \r\n );\r\n};\r\n","import React from \"react\";\r\n\r\nexport const ShadowBox = (props) => {\r\n const classes = `shadow bg-white rounded ${props.className}`;\r\n return
{props.children}
;\r\n};\r\n","import React from \"react\";\r\n\r\nexport const Stat = (props) => {\r\n const { title, value, size, info } = props;\r\n\r\n let style = {};\r\n if (size && size === \"sm\") {\r\n style = { fontSize: \".8em\" };\r\n } else {\r\n // className = \" text-center\";\r\n }\r\n return (\r\n
\r\n
\r\n
\r\n {title}\r\n
\r\n {info ?
{info}
: null}\r\n
\r\n
\r\n {Math.trunc(value)} ms\r\n
\r\n
\r\n );\r\n};\r\n","import { useContext, useEffect } from \"react\";\r\nimport { useLocation } from \"react-router-dom\";\r\nimport { pushPageViewEvent } from \"../utilities/gtm\";\r\nimport { ApplicationStateContext } from \"../contexts\";\r\n\r\n/** Make a page title for the GA event.\r\n */\r\nconst pageTitle = (path) => {\r\n if (path.includes(\"global-testing\")) {\r\n return \"Global Testing\";\r\n }\r\n if (path.includes(\"global-tests\")) {\r\n return \"Global Test Results\";\r\n }\r\n if (path.includes(\"detail-testing\")) {\r\n return \"Detail Testing\";\r\n }\r\n if (path.includes(\"detail-test\")) {\r\n return \"Detail Test Results\";\r\n }\r\n\r\n return \"Home\";\r\n};\r\n\r\n/** Determine if we should note this page view.\r\n *\r\n */\r\nconst shouldReport = (path, ads) => {\r\n // A testing page with no ads.\r\n if (path.includes(\"testing\") && !ads) {\r\n return true;\r\n }\r\n\r\n // Not a testing page.\r\n if (!path.includes(\"testing\")) {\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\n/** Make a page path for the GA event. Just uses the window location.\r\n */\r\nconst pagePath = () => {\r\n return window.location.pathname;\r\n};\r\n\r\nexport const PageTracking = (props) => {\r\n let location = useLocation();\r\n const { applicationState } = useContext(ApplicationStateContext);\r\n\r\n useEffect(() => {\r\n if (shouldReport(location.pathname.toLowerCase(), applicationState?.loadedAds ?? true)) {\r\n pushPageViewEvent(pagePath(), pageTitle(location.pathname.toLowerCase()));\r\n }\r\n }, [location]);\r\n\r\n return props.children;\r\n};\r\n","//import usePageTracking from \"./hooks/xUsePageTracking\";\r\nimport \"./App.css\";\r\nimport \"./App.css\";\r\nimport \"bootstrap/dist/css/bootstrap.min.css\";\r\nimport {\r\n ConfigurationContextProvider,\r\n TestsContextProvider,\r\n TargetsContextProvider,\r\n LocationContextProvider,\r\n ApplicationStateContextProvider,\r\n} from \"./contexts\";\r\nimport { Outlet, useLocation } from \"react-router-dom\";\r\nimport { Footer } from \"./components/footer/Footer.js\";\r\nimport { Header } from \"./components/header/Header.js\";\r\nimport { Row, Col, Container } from \"react-bootstrap\";\r\nimport { Ad } from \"./components/common\";\r\n//import { usePageTracking } from \"./hooks\";\r\nimport { PageTracking } from \"./components/PageTracking\";\r\n\r\nexport const App = () => {\r\n const location = useLocation();\r\n // usePageTracking();\r\n\r\n /** Function: Should the ad column show?\r\n */\r\n const showAdColumn = () => {\r\n if (location.pathname.includes(\"testing\")) {\r\n return false;\r\n }\r\n return true;\r\n };\r\n\r\n /** Rendering\r\n */\r\n return (\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n \r\n \r\n {/* View provided by router. */}\r\n \r\n \r\n {/* Ads */}\r\n {showAdColumn() ? (\r\n \r\n \r\n \r\n \r\n ) : null}\r\n \r\n
\r\n \r\n
\r\n \r\n
\r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n {\" \"}\r\n \r\n );\r\n};\r\n\r\nexport default App;\r\n","const reportWebVitals = onPerfEntry => {\r\n if (onPerfEntry && onPerfEntry instanceof Function) {\r\n import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {\r\n getCLS(onPerfEntry);\r\n getFID(onPerfEntry);\r\n getFCP(onPerfEntry);\r\n getLCP(onPerfEntry);\r\n getTTFB(onPerfEntry);\r\n });\r\n }\r\n};\r\n\r\nexport default reportWebVitals;\r\n","import { useEffect, useContext } from \"react\";\r\nimport { useLocation } from \"react-router-dom\";\r\nimport { ApplicationStateContext } from \"../contexts\";\r\n\r\nconst useAds = () => {\r\n const location = useLocation();\r\n const { applicationState, applicationStateDispatch } = useContext(ApplicationStateContext);\r\n\r\n /** Effect: Load the ads though Google Tag Manager.\r\n */\r\n useEffect(() => {\r\n // No ads on the testing views.\r\n if (location.pathname.includes(\"testing\")) {\r\n return;\r\n }\r\n\r\n // Only load them once.\r\n if (applicationState.loadedAds) {\r\n return;\r\n }\r\n\r\n // Fire up Google Tag Manager.\r\n (function (w, d, s, l, i) {\r\n w[l] = w[l] || [];\r\n w[l].push({ \"gtm.start\": new Date().getTime(), event: \"gtm.js\" });\r\n var f = d.getElementsByTagName(s)[0],\r\n j = d.createElement(s),\r\n dl = l !== \"dataLayer\" ? \"&l=\" + l : \"\";\r\n j.async = true;\r\n j.src = \"https://www.googletagmanager.com/gtm.js?id=\" + i + dl;\r\n f.parentNode.insertBefore(j, f);\r\n })(window, document, \"script\", \"dataLayer\", \"GTM-T6SRVZK\");\r\n\r\n // GTM migration\r\n (function (w, e) {\r\n var s = new XMLHttpRequest();\r\n s.open(\r\n \"GET\",\r\n \"https://api.enthusiastgaming.net/scripts/cdn.enthusiast.gg/script/eg-aps/release/eg-aps-bootstrap-v2.0.0.bundle.js?site=systemrequirementslab.com\",\r\n !0\r\n );\r\n s.onreadystatechange = function () {\r\n var t;\r\n let x =\r\n 4 == s.readyState &&\r\n ((200 <= s.status && s.status < 300) || 304 == s.status) &&\r\n (((t = e.createElement(\"script\")).type = \"text/javascript\"),\r\n (t.text = s.responseText),\r\n e.head.appendChild(t));\r\n };\r\n s.send(null);\r\n })(window, document);\r\n\r\n // Set the ad state.\r\n applicationStateDispatch({ type: \"set\" });\r\n }, [applicationState.loadedAds, applicationStateDispatch, location.pathname]);\r\n};\r\n\r\nexport default useAds;\r\n","export default __webpack_public_path__ + \"static/media/start.aebeacab.gif\";","import React, { useContext } from \"react\";\r\nimport { Accordion } from \"react-bootstrap\";\r\nimport { Link } from \"react-router-dom\";\r\nimport useAds from \"../../hooks/UseAds\";\r\nimport start from \"../../assets/img/start.gif\";\r\nimport { LocationContext } from \"../../contexts\";\r\nimport { TargetsContext } from \"../../contexts\";\r\n\r\nexport const Home = () => {\r\n useAds();\r\n const location = useContext(LocationContext);\r\n const targets = useContext(TargetsContext);\r\n\r\n const getTargetOrdinal = (id) => {\r\n for (let n = 0; n < targets.length; ++n) {\r\n if (targets[n].id === id) return n;\r\n }\r\n };\r\n\r\n const getTarget = (sourceCountry, sourceContinent) => {\r\n // Look for a country match in targets.\r\n let found = targets.find((target) => target.countryCode.toUpperCase() === sourceCountry);\r\n if (found) {\r\n return getTargetOrdinal(found.id);\r\n }\r\n\r\n // Look for a continent match in targets.\r\n found = targets.find((target) => target.continentCode.toUpperCase() === sourceContinent);\r\n if (found) {\r\n return getTargetOrdinal(found.id);\r\n }\r\n\r\n return 0;\r\n };\r\n\r\n const getBestTarget = () => {\r\n let sourceContinent = location.continent.toUpperCase();\r\n let sourceCountry = location.country.toUpperCase();\r\n\r\n switch (sourceContinent) {\r\n case \"SA\":\r\n sourceContinent = \"NA\";\r\n break;\r\n case \"AN\":\r\n sourceContinent = \"AF\";\r\n break;\r\n case \"\":\r\n sourceContinent = \"NA\";\r\n break;\r\n default:\r\n }\r\n\r\n if (!sourceCountry || sourceCountry === \"\") {\r\n sourceCountry = \"US\";\r\n }\r\n\r\n // return getTarget(\"JP\", \"AS\");\r\n\r\n return getTarget(sourceCountry, sourceContinent);\r\n };\r\n\r\n // Render.\r\n\r\n return (\r\n <>\r\n

Do You Lag?

\r\n\r\n
Don't be that person. In just 5 seconds you can test your Latency.
\r\n\r\n
\r\n \r\n ...\r\n \r\n
\r\n\r\n \r\n \r\n Bandwidth and Latency\r\n \r\n Let’s use an analogy of a highway. Bandwidth is the number of lanes on the highway. So, an 16-lane highway\r\n has more capacity or can handle more traffic than a 2-lane highway. The higher the bandwidth (lanes), the\r\n more traffic can move from one location to another during a specific timeframe. Bandwidth is the most used\r\n value for internet speed but it really measures the volume of information that can be transferred over a\r\n connection in a set amount of time (i.e. 80 Mbps Download and 10 Mbps Upload speed). Latency is a measure of\r\n how fast the cars travel on the highway. It is usually measured in milliseconds (ms). The lower the Latency\r\n value, the better your speed. It is a measure of how fast a packet of information goes between your location\r\n to a specific server.\r\n \r\n \r\n \r\n Jitter\r\n \r\n Jitter measures stability or the VARIATION, over time, of Latency. Data packets are sent in a continuous\r\n steady stream and are spaced evenly apart. But unforeseen issues like network congestion may alter this\r\n steady stream, or the delay between each packet can fluctuate instead of remaining constant. Kind of like\r\n rush hour traffic in Los Angeles. You may have experienced these problems on a VOIP or video conference if\r\n you lose a connection for a second or more. You want a stable connection or low Jitter.\r\n \r\n \r\n \r\n Ping\r\n \r\n Ping, which has its roots in active sonar (think submarine movies), is the signal transmitted across the\r\n network to another computer. This other computer then sends its own signal back, which is another ping. The\r\n signal is the ping. Think of Ping as a car. And the measurement of the car’s round trip is Latency.\r\n \r\n \r\n \r\n \r\n );\r\n};\r\n","import React, { useContext, useEffect, useState } from \"react\";\r\nimport { Chart } from \"react-google-charts\";\r\nimport { TestsContext } from \"../../contexts\";\r\n\r\nexport const LatencyChart = (props) => {\r\n const { tests } = useContext(TestsContext);\r\n const [chartData, setData] = useState(null);\r\n const targetIndex = props.index;\r\n\r\n /** Effect: Get and format the data for the chart.\r\n */\r\n useEffect(() => {\r\n if (tests.times && tests.times[targetIndex]) {\r\n // Set the chart data.\r\n let d = [[\"\", \"\"]];\r\n\r\n for (var n = 0; n < tests.times[targetIndex].length; ++n) {\r\n d.push([n + 1, tests.times[targetIndex][n]]);\r\n }\r\n setData(d);\r\n }\r\n }, [tests, targetIndex]);\r\n\r\n /** Function: Is there any data to display?\r\n */\r\n const hasData = () => {\r\n return tests.times && tests.times[targetIndex] && chartData;\r\n };\r\n\r\n // Google chart options.\r\n var chartOptions = {\r\n legend: \"none\",\r\n pointSize: 3,\r\n hAxis: {\r\n textPosition: \"none\",\r\n gridlines: {\r\n count: 1,\r\n },\r\n },\r\n vAxis: {\r\n format: \"# ms\",\r\n minValue: 0,\r\n gridlines: {\r\n xcount: 1,\r\n },\r\n },\r\n series: [{ color: \"grey\" }],\r\n };\r\n\r\n // Render.\r\n\r\n return (\r\n <>\r\n {hasData() && (\r\n \r\n )}\r\n \r\n );\r\n};\r\n","import React, { useContext, useEffect, useState } from \"react\";\r\nimport { LatencyChart } from \"./LatencyChart\";\r\nimport { TestsContext, TargetsContext } from \"../../contexts\";\r\nimport { Stat, Box } from \"../common\";\r\nimport { calculateAverage } from \"../../utilities\";\r\nimport { Link } from \"react-router-dom\";\r\nimport { Location } from \"../common\";\r\nimport { Row, Col } from \"react-bootstrap\";\r\n\r\n/** Init the data for the chart.\r\n *\r\n */\r\n//const initJitter = (tests) => {};\r\n\r\nexport const Test = (props) => {\r\n let targets = useContext(TargetsContext);\r\n let { tests } = useContext(TestsContext);\r\n const { index } = props;\r\n const [latency, setLatency] = useState(0);\r\n const [jitter, setJitter] = useState(0);\r\n const { area, country } = targets[index];\r\n\r\n const hasData = tests !== null && Array.isArray(tests.times) && Array.isArray(tests.times[index]);\r\n\r\n /** Initialize data and stats.\r\n */\r\n useEffect(() => {\r\n if (hasData) {\r\n // Calculate the jitter from the times data.\r\n let jitter = [];\r\n for (var n = 0; n < tests.times[index].length - 1; ++n) {\r\n jitter.push(Math.trunc(Math.abs(tests.times[index][n] - tests.times[index][n + 1])));\r\n }\r\n\r\n // Get the latency and jitter averages.\r\n setLatency(Math.trunc(calculateAverage(tests.times[index])));\r\n setJitter(Math.trunc(calculateAverage(jitter)));\r\n }\r\n }, [tests, index, hasData]);\r\n\r\n /** Generate a tag id from the location.\r\n */\r\n const generateID = () => {\r\n const loc = targets[index].id;\r\n return `detail-${loc.toLowerCase()}`;\r\n };\r\n\r\n return (\r\n <>\r\n
\r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n More Details\r\n \r\n \r\n \r\n \r\n );\r\n};\r\n","import React from \"react\";\r\nimport { About } from \"../common\";\r\n\r\nexport const AboutAverageLatency = (props) => {\r\n return (\r\n <>\r\n
\r\n \r\n Global average latency is the average of all latency measurements to all locations.\r\n \r\n
\r\n \r\n );\r\n};\r\n","import React from \"react\";\r\nimport { About } from \"../common\";\r\n\r\nexport const AboutMaximumLatency = (props) => {\r\n return (\r\n <>\r\n
\r\n \r\n Global maximum latency is the maximum (slowest) latency of all latency measurements to all locations.\r\n \r\n
\r\n \r\n );\r\n};\r\n","import React from \"react\";\r\nimport { About } from \"../common\";\r\n\r\nexport const AboutMinimumLatency = (props) => {\r\n return (\r\n <>\r\n
\r\n \r\n Global minimum latency is the minimum (fastest) latency of all latency measurements to all locations.\r\n \r\n
\r\n \r\n );\r\n};\r\n","import React, { useContext } from \"react\";\r\nimport { TestsContext } from \"../../contexts\";\r\nimport { ShadowBox, Stat } from \"../common\";\r\nimport { AboutMaximumLatency, AboutAverageLatency, AboutMinimumLatency } from \".\";\r\nimport { Row, Col } from \"react-bootstrap\";\r\n\r\nexport const Stats = (props) => {\r\n const { className } = props;\r\n const { tests } = useContext(TestsContext);\r\n const { averageLatency, minimumLatency, maximumLatency } = tests;\r\n\r\n return (\r\n <>\r\n \r\n \r\n \r\n } />\r\n \r\n \r\n \r\n \r\n } />\r\n \r\n \r\n \r\n \r\n } />\r\n \r\n \r\n \r\n \r\n );\r\n};\r\n","import React, { useContext, useEffect } from \"react\";\r\nimport { TargetsContext } from \"../../contexts\";\r\nimport { Test } from \"./Test.js\";\r\nimport useAds from \"../../hooks/UseAds\";\r\nimport { Link } from \"react-router-dom\";\r\nimport { Stats } from \"./Stats\";\r\nimport { Button } from \"react-bootstrap\";\r\n\r\nexport const Tests = () => {\r\n const targets = useContext(TargetsContext);\r\n\r\n useAds();\r\n\r\n /** Function: Map test data to list.\r\n */\r\n const mapper = () => {\r\n var ar = targets.map((item, index) => (\r\n
\r\n \r\n
\r\n ));\r\n\r\n return ar.reverse();\r\n };\r\n\r\n return (\r\n <>\r\n
\r\n
\r\n \r\n \r\n \r\n
\r\n
\r\n \r\n
{mapper() ?? \"\"}
\r\n \r\n );\r\n};\r\n","import React, { useEffect, useState, useContext } from \"react\";\r\nimport { Row, Col } from \"react-bootstrap\";\r\nimport { calculateAverage, calculateMinimum, calculateMaximum } from \"../../utilities\";\r\nimport { TestsContext } from \"../../contexts\";\r\nimport { Stat } from \"../common\";\r\n\r\nexport const LatencyDetail = (props) => {\r\n // const [data, setData] = useState([]);\r\n\r\n const [avg, setAverage] = useState(0);\r\n const [min, setMinimum] = useState(0);\r\n const [max, setMaximum] = useState(0);\r\n const { tests } = useContext(TestsContext);\r\n const { index } = props;\r\n\r\n /** Check if there is any data to display.\r\n */\r\n\r\n useEffect(() => {\r\n const hasData = (index) => {\r\n return tests !== null && Array.isArray(tests.times) && Array.isArray(tests.times[index]);\r\n };\r\n\r\n if (!hasData(index)) return null;\r\n\r\n let d = tests?.times[index] ?? [];\r\n\r\n setAverage(() => Math.trunc(calculateAverage(d)));\r\n setMinimum(() => Math.trunc(calculateMinimum(d)));\r\n setMaximum(() => Math.trunc(calculateMaximum(d)));\r\n }, [tests, index]);\r\n\r\n return (\r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n );\r\n};\r\n","import React, { useEffect, useState, useContext } from \"react\";\r\nimport { Row, Col } from \"react-bootstrap\";\r\nimport { calculateAverage, calculateMinimum, calculateMaximum } from \"../../utilities\";\r\nimport { TestsContext } from \"../../contexts\";\r\nimport { Stat } from \"../common\";\r\n\r\nconst initJitter = (tests) => {\r\n let j = [];\r\n for (var n = 0; n < tests.length - 1; ++n) {\r\n j.push(Math.trunc(Math.abs(tests[n] - tests[n + 1])));\r\n }\r\n return j;\r\n};\r\n\r\nexport const JitterDetail = (props) => {\r\n // const [data, setData] = useState([]);\r\n\r\n const [avg, setAverage] = useState(0);\r\n const [min, setMinimum] = useState(0);\r\n const [max, setMaximum] = useState(0);\r\n const { tests } = useContext(TestsContext);\r\n const { index } = props;\r\n\r\n /** Check if there is any data to display.\r\n */\r\n\r\n useEffect(() => {\r\n const hasData = (index) => {\r\n return tests !== null && Array.isArray(tests.times) && Array.isArray(tests.times[index]);\r\n };\r\n\r\n //let d = !props.data || !props.data//.length ? [] : props.data;\r\n\r\n if (!hasData(index)) return;\r\n\r\n let jitter = initJitter(tests?.times[index] ?? []);\r\n\r\n setAverage(() => Math.trunc(calculateAverage(jitter)));\r\n setMinimum(() => Math.trunc(calculateMinimum(jitter)));\r\n setMaximum(() => Math.trunc(calculateMaximum(jitter)));\r\n }, [tests, index]);\r\n\r\n return (\r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n );\r\n};\r\n","import React from \"react\";\r\nimport { About } from \"../common\";\r\n\r\nexport const AboutLatency = (props) => {\r\n return (\r\n <>\r\n
\r\n \r\n Network latency, sometimes called lag, is the delay in communication over a network.\r\n \r\n
\r\n \r\n );\r\n};\r\n","import React from \"react\";\r\nimport { About } from \"../common\";\r\n\r\nexport const AboutJitter = (props) => {\r\n return (\r\n <>\r\n
\r\n \r\n Jitter or packet delay variance is the fluctuation in delay as packets transfer across a network.\r\n \r\n
\r\n \r\n );\r\n};\r\n","import React, { useContext } from \"react\";\r\nimport { TestsContext, TargetsContext } from \"../../contexts\";\r\nimport { AboutLink } from \"../common\";\r\n\r\nexport const AboutLatencyChart = (props) => {\r\n const { className, targetIndex } = props;\r\n const { tests } = useContext(TestsContext);\r\n const targets = useContext(TargetsContext);\r\n const { area, country } = targets[targetIndex];\r\n\r\n return (\r\n <>\r\n
\r\n \r\n {`This chart shows ${tests.times[targetIndex].length} latency measurements (pings) against a server in ${area}, ${country}`}\r\n \r\n
\r\n \r\n );\r\n};\r\n","import React, { useContext } from \"react\";\r\nimport { TestsContext, TargetsContext } from \"../../contexts\";\r\nimport { AboutLink } from \"../common\";\r\n\r\nexport const AboutJitterChart = (props) => {\r\n const { className, targetIndex } = props;\r\n const { tests } = useContext(TestsContext);\r\n const targets = useContext(TargetsContext);\r\n const { area, country } = targets[targetIndex];\r\n\r\n return (\r\n <>\r\n
\r\n \r\n {`This chart shows jitter over ${tests.times[targetIndex].length} latency measurements (pings) against a server in ${area}, ${country}`}\r\n \r\n
\r\n \r\n );\r\n};\r\n","import React, { useContext } from \"react\";\r\nimport { useParams } from \"react-router-dom\";\r\nimport { TargetsContext } from \"../../contexts\";\r\nimport { LatencyDetail } from \"./LatencyDetail\";\r\nimport { JitterDetail } from \"./JitterDetail\";\r\nimport { ShadowBox } from \"../common\";\r\nimport { LatencyChart, JitterChart, Location } from \"../common\";\r\nimport { GoToButton } from \"./GoToButton\";\r\nimport useAds from \"../../hooks/UseAds\";\r\nimport { AboutLatency } from \"./AboutLatency\";\r\nimport { AboutJitter } from \"./AboutJitter\";\r\nimport { AboutLatencyChart } from \"./AboutLatencyChart\";\r\nimport { AboutJitterChart } from \"./AboutJitterChart\";\r\nimport { Row, Col } from \"react-bootstrap\";\r\nimport { Link } from \"react-router-dom\";\r\nimport start from \"../../assets/img/start.gif\";\r\n\r\nexport const Detail = () => {\r\n const { index } = useParams();\r\n let targets = useContext(TargetsContext);\r\n useAds();\r\n\r\n if (!targets || !targets[index]) return null;\r\n\r\n /** Render.\r\n *\r\n */\r\n return (\r\n <>\r\n \r\n \r\n \r\n \r\n {/* \r\n \r\n */}\r\n \r\n \r\n \r\n \r\n \r\n Latency\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n \r\n
\r\n \r\n \r\n \r\n \r\n Jitter\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n \r\n
\r\n \r\n
\r\n
\r\n \r\n

Discover Your Latency on a Global Scale

\r\n

Only takes 30 seconds

\r\n\r\n \r\n ...\r\n \r\n
\r\n \r\n );\r\n};\r\n","import React, { useEffect, useState, useContext } from \"react\";\r\nimport { Row, Col } from \"react-bootstrap\";\r\nimport { calculateAverage, calculateMinimum, calculateMaximum } from \"../../utilities\";\r\nimport { TestsContext } from \"../../contexts\";\r\nimport { Stat } from \"../common\";\r\n\r\nconst initJitter = (tests) => {\r\n let j = [];\r\n for (var n = 0; n < tests.length - 1; ++n) {\r\n j.push(Math.trunc(Math.abs(tests[n] - tests[n + 1])));\r\n }\r\n return j;\r\n};\r\n\r\nexport const JitterDetail = (props) => {\r\n // const [data, setData] = useState([]);\r\n\r\n const [avg, setAverage] = useState(0);\r\n const [min, setMinimum] = useState(0);\r\n const [max, setMaximum] = useState(0);\r\n const { tests } = useContext(TestsContext);\r\n const { index } = props;\r\n\r\n /** Check if there is any data to display.\r\n */\r\n\r\n useEffect(() => {\r\n const hasData = (index) => {\r\n return tests !== null && Array.isArray(tests.times) && Array.isArray(tests.times[index]);\r\n };\r\n\r\n //let d = !props.data || !props.data//.length ? [] : props.data;\r\n\r\n if (!hasData(index)) return;\r\n\r\n let jitter = initJitter(tests?.times[index] ?? []);\r\n\r\n setAverage(() => Math.trunc(calculateAverage(jitter)));\r\n setMinimum(() => Math.trunc(calculateMinimum(jitter)));\r\n setMaximum(() => Math.trunc(calculateMaximum(jitter)));\r\n }, [tests, index]);\r\n\r\n return (\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n );\r\n};\r\n","import React, { useEffect, useState, useContext } from \"react\";\r\nimport { Row, Col } from \"react-bootstrap\";\r\nimport { calculateAverage, calculateMinimum, calculateMaximum } from \"../../utilities\";\r\nimport { TestsContext } from \"../../contexts\";\r\nimport { Stat } from \"../common\";\r\n\r\nexport const LatencyDetail = (props) => {\r\n // const [data, setData] = useState([]);\r\n\r\n const [avg, setAverage] = useState(0);\r\n const [min, setMinimum] = useState(0);\r\n const [max, setMaximum] = useState(0);\r\n const { tests } = useContext(TestsContext);\r\n const { index } = props;\r\n\r\n /** Check if there is any data to display.\r\n */\r\n\r\n useEffect(() => {\r\n //let d = !props.data || !props.data//.length ? [] : props.data;\r\n\r\n const hasData = (index) => {\r\n return tests !== null && Array.isArray(tests.times) && Array.isArray(tests.times[index]);\r\n };\r\n\r\n if (!hasData(index)) return;\r\n\r\n let d = tests?.times[index] ?? [];\r\n\r\n setAverage(() => Math.trunc(calculateAverage(d)));\r\n setMinimum(() => Math.trunc(calculateMinimum(d)));\r\n setMaximum(() => Math.trunc(calculateMaximum(d)));\r\n }, [tests, index]);\r\n\r\n return (\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n );\r\n};\r\n","import React, { useContext, useEffect, useState } from \"react\";\r\nimport { ProgressBar } from \"react-bootstrap\";\r\nimport { ConfigurationContext } from \"../../contexts\";\r\n\r\n/** Testing progress.\r\n * Monitors the tests context and shows progress.\r\n */\r\nexport const Status = (props) => {\r\n // const { tests } = useContext(TestsContext);\r\n // const { testCount } = tests;\r\n // const { targetIndex } = props;\r\n const { localTestTime } = useContext(ConfigurationContext);\r\n const [startTime, setStartTime] = useState(Date.now());\r\n\r\n useEffect(() => {\r\n // Update the start time just once.\r\n setStartTime(Date.now());\r\n }, []);\r\n\r\n /** Calculate the percent of the tests done.\r\n */\r\n const percent = () => {\r\n const elapsedTime = Date.now() - startTime;\r\n // let p = Math.trunc((tests.times[targetIndex].length / 50) * 100);\r\n let p = Math.trunc((elapsedTime / localTestTime) * 100);\r\n return p > 95 ? 100 : p; // If the percent is over 95 just show 100.\r\n };\r\n\r\n /** Render.\r\n */\r\n\r\n return (\r\n <>\r\n \r\n \r\n );\r\n};\r\n","import React, { useContext, useEffect, useCallback } from \"react\";\r\nimport { useParams } from \"react-router-dom\";\r\nimport { useNavigate } from \"react-router-dom\";\r\nimport { ConfigurationContext, TargetsContext, TestsContext, ApplicationStateContext } from \"../../contexts\";\r\nimport { LatencyDetail, JitterDetail } from \".\";\r\nimport { ShadowBox, LatencyChart, JitterChart, Location } from \"../common\";\r\nimport { toInt } from \"../../utilities\";\r\nimport { UseTesting } from \"../../hooks\";\r\nimport { Status } from \"./Status\";\r\nimport { Row, Col } from \"react-bootstrap\";\r\n\r\n//import ReactGA from \"react-ga\";\r\n\r\n/**\r\n * DetailTesting component.\r\n *\r\n * Handles running the testing procedure and displaying the real time test results.\r\n */\r\nexport const DetailTesting = () => {\r\n const params = useParams(); // The URL parameters.\r\n const navigate = useNavigate();\r\n const { applicationState } = useContext(ApplicationStateContext);\r\n const targets = useContext(TargetsContext);\r\n const { dispatch } = useContext(TestsContext);\r\n const targetIndex = toInt(params.index);\r\n const { localTestTime, localTestLimit } = useContext(ConfigurationContext);\r\n\r\n /** Function: Handle the done testing event.\r\n */\r\n const onDoneTesting = useCallback(() => {\r\n // Go to the detail view.\r\n navigate(`/detail-test/${targetIndex}`);\r\n }, [targetIndex, navigate]);\r\n\r\n const { start } = UseTesting({ min: targetIndex, max: targetIndex }, localTestTime, localTestLimit, onDoneTesting);\r\n\r\n /** Function: Start the testing process.\r\n */\r\n const startTesting = useCallback(() => {\r\n dispatch({ type: \"reset\", index: targetIndex });\r\n start(onDoneTesting);\r\n }, [dispatch, targetIndex, start, onDoneTesting]);\r\n\r\n /** Effect: Reloads the page if ads are present.\r\n */\r\n useEffect(() => {\r\n // Reload the page if we're showing ads.\r\n if (applicationState.loadedAds) {\r\n window.location.reload(false);\r\n return;\r\n }\r\n }, [applicationState.loadedAds]);\r\n\r\n /** Effect: Start the testing process.\r\n */\r\n useEffect(() => {\r\n // Only start if there are no ads.\r\n if (!applicationState.loadedAds) {\r\n startTesting();\r\n }\r\n }, [applicationState.loadedAds, startTesting]);\r\n\r\n /** Function: Can or should we render this view?\r\n */\r\n const canRender = () => {\r\n // Check for no ads and that data is present.\r\n return !applicationState.loadedAds && targets && targets[targetIndex];\r\n };\r\n\r\n // Rendering\r\n\r\n if (!canRender()) {\r\n // Nothing to render.\r\n return null;\r\n }\r\n\r\n return (\r\n <>\r\n
\r\n
\r\n \r\n
\r\n \r\n \r\n
Latency
\r\n \r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n \r\n
Jitter
\r\n \r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
{\" \"}\r\n
\r\n \r\n );\r\n};\r\n","import React, { useContext, useEffect, useState } from \"react\";\r\nimport { Chart } from \"react-google-charts\";\r\nimport { TestsContext } from \"../../contexts\";\r\n\r\nexport const LatencyChart = (props) => {\r\n const { tests } = useContext(TestsContext);\r\n const [chartData, setData] = useState(null);\r\n\r\n useEffect(() => {\r\n if (tests.times && tests.times[props.index]) {\r\n // Set the chart data.\r\n let d = [[\"\", \"\"]];\r\n\r\n for (var n = 0; n < tests.times[props.index].length; ++n) {\r\n d.push([n + 1, tests.times[props.index][n]]);\r\n }\r\n setData(d);\r\n }\r\n }, [tests, props.index]);\r\n\r\n const hasData = () => {\r\n return tests.times && tests.times[props.index];\r\n };\r\n\r\n var options = {\r\n legend: \"none\",\r\n pointSize: 3,\r\n series: [{ color: \"grey\" }],\r\n hAxis: {\r\n textPosition: \"none\",\r\n gridlines: {\r\n count: 1,\r\n },\r\n },\r\n vAxis: {\r\n format: \"# ms\",\r\n minValue: 0,\r\n gridlines: {\r\n xcount: 1,\r\n },\r\n },\r\n };\r\n\r\n return (\r\n <>{hasData() && }\r\n );\r\n};\r\n","import React, { useContext, useEffect, useState } from \"react\";\r\nimport { LatencyChart } from \"./LatencyChart\";\r\nimport { TestsContext } from \"../../contexts\";\r\nimport { Stat, Box } from \"../common\";\r\nimport { calculateAverage } from \"../../utilities\";\r\nimport { Row, Col } from \"react-bootstrap\";\r\nimport { Location } from \"../common\";\r\n\r\nexport const Test = (props) => {\r\n let { tests } = useContext(TestsContext);\r\n const { index } = props;\r\n const [latency, setLatency] = useState(0);\r\n const [jitter, setJitter] = useState(0);\r\n const hasData = tests !== null && Array.isArray(tests.times) && Array.isArray(tests.times[index]);\r\n\r\n /** Initialize data and stats.\r\n */\r\n useEffect(() => {\r\n if (hasData) {\r\n // Calculate the jitter from the times data.\r\n let jitter = [];\r\n for (var n = 0; n < tests.times[index].length - 1; ++n) {\r\n jitter.push(Math.trunc(Math.abs(tests.times[index][n] - tests.times[index][n + 1])));\r\n }\r\n\r\n // Get the latency and jitter averages.\r\n setLatency(Math.trunc(calculateAverage(tests.times[index])));\r\n setJitter(Math.trunc(calculateAverage(jitter)));\r\n }\r\n }, [tests, index, hasData]);\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n","import React, { useContext } from \"react\";\r\nimport { ProgressBar } from \"react-bootstrap\";\r\nimport { TestsContext } from \"../../contexts\";\r\n\r\n/** Testing progress.\r\n * Monitors the tests context and shows progress.\r\n */\r\nexport const Status = () => {\r\n const { tests } = useContext(TestsContext);\r\n const { testCount } = tests;\r\n\r\n /** Calculate the percent of the tests done.\r\n */\r\n const percent = () => {\r\n let p = Math.trunc((testCount / 40) * 100);\r\n return p > 100 ? 100 : p;\r\n };\r\n\r\n /** Render.\r\n */\r\n return (\r\n <>\r\n \r\n \r\n );\r\n};\r\n","export default __webpack_public_path__ + \"static/media/as.aa142efd.mp4\";","export default __webpack_public_path__ + \"static/media/af.d0b9ebd4.mp4\";","export default __webpack_public_path__ + \"static/media/eu.bd299e10.mp4\";","export default __webpack_public_path__ + \"static/media/na.377a331c.mp4\";","export default __webpack_public_path__ + \"static/media/sa.1b5ddc90.mp4\";","export default __webpack_public_path__ + \"static/media/an.95df1c60.mp4\";","export default __webpack_public_path__ + \"static/media/oc.95df1c60.mp4\";","import React, { useContext } from \"react\";\r\nimport { LocationContext } from \"../../contexts\";\r\n//import beginTest from \"../../assets/img/begin-test.png\";\r\nimport asVideo from \"../../assets/video/as.mp4\";\r\nimport afVideo from \"../../assets/video/af.mp4\";\r\nimport euVideo from \"../../assets/video/eu.mp4\";\r\nimport naVideo from \"../../assets/video/na.mp4\";\r\nimport saVideo from \"../../assets/video/sa.mp4\";\r\nimport anVideo from \"../../assets/video/an.mp4\";\r\nimport ocVideo from \"../../assets/video/oc.mp4\";\r\n\r\nexport const Video = (props) => {\r\n const location = useContext(LocationContext);\r\n\r\n const video = () => {\r\n switch (location.continent.toUpperCase()) {\r\n case \"AF\":\r\n return afVideo;\r\n case \"AS\":\r\n return asVideo;\r\n case \"EU\":\r\n return euVideo;\r\n case \"NA\":\r\n return naVideo;\r\n case \"SA\":\r\n return saVideo;\r\n case \"OC\":\r\n return ocVideo;\r\n case \"AN\":\r\n return anVideo;\r\n default:\r\n return naVideo;\r\n }\r\n };\r\n\r\n /** Render.\r\n *\r\n */\r\n return (\r\n <>\r\n
\r\n {location?.continent && (\r\n \r\n )}\r\n
\r\n \r\n );\r\n};\r\n","import React, { useContext, useEffect, useState, useCallback } from \"react\";\r\nimport { useNavigate } from \"react-router-dom\";\r\nimport { Row, Col, Carousel, CarouselItem } from \"react-bootstrap\";\r\nimport { ConfigurationContext, TargetsContext, TestsContext, ApplicationStateContext } from \"../../contexts\";\r\nimport { UseTesting } from \"../../hooks\";\r\nimport { ShadowBox, Stat } from \"../common\";\r\nimport { Test } from \"./Test.js\";\r\nimport { Status } from \"./Status.js\";\r\nimport { Video } from \"./Video\";\r\n\r\n/**\r\n * GlobalTesting component.\r\n *\r\n * Handle the test running and display of real time results.\r\n */\r\nexport const GlobalTesting = () => {\r\n const targets = useContext(TargetsContext);\r\n const { applicationState } = useContext(ApplicationStateContext);\r\n const { tests, dispatch } = useContext(TestsContext);\r\n const [activeSlide, setActiveSlide] = useState(0);\r\n const { averageLatency, minimumLatency, maximumLatency } = tests;\r\n const navigate = useNavigate();\r\n const { globalTestTime, globalTestLimit } = useContext(ConfigurationContext);\r\n\r\n /** Function: Navigate to the results view.\r\n */\r\n const onDone = useCallback(() => {\r\n // Navigate to results view after a short time.\r\n setTimeout(() => {\r\n navigate(\"/global-tests\");\r\n }, 3000);\r\n }, [navigate]);\r\n\r\n const { start, count } = UseTesting({ min: 0, max: targets.length - 1 }, globalTestTime, globalTestLimit, onDone);\r\n\r\n /** Effect: Set the active slide whenever the count changes.\r\n */\r\n useEffect(() => {\r\n setActiveSlide(count);\r\n }, [count]);\r\n\r\n /** Effect: Reload the page if ads are showing.\r\n */\r\n useEffect(() => {\r\n // Reload the page if we're showing ads.\r\n if (applicationState.loadedAds) {\r\n window.location.reload(false);\r\n return;\r\n }\r\n });\r\n\r\n /** Effect: Start the testing.\r\n */\r\n useEffect(() => {\r\n // Check for ads.\r\n if (applicationState.loadedAds) {\r\n return;\r\n }\r\n\r\n const onStart = () => {\r\n // Reset the tests data and stats.\r\n dispatch({ type: \"reset\" });\r\n\r\n // Start the testing in 3 seconds to match the video intro.\r\n setTimeout(() => {\r\n start();\r\n }, 3000);\r\n };\r\n\r\n onStart();\r\n }, [applicationState.loadedAds, dispatch, start]);\r\n\r\n /** Function: Map all the test data to the carousel.\r\n */\r\n const mapper = () => {\r\n var ar = targets.map((item, index) => (\r\n \r\n \r\n \r\n ));\r\n\r\n return ar; //.reverse();\r\n };\r\n\r\n // Rendering.\r\n\r\n // Don't show anything until there are no ads via a page reload.\r\n if (applicationState.loadedAds) {\r\n return null;\r\n }\r\n\r\n return (\r\n <>\r\n
\r\n \r\n {mapper()}\r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n","import React from \"react\";\r\nimport ReactDOM from \"react-dom\";\r\nimport \"./index.css\";\r\nimport \"./App.scss\";\r\nimport App from \"./App\";\r\nimport reportWebVitals from \"./reportWebVitals\";\r\nimport { BrowserRouter, Routes, Route } from \"react-router-dom\";\r\nimport { Home } from \"./components/home/Home\";\r\nimport { Tests } from \"./components/global-tests/Tests\";\r\nimport { Detail } from \"./components/detail-test/Detail\";\r\nimport { DetailTesting } from \"./components/detail-testing/DetailTesting\";\r\nimport { createBrowserHistory } from \"history\";\r\nimport TagManager from \"react-gtm-module\";\r\n\r\n//import \"bootstrap/dist/css/bootstrap.css\";\r\nimport \"bootstrap-icons/font/bootstrap-icons.css\";\r\n\r\nimport { GlobalTesting } from \"./components/global-testing/GlobalTesting\";\r\n\r\n//import ReactGA from \"react-ga\";\r\n// Google analytics and tag manager initializations.\r\n//ReactGA.initialize(\"UA-2932866-3\");\r\n\r\n// TagManager.initialize({\r\n// gtmId: \"GTM-W3XGXX2\",\r\n// });\r\n\r\nconst baseUrl = document.getElementsByTagName(\"base\")[0].getAttribute(\"href\");\r\n\r\nexport const history = createBrowserHistory({\r\n basename: process.env.PUBLIC_URL,\r\n});\r\n\r\nTagManager.initialize({\r\n gtmId: \"GTM-W3XGXX2\",\r\n});\r\n\r\nReactDOM.render(\r\n \r\n \r\n \r\n }>\r\n }>\r\n }>\r\n }>\r\n }>\r\n }>\r\n \r\n \r\n \r\n ,\r\n document.getElementById(\"root\")\r\n);\r\n\r\nreportWebVitals();\r\n","/** \r\n *\r\n * Ping a URL and return the time taken (latency).\r\n *\r\n */\r\nconst pingAsync = async (url) => {\r\n\r\n let start = performance.now();\r\n\r\n try {\r\n let response = await fetch(\"https://\" + url + `/test.dat?cb=${Date.now()}`, {\r\n method: \"GET\",\r\n// mode: \"no-cors\",\r\n headers: {\r\n// Accept: \"binary/octet-stream,text/plain\",\r\n Accept: \"text/plain\",\r\n },\r\n });\r\n\r\n await response.text(); // Read response to get the actual time.\r\n \r\n let end = performance.now();\r\n\r\n if (response.ok) {\r\n return end - start;\r\n }\r\n } catch (error) {\r\n // TODO: Write to log.\r\n // console.log(error.message);\r\n }\r\n\r\n // Error.\r\n return 0;\r\n};\r\n\r\n/** Test latency by pinging a server multiple times.\r\n *\r\n * target -> URL of server to ping.\r\n * testCount -> maximum pings to perform.\r\n * testTime -> maximum time (ms) to perform pings.\r\n *\r\n * Returns an array of latencies.\r\n */\r\nexport const testLatencyAsync = async (\r\n target,\r\n testCount,\r\n testTime,\r\n setResults,\r\n onDone\r\n) => {\r\n var latencies = [];\r\n var stopTime = Date.now() + testTime; // Test stop time in ms.\r\n\r\n // Do the first and throw it away because it may include a DNS lookup.\r\n await pingAsync(target);\r\n\r\n // console.log(`max time: ${testTime}`);\r\n // console.log(`max tests: ${testCount}`);\r\n\r\n for (var n = 0; n < testCount && Date.now() < stopTime; ++n) {\r\n let latency = await pingAsync(target);\r\n if (latency) {\r\n // Latency from the ping is a two way timing with processing on the server so adjust it accordingly.\r\n latency = (latency - 10) / 2;\r\n if (latency <= 0) latency = 10; // Just in case. This really shouldn't ever happen.\r\n latencies.push(latency);\r\n setResults(latency);\r\n }\r\n }\r\n\r\n // console.log(`out of here`);\r\n\r\n if (onDone) {\r\n // Call the done handler.\r\n onDone();\r\n }\r\n\r\n return latencies;\r\n};\r\n","/** Calculate the average of an array of numbers.\r\n *\r\n */\r\nexport const calculateAverage = (stats) => {\r\n if (!stats || !stats.length) {\r\n return 0;\r\n }\r\n\r\n let sum = 0;\r\n let count = 0;\r\n for (var n = 0; n < stats.length; ++n) {\r\n if (stats[n]) {\r\n sum += stats[n];\r\n count++;\r\n }\r\n }\r\n\r\n return count !== 0 ? sum / count : 0;\r\n};\r\n\r\n/** Find the lowest amount in an array of numbers.\r\n *\r\n */\r\nexport const calculateMinimum = (stats) => {\r\n if (!stats || !stats.length) {\r\n return 0;\r\n }\r\n\r\n let min = stats[0];\r\n for (var n = 0; n < stats.length; ++n) {\r\n if (stats[n] < min) min = stats[n];\r\n }\r\n return min;\r\n};\r\n\r\n/** Find the maximum amount in an array of numbers.\r\n *\r\n */\r\nexport const calculateMaximum = (stats) => {\r\n if (!stats || !stats.length) {\r\n return 0;\r\n }\r\n\r\n let max = stats[0];\r\n for (var n = 0; n < stats.length; ++n) {\r\n if (stats[n] > max) max = stats[n];\r\n }\r\n return max;\r\n};\r\n","/** Set a session storage item.\r\n *\r\n */\r\nexport const setStorage = (key, value) => {\r\n if (!key || !value) {\r\n return;\r\n }\r\n\r\n if (typeof value === \"object\") {\r\n value = JSON.stringify(value);\r\n }\r\n localStorage.setItem(key, value);\r\n};\r\n\r\n/** Get a session storage item.\r\n *\r\n */\r\nexport const getStorage = (key) => {\r\n var value = localStorage.getItem(key);\r\n\r\n if (!value) {\r\n return;\r\n }\r\n\r\n // assume it is an object that has been stringified\r\n if (value[0] === \"{\") {\r\n value = JSON.parse(value);\r\n }\r\n\r\n return value;\r\n};\r\n","export const toInt = (s) => {\r\n const parsed = parseInt(s);\r\n if (isNaN(parsed)) {\r\n return null;\r\n }\r\n return parsed;\r\n};\r\n"],"sourceRoot":""}