{"version":3,"sources":["jsdelivr-header.js","/npm/@cloudflare/speedtest@1.8.5/src/config/defaultConfig.js","/npm/@cloudflare/speedtest@1.8.5/src/config/internalConfig.js","/npm/@cloudflare/speedtest@1.8.5/src/engines/BandwidthEngine/BandwidthEngine.js","/npm/@cloudflare/speedtest@1.8.5/src/engines/BandwidthEngine/ParallelLatency.js","/npm/@cloudflare/speedtest@1.8.5/src/engines/LoggingBandwidthEngine/index.js","/npm/@cloudflare/speedtest@1.8.5/src/engines/LoadNetworkEngine/index.js","/npm/@cloudflare/speedtest@1.8.5/src/engines/PacketLossEngine/SelfWebRtcDataConnection.js","/npm/@cloudflare/speedtest@1.8.5/src/engines/PacketLossEngine/PacketLossEngine.js","/npm/@cloudflare/speedtest@1.8.5/src/engines/PacketLossEngine/UnderLoad.js","/npm/@cloudflare/speedtest@1.8.5/src/engines/ReachabilityEngine/index.js","/npm/@cloudflare/speedtest@1.8.5/src/utils/numbers.js","/npm/@cloudflare/speedtest@1.8.5/src/Results/MeasurementCalculations.js","/npm/@cloudflare/speedtest@1.8.5/src/Results/ScoresCalculations.js","/npm/@cloudflare/speedtest@1.8.5/src/Results/index.js","/npm/@cloudflare/speedtest@1.8.5/src/logging/logFinalResults.js","/npm/@cloudflare/speedtest@1.8.5/src/index.js"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA,08KCNA,IAAM,EAAc,+BAEL,EAAA,CAEb,WAAW,EAGX,eAAc,UAAK,EAAoB,WACvC,aAAY,UAAK,EAAkB,SACnC,qBAAsB,KACtB,aAAc,mCACd,cAAe,kCACf,sBAAqB,UAAK,EAAwB,eAClD,eAAgB,KAChB,eAAgB,KAChB,gBAAiB,8BACjB,WAAU,UAAK,EAA2B,kBAC1C,oBAAoB,EACpB,eAAW,EAGX,aAAc,CACZ,CAAE,KAAM,UAAW,WAAY,GAC/B,CAAE,KAAM,WAAY,MAAO,IAAK,MAAO,EAAG,mBAAmB,GAC7D,CAAE,KAAM,UAAW,WAAY,IAC/B,CAAE,KAAM,WAAY,MAAO,IAAK,MAAO,GACvC,CAAE,KAAM,WAAY,MAAO,IAAK,MAAO,GACvC,CAAE,KAAM,SAAU,MAAO,IAAK,MAAO,GACrC,CACE,KAAM,aACN,WAAY,IACZ,UAAW,GACX,cAAe,GACf,kBAAmB,KAErB,CAAE,KAAM,SAAU,MAAO,IAAK,MAAO,GACrC,CAAE,KAAM,WAAY,MAAO,IAAK,MAAO,GACvC,CAAE,KAAM,SAAU,MAAO,IAAK,MAAO,GACrC,CAAE,KAAM,WAAY,MAAO,KAAO,MAAO,GACzC,CAAE,KAAM,SAAU,MAAO,KAAO,MAAO,GACvC,CAAE,KAAM,WAAY,MAAO,IAAK,MAAO,GACvC,CAAE,KAAM,SAAU,MAAO,IAAK,MAAO,GACrC,CAAE,KAAM,WAAY,MAAO,KAAO,MAAO,IAE3C,8BAA8B,EAC9B,4BAA4B,EAC5B,sBAAuB,IACvB,+BAAgC,IAChC,oBAAqB,GAGrB,8BAA+B,EAG/B,kBAAmB,GACnB,oBAAqB,GACrB,4BAA6B,GAC7B,yBAA0B,IAC1B,uBAAwB,ICxDX,EAAA,CAEb,sBAAuB,CACrB,WAAY,EAAe,CAAC,IAAM,IAAM,IAAM,IAAM,CAAC,GAAI,EAAG,GAAM,IAAK,KACvE,QAAS,EAAe,CAAC,GAAI,GAAI,GAAI,IAAK,KAAM,CAAC,GAAI,GAAI,EAAG,GAAG,IAAK,KACpE,sBAAuB,EACrB,CAAC,GAAI,GAAI,GAAI,IAAK,KAClB,CAAC,GAAI,GAAI,EAAG,GAAG,IAAK,KAEtB,OAAQ,EAAe,CAAC,GAAI,GAAI,IAAK,KAAM,CAAC,GAAI,EAAG,GAAM,IAAK,KAC9D,SAAU,EAAe,CAAC,IAAK,IAAM,IAAM,KAAQ,CAAC,EAAG,EAAG,GAAI,GAAI,KAClE,OAAQ,EAAe,CAAC,IAAK,IAAM,IAAM,KAAQ,CAAC,EAAG,EAAG,GAAI,GAAI,MAElE,mBAAoB,CAClB,UAAW,CACT,MAAO,CAAC,UAAW,aAAc,WAAY,yBAC7C,gBAAiB,CAAC,GAAI,GAAI,GAAI,KAEhC,OAAQ,CACN,MAAO,CAAC,UAAW,aAAc,yBACjC,gBAAiB,CAAC,EAAG,GAAI,GAAI,KAE/B,IAAK,CACH,MAAO,CAAC,UAAW,SAAU,aAAc,yBAC3C,gBAAiB,CAAC,EAAG,GAAI,GAAI,OClB7B,EAAkB,SAAA,GAEtB,IAAM,EAAe,EAAE,QAAQ,IAAG,iBAClC,GAAI,EAAc,CAChB,IAAM,EAAK,EAAa,MAAM,2BAC9B,GAAI,EAAI,OAAQ,EAAG,EACrB,CACF,EAEM,EAAU,SAAA,GAAI,OAAI,EAAK,cAAgB,EAAK,YAAY,EAExD,EAAoB,SAAA,GAAI,OAAI,EAAK,YAAc,EAAK,aAAa,EAEjE,EAAuB,SAAH,GAA+B,OAArB,EAAJ,KAAyB,EAAnB,mBACV,EAEtB,EAAqB,SAAH,GAAU,OAAA,EAAJ,IAAe,EAEvC,EAAoB,SAAH,EAAgC,GAAa,IAAvC,EAAQ,EAAR,SAAU,EAAY,EAAZ,aAI/B,EAAO,EAAW,IAExB,OAAQ,EAHN,GAAK,GAAyB,OAAR,GAGU,OAAnB,CACjB,EAEM,EAAkB,SAAH,EAAkB,GAAa,IAE5C,EAF2B,EAAR,SAED,IAExB,OAAQ,EAHK,EAAI,EAAQ,MAGS,OAAnB,CACjB,EAEM,EAAa,GAAQ,SAAA,GAAQ,MAAI,IAAI,OAAO,EAAS,IAE3D,EAAA,YAAA,EAAA,YAAA,EAAA,YAAA,EAAA,YAAA,EAAA,YAAA,EAAA,YAAA,EAAA,YAAA,EAAA,YAAA,EAAA,YAAA,EAAA,YAAA,EAAA,YAAA,EAAA,YAAA,EAAA,YAAA,EAAA,YAAA,EAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAEM,GAA0B,WAqB9B,OAAA,GApBA,SAAA,EACE,GAOA,IAAA,EAAA,UAAA,OAAA,QAAA,IAAA,UAAA,GAAA,UAAA,GADI,GAJF,EAAc,EAAd,eACA,EAAY,EAAZ,aAAY,EAAA,EACZ,kBAAa,IAAH,EAAG,EAAC,EAAA,EAAA,EACd,2BAAsB,IAAH,EAAG,EAAC,EAGzB,GAHyB,EAAA,QAoG3B,EAAA,SAhFA,EAAA,OAAY,IAQZ,EAAA,OAAgB,IAAG,EAQK,KAAA,6BAAM,EACP,KAAA,0BAAC,EACR,wBAEhB,EAAA,QAAgB,SAAA,GAAC,OAAI,CAAC,IAKtB,EAAA,QAAmB,WAAM,IAIzB,EAAA,QAA2B,WAAM,IAIjC,EAAA,QAAuB,WAAM,IAI7B,EAAA,QAAc,WAAM,IAIpB,EAAA,QAAqB,WAAM,IAmB3B,EAAA,KAAA,OAAa,GACb,EAAA,KAAA,OAAY,GACZ,EAAA,KAAA,OAAU,GAEV,EAAA,KAAA,GAAW,GACX,EAAA,KAAA,EAAY,CAAE,MAAM,EAAO,IAAI,IAC/B,EAAA,KAAA,EAAW,CAAE,KAAM,GAAI,GAAI,KAC3B,EAAA,KAAA,EAAW,GACX,EAAA,KAAA,GAAW,GACX,EAAA,KAAA,GAAW,GACX,EAAA,SAAgB,KAChB,EAAA,KAAA,GAAc,GACd,EAAA,KAAA,GAAuB,GAMvB,EAAA,KAAA,QAA0B,IA/FnB,EAAc,MAAM,IAAI,MAAM,iCACnC,IAAK,EAAgB,MAAM,IAAI,MAAM,mCACrC,IAAK,EAAc,MAAM,IAAI,MAAM,iCAEnC,EAAK,EAAL,KAAqB,GACrB,EAAK,EAAL,KAAoB,GACpB,EAAK,EAAL,KAAkB,GAClB,EAAK,GAAL,KAAmB,GACnB,EAAK,GAAL,KAA4B,KAAK,IAAI,EAAG,GAC1C,GAEA,EAAA,IAAA,UAAA,IACA,WAEE,OAAO,EAAK,EAAL,KACT,GAAC,CAAA,IAAA,WAAA,IAGD,WACE,OAAO,EAAK,EAAL,KACR,EAAA,IACD,SAAa,GACX,EAAK,EAAL,KAAiB,EACnB,GAAC,CAAA,IAAA,eAAA,IAGD,WACE,OAAO,EAAK,EAAL,KACR,EAAA,IACD,SAAiB,GACf,EAAK,EAAL,KAAqB,EACvB,GAAC,CAAA,IAAA,eAAA,IAOD,SAAiB,GACf,EAAK,EAAL,KAAqB,EACvB,GAAC,CAAA,IAAA,kBAAA,IAGD,SAAoB,GAClB,EAAK,EAAL,KAAwB,EAC1B,GAAC,CAAA,IAAA,0BAAA,IAED,SAA4B,GAC1B,EAAK,EAAL,KAAgC,EAClC,GAAC,CAAA,IAAA,sBAAA,IAED,SAAwB,GACtB,EAAK,EAAL,KAA4B,EAC9B,GAAC,CAAA,IAAA,aAAA,IAED,SAAe,GACb,EAAK,EAAL,KAAmB,EACrB,GAAC,CAAA,IAAA,oBAAA,IAED,SAAsB,GACpB,EAAK,EAAL,KAA0B,EAC5B,GAEA,CAAA,IAAA,QAAA,MACA,WACE,EAAA,GAAI,KAAC,IAAyB,KAA9B,KAAI,WACJ,EAAA,GAAA,KAAK,IAAW,KAAhB,MAAiB,EACnB,GAAC,CAAA,IAAA,OAAA,MAED,WACO,EAAK,EAAL,QACH,EAAA,GAAA,KAAK,IAAW,KAAhB,MAAiB,GACjB,EAAA,GAAI,KAAC,IAAgB,KAArB,MAEJ,IAAC,CApF6B,GAoF7B,SAAA,GAwBW,GAAS,IAML,EANK,EAAA,MACf,IAAY,EAAK,EAAL,QACd,EAAK,EAAL,KAAgB,GAChB,YAAW,kBAAM,EAAK,EAAL,GAAqB,KAArB,EAAsB,EAAK,EAAL,GAAa,KAGjD,KACyB,QAA5B,EAAA,EAAK,GAAL,aAAA,IAA4B,GAA5B,EAA8B,MAAM,qBAExC,CAAC,SAAA,GAEuB,EAAS,GAAY,IAAA,EAAA,KAC3C,EAAuB,EAAK,EAAL,MAAmB,GAAlC,EAAK,EAAL,MAAO,EAAG,EAAH,IAET,EAAU,EAAK,EAAL,MAEV,EAAc,EAAQ,GAAK,eAAe,GAC5C,EAAQ,GAAK,GACb,CACE,QAAS,GAET,gBAAiB,EAAK,EAAL,MACd,QAAO,SAAA,GAAA,IAAU,EAAC,EAAR,MAAe,EAAC,EAAN,IAAG,OAAU,IAAU,GAAK,IAAQ,CAAC,IACzD,KAAI,SAAA,GAAC,OAAI,EAAE,KAAK,IAChB,QAAO,SAAC,EAAK,GAAG,OAAK,EAAM,CAAG,GAAE,IAGvC,GAAc,EAAY,QAAQ,KAAK,GACzC,EAAY,QAAU,EAAY,QAAQ,OACvC,EAAY,iBAGf,EAAQ,GAAK,GAAS,EAElB,EACF,YAAW,WACT,EAAK,EAAL,GAAyB,KAAzB,EAAI,EAAA,CAEA,KAAM,EACN,SACG,GAEL,EAEJ,IAEA,EAAK,EAAL,MAA6B,KAA7B,KAA8B,EAAK,EAAL,MAAmB,GAAU,EAE/D,CAAC,SAAA,KAEkB,IAAA,EAAA,KACX,EAAe,EAAK,EAAL,MACjB,EAAO,EAAa,EAAK,EAAL,OAExB,GAAI,EAAK,GAAL,OAAiB,EAAK,MAAO,CAE/B,IAAM,EAAW,EAAK,EAAL,MACjB,GACE,EAAK,GAAL,MAAoB,KAAK,wBACxB,EAAK,kBACN,CAEA,IAAM,EAAM,EAAK,IACjB,EAAK,EAAL,MAAe,IAAO,EACtB,OAAO,OAAO,EAAK,EAAL,OAAgB,OAAM,SAAA,GAAQ,OAAI,CAAQ,KACtD,EAAK,EAAL,MAAgB,KAAhB,KAAiB,EAAK,EAAL,MACrB,CAGA,EAAK,GAAL,KAAgB,GAChB,EAAK,GAAL,MAAqB,KACrB,YAAY,uBAEZ,GACE,EAAK,EAAL,KAAA,EAAK,EAAL,MAAiB,SAEjB,EAAK,EAAL,MAAgB,EAAa,QAC7B,EAAS,EAAa,EAAK,EAAL,OAAe,MAGvC,GAAI,EAAK,EAAL,OAAiB,EAAa,OAKhC,OAHA,EAAK,EAAL,KAAiB,CAAE,MAAM,EAAM,IAAI,IACnC,EAAA,GAAA,KAAK,IAAW,KAAhB,MAAiB,QACjB,EAAK,EAAL,MAAgB,KAAhB,KAAiB,EAAK,EAAL,OAInB,EAAO,EAAa,EAAK,EAAL,MACtB,CAEA,IAAM,EAAU,EAAK,EAAL,MAEM,IAAlB,EAAK,GAAL,OACF,EAAA,GAAI,KAAC,IAAuB,KAA5B,KAA6B,GAG/B,IAAA,EAAiC,EAAlB,EAAQ,EAAf,MACF,EAAiB,SADK,EAAH,IAGnB,EAAkB,EAAT,EAAc,EAAoB,EAAzB,MAClB,EAAW,OAAO,OAAO,GAAI,EAAK,EAAL,OACnC,IAAW,EAAS,MAAK,GAAA,OAAM,IAE/B,IAmByB,EAoBrB,EAvCE,EAAG,UACP,EAAO,WAAW,SAAW,EAAO,WAAW,MAC3C,GACA,OAAO,SAAS,QAAO,OAC1B,EAAM,YAAI,OAAO,QAAQ,GACzB,KAAI,SAAA,GAAA,IAAA,EAAA,EAAA,EAAA,GAAE,EAAC,EAAA,GAAE,EAAC,EAAA,YAAA,OAAS,EAAC,YAAI,EAAC,IACzB,KAAK,MAEF,EAAW,OAAO,OACtB,GACA,EACI,GACA,CACE,OAAQ,OACR,KAAM,EAAW,IAEvB,EAAK,EAAL,OAGF,GAAsB,IAAlB,EAAK,GAAL,QAE0B,QAA5B,EAAA,EAAK,GAAL,aAAA,IAA4B,GAA5B,EAA8B,MAAM,qBAGpC,EAAK,GAAL,KAA+B,IAAI,iBAC/B,KAAK,sBAAsB,CAC7B,IAAM,EAAe,YAAW,WAC9B,IAAM,EAAY,UAAM,EAAS,WAAa,SAAQ,oBAAA,OAAmB,EAAQ,+EAAuE,EAAK,qBAAyB,OACtL,EAAA,GAAA,EAAK,IAAyB,KAA9B,EAA+B,GAC/B,EAAK,GAAL,EAAgB,GAChB,EAAA,GAAA,EAAK,IAAW,KAAhB,GAAiB,GACjB,EAAK,EAAL,GAAuB,KAAvB,EAAwB,EAC1B,GAAG,KAAK,sBACR,EAAK,GAAL,MAA6B,OAAO,iBAAiB,SAAS,kBAC5D,aAAa,EAAa,GAE9B,CAIF,MAAM,EAAG,IAAA,GACJ,GAAQ,IACX,OAAQ,EAAK,GAAL,MAA6B,UAEpC,MAAK,SAAA,GACJ,GAAI,EAAE,GAAI,OAAO,EACjB,MAAM,MAAM,EAAE,WAChB,IACC,MAAK,SAAA,GAEJ,OADA,EAAK,gBAAkB,EAAa,EAAK,cAAc,IAChD,CACT,IACC,MAAK,SAAA,GAAC,OACL,EAAE,OAAO,MAAK,SAAA,GAQZ,OAPA,EAAK,EAAL,IACE,EAAK,EAAL,GAAkB,KAAlB,EAAmB,CACjB,MACA,QAAS,EAAE,QACX,SAGG,CACT,GAAE,IAEH,MAAK,WACJ,IAAM,EAAO,YAAY,iBAAiB,GAAK,OAAM,GAAI,GACnD,EAAS,CACb,aAAc,EAAK,aACnB,KAAM,EAAQ,GACd,oBAAqB,EAAkB,GACvC,WAAY,IAAgB,EAC5B,SAAU,IAAI,MAehB,GAbA,EAAO,KAAO,KAAK,IACjB,IACA,EAAO,MAAQ,GAAc,EAAK,GAAL,KAG/B,EAAO,UAAY,EAAS,EAAuB,GACjD,GAEF,EAAO,KAAO,EAAS,EAAoB,GACzC,EACA,GAGE,GAAU,EAAU,CACtB,IAAM,GAAW,EAEf,EAAO,eACN,EAAO,aAAe,GACrB,EAAO,aAAe,EAAU,OAGlC,QAAQ,KAAI,oBACG,EAAO,0BAAkB,EAAO,aAAY,cACvD,KAAK,MAAO,EAAO,aAAe,EAAW,KAAO,IAAG,OAI/D,CAEA,EAAA,GAAA,EAAK,IAAuB,KAA5B,EAA6B,EAAS,GACtC,IAAM,EAAkB,EAAO,SAS/B,GARA,EAAK,GAAL,EACE,EAAK,GAAL,GAAoB,EAChB,EACA,KAAK,IAAI,EAAK,GAAL,GAAmB,IAElC,EAAK,GAAL,EAAA,EAAK,GAAL,GAAiB,GACjB,EAAK,GAAL,EAAgB,GAEZ,EAAK,GAAL,GAAkB,CACpB,IAAM,EAAkB,YACtB,kBAAM,EAAA,GAAA,EAAK,IAAgB,KAArB,EAAI,GACV,EAAK,GAAL,IAEF,EAAK,GAAL,GAA6B,OAAO,iBAAiB,SAAS,kBAC5D,aAAa,EAAgB,GAEjC,MACE,EAAA,GAAA,EAAK,IAAgB,KAArB,EAEJ,IAAE,OACK,SAAA,GAAS,IAAA,EAAA,EACV,EAAK,GAAL,GAA6B,OAAO,UAGxC,QAAQ,KAAI,kBAAA,OAAmB,EAAG,MAAA,OAAK,IAEnC,EAAK,GAAL,GAAI,EAAJ,EAAK,GAAL,GAAa,EAAA,QAAA,EAhYL,GAiYV,EAAA,GAAA,EAAK,IAAgB,KAArB,IAEA,EAAK,GAAL,EAAgB,GAChB,EAAA,GAAA,EAAK,IAAW,KAAhB,GAAiB,GACjB,EAAK,EAAL,GAAuB,KAAvB,EAAI,wBAAA,OACsB,EAAG,2BAtYnB,GAsYiD,eAG/D,GACJ,CAAC,SAAA,GAEyB,GAAQ,IAAA,EACJ,QAA5B,EAAA,EAAK,GAAL,aAA4B,IAAA,GAA5B,EAA8B,MAC5B,GAAM,kCAEV,C,oHCpZ8C,GAAA,YAAA,GAAA,YAAA,GAAA,YAE1C,GAAkC,WACtC,SAAA,EACE,GASA,IAAA,EAAA,EAAA,UAAA,OAAA,QAAA,IAAA,UAAA,GAAA,UAAA,GADI,GAAE,EAAA,EANJ,8BAAyB,IAAH,GAAQ,EAAA,EAAA,EAC9B,iCAA4B,IAAH,EAAG,IAAG,EAC/B,EAAc,EAAd,eACA,EAAY,EAAZ,aAAY,EAAA,EACZ,2BAAsB,IAAH,EAAG,EAAC,EACpB,EAAO,EAAA,EAAA,IAiCX,OAjCW,EAAA,QA2Ed,EAxEE,EAAA,EAAA,KAAA,EAAM,GAAY,EAAA,CAChB,iBACA,eACA,uBACG,KAoEP,IAHA,EAAA,EAAA,QAAc,GACd,EAAA,EAAA,QAAe,GA/DT,IACF,EAAK,GAAc,EAAG,IAAI,GACxB,CACE,CACE,IAAK,OACL,MAAO,EACP,MAAO,IACP,mBAAmB,IAGvB,CACE,iBACA,eACA,sBACA,WAAY,KAGhB,EAAK,GAAc,GAAC,SAAW,CAC7B,OAAM,GAAA,OAAK,EAAa,GAAG,IAAG,SAGhC,EAAA,EAAwB,oBAAA,GAAA,EAAK,IAAkB,EAAA,GAC/C,EAAA,EAA0B,uCAAM,EAAK,GAAc,GAAC,OAAO,GAAA,EAAA,IAC5D,CACH,CAEA,OAAA,EAAA,EA7C+C,IA6C/C,EAAA,EAAA,EAAA,IAAA,iBAAA,IACA,WAEE,OAAO,EAAK,GAAL,OAAuB,EAAK,GAAL,MAAoB,QAAQ,KAAK,GAAG,OACpE,GAEA,CAAA,IAAA,0BAAA,IACA,SAA4B,GAC1B,EAAK,GAAL,QACG,EAAK,GAAL,MAAoB,oBAAsB,SAAA,GAAG,OAAI,EAAE,E,EACxD,GAEA,CAAA,IAAA,eAAA,IACA,WACE,O,EAAA,e,EAAA,K,EAAA,E,MAAA,E,wFACD,EAAA,IACD,SAAiB,GACf,EAAA,EAAA,eAAqB,EAAY,KAAA,GACjC,EAAK,GAAL,QAAwB,EAAK,GAAL,MAAoB,aAAe,EAC7D,GAAC,CAAA,IAAA,kBAAA,IAED,SAAoB,GAAiB,IAAA,EAAA,KACnC,EAAA,EAAwB,4BAAA,GACtB,EAAA,GAAA,EAAK,IAAkB,KAAvB,EAAwB,GACxB,EAAgB,E,GACjB,KAAA,EACH,GAAC,CAAA,IAAA,oBAAA,IAED,SAAsB,GAAmB,IAAA,EAAA,KACvC,EAAA,EAAA,qBAA0B,WACxB,EAAK,GAAL,IAAuB,EAAK,GAAL,GAAoB,QAC3C,EAAiB,WAAA,Y,GAClB,KAAA,EACH,IAAC,CA9EqC,GAAwB,SAAA,GAqF3C,GAAS,IAAA,EAAA,KACtB,EAAK,GAAL,QACG,EAKH,EAAK,GAAL,KAAuB,YAAW,kBAAM,EAAK,GAAL,GAAoB,M,GAAQ,MAJpE,aAAa,EAAK,GAAL,OACb,EAAK,GAAL,MAAoB,SAM1B,C,iDC/F+C,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAE3C,GAAsB,WAC1B,SAAA,EACE,GAEA,IAAA,EAAA,EAAA,UAAA,OAAA,QAAA,IAAA,UAAA,GAAA,UAAA,GADsD,GAApD,EAAa,EAAb,cAAe,EAAS,EAAT,UAAW,EAAS,EAAT,UAAc,EAAO,EAAA,EAAA,IAUc,OAVd,EAAA,QAyCnD,EAvCE,EAAA,EAAA,KAAA,EAAM,GAAc,IAuCtB,IANA,EAAA,EAAA,QAAc,GACd,EAAA,EAAA,QAAM,GACN,EAAA,EAAA,QAAY,GACZ,EAAA,EAAA,QAAU,GACV,EAAA,EAAA,QAAU,GAnCR,EAAK,GAAc,EAAG,GACtB,EAAK,GAAU,EAAG,GAClB,EAAK,GAAU,EAAG,GAElB,EAAA,aAAiB,EAAY,CAAE,OAAQ,EAAK,GAAc,IAAK,GAAE,EAAA,GACjE,EAAA,kBAAqB,SAAA,GAAC,OAAI,EAAA,GAAA,EAAK,IAAoB,KAAA,EAAC,EAAC,GAAC,EAAA,GACtD,EAAA,yBAA4B,SAAA,GAAI,OAAI,EAAA,GAAA,EAAK,IAAe,KAAA,EAAC,EAAI,GAAC,EAAA,GAAC,CACjE,CAEA,OAAA,EAAA,EAhBmC,IAgBnC,EAAA,EAAA,EAAA,IAAA,WAAA,IACA,SAAa,GACX,EAAA,EAAA,WAAiB,EAAK,GAAL,MAAe,EAAA,CAC1B,OAAQ,EAAK,GAAL,OAAwB,GAClC,EAAQ,KAAA,EACd,GAAC,CAAA,IAAA,eAAA,IAED,SAAiB,GAAc,IAAA,EAAA,KAC7B,EAAA,EAAqB,yBAAA,GACnB,EAAa,GACb,EAAA,GAAA,EAAK,IAAoB,KAAzB,EAA0B,E,GAC3B,KAAA,EACH,GAAC,CAAA,IAAA,sBAAA,IAED,SAAwB,GAAqB,IAAA,EAAA,KAC3C,EAAA,EAA4B,gCAAC,GAAsB,IAAA,MAAA,UAAA,OAAb,EAAQ,IAAA,MAAA,MAAA,KAAA,EAAA,EAAA,EAAA,EAAA,IAAR,EAAQ,EAAA,aAAA,GAC5C,EAAmB,WAAC,MAAI,OAAK,IAC7B,EAAA,GAAA,EAAK,IAAe,KAApB,EAAqB,E,GACtB,KAAA,EACH,IAAC,CAnCyB,GAAwB,SAAA,GA6C7B,GACd,EAAK,GAAL,QAGL,EAAK,GAAL,MAAqB,EAAE,QAAQ,IAAG,yBAGlC,EAAK,GAAL,KAAc,EAAE,KAAK,OAAU,KAAE,MAAM,OAAO,OAChD,CAAC,SAAA,GAEe,GACd,GAAK,EAAK,GAAL,MAAL,CAEA,IAAM,EAAU,CACd,KAAM,EAAS,KACf,MAAO,EAAS,MAChB,KAAM,KAAK,MAAM,EAAS,MAC1B,KAAM,KAAK,MAAM,EAAS,MAC1B,oBAAqB,KAAK,MAAM,EAAS,qBACzC,SAAU,KAAK,MAAM,EAAS,UAC9B,aAAc,KAAK,MAAM,EAAS,cAClC,WAAY,KAAK,MAAM,EAAS,YAChC,MAAO,EAAK,GAAL,MACP,YAAa,EAAK,GAAL,MACb,OAAQ,EAAK,GAAL,MACR,UAAW,EAAK,GAAL,OAGb,EAAK,GAAL,KAAc,MACd,EAAK,GAAL,KAAoB,MAEpB,MAAM,EAAK,GAAL,MAAe,EAAA,CACnB,OAAQ,OACR,KAAM,KAAK,UAAU,IAClB,KAAK,cAvBY,CAyBxB,CCrFwB,IAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAEpB,GAAa,WAQjB,OAAA,GAPA,SAAA,EAAY,GACV,GADqB,EAAA,QA6BvB,EAAA,SAJA,EAAA,KAAA,IAAW,GACX,EAAA,KAAA,QAAkB,GAClB,EAAA,KAAA,QAAU,IA1BH,EAAW,MAAM,IAAI,MAAK,gCAE/B,EAAK,GAAL,KAAkB,GAClB,KAAK,MACP,GAEA,EAAA,IAAA,QAAA,MACA,WACE,EAAA,GAAI,KAAC,IAAc,KAAnB,MACA,EAAA,GAAA,KAAK,IAAW,KAAhB,MAAiB,EACnB,GAAC,CAAA,IAAA,OAAA,MAED,WACE,KAAK,OACP,GAAC,CAAA,IAAA,OAAA,MAED,WACO,EAAK,GAAL,QACH,EAAA,GAAA,KAAK,IAAW,KAAhB,MAAiB,GACjB,EAAA,GAAI,KAAC,IAAK,KAAV,MAEJ,IAAC,CAvBgB,GAuBhB,SAAA,GAQW,GACN,IAAY,EAAK,GAAL,OACd,EAAK,GAAL,KAAgB,EAEpB,CAAC,SAAA,KAEO,IAAA,EAAA,KACA,EAAc,EAAK,GAAL,KAAuB,EAAK,GAAL,MAAe,KAAf,MAAkB,MAAK,YAC/D,EAAW,SAAW,EAAA,GAAA,EAAK,IAAK,KAAV,EACzB,IACF,CAAC,SAAA,KAGC,IAAM,EAAa,EAAK,GAAL,MACnB,IAAe,EAAW,SAAU,EACtC,CAAC,IAAA,GAAA,YAGG,GAAiB,WAuDpB,OAAA,GAtDD,SAAA,IAAuC,IAAA,EAAA,KAAA,EAAA,UAAA,OAAA,QAAA,IAAA,UAAA,GAAA,UAAA,GAAJ,GAArB,EAAQ,EAAR,SAAU,EAAM,EAAN,OAEtB,GAF4B,EAAA,QAwD9B,EAAA,KAAA,WACW,IAAI,EAAA,KAAA,eACA,IAgBf,EAAA,KAAA,GAAW,KAxEJ,IAAa,EAChB,MAAM,IAAI,MAAM,kDAElB,CACE,CAAC,EAAU,YACX,CAAC,EAAQ,WAER,QAAO,SAAA,GAAK,OAAL,EAAA,EAAA,GAAK,EAAS,IACrB,SAAQ,SAAA,GAAiB,IAAA,EAAA,EAAA,EAAA,GAAf,EAAG,EAAA,GAAE,EAAI,EAAA,GACV,EAAsB,EAAtB,OAAQ,EAAc,EAAd,UAChB,IAAK,EAAQ,MAAM,IAAI,MAAK,WAAA,OAAY,EAAI,qBAC5C,IAAK,EAAW,MAAM,IAAI,MAAK,WAAA,OAAY,EAAI,uBACjD,IAEF,IAAM,EAAgB,SAAH,GAAA,IAAM,EAAM,EAAN,OAAM,EAAA,EAAE,gBAAQ,IAAA,EAAG,GAAE,EAAA,EAAA,EAAE,oBAAY,IAAA,EAAG,GAAE,EAAA,OAC/D,IAAI,IAAc,WAChB,IAAM,EAAgB,OAAO,OAAO,GAAI,EAAU,EAAK,UACjD,EAAG,UACP,EAAO,WAAW,SAAW,EAAO,WAAW,MAC3C,GACA,OAAO,SAAS,QAAO,OAC1B,EAAM,YAAI,OAAO,QAAQ,GACzB,KAAI,SAAA,GAAA,IAAA,EAAA,EAAA,EAAA,GAAE,EAAC,EAAA,GAAE,EAAC,EAAA,YAAA,OAAS,EAAC,YAAI,EAAC,IACzB,KAAK,MACF,EAAW,OAAO,OAAO,GAAI,EAAc,EAAK,cAEtD,OAAO,MAAM,EAAK,GACf,MAAK,SAAA,GACJ,GAAI,EAAE,GAAI,OAAO,EACjB,MAAM,MAAM,EAAE,WAChB,IACC,MAAK,SAAA,GAAC,OAAI,EAAE,M,GACjB,GAAE,EAEJ,GACE,EAAK,GAAL,MAAc,KACZ,EAAc,CACZ,OAAQ,EAAS,OACjB,SAAU,CAAE,MAAK,UAAK,EAAS,eAIrC,GACE,EAAK,GAAL,MAAc,KACZ,EAAc,CACZ,OAAQ,EAAO,OACf,aAAc,CACZ,OAAQ,OACR,KAAM,IAAI,OAAO,EAAO,cAIlC,GAAC,EAAA,IAAA,QAAA,MAOD,WACE,EAAK,GAAL,MAAc,SAAQ,SAAA,GAAM,OAAI,EAAO,O,GACzC,GAAC,CAAA,IAAA,OAAA,MAED,WACE,KAAK,OACP,GAAC,CAAA,IAAA,OAAA,MAED,WACE,EAAK,GAAL,MAAc,SAAQ,SAAA,GAAM,OAAI,EAAO,M,GACzC,IAAC,CAxEoB,G,mICnDF,GAAwB,WAuE1C,OAAA,GAtED,SAAA,IAgBQ,IAAA,EAAA,KAAA,EAAA,UAAA,OAAA,QAAA,IAAA,UAAA,GAAA,UAAA,GAAJ,GAAE,EAAA,EAfJ,kBAAa,IAAH,EAAG,GAAE,EAAA,EAAA,EACf,0BAAqB,IAAH,EAAG,SAAA,GACnB,IAAI,EAAW,EAAU,UAAY,GAErC,IAAK,GAAY,EAAU,UAAW,CACpC,IAAM,EAAW,EAAU,UAAU,MAAM,KAC3C,EAAS,QAAU,IAAM,EAAW,EAAS,GAC/C,CACA,MAAkC,QAA3B,EAAS,aAClB,EAAC,EAAA,EAAA,EACD,sBAAiB,IAAH,EAAG,CACf,SAAS,EACT,eAAgB,GACjB,EACE,EAAoB,EAAA,EAAA,IAAA,EAAA,QAyDzB,EAAA,KAAA,UACS,WAAM,IAAI,EAAA,KAAA,WACT,WAAM,IAAI,EAAA,KAAA,qBACA,WAAM,IAmB1B,EAAA,KAAA,IAAe,GAEf,EAAA,KAAA,QAAO,GACP,EAAA,KAAA,QAAS,GACT,EAAA,KAAA,QAAS,GACT,EAAA,KAAA,QAAW,GAlFT,IAAM,EAAS,IAAI,kBAAiB,EAAA,CAClC,cACG,IAEC,EAAW,IAAI,kBAAiB,EAAA,CACpC,cACG,IAGD,EAAW,EAAO,kBAAkB,UAAW,GACnD,EAAS,OAAS,WAChB,EAAK,GAAL,GAAoB,GACpB,EAAK,QACN,EACD,EAAS,QAAU,kBAAM,EAAK,OAAO,EAGrC,EAAS,cAAgB,SAAA,GACvB,IAAM,EAAK,EAAE,QACb,EAAG,QAAU,kBAAM,EAAK,OAAO,EAC/B,EAAG,UAAY,SAAA,GAAG,OAAI,EAAK,kBAAkB,EAAI,KAAK,EAEtD,EAAK,GAAL,EAAmB,EACpB,EAKD,EAAO,eAAiB,SAAA,GAEtB,EAAE,WACA,EAAmB,EAAE,YACrB,EAAS,gBAAgB,EAAE,UAC9B,EACD,EAAS,eAAiB,SAAA,GAExB,EAAE,WACA,EAAmB,EAAE,YACrB,EAAO,gBAAgB,EAAE,UAC5B,EAED,EACG,cACA,MAAK,SAAA,GAAK,OAAI,EAAO,oBAAoB,E,IACzC,MAAK,kBAAM,EAAS,qBAAqB,EAAO,iB,IAChD,MAAK,kBAAM,EAAS,cAAc,IAClC,MAAK,SAAA,GAAM,OAAI,EAAS,oBAAoB,E,IAC5C,MAAK,kBAAM,EAAO,qBAAqB,EAAS,iB,IAEnD,EAAK,GAAL,KAAe,GACf,EAAK,GAAL,KAAiB,GACjB,EAAK,GAAL,KAAiB,GACjB,EAAK,GAAL,MAAoB,EACtB,GAAC,EAAA,IAAA,OAAA,MAQD,SAAK,GACH,OAAO,EAAK,GAAL,MAAe,KAAK,EAC7B,GAAC,CAAA,IAAA,QAAA,MAED,WAQE,OAPA,EAAK,GAAL,OAAgB,EAAK,GAAL,MAAa,QAC7B,EAAK,GAAL,OAAkB,EAAK,GAAL,MAAe,QACjC,EAAK,GAAL,OAAkB,EAAK,GAAL,MAAe,QACjC,EAAK,GAAL,OAAoB,EAAK,GAAL,MAAiB,QAErC,EAAK,GAAL,OAAqB,KAAK,UAC1B,EAAK,GAAL,MAAoB,GACb,IACT,IAAC,CA5F0C,GCAqB,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAE7C,GAAgB,WA+HlC,OAAA,GA9HD,SAAA,IAgBQ,IAAA,EAAA,KAAA,EAAA,UAAA,OAAA,QAAA,IAAA,UAAA,GAAA,UAAA,GAAJ,GAfF,EAAa,EAAb,cACA,EAAkB,EAAlB,mBAAkB,EAAA,EAClB,gCAA2B,IAAH,EAAG,SAAA,GAA+B,MAAQ,CAChE,eADoC,EAAR,SAE5B,eAFgD,EAAV,WAGtC,cAHwD,EAAN,OAInD,EAAC,EAAA,EAAA,EACF,4CAAuC,IAAH,GAAQ,EAC5C,EAAc,EAAd,eACA,EAAc,EAAd,eAAc,EAAA,EACd,eAAU,IAAH,EAAG,IAAG,EAAA,EAAA,EACb,iBAAY,IAAH,EAAG,GAAE,EAAA,EAAA,EACd,qBAAgB,IAAH,EAAG,GAAE,EAAA,EAAA,EAClB,yBAAoB,IAAH,EAAG,IAAI,EAAA,EAAA,EACxB,yBAAoB,IAAH,EAAG,IAAI,EAExB,GAFwB,EAAA,QAkH1B,EAAA,SAAwB,WAAM,IAI9B,EAAA,SAAqB,WAAM,IAI3B,EAAA,SAAc,WAAM,IAAG,EAAA,KAAA,aAIX,WAAM,IAAI,EAAA,KAAA,iBACN,WAAM,IAAI,EAAA,KAAA,iBACV,WAAM,IAetB,EAAA,QAAc,IACd,EAAA,KAAA,QAAiB,GACjB,EAAA,KAAA,QAAQ,IA/ID,IAAkB,EACrB,MAAM,IAAI,MAAM,wDAElB,KAAM,GAAmB,GAAoB,GAC3C,MAAM,IAAI,MACR,gFAGJ,EAAK,GAAL,KAAgB,IAEd,GAAmB,EAajB,QAAQ,QAAQ,CACd,iBACA,mBAbF,MAAM,EAAoB,CACxB,YAAa,EACT,eACA,IAEH,MAAK,SAAA,GAAC,OAAI,EAAE,MAAM,IAClB,MAAK,SAAA,GACJ,GAAI,EAAE,MAAO,MAAM,EAAE,MACrB,OAAO,C,IAER,KAAK,IAIN,OAEG,SAAA,GAAC,OAAI,EAAK,GAAL,GAA0B,KAA1B,EAA2B,EAAC,IACvC,MACC,SAAA,GAIM,IAHJ,EAAc,EAAd,eACA,EAAc,EAAd,eACe,EAAqB,EAApC,cAEM,EAAK,EAAK,GAAL,EAAyB,IAAI,GAAyB,CAC/D,WAAY,CACV,CACE,KAAI,QAAA,OAAU,GAAyB,EAA6B,kBACpE,SAAU,EACV,WAAY,IAGhB,mBAAoB,WAGlB,GAAoB,EACxB,YAAW,WACJ,IACH,EAAE,QACF,EAAK,GAAL,GAAuB,KAAvB,EAAwB,2BAE3B,GAAE,GAEH,IAAM,EAAa,EAAK,GAAL,GACnB,EAAE,OAAS,WACT,GAAoB,EAEpB,IAAM,EAAO,GACb,SAAU,EAAQ,GAChB,GAAI,GAAK,EAAS,CAEhB,IADA,IAAI,EAAI,EACD,GAAK,KAAK,IAAI,EAAS,EAAI,EAAY,IAC5C,EAAW,IAAK,EAChB,EAAE,KAAK,GACP,EAAK,UAAU,GACf,IAEF,YAAW,kBAAM,EAAQ,EAAE,GAAE,EAC/B,KAAO,CACL,EAAK,cAAc,OAAO,KAAK,GAAY,QAE3C,IAAM,EAAW,WACf,EAAE,QACF,EAAK,GAAL,GAAgB,KAAhB,EAAiB,EAAK,QACvB,EACG,EAAgB,WAAW,EAAU,GAErC,EAAc,OAAO,OAAO,EAAK,GAAL,IAAkB,QAChD,SAAA,GAAI,OAAK,CACX,IAAE,OACF,EAAE,kBAAoB,SAAA,GACpB,aAAa,GAEb,EAAW,IAAO,EAClB,EAAK,cAAc,KAEnB,GAEiB,GACf,OAAO,OAAO,EAAK,GAAL,IAAkB,OAAM,SAAA,GAAI,OAAI,CAAI,IAGlD,IAGA,EAAgB,WAAW,EAAU,EAExC,CACH,CACD,CAzCD,CAyCG,EACJ,EACD,EAAE,kBAAoB,SAAA,GACpB,EAAW,IAAO,EAClB,EAAK,cAAc,EACpB,CACH,IACD,OACM,SAAA,GAAC,OAAI,EAAK,GAAL,GAAuB,KAAvB,EAAwB,EAAE,WAAU,GACpD,GAAC,EAAA,IAAA,uBAAA,IAID,SAAyB,GACvB,EAAK,GAAL,KAA6B,EAC/B,GAAC,CAAA,IAAA,oBAAA,IAED,SAAsB,GACpB,EAAK,GAAL,KAA0B,EAC5B,GAAC,CAAA,IAAA,aAAA,IAED,SAAe,GACb,EAAK,GAAL,KAAmB,EACrB,GAAC,CAAA,IAAA,UAAA,IAKD,WACE,IAAM,EAAgB,EAAK,GAAL,MAChB,EAAkB,OAAO,KAAK,EAAK,GAAL,OAAkB,OAChD,EAAe,OAAO,QAAQ,EAAK,GAAL,OACjC,QAAO,SAAA,GAAQ,OAAR,EAAA,EAAA,GAAQ,EAAW,IAC1B,KAAI,SAAA,GAAG,OAAH,EAAA,EAAA,GAAG,E,IAEV,MAAO,CAAE,gBAAe,kBAAiB,WADtB,EAAa,OAAS,EACY,eACvD,IAAC,CA1JkC,G,2ECDa,GAAA,YAE5C,GAAyB,WAC7B,SAAA,IAMQ,IAAA,EAAA,EAAA,UAAA,OAAA,QAAA,IAAA,UAAA,GAAA,UAAA,GAAJ,GALF,EAAiB,EAAjB,kBACA,EAAe,EAAf,gBACA,EAAc,EAAd,eACA,EAAY,EAAZ,aACG,EAAO,EAAA,EAAA,IAwBT,OAxBS,EAAA,QA0DZ,EAxDE,EAAA,EAAA,OAAA,CAAM,IAwDR,QAAW,IAtDL,GAAqB,KACvB,EAAK,GAAW,EAAG,IAAI,GAAkB,CACvC,SAAU,EACN,CACE,OAAQ,EACR,UAAW,GAEb,KACJ,OAAQ,EACJ,CACE,OAAQ,EACR,UAAW,GAEb,QAGN,EAAA,yBAAA,EAAA,sBAAA,EAAA,EAGI,gCAAM,EAAK,GAAW,GAAC,MAAM,GAAA,EAAA,GAAA,EAAA,GAAA,EAAA,IAClC,CACH,CAEA,OAAA,EAAA,EAjCsC,IAiCtC,EAAA,EAAA,EAAA,IAAA,WAAA,IACA,SAAa,GACX,EAAK,GAAL,QAAqB,EAAK,GAAL,MAAiB,SAAW,EACnD,GAAC,CAAA,IAAA,eAAA,IAED,SAAiB,GACf,EAAK,GAAL,QAAqB,EAAK,GAAL,MAAiB,aAAe,EACvD,GAAC,CAAA,IAAA,uBAAA,IAED,SAAyB,GAAsB,IAAA,EAAA,KAC7C,EAAA,EAAA,wBAA6B,WAC3B,EAAoB,WAAA,aACpB,EAAK,GAAL,IAAoB,EAAK,GAAL,GAAiB,M,GACtC,KAAA,EACH,GAAC,CAAA,IAAA,oBAAA,IAED,SAAsB,GAAmB,IAAA,EAAA,KACvC,EAAA,EAAA,qBAA0B,WACxB,EAAiB,WAAA,aACjB,EAAK,GAAL,IAAoB,EAAK,GAAL,GAAiB,M,GACtC,KAAA,EACH,GAAC,CAAA,IAAA,aAAA,IAED,SAAe,GAAY,IAAA,EAAA,KACzB,EAAA,EAAA,cAAmB,WACjB,EAAU,WAAA,aACV,EAAK,GAAL,IAAoB,EAAK,GAAL,GAAiB,M,GACtC,KAAA,EACH,IAAC,CA7D4B,G,iBCDV,GAAkB,GACrC,SAAA,EAAY,GAAqD,IAAA,EAAA,KAAA,EAAA,UAAA,OAAA,QAAA,IAAA,UAAA,GAAA,UAAA,GAAJ,GAAE,EAAA,EAAtC,eAAO,IAAA,GAAG,EAAE,EAAA,EAAA,EAAE,oBAAY,IAAA,EAAG,GAAE,EAAA,EAAA,QAiCxD,EAAA,KAAA,cACa,WAAM,IAjCjB,IAAI,GAAW,EACT,EAAS,SAAH,GAA+B,IAAzB,EAAS,EAAT,UAAc,EAAI,EAAA,EAAA,IAC9B,IACJ,GAAW,EACX,EAAK,WAAU,EAAA,CACb,YACA,aACG,IAEN,EAED,MAAM,EAAW,GACd,MAAK,SAAA,GACJ,EAAO,CACL,WAAW,EACX,YAEJ,IAAE,OACK,SAAA,GACL,EAAO,CACL,WAAW,EACX,SAEJ,IAEF,EAAU,GACR,YACE,kBAAM,EAAO,CAAE,WAAW,EAAO,MAAO,mBAAoB,GAC5D,EAEN,IC/BW,GAAa,SAAC,GAAqB,IAAf,EAAI,UAAA,OAAA,QAAA,IAAA,UAAA,GAAA,UAAA,GAAG,GACtC,IAAK,EAAK,OAAQ,OAAO,EAEzB,IAAM,EAAa,EAAK,QAAQ,MAAK,SAAC,EAAG,GAAC,OAAK,EAAI,C,IAE7C,GAAO,EAAK,OAAS,GAAK,EAC1B,EAAM,EAAM,EAElB,GAAY,IAAR,EAAW,OAAO,EAAW,KAAK,MAAM,IAG5C,IAAM,EAAQ,CAAC,KAAK,MAAO,KAAK,MAAM,KAAI,SAAA,GAAK,OAAI,EAAW,EAAM,G,IACpE,OAAO,EAAM,IAAM,EAAM,GAAK,EAAM,IAAM,CAC5C,EChB8C,GAAA,YAAA,GAAA,YAExC,GAAuB,WAG1B,OAAA,GAFD,SAAA,EAAY,GAAQ,IAAA,EAAA,KAAA,EAAA,QAIpB,EAAA,KAAA,oBACmB,SAAA,GAAc,OAAI,EAAe,QAAQ,KAAI,SAAA,GAAC,OAAI,EAAE,I,GAAK,IAAA,EAAA,KAAA,cAE/D,SAAA,GAAc,OACzB,GACE,EAAK,iBAAiB,GACtB,EAAK,GAAL,GAAa,kBACd,IAAA,EAAA,KAAA,sBAmBkB,SAAA,GAAgB,OACnC,OAAO,QAAQ,GACZ,KAAI,SAAA,GAAA,IAAA,EAAA,EAAA,EAAA,GAAE,EAAK,EAAA,GAAW,OAAA,EAAA,GAAP,QACN,KACN,SAAA,GAAA,IAAG,EAAG,EAAH,IAAK,EAAQ,EAAR,SAAU,EAAI,EAAJ,KAAM,EAAQ,EAAR,SAAU,EAAU,EAAV,WAAY,EAAY,EAAZ,aAAY,MAAQ,CAChE,OAAQ,EACR,MACA,WACA,OACA,WACA,aACA,eACD,GACF,IAEF,MAAM,IAAA,EAAA,KAAA,gBAEI,SAAA,GAAgB,OAC7B,GACE,EAAK,mBAAmB,GACrB,QAAO,SAAA,GAAC,OAAI,EAAE,UAAY,EAAK,GAAL,GAAa,2BAA2B,IAClE,KAAI,SAAA,GAAC,OAAI,EAAE,GAAG,IACd,QAAO,SAAA,GAAG,OAAI,C,IACjB,EAAK,GAAL,GAAa,oBACd,IAAA,EAAA,KAAA,oBAEgB,SAAA,GAAa,OAC9B,EAAK,WAAW,CAAE,QAAS,EAAK,GAAL,GAA4B,KAA5B,EAA6B,IAAiB,IAAA,EAAA,KAAA,mBAEzD,SAAA,GAAa,OAC7B,EAAK,UAAU,CAAE,QAAS,EAAK,GAAL,GAA4B,KAA5B,EAA6B,IAAiB,IAAA,EAAA,KAAA,0BAEjD,SAAA,GAAa,OACpC,EAAK,iBAAiB,CACpB,QAAS,EAAK,GAAL,GAA4B,KAA5B,EAA6B,IACtC,IAAA,EAAA,KAAA,iBAEY,SAAA,GAAS,OAAI,EAAU,UAAU,IAAA,EAAA,KAAA,wBAC1B,SAAA,GAAS,OAAI,CAAS,IAAA,EAAA,KAAA,mBAE3B,SAAA,GAAmB,QAAM,EAAoB,SAAS,IAAA,EAAA,KAAA,0BAC/C,SAAA,GAAC,MAAK,CAAE,KAAM,EAAE,KAAM,UAAW,EAAE,U,IAG5D,EAAA,KAAA,QAAO,GAGP,EAAA,SAA0B,SAAA,GAAa,OACrC,OAAO,OAAO,GACX,QAEC,SAAA,GAAC,OACC,EAAE,QAAQ,QACV,KAAK,IAAG,MAAR,KAAI,EAAQ,EAAE,QAAQ,KAAI,SAAA,GAAC,OAAI,EAAE,Q,OAC/B,EAAK,GAAL,GAAa,wBAAwB,IAE1C,KAAI,SAAA,GAAC,OAAI,EAAE,aAAe,EAAE,IAC5B,OACA,OAAO,EAAK,GAAL,GAAa,uBAAuB,IAvF9C,EAAK,GAAL,KAAe,EACjB,GAAC,EAAA,IAAA,YAAA,MAWD,SAAU,GAER,IAAM,EAAQ,KAAK,iBAAiB,GACpC,OAAO,EAAM,OAAS,EAClB,KACA,EAAM,QACJ,SAAA,EAAiC,GAAO,IAAA,EAAA,EAArC,iBAAY,IAAH,EAAG,EAAC,EAAE,EAAW,EAAX,YAAW,MAAiB,CAC5C,UACE,QACiB,IAAhB,EAA4B,KAAK,IAAI,EAAc,GAAW,GACjE,YAAa,EACd,GACD,IACA,WACC,EAAM,OAAS,EACxB,IA4DkD,CAzFvB,GCEvB,GAAsB,CAAC,MAAO,OAAQ,UAAW,OAAQ,SAEzD,GAAoB,CACxB,sBAAuB,SAAA,GAAY,OACjC,EAAa,UACZ,EAAa,mBAAqB,EAAa,iBAC5C,KAAK,IAAI,EAAa,kBAAmB,EAAa,iBACtD,EAAa,aACb,CAAS,GAGX,GAAgB,CACpB,WAAY,GACZ,GAAA,YAEI,GAAkB,WAGrB,OAAA,GAFD,SAAA,EAAY,GAAQ,EAAA,QA6CpB,EAAA,KAAA,QAAO,GA5CL,EAAK,GAAL,KAAe,EACjB,GAAC,EAAA,IAAA,YAAA,MAED,SAAU,GACR,IAAM,EAAS,OAAO,OAAM,MAAb,OAAM,EAChB,OAAO,QAAQ,EAAK,GAAL,MAAa,uBAAuB,KACpD,SAAA,GAAgB,IAAA,EAAA,EAAA,EAAA,GAAd,EAAI,EAAA,GAAE,EAAE,EAAA,GACF,EAAM,GAAkB,eAAe,GACzC,GAAkB,GAAM,GACxB,EAAa,GACjB,YAAe,IAAR,EACH,GAAc,eAAe,GAAK,EAAA,GAC7B,EAAO,GAAc,IACxB,GAAE,EAED,UAAe,IAAR,EAAoB,GAAK,EAAG,GAG9C,MAGF,OAAO,OAAO,OAAM,MAAb,OACL,KAAE,OAAA,EACC,OAAO,QAAQ,EAAK,GAAL,MAAa,oBAC5B,QAAO,SAAA,GAAW,OAAX,EAAA,EAAA,GAAW,GAAL,MAAmB,OAAM,SAAA,GAAC,OAAI,EAAO,eAAe,E,GAAG,IACpE,KAAI,SAAA,GAAqC,IF9C/B,EE8C+B,EAAA,EAAA,EAAA,GAAnC,EAAC,EAAA,GAAA,EAAA,EAAA,GAAI,EAAK,EAAL,MAAO,EAAe,EAAf,gBACX,EAAY,KAAK,IAAI,GF/ClB,EE+CyB,EAAM,KAAI,SAAA,GAAC,OAAI,EAAO,EAAE,IF/CzC,EAAK,QAAO,SAAC,EAAK,GAAG,OAAK,EAAM,CAAG,GAAE,KEgDhD,EAAoB,EACxB,EACA,CAAC,EAAG,EAAG,EAAG,EAAG,GAFW,CAGxB,GAEF,OAAA,EACG,KAAI,CACH,OAAQ,EACR,oBACA,mBALuB,GAAoB,IAQhD,MAEP,IAAC,CA3CqB,GClB8B,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAEhD,GAAO,WAMV,OAAA,GALD,SAAA,EAAY,GAAQ,IAAA,EAAA,KAAA,EAAA,QAOpB,EAAA,KAAA,cAAA,EAiBqB,KAAA,wCAAM,EAAK,GAAL,GAAgB,KAAhB,EAAiB,aAAc,U,IAAU,EAChD,KAAA,uCAAM,EAAK,GAAL,GAAgB,KAAhB,EAAiB,YAAa,U,IAAU,EACvC,KAAA,8CACzB,EAAK,GAAL,GAAgB,KAAhB,EAAiB,mBAAoB,UAAW,G,IAAG,EAC9B,KAAA,0CAAM,EAAK,GAAL,GAAgB,KAAhB,EAAiB,mBAAoB,W,IAAW,EACvD,KAAA,yCAAM,EAAK,GAAL,GAAgB,KAAhB,EAAiB,kBAAmB,W,IAAW,EAC9C,KAAA,gDAC3B,EAAK,GAAL,GAAgB,KAAhB,EAAiB,yBAA0B,WAAY,G,IAAG,EACvC,KAAA,wCAAM,EAAK,GAAL,GAAgB,KAAhB,EAAiB,mBAAoB,S,IAAS,EACrD,KAAA,uCAAM,EAAK,GAAL,GAAgB,KAAhB,EAAiB,kBAAmB,S,IAAS,EAC5C,KAAA,8CACzB,EAAK,GAAL,GAAgB,KAAhB,EAAiB,yBAA0B,SAAU,G,IAAG,EACnC,KAAA,0CAAM,EAAK,GAAL,GAAgB,KAAhB,EAAiB,eAAgB,W,IAAW,EAC5C,KAAA,gDAC3B,EAAK,GAAL,GAAgB,KAAhB,EAAiB,qBAAsB,WAAY,G,IAAG,EACnC,KAAA,wCAAM,EAAK,GAAL,GAAgB,KAAhB,EAAiB,eAAgB,S,IAAS,EAC1C,KAAA,8CACzB,EAAK,GAAL,GAAgB,KAAhB,EAAiB,qBAAsB,SAAU,G,IAAG,EACtC,KAAA,mCAAM,EAAK,GAAL,GAAgB,KAAhB,EAAiB,gBAAiB,a,IAAa,EAC9C,KAAA,0CACrB,EAAK,GAAL,GAAgB,KAAhB,EAAiB,uBAAwB,kBAAc,GAAW,E,IAAK,EA6B7D,KAAA,+BAAM,EAAK,GAAL,GAAiB,UAAU,EAAK,aAAa,IAG/D,EAAA,KAAA,QAAO,GACP,EAAA,KAAA,QAAS,GACT,EAAA,KAAA,QAAW,GAGX,EAAA,KAAA,IAAc,SACZ,EACA,GAAM,IACN,EAAU,UAAA,OAAA,QAAA,IAAA,UAAA,GAAA,UAAA,QAAG,EACb,EAAY,UAAA,OAAA,QAAA,IAAA,UAAA,IAAA,UAAA,GAAQ,OAEnB,EAAK,IAAI,eAAe,IAAY,EAAK,IAAI,GAAQ,QAElD,GAAgB,EAAK,IAAI,GAAQ,MAC/B,CAAE,MAAO,EAAK,IAAI,GAAQ,OAC1B,EAAK,GAAL,GAAe,GAAQ,EAAK,IAAI,GAAQ,SAH1C,CAGkD,IAExD,EAAA,KAAA,IAAqB,kBACnB,EAAK,GAAL,GAAgB,KAAhB,EAAiB,kBAAmB,iB,IACtC,EAAA,KAAA,IAA4B,kBAC1B,EAAK,GAAL,GAAgB,KAAhB,EAAiB,yBAA0B,iB,IAC7C,EAAA,KAAA,IAAqB,kBACnB,EAAK,GAAL,GAAgB,KAAhB,EAAiB,kBAAmB,iB,IACtC,EAAA,KAAA,IAA4B,kBAC1B,EAAK,GAAL,GAAgB,KAAhB,EAAiB,yBAA0B,iB,IAnG3C,EAAK,GAAL,KAAe,GACf,KAAK,QACL,EAAK,GAAL,KAAiB,IAAI,GAAwB,EAAK,GAAL,QAC7C,EAAK,GAAL,KAAmB,IAAI,GAAmB,EAAK,GAAL,OAC5C,GAAC,EAAA,IAAA,aAAA,IAKD,WACE,OAAO,OAAO,OAAO,KAAK,KAAK,OAAM,SAAA,GAAC,OAAI,EAAE,Q,GAC9C,GAEA,CAAA,IAAA,QAAA,MACA,WACE,KAAK,IAAM,OAAO,OAAM,MAAb,OACT,KAAE,OAAA,EACC,EAAI,IAAI,IAAI,EAAK,GAAL,MAAa,aAAa,KAAI,SAAA,GAAC,OAAI,EAAE,IAAI,MAAI,KAAI,SAAA,GAAC,OAAA,EAC9D,KAAI,CAAE,SAAS,EAAO,UAAU,EAAO,QAAS,IACjD,MAEN,GAAC,CAAA,IAAA,aAAA,MAwBD,WACE,IAAM,EAAQ,CACZ,SAAU,KAAK,qBACf,OAAQ,KAAK,mBACb,QAAS,KAAK,mBACd,OAAQ,KAAK,kBACb,kBAAmB,KAAK,qBACxB,iBAAkB,KAAK,oBACvB,gBAAiB,KAAK,mBACtB,eAAgB,KAAK,kBACrB,WAAY,KAAK,cACjB,eAAgB,EAAK,GAAL,MAChB,eAAgB,EAAK,GAAL,OAGlB,OAAO,OAAO,OAAM,MAAb,OAAM,EACR,OAAO,QAAQ,GAAO,KAAI,SAAA,GAAe,IAAA,EAAA,EAAA,EAAA,GAAb,EAAG,EAAA,GAC1B,GAAM,EADwB,EAAA,MAEpC,YAAe,IAAR,EACH,GAAE,EAEC,KAAM,EAEd,KAEL,IAAC,CAxEU,GCDP,GAAQ,SAAC,GAAG,IAAE,EAAQ,UAAA,OAAA,QAAA,IAAA,UAAA,GAAA,UAAA,GAAG,EAAC,OAC7B,EAAY,KAAK,MAAM,EAAG,KAAA,IAAG,GAAM,IAAS,KAAA,IAAG,GAAM,GAA/C,CAAuD,EAE1D,GAAsB,SAAA,GAAS,OAAI,EAAU,KAAI,SAAA,GAAC,OAAI,GAAM,EAAG,E,GAAG,EAClE,GAAkB,SAAA,GAAI,OAC1B,EAAK,KAAI,SAAA,GAAC,MAAK,CACb,OAAQ,EAAE,MACV,IAAK,GAAM,EAAE,KACd,GAAE,EAUC,GAAiB,CACrB,UAAW,CAAC,2BAA4B,IACxC,SAAU,CAAC,6BAA8B,IACzC,OAAQ,CAAC,2BAA4B,IACrC,oBAAqB,CAAC,6BAA8B,IACpD,kBAAmB,CAAC,2BAA4B,IAChD,WAAY,CAAC,uBAdU,SAAA,GAAC,OACxB,EAAE,WACE,EACA,CACE,YAAa,EAAE,gBACf,UAAW,GAAM,EAAE,WAAY,GAChC,I,2CCJD,GAAgB,CAAC,UAAW,mBAAoB,WAAY,UAE5D,GAAY,WAAH,SAAA,OAAY,KAAK,MAAsB,KAAhB,KAAK,UAAgB,EAAG,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAExD,GAAiB,WAOrB,OAAA,GANA,SAAA,IAA6B,IAAjB,EAAU,UAAA,OAAA,QAAA,IAAA,UAAA,GAAA,UAAA,GAAG,GAAE,EAAA,QAsE3B,EAAA,SAAA,EAAA,KAAA,mBAlDkB,WAAM,IAAE,EAAA,KAAA,mBACR,WAAM,IAAE,EAAA,KAAA,iBACV,WAAM,IAEtB,EAAA,SAAY,WAAM,IAKlB,EAAA,SAAW,WAAM,IA6BjB,EAAA,KAAA,QAAO,GACP,EAAA,KAAA,QAAQ,GAER,EAAA,QAAiB,MACjB,EAAA,SAAa,GACb,EAAA,KAAA,QAAU,GACV,EAAA,KAAA,GAzEoC,KA0EpC,EAAA,KAAA,GAzEkC,KA2ElC,EAAA,KAAA,IAAW,GACX,EAAA,KAAA,IAAY,GAnEV,EAAK,GAAL,KAAe,OAAO,OAAO,GAAI,EAAe,EAAY,IAC5D,EAAK,GAAL,KAAgB,IAAI,GAAQ,EAAK,GAAL,QAC5B,EAAK,GAAL,MAAa,WAAa,KAAK,MACjC,GAEA,EAAA,IAAA,UAAA,IACA,WAEE,OAAO,EAAK,GAAL,KACT,GAAC,CAAA,IAAA,YAAA,IAED,WACE,OAAO,EAAK,GAAL,KACT,GAAC,CAAA,IAAA,aAAA,IAED,WACE,OAAO,EAAK,GAAL,KACT,GAAC,CAAA,IAAA,WAAA,IAOD,SAAa,GACX,EAAK,GAAL,KAAiB,EACnB,GAAC,CAAA,IAAA,UAAA,IAGD,SAAY,GACV,EAAK,GAAL,KAAgB,EAClB,GAEA,CAAA,IAAA,QAAA,MACA,WACE,GAAc,SAAS,EAAA,GAAA,KAAK,IAAQ,KAAb,QAAoB,EAAK,GAAL,MAAgB,QAC3D,EAAA,GAAA,KAAK,IAAW,KAAhB,MAAiB,EACnB,GAAC,CAAA,IAAA,OAAA,MAED,WACO,EAAK,GAAL,QAEH,YAAY,uBAIZ,YAAY,4BAA4B,KACxC,EAAA,GAAA,KAAK,IAAW,KAAhB,MAAiB,GACjB,EAAA,GAAI,KAAC,IAAK,KAAV,MAEJ,GAAC,CAAA,IAAA,UAAA,MACD,WACE,EAAA,GAAI,KAAC,IAAM,KAAX,MACA,KAAK,MACP,IAAC,CAxDoB,GAwDpB,SAAA,GAgBW,GACN,IAAY,EAAK,GAAL,QACd,EAAK,GAAL,KAAgB,GAChB,KAAK,gBAAgB,EAAK,GAAL,OAEzB,CAAC,SAAA,GAEY,GAAU,IAAA,EAAA,KACjB,IAAa,EAAK,GAAL,QACf,EAAK,GAAL,KAAiB,GACjB,GAAY,YAAW,kBAAM,EAAK,GAAL,GAAc,KAAd,EAAe,EAAK,QAAO,IAE5D,CAAC,SAAA,KAGC,OAAO,EAAK,GAAL,MAAkB,GACvB,EAAK,GAAL,OAAmB,EAAK,GAAL,MAAa,aAAa,OAC3C,KACA,EAAK,GAAL,MAAa,aAAa,EAAK,GAAL,OAAiB,IACjD,CAAC,SAAA,KAGC,OAAO,EAAK,GAAL,MAAc,IAAI,EAAA,GAAI,KAAC,IAAQ,KAAb,aAAoB,CAC/C,CAAC,SAAA,KAGC,EAAA,GAAI,KAAC,IAAiB,KAAtB,MAEA,EAAK,GAAL,KAAsB,MACtB,EAAK,GAAL,MAAkB,GAClB,EAAK,GAAL,UAAkB,GAElB,EAAA,GAAA,KAAK,IAAW,KAAhB,MAAiB,GACjB,EAAA,GAAA,KAAK,IAAY,KAAjB,MAAkB,GAElB,EAAK,GAAL,MAAc,OAChB,CAAC,SAAA,KAGC,IAAM,EAAS,EAAK,GAAL,MACV,IAEL,EAAO,WACL,EAAO,kBACP,EAAO,OACP,EAAO,cACP,EAAO,qBACP,EAAO,oBACL,WAAM,EAEV,GAAc,SAAS,EAAA,GAAA,KAAK,IAAQ,KAAb,QAAoB,EAAO,QACpD,CAAC,SAAA,KAEO,IAAA,EAAA,EAAA,KACN,KACE,GAAc,SAAS,EAAA,GAAI,KAAC,IAAQ,KAAb,QACvB,EAAA,GAAI,KAAC,IAAe,KAApB,OACA,EAAA,GAAA,KAAK,IAAe,KAApB,MAAuB,UACtB,EAAA,GAAA,KAAK,IAAe,KAApB,MAAuB,UACvB,EAAA,GAAA,KAAK,IAAe,KAApB,MAAuB,sBACvB,EAAA,GAAA,KAAK,IAAe,KAApB,MAAuB,MAN1B,CAcA,GADA,EAAK,GAAL,MAAI,EAAJ,EAAK,GAAL,QAAe,IACX,EAAK,GAAL,OAAmB,EAAK,GAAL,MAAa,aAAa,OAI/C,OAFA,EAAA,GAAA,KAAK,IAAW,KAAhB,MAAiB,QACjB,EAAA,GAAA,KAAK,IAAY,KAAjB,MAAkB,GAIpB,IAAA,EAA+B,EAAK,GAAL,MAAa,aAAa,EAAK,GAAL,OAAjD,EAAI,EAAJ,KAAS,EAAS,EAAA,EAAA,IACpB,EAAa,EAAA,GAAA,KAAK,IAAe,KAApB,MAEnB,KAAK,cAAc,CACjB,cAAe,EAAK,GAAL,MACf,YAAW,EAAA,CAAI,QAAS,KAG1B,IAEI,EAFJ,EAA8D,EAAK,GAAL,MAAtD,EAAc,EAAd,eAAgB,EAAY,EAAZ,aAAc,EAAmB,EAAnB,oBAGtC,OAAQ,GACN,IAAK,iBACL,IAAK,kBACH,EAAS,IAAI,GAAkB,WAAA,OAAY,EAAU,MAAQ,CAC3D,aAAc,CACZ,OAAQ,MACR,KAAM,cAGH,WAAa,SAAA,GAClB,EAAW,UAAW,EACtB,EAAW,QAAO,EAAA,CAChB,KAAM,EAAU,MACb,GAEL,EAAK,gBAAgB,CAAE,SACvB,EAAA,GAAA,EAAK,IAAK,KAAV,EACD,EACD,MACF,IAAK,QACH,EAAS,IAAI,GAAkB,WAAA,OAClB,EAAK,GAAL,MAAa,iBACxB,CACE,QAAS,OAGN,WAAa,SAAA,IACjB,EAAO,SAAW,EAAO,SAAS,OAAS,QAAQ,WAAW,MAC7D,SAAA,GACE,EAAW,UAAW,EACtB,EAAW,QAAO,EAAA,CAChB,KAAM,EAAK,GAAL,GAAa,gBACnB,mBAAoB,EAAO,WACvB,EACA,CACE,IAAK,EAAS,IACd,KAAM,EAAS,MAEjB,IAEN,EAAK,gBAAgB,CAAE,SACvB,EAAA,GAAA,EAAK,IAAK,KAAV,EACF,GAEH,EACD,MACF,IAAK,YACH,EAAS,IAAI,GAAkB,WAAA,OAAY,EAAU,QAAU,CAC7D,aAAc,CAAE,KAAM,cAEjB,WAAa,SAAA,GAClB,EAAW,UAAW,EACtB,EAAW,QAAU,CACnB,KAAM,EAAU,OAChB,UAAW,EAAO,WAEpB,EAAK,gBAAgB,CAAE,SACvB,EAAA,GAAA,EAAK,IAAK,KAAV,EACD,EACD,MACF,IAAK,aACL,IAAK,sBAED,EAAW,UAAW,EAEtB,IAAoB,EAAsB,EAAlC,WAAwB,EAAK,EAAK,EAAS,IACnD,EAMI,EAAK,GAAL,MALF,EAAa,EAAb,cACuB,EAAkB,EAAzC,sBACA,EAAc,EAAd,eACA,EAAc,EAAd,eACA,EAAkB,EAAlB,oBAEF,EAAS,IAAI,GAAgB,EAAA,CAC3B,gBACA,qBACA,qCAAsC,EACtC,iBACA,iBACA,UAGA,kBAAmB,EAAU,SACzB,EAAK,GAAL,WACA,EACJ,gBAAiB,EAAU,OACvB,EAAK,GAAL,WACA,EACJ,iBACA,gBAEG,KAIA,cAAgB,WACrB,EAAW,QAAU,OAAO,OAAO,GAAI,EAAO,SAC9C,EAAK,gBAAgB,CAAE,QACxB,EAED,EAAO,WAAa,WAClB,EAAW,UAAW,EACtB,EAAK,gBAAgB,CAAE,SACvB,EAAA,GAAA,EAAK,IAAK,KAAV,EACD,EAED,EAAO,kBAAoB,SAAA,GACzB,EAAW,MAAQ,EACnB,EAAK,gBAAgB,CAAE,SACvB,EAAK,GAAL,GAAa,KAAb,EAAI,iDAAA,OAA2D,IAC/D,EAAA,GAAA,EAAK,IAAK,KAAV,EACD,EAED,EAAO,qBAAuB,WAC5B,EAAW,MAAQ,wCACnB,EAAK,gBAAgB,CAAE,SACvB,EAAK,GAAL,GAAa,KAAb,EACE,6EAEF,EAAA,GAAA,EAAK,IAAK,KAAV,EACD,EAED,MACF,IAAK,UACL,IAAK,mBACH,EAAW,UAAW,GAEtB,EAAS,IAAI,GACX,CACE,CACE,IAAK,OACL,MAAO,EACP,MAAO,EAAU,WACjB,mBAAmB,IAGvB,CACE,iBACA,eACA,sBACA,UAAW,EAAK,GAAL,MAAa,qBACxB,cAAe,EAAK,GAAL,MACf,UAAW,EAAK,GAAL,MAAa,UAGxB,kBAAmB,EAAU,SACzB,EAAK,GAAL,WACA,EACJ,gBAAiB,EAAU,OACvB,EAAK,GAAL,WACA,KAGD,aAAe,CACpB,YAAa,EAAK,GAAL,MAAa,mBAAqB,eAAY,GAE7D,EAAO,qBACL,EAAK,GAAL,MAAa,8BAEf,EAAO,oBAAsB,EAAO,wBAA0B,SAC5D,EACA,GAEA,EAAW,QAAU,OAAO,OAAO,GAAI,EAAQ,KAAK,IACpD,EAAK,gBAAgB,CAAE,QACxB,EAED,EAAO,WAAa,WAClB,EAAW,UAAW,EACtB,EAAK,gBAAgB,CAAE,SACvB,EAAK,GAAL,IAAiB,EAAA,GAAA,EAAK,IAAK,KAAV,EAClB,EAED,EAAO,kBAAoB,SAAA,GACzB,EAAW,MAAQ,EACnB,EAAK,gBAAgB,CAAE,SACvB,EAAK,GAAL,GAAa,KAAb,EAAI,6CAAA,OAAuD,IAC3D,EAAA,GAAA,EAAK,IAAK,KAAV,EACD,EAED,EAAO,OACP,MACF,IAAK,WACL,IAAK,SACH,GAAI,EAAW,UAAY,EAAW,MACpC,EAAA,GAAA,KAAK,IAAK,KAAV,UACK,QACE,EAAW,qBAElB,IAAM,EACJ,EAAK,GAAL,MAAY,UAAA,OACS,aAAT,EAAsB,OAAS,KAC1C,uBAEH,EAAS,IAAI,GACX,CAAA,EAAA,CAAG,IAAc,aAAT,EAAsB,OAAS,MAAS,IAChD,CACE,iBACA,eACA,sBACA,UAAW,EAAK,GAAL,MAAa,qBACxB,cAAe,EAAK,GAAL,MACf,yBACA,0BAA2B,EAAK,GAAL,MAAa,sBACxC,UAAW,EAAK,GAAL,MAAa,aAGrB,aAAe,CACpB,YAAa,EAAK,GAAL,MAAa,mBAAqB,eAAY,GAE7D,EAAO,sBACL,EAAK,GAAL,MAAa,+BACf,EAAO,qBACL,EAAK,GAAL,MAAa,8BAEf,EAAO,wBAA0B,SAAA,GAAsB,IAAnB,EAAK,EAAL,MAAO,EAAK,EAAL,MACnC,EAAO,EAAW,QAAU,OAAO,OACvC,GACA,EAAW,UAGZ,EAAI,eAAe,KACjB,EAAI,GAAS,CACZ,QAAS,GACT,gBAAiB,EACjB,YAAa,EAAyB,QAAK,IAK7C,EAAI,GAAO,gBAAkB,EAAI,GAAO,QAAQ,SAChD,IAEA,EAAI,GAAO,iBAAmB,EAC9B,EAAK,gBAAgB,CAAE,SAE1B,EAED,EAAO,oBAAsB,SAAA,GAA0B,IAAvB,EAAK,EAAL,MAAU,EAAM,EAAA,EAAA,IAE9C,EAAW,QAAQ,GAAO,QAAQ,KAAK,GACvC,EAAW,QAAU,OAAO,OAAO,GAAI,EAAW,SAClD,EAAK,gBAAgB,CAAE,QACxB,EAED,EAAO,wBAA0B,SAAA,GAE/B,EAAW,QAAQ,EAAU,OAAO,YAAY,KAAK,GACrD,EAAW,QAAU,OAAO,OAAO,GAAI,EAAW,SAClD,EAAK,gBAAgB,CAAE,QACxB,EAED,EAAO,WAAa,SAAA,GAClB,IAAM,GAAmB,EAAK,GAAL,GAAa,aACnC,MAAM,EAAK,GAAL,GAAkB,GACxB,KAAI,SAAA,GAAC,OAAI,EAAE,IAAI,IACf,SAAS,GAEN,EAAc,KAAK,IAAG,MAAR,KAAI,EACnB,OAAO,OAAgB,aAAT,EAAsB,EAAQ,KAAO,EAAQ,IAC3D,OAAQ,GAAE,GACV,QAAQ,KAAI,SAAA,GAAC,OAAI,EAAE,QAAQ,MAQhC,GAJE,IACE,EAAU,mBACV,EAAc,EAAK,GAAL,GAAa,+BAIxB,CACL,EAAW,UAAW,EACtB,EAAK,gBAAgB,CAAE,SAGvB,IAGM,EA3bO,GAwbO,OAAO,KAAK,EAAW,SACxC,KAAI,SAAA,GAAC,OAAK,CAAC,IACX,MAAK,SAAC,EAAG,GAAC,OAAK,EAAI,C,IAAG,GAGhB,aAAT,GACG,EAAK,GAAL,EAAiC,GAC3B,WAAT,GAAsB,EAAK,GAAL,EAA+B,EACvD,MAdE,EAAW,sBAAuB,EAgBpC,EAAK,GAAL,IAAiB,EAAA,GAAA,EAAK,IAAK,KAAV,EAClB,EAED,EAAO,kBAAoB,SAAA,GACzB,EAAW,MAAQ,EACnB,EAAK,gBAAgB,CAAE,SACvB,EAAK,GAAL,GAAa,KAAb,EAAI,oCAAA,OAA8C,EAAI,aAAK,IAC3D,EAAA,GAAA,EAAK,IAAK,KAAV,EACD,EAED,EAAO,MACT,EAKJ,EAAK,GAAL,KAAkB,GAElB,EAAW,SAAU,EACrB,KAAK,gBAAgB,CAAE,QAvUvB,MAFE,EAAK,GAAL,MAAgB,MA0UpB,CAAC,IAAA,GAAA,YAAA,GAAA,YAAA,GAAA,YAGG,GAAwB,WAC5B,SAAA,EAAY,GAAmB,IAAA,EAAA,EAAA,QAAA,IAAA,MAAA,UAAA,OAAJ,EAAE,IAAA,MAAA,MAAA,KAAA,EAAA,EAAA,EAAA,EAAA,IAAF,EAAE,EAAA,aAAA,GAmB7B,EAlBE,EAAA,EAAA,OAAA,CAAM,GAAU,OAAK,IAkBvB,QAAa,GACb,EAAA,EAAA,QAAU,GAGV,EAAA,EAAA,IAAmB,SAAA,GACjB,EAAK,GAAa,ID1dA,SAAC,EAAO,GAA4B,IAAxB,EAAM,EAAN,OAC1B,EAAU,CACd,UAF+C,EAAT,WAIxC,OAAO,QAAQ,IAAgB,SAAQ,SAAA,GAAmC,IAAA,EAAA,EAAA,EAAA,GAAjC,EAAI,EAAA,GAAA,EAAA,EAAA,EAAA,MAAG,EAAE,EAAA,GAAA,EAAA,EAAA,GAAE,OAAS,IAAH,EAAG,SAAA,GAAC,OAAI,CAAC,EAAA,EAC3D,EAAM,EAAQ,KACpB,IAAQ,EAAQ,GAAQ,EAAO,GACjC,IAEA,IAAM,EAAS,EAAQ,YACvB,IACG,EAAQ,OAAS,OAAO,OAAM,MAAb,OAAM,CACtB,IAAE,OAAA,EACC,OAAO,QAAQ,GAAQ,KAAI,SAAA,GAAA,IAlBhB,EAkBgB,EAAA,EAAA,EAAA,GAAU,OAAA,EACrC,GAD8B,EAAA,GAlBb,CACxB,QADkB,EAkB0B,EAAA,IAjBlC,OACV,eAAgB,EAAE,oB,QAqBlB,MAAM,EAAQ,CACZ,OAAQ,OACR,KAAM,KAAK,UAAU,IAEzB,CCqcM,CAAgB,EAAS,CACvB,OAAQ,EAAK,GAAa,GAC1B,UAAW,EAAK,GAAU,I,IAzB9B,EAAA,EAAiB,aAAK,GAAgB,KAAA,GAEtC,IAAM,EAAS,OAAO,OAAO,GAAI,EAAe,EAAY,GAGzB,OADnC,EAAK,GAAa,EAAG,EAAO,cAC5B,EAAK,GAAU,EAAG,EAAO,WAAU,CACrC,CAEA,OAAA,EAAA,EAXqC,IAWrC,EAAA,EAAA,EAAA,IAAA,WAAA,IACA,SAAa,GAAU,IAAA,EAAA,KACrB,EAAA,EAAiB,qBAAA,GACf,EAAS,GACT,EAAK,GAAL,GAAqB,KAArB,EAAsB,E,GACvB,KAAA,EACH,IAAC,CAjB2B,U","file":"/npm/@cloudflare/speedtest@1.8.5/dist/speedtest.js/+esm","sourceRoot":"","sourcesContent":["/**\n * Bundled by jsDelivr using Rollup v2.79.2 and Terser v5.39.0.\n * Original file: /npm/@cloudflare/speedtest@1.8.5/dist/speedtest.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","const REL_API_URL = 'https://speed.cloudflare.com';\n\nexport default {\n  // Engine\n  autoStart: true,\n\n  // APIs\n  downloadApiUrl: `${REL_API_URL}/__down`,\n  uploadApiUrl: `${REL_API_URL}/__up`,\n  logMeasurementApiUrl: null,\n  logAimApiUrl: 'https://aim.cloudflare.com/__log',\n  turnServerUri: 'turn.speed.cloudflare.com:50000',\n  turnServerCredsApiUrl: `${REL_API_URL}/turn-creds`,\n  turnServerUser: null,\n  turnServerPass: null,\n  rpkiInvalidHost: 'invalid.rpki.cloudflare.com',\n  cfTraceUrl: `${REL_API_URL}/cdn-cgi/trace`,\n  includeCredentials: false,\n  sessionId: undefined,\n\n  // Measurements\n  measurements: [\n    { type: 'latency', numPackets: 1 }, // initial ttfb estimation\n    { type: 'download', bytes: 1e5, count: 1, bypassMinDuration: true }, // initial download estimation\n    { type: 'latency', numPackets: 20 },\n    { type: 'download', bytes: 1e5, count: 9 },\n    { type: 'download', bytes: 1e6, count: 8 },\n    { type: 'upload', bytes: 1e5, count: 8 },\n    {\n      type: 'packetLoss',\n      numPackets: 1e3,\n      batchSize: 10,\n      batchWaitTime: 10, // ms (in between batches)\n      responsesWaitTime: 3000 // ms (silent time after last sent msg)\n    },\n    { type: 'upload', bytes: 1e6, count: 6 },\n    { type: 'download', bytes: 1e7, count: 6 },\n    { type: 'upload', bytes: 1e7, count: 4 },\n    { type: 'download', bytes: 2.5e7, count: 4 },\n    { type: 'upload', bytes: 2.5e7, count: 4 },\n    { type: 'download', bytes: 1e8, count: 3 },\n    { type: 'upload', bytes: 5e7, count: 3 },\n    { type: 'download', bytes: 2.5e8, count: 2 }\n  ],\n  measureDownloadLoadedLatency: true,\n  measureUploadLoadedLatency: true,\n  loadedLatencyThrottle: 400, // ms in between loaded latency requests\n  bandwidthFinishRequestDuration: 1000, // download/upload duration (ms) to reach for stopping further measurements of that type\n  estimatedServerTime: 10, // ms to discount from latency calculation (if not present in response headers)\n\n  // Test abort\n  bandwidthAbortRequestDuration: 0, // download/upload duration (ms) to abort measurement early and stop further measurements of that type\n\n  // Result interpretation\n  latencyPercentile: 0.5, // Percentile used to calculate latency from a set of measurements\n  bandwidthPercentile: 0.9, // Percentile used to calculate bandwidth from a set of measurements\n  bandwidthMinRequestDuration: 10, // minimum duration (ms) to consider a measurement good enough to use in bandwidth calculation\n  loadedRequestMinDuration: 250, // minimum duration (ms) of a request to consider it to be loading the connection\n  loadedLatencyMaxPoints: 20 // number of data points to keep for loaded latency\n};\n","import { scaleThreshold } from 'd3-scale';\n\nexport default {\n  // AIM\n  aimMeasurementScoring: {\n    packetLoss: scaleThreshold([0.01, 0.05, 0.25, 0.5], [10, 5, 0, -10, -20]),\n    latency: scaleThreshold([10, 20, 50, 100, 500], [20, 10, 5, 0, -10, -20]),\n    loadedLatencyIncrease: scaleThreshold(\n      [10, 20, 50, 100, 500],\n      [20, 10, 5, 0, -10, -20]\n    ),\n    jitter: scaleThreshold([10, 20, 100, 500], [10, 5, 0, -10, -20]),\n    download: scaleThreshold([1e6, 10e6, 50e6, 100e6], [0, 5, 10, 20, 30]),\n    upload: scaleThreshold([1e6, 10e6, 50e6, 100e6], [0, 5, 10, 20, 30])\n  },\n  aimExperiencesDefs: {\n    streaming: {\n      input: ['latency', 'packetLoss', 'download', 'loadedLatencyIncrease'],\n      pointThresholds: [15, 20, 40, 60]\n    },\n    gaming: {\n      input: ['latency', 'packetLoss', 'loadedLatencyIncrease'],\n      pointThresholds: [5, 15, 25, 30]\n    },\n    rtc: {\n      input: ['latency', 'jitter', 'packetLoss', 'loadedLatencyIncrease'],\n      pointThresholds: [5, 15, 25, 40]\n    }\n  }\n};\n","import 'isomorphic-fetch';\n\nimport memoize from 'lodash.memoize';\n\nconst MAX_RETRIES = 20;\n\nconst ESTIMATED_HEADER_FRACTION = 0.005; // ~.5% of packet header / payload size. used when transferSize is not available.\n\nconst cfGetServerTime = r => {\n  // extract server-timing from headers: server-timing: cfRequestDuration;dur=15.999794\n  const serverTiming = r.headers.get(`server-timing`);\n  if (serverTiming) {\n    const re = serverTiming.match(/(?:^|;)\\s*dur=([0-9.]+)/);\n    if (re) return +re[1];\n  }\n};\n\nconst getTtfb = perf => perf.responseStart - perf.requestStart;\n\nconst gePayloadDownload = perf => perf.responseEnd - perf.responseStart; // min 1ms\n\nconst calcDownloadDuration = ({ ping, payloadDownloadTime }) =>\n  ping + payloadDownloadTime; // request duration excluding server time\n\nconst calcUploadDuration = ({ ttfb }) => ttfb;\n\nconst calcDownloadSpeed = ({ duration, transferSize }, numBytes) => {\n  // use transferSize if available. if estimating from numBytes, add ~0.5% of headers.\n  const bits =\n    8 * (transferSize || +numBytes * (1 + ESTIMATED_HEADER_FRACTION));\n  const secs = duration / 1000;\n\n  return !secs ? undefined : bits / secs;\n};\n\nconst calcUploadSpeed = ({ duration }, numBytes) => {\n  const bits = 8 * numBytes * (1 + ESTIMATED_HEADER_FRACTION); // take into account estimated packet headers\n  const secs = duration / 1000; // subtract estimated server time\n\n  return !secs ? undefined : bits / secs;\n};\n\nconst genContent = memoize(numBytes => '0'.repeat(numBytes));\n\n//\n\nclass BandwidthMeasurementEngine {\n  constructor(\n    measurements,\n    {\n      downloadApiUrl,\n      uploadApiUrl,\n      throttleMs = 0,\n      estimatedServerTime = 0\n    } = {}\n  ) {\n    if (!measurements) throw new Error('Missing measurements argument');\n    if (!downloadApiUrl) throw new Error('Missing downloadApiUrl argument');\n    if (!uploadApiUrl) throw new Error('Missing uploadApiUrl argument');\n\n    this.#measurements = measurements;\n    this.#downloadApi = downloadApiUrl;\n    this.#uploadApi = uploadApiUrl;\n    this.#throttleMs = throttleMs;\n    this.#estimatedServerTime = Math.max(0, estimatedServerTime);\n  }\n\n  // Public attributes\n  get results() {\n    // read access to results\n    return this.#results;\n  }\n\n  #qsParams = {}; // additional query string params to include in the requests\n  get qsParams() {\n    return this.#qsParams;\n  }\n  set qsParams(v) {\n    this.#qsParams = v;\n  }\n\n  #fetchOptions = {}; // additional options included in the requests\n  get fetchOptions() {\n    return this.#fetchOptions;\n  }\n  set fetchOptions(v) {\n    this.#fetchOptions = v;\n  }\n\n  finishRequestDuration = 1000; // download/upload duration (ms) to reach for stopping further measurements\n  abortRequestDuration = 0;\n  getServerTime = cfGetServerTime; // method to extract server time from response\n\n  #responseHook = r => r; // pipe-through of response objects\n  set responseHook(f) {\n    this.#responseHook = f;\n  }\n\n  #onRunningChange = () => {}; // callback invoked when engine starts/stops\n  set onRunningChange(f) {\n    this.#onRunningChange = f;\n  }\n  #onNewMeasurementStarted = () => {}; // callback invoked when a new item in the measurement list is started\n  set onNewMeasurementStarted(f) {\n    this.#onNewMeasurementStarted = f;\n  }\n  #onMeasurementResult = () => {}; // callback invoked when a new measurement result arrives\n  set onMeasurementResult(f) {\n    this.#onMeasurementResult = f;\n  }\n  #onFinished = () => {}; // callback invoked when all the measurements are finished\n  set onFinished(f) {\n    this.#onFinished = f;\n  }\n  #onConnectionError = () => {}; // Invoked when unable to get a response from the API\n  set onConnectionError(f) {\n    this.#onConnectionError = f;\n  }\n\n  // Public methods\n  pause() {\n    this.#cancelCurrentMeasurement(`pause()`);\n    this.#setRunning(false);\n  }\n\n  play() {\n    if (!this.#running) {\n      this.#setRunning(true);\n      this.#nextMeasurement();\n    }\n  }\n\n  // Internal state\n  #measurements;\n  #downloadApi;\n  #uploadApi;\n\n  #running = false;\n  #finished = { down: false, up: false };\n  #results = { down: {}, up: {} };\n  #measIdx = 0;\n  #counter = 0;\n  #retries = 0;\n  #minDuration = -Infinity; // of current measurement\n  #throttleMs = 0;\n  #estimatedServerTime = 0;\n\n  /**\n   * Aborts the current measurement.\n   * @type AbortController\n   */\n  #currentAbortController = undefined;\n\n  // Internal methods\n  #setRunning(running) {\n    if (running !== this.#running) {\n      this.#running = running;\n      setTimeout(() => this.#onRunningChange(this.#running));\n    }\n\n    if (!running) {\n      this.#currentAbortController?.abort('setRunning(false)');\n    }\n  }\n\n  #saveMeasurementResults(measIdx, measTiming) {\n    const { bytes, dir } = this.#measurements[measIdx];\n\n    const results = this.#results;\n\n    const bytesResult = results[dir].hasOwnProperty(bytes)\n      ? results[dir][bytes]\n      : {\n          timings: [],\n          // count all measurements with same bytes and direction\n          numMeasurements: this.#measurements\n            .filter(({ bytes: b, dir: d }) => bytes === b && dir === d)\n            .map(m => m.count)\n            .reduce((agg, cnt) => agg + cnt, 0)\n        };\n\n    !!measTiming && bytesResult.timings.push(measTiming);\n    bytesResult.timings = bytesResult.timings.slice(\n      -bytesResult.numMeasurements\n    );\n\n    results[dir][bytes] = bytesResult;\n\n    if (measTiming) {\n      setTimeout(() => {\n        this.#onMeasurementResult(\n          {\n            type: dir,\n            bytes,\n            ...measTiming\n          },\n          results\n        );\n      });\n    } else {\n      this.#onNewMeasurementStarted(this.#measurements[measIdx], results);\n    }\n  }\n\n  #nextMeasurement() {\n    const measurements = this.#measurements;\n    let meas = measurements[this.#measIdx];\n\n    if (this.#counter >= meas.count) {\n      // Finished current measurement\n      const finished = this.#finished;\n      if (\n        this.#minDuration > this.finishRequestDuration &&\n        !meas.bypassMinDuration\n      ) {\n        // mark direction as finished\n        const dir = meas.dir;\n        this.#finished[dir] = true;\n        Object.values(this.#finished).every(finished => finished) &&\n          this.#onFinished(this.#results);\n      }\n\n      // clear settings\n      this.#counter = 0;\n      this.#minDuration = -Infinity;\n      performance.clearResourceTimings();\n\n      do {\n        this.#measIdx += 1; // skip through finished measurements\n      } while (\n        this.#measIdx < measurements.length &&\n        finished[measurements[this.#measIdx].dir]\n      );\n\n      if (this.#measIdx >= measurements.length) {\n        // reached the end: halt further measurements\n        this.#finished = { down: true, up: true };\n        this.#setRunning(false);\n        this.#onFinished(this.#results);\n        return;\n      }\n\n      meas = measurements[this.#measIdx];\n    }\n\n    const measIdx = this.#measIdx;\n\n    if (this.#counter === 0) {\n      this.#saveMeasurementResults(measIdx); // register measurement start\n    }\n\n    const { bytes: numBytes, dir } = meas;\n    const isDown = dir === 'down';\n\n    const apiUrl = isDown ? this.#downloadApi : this.#uploadApi;\n    const qsParams = Object.assign({}, this.#qsParams);\n    isDown && (qsParams.bytes = `${numBytes}`);\n\n    const url = `${\n      apiUrl.startsWith('http') || apiUrl.startsWith('//')\n        ? ''\n        : window.location.origin // use abs to match perf timing urls\n    }${apiUrl}?${Object.entries(qsParams)\n      .map(([k, v]) => `${k}=${v}`)\n      .join('&')}`;\n\n    const fetchOpt = Object.assign(\n      {},\n      isDown\n        ? {}\n        : {\n            method: 'POST',\n            body: genContent(numBytes)\n          },\n      this.#fetchOptions\n    );\n\n    if (this.#retries === 0) {\n      // abort existing abort controller\n      this.#currentAbortController?.abort('restarting engine');\n\n      // create new abort controller\n      this.#currentAbortController = new AbortController();\n      if (this.abortRequestDuration) {\n        const abortTimeout = setTimeout(() => {\n          const errorMessage = `${isDown ? 'Download' : 'Upload'} measurement of ${numBytes} bytes aborted. Measurement exceeded bandwidthAbortRequestDuration (${this.abortRequestDuration}ms)`;\n          this.#cancelCurrentMeasurement(errorMessage);\n          this.#retries = 0;\n          this.#setRunning(false);\n          this.#onConnectionError(errorMessage);\n        }, this.abortRequestDuration);\n        this.#currentAbortController.signal.addEventListener('abort', () =>\n          clearTimeout(abortTimeout)\n        );\n      }\n    }\n\n    let serverTime;\n    fetch(url, {\n      ...fetchOpt,\n      signal: this.#currentAbortController.signal\n    })\n      .then(r => {\n        if (r.ok) return r;\n        throw Error(r.statusText);\n      })\n      .then(r => {\n        this.getServerTime && (serverTime = this.getServerTime(r));\n        return r;\n      })\n      .then(r =>\n        r.text().then(body => {\n          this.#responseHook &&\n            this.#responseHook({\n              url,\n              headers: r.headers,\n              body\n            });\n\n          return body;\n        })\n      )\n      .then(() => {\n        const perf = performance.getEntriesByName(url).slice(-1)[0]; // get latest perf timing\n        const timing = {\n          transferSize: perf.transferSize,\n          ttfb: getTtfb(perf),\n          payloadDownloadTime: gePayloadDownload(perf),\n          serverTime: serverTime || -1,\n          measTime: new Date()\n        };\n        timing.ping = Math.max(\n          1e-2,\n          timing.ttfb - (serverTime || this.#estimatedServerTime)\n        ); // ttfb = network latency + server time\n\n        timing.duration = (isDown ? calcDownloadDuration : calcUploadDuration)(\n          timing\n        );\n        timing.bps = (isDown ? calcDownloadSpeed : calcUploadSpeed)(\n          timing,\n          numBytes\n        );\n\n        if (isDown && numBytes) {\n          const reqSize = +numBytes;\n          if (\n            timing.transferSize &&\n            (timing.transferSize < reqSize ||\n              timing.transferSize / reqSize > 1.05)\n          ) {\n            // log if transferSize is too different from requested size\n            console.warn(\n              `Requested ${reqSize}B but received ${timing.transferSize}B (${\n                Math.round((timing.transferSize / reqSize) * 1e4) / 1e2\n              }%).`\n            );\n          }\n        }\n\n        this.#saveMeasurementResults(measIdx, timing);\n        const requestDuration = timing.duration;\n        this.#minDuration =\n          this.#minDuration < 0\n            ? requestDuration\n            : Math.min(this.#minDuration, requestDuration); // carry minimum request duration\n\n        this.#counter += 1;\n        this.#retries = 0;\n\n        if (this.#throttleMs) {\n          const throttleTimeout = setTimeout(\n            () => this.#nextMeasurement(),\n            this.#throttleMs\n          );\n          this.#currentAbortController.signal.addEventListener('abort', () =>\n            clearTimeout(throttleTimeout)\n          );\n        } else {\n          this.#nextMeasurement();\n        }\n      })\n      .catch(error => {\n        if (this.#currentAbortController.signal.aborted) {\n          return;\n        }\n        console.warn(`Error fetching ${url}: ${error}`);\n\n        if (this.#retries++ < MAX_RETRIES) {\n          this.#nextMeasurement(); // keep trying\n        } else {\n          this.#retries = 0;\n          this.#setRunning(false);\n          this.#onConnectionError(\n            `Connection failed to ${url}. Gave up after ${MAX_RETRIES} retries.`\n          );\n        }\n      });\n  }\n\n  #cancelCurrentMeasurement(reason) {\n    this.#currentAbortController?.abort(\n      reason || `aborted with no reason provided`\n    );\n  }\n}\n\nexport default BandwidthMeasurementEngine;\n","import BandwidthEngine from './BandwidthEngine';\n\nclass BandwidthWithParallelLatencyEngine extends BandwidthEngine {\n  constructor(\n    measurements,\n    {\n      measureParallelLatency = false,\n      parallelLatencyThrottleMs = 100,\n      downloadApiUrl,\n      uploadApiUrl,\n      estimatedServerTime = 0,\n      ...ptProps\n    } = {}\n  ) {\n    super(measurements, {\n      downloadApiUrl,\n      uploadApiUrl,\n      estimatedServerTime,\n      ...ptProps\n    });\n\n    if (measureParallelLatency) {\n      this.#latencyEngine = new BandwidthEngine(\n        [\n          {\n            dir: 'down',\n            bytes: 0,\n            count: Infinity,\n            bypassMinDuration: true\n          }\n        ],\n        {\n          downloadApiUrl,\n          uploadApiUrl,\n          estimatedServerTime,\n          throttleMs: parallelLatencyThrottleMs\n        }\n      );\n      this.#latencyEngine.qsParams = {\n        during: `${measurements[0].dir}load`\n      };\n\n      super.onRunningChange = this.#setLatencyRunning;\n      super.onConnectionError = () => this.#latencyEngine.pause();\n    }\n  }\n\n  // Public attributes\n  get latencyResults() {\n    // read access to latency results\n    return this.#latencyEngine && this.#latencyEngine.results.down[0].timings;\n  }\n\n  // callback invoked when a new parallel latency result arrives\n  set onParallelLatencyResult(f) {\n    this.#latencyEngine &&\n      (this.#latencyEngine.onMeasurementResult = res => f(res));\n  }\n\n  // Overridden attributes\n  get fetchOptions() {\n    return super.fetchOptions;\n  }\n  set fetchOptions(fetchOptions) {\n    super.fetchOptions = fetchOptions;\n    this.#latencyEngine && (this.#latencyEngine.fetchOptions = fetchOptions);\n  }\n\n  set onRunningChange(onRunningChange) {\n    super.onRunningChange = running => {\n      this.#setLatencyRunning(running);\n      onRunningChange(running);\n    };\n  }\n\n  set onConnectionError(onConnectionError) {\n    super.onConnectionError = (...args) => {\n      this.#latencyEngine && this.#latencyEngine.pause();\n      onConnectionError(...args);\n    };\n  }\n\n  // Internal state\n  #latencyEngine;\n  #latencyTimeout;\n\n  // Internal methods\n  #setLatencyRunning(running) {\n    if (this.#latencyEngine) {\n      if (!running) {\n        clearTimeout(this.#latencyTimeout);\n        this.#latencyEngine.pause();\n      } else {\n        // slight delay in starting latency measurements\n        this.#latencyTimeout = setTimeout(() => this.#latencyEngine.play(), 20);\n      }\n    }\n  }\n}\n\nexport default BandwidthWithParallelLatencyEngine;\n","import 'isomorphic-fetch';\n\nimport BandwidthEngine from '../BandwidthEngine';\n\nclass LoggingBandwidthEngine extends BandwidthEngine {\n  constructor(\n    measurements,\n    { measurementId, logApiUrl, sessionId, ...ptProps } = {}\n  ) {\n    super(measurements, ptProps);\n\n    this.#measurementId = measurementId;\n    this.#logApiUrl = logApiUrl;\n    this.#sessionId = sessionId;\n\n    super.qsParams = logApiUrl ? { measId: this.#measurementId } : {};\n    super.responseHook = r => this.#loggingResponseHook(r);\n    super.onMeasurementResult = meas => this.#logMeasurement(meas);\n  }\n\n  // Overridden attributes\n  set qsParams(qsParams) {\n    super.qsParams = this.#logApiUrl\n      ? { measId: this.#measurementId, ...qsParams }\n      : qsParams;\n  }\n\n  set responseHook(responseHook) {\n    super.responseHook = r => {\n      responseHook(r);\n      this.#loggingResponseHook(r);\n    };\n  }\n\n  set onMeasurementResult(onMeasurementResult) {\n    super.onMeasurementResult = (meas, ...restArgs) => {\n      onMeasurementResult(meas, ...restArgs);\n      this.#logMeasurement(meas);\n    };\n  }\n\n  // Internal state\n  #measurementId;\n  #token;\n  #requestTime;\n  #logApiUrl;\n  #sessionId;\n\n  // Internal methods\n  #loggingResponseHook(r) {\n    if (!this.#logApiUrl) return;\n\n    // get request time\n    this.#requestTime = +r.headers.get(`cf-meta-request-time`);\n\n    // get token in payload\n    this.#token = r.body.slice(-300).split('___').pop();\n  }\n\n  #logMeasurement(measData) {\n    if (!this.#logApiUrl) return;\n\n    const logData = {\n      type: measData.type,\n      bytes: measData.bytes,\n      ping: Math.round(measData.ping), // round to ms\n      ttfb: Math.round(measData.ttfb), // round to ms\n      payloadDownloadTime: Math.round(measData.payloadDownloadTime),\n      duration: Math.round(measData.duration),\n      transferSize: Math.round(measData.transferSize),\n      serverTime: Math.round(measData.serverTime),\n      token: this.#token,\n      requestTime: this.#requestTime,\n      measId: this.#measurementId,\n      sessionId: this.#sessionId\n    };\n\n    this.#token = null;\n    this.#requestTime = null;\n\n    fetch(this.#logApiUrl, {\n      method: 'POST',\n      body: JSON.stringify(logData),\n      ...this.fetchOptions\n    });\n  }\n}\n\nexport default LoggingBandwidthEngine;\n","import 'isomorphic-fetch';\n\nclass PromiseEngine {\n  constructor(promiseFn) {\n    if (!promiseFn) throw new Error(`Missing operation to perform`);\n\n    this.#promiseFn = promiseFn;\n    this.play();\n  }\n\n  // Public methods\n  pause() {\n    this.#cancelCurrent();\n    this.#setRunning(false);\n  }\n\n  stop() {\n    this.pause();\n  }\n\n  play() {\n    if (!this.#running) {\n      this.#setRunning(true);\n      this.#next();\n    }\n  }\n\n  // Internal state\n  #running = false;\n  #currentPromise = undefined;\n  #promiseFn;\n\n  // Internal methods\n  #setRunning(running) {\n    if (running !== this.#running) {\n      this.#running = running;\n    }\n  }\n\n  #next() {\n    const curPromise = (this.#currentPromise = this.#promiseFn().then(() => {\n      !curPromise._cancel && this.#next();\n    }));\n  }\n\n  #cancelCurrent() {\n    const curPromise = this.#currentPromise;\n    curPromise && (curPromise._cancel = true);\n  }\n}\n\nclass LoadNetworkEngine {\n  constructor({ download, upload } = {}) {\n    // Expected attrs for each: { apiUrl, chunkSize }\n    if (!download && !upload)\n      throw new Error('Missing at least one of download/upload config');\n\n    [\n      [download, 'download'],\n      [upload, 'upload']\n    ]\n      .filter(([cfg]) => cfg)\n      .forEach(([cfg, type]) => {\n        const { apiUrl, chunkSize } = cfg;\n        if (!apiUrl) throw new Error(`Missing ${type} apiUrl argument`);\n        if (!chunkSize) throw new Error(`Missing ${type} chunkSize argument`);\n      });\n\n    const getLoadEngine = ({ apiUrl, qsParams = {}, fetchOptions = {} }) =>\n      new PromiseEngine(() => {\n        const fetchQsParams = Object.assign({}, qsParams, this.qsParams);\n        const url = `${\n          apiUrl.startsWith('http') || apiUrl.startsWith('//')\n            ? ''\n            : window.location.origin // use abs to match perf timing urls\n        }${apiUrl}?${Object.entries(fetchQsParams)\n          .map(([k, v]) => `${k}=${v}`)\n          .join('&')}`;\n        const fetchOpt = Object.assign({}, fetchOptions, this.fetchOptions);\n\n        return fetch(url, fetchOpt)\n          .then(r => {\n            if (r.ok) return r;\n            throw Error(r.statusText);\n          })\n          .then(r => r.text());\n      });\n\n    download &&\n      this.#engines.push(\n        getLoadEngine({\n          apiUrl: download.apiUrl,\n          qsParams: { bytes: `${download.chunkSize}` }\n        })\n      );\n\n    upload &&\n      this.#engines.push(\n        getLoadEngine({\n          apiUrl: upload.apiUrl,\n          fetchOptions: {\n            method: 'POST',\n            body: '0'.repeat(upload.chunkSize)\n          }\n        })\n      );\n  }\n\n  // Public attributes\n  qsParams = {}; // additional query string params to include in the requests\n  fetchOptions = {}; // additional options included in the requests\n\n  // Public methods\n  pause() {\n    this.#engines.forEach(engine => engine.pause());\n  }\n\n  stop() {\n    this.pause();\n  }\n\n  play() {\n    this.#engines.forEach(engine => engine.play());\n  }\n\n  // Internal state\n  #engines = [];\n}\n\nexport default LoadNetworkEngine;\n","export default class SelfWebRtcDataConnection {\n  constructor({\n    iceServers = [],\n    acceptIceCandidate = candidate => {\n      let protocol = candidate.protocol || '';\n      // parsed webRTC candidate properties not extracted in Firefox: https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidate\n      if (!protocol && candidate.candidate) {\n        const sdpAttrs = candidate.candidate.split(' ');\n        sdpAttrs.length >= 3 && (protocol = sdpAttrs[2]);\n      }\n      return protocol.toLowerCase() === 'udp';\n    },\n    dataChannelCfg = {\n      ordered: false,\n      maxRetransmits: 0\n    },\n    ...rtcPeerConnectionCfg\n  } = {}) {\n    const sender = new RTCPeerConnection({\n      iceServers,\n      ...rtcPeerConnectionCfg\n    });\n    const receiver = new RTCPeerConnection({\n      iceServers,\n      ...rtcPeerConnectionCfg\n    });\n\n    let senderDc = sender.createDataChannel('channel', dataChannelCfg);\n    senderDc.onopen = () => {\n      this.#established = true;\n      this.onOpen();\n    };\n    senderDc.onclose = () => this.close();\n    // senderDc.onmessage = msg => this.#onMessage(msg.data);\n\n    receiver.ondatachannel = e => {\n      const dc = e.channel;\n      dc.onclose = () => this.close();\n      dc.onmessage = msg => this.onMessageReceived(msg.data);\n\n      this.#receiverDc = dc;\n    };\n\n    // sender.onconnectionstatechange = e => console.log('connection state change', e);\n    // sender.oniceconnectionstatechange = e => console.log('ice connection state change', e);\n    // sender.onicecandidateerror = e => console.log('ice error', e);\n    sender.onicecandidate = e => {\n      // console.log('sender', e.candidate);\n      e.candidate &&\n        acceptIceCandidate(e.candidate) &&\n        receiver.addIceCandidate(e.candidate);\n    };\n    receiver.onicecandidate = e => {\n      // console.log('receiver', e.candidate);\n      e.candidate &&\n        acceptIceCandidate(e.candidate) &&\n        sender.addIceCandidate(e.candidate);\n    };\n\n    sender\n      .createOffer()\n      .then(offer => sender.setLocalDescription(offer))\n      .then(() => receiver.setRemoteDescription(sender.localDescription))\n      .then(() => receiver.createAnswer())\n      .then(answer => receiver.setLocalDescription(answer))\n      .then(() => sender.setRemoteDescription(receiver.localDescription));\n\n    this.#sender = sender;\n    this.#receiver = receiver;\n    this.#senderDc = senderDc;\n    this.#established = false;\n  }\n\n  // Public attributes\n  onOpen = () => {}; // callback invoked when WebRTC TURN connection is established\n  onClose = () => {}; // callback invoked when WebRTC TURN connection is closed\n  onMessageReceived = () => {}; // callback invoked when a new message is received from the TURN server\n\n  // Public methods\n  send(msg) {\n    return this.#senderDc.send(msg);\n  }\n\n  close() {\n    this.#sender && this.#sender.close();\n    this.#receiver && this.#receiver.close();\n    this.#senderDc && this.#senderDc.close();\n    this.#receiverDc && this.#receiverDc.close();\n\n    this.#established && this.onClose();\n    this.#established = false;\n    return this;\n  }\n\n  // Internal state\n  #established = false;\n\n  #sender;\n  #receiver;\n  #senderDc;\n  #receiverDc;\n}\n","import SelfWebRtcDataConnection from './SelfWebRtcDataConnection';\n\nexport default class PacketLossEngine {\n  constructor({\n    turnServerUri,\n    turnServerCredsApi,\n    turnServerCredsApiParser = ({ username, credential, server }) => ({\n      turnServerUser: username,\n      turnServerPass: credential,\n      turnServerUri: server\n    }),\n    turnServerCredsApiIncludeCredentials = false,\n    turnServerUser,\n    turnServerPass,\n    numMsgs = 100,\n    batchSize = 10,\n    batchWaitTime = 10, // ms (in between batches)\n    responsesWaitTime = 5000, // ms (debounced time after last msg without any response)\n    connectionTimeout = 5000 // ms\n  } = {}) {\n    if (!turnServerUri && !turnServerCredsApi)\n      throw new Error('Missing turnServerCredsApi or turnServerUri argument');\n\n    if ((!turnServerUser || !turnServerPass) && !turnServerCredsApi)\n      throw new Error(\n        'Missing either turnServerCredsApi or turnServerUser+turnServerPass arguments'\n      );\n\n    this.#numMsgs = numMsgs;\n\n    (!turnServerUser || !turnServerPass\n      ? // Get TURN credentials from API endpoint if not statically supplied\n        fetch(turnServerCredsApi, {\n          credentials: turnServerCredsApiIncludeCredentials\n            ? 'include'\n            : undefined\n        })\n          .then(r => r.json())\n          .then(d => {\n            if (d.error) throw d.error;\n            return d;\n          })\n          .then(turnServerCredsApiParser)\n      : Promise.resolve({\n          turnServerUser,\n          turnServerPass\n        })\n    )\n      .catch(e => this.#onCredentialsFailure(e))\n      .then(\n        ({\n          turnServerUser,\n          turnServerPass,\n          turnServerUri: credsApiTurnServerUri\n        }) => {\n          const c = (this.#webRtcConnection = new SelfWebRtcDataConnection({\n            iceServers: [\n              {\n                urls: `turn:${credsApiTurnServerUri || turnServerUri}?transport=udp`,\n                username: turnServerUser,\n                credential: turnServerPass\n              }\n            ],\n            iceTransportPolicy: 'relay'\n          }));\n\n          let connectionSuccess = false;\n          setTimeout(() => {\n            if (!connectionSuccess) {\n              c.close();\n              this.#onConnectionError('ICE connection timeout!');\n            }\n          }, connectionTimeout);\n\n          const msgTracker = this.#msgTracker;\n          c.onOpen = () => {\n            connectionSuccess = true;\n\n            const self = this;\n            (function sendNum(n) {\n              if (n <= numMsgs) {\n                let i = n;\n                while (i <= Math.min(numMsgs, n + batchSize - 1)) {\n                  msgTracker[i] = false;\n                  c.send(i);\n                  self.onMsgSent(i);\n                  i++;\n                }\n                setTimeout(() => sendNum(i), batchWaitTime);\n              } else {\n                self.onAllMsgsSent(Object.keys(msgTracker).length);\n\n                const finishFn = () => {\n                  c.close();\n                  self.#onFinished(self.results);\n                };\n                let finishTimeout = setTimeout(finishFn, responsesWaitTime);\n\n                let missingMsgs = Object.values(self.#msgTracker).filter(\n                  recv => !recv\n                ).length;\n                c.onMessageReceived = msg => {\n                  clearTimeout(finishTimeout);\n\n                  msgTracker[msg] = true;\n                  self.onMsgReceived(msg);\n\n                  missingMsgs--;\n                  if (\n                    missingMsgs <= 0 &&\n                    Object.values(self.#msgTracker).every(recv => recv)\n                  ) {\n                    // Last msg received, shortcut out\n                    finishFn();\n                  } else {\n                    // restart timeout\n                    finishTimeout = setTimeout(finishFn, responsesWaitTime);\n                  }\n                };\n              }\n            })(1);\n          };\n          c.onMessageReceived = msg => {\n            msgTracker[msg] = true;\n            this.onMsgReceived(msg);\n          };\n        }\n      )\n      .catch(e => this.#onConnectionError(e.toString()));\n  }\n\n  // Public attributes\n  #onCredentialsFailure = () => {}; // Invoked when unable to fetch TURN server credentials\n  set onCredentialsFailure(f) {\n    this.#onCredentialsFailure = f;\n  }\n  #onConnectionError = () => {}; // Invoked when unable to establish a connection with TURN server\n  set onConnectionError(f) {\n    this.#onConnectionError = f;\n  }\n  #onFinished = () => {}; // Invoked when the packet loss measurement is complete\n  set onFinished(f) {\n    this.#onFinished = f;\n  }\n  onMsgSent = () => {}; // Invoked when sending a new message to the TURN server\n  onAllMsgsSent = () => {}; // Invoked when all messages have been sent\n  onMsgReceived = () => {}; // Invoked when receiving a new message from the TURN server\n\n  get results() {\n    const totalMessages = this.#numMsgs;\n    const numMessagesSent = Object.keys(this.#msgTracker).length;\n    const lostMessages = Object.entries(this.#msgTracker)\n      .filter(([, recv]) => !recv)\n      .map(([n]) => +n);\n    const packetLoss = lostMessages.length / numMessagesSent;\n    return { totalMessages, numMessagesSent, packetLoss, lostMessages };\n  }\n\n  // Public methods\n\n  // Internal state\n  #msgTracker = {};\n  #webRtcConnection;\n  #numMsgs;\n}\n","import LoadNetworkEngine from '../LoadNetworkEngine';\nimport PacketLossEngine from './PacketLossEngine';\n\nclass PacketLossUnderLoadEngine extends PacketLossEngine {\n  constructor({\n    downloadChunkSize,\n    uploadChunkSize,\n    downloadApiUrl,\n    uploadApiUrl,\n    ...ptProps\n  } = {}) {\n    super(ptProps);\n\n    if (downloadChunkSize || uploadChunkSize) {\n      this.#loadEngine = new LoadNetworkEngine({\n        download: downloadChunkSize\n          ? {\n              apiUrl: downloadApiUrl,\n              chunkSize: downloadChunkSize\n            }\n          : null,\n        upload: uploadChunkSize\n          ? {\n              apiUrl: uploadApiUrl,\n              chunkSize: uploadChunkSize\n            }\n          : null\n      });\n\n      super.onCredentialsFailure =\n        super.onConnectionError =\n        super.onFinished =\n          () => this.#loadEngine.stop();\n    }\n  }\n\n  // Overridden attributes\n  set qsParams(qsParams) {\n    this.#loadEngine && (this.#loadEngine.qsParams = qsParams);\n  }\n\n  set fetchOptions(fetchOptions) {\n    this.#loadEngine && (this.#loadEngine.fetchOptions = fetchOptions);\n  }\n\n  set onCredentialsFailure(onCredentialsFailure) {\n    super.onCredentialsFailure = (...args) => {\n      onCredentialsFailure(...args);\n      this.#loadEngine && this.#loadEngine.stop();\n    };\n  }\n\n  set onConnectionError(onConnectionError) {\n    super.onConnectionError = (...args) => {\n      onConnectionError(...args);\n      this.#loadEngine && this.#loadEngine.stop();\n    };\n  }\n\n  set onFinished(onFinished) {\n    super.onFinished = (...args) => {\n      onFinished(...args);\n      this.#loadEngine && this.#loadEngine.stop();\n    };\n  }\n\n  // Internal state\n  #loadEngine;\n}\n\nexport default PacketLossUnderLoadEngine;\n","import 'isomorphic-fetch';\n\nexport default class ReachabilityEngine {\n  constructor(targetUrl, { timeout = -1, fetchOptions = {} } = {}) {\n    let finished = false;\n    const finish = ({ reachable, ...rest }) => {\n      if (finished) return;\n      finished = true;\n      this.onFinished({\n        targetUrl,\n        reachable,\n        ...rest\n      });\n    };\n\n    fetch(targetUrl, fetchOptions)\n      .then(response => {\n        finish({\n          reachable: true,\n          response\n        });\n      })\n      .catch(error => {\n        finish({\n          reachable: false,\n          error\n        });\n      });\n\n    timeout > 0 &&\n      setTimeout(\n        () => finish({ reachable: false, error: 'Request timeout' }),\n        timeout\n      );\n  }\n\n  // Public attributes\n  onFinished = () => {};\n}\n","export const sum = vals => vals.reduce((agg, val) => agg + val, 0);\nexport const avg = vals => sum(vals) / vals.length;\n\nexport const percentile = (vals, perc = 0.5) => {\n  if (!vals.length) return 0;\n\n  const sortedVals = vals.slice().sort((a, b) => a - b);\n\n  const idx = (vals.length - 1) * perc;\n  const rem = idx % 1;\n\n  if (rem === 0) return sortedVals[Math.round(idx)];\n\n  // calculate weighted average\n  const edges = [Math.floor, Math.ceil].map(rndFn => sortedVals[rndFn(idx)]);\n  return edges[0] + (edges[1] - edges[0]) * rem;\n};\n","import { percentile } from '../utils/numbers';\n\nclass MeasurementCalculations {\n  constructor(config) {\n    this.#config = config;\n  }\n\n  // Public methods\n  getLatencyPoints = latencyResults => latencyResults.timings.map(d => d.ping);\n\n  getLatency = latencyResults =>\n    percentile(\n      this.getLatencyPoints(latencyResults),\n      this.#config.latencyPercentile\n    );\n\n  getJitter(latencyResults) {\n    // calc jitter as the average latency delta between consecutive samples\n    const pings = this.getLatencyPoints(latencyResults);\n    return pings.length < 2\n      ? null\n      : pings.reduce(\n          ({ sumDeltas = 0, prevLatency }, latency) => ({\n            sumDeltas:\n              sumDeltas +\n              (prevLatency !== undefined ? Math.abs(prevLatency - latency) : 0),\n            prevLatency: latency\n          }),\n          {}\n        ).sumDeltas /\n          (pings.length - 1);\n  }\n\n  getBandwidthPoints = bandwidthResults =>\n    Object.entries(bandwidthResults)\n      .map(([bytes, { timings }]) =>\n        timings.map(\n          ({ bps, duration, ping, measTime, serverTime, transferSize }) => ({\n            bytes: +bytes,\n            bps,\n            duration,\n            ping,\n            measTime,\n            serverTime,\n            transferSize\n          })\n        )\n      )\n      .flat();\n\n  getBandwidth = bandwidthResults =>\n    percentile(\n      this.getBandwidthPoints(bandwidthResults)\n        .filter(d => d.duration >= this.#config.bandwidthMinRequestDuration)\n        .map(d => d.bps)\n        .filter(bps => bps),\n      this.#config.bandwidthPercentile\n    );\n\n  getLoadedLatency = loadedResults =>\n    this.getLatency({ timings: this.#extractLoadedLatencies(loadedResults) });\n\n  getLoadedJitter = loadedResults =>\n    this.getJitter({ timings: this.#extractLoadedLatencies(loadedResults) });\n\n  getLoadedLatencyPoints = loadedResults =>\n    this.getLatencyPoints({\n      timings: this.#extractLoadedLatencies(loadedResults)\n    });\n\n  getPacketLoss = plResults => plResults.packetLoss;\n  getPacketLossDetails = plResults => plResults;\n\n  getReachability = reachabilityResults => !!reachabilityResults.reachable;\n  getReachabilityDetails = d => ({ host: d.host, reachable: d.reachable });\n\n  // Internal state\n  #config;\n\n  // Internal methods\n  #extractLoadedLatencies = loadedResults =>\n    Object.values(loadedResults)\n      .filter(\n        // keep only file sizes that saturated the connection\n        d =>\n          d.timings.length &&\n          Math.min(...d.timings.map(d => d.duration)) >=\n            this.#config.loadedRequestMinDuration\n      )\n      .map(d => d.sideLatency || [])\n      .flat()\n      .slice(-this.#config.loadedLatencyMaxPoints); // last measurements are most accurate\n}\n\nexport default MeasurementCalculations;\n","import { scaleThreshold } from 'd3-scale';\n\nimport { sum } from '../utils/numbers';\n\nconst classificationNames = ['bad', 'poor', 'average', 'good', 'great'];\n\nconst customResultTypes = {\n  loadedLatencyIncrease: measurements =>\n    measurements.latency &&\n    (measurements.downLoadedLatency || measurements.upLoadedLatency)\n      ? Math.max(measurements.downLoadedLatency, measurements.upLoadedLatency) -\n        measurements.latency\n      : undefined\n};\n\nconst defaultPoints = {\n  packetLoss: 0\n};\n\nclass ScoresCalculations {\n  constructor(config) {\n    this.#config = config;\n  }\n\n  getScores(measurements) {\n    const scores = Object.assign(\n      ...Object.entries(this.#config.aimMeasurementScoring).map(\n        ([type, fn]) => {\n          const val = customResultTypes.hasOwnProperty(type)\n            ? customResultTypes[type](measurements)\n            : measurements[type];\n          return val === undefined\n            ? defaultPoints.hasOwnProperty(type)\n              ? { [type]: defaultPoints[type] }\n              : {}\n            : {\n                [type]: val === undefined ? 0 : +fn(val)\n              };\n        }\n      )\n    );\n\n    return Object.assign(\n      {},\n      ...Object.entries(this.#config.aimExperiencesDefs)\n        .filter(([, { input }]) => input.every(k => scores.hasOwnProperty(k)))\n        .map(([k, { input, pointThresholds }]) => {\n          const sumPoints = Math.max(0, sum(input.map(k => scores[k])));\n          const classificationIdx = scaleThreshold(\n            pointThresholds,\n            [0, 1, 2, 3, 4]\n          )(sumPoints);\n          const classificationName = classificationNames[classificationIdx];\n          return {\n            [k]: {\n              points: sumPoints,\n              classificationIdx,\n              classificationName\n            }\n          };\n        })\n    );\n  }\n\n  // Internal state\n  #config;\n}\n\nexport default ScoresCalculations;\n","import MeasurementCalculations from './MeasurementCalculations';\nimport ScoresCalculations from './ScoresCalculations';\n\nclass Results {\n  constructor(config) {\n    this.#config = config;\n    this.clear();\n    this.#measCalc = new MeasurementCalculations(this.#config);\n    this.#scoresCalc = new ScoresCalculations(this.#config);\n  }\n\n  // Public attributes\n  raw;\n\n  get isFinished() {\n    return Object.values(this.raw).every(d => d.finished);\n  }\n\n  // Public methods\n  clear() {\n    this.raw = Object.assign(\n      {},\n      ...[...new Set(this.#config.measurements.map(m => m.type))].map(m => ({\n        [m]: { started: false, finished: false, results: {} }\n      }))\n    );\n  }\n\n  getUnloadedLatency = () => this.#calcGetter('getLatency', 'latency');\n  getUnloadedJitter = () => this.#calcGetter('getJitter', 'latency');\n  getUnloadedLatencyPoints = () =>\n    this.#calcGetter('getLatencyPoints', 'latency', []);\n  getDownLoadedLatency = () => this.#calcGetter('getLoadedLatency', 'download');\n  getDownLoadedJitter = () => this.#calcGetter('getLoadedJitter', 'download');\n  getDownLoadedLatencyPoints = () =>\n    this.#calcGetter('getLoadedLatencyPoints', 'download', []);\n  getUpLoadedLatency = () => this.#calcGetter('getLoadedLatency', 'upload');\n  getUpLoadedJitter = () => this.#calcGetter('getLoadedJitter', 'upload');\n  getUpLoadedLatencyPoints = () =>\n    this.#calcGetter('getLoadedLatencyPoints', 'upload', []);\n  getDownloadBandwidth = () => this.#calcGetter('getBandwidth', 'download');\n  getDownloadBandwidthPoints = () =>\n    this.#calcGetter('getBandwidthPoints', 'download', []);\n  getUploadBandwidth = () => this.#calcGetter('getBandwidth', 'upload');\n  getUploadBandwidthPoints = () =>\n    this.#calcGetter('getBandwidthPoints', 'upload', []);\n  getPacketLoss = () => this.#calcGetter('getPacketLoss', 'packetLoss');\n  getPacketLossDetails = () =>\n    this.#calcGetter('getPacketLossDetails', 'packetLoss', undefined, true);\n\n  getSummary() {\n    const items = {\n      download: this.getDownloadBandwidth,\n      upload: this.getUploadBandwidth,\n      latency: this.getUnloadedLatency,\n      jitter: this.getUnloadedJitter,\n      downLoadedLatency: this.getDownLoadedLatency,\n      downLoadedJitter: this.getDownLoadedJitter,\n      upLoadedLatency: this.getUpLoadedLatency,\n      upLoadedJitter: this.getUpLoadedJitter,\n      packetLoss: this.getPacketLoss,\n      v4Reachability: this.#getV4Reachability,\n      v6Reachability: this.#getV6Reachability\n    };\n\n    return Object.assign(\n      ...Object.entries(items).map(([key, fn]) => {\n        const val = fn();\n        return val === undefined\n          ? {}\n          : {\n              [key]: val\n            };\n      })\n    );\n  }\n\n  getScores = () => this.#scoresCalc.getScores(this.getSummary());\n\n  // Internal state\n  #config;\n  #measCalc;\n  #scoresCalc;\n\n  // Internal methods\n  #calcGetter = (\n    calcFn,\n    resKey,\n    defaultVal = undefined,\n    surfaceError = false\n  ) =>\n    !this.raw.hasOwnProperty(resKey) || !this.raw[resKey].started\n      ? defaultVal\n      : surfaceError && this.raw[resKey].error\n        ? { error: this.raw[resKey].error }\n        : this.#measCalc[calcFn](this.raw[resKey].results);\n\n  #getV4Reachability = () =>\n    this.#calcGetter('getReachability', 'v4Reachability');\n  #getV4ReachabilityDetails = () =>\n    this.#calcGetter('getReachabilityDetails', 'v4Reachability');\n  #getV6Reachability = () =>\n    this.#calcGetter('getReachability', 'v6Reachability');\n  #getV6ReachabilityDetails = () =>\n    this.#calcGetter('getReachabilityDetails', 'v6Reachability');\n}\n\nexport default Results;\n","import 'isomorphic-fetch';\n\nconst round = (num, decimals = 0) =>\n  !num ? num : Math.round(num * 10 ** decimals) / 10 ** decimals;\n\nconst latencyPointsParser = durations => durations.map(d => round(d, 2));\nconst bpsPointsParser = pnts =>\n  pnts.map(d => ({\n    bytes: +d.bytes,\n    bps: round(d.bps)\n  }));\n\nconst packetLossParser = d =>\n  d.error\n    ? undefined\n    : {\n        numMessages: d.numMessagesSent,\n        lossRatio: round(d.packetLoss, 4)\n      };\n\nconst resultsParsers = {\n  latencyMs: ['getUnloadedLatencyPoints', latencyPointsParser],\n  download: ['getDownloadBandwidthPoints', bpsPointsParser],\n  upload: ['getUploadBandwidthPoints', bpsPointsParser],\n  downLoadedLatencyMs: ['getDownLoadedLatencyPoints', latencyPointsParser],\n  upLoadedLatencyMs: ['getUpLoadedLatencyPoints', latencyPointsParser],\n  packetLoss: ['getPacketLossDetails', packetLossParser]\n  // v4Reachability: ['getV4ReachabilityDetails'],\n  // v6Reachability: ['getV6ReachabilityDetails']\n};\n\nconst scoreParser = d => ({\n  points: d.points,\n  classification: d.classificationName\n});\n\nconst logAimResults = (results, { apiUrl, sessionId }) => {\n  const logData = {\n    sessionId\n  };\n  Object.entries(resultsParsers).forEach(([logK, [fn, parser = d => d]]) => {\n    const val = results[fn]();\n    val && (logData[logK] = parser(val));\n  });\n\n  const scores = results.getScores();\n  scores &&\n    (logData.scores = Object.assign(\n      {},\n      ...Object.entries(scores).map(([k, score]) => ({\n        [k]: scoreParser(score)\n      }))\n    ));\n\n  fetch(apiUrl, {\n    method: 'POST',\n    body: JSON.stringify(logData)\n  });\n};\n\nexport default logAimResults;\n","import 'isomorphic-fetch';\n\nimport { defaultConfig, internalConfig } from './config';\nimport BandwidthEngine from './engines/LoggingBandwidthEngine';\nimport PacketLossEngine from './engines/PacketLossEngine';\nimport ReachabilityEngine from './engines/ReachabilityEngine';\n\nimport Results from './Results';\nimport logFinalResults from './logging/logFinalResults';\n\nconst DEFAULT_OPTIMAL_DOWNLOAD_SIZE = 1e6;\nconst DEFAULT_OPTIMAL_UPLOAD_SIZE = 1e6;\nconst OPTIMAL_SIZE_RATIO = 0.5; // of largest size reached in measurement\n\nconst pausableTypes = ['latency', 'latencyUnderLoad', 'download', 'upload'];\n\nconst genMeasId = () => `${Math.round(Math.random() * 1e16)}`;\n\nclass MeasurementEngine {\n  constructor(userConfig = {}) {\n    this.#config = Object.assign({}, defaultConfig, userConfig, internalConfig);\n    this.#results = new Results(this.#config);\n    this.#config.autoStart && this.play();\n  }\n\n  // Public attributes\n  get results() {\n    // read access to results\n    return this.#results;\n  }\n\n  get isRunning() {\n    return this.#running;\n  }\n\n  get isFinished() {\n    return this.#finished;\n  }\n\n  onRunningChange = () => {};\n  onResultsChange = () => {};\n  onPhaseChange = () => {};\n\n  #onFinish = () => {}; // callback invoked when all the measurements are finished\n  set onFinish(f) {\n    this.#onFinish = f;\n  }\n\n  #onError = () => {}; // callback invoked if an error occurs during measurement\n  set onError(f) {\n    this.#onError = f;\n  }\n\n  // Public methods\n  pause() {\n    pausableTypes.includes(this.#curType()) && this.#curEngine.pause();\n    this.#setRunning(false);\n  }\n\n  play() {\n    if (!this.#running) {\n      // Clear timings before running the engine\n      performance.clearResourceTimings();\n\n      // Default is 250. This can mean the buffer is filled between measurements if many requests are being done\n      // in the same page the engine is running.\n      performance.setResourceTimingBufferSize(10000);\n      this.#setRunning(true);\n      this.#next();\n    }\n  }\n  restart() {\n    this.#clear();\n    this.play();\n  }\n\n  // Internal state\n  #config;\n  #results;\n\n  #measurementId = genMeasId();\n  #curMsmIdx = -1;\n  #curEngine;\n  #optimalDownloadChunkSize = DEFAULT_OPTIMAL_DOWNLOAD_SIZE;\n  #optimalUploadChunkSize = DEFAULT_OPTIMAL_UPLOAD_SIZE;\n\n  #running = false;\n  #finished = false;\n\n  // Internal methods\n  #setRunning(running) {\n    if (running !== this.#running) {\n      this.#running = running;\n      this.onRunningChange(this.#running);\n    }\n  }\n\n  #setFinished(finished) {\n    if (finished !== this.#finished) {\n      this.#finished = finished;\n      finished && setTimeout(() => this.#onFinish(this.results));\n    }\n  }\n\n  #curType() {\n    return this.#curMsmIdx < 0 ||\n      this.#curMsmIdx >= this.#config.measurements.length\n      ? null\n      : this.#config.measurements[this.#curMsmIdx].type;\n  }\n\n  #curTypeResults() {\n    return this.#results.raw[this.#curType()] || undefined;\n  }\n\n  #clear() {\n    this.#destroyCurEngine();\n\n    this.#measurementId = genMeasId();\n    this.#curMsmIdx = -1;\n    this.#curEngine = undefined;\n\n    this.#setRunning(false);\n    this.#setFinished(false);\n\n    this.#results.clear();\n  }\n\n  #destroyCurEngine() {\n    const engine = this.#curEngine;\n    if (!engine) return;\n\n    engine.onFinished =\n      engine.onConnectionError =\n      engine.onFail =\n      engine.onMsgReceived =\n      engine.onCredentialsFailure =\n      engine.onMeasurementResult =\n        () => {};\n\n    pausableTypes.includes(this.#curType()) && engine.pause();\n  }\n\n  #next() {\n    if (\n      pausableTypes.includes(this.#curType()) &&\n      this.#curTypeResults() &&\n      this.#curTypeResults().started &&\n      !this.#curTypeResults().finished &&\n      !this.#curTypeResults().finishedCurrentRound &&\n      !this.#curTypeResults().error\n    ) {\n      this.#curEngine.play();\n      return;\n    }\n\n    // advance to next msm\n    this.#curMsmIdx++;\n    if (this.#curMsmIdx >= this.#config.measurements.length) {\n      // done with measurements\n      this.#setRunning(false);\n      this.#setFinished(true);\n      return;\n    }\n\n    const { type, ...msmConfig } = this.#config.measurements[this.#curMsmIdx];\n    const msmResults = this.#curTypeResults();\n\n    this.onPhaseChange({\n      measurementId: this.#curMsmIdx,\n      measurement: { type, ...msmConfig }\n    });\n\n    const { downloadApiUrl, uploadApiUrl, estimatedServerTime } = this.#config;\n\n    let engine;\n    switch (type) {\n      case 'v4Reachability':\n      case 'v6Reachability':\n        engine = new ReachabilityEngine(`https://${msmConfig.host}`, {\n          fetchOptions: {\n            method: 'GET',\n            mode: 'no-cors'\n          }\n        });\n        engine.onFinished = result => {\n          msmResults.finished = true;\n          msmResults.results = {\n            host: msmConfig.host,\n            ...result\n          };\n          this.onResultsChange({ type });\n          this.#next();\n        };\n        break;\n      case 'rpki':\n        engine = new ReachabilityEngine(\n          `https://${this.#config.rpkiInvalidHost}`,\n          {\n            timeout: 5000\n          }\n        );\n        engine.onFinished = result => {\n          (result.response ? result.response.json() : Promise.resolve()).then(\n            response => {\n              msmResults.finished = true;\n              msmResults.results = {\n                host: this.#config.rpkiInvalidHost,\n                filteringInvalids: !result.reachable,\n                ...(response\n                  ? {\n                      asn: response.asn,\n                      name: response.name\n                    }\n                  : {})\n              };\n              this.onResultsChange({ type });\n              this.#next();\n            }\n          );\n        };\n        break;\n      case 'nxdomain':\n        engine = new ReachabilityEngine(`https://${msmConfig.nxhost}`, {\n          fetchOptions: { mode: 'no-cors' }\n        });\n        engine.onFinished = result => {\n          msmResults.finished = true;\n          msmResults.results = {\n            host: msmConfig.nxhost,\n            reachable: result.reachable\n          };\n          this.onResultsChange({ type });\n          this.#next();\n        };\n        break;\n      case 'packetLoss':\n      case 'packetLossUnderLoad':\n        {\n          msmResults.finished = false;\n\n          const { numPackets: numMsgs, ...ptCfg } = msmConfig;\n          const {\n            turnServerUri,\n            turnServerCredsApiUrl: turnServerCredsApi,\n            turnServerUser,\n            turnServerPass,\n            includeCredentials\n          } = this.#config;\n          engine = new PacketLossEngine({\n            turnServerUri,\n            turnServerCredsApi,\n            turnServerCredsApiIncludeCredentials: includeCredentials,\n            turnServerUser,\n            turnServerPass,\n            numMsgs,\n\n            // if under load\n            downloadChunkSize: msmConfig.loadDown\n              ? this.#optimalDownloadChunkSize\n              : undefined,\n            uploadChunkSize: msmConfig.loadUp\n              ? this.#optimalUploadChunkSize\n              : undefined,\n            downloadApiUrl,\n            uploadApiUrl,\n\n            ...ptCfg\n          });\n        }\n\n        engine.onMsgReceived = () => {\n          msmResults.results = Object.assign({}, engine.results);\n          this.onResultsChange({ type });\n        };\n\n        engine.onFinished = () => {\n          msmResults.finished = true;\n          this.onResultsChange({ type });\n          this.#next();\n        };\n\n        engine.onConnectionError = e => {\n          msmResults.error = e;\n          this.onResultsChange({ type });\n          this.#onError(`Connection error while measuring packet loss: ${e}`);\n          this.#next();\n        };\n\n        engine.onCredentialsFailure = () => {\n          msmResults.error = 'unable to get turn server credentials';\n          this.onResultsChange({ type });\n          this.#onError(\n            'Error while measuring packet loss: unable to get turn server credentials.'\n          );\n          this.#next();\n        };\n\n        break;\n      case 'latency':\n      case 'latencyUnderLoad':\n        msmResults.finished = false;\n\n        engine = new BandwidthEngine(\n          [\n            {\n              dir: 'down',\n              bytes: 0,\n              count: msmConfig.numPackets,\n              bypassMinDuration: true\n            }\n          ],\n          {\n            downloadApiUrl,\n            uploadApiUrl,\n            estimatedServerTime,\n            logApiUrl: this.#config.logMeasurementApiUrl,\n            measurementId: this.#measurementId,\n            sessionId: this.#config.sessionId,\n\n            // if under load\n            downloadChunkSize: msmConfig.loadDown\n              ? this.#optimalDownloadChunkSize\n              : undefined,\n            uploadChunkSize: msmConfig.loadUp\n              ? this.#optimalUploadChunkSize\n              : undefined\n          }\n        );\n        engine.fetchOptions = {\n          credentials: this.#config.includeCredentials ? 'include' : undefined\n        };\n        engine.abortRequestDuration =\n          this.#config.bandwidthAbortRequestDuration;\n\n        engine.onMeasurementResult = engine.onNewMeasurementStarted = (\n          meas,\n          results\n        ) => {\n          msmResults.results = Object.assign({}, results.down[0]);\n          this.onResultsChange({ type });\n        };\n\n        engine.onFinished = () => {\n          msmResults.finished = true;\n          this.onResultsChange({ type });\n          this.#running && this.#next();\n        };\n\n        engine.onConnectionError = e => {\n          msmResults.error = e;\n          this.onResultsChange({ type });\n          this.#onError(`Connection error while measuring latency: ${e}`);\n          this.#next();\n        };\n\n        engine.play();\n        break;\n      case 'download':\n      case 'upload':\n        if (msmResults.finished || msmResults.error) {\n          this.#next(); // skip, already concluded this bandwidth measurement type\n        } else {\n          delete msmResults.finishedCurrentRound;\n\n          const measureParallelLatency =\n            this.#config[\n              `measure${type === 'download' ? 'Down' : 'Up'}loadLoadedLatency`\n            ];\n\n          engine = new BandwidthEngine(\n            [{ dir: type === 'download' ? 'down' : 'up', ...msmConfig }],\n            {\n              downloadApiUrl,\n              uploadApiUrl,\n              estimatedServerTime,\n              logApiUrl: this.#config.logMeasurementApiUrl,\n              measurementId: this.#measurementId,\n              measureParallelLatency,\n              parallelLatencyThrottleMs: this.#config.loadedLatencyThrottle,\n              sessionId: this.#config.sessionId\n            }\n          );\n          engine.fetchOptions = {\n            credentials: this.#config.includeCredentials ? 'include' : undefined\n          };\n          engine.finishRequestDuration =\n            this.#config.bandwidthFinishRequestDuration;\n          engine.abortRequestDuration =\n            this.#config.bandwidthAbortRequestDuration;\n\n          engine.onNewMeasurementStarted = ({ count, bytes }) => {\n            const res = (msmResults.results = Object.assign(\n              {},\n              msmResults.results\n            ));\n\n            !res.hasOwnProperty(bytes) &&\n              (res[bytes] = {\n                timings: [],\n                numMeasurements: 0,\n                sideLatency: measureParallelLatency ? [] : undefined\n              });\n\n            // check if count hasn't already been added\n            if (\n              res[bytes].numMeasurements - res[bytes].timings.length !==\n              count\n            ) {\n              res[bytes].numMeasurements += count;\n              this.onResultsChange({ type });\n            }\n          };\n\n          engine.onMeasurementResult = ({ bytes, ...timing }) => {\n            // merge in new result\n            msmResults.results[bytes].timings.push(timing);\n            msmResults.results = Object.assign({}, msmResults.results);\n            this.onResultsChange({ type });\n          };\n\n          engine.onParallelLatencyResult = res => {\n            // merge in new latency result\n            msmResults.results[msmConfig.bytes].sideLatency.push(res);\n            msmResults.results = Object.assign({}, msmResults.results);\n            this.onResultsChange({ type });\n          };\n\n          engine.onFinished = results => {\n            const isLastMsmOfType = !this.#config.measurements\n              .slice(this.#curMsmIdx + 1)\n              .map(d => d.type)\n              .includes(type);\n\n            const minDuration = Math.min(\n              ...Object.values(type === 'download' ? results.down : results.up)\n                .slice(-1)[0]\n                .timings.map(d => d.duration)\n            );\n\n            const reachedEndOfMsmType =\n              isLastMsmOfType ||\n              (!msmConfig.bypassMinDuration &&\n                minDuration > this.#config.bandwidthFinishRequestDuration);\n\n            if (!reachedEndOfMsmType) {\n              msmResults.finishedCurrentRound = true;\n            } else {\n              msmResults.finished = true;\n              this.onResultsChange({ type });\n\n              // record optimal load size\n              const largestSize = Object.keys(msmResults.results)\n                .map(n => +n)\n                .sort((a, b) => b - a)[0];\n              const optimalSize = largestSize * OPTIMAL_SIZE_RATIO;\n\n              type === 'download' &&\n                (this.#optimalDownloadChunkSize = optimalSize);\n              type === 'upload' && (this.#optimalUploadChunkSize = optimalSize);\n            }\n\n            this.#running && this.#next();\n          };\n\n          engine.onConnectionError = e => {\n            msmResults.error = e;\n            this.onResultsChange({ type });\n            this.#onError(`Connection error while measuring ${type}: ${e}`);\n            this.#next();\n          };\n\n          engine.play();\n        }\n        break;\n      default:\n    }\n\n    this.#curEngine = engine;\n\n    msmResults.started = true;\n    this.onResultsChange({ type });\n  }\n}\n\nclass LoggingMeasurementEngine extends MeasurementEngine {\n  constructor(userConfig, ...pt) {\n    super(userConfig, ...pt);\n    super.onFinish = this.#logFinalResults;\n\n    const config = Object.assign({}, defaultConfig, userConfig, internalConfig);\n\n    this.#logAimApiUrl = config.logAimApiUrl;\n    this.#sessionId = config.sessionId;\n  }\n\n  // Public attributes\n  set onFinish(onFinish) {\n    super.onFinish = results => {\n      onFinish(results);\n      this.#logFinalResults(results);\n    };\n  }\n\n  // Internal state\n  #logAimApiUrl;\n  #sessionId;\n\n  // Internal methods\n  #logFinalResults = results => {\n    this.#logAimApiUrl &&\n      logFinalResults(results, {\n        apiUrl: this.#logAimApiUrl,\n        sessionId: this.#sessionId\n      });\n  };\n}\n\nexport default LoggingMeasurementEngine;\n"]}