bitmovin-analytics 2.53.0 → 2.53.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"bitmovin-analytics.js","mappings":"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H,aAA4B,IAAb6I,EAAG3I,SAGzB,IAAMoY,EAAWzP,EAAGyP,UAChB,IAAA7N,cAAa6N,KACfhgB,KAAKkgB,SAAWF,EAASE,SACzBlgB,KAAKmgB,eAAiBH,EAASG,eAC/BngB,KAAKqgB,aAAeL,EAASK,aAC7BrgB,KAAKsgB,aAAeN,EAASM,aAC7BtgB,KAAKygB,WAAaT,EAASS,WAC3BzgB,KAAK0gB,sBAAwBV,EAASU,sBACtC1gB,KAAK6gB,mBAAqBb,EAASa,mBACnC7gB,KAAK+gB,cAAgBf,EAASe,cAC9B/gB,KAAKshB,sBAAuB,IAAA0B,4BAA2BhD,EAASsB,sBAChEthB,KAAKmhB,UAAYnB,EAASmB,UAC1BnhB,KAAKghB,QAAUhB,EAASgB,QACxBhhB,KAAKihB,gBAAkBjB,EAASiB,iBAGlCjhB,KAAKkyD,YAMT,SAAwBC,GACtB,QAAkBhyD,IAAdgyD,EAGJ,OAAmB,IAAfA,EACKA,GAEF,IAAAvf,eAAcuf,EACvB,CAduBC,CAAe7hD,EAAGsP,gBACrC7f,KAAKqyD,YAA0B,QAAZ,EAAA9hD,EAAGqP,iBAAS,SAAK,IAAAzN,cAAanS,KAAKkyD,aAAelyD,KAAKkyD,aAAe,OAAI/xD,EAC7FH,KAAKiwC,YAAa,IAAAjtB,4BAA2BzS,EAAGoP,SAzChD,CA0CF,EAvGW,EAAAgwB,SAAAA,C,mMCJb,cA6Ga,EAAAuV,qBAAsD,CACjE,cACA,cACA,cACA,cACA,cACA,cACA,cACA,cACA,cACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,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","sources":["webpack://bitmovin.analytics/webpack/universalModuleDefinition","webpack://bitmovin.analytics/./node_modules/javascript-state-machine/state-machine.js","webpack://bitmovin.analytics/./src/adapters/amazonIVS/AmazonIVSAdapter.ts","webpack://bitmovin.analytics/./src/adapters/amazonIVS/AmazonIVSInternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/amazonIVS/playback/ErrorService.ts","webpack://bitmovin.analytics/./src/adapters/amazonIVS/playback/PauseEventDispatcher.ts","webpack://bitmovin.analytics/./src/adapters/amazonIVS/playback/PlaybackService.ts","webpack://bitmovin.analytics/./src/adapters/amazonIVS/playback/VideoStartupService.ts","webpack://bitmovin.analytics/./src/adapters/amazonIVS/player/AmazonIVSPlayerContext.ts","webpack://bitmovin.analytics/./src/adapters/amazonIVS/player/AmazonIVSPlayerEventHandler.ts","webpack://bitmovin.analytics/./src/adapters/amazonIVS/player/AmazonIVSPlayerEventListener.ts","webpack://bitmovin.analytics/./src/adapters/amazonIVS/player/SourceUrlProvider.ts","webpack://bitmovin.analytics/./src/adapters/amazonIVS/utils/CollectorEventBus.ts","webpack://bitmovin.analytics/./src/adapters/amazonIVS/window/WindowEventListener.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/Bitmovin8AdModule.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/Bitmovin8Adapter.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/Bitmovin8InternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/ads/AdUtils.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/bitmovin8AdapterSsaiApiSanitizeUtils.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/player/HttpRequestTrackingAdapter.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/player/SegmentTrackerAdapter.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/player/SpeedMeterAdapter.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/playerModule.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/playerUtils.ts","webpack://bitmovin.analytics/./src/adapters/bitmovinPwx/BitmovinPwxAdapter.ts","webpack://bitmovin.analytics/./src/adapters/bitmovinPwx/BitmovinPwxAnalyticsPackage.ts","webpack://bitmovin.analytics/./src/adapters/bitmovinPwx/BitmovinPwxAnalyticsStateMachine.ts","webpack://bitmovin.analytics/./src/adapters/bitmovinPwx/BitmovinPwxInternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/bitmovinPwx/ExportNames.ts","webpack://bitmovin.analytics/./src/adapters/cafv3/CAFv3Adapter.ts","webpack://bitmovin.analytics/./src/adapters/cafv3/CAFv3InternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/cafv3/castFrameworkTypes.ts","webpack://bitmovin.analytics/./src/adapters/dashjs/DashjsAdapter.ts","webpack://bitmovin.analytics/./src/adapters/dashjs/DashjsInternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/dashjs/dashjsApiUtils.ts","webpack://bitmovin.analytics/./src/adapters/hlsjs/HlsAdapter.ts","webpack://bitmovin.analytics/./src/adapters/hlsjs/HlsInternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/hlsjs/player/HlsJsPlayerTypes.ts","webpack://bitmovin.analytics/./src/adapters/hlsjs/player/HlsSpeedMeterAdapter.ts","webpack://bitmovin.analytics/./src/adapters/html5/HTML5InternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/html5/HTMLVideoElementAdapter.ts","webpack://bitmovin.analytics/./src/adapters/html5/HTMLVideoElementInternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/html5/player/HTMLVideoElementStatisticsProvider.ts","webpack://bitmovin.analytics/./src/adapters/internal/InternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/internal/ads/AdModuleAPI.ts","webpack://bitmovin.analytics/./src/adapters/shaka/ShakaAdapter.ts","webpack://bitmovin.analytics/./src/adapters/shaka/ShakaInternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/shaka/shakaPlayerTypes.ts","webpack://bitmovin.analytics/./src/adapters/theo/DrmPerformanceService.ts","webpack://bitmovin.analytics/./src/adapters/theo/THEOplayerAdapter.ts","webpack://bitmovin.analytics/./src/adapters/theo/THEOplayerInternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/theo/THEOplayerNetworkInterceptor.ts","webpack://bitmovin.analytics/./src/adapters/theo/ads/AdUtils.ts","webpack://bitmovin.analytics/./src/adapters/theo/ads/THEOplayerAdModule.ts","webpack://bitmovin.analytics/./src/adapters/theo/playback/CallbackScheduler.ts","webpack://bitmovin.analytics/./src/adapters/theo/playback/DelayedEventDispatcher.ts","webpack://bitmovin.analytics/./src/adapters/videojs/VideoJsAdapter.ts","webpack://bitmovin.analytics/./src/adapters/videojs/VideojsInternalAdapter.ts","webpack://bitmovin.analytics/./src/analyticsStateMachines/AnalyticsStateMachine.ts","webpack://bitmovin.analytics/./src/analyticsStateMachines/CAFv3AnalyticsStateMachine.ts","webpack://bitmovin.analytics/./src/analyticsStateMachines/HTML5AnalyticsStateMachine.ts","webpack://bitmovin.analytics/./src/analyticsStateMachines/THEOplayerAnalyticsStateMachine.ts","webpack://bitmovin.analytics/./src/analyticsStateMachines/VideoJsAnalyticsStateMachine.ts","webpack://bitmovin.analytics/./src/analyticsStateMachines/amazonivs/AmazonIVSStateMachine.ts","webpack://bitmovin.analytics/./src/analyticsStateMachines/bitmovin8/Bitmovin8AnalyticsStateMachine.ts","webpack://bitmovin.analytics/./src/analyticsStateMachines/stateMachineUtils.ts","webpack://bitmovin.analytics/./src/api/adapterApiUtils.ts","webpack://bitmovin.analytics/./src/core/AdAnalytics.ts","webpack://bitmovin.analytics/./src/core/Analytics.ts","webpack://bitmovin.analytics/./src/core/BackendFactory.ts","webpack://bitmovin.analytics/./src/core/DebuggingBackend.ts","webpack://bitmovin.analytics/./src/core/DownloadSpeedMeter.ts","webpack://bitmovin.analytics/./src/core/EventDispatcher.ts","webpack://bitmovin.analytics/./src/core/HeartbeatService.ts","webpack://bitmovin.analytics/./src/core/IdenticalErrorReportingLimiter.ts","webpack://bitmovin.analytics/./src/core/LicenseCheckingBackend.ts","webpack://bitmovin.analytics/./src/core/LongPlaytimeFilteringBackend.ts","webpack://bitmovin.analytics/./src/core/Measure.ts","webpack://bitmovin.analytics/./src/core/NoOpBackend.ts","webpack://bitmovin.analytics/./src/core/QualityChangeService.ts","webpack://bitmovin.analytics/./src/core/QueueBackend.ts","webpack://bitmovin.analytics/./src/core/RemoteBackend.ts","webpack://bitmovin.analytics/./src/core/SegmentTracker.ts","webpack://bitmovin.analytics/./src/core/SequenceNumberBackend.ts","webpack://bitmovin.analytics/./src/core/SessionPersistenceHandler.ts","webpack://bitmovin.analytics/./src/core/SourceInfoFallbackService.ts","webpack://bitmovin.analytics/./src/core/VideoCompletionTracker.ts","webpack://bitmovin.analytics/./src/core/ssai/SsaiService.ts","webpack://bitmovin.analytics/./src/core/ssai/ssaiApiUtils.ts","webpack://bitmovin.analytics/./src/core/ssai/ssaiEngagementInteractionData.ts","webpack://bitmovin.analytics/./src/core/ssai/ssaiUtils.ts","webpack://bitmovin.analytics/./src/enums/AdType.ts","webpack://bitmovin.analytics/./src/enums/CDNProvider.ts","webpack://bitmovin.analytics/./src/enums/CastTech.ts","webpack://bitmovin.analytics/./src/enums/Codecs.ts","webpack://bitmovin.analytics/./src/enums/ErrorCode.ts","webpack://bitmovin.analytics/./src/enums/Event.ts","webpack://bitmovin.analytics/./src/enums/MIMETypes.ts","webpack://bitmovin.analytics/./src/enums/PageLoadType.ts","webpack://bitmovin.analytics/./src/enums/Player.ts","webpack://bitmovin.analytics/./src/enums/PlayerSize.ts","webpack://bitmovin.analytics/./src/enums/StreamTypes.ts","webpack://bitmovin.analytics/./src/enums/VideoStartFailedReason.ts","webpack://bitmovin.analytics/./src/features/Feature.ts","webpack://bitmovin.analytics/./src/features/FeatureManager.ts","webpack://bitmovin.analytics/./src/features/errordetails/ErrorDetailBackend.ts","webpack://bitmovin.analytics/./src/features/errordetails/ErrorDetailTracking.ts","webpack://bitmovin.analytics/./src/features/httprequesttracking/HttpRequestTracking.ts","webpack://bitmovin.analytics/./src/features/httprequesttracking/HttpRequestType.ts","webpack://bitmovin.analytics/./src/types/AdAnalyticsSample.ts","webpack://bitmovin.analytics/./src/types/AdBreakSample.ts","webpack://bitmovin.analytics/./src/types/AdSample.ts","webpack://bitmovin.analytics/./src/types/CustomDataValues.ts","webpack://bitmovin.analytics/./src/types/LicensingRequest.ts","webpack://bitmovin.analytics/./src/types/PlaybackInfo.ts","webpack://bitmovin.analytics/./src/types/SourceMetadata.ts","webpack://bitmovin.analytics/./src/types/StateMachineCallbacks.ts","webpack://bitmovin.analytics/./src/types/SubtitleInfo.ts","webpack://bitmovin.analytics/./src/utils/AnalyticsCall.ts","webpack://bitmovin.analytics/./src/utils/BitmovinProgressiveSourceHelper.ts","webpack://bitmovin.analytics/./src/utils/CodecHelper.ts","webpack://bitmovin.analytics/./src/utils/Converter.ts","webpack://bitmovin.analytics/./src/utils/EventDebugging.ts","webpack://bitmovin.analytics/./src/utils/Http.ts","webpack://bitmovin.analytics/./src/utils/LicenseCall.ts","webpack://bitmovin.analytics/./src/utils/Logger.ts","webpack://bitmovin.analytics/./src/utils/Queue.ts","webpack://bitmovin.analytics/./src/utils/Settings.ts","webpack://bitmovin.analytics/./src/utils/Utils.ts","webpack://bitmovin.analytics/./src/utils/Version.ts","webpack://bitmovin.analytics/./src/utils/ViewportTracker.ts","webpack://bitmovin.analytics/./src/utils/WebOSUtils.ts","webpack://bitmovin.analytics/./src/utils/WindowEventTracker.ts","webpack://bitmovin.analytics/./src/utils/analyticsConfigUtils.ts","webpack://bitmovin.analytics/./src/utils/collectorRequirementChecks.ts","webpack://bitmovin.analytics/./src/utils/documentUtils.ts","webpack://bitmovin.analytics/./src/utils/globalScope.ts","webpack://bitmovin.analytics/./src/utils/globalScopeUtils.ts","webpack://bitmovin.analytics/./src/utils/numberUtils.ts","webpack://bitmovin.analytics/./src/utils/objectUtils.ts","webpack://bitmovin.analytics/./src/utils/playerAugmentationUtils.ts","webpack://bitmovin.analytics/./src/utils/sampleUtils.ts","webpack://bitmovin.analytics/./src/utils/stringUtils.ts","webpack://bitmovin.analytics/./src/utils/uuidUtils.ts","webpack://bitmovin.analytics/webpack/bootstrap","webpack://bitmovin.analytics/webpack/runtime/global","webpack://bitmovin.analytics/./src/bitmovin-analytics.ts"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"bitmovin\"] = factory();\n\telse\n\t\troot[\"bitmovin\"] = root[\"bitmovin\"] || {}, root[\"bitmovin\"][\"analytics\"] = factory();\n})(self, function() {\nreturn ","/*\n\n Javascript State Machine Library - https://github.com/jakesgordon/javascript-state-machine\n\n Copyright (c) 2012, 2013, 2014, 2015, Jake Gordon and contributors\n Released under the MIT license - https://github.com/jakesgordon/javascript-state-machine/blob/master/LICENSE\n\n*/\n\n(function () {\n\n var StateMachine = {\n\n //---------------------------------------------------------------------------\n\n VERSION: \"2.4.0\",\n\n //---------------------------------------------------------------------------\n\n Result: {\n SUCCEEDED: 1, // the event transitioned successfully from one state to another\n NOTRANSITION: 2, // the event was successfull but no state transition was necessary\n CANCELLED: 3, // the event was cancelled by the caller in a beforeEvent callback\n PENDING: 4 // the event is asynchronous and the caller is in control of when the transition occurs\n },\n\n Error: {\n INVALID_TRANSITION: 100, // caller tried to fire an event that was innapropriate in the current state\n PENDING_TRANSITION: 200, // caller tried to fire an event while an async transition was still pending\n INVALID_CALLBACK: 300 // caller provided callback function threw an exception\n },\n\n WILDCARD: '*',\n ASYNC: 'async',\n\n //---------------------------------------------------------------------------\n\n create: function(cfg, target) {\n\n var initial = (typeof cfg.initial == 'string') ? { state: cfg.initial } : cfg.initial; // allow for a simple string, or an object with { state: 'foo', event: 'setup', defer: true|false }\n var terminal = cfg.terminal || cfg['final'];\n var fsm = target || cfg.target || {};\n var events = cfg.events || [];\n var callbacks = cfg.callbacks || {};\n var map = {}; // track state transitions allowed for an event { event: { from: [ to ] } }\n var transitions = {}; // track events allowed from a state { state: [ event ] }\n\n var add = function(e) {\n var from = Array.isArray(e.from) ? e.from : (e.from ? [e.from] : [StateMachine.WILDCARD]); // allow 'wildcard' transition if 'from' is not specified\n map[e.name] = map[e.name] || {};\n for (var n = 0 ; n < from.length ; n++) {\n transitions[from[n]] = transitions[from[n]] || [];\n transitions[from[n]].push(e.name);\n\n map[e.name][from[n]] = e.to || from[n]; // allow no-op transition if 'to' is not specified\n }\n if (e.to)\n transitions[e.to] = transitions[e.to] || [];\n };\n\n if (initial) {\n initial.event = initial.event || 'startup';\n add({ name: initial.event, from: 'none', to: initial.state });\n }\n\n for(var n = 0 ; n < events.length ; n++)\n add(events[n]);\n\n for(var name in map) {\n if (map.hasOwnProperty(name))\n fsm[name] = StateMachine.buildEvent(name, map[name]);\n }\n\n for(var name in callbacks) {\n if (callbacks.hasOwnProperty(name))\n fsm[name] = callbacks[name]\n }\n\n fsm.current = 'none';\n fsm.is = function(state) { return Array.isArray(state) ? (state.indexOf(this.current) >= 0) : (this.current === state); };\n fsm.can = function(event) { return !this.transition && (map[event] !== undefined) && (map[event].hasOwnProperty(this.current) || map[event].hasOwnProperty(StateMachine.WILDCARD)); }\n fsm.cannot = function(event) { return !this.can(event); };\n fsm.transitions = function() { return (transitions[this.current] || []).concat(transitions[StateMachine.WILDCARD] || []); };\n fsm.isFinished = function() { return this.is(terminal); };\n fsm.error = cfg.error || function(name, from, to, args, error, msg, e) { throw e || msg; }; // default behavior when something unexpected happens is to throw an exception, but caller can override this behavior if desired (see github issue #3 and #17)\n fsm.states = function() { return Object.keys(transitions).sort() };\n\n if (initial && !initial.defer)\n fsm[initial.event]();\n\n return fsm;\n\n },\n\n //===========================================================================\n\n doCallback: function(fsm, func, name, from, to, args) {\n if (func) {\n try {\n return func.apply(fsm, [name, from, to].concat(args));\n }\n catch(e) {\n return fsm.error(name, from, to, args, StateMachine.Error.INVALID_CALLBACK, \"an exception occurred in a caller-provided callback function\", e);\n }\n }\n },\n\n beforeAnyEvent: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onbeforeevent'], name, from, to, args); },\n afterAnyEvent: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onafterevent'] || fsm['onevent'], name, from, to, args); },\n leaveAnyState: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onleavestate'], name, from, to, args); },\n enterAnyState: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onenterstate'] || fsm['onstate'], name, from, to, args); },\n changeState: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onchangestate'], name, from, to, args); },\n\n beforeThisEvent: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onbefore' + name], name, from, to, args); },\n afterThisEvent: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onafter' + name] || fsm['on' + name], name, from, to, args); },\n leaveThisState: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onleave' + from], name, from, to, args); },\n enterThisState: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onenter' + to] || fsm['on' + to], name, from, to, args); },\n\n beforeEvent: function(fsm, name, from, to, args) {\n if ((false === StateMachine.beforeThisEvent(fsm, name, from, to, args)) ||\n (false === StateMachine.beforeAnyEvent( fsm, name, from, to, args)))\n return false;\n },\n\n afterEvent: function(fsm, name, from, to, args) {\n StateMachine.afterThisEvent(fsm, name, from, to, args);\n StateMachine.afterAnyEvent( fsm, name, from, to, args);\n },\n\n leaveState: function(fsm, name, from, to, args) {\n var specific = StateMachine.leaveThisState(fsm, name, from, to, args),\n general = StateMachine.leaveAnyState( fsm, name, from, to, args);\n if ((false === specific) || (false === general))\n return false;\n else if ((StateMachine.ASYNC === specific) || (StateMachine.ASYNC === general))\n return StateMachine.ASYNC;\n },\n\n enterState: function(fsm, name, from, to, args) {\n StateMachine.enterThisState(fsm, name, from, to, args);\n StateMachine.enterAnyState( fsm, name, from, to, args);\n },\n\n //===========================================================================\n\n buildEvent: function(name, map) {\n return function() {\n\n var from = this.current;\n var to = map[from] || (map[StateMachine.WILDCARD] != StateMachine.WILDCARD ? map[StateMachine.WILDCARD] : from) || from;\n var args = Array.prototype.slice.call(arguments); // turn arguments into pure array\n\n if (this.transition)\n return this.error(name, from, to, args, StateMachine.Error.PENDING_TRANSITION, \"event \" + name + \" inappropriate because previous transition did not complete\");\n\n if (this.cannot(name))\n return this.error(name, from, to, args, StateMachine.Error.INVALID_TRANSITION, \"event \" + name + \" inappropriate in current state \" + this.current);\n\n if (false === StateMachine.beforeEvent(this, name, from, to, args))\n return StateMachine.Result.CANCELLED;\n\n if (from === to) {\n StateMachine.afterEvent(this, name, from, to, args);\n return StateMachine.Result.NOTRANSITION;\n }\n\n // prepare a transition method for use EITHER lower down, or by caller if they want an async transition (indicated by an ASYNC return value from leaveState)\n var fsm = this;\n this.transition = function() {\n fsm.transition = null; // this method should only ever be called once\n fsm.current = to;\n StateMachine.enterState( fsm, name, from, to, args);\n StateMachine.changeState(fsm, name, from, to, args);\n StateMachine.afterEvent( fsm, name, from, to, args);\n return StateMachine.Result.SUCCEEDED;\n };\n this.transition.cancel = function() { // provide a way for caller to cancel async transition if desired (issue #22)\n fsm.transition = null;\n StateMachine.afterEvent(fsm, name, from, to, args);\n }\n\n var leave = StateMachine.leaveState(this, name, from, to, args);\n if (false === leave) {\n this.transition = null;\n return StateMachine.Result.CANCELLED;\n }\n else if (StateMachine.ASYNC === leave) {\n return StateMachine.Result.PENDING;\n }\n else {\n if (this.transition) // need to check in case user manually called transition() but forgot to return StateMachine.ASYNC\n return this.transition();\n }\n\n };\n }\n\n }; // StateMachine\n\n //===========================================================================\n\n //======\n // NODE\n //======\n if (typeof exports !== 'undefined') {\n if (typeof module !== 'undefined' && module.exports) {\n exports = module.exports = StateMachine;\n }\n exports.StateMachine = StateMachine;\n }\n //============\n // AMD/REQUIRE\n //============\n else if (typeof define === 'function' && define.amd) {\n define(function(require) { return StateMachine; });\n }\n //========\n // BROWSER\n //========\n else if (typeof window !== 'undefined') {\n window.StateMachine = StateMachine;\n }\n //===========\n // WEB WORKER\n //===========\n else if (typeof self !== 'undefined') {\n self.StateMachine = StateMachine;\n }\n\n}());\n","import type {AdapterAPI} from '../../api/AdapterAPI';\nimport {Analytics} from '../../core/Analytics';\nimport type {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {logger} from '../../utils/Logger';\nimport {\n hasPlayerAlreadyBeenAugmented,\n isDefined,\n markPlayerInstanceAsAugmented,\n} from '../../utils/playerAugmentationUtils';\nimport {VERSION} from '../../utils/Version';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {AmazonIVSInternalAdapter} from './AmazonIVSInternalAdapter';\nimport {SourceUrlProvider} from './player/SourceUrlProvider';\n\nexport class AmazonIVSAdapter implements AdapterAPI {\n private readonly internalAdapter: InternalAdapterAPI | undefined;\n private readonly analytics: Analytics | undefined;\n\n constructor(config: AnalyticsConfig, player: any, opts?: AnalyticsStateMachineOptions) {\n if (hasPlayerAlreadyBeenAugmented(player)) {\n logger.errorMessageToUser('Bitmovin Analytics is already hooked up to this player instance');\n return;\n }\n markPlayerInstanceAsAugmented(player);\n\n const sanitizedConfig = sanitizeAnalyticsConfig(config);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n return;\n }\n\n guardAgainstDuplicatedUserId(sanitizedConfig);\n\n const sourceUrlProvider = new SourceUrlProvider();\n this.internalAdapter = new AmazonIVSInternalAdapter(player, sourceUrlProvider, opts);\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n\n this.wrapPlayerLoad(player, sourceUrlProvider);\n }\n\n private wrapPlayerLoad(player: any, sourceUrlProvider: SourceUrlProvider) {\n const originalLoad = player.load;\n\n player.load = (...args: Parameters<typeof player.load>): ProgressEvent<FileReader> => {\n sourceUrlProvider.m3u8Url = args[0] as string;\n return originalLoad.apply(player, args);\n };\n }\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getCurrentImpressionId();\n }\n\n getUserId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getUserId();\n }\n\n setCustomData(values: CustomDataValues) {\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.setCustomData(values);\n }\n\n setCustomDataOnce(values: CustomDataValues) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.setCustomDataOnce(values);\n }\n\n sourceChange(_config: AnalyticsConfig) {\n if (!isDefined(this.analytics)) return;\n\n throw new Error('Method not implemented.');\n }\n}\n","import type {MediaPlayer} from 'amazon-ivs-player';\n\nimport {AmazonIVSStateMachine} from '../../analyticsStateMachines/amazonivs/AmazonIVSStateMachine';\nimport {Analytics} from '../../core/Analytics';\nimport {HeartbeatService} from '../../core/HeartbeatService';\nimport {Player} from '../../enums/Player';\nimport {PlayerSize} from '../../enums/PlayerSize';\nimport {StreamTypes} from '../../enums/StreamTypes';\nimport {Feature} from '../../features/Feature';\nimport {FeatureConfig} from '../../features/FeatureConfig';\nimport {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport {normalizeVideoDuration, PlaybackInfo} from '../../types/PlaybackInfo';\nimport {isVideoInFullscreen} from '../../utils/documentUtils';\nimport HTMLVideoElementStatisticsProvider from '../html5/player/HTMLVideoElementStatisticsProvider';\nimport {InternalAdapter} from '../internal/InternalAdapter';\nimport {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {AmazonIVSPlayerContext} from './player/AmazonIVSPlayerContext';\nimport {AmazonIVSPlayerEventListener} from './player/AmazonIVSPlayerEventListener';\nimport {SourceUrlProvider} from './player/SourceUrlProvider';\nimport CollectorEvents from './utils/CollectorEventBus';\nimport {WindowEventListener} from './window/WindowEventListener';\n\nexport class AmazonIVSInternalAdapter extends InternalAdapter implements InternalAdapterAPI {\n private listener: AmazonIVSPlayerEventListener;\n private windowEventListener: WindowEventListener;\n private playerStatisticsProvider: HTMLVideoElementStatisticsProvider;\n\n private readonly player: MediaPlayer;\n private readonly sourceUrlProvider: SourceUrlProvider;\n\n constructor(player: MediaPlayer, sourceUrlProvider: SourceUrlProvider, opts?: AnalyticsStateMachineOptions) {\n super(opts);\n this.player = player;\n this.sourceUrlProvider = sourceUrlProvider;\n\n const playingHeartbeatService = new HeartbeatService(() => this.currentTime);\n const stateMachine = new AmazonIVSStateMachine(this.stateMachineCallbacks, playingHeartbeatService, this.opts);\n playingHeartbeatService.setListener(stateMachine);\n this.stateMachine = stateMachine;\n\n const playerContext = new AmazonIVSPlayerContext(player);\n this.listener = AmazonIVSPlayerEventListener.create(this, playerContext, this.qualityChangeService);\n\n this.playerStatisticsProvider = new HTMLVideoElementStatisticsProvider(player.getHTMLVideoElement());\n\n this.windowEventListener = new WindowEventListener(this.windowEventTracker, this, playerContext);\n }\n\n initialize(_analytics: Analytics): Feature<FeatureConfigContainer, FeatureConfig>[] {\n this.listener.startMonitoring(this.player);\n this.windowEventListener.startMonitoring();\n CollectorEvents.RELEASE.subscribe(() => {\n this.release();\n });\n // we do not support any analytics features on IVS yet\n return [];\n }\n\n protected override get currentTime(): number {\n return this.player.getPosition();\n }\n\n override resetSourceRelatedState() {\n this.drmPerformanceInfo = undefined;\n this.playerStatisticsProvider.reset();\n }\n\n getPlayerVersion = () => this.player.getVersion();\n getPlayerName = () => Player.AMAZON_IVS;\n getPlayerTech = () => 'html5';\n getAutoPlay = () => this.player.isAutoplay();\n getCurrentPlaybackInfo(): PlaybackInfo {\n const videoElement = this.player.getHTMLVideoElement();\n\n const info: PlaybackInfo = {\n droppedFrames: this.playerStatisticsProvider.getDroppedFrames(),\n isLive: this.player.getDuration() === Infinity,\n isMuted: this.player.isMuted(),\n playerTech: this.getPlayerTech(),\n videoWindowWidth: videoElement.clientWidth,\n videoWindowHeight: videoElement.clientHeight,\n videoPlaybackHeight: videoElement.videoHeight,\n videoPlaybackWidth: videoElement.videoWidth,\n videoBitrate: this.player.getQuality().bitrate,\n videoDuration: normalizeVideoDuration(this.player.getDuration()),\n size: isVideoInFullscreen() ? PlayerSize.Fullscreen : PlayerSize.Window,\n ...this.getVideoAndAudioCodecs(),\n ...this.getCommonPlaybackInfo(),\n streamFormat: StreamTypes.hls,\n m3u8Url: this.sourceUrlProvider.m3u8Url,\n };\n return info;\n }\n\n private getVideoAndAudioCodecs() {\n const codecs = this.player.getQuality().codecs.split(',');\n if (codecs.length == 2) {\n return {\n videoCodec: codecs[0],\n audioCodec: codecs[1],\n };\n }\n return {};\n }\n}\n","import type {PlayerError} from 'amazon-ivs-player';\n\nimport {Event} from '../../../enums/Event';\nimport {ErrorEvent} from '../../../types/EventData';\nimport {EventCallbackDispatcher} from '../../internal/EventCallbackDispatcher';\nimport {PlayerContext} from '../player/AmazonIVSPlayerContext';\n\nexport class ErrorService {\n constructor(\n private dispatcher: EventCallbackDispatcher,\n private playerContext: PlayerContext,\n ) {}\n onError(payload: PlayerError) {\n const errorEvent: ErrorEvent = {\n currentTime: this.playerContext.position,\n code: payload.code,\n message: payload.message,\n originalError: payload,\n data: {\n exceptionMessage: payload.message,\n exceptionStacktrace: [payload.source],\n },\n };\n this.dispatcher.eventCallback(Event.ERROR, errorEvent);\n }\n}\n","import {Event} from '../../../enums/Event';\nimport {AnalyticsEventBase} from '../../../types/EventData';\nimport {EventCallbackDispatcher} from '../../internal/EventCallbackDispatcher';\nimport {PlayerContext} from '../player/AmazonIVSPlayerContext';\n\nenum State {\n IDLE,\n PAUSE_SCHEDULED,\n PAUSE_CANCELLED,\n}\n\nexport class PauseEventDispatcher {\n private readonly EVENT_DELAY_MS = 10;\n private state: State = State.IDLE;\n\n constructor(\n private dispatcher: EventCallbackDispatcher,\n private playerContext: PlayerContext,\n ) {}\n\n /**\n * In case of pause events emitted right before the real event\n * this method is used to cancel the scheduled pause event\n * Know cases:\n * BUFFERING: when buffer runs out `onPause` and `onRebuffering` are\n * triggered simultanously causing inconsistency which event comes first\n * PLAYING: when playback continues in vod there is a series of events triggered\n * play -> playing -> pause -> play -> playing.\n * in order to not transition into pause again we cancel the one in between the play/playing events\n * SEEKING (VOD): right before a seek/seeked event a Pause Event is triggered\n */\n cancelPause() {\n if (this.state == State.PAUSE_SCHEDULED) {\n this.state = State.PAUSE_CANCELLED;\n }\n }\n\n /**\n * schedules an pause event in the very near future\n * scheduled event is cancelable using `cancelPause`\n */\n schedulePauseEvent() {\n if (this.state == State.PAUSE_SCHEDULED) {\n return;\n }\n\n this.state = State.PAUSE_SCHEDULED;\n const eventObject: AnalyticsEventBase = {\n currentTime: this.playerContext.position,\n };\n\n setTimeout(\n () => {\n this.triggerPause(eventObject);\n this.state = State.IDLE;\n },\n this.EVENT_DELAY_MS,\n this,\n );\n }\n\n private triggerPause(event: AnalyticsEventBase) {\n if (this.state == State.PAUSE_CANCELLED) {\n return;\n }\n\n this.dispatcher.eventCallback(Event.PAUSE, event);\n }\n}\n","import type {Quality} from 'amazon-ivs-player';\n\nimport QualityChangeService from '../../../core/QualityChangeService';\nimport {Event} from '../../../enums/Event';\nimport {EventCallbackDispatcher} from '../../internal/EventCallbackDispatcher';\nimport {AmazonIVSPlayerContext, PlayerContext} from '../player/AmazonIVSPlayerContext';\n\nimport {PauseEventDispatcher} from './PauseEventDispatcher';\n\nexport class PlaybackService {\n private ignorePause = false;\n constructor(\n private dispatcher: EventCallbackDispatcher,\n private playerContext: PlayerContext,\n private pauseDispatcher: PauseEventDispatcher,\n private qualityChangeService: QualityChangeService,\n ) {}\n\n onStartupPlaying() {\n this.ignorePause = true;\n // ignore pause for the first 100ms after startup\n // needed to prevent unnecessary pause sample at the beginning\n setTimeout(() => {\n this.ignorePause = false;\n }, 100);\n }\n\n onPause() {\n if (this.ignorePause) {\n return;\n }\n\n this.pauseDispatcher.schedulePauseEvent();\n }\n\n onPlaying() {\n this.pauseDispatcher.cancelPause();\n this.playing();\n }\n\n onRebuffering() {\n this.pauseDispatcher.cancelPause();\n this.startBuffering();\n }\n\n onQualityChange(payload: Quality) {\n this.qualityChange(payload);\n }\n\n onSeek() {\n this.seek();\n }\n\n onSeeked() {\n this.seeked();\n }\n\n private startBuffering() {\n const currentTime = this.playerContext.position;\n this.dispatcher.eventCallback(Event.START_BUFFERING, {\n currentTime,\n });\n }\n\n private playing() {\n const currentTime = this.playerContext.position;\n this.dispatcher.eventCallback(Event.PLAYING, {\n currentTime,\n });\n }\n\n private qualityChange(payload: Quality) {\n if (!this.qualityChangeService.shouldAllowVideoQualityChange(payload.bitrate)) {\n this.qualityChangeService.setVideoBitrate(payload.bitrate);\n return;\n }\n this.qualityChangeService.setVideoBitrate(payload.bitrate);\n const currentTime = this.playerContext.position;\n this.dispatcher.eventCallback(Event.VIDEO_CHANGE, {\n type: 'video',\n bitrate: payload.bitrate,\n width: payload.width,\n height: payload.height,\n codec: payload.codecs,\n currentTime,\n });\n }\n\n private seek() {\n //Seeking for live streams is not supported, so seek method should do nothing for live streams\n if (this.playerContext.isLive) return;\n this.pauseDispatcher.cancelPause();\n const currentTime = this.playerContext.position;\n this.dispatcher.eventCallback(Event.SEEK, {currentTime});\n }\n\n private seeked() {\n //Seeking for live streams is not supported, so seek method should do nothing for live streams\n if (this.playerContext.isLive) return;\n this.pauseDispatcher.cancelPause();\n const currentTime = this.playerContext.position;\n this.dispatcher.eventCallback(Event.SEEKED, {currentTime});\n }\n\n static create(\n dispatcher: EventCallbackDispatcher,\n playerContext: AmazonIVSPlayerContext,\n qualityChangeService: QualityChangeService,\n ): PlaybackService {\n const pauseDispatcher = new PauseEventDispatcher(dispatcher, playerContext);\n return new PlaybackService(dispatcher, playerContext, pauseDispatcher, qualityChangeService);\n }\n}\n","import QualityChangeService from '../../../core/QualityChangeService';\nimport {Event} from '../../../enums/Event';\nimport {EventCallbackDispatcher} from '../../internal/EventCallbackDispatcher';\nimport {PlayerContext} from '../player/AmazonIVSPlayerContext';\n\nenum StartupState {\n SETUP,\n IDLE,\n STARTUP,\n STARTUP_FINISHED,\n}\n\nexport class VideoStartupService {\n constructor(\n private dispatcher: EventCallbackDispatcher,\n private playerContext: PlayerContext,\n private qualityChangeService: QualityChangeService,\n ) {}\n\n private state: StartupState = StartupState.SETUP;\n\n get finishedStartup(): boolean {\n return this.state == StartupState.STARTUP_FINISHED;\n }\n\n onInitialized() {\n this.finishSetup();\n }\n\n onPlay() {\n this.startStartup();\n }\n\n onPlaying() {\n this.finishStartup();\n }\n\n private finishSetup() {\n this.state = StartupState.IDLE;\n const currentTime = this.playerContext.position;\n this.dispatcher.eventCallback(Event.READY, {\n currentTime,\n });\n }\n\n private startStartup() {\n if (this.state != StartupState.IDLE) {\n return;\n }\n\n this.state = StartupState.STARTUP;\n const currentTime = this.playerContext.position;\n this.dispatcher.eventCallback(Event.PLAY, {\n currentTime,\n });\n }\n\n private finishStartup() {\n if (this.state != StartupState.STARTUP) {\n return;\n }\n\n this.state = StartupState.STARTUP_FINISHED;\n const currentTime = this.playerContext.position;\n this.dispatcher.eventCallback(Event.PLAYING, {\n currentTime,\n });\n\n this.qualityChangeService.resetValues();\n // pass undefined for both video and audio bitrate.\n // Why? The quality change logic in this collector was written before these args have been introduced, and the logic\n // is built in a way that the first quality change event after the startup should set them for the first time.\n //\n // Maybe in the future, we can think about setting these values already here (if available). Or completely delete\n // the usage of quality service here, as I don't think this is a place where such 'reset' or startup marking logic\n // should be (because it is done by analytics module when the startup sample is sent)\n this.qualityChangeService.setStartupHasFinished(undefined, undefined);\n }\n}\n","import type {MediaPlayer, Quality} from 'amazon-ivs-player';\n\nexport interface PlayerContext {\n position: number;\n isLive: boolean;\n currentQuality: Quality;\n}\n\nexport class AmazonIVSPlayerContext implements PlayerContext {\n constructor(private player: MediaPlayer) {}\n\n get position(): number {\n return this.player.getPosition();\n }\n\n get isLive(): boolean {\n return this.player.getDuration() === Infinity;\n }\n\n get currentQuality(): Quality {\n return this.player.getQuality();\n }\n}\n","import type {PlayerError, Quality} from 'amazon-ivs-player';\n\nimport QualityChangeService from '../../../core/QualityChangeService';\nimport {logger} from '../../../utils/Logger';\nimport {tryJSONStringify} from '../../../utils/Utils';\nimport {EventCallbackDispatcher} from '../../internal/EventCallbackDispatcher';\nimport {ErrorService} from '../playback/ErrorService';\nimport {PlaybackService} from '../playback/PlaybackService';\nimport {VideoStartupService} from '../playback/VideoStartupService';\n\nimport {AmazonIVSPlayerContext} from './AmazonIVSPlayerContext';\n\nexport class AmazonIVSPlayerEventHandler {\n constructor(\n private videoStartupService: VideoStartupService,\n private playbackService: PlaybackService,\n private errorService: ErrorService,\n ) {}\n\n onRebuffering() {\n logger.log('onRebuffering');\n this.playbackService.onRebuffering();\n }\n\n onDurationChanged(payload: number) {\n logger.log('onDurationChanged: ' + payload);\n }\n\n onError(payload: PlayerError) {\n logger.log('onError: ' + tryJSONStringify(payload));\n this.errorService.onError(payload);\n }\n\n onInitialized() {\n logger.log('onInitialized');\n if (!this.videoStartupService.finishedStartup) {\n this.videoStartupService.onInitialized();\n }\n }\n\n onQualityChanged(payload: Quality) {\n logger.log('onQualityChanged: ' + tryJSONStringify(payload));\n this.playbackService.onQualityChange(payload);\n }\n\n onTimeUpdate(payload: number) {\n logger.log('onTimeUpdate: ' + payload);\n }\n\n // HTMLVideoElement Events\n\n onPlay(event: Event) {\n if (!this.videoStartupService.finishedStartup) {\n this.videoStartupService.onPlay();\n } else {\n logger.log('onPlay:', event);\n }\n }\n\n onPause(event: Event) {\n if (this.videoStartupService.finishedStartup) {\n logger.log('onPause:', event);\n this.playbackService.onPause();\n }\n }\n\n onPlaying(event: Event) {\n logger.log('onPlaying:', event);\n if (!this.videoStartupService.finishedStartup) {\n this.videoStartupService.onPlaying();\n this.playbackService.onStartupPlaying();\n } else {\n this.playbackService.onPlaying();\n }\n }\n\n onSeek() {\n if (this.videoStartupService.finishedStartup) {\n this.playbackService.onSeek();\n }\n }\n\n onSeeked() {\n if (this.videoStartupService.finishedStartup) {\n this.playbackService.onSeeked();\n }\n }\n\n static create(\n dispatcher: EventCallbackDispatcher,\n playerContext: AmazonIVSPlayerContext,\n qualityChangeService: QualityChangeService,\n ): AmazonIVSPlayerEventHandler {\n const videoStartupService = new VideoStartupService(dispatcher, playerContext, qualityChangeService);\n const playbackService = PlaybackService.create(dispatcher, playerContext, qualityChangeService);\n const errorService = new ErrorService(dispatcher, playerContext);\n return new AmazonIVSPlayerEventHandler(videoStartupService, playbackService, errorService);\n }\n\n // for now we will keep those in here\n // once we have finished the implementation of IVS we can remove them\n\n // private onAudioBlocked() {}\n // private onBufferUpdate() {}\n // private onMutedChanged() {}\n // private onNetworkUnavailable() {}\n // private onPlaybackBlocked() {}\n // private onPlaybackRateChanged(payload: number) {}\n // private onTextCue(payload: TextCue) {}\n // private onTextMetadataCue(payload: TextMetadataCue) {}\n // private onVolumeChanged(payload: number) {}\n}\n","import type {MediaPlayer, PlayerEventType} from 'amazon-ivs-player';\n\nimport QualityChangeService from '../../../core/QualityChangeService';\nimport {EventCallbackDispatcher} from '../../internal/EventCallbackDispatcher';\n\nimport {AmazonIVSPlayerContext} from './AmazonIVSPlayerContext';\nimport {AmazonIVSPlayerEventHandler} from './AmazonIVSPlayerEventHandler';\n\n/**\n * Map of IVS Player events that we listen to, each should be type of {@link PlayerEventType}.\n *\n * Why: This way, we don't need to import string enum {@link PlayerEventType} from 'amazon-ivs-player' directly,\n * aka. compile/include it (as value) in our distribution code\n */\nexport const IVS_PLAYER_EVENT = {\n DURATION_CHANGED: 'PlayerDurationChanged' as PlayerEventType.DURATION_CHANGED,\n ERROR: 'PlayerError' as PlayerEventType.ERROR,\n INITIALIZED: 'PlayerInitialized' as PlayerEventType.INITIALIZED,\n QUALITY_CHANGED: 'PlayerQualityChanged' as PlayerEventType.QUALITY_CHANGED,\n REBUFFERING: 'PlayerRebuffering' as PlayerEventType.REBUFFERING,\n SEEK_COMPLETED: 'PlayerSeekCompleted' as PlayerEventType.SEEK_COMPLETED,\n TIME_UPDATE: 'PlayerTimeUpdate' as PlayerEventType.TIME_UPDATE,\n PLAYBACK_RATE_CHANGED: 'PlayerPlaybackRateChanged' as PlayerEventType.PLAYBACK_RATE_CHANGED,\n PLAYBACK_BLOCKED: 'PlayerPlaybackBlocked' as PlayerEventType.PLAYBACK_BLOCKED,\n} as const;\n\nexport class AmazonIVSPlayerEventListener {\n constructor(private eventHandler: AmazonIVSPlayerEventHandler) {}\n\n startMonitoring(player: MediaPlayer) {\n this.startMonitoringIVSPlayer(player);\n this.startMonitoringHTMLVideoElement(player.getHTMLVideoElement());\n }\n\n private startMonitoringHTMLVideoElement(video: HTMLVideoElement) {\n video.addEventListener('play', this.eventHandler.onPlay.bind(this.eventHandler));\n video.addEventListener('playing', this.eventHandler.onPlaying.bind(this.eventHandler));\n video.addEventListener('pause', this.eventHandler.onPause.bind(this.eventHandler));\n video.addEventListener('seeking', this.eventHandler.onSeek.bind(this.eventHandler));\n video.addEventListener('seeked', this.eventHandler.onSeeked.bind(this.eventHandler));\n }\n\n //https://aws.github.io/amazon-ivs-player-docs/1.18.0/web/interfaces/playereventtypemap.html\n private startMonitoringIVSPlayer(player: MediaPlayer) {\n player.addEventListener(IVS_PLAYER_EVENT.REBUFFERING, this.eventHandler.onRebuffering.bind(this.eventHandler));\n player.addEventListener(\n IVS_PLAYER_EVENT.DURATION_CHANGED,\n this.eventHandler.onDurationChanged.bind(this.eventHandler),\n );\n player.addEventListener(IVS_PLAYER_EVENT.ERROR, this.eventHandler.onError.bind(this.eventHandler));\n player.addEventListener(IVS_PLAYER_EVENT.INITIALIZED, this.eventHandler.onInitialized.bind(this.eventHandler));\n player.addEventListener(\n IVS_PLAYER_EVENT.QUALITY_CHANGED,\n this.eventHandler.onQualityChanged.bind(this.eventHandler),\n );\n player.addEventListener(IVS_PLAYER_EVENT.TIME_UPDATE, this.eventHandler.onTimeUpdate.bind(this.eventHandler));\n\n // unused events for reference\n // player.addEventListener(PlayerEventType.AUDIO_BLOCKED, this.onAudioBlocked);\n // player.addEventListener(PlayerEventType.BUFFER_UPDATE, this.onBufferUpdate);\n // player.addEventListener(PlayerEventType.MUTED_CHANGED, this.onMutedChanged);\n // player.addEventListener(PlayerEventType.NETWORK_UNAVAILABLE, this.onNetworkUnavailable);\n // player.addEventListener(PlayerEventType.PLAYBACK_BLOCKED, this.onPlaybackBlocked);\n // player.addEventListener(PlayerEventType.PLAYBACK_RATE_CHANGED, this.onPlaybackRateChanged);\n // player.addEventListener(PlayerEventType.TEXT_CUE, this.onTextCue);\n // player.addEventListener(PlayerEventType.TEXT_METADATA_CUE, this.onTextMetadataCue);\n // player.addEventListener(PlayerEventType.VOLUME_CHANGED, this.onVolumeChanged);\n }\n\n static create(\n dispatcher: EventCallbackDispatcher,\n playerContext: AmazonIVSPlayerContext,\n qualityChangeService: QualityChangeService,\n ): AmazonIVSPlayerEventListener {\n const handler = AmazonIVSPlayerEventHandler.create(dispatcher, playerContext, qualityChangeService);\n return new AmazonIVSPlayerEventListener(handler);\n }\n}\n","export class SourceUrlProvider {\n m3u8Url?: string;\n}\n","const COLLECTOR_EVENTS = {\n RELEASE: 'RELEASE',\n} as const;\n\nconst _ALL_COLLECTOR_EVENTS = [COLLECTOR_EVENTS.RELEASE] as const;\n\ntype CollectorEvent = (typeof _ALL_COLLECTOR_EVENTS)[number];\n\ntype Listener = () => void;\n\nclass CollectorEventBus {\n private observer: Record<CollectorEvent, Listener[]> = {\n [COLLECTOR_EVENTS.RELEASE]: [],\n };\n subscribe(event: CollectorEvent, func: Listener) {\n this.observer[event].push(func);\n }\n\n trigger(event: CollectorEvent) {\n this.observer[event].forEach((handler) => {\n handler();\n });\n }\n}\nconst eventBus = new CollectorEventBus();\n\ninterface EventHandler {\n subscribe(func: Listener);\n trigger();\n}\n\nconst buildEventHandler = (event: CollectorEvent): EventHandler => {\n return {\n subscribe(func) {\n eventBus.subscribe(event, func);\n },\n trigger() {\n eventBus.trigger(event);\n },\n };\n};\n\nconst CollectorEvents: Record<CollectorEvent, EventHandler> = {\n RELEASE: buildEventHandler(COLLECTOR_EVENTS.RELEASE),\n};\n\nexport default CollectorEvents;\n","import {Event} from '../../../enums/Event';\nimport {WindowEventTracker} from '../../../utils/WindowEventTracker';\nimport {EventCallbackDispatcher} from '../../internal/EventCallbackDispatcher';\nimport {PlayerContext} from '../player/AmazonIVSPlayerContext';\nimport CollectorEvents from '../utils/CollectorEventBus';\n\nenum State {\n IDLE,\n UNLOADED,\n}\n\nexport class WindowEventListener {\n private state = State.IDLE;\n constructor(\n private windowEventTracker: WindowEventTracker,\n private dispatcher: EventCallbackDispatcher,\n private playerContext: PlayerContext,\n ) {}\n\n startMonitoring() {\n this.windowEventTracker.addEventListener('beforeunload', this.onPageUnload);\n this.windowEventTracker.addEventListener('unload', this.onPageUnload);\n }\n\n private onPageUnload = () => {\n if (this.state != State.IDLE) {\n return;\n }\n\n this.dispatcher.eventCallback(Event.UNLOAD, {\n currentTime: this.playerContext.position,\n });\n this.state = State.UNLOADED;\n CollectorEvents.RELEASE.trigger();\n };\n}\n","import type {AdTagConfig, PlayerAPI, PlayerEventBase, UserInteractionEvent} from 'bitmovin-player';\n\nimport {isNotNullish} from '../../utils/Utils';\nimport {WindowEventTracker} from '../../utils/WindowEventTracker';\nimport {AdCallbacks, AdModuleAPI} from '../internal/ads/AdModuleAPI';\n\nimport {mapBitmovinAd, mapBitmovinAdBreak, mapBitmovinAdError} from './ads/AdUtils';\nimport {getAutoPlay} from './playerUtils';\n\nexport class Bitmovin8AdModule implements AdModuleAPI {\n adCallbacks = new AdCallbacks();\n\n constructor(\n private player: PlayerAPI,\n private windowEventTracker: WindowEventTracker,\n ) {\n this.register();\n }\n\n isLinearAdActive = () => {\n if (this.player.ads) {\n return (this.player.ads as any).isLinearAdActive() || false;\n }\n return false;\n };\n getContainer = () => this.player.getContainer();\n getAdModuleInfo = () => {\n if (this.player.ads) {\n return (this.player.ads as any).getModuleInfo();\n }\n return {name: undefined, version: undefined};\n };\n currentTime = () => this.player.getCurrentTime();\n getAutoPlay(): boolean {\n return getAutoPlay(this.player);\n }\n\n private register() {\n this.player.on(this.player.exports.PlayerEvent.Play, (e: UserInteractionEvent) => {\n if (e.issuer === 'advertising-api') {\n this.adCallbacks.onPlay();\n }\n });\n this.player.on(this.player.exports.PlayerEvent.Paused, (e: UserInteractionEvent) => {\n if (e.issuer === 'advertising-api') {\n this.adCallbacks.onPause();\n }\n });\n this.player.on(this.player.exports.PlayerEvent.AdStarted, (event: any) => {\n this.adCallbacks.onAdStarted(mapBitmovinAd(event.ad));\n });\n this.player.on(this.player.exports.PlayerEvent.AdFinished, (event: any) => {\n this.adCallbacks.onAdFinished(mapBitmovinAd(event.ad));\n });\n this.player.on(this.player.exports.PlayerEvent.AdBreakStarted, (event: any) => {\n this.adCallbacks.onAdBreakStarted(mapBitmovinAdBreak(event.adBreak));\n });\n this.player.on(this.player.exports.PlayerEvent.AdBreakFinished, (event: any) => {\n this.adCallbacks.onAdBreakFinished(mapBitmovinAdBreak(event.adBreak));\n });\n this.player.on(this.player.exports.PlayerEvent.AdClicked, (event: any) => {\n this.adCallbacks.onAdClicked({clickThroughUrl: event.clickThroughUrl});\n });\n this.player.on(this.player.exports.PlayerEvent.AdQuartile, (event: any) => {\n this.adCallbacks.onAdQuartile({quartile: event.quartile});\n });\n this.player.on(this.player.exports.PlayerEvent.AdSkipped, (event: any) => {\n this.adCallbacks.onAdSkipped(mapBitmovinAd(event.ad));\n });\n this.player.on(this.player.exports.PlayerEvent.AdError, (event: PlayerEventBase) => {\n this.adCallbacks.onAdError(mapBitmovinAdError(event, this.player.ads.getActiveAd()?.id));\n });\n this.player.on(this.player.exports.PlayerEvent.AdManifestLoaded, (event: any) => {\n const adTagConfig = event.adConfig as AdTagConfig;\n const isVmap = adTagConfig?.tag?.type === 'vmap';\n const adBreakInfo = isNotNullish(event.adConfig) ? mapBitmovinAdBreak(event.adConfig) : undefined;\n const manifestDownloadTime = event.downloadTiming?.downloadTime;\n this.adCallbacks.onAdManifestLoaded({\n adBreakInfo,\n manifestDownloadTime,\n isVmap,\n });\n });\n const handlePageClose = () => {\n this.adCallbacks.onBeforeUnload();\n };\n this.windowEventTracker.addEventListener('beforeunload', handlePageClose);\n this.windowEventTracker.addEventListener('unload', handlePageClose);\n }\n}\n","import type {PlayerAPI, PlayerConfig} from 'bitmovin-player';\n\nimport type {\n AdapterAPI,\n SsaiAdBreakMetadata,\n SsaiAdMetadata,\n SsaiAdQuartile,\n SsaiAdQuartileMetadata,\n SsaiApi,\n} from '../../api/AdapterAPI';\nimport {Analytics} from '../../core/Analytics';\nimport {\n hasValidSsaiAdBreakMetadataStructure,\n hasValidSsaiAdMetadataStructure,\n hasValidSsaiAdQuartileStructure,\n sanitizeSsaiAdQuartileMetadata,\n simplySanitizeSsaiAdBreakMetadata,\n simplySanitizeSsaiAdMetadata,\n} from '../../core/ssai/ssaiApiUtils';\nimport type {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {logger} from '../../utils/Logger';\nimport {\n hasPlayerAlreadyBeenAugmented,\n isDefined,\n markPlayerInstanceAsAugmented,\n} from '../../utils/playerAugmentationUtils';\nimport {VERSION} from '../../utils/Version';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {sanitizeBitmovin8AdapterSsaiAdBreakMetadataAdPosition} from './bitmovin8AdapterSsaiApiSanitizeUtils';\nimport {Bitmovin8InternalAdapter} from './Bitmovin8InternalAdapter';\n\nexport class Bitmovin8Adapter implements AdapterAPI {\n private readonly internalAdapter: InternalAdapterAPI | undefined;\n private readonly analytics: Analytics | undefined;\n\n constructor(player: any, opts?: AnalyticsStateMachineOptions) {\n if (hasPlayerAlreadyBeenAugmented(player)) {\n logger.errorMessageToUser('Bitmovin Analytics is already hooked up to this player instance');\n return;\n }\n markPlayerInstanceAsAugmented(player);\n\n const playerConfig: PlayerConfig = (player as PlayerAPI).getConfig();\n const sanitizedConfig = sanitizeAnalyticsConfig(playerConfig.analytics as AnalyticsConfig);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n return;\n }\n\n guardAgainstDuplicatedUserId(sanitizedConfig);\n // if the player key is not set in analytics config, use the one from player config\n sanitizedConfig.playerKey = sanitizedConfig.playerKey ?? playerConfig.key;\n\n const internalAdapter = Bitmovin8InternalAdapter.create(player, opts);\n this.internalAdapter = internalAdapter;\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n\n // We do this here in order to put the reference of the adapter onto the player\n // customer using the bitmovin adapter standalone might not know that they need to\n // hold a reference\n player.analytics = this;\n\n this.wrapPlayerLoad(player, this.analytics, internalAdapter);\n }\n\n readonly ssai: SsaiApi = {\n adBreakStart: (adBreakMetadata?: SsaiAdBreakMetadata) => {\n if (!isDefined(this.internalAdapter)) return;\n\n // Bitmovin8Adapter v2.39.0 quick fix: Missing validation for adPosition values\n //\n // We need to apply this quick fix only here, because at the time when the SSAI feature was introduced:\n // - the customers started to use it right away with adPosition values that were not valid, and we did not want\n // to break their implementation.\n // - this feature was implemented only in the Bitmovin8 adapter, so other adapters are not affected by this issue,\n // once they will implement SSAI, they should implement proper validation from the beginning.\n const adBreakMetadataWithValidAdPosition = sanitizeBitmovin8AdapterSsaiAdBreakMetadataAdPosition(adBreakMetadata);\n\n if (!hasValidSsaiAdBreakMetadataStructure(adBreakMetadataWithValidAdPosition)) {\n // if we don't have valid ad break metadata, we don't want to proceed and use SSAI API\n return;\n }\n\n const sanitizedAdBreakMetadata = simplySanitizeSsaiAdBreakMetadata(adBreakMetadataWithValidAdPosition);\n\n this.internalAdapter.ssaiService.adBreakStart(sanitizedAdBreakMetadata);\n },\n\n adStart: (adMetadata?: SsaiAdMetadata) => {\n if (!isDefined(this.analytics)) return;\n if (!isDefined(this.internalAdapter)) return;\n\n if (!hasValidSsaiAdMetadataStructure(adMetadata)) {\n // if we don't have valid ad metadata, we don't want to proceed and use SSAI API\n return;\n }\n\n const sanitizedAdMetadata = simplySanitizeSsaiAdMetadata(adMetadata);\n\n this.internalAdapter.ssaiService.adStart(sanitizedAdMetadata);\n // we need to call this here to revert the customData values to the values before the adBreak\n // this is mainly needed to have clear transitions between ads, and we don't\n // copy over customData values from the first ad into the second ad\n // the adMetadata is applied after this call in the manipulate method when a sample is sent\n // it is a bit of a hack, but it is necessary right now due to the way how samples are created\n this.analytics.setConfigParameters();\n this.analytics.setAutoDetectedDeviceInformation();\n },\n\n adQuartileFinished: (adQuartile: SsaiAdQuartile, adQuartileMetadata?: SsaiAdQuartileMetadata) => {\n if (!isDefined(this.analytics)) return;\n if (!isDefined(this.internalAdapter)) return;\n\n if (!hasValidSsaiAdQuartileStructure(adQuartile)) {\n // if we don't have valid ad quartile, we don't want to proceed and use SSAI API\n return;\n }\n\n const sanitizedSsaiAdQuartileMetadata = sanitizeSsaiAdQuartileMetadata(adQuartileMetadata);\n\n this.internalAdapter.ssaiService.adQuartileFinished(adQuartile, sanitizedSsaiAdQuartileMetadata);\n },\n\n adBreakEnd: () => {\n if (!isDefined(this.analytics)) return;\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.ssaiService.adBreakEnd();\n // we need to call this here to revert the customData values to the values we had before the ad\n this.analytics.setConfigParameters();\n this.analytics.setAutoDetectedDeviceInformation();\n },\n };\n\n /*\n * intercept `player.load` with automated sourceChange handling and correct autoplay video startup time detection\n */\n private wrapPlayerLoad(player: PlayerAPI, analytics: Analytics, internalAdapter: Bitmovin8InternalAdapter) {\n const originalLoad = player.load;\n player.load = (...args: Parameters<typeof player.load>): Promise<void> => {\n if (args.length > 0) {\n const analyticsConfig = (args[0] as any).analytics;\n // we reset the analytics and reload with a new config\n analytics.sourceChange(analyticsConfig);\n }\n internalAdapter.trackLoadstartWithAutoplay();\n\n return originalLoad.apply(player, args);\n };\n }\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getCurrentImpressionId();\n }\n\n getUserId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getUserId();\n }\n\n setCustomData(values: CustomDataValues) {\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.setCustomData(values);\n }\n\n setCustomDataOnce(values: CustomDataValues) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.setCustomDataOnce(values);\n }\n\n sourceChange(config: AnalyticsConfig) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.sourceChange(config);\n }\n}\n","import type {\n AudioPlaybackQualityChangedEvent,\n PlayerAPI,\n PlayerEventBase,\n SeekEvent,\n UserInteractionEvent,\n VideoPlaybackQualityChangedEvent,\n} from 'bitmovin-player';\n\nimport {Bitmovin8AnalyticsStateMachine} from '../../analyticsStateMachines/bitmovin8/Bitmovin8AnalyticsStateMachine';\nimport {Analytics} from '../../core/Analytics';\nimport {DownloadSpeedMeter} from '../../core/DownloadSpeedMeter';\nimport {HeartbeatService} from '../../core/HeartbeatService';\nimport {SegmentTracker} from '../../core/SegmentTracker';\nimport {SourceInfoFallbackService} from '../../core/SourceInfoFallbackService';\nimport VideoCompletionTracker from '../../core/VideoCompletionTracker';\nimport {CastTech} from '../../enums/CastTech';\nimport {ErrorCode} from '../../enums/ErrorCode';\nimport {Event} from '../../enums/Event';\nimport {Player} from '../../enums/Player';\nimport {PlayerSize} from '../../enums/PlayerSize';\nimport {ErrorDetailBackend} from '../../features/errordetails/ErrorDetailBackend';\nimport {ErrorDetailTracking} from '../../features/errordetails/ErrorDetailTracking';\nimport {Feature} from '../../features/Feature';\nimport {FeatureConfig} from '../../features/FeatureConfig';\nimport {HttpRequestTracking} from '../../features/httprequesttracking/HttpRequestTracking';\nimport {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport {DownloadSpeedInfo} from '../../types/DownloadSpeedInfo';\nimport {DrmPerformanceInfo} from '../../types/DrmPerformanceInfo';\nimport type {QualityChangeEvent} from '../../types/EventData';\nimport {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport {normalizeVideoDuration, PlaybackInfo} from '../../types/PlaybackInfo';\nimport {SegmentInfo} from '../../types/SegmentInfo';\nimport {getSourceInfoFromBitmovinSourceConfig} from '../../utils/BitmovinProgressiveSourceHelper';\nimport {logger} from '../../utils/Logger';\nimport * as AnalyticsSettings from '../../utils/Settings';\nimport {isNotNullish, isNullish, tryJSONStringify} from '../../utils/Utils';\nimport {AdModuleAPI} from '../internal/ads/AdModuleAPI';\nimport {InternalAdapter} from '../internal/InternalAdapter';\nimport {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {Bitmovin8AdModule} from './Bitmovin8AdModule';\nimport {HttpRequestTrackingAdapter} from './player/HttpRequestTrackingAdapter';\nimport {SegmentTrackerAdapter} from './player/SegmentTrackerAdapter';\nimport {SpeedMeterAdapter} from './player/SpeedMeterAdapter';\nimport {getAutoPlay, getPlayerConfig} from './playerUtils';\n\nenum ViewMode {\n Fullscreen = 'fullscreen',\n Inline = 'inline',\n PictureInPicture = 'pictureinpicture',\n}\n\nexport class Bitmovin8InternalAdapter extends InternalAdapter implements InternalAdapterAPI {\n /** Boolean flag to prevent multiple calls of the {@link Event.UNLOAD} event */\n private onBeforeUnLoadEvent = false;\n private _adModule?: AdModuleAPI;\n private readonly _videoCompletionTracker: VideoCompletionTracker;\n private lastTrackedCurrentTime: number | undefined;\n private videoDuration: number | undefined;\n\n private readonly player: PlayerAPI;\n private readonly speedMeter: DownloadSpeedMeter;\n private readonly segmentTracker: SegmentTracker;\n private readonly httpRequestTrackingAdapter: HttpRequestTrackingAdapter;\n\n constructor(\n player: PlayerAPI,\n speedMeter: DownloadSpeedMeter,\n segmentTracker: SegmentTracker,\n videoCompletionTracker: VideoCompletionTracker,\n httpRequestTrackingAdapter: HttpRequestTrackingAdapter,\n sourceInfoFallbackService: SourceInfoFallbackService,\n opts?: AnalyticsStateMachineOptions,\n ) {\n super(opts);\n this.httpRequestTrackingAdapter = httpRequestTrackingAdapter;\n this._videoCompletionTracker = videoCompletionTracker;\n this.segmentTracker = segmentTracker;\n this.speedMeter = speedMeter;\n this.player = player;\n const playingHeartbeatService = new HeartbeatService(() => player.getCurrentTime());\n const stateMachine = new Bitmovin8AnalyticsStateMachine(\n this.stateMachineCallbacks,\n playingHeartbeatService,\n this.opts,\n );\n playingHeartbeatService.setListener(stateMachine);\n this.sourceInfoFallbackService = sourceInfoFallbackService;\n\n this.stateMachine = stateMachine;\n }\n\n protected get currentTime(): number {\n try {\n // during ad this.player.getCurrentTime() returns time of ad and not video\n // this then messes with videotime_start and videotime_end measurements of video\n // we don't track videotimes for ads\n if (isNotNullish(this.player?.getCurrentTime) && !this.isAdPlaying) {\n return this.player.getCurrentTime();\n }\n } catch {\n logger.warn('Analytics Collector attempted to access player, but player is not available anymore');\n }\n return this.lastTrackedCurrentTime ? this.lastTrackedCurrentTime : 0;\n }\n\n private get isAdPlaying(): boolean {\n const currentAd = this.player.ads && this.player.ads.getActiveAd();\n return isNotNullish(currentAd);\n }\n\n get supportsDeferredLicenseLoading(): boolean {\n return true;\n }\n\n get adModule(): AdModuleAPI | undefined {\n return this._adModule;\n }\n\n get videoCompletionTracker(): VideoCompletionTracker | undefined {\n return this._videoCompletionTracker;\n }\n\n initialize(analytics: Analytics): Array<Feature<FeatureConfigContainer, FeatureConfig>> {\n this.registerPlayerEventListeners();\n this.registerUnloadEventListeners();\n\n this._adModule = new Bitmovin8AdModule(this.player, this.windowEventTracker);\n\n this.ssaiService.activate({\n getPlayerCurrentTime: () => this.currentTime,\n reportEngagementInteraction: (ssaiEngagementInteractionData) => {\n analytics.sendSsaiEngagementAdSample(ssaiEngagementInteractionData);\n },\n reportPlaybackInteraction: (timestamp: number, playerCurrentTime: number) => {\n // Because ssai playback interaction can happen before Ssai Service is active (e.g. first ssai startAd call),\n // we need to manually mark sample as triggered by ssai\n //\n // This is also including the last sample marking, before a ssai ad block (due to ssai being spiky by design)\n this.stateMachine.sendPlayingSample(timestamp, playerCurrentTime, true);\n },\n });\n\n const requestTracking = new HttpRequestTracking([this.httpRequestTrackingAdapter]);\n const errorDetailTracking = new ErrorDetailTracking(\n analytics.errorDetailTrackingSettingsProvider,\n new ErrorDetailBackend(analytics.errorDetailTrackingSettingsProvider.collectorConfig),\n [analytics.errorDetailSubscribable],\n requestTracking,\n );\n return [errorDetailTracking];\n }\n\n override resetSourceRelatedState(): void {\n this.ssaiService.resetSourceRelatedState();\n super.resetSourceRelatedState();\n }\n\n getPlayerVersion = () => this.player.version;\n getPlayerName = () => Player.BITMOVIN;\n getPlayerTech = () => this.player.getPlayerType();\n getAutoPlay(): boolean {\n return getAutoPlay(this.player);\n }\n override getDrmPerformanceInfo = (): DrmPerformanceInfo | undefined => this.drmPerformanceInfo;\n getCurrentPlaybackInfo(): PlaybackInfo {\n const container = this.player.getContainer();\n const info: PlaybackInfo = {\n ...super.getCommonPlaybackInfo(),\n size: this.player.getViewMode() === ViewMode.Fullscreen ? PlayerSize.Fullscreen : PlayerSize.Window,\n playerTech: this.getPlayerTech(),\n isLive: this.player.isLive(),\n videoDuration: normalizeVideoDuration(this.videoDuration),\n streamFormat: this.player.getStreamType(),\n videoWindowWidth: container?.offsetWidth,\n videoWindowHeight: container?.offsetHeight,\n isMuted: this.player.isMuted(),\n isCasting: this.player.isCasting(),\n audioLanguage: isNotNullish(this.player.getAudio()) ? this.player.getAudio()?.lang : undefined,\n subtitleEnabled: false,\n droppedFrames: isNotNullish(this.player.getSource()) ? this.player.getDroppedVideoFrames() : 0,\n };\n\n this.applySubtitleProperties(info);\n this.applyPlaybackQualityProperties(info);\n this.applyCastingProperties(info);\n this.applySourceProperties(info);\n\n if (isNullish(info.streamFormat) || info.streamFormat === 'unknown') {\n // in case we cannot detect the streamFormat directly from\n // the player, we use the stored streamFormat as a fallback\n this.sourceInfoFallbackService.applyStreamFormat(info);\n }\n\n return info;\n }\n override getSegmentInfo(): SegmentInfo[] {\n return this.segmentTracker.getSegments();\n }\n override getDownloadSpeedInfo(): DownloadSpeedInfo {\n return this.speedMeter.getInfo();\n }\n override resetDownloadSpeedInfoMeasures(): void {\n this.speedMeter.reset();\n }\n\n onError(): void {\n this.segmentTracker.reset();\n }\n\n trackLoadstartWithAutoplay(): void {\n if (this.getAutoPlay()) {\n this.eventCallback(Event.LOADSTART_AUTOPLAY, {currentTime: this.currentTime});\n }\n }\n\n private registerPlayerEventListeners() {\n this.player.on(this.player.exports.PlayerEvent.SourceUnloaded, (_event: any) => {\n this.segmentTracker.reset();\n this.eventCallback(Event.SOURCE_UNLOADED, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(this.player.exports.PlayerEvent.SourceLoaded, (_event: any) => {\n this._videoCompletionTracker.reset();\n this.videoDuration = this.player.getDuration();\n this._videoCompletionTracker.setVideoDuration(this.player.getDuration());\n this.sourceInfoFallbackService.setStreamFormat(this.player.getStreamType());\n this.eventCallback(Event.SOURCE_LOADED, {});\n });\n\n this.player.on(this.player.exports.PlayerEvent.CastStarted, (event: any) => {\n this.eventCallback(Event.START_CAST, event);\n });\n\n this.player.on(this.player.exports.PlayerEvent.CastStopped, () => {\n this.eventCallback(Event.END_CAST, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(this.player.exports.PlayerEvent.Play, (e: UserInteractionEvent) => {\n if (e.issuer !== 'ui-seek') {\n this.eventCallback(Event.PLAY, {\n currentTime: this.currentTime,\n });\n }\n });\n\n this.player.on(this.player.exports.PlayerEvent.Playing, (e: UserInteractionEvent) => {\n if (e.issuer !== 'advertising-api') {\n this.eventCallback(Event.PLAYING, {\n currentTime: this.currentTime,\n });\n }\n });\n\n this.player.on(this.player.exports.PlayerEvent.Paused, (e: UserInteractionEvent) => {\n if (e.issuer !== 'ui-seek') {\n this.eventCallback(Event.PAUSE, {\n currentTime: this.currentTime,\n });\n }\n });\n\n this.player.on(this.player.exports.PlayerEvent.TimeChanged, (_event: PlayerEventBase) => {\n if (!this.isAdPlaying) {\n this.lastTrackedCurrentTime = this.player.getCurrentTime();\n }\n this.eventCallback(Event.TIMECHANGED, {\n currentTime: this.lastTrackedCurrentTime,\n });\n });\n\n this.player.on(this.player.exports.PlayerEvent.Seek, (e: UserInteractionEvent) => {\n if (this.allowSeeking(e)) {\n this.eventCallback(Event.SEEK, {\n currentTime: this.currentTime,\n });\n }\n });\n\n this.player.on(this.player.exports.PlayerEvent.Seeked, () => {\n this.eventCallback(Event.SEEKED, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(this.player.exports.PlayerEvent.StallStarted, () => {\n this.eventCallback(Event.START_BUFFERING, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(this.player.exports.PlayerEvent.StallEnded, () => {\n this.eventCallback(Event.END_BUFFERING, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(this.player.exports.PlayerEvent.AudioPlaybackQualityChanged, (eventData) => {\n const audioQualityChangedData = eventData as AudioPlaybackQualityChangedEvent;\n const sourceQuality = audioQualityChangedData.sourceQuality;\n const targetQuality = audioQualityChangedData.targetQuality;\n\n if (isNullish(targetQuality)) {\n return;\n }\n\n const qualityEventInfo: QualityChangeEvent = {\n type: 'audio',\n bitrate: targetQuality.bitrate,\n currentTime: this.currentTime,\n codec: (targetQuality as any).codec,\n };\n\n // for initial quality changes (no target quality set) we do not want to send a qualitychange sample\n if (\n isNotNullish(sourceQuality) &&\n this.qualityChangeService.shouldAllowAudioQualityChange(targetQuality.bitrate)\n ) {\n this.eventCallback(Event.AUDIO_CHANGE, qualityEventInfo);\n }\n\n this.qualityChangeService.setAudioBitrate(targetQuality.bitrate);\n this.stateMachineCallbacks.updateSampleQualityInfo(qualityEventInfo);\n });\n\n this.player.on(this.player.exports.PlayerEvent.VideoPlaybackQualityChanged, (eventData) => {\n const videoQualityChangedData = eventData as VideoPlaybackQualityChangedEvent;\n const sourceQuality = videoQualityChangedData.sourceQuality;\n const targetQuality = videoQualityChangedData.targetQuality;\n\n // if targetQuality is null we just ignore the event\n // this is probably and outlier or the end of a session\n // where we don't want to track quality changes\n if (isNullish(targetQuality)) {\n return;\n }\n\n const qualityEventInfo: QualityChangeEvent = {\n type: 'video',\n width: targetQuality.width,\n height: targetQuality.height,\n bitrate: targetQuality.bitrate,\n currentTime: this.currentTime,\n codec: (targetQuality as any).codec,\n };\n\n // for initial quality changes (no target quality set) we do not want to send a qualitychange sample\n if (\n isNotNullish(sourceQuality) &&\n this.qualityChangeService.shouldAllowVideoQualityChange(targetQuality.bitrate)\n ) {\n this.eventCallback(Event.VIDEO_CHANGE, qualityEventInfo);\n }\n\n this.qualityChangeService.setVideoBitrate(targetQuality.bitrate);\n this.stateMachineCallbacks.updateSampleQualityInfo(qualityEventInfo);\n });\n\n this.player.on(this.player.exports.PlayerEvent.ViewModeChanged, (e: any) => {\n if (e.to === 'fullscreen') {\n this.eventCallback(Event.START_FULLSCREEN, {\n currentTime: this.currentTime,\n });\n } else if (e.from === 'fullscreen') {\n this.eventCallback(Event.END_FULLSCREEN, {\n currentTime: this.currentTime,\n });\n }\n });\n\n this.player.on(this.player.exports.PlayerEvent.AdStarted, (_event: any) => {\n this.eventCallback(Event.START_AD, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(this.player.exports.PlayerEvent.AdFinished, (_event: any) => {\n this.eventCallback(Event.END_AD, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(this.player.exports.PlayerEvent.AdSkipped, (_event: any) => {\n this.eventCallback(Event.END_AD, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(this.player.exports.PlayerEvent.AdError, (_event: any) => {\n this.eventCallback(Event.END_AD, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(this.player.exports.PlayerEvent.Muted, () => {\n this.eventCallback(Event.MUTE, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(this.player.exports.PlayerEvent.Unmuted, () => {\n this.eventCallback(Event.UN_MUTE, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(this.player.exports.PlayerEvent.Error, (event: any) => {\n this.eventCallback(Event.ERROR, {\n code: event.code,\n message: event.name,\n legacyData: event.data,\n currentTime: this.currentTime,\n originalError: event,\n data: {\n additionalData: tryJSONStringify(event.data),\n },\n });\n if (\n event.code === ErrorCode.BITMOVIN_PLAYER_LICENSING_ERROR.code ||\n event.code === ErrorCode.SETUP_MISSING_LICENSE_WHITELIST.code\n ) {\n this.onLicenseCallFailed.dispatch({});\n }\n this.ssaiService.sendAdEngagementErrorSample(\n {code: event.code, message: event.name, severity: 'CRITICAL'},\n event,\n );\n });\n\n this.player.on(this.player.exports.PlayerEvent.PlaybackFinished, () => {\n this.eventCallback(Event.END, {currentTime: this.currentTime});\n });\n\n this.player.on(this.player.exports.PlayerEvent.DownloadFinished, (event: any) => {\n if (event.downloadType.indexOf('drm/license/') === 0) {\n this.drmPerformanceInfo = {\n drmType: event.downloadType.replace('drm/license/', ''),\n drmLoadTime: event.downloadTime * 1000,\n };\n }\n });\n\n this.player.on(this.player.exports.PlayerEvent.AudioChanged, (_event: any) => {\n this.eventCallback(Event.AUDIOTRACK_CHANGED, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(this.player.exports.PlayerEvent.SubtitleEnabled, (_event: any) => {\n this.eventCallback(Event.SUBTITLE_CHANGE, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(this.player.exports.PlayerEvent.SubtitleDisabled, (_event: any) => {\n this.eventCallback(Event.SUBTITLE_CHANGE, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(this.player.exports.PlayerEvent.LicenseValidated, (event: any) => {\n if (event.data.analytics && event.data.analytics.key !== undefined) {\n this.onLicenseKeyReceived.dispatch({licenseKey: event.data.analytics.key});\n } else {\n this.onLicenseCallFailed.dispatch({});\n }\n });\n }\n\n private registerUnloadEventListeners() {\n let handleCollectorUnload = () => {\n if (!this.onBeforeUnLoadEvent) {\n this.onBeforeUnLoadEvent = true;\n // we use here the last tracked video time as we cannot be sure if the player is still working at this place\n const currentTime = this.lastTrackedCurrentTime;\n this.eventCallback(Event.UNLOAD, {currentTime});\n }\n this.release();\n };\n handleCollectorUnload = handleCollectorUnload.bind(true);\n\n this.player.on(this.player.exports.PlayerEvent.Destroy, handleCollectorUnload);\n this.windowEventTracker.addEventListener('beforeunload', handleCollectorUnload);\n this.windowEventTracker.addEventListener('unload', handleCollectorUnload);\n }\n\n private applySourceProperties(info: PlaybackInfo) {\n const source = this.player.getSource();\n if (isNullish(source)) {\n return;\n }\n\n info.videoTitle = source.title;\n info.mpdUrl = source.dash;\n info.m3u8Url = source.hls;\n\n const progSourceInfo = getSourceInfoFromBitmovinSourceConfig(source.progressive, this.player);\n info.progUrl = progSourceInfo.progUrl;\n if (this.player.getStreamType() === 'progressive') {\n info.videoBitrate = progSourceInfo.progBitrate;\n }\n }\n\n private applySubtitleProperties(info: PlaybackInfo) {\n let enabledSubtitle;\n if (this.player.subtitles) {\n enabledSubtitle = this.player.subtitles.list().find((s) => s.enabled === true);\n }\n\n info.subtitleEnabled = isNotNullish(enabledSubtitle);\n info.subtitleLanguage = isNotNullish(enabledSubtitle) ? enabledSubtitle.lang : null;\n }\n\n private applyPlaybackQualityProperties(info: PlaybackInfo) {\n const videoQuality = this.player.getPlaybackVideoData();\n if (isNotNullish(videoQuality)) {\n info.videoBitrate = videoQuality.bitrate;\n info.videoPlaybackHeight = videoQuality.height;\n info.videoPlaybackWidth = videoQuality.width;\n info.videoCodec = (videoQuality as any).codec;\n }\n\n const audioQuality = this.player.getPlaybackAudioData();\n if (isNotNullish(audioQuality)) {\n info.audioBitrate = audioQuality.bitrate;\n info.audioCodec = (audioQuality as any).codec;\n }\n }\n\n private applyCastingProperties(info: PlaybackInfo) {\n const isCasting = this.player.isCasting() || this.player.isAirplayActive() || false;\n info.isCasting = isCasting;\n if (!isCasting) {\n return;\n }\n\n // AirPlay\n if (this.player.isAirplayActive()) {\n info.castTech = CastTech.AirPlay;\n return;\n }\n\n // Casting Tech from RemoteControlConfig\n const remoteControlConfig = getPlayerConfig(this.player)?.remotecontrol;\n if (isNullish(remoteControlConfig)) {\n return;\n }\n\n switch (remoteControlConfig.type) {\n case 'googlecast':\n info.castTech = CastTech.GoogleCast;\n break;\n case 'websocket':\n info.castTech = CastTech.WebSocket;\n break;\n }\n }\n\n // with this check we ignore seek events which are smaller than the Threshold\n // mainly to ignore keyboard triggered seeks\n private allowSeeking(e: UserInteractionEvent): boolean {\n const seekEvent = e as SeekEvent;\n const seekDifference = Math.abs(seekEvent.position - seekEvent.seekTarget);\n return seekDifference > AnalyticsSettings.ANALYTICS_MIN_SEEK_DIFFERENCE_THRESHOLD;\n }\n\n static create(player: PlayerAPI, opts?: AnalyticsStateMachineOptions): Bitmovin8InternalAdapter {\n const speedMeter = new SpeedMeterAdapter(player, new DownloadSpeedMeter()).getDownloadSpeedMeter();\n const segmentTracker = new SegmentTrackerAdapter(player, new SegmentTracker()).getSegmentTracker();\n const httpRequestTrackingAdapter = new HttpRequestTrackingAdapter(player);\n const videoCompletionTracker = new VideoCompletionTracker();\n const sourceInfoFallbackService = new SourceInfoFallbackService();\n return new Bitmovin8InternalAdapter(\n player,\n speedMeter,\n segmentTracker,\n videoCompletionTracker,\n httpRequestTrackingAdapter,\n sourceInfoFallbackService,\n opts,\n );\n }\n}\n","import type {\n Ad as PlayerAd,\n AdBreak as PlayerAdBreak,\n AdBreakConfig as PlayerAdBreakConfig,\n AdTagConfig as PlayerAdTagConfig,\n ErrorEvent as PlayerErrorEvent,\n PlayerEventBase,\n LinearAd as PlayerLinearAd,\n VastAdData as PlayerVastAdData,\n} from 'bitmovin-player';\n\nimport type {AdBreakInfo} from '../../../types/ads/AdBreakInfo';\nimport type {AdInfo} from '../../../types/ads/AdInfo';\nimport {isNotNullish, isNullish} from '../../../utils/Utils';\nimport type {AdErrorPayload} from '../../internal/ads/AdModuleAPI';\n\nexport function mapBitmovinAdError(event: PlayerEventBase, activeAdId?: string): AdErrorPayload {\n const adErrorPayload: AdErrorPayload = {\n activeAdId,\n };\n\n const errorEvent = event as PlayerErrorEvent;\n const errorData = errorEvent.data;\n if (isNotNullish(errorData)) {\n adErrorPayload.code = errorData.code || errorEvent.code;\n adErrorPayload.message = errorData.message || errorEvent.name;\n\n if ('adBreak' in errorData || 'adConfig' in errorData) {\n const adInfo = errorData.adBreak ?? errorData.adConfig;\n adErrorPayload.adBreakInfo = mapBitmovinAdBreak(adInfo);\n }\n }\n\n return adErrorPayload;\n}\n\nexport function mapBitmovinAd(ad: PlayerAd): AdInfo {\n const adInfo: AdInfo = {\n id: ad.id,\n isLinear: ad.isLinear,\n clickThroughUrl: ad.clickThroughUrl,\n width: ad.width,\n height: ad.height,\n };\n\n const linearAd = ad.isLinear ? (ad as PlayerLinearAd) : undefined;\n if (isNotNullish(linearAd)) {\n adInfo.duration = linearAd.duration;\n adInfo.skippable = isNotNullish(linearAd.skippableAfter);\n adInfo.skippableAfter = linearAd.skippableAfter;\n adInfo.mediaUrl = linearAd.mediaFileUrl;\n }\n\n const vastData = ad.data as PlayerVastAdData | undefined;\n if (isNotNullish(vastData)) {\n adInfo.bitrate = vastData.bitrate;\n adInfo.mimeType = vastData.mimeType;\n adInfo.vastData = {\n adSystem: vastData.adSystem?.name,\n advertiserName: vastData.advertiser?.name,\n apiFramework: vastData.apiFramework,\n creativeAdId: vastData.creative?.adId,\n creativeId: vastData.creative?.id,\n universalAdIdRegistry: vastData.creative?.universalAdId?.idRegistry,\n universalAdIdValue: vastData.creative?.universalAdId?.value,\n adDescription: vastData.adDescription,\n adTitle: vastData.adTitle,\n wrapperAdsCount: vastData.wrapperAdIds?.length ?? 0,\n surveyUrl: vastData.survey?.uri,\n minSuggestedDuration: vastData.minSuggestedDuration,\n };\n }\n\n return adInfo;\n}\n\nexport function mapBitmovinAdBreak(adConfig: PlayerAdBreak | PlayerAdTagConfig): AdBreakInfo {\n const adBreakInfo: AdBreakInfo = {\n replaceContentDuration: adConfig.replaceContentDuration,\n fallbackIndex: getFallbackIndex(adConfig),\n };\n\n // AdBreak\n adBreakInfo.id = 'id' in adConfig ? adConfig.id : undefined;\n adBreakInfo.scheduleTime = 'scheduleTime' in adConfig ? adConfig.scheduleTime : undefined;\n\n // AdTagConfig / AdBreakConfig\n const adTagConfig = adConfig as PlayerAdTagConfig;\n const {tagUrl, tagType} = resolveEffectiveAdTag(adTagConfig);\n adBreakInfo.tagUrl = tagUrl;\n adBreakInfo.tagType = tagType;\n adBreakInfo.persistent = 'persistent' in adConfig ? adTagConfig.persistent : undefined;\n adBreakInfo.position = 'position' in adConfig ? (adConfig as PlayerAdBreakConfig).position : undefined;\n adBreakInfo.preloadOffset = 'preloadOffset' in adConfig ? (adConfig as PlayerAdBreakConfig).preloadOffset : undefined;\n\n return adBreakInfo;\n}\n\n/**\n * Resolves the effective ad tag URL and type, applying the fallback tag\n * if `fallbackIndex` indicates a fallback is active.\n */\nexport function resolveEffectiveAdTag(adTagConfig: PlayerAdTagConfig): {tagType?: string; tagUrl?: string} {\n if (isNullish(adTagConfig.tag)) {\n return {};\n }\n\n const fallbackIndex = getFallbackIndex(adTagConfig);\n const directTag = {tagType: adTagConfig.tag.type, tagUrl: adTagConfig.tag.url};\n if (isNullish(adTagConfig.fallbackTags) || fallbackIndex <= 0 || adTagConfig.fallbackTags.length < fallbackIndex) {\n return directTag;\n }\n\n const fallbackTag = adTagConfig.fallbackTags[fallbackIndex - 1];\n return {tagType: fallbackTag.type, tagUrl: fallbackTag.url};\n}\n\n/**\n * Maps the Bitmovin player's internal `currentFallbackIndex` to the analytics `adFallbackIndex`.\n *\n * Player convention (ImaAdBreak.currentFallbackIndex):\n * - absent/null → no fallback tracking (treat as primary ad)\n * - `0` → primary ad is playing\n * - `1` → first fallback tag (`fallbackTags[0]`) is playing\n * - `2` → second fallback tag (`fallbackTags[1]`) is playing\n *\n * Analytics convention matches 1:1, so the mapping is an identity for defined values.\n * Both absent and `0` map to `adFallbackIndex = 0` (primary ad, no fallback used).\n */\nexport function getFallbackIndex(adConfig: PlayerAdBreak | PlayerAdTagConfig): number {\n const rawFallbackIndex = (adConfig as any).currentFallbackIndex;\n\n if (isNullish(rawFallbackIndex)) {\n return 0;\n }\n\n return rawFallbackIndex;\n}\n","import type {SsaiAdBreakMetadata} from '../../api/AdapterAPI';\nimport {isNotNullish} from '../../utils/Utils';\n\n/**\n * Utility function to sanitize the adPosition value in the SsaiAdBreakMetadata object passed to Bitmovin8Adapter.\n *\n * Needed, because we have introduced SSAI API in `Bitmovin8Adapter` in v2.39.0, without doing proper validation of\n * the passed adPosition value and customer started to use us with invalid values (having `-` in string in JavaScript).\n * Because we did not want to break the customer's implementation, we decided to sanitize the value to the correct one.\n *\n * @deprecated This function will be removed in v3\n */\nexport const sanitizeBitmovin8AdapterSsaiAdBreakMetadataAdPosition = <T = unknown>(anything: T): T => {\n const maybeSsaiAdBreakMetadata = anything as SsaiAdBreakMetadata;\n\n if (isNotNullish(maybeSsaiAdBreakMetadata?.adPosition)) {\n if ((maybeSsaiAdBreakMetadata.adPosition as string) === 'pre-roll') {\n maybeSsaiAdBreakMetadata.adPosition = 'preroll';\n } else if ((maybeSsaiAdBreakMetadata.adPosition as string) === 'mid-roll') {\n maybeSsaiAdBreakMetadata.adPosition = 'midroll';\n } else if ((maybeSsaiAdBreakMetadata?.adPosition as string) === 'post-roll') {\n maybeSsaiAdBreakMetadata.adPosition = 'postroll';\n }\n }\n\n return maybeSsaiAdBreakMetadata as T;\n};\n","import type {DownloadFinishedEvent, PlayerAPI, PlayerExports} from 'bitmovin-player';\n\nimport {EventDispatcher, Subscribable} from '../../../core/EventDispatcher';\nimport {HttpRequestType} from '../../../features/httprequesttracking/HttpRequestType';\nimport {OnDownloadFinishedEventObject} from '../../../features/httprequesttracking/OnDownloadFinishedEventObject';\nimport {objectValues} from '../../../utils/objectUtils';\nimport {calculateTimeWithUndefined, getCurrentTimestamp} from '../../../utils/Utils';\n\nexport class HttpRequestTrackingAdapter implements Subscribable<OnDownloadFinishedEventObject> {\n private eventDispatcher = new EventDispatcher<OnDownloadFinishedEventObject>();\n private playerExports: PlayerExports;\n\n constructor(player: PlayerAPI) {\n this.playerExports = player.exports;\n player.on(this.playerExports.PlayerEvent.DownloadFinished, (event) =>\n this.onDownloadFinished(event as DownloadFinishedEvent),\n );\n }\n\n subscribe(callback: (args: OnDownloadFinishedEventObject) => void): () => void {\n return this.eventDispatcher.subscribe(callback);\n }\n\n unsubscribe(callback: (args: OnDownloadFinishedEventObject) => void) {\n this.eventDispatcher.unsubscribe(callback);\n }\n\n private onDownloadFinished(event?: DownloadFinishedEvent) {\n this.eventDispatcher.dispatch({\n httpRequest: {\n downloadTime: calculateTimeWithUndefined(event?.downloadTime) ?? 0,\n httpStatus: event?.httpStatus ?? 0,\n success: event?.success ?? false,\n timestamp: getCurrentTimestamp(),\n url: event?.url,\n size: event?.size,\n timeToFirstByte: calculateTimeWithUndefined(event?.timeToFirstByte),\n type: mapHttpRequestType(event?.downloadType),\n },\n });\n }\n}\n\n/**\n * Map Bitmovin8 player `HttpRequestType` to the analytics {@link HttpRequestType} enum, defaulting to `UNKNOWN` for unmapped values.\n */\nexport function mapHttpRequestType(httpRequestTypeValue: string | undefined): HttpRequestType {\n if (objectValues(HttpRequestType).includes(httpRequestTypeValue)) {\n return httpRequestTypeValue as HttpRequestType;\n }\n // For unmapped values (including undefined), return UNKNOWN. This ensures that the analytics system receives a valid\n // enum value and can handle it appropriately.\n // The unmapped value itself should be detected by unit tests, once the bitmovin player dependency is updated in the project.\n return HttpRequestType.UNKNOWN;\n}\n","import type {PlayerAPI} from 'bitmovin-player';\n\nimport {SegmentTracker} from '../../../core/SegmentTracker';\nimport {SegmentInfo} from '../../../types/SegmentInfo';\nimport * as Utils from '../../../utils/Utils';\n\ninterface DownloadFinishedEvent {\n attempt?: number;\n downloadType?: string;\n httpStatus: number;\n mimeType?: string;\n success: boolean;\n timestamp: number;\n type: string;\n url: string;\n}\n\ninterface SegmentPlaybackEvent {\n duration?: number;\n mediaInfo?: any;\n mimeType?: string;\n playbackTime?: number;\n representationId?: string;\n timestamp?: number;\n type?: string;\n uid?: string;\n url?: string;\n}\n\nexport class SegmentTrackerAdapter {\n private segmentTracker: SegmentTracker;\n\n constructor(player: PlayerAPI, segmentTracker: SegmentTracker) {\n this.segmentTracker = segmentTracker;\n\n player.on(player.exports.PlayerEvent.DownloadFinished, (event) => this.handleOnDownloadFinishEvent(event));\n player.on(player.exports.PlayerEvent.SegmentPlayback, (event) => this.handleSegmentPlaybackEvent(event));\n }\n\n getSegmentTracker(): SegmentTracker {\n return this.segmentTracker;\n }\n\n handleOnDownloadFinishEvent(event: any & DownloadFinishedEvent) {\n if (event.downloadType.indexOf('media/video') === 0) {\n const url = event.url;\n const segment: SegmentInfo = {\n name: Utils.getURLResourceName(url),\n url,\n timestamp: event.timestamp,\n };\n this.segmentTracker.addSegment(segment);\n }\n }\n\n handleSegmentPlaybackEvent = (event: any & SegmentPlaybackEvent) => {\n this.segmentTracker.removeSegment(event.url);\n };\n}\n","import type {PlayerAPI} from 'bitmovin-player';\n\nimport {DownloadSpeedMeter} from '../../../core/DownloadSpeedMeter';\n\nexport class SpeedMeterAdapter {\n private meter: DownloadSpeedMeter;\n\n constructor(player: PlayerAPI, meter: DownloadSpeedMeter) {\n this.meter = meter;\n player.on(player.exports.PlayerEvent.DownloadFinished, (event) => this.handleOnDownloadFinishEvent(event));\n }\n\n getDownloadSpeedMeter(): DownloadSpeedMeter {\n return this.meter;\n }\n\n handleOnDownloadFinishEvent(event: any) {\n if (!event.success) {\n return;\n }\n if (event.downloadType.indexOf('media/video') === 0) {\n this.meter.addMeasurement({\n duration: event.downloadTime,\n size: event.size,\n timeToFirstByte: event.timeToFirstByte,\n timestamp: new Date(),\n httpStatus: event.httpStatus,\n });\n }\n }\n}\n","import {Bitmovin8Adapter} from './Bitmovin8Adapter';\n\n/*\n * @see https://github.com/bitmovin-engineering/bitdash/blob/ccd3227dac82d1416a471711b40ee0f65d7f9ddb/src/ModuleDefinition.ts#L17\n */\nexport const PlayerModule = {\n name: 'analytics',\n module: {\n Analytics: Bitmovin8Adapter,\n },\n hooks: {\n setup: (module: any, player: any) => {\n const config = player.getConfig();\n const isConfigMissing = !config;\n const isAnalyticsDisabled = config?.analytics === false;\n\n if (isConfigMissing || isAnalyticsDisabled) {\n return Promise.resolve();\n }\n\n const analyticsBitmovin8Adapter = module.Analytics;\n const analyticsModuleInstance = new analyticsBitmovin8Adapter(player);\n return Promise.resolve(analyticsModuleInstance);\n },\n },\n} as const;\n","import {PlayerAPI, PlayerConfig} from 'bitmovin-player';\n\nimport {isNullish} from '../../utils/Utils';\n\nexport function getPlayerConfig(player: PlayerAPI | undefined): PlayerConfig | undefined {\n try {\n if (isNullish(player) || isNullish(player.getConfig())) {\n return undefined;\n }\n\n return player.getConfig();\n } catch (_e) {\n // exception might be thrown if player was destroyed - this is expected, so no need to throw or log the exception\n return undefined;\n }\n}\n\nexport function getAutoPlay(player: PlayerAPI | undefined): boolean {\n const playerConfig = getPlayerConfig(player);\n if (isNullish(playerConfig)) {\n return false;\n }\n\n return playerConfig.playback?.autoplay || false;\n}\n","import type {AnalyticsConfig} from 'bitmovin-player';\n\nimport type {AdapterAPI} from '../../api/AdapterAPI';\nimport {Analytics} from '../../core/Analytics';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {VERSION} from '../../utils/Version';\n\nimport {BitmovinPwxInternalAdapter} from './BitmovinPwxInternalAdapter';\nimport type {AnalyticsContext} from './Types';\n\nexport class BitmovinPwxAdapter implements AdapterAPI {\n private readonly internalAdapter: BitmovinPwxInternalAdapter;\n private readonly analytics: Analytics;\n\n constructor(context: AnalyticsContext, config: AnalyticsConfig) {\n // no need to check for player augmentation, if analytics has already been initialized on this player instance,\n // because this adapter is created only once with BitmovinPwxAnalyticsPackage\n\n const sanitizedConfig = sanitizeAnalyticsConfig(config);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n throw new Error('Failed to create BitmovinPwxAdapter: domain is required');\n }\n\n guardAgainstDuplicatedUserId(sanitizedConfig);\n\n this.internalAdapter = new BitmovinPwxInternalAdapter(context);\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n }\n\n dispose() {\n this.internalAdapter.release();\n }\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId = () => this.analytics.getCurrentImpressionId();\n\n getUserId = () => this.analytics.getUserId();\n\n setCustomData = (values: CustomDataValues) => this.internalAdapter.setCustomData(values);\n\n setCustomDataOnce = (values: CustomDataValues) => this.analytics.setCustomDataOnce(values);\n\n sourceChange = (_config: AnalyticsConfig) => {\n // Every time a source is added, a new instance of analytics package is triggered. So technically there are\n // no source changes. Also, a single player instance can handle infinite amount of sources at once.\n //\n // We are aware, at the moment we are handling it as \"every source = one session\". We will need to do\n // some additional work in the future (once we figure out how this part should work) to handle multiple\n // sources in one session (e.g. ads).\n //\n // What we mean by \"no source changes\", is that you do not have API to change \"current playing\" source\n // to something else. You would need to add new source and remove old one (or keep it). One instance can\n // have infinite amount of sources, each source for us is a new analytics session (for now, in certain cases\n // they should be tied together - e.g. ads)\n //\n // @see https://github.com/bitmovin-engineering/bitmovin-analytics-collector/pull/867#discussion_r1660699646\n\n throw new Error('Method not implemented.');\n };\n}\n","import type {EmptyObject} from '@bitmovin/player-web-x/framework-types/BaseTypes';\nimport type {AnyPackage} from '@bitmovin/player-web-x/framework-types/package-api/PackageApi';\n\nimport {tryJSONStringify} from '../../utils/Utils';\n\nimport {BitmovinPwxAdapter} from './BitmovinPwxAdapter';\nimport {\n BundleExportNames,\n CoreExportNames,\n PlaybackApiEventsPackageExportNames,\n SourceExportNames,\n SourcesApiExportNames,\n} from './ExportNames';\nimport type {AnalyticsContext, CreatePackage} from './Types';\n\n/**\n * Copy&pasted from `@bitmovin/player-web-x` !\n *\n * We need `createPackage` function from util file to create a PWX package, but because `@bitmovin/player-web-x` is not\n * ES5 compliant, we had to copy it here.\n *\n * @see https://github.com/bitmovin-engineering/player-web-phoenix-framework/blob/main/src/package-api/PackageApiUtils.ts#L9\n */\nconst createPackageFn: CreatePackage = (name, onAdd, dependencies) => {\n (onAdd as any)._name = name;\n\n return {\n onAdd,\n dependencies,\n } as unknown as AnyPackage<EmptyObject>;\n};\n\nexport const BitmovinPwxAnalyticsPackage = createPackageFn(\n 'analytics-package',\n (_, baseContext) => {\n /*\n Player Web X analytics package.\n It is being run for every source added - so there is no actual source switching per analytics instance.\n Package is instantiating the adapter, and making sure it is disposed once package is aborted.\n */\n\n const {EventListenerEffectFactory, StateEffectFactory} = baseContext.registry.get(CoreExportNames.CoreEffects);\n const context = baseContext.using(EventListenerEffectFactory, StateEffectFactory) as unknown as AnalyticsContext;\n const logger = context.registry.get(BundleExportNames.Logger);\n const source = context.registry.get(SourceExportNames.SourceState);\n const playerConfig = context.registry.get(BundleExportNames.PlayerConfig);\n const analyticsConfig = playerConfig.analytics ?? {};\n // if the player key is not set in analytics config, use the one from player config\n analyticsConfig.playerKey = analyticsConfig.playerKey ?? playerConfig.key;\n\n logger.log(`Applying analytics config ${tryJSONStringify(analyticsConfig)}`);\n const adapter = new BitmovinPwxAdapter(context, analyticsConfig);\n\n logger.log(`Analytics package initializing for \"${source.url}\"...`);\n\n const listener = () => {\n context.abortSignal.removeEventListener('abort', listener);\n logger.log(`Analytics package disposing for \"${source.url}\"`);\n adapter.dispose();\n };\n\n context.abortSignal.addEventListener('abort', listener);\n },\n [\n BundleExportNames.Logger,\n BundleExportNames.PlayerConfig,\n CoreExportNames.Constants,\n CoreExportNames.CoreEffects,\n CoreExportNames.CoreStateAtoms,\n SourceExportNames.SourceState,\n SourcesApiExportNames.SourceEventBus,\n PlaybackApiEventsPackageExportNames.PlaybackEvent,\n ],\n) as any; // we cast package as any to prevent DTS bundle type merging\n","import {StateMachine} from 'javascript-state-machine';\n\nimport {AnalyticsStateMachine} from '../../analyticsStateMachines/AnalyticsStateMachine';\nimport {\n customStateMachineErrorCallback,\n getAllStatesBut,\n logMissingCallbackWarning,\n logStateMachineTransition,\n on,\n} from '../../analyticsStateMachines/stateMachineUtils';\nimport type {HeartbeatService} from '../../core/HeartbeatService';\nimport {Event, JSM_INITIAL_EVENT} from '../../enums/Event';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {StateMachineCallbacks} from '../../types/StateMachineCallbacks';\nimport {EventDebugging} from '../../utils/EventDebugging';\nimport {logger} from '../../utils/Logger';\nimport {isNumber} from '../../utils/numberUtils';\nimport {isFunction} from '../../utils/Utils';\n\nexport enum State {\n END = 'END',\n ERROR = 'ERROR',\n PAUSE = 'PAUSE',\n PLAYING = 'PLAYING',\n READY = 'READY',\n SETUP = 'SETUP',\n SOURCE_LOADED = 'SOURCE_LOADED',\n STARTUP = 'STARTUP',\n VIDEOSTART_FAILED = 'VIDEOSTART_FAILED',\n}\n\nexport class BitmovinPwxAnalyticsStateMachine extends AnalyticsStateMachine {\n private enabledDebugging = false;\n private debuggingStates: EventDebugging[] = [];\n\n constructor(\n stateMachineCallbacks: StateMachineCallbacks,\n playingHeartbeatService: HeartbeatService,\n opts: AnalyticsStateMachineOptions,\n ) {\n super(stateMachineCallbacks, playingHeartbeatService, opts);\n }\n\n override createStateMachine(opts: AnalyticsStateMachineOptions): StateMachine {\n return StateMachine.create({\n // custom initial state and custom JSM initial event name\n // initial event is used by JSM for the initial state transition 'none' -> 'SETUP'\n initial: {state: State.SETUP, event: JSM_INITIAL_EVENT},\n error: customStateMachineErrorCallback,\n events: [\n {\n name: Event.SOURCE_LOADED,\n from: [State.SETUP, State.ERROR],\n to: State.READY,\n },\n on(Event.READY).stayIn(State.READY),\n on(Event.PAUSE).stayIn(State.READY),\n on(Event.TIMECHANGED).stayIn(State.READY),\n {name: Event.PLAY, from: State.READY, to: State.STARTUP},\n {name: Event.PLAYING, from: State.READY, to: State.PLAYING},\n\n on(Event.PLAY).stayIn(State.STARTUP),\n on(Event.PLAYING).stayIn(State.STARTUP),\n {name: Event.TIMECHANGED, from: State.STARTUP, to: State.PLAYING},\n on(Event.READY).stayIn(State.STARTUP),\n {name: Event.PAUSE, from: State.STARTUP, to: State.READY},\n\n on(Event.PLAYING).stayIn(State.PLAYING),\n on(Event.TIMECHANGED).stayIn(State.PLAYING),\n\n {name: Event.PAUSE, from: State.PLAYING, to: State.PAUSE},\n on(Event.TIMECHANGED).stayIn(State.PAUSE),\n on(Event.PAUSE).stayIn(State.PAUSE),\n {name: Event.PLAY, from: State.PAUSE, to: State.PLAYING},\n {name: Event.PLAYING, from: State.PAUSE, to: State.PLAYING},\n\n {name: Event.END, from: State.PLAYING, to: State.END},\n {name: Event.END, from: State.PAUSE, to: State.END},\n // when replay is triggered (play button is clicked once video finished),\n // we should start a new session, so we should go to STARTUP state\n {name: Event.PLAYING, from: State.END, to: State.STARTUP},\n\n on(Event.TIMECHANGED).stayIn(State.END),\n on(Event.END).stayIn(State.END),\n\n {name: Event.PLAY, from: State.END, to: State.STARTUP},\n {name: Event.ERROR, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.ERROR, from: getAllStatesBut([State.STARTUP], State), to: State.ERROR},\n\n {name: Event.UNLOAD, from: getAllStatesBut([State.STARTUP], State), to: State.END},\n {name: Event.UNLOAD, from: [State.STARTUP], to: State.VIDEOSTART_FAILED},\n ],\n\n // Keep callbacks sorted by order in which they are called by JSM library (and after order, sorted by name)\n //\n // Do not use convenience, shortened callbacks\n // - instead of `onEVENT` use `onafterEVENT`\n // - instead of `onSTATE` use `onenterSTATE`\n //\n // see: https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#callbacks\n callbacks: {\n [`onleave${State.PLAYING}`]: () => {\n this.playingHeartbeatService.stopHeartbeat();\n },\n\n onleavestate: (event, from, to, eventTimestamp, eventData) => {\n logStateMachineTransition('LEAVE', event, from, to);\n\n // Skip this JSM callback for JSM initial event\n // This event is fired when the state machine is constructed,\n // to transition us from 'none' to custom initial 'SETUP' state\n if (event === JSM_INITIAL_EVENT) {\n return;\n }\n\n // Skip this JSM callback when an JSM event without a timestamp is called,\n // because it would cause NPE in analytics code (state duration calculation etc.).\n // This probably has happened because the state machine was not used correctly,\n // aka. JSM event was not called via `callEvent` method as it should be!\n if (!eventTimestamp) {\n return;\n }\n\n this.addStatesToLog(event, from, to, eventTimestamp, eventData);\n const stateDuration = eventTimestamp - this.onEnterStateTimestamp;\n const isStartup = from === State.STARTUP && to === State.PLAYING;\n this.maybeSetOrClearVideoStartTimeouts(from, to);\n\n if (isStartup) {\n this.stateMachineCallbacks.startup(stateDuration, State.STARTUP.toLowerCase());\n }\n\n const lowerCaseFrom = String(from).toLowerCase();\n if (event === Event.UNLOAD) {\n this.stateMachineCallbacks.unload(stateDuration, lowerCaseFrom);\n } else if (from === State.SETUP) {\n // Setting Player Startup Time to fixed value of 1ms.\n // We can not get correct Player Startup Time from PWX player, because it does not have an \"onInitialized\" event\n this.stateMachineCallbacks.setup(1, State.SETUP.toLowerCase());\n } else if (event === Event.PAUSE && from === State.STARTUP && to === State.READY) {\n // fired PAUSE event in STARTUP state indicates we are moving back to READY,\n // so we have to clean setTimeout, and we should not call any stateMachineCallbacks\n this.clearVideoStartTimeout();\n } else if (from !== State.ERROR && !isStartup) {\n // Default \"onleavestate\" state machine callback\n //\n // Every time, when we leave a state, we should try to call \"state\" callback,\n // to be able to make \"a cut\" and send analytics sample (if necessary)\n const defaultStateMachineCallbackFn = this.stateMachineCallbacks[lowerCaseFrom];\n if (isFunction(defaultStateMachineCallbackFn)) {\n // a try-catch block to add more resilience against callback errors\n try {\n defaultStateMachineCallbackFn(stateDuration, lowerCaseFrom, eventData);\n } catch (e) {\n logger.error('Exception occurred in State Machine callback ' + lowerCaseFrom, eventData, e);\n }\n } else {\n // if callback is not defined, log a warning to indicate to the developer that\n // - a new callback function needs to be implemented to relay on this default state machine callback\n // - or if no callback is needed, we should\n // - early return from this JSM callback\n // - or add this state to the ignored list\n logMissingCallbackWarning(from, [State.READY]);\n }\n }\n },\n\n [`onenter${State.PLAYING}`]: () => {\n this.playingHeartbeatService.startHeartbeat();\n },\n\n onenterstate: (event, from, to, eventTimestamp, _eventData) => {\n logStateMachineTransition('ENTER', event, from, to);\n\n this.onEnterStateTimestamp = eventTimestamp ?? Date.now();\n // if customer set custom \"start time\" timestamp in AnalyticsStateMachineOptions of adapter constructor,\n // use it and override `onEnterStateTimestamp` during JSM initialization (transition to initial SETUP state)\n if (isNumber(opts.starttime) && event === JSM_INITIAL_EVENT) {\n this.onEnterStateTimestamp = opts.starttime;\n }\n },\n\n [`onafter${Event.ERROR}`]: (_event, _from, _to, _eventTimestamp, eventData) => {\n this.stateMachineCallbacks.error(eventData);\n },\n },\n });\n }\n\n addStatesToLog(\n event: string | undefined,\n from: string | undefined,\n to: string | undefined,\n timestamp: number,\n eventObject: any,\n ) {\n if (this.enabledDebugging) {\n this.debuggingStates.push(new EventDebugging(event, from, to, timestamp, eventObject));\n }\n }\n\n getStates() {\n return this.debuggingStates;\n }\n\n setEnabledDebugging(enabled: boolean) {\n this.enabledDebugging = enabled;\n }\n\n private maybeSetOrClearVideoStartTimeouts(from: string | undefined, to: string | undefined) {\n if (from === State.READY && to === State.STARTUP) {\n this.setVideoStartTimeout();\n } else if (from === State.STARTUP && to === State.PLAYING) {\n this.clearVideoStartTimeout();\n }\n }\n}\n","import type {Analytics} from '../../core/Analytics';\nimport {HeartbeatService} from '../../core/HeartbeatService';\nimport {Event} from '../../enums/Event';\nimport {Player} from '../../enums/Player';\nimport {StreamTypes} from '../../enums/StreamTypes';\nimport {ErrorDetailBackend} from '../../features/errordetails/ErrorDetailBackend';\nimport {ErrorDetailTracking} from '../../features/errordetails/ErrorDetailTracking';\nimport type {Feature} from '../../features/Feature';\nimport type {FeatureConfig} from '../../features/FeatureConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport {normalizeVideoDuration, PlaybackInfo} from '../../types/PlaybackInfo';\nimport {InternalAdapter} from '../internal/InternalAdapter';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {BitmovinPwxAnalyticsStateMachine} from './BitmovinPwxAnalyticsStateMachine';\nimport {\n CoreExportNames,\n PlaybackApiEventsPackageExportNames,\n SourceExportNames,\n SourcesApiExportNames,\n} from './ExportNames';\nimport {AnalyticsContext} from './Types';\n\nconst PWX_ABORT_ERROR_CODE = 1007;\n\nexport class BitmovinPwxInternalAdapter extends InternalAdapter implements InternalAdapterAPI {\n /** Boolean flag to prevent multiple calls of the {@link Event.UNLOAD} event */\n private onBeforeUnLoadEvent = false;\n\n private readonly context: AnalyticsContext;\n\n constructor(context: AnalyticsContext, opts?: AnalyticsStateMachineOptions) {\n super(opts);\n this.context = context;\n const playingHeartbeatService = new HeartbeatService(() => this.currentTime);\n const stateMachine = new BitmovinPwxAnalyticsStateMachine(\n this.stateMachineCallbacks,\n playingHeartbeatService,\n this.opts,\n );\n playingHeartbeatService.setListener(stateMachine);\n this.stateMachine = stateMachine;\n }\n\n private getSource() {\n return this.context.registry.get(SourceExportNames.SourceState);\n }\n\n protected get currentTime(): number {\n return this.getSource().playback.playhead.position;\n }\n\n getAutoPlay(): boolean {\n return this.getSource().config.playback.autoplay;\n }\n\n getCurrentPlaybackInfo(): PlaybackInfo {\n const hls = this.getSource().sourceConfig.resources.filter((v) => v.url.includes('.m3u8'))[0]?.url;\n const dash = this.getSource().sourceConfig.resources.filter((v) => v.url.includes('.mpd'))[0]?.url;\n\n const videoRect = this.getSource().video.element?.getBoundingClientRect();\n const videoWidth = Math.round(videoRect?.width ?? 1);\n const videoHeight = Math.round(videoRect?.height ?? 1);\n\n let streamFormat: StreamTypes | undefined = undefined;\n if (hls) {\n streamFormat = StreamTypes.hls;\n } else if (dash) {\n streamFormat = StreamTypes.dash;\n }\n\n // height, width, codecs and bitrate are fixed until we have quality api\n return {\n ...this.getCommonPlaybackInfo(),\n droppedFrames: 0,\n isMuted: this.getSource().video.element?.muted,\n isLive: this.getSource().stream.type === 'live',\n videoWindowHeight: videoHeight,\n videoWindowWidth: videoWidth,\n videoDuration: normalizeVideoDuration(this.getSource().video.element?.duration),\n videoPlaybackHeight: videoHeight,\n videoPlaybackWidth: videoWidth,\n m3u8Url: hls,\n mpdUrl: dash,\n streamFormat,\n videoCodec: undefined, // not tracked yet\n audioCodec: undefined, // not tracked yet\n videoBitrate: 0, // not tracked yet\n audioBitrate: 0, // not tracked yet\n };\n }\n\n getPlayerName(): string {\n return Player.BITMOVIN_PWX;\n }\n\n getPlayerTech(): string {\n return 'webx:html5';\n }\n\n getPlayerVersion(): string {\n return this.context.registry.get(CoreExportNames.Constants).Version;\n }\n\n initialize(analytics: Analytics): Array<Feature<FeatureConfigContainer, FeatureConfig>> {\n this.registerEventListeners();\n this.registerUnloadEventListeners();\n\n const errorDetailTracking = new ErrorDetailTracking(\n analytics.errorDetailTrackingSettingsProvider,\n new ErrorDetailBackend(analytics.errorDetailTrackingSettingsProvider.collectorConfig),\n [analytics.errorDetailSubscribable],\n undefined,\n );\n\n return [errorDetailTracking];\n }\n\n private registerUnloadEventListeners() {\n let handleCollectorUnload = () => {\n if (!this.onBeforeUnLoadEvent) {\n this.onBeforeUnLoadEvent = true;\n const currentTime = this.context.registry.get(SourceExportNames.SourceState).playback.playhead.position;\n this.eventCallback(Event.UNLOAD, {currentTime});\n }\n this.release();\n };\n handleCollectorUnload = handleCollectorUnload.bind(true);\n\n this.context.abortSignal.addEventListener('abort', handleCollectorUnload);\n this.windowEventTracker.addEventListener('beforeunload', handleCollectorUnload);\n this.windowEventTracker.addEventListener('unload', handleCollectorUnload);\n }\n\n private registerEventListeners() {\n // The context might not be same so a different source event bus is available\n const sourceEventBus = this.context.registry.get(SourcesApiExportNames.SourceEventBus);\n const playbackAtom = this.context.registry.get(SourceExportNames.SourceState).playback;\n const PlaybackEvent = this.context.registry.get(PlaybackApiEventsPackageExportNames.PlaybackEvent);\n\n sourceEventBus.on(PlaybackEvent.Ready, () => {\n this.eventCallback(Event.SOURCE_LOADED, {currentTime: playbackAtom.playhead.position});\n });\n sourceEventBus.on(PlaybackEvent.Play, () => {\n this.eventCallback(Event.PLAY, {currentTime: playbackAtom.playhead.position});\n });\n sourceEventBus.on(PlaybackEvent.Playing, () => {\n this.eventCallback(Event.PLAYING, {currentTime: playbackAtom.playhead.position});\n });\n sourceEventBus.on(PlaybackEvent.Paused, () => {\n this.eventCallback(Event.PAUSE, {currentTime: playbackAtom.playhead.position});\n });\n sourceEventBus.on(PlaybackEvent.TimeChanged, () => {\n this.eventCallback(Event.TIMECHANGED, {currentTime: playbackAtom.playhead.position});\n });\n sourceEventBus.on(PlaybackEvent.VideoAttached, () => {\n this.eventCallback(Event.SOURCE_LOADED, {currentTime: playbackAtom.playhead.position});\n });\n\n sourceEventBus.on(PlaybackEvent.Ended, () => {\n this.eventCallback(Event.END, {currentTime: playbackAtom.playhead.position});\n });\n\n const abortListener = () => {\n const abortSignalReason = this.context.abortSignal.reason;\n if (abortSignalReason.name === 'SourceRemovedError' || abortSignalReason.name === 'FrameworkDisposedError') {\n this.eventCallback(Event.SOURCE_UNLOADED, {currentTime: playbackAtom.playhead.position});\n } else {\n this.eventCallback(Event.ERROR, {\n currentTime: playbackAtom.playhead.position,\n code: PWX_ABORT_ERROR_CODE,\n message: abortSignalReason.message,\n data: abortSignalReason,\n originalError: abortSignalReason,\n });\n }\n\n this.context.abortSignal.removeEventListener('abort', abortListener);\n };\n\n this.context.abortSignal.addEventListener('abort', abortListener);\n }\n}\n","/*!\n * This file was created to provide Bitmovin Player Web X \"export names\" as constants,\n * because they are exported as enums in 'd.ts' files, that we can't import as value in this project.\n *\n * Once `@bitmovin/player-web-x` bundle will provide these enums in way we could import them, we could remove/simplify this file.\n */\n\nimport type {BundleExportNames as BundleExportNamesEnum} from '@bitmovin/player-web-x/types/bundles/Types';\nimport type {CoreExportNames as CoreExportNamesEnum} from '@bitmovin/player-web-x/types/packages/core/Types';\nimport type {PlaybackApiEventsPackageExportNames as PlaybackApiEventsPackageExportNamesEnum} from '@bitmovin/player-web-x/types/packages/playback-api/playback-api-events/Types';\nimport type {SourceExportNames as SourceExportNamesEnum} from '@bitmovin/player-web-x/types/packages/source/Types';\nimport type {SourcesApiExportNames as SourcesApiExportNameEnum} from '@bitmovin/player-web-x/types/packages/sources-api/Types';\n\nimport type {EnumAsUnion} from '../../utils/EnumAsUnion';\n\nconst BundleExportNamesLogger: EnumAsUnion<typeof BundleExportNamesEnum> = 'logger';\nconst BundleExportNamesPlayerConfig: EnumAsUnion<typeof BundleExportNamesEnum> = 'player-config';\nexport const BundleExportNames = {\n Logger: BundleExportNamesLogger,\n PlayerConfig: BundleExportNamesPlayerConfig,\n};\n\nconst CoreExportNamesUtils: EnumAsUnion<typeof CoreExportNamesEnum> = 'utils';\nconst CoreExportNamesConstants: EnumAsUnion<typeof CoreExportNamesEnum> = 'constants';\nconst CoreExportNamesCoreEffects: EnumAsUnion<typeof CoreExportNamesEnum> = 'core-effects';\nconst CoreExportNamesCoreStateAtoms: EnumAsUnion<typeof CoreExportNamesEnum> = 'core-state-atoms';\nexport const CoreExportNames = {\n Utils: CoreExportNamesUtils,\n Constants: CoreExportNamesConstants,\n CoreEffects: CoreExportNamesCoreEffects,\n CoreStateAtoms: CoreExportNamesCoreStateAtoms,\n} as const;\n\nconst PlaybackApiEventsPackageExportNamesPlaybackEvent: EnumAsUnion<typeof PlaybackApiEventsPackageExportNamesEnum> =\n 'playback-event';\nexport const PlaybackApiEventsPackageExportNames = {\n PlaybackEvent: PlaybackApiEventsPackageExportNamesPlaybackEvent,\n} as const;\n\nconst SourceExportNamesCreateSourceStateAtom: EnumAsUnion<typeof SourceExportNamesEnum> = 'create-source-state-atom';\nconst SourceExportNamesCreateSourceReference: EnumAsUnion<typeof SourceExportNamesEnum> = 'create-source-reference';\nconst SourceExportNamesSourceReferences: EnumAsUnion<typeof SourceExportNamesEnum> = 'source-references';\nconst SourceExportNamesSourceState: EnumAsUnion<typeof SourceExportNamesEnum> = 'source-state-atom';\nexport const SourceExportNames = {\n CreateSourceStateAtom: SourceExportNamesCreateSourceStateAtom,\n CreateSourceReference: SourceExportNamesCreateSourceReference,\n SourceReferences: SourceExportNamesSourceReferences,\n SourceState: SourceExportNamesSourceState,\n} as const;\n\nconst SourcesApiExportNamesSourceApiManager: EnumAsUnion<typeof SourcesApiExportNameEnum> = 'source-api-manager';\nconst SourcesApiExportNamesVideoElementUtils: EnumAsUnion<typeof SourcesApiExportNameEnum> = 'video-element-utils';\nconst SourcesApiExportNamesSourceEventBus: EnumAsUnion<typeof SourcesApiExportNameEnum> = 'source-event-bus';\nexport const SourcesApiExportNames = {\n SourceApiManager: SourcesApiExportNamesSourceApiManager,\n VideoElementUtils: SourcesApiExportNamesVideoElementUtils,\n SourceEventBus: SourcesApiExportNamesSourceEventBus,\n} as const;\n","import type {AdapterAPI} from '../../api/AdapterAPI';\nimport {Analytics} from '../../core/Analytics';\nimport type {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {logger} from '../../utils/Logger';\nimport {\n hasPlayerAlreadyBeenAugmented,\n isDefined,\n markPlayerInstanceAsAugmented,\n} from '../../utils/playerAugmentationUtils';\nimport {VERSION} from '../../utils/Version';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {CAFv3InternalAdapter} from './CAFv3InternalAdapter';\n\nexport class CAFv3Adapter implements AdapterAPI {\n private readonly internalAdapter: InternalAdapterAPI | undefined;\n private readonly analytics: Analytics | undefined;\n\n constructor(config: AnalyticsConfig, castReceiverContext: any, opts?: AnalyticsStateMachineOptions) {\n if (hasPlayerAlreadyBeenAugmented(castReceiverContext)) {\n logger.errorMessageToUser('Bitmovin Analytics is already hooked up to this CastReceiverContext instance');\n return;\n }\n markPlayerInstanceAsAugmented(castReceiverContext);\n\n const sanitizedConfig = sanitizeAnalyticsConfig(config);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n return;\n }\n\n guardAgainstDuplicatedUserId(sanitizedConfig);\n\n this.internalAdapter = new CAFv3InternalAdapter(castReceiverContext, opts);\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n }\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getCurrentImpressionId();\n }\n\n getUserId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getUserId();\n }\n\n setCustomData(values: CustomDataValues) {\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.setCustomData(values);\n }\n\n setCustomDataOnce(values: CustomDataValues) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.setCustomDataOnce(values);\n }\n\n sourceChange(config: AnalyticsConfig) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.sourceChange(config);\n }\n}\n","import type {CastReceiverContext, PlayerManager} from 'chromecast-caf-receiver/cast.framework';\nimport type {Track} from 'chromecast-caf-receiver/cast.framework.messages';\n\nimport {CAFv3AnalyticsStateMachine} from '../../analyticsStateMachines/CAFv3AnalyticsStateMachine';\nimport type {Analytics} from '../../core/Analytics';\nimport {HeartbeatService} from '../../core/HeartbeatService';\nimport {Event} from '../../enums/Event';\nimport {Player} from '../../enums/Player';\nimport {getStreamTypesFromURL} from '../../enums/StreamTypes';\nimport {ErrorDetailBackend} from '../../features/errordetails/ErrorDetailBackend';\nimport {ErrorDetailTracking} from '../../features/errordetails/ErrorDetailTracking';\nimport type {Feature} from '../../features/Feature';\nimport type {FeatureConfig} from '../../features/FeatureConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {DrmPerformanceInfo} from '../../types/DrmPerformanceInfo';\nimport type {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport {buildPlaybackInfoStreamTypeFields, normalizeVideoDuration, PlaybackInfo} from '../../types/PlaybackInfo';\nimport {isBlank} from '../../utils/stringUtils';\nimport {isNotNullish, isNullish, tryJSONStringify} from '../../utils/Utils';\nimport {InternalAdapter} from '../internal/InternalAdapter';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {CastFrameworkEvent} from './castFrameworkTypes';\n\nexport class CAFv3InternalAdapter extends InternalAdapter implements InternalAdapterAPI {\n private readonly playerManager: PlayerManager;\n\n /** Boolean flag to prevent multiple calls of the {@link Event.UNLOAD} event */\n private onBeforeUnLoadEvent = false;\n private activeTextTracks: Track[] = [];\n\n constructor(castReceiverContext: CastReceiverContext, opts?: AnalyticsStateMachineOptions) {\n super(opts);\n const playingHeartbeatService = new HeartbeatService(() =>\n castReceiverContext.getPlayerManager().getCurrentTimeSec(),\n );\n const stateMachine = new CAFv3AnalyticsStateMachine(this.stateMachineCallbacks, playingHeartbeatService, this.opts);\n playingHeartbeatService.setListener(stateMachine);\n this.playerManager = castReceiverContext.getPlayerManager();\n this.stateMachine = stateMachine;\n }\n\n initialize(analytics: Analytics): Array<Feature<FeatureConfigContainer, FeatureConfig>> {\n this.registerCastFrameworkEventListeners();\n this.registerWindowUnloadEventListeners();\n\n const errorDetailTracking = new ErrorDetailTracking(\n analytics.errorDetailTrackingSettingsProvider,\n new ErrorDetailBackend(analytics.errorDetailTrackingSettingsProvider.collectorConfig),\n [analytics.errorDetailSubscribable],\n undefined,\n );\n return [errorDetailTracking];\n }\n\n getPlayerVersion = () => cast?.framework?.VERSION ?? 'unknown';\n getPlayerName = () => Player.CHROMECAST_SHAKA;\n getPlayerTech = () => 'html5';\n getAutoPlay = () => this.playerManager.getQueueManager()?.getCurrentItem()?.autoplay ?? false;\n override getDrmPerformanceInfo = (): DrmPerformanceInfo | undefined => this.drmPerformanceInfo;\n getCurrentPlaybackInfo(): PlaybackInfo {\n const stats = this.playerManager.getStats();\n\n // filter out undefined and null values\n const subtitleLanguages = this.activeTextTracks?.map((t) => t.language).filter(isNotNullish);\n\n return {\n ...this.getCommonPlaybackInfo(),\n ...detectCAFv3PlaybackInfoStreamTypeFields(this.playerManager),\n ...detectCAFv3PlaybackInfoAudioFields(this.playerManager),\n isLive: detectIsLive(this.playerManager),\n playerTech: this.getPlayerTech(),\n videoDuration: normalizeVideoDuration(this.playerManager.getMediaInformation()?.duration ?? 0),\n videoPlaybackHeight: stats.height,\n videoPlaybackWidth: stats.width,\n subtitleLanguage: subtitleLanguages ? subtitleLanguages.join(',') : undefined,\n // TODO: Implement `droppedFrames` tracking in CAFv3\n // - https://developers.google.com/cast/docs/reference/web_receiver/cast.framework.stats.Stats#droppedFrames\n droppedFrames: 0,\n };\n }\n\n protected get currentTime(): number {\n return this.playerManager.getCurrentTimeSec();\n }\n\n private registerCastFrameworkEventListeners() {\n // This is a special identifier, which can be used to listen for all events (mostly used for debugging purposes)\n // see: https://developers.google.com/cast/docs/reference/web_receiver/cast.framework.events#.EventType\n // this.playerManager.addEventListener(CastFrameworkEvent.ALL, (event) => {\n // console.log(`⭐ [${event.type}]`, JSON.stringify(event));\n // });\n\n // Fired when the browser has finished loading the metadata for a clip. This event is forwarded from the MediaElement, and has been wrapped.\n this.playerManager.addEventListener(CastFrameworkEvent.LOADED_METADATA, (_event) => {\n this.eventCallback(Event.SOURCE_LOADED, {});\n });\n\n // Fired when the player has finished processing a load request and is ready to play.\n this.playerManager.addEventListener(CastFrameworkEvent.PLAYER_LOAD_COMPLETE, () => {\n // captions\n const textTracksManager = this.playerManager.getTextTracksManager();\n this.activeTextTracks = textTracksManager.getActiveTracks();\n\n this.eventCallback(Event.READY, {});\n });\n\n // Fired when playback is ready to start (ie: after being paused). This event is forwarded from the MediaElement, and has been wrapped.\n this.playerManager.addEventListener(CastFrameworkEvent.PLAY, (event) => {\n this.eventCallback(Event.PLAY, {currentTime: event.currentMediaTime});\n });\n\n // Fired when playback has started. This event is forwarded from the MediaElement, and has been wrapped in a cast.framework.events.MediaElementEvent.\n this.playerManager.addEventListener(CastFrameworkEvent.PLAYING, (_event) => {\n this.eventCallback(Event.PLAYING, {currentTime: this.currentTime});\n });\n\n // Fired periodically while the media is playing. This will fire whenever the currentTime attribute changes\n this.playerManager.addEventListener(CastFrameworkEvent.TIME_UPDATE, (event) => {\n this.eventCallback(Event.TIMECHANGED, {currentTime: event.currentMediaTime});\n });\n\n // Fired when playback is paused. This event is forwarded from the MediaElement, and has been wrapped.\n this.playerManager.addEventListener(CastFrameworkEvent.PAUSE, (_event) => {\n this.eventCallback(Event.PAUSE, {currentTime: this.currentTime});\n });\n\n // Fired when an error occurs\n this.playerManager.addEventListener(CastFrameworkEvent.ERROR, (event) => {\n const errorData = isNotNullish(event.error) ? event.error : undefined;\n this.eventCallback(Event.ERROR, {\n currentTime: this.playerManager.getCurrentTimeSec(),\n code: event.detailedErrorCode,\n message: event.reason,\n legacyData: errorData,\n originalError: event,\n data: {additionalData: tryJSONStringify(errorData)},\n });\n });\n\n // Fired when the media is being seeked. This event is forwarded from the MediaElement, and has been wrapped.\n this.playerManager.addEventListener(CastFrameworkEvent.SEEKING, (event) => {\n this.eventCallback(Event.SEEK, {currentTime: event.currentMediaTime});\n });\n\n // Fired when a seek has finished. This will not be fired in case seeking finishes when the media is paused. This event is forwarded from the MediaElement, and has been wrapped.\n this.playerManager.addEventListener(CastFrameworkEvent.SEEKED, (event) => {\n this.eventCallback(Event.SEEKED, {currentTime: event.currentMediaTime});\n });\n\n this.playerManager.addEventListener(CastFrameworkEvent.BUFFERING, (event) => {\n if (event.isBuffering) {\n this.eventCallback(Event.START_BUFFERING, {currentTime: this.currentTime});\n }\n });\n\n // Fired when a LOAD message is received\n //\n // Why REQUEST_LOAD and not LOAD_START like in HTML5 adapters?\n // Later after the REQUEST_LOAD, also the LOAD_START event is always called. However, we use REQUEST_LOAD,\n // because TIME_UPDATE event happens between before the LOAD_START, and that would wrongly move us to PLAYING state.\n // For example:\n // If we would be in PAUSE state and relay on LOAD_START event, at first the TIME_UPDATE would happen\n // and move us to PLAYING state and only after that we would call sourceChange and be SOURCE_CHANGE state,\n // but this would generate short playing sample before the source change from PAUSE state.\n this.playerManager.addEventListener(CastFrameworkEvent.REQUEST_LOAD, (_event) => {\n this.sourceChange({});\n });\n }\n\n private registerWindowUnloadEventListeners() {\n const handleWindowUnloadEvent = () => {\n if (!this.onBeforeUnLoadEvent) {\n this.onBeforeUnLoadEvent = true;\n this.eventCallback(Event.UNLOAD, {currentTime: this.currentTime});\n }\n this.release();\n };\n\n this.windowEventTracker.addEventListener('beforeunload', handleWindowUnloadEvent);\n this.windowEventTracker.addEventListener('unload', handleWindowUnloadEvent);\n }\n}\n\nfunction detectIsLive(playerManager: PlayerManager): true | undefined {\n // needs to be explicitly set to \"LIVE\" by customers in their receiver implementation\n if (playerManager.getMediaInformation()?.streamType === 'LIVE') {\n return true;\n }\n\n // hack because the object exists only for live streams\n const liveSeekableRange = playerManager.getLiveSeekableRange();\n\n if (liveSeekableRange) {\n return true;\n }\n\n return undefined;\n}\n\nexport function detectCAFv3PlaybackInfoStreamTypeFields(\n playerManager: PlayerManager,\n): Pick<PlaybackInfo, 'm3u8Url' | 'mpdUrl' | 'progUrl' | 'streamFormat'> {\n // Optional media URL, to allow using contentId for the actual ID. If contentUrl is provided, it is used as\n // the media URL. Otherwise, the contentId is used as the media URL.\n // see: https://developers.google.com/cast/docs/reference/web_receiver/cast.framework.messages.MediaInformation#contentUrl\n let url = playerManager.getMediaInformation()?.contentUrl;\n if (isNullish(url) || isBlank(url)) {\n url = playerManager.getMediaInformation()?.contentId;\n }\n\n const streamType = getStreamTypesFromURL(url);\n\n return buildPlaybackInfoStreamTypeFields(streamType, url);\n}\n\nfunction detectCAFv3PlaybackInfoAudioFields(\n playerManager: PlayerManager,\n): Pick<PlaybackInfo, 'audioBitrate' | 'audioCodec' | 'audioLanguage'> {\n try {\n const audioTracksManager = playerManager.getAudioTracksManager();\n\n // getActiveTrack() can throw error if there is no video loaded yet, or no active audio track\n const activeTract = audioTracksManager.getActiveTrack();\n\n return {\n audioLanguage: activeTract?.language,\n audioCodec: activeTract?.audioTrackInfo?.audioCodec,\n audioBitrate: undefined, // bitrate is not available in CAFv3\n };\n } catch (_error) {\n // no action needed\n // active track is not available, so we cannot get audio fields\n return {};\n }\n}\n","/*!\n * This file was created to avoid usage of \"global `cast.framework` values\" (constants/enums/classes/etc.) that should be\n * defined by JavaScript file `cast_receiver_framework.js` imported by the Web Cast Receiver app. We should not relay on it,\n * and instead, we should define our own necessary primitive values and constants we need.\n *\n * We should still use \"type imports\" (`import type {}`) from the `@types/chromecast-caf-receiver` package!\n *\n * Cypress test should cover \"copies of the library values\" to be sure they are up to date with the library!\n */\n\nimport type {EventType} from 'chromecast-caf-receiver/cast.framework.events';\n\n/**\n * https://developers.google.com/cast/docs/reference/web_receiver/cast.framework.events#.EventType\n */\nexport const CastFrameworkEvent = {\n ALL: '*' as EventType.ALL,\n BUFFERING: 'BUFFERING' as EventType.BUFFERING,\n ERROR: 'ERROR' as EventType.ERROR,\n LOADED_METADATA: 'LOADED_METADATA' as EventType.LOADED_METADATA,\n PAUSE: 'PAUSE' as EventType.PAUSE,\n PLAY: 'PLAY' as EventType.PLAY,\n PLAYING: 'PLAYING' as EventType.PLAYING,\n PLAYER_LOAD_COMPLETE: 'PLAYER_LOAD_COMPLETE' as EventType.PLAYER_LOAD_COMPLETE,\n REQUEST_LOAD: 'REQUEST_LOAD' as EventType.REQUEST_LOAD,\n SEEKED: 'SEEKED' as EventType.SEEKED,\n SEEKING: 'SEEKING' as EventType.SEEKING,\n STALLED: 'STALLED' as EventType.STALLED,\n TIME_UPDATE: 'TIME_UPDATE' as EventType.TIME_UPDATE,\n} as const;\n","import type {AdapterAPI} from '../../api/AdapterAPI';\nimport {Analytics} from '../../core/Analytics';\nimport type {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {logger} from '../../utils/Logger';\nimport {\n hasPlayerAlreadyBeenAugmented,\n isDefined,\n markPlayerInstanceAsAugmented,\n} from '../../utils/playerAugmentationUtils';\nimport {VERSION} from '../../utils/Version';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {DashjsInternalAdapter} from './DashjsInternalAdapter';\n\nexport class DashjsAdapter implements AdapterAPI {\n private readonly internalAdapter: InternalAdapterAPI | undefined;\n private readonly analytics: Analytics | undefined;\n\n constructor(config: AnalyticsConfig, player: any, opts?: AnalyticsStateMachineOptions) {\n if (hasPlayerAlreadyBeenAugmented(player)) {\n logger.errorMessageToUser('Bitmovin Analytics is already hooked up to this player instance');\n return;\n }\n markPlayerInstanceAsAugmented(player);\n\n const sanitizedConfig = sanitizeAnalyticsConfig(config);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n return;\n }\n\n guardAgainstDuplicatedUserId(sanitizedConfig);\n\n this.internalAdapter = new DashjsInternalAdapter(player, opts);\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n }\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getCurrentImpressionId();\n }\n\n getUserId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getUserId();\n }\n\n setCustomData(values: CustomDataValues) {\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.setCustomData(values);\n }\n\n setCustomDataOnce(values: CustomDataValues) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.setCustomDataOnce(values);\n }\n\n sourceChange(config: AnalyticsConfig) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.sourceChange(config);\n }\n}\n","import type {MediaPlayerClass} from 'dashjs';\n\nimport {Analytics} from '../../core/Analytics';\nimport {Event} from '../../enums/Event';\nimport {MIMETypes} from '../../enums/MIMETypes';\nimport {Player} from '../../enums/Player';\nimport {ErrorDetailBackend} from '../../features/errordetails/ErrorDetailBackend';\nimport {ErrorDetailTracking} from '../../features/errordetails/ErrorDetailTracking';\nimport {Feature} from '../../features/Feature';\nimport {FeatureConfig} from '../../features/FeatureConfig';\nimport {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport type {PlaybackInfo} from '../../types/PlaybackInfo';\nimport {QualityLevelInfo} from '../../types/QualityLevelInfo';\nimport {logger} from '../../utils/Logger';\nimport {isNotNullish} from '../../utils/Utils';\nimport {HTML5InternalAdapter} from '../html5/HTML5InternalAdapter';\nimport {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {getCodecInfo, getQualityLevelInfo} from './dashjsApiUtils';\n\nexport class DashjsInternalAdapter extends HTML5InternalAdapter implements InternalAdapterAPI {\n private readonly mediaPlayer: MediaPlayerClass;\n\n constructor(mediaPlayer: any, opts?: AnalyticsStateMachineOptions) {\n super(undefined, opts);\n this.mediaPlayer = mediaPlayer;\n }\n\n override initialize(analytics: Analytics): Array<Feature<FeatureConfigContainer, FeatureConfig>> {\n super.initialize(analytics);\n let videoEl: HTMLVideoElement | null = null;\n try {\n videoEl = this.mediaPlayer.getVideoElement();\n } catch (_e) {\n // empty\n }\n\n if (!videoEl) {\n this.mediaPlayer.on(\n 'manifestLoaded',\n () => {\n try {\n videoEl = this.mediaPlayer.getVideoElement();\n this.setMediaElement(videoEl);\n this.registerMediaElementEventsForDashJS();\n } catch (e) {\n logger.errorMessageToUser(\n 'Something went wrong while getting underlying HTMLVideoElement. Not possible to attach adapter and initialize Bitmovin Analytics. Error: ',\n e,\n );\n this.release();\n }\n },\n this,\n );\n } else {\n this.setMediaElement(videoEl);\n this.registerMediaElementEventsForDashJS();\n }\n const errorDetailTracking = new ErrorDetailTracking(\n analytics.errorDetailTrackingSettingsProvider,\n new ErrorDetailBackend(analytics.errorDetailTrackingSettingsProvider.collectorConfig),\n [analytics.errorDetailSubscribable],\n undefined,\n );\n return [errorDetailTracking];\n }\n\n private registerMediaElementEventsForDashJS() {\n const mediaElement = this.mediaElement;\n\n if (!mediaElement) {\n return;\n }\n\n this.listenToMediaElementEvent('playing', () => {\n const {currentTime} = mediaElement;\n this.needsFirstPlayIntent = false;\n this.eventCallback(Event.TIMECHANGED, {\n currentTime,\n });\n });\n }\n\n override getPlayerName = () => Player.DASHJS;\n\n override getCurrentPlaybackInfo(): PlaybackInfo {\n const html5PlaybackInfo = super.getCurrentPlaybackInfo();\n\n const playbackInfo: PlaybackInfo = {\n ...html5PlaybackInfo,\n };\n\n const codecInfo = getCodecInfo(this.mediaPlayer);\n this.sourceInfoFallbackService.applyAndStoreCodecInfo(playbackInfo, codecInfo);\n\n return playbackInfo;\n }\n\n override getPlayerVersion = () => this.mediaPlayer.getVersion();\n\n override getMIMEType() {\n return MIMETypes.DASH;\n }\n\n override getStreamURL(): string | undefined {\n if (!this.mediaPlayer) {\n return undefined;\n }\n\n // In case of error/unloading the source might be undefined and the getter will throw an error\n let source: object | string | undefined = undefined;\n try {\n source = this.mediaPlayer.getSource();\n } catch (error) {\n logger.warn('no source available', error);\n }\n\n return isNotNullish(source) ? source?.toString() : undefined;\n }\n\n override getCurrentQualityLevelInfo(): QualityLevelInfo | null {\n if (!this.mediaPlayer) {\n return null;\n }\n\n // quality info is not available on source change, player API methods exist but throw exception\n try {\n return getQualityLevelInfo(this.mediaPlayer);\n } catch (_error) {\n logger.warn('Quality information not available');\n }\n\n return null;\n }\n}\n","import type {MediaPlayerClass} from 'dashjs';\n\nimport type {CodecInfo} from '../../types/CodecInfo';\nimport type {QualityLevelInfo} from '../../types/QualityLevelInfo';\nimport {Converter} from '../../utils/Converter';\nimport {isNumber} from '../../utils/numberUtils';\nimport {isBlank, isValidString} from '../../utils/stringUtils';\nimport {isFunction, isNullish} from '../../utils/Utils';\n\n//#region dashjs API v4.7.4\n\n/**\n * @see https://github.com/Dash-Industry-Forum/dash.js/blob/v4.7.4/index.d.ts#L950\n */\ntype MediaTypeApiV4 = 'audio' | 'image' | 'text' | 'video';\n\n/**\n * @see https://github.com/Dash-Industry-Forum/dash.js/blob/v4.7.4/index.d.ts#L4110\n */\ntype BitrateInfoApiV4 = {\n bitrate: number;\n height: number;\n mediaType: MediaTypeApiV4;\n qualityIndex: number;\n scanType: string;\n width: number;\n};\n\ntype HasApiV4ToGetQualityLevelInfo = {\n getBitrateInfoListFor: (type: MediaTypeApiV4) => BitrateInfoApiV4[];\n getQualityFor: (type: string) => number;\n};\n\nfunction hasApiV4ToGetQualityLevelInfo(mediaPlayer: any): mediaPlayer is HasApiV4ToGetQualityLevelInfo {\n return isFunction(mediaPlayer['getBitrateInfoListFor']) && isFunction(mediaPlayer['getQualityFor']);\n}\n\n//#endregion\n\n/**\n * Use dashjs v5 API to get {@link QualityLevelInfo}.\n *\n * Support also dashjs v4 API.\n *\n * @throws Error\n */\nexport const getQualityLevelInfo = (mediaPlayer: MediaPlayerClass): QualityLevelInfo | null => {\n if (hasApiV4ToGetQualityLevelInfo(mediaPlayer)) {\n const videoBitrateInfoList = mediaPlayer.getBitrateInfoListFor('video');\n const currentVideoQualityIndex = mediaPlayer.getQualityFor('video');\n const currentVideoQuality = videoBitrateInfoList[currentVideoQualityIndex];\n\n if (isNullish(currentVideoQuality)) {\n return null;\n }\n\n return {\n width: currentVideoQuality.width,\n height: currentVideoQuality.height,\n bitrate: currentVideoQuality.bitrate,\n };\n }\n\n const currentVideoRepresentation = mediaPlayer.getCurrentRepresentationForType('video');\n\n if (isNullish(currentVideoRepresentation)) {\n return null;\n }\n\n return {\n width: currentVideoRepresentation.width,\n height: currentVideoRepresentation.height,\n bitrate: isNumber(currentVideoRepresentation.bitrateInKbit)\n ? Converter.kiloBitsToBits(currentVideoRepresentation.bitrateInKbit)\n : 0,\n };\n};\n\n/**\n * Use dashjs v5 API to get {@link CodecInfo}.\n *\n * Compatible also with dashjs v4 API.\n */\nexport const getCodecInfo = (mediaPlayer: MediaPlayerClass): CodecInfo => {\n /**\n * Same RegExp for video and audio codec property parsing, because it's string value has same format with `codecs`\n *\n * Parse string and extract codec as first captured group, value between `\\\"` and `\\\"`\n *\n * Example 'video' value from player API:\n * `video/mp4;codecs=\"avc1.4d400d\"`\n * should be parsed by RegExp and return match\n * `avc1.4d400d`\n *\n * Example 'audio' value from player API:\n * `audio/mp4;codecs=\"mp4a.40.5\"`\n * should be parsed by RegExp and return match\n * `mp4a.40.5`\n */\n const codecsRegExp = new RegExp(/codecs=\"(.*)\"/);\n\n // try-catches in code, because `mediaPlayer.getCurrentTrackFor`\n // can throw STREAMING_NOT_INITIALIZED_ERROR, if called before initializePlayback function\n //\n // see https://cdn.dashjs.org/latest/jsdoc/module-MediaPlayer.html#getCurrentTrackFor\n\n let videoCodec: string | undefined;\n try {\n const rawVideoCodec = mediaPlayer.getCurrentTrackFor('video')?.codec;\n if (isValidString(rawVideoCodec) && !isBlank(rawVideoCodec)) {\n const matches = codecsRegExp.exec(rawVideoCodec);\n videoCodec = matches?.[1];\n }\n } catch (_e) {\n videoCodec = undefined;\n }\n\n let audioCodec: string | undefined;\n try {\n const rawAudioCodec = mediaPlayer.getCurrentTrackFor('audio')?.codec;\n if (isValidString(rawAudioCodec) && !isBlank(rawAudioCodec)) {\n const matches = codecsRegExp.exec(rawAudioCodec);\n audioCodec = matches?.[1];\n }\n } catch (_e) {\n audioCodec = undefined;\n }\n\n return {videoCodec, audioCodec};\n};\n","import type {AdapterAPI} from '../../api/AdapterAPI';\nimport {Analytics} from '../../core/Analytics';\nimport type {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {logger} from '../../utils/Logger';\nimport {\n hasPlayerAlreadyBeenAugmented,\n isDefined,\n markPlayerInstanceAsAugmented,\n} from '../../utils/playerAugmentationUtils';\nimport {VERSION} from '../../utils/Version';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {HlsInternalAdapter} from './HlsInternalAdapter';\n\nexport class HlsAdapter implements AdapterAPI {\n private readonly internalAdapter: InternalAdapterAPI | undefined;\n private readonly analytics: Analytics | undefined;\n\n constructor(config: AnalyticsConfig, player: any, opts?: AnalyticsStateMachineOptions) {\n if (hasPlayerAlreadyBeenAugmented(player)) {\n logger.errorMessageToUser('Bitmovin Analytics is already hooked up to this player instance');\n return;\n }\n markPlayerInstanceAsAugmented(player);\n\n const sanitizedConfig = sanitizeAnalyticsConfig(config);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n return;\n }\n\n guardAgainstDuplicatedUserId(sanitizedConfig);\n\n this.internalAdapter = new HlsInternalAdapter(player, opts);\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n }\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getCurrentImpressionId();\n }\n\n getUserId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getUserId();\n }\n\n setCustomData(values: CustomDataValues) {\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.setCustomData(values);\n }\n\n setCustomDataOnce(values: CustomDataValues) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.setCustomDataOnce(values);\n }\n\n sourceChange(config: AnalyticsConfig) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.sourceChange(config);\n }\n}\n","import type {AudioTrackSwitchedData, default as Hls, Level, SubtitleTrackSwitchData} from 'hls.js';\n\nimport {Analytics} from '../../core/Analytics';\nimport {DownloadSpeedMeter} from '../../core/DownloadSpeedMeter';\nimport {Event} from '../../enums/Event';\nimport {MIMETypes} from '../../enums/MIMETypes';\nimport {Player} from '../../enums/Player';\nimport {ErrorDetailBackend} from '../../features/errordetails/ErrorDetailBackend';\nimport {ErrorDetailTracking} from '../../features/errordetails/ErrorDetailTracking';\nimport {Feature} from '../../features/Feature';\nimport {FeatureConfig} from '../../features/FeatureConfig';\nimport {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport {CodecInfo} from '../../types/CodecInfo';\nimport {DownloadSpeedInfo} from '../../types/DownloadSpeedInfo';\nimport {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport {PlaybackInfo} from '../../types/PlaybackInfo';\nimport {QualityLevelInfo} from '../../types/QualityLevelInfo';\nimport {SubtitleInfo} from '../../types/SubtitleInfo';\nimport {isNumber} from '../../utils/numberUtils';\nimport {isNotNullish, isNullish} from '../../utils/Utils';\nimport {HTML5InternalAdapter} from '../html5/HTML5InternalAdapter';\nimport {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {HLS_PLAYER_EVENT} from './player/HlsJsPlayerTypes';\nimport {HlsSpeedMeterAdapter} from './player/HlsSpeedMeterAdapter';\n\nexport class HlsInternalAdapter extends HTML5InternalAdapter implements InternalAdapterAPI {\n private readonly hls: Hls;\n private speedMeter: DownloadSpeedMeter;\n\n constructor(hls: any, opts?: AnalyticsStateMachineOptions) {\n super(undefined, opts);\n this.hls = hls;\n this.speedMeter = new HlsSpeedMeterAdapter(hls, new DownloadSpeedMeter()).getDownloadSpeedMeter();\n }\n\n override initialize(analytics: Analytics): Array<Feature<FeatureConfigContainer, FeatureConfig>> {\n super.initialize(analytics);\n this.registerHlsEvents();\n const errorDetailTracking = new ErrorDetailTracking(\n analytics.errorDetailTrackingSettingsProvider,\n new ErrorDetailBackend(analytics.errorDetailTrackingSettingsProvider.collectorConfig),\n [analytics.errorDetailSubscribable],\n undefined,\n );\n return [errorDetailTracking];\n }\n\n override getPlayerName = () => Player.HLSJS;\n\n getPlayerVersion = () => (this.hls as any).constructor.version;\n\n override getCurrentPlaybackInfo(): PlaybackInfo {\n const selectedSubtitle = this.getSelectedSubtitleLanguage();\n\n const playbackInfo: PlaybackInfo = {\n ...super.getCurrentPlaybackInfo(),\n audioLanguage: this.getSelectedAudioLanguage(),\n subtitleEnabled: isNotNullish(selectedSubtitle) ? selectedSubtitle.enabled : undefined,\n subtitleLanguage: isNotNullish(selectedSubtitle) ? selectedSubtitle.language : undefined,\n };\n\n const codecInfo = getHlsCodecInfo(this.hls);\n this.sourceInfoFallbackService.applyAndStoreCodecInfo(playbackInfo, codecInfo);\n\n return playbackInfo;\n }\n override getDownloadSpeedInfo(): DownloadSpeedInfo {\n return this.speedMeter.getInfo();\n }\n override resetDownloadSpeedInfoMeasures() {\n this.speedMeter.reset();\n }\n\n getCurrentQualityLevelInfo(): QualityLevelInfo | null {\n const currentLevelObj = getHlsCurrentLevel(this.hls);\n if (!currentLevelObj) {\n return null;\n }\n\n const bitrate = currentLevelObj.bitrate;\n const width = currentLevelObj.width;\n const height = currentLevelObj.height;\n\n return {\n bitrate: bitrate,\n width: width,\n height: height,\n };\n }\n\n override isLive = () => {\n const currentLevelObj = getHlsCurrentLevel(this.hls);\n\n if (isNullish(currentLevelObj?.details)) {\n return undefined;\n }\n\n return currentLevelObj.details.live;\n };\n\n override getMIMEType() {\n return MIMETypes.HLS;\n }\n\n override getStreamURL() {\n return (this.hls as any).url;\n }\n\n registerHlsEvents() {\n this.hls.on(HLS_PLAYER_EVENT.MEDIA_ATTACHING, this.onMediaAttaching.bind(this));\n this.hls.on(HLS_PLAYER_EVENT.MEDIA_DETACHING, this.onMediaDetaching.bind(this));\n this.hls.on(HLS_PLAYER_EVENT.MANIFEST_LOADING, this.onManifestLoading.bind(this));\n this.hls.on(HLS_PLAYER_EVENT.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched.bind(this));\n this.hls.on(HLS_PLAYER_EVENT.SUBTITLE_TRACK_SWITCH, this.onSubtitleLanguageSwitched.bind(this));\n this.hls.on(HLS_PLAYER_EVENT.DESTROYING, this.onDestroying.bind(this));\n this.hls.on(HLS_PLAYER_EVENT.ERROR, this.onHlsError.bind(this));\n\n // media is already attached, event has been triggered before\n // or we are in the event handler of this event itself.\n // we can not know how the stacktrace to this constructor will look like.\n // therefore we will guard from this case in\n // the onMediaAttaching method (avoid running it twice)\n if (this.hls.media) {\n this.onMediaAttaching();\n this.onManifestLoading();\n }\n }\n\n onMediaAttaching() {\n // in case we are called again (when we are triggering this ourselves\n // but from the event handler of MEDIA_ATTACHING) we should not run again.\n if (this.mediaElement) {\n return;\n }\n\n this.mediaElement = this.hls.media as HTMLVideoElement;\n\n this.registerMediaElement();\n this.onMaybeReady();\n }\n\n onMediaDetaching() {\n this.unregisterMediaElement();\n }\n\n onManifestLoading() {\n this.onMaybeReady();\n }\n\n /**\n * errorData: { type : error type, details : error details, fatal : if true, hls.js cannot/will not try to recover, if false, hls.js will try to recover,other error specific data }\n * https://hls-js.netlify.com/api-docs/file/src/events.js.html#lineNumber98\n */\n onHlsError(errorName, errorData) {\n const isFatal = errorData ? errorData.fatal : true;\n if (isFatal) {\n const mediaElement = this.mediaElement;\n let currentTime;\n if (isNotNullish(mediaElement)) {\n currentTime = mediaElement.currentTime;\n }\n\n const errorMessage = isNotNullish(errorData) ? `${errorData.type}: ${errorData.details}` : undefined;\n this.eventCallback(Event.ERROR, {\n currentTime,\n code: this.getErrorCodeFromHlsErrorType(errorData.type),\n message: errorMessage,\n originalError: errorData,\n data: {},\n });\n }\n }\n\n onAudioTrackSwitched(_event: string, _data: AudioTrackSwitchedData) {\n const mediaElement = this.mediaElement;\n let currentTime;\n if (isNotNullish(mediaElement)) {\n currentTime = mediaElement.currentTime;\n }\n\n this.eventCallback(Event.AUDIOTRACK_CHANGED, {\n currentTime,\n });\n }\n\n onSubtitleLanguageSwitched(_event: string, _data: SubtitleTrackSwitchData) {\n const mediaElement = this.mediaElement;\n let currentTime;\n if (isNotNullish(mediaElement)) {\n currentTime = mediaElement.currentTime;\n }\n\n this.eventCallback(Event.SUBTITLE_CHANGE, {\n currentTime,\n });\n }\n\n private onDestroying = () => {\n this.eventCallback(Event.SOURCE_UNLOADED, {});\n this.release();\n };\n\n /**\n * returns mapped error code for Hlsjs ErrorTypes\n * @param type one of the ErrorTypes according to https://github.com/video-dev/hls.js/blob/v1.5.1/src/errors.ts#L1\n */\n private getErrorCodeFromHlsErrorType(type: string): number {\n switch (type) {\n case 'networkError':\n return 2;\n case 'mediaError':\n return 3;\n case 'keySystemError':\n return 4;\n case 'muxError':\n return 5;\n // default equals `otherError`\n default:\n return 1;\n }\n }\n\n private getSelectedAudioLanguage(): string | undefined {\n if (isNullish(this.hls.audioTrack) || this.hls.audioTrack < 0) {\n return undefined;\n }\n return (this.hls.audioTracks[this.hls.audioTrack] as any).lang;\n }\n\n private getSelectedSubtitleLanguage(): SubtitleInfo | undefined {\n // Check if function is supported (in latest hls version), otherwise use fallback option\n if (isNotNullish(this.hls.subtitleDisplay)) {\n const isSubtitleDisplayed = this.hls.subtitleTrack >= 0 && this.hls.subtitleDisplay === true;\n return {\n enabled: isSubtitleDisplayed,\n language: isSubtitleDisplayed ? this.hls.subtitleTracks[this.hls.subtitleTrack].lang : undefined,\n };\n } else {\n const {subtitleTrackController} = this.hls as any;\n if (isNotNullish(subtitleTrackController) && isNotNullish(subtitleTrackController.media)) {\n return this.getSelectedSubtitleFromMediaElement(subtitleTrackController.media);\n }\n }\n return undefined;\n }\n}\n\nexport const getHlsCodecInfo = (hls: Hls): CodecInfo | undefined => {\n const currentLevelObj = getHlsCurrentLevel(hls);\n if (!currentLevelObj) {\n return undefined;\n }\n\n return {\n videoCodec: currentLevelObj.videoCodec,\n audioCodec: currentLevelObj.audioCodec,\n };\n};\n\nexport const getHlsCurrentLevel = (hls: Hls): Level | undefined => {\n if (isNullish(hls.levels) || hls.levels.length === 0) {\n return undefined;\n }\n\n if (!isNumber(hls.currentLevel) || hls.currentLevel < 0) {\n return undefined;\n }\n\n return hls.levels[hls.currentLevel];\n};\n","/*!\n * This file was created to only avoid \"values imports\" (constants/enums/classes/etc.) from the `hls.js@1.6.2`\n * to avoid including the whole package in our distribution code.\n *\n * We should still use \"type imports\" (`import type {}`) from the library!\n *\n * Unit test should cover \"copies of the library values\" to be sure they are up to date with the library!\n */\nimport type {Events} from 'hls.js';\n\n/**\n * Partial copy from Hls.js repository\n * @see https://github.com/video-dev/hls.js/blob/v1.6.2/src/types/events.ts#L390\n */\nexport interface FragLoadedData {\n frag: Fragment;\n networkDetails: unknown;\n}\n\n/**\n * Partial copy from Hls.js repository\n * @see https://github.com/video-dev/hls.js/blob/v1.6.2/src/types/loader.ts#L175\n */\nexport enum PlaylistLevelType {\n AUDIO = 'audio',\n MAIN = 'main',\n SUBTITLE = 'subtitle',\n}\n\n/**\n * Partial copy from Hls.js repository\n * @see https://github.com/video-dev/hls.js/blob/v1.6.2/src/loader/fragment.ts#L163\n */\ninterface Fragment {\n stats: LoaderStats; // `get stats()` in `BaseSegment`\n readonly type: PlaylistLevelType;\n}\n\n/**\n * Partial copy from Hls.js repository\n * @see https://github.com/video-dev/hls.js/blob/v1.6.2/src/types/loader.ts#L73\n */\ninterface LoaderStats {\n total: number;\n loading: {\n end: number;\n first: number;\n start: number;\n };\n}\n\n/**\n * Map of Hls Player events that we listen to, each should be type of {@link Events}.\n *\n * Why: This way, we don't need to import string enum {@link Events} from 'hls.js' directly,\n * aka. compile/include it (as value) in our distribution code\n */\nexport const HLS_PLAYER_EVENT = {\n MEDIA_ATTACHING: 'hlsMediaAttaching' as Events.MEDIA_ATTACHING,\n MEDIA_DETACHING: 'hlsMediaDetaching' as Events.MEDIA_DETACHING,\n MANIFEST_LOADING: 'hlsManifestLoading' as Events.MANIFEST_LOADING,\n AUDIO_TRACK_SWITCHED: 'hlsAudioTrackSwitched' as Events.AUDIO_TRACK_SWITCHED,\n SUBTITLE_TRACK_SWITCH: 'hlsSubtitleTrackSwitch' as Events.SUBTITLE_TRACK_SWITCH,\n DESTROYING: 'hlsDestroying' as Events.DESTROYING,\n ERROR: 'hlsError' as Events.ERROR,\n} as const;\n","import {DownloadSpeedMeter} from '../../../core/DownloadSpeedMeter';\nimport {isNotNullish, isNullish} from '../../../utils/Utils';\n\nimport type {FragLoadedData} from './HlsJsPlayerTypes';\n\nexport class HlsSpeedMeterAdapter {\n private meter: DownloadSpeedMeter;\n\n constructor(hls: any, meter: DownloadSpeedMeter) {\n this.meter = meter;\n hls.on(hls.constructor.Events.FRAG_LOADED, (_eventName, data) => this.handleFragmentLoadedEvent(data));\n }\n\n getDownloadSpeedMeter(): DownloadSpeedMeter {\n return this.meter;\n }\n\n handleFragmentLoadedEvent(eventData: FragLoadedData) {\n if (eventData.frag.type !== 'main') {\n // ignore non-video fragments\n return;\n }\n\n const httpStatus = isNotNullish(eventData.networkDetails)\n ? (eventData.networkDetails as {status: number}).status\n : undefined;\n if (isNullish(httpStatus)) {\n // ignore fragments that https status is undefined (networkDetails are null)\n return;\n }\n\n const stats = eventData.frag.stats;\n const loadingDuration = (stats.loading.end - stats.loading.start) / 1000;\n const timeToFirstByte = (stats.loading.first - stats.loading.start) / 1000;\n\n const measurement = {\n duration: loadingDuration,\n size: stats.total,\n timeToFirstByte: timeToFirstByte,\n timestamp: new Date(),\n httpStatus,\n };\n\n this.meter.addMeasurement(measurement);\n }\n}\n","import {HTML5AnalyticsStateMachine} from '../../analyticsStateMachines/HTML5AnalyticsStateMachine';\nimport {Analytics} from '../../core/Analytics';\nimport {HeartbeatService} from '../../core/HeartbeatService';\nimport VideoCompletionTracker from '../../core/VideoCompletionTracker';\nimport {Event} from '../../enums/Event';\nimport {getMIMETypeFromFileExtension} from '../../enums/MIMETypes';\nimport {Player} from '../../enums/Player';\nimport {PlayerSize} from '../../enums/PlayerSize';\nimport {getStreamTypeFromMIMEType, StreamTypes} from '../../enums/StreamTypes';\nimport {Feature} from '../../features/Feature';\nimport {FeatureConfig} from '../../features/FeatureConfig';\nimport {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport {DrmPerformanceInfo} from '../../types/DrmPerformanceInfo';\nimport {QualityChangeEvent} from '../../types/EventData';\nimport {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport {buildPlaybackInfoStreamTypeFields, normalizeVideoDuration, PlaybackInfo} from '../../types/PlaybackInfo';\nimport {QualityLevelInfo} from '../../types/QualityLevelInfo';\nimport {SubtitleInfo} from '../../types/SubtitleInfo';\nimport {isVideoInFullscreen} from '../../utils/documentUtils';\nimport {logger} from '../../utils/Logger';\nimport {isAudioMuted, isNotNullish, isNullish} from '../../utils/Utils';\nimport {InternalAdapter} from '../internal/InternalAdapter';\nimport {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport HTMLVideoElementStatisticsProvider from './player/HTMLVideoElementStatisticsProvider';\n\nexport abstract class HTML5InternalAdapter extends InternalAdapter implements InternalAdapterAPI {\n private static BUFFERING_TIMECHANGED_TIMEOUT_IN_MS = 1000;\n\n protected mediaElement: HTMLVideoElement | undefined;\n private mediaElementEventHandlers: Array<{event: string; handler: any}>;\n /** holds reference of original mediaElement.load */\n private mediaElementOriginalLoadFn?: () => void;\n\n private readonly _videoCompletionTracker: VideoCompletionTracker;\n\n protected needsFirstPlayIntent: boolean = true;\n /** Boolean flag to prevent multiple calls of the {@link Event.UNLOAD} event */\n private onBeforeUnLoadEvent = false;\n\n private bufferingTimeout?: ReturnType<typeof setTimeout>;\n private isBuffering: boolean = false;\n private isPaused: boolean = false;\n private isSeeking: boolean = false;\n /** Previous media element time in seconds */\n private previousMediaTimeInSeconds: number = 0;\n /** Previous client time in milliseconds */\n private previousClientTime: number;\n private needsReadyEvent: boolean;\n private previousMutedValue = false;\n private playerStatisticsProvider: HTMLVideoElementStatisticsProvider;\n\n protected constructor(mediaElement: HTMLVideoElement | undefined, opts?: AnalyticsStateMachineOptions) {\n super(opts);\n const playingHeartbeatService = new HeartbeatService(() => mediaElement?.currentTime ?? 0);\n const stateMachine = new HTML5AnalyticsStateMachine(this.stateMachineCallbacks, playingHeartbeatService, this.opts);\n playingHeartbeatService.setListener(stateMachine);\n this.stateMachine = stateMachine;\n\n this.mediaElement = mediaElement;\n this.mediaElementEventHandlers = [];\n this.mediaElementOriginalLoadFn = undefined;\n\n this.bufferingTimeout = undefined;\n this.isBuffering = false;\n this.isPaused = false;\n this.isSeeking = false;\n this.previousMediaTimeInSeconds = 0;\n this.previousClientTime = 0;\n this.needsReadyEvent = true;\n this.needsFirstPlayIntent = true;\n this._videoCompletionTracker = new VideoCompletionTracker();\n this.playerStatisticsProvider = new HTMLVideoElementStatisticsProvider(mediaElement);\n }\n\n get videoCompletionTracker(): VideoCompletionTracker | undefined {\n return this._videoCompletionTracker;\n }\n\n initialize(_analytics: Analytics): Array<Feature<FeatureConfigContainer, FeatureConfig>> {\n if (this.mediaElement) {\n // calling `setMediaElement` with `null` argument on purpose to register all media element event\n // listeners with existing/already set media element during adapter initialization.\n this.setMediaElement();\n }\n this.registerWindowEvents();\n return [];\n }\n\n abstract getPlayerVersion(): string;\n getPlayerName = () => Player.HTML5;\n getPlayerTech = () => 'html5';\n getAutoPlay = () => (this.mediaElement ? this.mediaElement.autoplay : false);\n override getDrmPerformanceInfo = (): DrmPerformanceInfo | undefined => this.drmPerformanceInfo;\n getCurrentPlaybackInfo(): PlaybackInfo {\n const streamType = this.getStreamType();\n if (isNotNullish(streamType)) {\n this.sourceInfoFallbackService.setStreamFormat(streamType);\n }\n\n let info: PlaybackInfo = {\n ...this.getCommonPlaybackInfo(),\n ...buildPlaybackInfoStreamTypeFields(streamType, this.getStreamURL()),\n isLive: this.isLive(),\n size: isVideoInFullscreen() ? PlayerSize.Fullscreen : PlayerSize.Window,\n playerTech: this.getPlayerTech(),\n droppedFrames: this.playerStatisticsProvider.getDroppedFrames(),\n // TODO: Implement `audioBitrate`\n // TODO: Implement `isCasting`\n // TODO: Implement getting `videoTitle` from player (currently only from the analytics config)\n };\n\n if (this.mediaElement) {\n info = {\n ...info,\n videoDuration: normalizeVideoDuration(this.mediaElement.duration),\n isMuted: this.mediaElement.muted,\n videoWindowHeight: this.mediaElement.height,\n videoWindowWidth: this.mediaElement.width,\n };\n }\n\n const qualityInfo = this.getCurrentQualityLevelInfo();\n if (qualityInfo) {\n info = {\n ...info,\n videoPlaybackHeight: qualityInfo.height,\n videoPlaybackWidth: qualityInfo.width,\n videoBitrate: qualityInfo.bitrate,\n };\n }\n\n this.sourceInfoFallbackService.applyStreamFormat(info);\n\n return info;\n }\n\n override resetSourceRelatedState() {\n super.resetSourceRelatedState();\n this.playerStatisticsProvider.reset();\n this.needsFirstPlayIntent = true;\n this.isBuffering = false;\n this.isPaused = false;\n this.isSeeking = false;\n this.previousMediaTimeInSeconds = 0;\n clearTimeout(this.bufferingTimeout);\n }\n\n protected get currentTime(): number {\n if (!this.mediaElement) {\n throw new Error('No media attached');\n }\n\n return this.mediaElement.currentTime;\n }\n\n override release() {\n this.unregisterMediaElement();\n super.release();\n }\n\n isLive = () => {\n if (!this.mediaElement || isNaN(this.mediaElement.duration)) {\n return undefined;\n }\n\n return this.mediaElement.duration === Infinity;\n };\n\n /**\n * Used to setup against the media element.\n * We need this method to desynchronize construction of this class\n * and the actual initialization against the media element.\n * That is because at construction some media engine\n * may not already have the media element attached, for example\n * when passing in the DOM element is happening at once with passing the source URL\n * and can not be decoupled.\n * We are then awaiting an event from the engine and calling this with the media element\n * as argument from our sub-class.\n *\n * This method can also be called without arguments and then it will perform\n * initialization against the existing media element (should only be called once, will throw an error otherwise)\n *\n * It can also be used to replace the element.\n *\n *\n */\n setMediaElement(mediaElement: HTMLVideoElement | null = null) {\n // if called with argument (new media element)\n if (mediaElement) {\n // if we already have one, we need to unregister current one before replacing it\n if (this.mediaElement) {\n this.unregisterMediaElement();\n }\n\n // set the new media element\n this.mediaElement = mediaElement;\n }\n\n // if called without argument (and that is feature of function),\n // we assume media element is already set and ready to be registered\n\n // ...if not, we throw an error\n if (!this.mediaElement) {\n throw new Error('No media element owned');\n }\n\n // ...if it was already registered, we throw an error\n if (this.mediaElementEventHandlers.length > 0) {\n throw new Error('Media element already set (only call this once)');\n }\n\n this.registerMediaElement();\n this.onMaybeReady();\n }\n\n /**\n * Implemented by sub-class to deliver current quality-level info specific to media-engine.\n */\n abstract getCurrentQualityLevelInfo(): QualityLevelInfo | null;\n\n /**\n * Can be overriden by sub-classes\n * @returns {string}\n *\n */\n getMIMEType(): string | undefined {\n const streamUrl = this.getStreamURL();\n if (!streamUrl || streamUrl === undefined) {\n return;\n }\n return getMIMETypeFromFileExtension(streamUrl);\n }\n\n /**\n * Can be overriden by sub-classes\n * @returns {string}\n */\n getStreamType(): StreamTypes | undefined {\n const mimetype = this.getMIMEType();\n if (mimetype) {\n return getStreamTypeFromMIMEType(mimetype);\n }\n\n return undefined;\n }\n\n /**\n * Can be overriden by subclasses.\n * @returns {string}\n */\n getStreamURL(): string | undefined {\n const mediaElement = this.mediaElement;\n if (!mediaElement) {\n return;\n }\n\n return mediaElement.src;\n }\n\n registerMediaElement() {\n const mediaElement = this.mediaElement;\n if (!mediaElement) {\n return;\n }\n\n // wrap the original Media Element `load` function\n this.mediaElementOriginalLoadFn = mediaElement.load;\n const originalLoad = this.mediaElementOriginalLoadFn;\n mediaElement.load = (...args: Parameters<typeof mediaElement.load>): void => {\n this.sourceChange({});\n originalLoad.apply(mediaElement, args);\n };\n\n this.listenToMediaElementEvent('loadstart', () => {\n log(`loadstart ${mediaElement.currentTime}`);\n this.sourceChange({});\n });\n\n this.listenToMediaElementEvent('loadedmetadata', () => {\n log(`loadedmetadata time:${mediaElement.currentTime} / readyState: ${mediaElement.readyState}`);\n\n // silent\n this.checkQualityLevelAttributes(true);\n\n // set streamFormat if possible,\n // loadedMetadata seems to be the first event where this could be available\n const streamFormat = this.getStreamType();\n if (isNotNullish(streamFormat)) {\n this.sourceInfoFallbackService.setStreamFormat(streamFormat);\n }\n\n if (isNotNullish(this.mediaElement)) {\n this._videoCompletionTracker.reset();\n this._videoCompletionTracker.setVideoDuration(this.mediaElement.duration);\n this.previousMutedValue = this.mediaElement.muted;\n }\n this.eventCallback(Event.SOURCE_LOADED, {});\n });\n\n // We need the PLAY event to indicate the intent to play\n // NOTE: use TIMECHANGED event on 'playing' and trigger PLAY as intended in states.dot graph\n this.listenToMediaElementEvent('play', () => {\n log(`play ${mediaElement.currentTime}`);\n const {currentTime} = mediaElement;\n\n if (this.needsFirstPlayIntent) {\n this.previousMediaTimeInSeconds = currentTime;\n }\n this.needsFirstPlayIntent = false;\n\n this.eventCallback(Event.PLAY, {currentTime});\n });\n\n this.listenToMediaElementEvent('pause', () => {\n log(`pause ${mediaElement.currentTime}`);\n this.onPaused();\n });\n\n this.listenToMediaElementEvent('playing', () => {\n log(`playing ${mediaElement.currentTime}`);\n clearTimeout(this.bufferingTimeout);\n this.isPaused = false;\n\n // when the play attempt was before we have been attached to the player\n // no play event will set this to false -> collector is stuck in READY state\n this.needsFirstPlayIntent = false;\n });\n\n this.registerMediaElementErrorEvent(mediaElement);\n this.listenToMediaElementEvent('volumechange', () => {\n log(`volumechange ${mediaElement.currentTime}`);\n const {muted, currentTime, volume} = mediaElement;\n const isMuted = isAudioMuted(muted, volume);\n\n if (this.previousMutedValue !== isMuted) {\n if (isMuted) {\n this.eventCallback(Event.MUTE, {currentTime});\n } else {\n this.eventCallback(Event.UN_MUTE, {currentTime});\n }\n this.previousMutedValue = isMuted;\n }\n });\n\n this.listenToMediaElementEvent('seeking', () => {\n log(`seeking ${mediaElement.currentTime}`);\n const {currentTime} = mediaElement;\n\n this.eventCallback(Event.SEEK, {currentTime});\n });\n\n this.listenToMediaElementEvent('seeked', () => {\n log(`seeked ${mediaElement.currentTime}`);\n const {currentTime} = mediaElement;\n\n clearTimeout(this.bufferingTimeout);\n\n this.eventCallback(Event.SEEKED, {currentTime});\n });\n\n this.listenToMediaElementEvent('timeupdate', () => {\n const {currentTime} = mediaElement;\n\n this.isBuffering = false;\n this.isSeeking = false;\n\n // silence events if we have not yet intended play\n if (this.needsFirstPlayIntent) {\n return;\n }\n\n if (!this.isPaused) {\n // This check ensures that the 'TIMECHANGED' event is only triggered when there is a measurable\n // change in 'currentTime'.\n // On Tizen and WebOS platforms, we observed cases where the 'timeupdate' event was triggered without\n // any actual change in the 'currentTime'. During bufferings this caused buffering - playing loops\n // with over 900 samples sent under one minute. (https://bitmovin.atlassian.net/browse/AN-4546)\n const absoluteTimeDeltaInMs = Math.abs(currentTime - this.previousMediaTimeInSeconds) * 1000;\n if (absoluteTimeDeltaInMs > 0) {\n this.eventCallback(Event.TIMECHANGED, {currentTime});\n }\n }\n\n this.checkQualityLevelAttributes();\n\n this.checkSeeking();\n\n // We are doing this in case we can not rely\n // on the \"stalled\" or \"waiting\" events in a specific browser\n // and to detect intrinsinc paused states (when we do not get a paused event)\n // but the player is paused already before attach or is paused from initialization on.\n this.checkPlayheadProgress();\n\n this.previousMediaTimeInSeconds = currentTime;\n });\n\n // The stalled event is fired when the user agent is trying to fetch media data,\n // but data is unexpectedly not forthcoming.\n // https://developer.mozilla.org/en-US/docs/Web/Events/stalled\n this.listenToMediaElementEvent('stalled', () => {\n // this event doesn't indicate buffering by definition (interupted playback),\n // only that data throughput to playout buffers is not as high as expected\n // It happens on Chrome every once in a while as SourceBuffer's are not fed\n // as fast as the underlying native player may prefer (but it does not lead to\n // interruption).\n });\n\n // The waiting event is fired when playback has stopped because of a temporary lack of data.\n // See https://developer.mozilla.org/en-US/docs/Web/Events/waiting\n this.listenToMediaElementEvent('waiting', () => {\n // we check here for seeking because a programmatically seek where just\n // the currentTime has been changed does not trigger a proper seek event\n log(`waiting ${mediaElement.currentTime}`);\n this.checkSeeking();\n this.onBuffering();\n });\n }\n\n protected registerMediaElementErrorEvent(mediaElement: HTMLVideoElement) {\n this.listenToMediaElementEvent('error', () => {\n log(`error ${mediaElement.currentTime}`);\n const {currentTime, error} = mediaElement;\n this.eventCallback(Event.ERROR, {\n currentTime,\n // See https://developer.mozilla.org/en-US/docs/Web/API/MediaError\n code: error?.code ?? undefined,\n message: error?.message ?? undefined,\n originalError: error,\n data: {},\n });\n });\n }\n\n /**\n * Should only be calld when a mediaElement is attached\n */\n listenToMediaElementEvent(event: any, handler: any) {\n if (!this.mediaElement) {\n throw new Error('No media attached');\n }\n\n const boundHandler = handler.bind(this);\n\n this.mediaElementEventHandlers.push({event, handler: boundHandler});\n this.mediaElement.addEventListener(event, boundHandler, false);\n }\n\n onMaybeReady() {\n if (!this.needsReadyEvent || !this.mediaElement) {\n return;\n }\n\n this.needsReadyEvent = false;\n\n this.getCurrentPlaybackInfo();\n\n this._videoCompletionTracker.reset();\n this._videoCompletionTracker.setVideoDuration(this.mediaElement.duration);\n }\n\n /**\n * unregister the mediaElement and removes it from the class\n * will also remove all references to this adapter instance (listener, interceptor)\n */\n protected unregisterMediaElement() {\n if (!this.mediaElement) {\n throw new Error('No media element attached');\n }\n\n const mediaElement = this.mediaElement;\n\n this.mediaElementEventHandlers.forEach((item: {event: string; handler: any}) => {\n mediaElement.removeEventListener(item.event, item.handler);\n });\n\n // assign the original load func to the html video element remove references to `this`\n const originalLoadFunc = this.mediaElementOriginalLoadFn;\n if (isNotNullish(originalLoadFunc)) {\n mediaElement.load = originalLoadFunc;\n }\n\n this.mediaElement = undefined;\n this.mediaElementEventHandlers = [];\n this.mediaElementOriginalLoadFn = undefined;\n\n // we can clear `checkPlayheadProgress` timeout, as it is not needed anymore\n clearTimeout(this.bufferingTimeout);\n }\n\n registerWindowEvents() {\n this.windowEventTracker.addEventListener('beforeunload', this.onPageClose.bind(this));\n this.windowEventTracker.addEventListener('unload', this.onPageClose.bind(this));\n }\n\n onPageClose() {\n if (!this.onBeforeUnLoadEvent) {\n this.onBeforeUnLoadEvent = true;\n const mediaElement = this.mediaElement;\n let currentTime: number | undefined;\n if (isNotNullish(mediaElement)) {\n currentTime = mediaElement.currentTime;\n }\n this.eventCallback(Event.UNLOAD, {currentTime});\n }\n this.release();\n }\n\n checkQualityLevelAttributes(silent = false) {\n if (!this.mediaElement) {\n throw new Error('No media attached');\n }\n\n const mediaElement = this.mediaElement;\n\n const qualityLevelInfo = this.getCurrentQualityLevelInfo();\n if (!qualityLevelInfo) {\n return;\n }\n\n const {bitrate, width, height} = qualityLevelInfo;\n\n if (isNotNullish(bitrate)) {\n const eventData: QualityChangeEvent = {\n type: 'video',\n width,\n height,\n bitrate,\n currentTime: mediaElement.currentTime,\n };\n if (this.qualityChangeService.shouldAllowVideoQualityChange(bitrate)) {\n if (!silent) {\n this.eventCallback(Event.VIDEO_CHANGE, eventData);\n }\n }\n\n this.qualityChangeService.setVideoBitrate(bitrate);\n this.stateMachineCallbacks.updateSampleQualityInfo(eventData);\n }\n }\n\n getSelectedSubtitleFromMediaElement(mediaElement: any): SubtitleInfo | undefined {\n if (isNullish(mediaElement.textTracks)) {\n return undefined;\n }\n const textTrackList = mediaElement.textTracks;\n for (const attr of textTrackList) {\n if (isNotNullish(attr.mode) && attr.mode === 'showing') {\n const isSubtitleDisplayed = isNotNullish(attr.language) && attr.language.length > 0;\n return {\n enabled: isSubtitleDisplayed,\n language: isSubtitleDisplayed ? attr.language : undefined,\n };\n }\n }\n return {\n enabled: false,\n };\n }\n\n private onPaused(currentTime?: number) {\n if (this.isPaused) {\n return;\n }\n if (!this.mediaElement) {\n throw new Error('No media attached');\n }\n\n if (!currentTime) {\n currentTime = this.mediaElement.currentTime;\n }\n\n this.eventCallback(Event.PAUSE, {currentTime});\n\n this.isPaused = true;\n }\n\n private onBuffering() {\n if (!this.mediaElement) {\n throw new Error('No media attached');\n }\n const {currentTime} = this.mediaElement;\n\n // this handler may be called multiple times\n // for one actual buffering-event occuring so lets guard from\n // triggering this event redundantly.\n if (this.isBuffering || (this.isPaused && !this.isSeeking)) {\n return;\n }\n\n if (this.isSeeking) {\n this.eventCallback(Event.SEEK, {currentTime});\n } else {\n this.eventCallback(Event.START_BUFFERING, {currentTime});\n }\n this.isBuffering = true;\n }\n\n private checkPlayheadProgress() {\n if (!this.mediaElement) {\n throw new Error('No media attached');\n }\n const mediaElement = this.mediaElement;\n if (mediaElement.paused) {\n this.onPaused();\n }\n\n clearTimeout(this.bufferingTimeout);\n\n this.bufferingTimeout = setTimeout(() => {\n if (mediaElement.paused || (mediaElement.ended && !this.isBuffering)) {\n return;\n }\n\n // Calculate the playback time difference (delta) to later verify if playback progress\n // has halted or slowed down. The \"timeupdate\" event in HTML5 media elements is\n // not reliable, especially on slower devices like TVs or when the JavaScript\n // main thread is blocked. These scenarios can lead to delays in\n // \"timeupdate\" event emissions, even though playback progresses normally in\n // the video rendering pipeline.\n const playingDeltaInSeconds = mediaElement.currentTime - this.previousMediaTimeInSeconds;\n\n // Minimum playback progress threshold to avoid incorrectly reporting buffering events.\n // A 20% margin is applied in relation to the Timeout to account for timing inaccuracies\n // and short stalling events. This is a tradeoff between overreporting and underreporting\n // buffering events as well as preventing buffering -> playing loops. (https://bitmovin.atlassian.net/browse/AN-4572)\n const minPlayingDeltaThresholdInSeconds = (HTML5InternalAdapter.BUFFERING_TIMECHANGED_TIMEOUT_IN_MS / 1000) * 0.8;\n\n // If the playback progress is less than the threshold, treat it as buffering.\n if (playingDeltaInSeconds < minPlayingDeltaThresholdInSeconds) {\n this.onBuffering();\n }\n }, HTML5InternalAdapter.BUFFERING_TIMECHANGED_TIMEOUT_IN_MS);\n }\n\n /**\n * Method to detect seeking events on platforms where seeking events are not reliable\n * This code is currently called in timeUpdate event and waiting event.\n * - We can't rely on the `seeking` and 'seeked' events on certain platforms (Tizen, WebOs, Safari, etc.)\n * - Another limitation is that we cannot rely on the time update event to be fired in regular intervals\n * The time between two timeupdate events can be 1ms or 250ms for example. This code needs to handle this variance.\n */\n private checkSeeking() {\n if (!this.mediaElement) {\n throw new Error('No media attached');\n }\n const currentMediaTimeInSeconds = this.mediaElement.currentTime;\n\n // absolut difference of playback position compared with last call of method\n const playbackPositionDeltaInSeconds = Math.abs(currentMediaTimeInSeconds - this.previousMediaTimeInSeconds);\n\n // If the playback position has not changed more than 1 second we ignore it, to avoid\n // issuing of micro seeks. If not ignored the progressThreshold below might be too low, in order to\n // be reliable for such minor seeks. This is a tradeoff between overreporting and underreporting of seek events.\n if (playbackPositionDeltaInSeconds < 1) {\n this.previousClientTime = Date.now();\n return;\n }\n\n const currentClientTimeInMillis = Date.now();\n\n // Real time delta of method calls. How much time has passed since last call (in seconds)\n const clientTimeProgressInSeconds = (currentClientTimeInMillis - this.previousClientTime) / 1000;\n\n // we have to consider the playbackRate when calculating the threshold to trigger seeks\n // playbackRate of 3 progresses the playback triple the speed so the playbackPositionDelta\n // is also higher. This needs to be considered here\n // Adding 0.5 is a safety margin to avoid over reporting of seek events\n const thresholdModifier = this.mediaElement.playbackRate + 0.5;\n const progressThresholdInSeconds = clientTimeProgressInSeconds * thresholdModifier;\n\n // If the media time (current position of the playback) progresses much faster than real time\n // we consider this a time jump/seek\n if (playbackPositionDeltaInSeconds > progressThresholdInSeconds) {\n this.isSeeking = true;\n this.onPaused(this.previousMediaTimeInSeconds + clientTimeProgressInSeconds);\n }\n\n this.previousClientTime = Date.now();\n }\n}\n\nconst log = (msg: string) => {\n const msgTime = new Date().toISOString().substring(11);\n const prefix = `${msgTime}[HTML5InternalAdapter]`;\n const logMsg = `${prefix}: ${msg}`;\n logger.log(logMsg);\n};\n","import type {AdapterAPI, SessionMetadataAPI} from '../../api/AdapterAPI';\nimport {\n sanitizeSessionMetadataAudioLanguage,\n sanitizeSessionMetadataSubtitleEnabled,\n sanitizeSessionMetadataSubtitleLanguage,\n} from '../../api/adapterApiUtils';\nimport {Analytics} from '../../core/Analytics';\nimport type {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {logger} from '../../utils/Logger';\nimport {\n hasPlayerAlreadyBeenAugmented,\n isDefined,\n markPlayerInstanceAsAugmented,\n} from '../../utils/playerAugmentationUtils';\nimport {VERSION} from '../../utils/Version';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {HTMLVideoElementInternalAdapter} from './HTMLVideoElementInternalAdapter';\n\nexport class HTMLVideoElementAdapter implements AdapterAPI {\n private readonly internalAdapter: InternalAdapterAPI | undefined;\n private readonly analytics: Analytics | undefined;\n\n constructor(\n config: AnalyticsConfig,\n player: HTMLVideoElement,\n opts?: AnalyticsStateMachineOptions,\n // anonymous type for source metadata to not create any public named interface, until we stabilize the adapter API and provided typings\n sourceMetadata?: {\n audioCodec?: string;\n audioLanguage?: string;\n streamFormat?: string;\n videoCodec?: string;\n },\n ) {\n if (hasPlayerAlreadyBeenAugmented(player)) {\n logger.errorMessageToUser('Bitmovin Analytics is already hooked up to this player instance');\n return;\n }\n markPlayerInstanceAsAugmented(player);\n\n const sanitizedConfig = sanitizeAnalyticsConfig(config);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n return;\n }\n guardAgainstDuplicatedUserId(sanitizedConfig);\n\n this.internalAdapter = new HTMLVideoElementInternalAdapter(player, opts, sourceMetadata);\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n }\n\n get sessionMetadata() {\n const internalAdapter = this.internalAdapter as HTMLVideoElementInternalAdapter;\n\n return {\n setAudioLanguage(audioLanguage: string) {\n internalAdapter.sessionData.audioLanguage = sanitizeSessionMetadataAudioLanguage(audioLanguage);\n },\n setSubtitleEnabled(enabled: boolean) {\n internalAdapter.sessionData.subtitleEnabled = sanitizeSessionMetadataSubtitleEnabled(enabled);\n },\n setSubtitleLanguage(subtitleLanguage: string) {\n internalAdapter.sessionData.subtitleLanguage = sanitizeSessionMetadataSubtitleLanguage(subtitleLanguage);\n },\n } satisfies SessionMetadataAPI;\n }\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getCurrentImpressionId();\n }\n\n getUserId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getUserId();\n }\n\n setCustomData(values: CustomDataValues) {\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.setCustomData(values);\n }\n\n setCustomDataOnce(values: CustomDataValues) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.setCustomDataOnce(values);\n }\n\n sourceChange(\n config: AnalyticsConfig,\n /*\n * Custom implementation adds 2nd argument to support session data feature only on HTML5 for now.\n */\n sourceMetadata?: {\n audioCodec?: string;\n audioLanguage?: string;\n streamFormat?: string;\n videoCodec?: string;\n },\n ) {\n if (!isDefined(this.analytics)) return;\n if (!isDefined(this.internalAdapter)) return;\n\n this.analytics.sourceChange(config);\n\n const internalAdapter = this.internalAdapter as HTMLVideoElementInternalAdapter;\n internalAdapter.sessionData.streamFormat = sourceMetadata?.streamFormat;\n internalAdapter.sessionData.audioCodec = sourceMetadata?.audioCodec;\n internalAdapter.sessionData.videoCodec = sourceMetadata?.videoCodec;\n internalAdapter.sessionData.audioLanguage = sourceMetadata?.audioLanguage;\n }\n}\n","import {Player} from '../../enums/Player';\nimport {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport {PlaybackInfo} from '../../types/PlaybackInfo';\nimport {QualityLevelInfo} from '../../types/QualityLevelInfo';\nimport {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {HTML5InternalAdapter} from './HTML5InternalAdapter';\n\nexport class HTMLVideoElementInternalAdapter extends HTML5InternalAdapter implements InternalAdapterAPI {\n sessionData: InternalHTML5SessionData = {};\n\n constructor(\n mediaElement: HTMLVideoElement,\n opts?: AnalyticsStateMachineOptions,\n sourceMetadata?: {\n audioCodec?: string;\n audioLanguage?: string;\n streamFormat?: string;\n videoCodec?: string;\n },\n ) {\n super(mediaElement, opts);\n\n // source metadata\n this.sessionData.streamFormat = sourceMetadata?.streamFormat;\n this.sessionData.audioCodec = sourceMetadata?.audioCodec;\n this.sessionData.videoCodec = sourceMetadata?.videoCodec;\n this.sessionData.audioLanguage = sourceMetadata?.audioLanguage;\n }\n\n getPlayerVersion = () => {\n // player version is set by ingress for html5 player, thus we only return empty string here\n return '';\n };\n override getPlayerName = () => Player.HTML5;\n override getCurrentPlaybackInfo(): PlaybackInfo {\n const info = super.getCurrentPlaybackInfo();\n\n // source metadata\n info.streamFormat = this.sessionData.streamFormat ?? info.streamFormat;\n info.audioCodec = this.sessionData.audioCodec ?? info.audioCodec;\n info.videoCodec = this.sessionData.videoCodec ?? info.videoCodec;\n\n // language info\n info.subtitleEnabled = this.sessionData.subtitleEnabled ?? info.subtitleEnabled;\n // only set if enabled\n const subtitleLanguage = this.sessionData.subtitleLanguage ?? info.subtitleLanguage;\n info.subtitleLanguage = info.subtitleEnabled === true ? subtitleLanguage : undefined;\n\n info.audioLanguage = this.sessionData.audioLanguage ?? info.audioLanguage;\n\n return info;\n }\n\n override resetSourceRelatedState() {\n super.resetSourceRelatedState();\n this.sessionData = {};\n }\n\n override getStreamURL() {\n return this.mediaElement ? this.mediaElement.currentSrc : undefined;\n }\n\n getCurrentQualityLevelInfo(): QualityLevelInfo | null {\n return {\n bitrate: undefined,\n width: this.mediaElement ? this.mediaElement.videoWidth : undefined,\n height: this.mediaElement ? this.mediaElement.videoHeight : undefined,\n };\n }\n}\n\n/** Represents the internal html5-only adapter state, holding the source and session metadata. */\ninterface InternalHTML5SessionData {\n streamFormat?: string;\n audioCodec?: string;\n videoCodec?: string;\n audioLanguage?: string;\n subtitleEnabled?: boolean;\n subtitleLanguage?: string;\n}\n","export default class HTMLVideoElementStatisticsProvider {\n private previousTotalDroppedFrames = 0;\n\n constructor(private videoElement: HTMLVideoElement | undefined) {}\n\n getDroppedFrames(): number {\n if (this.videoElement == undefined) {\n return 0;\n }\n\n // this API is not supported in all browsers (especially on iOS Safari it was added quite late)\n // reference: https://developer.mozilla.org/en-US/docs/Web/API/VideoPlaybackQuality\n if (this.videoElement.getVideoPlaybackQuality === undefined) {\n return 0;\n }\n\n const droppedFrames = this.videoElement.getVideoPlaybackQuality().droppedVideoFrames;\n const currentDroppedFrames = droppedFrames - this.previousTotalDroppedFrames;\n this.previousTotalDroppedFrames = droppedFrames;\n return currentDroppedFrames;\n }\n reset() {\n this.previousTotalDroppedFrames = 0;\n }\n}\n","import {AnalyticsStateMachine} from '../../analyticsStateMachines/AnalyticsStateMachine';\nimport {EventDispatcher} from '../../core/EventDispatcher';\nimport QualityChangeService from '../../core/QualityChangeService';\nimport {SourceInfoFallbackService} from '../../core/SourceInfoFallbackService';\nimport {SsaiService} from '../../core/ssai/SsaiService';\nimport {Event, EventMap} from '../../enums/Event';\nimport {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport {CustomDataValues} from '../../types/CustomDataValues';\nimport {DownloadSpeedInfo} from '../../types/DownloadSpeedInfo';\nimport {DrmPerformanceInfo} from '../../types/DrmPerformanceInfo';\nimport type {CustomDataValuesEvent} from '../../types/EventData';\nimport {NoExtraProperties} from '../../types/NoExtraProperties';\nimport {SegmentInfo} from '../../types/SegmentInfo';\nimport type {SourceMetadata} from '../../types/SourceMetadata';\nimport {defaultStateMachineCallbacks, StateMachineCallbacks} from '../../types/StateMachineCallbacks';\nimport {getGlobalScreenDimensions} from '../../utils/globalScopeUtils';\nimport {logger} from '../../utils/Logger';\nimport {getCurrentTimestamp} from '../../utils/Utils';\nimport {WindowEventTracker} from '../../utils/WindowEventTracker';\n\nimport {EventCallbackDispatcher} from './EventCallbackDispatcher';\n\nexport abstract class InternalAdapter implements EventCallbackDispatcher {\n readonly onLicenseKeyReceived: EventDispatcher<{licenseKey: string}> = new EventDispatcher();\n readonly onLicenseCallFailed: EventDispatcher<any> = new EventDispatcher();\n readonly qualityChangeService: QualityChangeService = new QualityChangeService();\n readonly ssaiService = new SsaiService();\n readonly stateMachineCallbacks: StateMachineCallbacks = {...defaultStateMachineCallbacks};\n\n protected stateMachine!: AnalyticsStateMachine;\n protected opts: AnalyticsStateMachineOptions;\n protected sourceInfoFallbackService: SourceInfoFallbackService = new SourceInfoFallbackService();\n protected drmPerformanceInfo: DrmPerformanceInfo | undefined = undefined;\n protected readonly windowEventTracker: WindowEventTracker = new WindowEventTracker();\n\n protected abstract get currentTime(): number;\n\n constructor(opts?: AnalyticsStateMachineOptions) {\n if (!opts) {\n opts = {\n starttime: undefined,\n };\n }\n if (!opts.starttime) {\n opts.starttime = getCurrentTimestamp();\n }\n\n this.opts = opts;\n }\n\n release() {\n this.stateMachine.resetIntervals();\n this.stateMachineCallbacks.release();\n this.resetSourceRelatedState();\n this.windowEventTracker.release();\n }\n\n eventCallback<StateMachineEvent extends keyof EventMap, StateMachineEventData extends EventMap[StateMachineEvent]>(\n event: StateMachineEvent,\n eventData: NoExtraProperties<EventMap[StateMachineEvent], StateMachineEventData>,\n eventTimestamp: number = Date.now(),\n ) {\n eventData = eventData || {};\n if (!this.stateMachine) {\n logger.log(\"Bitmovin Analytics: StateMachine isn't ready yet\");\n } else {\n this.stateMachine.callEvent(event, eventData, eventTimestamp);\n }\n }\n\n getCommonPlaybackInfo() {\n const dimensions = getGlobalScreenDimensions();\n\n return {\n screenHeight: dimensions?.height,\n screenWidth: dimensions?.width,\n };\n }\n\n getDrmPerformanceInfo(): DrmPerformanceInfo | undefined {\n return undefined;\n }\n\n getSegmentInfo(): SegmentInfo[] {\n return [];\n }\n\n getDownloadSpeedInfo(): DownloadSpeedInfo {\n return {\n segmentsDownloadCount: 0,\n segmentsDownloadSize: 0,\n segmentsDownloadTime: 0,\n avgDownloadSpeed: 0,\n minDownloadSpeed: 0,\n maxDownloadSpeed: 0,\n avgTimeToFirstByte: 0,\n };\n }\n\n resetDownloadSpeedInfoMeasures(): void {\n // noop by default\n }\n\n setCustomData(values: CustomDataValues) {\n const previousState = this.stateMachine.currentState;\n const eventData: CustomDataValuesEvent = {customDataValues: values, currentTime: this.currentTime};\n\n if (\n this.stateMachine.currentState &&\n (this.stateMachine.currentState === 'PAUSE' || this.stateMachine.currentState === 'PLAYING')\n ) {\n // If we are in State.PAUSE or State.PLAYING, we want to make \"a cut\" of the current state\n // to trigger sample sending with current custom data values.\n this.eventCallback(Event.CUSTOM_DATA_CHANGE, {currentTime: this.currentTime});\n // Then we have to call this \"previous state\" event to return back\n // to the previous state and to set new custom data values.\n // !! here we relay on the fact that we have `PAUSE` and `PLAYING` events with the same name as the states above !!\n this.eventCallback(Event[previousState], eventData);\n }\n // ... else, for any other states, we don't care, and we will just set new custom data values asap, so they will\n // be sent with the upcoming sample\n else {\n this.stateMachineCallbacks.customdatachange(undefined, undefined, eventData);\n }\n }\n\n sourceChange(analyticsConfig: AnalyticsConfig): void {\n this.eventCallback(Event.MANUAL_SOURCE_CHANGE, {currentTime: this.currentTime, config: analyticsConfig});\n }\n\n resetSourceRelatedState(): void {\n this.sourceInfoFallbackService.reset();\n this.drmPerformanceInfo = undefined;\n }\n\n programChange(sourceMetadata: SourceMetadata): void {\n const isSsaiActive = this.ssaiService.isInActiveState();\n this.stateMachine.programChange(this.currentTime, isSsaiActive, sourceMetadata);\n }\n}\n","import {AdBreakInfo} from '../../../types/ads/AdBreakInfo';\nimport {AdInfo} from '../../../types/ads/AdInfo';\n\nexport class AdCallbacks {\n onAdStarted = (_ad: AdInfo): void => undefined;\n onAdFinished = (_ad: AdInfo): void => undefined;\n onAdBreakStarted = (_adBreak: AdBreakInfo): void => undefined;\n onAdBreakFinished = (_adBreak: AdBreakInfo): void => undefined;\n onAdClicked = (_event: AdClickedPayload): void => undefined;\n onAdError = (_event: AdErrorPayload): void => undefined;\n onAdManifestLoaded = (_event: AdManifestLoadedPayload): void => undefined;\n onAdQuartile = (_event: AdQuartilePayload): void => undefined;\n onAdSkipped = (_ad: AdInfo): void => undefined;\n onPlay = (): void => undefined;\n onPause = (): void => undefined;\n onBeforeUnload = (): void => undefined;\n}\n\nexport interface AdModuleAPI {\n readonly adCallbacks: AdCallbacks;\n isLinearAdActive: () => boolean;\n getContainer: () => HTMLElement;\n getAdModuleInfo: () => {name?: string; version?: string};\n currentTime: () => number;\n getAutoPlay(): boolean;\n}\n\nexport interface AdClickedPayload {\n clickThroughUrl?: string;\n}\n\nexport interface AdErrorPayload {\n code?: number;\n message?: string;\n adBreakInfo?: AdBreakInfo;\n activeAdId?: string;\n}\n\nexport interface AdManifestLoadedPayload {\n adBreakInfo?: AdBreakInfo;\n manifestDownloadTime?: number;\n isVmap: boolean;\n}\n\nexport enum AdQuartile {\n FIRST_QUARTILE = 'firstQuartile',\n MIDPOINT = 'midpoint',\n THIRD_QUARTILE = 'thirdQuartile',\n}\n\nexport interface AdQuartilePayload {\n quartile: AdQuartile;\n}\n","import type {AdapterAPI} from '../../api/AdapterAPI';\nimport {Analytics} from '../../core/Analytics';\nimport {Event} from '../../enums/Event';\nimport type {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {logger} from '../../utils/Logger';\nimport {\n hasPlayerAlreadyBeenAugmented,\n isDefined,\n markPlayerInstanceAsAugmented,\n} from '../../utils/playerAugmentationUtils';\nimport {tryJSONStringify} from '../../utils/Utils';\nimport {VERSION} from '../../utils/Version';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {ShakaInternalAdapter} from './ShakaInternalAdapter';\n\nexport class ShakaAdapter implements AdapterAPI {\n private readonly internalAdapter: InternalAdapterAPI | undefined;\n private readonly analytics: Analytics | undefined;\n\n constructor(config: AnalyticsConfig, player: any, opts?: AnalyticsStateMachineOptions) {\n if (hasPlayerAlreadyBeenAugmented(player)) {\n logger.errorMessageToUser('Bitmovin Analytics is already hooked up to this player instance');\n return;\n }\n markPlayerInstanceAsAugmented(player);\n\n const sanitizedConfig = sanitizeAnalyticsConfig(config);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n return;\n }\n\n guardAgainstDuplicatedUserId(sanitizedConfig);\n\n this.internalAdapter = new ShakaInternalAdapter(player, opts);\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n this.wrapPlayerLoad(player);\n }\n\n // The Shaka player's `load()` method does not trigger error events for exceptions thrown while loading the manifest.\n // Therefore, we wrap this method and catch exceptions and forward them to analytics.\n // TODO [AN-4149]: this needs to be reevaluated, since the cypress test with a none existing manifest is not working\n private wrapPlayerLoad(player: any) {\n // Check if `player.load` can be overwritten\n const playerPrototype = Object.getPrototypeOf(player); // in the case of the player proxy, the load method is in the prototype\n const loadPropertyDescriptor =\n Object.getOwnPropertyDescriptor(player, 'load') ?? Object.getOwnPropertyDescriptor(playerPrototype, 'load');\n if (loadPropertyDescriptor?.writable !== true && loadPropertyDescriptor?.set === undefined) {\n // The player instance might be a proxy (e.g., from Shaka UI Library), making `player.load` a getter-only accessor.\n // This prevents us to override `load` function with our error interception logic.\n logger.errorMessageToUser(\n 'Bitmovin Analytics is unable to intercept player.load method. The provided Shaka player instance appears to be a ' +\n 'proxy object (e.g. created via Shaka UI Library). Ensure you provide the local player instance instead.',\n );\n return;\n }\n\n const originalLoad = player.load;\n /**\n * Avoid passing `this` (the adapter reference) to an interceptor or its error handler.\n *\n * Reason:\n * Passing `this` can lead to memory leaks. When that shaka player is destroyed, it does not clean up the `player.load`\n * method, which we intercept. This leaves the old adapter and interceptor still referenced, even though the shaka player\n * has been destroyed. If a new adapter is then created for the same shaka player, a new interceptor will also be created.\n * This new interceptor will wrap the `player.load` method again, which was already wrapped by the previous adapter,\n * leading to unnecessary memory usage and potential memory leaks.\n */\n const thatInternalAdapter = this.internalAdapter as ShakaInternalAdapter;\n\n player.load = (...args) =>\n new Promise((resolve, reject) => {\n originalLoad\n .apply(player, args)\n .then((result) => resolve(result))\n .catch((error) => {\n const eventObject = {\n currentTime: 0,\n // See https://github.com/shaka-project/shaka-player/blob/main/lib/util/error.js\n code: error?.code ?? undefined,\n message: tryJSONStringify({category: error?.category, severity: error?.severity}),\n data: {additionalData: tryJSONStringify(error?.data)},\n originalError: error,\n };\n\n thatInternalAdapter.eventCallback(Event.ERROR, eventObject);\n\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n reject(error);\n });\n });\n }\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getCurrentImpressionId();\n }\n\n getUserId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getUserId();\n }\n\n setCustomData(values: CustomDataValues) {\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.setCustomData(values);\n }\n\n setCustomDataOnce(values: CustomDataValues) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.setCustomDataOnce(values);\n }\n\n sourceChange(config: AnalyticsConfig) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.sourceChange(config);\n }\n}\n","import type {Analytics} from '../../core/Analytics';\nimport {Event} from '../../enums/Event';\nimport {Player} from '../../enums/Player';\nimport {StreamTypes} from '../../enums/StreamTypes';\nimport {ErrorDetailBackend} from '../../features/errordetails/ErrorDetailBackend';\nimport {ErrorDetailTracking} from '../../features/errordetails/ErrorDetailTracking';\nimport type {Feature} from '../../features/Feature';\nimport type {FeatureConfig} from '../../features/FeatureConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CodecInfo} from '../../types/CodecInfo';\nimport type {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport type {PlaybackInfo} from '../../types/PlaybackInfo';\nimport type {QualityLevelInfo} from '../../types/QualityLevelInfo';\nimport {logger} from '../../utils/Logger';\nimport {isNotNullish, isNullish, tryJSONStringify} from '../../utils/Utils';\nimport {HTML5InternalAdapter} from '../html5/HTML5InternalAdapter';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {ShakaErrorEvent, ShakaPlayerEvent} from './shakaPlayerTypes';\n\nexport class ShakaInternalAdapter extends HTML5InternalAdapter implements InternalAdapterAPI {\n private readonly player: any;\n\n constructor(player: any, opts?: AnalyticsStateMachineOptions) {\n super(player.getMediaElement(), opts);\n this.player = player;\n }\n\n override initialize(analytics: Analytics): Array<Feature<FeatureConfigContainer, FeatureConfig>> {\n super.initialize(analytics);\n let videoElement: HTMLVideoElement | undefined;\n try {\n // returns null if content was not loaded yet\n // @see https://shaka-player-demo.appspot.com/docs/api/shaka.Player.html#getMediaElement\n videoElement = this.player.getMediaElement();\n } catch (_e) {\n // no action needed, because we will throw error later in code, because of video element null check\n }\n\n if (isNotNullish(videoElement)) {\n this.setMediaElement(videoElement);\n } else {\n // if we don't have video/media element from shaka player during initialization (shaka behaviour:\n // it has not loaded content yet), we need to wait for the `media-source` state change event and\n // then try to get the media element.\n const handleOnStateChangeAndSetMediaElement = (event: {state: string}) => {\n if (event.state === 'media-source') {\n try {\n this.player.removeEventListener(ShakaPlayerEvent.ONSTATECHANGE, handleOnStateChangeAndSetMediaElement);\n this.setMediaElement(this.player.getMediaElement());\n } catch (e) {\n logger.errorMessageToUser(\n 'Something went wrong while getting underlying HTMLVideoElement. Not possible to attach adapter and initialize Bitmovin Analytics. Error: ',\n e,\n );\n this.release();\n }\n }\n };\n\n this.player.addEventListener(ShakaPlayerEvent.ONSTATECHANGE, handleOnStateChangeAndSetMediaElement);\n }\n\n // With shaka a qualitychange only triggers a rebuffering, so to catch a qualitychange in time, we need to check qualityinfo on bufferings as well.\n this.player.addEventListener(ShakaPlayerEvent.BUFFERING, (_) => {\n this.checkQualityLevelAttributes();\n });\n\n this.player.addEventListener(ShakaPlayerEvent.ONSTATECHANGE, (event: {state: string}) => {\n if (event.state === 'detach') {\n // Detach the player from the current media element. Leaves the player in a state where\n // it cannot play media, until it has been attached to something else.\n this.eventCallback(Event.UNLOAD, {});\n this.release();\n }\n });\n\n const errorDetailTracking = new ErrorDetailTracking(\n analytics.errorDetailTrackingSettingsProvider,\n new ErrorDetailBackend(analytics.errorDetailTrackingSettingsProvider.collectorConfig),\n [analytics.errorDetailSubscribable],\n undefined,\n );\n return [errorDetailTracking];\n }\n\n override getPlayerName = () => Player.SHAKA;\n\n getPlayerVersion = () => this.player.constructor.version;\n\n override isLive = () => {\n return this.player ? this.player.isLive() : undefined;\n };\n\n override getCurrentPlaybackInfo(): PlaybackInfo {\n const playbackInfo: PlaybackInfo = {\n ...super.getCurrentPlaybackInfo(),\n };\n\n const codecInfo = getShakaCodecInfo(this.player);\n this.sourceInfoFallbackService.applyAndStoreCodecInfo(playbackInfo, codecInfo);\n\n return playbackInfo;\n }\n\n override getStreamType(): StreamTypes | undefined {\n return getShakaStreamFormat(this.player);\n }\n\n override getStreamURL() {\n return this.player ? this.player.getAssetUri() : null;\n }\n\n override getCurrentQualityLevelInfo(): QualityLevelInfo | null {\n const variantTracks = this.player.getVariantTracks();\n\n const activeVideoTrack = variantTracks\n .filter((track: any) => track.active)\n .filter((track: any) => track.videoCodec || track.videoId !== undefined)[0];\n\n if (!activeVideoTrack) {\n // can only happen for audio-only streams\n return null;\n }\n\n const bitrate = activeVideoTrack.videoBandwidth || activeVideoTrack.bandwidth;\n const width = activeVideoTrack.width;\n const height = activeVideoTrack.height;\n\n return {\n bitrate: bitrate,\n width: width,\n height: height,\n };\n }\n\n /** override html5 adapter function to not listen to native media element \"error\" event,\n * but instead use shaka player \"error\" event\n */\n override registerMediaElementErrorEvent = (_: HTMLVideoElement) => {\n this.player.addEventListener(ShakaPlayerEvent.ERROR, (event: {detail: ShakaErrorEvent}) => {\n this.eventCallback(Event.ERROR, {\n currentTime: this.mediaElement?.currentTime ?? 0,\n code: event.detail?.code ?? undefined,\n message: event.detail?.message ?? undefined,\n originalError: event,\n data: {\n additionalData: tryJSONStringify(event.detail),\n exceptionMessage: event.detail?.message ?? undefined,\n exceptionStacktrace: event.detail?.stack?.split('\\n') ?? undefined,\n },\n });\n });\n };\n}\n\nexport const getShakaCodecInfo = (player: any): CodecInfo | undefined => {\n const variantTracks = player.getVariantTracks();\n const activeTrack = variantTracks.find((track: any) => track.active);\n\n return {\n videoCodec: activeTrack?.videoCodec,\n audioCodec: activeTrack?.audioCodec,\n };\n};\n\nexport const getShakaStreamFormat = (player: any): StreamTypes | undefined => {\n if (!player) {\n return undefined;\n }\n\n // `getManifestType` is only available in shaka v4.4.0 and later (we need to support 4.0.0)\n const manifestType = player.getManifestType?.()?.toLowerCase();\n\n if (manifestType === StreamTypes.dash) {\n return StreamTypes.dash;\n } else if (manifestType === StreamTypes.hls) {\n return StreamTypes.hls;\n }\n\n // https://shaka-player-demo.appspot.com/docs/api/shaka.Player.html#.LoadMode\n const LOAD_MODE_SRC_EQUALS = 3;\n\n // Fallback to progressive if no manifest type is available.\n // In order to avoid over-reporting of progressive when the source is not loaded yet\n // (where getManifestType is also null similar to when a progressive source is used)\n // we check that the load mode is SRC_EQUALS which indicates native player usage\n // and make sure that the asset is already loaded through check if the uri is available\n if (isNullish(manifestType) && player.getLoadMode() === LOAD_MODE_SRC_EQUALS && isNotNullish(player.getAssetUri())) {\n return StreamTypes.prog;\n }\n\n return undefined;\n};\n","/*!\n * This file was created to avoid \"values imports\" (constants/enums/classes/etc.) from the `shaka-player@4.16.0`\n * to avoid including the whole package in our distribution code.\n *\n * Because `shaka-player` npm package is not installed, because it has bad TypeScript definitions\n * @see https://github.com/shaka-project/shaka-player/issues/6442)\n * - we can't use \"type imports\" (`import type {}`),\n * - we can't cover copies of the library values with unit tests\n *\n * Shaka discussion about migration to TypeScript\n * @see https://github.com/shaka-project/shaka-player/issues/8262\n */\n\nexport const ShakaPlayerEvent = {\n /**\n * Fired when the player unloads or fails to load. Used by the Cast receiver to determine idle state.\n * @see https://shaka-player-demo.appspot.com/docs/api/shaka.Player.html#.event:UnloadingEvent\n */\n UNLOADING: 'unloading',\n /**\n * Fired when the player changes load states.\n * @see https://shaka-player-demo.appspot.com/docs/api/shaka.Player.html#.event:StateChangeEvent\n */\n ONSTATECHANGE: 'onstatechange',\n /**\n * Fired when player state is changed.\n * @see https://shaka-player-demo.appspot.com/docs/api/shaka.Player.html#.event:StateChanged\n */\n STATECHANGED: 'statechanged',\n /**\n * Fired when the player's buffering state changes.\n * @see https://shaka-player-demo.appspot.com/docs/api/shaka.Player.html#.event:BufferingEvent\n */\n BUFFERING: 'buffering',\n /**\n * Fired when a playback error occurs.\n * @see https://shaka-player-demo.appspot.com/docs/api/shaka.Player.html#.event:ErrorEvent\n */\n ERROR: 'error',\n} as const;\n\n/**\n * @see https://shaka-player-demo.appspot.com/docs/api/shaka.util.Error.html\n */\nexport type ShakaErrorEvent = Error & {\n category: number;\n code: number;\n severity: number;\n};\n","import {HttpRequestType} from '../../features/httprequesttracking/HttpRequestType';\nimport type {OnDownloadFinishedEventObject} from '../../features/httprequesttracking/OnDownloadFinishedEventObject';\nimport type {DrmPerformanceInfo} from '../../types/DrmPerformanceInfo';\nimport {isNotNullish} from '../../utils/Utils';\n\n/**\n * Service that subscribes to network download events and tracks\n * DRM license acquisition performance.\n *\n * Only the first successful DRM license request is tracked,\n * capturing the DRM type and load time.\n */\nexport class DrmPerformanceService {\n private drmPerformanceInfo: DrmPerformanceInfo | undefined = undefined;\n\n /**\n * Returns the captured DRM performance information.\n * @returns DrmPerformanceInfo if a license was tracked, undefined otherwise\n */\n getInfo(): DrmPerformanceInfo | undefined {\n return this.drmPerformanceInfo;\n }\n\n /**\n * Resets the service state for a new playback session.\n * Clears tracked DRM info and allows tracking of the next license request.\n */\n reset(): void {\n this.drmPerformanceInfo = undefined;\n }\n\n onDownloadFinished = (event: OnDownloadFinishedEventObject): void => {\n const httpRequest = event.httpRequest;\n\n // Only track successful requests\n if (!httpRequest.success) {\n return;\n }\n\n // Only track the first DRM license request (not certificates)\n if (isNotNullish(this.drmPerformanceInfo) || !isDrmLicenseType(httpRequest.type)) {\n return;\n }\n\n const drmType = extractDrmType(httpRequest.type);\n this.drmPerformanceInfo = {\n drmType: drmType,\n drmLoadTime: httpRequest.downloadTime,\n };\n };\n}\n\nexport function isDrmLicenseType(type: HttpRequestType): boolean {\n return (\n type === HttpRequestType.DRM_LICENSE_WIDEVINE ||\n type === HttpRequestType.DRM_LICENSE_FAIRPLAY ||\n type === HttpRequestType.DRM_LICENSE_PLAYREADY ||\n type === HttpRequestType.DRM_LICENSE_CLEARKEY\n );\n}\n\nexport function extractDrmType(requestType: HttpRequestType): string {\n // Extract 'widevine' from 'drm/license/widevine'\n const match = requestType.match(/drm\\/license\\/(.+)/);\n return match ? match[1] : 'unknown';\n}\n","import type {\n AdapterAPI,\n SsaiAdBreakMetadata,\n SsaiAdMetadata,\n SsaiAdQuartile,\n SsaiAdQuartileMetadata,\n SsaiApi,\n} from '../../api/AdapterAPI';\nimport {Analytics} from '../../core/Analytics';\nimport {\n hasValidSsaiAdBreakMetadataStructure,\n hasValidSsaiAdMetadataStructure,\n hasValidSsaiAdQuartileStructure,\n sanitizeSsaiAdQuartileMetadata,\n simplySanitizeSsaiAdBreakMetadata,\n simplySanitizeSsaiAdMetadata,\n} from '../../core/ssai/ssaiApiUtils';\nimport type {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {hasValidSourceMetadataStructure, sanitizeSourceMetadata} from '../../types/SourceMetadata';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {logger} from '../../utils/Logger';\nimport {\n hasPlayerAlreadyBeenAugmented,\n isDefined,\n markPlayerInstanceAsAugmented,\n} from '../../utils/playerAugmentationUtils';\nimport {VERSION} from '../../utils/Version';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {THEOplayerInternalAdapter} from './THEOplayerInternalAdapter';\n\nexport class THEOplayerAdapter implements AdapterAPI {\n private readonly internalAdapter: InternalAdapterAPI | undefined;\n private readonly analytics: Analytics | undefined;\n\n constructor(config: AnalyticsConfig, player: any, opts?: AnalyticsStateMachineOptions) {\n if (hasPlayerAlreadyBeenAugmented(player.element)) {\n logger.errorMessageToUser('Bitmovin Analytics is already hooked up to this player instance');\n return;\n }\n // Since the THEOplayer instance is a frozen object, we can't directly add properties to it.\n // To work around this, we add the augmentation marker to the player's HTML element.\n markPlayerInstanceAsAugmented(player.element);\n\n const sanitizedConfig = sanitizeAnalyticsConfig(config);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n return;\n }\n\n guardAgainstDuplicatedUserId(sanitizedConfig);\n\n this.internalAdapter = new THEOplayerInternalAdapter(player, opts);\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n }\n\n readonly ssai: SsaiApi = {\n adBreakStart: (adBreakMetadata?: SsaiAdBreakMetadata) => {\n if (!isDefined(this.internalAdapter)) return;\n\n if (!hasValidSsaiAdBreakMetadataStructure(adBreakMetadata)) {\n // if we don't have valid ad break metadata, we don't want to proceed and use SSAI API\n return;\n }\n\n const sanitizedAdBreakMetadata = simplySanitizeSsaiAdBreakMetadata(adBreakMetadata);\n\n this.internalAdapter.ssaiService.adBreakStart(sanitizedAdBreakMetadata);\n },\n\n adStart: (adMetadata?: SsaiAdMetadata) => {\n if (!isDefined(this.analytics)) return;\n if (!isDefined(this.internalAdapter)) return;\n\n if (!hasValidSsaiAdMetadataStructure(adMetadata)) {\n // if we don't have valid ad metadata, we don't want to proceed and use SSAI API\n return;\n }\n\n const sanitizedAdMetadata = simplySanitizeSsaiAdMetadata(adMetadata);\n\n this.internalAdapter.ssaiService.adStart(sanitizedAdMetadata);\n // we need to call this here to revert the customData values to the values before the adBreak\n // this is mainly needed to have clear transitions between ads, and we don't\n // copy over customData values from the first ad into the second ad\n // the adMetadata is applied after this call in the manipulate method when a sample is sent\n // it is a bit of a hack, but it is necessary right now due to the way how samples are created\n this.analytics.setConfigParameters();\n this.analytics.setAutoDetectedDeviceInformation();\n },\n\n adQuartileFinished: (adQuartile: SsaiAdQuartile, adQuartileMetadata?: SsaiAdQuartileMetadata) => {\n if (!isDefined(this.analytics)) return;\n if (!isDefined(this.internalAdapter)) return;\n\n if (!hasValidSsaiAdQuartileStructure(adQuartile)) {\n // if we don't have valid ad quartile, we don't want to proceed and use SSAI API\n return;\n }\n\n const sanitizedSsaiAdQuartileMetadata = sanitizeSsaiAdQuartileMetadata(adQuartileMetadata);\n\n this.internalAdapter.ssaiService.adQuartileFinished(adQuartile, sanitizedSsaiAdQuartileMetadata);\n },\n\n adBreakEnd: () => {\n if (!isDefined(this.analytics)) return;\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.ssaiService.adBreakEnd();\n // we need to call this here to revert the customData values to the values we had before the ad\n this.analytics.setConfigParameters();\n this.analytics.setAutoDetectedDeviceInformation();\n },\n };\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getCurrentImpressionId();\n }\n\n getUserId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getUserId();\n }\n\n setCustomData(values: CustomDataValues) {\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.setCustomData(values);\n }\n\n setCustomDataOnce(values: CustomDataValues) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.setCustomDataOnce(values);\n }\n\n sourceChange(config: AnalyticsConfig) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.sourceChange(config);\n }\n\n programChange(sourceMetadata: {\n /* eslint-disable perfectionist/sort-object-types */\n title?: string;\n videoId?: string;\n cdnProvider?: string;\n path?: string;\n isLive?: boolean;\n customData?: CustomDataValues;\n /* eslint-enable perfectionist/sort-object-types */\n }) {\n if (!hasValidSourceMetadataStructure(sourceMetadata)) {\n // if we don't have valid source metadata, we don't want to proceed\n return;\n }\n\n const sanitizedSourceMetadata = sanitizeSourceMetadata(sourceMetadata);\n\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.programChange(sanitizedSourceMetadata);\n }\n}\n","import type {ChromelessPlayer, MediaTrack, QualityEvent, TypedSource, VideoQuality} from 'theoplayer';\n\nimport {THEOplayerAnalyticsStateMachine} from '../../analyticsStateMachines/THEOplayerAnalyticsStateMachine';\nimport type {Analytics} from '../../core/Analytics';\nimport {DownloadSpeedMeter} from '../../core/DownloadSpeedMeter';\nimport {HeartbeatService} from '../../core/HeartbeatService';\nimport {CastTech} from '../../enums/CastTech';\nimport {Event, EventMap} from '../../enums/Event';\nimport {Player as PlayerEnum} from '../../enums/Player';\nimport {PlayerSize} from '../../enums/PlayerSize';\nimport {getStreamTypeFromMIMEType, getStreamTypesFromURL, StreamTypes} from '../../enums/StreamTypes';\nimport {ErrorDetailBackend} from '../../features/errordetails/ErrorDetailBackend';\nimport {ErrorDetailTracking} from '../../features/errordetails/ErrorDetailTracking';\nimport type {Feature} from '../../features/Feature';\nimport type {FeatureConfig} from '../../features/FeatureConfig';\nimport {HttpRequestTracking} from '../../features/httprequesttracking/HttpRequestTracking';\nimport {HttpRequestType} from '../../features/httprequesttracking/HttpRequestType';\nimport type {OnDownloadFinishedEventObject} from '../../features/httprequesttracking/OnDownloadFinishedEventObject';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {DownloadSpeedInfo} from '../../types/DownloadSpeedInfo';\nimport type {DrmPerformanceInfo} from '../../types/DrmPerformanceInfo';\nimport type {QualityChangeEvent} from '../../types/EventData';\nimport type {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport type {NoExtraProperties} from '../../types/NoExtraProperties';\nimport {buildPlaybackInfoStreamTypeFields, normalizeVideoDuration, PlaybackInfo} from '../../types/PlaybackInfo';\nimport type {SpeedMeasurement} from '../../types/SpeedMeasurement';\nimport {getGlobalTheoPlayerVersion} from '../../utils/globalScopeUtils';\nimport {isNumber} from '../../utils/numberUtils';\nimport {isBlank, isValidString} from '../../utils/stringUtils';\nimport {isNotNullish, isNullish, tryJSONStringify} from '../../utils/Utils';\nimport {InternalAdapter} from '../internal/InternalAdapter';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {THEOplayerAdModule} from './ads/THEOplayerAdModule';\nimport {DrmPerformanceService} from './DrmPerformanceService';\nimport {DelayedEventDispatcher} from './playback/DelayedEventDispatcher';\nimport {THEOplayerNetworkInterceptor} from './THEOplayerNetworkInterceptor';\n\nexport class THEOplayerInternalAdapter extends InternalAdapter implements InternalAdapterAPI {\n private readonly player: ChromelessPlayer;\n private readonly networkInterceptor: THEOplayerNetworkInterceptor;\n private readonly speedMeter: DownloadSpeedMeter = new DownloadSpeedMeter();\n private readonly delayedEventDispatcher: DelayedEventDispatcher = DelayedEventDispatcher.create();\n private readonly drmPerformanceService: DrmPerformanceService = new DrmPerformanceService();\n private _adModule: THEOplayerAdModule | undefined;\n\n /** Boolean flag to prevent multiple calls of the {@link Event.UNLOAD} event */\n private onBeforeUnLoadEvent = false;\n\n private lastTrackedCurrentTime: number | undefined;\n\n private currentSource: TypedSource | undefined;\n\n private videoTrackListeners: Map<MediaTrack, (event: QualityEvent<'activequalitychanged'>) => void> = new Map();\n private audioTrackListeners: Map<MediaTrack, (event: QualityEvent<'activequalitychanged'>) => void> = new Map();\n\n constructor(player: ChromelessPlayer, opts?: AnalyticsStateMachineOptions) {\n super(opts);\n this.player = player;\n this.networkInterceptor = new THEOplayerNetworkInterceptor(player);\n this.networkInterceptor.subscribe((event) => {\n // SpeedMeter\n const speedMeasurement = createSpeedMeasurementFromEvent(event);\n if (isNotNullish(speedMeasurement)) {\n this.speedMeter.addMeasurement(speedMeasurement);\n }\n\n // DrmPerformanceService\n this.drmPerformanceService.onDownloadFinished(event);\n });\n\n const playingHeartbeatService = new HeartbeatService(() => this.currentTime);\n this.stateMachine = new THEOplayerAnalyticsStateMachine(\n this.stateMachineCallbacks,\n playingHeartbeatService,\n this.opts,\n );\n playingHeartbeatService.setListener(this.stateMachine);\n\n this.player = player;\n }\n\n get adModule(): THEOplayerAdModule | undefined {\n return this._adModule;\n }\n\n initialize(analytics: Analytics): Array<Feature<FeatureConfigContainer, FeatureConfig>> {\n this.registerEventListeners();\n\n if (this.player.ads) {\n this._adModule = new THEOplayerAdModule(this.player, this.windowEventTracker);\n }\n\n this.ssaiService.activate({\n getPlayerCurrentTime: () => this.currentTime,\n reportEngagementInteraction: (ssaiEngagementInteractionData) => {\n analytics.sendSsaiEngagementAdSample(ssaiEngagementInteractionData);\n },\n reportPlaybackInteraction: (timestamp: number, playerCurrentTime: number) => {\n // Because ssai playback interaction can happen before Ssai Service is active (e.g. first ssai startAd call),\n // we need to manually mark sample as triggered by ssai\n //\n // This is also including the last sample marking, before a ssai ad block (due to ssai being spiky by design)\n this.stateMachine.sendPlayingSample(timestamp, playerCurrentTime, true);\n },\n });\n\n const httpRequestTracking = new HttpRequestTracking([this.networkInterceptor]);\n const errorDetailTracking = new ErrorDetailTracking(\n analytics.errorDetailTrackingSettingsProvider,\n new ErrorDetailBackend(analytics.errorDetailTrackingSettingsProvider.collectorConfig),\n [analytics.errorDetailSubscribable],\n httpRequestTracking,\n );\n\n this.eventCallback(Event.READY, {currentTime: this.currentTime});\n\n return [errorDetailTracking];\n }\n\n getPlayerVersion(): string {\n // try to get the version from the global `window.THEOplayer` (if npm module is used, it doesn't exist)\n const windowTHEOplayerVersion = getGlobalTheoPlayerVersion();\n if (isValidString(windowTHEOplayerVersion) && !isBlank(windowTHEOplayerVersion)) {\n return windowTHEOplayerVersion;\n }\n\n return 'unknown';\n }\n getPlayerName(): string {\n return PlayerEnum.THEOPLAYER;\n }\n getPlayerTech(): string {\n return 'html5';\n }\n getAutoPlay(): boolean {\n return this.player.autoplay ?? false;\n }\n\n override getDrmPerformanceInfo = (): DrmPerformanceInfo | undefined => this.drmPerformanceService.getInfo();\n\n getCurrentPlaybackInfo(): PlaybackInfo {\n const activeVideoTrack = this.player.videoTracks.find((t) => t.enabled);\n const activeAudioTrack = this.player.audioTracks.find((t) => t.enabled);\n const activeTextTrack = this.player.textTracks.find((t) => t.mode === 'showing');\n\n let castTech: CastTech | undefined = undefined;\n if (isNotNullish(this.player.cast?.airplay)) {\n castTech = CastTech.AirPlay;\n } else if (isNotNullish(this.player.cast?.chromecast)) {\n castTech = CastTech.GoogleCast;\n }\n\n return {\n ...this.getCommonPlaybackInfo(),\n ...detectPlaybackInfoStreamTypeFieldsFromSource(this.currentSource),\n audioBitrate: activeAudioTrack?.activeQuality?.bandwidth,\n audioCodec: activeAudioTrack?.activeQuality?.codecs,\n audioLanguage: activeAudioTrack?.language,\n castTech: castTech,\n droppedFrames: 0,\n isCasting: this.player.cast?.casting === true,\n isLive: !isFinite(this.player.duration),\n isMuted: this.player.muted,\n playerTech: this.getPlayerTech(),\n size: this.player.presentation.currentMode === 'fullscreen' ? PlayerSize.Fullscreen : PlayerSize.Window,\n subtitleEnabled: isNotNullish(activeTextTrack),\n subtitleLanguage: activeTextTrack?.language,\n videoBitrate: activeVideoTrack?.activeQuality?.bandwidth,\n videoCodec: activeVideoTrack?.activeQuality?.codecs,\n videoDuration: normalizeVideoDuration(this.player.duration),\n videoPlaybackHeight: this.player.videoHeight,\n videoPlaybackWidth: this.player.videoWidth,\n videoWindowHeight: this.player.element.offsetHeight,\n videoWindowWidth: this.player.element.offsetWidth,\n } as PlaybackInfo;\n }\n\n protected override get currentTime(): number {\n return this.player.currentTime;\n }\n\n override getDownloadSpeedInfo(): DownloadSpeedInfo {\n return this.speedMeter.getInfo();\n }\n\n override resetDownloadSpeedInfoMeasures(): void {\n this.speedMeter.reset();\n }\n\n override resetSourceRelatedState(): void {\n super.resetSourceRelatedState();\n this.ssaiService.resetSourceRelatedState();\n\n this.videoTrackListeners.forEach((listener, track) => {\n track.removeEventListener('activequalitychanged', listener);\n });\n this.videoTrackListeners.clear();\n\n this.audioTrackListeners.forEach((listener, track) => {\n track.removeEventListener('activequalitychanged', listener);\n });\n this.audioTrackListeners.clear();\n\n this.lastTrackedCurrentTime = undefined;\n this.currentSource = undefined;\n this.speedMeter.reset();\n this.drmPerformanceService.reset();\n this.networkInterceptor.reset();\n }\n\n override eventCallback<\n StateMachineEvent extends keyof EventMap,\n StateMachineEventData extends EventMap[StateMachineEvent],\n >(event: StateMachineEvent, eventData: NoExtraProperties<EventMap[StateMachineEvent], StateMachineEventData>) {\n this.delayedEventDispatcher.dispatchEvent(\n event,\n eventData,\n this.stateMachine.currentState,\n super.eventCallback.bind(this),\n );\n }\n\n private handleVideoQualityChanged(qualityEvent: QualityEvent<'activequalitychanged'>): void {\n // The issue is that the quality from the activequalitychanged event has a generic type Quality, which only has\n // the base properties. But the actual object has more properties for video tracks, so we need to narrow the type\n // to VideoQuality to access them.\n const videoQuality = qualityEvent.quality as VideoQuality;\n\n const qualityEventInfo: QualityChangeEvent = {\n type: 'video',\n width: videoQuality.width,\n height: videoQuality.height,\n bitrate: videoQuality.bandwidth,\n currentTime: this.currentTime,\n };\n\n if (this.qualityChangeService.shouldAllowVideoQualityChange(videoQuality.bandwidth)) {\n this.eventCallback(Event.VIDEO_CHANGE, qualityEventInfo);\n }\n\n this.qualityChangeService.setVideoBitrate(videoQuality.bandwidth);\n this.stateMachineCallbacks.updateSampleQualityInfo(qualityEventInfo);\n }\n\n private handleAudioQualityChanged(qualityEvent: QualityEvent<'activequalitychanged'>): void {\n const quality = qualityEvent.quality;\n\n const qualityEventInfo: QualityChangeEvent = {\n type: 'audio',\n bitrate: quality.bandwidth,\n currentTime: this.currentTime,\n };\n\n if (this.qualityChangeService.shouldAllowAudioQualityChange(quality.bandwidth)) {\n this.eventCallback(Event.AUDIO_CHANGE, qualityEventInfo);\n }\n\n this.qualityChangeService.setAudioBitrate(quality.bandwidth);\n this.stateMachineCallbacks.updateSampleQualityInfo(qualityEventInfo);\n }\n\n private registerEventListeners() {\n this.player.addEventListener('sourcechange', (_event) => {\n // We use the 'sourcechange' event to indicate that the player that was in State.SOURCE_CHANGING is ready\n // with a new source and should move to State.READY. It doesn't mean that the source is fully loaded, it\n // only means that the player is ready to play (play button is enabled), and a video source can be loaded\n // later as part of the startup.\n //\n // Why not use the 'loadedmetadata' event?\n // Because we need to support also player setup without preload (preload=\"none\"), where 'loadedmetadata'\n // is not fired, but the player is already able to trigger \"play\" action (play button or API call is available)\n // aka. the player should already leave State.SOURCE_CHANGING and be in State.READY, because if a \"play\" action\n // is triggered, we should transition to State.STARTUP. Without preload, 'loadedmetadata' is fired later, and\n // we track a whole source loading time as part of startup.\n this.eventCallback(Event.READY, {});\n });\n\n this.player.addEventListener('currentsourcechange', (event) => {\n // prevents MANUAL_SOURCE_CHANGE on the first occurrence - in the beginning the player is setting up the first video\n if (isNotNullish(this.currentSource)) {\n // Why not use the 'loadstart' event?\n // Because with THEOplayer, the load of the video can actually happen after startup (especially without preload: on)\n // and using 'loadstart' to indicate the start of the source change would send startup failure instead of normal startup.\n this.eventCallback(Event.MANUAL_SOURCE_CHANGE, {currentTime: this.lastTrackedCurrentTime, config: {}});\n }\n this.currentSource = event.currentSource;\n });\n\n this.player.addEventListener('play', (event) => {\n this.eventCallback(Event.PLAY, {currentTime: event.currentTime});\n });\n\n this.player.addEventListener('pause', (event) => {\n this.eventCallback(Event.PAUSE, {currentTime: event.currentTime});\n });\n\n this.player.videoTracks.addEventListener('addtrack', (event) => {\n // The issue is that the track from the addtrack event is typed as the base Track interface,\n // which only has TrackEventMap — not MediaTrackEventMap. We need to narrow the type to MediaTrack\n const mediaTrack = event.track as MediaTrack;\n\n const listener = (qualityEvent: QualityEvent<'activequalitychanged'>) => {\n this.handleVideoQualityChanged(qualityEvent);\n };\n mediaTrack.addEventListener('activequalitychanged', listener);\n this.videoTrackListeners.set(mediaTrack, listener);\n });\n\n this.player.videoTracks.addEventListener('removetrack', (event) => {\n // The issue is that the track from the removetrack event is typed as the base Track interface,\n // which only has TrackEventMap — not MediaTrackEventMap. We need to narrow the type to MediaTrack\n const mediaTrack = event.track as MediaTrack;\n\n const listener = this.videoTrackListeners.get(mediaTrack);\n if (listener) {\n mediaTrack.removeEventListener('activequalitychanged', listener);\n this.videoTrackListeners.delete(mediaTrack);\n }\n });\n\n // add listeners to all already added/existing video tracks\n for (const track of this.player.videoTracks) {\n const listener = (qualityEvent: QualityEvent<'activequalitychanged'>) => {\n this.handleVideoQualityChanged(qualityEvent);\n };\n track.addEventListener('activequalitychanged', listener);\n this.videoTrackListeners.set(track, listener);\n }\n\n this.player.audioTracks.addEventListener('addtrack', (event) => {\n // The issue is that the track from the addtrack event is typed as the base Track interface,\n // which only has TrackEventMap — not MediaTrackEventMap. We need to narrow the type to MediaTrack\n const mediaTrack = event.track as MediaTrack;\n\n const listener = (qualityEvent: QualityEvent<'activequalitychanged'>) => {\n this.handleAudioQualityChanged(qualityEvent);\n };\n mediaTrack.addEventListener('activequalitychanged', listener);\n this.audioTrackListeners.set(mediaTrack, listener);\n });\n\n this.player.audioTracks.addEventListener('removetrack', (event) => {\n // The issue is that the track from the removetrack event is typed as the base Track interface,\n // which only has TrackEventMap — not MediaTrackEventMap. We need to narrow the type to MediaTrack\n const mediaTrack = event.track as MediaTrack;\n\n const listener = this.audioTrackListeners.get(mediaTrack);\n if (listener) {\n mediaTrack.removeEventListener('activequalitychanged', listener);\n this.audioTrackListeners.delete(mediaTrack);\n }\n });\n\n // add listeners to all already added/existing audio tracks\n for (const track of this.player.audioTracks) {\n const listener = (qualityEvent: QualityEvent<'activequalitychanged'>) => {\n this.handleAudioQualityChanged(qualityEvent);\n };\n track.addEventListener('activequalitychanged', listener);\n this.audioTrackListeners.set(track, listener);\n }\n\n this.player.addEventListener('seeking', (_event) => {\n // we have to send the last tracked time as currentTime here,\n // because at this point the event.currentTime is already set to the new seeked time\n this.eventCallback(Event.SEEK, {currentTime: this.lastTrackedCurrentTime});\n });\n\n this.player.addEventListener('timeupdate', (event) => {\n this.lastTrackedCurrentTime = event.currentTime;\n });\n\n this.player.addEventListener('playing', (event) => {\n this.eventCallback(Event.PLAYING, {currentTime: event.currentTime});\n });\n\n this.player.addEventListener('waiting', (event) => {\n this.eventCallback(Event.START_BUFFERING, {currentTime: event.currentTime});\n });\n\n this.player.addEventListener('ended', (event) => {\n this.eventCallback(Event.END, {currentTime: event.currentTime});\n });\n\n this.player.addEventListener('segmenterror', (event) => {\n // theoplayer does not provide a correct type for the segment error event,\n // so we have to use any here to get `error` property and its data\n const code = isNotNullish(event['error']?.code) ? Number(event['error']?.code) : undefined;\n const maybeMessage = event['error']?.message;\n const message = isValidString(maybeMessage) ? maybeMessage : undefined;\n const originalError = event['error']?.cause;\n const maybeStacktrace = event['error']?.stack;\n const stacktrace = isValidString(maybeStacktrace) ? maybeStacktrace.split('\\n') : undefined;\n const errorAsData = tryJSONStringify(event);\n\n this.eventCallback(Event.ERROR, {\n code: code,\n message: message,\n legacyData: errorAsData,\n currentTime: this.currentTime,\n originalError: originalError,\n data: {\n exceptionMessage: message,\n exceptionStacktrace: stacktrace,\n additionalData: errorAsData,\n },\n });\n\n this.ssaiService.sendAdEngagementErrorSample({code: code, message: message, severity: 'CRITICAL'}, event);\n });\n\n this.player.addEventListener('error', (event) => {\n const code = event.errorObject.code;\n const message = event.errorObject.message;\n const originalError = event.errorObject.cause;\n const errorAsData = tryJSONStringify(event.errorObject);\n\n this.eventCallback(Event.ERROR, {\n code: code,\n message: message,\n legacyData: errorAsData,\n currentTime: this.currentTime,\n originalError: originalError,\n data: {\n exceptionMessage: message,\n exceptionStacktrace: event.errorObject.stack?.split('\\n') ?? undefined,\n additionalData: errorAsData,\n },\n });\n\n this.ssaiService.sendAdEngagementErrorSample({code: code, message: message, severity: 'CRITICAL'}, event);\n });\n\n this.player.ads?.addEventListener('adbreakbegin', (_event) => {\n this.eventCallback(Event.START_AD, {currentTime: this.currentTime});\n });\n this.player.ads?.addEventListener('adbreakend', (_event) => {\n this.eventCallback(Event.END_AD, {currentTime: this.currentTime});\n });\n\n const handleCollectorUnload = () => {\n if (!this.onBeforeUnLoadEvent) {\n this.onBeforeUnLoadEvent = true;\n // we use here the last tracked video time as we cannot be sure if the player is still working at this place\n const currentTime = this.lastTrackedCurrentTime;\n this.eventCallback(Event.UNLOAD, {currentTime});\n }\n this.release();\n };\n\n this.windowEventTracker.addEventListener('beforeunload', handleCollectorUnload);\n this.windowEventTracker.addEventListener('unload', handleCollectorUnload);\n this.player.addEventListener('destroy', (_event) => {\n handleCollectorUnload();\n });\n }\n}\n\nexport function detectPlaybackInfoStreamTypeFieldsFromSource(\n source: TypedSource | undefined,\n): Pick<PlaybackInfo, 'm3u8Url' | 'mpdUrl' | 'progUrl' | 'streamFormat'> {\n if (isNullish(source)) {\n return {};\n }\n\n let streamType: StreamTypes | undefined = undefined;\n if (!isNullish(source.type)) {\n streamType = getStreamTypeFromMIMEType(source.type);\n }\n if (isNullish(streamType)) {\n streamType = getStreamTypesFromURL(source.src);\n }\n\n return buildPlaybackInfoStreamTypeFields(streamType, source.src);\n}\n\nexport function createSpeedMeasurementFromEvent(event: OnDownloadFinishedEventObject): SpeedMeasurement | undefined {\n const httpRequest = event.httpRequest;\n\n if (!httpRequest.success) {\n return undefined;\n }\n\n if (httpRequest.type !== HttpRequestType.MEDIA_VIDEO && httpRequest.type !== HttpRequestType.MEDIA_AUDIO) {\n return undefined;\n }\n\n return {\n duration: httpRequest.downloadTime / 1000,\n size: isNumber(httpRequest.size) ? httpRequest.size : 0,\n timeToFirstByte: isNotNullish(httpRequest.timeToFirstByte) ? httpRequest.timeToFirstByte / 1000 : 0,\n timestamp: new Date(),\n httpStatus: httpRequest.httpStatus,\n };\n}\n","import type {ChromelessPlayer, InterceptableRequest, InterceptableResponse} from 'theoplayer';\n\nimport {EventDispatcher, Subscribable} from '../../core/EventDispatcher';\nimport {HttpRequestType} from '../../features/httprequesttracking/HttpRequestType';\nimport {OnDownloadFinishedEventObject} from '../../features/httprequesttracking/OnDownloadFinishedEventObject';\nimport {getGlobalPerformanceNow} from '../../utils/globalScopeUtils';\nimport {logger} from '../../utils/Logger';\nimport {isNumber, parseIntOrUndefined} from '../../utils/numberUtils';\nimport {endsWith, isBlank, isValidString} from '../../utils/stringUtils';\nimport {isArrayBuffer, isNotNullish, isNullish} from '../../utils/Utils';\n\nexport const STALE_REQUEST_TIMEOUT_MS = 3 * 60 * 1_000; // three minutes\n\ninterface PendingRequest {\n url: string;\n startTime: number;\n type: string | undefined;\n subType: string | undefined;\n mediaType: string | undefined;\n}\n\n/**\n * Unified network interceptor for THEOplayer that captures HTTP request/response data\n * and publishes standardized {@link OnDownloadFinishedEventObject} events.\n *\n * This allows both {@link DownloadSpeedMeter} and {@link HttpRequestTracking} to subscribe\n * to a single source of network events.\n */\nexport class THEOplayerNetworkInterceptor implements Subscribable<OnDownloadFinishedEventObject> {\n private eventDispatcher = new EventDispatcher<OnDownloadFinishedEventObject>();\n private pendingRequests = new Map<string, PendingRequest[]>();\n\n constructor(private player: ChromelessPlayer) {\n if (isNullish(this.player.network)) {\n logger.warn('THEOplayerNetworkInterceptor: player.network is not available');\n return;\n }\n\n this.player.network.addRequestInterceptor(this.onRequest);\n this.player.network.addResponseInterceptor(this.onResponse);\n }\n\n subscribe(callback: (args: OnDownloadFinishedEventObject) => void): () => void {\n return this.eventDispatcher.subscribe(callback);\n }\n\n unsubscribe(callback: (args: OnDownloadFinishedEventObject) => void): void {\n this.eventDispatcher.unsubscribe(callback);\n }\n\n reset(): void {\n this.pendingRequests.clear();\n }\n\n private onRequest = (request: InterceptableRequest): void => {\n try {\n const url = request.url;\n // we need to double-check the url as a valid string, because our implementation is using it as a key in the map,\n // and if it's invalid, it can cause issues\n if (!isValidString(url) || isBlank(url)) {\n return;\n }\n\n const performanceNow = getGlobalPerformanceNow();\n const now = performanceNow ?? Date.now();\n\n // clean up any stale pending requests that have been pending for too long before adding the new request\n // to prevent map overflow in case of missing responses or other issues\n // No need for logic with timeout here, let's keep it simple\n this.cleanupStaleRequests(now);\n\n const pendingRequest: PendingRequest = {\n url: url,\n startTime: now,\n type: request.type,\n subType: request.subType,\n mediaType: request.mediaType,\n };\n\n const existing = this.pendingRequests.get(url);\n if (isNullish(existing)) {\n this.pendingRequests.set(url, [pendingRequest]);\n } else {\n existing.push(pendingRequest);\n }\n } catch (error) {\n logger.error('THEOplayerNetworkInterceptor: Error in request interceptor', error);\n }\n };\n\n private onResponse = (response: InterceptableResponse): void => {\n try {\n const request = response.request;\n // if the original request is missing, we can't correlate the response to a pending request, so we skip processing\n if (isNullish(request)) {\n return;\n }\n\n const url = request.url;\n // we need to double-check the url as a valid string, because our implementation is using it as a key in the map,\n // and if it's invalid, it can cause issues\n if (!isValidString(url) || isBlank(url)) {\n return;\n }\n\n const pendingArray = this.pendingRequests.get(url);\n if (isNullish(pendingArray) || pendingArray.length === 0) {\n return;\n }\n\n // Use FIFO: remove the oldest (first) pending request\n const pending = pendingArray.shift()!;\n\n if (pendingArray.length === 0) {\n this.pendingRequests.delete(url);\n }\n\n const performanceNow = getGlobalPerformanceNow();\n const endTime = performanceNow ?? Date.now();\n\n // round the final download time to a whole number to avoid unnecessary precision (performance.now() returns a high-precision timestamp as double)\n const downloadTime = Math.round(endTime - pending.startTime);\n\n const size = extractResponseSize(response);\n const httpStatus: number = isNumber(response.status) ? response.status : 0;\n const success = httpStatus >= 200 && httpStatus < 400;\n\n this.eventDispatcher.dispatch({\n httpRequest: {\n downloadTime: downloadTime,\n httpStatus: httpStatus,\n success: success,\n timestamp: Date.now(),\n url: url,\n size: size,\n timeToFirstByte: undefined, // missing in THEOplayer network API\n type: mapHttpRequestType(pending.type, pending.subType, pending.mediaType, url),\n },\n });\n } catch (error) {\n logger.error('THEOplayerNetworkInterceptor: Error in response interceptor', error);\n }\n };\n\n private cleanupStaleRequests(now: number): void {\n this.pendingRequests.forEach((pendingArray: PendingRequest[], url: string) => {\n const filtered = pendingArray.filter(\n (pending: PendingRequest) => now - pending.startTime <= STALE_REQUEST_TIMEOUT_MS,\n );\n\n if (filtered.length === 0) {\n this.pendingRequests.delete(url);\n } else if (filtered.length !== pendingArray.length) {\n this.pendingRequests.set(url, filtered);\n }\n });\n }\n}\n\nexport function extractResponseSize(response: InterceptableResponse): number | undefined {\n const contentLength = response.headers?.['content-length'] ?? response.headers?.['Content-Length'];\n if (isNotNullish(contentLength)) {\n const parsed = parseIntOrUndefined(contentLength);\n if (isNotNullish(parsed)) {\n return parsed;\n }\n }\n\n if (isNotNullish(response.body)) {\n if (isValidString(response.body)) {\n return response.body.length;\n }\n if (isArrayBuffer(response.body) && isNumber(response.body.byteLength)) {\n return response.body.byteLength;\n }\n }\n\n return undefined;\n}\n\nexport function mapHttpRequestType(\n requestType: string | undefined,\n requestSubType: string | undefined,\n mediaType: string | undefined,\n url: string,\n): HttpRequestType {\n // Check for content protection (DRM) requests first\n if (requestType === 'content-protection') {\n switch (requestSubType) {\n case 'widevine-license':\n return HttpRequestType.DRM_LICENSE_WIDEVINE;\n case 'fairplay-license':\n return HttpRequestType.DRM_LICENSE_FAIRPLAY;\n case 'playready-license':\n return HttpRequestType.DRM_LICENSE_PLAYREADY;\n case 'clearkey-license':\n return HttpRequestType.DRM_LICENSE_CLEARKEY;\n case 'aes128-key':\n return HttpRequestType.KEY_HLS_AES;\n case 'fairplay-certificate':\n return HttpRequestType.DRM_CERTIFICATE_FAIRPLAY;\n case 'widevine-certificate':\n // no enum value for this category on HttpRequestType - needs update from player team\n return HttpRequestType.UNKNOWN;\n default:\n return HttpRequestType.UNKNOWN;\n }\n }\n\n // Check for manifest requests based on URL extension\n if (requestType === 'manifest') {\n if (endsWith(url, '.mpd')) {\n return HttpRequestType.MANIFEST_DASH;\n }\n if (endsWith(url, '.m3u8')) {\n return HttpRequestType.MANIFEST_HLS_MASTER;\n }\n return HttpRequestType.UNKNOWN;\n }\n\n // Check for media segment requests based on mediaType\n if (mediaType === 'video') {\n return HttpRequestType.MEDIA_VIDEO;\n }\n if (mediaType === 'audio') {\n return HttpRequestType.MEDIA_AUDIO;\n }\n if (mediaType === 'text') {\n return HttpRequestType.MEDIA_SUBTITLES;\n }\n\n // Fallback: check URL extension for manifests even without explicit type\n if (endsWith(url, '.mpd')) {\n return HttpRequestType.MANIFEST_DASH;\n }\n if (endsWith(url, '.m3u8')) {\n return HttpRequestType.MANIFEST_HLS_MASTER;\n }\n\n return HttpRequestType.UNKNOWN;\n}\n","import type {\n Ad as PlayerAd,\n AdBreak as PlayerAdBreak,\n GoogleImaAd as PlayerGoogleImaAd,\n LinearAd as PlayerLinearAd,\n} from 'theoplayer';\n\nimport type {AdBreakInfo} from '../../../types/ads/AdBreakInfo';\nimport type {AdInfo} from '../../../types/ads/AdInfo';\nimport {isFiniteNumber} from '../../../utils/numberUtils';\nimport {isNotNullish} from '../../../utils/Utils';\n\nexport function mapTheoAd(ad: PlayerAd): AdInfo {\n const isLinear = ad.type === 'linear';\n\n const adInfo: AdInfo = {\n id: ad.id,\n isLinear,\n clickThroughUrl: ad.clickThrough,\n width: ad.width,\n height: ad.height,\n };\n\n const linearAd = isLinear ? (ad as PlayerLinearAd) : undefined;\n if (isNotNullish(linearAd)) {\n adInfo.mediaUrl = linearAd.mediaUrl;\n }\n\n if (isNotNullish(ad.skipOffset)) {\n adInfo.skippable = ad.skipOffset !== -1;\n adInfo.skippableAfter = ad.skipOffset;\n }\n\n if (isNotNullish(ad.duration)) {\n adInfo.duration = ad.duration;\n }\n\n const isGoogleIma = ad.integration === 'google-ima' || ad.integration === 'google-dai';\n const googleAd = isGoogleIma ? (ad as PlayerGoogleImaAd) : undefined;\n if (isNotNullish(googleAd)) {\n adInfo.bitrate = isNotNullish(googleAd.bitrate) ? googleAd.bitrate / 1000 : undefined;\n adInfo.mimeType = googleAd.contentType;\n }\n\n adInfo.vastData = {\n adSystem: ad.adSystem,\n creativeId: ad.creativeId,\n };\n\n const universalAdId = ad.universalAdIds && ad.universalAdIds.length > 0 ? ad.universalAdIds[0] : undefined;\n if (isNotNullish(universalAdId)) {\n adInfo.vastData.universalAdIdRegistry = universalAdId.adIdRegistry;\n adInfo.vastData.universalAdIdValue = universalAdId.adIdValue;\n }\n\n if (isNotNullish(googleAd)) {\n adInfo.vastData.apiFramework = googleAd.apiFramework;\n adInfo.vastData.adDescription = googleAd.description;\n adInfo.vastData.adTitle = googleAd.title;\n adInfo.vastData.wrapperAdsCount = isNotNullish(googleAd.wrapperAdIds) ? googleAd.wrapperAdIds.length : undefined;\n }\n\n return adInfo;\n}\n\nexport function mapTheoAdBreak(adBreak: PlayerAdBreak, videoDuration?: number): AdBreakInfo {\n const timeOffset = adBreak.timeOffset;\n if (!isFiniteNumber(timeOffset) || timeOffset < 0) {\n return {position: undefined, scheduleTime: undefined};\n }\n\n if (timeOffset === 0) {\n return {position: 'pre', scheduleTime: 0};\n }\n\n // checks if timeOffset (aka ad schedule time) is close to video duration (aka end of video)\n // the 1sec delta threshold is an arbitrary number that accounts for small errors in the reported numbers.\n const DELTA_THRESHOLD_SEC = 1;\n const deltaTimeOffsetVideoDuration = isNotNullish(videoDuration) ? Math.abs(timeOffset - videoDuration) : undefined;\n if (isNotNullish(deltaTimeOffsetVideoDuration) && deltaTimeOffsetVideoDuration <= DELTA_THRESHOLD_SEC) {\n return {position: 'post', scheduleTime: videoDuration};\n }\n\n // default to midroll\n return {position: String(timeOffset), scheduleTime: timeOffset};\n}\n","import type {ChromelessPlayer, Event as PlayerEvent} from 'theoplayer';\n\nimport {isFiniteNumber} from '../../../utils/numberUtils';\nimport {isNotNullish, isNullish} from '../../../utils/Utils';\nimport {WindowEventTracker} from '../../../utils/WindowEventTracker';\nimport {AdCallbacks, AdErrorPayload, AdManifestLoadedPayload, AdModuleAPI} from '../../internal/ads/AdModuleAPI';\n\nimport {mapTheoAd, mapTheoAdBreak} from './AdUtils';\n\nexport class THEOplayerAdModule implements AdModuleAPI {\n adCallbacks = new AdCallbacks();\n /**\n * this field stores the duration of the video.\n * during active ad the property `player.duration` shows the duration of the ad.\n */\n private videoDuration: number | undefined;\n\n private readonly player: ChromelessPlayer;\n\n constructor(player: ChromelessPlayer, windowEventTracker: WindowEventTracker) {\n this.player = player;\n this.register(windowEventTracker);\n }\n\n isLinearAdActive = (): boolean => {\n return this.player.ads ? this.player.ads.playing : false;\n };\n\n getContainer = (): HTMLElement => this.player.element;\n\n getAdModuleInfo = (): {name?: string; version?: string} => {\n return {name: 'theo-ads', version: undefined};\n };\n\n currentTime = (): number => this.player.currentTime;\n\n getAutoPlay = (): boolean => this.player.autoplay ?? false;\n\n private register(windowEventTracker: WindowEventTracker) {\n const ads = this.player.ads;\n if (isNullish(ads)) {\n return;\n }\n\n ads.addEventListener('adbreakbegin', (event) => {\n this.adCallbacks.onAdBreakStarted(mapTheoAdBreak(event.adBreak, this.videoDuration));\n });\n ads.addEventListener('adbreakend', (event) => {\n this.adCallbacks.onAdBreakFinished(mapTheoAdBreak(event.adBreak, this.videoDuration));\n });\n ads.addEventListener('adbegin', (event) => {\n this.adCallbacks.onAdStarted(mapTheoAd(event.ad));\n });\n ads.addEventListener('adend', (event) => {\n this.adCallbacks.onAdFinished(mapTheoAd(event.ad));\n });\n ads.addEventListener('adskip', (event) => {\n this.adCallbacks.onAdSkipped(mapTheoAd(event.ad));\n });\n ads.addEventListener('aderror', (event) => {\n const errorPayload: AdErrorPayload = {};\n\n if (isAdErrorEvent(event)) {\n errorPayload.code = event.errorCode;\n errorPayload.message = event.message;\n }\n\n // fallback to player recorded error if event does not provide error info\n const errorObject = this.player.errorObject;\n if (isNotNullish(errorObject) && isNullish(errorPayload.code)) {\n errorPayload.code = errorObject.code;\n errorPayload.message = errorObject.message;\n }\n this.adCallbacks.onAdError(errorPayload);\n });\n ads.addEventListener('adloaded', (_event) => {\n if (isFiniteNumber(this.player.duration) && this.videoDuration !== this.player.duration) {\n this.videoDuration = this.player.duration;\n }\n\n const adManifestPayload: AdManifestLoadedPayload = {\n isVmap: false,\n };\n\n const sourceAds = this.player.source?.ads;\n if (isNotNullish(sourceAds) && sourceAds.length > 0) {\n // if VMAP is set up only one ad will be defined and that's the vmap definition.\n adManifestPayload.isVmap = (sourceAds[0] as {type?: string}).type === 'vmap';\n }\n\n if (isNotNullish(this.player.ads?.currentAdBreak)) {\n adManifestPayload.adBreakInfo = mapTheoAdBreak(this.player.ads.currentAdBreak, this.player.duration);\n }\n\n this.adCallbacks.onAdManifestLoaded(adManifestPayload);\n });\n\n // Note: THEOplayer doesn't emit quartile events for CSAI ads.\n // We tried to use them, but at the moment we don't see them emitted in the THEOplayer@10.12.0. We relay on fallback\n // in the AdAnalytics module that calculates it from play percentage.\n //\n // ads.addEventListener('adfirstquartile', (_event) => {});\n // ads.addEventListener('admidpoint', (_event) => {});\n // ads.addEventListener('adthirdquartile', (_event) => {});\n\n const handlePageClose = () => {\n this.adCallbacks.onBeforeUnload();\n };\n windowEventTracker.addEventListener('beforeunload', handlePageClose);\n windowEventTracker.addEventListener('unload', handlePageClose);\n }\n}\n\n/**\n * Used to narrow the Event<'aderror'> type to a more specific type that contains the error details.\n *\n * @privateRemarks\n * THEOplayer SDK does expose only a \"general\" Event<'aderror'> type in AdsEventMap, but we could see in runtime that\n * the AdError event payload contains more properties that we could use.\n */\ninterface PlayerAdErrorEvent extends PlayerEvent<'aderror'> {\n errorCode: number;\n message: string;\n problemType: string;\n source: string;\n}\n\nfunction isAdErrorEvent(event: PlayerEvent<'aderror'>): event is PlayerAdErrorEvent {\n return isNotNullish(event) && 'errorCode' in event;\n}\n","import {isNotNullish} from '../../../utils/Utils';\n\nexport const CALLBACK_SCHEDULER_TIMEOUT_DELAY_MS = 50;\n\nexport class CallbackScheduler {\n private timeout: ReturnType<typeof setTimeout> | undefined = undefined;\n private callback: (() => void) | undefined;\n\n schedule(callback: () => void) {\n if (isNotNullish(this.timeout)) {\n return;\n }\n\n this.callback = callback;\n this.timeout = setTimeout(() => {\n this.callback?.();\n this.cancel();\n }, CALLBACK_SCHEDULER_TIMEOUT_DELAY_MS);\n }\n\n isScheduled() {\n return isNotNullish(this.timeout);\n }\n\n execute() {\n this.callback?.();\n this.cancel();\n }\n\n cancel() {\n clearTimeout(this.timeout);\n this.timeout = undefined;\n this.callback = undefined;\n }\n}\n","import {State} from '../../../analyticsStateMachines/THEOplayerAnalyticsStateMachine';\nimport {Event, EventMap} from '../../../enums/Event';\nimport type {NoExtraProperties} from '../../../types/NoExtraProperties';\nimport {logger} from '../../../utils/Logger';\n\nimport {CallbackScheduler} from './CallbackScheduler';\n\nexport interface DelayScenario {\n /** The event to delay dispatching */\n delayEvent: Event;\n /** Only delay when the state machine is in this state */\n inState: string;\n /** If this event arrives while the delayed event is pending, cancel it */\n cancelOnEvent: Event;\n}\n\nexport class DelayedEventDispatcher {\n private readonly scheduler: CallbackScheduler = new CallbackScheduler();\n private activeScenario: DelayScenario | undefined;\n\n static create(): DelayedEventDispatcher {\n return new DelayedEventDispatcher([\n // Delayed PAUSE event execution to handle the case: PRECEDING \"PAUSE\" EVENT ON STARTUP ERRORS\n {delayEvent: Event.PAUSE, inState: State.STARTUP, cancelOnEvent: Event.ERROR},\n\n // Delayed PAUSE event execution to handle the case: PRECEDING \"PAUSE\" EVENT BEFORE \"SEEK\" WHEN SEEKING VIA UI PROGRESS BAR\n {delayEvent: Event.PAUSE, inState: State.PLAYING, cancelOnEvent: Event.SEEK},\n\n // Delayed END_AD event execution to handle the case: MIDROLL & POSTROLL ADS DETERMINATION\n {delayEvent: Event.END_AD, inState: State.AD_PLAYBACK, cancelOnEvent: Event.END},\n ]);\n }\n\n private constructor(private readonly scenarios: DelayScenario[]) {}\n\n dispatchEvent<StateMachineEvent extends keyof EventMap, StateMachineEventData extends EventMap[StateMachineEvent]>(\n event: StateMachineEvent,\n eventData: NoExtraProperties<EventMap[StateMachineEvent], StateMachineEventData>,\n state: string,\n dispatch: (\n event: StateMachineEvent,\n eventData: NoExtraProperties<EventMap[StateMachineEvent], StateMachineEventData>,\n eventTimestamp?: number,\n ) => void,\n ) {\n if (this.scheduler.isScheduled() && this.activeScenario != null) {\n if (this.activeScenario.cancelOnEvent === event) {\n logger.log(\n `⏳ [DelayedEventDispatcher] 🚫 Cancelling delayed '${String(this.activeScenario.delayEvent)}' — canceled by event '${String(event)}'`,\n );\n this.scheduler.cancel();\n this.activeScenario = undefined;\n } else {\n logger.log(\n `⏳ [DelayedEventDispatcher] ✅ Executing delayed '${String(this.activeScenario.delayEvent)}' early — unrelated event '${String(event)}' arrived`,\n );\n this.scheduler.execute();\n this.activeScenario = undefined;\n }\n }\n\n const matchingScenario = this.findMatchingScenario(event, state);\n if (matchingScenario != null) {\n const eventTimestamp = Date.now();\n this.activeScenario = matchingScenario;\n logger.log(`⏳ [DelayedEventDispatcher] ➕ Delaying '${String(event)}' in state '${state}'`);\n this.scheduler.schedule(() => {\n this.activeScenario = undefined;\n dispatch(event, eventData, eventTimestamp);\n });\n return;\n }\n\n dispatch(event, eventData);\n }\n\n private findMatchingScenario(event: keyof EventMap, state: string): DelayScenario | undefined {\n for (const scenario of this.scenarios) {\n if (scenario.delayEvent === event && scenario.inState === state) {\n return scenario;\n }\n }\n return undefined;\n }\n}\n","import type {AdapterAPI} from '../../api/AdapterAPI';\nimport {Analytics} from '../../core/Analytics';\nimport type {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {logger} from '../../utils/Logger';\nimport {\n hasPlayerAlreadyBeenAugmented,\n isDefined,\n markPlayerInstanceAsAugmented,\n} from '../../utils/playerAugmentationUtils';\nimport {VERSION} from '../../utils/Version';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {VideojsInternalAdapter} from './VideojsInternalAdapter';\n\nexport class VideojsAdapter implements AdapterAPI {\n private readonly internalAdapter: InternalAdapterAPI | undefined;\n private readonly analytics: Analytics | undefined;\n\n constructor(config: AnalyticsConfig, player: any, opts?: AnalyticsStateMachineOptions) {\n if (hasPlayerAlreadyBeenAugmented(player)) {\n logger.errorMessageToUser('Bitmovin Analytics is already hooked up to this player instance');\n return;\n }\n markPlayerInstanceAsAugmented(player);\n\n const sanitizedConfig = sanitizeAnalyticsConfig(config);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n return;\n }\n\n guardAgainstDuplicatedUserId(sanitizedConfig);\n\n this.internalAdapter = new VideojsInternalAdapter(player, opts);\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n }\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getCurrentImpressionId();\n }\n\n getUserId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getUserId();\n }\n\n setCustomData(values: CustomDataValues) {\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.setCustomData(values);\n }\n\n setCustomDataOnce(values: CustomDataValues) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.setCustomDataOnce(values);\n }\n\n sourceChange(config: AnalyticsConfig) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.sourceChange(config);\n }\n}\n","import type {VideoJsPlayer} from 'video.js';\n\nimport {VideojsAnalyticsStateMachine} from '../../analyticsStateMachines/VideoJsAnalyticsStateMachine';\nimport {Analytics} from '../../core/Analytics';\nimport {HeartbeatService} from '../../core/HeartbeatService';\nimport VideoCompletionTracker from '../../core/VideoCompletionTracker';\nimport * as CodecHelper from '../../enums/Codecs';\nimport {Event} from '../../enums/Event';\nimport {Player} from '../../enums/Player';\nimport {PlayerSize} from '../../enums/PlayerSize';\nimport {getStreamTypeFromMIMEType, getStreamTypesFromURL} from '../../enums/StreamTypes';\nimport {ErrorDetailBackend} from '../../features/errordetails/ErrorDetailBackend';\nimport {ErrorDetailTracking} from '../../features/errordetails/ErrorDetailTracking';\nimport {Feature} from '../../features/Feature';\nimport {FeatureConfig} from '../../features/FeatureConfig';\nimport {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport {CodecInfo} from '../../types/CodecInfo';\nimport {DrmPerformanceInfo} from '../../types/DrmPerformanceInfo';\nimport {QualityChangeEvent} from '../../types/EventData';\nimport {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport {buildPlaybackInfoStreamTypeFields, normalizeVideoDuration, PlaybackInfo} from '../../types/PlaybackInfo';\nimport {QualityLevelInfo} from '../../types/QualityLevelInfo';\nimport {isDifferentSubtitleInfo, SubtitleInfo} from '../../types/SubtitleInfo';\nimport {getGlobalVideojsVersion} from '../../utils/globalScopeUtils';\nimport {isBlank, isValidString} from '../../utils/stringUtils';\nimport {isAudioMuted, isFunction, isNotNullish, isNullish} from '../../utils/Utils';\nimport {InternalAdapter} from '../internal/InternalAdapter';\nimport {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\n// Declaration merging to extend the VideoJsPlayer interface.\n// @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html\ndeclare module 'video.js' {\n interface VideoJsPlayer {\n // Extend the VideoJsPlayer interface with missing `version` function, introduced in 8.10.0\n // by https://github.com/videojs/video.js/pull/8543/files, but not present in `@types/video.js@7.3.58` yet.\n //\n // Function set as nullable to be able to covert older VideoJs players\n //\n // see: https://github.com/videojs/video.js/blob/6fe68e5dad6853d8f0eaf45534873607c1b32277/src/js/player.js#L1345\n version?(): {'video.js': string};\n }\n}\nexport class VideojsInternalAdapter extends InternalAdapter implements InternalAdapterAPI {\n readonly videoCompletionTracker: VideoCompletionTracker;\n\n private readonly player: VideoJsPlayer;\n\n private _subtitleInfo: SubtitleInfo = {enabled: false};\n private selectedAudioLanguage?: string;\n /** Boolean flag to prevent multiple calls of the {@link Event.UNLOAD} event */\n private onBeforeUnLoadEvent = false;\n private previousTime = 0;\n\n constructor(player: any, opts?: AnalyticsStateMachineOptions) {\n super(opts);\n this.player = player;\n const playingHeartbeatService = new HeartbeatService(() => this.currentTime);\n const stateMachine = new VideojsAnalyticsStateMachine(\n this.stateMachineCallbacks,\n playingHeartbeatService,\n this.opts,\n );\n playingHeartbeatService.setListener(stateMachine);\n this.stateMachine = stateMachine;\n\n this.videoCompletionTracker = new VideoCompletionTracker();\n }\n\n override resetSourceRelatedState() {\n super.resetSourceRelatedState();\n\n this.videoCompletionTracker.reset();\n this.videoCompletionTracker.setVideoDuration(this.player.duration());\n this.previousTime = 0;\n }\n\n initialize(analytics: Analytics): Array<Feature<FeatureConfigContainer, FeatureConfig>> {\n this.register();\n const errorDetailTracking = new ErrorDetailTracking(\n analytics.errorDetailTrackingSettingsProvider,\n new ErrorDetailBackend(analytics.errorDetailTrackingSettingsProvider.collectorConfig),\n [analytics.errorDetailSubscribable],\n undefined,\n );\n return [errorDetailTracking];\n }\n\n getPlayerVersion = () => {\n // try to get the version from the player instance\n // - `VideoJsPlayer.version()` was introduced in 8.10.0, so we need to check for it\n const playerInstanceVersion = this.player.version?.()['video.js'];\n if (isValidString(playerInstanceVersion) && !isBlank(playerInstanceVersion)) {\n return playerInstanceVersion;\n }\n\n // try to get the version from the global `window` variable (if npm module is used, it doesn't exist)\n const windowVideoJsVersion = getGlobalVideojsVersion();\n if (isValidString(windowVideoJsVersion) && !isBlank(windowVideoJsVersion)) {\n return windowVideoJsVersion;\n }\n\n return 'unknown';\n };\n getPlayerName = () => Player.VIDEOJS;\n getPlayerTech = () => 'html5';\n getAutoPlay = () => this.player.autoplay() === true;\n override getDrmPerformanceInfo = (): DrmPerformanceInfo | undefined => this.drmPerformanceInfo;\n\n getCurrentPlaybackInfo(): PlaybackInfo {\n this.selectedAudioLanguage = this.getSelectedAudioTrackLanguage(this.player);\n const codecInfo = this.getCodecInfo(this.player.tech({IWillNotUseThisInPlugins: true}));\n\n const info: PlaybackInfo = {\n ...this.getCommonPlaybackInfo(),\n ...detectVideoJsPlaybackInfoStreamTypeFields(this.player),\n isLive: isNaN(this.player.duration()) ? undefined : this.player.duration() === Infinity,\n size: this.player.isFullscreen() ? PlayerSize.Fullscreen : PlayerSize.Window,\n playerTech: this.getPlayerTech(),\n isMuted: this.player.muted(),\n videoDuration: normalizeVideoDuration(this.player.duration()),\n videoWindowHeight: this.player.height(),\n videoWindowWidth: this.player.width(),\n videoPlaybackHeight: this.player.videoHeight(),\n videoPlaybackWidth: this.player.videoWidth(),\n audioLanguage: this.selectedAudioLanguage,\n subtitleEnabled: this._subtitleInfo.enabled,\n subtitleLanguage: this._subtitleInfo.language,\n videoCodec: codecInfo?.videoCodec,\n audioCodec: codecInfo?.audioCodec,\n droppedFrames: 0, // TODO\n // TODO audioBitrate:\n // TODO isCasting:\n // TODO videoTitle: (currently only from the analytics config)\n };\n\n const qualityInfo = this.getCurrentQualityLevelInfo();\n if (qualityInfo) {\n info.videoPlaybackWidth = qualityInfo.width ?? info.videoPlaybackWidth;\n info.videoPlaybackHeight = qualityInfo.height ?? info.videoPlaybackHeight;\n info.videoBitrate = qualityInfo.bitrate ?? info.videoBitrate;\n }\n\n return info;\n }\n\n getCurrentQualityLevelInfo(): QualityLevelInfo | null {\n return this.currentVideoJsQualityLevel();\n }\n\n register() {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const that = this;\n\n // if one source is being played and we load new source and start playing it\n // we need to reset all session related data and initialize new session\n // videojs does not provide a way for figuring out when current source or player is unloaded\n // so we need to reset everything with \"manualSourceChange\" event every time new source is loaded\n this.player.on('loadstart', function (this: any) {\n that.eventCallback(Event.MANUAL_SOURCE_CHANGE, {config: {}});\n });\n this.player.on('loadedmetadata', function (this: any) {\n that.videoCompletionTracker.reset();\n that.videoCompletionTracker.setVideoDuration(this.duration());\n that.previousTime = 0;\n that.eventCallback(Event.SOURCE_LOADED, {});\n });\n this.player.ready(function (this: any) {\n that._subtitleInfo = that.getSubtitleInfo(this);\n that.eventCallback(Event.READY, {});\n });\n this.player.on('play', function (this: any) {\n that.eventCallback(Event.PLAY, {\n currentTime: this.currentTime(),\n });\n });\n this.player.on('pause', function (this: any) {\n if (!this.seeking()) {\n that.eventCallback(Event.PAUSE, {\n currentTime: this.currentTime(),\n });\n }\n });\n this.player.on('error', function (this: any) {\n const error: MediaError = this.error();\n that.eventCallback(Event.ERROR, {\n currentTime: this.currentTime(),\n code: error.code,\n message: error.message,\n originalError: error,\n data: {},\n });\n });\n this.player.on('volumechange', function (this: any) {\n const muted = this.muted();\n const volume = this.volume();\n const isMuted = isAudioMuted(muted, volume);\n\n if (this.previousMutedValue !== isMuted) {\n if (isMuted) {\n that.eventCallback(Event.MUTE, {\n currentTime: this.currentTime(),\n });\n } else {\n that.eventCallback(Event.UN_MUTE, {\n currentTime: this.currentTime(),\n });\n }\n this.previousMutedValue = isMuted;\n }\n });\n this.player.on('seeking', function (this: any) {\n that.eventCallback(Event.SEEK, {\n currentTime: isNotNullish(that.previousTime) ? that.previousTime : this.currentTime(),\n });\n });\n this.player.on('seeked', function (this: any) {\n that.eventCallback(Event.SEEKED, {\n currentTime: this.currentTime(),\n });\n });\n\n this.player.on('texttrackchange', function (this: any) {\n const newSubtitleInfo = that.getSubtitleInfo(this);\n const hasInfoChanged = isNullish(that._subtitleInfo)\n ? true\n : isDifferentSubtitleInfo(that._subtitleInfo, newSubtitleInfo);\n that._subtitleInfo = newSubtitleInfo;\n\n if (hasInfoChanged) {\n that.eventCallback(Event.SUBTITLE_CHANGE, {\n currentTime: this.currentTime(),\n });\n }\n });\n\n const audioTracks = this.player.audioTracks();\n audioTracks.on('change', () => {\n const newSelectedAudioLanguage = that.getSelectedAudioTrackLanguage(that.player);\n if (isNotNullish(newSelectedAudioLanguage) && newSelectedAudioLanguage !== that.selectedAudioLanguage) {\n that.eventCallback(Event.AUDIOTRACK_CHANGED, {\n currentTime: that.player.currentTime(),\n });\n }\n });\n\n this.player.on('stalled', function (this: any) {\n that.eventCallback(Event.START_BUFFERING, {\n currentTime: this.currentTime(),\n });\n });\n this.player.on('waiting', function (this: any) {\n that.eventCallback(Event.START_BUFFERING, {\n currentTime: this.currentTime(),\n });\n });\n this.player.on('timeupdate', function (this: any) {\n if (!this.seeking()) {\n that.previousTime = this.currentTime();\n }\n that.eventCallback(Event.TIMECHANGED, {\n currentTime: this.currentTime(),\n });\n\n const qualityInfo = that.currentVideoJsQualityLevel();\n if (qualityInfo?.height && qualityInfo?.width && qualityInfo?.bitrate) {\n const eventObject: QualityChangeEvent = {\n type: 'video',\n bitrate: qualityInfo.bitrate,\n height: qualityInfo.height,\n width: qualityInfo.width,\n currentTime: this.currentTime(),\n };\n if (that.qualityChangeService.shouldAllowVideoQualityChange(qualityInfo.bitrate)) {\n that.eventCallback(Event.VIDEO_CHANGE, eventObject);\n }\n\n that.qualityChangeService.setVideoBitrate(qualityInfo.bitrate);\n that.stateMachineCallbacks.updateSampleQualityInfo(eventObject);\n }\n });\n\n let handlePageClose = () => {\n if (!this.onBeforeUnLoadEvent) {\n this.onBeforeUnLoadEvent = true;\n let currentTime: number | undefined;\n if (isNotNullish(this.player)) {\n currentTime = this.player.currentTime();\n }\n this.eventCallback(Event.UNLOAD, {\n currentTime,\n });\n }\n this.release();\n };\n\n handlePageClose = handlePageClose.bind(this);\n\n this.player.on('dispose', handlePageClose);\n this.windowEventTracker.addEventListener('beforeunload', handlePageClose);\n this.windowEventTracker.addEventListener('unload', handlePageClose);\n }\n\n protected get currentTime(): number {\n return this.player.currentTime();\n }\n\n private getSelectedAudioTrackLanguage(player: any): string | undefined {\n for (const track of player.audioTracks()) {\n if (track.enabled) {\n return track.language;\n }\n }\n return undefined;\n }\n\n private getSubtitleInfo(player: any): SubtitleInfo {\n const textTracks = player.textTracks() || [];\n let enabled = false;\n let language;\n for (const track of textTracks) {\n if (track.mode === 'showing') {\n enabled = true;\n language = track.language;\n break;\n }\n }\n return {\n enabled,\n language,\n };\n }\n\n private currentVideoJsQualityLevel(): QualityLevelInfo | null {\n // Check for HLS source-handler (http-streaming)\n // When we just use Videojs without any specific source-handler (not using MSE API based engine)\n // but just native technology (HTML5/Flash) to do for example \"progressive download\" with plain Webm/Mp4\n // or use native HLS on Safari this may not be present. In that case Videojs is just\n // a wrapper around the respective playback tech (HTML or Flash).\n const tech = this.player.tech({IWillNotUseThisInPlugins: true}) as any;\n\n if (isNullish(tech)) {\n return null;\n }\n\n if (isNullish(tech.vhs) && isNullish(tech.hls)) {\n return null;\n }\n\n const mediaAttributes = this.getMediaAttributes(tech);\n\n if (!mediaAttributes || !mediaAttributes.bitrate) {\n return null;\n }\n\n return {\n bitrate: mediaAttributes.bitrate,\n width: mediaAttributes.width,\n height: mediaAttributes.height,\n };\n }\n\n // more detailed info from segment can be obtained using\n // https://github.com/videojs/http-streaming#segment-metadata\n // but some properties are not available in older videojs versions\n private getMediaAttributes(playerTech: any): MediaAttributes | undefined {\n if (!playerTech) {\n return;\n }\n\n // From here we are going onto Videojs-HLS source-handler specific API\n let sourceHandler;\n if (playerTech.vhs) {\n sourceHandler = playerTech.vhs;\n } else if (playerTech.hls) {\n // older videojs versions don't have vhs property\n sourceHandler = playerTech.hls;\n }\n\n // Maybe we have the HLS source-handler initialized, but it is\n // not actually activated and used (just wrapping HTML5 built-in HLS playback like in Safari)\n if (!sourceHandler || !sourceHandler.playlists || !isFunction(sourceHandler.playlists.media)) {\n return;\n }\n\n // Check for current media playlist\n const selectedPlaylist = sourceHandler.playlists.media();\n\n if (!selectedPlaylist) {\n return;\n }\n\n const {attributes} = selectedPlaylist;\n\n if (!attributes || Object.keys(attributes).length === 0) {\n return;\n }\n\n return {\n bitrate: attributes.BANDWIDTH,\n width: (attributes.RESOLUTION || {}).width,\n height: (attributes.RESOLUTION || {}).height,\n codecs: attributes.CODECS,\n };\n }\n\n private getCodecInfo(playerTech: any): CodecInfo | undefined {\n const mediaAttributes = this.getMediaAttributes(playerTech);\n\n if (!mediaAttributes || !mediaAttributes.codecs) {\n return;\n }\n\n const codecs = mediaAttributes.codecs.split(',');\n\n if (!codecs) {\n return;\n }\n\n return {\n videoCodec: codecs.find((codec: string) => CodecHelper.isVideoCodec(codec)),\n audioCodec: codecs.find((codec: string) => CodecHelper.isAudioCodec(codec)),\n };\n }\n}\n\nexport interface MediaAttributes {\n codecs: string | undefined;\n bitrate: number | undefined;\n width: number | undefined;\n height: number | undefined;\n}\n\nexport function detectVideoJsPlaybackInfoStreamTypeFields(\n videoJsPlayer: VideoJsPlayer,\n): Pick<PlaybackInfo, 'm3u8Url' | 'mpdUrl' | 'progUrl' | 'streamFormat'> {\n const url = videoJsPlayer.currentSrc();\n\n let streamType = getStreamTypesFromURL(url);\n if (isNullish(streamType)) {\n // if we could not detect a stream type from URL, we will try to detect it from a MIME type\n const streamMimeType = videoJsPlayer.currentType?.();\n if (streamMimeType) {\n streamType = getStreamTypeFromMIMEType(streamMimeType);\n }\n }\n\n return buildPlaybackInfoStreamTypeFields(streamType, url);\n}\n","import type {HeartbeatListener} from '../core/HeartbeatService';\nimport {HeartbeatService} from '../core/HeartbeatService';\nimport {SSAI_RELATED_SAMPLE_MARKER} from '../core/ssai/ssaiUtils';\nimport {ErrorCode} from '../enums/ErrorCode';\nimport {Event, EventMap} from '../enums/Event';\nimport type {AnalyticsStateMachineOptions} from '../types/AnalyticsStateMachineOptions';\nimport type {NoExtraProperties} from '../types/NoExtraProperties';\nimport type {SourceMetadata} from '../types/SourceMetadata';\nimport {HeartbeatPayload, StateMachineCallbacks} from '../types/StateMachineCallbacks';\nimport {logger} from '../utils/Logger';\nimport * as Settings from '../utils/Settings';\nimport * as Utils from '../utils/Utils';\nimport {isNotNullish} from '../utils/Utils';\n\nconst REBUFFERING_HEARTBEAT_INTERVALS = [3000, 5000, 10000, 30000, 59700];\n\nexport abstract class AnalyticsStateMachine implements HeartbeatListener {\n protected stateMachine: StateMachine.StateMachine & {[key: string]: any};\n protected onEnterStateTimestamp = 0;\n\n protected readonly videoStartupTimeoutMs: number = Settings.ANALYTICS_VIDEOSTART_TIMEOUT;\n protected readonly rebufferTimeoutMs: number = Settings.ANALYTICS_REBUFFER_TIMEOUT;\n protected readonly playingHeartbeatService: HeartbeatService;\n\n private rebufferingHeartbeatIntervalHandle?: ReturnType<typeof setInterval>;\n private currentRebufferingIntervalIndex = 0;\n private rebufferingTimeoutHandle?: ReturnType<typeof setTimeout>;\n private videoStartTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(\n protected stateMachineCallbacks: StateMachineCallbacks,\n playingHeartbeatService: HeartbeatService,\n opts: AnalyticsStateMachineOptions,\n ) {\n this.stateMachine = this.createStateMachine(opts);\n this.playingHeartbeatService = playingHeartbeatService;\n }\n\n abstract createStateMachine(opts: AnalyticsStateMachineOptions): StateMachine.StateMachine;\n\n callEvent<StateMachineEvent extends keyof EventMap, StateMachineEventData extends EventMap[StateMachineEvent]>(\n event: StateMachineEvent,\n eventData: NoExtraProperties<EventMap[StateMachineEvent], StateMachineEventData>,\n eventTimestamp: number,\n ): void {\n const stateMachineEventMethod = this.stateMachine[event];\n\n if (stateMachineEventMethod == null) {\n // If the event (aka. the event method) is not defined in the JSM, we log a warning,\n // because it means that we are explicitly trying to call that JSM event from our code (probably adapter),\n // but it was not defined in the JSM at all. Either we are missing it or it should not be called at all!\n logger.warn(`StateMachine ignored event \"${event}\" call, because it was not defined`, eventData, eventTimestamp);\n return;\n }\n\n try {\n // By default, if you try to call an event method not allowed in the current state, the state machine will throw an exception.\n // see: https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#handling-failures\n //\n // This JSM library behavior can be changed by providing \"a custom error handler\" in the `create()`\n // method of the state machine, and we do that in every state machine!\n //\n // But we still want to have here a try-catch block, in case of unexpected state machine code,\n // to avoid propagating the exception to the rest of the application (and breaking customer app).\n stateMachineEventMethod.call(this.stateMachine, eventTimestamp, eventData);\n } catch (e) {\n logger.error(\n `StateMachine ignored event \"${event}\" call, because it has thrown exception in the current state \"${this.currentState}\"`,\n eventData,\n eventTimestamp,\n e,\n );\n }\n }\n\n get currentState(): string {\n return this.stateMachine.current;\n }\n\n resetIntervals() {\n this.clearVideoStartTimeout();\n this.clearRebufferingTimeoutHandle(true);\n this.clearRebufferingHeartbeatHandle();\n }\n\n //#region rebuffer timeout\n\n protected startRebufferingHeartbeatInterval(reset = true) {\n this.resetRebufferingHelpers(reset);\n\n this.startRebufferingTimeoutHandle();\n\n this.rebufferingHeartbeatIntervalHandle = setInterval(() => {\n const state = this.stateMachine.current.toLowerCase();\n if (state !== 'rebuffering') {\n this.resetRebufferingHelpers();\n return;\n }\n const timestamp = new Date().getTime();\n const stateDuration = timestamp - this.onEnterStateTimestamp;\n this.stateMachineCallbacks.heartbeat(stateDuration, state, {buffered: stateDuration});\n this.onEnterStateTimestamp = timestamp;\n this.currentRebufferingIntervalIndex = Math.min(\n this.currentRebufferingIntervalIndex + 1,\n REBUFFERING_HEARTBEAT_INTERVALS.length - 1,\n );\n this.startRebufferingHeartbeatInterval(false);\n }, REBUFFERING_HEARTBEAT_INTERVALS[this.currentRebufferingIntervalIndex]);\n }\n\n protected resetRebufferingHelpers(reset = true) {\n if (reset) {\n this.currentRebufferingIntervalIndex = 0;\n }\n this.clearRebufferingHeartbeatHandle();\n this.clearRebufferingTimeoutHandle(reset);\n }\n\n protected clearRebufferingHeartbeatHandle() {\n if (isNotNullish(this.rebufferingHeartbeatIntervalHandle)) {\n clearInterval(this.rebufferingHeartbeatIntervalHandle);\n this.rebufferingHeartbeatIntervalHandle = undefined;\n }\n }\n\n private startRebufferingTimeoutHandle() {\n if (this.currentRebufferingIntervalIndex > 0) {\n return;\n }\n this.rebufferingTimeoutHandle = setTimeout(() => {\n this.callEvent(\n Event.ERROR,\n {\n ...ErrorCode.BUFFERING_TIMEOUT_REACHED,\n data: {\n additionalData: `StateMachine timed out after ${this.rebufferTimeoutMs} ms of consecutive buffering.`,\n },\n },\n Utils.getCurrentTimestamp(),\n );\n this.stateMachineCallbacks.release();\n }, this.rebufferTimeoutMs);\n }\n\n protected clearRebufferingTimeoutHandle(reset: boolean) {\n if (reset && isNotNullish(this.rebufferingTimeoutHandle)) {\n clearTimeout(this.rebufferingTimeoutHandle);\n this.rebufferingTimeoutHandle = undefined;\n }\n }\n //#endregion\n\n //#region videoStartupFailed\n protected setVideoStartTimeout() {\n if (isNotNullish(this.videoStartTimeout)) {\n this.clearVideoStartTimeout();\n }\n this.videoStartTimeout = setTimeout(() => {\n this.callEvent(Event.VIDEOSTART_TIMEOUT, {}, Date.now());\n this.stateMachineCallbacks.release();\n }, this.videoStartupTimeoutMs);\n }\n\n protected clearVideoStartTimeout() {\n clearTimeout(this.videoStartTimeout);\n this.videoStartTimeout = undefined;\n }\n //#endregion\n\n onHeartbeat(playerCurrentTime: number): void {\n this.sendPlayingSample(Date.now(), playerCurrentTime);\n }\n\n /**\n * Should be used in the \"PLAYING\" state only, and only by \"SSAI\", \"ProgramChange\" and \"Playing Heartbeat\" features,\n * otherwise it will log a warning and do nothing!\n *\n * It calls the {@link StateMachineCallbacks.heartbeat} callback, to send out the current playing sample (it cuts\n * current PLAYING state) and resets time measurements to set a new start of PLAYING state again with new timestamp\n * and video time. So the next sample will be sent with the duration from the last cut.\n *\n * We have chosen to use {@link StateMachineCallbacks.heartbeat} callback here, because it was the easiest and the\n * fastest way to trigger 'playing' sample sending (with additional properties like \"ssai marker\"), without changing\n * and refactoring too much code, in future this code should be refactored with better naming.\n *\n * @param timestamp current timestamp\n * @param playerCurrentTime the current player playback time of the video in seconds\n * @param triggeredBySsai boolean to mark the sample as SSAI triggered\n * @param triggeredByProgramChange boolean to mark the sample as ProgramChange triggered\n */\n sendPlayingSample(\n timestamp: number,\n playerCurrentTime: number,\n triggeredBySsai = false,\n triggeredByProgramChange = false,\n ) {\n const state = this.stateMachine.current.toLowerCase();\n // We don't allow this in any other state because it could interrupt the natural flow of the states.\n // Only PLAYING is considered a state which we can interrupt/cut by heartbeat or SSAI interaction.\n if (state !== 'playing') {\n // our logic for \"SSAI\" and \"playing heartbeat\" is built on the assumption that we send only 'playing' samples,\n // but that \"if\" restriction is spread across the codebase, so we need to log a warning here, to see a potential\n // problems in our logic, if reported by from customer and report will contain these logs\n logger.warn(`Unexpected call of \"sendPlayingSample\" in AnalyticsStateMachine from \"${state}\" state`);\n return;\n }\n\n this.stateMachineCallbacks.setVideoTimeEndFromEvent({currentTime: playerCurrentTime});\n\n const stateDuration = timestamp - this.onEnterStateTimestamp;\n const payload: HeartbeatPayload = {\n played: stateDuration,\n isProgramChange: triggeredByProgramChange ? true : undefined,\n };\n\n if (triggeredBySsai) {\n payload[SSAI_RELATED_SAMPLE_MARKER] = true;\n }\n\n this.stateMachineCallbacks.heartbeat(stateDuration, state, payload);\n\n this.resetCurrentStateStart(timestamp, playerCurrentTime);\n }\n\n private resetCurrentStateStart(stateEnterTimestamp: number, playerCurrentTime: number): void {\n this.onEnterStateTimestamp = stateEnterTimestamp;\n this.stateMachineCallbacks.setVideoTimeStartFromEvent({currentTime: playerCurrentTime});\n }\n\n programChange(playerCurrentTime: number, isSsaiActive: boolean, sourceMetadata: SourceMetadata): void {\n // if program change happens before or during STARTUP (or other \"startup state\", like bitmovin8 STARTUP_AUTOPLAY),\n // we don't want to do any \"cut\", because it has not started yet, we just want to update source metadata\n // and wait for the natural start\n if (\n this.stateMachine.current === 'SETUP' ||\n this.stateMachine.current === 'READY' ||\n this.stateMachine.current === 'STARTUP' ||\n this.stateMachine.current === 'STARTUP_AUTOPLAY'\n ) {\n this.stateMachineCallbacks.updateSourceMetadata(sourceMetadata);\n return;\n }\n\n const programChangeTimestamp = Date.now();\n\n // If the program change happens during PLAYING state, we want to \"cut it\" and send asap last playing sample\n // of the previous program (session) with the duration from the start of PLAYING state to the program change\n if (this.stateMachine.current === 'PLAYING') {\n this.sendPlayingSample(programChangeTimestamp, playerCurrentTime, isSsaiActive, true);\n }\n // ... else in any other state, we just want to reset time measurements to set a new start of the current state\n else {\n this.resetCurrentStateStart(programChangeTimestamp, playerCurrentTime);\n }\n\n this.stateMachineCallbacks.programChange(sourceMetadata);\n }\n}\n","import {create} from 'javascript-state-machine';\n\nimport {Event, JSM_INITIAL_EVENT} from '../enums/Event';\nimport {createVideoStartFailedReason} from '../enums/VideoStartFailedReason';\nimport type {AnalyticsStateMachineOptions} from '../types/AnalyticsStateMachineOptions';\nimport {AnalyticsEventBase} from '../types/EventData';\nimport {logger} from '../utils/Logger';\nimport {isNumber} from '../utils/numberUtils';\nimport {isFunction} from '../utils/Utils';\n\nimport {AnalyticsStateMachine} from './AnalyticsStateMachine';\nimport {\n customStateMachineErrorCallback,\n getAllStatesBut,\n logMissingCallbackWarning,\n logStateMachineTransition,\n whileIn,\n} from './stateMachineUtils';\n\nexport enum State {\n /**\n * This state was created only to be able to \"cut\" the {@link State.PLAYING} and {@link State.PAUSE}\n * and send playing/pause sample with current custom data, while calling {@link AdapterAPI.setCustomData} function\n * and setting the new custom data values.\n *\n * @remarks\n *\n * Our implementation relays on a specific state name \"CUSTOMDATACHANGE\" because it should call the\n * default \"onleavestate\" state machine callback {@link stateMachineCallbacks.customdatachange}.\n */\n CUSTOMDATACHANGE = 'CUSTOMDATACHANGE',\n ERROR = 'ERROR',\n PAUSE = 'PAUSE',\n PLAYING = 'PLAYING',\n READY = 'READY',\n /**\n * We track and consider the rebuffering state only when it comes from the {@link State.PLAYING},\n * aka. when the video was playing and stopped because it started to rebuffer.\n */\n REBUFFERING = 'REBUFFERING',\n /**\n * We track and consider the \"seeking\" state only when it comes from the {@link State.PLAYING},\n * aka. when the video has already started to play and is already playing.\n */\n SEEKING = 'SEEKING',\n /**\n * We do not track the \"seeking\" while the playback is paused!\n *\n * We should not produce a \"seeking\" sample, but rather we should just extend the existing \"pause\" sample.\n *\n * Why do we recognize this state?\n * - because during the seeking, {@link Event.TIMECHANGED} is fired and if we would just use {@link State.PAUSE},\n * it would trigger a JSM transition to {@link State.PLAYING} and break the tracking of current pause.\n * - because once seeking is finished, we need to transition the JSM back to {@link State.PAUSE}\n *\n * @remarks\n *\n * To be sure state machine works correctly, we need to be sure only calling {@link Event.SEEK} from\n * {@link State.PAUSE} should transition JSM to {@link State.SEEKING_IN_PAUSE}!\n */\n SEEKING_IN_PAUSE = 'SEEKING_IN_PAUSE',\n SETUP = 'SETUP',\n SOURCE_CHANGING = 'SOURCE_CHANGING',\n STARTUP = 'STARTUP',\n /**\n * The browser window was closed (window 'unload' event), aka. sender has stopped the casting\n */\n UNLOADED = 'UNLOADED',\n VIDEOSTART_FAILED = 'VIDEOSTART_FAILED',\n}\n\nexport class CAFv3AnalyticsStateMachine extends AnalyticsStateMachine {\n override createStateMachine(opts: AnalyticsStateMachineOptions): StateMachine.StateMachine {\n return create({\n // custom initial state and custom JSM initial event name\n // initial event is used by JSM for the initial state transition 'none' -> 'SETUP'\n initial: {state: State.SETUP, event: JSM_INITIAL_EVENT},\n error: customStateMachineErrorCallback,\n events: [\n ...whileIn(State.SETUP).passOver(\n // We track and consider the rebuffering state only when it comes from the State.PLAYING\n Event.START_BUFFERING,\n ),\n\n {name: Event.SOURCE_LOADED, from: State.SETUP, to: State.READY},\n {name: Event.READY, from: State.SETUP, to: State.READY},\n\n ...whileIn(State.READY).passOver(\n Event.READY,\n // We track and consider the rebuffering state only when it comes from the State.PLAYING\n Event.START_BUFFERING,\n Event.END_BUFFERING,\n // this will fire whenever the currentTime attribute changes\n Event.TIMECHANGED,\n Event.SEEK,\n Event.SEEKED,\n ),\n\n {name: Event.PLAY, from: State.READY, to: State.STARTUP},\n\n {name: Event.ERROR, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.UNLOAD, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.VIDEOSTART_TIMEOUT, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n\n {name: Event.ERROR, from: getAllStatesBut([State.STARTUP], State), to: State.ERROR},\n {name: Event.UNLOAD, from: getAllStatesBut([State.STARTUP], State), to: State.UNLOADED},\n\n // We need to wait for the 'TIME_UPDATE' event to also include startup video buffering in State.STARTUP time.\n //\n // We shouldn't use 'PLAYING' event, because that event is fired immediately, followed by buffering events that\n // would cut State.STARTUP sooner, then move us to State.PLAYING and then even to State.REBUFFERING.\n {name: Event.TIMECHANGED, from: State.STARTUP, to: State.PLAYING},\n ...whileIn(State.PLAYING).passOver(Event.TIMECHANGED),\n\n {name: Event.START_BUFFERING, from: State.PLAYING, to: State.REBUFFERING},\n // While in State.REBUFFERING, we are waiting for 'TIME_UPDATE' event to be able to recognize end of the\n // rebuffering and to return back to State.PLAYING. The relay also on fact that State.REBUFFERING can only\n // start from State.PLAYING.\n //\n // We tried to use the 'BUFFERING' event containing `isBuffering: false`, but that was not reliable,\n // because of a scenario when the 'error' event would happen while rebuffering (because of rebuffering timeout\n // or Shaka player throwing error). Because this 'BUFFERING' event is also fired when player throws error, and\n // it would transition us to State.PLAYING and then it would send the short \"playing\" sample, before 'ERROR'\n // event would be fired and would move us to State.ERROR.\n {name: Event.TIMECHANGED, from: State.REBUFFERING, to: State.PLAYING},\n\n {name: Event.PAUSE, from: State.PLAYING, to: State.PAUSE},\n {name: Event.PAUSE, from: State.REBUFFERING, to: State.PAUSE},\n // if a 'PAUSE' event happens during State.SEEKING, we need to transition to State.PAUSE\n // instead of recovering back State.PLAYING (where State.SEEKING was started from)\n {name: Event.PAUSE, from: State.SEEKING, to: State.PAUSE},\n ...whileIn(State.PAUSE).passOver(\n // We track and consider the rebuffering state only when it comes from the State.PLAYING\n Event.START_BUFFERING,\n Event.END_BUFFERING,\n ),\n // We use Event.PLAYING because it is more reliable for tracking transition from State.PAUSE to State.PLAYING.\n //\n // We shouldn't use 'TIME_UPDATE' to interrupt State.PAUSE, because that event is fired when the time indicated\n // by the currentTime property has been updated.\n // Example: this happens when a user clicks 'PAUSE' during the seeking. Our state machine should move to\n // State.PAUSE asap, but later because of the seeking, the events 'SEEKED' and 'TIME_UPDATE' are still fired,\n // and that would break our state machine as we would end up in State.PLAYING\n {name: Event.PLAYING, from: State.PAUSE, to: State.PLAYING},\n\n {name: Event.SEEK, from: State.PAUSE, to: State.SEEKING_IN_PAUSE},\n ...whileIn(State.SEEKING_IN_PAUSE).passOver(\n Event.SEEK,\n // We track and consider the rebuffering state only when it comes from the State.PLAYING\n Event.START_BUFFERING,\n Event.END_BUFFERING,\n // this will fire whenever the currentTime attribute changes\n Event.TIMECHANGED,\n ),\n {name: Event.SEEKED, from: State.SEEKING_IN_PAUSE, to: State.PAUSE},\n\n {name: Event.SEEK, from: State.PLAYING, to: State.SEEKING},\n ...whileIn(State.SEEKING).passOver(\n Event.SEEK,\n // We track and consider the rebuffering state only when it comes from the State.PLAYING\n Event.START_BUFFERING,\n Event.END_BUFFERING,\n // this will fire whenever the currentTime attribute changes\n Event.TIMECHANGED,\n ),\n {name: Event.SEEKED, from: State.SEEKING, to: State.PLAYING},\n\n {\n name: Event.MANUAL_SOURCE_CHANGE,\n // We dont track source change during SETUP\n from: getAllStatesBut([State.SETUP], State),\n to: State.SOURCE_CHANGING,\n },\n ...whileIn(State.SOURCE_CHANGING).passOver(Event.START_BUFFERING, Event.TIMECHANGED),\n // Once the source is loaded, we are READY to receive play interaction\n {name: Event.SOURCE_LOADED, from: State.SOURCE_CHANGING, to: State.READY},\n\n // Because of this state transition, we are able to male \"a cut\" in the current PLAYING / PAUSE state\n // and send \"playing\" / \"pause\" sample with the current custom data values. The new changed custom data values\n // will be set on upcoming samples after we transition back from the CUSTOMDATACHANGE state.\n // For any other states, we don't care, because InternalAdapter is not emitting the event.\n {name: Event.CUSTOM_DATA_CHANGE, from: [State.PLAYING, State.PAUSE], to: State.CUSTOMDATACHANGE},\n {name: Event.PLAYING, from: State.CUSTOMDATACHANGE, to: State.PLAYING},\n {name: Event.PAUSE, from: State.CUSTOMDATACHANGE, to: State.PAUSE},\n ],\n\n callbacks: {\n [`onleave${State.PLAYING}`]: () => {\n this.playingHeartbeatService.stopHeartbeat();\n },\n\n [`onleave${State.STARTUP}`]: () => {\n this.clearVideoStartTimeout();\n },\n\n onleavestate: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n logStateMachineTransition('LEAVE', event, from, to);\n\n // Skip this JSM callback for JSM initial event\n // This event is fired when the state machine is constructed,\n // to transition us from 'none' to custom initial 'SETUP' state\n if (event === JSM_INITIAL_EVENT) {\n return;\n }\n\n if (from === State.REBUFFERING) {\n this.resetRebufferingHelpers();\n }\n\n // Skip this JSM callback when an JSM event without a timestamp is called,\n // because it would cause NPE in analytics code (state duration calculation etc.).\n // This probably has happened because the state machine was not used correctly,\n // aka. JSM event was not called via `callEvent` method as it should be!\n if (!eventTimestamp) {\n return;\n }\n\n // Skip \"default onleavestate analytics state machine callback\" when leaving ERROR state,\n // because we call \"error\" state machine callback asap in \"onafterEVENT\" handler\n if (from === State.ERROR) {\n return;\n }\n\n // Skip, because we should ignore and do not track the \"seeking\" while the playback is paused\n // This means we should not use any callbacks, nor set any state properties\n if (\n (from === State.PAUSE && to === State.SEEKING_IN_PAUSE) ||\n (from === State.SEEKING_IN_PAUSE && to === State.PAUSE)\n ) {\n return;\n }\n\n // When leaving a state, before calling any callback (sending sample), we should set a correct sample `videoTimeEnd`\n if (eventData) {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n }\n\n const stateDuration = eventTimestamp - this.onEnterStateTimestamp;\n const lowerCaseFrom = String(from).toLowerCase();\n\n // Calling a custom callback when leaving STARTUP into STARTUP_FAILURE\n if (from === State.STARTUP && to === State.VIDEOSTART_FAILED) {\n this.stateMachineCallbacks.videoStartFailed(stateDuration, createVideoStartFailedReason(event));\n return;\n }\n\n // Calling a custom callback when leaving SEEKING (started in the PAUSE/PLAY state)\n if (from === State.SEEKING) {\n this.stateMachineCallbacks.seeking(stateDuration);\n return;\n }\n\n // Calling a custom callback handling UNLOAD event\n if (event === Event.UNLOAD) {\n this.stateMachineCallbacks.unload(stateDuration, lowerCaseFrom);\n return;\n }\n\n // Default \"onleavestate\" state machine callback\n //\n // Every time, when we leave a state, we should try to call \"state\" callback,\n // to be able to make \"a cut\" and send analytics sample (if necessary)\n const defaultStateMachineCallbackFn = this.stateMachineCallbacks[lowerCaseFrom];\n if (isFunction(defaultStateMachineCallbackFn)) {\n // a try-catch block to add more resilience against callback errors\n try {\n defaultStateMachineCallbackFn(stateDuration, lowerCaseFrom, eventData);\n } catch (e) {\n logger.error('Exception occurred in State Machine callback ' + lowerCaseFrom, eventData, e);\n }\n } else {\n // if callback is not defined, log a warning to indicate to the developer that\n // - a new callback function needs to be implemented to relay on this default state machine callback\n // - or if no callback is needed, we should\n // - early return from this JSM callback\n // - or add this state to the ignored list\n logMissingCallbackWarning(from, [State.READY, State.SOURCE_CHANGING]);\n }\n },\n\n [`onenter${State.PLAYING}`]: () => {\n this.playingHeartbeatService.startHeartbeat();\n },\n\n [`onenter${State.SOURCE_CHANGING}`]: (_event, _from, _to, _eventTimestamp, eventData) => {\n this.stateMachineCallbacks.manualSourceChange(eventData);\n },\n\n [`onenter${State.STARTUP}`]: () => {\n this.setVideoStartTimeout();\n },\n\n onenterstate: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n logStateMachineTransition('ENTER', event, from, to);\n\n // Skip, because we should ignore and do not track the \"seeking\" while the playback is paused\n // This means we should not use any callbacks, nor set any state properties\n if (\n (from === State.PAUSE && to === State.SEEKING_IN_PAUSE) ||\n (from === State.SEEKING_IN_PAUSE && to === State.PAUSE)\n ) {\n return;\n }\n\n this.onEnterStateTimestamp = eventTimestamp ?? Date.now();\n // if customer set custom \"start time\" timestamp in AnalyticsStateMachineOptions of adapter constructor,\n // use it and override `onEnterStateTimestamp` during JSM initialization (transition to initial SETUP state)\n if (isNumber(opts.starttime) && event === JSM_INITIAL_EVENT) {\n this.onEnterStateTimestamp = opts.starttime;\n }\n\n if (eventData) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n }\n\n if (to === State.REBUFFERING) {\n this.startRebufferingHeartbeatInterval();\n }\n },\n\n [`onafter${Event.ERROR}`]: (_event, _from, _to, _eventTimestamp, eventData) => {\n this.stateMachineCallbacks.error(eventData);\n },\n },\n });\n }\n}\n","import * as StateMachine from 'javascript-state-machine';\n\nimport type {HeartbeatService} from '../core/HeartbeatService';\nimport {Event, JSM_INITIAL_EVENT} from '../enums/Event';\nimport {createVideoStartFailedReason} from '../enums/VideoStartFailedReason';\nimport type {AnalyticsStateMachineOptions} from '../types/AnalyticsStateMachineOptions';\nimport type {StateMachineCallbacks} from '../types/StateMachineCallbacks';\nimport {logger} from '../utils/Logger';\nimport {isNumber} from '../utils/numberUtils';\nimport {isFunction} from '../utils/Utils';\n\nimport {AnalyticsStateMachine} from './AnalyticsStateMachine';\nimport {\n customStateMachineErrorCallback,\n logMissingCallbackWarning,\n logStateMachineTransition,\n on,\n whileIn,\n} from './stateMachineUtils';\n\nenum State {\n AD = 'AD',\n AUDIOTRACK_CHANGING = 'AUDIOTRACK_CHANGING',\n CASTING = 'CASTING',\n /**\n * This state was created only to be able to \"cut\" the {@link State.PLAYING} and {@link State.PAUSE}\n * and send playing/pause sample with current custom data, while calling {@link AdapterAPI.setCustomData} function\n * and setting the new custom data values.\n *\n * @remarks\n *\n * Our implementation relays on a specific state name \"CUSTOMDATACHANGE\" because it should call the\n * default \"onleavestate\" state machine callback {@link stateMachineCallbacks.customdatachange}.\n */\n CUSTOMDATACHANGE = 'CUSTOMDATACHANGE',\n END = 'END',\n ERROR = 'ERROR',\n MUTING_PAUSE = 'MUTING_PAUSE',\n MUTING_PLAY = 'MUTING_PLAY',\n MUTING_READY = 'MUTING_READY',\n PAUSE = 'PAUSE',\n PAUSED_SEEKING = 'PAUSED_SEEKING',\n PLAYING = 'PLAYING',\n QUALITY_CHANGE = 'QUALITY_CHANGE',\n READY = 'READY',\n REBUFFERING = 'REBUFFERING',\n SETUP = 'SETUP',\n SETUP_SOURCE_CHANGE = 'SETUP_SOURCE_CHANGE',\n SOURCE_CHANGING = 'SOURCE_CHANGING',\n STARTUP = 'STARTUP',\n SUBTITLE_CHANGING = 'SUBTITLE_CHANGING',\n VIDEOSTART_FAILED = 'VIDEOSTART_FAILED',\n}\n\nexport class HTML5AnalyticsStateMachine extends AnalyticsStateMachine {\n constructor(\n stateMachineCallbacks: StateMachineCallbacks,\n playingHeartbeatService: HeartbeatService,\n opts: AnalyticsStateMachineOptions,\n ) {\n super(stateMachineCallbacks, playingHeartbeatService, opts);\n\n this.createStateMachine(opts);\n }\n\n getAllStates() {\n return [...Object.keys(State).map((key) => State[key])];\n }\n\n getAllStatesBut(states: string[]) {\n return this.getAllStates().filter((i) => states.indexOf(i) < 0);\n }\n\n override createStateMachine(opts: AnalyticsStateMachineOptions) {\n return StateMachine.create({\n // custom initial state and custom JSM initial event name\n // initial event is used by JSM for the initial state transition 'none' -> 'SETUP'\n initial: {state: State.SETUP, event: JSM_INITIAL_EVENT},\n error: customStateMachineErrorCallback,\n events: [\n {\n name: Event.SOURCE_LOADED,\n from: [State.SETUP, State.SETUP_SOURCE_CHANGE, State.SOURCE_CHANGING],\n to: State.READY,\n },\n\n // just passing since it's pushed in a live stream\n ...whileIn(State.READY).passOver(Event.SEEK, Event.SEEKED),\n\n on(Event.TIMECHANGED).stayIn(State.SETUP),\n on(Event.SOURCE_LOADED).stayIn(State.READY),\n\n {name: Event.PLAY, from: State.READY, to: State.STARTUP},\n // play attempt during sourceChanging\n {name: Event.PLAY, from: State.SOURCE_CHANGING, to: State.STARTUP},\n\n {name: Event.ERROR, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.UNLOAD, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.VIDEOSTART_TIMEOUT, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n\n ...whileIn(State.STARTUP).passOver(\n Event.SOURCE_LOADED, // when we have autoplay we will receive SOURCE_LOADED after we enter the STARTUP state\n Event.START_BUFFERING,\n Event.END_BUFFERING,\n Event.VIDEO_CHANGE,\n Event.AUDIO_CHANGE,\n Event.SEEK, // just passing since it's pushed in a live stream\n Event.SEEKED, // just passing since it's pushed in a live stream\n ),\n\n {name: Event.TIMECHANGED, from: State.READY, to: State.STARTUP},\n {name: Event.TIMECHANGED, from: State.STARTUP, to: State.PLAYING},\n ...whileIn(State.PLAYING).passOver(Event.TIMECHANGED),\n\n on(Event.SEEKED).stayIn(State.PAUSE),\n\n on(Event.END_BUFFERING).stayIn(State.PLAYING),\n {name: Event.START_BUFFERING, from: State.PLAYING, to: State.REBUFFERING},\n on(Event.START_BUFFERING).stayIn(State.REBUFFERING),\n\n {name: Event.PLAY, from: State.REBUFFERING, to: State.PLAYING},\n {name: Event.TIMECHANGED, from: State.REBUFFERING, to: State.PLAYING},\n\n {name: Event.PAUSE, from: State.PLAYING, to: State.PAUSE},\n {name: Event.PAUSE, from: State.REBUFFERING, to: State.PAUSE},\n\n {name: Event.PLAY, from: State.PAUSE, to: State.PLAYING},\n {name: Event.TIMECHANGED, from: State.PAUSE, to: State.PLAYING},\n\n {name: Event.VIDEO_CHANGE, from: State.PLAYING, to: State.QUALITY_CHANGE},\n {name: Event.AUDIO_CHANGE, from: State.PLAYING, to: State.QUALITY_CHANGE},\n {name: Event.FINISH_QUALITY_CHANGE, from: State.QUALITY_CHANGE, to: State.PLAYING},\n\n {name: Event.SEEK, from: State.PAUSE, to: State.PAUSED_SEEKING},\n ...whileIn(State.PAUSED_SEEKING).passOver(Event.PLAY, Event.SEEK, Event.START_BUFFERING, Event.END_BUFFERING),\n\n {name: Event.SEEKED, from: State.PAUSED_SEEKING, to: State.PAUSE},\n {name: Event.TIMECHANGED, from: State.PAUSED_SEEKING, to: State.PLAYING},\n {name: Event.PAUSE, from: State.PAUSED_SEEKING, to: State.PAUSE},\n\n {name: Event.END, from: State.PAUSED_SEEKING, to: State.END},\n {name: Event.END, from: State.PLAYING, to: State.END},\n {name: Event.END, from: State.PAUSE, to: State.END},\n ...whileIn(State.END).passOver(\n Event.PAUSE,\n Event.SEEK,\n Event.SEEKED,\n Event.TIMECHANGED,\n Event.END_BUFFERING,\n Event.START_BUFFERING,\n Event.END,\n ),\n\n // just passing since it's pushed in a live stream\n ...whileIn(State.PLAYING).passOver(Event.SEEK, Event.SEEKED),\n\n {name: Event.PLAY, from: State.END, to: State.PLAYING},\n\n {name: Event.ERROR, from: this.getAllStatesBut([State.STARTUP]), to: State.ERROR},\n {name: Event.PAUSE, from: State.ERROR, to: State.ERROR},\n\n {name: Event.UNLOAD, from: this.getAllStatesBut([State.STARTUP]), to: State.END},\n\n {name: Event.SUBTITLE_CHANGE, from: State.PLAYING, to: State.SUBTITLE_CHANGING},\n\n on(Event.SUBTITLE_CHANGE).stayIn(State.PAUSE),\n on(Event.SUBTITLE_CHANGE).stayIn(State.READY),\n on(Event.SUBTITLE_CHANGE).stayIn(State.STARTUP),\n on(Event.SUBTITLE_CHANGE).stayIn(State.REBUFFERING),\n on(Event.SUBTITLE_CHANGE).stayIn(State.SUBTITLE_CHANGING),\n\n {name: Event.TIMECHANGED, from: State.SUBTITLE_CHANGING, to: State.PLAYING},\n\n {name: Event.AUDIOTRACK_CHANGED, from: State.PLAYING, to: State.AUDIOTRACK_CHANGING},\n\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.PAUSE),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.READY),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.STARTUP),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.REBUFFERING),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.AUDIOTRACK_CHANGING),\n {name: Event.TIMECHANGED, from: State.AUDIOTRACK_CHANGING, to: State.PLAYING},\n\n {name: Event.START_AD, from: State.PLAYING, to: State.AD},\n {name: Event.END_AD, from: State.AD, to: State.PLAYING},\n\n {name: Event.MUTE, from: State.READY, to: State.MUTING_READY},\n {name: Event.UN_MUTE, from: State.READY, to: State.MUTING_READY},\n {name: 'FINISH_MUTING', from: State.MUTING_READY, to: State.READY},\n\n {name: Event.MUTE, from: State.PLAYING, to: State.MUTING_PLAY},\n {name: Event.UN_MUTE, from: State.PLAYING, to: State.MUTING_PLAY},\n {name: 'FINISH_MUTING', from: State.MUTING_PLAY, to: State.PLAYING},\n\n {name: Event.MUTE, from: State.PAUSE, to: State.MUTING_PAUSE},\n {name: Event.UN_MUTE, from: State.PAUSE, to: State.MUTING_PAUSE},\n {name: 'FINISH_MUTING', from: State.MUTING_PAUSE, to: State.PAUSE},\n\n {name: Event.START_CAST, from: [State.READY, State.PAUSE], to: State.CASTING},\n ...whileIn(State.CASTING).passOver(\n Event.PAUSE,\n Event.PLAY,\n Event.TIMECHANGED,\n Event.MUTE,\n Event.SEEK,\n Event.SEEKED,\n ),\n\n {name: Event.END_CAST, from: State.CASTING, to: State.READY},\n\n {name: Event.MANUAL_SOURCE_CHANGE, from: State.SETUP, to: State.SETUP_SOURCE_CHANGE},\n on(Event.MANUAL_SOURCE_CHANGE).stayIn(State.SETUP_SOURCE_CHANGE),\n {\n name: Event.MANUAL_SOURCE_CHANGE,\n from: this.getAllStatesBut([State.SETUP, State.SETUP_SOURCE_CHANGE]),\n to: State.SOURCE_CHANGING,\n },\n {name: Event.SOURCE_UNLOADED, from: this.getAllStates(), to: State.SOURCE_CHANGING},\n\n on(Event.TIMECHANGED).stayIn(State.SOURCE_CHANGING),\n on(Event.PAUSE).stayIn(State.SOURCE_CHANGING),\n\n // Because of this state transition, we are able to male \"a cut\" in the current PLAYING / PAUSE state\n // and send \"playing\" / \"pause\" sample with the current custom data values. The new changed custom data values\n // will be set on upcoming samples after we transition back from the CUSTOMDATACHANGE state.\n // For any other states, we don't care, because InternalAdapter is not emitting the event.\n {name: Event.CUSTOM_DATA_CHANGE, from: [State.PLAYING, State.PAUSE], to: State.CUSTOMDATACHANGE},\n {name: Event.PLAYING, from: State.CUSTOMDATACHANGE, to: State.PLAYING},\n {name: Event.PAUSE, from: State.CUSTOMDATACHANGE, to: State.PAUSE},\n ],\n\n // Keep callbacks sorted by order in which they are called by JSM library (and after order, sorted by name)\n //\n // Do not use convenience, shortened callbacks\n // - instead of `onEVENT` use `onafterEVENT`\n // - instead of `onSTATE` use `onenterSTATE`\n //\n // see: https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#callbacks\n callbacks: {\n [`onleave${State.PLAYING}`]: (_event, _from, _to, _eventTimestamp, _eventData) => {\n this.playingHeartbeatService.stopHeartbeat();\n },\n\n [`onleave${State.STARTUP}`]: (_event, _from, _to, _eventTimestamp, _eventData) => {\n this.clearVideoStartTimeout();\n },\n\n onleavestate: (event, from, to, eventTimestamp, eventData) => {\n logStateMachineTransition('LEAVE', event, from, to);\n\n // Skip this JSM callback for JSM initial event\n // This event is fired when the state machine is constructed,\n // to transition us from 'none' to custom initial 'SETUP' state\n if (event === JSM_INITIAL_EVENT) {\n return;\n }\n\n if (from === State.REBUFFERING) {\n this.resetRebufferingHelpers();\n }\n\n // Skip this JSM callback when an JSM event without a timestamp is called,\n // because it would cause NPE in analytics code (state duration calculation etc.).\n // This probably has happened because the state machine was not used correctly,\n // aka. JSM event was not called via `callEvent` method as it should be!\n if (!eventTimestamp) {\n return;\n }\n\n // player errors will be sent via eventCallback() -> callEvent() -> onPlayerError() function chain\n // if then sourceChange is called same error will be sent second time\n if (from === State.ERROR && (event === Event.MANUAL_SOURCE_CHANGE || event === Event.SOURCE_UNLOADED)) {\n return;\n }\n\n const stateDuration = eventTimestamp - this.onEnterStateTimestamp;\n\n if (eventData && to !== State.PAUSED_SEEKING) {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n }\n\n const lowerCaseFrom = String(from).toLowerCase();\n if (to === State.VIDEOSTART_FAILED) {\n this.clearVideoStartTimeout();\n this.stateMachineCallbacks.videoStartFailed(stateDuration, createVideoStartFailedReason(event));\n } else if (from === State.PAUSED_SEEKING) {\n this.stateMachineCallbacks.seeking(stateDuration);\n } else if (event === Event.UNLOAD) {\n this.stateMachineCallbacks.unload(stateDuration, lowerCaseFrom);\n } else if (from === State.PAUSE && to !== State.PAUSED_SEEKING) {\n this.stateMachineCallbacks.pause(stateDuration, lowerCaseFrom);\n } else {\n // Default \"onleavestate\" state machine callback\n //\n // Every time, when we leave a state, we should try to call \"state\" callback,\n // to be able to make \"a cut\" and send analytics sample (if necessary)\n const defaultStateMachineCallbackFn = this.stateMachineCallbacks[lowerCaseFrom];\n if (isFunction(defaultStateMachineCallbackFn)) {\n // a try-catch block to add more resilience against callback errors\n try {\n defaultStateMachineCallbackFn(stateDuration, lowerCaseFrom, eventData);\n } catch (e) {\n logger.error('Exception occurred in State Machine callback ' + lowerCaseFrom, eventData, e);\n }\n } else {\n // if callback is not defined, log a warning to indicate to the developer that\n // - a new callback function needs to be implemented to relay on this default state machine callback\n // - or if no callback is needed, we should\n // - early return from this JSM callback\n // - or add this state to the ignored list\n logMissingCallbackWarning(from, [State.READY, State.SOURCE_CHANGING, State.SETUP_SOURCE_CHANGE]);\n }\n }\n\n if (eventData && to !== State.PAUSED_SEEKING) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n }\n\n if (event === Event.MUTE) {\n this.stateMachineCallbacks.mute();\n } else if (event === Event.UN_MUTE) {\n this.stateMachineCallbacks.unMute();\n }\n },\n\n [`onenter${State.PLAYING}`]: (_event, _from, _to, eventTimestamp, _eventData) => {\n this.onEnterStateTimestamp = eventTimestamp;\n this.playingHeartbeatService.startHeartbeat();\n },\n\n [`onenter${State.SOURCE_CHANGING}`]: (event, _from, _to, _eventTimestamp, eventData) => {\n if (event === Event.MANUAL_SOURCE_CHANGE) {\n this.stateMachineCallbacks.manualSourceChange(eventData);\n }\n },\n\n [`onenter${State.STARTUP}`]: (_event, _from, _to, _eventTimestamp, _eventData) => {\n this.setVideoStartTimeout();\n },\n\n [`onenter${State.QUALITY_CHANGE}`]: (_event, _from, _to, eventTimestamp, eventData) => {\n // Quality change should produce a \"signal sample\" and immediately transition us back to PLAYING state\n this.stateMachineCallbacks.qualitychange(eventData);\n this.stateMachine[Event.FINISH_QUALITY_CHANGE](eventTimestamp);\n },\n\n onenterstate: (event, from, to, eventTimestamp: number, eventData) => {\n logStateMachineTransition('ENTER', event, from, to);\n\n this.onEnterStateTimestamp = eventTimestamp ?? Date.now();\n // if customer set custom \"start time\" timestamp in AnalyticsStateMachineOptions of adapter constructor,\n // use it and override `onEnterStateTimestamp` during JSM initialization (transition to initial SETUP state)\n if (isNumber(opts.starttime) && event === JSM_INITIAL_EVENT) {\n this.onEnterStateTimestamp = opts.starttime;\n }\n\n if (eventData && to !== State.PAUSED_SEEKING) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n }\n\n if (event === Event.START_CAST && to === State.CASTING) {\n this.stateMachineCallbacks.startCasting(eventTimestamp, eventData);\n }\n\n if (to === State.REBUFFERING) {\n this.startRebufferingHeartbeatInterval();\n }\n },\n\n [`onafter${Event.ERROR}`]: (_event, _from, _to, _eventTimestamp, eventData) => {\n this.stateMachineCallbacks.error(eventData);\n },\n\n onafterevent: (_event, _from, to, eventTimestamp, _eventData) => {\n if (to === State.MUTING_READY || to === State.MUTING_PLAY || to === State.MUTING_PAUSE) {\n this.stateMachine.FINISH_MUTING(eventTimestamp);\n }\n },\n },\n });\n }\n}\n","import {create, StateMachine} from 'javascript-state-machine';\n\nimport type {HeartbeatService} from '../core/HeartbeatService';\nimport {Event, JSM_INITIAL_EVENT} from '../enums/Event';\nimport {createVideoStartFailedReason, VideoStartFailedReason} from '../enums/VideoStartFailedReason';\nimport type {AnalyticsStateMachineOptions} from '../types/AnalyticsStateMachineOptions';\nimport type {AnalyticsEventBase, CustomDataValuesEvent, ErrorEvent, QualityChangeEvent} from '../types/EventData';\nimport type {StateMachineCallbacks} from '../types/StateMachineCallbacks';\nimport {isNumber} from '../utils/numberUtils';\n\nimport {AnalyticsStateMachine} from './AnalyticsStateMachine';\nimport {customStateMachineErrorCallback, getAllStatesBut, logStateMachineTransition} from './stateMachineUtils';\n\nexport enum State {\n // handles ads in the middle of playback (midroll & postroll ads)\n AD_PLAYBACK = 'AD_PLAYBACK',\n // handles ad that occur during startup aka preroll ads\n AD_PLAYBACK_IN_STARTUP = 'AD_PLAYBACK_IN_STARTUP',\n\n /**\n * This state was created only to be able to \"cut\" the {@link State.PLAYING} and {@link State.PAUSE}\n * and send playing/pause sample with current custom data, while calling {@link AdapterAPI.setCustomData} function\n * and setting the new custom data values.\n *\n * @remarks\n *\n * Our implementation relays on a specific state name \"CUSTOMDATACHANGE\" because it should call the\n * default \"onleavestate\" state machine callback {@link stateMachineCallbacks.customdatachange}.\n */\n CUSTOMDATACHANGE = 'CUSTOMDATACHANGE',\n ERROR = 'ERROR',\n PAUSE = 'PAUSE',\n PLAYING = 'PLAYING',\n QUALITY_CHANGE = 'QUALITY_CHANGE',\n READY = 'READY',\n /**\n * We track and consider the rebuffering state only when it comes from the {@link State.PLAYING},\n * aka. when the video was playing and stopped because it started to rebuffer.\n */\n REBUFFERING = 'REBUFFERING',\n /**\n * We track and consider the \"seeking\" state only when it comes from the {@link State.PLAYING},\n * aka. when the video has already started to play and is already playing.\n */\n SEEKING = 'SEEKING',\n SETUP = 'SETUP',\n SOURCE_CHANGING = 'SOURCE_CHANGING',\n STARTUP = 'STARTUP',\n UNLOADED = 'UNLOADED',\n VIDEOSTART_FAILED = 'VIDEOSTART_FAILED',\n}\n\nexport class THEOplayerAnalyticsStateMachine extends AnalyticsStateMachine {\n constructor(\n stateMachineCallbacks: StateMachineCallbacks,\n playingHeartbeatService: HeartbeatService,\n opts: AnalyticsStateMachineOptions,\n ) {\n super(stateMachineCallbacks, playingHeartbeatService, opts);\n }\n\n override createStateMachine(opts: AnalyticsStateMachineOptions): StateMachine {\n return create({\n // custom initial state and custom JSM initial event name\n // initial event is used by JSM for the initial state transition 'none' -> 'SETUP'\n initial: {state: State.SETUP, event: JSM_INITIAL_EVENT},\n error: customStateMachineErrorCallback,\n events: [\n {name: Event.READY, from: State.SETUP, to: State.READY},\n\n {name: Event.PLAY, from: State.READY, to: State.STARTUP},\n // Fallback transition: to handle a missing \"play\" event and a missing transition from READY to STARTUP\n //\n // Case: MISSING \"PLAY\" EVENT FROM A PLAY ATTEMPT DURING SLOW SOURCE CHANGE.\n // Problem:\n // When the source change was triggered, the player started to load the video (probably on slow network),\n // and we were in the SOURCE_CHANGING state. But when `player.play()` was called during that state, the player\n // did not fire \"play\" (player bug?), so this play attempt was not recognized by us, and we have not\n // transitioned to the STARTUP state. Once the source was loaded, we transitioned to the READY state, but\n // the player remembered the play attempt from before, so the video actually started to play. But because\n // of the missing transition to STARTUP, we got stuck in the READY state.\n // Solution:\n // If we are still in the READY state and there was a \"playing\" event, it means that the play attempt was not\n // recognized by us, but the video actually started to play, so we will immediately transition to the PLAYING\n // state. But before that, we will trigger the \"startup\" sample with a fixed duration of 1ms, when leaving\n // the READY state.\n // Found on:\n // theoplayer@10.10.0\n {name: Event.PLAYING, from: State.READY, to: State.PLAYING},\n\n // Case: PRECEDING \"PAUSE\" EVENT ON STARTUP ERRORS\n // Problem:\n // In case of a player \"error\" event during the STARTUP state, we see that the player fires a \"pause\" event\n // automatically before the actual \"error\" event. This messes with our state machine, to not be able to track\n // the error as a startup failure, because such the preceding PAUSE event would first get us into the PAUSE\n // state, where the following \"error\" event would be considered as a normal error during the PAUSE state.\n // Solution:\n // To handle this case, we delay the PAUSE event execution to see if an ERROR event is fired right after, and\n // if so, we give the ERROR event the priority to be executed first, and we cancel the delayed PAUSE event,\n // so that the state machine can correctly track the startup failure. If there is no ERROR event fired right\n // after, we execute the delayed PAUSE event as if nothing happened.\n {name: Event.ERROR, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.MANUAL_SOURCE_CHANGE, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.VIDEOSTART_TIMEOUT, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n\n {name: Event.READY, from: State.VIDEOSTART_FAILED, to: State.READY},\n\n // cover the case when a user double-click the play button.\n // aka. when after the first play click, a video starts to load, and we are in the startup state,\n // but during the loading a user clicks the play button again to pause the video\n {name: Event.PAUSE, from: State.STARTUP, to: State.READY},\n\n // We can't use a player 'timeupdate' event, because it is fired asap after the play button is hit\n // with currentTime: 0, just to set playback state to beginning / to initial state, and THEOplayer is\n // still loading the asset (a specific THEOplayer behavior)\n {name: Event.PLAYING, from: State.STARTUP, to: State.PLAYING},\n\n // Case: PREROLL AD\n // Problem:\n // In the case of preroll Ads, they always start when we have already entered the STARTUP state.\n // Solution:\n // We had to create a specific AD_PLAYBACK_IN_STARTUP state:\n // - to not affect STARTUP state and the startup time calculation with the preroll ad time.\n // - to be able to send an \"ad\" sample for preroll ads in onleaveSTATE callback.\n // - to be able to return us back to STARTUP state after the preroll ad is finished, to continue the normal startup.\n {name: Event.START_AD, from: State.STARTUP, to: State.AD_PLAYBACK_IN_STARTUP},\n {name: Event.END_AD, from: State.AD_PLAYBACK_IN_STARTUP, to: State.STARTUP},\n\n // Case: MIDROLL & POSTROLL ADS DETERMINATION\n // Problem:\n // Player event \"adbreakbegin\" for both midroll and postroll Ad, can theoretically happen at any of our states\n // (PLAYING, SEEKING, maybe also REBUFFERING etc.), and it is hard to determine to which state we should return\n // back after the ad is finished. An additional problem to that is that we can't clearly detect a postroll ad,\n // because the THEOplayer will start it before emitting a player \"end\" event, so in the same way as a midroll ad.\n // Solution:\n // - We will transition to the AD_PLAYBACK state on \"adbreakbegin\" no matter in which state it happens, and when\n // it ends, we will return to the PLAYING state. Why PLAYING? Because we could see THEOplayer behavior that\n // after midroll ad (for postroll we did special handling), the video continues to play automatically no\n // matter from what state Ads has started. For example, the use case, when we seeked, or paused and seeked\n // the video over the Ad position.\n // - For the postroll ads we have a special handling! We will rely on the fact that after the postroll ad has\n // finished, THEOplayer will always emit a player \"end\" event (because playback is/was at the end of the video).\n // So what we need to do is to always delay END_AD event execution! If we see that an END event is fired\n // right after, it means that the ad that just finished was a postroll ad, so we will cancel the END_AD event\n // and transition directly to the PAUSE state. If no END event follows, it means that it was a midroll ad,\n // so we will execute the END_AD event as normal and transition back to PLAYING state.\n // Without this, we would be tracking postroll ads as normal midroll ones, and we would be returning back to\n // PLAYING state that would be tracked as \"micro-short playing sample\" as the player \"end\" event came soon.\n // Found on:\n // theoplayer@10.12.0\n {name: Event.START_AD, from: getAllStatesBut([State.STARTUP], State), to: State.AD_PLAYBACK},\n {name: Event.END_AD, from: State.AD_PLAYBACK, to: State.PLAYING},\n // to support the case: MIDROLL & POSTROLL ADS DETERMINATION\n {name: Event.END, from: State.AD_PLAYBACK, to: State.PAUSE},\n\n {name: Event.START_BUFFERING, from: State.PLAYING, to: State.REBUFFERING},\n {name: Event.PLAYING, from: State.REBUFFERING, to: State.PLAYING},\n {name: Event.PAUSE, from: State.REBUFFERING, to: State.PAUSE},\n\n {name: Event.PAUSE, from: State.PLAYING, to: State.PAUSE},\n {name: Event.PLAYING, from: State.PAUSE, to: State.PLAYING},\n // PAUSE state should be also interrupted with the \"play\" player event\n // to already start PLAYING state tracking with \"attempt to play\"\n {name: Event.PLAY, from: State.PAUSE, to: State.PLAYING},\n\n // Case: PRECEDING \"PAUSE\" EVENT BEFORE \"SEEK\" WHEN SEEKING VIA UI PROGRESS BAR\n // Problem:\n // When the user seeks via the UI progress bar while the video is playing, THEOplayer fires a \"pause\" event\n // immediately before the \"seeking\" event. This causes our state machine to transition from PLAYING → PAUSE,\n // which sends a spurious \"pause sample\" and loses the seek tracking — the SEEK event is then ignored because\n // the state machine is no longer in the PLAYING state. (Only PLAYING → SEEKING is a valid transition.)\n //\n // That THEOplayer behavior is a feature for UI, not a bug! Response from THEOplayer team: Both default UI\n // (based off video.js 5 UI) and the Web Open Video UI pause when scrubbing. This is done so that if you hover\n // somewhere still while scrubbing without releasing, the player doesn't suddenly start playing again while\n // you're still scrubbing, until the scrubbing action is stopped by releasing the mouse and the playback resumes.\n //\n // Solution:\n // To handle this case, we delay the PAUSE event to see if a SEEK event is fired right after. If a SEEK event\n // arrives while the PAUSE is pending, we cancel the PAUSE and let the SEEK be dispatched normally, so the\n // state machine correctly tracks PLAYING → SEEKING. If no SEEK follows, the PAUSE is dispatched as normal.\n {name: Event.SEEK, from: State.PLAYING, to: State.SEEKING},\n {name: Event.PLAYING, from: State.SEEKING, to: State.PLAYING},\n\n {name: Event.VIDEO_CHANGE, from: State.PLAYING, to: State.QUALITY_CHANGE},\n {name: Event.AUDIO_CHANGE, from: State.PLAYING, to: State.QUALITY_CHANGE},\n {name: Event.FINISH_QUALITY_CHANGE, from: State.QUALITY_CHANGE, to: State.PLAYING},\n\n {\n name: Event.MANUAL_SOURCE_CHANGE,\n from: getAllStatesBut([State.STARTUP], State),\n to: State.SOURCE_CHANGING,\n },\n {name: Event.READY, from: State.SOURCE_CHANGING, to: State.READY},\n // play attempt during sourceChanging\n {name: Event.PLAY, from: State.SOURCE_CHANGING, to: State.STARTUP},\n\n // Because of this state transition, we are able to make \"a cut\" in the current PLAYING / PAUSE state\n // and send \"playing\" / \"pause\" sample with the current custom data values. The new changed custom data values\n // will be set on upcoming samples after we transition back from the CUSTOMDATACHANGE state.\n // For any other states, we don't care, because InternalAdapter is not emitting the event.\n {name: Event.CUSTOM_DATA_CHANGE, from: [State.PLAYING, State.PAUSE], to: State.CUSTOMDATACHANGE},\n {name: Event.PLAYING, from: State.CUSTOMDATACHANGE, to: State.PLAYING},\n {name: Event.PAUSE, from: State.CUSTOMDATACHANGE, to: State.PAUSE},\n\n {name: Event.ERROR, from: getAllStatesBut([State.STARTUP, State.VIDEOSTART_FAILED], State), to: State.ERROR},\n\n // Special case to handle unload from any state\n // Transition is canceled in 'onbefore' callback and handled there.\n {name: Event.UNLOAD, from: '*', to: State.UNLOADED},\n ],\n\n // Keep callbacks sorted by order in which they are called by JSM library (and after order, sorted by name)\n //\n // Do not use convenience, shortened callbacks\n // - instead of `onEVENT` use `onafterEVENT`\n // - instead of `onSTATE` use `onenterSTATE`\n //\n // see: https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#callbacks\n callbacks: {\n [`onbefore${Event.UNLOAD}`]: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n const duration = eventTimestamp - this.onEnterStateTimestamp;\n\n if (from === State.STARTUP) {\n this.stateMachineCallbacks.videoStartFailed(duration, VideoStartFailedReason.PAGE_CLOSED);\n } else {\n this.stateMachineCallbacks.unload(duration, String(from).toLowerCase());\n }\n\n // Return false to cancel the event (and state transition) to avoid other 'onleaveXXX' callbacks calls.\n // We have to handle these special cases\n // - when the page is unloaded, the browser can't make a standard http requests (we need sendBeacon)\n // - when the player is destroyed, we can't access it to fill all sample properties\n return false;\n },\n\n [`onleave${State.AD_PLAYBACK_IN_STARTUP}`]: (\n event,\n from,\n to,\n eventTimestamp: number,\n eventData: AnalyticsEventBase,\n ) => {\n // To support the transition for the case: PREROLL AD\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n const duration = eventTimestamp - this.onEnterStateTimestamp;\n this.stateMachineCallbacks.ad(duration, 'ad');\n },\n\n [`onleave${State.AD_PLAYBACK}`]: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n const duration = eventTimestamp - this.onEnterStateTimestamp;\n this.stateMachineCallbacks.ad(duration, 'ad');\n },\n\n [`onleave${State.CUSTOMDATACHANGE}`]: (\n _event,\n _from,\n _to,\n _eventTimestamp: number,\n eventData: CustomDataValuesEvent,\n ) => {\n this.stateMachineCallbacks.customdatachange(undefined, undefined, eventData);\n },\n\n [`onleave${State.PAUSE}`]: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n const duration = eventTimestamp - this.onEnterStateTimestamp;\n this.stateMachineCallbacks.pause(duration, 'pause');\n },\n\n [`onleave${State.PLAYING}`]: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n this.playingHeartbeatService.stopHeartbeat();\n\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n const duration = eventTimestamp - this.onEnterStateTimestamp;\n this.stateMachineCallbacks.playing(duration, 'playing');\n },\n\n [`onleave${State.REBUFFERING}`]: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n this.resetRebufferingHelpers();\n\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n const duration = eventTimestamp - this.onEnterStateTimestamp;\n this.stateMachineCallbacks.rebuffering(duration, 'rebuffering');\n },\n\n [`onleave${State.READY}`]: (event, from, to, _eventTimestamp: number, eventData: AnalyticsEventBase) => {\n // To support the fallback transition for the case: MISSING \"PLAY\" EVENT FROM A PLAY ATTEMPT DURING SLOW SOURCE CHANGE.\n if (event === Event.PLAYING && to === State.PLAYING) {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n this.stateMachineCallbacks.startup(1, 'startup');\n return;\n }\n },\n\n [`onleave${State.SEEKING}`]: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n const duration = eventTimestamp - this.onEnterStateTimestamp;\n this.stateMachineCallbacks.seeking(duration);\n },\n\n [`onleave${State.SETUP}`]: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n // Setting player setup duration to fixed value of 1ms.\n // We can't get a correct setup duration from player, because it does not have an \"onInitialized\" event,\n // and we can't relay on the video 'loadedmetadata' event, because it is not fired in all cases, like when\n // player is initialized without source preloading (THEOplayer default behavior).\n this.stateMachineCallbacks.setup(1, 'setup');\n },\n\n [`onleave${State.STARTUP}`]: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n this.clearVideoStartTimeout();\n\n // if we are transitioning from STARTUP to READY state, it means that playback was not started (such as when\n // a user clicked pause during video loading), so we do not send a startup sample in that case\n if (to === State.READY) {\n return;\n }\n\n // To support the case: PREROLL AD\n // if we are transitioning from STARTUP to AD_PLAYBACK_IN_STARTUP state, it means that preroll ad has started,\n // so we do not want to send a startup sample in that case\n if (to === State.AD_PLAYBACK_IN_STARTUP) {\n return;\n }\n\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n const duration = eventTimestamp - this.onEnterStateTimestamp;\n if (to === State.VIDEOSTART_FAILED) {\n this.stateMachineCallbacks.videoStartFailed(duration, createVideoStartFailedReason(event));\n return;\n }\n\n this.stateMachineCallbacks.startup(duration, 'startup');\n },\n\n onleavestate: (event, from, to) => {\n logStateMachineTransition('LEAVE', event, from, to);\n },\n\n [`onenter${State.PLAYING}`]: () => {\n this.playingHeartbeatService.startHeartbeat();\n },\n\n [`onenter${State.REBUFFERING}`]: () => {\n this.startRebufferingHeartbeatInterval();\n },\n\n [`onenter${State.STARTUP}`]: () => {\n this.setVideoStartTimeout();\n },\n\n [`onenter${State.QUALITY_CHANGE}`]: (_event, _from, _to, eventTimestamp, eventData: QualityChangeEvent) => {\n // Quality change should produce a \"signal sample\" and immediately transition us back to PLAYING state\n this.stateMachineCallbacks.qualitychange(eventData);\n this.stateMachine[Event.FINISH_QUALITY_CHANGE](eventTimestamp);\n },\n\n onenterstate: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n logStateMachineTransition('ENTER', event, from, to);\n\n this.onEnterStateTimestamp = eventTimestamp ?? Date.now();\n // if customer set custom \"start time\" timestamp in AnalyticsStateMachineOptions of adapter constructor,\n // use it and override `onEnterStateTimestamp` during JSM initialization (transition to initial SETUP state)\n if (isNumber(opts.starttime) && event === JSM_INITIAL_EVENT) {\n this.onEnterStateTimestamp = opts.starttime;\n }\n\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n },\n\n [`onafter${Event.MANUAL_SOURCE_CHANGE}`]: (event, _from, _to, _eventTimestamp, eventData) => {\n this.stateMachineCallbacks.manualSourceChange(eventData);\n },\n\n [`onafter${Event.ERROR}`]: (_event, _from, _to, _eventTimestamp, eventData: ErrorEvent) => {\n this.stateMachineCallbacks.error(eventData);\n },\n },\n });\n }\n}\n","import * as StateMachine from 'javascript-state-machine';\n\nimport type {HeartbeatService} from '../core/HeartbeatService';\nimport {Event, JSM_INITIAL_EVENT} from '../enums/Event';\nimport {createVideoStartFailedReason} from '../enums/VideoStartFailedReason';\nimport type {AnalyticsStateMachineOptions} from '../types/AnalyticsStateMachineOptions';\nimport type {StateMachineCallbacks} from '../types/StateMachineCallbacks';\nimport {logger} from '../utils/Logger';\nimport {isNumber} from '../utils/numberUtils';\nimport {isFunction} from '../utils/Utils';\n\nimport {AnalyticsStateMachine} from './AnalyticsStateMachine';\nimport {\n customStateMachineErrorCallback,\n logMissingCallbackWarning,\n logStateMachineTransition,\n on,\n} from './stateMachineUtils';\n\nenum State {\n AD = 'AD',\n AUDIOTRACK_CHANGED_PLAYING = 'AUDIOTRACK_CHANGED_PLAYING',\n AUDIOTRACK_CHANGING = 'AUDIOTRACK_CHANGING',\n CASTING = 'CASTING',\n /**\n * This state was created only to be able to \"cut\" the {@link State.PLAYING} and {@link State.PAUSE}\n * and send playing/pause sample with current custom data, while calling {@link AdapterAPI.setCustomData} function\n * and setting the new custom data values.\n *\n * @remarks\n *\n * Our implementation relays on a specific state name \"CUSTOMDATACHANGE\" because it should call the\n * default \"onleavestate\" state machine callback {@link stateMachineCallbacks.customdatachange}.\n */\n CUSTOMDATACHANGE = 'CUSTOMDATACHANGE',\n END = 'END',\n END_PLAY_SEEKING = 'END_PLAY_SEEKING',\n ERROR = 'ERROR',\n MUTING_PAUSE = 'MUTING_PAUSE',\n MUTING_PLAY = 'MUTING_PLAY',\n MUTING_READY = 'MUTING_READY',\n PAUSE = 'PAUSE',\n PAUSED_SEEKING = 'PAUSED_SEEKING',\n PLAY_SEEKING = 'PLAY_SEEKING',\n PLAYING = 'PLAYING',\n QUALITY_CHANGE = 'QUALITY_CHANGE',\n READY = 'READY',\n REBUFFERING = 'REBUFFERING',\n SETUP = 'SETUP',\n SOURCE_CHANGING = 'SOURCE_CHANGING',\n STARTUP = 'STARTUP',\n SUBTITLE_CHANGED_PLAYING = 'SUBTITLE_CHANGED_PLAYING',\n SUBTITLE_CHANGING = 'SUBTITLE_CHANGING',\n VIDEOSTART_FAILED = 'VIDEOSTART_FAILED',\n}\n\nexport class VideojsAnalyticsStateMachine extends AnalyticsStateMachine {\n private seekTimestamp: number;\n private seekedTimestamp: number;\n\n constructor(\n stateMachineCallbacks: StateMachineCallbacks,\n playingHeartbeatService: HeartbeatService,\n opts: AnalyticsStateMachineOptions,\n ) {\n super(stateMachineCallbacks, playingHeartbeatService, opts);\n\n this.seekTimestamp = 0;\n this.seekedTimestamp = 0;\n }\n\n getAllStates() {\n return [...Object.keys(State).map((key) => State[key]), 'FINISH_PLAY_SEEKING', 'PLAY_SEEK'];\n }\n\n getAllStatesBut(state: string) {\n return this.getAllStates().filter((i) => i !== state);\n }\n\n override createStateMachine(opts: AnalyticsStateMachineOptions) {\n return StateMachine.create({\n // custom initial state and custom JSM initial event name\n // initial event is used by JSM for the initial state transition 'none' -> 'SETUP'\n initial: {state: State.SETUP, event: JSM_INITIAL_EVENT},\n error: customStateMachineErrorCallback,\n events: [\n {name: Event.SOURCE_LOADED, from: [State.SETUP, State.ERROR, State.SOURCE_CHANGING], to: State.READY},\n on(Event.TIMECHANGED).stayIn(State.SETUP),\n on(Event.SOURCE_LOADED).stayIn(State.READY),\n {name: Event.READY, from: [State.SETUP, State.ERROR], to: State.READY},\n {name: Event.PLAY, from: State.READY, to: State.STARTUP},\n\n {name: Event.ERROR, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.UNLOAD, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.VIDEOSTART_TIMEOUT, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n\n on(Event.START_BUFFERING).stayIn(State.STARTUP),\n on(Event.END_BUFFERING).stayIn(State.STARTUP),\n {name: Event.TIMECHANGED, from: State.STARTUP, to: State.PLAYING},\n\n on(Event.TIMECHANGED).stayIn(State.PLAYING),\n on(Event.END_BUFFERING).stayIn(State.PLAYING),\n {name: Event.START_BUFFERING, from: State.PLAYING, to: State.REBUFFERING},\n on(Event.START_BUFFERING).stayIn(State.REBUFFERING),\n {name: Event.TIMECHANGED, from: State.REBUFFERING, to: State.PLAYING},\n\n // Ignoring since it's pushed in a live stream\n on(Event.SEEK).stayIn(State.STARTUP),\n {name: Event.SEEK, from: State.PLAYING, to: State.PLAY_SEEKING},\n on(Event.TIMECHANGED).stayIn(State.PLAY_SEEKING),\n on(Event.TIMECHANGED).stayIn(State.PAUSED_SEEKING),\n\n {name: Event.PAUSE, from: State.PLAYING, to: State.PAUSE},\n {name: Event.PAUSE, from: State.REBUFFERING, to: State.PAUSE},\n on(Event.TIMECHANGED).stayIn(State.PAUSE),\n {name: Event.PLAY, from: State.PAUSE, to: State.PLAYING},\n\n {name: Event.VIDEO_CHANGE, from: State.PLAYING, to: State.QUALITY_CHANGE},\n {name: Event.AUDIO_CHANGE, from: State.PLAYING, to: State.QUALITY_CHANGE},\n {name: Event.FINISH_QUALITY_CHANGE, from: State.QUALITY_CHANGE, to: State.PLAYING},\n\n {name: Event.SEEK, from: State.PAUSE, to: State.PAUSED_SEEKING},\n on(Event.SEEK).stayIn(State.PAUSED_SEEKING),\n on(Event.START_BUFFERING).stayIn(State.PAUSED_SEEKING),\n on(Event.END_BUFFERING).stayIn(State.PAUSED_SEEKING),\n {name: Event.SEEKED, from: State.PAUSED_SEEKING, to: State.PAUSE},\n {name: Event.PLAY, from: State.PAUSED_SEEKING, to: State.PLAYING},\n {name: Event.PAUSE, from: State.PAUSED_SEEKING, to: State.PAUSE},\n\n {name: 'PLAY_SEEK', from: State.PAUSE, to: State.PLAY_SEEKING},\n {name: 'PLAY_SEEK', from: State.PAUSED_SEEKING, to: State.PLAY_SEEKING},\n on('PLAY_SEEK').stayIn(State.PLAY_SEEKING),\n on(Event.SEEK).stayIn(State.PLAY_SEEKING),\n on(Event.START_BUFFERING).stayIn(State.PLAY_SEEKING),\n on(Event.END_BUFFERING).stayIn(State.PLAY_SEEKING),\n on(Event.SEEKED).stayIn(State.PLAY_SEEKING),\n\n // We are ending the seek\n {name: Event.SEEKED, from: State.PLAY_SEEKING, to: State.END_PLAY_SEEKING},\n\n on(Event.START_BUFFERING).stayIn(State.END_PLAY_SEEKING),\n on(Event.END_BUFFERING).stayIn(State.END_PLAY_SEEKING),\n on(Event.SEEKED).stayIn(State.END_PLAY_SEEKING),\n {name: Event.TIMECHANGED, from: State.END_PLAY_SEEKING, to: State.PLAYING},\n\n {name: Event.END, from: State.PLAY_SEEKING, to: State.END},\n {name: Event.END, from: State.PAUSED_SEEKING, to: State.END},\n {name: Event.END, from: State.PLAYING, to: State.END},\n {name: Event.END, from: State.PAUSE, to: State.END},\n on(Event.SEEK).stayIn(State.END),\n on(Event.SEEKED).stayIn(State.END),\n on(Event.TIMECHANGED).stayIn(State.END),\n on(Event.END_BUFFERING).stayIn(State.END),\n on(Event.START_BUFFERING).stayIn(State.END),\n on(Event.END).stayIn(State.END),\n\n // Ignored - Livestreams do a Seek during startup and SEEKED once playback started\n on(Event.SEEKED).stayIn(State.PLAYING),\n\n {name: Event.PLAY, from: State.END, to: State.PLAYING},\n\n {name: Event.ERROR, from: this.getAllStatesBut(State.STARTUP), to: State.ERROR},\n {name: Event.PAUSE, from: State.ERROR, to: State.ERROR},\n\n {name: Event.SEEK, from: State.END_PLAY_SEEKING, to: State.PLAY_SEEKING},\n {name: 'FINISH_PLAY_SEEKING', from: State.END_PLAY_SEEKING, to: State.PLAYING},\n\n {name: Event.UNLOAD, from: this.getAllStatesBut(State.STARTUP), to: State.END},\n\n {name: Event.START_AD, from: State.PLAYING, to: State.AD},\n {name: Event.END_AD, from: State.AD, to: State.PLAYING},\n\n // in scenario, where VideoJS player is initialized with `muted: true` option, VideoJS player\n // triggers PlayerEvent `volumechange` before PlayerEvent `ready`\n on(Event.MUTE).stayIn(State.SETUP),\n\n {name: Event.MUTE, from: State.READY, to: State.MUTING_READY},\n {name: Event.UN_MUTE, from: State.READY, to: State.MUTING_READY},\n {name: 'FINISH_MUTING', from: State.MUTING_READY, to: State.READY},\n\n {name: Event.MUTE, from: State.PLAYING, to: State.MUTING_PLAY},\n {name: Event.UN_MUTE, from: State.PLAYING, to: State.MUTING_PLAY},\n {name: 'FINISH_MUTING', from: State.MUTING_PLAY, to: State.PLAYING},\n\n {name: Event.MUTE, from: State.PAUSE, to: State.MUTING_PAUSE},\n {name: Event.UN_MUTE, from: State.PAUSE, to: State.MUTING_PAUSE},\n {name: 'FINISH_MUTING', from: State.MUTING_PAUSE, to: State.PAUSE},\n\n {name: Event.START_CAST, from: [State.READY, State.PAUSE], to: State.CASTING},\n on(Event.PAUSE).stayIn(State.CASTING),\n on(Event.PLAY).stayIn(State.CASTING),\n on(Event.TIMECHANGED).stayIn(State.CASTING),\n on(Event.MUTE).stayIn(State.CASTING),\n on(Event.SEEK).stayIn(State.CASTING),\n on(Event.SEEKED).stayIn(State.CASTING),\n {name: Event.END_CAST, from: State.CASTING, to: State.READY},\n\n on(Event.SEEK).stayIn(State.READY),\n on(Event.SEEKED).stayIn(State.READY),\n {name: Event.SEEKED, from: State.STARTUP, to: State.STARTUP},\n\n {name: Event.AUDIOTRACK_CHANGED, from: State.PLAYING, to: State.AUDIOTRACK_CHANGED_PLAYING},\n {name: 'FINISH_AUDIOTRACK_CHANGING', from: State.AUDIOTRACK_CHANGED_PLAYING, to: State.PLAYING},\n // States which should ignore audioTrack changes\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.PAUSE),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.READY),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.REBUFFERING),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.END_PLAY_SEEKING),\n {name: Event.AUDIOTRACK_CHANGED, from: State.AUDIOTRACK_CHANGING, to: State.AUDIOTRACK_CHANGING},\n\n {name: Event.SUBTITLE_CHANGE, from: State.PLAYING, to: State.SUBTITLE_CHANGED_PLAYING},\n {name: 'FINISH_SUBTITLE_CHANGING', from: State.SUBTITLE_CHANGED_PLAYING, to: State.PLAYING},\n // States which should ignore subtitle changes\n on(Event.SUBTITLE_CHANGE).stayIn(State.PAUSE),\n on(Event.SUBTITLE_CHANGE).stayIn(State.READY),\n on(Event.SUBTITLE_CHANGE).stayIn(State.REBUFFERING),\n on(Event.SUBTITLE_CHANGE).stayIn(State.END_PLAY_SEEKING),\n on(Event.SUBTITLE_CHANGE).stayIn(State.SOURCE_CHANGING),\n on(Event.SUBTITLE_CHANGE).stayIn(State.SUBTITLE_CHANGING),\n\n {name: Event.MANUAL_SOURCE_CHANGE, from: this.getAllStatesBut(State.READY), to: State.SOURCE_CHANGING},\n on(Event.MANUAL_SOURCE_CHANGE).stayIn(State.READY),\n on(Event.MANUAL_SOURCE_CHANGE).stayIn(State.SETUP),\n on(Event.TIMECHANGED).stayIn(State.SOURCE_CHANGING),\n\n // Context: videojs `play()` can be called before source is loaded\n //\n // This means that we should transition to STARTUP state already, even while source is still loading,\n // to be able to measure the startup time correctly. Because once video is loaded, it will start playing\n // and player event 'timeupdate' will be emitted.\n //\n // If we would not do this state transition, player event 'loadedmetadata' (SOURCE_LOADED) would move us\n // to READY state, which would be incorrect, because:\n // - the most important, we would not be able to measure the time from play() to first frame as startup time\n // - we would be stuck in READY state, and not able to move to state PLAYING, on emitted player event\n // 'timeupdate', because such transition doesn't exist in the state machine (STARTUP state is required)\n {name: Event.PLAY, from: State.SOURCE_CHANGING, to: State.STARTUP},\n // Context: videojs `play()` can be called before source is loaded\n //\n // This means that when source is loaded, and `play()` was already called, so we are in STARTUP state and\n // measuring startup time, we should stay in STARTUP state, because player event 'timeupdate' will be emitted,\n // and it will move us to PLAYING state later.\n on(Event.SOURCE_LOADED).stayIn(State.STARTUP),\n\n // Because of this state transition, we are able to male \"a cut\" in the current PLAYING / PAUSE state\n // and send \"playing\" / \"pause\" sample with the current custom data values. The new changed custom data values\n // will be set on upcoming samples after we transition back from the CUSTOMDATACHANGE state.\n // For any other states, we don't care, because InternalAdapter is not emitting the event.\n {name: Event.CUSTOM_DATA_CHANGE, from: [State.PLAYING, State.PAUSE], to: State.CUSTOMDATACHANGE},\n {name: Event.PLAYING, from: State.CUSTOMDATACHANGE, to: State.PLAYING},\n {name: Event.PAUSE, from: State.CUSTOMDATACHANGE, to: State.PAUSE},\n ],\n\n // Keep callbacks sorted by order in which they are called by JSM library (and after order, sorted by name)\n //\n // Do not use convenience, shortened callbacks\n // - instead of `onEVENT` use `onafterEVENT`\n // - instead of `onSTATE` use `onenterSTATE`\n //\n // see: https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#callbacks\n callbacks: {\n [`onleave${State.PLAYING}`]: () => {\n this.playingHeartbeatService.stopHeartbeat();\n },\n\n onleavestate: (event, from, to, eventTimestamp, eventData): any => {\n logStateMachineTransition('LEAVE', event, from, to);\n\n // Skip this JSM callback for JSM initial event\n // This event is fired when the state machine is constructed,\n // to transition us from 'none' to custom initial 'SETUP' state\n if (event === JSM_INITIAL_EVENT) {\n return;\n }\n\n if (from === State.REBUFFERING) {\n this.resetRebufferingHelpers();\n }\n\n // Skip this JSM callback when an JSM event without a timestamp is called,\n // because it would cause NPE in analytics code (state duration calculation etc.).\n // This probably has happened because the state machine was not used correctly,\n // aka. JSM event was not called via `callEvent` method as it should be!\n if (!eventTimestamp) {\n return;\n }\n\n const stateDuration = eventTimestamp - this.onEnterStateTimestamp;\n\n if (eventData && to !== State.PAUSED_SEEKING && to !== State.END_PLAY_SEEKING) {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n }\n\n if (event === 'PLAY_SEEK' && from === State.PAUSE) {\n return true;\n }\n\n if (from === State.READY && to === State.STARTUP) {\n this.setVideoStartTimeout();\n } else if (from === State.STARTUP && (to === State.PLAYING || to === State.VIDEOSTART_FAILED)) {\n this.clearVideoStartTimeout();\n }\n\n const lowerCaseFrom = String(from).toLowerCase();\n if (to === State.VIDEOSTART_FAILED) {\n this.clearVideoStartTimeout();\n this.stateMachineCallbacks.videoStartFailed(stateDuration, createVideoStartFailedReason(event));\n } else if (from === State.PAUSED_SEEKING) {\n const seekDuration = eventTimestamp - this.seekTimestamp;\n this.stateMachineCallbacks.seeking(seekDuration);\n } else if (from === State.END_PLAY_SEEKING) {\n const seekDuration = this.seekedTimestamp - this.seekTimestamp;\n this.stateMachineCallbacks.seeking(seekDuration);\n } else if (event === Event.UNLOAD) {\n this.stateMachineCallbacks.unload(stateDuration, lowerCaseFrom);\n } else if (from === State.PAUSE && to !== State.PAUSED_SEEKING) {\n this.stateMachineCallbacks.pause(stateDuration, lowerCaseFrom);\n } else {\n // Default \"onleavestate\" state machine callback\n //\n // Every time, when we leave a state, we should try to call \"state\" callback,\n // to be able to make \"a cut\" and send analytics sample (if necessary)\n const defaultStateMachineCallbackFn = this.stateMachineCallbacks[lowerCaseFrom];\n if (isFunction(defaultStateMachineCallbackFn)) {\n // a try-catch block to add more resilience against callback errors\n try {\n defaultStateMachineCallbackFn(stateDuration, lowerCaseFrom, eventData);\n } catch (e) {\n logger.error('Exception occurred in State Machine callback ' + lowerCaseFrom, eventData, e);\n }\n } else {\n // if callback is not defined, log a warning to indicate to the developer that\n // - a new callback function needs to be implemented to relay on this default state machine callback\n // - or if no callback is needed, we should\n // - early return from this JSM callback\n // - or add this state to the ignored list\n logMissingCallbackWarning(from, [\n State.READY,\n State.SOURCE_CHANGING,\n State.MUTING_PAUSE,\n State.MUTING_PLAY,\n State.AUDIOTRACK_CHANGED_PLAYING,\n State.SUBTITLE_CHANGED_PLAYING,\n ]);\n }\n }\n\n if (eventData && to !== State.PAUSED_SEEKING && to !== State.PLAY_SEEKING && to !== State.END_PLAY_SEEKING) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n }\n\n if (event === Event.MUTE) {\n this.stateMachineCallbacks.mute();\n } else if (event === Event.UN_MUTE) {\n this.stateMachineCallbacks.unMute();\n } else if (event === Event.MANUAL_SOURCE_CHANGE) {\n this.stateMachineCallbacks.manualSourceChange(eventData);\n }\n },\n\n [`onenter${State.PLAYING}`]: () => {\n this.playingHeartbeatService.startHeartbeat();\n },\n\n [`onenter${State.QUALITY_CHANGE}`]: (_event, _from, _to, eventTimestamp, eventData) => {\n // Quality change should produce a \"signal sample\" and immediately transition us back to PLAYING state\n this.stateMachineCallbacks.qualitychange(eventData);\n this.stateMachine[Event.FINISH_QUALITY_CHANGE](eventTimestamp);\n },\n\n onenterstate: (event, from, to, eventTimestamp, eventData) => {\n logStateMachineTransition('ENTER', event, from, to);\n\n this.onEnterStateTimestamp = eventTimestamp ?? Date.now();\n // if customer set custom \"start time\" timestamp in AnalyticsStateMachineOptions of adapter constructor,\n // use it and override `onEnterStateTimestamp` during JSM initialization (transition to initial SETUP state)\n if (isNumber(opts.starttime) && event === JSM_INITIAL_EVENT) {\n this.onEnterStateTimestamp = opts.starttime;\n }\n\n if (eventData && to !== State.PAUSED_SEEKING && to !== State.PLAY_SEEKING && to !== State.END_PLAY_SEEKING) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n }\n\n if (event === Event.SEEK) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n }\n\n if (event === Event.SEEKED) {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n }\n\n if (\n event === 'PLAY_SEEK' &&\n to === State.PLAY_SEEKING &&\n to !== State.PLAY_SEEKING &&\n to !== State.END_PLAY_SEEKING\n ) {\n this.seekTimestamp = this.onEnterStateTimestamp;\n }\n\n if (event === Event.START_CAST && to === State.CASTING) {\n this.stateMachineCallbacks.startCasting(eventTimestamp, eventData);\n }\n\n if (to === State.REBUFFERING) {\n this.startRebufferingHeartbeatInterval();\n }\n },\n\n [`onafter${Event.ERROR}`]: (_event, _from, _to, _eventTimestamp, eventData) => {\n this.stateMachineCallbacks.error(eventData);\n },\n\n [`onafter${Event.SEEK}`]: (_event, _from, _to, eventTimestamp, _eventData) => {\n this.seekTimestamp = eventTimestamp;\n },\n\n [`onafter${Event.SEEKED}`]: (_event, _from, _to, eventTimestamp, _eventData) => {\n this.seekedTimestamp = eventTimestamp;\n },\n\n onafterevent: (_event, _from, to, eventTimestamp, _eventData) => {\n if (to === State.MUTING_READY || to === State.MUTING_PLAY || to === State.MUTING_PAUSE) {\n this.stateMachine.FINISH_MUTING(eventTimestamp);\n }\n if (to === State.AUDIOTRACK_CHANGED_PLAYING) {\n this.stateMachine.FINISH_AUDIOTRACK_CHANGING(eventTimestamp);\n }\n if (to === State.SUBTITLE_CHANGED_PLAYING) {\n this.stateMachine.FINISH_SUBTITLE_CHANGING(eventTimestamp);\n }\n },\n },\n });\n }\n}\n","import {StateMachine} from 'javascript-state-machine';\n\nimport type {HeartbeatService} from '../../core/HeartbeatService';\nimport {Event, JSM_INITIAL_EVENT} from '../../enums/Event';\nimport {createVideoStartFailedReason} from '../../enums/VideoStartFailedReason';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {AnalyticsEventBase, ErrorEvent, QualityChangeEvent} from '../../types/EventData';\nimport type {StateMachineCallbacks} from '../../types/StateMachineCallbacks';\nimport {isNumber} from '../../utils/numberUtils';\nimport {isNullish} from '../../utils/Utils';\nimport {AnalyticsStateMachine} from '../AnalyticsStateMachine';\nimport {customStateMachineErrorCallback, logStateMachineTransition, on} from '../stateMachineUtils';\n\nenum State {\n ERROR = 'ERROR',\n PAUSE = 'PAUSE',\n PLAYING = 'PLAYING',\n QUALITY_CHANGE = 'QUALITY_CHANGE',\n READY = 'READY',\n REBUFFERING = 'REBUFFERING',\n SEEKING = 'SEEKING',\n SETUP = 'SETUP',\n STARTUP = 'STARTUP',\n UNLOADED = 'UNLOADED',\n VIDEOSTART_FAILED = 'VIDEOSTART_FAILED',\n}\n\nexport class AmazonIVSStateMachine extends AnalyticsStateMachine {\n constructor(\n stateMachineCallbacks: StateMachineCallbacks,\n playingHeartbeatService: HeartbeatService,\n opts: AnalyticsStateMachineOptions,\n ) {\n super(stateMachineCallbacks, playingHeartbeatService, opts);\n }\n\n override createStateMachine(opts: AnalyticsStateMachineOptions): StateMachine {\n return StateMachine.create({\n // custom initial state and custom JSM initial event name\n // initial event is used by JSM for the initial state transition 'none' -> 'SETUP'\n initial: {state: State.SETUP, event: JSM_INITIAL_EVENT},\n error: customStateMachineErrorCallback,\n events: [\n // STARTUP\n {name: Event.READY, from: State.SETUP, to: State.READY},\n {name: Event.PLAY, from: State.READY, to: State.STARTUP},\n {name: Event.PLAYING, from: State.STARTUP, to: State.PLAYING},\n\n // PLAYBACK\n {name: Event.PAUSE, from: State.PLAYING, to: State.PAUSE},\n {name: Event.PLAYING, from: State.PAUSE, to: State.PLAYING},\n {name: Event.PLAY, from: State.PAUSE, to: State.PLAYING},\n // TODO: [AN-5180] Fix unload event handling\n // - fix: event should transition from any state (except STARTUP), to always send \"closed sample\".\n // In case of STARTUP state, we should not send \"closed sample\" but only \"video start failed sample\"\n // - fix: if event was fired in PLAYING state, we should send \"last playing sample\", before the \"close sample\"\n // to not lost playback tracking\n // https://bitmovin.atlassian.net/browse/AN-5180\n {name: Event.UNLOAD, from: State.PLAYING, to: State.UNLOADED},\n {name: Event.PLAYING, from: State.ERROR, to: State.PLAYING}, // recover from error and continue playing\n\n {name: Event.VIDEO_CHANGE, from: State.PLAYING, to: State.QUALITY_CHANGE},\n // AUDIO_CHANGE is not implemented\n {name: Event.FINISH_QUALITY_CHANGE, from: State.QUALITY_CHANGE, to: State.PLAYING},\n\n // SEEKING\n {name: Event.SEEK, from: State.PLAYING, to: State.SEEKING},\n {name: Event.SEEKED, from: State.SEEKING, to: State.PLAYING},\n {name: Event.PAUSE, from: State.SEEKING, to: State.PAUSE},\n\n // BUFFERING\n {name: Event.START_BUFFERING, from: State.PLAYING, to: State.REBUFFERING},\n {name: Event.PLAYING, from: State.REBUFFERING, to: State.PLAYING},\n\n // VIDEOSTART_FAILED\n {name: Event.ERROR, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.UNLOAD, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.VIDEOSTART_TIMEOUT, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n\n // ERROR\n {name: Event.ERROR, from: getAllStatesBut([State.STARTUP, State.VIDEOSTART_FAILED]), to: State.ERROR},\n\n // EVENTS TO IGNORE\n on(Event.PAUSE).stayIn(State.PAUSE),\n on(Event.PAUSE).stayIn(State.STARTUP),\n on(Event.PAUSE).stayIn(State.REBUFFERING),\n on(Event.PLAY).stayIn(State.PLAYING),\n on(Event.PLAYING).stayIn(State.PLAYING),\n on(Event.START_BUFFERING).stayIn(State.PAUSE),\n on(Event.START_BUFFERING).stayIn(State.REBUFFERING),\n on(Event.VIDEOSTART_TIMEOUT).stayIn(State.PLAYING),\n on(Event.VIDEOSTART_TIMEOUT).stayIn(State.PAUSE),\n on(Event.VIDEOSTART_TIMEOUT).stayIn(State.SEEKING),\n on(Event.UNLOAD).stayIn(State.READY),\n on(Event.UNLOAD).stayIn(State.SEEKING),\n\n on(Event.VIDEO_CHANGE).stayIn(State.QUALITY_CHANGE),\n on(Event.VIDEO_CHANGE).stayIn(State.STARTUP),\n on(Event.VIDEO_CHANGE).stayIn(State.REBUFFERING),\n on(Event.VIDEO_CHANGE).stayIn(State.PAUSE),\n on(Event.VIDEO_CHANGE).stayIn(State.ERROR),\n on(Event.VIDEO_CHANGE).stayIn(State.VIDEOSTART_FAILED),\n on(Event.VIDEO_CHANGE).stayIn(State.READY),\n on(Event.VIDEO_CHANGE).stayIn(State.SEEKING),\n\n // Seeking\n on(Event.SEEK).stayIn(State.SEEKING),\n on(Event.SEEK).stayIn(State.PAUSE),\n on(Event.SEEK).stayIn(State.QUALITY_CHANGE),\n on(Event.SEEK).stayIn(State.REBUFFERING),\n on(Event.SEEK).stayIn(State.ERROR),\n on(Event.SEEK).stayIn(State.STARTUP),\n on(Event.SEEK).stayIn(State.READY),\n on(Event.SEEK).stayIn(State.VIDEOSTART_FAILED),\n on(Event.SEEKED).stayIn(State.PAUSE),\n on(Event.SEEKED).stayIn(State.QUALITY_CHANGE),\n on(Event.SEEKED).stayIn(State.REBUFFERING),\n on(Event.SEEKED).stayIn(State.ERROR),\n on(Event.SEEKED).stayIn(State.STARTUP),\n on(Event.SEEKED).stayIn(State.READY),\n on(Event.SEEKED).stayIn(State.VIDEOSTART_FAILED),\n ],\n\n // Keep callbacks sorted by order in which they are called by JSM library (and after order, sorted by name)\n //\n // Do not use convenience, shortened callbacks\n // - instead of `onEVENT` use `onafterEVENT`\n // - instead of `onSTATE` use `onenterSTATE`\n //\n // see: https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#callbacks\n callbacks: {\n onleavestate: (\n event: string | undefined,\n from: string | undefined,\n to: string | undefined,\n eventTimestamp: number,\n eventData: AnalyticsEventBase,\n ) => {\n // Skip this JSM callback when one of the JSM callback arguments is \"nullish\".\n // Callback arguments `event, from, to` should always be defined, but JSM types say they can be `undefined`,\n // so we have to use type predicates to check if they are not nullish to avoid TypeScript errors\n if (isNullish(event) || isNullish(from) || isNullish(to)) {\n return;\n }\n\n logStateMachineTransition('LEAVE', event, from, to);\n\n // Skip this JSM callback for JSM initial event\n // This event is fired when the state machine is constructed,\n // to transition us from 'none' to custom initial 'SETUP' state\n if (event === JSM_INITIAL_EVENT) {\n return;\n }\n\n // Skip this JSM callback when an JSM event without a timestamp is called,\n // because it would cause NPE in analytics code (state duration calculation etc.).\n // This probably has happened because the state machine was not used correctly,\n // aka. JSM event was not called via `callEvent` method as it should be!\n if (!eventTimestamp) {\n return;\n }\n\n if (eventData) {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n }\n\n const stateDuration = eventTimestamp - this.onEnterStateTimestamp;\n this.getStateHandler()[from].onleavestate(stateDuration, to, event);\n },\n\n onenterstate: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n // Skip this JSM callback when one of the JSM callback arguments is \"nullish\".\n // Callback arguments `event, from, to` should always be defined, but JSM types say they can be undefined,\n // so we have to use type predicates to check if they are not nullish to avoid TypeScript errors\n if (isNullish(event) || isNullish(from) || isNullish(to)) {\n return;\n }\n\n logStateMachineTransition('ENTER', event, from, to);\n\n this.onEnterStateTimestamp = eventTimestamp ?? Date.now();\n // if customer set custom \"start time\" timestamp in AnalyticsStateMachineOptions of adapter constructor,\n // use it and override `onEnterStateTimestamp` during JSM initialization (transition to initial SETUP state)\n if (isNumber(opts.starttime) && event === JSM_INITIAL_EVENT) {\n this.onEnterStateTimestamp = opts.starttime;\n }\n\n if (eventData) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n }\n\n this.getStateHandler()[to].onenterstate(event, eventData);\n },\n },\n });\n }\n\n private getStateHandler = (): StateHandlerList => {\n return {\n [State.SETUP]: {\n onenterstate: () => undefined,\n onleavestate: (duration: number) => {\n this.stateMachineCallbacks.setup(duration, State.SETUP.toLowerCase());\n },\n },\n [State.READY]: {\n onenterstate: () => undefined,\n onleavestate: () => undefined,\n },\n [State.STARTUP]: {\n onenterstate: () => {\n this.setVideoStartTimeout();\n },\n onleavestate: (duration, to, event) => {\n this.clearVideoStartTimeout();\n if (to == State.PLAYING) {\n this.stateMachineCallbacks.startup(duration, State.STARTUP.toLowerCase());\n }\n\n if (to == State.VIDEOSTART_FAILED) {\n this.stateMachineCallbacks.videoStartFailed(duration, createVideoStartFailedReason(event));\n }\n },\n },\n [State.PLAYING]: {\n onenterstate: () => {\n this.playingHeartbeatService.startHeartbeat();\n },\n onleavestate: (duration) => {\n this.playingHeartbeatService.stopHeartbeat();\n this.stateMachineCallbacks.playing(duration, State.PLAYING.toLowerCase());\n },\n },\n [State.PAUSE]: {\n onenterstate: () => undefined,\n onleavestate: (duration) => {\n this.stateMachineCallbacks.pause(duration, State.PAUSE.toLowerCase());\n },\n },\n [State.REBUFFERING]: {\n onenterstate: () => {\n this.startRebufferingHeartbeatInterval();\n },\n onleavestate: (duration) => {\n this.resetRebufferingHelpers();\n this.stateMachineCallbacks.rebuffering(duration, State.REBUFFERING.toLowerCase());\n },\n },\n [State.VIDEOSTART_FAILED]: {\n onenterstate: (event: string, eventData: AnalyticsEventBase) => {\n if (event === Event.ERROR) {\n this.stateMachineCallbacks.error(eventData as ErrorEvent);\n }\n },\n onleavestate: () => undefined,\n },\n [State.ERROR]: {\n onenterstate: (_event: string, eventData: AnalyticsEventBase) => {\n this.stateMachineCallbacks.error(eventData as ErrorEvent);\n },\n onleavestate: () => undefined,\n },\n [State.UNLOADED]: {\n onenterstate: () => {\n this.stateMachineCallbacks.unload(0, State.UNLOADED);\n },\n onleavestate: () => undefined,\n },\n [State.QUALITY_CHANGE]: {\n onenterstate: (_event, eventData) => {\n // Quality change should produce a \"signal sample\" and immediately transition us back to PLAYING state\n this.stateMachineCallbacks.qualitychange(eventData as QualityChangeEvent);\n this.stateMachine[Event.FINISH_QUALITY_CHANGE](this.onEnterStateTimestamp);\n },\n onleavestate: () => undefined,\n },\n [State.SEEKING]: {\n onenterstate: () => undefined,\n onleavestate: (duration) => {\n this.stateMachineCallbacks.seeking(duration);\n },\n },\n };\n };\n}\n\nconst getAllStatesBut = (states: string[]) => {\n return getAllStates().filter((i) => states.indexOf(i) < 0);\n};\n\nconst getAllStates = () => {\n return Object.keys(State).map((key) => State[key]);\n};\n\ntype StateHandler = {\n onenterstate: (event: string, eventData: AnalyticsEventBase) => void;\n onleavestate: (duration: number, to: string, event: string) => void;\n};\n\ntype StateHandlerList = Record<State, StateHandler>;\n","import * as StateMachine from 'javascript-state-machine';\n\nimport {HeartbeatService} from '../../core/HeartbeatService';\nimport {Event, JSM_INITIAL_EVENT} from '../../enums/Event';\nimport {createVideoStartFailedReason} from '../../enums/VideoStartFailedReason';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport {AnalyticsEventBase, ErrorEvent} from '../../types/EventData';\nimport type {StateMachineCallbacks} from '../../types/StateMachineCallbacks';\nimport {EventDebugging} from '../../utils/EventDebugging';\nimport {logger} from '../../utils/Logger';\nimport {isNumber} from '../../utils/numberUtils';\nimport {isFunction, isNotNullish, noOp} from '../../utils/Utils';\nimport {AnalyticsStateMachine} from '../AnalyticsStateMachine';\nimport {\n customStateMachineErrorCallback,\n logMissingCallbackWarning,\n logStateMachineTransition,\n on,\n whileIn,\n} from '../stateMachineUtils';\n\nenum State {\n AD_PAUSE = 'AD_PAUSE',\n AD_PLAYING = 'AD_PLAYING',\n AD_READY = 'AD_READY',\n /** This event is called when an ad is played directly after the player startup phase */\n AD_STARTUP = 'AD_STARTUP',\n AUDIOTRACK_CHANGING = 'AUDIOTRACK_CHANGING',\n CASTING = 'CASTING',\n /**\n * This state was created only to be able to \"cut\" the {@link State.PLAYING} and {@link State.PAUSE}\n * and send playing/pause sample with current custom data, while calling {@link AdapterAPI.setCustomData} function\n * and setting the new custom data values.\n *\n * @remarks\n *\n * Our implementation relays on a specific state name \"CUSTOMDATACHANGE\" because it should call the\n * default \"onleavestate\" state machine callback {@link stateMachineCallbacks.customdatachange}.\n */\n CUSTOMDATACHANGE = 'CUSTOMDATACHANGE',\n END = 'END',\n /** see {@link State.PLAY_SEEKING} */\n END_PLAY_SEEKING = 'END_PLAY_SEEKING',\n ERROR = 'ERROR',\n INITIAL_SOURCE_CHANGE = 'INITIAL_SOURCE_CHANGE',\n MUTING_PAUSE = 'MUTING_PAUSE',\n MUTING_PLAY = 'MUTING_PLAY',\n MUTING_READY = 'MUTING_READY',\n PAUSE = 'PAUSE',\n /**\n * THE Seeking state.\n * Seeking tracking = time spend in PLAY_SEEKING + END_PLAY_SEEKING.\n * - PLAY_SEEKING - THE seeking state for tracking time spend in seeking.\n * - END_PLAY_SEEKING - part of seeking time, where we wait `in between` seeking and continuing with other states.\n * - usually we are in this state when holding the mouse while seeking -> this will produce multiple connected seeks.\n */\n PLAY_SEEKING = 'PLAY_SEEKING',\n PLAYING = 'PLAYING',\n QUALITY_CHANGE = 'QUALITY_CHANGE',\n /**\n * Being in the READY state means that a source was loaded successfully\n */\n READY = 'READY',\n REBUFFERING = 'REBUFFERING',\n SETUP = 'SETUP',\n SOURCE_CHANGING = 'SOURCE_CHANGING',\n STARTUP = 'STARTUP',\n /**\n * Special state for tracking startup when autoplay is enabled.\n *\n * A dedicated state is required because the normal STARTUP state has custom transitions that would compromise\n * the semantic meaning of the READY state (which should indicate \"source successfully loaded\").\n *\n * Problem: In normal startup, a PAUSE event during startup transitions back to READY.\n * If we reused STARTUP for autoplay, this would break the invariant that READY always means\n * \"source was successfully loaded\" - because autoplay startup can PAUSE before the source is loaded.\n *\n * Solution: STARTUP_AUTOPLAY maintains separate transition logic and tracking of whether\n * the source has been loaded, allowing correct startup time calculation and state semantics.\n */\n STARTUP_AUTOPLAY = 'STARTUP_AUTOPLAY',\n SUBTITLE_CHANGING = 'SUBTITLE_CHANGING',\n VIDEOSTART_FAILED = 'VIDEOSTART_FAILED',\n}\n\n// Custom internal state machine events\nenum CustomEvents {\n PAUSE_AFTER_SOURCE_LOADED = 'PAUSE_AFTER_SOURCE_LOADED',\n PAUSE_BEFORE_SOURCE_LOADED = 'PAUSE_BEFORE_SOURCE_LOADED',\n}\n\nexport class Bitmovin8AnalyticsStateMachine extends AnalyticsStateMachine {\n private debuggingStates: EventDebugging[] = [];\n private enabledDebugging = false;\n\n private seekStartTimestamp: number | undefined;\n /**\n * Used for ads, because when AdFinished event is fired and a call to state machine is made,\n * data from player indicate that video is playing from beginning even if ad is in the middle of video\n */\n private lastTrackedVideoEndObject?: AnalyticsEventBase;\n\n /**\n * Tracks whether a source was successfully loaded during the STARTUP_AUTOPLAY state.\n *\n * This flag is critical for handling two edge cases during autoplay startup:\n *\n * **Case 1: SOURCE_UNLOADED event handling**\n * In autoplay, the transition to STARTUP_AUTOPLAY happens immediately after player.load() is called.\n * During a source change, SOURCE_UNLOADED may be fired to clean up the previous source,\n * but this can occur BEFORE SOURCE_LOADED for the new source and AFTER the transition to STARTUP_AUTOPLAY.\n *\n * - If flag=false (no source loaded yet): SOURCE_UNLOADED is cleanup of old source → ignore\n * Example: PLAYING → SOURCE_CHANGING → LOADSTART_AUTOPLAY → STARTUP_AUTOPLAY → SOURCE_UNLOADED (ignored)\n *\n * - If flag=true (source is loaded): SOURCE_UNLOADED is an error condition → trigger VIDEOSTART_FAILED\n * Example: PLAYING → SOURCE_CHANGING → LOADSTART_AUTOPLAY → STARTUP_AUTOPLAY → SOURCE_LOADED → SOURCE_UNLOADED (error)\n *\n * **Case 2: PAUSE event handling**\n * In normal startup, PAUSE returns to READY state (safe because source is loaded).\n * In autoplay startup, we must transition based on whether source is loaded:\n *\n * - If flag=false (no source loaded yet): PAUSE → INITIAL_SOURCE_CHANGE (no sample)\n * Example: SETUP → STARTUP_AUTOPLAY → PAUSE → INITIAL_SOURCE_CHANGE\n *\n * - If flag=true (source is loaded): PAUSE → READY (no sample, source is loaded)\n * Example: SETUP → STARTUP_AUTOPLAY → SOURCE_LOADED → PAUSE → READY\n */\n private sourceLoadedDuringAutoplayStartup = false;\n\n constructor(\n stateMachineCallbacks: StateMachineCallbacks,\n playingHeartbeatService: HeartbeatService,\n opts: AnalyticsStateMachineOptions,\n ) {\n super(stateMachineCallbacks, playingHeartbeatService, opts);\n }\n\n getAllStatesBut(states: string[]) {\n return this.getAllStates().filter((i) => states.indexOf(i) < 0);\n }\n\n getAllStates() {\n return Object.keys(State).map((key) => State[key]);\n }\n\n override createStateMachine(opts: AnalyticsStateMachineOptions): StateMachine.StateMachine {\n return StateMachine.create({\n // custom initial state and custom JSM initial event name\n // initial event is used by JSM for the initial state transition 'none' -> 'SETUP'\n initial: {state: State.SETUP, event: JSM_INITIAL_EVENT},\n error: customStateMachineErrorCallback,\n events: [\n {\n name: Event.SOURCE_LOADED,\n from: [State.SETUP, State.ERROR, State.SOURCE_CHANGING, State.INITIAL_SOURCE_CHANGE],\n to: State.READY,\n },\n\n {name: Event.PLAY, from: State.READY, to: State.STARTUP},\n {name: Event.PLAYING, from: State.READY, to: State.PLAYING},\n on(Event.READY).stayIn(State.READY),\n\n //#region VIDEOSTART_FAILED\n {\n name: Event.ERROR,\n from: [State.STARTUP, State.AD_STARTUP, State.STARTUP_AUTOPLAY],\n to: State.VIDEOSTART_FAILED,\n },\n {\n name: Event.UNLOAD,\n from: [State.STARTUP, State.AD_STARTUP, State.STARTUP_AUTOPLAY],\n to: State.VIDEOSTART_FAILED,\n },\n {name: Event.VIDEOSTART_TIMEOUT, from: [State.STARTUP, State.STARTUP_AUTOPLAY], to: State.VIDEOSTART_FAILED},\n {name: Event.SOURCE_UNLOADED, from: [State.STARTUP, State.STARTUP_AUTOPLAY], to: State.VIDEOSTART_FAILED},\n {name: Event.MANUAL_SOURCE_CHANGE, from: [State.STARTUP, State.STARTUP_AUTOPLAY], to: State.VIDEOSTART_FAILED},\n //#endregion VIDEOSTART_FAILED\n\n //#region STARTUP and STARTUP_AUTOPLAY\n {name: Event.TIMECHANGED, from: [State.STARTUP, State.STARTUP_AUTOPLAY], to: State.PLAYING},\n on(Event.PLAY).stayIn(State.STARTUP),\n on(Event.PLAYING).stayIn(State.STARTUP),\n on(Event.START_BUFFERING).stayIn(State.STARTUP),\n on(Event.END_BUFFERING).stayIn(State.STARTUP),\n on(Event.VIDEO_CHANGE).stayIn(State.STARTUP),\n on(Event.AUDIO_CHANGE).stayIn(State.STARTUP),\n on(Event.READY).stayIn(State.STARTUP),\n {name: Event.PAUSE, from: State.STARTUP, to: State.READY},\n\n // ready state transition is not needed because the player.load() will always happen before the SOURCE_LOADED event\n {\n name: Event.LOADSTART_AUTOPLAY,\n from: [State.SETUP, State.SOURCE_CHANGING, State.INITIAL_SOURCE_CHANGE],\n to: State.STARTUP_AUTOPLAY,\n },\n {name: CustomEvents.PAUSE_BEFORE_SOURCE_LOADED, from: State.STARTUP_AUTOPLAY, to: State.INITIAL_SOURCE_CHANGE},\n {name: CustomEvents.PAUSE_AFTER_SOURCE_LOADED, from: State.STARTUP_AUTOPLAY, to: State.READY},\n ...whileIn(State.STARTUP_AUTOPLAY).passOver(\n // Custom behaviour in the onbeforePause callback\n Event.PAUSE,\n // Custom behaviour in the onbeforeSourceLoaded callback\n Event.SOURCE_LOADED,\n ),\n //#endregion STARTUP and STARTUP_AUTOPLAY\n\n on(Event.PLAYING).stayIn(State.PLAYING),\n on(Event.TIMECHANGED).stayIn(State.PLAYING),\n on(Event.END_BUFFERING).stayIn(State.PLAYING),\n {name: Event.START_BUFFERING, from: State.PLAYING, to: State.REBUFFERING},\n {name: Event.END_BUFFERING, from: State.REBUFFERING, to: State.PLAYING},\n on(Event.TIMECHANGED).stayIn(State.REBUFFERING),\n\n {name: Event.PAUSE, from: State.PLAYING, to: State.PAUSE},\n {name: Event.PAUSE, from: State.REBUFFERING, to: State.PAUSE},\n {name: Event.PLAY, from: State.PAUSE, to: State.PLAYING},\n\n {name: Event.VIDEO_CHANGE, from: State.PLAYING, to: State.QUALITY_CHANGE},\n {name: Event.AUDIO_CHANGE, from: State.PLAYING, to: State.QUALITY_CHANGE},\n {name: Event.FINISH_QUALITY_CHANGE, from: State.QUALITY_CHANGE, to: State.PLAYING},\n\n //#region Seeking\n\n // start seeking\n {name: Event.SEEK, from: State.PLAYING, to: State.PLAY_SEEKING},\n\n // mark the seeked as finished\n {name: Event.PLAY, from: State.PLAY_SEEKING, to: State.END_PLAY_SEEKING},\n {name: Event.PLAYING, from: State.PLAY_SEEKING, to: State.END_PLAY_SEEKING},\n {name: Event.SEEKED, from: State.PLAY_SEEKING, to: State.END_PLAY_SEEKING},\n\n // seek while previous seek not completed\n {name: Event.SEEK, from: State.END_PLAY_SEEKING, to: State.PLAY_SEEKING},\n\n // seek completely finished and cont playing\n {name: Event.PLAYING, from: State.END_PLAY_SEEKING, to: State.PLAYING},\n {name: Event.TIMECHANGED, from: State.END_PLAY_SEEKING, to: State.PLAYING},\n\n // if PAUSE happens during the seeking (or at the end of seeking) we need to transition to PAUSE state\n {name: Event.PAUSE, from: [State.PLAY_SEEKING, State.END_PLAY_SEEKING], to: State.PAUSE},\n\n //#region Seeking disabled transitions\n // ignore transitions in PLAY_SEEKING\n on(Event.SEEK).stayIn(State.PLAY_SEEKING),\n on(Event.START_BUFFERING).stayIn(State.PLAY_SEEKING),\n on(Event.END_BUFFERING).stayIn(State.PLAY_SEEKING),\n\n // ignore transitions in END_PLAY_SEEKING\n on(Event.START_BUFFERING).stayIn(State.END_PLAY_SEEKING),\n on(Event.END_BUFFERING).stayIn(State.END_PLAY_SEEKING),\n on(Event.SEEKED).stayIn(State.END_PLAY_SEEKING),\n on(Event.PLAY).stayIn(State.END_PLAY_SEEKING),\n\n // ignore Seek events during PAUSE\n on(Event.SEEK).stayIn(State.PAUSE),\n on(Event.SEEKED).stayIn(State.PAUSE),\n\n // ignore seeked during Playing because of not allowed keyboard seeking\n on(Event.SEEKED).stayIn(State.PLAYING),\n //#endregion Seeking disabled transitions\n\n //#endregion Seeking\n\n {name: Event.END, from: State.PLAY_SEEKING, to: State.END},\n {name: Event.END, from: State.PLAYING, to: State.END},\n {name: Event.END, from: State.PAUSE, to: State.END},\n\n on(Event.SEEK).stayIn(State.END),\n on(Event.SEEKED).stayIn(State.END),\n on(Event.TIMECHANGED).stayIn(State.END),\n on(Event.END_BUFFERING).stayIn(State.END),\n on(Event.START_BUFFERING).stayIn(State.END),\n on(Event.END).stayIn(State.END),\n\n {name: Event.PLAY, from: State.END, to: State.STARTUP},\n\n {name: Event.ERROR, from: this.getAllStatesBut([State.STARTUP, State.STARTUP_AUTOPLAY]), to: State.ERROR},\n\n {\n name: Event.UNLOAD,\n from: this.getAllStatesBut([State.STARTUP, State.STARTUP_AUTOPLAY, State.AD_STARTUP]),\n to: State.END,\n },\n\n {name: Event.SUBTITLE_CHANGE, from: State.PLAYING, to: State.SUBTITLE_CHANGING},\n on(Event.SUBTITLE_CHANGE).stayIn(State.PAUSE),\n on(Event.SUBTITLE_CHANGE).stayIn(State.REBUFFERING),\n on(Event.SUBTITLE_CHANGE).stayIn(State.END_PLAY_SEEKING),\n on(Event.SUBTITLE_CHANGE).stayIn(State.SUBTITLE_CHANGING),\n {name: Event.TIMECHANGED, from: State.SUBTITLE_CHANGING, to: State.PLAYING},\n\n {name: Event.AUDIOTRACK_CHANGED, from: State.PLAYING, to: State.AUDIOTRACK_CHANGING},\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.PAUSE),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.REBUFFERING),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.END_PLAY_SEEKING),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.AUDIOTRACK_CHANGING),\n {name: Event.TIMECHANGED, from: State.AUDIOTRACK_CHANGING, to: State.PLAYING},\n\n // #region Ads\n {name: Event.START_AD, from: State.STARTUP, to: State.AD_STARTUP},\n {name: Event.END_AD, from: State.AD_STARTUP, to: State.STARTUP},\n on(Event.PLAY).stayIn(State.AD_STARTUP),\n on(Event.PAUSE).stayIn(State.AD_STARTUP),\n\n {name: Event.START_AD, from: State.READY, to: State.AD_READY},\n /** After the pre-rolls, the main content will always start playing, no matter if autoplay: true/false */\n {name: Event.END_AD, from: State.AD_READY, to: State.STARTUP},\n on(Event.PLAY).stayIn(State.AD_READY),\n on(Event.PAUSE).stayIn(State.AD_READY),\n\n {name: Event.START_AD, from: State.PAUSE, to: State.AD_PAUSE},\n {name: Event.END_AD, from: State.AD_PAUSE, to: State.PAUSE},\n on(Event.PLAY).stayIn(State.AD_PAUSE),\n on(Event.PAUSE).stayIn(State.AD_PAUSE),\n\n {name: Event.START_AD, from: State.PLAYING, to: State.AD_PLAYING},\n {name: Event.END_AD, from: State.AD_PLAYING, to: State.PLAYING},\n on(Event.PLAY).stayIn(State.AD_PLAYING),\n on(Event.PAUSE).stayIn(State.AD_PLAYING),\n {name: Event.END, from: State.AD_PLAYING, to: State.END},\n\n // Ignore timechanged events during ads\n on(Event.TIMECHANGED).stayIn(State.AD_STARTUP),\n on(Event.TIMECHANGED).stayIn(State.AD_READY),\n on(Event.TIMECHANGED).stayIn(State.AD_PAUSE),\n on(Event.TIMECHANGED).stayIn(State.AD_PLAYING),\n\n // Ignore End Ad events when no ad has started\n on(Event.END_AD).stayIn(State.PLAYING),\n on(Event.END_AD).stayIn(State.PAUSE),\n on(Event.END_AD).stayIn(State.READY),\n on(Event.END_AD).stayIn(State.STARTUP),\n // #endregion\n\n {name: Event.MUTE, from: State.READY, to: State.MUTING_READY},\n {name: Event.UN_MUTE, from: State.READY, to: State.MUTING_READY},\n {name: 'FINISH_MUTING', from: State.MUTING_READY, to: State.READY},\n\n {name: Event.MUTE, from: State.PLAYING, to: State.MUTING_PLAY},\n {name: Event.UN_MUTE, from: State.PLAYING, to: State.MUTING_PLAY},\n {name: 'FINISH_MUTING', from: State.MUTING_PLAY, to: State.PLAYING},\n\n {name: Event.MUTE, from: State.PAUSE, to: State.MUTING_PAUSE},\n {name: Event.UN_MUTE, from: State.PAUSE, to: State.MUTING_PAUSE},\n {name: 'FINISH_MUTING', from: State.MUTING_PAUSE, to: State.PAUSE},\n\n {name: Event.START_CAST, from: [State.READY, State.PAUSE, State.PLAYING], to: State.CASTING},\n on(Event.PAUSE).stayIn(State.CASTING),\n on(Event.PLAY).stayIn(State.CASTING),\n on(Event.PLAYING).stayIn(State.CASTING),\n on(Event.TIMECHANGED).stayIn(State.CASTING),\n on(Event.MUTE).stayIn(State.CASTING),\n on(Event.UN_MUTE).stayIn(State.CASTING),\n on(Event.SEEK).stayIn(State.CASTING),\n on(Event.SEEKED).stayIn(State.CASTING),\n {name: Event.END_CAST, from: State.CASTING, to: State.READY},\n\n on(Event.SEEK).stayIn(State.READY),\n on(Event.SEEKED).stayIn(State.READY),\n on(Event.SEEKED).stayIn(State.STARTUP),\n\n {\n name: Event.MANUAL_SOURCE_CHANGE,\n from: this.getAllStatesBut([State.SETUP, State.STARTUP, State.STARTUP_AUTOPLAY]),\n to: State.SOURCE_CHANGING,\n },\n {name: Event.MANUAL_SOURCE_CHANGE, from: State.SETUP, to: State.INITIAL_SOURCE_CHANGE},\n {\n name: Event.SOURCE_UNLOADED,\n from: this.getAllStatesBut([State.STARTUP, State.STARTUP_AUTOPLAY]),\n to: State.SOURCE_CHANGING,\n },\n\n // {name: Event.READY, from: State.SOURCE_CHANGING, to: State.READY},\n\n // Because of this state transition, we are able to make \"a cut\" in the current PLAYING / PAUSE state\n // and send \"playing\" / \"pause\" sample with the current custom data values. The new changed custom data values\n // will be set on upcoming samples after we transition back from the CUSTOMDATACHANGE state.\n // For any other states, we don't care, because InternalAdapter is not emitting the event.\n {name: Event.CUSTOM_DATA_CHANGE, from: [State.PLAYING, State.PAUSE], to: State.CUSTOMDATACHANGE},\n {name: Event.PLAYING, from: State.CUSTOMDATACHANGE, to: State.PLAYING},\n {name: Event.PAUSE, from: State.CUSTOMDATACHANGE, to: State.PAUSE},\n ],\n\n // Keep callbacks sorted by order in which they are called by JSM library (and after order, sorted by name)\n //\n // Do not use convenience, shortened callbacks\n // - instead of `onEVENT` use `onafterEVENT`\n // - instead of `onSTATE` use `onenterSTATE`\n //\n // see: https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#callbacks\n callbacks: {\n [`onbefore${Event.SOURCE_LOADED}`]: (\n _event,\n from,\n _to,\n _eventTimestamp: number,\n _eventData: AnalyticsEventBase,\n ) => {\n if (from === State.STARTUP_AUTOPLAY) {\n this.sourceLoadedDuringAutoplayStartup = true;\n }\n },\n\n [`onbefore${Event.SOURCE_UNLOADED}`]: (\n _event,\n from,\n _to,\n _eventTimestamp: number,\n _eventData: AnalyticsEventBase,\n ) => {\n // Prevent SOURCE_UNLOADED from triggering VIDEOSTART_FAILED during STARTUP_AUTOPLAY\n // if the new source hasn't been loaded yet.\n //\n // During source changes with autoplay, SOURCE_UNLOADED (cleanup of previous source)\n // may arrive AFTER player.load() is called but BEFORE SOURCE_LOADED (new source).\n // We ignore this cleanup event and only treat SOURCE_UNLOADED as an error\n // once the new source has been successfully loaded.\n if (from === State.STARTUP_AUTOPLAY && !this.sourceLoadedDuringAutoplayStartup) {\n return false;\n }\n\n return true;\n },\n\n [`onbefore${Event.PAUSE}`]: (_event, from, _to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n // Handle PAUSE during STARTUP_AUTOPLAY with special transitions based on source load status.\n // See sourceLoadedDuringAutoplayStartup documentation for detailed explanation.\n if (from === State.STARTUP_AUTOPLAY) {\n if (this.sourceLoadedDuringAutoplayStartup) {\n // Source loaded: transition to READY (normal behavior)\n this.stateMachine[CustomEvents.PAUSE_AFTER_SOURCE_LOADED](eventTimestamp, eventData);\n } else {\n // Source not loaded: transition to INITIAL_SOURCE_CHANGE (preserve READY semantics)\n this.stateMachine[CustomEvents.PAUSE_BEFORE_SOURCE_LOADED](eventTimestamp, eventData);\n }\n return false;\n }\n\n return true;\n },\n\n [`onleave${State.END_PLAY_SEEKING}`]: (\n _event,\n _from,\n to,\n eventTimestamp: number,\n eventData: AnalyticsEventBase,\n ) => {\n if (to === State.PLAY_SEEKING) {\n // seeking is not finished yet, do not send \"seeking\" sample\n return;\n }\n\n // seeking has finished / was interrupted - send out seeking sample\n const seekDuration = eventTimestamp - (this.seekStartTimestamp ?? eventTimestamp);\n this.seekStartTimestamp = undefined;\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n this.stateMachineCallbacks.seeking(seekDuration);\n },\n\n [`onleave${State.PLAYING}`]: () => {\n this.playingHeartbeatService.stopHeartbeat();\n },\n\n [`onleave${State.STARTUP_AUTOPLAY}`]: () => {\n this.sourceLoadedDuringAutoplayStartup = false;\n this.clearVideoStartTimeout();\n },\n\n [`onleave${State.PLAY_SEEKING}`]: (_event, _from, to, eventTimestamp: number, _eventData) => {\n if (to === State.END_PLAY_SEEKING) {\n // regular seek workflow preparing to end seeking\n return;\n }\n\n // seek interrupted - not regular exit of seeking\n const seekDuration = eventTimestamp - (this.seekStartTimestamp ?? eventTimestamp);\n this.seekStartTimestamp = undefined;\n this.stateMachineCallbacks.seeking(seekDuration);\n },\n\n onleavestate: (event, from, to, eventTimestamp, eventData: AnalyticsEventBase) => {\n logStateMachineTransition('LEAVE', event, from, to);\n\n // Skip this JSM callback for JSM initial event\n // This event is fired when the state machine is constructed,\n // to transition us from 'none' to custom initial 'SETUP' state\n if (event === JSM_INITIAL_EVENT) {\n return;\n }\n\n if (from === State.REBUFFERING) {\n this.resetRebufferingHelpers();\n }\n\n // Skip this JSM callback when an JSM event without a timestamp is called,\n // because it would cause NPE in analytics code (state duration calculation etc.).\n // This probably has happened because the state machine was not used correctly,\n // aka. JSM event was not called via `callEvent` method as it should be!\n if (!eventTimestamp) {\n return;\n }\n\n this.addStatesToLog(event, from, to, eventTimestamp, eventData);\n const stateDuration = eventTimestamp - this.onEnterStateTimestamp;\n\n if (eventData && to !== State.END_PLAY_SEEKING) {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n }\n\n if (eventData && event !== Event.END_AD) {\n this.lastTrackedVideoEndObject = eventData;\n }\n\n if ((from === State.READY || from === State.AD_STARTUP) && to === State.STARTUP) {\n this.setVideoStartTimeout();\n } else if (from === State.STARTUP && (to === State.PLAYING || to === State.AD_STARTUP)) {\n this.clearVideoStartTimeout();\n }\n\n const lowerCaseFrom = String(from).toLowerCase();\n if (to === State.VIDEOSTART_FAILED) {\n this.clearVideoStartTimeout();\n this.stateMachineCallbacks.videoStartFailed(stateDuration, createVideoStartFailedReason(event));\n } else if (from === State.END_PLAY_SEEKING) {\n // NOOP - skip last else block to not send sample\n // sending of sample is handled in `on Leave Seeking` state transition handler\n noOp();\n } else if (event === Event.UNLOAD) {\n this.stateMachineCallbacks.unload(stateDuration, lowerCaseFrom);\n } else if (\n from === State.AD_PAUSE ||\n from === State.AD_READY ||\n from === State.AD_PLAYING ||\n from === State.AD_STARTUP\n ) {\n if (isNotNullish(this.lastTrackedVideoEndObject)) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(this.lastTrackedVideoEndObject);\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(this.lastTrackedVideoEndObject);\n }\n this.stateMachineCallbacks.ad(stateDuration, 'ad');\n } else if (event === Event.START_AD && from === State.STARTUP) {\n noOp();\n } else if (event === Event.SOURCE_LOADED && from === State.INITIAL_SOURCE_CHANGE) {\n noOp();\n } else if (from === State.SETUP) {\n // Setting Player Startup Time to fixed value of 1ms.\n // We can not get correct Player Startup Time from bitmovin player, because it does not have an \"onInitialized\" event\n this.stateMachineCallbacks.setup(1, State.SETUP.toLowerCase());\n } else if (\n (event === Event.PAUSE && from === State.STARTUP && to === State.READY) ||\n (event === CustomEvents.PAUSE_BEFORE_SOURCE_LOADED &&\n from === State.STARTUP_AUTOPLAY &&\n to === State.INITIAL_SOURCE_CHANGE) ||\n (event === CustomEvents.PAUSE_AFTER_SOURCE_LOADED && from === State.STARTUP_AUTOPLAY && to === State.READY)\n ) {\n // fired PAUSE event in STARTUP state or STARTUP_AUTOPLAY state indicates we are moving back to READY/INITIAL_SOURCE_CHANGE,\n // so we have to clean setTimeout, and we should not call any stateMachineCallbacks\n this.clearVideoStartTimeout();\n } else if (from === State.STARTUP_AUTOPLAY) {\n // send normal startup sample when leaving STARTUP_AUTOPLAY state\n this.stateMachineCallbacks.startup(stateDuration, State.STARTUP.toLowerCase());\n } else if (from !== State.ERROR) {\n // Default \"onleavestate\" state machine callback\n //\n // Every time, when we leave a state, we should try to call \"state\" callback,\n // to be able to make \"a cut\" and send analytics sample (if necessary)\n const defaultStateMachineCallbackFn = this.stateMachineCallbacks[lowerCaseFrom];\n if (isFunction(defaultStateMachineCallbackFn)) {\n // a try-catch block to add more resilience against callback errors\n try {\n defaultStateMachineCallbackFn(stateDuration, lowerCaseFrom, eventData);\n } catch (e) {\n logger.error('Exception occurred in State Machine callback ' + lowerCaseFrom, eventData, e);\n }\n } else {\n // if callback is not defined, log a warning to indicate to the developer that\n // - a new callback function needs to be implemented to relay on this default state machine callback\n // - or if no callback is needed, we should\n // - early return from this JSM callback\n // - or add this state to the ignored list\n logMissingCallbackWarning(from, [State.READY, State.SOURCE_CHANGING]);\n }\n }\n\n if (\n eventData &&\n to !== State.END_PLAY_SEEKING &&\n from !== State.PLAY_SEEKING &&\n to !== State.PLAY_SEEKING &&\n from !== State.AD_STARTUP &&\n from !== State.AD_READY &&\n from !== State.AD_PLAYING &&\n from !== State.AD_PAUSE\n ) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n }\n\n if (event === Event.MUTE) {\n this.stateMachineCallbacks.mute();\n } else if (event === Event.UN_MUTE) {\n this.stateMachineCallbacks.unMute();\n }\n },\n\n [`onenter${State.STARTUP_AUTOPLAY}`]: () => {\n this.setVideoStartTimeout();\n },\n\n [`onenter${State.PLAYING}`]: () => {\n this.playingHeartbeatService.startHeartbeat();\n },\n\n [`onenter${State.PLAY_SEEKING}`]: (event, from, _to, eventTimestamp: number, _eventData) => {\n if (from === State.END_PLAY_SEEKING) {\n // no start of seeking -> continues to seek and we don't need to have seek start timestamp\n return;\n }\n\n this.seekStartTimestamp = eventTimestamp;\n },\n\n [`onenter${State.QUALITY_CHANGE}`]: (_event, _from, _to, eventTimestamp, eventData) => {\n // Quality change should produce a \"signal sample\" and immediately transition us back to PLAYING state\n this.stateMachineCallbacks.qualitychange(eventData);\n this.stateMachine[Event.FINISH_QUALITY_CHANGE](eventTimestamp);\n },\n\n onenterstate: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n logStateMachineTransition('ENTER', event, from, to);\n\n this.onEnterStateTimestamp = eventTimestamp ?? Date.now();\n // if customer set custom \"start time\" timestamp in AnalyticsStateMachineOptions of adapter constructor,\n // use it and override `onEnterStateTimestamp` during JSM initialization (transition to initial SETUP state)\n if (isNumber(opts.starttime) && event === JSM_INITIAL_EVENT) {\n this.onEnterStateTimestamp = opts.starttime;\n }\n\n if (\n eventData &&\n to !== State.END_PLAY_SEEKING &&\n from !== State.PLAY_SEEKING &&\n from !== State.AD_STARTUP &&\n from !== State.AD_READY &&\n from !== State.AD_PLAYING &&\n from !== State.AD_PAUSE &&\n !(event === Event.SEEK && from === State.END_PLAY_SEEKING)\n ) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n }\n\n if (event === Event.START_CAST && to === State.CASTING) {\n this.stateMachineCallbacks.startCasting(eventTimestamp, eventData);\n }\n\n if (to === State.REBUFFERING) {\n this.startRebufferingHeartbeatInterval();\n }\n },\n\n [`onafter${Event.ERROR}`]: (_event, _from, _to, _eventTimestamp, eventData: ErrorEvent) => {\n this.stateMachineCallbacks.error(eventData);\n },\n\n [`onafter${Event.SOURCE_UNLOADED}`]: (\n _event,\n _from,\n _to,\n _eventTimestamp: number,\n _eventData: AnalyticsEventBase,\n ) => {\n // Reset the flag after SOURCE_UNLOADED is processed.\n // This prepares the state machine for the next source load/change cycle.\n this.sourceLoadedDuringAutoplayStartup = false;\n },\n\n onafterevent: (event, from, to, eventTimestamp: number, eventData) => {\n if (event === Event.MANUAL_SOURCE_CHANGE && from === State.SETUP) {\n this.stateMachineCallbacks.initialSourceChange(eventData);\n } else if (event === Event.MANUAL_SOURCE_CHANGE) {\n this.stateMachineCallbacks.manualSourceChange(eventData);\n }\n\n if (to === State.MUTING_READY || to === State.MUTING_PLAY || to === State.MUTING_PAUSE) {\n this.stateMachine.FINISH_MUTING(eventTimestamp);\n }\n },\n },\n });\n }\n\n getStates() {\n return this.debuggingStates;\n }\n\n setEnabledDebugging(enabled: boolean) {\n this.enabledDebugging = enabled;\n }\n\n private addStatesToLog(\n event: string | undefined,\n from: string | undefined,\n to: string | undefined,\n timestamp: number,\n eventObject: any,\n ) {\n if (this.enabledDebugging) {\n this.debuggingStates.push(new EventDebugging(event, from, to, timestamp, eventObject));\n }\n }\n}\n","import {\n StateMachineErrorCallback,\n Error as StateMachineErrorCode,\n StateMachineEventDef,\n} from 'javascript-state-machine';\n\nimport {logger, padRight} from '../utils/Logger';\nimport {objectValues} from '../utils/objectUtils';\nimport {isNullish, tryJSONStringify} from '../utils/Utils';\n\n/**\n * @deprecated use {@link whileIn} instead, to switch mindset and think about allowed events in the current state\n * instead of thinking of current event and its allowed states. Because as analytics we focus mostly on reporting\n * states or states changes.\n */\nexport const on = (event: string): {stayIn: (state: string) => StateMachineEventDef} => ({\n stayIn: (state: string) => ({name: event, from: state, to: state}),\n});\n\ntype EventsToStateMachineEventDefFn = (...events: string[]) => StateMachineEventDef[];\ntype WhileInReturnType = {\n /**\n * Create {@link StateMachineEventDef} from event(s) to be used in the state machine definition, but ONLY to indicate\n * that we want to only pass event(s) over, to avoid a log message of ignored event in the current state from\n * the state machine.\n *\n * @remarks\n *\n * If we decide in the future to ignore {@link StateMachineErrorCode.INVALID_TRANSITION} logs created in\n * {@link customStateMachineErrorCallback}, this method and JSM event definitions created with could be removed\n * from source code. Until then, we use it to make code more readable.\n */\n passOver: EventsToStateMachineEventDefFn;\n\n /**\n * Same as {@link passOver}, but used in rare cases, when it indicates that we expect the event(s) to occur\n * in the current state, aka. we want to trigger the state machine event callbacks for these event(s),\n * even if we stay in the same state.\n *\n * @remarks\n *\n * If we don't expect the event while staying in the current state, we don't expect state machine event callbacks\n * to run, we should use {@link passOver} instead!\n */\n runEventCallbacksFor: EventsToStateMachineEventDefFn;\n};\n\n/**\n * This utility is here to help us write more readable code and let us define allowed/expected events in the current state.\n *\n * ### Example:\n *\n * Instead of writing:\n *\n * ```typescript\n * {name: Event.PAUSE, from: State.END, to: State.END},\n * {name: Event.SEEK, from: State.END, to: State.END},\n * {name: Event.SEEKED, from: State.END, to: State.END},\n * {name: Event.TIMECHANGED, from: State.END, to: State.END},\n * ```\n *\n * we can write:\n *\n * ```typescript\n * ...whileIn(State.END).passOver(Event.PAUSE, Event.SEEK, Event.SEEKED, Event.TIMECHANGED),\n * // OR when we expect and react on that event occurrence:\n * ...whileIn(State.END).runEventCallbacksFor(Event.PAUSE, Event.SEEK, Event.SEEKED, Event.TIMECHANGED),\n * ```\n *\n * @see customStateMachineErrorCallback\n * @see https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#handling-failures\n */\nexport const whileIn = (state: string): WhileInReturnType => {\n const stateMachineEventDefBuilderFn = (...events: string[]) =>\n events.map((event) => ({name: event, from: state, to: state}));\n return {runEventCallbacksFor: stateMachineEventDefBuilderFn, passOver: stateMachineEventDefBuilderFn};\n};\n\n/**\n * By default, if you try to call an event method not allowed in the current state,\n * the state machine will throw an exception (not allow it).\n *\n * This JSM library behavior can be changed by providing \"a custom error handler\" in the `create()`\n * method of the state machine, and we do that in every state machine!\n *\n * This way we make code more resilient to errors, because we do not throw errors from JSM event methods,\n * but instead we handle them here and just log them with {@link logger}.\n *\n * @see https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#handling-failures\n */\nexport const customStateMachineErrorCallback: StateMachineErrorCallback = (\n eventName,\n from,\n to,\n args,\n errorCode,\n errorMessage,\n _ex,\n) => {\n const loggerMessage = `StateMachine ignored event \"${eventName}\", ${errorMessage}`;\n const loggerMessageData = {\n eventName,\n from,\n to,\n args: tryJSONStringify(args),\n errorCode,\n errorMessage,\n };\n\n // if caller tried to fire an event that was inappropriate in the current state\n if (errorCode === StateMachineErrorCode.INVALID_TRANSITION) {\n // The event itself is defined in JSM (in some other StateMachineEventDef). However, it is just not considered to\n // be appropriate in the current state.\n //\n // We should log it as a simple log. It is not an error nor a warning,\n // - because JSM will just stay in the same JSM state (and that can be considered as expected behavior)\n // - BUT it will NOT trigger JSM event callbacks like `onafterEVENT`, on `onbeforeEVENT`!\n logger.log(loggerMessage, loggerMessageData);\n return;\n }\n\n logger.error(loggerMessage, loggerMessageData);\n};\n\n/**\n * Log warning messages with {@link logger} about missing StateMachine callback,\n * if the state is not nullish and does not match any of the ignored states.\n */\nexport const logMissingCallbackWarning = (state: string | undefined, ignoreStates: string[] = []) => {\n if (isNullish(state)) {\n return;\n }\n\n const shouldReportMissingCallback = isNullish(ignoreStates.find((ignoredState) => state === ignoredState));\n if (shouldReportMissingCallback) {\n logger.warn('Could not find StateMachine callback function for ' + state);\n }\n};\n\n/** Log message with {@link logger} about StateMachine ENTER/LEAVE transition */\nexport const logStateMachineTransition = (\n transition: 'ENTER' | 'LEAVE',\n event: string | undefined,\n from: string | undefined,\n to: string | undefined,\n) => {\n if (transition === 'ENTER') {\n logger.log(`[ENTER] ${padRight(to, 20)} EVENT: ${padRight(event, 20)} from ${padRight(from, 20)}`);\n } else {\n logger.log(`[LEAVE] ${padRight(from, 20)} EVENT: ${padRight(event, 20)} to ${padRight(to, 20)}`);\n }\n};\n\n/**\n * Return all values/states of the given state string enum.\n *\n * @param stateStringEnumObj\n *\n * @remarks\n *\n * We cannot directly check at if an object is a TypeScript string enum, because enums are erased at compile time and\n * become plain objects in JavaScript. However, you can heuristically check if an object looks like a string enum\n * by verifying that all its values are strings. This checks if all values of the object are strings, which is typical\n * for a string enum. However, this is not a foolproof check, just a heuristic.\n */\nexport function getAllStates<T extends {[key: string]: string}>(stateStringEnumObj: T): Array<T[keyof T]> {\n return objectValues(stateStringEnumObj) as Array<T[keyof T]>;\n}\n\nexport function getAllStatesBut<T extends {[key: string]: string}>(\n excludedStates: Array<T[keyof T]>,\n stateEnumObj: T,\n): Array<T[keyof T]> {\n return getAllStates(stateEnumObj).filter((s) => excludedStates.indexOf(s) < 0);\n}\n","import {isNullish, toBoolean} from '../utils/Utils';\n\nexport function sanitizeSessionMetadataAudioLanguage(anything: unknown): string | undefined {\n // \"nullish\" is considered to be valid (to \"reset\" session metadata property)\n if (isNullish(anything)) {\n // sanitize to use `undefined` in code\n return undefined;\n }\n\n return String(anything).substring(0, 50);\n}\n\nexport function sanitizeSessionMetadataSubtitleEnabled(anything: unknown): boolean | undefined {\n // \"nullish\" is considered to be valid (to \"reset\" session metadata property)\n if (isNullish(anything)) {\n // sanitize to use `undefined` in code\n return undefined;\n }\n\n return toBoolean(anything);\n}\n\nexport function sanitizeSessionMetadataSubtitleLanguage(anything: unknown): string | undefined {\n // \"nullish\" is considered to be valid (to \"reset\" session metadata property)\n if (isNullish(anything)) {\n // sanitize to use `undefined` in code\n return undefined;\n }\n\n return String(anything).substring(0, 100);\n}\n","import {\n AdClickedPayload,\n AdErrorPayload,\n AdManifestLoadedPayload,\n AdModuleAPI,\n AdQuartile,\n AdQuartilePayload,\n} from '../adapters/internal/ads/AdModuleAPI';\nimport {AdAnalyticsSample} from '../types/AdAnalyticsSample';\nimport {AdBreakSample} from '../types/AdBreakSample';\nimport {AdBreakInfo} from '../types/ads/AdBreakInfo';\nimport {AdInfo} from '../types/ads/AdInfo';\nimport {AdSample} from '../types/AdSample';\nimport {Sample} from '../types/Sample';\nimport {logger} from '../utils/Logger';\nimport * as Utils from '../utils/Utils';\nimport {isNotNullish, tryJSONStringify} from '../utils/Utils';\nimport {generateUUID} from '../utils/uuidUtils';\nimport {VERSION} from '../utils/Version';\nimport {ViewportTracker} from '../utils/ViewportTracker';\n\nimport {Analytics} from './Analytics';\n\nexport class AdAnalytics {\n static readonly MODULE_NAME = 'ads';\n private static readonly TIMEOUT_CURRENT_TIME_INTERVAL = 100;\n\n /** Boolean flag to prevent multiple calls of the {@link Event.UNLOAD} event */\n private onBeforeUnLoadEvent = false;\n private analytics: Analytics;\n private adapter: AdModuleAPI;\n private viewportTracker: ViewportTracker;\n\n private activeAdBreakSample?: AdBreakSample;\n private activeAdSample?: AdSample;\n\n private adManifestDownloadTime: number | undefined;\n private adStartupTimestamp?: number;\n private beginPlayingTimestamp?: number;\n private enterViewportTimestamp?: number;\n private isPlaying = false;\n private currentTime?: number;\n private currentTimeInterval?: ReturnType<typeof setInterval>;\n private adPodPosition = 0;\n\n constructor(analytics: Analytics, adapter: AdModuleAPI) {\n this.analytics = analytics;\n this.adapter = adapter;\n\n this.adapter.adCallbacks.onAdStarted = (event) => this.onAdStarted(event);\n this.adapter.adCallbacks.onAdFinished = (event) => this.onAdFinished(event);\n this.adapter.adCallbacks.onAdBreakStarted = (event) => this.onAdBreakStarted(event);\n this.adapter.adCallbacks.onAdBreakFinished = (event) => this.onAdBreakFinished(event);\n this.adapter.adCallbacks.onAdClicked = (event) => this.onAdClicked(event);\n this.adapter.adCallbacks.onAdError = (event) => this.onAdError(event);\n this.adapter.adCallbacks.onAdManifestLoaded = (event) => this.onAdManifestLoaded(event);\n this.adapter.adCallbacks.onPlay = () => this.onPlay();\n this.adapter.adCallbacks.onPause = () => this.onPause();\n this.adapter.adCallbacks.onBeforeUnload = () => this.onBeforeUnload();\n this.adapter.adCallbacks.onAdSkipped = (event) => this.onAdSkipped(event);\n this.adapter.adCallbacks.onAdQuartile = (event) => this.onAdQuartile(event);\n\n this.viewportTracker = new ViewportTracker(this.adapter.getContainer(), () => this.onIntersectionChanged(), 0.5);\n }\n\n release() {\n this.clearCurrentTimeInterval();\n this.viewportTracker.dispose();\n this.adManifestDownloadTime = undefined;\n }\n\n onIntersectionChanged() {\n if (!this.activeAdSample) {\n return;\n }\n if (this.isContainerInViewport()) {\n this.enterViewportTimestamp = Utils.getCurrentTimestamp();\n } else {\n if (this.enterViewportTimestamp) {\n this.activeAdSample.timeInViewport =\n (this.activeAdSample.timeInViewport || 0) + Utils.getCurrentTimestamp() - this.enterViewportTimestamp;\n }\n }\n }\n\n isContainerInViewport(): boolean {\n return this.viewportTracker ? this.viewportTracker.isInViewport() : true;\n }\n\n onPlay() {\n if (this.adapter && this.adapter.isLinearAdActive() && this.activeAdSample) {\n const timestamp = Utils.getCurrentTimestamp();\n this.beginPlayingTimestamp = timestamp;\n this.enterViewportTimestamp = timestamp;\n this.isPlaying = true;\n }\n }\n\n onPause() {\n if (this.adapter && this.adapter.isLinearAdActive() && this.activeAdSample) {\n this.updatePlayingTime(this.activeAdSample);\n this.isPlaying = false;\n }\n }\n\n onAdManifestLoaded(payload: AdManifestLoadedPayload) {\n if (payload.isVmap) {\n this.sendAnalyticsRequest(new AdBreakSample(payload.adBreakInfo));\n return;\n }\n\n this.adManifestDownloadTime = payload.manifestDownloadTime;\n }\n\n onAdBreakStarted(adBreak: AdBreakInfo) {\n this.adPodPosition = 0;\n this.activeAdBreakSample = new AdBreakSample({\n ...adBreak,\n manifestDownloadTime: this.adManifestDownloadTime,\n });\n delete this.adManifestDownloadTime;\n this.adStartupTimestamp = Utils.getCurrentTimestamp();\n }\n\n onAdBreakFinished(_adBreak: AdBreakInfo) {\n this.resetActiveAd();\n this.activeAdBreakSample = undefined;\n }\n\n onAdStarted(ad: AdInfo) {\n if (!ad.isLinear) {\n return;\n }\n\n this.resetActiveAd();\n this.activeAdSample = new AdSample(ad);\n this.currentTime = undefined;\n this.activeAdSample.adStartupTime = this.adStartupTimestamp\n ? Utils.getCurrentTimestamp() - this.adStartupTimestamp\n : undefined;\n\n this.startAd(this.activeAdSample);\n }\n\n onAdFinished(_ad: AdInfo) {\n if (!this.activeAdBreakSample || !this.activeAdSample) {\n return;\n }\n\n const adSample = {...this.activeAdSample};\n adSample.completed = 1;\n this.resetActiveAd();\n this.completeAd(this.activeAdBreakSample, adSample, adSample.adDuration);\n }\n\n onAdSkipped(_ad: AdInfo) {\n if (!this.activeAdBreakSample || !this.activeAdSample) {\n return;\n }\n\n const adSample = {...this.activeAdSample};\n adSample.skipped = 1;\n adSample.skipPosition = this.currentTime;\n adSample.skipPercentage = Utils.calculatePercentage(adSample.skipPosition, this.activeAdSample.adDuration);\n this.resetActiveAd();\n this.completeAd(this.activeAdBreakSample, adSample, adSample.skipPosition);\n }\n\n onAdError(payload: AdErrorPayload) {\n const adBreakSample = new AdBreakSample(payload.adBreakInfo);\n\n const transformedError = this.analytics.transformError(\n {code: payload.code, message: payload.message, severity: 'CRITICAL'},\n payload,\n );\n\n adBreakSample.errorCode = transformedError.code;\n adBreakSample.errorData = tryJSONStringify({code: payload.code, message: payload.message});\n adBreakSample.errorMessage = transformedError.message;\n adBreakSample.errorSeverity = transformedError.severity;\n\n let adSample: AdSample | undefined;\n let errorPosition: number | undefined;\n if (this.activeAdSample && payload.activeAdId && this.activeAdSample.adId === payload.activeAdId) {\n adSample = this.activeAdSample;\n errorPosition = adSample.errorPosition = this.currentTime;\n adSample.errorPercentage = Utils.calculatePercentage(adSample.errorPosition, adSample.adDuration);\n }\n this.completeAd(adBreakSample, adSample, errorPosition);\n }\n\n onAdClicked(payload: AdClickedPayload) {\n if (!this.activeAdSample) {\n return;\n }\n this.activeAdSample.adClickthroughUrl = payload.clickThroughUrl;\n this.activeAdSample.clicked = 1;\n this.activeAdSample.clickPosition = this.currentTime;\n this.activeAdSample.clickPercentage = Utils.calculatePercentage(\n this.activeAdSample.clickPosition,\n this.activeAdSample.adDuration,\n );\n }\n\n onAdQuartile(payload: AdQuartilePayload) {\n if (!this.activeAdSample) {\n return;\n }\n if (payload.quartile === AdQuartile.FIRST_QUARTILE) {\n this.activeAdSample.quartile1 = 1;\n } else if (payload.quartile === AdQuartile.MIDPOINT) {\n this.activeAdSample.midpoint = 1;\n } else if (payload.quartile === AdQuartile.THIRD_QUARTILE) {\n this.activeAdSample.quartile3 = 1;\n }\n }\n\n onBeforeUnload() {\n if (this.onBeforeUnLoadEvent) {\n return;\n }\n this.onBeforeUnLoadEvent = true;\n if (!this.activeAdSample || !this.activeAdBreakSample) {\n return;\n }\n\n const adSample = {...this.activeAdSample};\n adSample.closed = 1;\n adSample.closePosition = this.currentTime;\n adSample.closePercentage = Utils.calculatePercentage(adSample.closePosition, adSample.adDuration);\n this.resetActiveAd();\n this.completeAd(this.activeAdBreakSample, adSample, adSample.closePosition);\n }\n\n createNewAdAnalyticsSample(analyticsSample: Sample): AdAnalyticsSample {\n const moduleInfo = this.adapter.getAdModuleInfo();\n return {\n ...new AdAnalyticsSample(analyticsSample),\n analyticsVersion: VERSION,\n adModule: moduleInfo.name,\n adModuleVersion: moduleInfo.version,\n autoplay: this.adapter.getAutoPlay(),\n pageLoadType: Utils.getPageLoadType(),\n };\n }\n\n private sendAnalyticsRequest(adBreakSample: AdBreakSample, adSample?: AdSample) {\n const sample = {\n ...this.createNewAdAnalyticsSample(this.analytics.sample),\n ...adBreakSample,\n ...(adSample || new AdSample()),\n };\n sample.time = Utils.getCurrentTimestamp();\n sample.adImpressionId = generateUUID();\n sample.percentageInViewport = Utils.calculatePercentage(sample.timeInViewport, sample.timePlayed);\n this.analytics.backend.sendAdRequest(sample);\n }\n\n private updatePlayingTime(adSample: AdSample) {\n const timestamp = Utils.getCurrentTimestamp();\n if (this.beginPlayingTimestamp && this.isPlaying) {\n if (adSample.timePlayed !== undefined) {\n adSample.timePlayed += timestamp - this.beginPlayingTimestamp;\n }\n if (this.isContainerInViewport() && this.enterViewportTimestamp && adSample.timeInViewport !== undefined) {\n adSample.timeInViewport += timestamp - this.enterViewportTimestamp;\n }\n }\n }\n\n private startAd(adSample: AdSample) {\n adSample.started = 1;\n adSample.timePlayed = 0;\n adSample.timeInViewport = 0;\n adSample.adPodPosition = this.adPodPosition;\n const timestamp = Utils.getCurrentTimestamp();\n this.beginPlayingTimestamp = timestamp;\n this.enterViewportTimestamp = this.isContainerInViewport() ? timestamp : undefined;\n this.isPlaying = true;\n this.currentTime = 0;\n this.adPodPosition++;\n this.currentTimeInterval = setInterval(() => {\n try {\n if (\n adSample &&\n adSample.adDuration !== undefined &&\n adSample.adDuration > 0 &&\n this.adapter.isLinearAdActive()\n ) {\n this.currentTime = Utils.calculateTime(Math.max(this.adapter.currentTime(), 0));\n }\n } catch (e) {\n logger.log('AdStarted monitoring interval failed and got cleared', e);\n this.resetActiveAd();\n }\n }, AdAnalytics.TIMEOUT_CURRENT_TIME_INTERVAL);\n }\n\n private completeAd(adBreakSample: AdBreakSample, adSample: AdSample = new AdSample(), exitPosition?: number) {\n adSample.exitPosition = exitPosition;\n adSample.playPercentage = Utils.calculatePercentage(adSample.exitPosition, adSample.adDuration);\n\n // Fallback to set quartile properties (if not set yet)\n // For players that don't emit native quartile events (THEOplayer) we calculate quartile properties based on playPercentage\n if (isNotNullish(adSample.playPercentage)) {\n if (adSample.quartile1 === 0 && adSample.playPercentage >= 25) {\n adSample.quartile1 = 1;\n }\n if (adSample.midpoint === 0 && adSample.playPercentage >= 50) {\n adSample.midpoint = 1;\n }\n if (adSample.quartile3 === 0 && adSample.playPercentage >= 75) {\n adSample.quartile3 = 1;\n }\n }\n\n // reset startupTimestamp for the next ad, in case there are multiple ads in one ad break\n this.adStartupTimestamp = Utils.getCurrentTimestamp();\n this.updatePlayingTime(adSample);\n this.isPlaying = false;\n this.sendAnalyticsRequest(adBreakSample, adSample);\n }\n\n private resetActiveAd() {\n this.clearCurrentTimeInterval();\n this.activeAdSample = undefined;\n }\n\n private clearCurrentTimeInterval() {\n clearInterval(this.currentTimeInterval);\n delete this.currentTime;\n }\n}\n","import {InternalAdapterAPI} from '../adapters/internal/InternalAdapterAPI';\nimport {AD_TYPE} from '../enums/AdType';\nimport {ErrorCode} from '../enums/ErrorCode';\nimport {PlayerSize} from '../enums/PlayerSize';\nimport {VideoStartFailedReason} from '../enums/VideoStartFailedReason';\nimport {ErrorDetailTrackingSettingsProvider} from '../features/errordetails/ErrorDetailTracking';\nimport {OnErrorDetailEventObject} from '../features/errordetails/OnErrorDetailEventObject';\nimport {FeatureManager} from '../features/FeatureManager';\nimport type {AnalyticsConfig, AnalyticsError} from '../types/AnalyticsConfig';\nimport {AuthenticationCallback} from '../types/AuthenticationCallback';\nimport {CustomDataValues, extractCustomDataFieldsOnly} from '../types/CustomDataValues';\nimport type {QualityChangeEvent} from '../types/EventData';\nimport * as EventData from '../types/EventData';\nimport {FeatureConfigContainer} from '../types/FeatureConfigContainer';\nimport {PlaybackInfo} from '../types/PlaybackInfo';\nimport {Sample} from '../types/Sample';\nimport type {SourceMetadata} from '../types/SourceMetadata';\nimport Timespan from '../types/Timespan';\nimport {\n applySourceMetadataToAnalyticsConfig,\n getDeviceInformationFromAnalyticsConfig,\n getDomainFromAnalyticsConfig,\n guardAgainstDuplicatedUserId,\n guardConfigChangeAgainstMissingIsLive,\n guardConfigChangeAgainstMissingTitle,\n mergeAnalyticsConfig,\n} from '../utils/analyticsConfigUtils';\nimport {CodecHelper} from '../utils/CodecHelper';\nimport {globalScope} from '../utils/globalScope';\nimport {\n getGlobalNavigatorLanguage,\n getGlobalNavigatorUserAgent,\n getGlobalScreenDimensions,\n hasGlobalWebOSApi,\n} from '../utils/globalScopeUtils';\nimport {logger} from '../utils/Logger';\nimport {isFiniteNumber, isNumber} from '../utils/numberUtils';\nimport {clearSampleStateValues, getDefaultSamplePath} from '../utils/sampleUtils';\nimport {isBlank, isValidString} from '../utils/stringUtils';\nimport * as Utils from '../utils/Utils';\nimport {isErrorSeverity, isNotNullish, isNullish, tryJSONStringify} from '../utils/Utils';\nimport {generateUUID} from '../utils/uuidUtils';\nimport {VERSION} from '../utils/Version';\nimport {getWebOSTVModelName} from '../utils/WebOSUtils';\n\nimport {AdAnalytics} from './AdAnalytics';\nimport {Backend} from './Backend';\nimport {BackendFactory} from './BackendFactory';\nimport {EventDispatcher, Subscribable} from './EventDispatcher';\nimport {IdenticalErrorReportingLimiter} from './IdenticalErrorReportingLimiter';\nimport {NoOpBackend} from './NoOpBackend';\nimport {SessionPersistenceHandler} from './SessionPersistenceHandler';\nimport {\n isSsaiEngagementErrorData,\n isSsaiEngagementQuartileData,\n isSsaiEngagementStartedData,\n SsaiEngagementInteractionData,\n} from './ssai/ssaiEngagementInteractionData';\nimport {createErrorAdSample, createQuartileAdSample, createStartedAdSample} from './ssai/ssaiUtils';\n\nexport class Analytics {\n get version(): string {\n return VERSION;\n }\n\n static version: string = VERSION;\n\n private readonly adAnalytics: AdAnalytics | undefined;\n\n sample: Sample;\n\n private hasSentStartupSample = false;\n backend!: Backend;\n readonly errorDetailTrackingSettingsProvider: ErrorDetailTrackingSettingsProvider;\n\n private config: AnalyticsConfig;\n private droppedSampleFrames = 0;\n /**\n * Used to save and store player startup time once the \"setup sample\" is created, to pick it up and use it to set\n * the \"startup sample\" property \"startupTime\" as a sum of player and video startup time.\n */\n private playerStartupTime = 0;\n\n private readonly authenticationCallback: AuthenticationCallback = {\n authenticationCompleted: (success: boolean, featureConfigs?: FeatureConfigContainer) => {\n this.featureManager.configureFeatures(success, featureConfigs);\n },\n };\n\n // used only in tests to inject mocks\n constructor(\n initialAnalyticsConfig: AnalyticsConfig,\n private readonly adapter: InternalAdapterAPI,\n private readonly backendFactory: BackendFactory,\n private readonly sessionHandler: SessionPersistenceHandler,\n private readonly featureManager: FeatureManager<FeatureConfigContainer>,\n private readonly onErrorDetailEventDispatcher: EventDispatcher<OnErrorDetailEventObject>,\n private readonly identicalErrorReportingLimiter: IdenticalErrorReportingLimiter,\n ) {\n this.config = initialAnalyticsConfig;\n this.sessionHandler = new SessionPersistenceHandler(this.config);\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const that = this;\n this.errorDetailTrackingSettingsProvider = {\n get domain() {\n return getDomainFromAnalyticsConfig(that.config);\n },\n get licenseKey() {\n return that.config.key ?? '';\n },\n get impressionId() {\n return that.getCurrentImpressionId() ?? '';\n },\n get collectorConfig() {\n return that.config.config;\n },\n };\n\n const licenseKeyReceivedUnsubscriber = this.adapter.onLicenseKeyReceived.subscribe(\n (eventArgs: {licenseKey: string}) => {\n if (!this.config.key) {\n this.config.key = eventArgs.licenseKey;\n }\n licenseKeyReceivedUnsubscriber();\n },\n );\n\n this.sample = this.buildInitialSample();\n this.droppedSampleFrames = 0;\n this.init();\n this.setupStateMachineCallbacks();\n\n // initialize adapter (start to listen to the player events and call the callbacks accordingly)\n const features = this.adapter.initialize(this);\n this.featureManager.registerFeatures(features);\n\n if (this.adapter.adModule) {\n // this needs to be called after the adapter has been initialized and has created adModule (if any)\n this.adAnalytics = new AdAnalytics(this, this.adapter.adModule);\n }\n }\n\n get errorDetailSubscribable(): Subscribable<OnErrorDetailEventObject> {\n return this.onErrorDetailEventDispatcher;\n }\n\n init() {\n if (\n this.adapter.supportsDeferredLicenseLoading !== true &&\n (!isValidString(this.config.key) || isBlank(this.config.key))\n ) {\n logger.errorMessageToUser('Invalid analytics license key provided');\n return;\n }\n\n logger.initialize(this.config.debug);\n\n this.featureManager.resetFeatures();\n\n const domain = getDomainFromAnalyticsConfig(this.config);\n this.backend = this.backendFactory.createBackend(\n this.config,\n {key: this.config.key, domain, version: VERSION},\n this.adapter,\n this.authenticationCallback,\n );\n\n this.hasSentStartupSample = false;\n this.identicalErrorReportingLimiter.reset();\n\n this.setConfigParameters();\n this.setAutoDetectedDeviceInformation();\n this.sample.impressionId = generateUUID();\n this.sample.userId = this.sessionHandler.userId;\n\n if (this.adapter.videoCompletionTracker) {\n this.adapter.videoCompletionTracker.reset();\n }\n\n this.adapter.qualityChangeService.resetValues();\n this.adapter.ssaiService.resetSourceRelatedState();\n }\n\n setConfigParameters() {\n this.sample.key = this.config.key;\n this.sample.playerKey = this.config.playerKey;\n if (this.config.player) {\n this.sample.player = this.config.player;\n }\n this.sample.domain = getDomainFromAnalyticsConfig(this.config);\n\n this.sample.deviceInformation = getDeviceInformationFromAnalyticsConfig(this.config);\n\n this.sample.isLive = isNotNullish(this.config.isLive) ? this.config.isLive : false;\n\n this.sample.cdnProvider = this.config.cdnProvider;\n this.sample.videoId = this.config.videoId;\n this.sample.videoTitle = this.config.title;\n this.sample.customUserId = this.config.userId ?? this.config.customUserId;\n\n Utils.transferCustomDataFields(this.config, this.sample);\n\n this.sample.experimentName = this.config.experimentName;\n }\n\n setAutoDetectedDeviceInformation(): void {\n // do not overwrite existing model value (set through config)\n if (isNotNullish(this.sample.deviceInformation?.model)) {\n return;\n }\n\n if (!hasGlobalWebOSApi()) return;\n\n const modelName = getWebOSTVModelName();\n if (isNullish(modelName)) return;\n\n this.sample.deviceInformation = this.sample.deviceInformation ?? {};\n this.sample.deviceInformation.model = modelName;\n }\n\n private setupStateMachineCallbacks() {\n // All of these are called in the onLeaveState Method.\n // So it's the last sample\n this.adapter.stateMachineCallbacks.setup = (duration: number, state: string) => {\n logger.log(\n 'Setup bitmovin analytics ' + this.sample.analyticsVersion + ' with impressionId: ' + this.sample.impressionId,\n );\n\n this.setDuration(duration);\n this.setState(state);\n this.sample.playerStartupTime = duration;\n this.playerStartupTime = this.sample.playerStartupTime;\n\n const navigationStart = globalScope.performance?.timing?.navigationStart;\n if (isNotNullish(navigationStart) && isFiniteNumber(navigationStart)) {\n // round the final time to a whole number to avoid unnecessary precision (performance API returns a high-precision timestamp as double)\n const pageLoadTime = Math.round(Date.now() - globalScope.performance.timing.navigationStart);\n this.sample.pageLoadTime = pageLoadTime;\n }\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.startup = (duration: number, state: string) => {\n this.setState(state);\n this.sample.supportedVideoCodecs = CodecHelper.supportedVideoFormats;\n // videoStartupTime has to be > 0 on startup sample\n // it is used to mark a successfull impression and billing depends on it\n const sanitizeVideoStartupTime = Math.max(duration, 1);\n this.setDuration(sanitizeVideoStartupTime);\n this.sample.videoStartupTime = sanitizeVideoStartupTime;\n this.sample.startupTime = (this.playerStartupTime || 0) + sanitizeVideoStartupTime;\n\n this.sample.autoplay = this.adapter.getAutoPlay();\n\n const drmPerformance = this.adapter.getDrmPerformanceInfo();\n if (isNotNullish(drmPerformance)) {\n this.sample.drmType = drmPerformance.drmType;\n this.sample.drmLoadTime = drmPerformance.drmLoadTime;\n }\n\n const {videoBitrate, audioBitrate} = this.adapter.getCurrentPlaybackInfo();\n // set the flag to allow quality change events after startup and try to set the startup bitrate values (if any)\n // as the initial ones, to be able to compare them with future quality changes\n this.adapter.qualityChangeService.setStartupHasFinished(videoBitrate, audioBitrate);\n\n this.hasSentStartupSample = true;\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.programChange = (sourceMetadata: SourceMetadata) => {\n // reset analytics\n // player is already loaded, so it is irrelevant for the program change startup sample\n this.playerStartupTime = 0;\n\n // apply source metadata to config\n this.config = applySourceMetadataToAnalyticsConfig(this.config, sourceMetadata);\n\n // reset sample to init values\n this.sample = this.buildInitialSample();\n // apply a source metadata path to the sample (if any)\n this.sample.path = isValidString(sourceMetadata.path) ? sourceMetadata.path : getDefaultSamplePath();\n\n // reinitialize to finish reset of the Analytics module\n this.init();\n\n // build startup \"programchange\" sample\n this.setState('programchange');\n this.sample.isProgramChange = true;\n this.sample.supportedVideoCodecs = CodecHelper.supportedVideoFormats;\n // videoStartupTime has to be > 0 on the startup sample\n // it is used to mark a successful impression and billing depends on it\n const programChangeVideoStartupTime = 1;\n this.setDuration(programChangeVideoStartupTime);\n this.sample.videoStartupTime = programChangeVideoStartupTime;\n this.sample.startupTime = programChangeVideoStartupTime; // is not affected now by player startup time\n\n this.sample.autoplay = this.adapter.getAutoPlay();\n\n // DRM load time is only important when we load the source, DRM request does not happen between active playback\n // so it can't happen during the program change\n this.sample.drmType = undefined;\n this.sample.drmLoadTime = undefined;\n\n const {videoBitrate, audioBitrate} = this.adapter.getCurrentPlaybackInfo();\n // set the flag to allow quality change events after startup and try to set the startup bitrate values (if any)\n // as the initial ones, to be able to compare them with future quality changes\n this.adapter.qualityChangeService.setStartupHasFinished(videoBitrate, audioBitrate);\n\n this.hasSentStartupSample = true;\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.updateSourceMetadata = (sourceMetadata: SourceMetadata) => {\n // apply source metadata to config\n this.config = applySourceMetadataToAnalyticsConfig(this.config, sourceMetadata);\n // new config should be immediately applied to the current sample\n this.setConfigParameters();\n this.setAutoDetectedDeviceInformation();\n // apply a source metadata path to the sample (if any)\n this.sample.path = isValidString(sourceMetadata.path) ? sourceMetadata.path : getDefaultSamplePath();\n };\n\n this.adapter.stateMachineCallbacks.playing = (duration: number, state: string) => {\n this.setDuration(duration);\n this.setState(state);\n this.sample.played = duration;\n this.setCompletionValues();\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.unload = (duration: number, state: string) => {\n let videoStartForClosedState = this.sample.videoTimeStart;\n if (state === 'playing') {\n this.setDuration(duration);\n this.setState(state);\n this.sample.played = duration;\n this.setCompletionValues();\n if (isNumber(this.sample.videoTimeEnd)) {\n videoStartForClosedState = this.sample.videoTimeEnd;\n }\n\n this.backend.sendUnloadRequest(this.sample);\n clearSampleStateValues(this.sample);\n }\n\n if (this.hasSentStartupSample) {\n this.setVideoTimeStart(videoStartForClosedState);\n this.setVideoTimeEnd(videoStartForClosedState);\n this.setState('closed');\n\n this.backend.sendUnloadRequest(this.sample);\n clearSampleStateValues(this.sample);\n }\n };\n\n this.adapter.stateMachineCallbacks.heartbeat = (duration, state, heartbeatPayload) => {\n this.setState(state);\n this.setDuration(duration);\n\n this.sample = {\n ...this.sample,\n ...heartbeatPayload,\n };\n\n if (state === 'playing') {\n this.setCompletionValues();\n }\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.qualitychange = (event: QualityChangeEvent) => {\n this.adapter.qualityChangeService.startResetInterval();\n this.adapter.qualityChangeService.increaseCounter();\n\n if (this.adapter.qualityChangeService.hasExceededQualityChangeThreshold()) {\n this.adapter.stateMachineCallbacks.error({\n code: ErrorCode.QUALITY_CHANGE_THRESHOLD_EXCEEDED.code,\n message: ErrorCode.QUALITY_CHANGE_THRESHOLD_EXCEEDED.message,\n errorSeverity: ErrorCode.QUALITY_CHANGE_THRESHOLD_EXCEEDED.errorSeverity,\n legacyData: undefined,\n data: {},\n currentTime: event.currentTime,\n });\n return;\n }\n\n this.setState('qualitychange');\n this.setDuration(0);\n this.adapter.stateMachineCallbacks.setVideoTimeEndFromEvent(event);\n this.adapter.stateMachineCallbacks.setVideoTimeStartFromEvent(event);\n this.adapter.stateMachineCallbacks.updateSampleQualityInfo(event);\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.updateSampleQualityInfo = (event: QualityChangeEvent) => {\n if (event.type === 'audio') {\n if (isNumber(event.bitrate)) {\n this.sample.audioBitrate = event.bitrate;\n }\n if (isValidString(event.codec)) {\n this.sample.audioCodec = event.codec;\n }\n } else if (event.type === 'video') {\n if (isNumber(event.bitrate)) {\n this.sample.videoBitrate = event.bitrate;\n }\n if (isValidString(event.codec)) {\n this.sample.videoCodec = event.codec;\n }\n if (isNumber(event.height)) {\n this.sample.videoPlaybackHeight = event.height;\n }\n if (isNumber(event.width)) {\n this.sample.videoPlaybackWidth = event.width;\n }\n }\n };\n\n this.adapter.stateMachineCallbacks.audiotrack_changing = () => {\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.pause = (duration: number, state: string) => {\n this.setDuration(duration);\n this.setState(state);\n\n this.sample.paused = duration;\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.seeking = (duration: number) => {\n this.setDuration(duration);\n this.setState('seeking');\n this.sample.seeked = duration;\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.rebuffering = (duration: number, state: string) => {\n this.setDuration(duration);\n this.setState(state);\n\n this.sample.buffered = duration;\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.videoStartFailed = (duration, reason) => {\n this.setState('startup');\n this.sample.videoStartFailed = true;\n this.sample.videoStartFailedReason = reason;\n this.sample.duration = duration;\n\n if (reason === VideoStartFailedReason.PLAYER_ERROR) {\n // on player error we should not send a video startup sample\n return;\n }\n\n if (reason === VideoStartFailedReason.TIMEOUT) {\n this.sample.errorCode = ErrorCode.VIDEO_STARTUP_TIMEOUT_REACHED.code;\n this.sample.errorMessage = ErrorCode.VIDEO_STARTUP_TIMEOUT_REACHED.message;\n this.sample.errorSeverity = ErrorCode.VIDEO_STARTUP_TIMEOUT_REACHED.errorSeverity;\n\n this.onErrorDetailEventDispatcher.dispatch({\n code: ErrorCode.VIDEO_STARTUP_TIMEOUT_REACHED.code,\n message: ErrorCode.VIDEO_STARTUP_TIMEOUT_REACHED.message,\n severity: ErrorCode.VIDEO_STARTUP_TIMEOUT_REACHED.errorSeverity,\n });\n }\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.error = (event: Readonly<EventData.ErrorEvent>) => {\n const error = this.transformError(\n {code: event.code, message: event.message, severity: event.errorSeverity ?? 'CRITICAL'},\n event.originalError,\n );\n\n if (error.code && !this.identicalErrorReportingLimiter.shouldReportError(error.code, error.severity)) {\n logger.log(\n `Bitmovin Analytics: Processing of the error with code ${error.code} was ignored because the error limit was exceeded.`,\n );\n return;\n }\n\n this.adapter.stateMachineCallbacks.setVideoTimeEndFromEvent(event);\n this.adapter.stateMachineCallbacks.setVideoTimeStartFromEvent(event);\n\n this.setState('error');\n this.setDuration(0);\n this.sample.errorCode = error.code;\n this.sample.errorMessage = error.message;\n this.sample.errorSeverity = error.severity;\n this.sample.errorData = tryJSONStringify(event.legacyData);\n this.sample.errorSegments = this.adapter.getSegmentInfo().map((s) => s.name);\n\n if (this.adapter.onError) {\n this.adapter.onError();\n }\n\n this.onErrorDetailEventDispatcher.dispatch({\n code: error.code,\n message: error.message,\n severity: error.severity,\n errorData: event.data,\n });\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.ad = (duration: number, state: string) => {\n this.setDuration(duration);\n this.setState(state);\n this.sample.ad = AD_TYPE.CSAI;\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.mute = () => {\n this.sample.isMuted = true;\n };\n\n this.adapter.stateMachineCallbacks.unMute = () => {\n this.sample.isMuted = false;\n };\n\n this.adapter.stateMachineCallbacks.subtitle_changing = () => {\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.setVideoTimeEndFromEvent = (analyticsEventBase) => {\n // if we don't have the current playback time, skip and do nothing\n if (!isNumber(analyticsEventBase?.currentTime)) {\n return;\n }\n\n this.setVideoTimeEnd(Utils.calculateTime(analyticsEventBase.currentTime));\n };\n\n this.adapter.stateMachineCallbacks.setVideoTimeStartFromEvent = (analyticsEventBase) => {\n // if we don't have the current playback time, skip and do nothing\n if (!isNumber(analyticsEventBase?.currentTime)) {\n return;\n }\n\n this.setVideoTimeStart(Utils.calculateTime(analyticsEventBase.currentTime));\n };\n\n this.adapter.stateMachineCallbacks.manualSourceChange = (event: {config: AnalyticsConfig}) => {\n this.adapter.resetSourceRelatedState();\n this.sample = this.buildInitialSample();\n this.droppedSampleFrames = 0;\n this.playerStartupTime = 0;\n this.config = Object.keys(event.config).length > 0 ? event.config : this.config;\n this.init();\n };\n\n this.adapter.stateMachineCallbacks.initialSourceChange = (event: {config: AnalyticsConfig}) => {\n this.config = event.config;\n this.setConfigParameters();\n this.setAutoDetectedDeviceInformation();\n };\n\n // The video has ended and we set up for a new impression\n this.adapter.stateMachineCallbacks.end = () => {\n // !!!! THIS IS OLD AND WRONG IMPLEMENTATION !!!!\n // (check deprecation comment on callback)\n this.sample = this.buildInitialSample();\n this.droppedSampleFrames = 0;\n this.playerStartupTime = 0;\n this.init();\n };\n\n this.adapter.stateMachineCallbacks.release = () => {\n this.backend = new NoOpBackend();\n this.adAnalytics?.release();\n this.adapter.qualityChangeService.stopResetInterval();\n this.identicalErrorReportingLimiter.reset();\n };\n\n this.adapter.stateMachineCallbacks.customdatachange = (_duration, _state, eventData) => {\n if (isNotNullish(eventData?.customDataValues)) {\n this.changeCustomData(eventData.customDataValues);\n }\n };\n }\n\n sourceChange = (config: AnalyticsConfig | null | undefined) => {\n logger.log('Processing Source Change for Analytics', config);\n if (isNullish(config)) {\n this.adapter.sourceChange(this.config);\n return;\n }\n\n guardConfigChangeAgainstMissingTitle(this.config, config);\n guardConfigChangeAgainstMissingIsLive(this.config, config);\n guardAgainstDuplicatedUserId(config);\n\n const newConfig = mergeAnalyticsConfig(this.config, config);\n this.adapter.sourceChange(newConfig);\n };\n\n setCustomDataOnce = (values: CustomDataValues) => {\n // save old config to be able to return previous custom data values once the sample is sent\n const oldConfig = {...this.config};\n\n this.setState('customdatachange');\n\n this.sendSample(values);\n // this method doesn't call changeCustomData() second time because in that method we have check for null values\n // to prevent overriding existing customData values with null if some field in object doesn't have value\n // because of that if some customData field had previous value null and it got changed to something else\n // it will not be possible to return it back to null using that method\n this.config = {...oldConfig};\n this.setConfigParameters();\n this.setAutoDetectedDeviceInformation();\n };\n\n setCustomData = (values: CustomDataValues) => {\n this.adapter.setCustomData(values);\n };\n\n getCurrentImpressionId = (): string | undefined => {\n return this.sample.impressionId;\n };\n\n getUserId = (): string => {\n return this.sessionHandler.userId;\n };\n\n setDuration(duration: number) {\n this.sample.duration = duration;\n }\n\n setState(state: string) {\n this.sample.state = state;\n }\n\n setPlaybackInfoFromAdapter() {\n const info = this.adapter.getCurrentPlaybackInfo();\n if (!info) {\n return;\n }\n\n // if set, we always apply `config.isLive` in favor of `info.isLive`\n this.sample.isLive = isNotNullish(this.config.isLive) ? this.config.isLive : info.isLive;\n // if `isLive` is still not defined, we set it to default `false` value\n if (isNullish(this.sample.isLive)) {\n this.sample.isLive = false;\n }\n\n if (isValidString(info.size)) {\n this.sample.size = info.size;\n }\n if (isValidString(info.playerTech)) {\n this.sample.playerTech = info.playerTech;\n }\n if (isNumber(info.videoDuration)) {\n this.sample.videoDuration = Utils.calculateTime(info.videoDuration || 0);\n }\n if (isValidString(info.streamFormat)) {\n this.sample.streamFormat = info.streamFormat;\n }\n if (isValidString(info.mpdUrl)) {\n this.sample.mpdUrl = info.mpdUrl;\n }\n if (isValidString(info.m3u8Url)) {\n this.sample.m3u8Url = info.m3u8Url;\n }\n if (isValidString(info.progUrl)) {\n this.sample.progUrl = info.progUrl;\n }\n if (isNumber(info.videoWindowWidth)) {\n this.sample.videoWindowWidth = info.videoWindowWidth;\n }\n if (isNumber(info.videoWindowHeight)) {\n this.sample.videoWindowHeight = info.videoWindowHeight;\n }\n if (isNumber(info.screenHeight)) {\n this.sample.screenHeight = info.screenHeight;\n }\n if (isNumber(info.screenWidth)) {\n this.sample.screenWidth = info.screenWidth;\n }\n if (Utils.isBoolean(info.isMuted)) {\n this.sample.isMuted = info.isMuted;\n }\n if (Utils.isBoolean(info.isCasting)) {\n this.sample.isCasting = info.isCasting;\n }\n if (isValidString(info.castTech)) {\n this.sample.castTech = info.castTech;\n }\n if (isValidString(info.videoTitle) && !this.config.title) {\n this.sample.videoTitle = info.videoTitle;\n }\n if (isValidString(info.audioCodec)) {\n this.sample.audioCodec = info.audioCodec;\n }\n if (isValidString(info.videoCodec)) {\n this.sample.videoCodec = info.videoCodec;\n }\n if (isValidString(info.audioLanguage)) {\n this.sample.audioLanguage = info.audioLanguage;\n }\n if (Utils.isBoolean(info.subtitleEnabled)) {\n this.sample.subtitleEnabled = info.subtitleEnabled;\n }\n if (isValidString(info.subtitleLanguage)) {\n this.sample.subtitleLanguage = info.subtitleLanguage;\n } else {\n this.sample.subtitleLanguage = undefined;\n }\n if (isNumber(info.droppedFrames)) {\n this.sample.droppedFrames = Math.max(info.droppedFrames - this.droppedSampleFrames, 0);\n this.droppedSampleFrames = info.droppedFrames;\n }\n }\n\n sendSample(customDataOnceValues?: CustomDataValues) {\n this.setPlaybackInfoFromAdapter();\n this.sample.time = Utils.getCurrentTimestamp();\n\n // get current download speed info from the adapter and set it on the sample before sending it\n this.sample.downloadSpeedInfo = this.adapter.getDownloadSpeedInfo();\n // reset current download speed info measures in the adapter to start fresh for the next sample,\n // so we always have the info for the current sample only\n this.adapter.resetDownloadSpeedInfoMeasures();\n\n this.adapter.ssaiService.manipulate(this.sample);\n\n // if we have received custom data from the setCustomDataOnce API call, we need to set\n // them as \"the last one\" (we need to override normal customData and SSAI custom data)\n if (customDataOnceValues != null) {\n this.changeCustomData(customDataOnceValues);\n }\n\n // Initial quality info should be available for the first sample after setup, so if there is no quality info yet, we try to set it *before* sending a sample.\n // In the general case, a qualitychange event first triggers a sample of the state we were in before the qualitychange sample itself is sent.\n // So to only report quality updates on the qualitychange sample and not the ones before it, we need to update the quality info *after* sending a sample,\n // making it available for future samples (e.g. qualitychange sample).\n // We only check videoBitrate and not audioBitrate since the latter is often reported as null/0 anyways.\n if (isNullish(this.sample.videoBitrate) || this.sample.videoBitrate <= 0) {\n setQualityInfoOnSample(this.sample, this.adapter.getCurrentPlaybackInfo());\n const copySample = {...this.sample};\n this.backend.sendRequest(copySample);\n } else {\n const copySample = {...this.sample};\n this.backend.sendRequest(copySample);\n setQualityInfoOnSample(this.sample, this.adapter.getCurrentPlaybackInfo());\n }\n\n // clear sample state values after sending a sample\n clearSampleStateValues(this.sample);\n }\n\n sendSsaiEngagementAdSample(data: SsaiEngagementInteractionData) {\n if (this.config.config?.ssaiEngagementTrackingEnabled !== true) {\n // if not enabled in config, do not send SSAI engagement AdSample\n return;\n }\n\n if (isSsaiEngagementStartedData(data)) {\n const ssaiAdSample = createStartedAdSample(this.sample, data);\n\n this.backend.sendAdRequest(ssaiAdSample);\n return;\n }\n\n if (isSsaiEngagementQuartileData(data)) {\n const ssaiAdSample = createQuartileAdSample(this.sample, data);\n\n this.backend.sendAdRequest(ssaiAdSample);\n return;\n }\n\n if (isSsaiEngagementErrorData(data)) {\n data.analyticsError = this.transformError(data.analyticsError, data.originalError);\n\n const ssaiErrorAdSample = createErrorAdSample(this.sample, data);\n\n this.backend.sendAdRequest(ssaiErrorAdSample);\n return;\n }\n }\n\n /**\n * This method sanitizes the input and updates the analytics config.\n * @param values Object containing the customData and other fields\n */\n private changeCustomData = (values: CustomDataValues) => {\n this.config = {\n ...this.config,\n ...extractCustomDataFieldsOnly(values),\n };\n this.setConfigParameters();\n this.setAutoDetectedDeviceInformation();\n };\n\n private setCompletionValues() {\n if (this.adapter.videoCompletionTracker) {\n const completed = this.adapter.videoCompletionTracker.addWatched({\n start: this.sample.videoTimeStart,\n end: this.sample.videoTimeEnd,\n } as Timespan);\n const completedTotal = this.adapter.videoCompletionTracker.getCompletionPercentage();\n\n if (!Number.isNaN(completed) && !Number.isNaN(completedTotal)) {\n this.sample.completed = completed;\n this.sample.completedTotal = completedTotal;\n }\n }\n }\n\n private setVideoTimeStart(value: number | undefined) {\n this.sample.videoTimeStart = value;\n }\n\n private setVideoTimeEnd(value: number | undefined) {\n this.sample.videoTimeEnd = value;\n }\n\n transformError(error: AnalyticsError, originalError: any): AnalyticsError {\n const analyticsError = {\n code: error.code,\n message: error.message,\n severity: error.severity,\n };\n\n try {\n const transformedError = this.config.config?.errorTransformerCallback?.transform(analyticsError, {\n originalError: originalError,\n });\n\n analyticsError.code = isNumber(transformedError?.code) ? transformedError?.code : analyticsError.code;\n analyticsError.message = isValidString(transformedError?.message)\n ? transformedError?.message\n : analyticsError.message;\n analyticsError.severity =\n isValidString(transformedError?.severity) && isErrorSeverity(transformedError?.severity)\n ? transformedError!.severity\n : analyticsError.severity;\n } catch (error) {\n logger.error('Error in errorTransformerCallback', error);\n }\n\n return analyticsError;\n }\n\n private buildInitialSample(): Sample {\n const player = this.config.player || this.adapter.getPlayerName();\n const screenDimensions = getGlobalScreenDimensions();\n\n return {\n ad: 0,\n analyticsVersion: VERSION,\n audioBitrate: 0,\n buffered: 0,\n completedTotal: 0,\n droppedFrames: 0,\n duration: 0,\n isLive: this.config.isLive ?? false,\n language: getGlobalNavigatorLanguage(),\n pageLoadTime: 0,\n pageLoadType: Utils.getPageLoadType(),\n path: getDefaultSamplePath(),\n paused: 0,\n platform: 'web',\n played: 0,\n player,\n playerStartupTime: 0,\n playerTech: this.adapter.getPlayerTech(),\n screenHeight: screenDimensions?.height,\n screenWidth: screenDimensions?.width,\n seeked: 0,\n size: PlayerSize.Window,\n startupTime: 0,\n time: 0,\n userAgent: getGlobalNavigatorUserAgent(),\n version: player + '-' + this.adapter.getPlayerVersion(),\n videoBitrate: 0,\n videoDuration: 0,\n videoPlaybackHeight: 0,\n videoPlaybackWidth: 0,\n videoStartupTime: 0,\n videoTimeEnd: 0,\n videoTimeStart: 0,\n videoWindowHeight: 0,\n videoWindowWidth: 0,\n };\n }\n\n static create(config: AnalyticsConfig, adapter: InternalAdapterAPI): Analytics {\n const backendFactory: BackendFactory = new BackendFactory();\n const sessionHandler: SessionPersistenceHandler = new SessionPersistenceHandler(config);\n const featureManager = new FeatureManager<FeatureConfigContainer>();\n const onErrorDetailEventDispatcher = new EventDispatcher<OnErrorDetailEventObject>();\n const identicalErrorReportingLimiter = new IdenticalErrorReportingLimiter();\n return new Analytics(\n config,\n adapter,\n backendFactory,\n sessionHandler,\n featureManager,\n onErrorDetailEventDispatcher,\n identicalErrorReportingLimiter,\n );\n }\n}\n\n// We separate the quality info from `setPlaybackInfoFromAdapter` to be able to explicitly set/update the quality info only when it changes.\nexport function setQualityInfoOnSample(sample: Sample, playbackInfo: PlaybackInfo) {\n if (isNumber(playbackInfo.videoPlaybackHeight)) {\n sample.videoPlaybackHeight = playbackInfo.videoPlaybackHeight;\n }\n if (isNumber(playbackInfo.videoPlaybackWidth)) {\n sample.videoPlaybackWidth = playbackInfo.videoPlaybackWidth;\n }\n if (isNumber(playbackInfo.videoBitrate)) {\n sample.videoBitrate = playbackInfo.videoBitrate;\n }\n if (isNumber(playbackInfo.audioBitrate)) {\n sample.audioBitrate = playbackInfo.audioBitrate;\n }\n}\n","import {DeferredLicenseLoadingAdapterAPI} from '../adapters/internal/DeferredLicenseLoadingAdapterAPI';\nimport {AnalyticsConfig, CollectorConfig} from '../types/AnalyticsConfig';\nimport {AuthenticationCallback} from '../types/AuthenticationCallback';\nimport {LicensingRequest} from '../types/LicensingRequest';\nimport {LicenseCall} from '../utils/LicenseCall';\nimport {ANALYTICS_BACKEND_BASE_URL} from '../utils/Settings';\n\nimport {Backend} from './Backend';\nimport {DebuggingBackend} from './DebuggingBackend';\nimport {LicenseCheckingBackend} from './LicenseCheckingBackend';\nimport {LongPlaytimeFilteringBackend} from './LongPlaytimeFilteringBackend';\nimport {NoOpBackend} from './NoOpBackend';\nimport {SequenceNumberBackend} from './SequenceNumberBackend';\n\ninterface InternalCollectorConfig extends CollectorConfig {\n wrapBackend: (innerBackend: Backend) => Backend;\n}\n\nexport class BackendFactory {\n createBackend(\n analyticsConfig: AnalyticsConfig,\n licensingRequest: LicensingRequest,\n adapter: DeferredLicenseLoadingAdapterAPI,\n authenticationCallback: AuthenticationCallback,\n ): Backend {\n if (!this.isEnabled(analyticsConfig)) {\n return new NoOpBackend();\n }\n const inner = this.createInnerBackend(analyticsConfig, licensingRequest, adapter, authenticationCallback);\n return this.decorateWithDebuggingBackend(analyticsConfig, inner);\n }\n\n private decorateWithDebuggingBackend(config: AnalyticsConfig, backend: Backend): Backend {\n if (config.debug) {\n return new DebuggingBackend(config, backend);\n }\n return backend;\n }\n\n private decorateWithBackendFromConfigIfAvailable(analyticsConfig: AnalyticsConfig, innerBackend: Backend): Backend {\n if (\n analyticsConfig !== undefined &&\n analyticsConfig.config !== undefined &&\n (analyticsConfig.config as InternalCollectorConfig).wrapBackend !== undefined\n ) {\n return (analyticsConfig.config as InternalCollectorConfig).wrapBackend(innerBackend);\n }\n\n return innerBackend;\n }\n\n private isEnabled(analyticsConfig: AnalyticsConfig): boolean {\n return analyticsConfig.config === undefined || analyticsConfig.config.enabled !== false;\n }\n\n private createInnerBackend(\n analyticsConfig: AnalyticsConfig,\n licensingRequest: LicensingRequest,\n adapter: DeferredLicenseLoadingAdapterAPI,\n authenticationCallback: AuthenticationCallback,\n ): Backend {\n const backendUrl = (analyticsConfig.config && analyticsConfig.config.backendUrl) || ANALYTICS_BACKEND_BASE_URL;\n let innerBackend: Backend = new LicenseCheckingBackend(\n licensingRequest,\n LicenseCall,\n backendUrl,\n adapter,\n authenticationCallback,\n );\n innerBackend = this.decorateWithBackendFromConfigIfAvailable(analyticsConfig, innerBackend);\n\n const sequenceNumberAssigningBackend = new SequenceNumberBackend(innerBackend);\n return new LongPlaytimeFilteringBackend(sequenceNumberAssigningBackend);\n }\n}\n","import {AdAnalyticsSample} from '../types/AdAnalyticsSample';\nimport {AdBreakSample} from '../types/AdBreakSample';\nimport {AdSample} from '../types/AdSample';\nimport type {AnalyticsConfig, AnalyticsDebugConfig} from '../types/AnalyticsConfig';\nimport {Sample} from '../types/Sample';\nimport {logger} from '../utils/Logger';\n\nimport {Backend} from './Backend';\n\n/**\n * The `DebuggingBackend` is responsible for printing debugging information\n * before forwarding the requests to the specified underlying backend.\n *\n * This allows for inspection of specific fields in the sample data before it is sent.\n * The fields can be specified through the {@link AnalyticsDebugConfig#fields}.\n *\n * @implements {Backend}\n * */\nexport class DebuggingBackend implements Backend {\n private underlying: Backend;\n private debugFields?: string[];\n\n constructor(config: AnalyticsConfig, underlying: Backend) {\n this.underlying = underlying;\n if (config.debug && (config.debug as AnalyticsDebugConfig).fields) {\n this.debugFields = (config.debug as AnalyticsDebugConfig).fields;\n }\n }\n\n sendRequest(sample: Sample) {\n this.printFields(sample);\n this.underlying.sendRequest(sample);\n }\n\n sendUnloadRequest(sample: Sample) {\n this.printFields(sample);\n this.underlying.sendUnloadRequest(sample);\n }\n\n sendRequestSynchronous(sample: Sample) {\n this.printFields(sample);\n this.underlying.sendRequestSynchronous(sample);\n }\n\n sendAdRequest(sample: AdAnalyticsSample & AdBreakSample & AdSample) {\n this.underlying.sendAdRequest(sample);\n }\n\n private printFields(sample: Sample) {\n if (this.debugFields && this.debugFields.length) {\n const fields = {};\n this.debugFields.forEach((f) => (fields[f] = sample[f]));\n logger.table([fields]);\n }\n }\n}\n","import {DownloadSpeedInfo} from '../types/DownloadSpeedInfo';\nimport {SpeedMeasurement} from '../types/SpeedMeasurement';\nimport {Converter} from '../utils/Converter';\n\nimport {Measure} from './Measure';\n\nexport class DownloadSpeedMeter {\n protected measures: Measure[];\n\n constructor() {\n this.measures = [];\n }\n\n reset(): void {\n this.measures = [];\n }\n\n addMeasurement(measurement: SpeedMeasurement): void {\n if (measurement.httpStatus >= 400) {\n return;\n }\n const measure = new Measure(measurement);\n\n const threshold = Converter.bitsToBytes(300 * 1000 * 1000); // 300 Megabit per second in bytes\n if (measure.speed >= threshold) {\n return;\n }\n\n this.measures.push(measure);\n }\n\n getInfo(): DownloadSpeedInfo {\n return {\n segmentsDownloadCount: this.measures.length,\n segmentsDownloadSize: this.measures.map((m) => m.size).reduce(this.add, 0),\n segmentsDownloadTime: Math.ceil(this.totalTime() * 1000),\n avgDownloadSpeed: this.avgSpeed(),\n minDownloadSpeed: this.minSpeed(),\n maxDownloadSpeed: this.maxSpeed(),\n avgTimeToFirstByte: this.avgTimeToFirstByte(),\n };\n }\n\n private add(a: number, b: number): number {\n return a + b;\n }\n\n private avgSpeed(): number {\n if (this.measures.length === 0) {\n return 0;\n }\n const totalSpeed = this.speeds().reduce((a, b) => {\n return a + b;\n }, 0);\n const numMeasurements = this.measures.length;\n return this.bytePerSecondToBitPerSecond(totalSpeed / numMeasurements);\n }\n\n private bytePerSecondToBitPerSecond(bps: number): number {\n return Converter.bytesToBits(bps);\n }\n\n private minSpeed(): number {\n if (this.measures.length === 0) {\n return 0;\n }\n return this.bytePerSecondToBitPerSecond(Math.min(...this.speeds()));\n }\n\n private speeds(): number[] {\n return this.measures.map((m) => {\n return m.speed;\n });\n }\n\n private maxSpeed(): number {\n if (this.measures.length === 0) {\n return 0;\n }\n return this.bytePerSecondToBitPerSecond(Math.max(...this.speeds()));\n }\n\n private totalTime(): number {\n if (this.measures.length === 0) {\n return 0;\n }\n return this.measures.reduce((a, b) => {\n return a + b.duration;\n }, 0);\n }\n\n private avgTimeToFirstByte(): number {\n if (this.measures.length === 0) {\n return 0;\n }\n const avg =\n this.measures.reduce((a, b) => {\n return a + b.timeToFirstByte * 1000;\n }, 0) / this.measures.length;\n\n return Math.ceil(avg);\n }\n}\n","export interface Subscribable<TArgs> {\n subscribe(callback: EventHandler<TArgs>): () => void;\n unsubscribe(callback: EventHandler<TArgs>);\n}\n\ntype EventHandler<TArgs> = (args: TArgs) => void;\n\nexport class EventDispatcher<TArgs> implements Subscribable<TArgs> {\n private callbacks: Array<EventHandler<TArgs>> = [];\n\n subscribe(callback: EventHandler<TArgs>): () => void {\n this.callbacks.push(callback);\n\n return () => this.unsubscribe(callback);\n }\n\n dispatch(args: TArgs) {\n const callbacks = this.callbacks.slice(0);\n callbacks.forEach((callback) => {\n callback(args);\n });\n }\n\n unsubscribe(callback: EventHandler<TArgs>) {\n const index = this.callbacks.indexOf(callback);\n if (index > -1) {\n this.callbacks.splice(index, 1);\n }\n }\n\n get subscriberCount() {\n return this.callbacks.length;\n }\n}\n","export const DEFAULT_HEARTBEAT_INTERVAL_MS = 59700;\n\nexport interface HeartbeatListener {\n /**\n * @param playerCurrentTime the current player playback time of the video in seconds.\n */\n onHeartbeat: (playerCurrentTime: number) => void;\n}\n\n/** Get the current player playback time of the video in seconds. */\ntype PlayerCurrentTimeCallback = () => number;\n\nexport class HeartbeatService {\n private heartbeatInterval: ReturnType<typeof setInterval> | undefined;\n private listener: HeartbeatListener | undefined;\n private readonly getPlayerCurrentTime: PlayerCurrentTimeCallback;\n\n constructor(getPlayerCurrentTime: PlayerCurrentTimeCallback) {\n this.getPlayerCurrentTime = getPlayerCurrentTime;\n }\n\n setListener(listener: HeartbeatListener) {\n this.listener = listener;\n }\n\n startHeartbeat() {\n if (this.heartbeatInterval !== undefined) {\n this.clearHeartbeat();\n }\n this.heartbeatInterval = setInterval(() => {\n this.listener?.onHeartbeat(this.getPlayerCurrentTime());\n }, DEFAULT_HEARTBEAT_INTERVAL_MS);\n }\n\n stopHeartbeat() {\n this.clearHeartbeat();\n }\n\n private clearHeartbeat() {\n clearTimeout(this.heartbeatInterval);\n this.heartbeatInterval = undefined;\n }\n}\n","import {ErrorSeverity} from '../types/AnalyticsConfig';\n\n/**\n * This class is used to limit error reporting for identical consecutive error codes and severities per session.\n *\n * Repeated consecutive errors of the same code and severity are limited to {@link IdenticalErrorReportingLimiter.MAX_IDENTICAL_ERROR_REPORTING}.\n */\nexport class IdenticalErrorReportingLimiter {\n /** The maximum number of times the same error code and severity can be reported consecutively. */\n private static MAX_IDENTICAL_ERROR_REPORTING = 5;\n\n private _lastErrorCode: number | undefined;\n private _lastErrorSeverity: ErrorSeverity | undefined;\n private _currentErrorCount = 0;\n\n /**\n * Determines whether an error with the given errorCode and errorSeverity should be reported,\n * based on the limit of identical consecutive error reports.\n *\n * @param errorCode - The error code for which we are checking the reporting conditions.\n * @param errorSeverity - The error severity for which we are checking the reporting conditions.\n * @returns {boolean} - Returns true if the error can be reported, false if it exceeds the limits.\n */\n shouldReportError(errorCode: number, errorSeverity: ErrorSeverity): boolean {\n if (errorCode === this._lastErrorCode && errorSeverity === this._lastErrorSeverity) {\n this._currentErrorCount++;\n return this._currentErrorCount <= IdenticalErrorReportingLimiter.MAX_IDENTICAL_ERROR_REPORTING;\n }\n\n this._lastErrorCode = errorCode;\n this._lastErrorSeverity = errorSeverity;\n this._currentErrorCount = 1;\n return true;\n }\n\n reset() {\n this._lastErrorCode = undefined;\n this._lastErrorSeverity = undefined;\n this._currentErrorCount = 0;\n }\n}\n","import {DeferredLicenseLoadingAdapterAPI} from '../adapters/internal/DeferredLicenseLoadingAdapterAPI';\nimport {AdAnalyticsSample} from '../types/AdAnalyticsSample';\nimport {AdBreakSample} from '../types/AdBreakSample';\nimport {AdSample} from '../types/AdSample';\nimport {AuthenticationCallback} from '../types/AuthenticationCallback';\nimport {LicenseCallFunc, LicensingRequest, LicensingResponse, LicensingResult} from '../types/LicensingRequest';\nimport {Sample} from '../types/Sample';\nimport {logger} from '../utils/Logger';\nimport {ANALYTICS_LICENSECALL_TIMEOUT} from '../utils/Settings';\n\nimport {Backend} from './Backend';\nimport {NoOpBackend} from './NoOpBackend';\nimport {QueueBackend} from './QueueBackend';\nimport {RemoteBackend} from './RemoteBackend';\n\n/**\n * The `LicenseCheckingBackend` class is responsible for sending license requests\n * and routing samples to the appropriate backend based on the license status.\n *\n * The class manages a queue of samples during the license check process, ensuring that\n * samples are not lost while the license status is being determined. Once the license\n * is validated, the queued samples are flushed to the appropriate backend.\n *\n * @implements {Backend}\n */\nexport class LicenseCheckingBackend implements Backend {\n promise?: Promise<LicensingResponse>;\n private licenseLazyLoadingTimeoutHandle?: ReturnType<typeof setTimeout>;\n private backend: Backend;\n private info: LicensingRequest;\n\n constructor(\n info: LicensingRequest,\n private licenseCall: LicenseCallFunc,\n private backendBaseUrl: string,\n private adapter: DeferredLicenseLoadingAdapterAPI,\n private authenticationCallback: AuthenticationCallback,\n ) {\n this.info = {...info};\n this.backend = new QueueBackend();\n this.licenseCall = licenseCall;\n\n if (info.key !== undefined && info.key !== '') {\n this.promise = this.wrapLicenseCheckPromiseWithCallback(this.performLicenseCheck(), this.authenticationCallback);\n } else if (adapter.supportsDeferredLicenseLoading === true) {\n adapter.onLicenseKeyReceived.subscribe(this.licenseKeyReceived);\n adapter.onLicenseCallFailed.subscribe(this.licenseCallFailed);\n this.licenseLazyLoadingTimeoutHandle = setTimeout(this.licenseLazyLoadingTimeout, ANALYTICS_LICENSECALL_TIMEOUT);\n } else {\n authenticationCallback.authenticationCompleted(false, undefined);\n this.backend = new NoOpBackend();\n }\n }\n\n performLicenseCheck(): Promise<LicensingResponse> {\n const {key, domain, version} = this.info;\n if (!key || key === '') {\n const error: LicensingResponse = {\n status: LicensingResult.Denied,\n message: 'No license key provided',\n };\n this.backend = new NoOpBackend();\n return Promise.resolve(error);\n }\n\n return this.licenseCall(key, domain, version, this.backendBaseUrl)\n .then((result) => {\n if (result.status === LicensingResult.Granted) {\n const remoteBackend = new RemoteBackend(true, this.backendBaseUrl, key);\n (this.backend as QueueBackend).flushTo(remoteBackend);\n this.backend = remoteBackend;\n } else {\n throw new Error(result.message);\n }\n return result;\n })\n .catch((err: Error) => {\n if (err.message === 'Ignoring Impression due to DNT Header being set') {\n logger.error('License Check for Bitmovin Analytics failed because of', err);\n } else {\n logger.errorMessageToUser('License Check for Bitmovin Analytics failed because of', err);\n }\n this.backend = new NoOpBackend();\n return {\n status: LicensingResult.Denied,\n message: err.message,\n };\n });\n }\n\n sendRequest(sample: Sample) {\n this.backend.sendRequest(sample);\n }\n sendUnloadRequest(sample: Sample) {\n this.backend.sendUnloadRequest(sample);\n }\n sendRequestSynchronous(sample: Sample) {\n this.backend.sendRequestSynchronous(sample);\n }\n sendAdRequest(sample: AdAnalyticsSample & AdBreakSample & AdSample) {\n this.backend.sendAdRequest(sample);\n }\n\n private licenseKeyReceived = (eventArgs: {licenseKey: string}) => {\n clearTimeout(this.licenseLazyLoadingTimeoutHandle);\n this.unsubscribeFromAdapter();\n this.info.key = eventArgs.licenseKey;\n this.promise = this.wrapLicenseCheckPromiseWithCallback(this.performLicenseCheck(), this.authenticationCallback);\n };\n\n private licenseCallFailed = () => {\n clearTimeout(this.licenseLazyLoadingTimeoutHandle);\n this.unsubscribeFromAdapter();\n this.backend = new NoOpBackend();\n this.authenticationCallback.authenticationCompleted(false, undefined);\n };\n\n private licenseLazyLoadingTimeout = () => {\n this.unsubscribeFromAdapter();\n this.backend = new NoOpBackend();\n this.authenticationCallback.authenticationCompleted(false, undefined);\n };\n\n private unsubscribeFromAdapter() {\n this.adapter.onLicenseKeyReceived.unsubscribe(this.licenseKeyReceived);\n this.adapter.onLicenseCallFailed.unsubscribe(this.licenseCallFailed);\n }\n\n private wrapLicenseCheckPromiseWithCallback(\n promise: Promise<LicensingResponse>,\n authenticationCallback: AuthenticationCallback,\n ): Promise<LicensingResponse> {\n return promise.then((response) => {\n authenticationCallback.authenticationCompleted(response.status === LicensingResult.Granted, response.features);\n return response;\n });\n }\n}\n","import {Sample} from '../types/Sample';\nimport {isNullish} from '../utils/Utils';\n\nimport {Backend} from './Backend';\n\n/**\n * The `LongPlaytimeFilteringBackend` is a decorator class that filters out samples\n * where the `played` time exceeds a specified threshold.\n *\n * If a sample's `played` time surpasses the threshold, it is not forwarded to the next backend.\n * Otherwise, the sample is passed along to the next backend for further processing.\n *\n * @implements {Backend}\n */\nexport class LongPlaytimeFilteringBackend implements Backend {\n nextBackend: Backend;\n\n constructor(next: Backend) {\n this.nextBackend = next;\n }\n\n sendRequest(sample: Sample) {\n if (this.isPlayedAboveThreshold(sample)) {\n return;\n }\n this.nextBackend.sendRequest(sample);\n }\n\n sendUnloadRequest(sample: Sample) {\n if (this.isPlayedAboveThreshold(sample)) {\n return;\n }\n this.nextBackend.sendUnloadRequest(sample);\n }\n\n sendRequestSynchronous(sample: Sample) {\n if (this.isPlayedAboveThreshold(sample)) {\n return;\n }\n this.nextBackend.sendRequestSynchronous(sample);\n }\n\n sendAdRequest(sample: any) {\n this.nextBackend.sendAdRequest(sample);\n }\n\n private isPlayedAboveThreshold(sample: Sample): boolean {\n return (isNullish(sample.played) ? 0 : sample.played) >= 90000;\n }\n}\n","import {SpeedMeasurement} from '../types/SpeedMeasurement';\n\nexport class Measure implements SpeedMeasurement {\n private download: SpeedMeasurement;\n\n get speed(): number {\n return this.download.size / this.download.duration;\n }\n get duration(): number {\n return this.download.duration;\n }\n get size(): number {\n return this.download.size;\n }\n get timeToFirstByte(): number {\n return this.download.timeToFirstByte;\n }\n get timestamp(): Date {\n return this.download.timestamp;\n }\n\n get httpStatus(): number {\n return this.download.httpStatus;\n }\n\n constructor(download: SpeedMeasurement) {\n this.download = download;\n }\n}\n","import {AdAnalyticsSample} from '../types/AdAnalyticsSample';\nimport {AdBreakSample} from '../types/AdBreakSample';\nimport {AdSample} from '../types/AdSample';\nimport {Sample} from '../types/Sample';\n\nimport {Backend} from './Backend';\n\n/**\n * The `NoOpBackend` is a no-operation implementation of the `Backend` interface.\n * It serves as a placeholder backend when the actual `Backend` functionality is disabled or not required.\n * E.g. in scenarios such as releasing the adapter or when the Collector is disabled via {@link CollectorConfig#enabled}.\n *\n * Using `NoOpBackend` ensures that the code does not need to handle cases where `Backend` might be undefined,\n * thereby simplifying the logic and reducing the need for null or undefined checks.\n *\n * @implements {Backend}\n */\nexport class NoOpBackend implements Backend {\n sendRequest(_sample: Sample) {\n // empty\n }\n sendUnloadRequest(_sample: Sample) {\n // empty\n }\n sendRequestSynchronous(_sample: Sample) {\n // empty\n }\n sendAdRequest(_sample: AdAnalyticsSample & AdBreakSample & AdSample) {\n // empty\n }\n}\n","import {isFiniteNumber} from '../utils/numberUtils';\nimport * as Settings from '../utils/Settings';\n\nconst INITIAL_VALUE = 0;\n\n/**\n * This service is responsible for deciding whether a quality change event should be sent or not, based on\n * - the quality changes count that has already been sent in a certain timeframe/interval\n * - the previous video and audio bitrate values, to avoid sending the first quality change event or the following\n * events when the bitrate did not change (some players report quality changes with the same bitrate, which should\n * not be tracked)\n * - whether the startup has finished, to avoid sending quality change events for the initial bitrate values\n * that some players report before startup, which can differ from the ones that are used after startup\n */\nexport default class QualityChangeService {\n /** Flag to block quality change events when a certain threshold in a certain timeframe/interval is exceeded */\n private qualityChangeCount = INITIAL_VALUE;\n private qualityChangeCountResetIntervalId: ReturnType<typeof setInterval> | undefined;\n private readonly QUALITY_CHANGE_COUNT_THRESHOLD: number;\n\n /** Flag to block the first (initial) video quality change event or the following events when the bitrate did not change */\n private previousVideoBitrate = INITIAL_VALUE;\n /** Flag to block the first (initial) audio quality change event or the following events when the bitrate did not change */\n private previousAudioBitrate = INITIAL_VALUE;\n\n /** Flag to block quality change events until startup has finished */\n private startupHasFinished = false;\n\n constructor(qualityChangeCountThreshold: number = Settings.ANALYTICS_QUALITY_CHANGE_COUNT_THRESHOLD) {\n this.QUALITY_CHANGE_COUNT_THRESHOLD = qualityChangeCountThreshold;\n }\n\n resetValues() {\n this.qualityChangeCount = INITIAL_VALUE;\n this.stopResetInterval();\n\n this.previousVideoBitrate = INITIAL_VALUE;\n this.previousAudioBitrate = INITIAL_VALUE;\n\n this.startupHasFinished = false;\n }\n\n increaseCounter() {\n this.qualityChangeCount++;\n }\n\n hasExceededQualityChangeThreshold(): boolean {\n return this.qualityChangeCount > this.QUALITY_CHANGE_COUNT_THRESHOLD;\n }\n\n setStartupHasFinished(startupVideoBitrate: number | undefined, startupAudioBitrate: number | undefined): void {\n this.startupHasFinished = true;\n\n // check if the startup video bitrate value is known/defined and valid\n if (isFiniteNumber(startupVideoBitrate)) {\n this.previousVideoBitrate = startupVideoBitrate;\n }\n // check if the startup audio bitrate value is known/defined and valid\n if (isFiniteNumber(startupAudioBitrate)) {\n this.previousAudioBitrate = startupAudioBitrate;\n }\n }\n\n shouldAllowVideoQualityChange(newBitrate: number | undefined): boolean {\n return (\n // if the startup has finished\n this.startupHasFinished &&\n // if the new bitrate value is valid\n isFiniteNumber(newBitrate) &&\n // if the new bitrate is not the first one reported (the initial value is not still set)\n this.previousVideoBitrate !== INITIAL_VALUE &&\n // if the bitrate did change\n this.previousVideoBitrate !== newBitrate &&\n // if the quality change count threshold has not been exceeded\n !this.hasExceededQualityChangeThreshold()\n );\n }\n\n setVideoBitrate(newBitrate: number): void {\n if (this.startupHasFinished) {\n this.previousVideoBitrate = newBitrate;\n }\n }\n\n shouldAllowAudioQualityChange(newBitrate: number | undefined): boolean {\n return (\n // if the startup has finished\n this.startupHasFinished &&\n // if the new bitrate value is valid\n isFiniteNumber(newBitrate) &&\n // if the new bitrate is not the first one reported (the initial value is not still set)\n this.previousAudioBitrate !== INITIAL_VALUE &&\n // if the bitrate did change\n this.previousAudioBitrate !== newBitrate &&\n // if the quality change count threshold has not been exceeded\n !this.hasExceededQualityChangeThreshold()\n );\n }\n\n setAudioBitrate(newBitrate: number): void {\n if (this.startupHasFinished) {\n this.previousAudioBitrate = newBitrate;\n }\n }\n\n startResetInterval() {\n if (this.qualityChangeCountResetIntervalId !== undefined) {\n return;\n }\n\n this.qualityChangeCountResetIntervalId = setInterval(() => {\n this.qualityChangeCount = 0;\n }, Settings.ANALYTICS_QUALITY_CHANGE_COUNT_RESET_INTERVAL);\n }\n\n stopResetInterval() {\n if (this.qualityChangeCountResetIntervalId === undefined) {\n return;\n }\n\n clearInterval(this.qualityChangeCountResetIntervalId);\n delete this.qualityChangeCountResetIntervalId;\n }\n}\n","import {AdAnalyticsSample} from '../types/AdAnalyticsSample';\nimport {AdBreakSample} from '../types/AdBreakSample';\nimport {AdSample} from '../types/AdSample';\nimport {Sample} from '../types/Sample';\n\nimport {Backend} from './Backend';\n\n/**\n * The `QueueBackend` class is responsible for queuing samples for deferred processing.\n * Samples are stored in different queues depending on the sample type and can be flushed\n * to another backend for further processing.\n *\n * This is useful e.g. to still collect sample data while waiting for a license call to succeed.\n *\n * @implements {Backend}\n */\nexport class QueueBackend implements Backend {\n queue: Sample[] = [];\n unloadQueue: Sample[] = [];\n syncQueue: Sample[] = [];\n adQueue: Array<AdAnalyticsSample & AdBreakSample & AdSample> = [];\n\n sendRequest(sample: Sample) {\n this.queue.push(sample);\n }\n sendUnloadRequest(sample: Sample) {\n this.unloadQueue.push(sample);\n }\n sendRequestSynchronous(sample: Sample) {\n this.syncQueue.push(sample);\n }\n sendAdRequest(sample: AdAnalyticsSample & AdBreakSample & AdSample) {\n this.adQueue.push(sample);\n }\n\n flushTo(backend: Backend) {\n this.queue.forEach((e) => {\n backend.sendRequest(e);\n });\n this.unloadQueue.forEach((e) => {\n backend.sendUnloadRequest(e);\n });\n this.syncQueue.forEach((e) => {\n backend.sendRequestSynchronous(e);\n });\n this.adQueue.forEach((e) => {\n backend.sendAdRequest(e);\n });\n }\n}\n","import {AdAnalyticsSample} from '../types/AdAnalyticsSample';\nimport {AdBreakSample} from '../types/AdBreakSample';\nimport {AdSample} from '../types/AdSample';\nimport {Sample} from '../types/Sample';\nimport {AnalyticsCall} from '../utils/AnalyticsCall';\nimport {noOp} from '../utils/Utils';\n\nimport {Backend} from './Backend';\n\n/**\n * The `RemoteBackend` class is responsible for actually sending out the samples using the {@link AnalyticsCall} class.\n * Before each sample is sent, the `RemoteBackend` attaches a license key to the sample.\n *\n * @implements {Backend}\n */\nexport class RemoteBackend implements Backend {\n analyticsCall: AnalyticsCall;\n hasAdModule: boolean;\n\n constructor(\n hasAdModule: boolean,\n backendBaseUrl: string,\n private licenseKey: string,\n ) {\n this.hasAdModule = hasAdModule;\n this.analyticsCall = new AnalyticsCall(backendBaseUrl);\n }\n\n sendRequest(sample: Sample) {\n sample.key = this.licenseKey;\n this.analyticsCall.sendRequest(sample, noOp);\n }\n\n sendUnloadRequest(sample: Sample) {\n sample.key = this.licenseKey;\n this.analyticsCall.sendUnloadRequest(sample);\n }\n\n sendRequestSynchronous(sample: Sample) {\n sample.key = this.licenseKey;\n this.analyticsCall.sendRequestSynchronous(sample, noOp);\n }\n\n sendAdRequest(sample: AdAnalyticsSample & AdBreakSample & AdSample) {\n sample.key = this.licenseKey;\n if (!this.hasAdModule) {\n return;\n }\n this.analyticsCall.sendAdRequest(sample);\n }\n}\n","import {SegmentInfo} from '../types/SegmentInfo';\n\nexport class SegmentTracker {\n protected segments: SegmentInfo[];\n\n constructor() {\n this.segments = [];\n }\n\n reset(): void {\n this.segments = [];\n }\n\n addSegment(segment: SegmentInfo): void {\n this.segments.push(segment);\n }\n\n removeSegment(url: string): void {\n this.segments = this.segments.filter((s) => s.url !== url);\n }\n\n getSegments(): SegmentInfo[] {\n return this.segments;\n }\n}\n","import {AdAnalyticsSample} from '../types/AdAnalyticsSample';\nimport {AdBreakSample} from '../types/AdBreakSample';\nimport {AdSample} from '../types/AdSample';\nimport {Sample} from '../types/Sample';\nimport {SEQUENCE_NUMBER_LIMIT} from '../utils/Settings';\n\nimport {Backend} from './Backend';\n\n/**\n * The `SequenceNumberBackend` is a decorator class that increments a samples sequence number and filters out samples\n * where the `sequenceNumber` exceeds a specified threshold.\n *\n * If a sample's `sequenceNumber` surpasses the threshold, it is not forwarded to the next backend.\n * Otherwise, the sample is passed along to the next backend for further processing.\n *\n * @implements {Backend}\n */\nexport class SequenceNumberBackend implements Backend {\n nextBackend: Backend;\n sequenceNumber = 0;\n\n constructor(underlying: Backend) {\n this.nextBackend = underlying;\n }\n\n sendRequest(sample: Sample) {\n this.updateSampleBeforeSending(sample);\n if (this.isSequenceNumberAboveThreshold(sample)) {\n return;\n }\n this.nextBackend.sendRequest(sample);\n }\n\n sendUnloadRequest(sample: Sample) {\n this.updateSampleBeforeSending(sample);\n if (this.isSequenceNumberAboveThreshold(sample)) {\n return;\n }\n this.nextBackend.sendUnloadRequest(sample);\n }\n\n sendRequestSynchronous(sample: Sample) {\n this.updateSampleBeforeSending(sample);\n if (this.isSequenceNumberAboveThreshold(sample)) {\n return;\n }\n this.nextBackend.sendRequestSynchronous(sample);\n }\n\n sendAdRequest(sample: AdAnalyticsSample & AdBreakSample & AdSample) {\n if (this.isSequenceNumberAboveThreshold(sample)) {\n return;\n }\n this.nextBackend.sendAdRequest(sample);\n }\n\n private updateSampleBeforeSending(sample: Sample) {\n sample.sequenceNumber = this.sequenceNumber++;\n }\n\n private isSequenceNumberAboveThreshold(sample: Sample): boolean {\n return (sample.sequenceNumber ?? 0) > SEQUENCE_NUMBER_LIMIT;\n }\n}\n","import type {AnalyticsConfig} from '../types/AnalyticsConfig';\nimport {deleteCookie, getCookie, setCookie} from '../utils/documentUtils';\nimport {isNumber} from '../utils/numberUtils';\nimport {isBlank, isValidString} from '../utils/stringUtils';\nimport {isNotNullish, isNullish} from '../utils/Utils';\nimport {generateUUID} from '../utils/uuidUtils';\n\nexport const COOKIE_NAME_BITMOVIN_ANALYTICS_UUID = 'bitmovin_analytics_uuid';\n/** One year in seconds */\nexport const COOKIE_DEFAULT_MAX_AGE = 365 * 24 * 60 * 60;\n\nexport class SessionPersistenceHandler {\n readonly userId: string;\n\n constructor(config: AnalyticsConfig) {\n const collectorConfig = config.config;\n\n const shouldNotUseCookies = collectorConfig?.cookiesEnabled === false;\n\n if (shouldNotUseCookies) {\n deleteCookie(COOKIE_NAME_BITMOVIN_ANALYTICS_UUID);\n this.userId = generateUUID();\n return;\n }\n\n const existingUserId = getCookie(COOKIE_NAME_BITMOVIN_ANALYTICS_UUID);\n this.userId = isNotNullish(existingUserId) && !isBlank(existingUserId) ? existingUserId : generateUUID();\n\n const cookieDomain = validateCookieDomainValue(collectorConfig?.cookiesDomain);\n const cookieMaxAge = validateCookieMaxAgeValue(collectorConfig?.cookiesMaxAge);\n\n // we set also expires, because max-age is not supported on old browsers like IE8\n const nowMillis = Date.now();\n const expirationDate = new Date(nowMillis + cookieMaxAge * 1000);\n const cookieExpires = expirationDate.toUTCString();\n\n setCookie(COOKIE_NAME_BITMOVIN_ANALYTICS_UUID, this.userId, {\n domain: cookieDomain,\n expires: cookieExpires,\n maxAge: cookieMaxAge,\n });\n }\n}\n\nexport const validateCookieDomainValue = (value: unknown): string | undefined => {\n if (isNullish(value)) {\n return undefined;\n }\n\n if (!isValidString(value)) {\n return undefined;\n }\n\n if (isBlank(value)) {\n return undefined;\n }\n\n return encodeURIComponent(value);\n};\n\nexport const validateCookieMaxAgeValue = (value: unknown): number => {\n if (isNullish(value)) {\n return COOKIE_DEFAULT_MAX_AGE;\n }\n\n if (!isNumber(value)) {\n return COOKIE_DEFAULT_MAX_AGE;\n }\n\n return value;\n};\n","import type {CodecInfo} from '../types/CodecInfo';\nimport type {PlaybackInfo} from '../types/PlaybackInfo';\nimport {isBlank} from '../utils/stringUtils';\nimport {isNotNullish} from '../utils/Utils';\n\n/**\n * This class is used to store source specific information for the player\n * mainly as a fallback if sourceInfo cannot be determined by the player since the source is already unloaded\n */\nexport class SourceInfoFallbackService {\n private streamFormat: PlaybackInfo['streamFormat'];\n private audioCodec: PlaybackInfo['audioCodec'];\n private videoCodec: PlaybackInfo['videoCodec'];\n\n reset() {\n this.streamFormat = undefined;\n this.audioCodec = undefined;\n this.videoCodec = undefined;\n }\n\n setStreamFormat(streamFormat: PlaybackInfo['streamFormat']) {\n this.streamFormat = streamFormat;\n }\n\n applyStreamFormat(playbackInfo: PlaybackInfo) {\n if (isBlank(this.streamFormat)) {\n return;\n }\n playbackInfo.streamFormat = this.streamFormat;\n }\n\n /**\n * Apply fallback values to {@link PlaybackInfo} if available.\n * If provided {@link CodecInfo} values are available, we store them as new fallback values, before we apply them.\n */\n applyAndStoreCodecInfo(playbackInfo: PlaybackInfo, codecInfo: CodecInfo | undefined) {\n if (isNotNullish(codecInfo?.audioCodec)) {\n this.audioCodec = codecInfo.audioCodec;\n }\n if (isNotNullish(codecInfo?.videoCodec)) {\n this.videoCodec = codecInfo.videoCodec;\n }\n\n if (!isBlank(this.audioCodec)) {\n playbackInfo.audioCodec = this.audioCodec;\n }\n if (!isBlank(this.videoCodec)) {\n playbackInfo.videoCodec = this.videoCodec;\n }\n }\n}\n","import Timespan from '../types/Timespan';\nimport {isNullish} from '../utils/Utils';\n\nenum TimespanOverlappingType {\n None,\n Overlapping,\n FirstContainedInSecond,\n SecondContainedInFirst,\n}\n\nexport default class VideoCompletionTracker {\n private watched: Timespan[] = [];\n private videoDuration: number | null = null;\n\n reset(): void {\n this.watched = [];\n }\n\n /**\n * sets video Duration\n * @param videoDuration in sec\n */\n setVideoDuration(videoDuration: number): void {\n this.videoDuration = videoDuration * 1000;\n }\n\n /**\n * Adds the watched timespan to the tracker\n * @param watched watched timespan you want to add to the tracker\n * @returns how much time(video parts which have not been seen yet) was added to the tracker\n */\n addWatched(watched: Timespan): number {\n if (isNullish(this.videoDuration)) {\n throw new Error('no video duration set for completion tracker');\n }\n\n this.watched.push(watched);\n const overlappingTimespan = this.mergeWatched(this.watched);\n return (this.getDuration(watched) - overlappingTimespan) / this.videoDuration;\n }\n\n /**\n * returns the relative value of how much the user watch the content of the video\n */\n getCompletionPercentage(): number {\n if (isNullish(this.videoDuration)) {\n throw new Error('no video duration set for completion tracker');\n }\n\n let watched = 0;\n for (const w of this.watched) {\n watched += this.getDuration(w);\n }\n return watched / this.videoDuration;\n }\n\n /**\n * Recursive Method to merge All Watched Blocks\n * @param watched\n *\n * @returns how much timespan was overlapping while merging the watchBlocks\n */\n private mergeWatched(watched: Timespan[]): number {\n for (let i = 0; i < watched.length; i++) {\n const time1 = watched[i];\n for (let k = i + 1; k < watched.length; k++) {\n const time2 = watched[k];\n let overlappingTimespan = 0;\n const overlapType = this.getOverlappingType(time1, time2);\n\n if (overlapType === TimespanOverlappingType.Overlapping) {\n this.mergeAndReplace(time1, i, time2, k);\n overlappingTimespan = this.getOverlappingTimespan(time1, time2);\n } else if (overlapType === TimespanOverlappingType.FirstContainedInSecond) {\n this.watched.splice(i, 1);\n overlappingTimespan = this.getDuration(time1);\n } else if (overlapType === TimespanOverlappingType.SecondContainedInFirst) {\n this.watched.splice(k, 1);\n overlappingTimespan = this.getDuration(time2);\n }\n if (overlapType !== TimespanOverlappingType.None) {\n return overlappingTimespan + this.mergeWatched(this.watched);\n }\n }\n }\n return 0;\n }\n\n private getOverlappingType(first: Timespan, second: Timespan): TimespanOverlappingType {\n if (\n (this.isMomentInTimespan(first.end, second) && first.start < second.start) ||\n (this.isMomentInTimespan(first.start, second) && first.end > second.end)\n ) {\n return TimespanOverlappingType.Overlapping;\n } else if (this.isMomentInTimespan(first.start, second) && this.isMomentInTimespan(first.end, second)) {\n return TimespanOverlappingType.FirstContainedInSecond;\n } else if (this.isMomentInTimespan(second.start, first) && this.isMomentInTimespan(second.end, first)) {\n return TimespanOverlappingType.SecondContainedInFirst;\n }\n return TimespanOverlappingType.None;\n }\n\n private isMomentInTimespan(moment: number, timespan: Timespan): boolean {\n return moment >= timespan.start && moment < timespan.end;\n }\n\n private mergeAndReplace(first: Timespan, firstIndex: number, second: Timespan, secondIndex: number): void {\n const end = first.end > second.end ? first.end : second.end;\n const start = first.start < second.start ? first.start : second.start;\n const newWatchedTimespan: Timespan = {start, end};\n this.watched.splice(firstIndex, 1, newWatchedTimespan);\n this.watched.splice(secondIndex, 1);\n }\n\n private getOverlappingTimespan(first: Timespan, second: Timespan): number {\n const end = first.end < second.end ? first.end : second.end;\n const start = first.start >= second.start ? first.start : second.start;\n return end - start;\n }\n\n private getDuration(watched: Timespan): number {\n return Math.abs(watched.end - watched.start);\n }\n}\n","import type {SsaiAdBreakMetadata, SsaiAdMetadata, SsaiAdQuartile, SsaiAdQuartileMetadata} from '../../api/AdapterAPI';\nimport {AD_TYPE} from '../../enums/AdType';\nimport {ErrorCode} from '../../enums/ErrorCode';\nimport {AnalyticsError} from '../../types/AnalyticsConfig';\nimport {customDataValuesKeys} from '../../types/CustomDataValues';\nimport type {Sample} from '../../types/Sample';\nimport {isNotNullish} from '../../utils/Utils';\nimport {generateUUID} from '../../utils/uuidUtils';\n\nimport type {InternalSsaiMetadata, SsaiEngagementInteractionData} from './ssaiEngagementInteractionData';\nimport {\n getCurrentMonotonicTimestampInMs,\n getMonotonicTimestampInMsSince,\n SSAI_RELATED_SAMPLE_MARKER,\n} from './ssaiUtils';\n\nexport type SsaiEventHandler = {\n getPlayerCurrentTime: () => number;\n reportEngagementInteraction: (data: SsaiEngagementInteractionData) => void;\n reportPlaybackInteraction: (timestamp: number, playerCurrentTime: number) => void;\n};\n\nenum SsaiState {\n AD_BREAK_STARTED,\n ACTIVE,\n IDLE,\n}\n\n// we start with -1, to be able to increment it before sending the first sample\n// this way the current adIndex is the one of the current playing ad\nconst INITIAL_AD_INDEX_VALUE = -1;\n\nexport class SsaiService {\n /** if `undefined` then service is not active and should not do anything, why: initially we activate it only for Bitmovin8 */\n private eventHandler: SsaiEventHandler | undefined = undefined;\n\n /** Index of the current ad in the whole session */\n private adIndex: number = INITIAL_AD_INDEX_VALUE;\n\n private state: SsaiState = SsaiState.IDLE;\n private isFirstSampleOfAd = false;\n /**\n * represents the current playing ad metadata\n * is `undefined` when no ad is playing (after endAdBreak)\n * or omitted by customer\n */\n private currentAdMetadata: InternalSsaiMetadata | undefined;\n\n /**\n * The impression id for the currently playing ad\n * is undefined when no ad is playing\n */\n private currentAdImpressionId: string | undefined;\n\n /** List of quartiles already sent for the current ad */\n private sentAdQuartiles: SsaiAdQuartile[] = [];\n\n /**\n * Flags whether an error was sent during an ad to avoid sending multiple errors for one ad,\n * which would skew e.g. the ad abandonment rate.\n */\n private errorSent: boolean = false;\n\n /**\n * The timestamp marking when the `adStart` method was called.\n * This timestamp is used to calculate the time difference between the `adStart` call\n * and subsequent `adQuartileFinished` or `sendAdEngagementErrorSample` calls.\n */\n private timestampOfAdStart: number | undefined;\n\n activate(eventHandler: SsaiEventHandler) {\n this.eventHandler = eventHandler;\n }\n\n adBreakStart(adBreakMetadata?: SsaiAdBreakMetadata) {\n if (!isActivated(this.eventHandler)) {\n // nothing to do if service is not active\n return;\n }\n\n if (this.state != SsaiState.IDLE) {\n return;\n }\n\n this.state = SsaiState.AD_BREAK_STARTED;\n this.currentAdMetadata = {\n ...adBreakMetadata,\n };\n }\n\n adStart(adMetadata?: SsaiAdMetadata) {\n if (!isActivated(this.eventHandler)) {\n // nothing to do if service is not active\n return;\n }\n\n if (this.state == SsaiState.IDLE) {\n return;\n }\n\n const timestamp = new Date().getTime();\n const playerCurrentTime = this.eventHandler.getPlayerCurrentTime();\n\n // report playback sample - will be saved in our playback related data lake\n // - with the first adStart call we need to close the current normal playback sample (no ssai ad information yet because SsaiState is not yet set to active)\n // - with all following adStart calls, we will deliver previous ssai ad information (SsaiState is already set to active)\n this.eventHandler.reportPlaybackInteraction(timestamp, playerCurrentTime);\n\n this.state = SsaiState.ACTIVE;\n // to include the adIndex in the next sample which will be the first sample of this started ad\n this.isFirstSampleOfAd = true;\n this.adIndex++;\n\n this.resetAdData();\n\n this.currentAdMetadata = {\n adPosition: this.currentAdMetadata?.adPosition,\n adId: adMetadata?.adId,\n adSystem: adMetadata?.adSystem,\n customData: adMetadata?.customData,\n };\n\n this.currentAdImpressionId = generateUUID();\n this.timestampOfAdStart = getCurrentMonotonicTimestampInMs();\n\n // report engagement sample - will be saved in our ad related data lake\n this.eventHandler.reportEngagementInteraction({\n type: 'started',\n adIndex: this.adIndex,\n currentAdImpressionId: this.currentAdImpressionId,\n currentAdMetadata: isNotNullish(this.currentAdMetadata) ? this.currentAdMetadata : {},\n });\n }\n\n adQuartileFinished(adQuartile: SsaiAdQuartile, adQuartileMetadata: SsaiAdQuartileMetadata) {\n if (!isActivated(this.eventHandler)) {\n // nothing to do if service is not activated\n return;\n }\n\n if (this.state != SsaiState.ACTIVE) {\n return;\n }\n\n if (this.sentAdQuartiles.includes(adQuartile)) {\n //do nothing if adQuartile was already sent\n return;\n }\n\n this.eventHandler.reportEngagementInteraction({\n type: 'quartile',\n adIndex: this.adIndex,\n currentAdImpressionId: this.currentAdImpressionId!,\n currentAdMetadata: isNotNullish(this.currentAdMetadata) ? this.currentAdMetadata : {},\n quartile: adQuartile,\n quartileMetadata: adQuartileMetadata,\n timeSinceAdStartedInMs: getMonotonicTimestampInMsSince(this.timestampOfAdStart),\n });\n this.sentAdQuartiles.push(adQuartile);\n }\n\n adBreakEnd() {\n if (!isActivated(this.eventHandler)) {\n // nothing to do if service is not active\n return;\n }\n\n if (this.state == SsaiState.IDLE) {\n return;\n }\n\n if (this.state == SsaiState.ACTIVE) {\n const timestamp = new Date().getTime();\n const playerCurrentTime = this.eventHandler.getPlayerCurrentTime();\n this.eventHandler.reportPlaybackInteraction(timestamp, playerCurrentTime);\n }\n\n this.resetAdBreakData();\n }\n\n manipulate(sample: Sample): void {\n if (!isActivated(this.eventHandler)) {\n // nothing to do if service is not active\n return;\n }\n\n if (this.state != SsaiState.ACTIVE) {\n return;\n }\n\n sample.ad = AD_TYPE.SSAI;\n sample.adId = this.currentAdMetadata?.adId;\n sample.adSystem = this.currentAdMetadata?.adSystem;\n sample.adPosition = this.currentAdMetadata?.adPosition;\n // we only mark the first sample of an ssai ad with the index in the playback/audience data (non ad table)\n // this allows us to count the number of ads\n if (this.isFirstSampleOfAd) {\n sample.adIndex = this.adIndex;\n this.isFirstSampleOfAd = false;\n }\n\n const customData = this.currentAdMetadata?.customData;\n if (isNotNullish(customData)) {\n customDataValuesKeys.forEach((key) => {\n if (customData[key]) {\n sample[key] = customData[key];\n }\n });\n }\n\n sample[SSAI_RELATED_SAMPLE_MARKER] = true; // mark it as ssai sample\n }\n\n sendAdEngagementErrorSample(error: AnalyticsError, originalError: any) {\n if (!isActivated(this.eventHandler)) {\n // nothing to do if service is not active\n return;\n }\n\n if (this.state !== SsaiState.ACTIVE) {\n return;\n }\n\n // only send one error sample per ad\n if (this.errorSent) {\n return;\n }\n\n // This error code is related to the Analytics product and is non-fatal.\n // It is not triggered by the Player and does not interrupt or affect playback,\n // so there is no need to report an ad error sample.\n if (error.code === ErrorCode.QUALITY_CHANGE_THRESHOLD_EXCEEDED.code) {\n return;\n }\n\n this.eventHandler.reportEngagementInteraction({\n type: 'error',\n adIndex: this.adIndex,\n currentAdImpressionId: this.currentAdImpressionId!,\n currentAdMetadata: isNotNullish(this.currentAdMetadata) ? this.currentAdMetadata : {},\n analyticsError: error,\n originalError: originalError,\n timeSinceAdStartedInMs: getMonotonicTimestampInMsSince(this.timestampOfAdStart),\n });\n this.errorSent = true;\n }\n\n isInActiveState(): boolean {\n return this.state === SsaiState.ACTIVE;\n }\n\n resetSourceRelatedState() {\n this.resetAdBreakData();\n this.adIndex = INITIAL_AD_INDEX_VALUE;\n }\n\n private resetAdBreakData() {\n this.state = SsaiState.IDLE;\n this.isFirstSampleOfAd = false;\n delete this.currentAdMetadata;\n this.resetAdData();\n }\n\n private resetAdData() {\n delete this.currentAdMetadata?.customData;\n delete this.currentAdMetadata?.adId;\n delete this.currentAdMetadata?.adSystem;\n this.errorSent = false;\n this.currentAdImpressionId = undefined;\n this.sentAdQuartiles = [];\n this.timestampOfAdStart = undefined;\n }\n}\n\nfunction isActivated(eventHandler: SsaiEventHandler | undefined): eventHandler is SsaiEventHandler {\n return isNotNullish(eventHandler);\n}\n","import type {\n AdPosition,\n SsaiAdBreakMetadata,\n SsaiAdMetadata,\n SsaiAdQuartile,\n SsaiAdQuartileMetadata,\n} from '../../api/AdapterAPI';\nimport {CustomDataValues, sanitizeCustomDataValues} from '../../types/CustomDataValues';\nimport {logger} from '../../utils/Logger';\nimport {isValidString} from '../../utils/stringUtils';\nimport {isNotNullish, isNullish, isPlainObject} from '../../utils/Utils';\n\nexport function isAdPosition(anything: unknown): anything is AdPosition {\n // invalid, when not defined as one of string values we expect\n return anything === 'preroll' || anything === 'midroll' || anything === 'postroll';\n}\n\n/** User SSAI API input validation */\nexport function hasValidSsaiAdBreakMetadataStructure(\n anything: unknown,\n): anything is SsaiAdBreakMetadata | null | undefined {\n // \"nullish\" is considered to be valid (SSAI API parameter is optional)\n if (isNullish(anything)) return true;\n\n // invalid, when value was defined, but not as a plain object\n if (!isPlainObject(anything as object)) {\n logger.errorMessageToUser('Invalid SsaiAdBreakMetadata: not a plain object');\n return false;\n }\n\n const maybeSsaiAdBreakMetadata = anything as SsaiAdBreakMetadata;\n\n // invalid, when `adPosition` was defined, but not as an ad position string we expect\n if (isNotNullish(maybeSsaiAdBreakMetadata.adPosition) && !isAdPosition(maybeSsaiAdBreakMetadata.adPosition)) {\n logger.errorMessageToUser(\"Invalid SsaiAdBreakMetadata: 'adPosition' property is not valid\");\n return false;\n }\n\n return true;\n}\n\n/**\n * Simple sanitization of {@link SsaiAdBreakMetadata} without object structure check,\n * because {@link hasValidSsaiAdBreakMetadataStructure} should be called before in adapter SSAI API function!\n *\n * Sanitization:\n * - if `undefined/null` is passed, it will return `undefined`\n * - recreate a new object to avoid side effects by using same reference from outside\n *\n * @param adBreakMetadata SsaiAdBreakMetadata or `undefined` (optional SSAI API parameter)\n */\nexport function simplySanitizeSsaiAdBreakMetadata(\n adBreakMetadata: SsaiAdBreakMetadata | undefined,\n): SsaiAdBreakMetadata | undefined {\n // \"nullish\" is considered to be valid (SSAI API parameter is optional)\n if (isNullish(adBreakMetadata)) {\n // sanitize to use `undefined` in code\n return undefined;\n }\n\n // recreate a new object\n return {\n adPosition: adBreakMetadata.adPosition,\n };\n}\n\n/** User SSAI API input validation */\nexport function hasValidSsaiAdMetadataStructure(anything: unknown): anything is SsaiAdMetadata | null | undefined {\n // \"nullish\" is considered to be valid (SSAI API parameter is optional)\n if (isNullish(anything)) {\n return true;\n }\n\n // invalid, when value was defined, but not as a plain object\n if (!isPlainObject(anything as object)) {\n logger.errorMessageToUser('Invalid SsaiAdMetadata: not a plain object');\n return false;\n }\n\n const maybeSsaiAdMetadata = anything as SsaiAdMetadata;\n\n // invalid, when `adId` was defined, but not as a string\n if (isNotNullish(maybeSsaiAdMetadata.adId) && !isValidString(maybeSsaiAdMetadata.adId)) {\n logger.errorMessageToUser(\"Invalid SsaiAdMetadata: 'adId' property is not string\");\n return false;\n }\n\n // invalid, when `adSystem` was defined, but not as a string\n if (isNotNullish(maybeSsaiAdMetadata.adSystem) && !isValidString(maybeSsaiAdMetadata.adSystem)) {\n logger.errorMessageToUser(\"Invalid SsaiAdMetadata: 'adSystem' property is not string\");\n return false;\n }\n\n // invalid, when `customData` was defined, but not as an object\n if (isNotNullish(maybeSsaiAdMetadata.customData) && !isPlainObject(maybeSsaiAdMetadata.customData)) {\n logger.errorMessageToUser(\"Invalid SsaiAdMetadata: 'customData' property is not a plain object\");\n return false;\n }\n\n return true;\n}\n\n/**\n * Simple sanitization of {@link SsaiAdMetadata} without object structure check,\n * because {@link hasValidSsaiAdMetadataStructure} should be called before in adapter SSAI API function!\n *\n * Sanitization:\n * - if `undefined/null` is passed, it will return `undefined`\n * - recreate a new object to avoid side effects by using same reference from outside\n *\n * @param ssaiAdMetadata SsaiAdMetadata or `undefined` (optional SSAI API parameter)\n */\nexport function simplySanitizeSsaiAdMetadata(ssaiAdMetadata: SsaiAdMetadata | undefined): SsaiAdMetadata | undefined {\n // \"nullish\" is considered to be valid (SSAI API parameter is optional)\n if (isNullish(ssaiAdMetadata)) {\n // sanitize to use `undefined` in code\n return undefined;\n }\n\n let sanitizedCustomDataValues: CustomDataValues | undefined = undefined;\n if (isNotNullish(ssaiAdMetadata.customData)) {\n sanitizedCustomDataValues = sanitizeCustomDataValues(ssaiAdMetadata.customData);\n }\n\n // recreate a new object\n return {\n adId: ssaiAdMetadata.adId,\n adSystem: ssaiAdMetadata.adSystem,\n customData: sanitizedCustomDataValues,\n };\n}\n\nexport function isSsaiAdQuartile(anything: unknown): anything is SsaiAdQuartile {\n return anything === 'first' || anything === 'midpoint' || anything === 'third' || anything === 'completed';\n}\n\n/** User SSAI API input validation */\nexport function hasValidSsaiAdQuartileStructure(anything: unknown): anything is SsaiAdQuartile {\n if (!isSsaiAdQuartile(anything)) {\n logger.errorMessageToUser('Invalid SsaiAdQuartile');\n return false;\n }\n\n return true;\n}\n\n/**\n * Full sanitization of unknown customer input.\n * We sanitize correct object structure and print user error messages for incorrect input.\n *\n * Sanitization:\n * - if `undefined/null` is passed, it will return empty object `{}`\n * - if NOT `typeof 'object'` is passed, it will return empty object `{}` and print user error message\n * - recreate a new object to avoid side effects by using same reference from outside\n * - if `failedBeaconUrl` is not valid string, we use `undefined` and print user error message\n * - if `failedBeaconUrl` is longer than 500 characters, we cut it\n *\n * @param anything Can be anything, as it is coming from customer JavaScript code\n */\nexport function sanitizeSsaiAdQuartileMetadata(anything: unknown): SsaiAdQuartileMetadata {\n if (isNullish(anything)) {\n // \"nullish\" is considered to be valid (SSAI API parameter is optional)\n // sanitize to plain object to not use nullish value in code\n return {};\n }\n\n if (!isPlainObject(anything as object)) {\n // if NOT a plain object, we return empty plain object and print user error message\n logger.errorMessageToUser('Invalid SsaiAdQuartileMetadata: not a plain object');\n return {};\n }\n\n const maybeSsaiAdQuartileMetadata = anything as SsaiAdQuartileMetadata;\n\n // recreate a new object\n const ssaiAdQuartileMetadata: SsaiAdQuartileMetadata = {\n failedBeaconUrl: maybeSsaiAdQuartileMetadata.failedBeaconUrl,\n };\n\n if (!isValidString(ssaiAdQuartileMetadata.failedBeaconUrl)) {\n logger.errorMessageToUser(\"Invalid SsaiAdQuartileMetadata: 'failedBeaconUrl' property is not string\");\n ssaiAdQuartileMetadata.failedBeaconUrl = undefined;\n } else {\n ssaiAdQuartileMetadata.failedBeaconUrl = ssaiAdQuartileMetadata.failedBeaconUrl.substring(0, 500);\n }\n\n return ssaiAdQuartileMetadata;\n}\n","import {SsaiAdBreakMetadata, SsaiAdMetadata, SsaiAdQuartile, SsaiAdQuartileMetadata} from '../../api/AdapterAPI';\nimport {AnalyticsError} from '../../types/AnalyticsConfig';\n\nexport type InternalSsaiMetadata = SsaiAdBreakMetadata & SsaiAdMetadata;\n\ntype SsaiEngagementBaseData = {\n adIndex: number;\n currentAdImpressionId: string;\n currentAdMetadata: InternalSsaiMetadata;\n type: 'error' | 'quartile' | 'started';\n};\n\nexport type SsaiEngagementErrorData = SsaiEngagementBaseData & {\n analyticsError: AnalyticsError;\n originalError?: any;\n timeSinceAdStartedInMs: number | undefined;\n type: 'error';\n};\n\nexport function isSsaiEngagementErrorData(data: SsaiEngagementInteractionData): data is SsaiEngagementErrorData {\n return data.type === 'error';\n}\n\nexport type SsaiEngagementQuartileData = SsaiEngagementBaseData & {\n quartile: SsaiAdQuartile;\n quartileMetadata: SsaiAdQuartileMetadata;\n timeSinceAdStartedInMs: number | undefined;\n type: 'quartile';\n};\n\nexport function isSsaiEngagementQuartileData(data: SsaiEngagementInteractionData): data is SsaiEngagementQuartileData {\n return data.type === 'quartile';\n}\n\nexport type SsaiEngagementStartedData = SsaiEngagementBaseData & {type: 'started'};\n\nexport function isSsaiEngagementStartedData(data: SsaiEngagementInteractionData): data is SsaiEngagementStartedData {\n return data.type === 'started';\n}\n\nexport type SsaiEngagementInteractionData =\n | SsaiEngagementErrorData\n | SsaiEngagementQuartileData\n | SsaiEngagementStartedData;\n","import type {SsaiAdQuartile, SsaiAdQuartileMetadata} from '../../api/AdapterAPI';\nimport {ErrorSeverity} from '../../types/AnalyticsConfig';\nimport {customDataValuesKeys} from '../../types/CustomDataValues';\nimport type {AdSample, Sample} from '../../types/Sample';\nimport {getGlobalPerformanceNow} from '../../utils/globalScopeUtils';\nimport {isNotNullish, isNullish} from '../../utils/Utils';\n\nimport type {\n InternalSsaiMetadata,\n SsaiEngagementErrorData,\n SsaiEngagementQuartileData,\n SsaiEngagementStartedData,\n} from './ssaiEngagementInteractionData';\n\n/**\n * Ssai marker property for {@link Sample} to indicate that this is \"ssai related sample\" and can cause the spike\n * on ingress side. It will be picked up in `AnalyticsCall` and used to send that \"ssai related sample\" as request\n * with ssai redirection. @see {@link ROUTING_URL_PARAM}\n *\n * What is \"ssai related sample\" ?\n * - \"last sample\" that was triggered to be sent, because of coming SSAI interaction, the SSAI ad break start (WITHOUT `sample.ad = 2`),\n * because it causes also the spike as all viewers are received same SSAI at the same time.\n * - all following samples, triggered by SSAI interaction while SSAI ad break is running (now WITH `sample.ad = 2`)\n *\n * We don't we need it with {@link AdSample} too?\n * Because all \"ssai related ad samples\" are triggered only during ssai ad break, so all have already\n * {@link AdSample#adType} property set and we can relay on that in `AnalyticsCall` to send them with ssai redirection.\n */\nexport const SSAI_RELATED_SAMPLE_MARKER = 'triggeredBySsai';\n\nexport function isSsaiRelatedSample(sample: AdSample | Sample): boolean {\n if (sample[SSAI_RELATED_SAMPLE_MARKER]) {\n delete sample[SSAI_RELATED_SAMPLE_MARKER]; // clean up the marker property that should not be present on the sample property\n return true;\n } else if ((sample as AdSample).adType === 2) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Due to ssai being spiky by design, we should mark all analytics requests (with samples / ad samples)\n * that are ssai related, with a specific URL parameter. The load balancer can then route traffic according to the URL\n * parameter to a different ingress instance, which gives us more flexibility when ssai spikes are coming in.\n */\nexport const ROUTING_URL_PARAM = 'routingParam';\nexport const ROUTING_URL_PARAM_VALUE_SSAI = 'ssai';\n\nexport function appendSsaiRoutingParam(url: string): string {\n return `${url}?${ROUTING_URL_PARAM}=${ROUTING_URL_PARAM_VALUE_SSAI}`;\n}\n\nfunction createAdSampleFromSample(sample: Sample): AdSample {\n return {\n audioBitrate: sample?.audioBitrate,\n analyticsVersion: sample?.analyticsVersion,\n adPlaybackHeight: sample?.videoPlaybackHeight,\n adPlaybackWidth: sample?.videoPlaybackWidth,\n cdnProvider: sample?.cdnProvider,\n customData1: sample?.customData1,\n customData2: sample?.customData2,\n customData3: sample?.customData3,\n customData4: sample?.customData4,\n customData5: sample?.customData5,\n customData6: sample?.customData6,\n customData7: sample?.customData7,\n customData8: sample?.customData8,\n customData9: sample?.customData9,\n customData10: sample?.customData10,\n customData11: sample?.customData11,\n customData12: sample?.customData12,\n customData13: sample?.customData13,\n customData14: sample?.customData14,\n customData15: sample?.customData15,\n customData16: sample?.customData16,\n customData17: sample?.customData17,\n customData18: sample?.customData18,\n customData19: sample?.customData19,\n customData20: sample?.customData20,\n customData21: sample?.customData21,\n customData22: sample?.customData22,\n customData23: sample?.customData23,\n customData24: sample?.customData24,\n customData25: sample?.customData25,\n customData26: sample?.customData26,\n customData27: sample?.customData27,\n customData28: sample?.customData28,\n customData29: sample?.customData29,\n customData30: sample?.customData30,\n customData31: sample?.customData31,\n customData32: sample?.customData32,\n customData33: sample?.customData33,\n customData34: sample?.customData34,\n customData35: sample?.customData35,\n customData36: sample?.customData36,\n customData37: sample?.customData37,\n customData38: sample?.customData38,\n customData39: sample?.customData39,\n customData40: sample?.customData40,\n customData41: sample?.customData41,\n customData42: sample?.customData42,\n customData43: sample?.customData43,\n customData44: sample?.customData44,\n customData45: sample?.customData45,\n customData46: sample?.customData46,\n customData47: sample?.customData47,\n customData48: sample?.customData48,\n customData49: sample?.customData49,\n customData50: sample?.customData50,\n customData51: sample?.customData51,\n customData52: sample?.customData52,\n customData53: sample?.customData53,\n customData54: sample?.customData54,\n customData55: sample?.customData55,\n customData56: sample?.customData56,\n customData57: sample?.customData57,\n customData58: sample?.customData58,\n customData59: sample?.customData59,\n customData60: sample?.customData60,\n customData61: sample?.customData61,\n customData62: sample?.customData62,\n customData63: sample?.customData63,\n customData64: sample?.customData64,\n customData65: sample?.customData65,\n customData66: sample?.customData66,\n customData67: sample?.customData67,\n customData68: sample?.customData68,\n customData69: sample?.customData69,\n customData70: sample?.customData70,\n customData71: sample?.customData71,\n customData72: sample?.customData72,\n customData73: sample?.customData73,\n customData74: sample?.customData74,\n customData75: sample?.customData75,\n customData76: sample?.customData76,\n customData77: sample?.customData77,\n customData78: sample?.customData78,\n customData79: sample?.customData79,\n customData80: sample?.customData80,\n customData81: sample?.customData81,\n customData82: sample?.customData82,\n customData83: sample?.customData83,\n customData84: sample?.customData84,\n customData85: sample?.customData85,\n customData86: sample?.customData86,\n customData87: sample?.customData87,\n customData88: sample?.customData88,\n customData89: sample?.customData89,\n customData90: sample?.customData90,\n customData91: sample?.customData91,\n customData92: sample?.customData92,\n customData93: sample?.customData93,\n customData94: sample?.customData94,\n customData95: sample?.customData95,\n customData96: sample?.customData96,\n customData97: sample?.customData97,\n customData98: sample?.customData98,\n customData99: sample?.customData99,\n customData100: sample?.customData100,\n customUserId: sample?.customUserId,\n domain: sample?.domain,\n experimentName: sample?.experimentName,\n key: sample?.key,\n language: sample?.language,\n path: sample?.path,\n platform: sample?.platform,\n player: sample?.player,\n playerKey: sample?.playerKey,\n playerTech: sample?.playerTech,\n size: sample?.size,\n screenHeight: sample?.screenHeight,\n screenWidth: sample?.screenWidth,\n streamFormat: sample?.streamFormat,\n userAgent: sample?.userAgent,\n userId: sample?.userId,\n version: sample?.version,\n videoBitrate: sample?.videoBitrate,\n videoId: sample?.videoId,\n videoImpressionId: sample?.impressionId,\n videoTitle: sample?.videoTitle,\n videoWindowHeight: sample?.videoWindowHeight,\n videoWindowWidth: sample?.videoWindowWidth,\n };\n}\n\nexport function createErrorAdSample(\n playbackSample: Sample,\n ssaiEngagementErrorData: SsaiEngagementErrorData,\n): AdSample {\n return buildAdSample({\n playbackSample,\n currentAdImpressionId: ssaiEngagementErrorData.currentAdImpressionId,\n adIndex: ssaiEngagementErrorData.adIndex,\n currentAdMetadata: ssaiEngagementErrorData.currentAdMetadata,\n quartile: undefined,\n quartileMetadata: undefined,\n errorCode: ssaiEngagementErrorData.analyticsError.code,\n errorMessage: ssaiEngagementErrorData.analyticsError.message,\n errorSeverity: ssaiEngagementErrorData.analyticsError.severity,\n timeSinceAdStartedInMs: ssaiEngagementErrorData.timeSinceAdStartedInMs,\n });\n}\n\nexport function createStartedAdSample(\n playbackSample: Sample,\n ssaiEngagementStartedData: SsaiEngagementStartedData,\n): AdSample {\n return buildAdSample({\n playbackSample,\n currentAdImpressionId: ssaiEngagementStartedData.currentAdImpressionId,\n adIndex: ssaiEngagementStartedData.adIndex,\n currentAdMetadata: ssaiEngagementStartedData.currentAdMetadata,\n quartile: 'started',\n quartileMetadata: undefined,\n errorCode: undefined,\n errorMessage: undefined,\n errorSeverity: undefined,\n timeSinceAdStartedInMs: undefined,\n });\n}\n\nexport function createQuartileAdSample(\n playbackSample: Sample,\n ssaiEngagementQuartileData: SsaiEngagementQuartileData,\n): AdSample {\n return buildAdSample({\n playbackSample,\n currentAdImpressionId: ssaiEngagementQuartileData.currentAdImpressionId,\n adIndex: ssaiEngagementQuartileData.adIndex,\n currentAdMetadata: ssaiEngagementQuartileData.currentAdMetadata,\n quartile: ssaiEngagementQuartileData.quartile,\n quartileMetadata: ssaiEngagementQuartileData.quartileMetadata,\n timeSinceAdStartedInMs: ssaiEngagementQuartileData.timeSinceAdStartedInMs,\n errorCode: undefined,\n errorMessage: undefined,\n errorSeverity: undefined,\n });\n}\n\nfunction buildAdSample({\n playbackSample,\n currentAdImpressionId,\n adIndex,\n currentAdMetadata,\n quartile,\n quartileMetadata,\n errorCode,\n errorMessage,\n errorSeverity,\n timeSinceAdStartedInMs,\n}: {\n adIndex: number;\n currentAdImpressionId: string;\n currentAdMetadata: InternalSsaiMetadata;\n errorCode: number | undefined;\n errorMessage: string | undefined;\n errorSeverity: ErrorSeverity | undefined;\n playbackSample: Sample;\n quartile: 'started' | SsaiAdQuartile | undefined;\n quartileMetadata: SsaiAdQuartileMetadata | undefined;\n timeSinceAdStartedInMs: number | undefined;\n}): AdSample {\n const adEngagementSample: AdSample = {\n ...createAdSampleFromSample(playbackSample),\n adId: currentAdMetadata?.adId,\n adImpressionId: currentAdImpressionId,\n adIndex: adIndex,\n adPosition: currentAdMetadata?.adPosition,\n adSystem: currentAdMetadata?.adSystem,\n adType: 2,\n errorCode: errorCode,\n errorMessage: errorMessage,\n errorSeverity: errorSeverity,\n time: Date.now(),\n timeSinceAdStartedInMs: timeSinceAdStartedInMs,\n };\n\n // set quartile data\n switch (quartile) {\n case 'started':\n adEngagementSample.started = 1;\n break;\n case 'first':\n adEngagementSample.quartile1 = 1;\n adEngagementSample.quartile1FailedBeaconUrl = quartileMetadata?.failedBeaconUrl;\n break;\n case 'midpoint':\n adEngagementSample.midpoint = 1;\n adEngagementSample.midpointFailedBeaconUrl = quartileMetadata?.failedBeaconUrl;\n break;\n case 'third':\n adEngagementSample.quartile3 = 1;\n adEngagementSample.quartile3FailedBeaconUrl = quartileMetadata?.failedBeaconUrl;\n break;\n case 'completed':\n adEngagementSample.completed = 1;\n adEngagementSample.completedFailedBeaconUrl = quartileMetadata?.failedBeaconUrl;\n break;\n }\n\n // set ssai customData\n const customData = currentAdMetadata?.customData;\n if (isNotNullish(customData)) {\n customDataValuesKeys.forEach((key) => {\n if (customData[key]) {\n adEngagementSample[key] = customData[key];\n }\n });\n }\n\n return adEngagementSample;\n}\n\n/**\n * Returns the current timestamp in milliseconds using the `performance.now()` method if available\n * to ensure monotonic timestamps; otherwise, it falls back to using `Date.now()`.\n *\n * Date.now() is dependent on the system clock and not monotonic, it may have been impacted by system\n * and user clock adjustments. The performance.now() method is relative to the timeOrigin property\n * which is a monotonic clock: its current time never decreases and isn't subject to adjustments.\n */\nexport function getCurrentMonotonicTimestampInMs(): number {\n const performanceNow = getGlobalPerformanceNow();\n if (isNullish(performanceNow)) {\n return Date.now();\n }\n\n // floor to return integer value (not double as performance.now() returns)\n return Math.floor(performanceNow);\n}\n\nexport function getMonotonicTimestampInMsSince(timestampInMs: number | undefined): number | undefined {\n if (isNullish(timestampInMs)) {\n return undefined;\n }\n\n return getCurrentMonotonicTimestampInMs() - timestampInMs;\n}\n","export enum AD_TYPE {\n NO_AD = 0,\n CSAI = 1,\n SSAI = 2,\n}\n","export enum CdnProvider {\n AKAMAI = 'akamai',\n BITGRAVITY = 'bitgravity',\n CHINACACHE = 'chinacache',\n CLOUDFLARE = 'cloudflare',\n CLOUDFRONT = 'cloudfront',\n FASTLY = 'fastly',\n MAXCDN = 'maxcdn',\n}\n","export enum CastTech {\n AirPlay = 'AirPlay',\n GoogleCast = 'GoogleCast',\n WebSocket = 'WebSocket',\n}\n","const videoCodecs = ['avc1', 'avc3', 'hvc1', 'av01', 'av1', 'hev1', 'vp9'];\n\nconst audioCodecs = ['mp4a', 'ec-3', 'ac-3', 'opus', 'audio/mp4'];\n\nexport function isVideoCodec(codec: string): boolean {\n if (!codec) {\n return false;\n }\n const index = videoCodecs.findIndex((videoCodec) => codec.startsWith(videoCodec));\n return index !== -1;\n}\n\nexport function isAudioCodec(codec: string): boolean {\n if (!codec) {\n return false;\n }\n const index = audioCodecs.findIndex((videoCodec) => codec.startsWith(videoCodec));\n return index !== -1;\n}\n","import {ErrorSeverity} from '../types/AnalyticsConfig';\n\nexport class ErrorCode {\n static BITMOVIN_PLAYER_LICENSING_ERROR = new ErrorCode(1103, '');\n static SETUP_MISSING_LICENSE_WHITELIST = new ErrorCode(1105, '');\n static QUALITY_CHANGE_THRESHOLD_EXCEEDED = new ErrorCode(\n 10000,\n 'ANALYTICS_QUALITY_CHANGE_THRESHOLD_EXCEEDED',\n 'INFO',\n );\n static BUFFERING_TIMEOUT_REACHED = new ErrorCode(10001, 'ANALYTICS_BUFFERING_TIMEOUT_REACHED');\n static VIDEO_STARTUP_TIMEOUT_REACHED = new ErrorCode(10002, 'ANALYTICS_VIDEOSTART_TIMEOUT_REACHED');\n\n private constructor(\n readonly code: number,\n readonly message: string,\n readonly errorSeverity: ErrorSeverity = 'CRITICAL',\n ) {}\n}\n","import type {\n AnalyticsEventBase,\n CustomDataValuesEvent,\n ErrorEvent,\n QualityChangeEvent,\n SourceChangeEvent,\n} from '../types/EventData';\n\n/**\n * If we specify the name of our initial state, then an implicit 'startup' initial event will be created by JSM\n * and fired when the state machine is constructed.\n *\n * Because that implicit JSM initial event is called 'startup', it could cause confusion with our \"STARTUP state\", so for\n * that reason we will use custom JSM initial event name, to be able to distinguish it from our other {@link Event}s.\n *\n * This event should not be used in the application code, it is only used by the JSM library!\n *\n * @see https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#initialization-options\n */\nexport const JSM_INITIAL_EVENT = 'jsm-initial';\n\nexport enum Event {\n AUDIO_CHANGE = 'audioChange',\n AUDIOTRACK_CHANGED = 'audioTrackChanged',\n CUSTOM_DATA_CHANGE = 'customDataChange',\n /**\n * Fired when the player has finished playback.\n */\n END = 'end',\n END_AD = 'adEnd',\n END_BUFFERING = 'endBuffering',\n END_CAST = 'endCasting',\n END_FULLSCREEN = 'endFullscreen',\n ERROR = 'playerError',\n /**\n * Custom Event fired by Analytics State Machine. Used to immediately transition out of the QUALITY_CHANGE State\n * back to PLAYING State where the quality change was tracked.\n */\n FINISH_QUALITY_CHANGE = 'finishQualityChange',\n /**\n * Manually fired when a source load with autoplay is detected.\n * Required for accurate VST (video startup time) measurement: Some players delay sending PLAY events until\n * manifest/content is loaded, making VST unreliable if calculated from player events alone.\n * For autoplay scenarios, VST is measured as the time from source load to the first\n * PLAYING or TIMEUPDATE event from the player.\n */\n LOADSTART_AUTOPLAY = 'loadstartAutoplay',\n MANUAL_SOURCE_CHANGE = 'manualSourceChangeInitiated',\n MUTE = 'mute',\n PAUSE = 'pause',\n PLAY = 'play',\n PLAYING = 'playing',\n /**\n * Fired when the player is ready to play.\n */\n READY = 'ready',\n SCREEN_RESIZE = 'resize',\n SEEK = 'seek',\n SEEKED = 'seeked',\n SOURCE_LOADED = 'sourceLoaded',\n SOURCE_UNLOADED = 'sourceUnloaded',\n START_AD = 'adStart',\n START_BUFFERING = 'startBuffering',\n START_CAST = 'startCasting',\n START_FULLSCREEN = 'startFullscreen',\n SUBTITLE_CHANGE = 'subtitleChange',\n TIMECHANGED = 'timechanged',\n UN_MUTE = 'unMute',\n /**\n * Fired when page with player is closed or when the player is unloaded/destroyed.\n */\n UNLOAD = 'unload',\n VIDEO_CHANGE = 'videoChange',\n VIDEOSTART_TIMEOUT = 'VIDEOSTART_TIMEOUT',\n}\n\nexport interface EventMap {\n [Event.READY]: AnalyticsEventBase;\n [Event.SOURCE_LOADED]: AnalyticsEventBase;\n [Event.PLAY]: AnalyticsEventBase;\n [Event.PLAYING]: AnalyticsEventBase | CustomDataValuesEvent;\n [Event.PAUSE]: AnalyticsEventBase | CustomDataValuesEvent;\n [Event.TIMECHANGED]: AnalyticsEventBase;\n [Event.SEEK]: AnalyticsEventBase;\n [Event.SEEKED]: AnalyticsEventBase;\n [Event.START_CAST]: AnalyticsEventBase;\n [Event.END_CAST]: AnalyticsEventBase;\n [Event.START_BUFFERING]: AnalyticsEventBase;\n [Event.END_BUFFERING]: AnalyticsEventBase;\n [Event.AUDIOTRACK_CHANGED]: AnalyticsEventBase;\n [Event.AUDIO_CHANGE]: QualityChangeEvent;\n [Event.VIDEO_CHANGE]: QualityChangeEvent;\n [Event.FINISH_QUALITY_CHANGE]: AnalyticsEventBase;\n [Event.START_FULLSCREEN]: AnalyticsEventBase;\n [Event.END_FULLSCREEN]: AnalyticsEventBase;\n [Event.START_AD]: AnalyticsEventBase;\n [Event.SUBTITLE_CHANGE]: AnalyticsEventBase;\n [Event.END_AD]: AnalyticsEventBase;\n [Event.MUTE]: AnalyticsEventBase;\n [Event.UN_MUTE]: AnalyticsEventBase;\n [Event.ERROR]: ErrorEvent;\n [Event.SCREEN_RESIZE]: AnalyticsEventBase;\n [Event.UNLOAD]: AnalyticsEventBase;\n [Event.END]: AnalyticsEventBase;\n [Event.SOURCE_UNLOADED]: AnalyticsEventBase;\n [Event.MANUAL_SOURCE_CHANGE]: SourceChangeEvent;\n [Event.VIDEOSTART_TIMEOUT]: AnalyticsEventBase;\n [Event.CUSTOM_DATA_CHANGE]: AnalyticsEventBase;\n [Event.LOADSTART_AUTOPLAY]: AnalyticsEventBase;\n}\n","import {endsWith} from '../utils/stringUtils';\n\nexport const MIMETypes = {\n MP4: 'video/mp4',\n WEBM: 'video/webm',\n HLS: 'application/x-mpegURL',\n DASH: 'application/dash+xml',\n} as const;\n\n/**\n * @deprecated use {@link getStreamTypesFromURL} directly, when we want to detect {@link StreamTypes} from URL\n *\n * @remarks\n *\n * In our current code, it is visible that detection of MIME Type is only used as \"an additional step\" between\n * stream URL and stream type:\n * - we parse stream URL to detect MIME type\n * - we parse the detected MIME type to get a stream type\n *\n * Because we are not sending the detected MIME type in sample and because we can get {@link StreamTypes} directly from\n * stream URL, we should stop using this MIME type detection code.\n */\nexport function getMIMETypeFromFileExtension(url: string): string | undefined {\n const urlPath = url.split(/[?#]/)[0].toLowerCase();\n\n if (endsWith(urlPath, '.m3u8')) {\n return MIMETypes.HLS;\n }\n if (endsWith(urlPath, '.mp4') || endsWith(urlPath, '.m4v') || endsWith(urlPath, '.m4a')) {\n return MIMETypes.MP4;\n }\n if (endsWith(urlPath, '.webm')) {\n return MIMETypes.WEBM;\n }\n if (endsWith(urlPath, '.mpd')) {\n return MIMETypes.DASH;\n }\n\n return undefined;\n}\n","export enum PAGE_LOAD_TYPE {\n FOREGROUND = 1,\n BACKGROUND = 2,\n}\n","export enum Player {\n AMAZON_IVS = 'amazonivs',\n BITMOVIN = 'bitmovin',\n BITMOVIN_PWX = 'bitmovin-pwx',\n CHROMECAST_SHAKA = 'chromecast-shaka',\n DASHJS = 'dashjs',\n HLSJS = 'hlsjs',\n HTML5 = 'html5',\n JW = 'jw',\n RADIANT = 'radiant',\n SHAKA = 'shaka',\n THEOPLAYER = 'theoplayer',\n VIDEOJS = 'videojs',\n}\n","export enum PlayerSize {\n Fullscreen = 'FULLSCREEN',\n Window = 'WINDOW',\n}\n","import {endsWith, isBlank} from '../utils/stringUtils';\nimport {isNullish} from '../utils/Utils';\n\nimport {MIMETypes} from './MIMETypes';\n\nexport enum StreamTypes {\n dash = 'dash',\n hls = 'hls',\n prog = 'progressive',\n}\n\nexport function getStreamTypesFromURL(url: string | undefined): StreamTypes | undefined {\n if (isNullish(url) || isBlank(url)) {\n return undefined;\n }\n\n const urlPath = url.split(/[?#]/)[0].toLowerCase();\n\n if (endsWith(urlPath, '.m3u8')) {\n return StreamTypes.hls;\n }\n if (endsWith(urlPath, '.mp4') || endsWith(urlPath, '.m4v') || endsWith(urlPath, '.m4a')) {\n return StreamTypes.prog;\n }\n if (endsWith(urlPath, '.webm')) {\n return StreamTypes.prog;\n }\n if (endsWith(urlPath, '.mpd')) {\n return StreamTypes.dash;\n }\n\n return undefined;\n}\n\nexport function getStreamTypeFromMIMEType(mimeType: string): StreamTypes | undefined {\n const MIME_TYPE_TO_STREAM_TYPE_MAP = {\n [MIMETypes.MP4]: StreamTypes.prog,\n [MIMETypes.WEBM]: StreamTypes.prog,\n [MIMETypes.HLS]: StreamTypes.hls,\n [MIMETypes.DASH]: StreamTypes.dash,\n };\n\n return MIME_TYPE_TO_STREAM_TYPE_MAP[mimeType];\n}\n","import {Event} from './Event';\n\nexport enum VideoStartFailedReason {\n PAGE_CLOSED = 'PAGE_CLOSED',\n PLAYER_ERROR = 'PLAYER_ERROR',\n TIMEOUT = 'TIMEOUT',\n UNKNOWN = 'UNKNOWN',\n}\n\nexport function createVideoStartFailedReason(stateMachineEvent: string | undefined): VideoStartFailedReason {\n switch (stateMachineEvent) {\n case Event.ERROR:\n return VideoStartFailedReason.PLAYER_ERROR;\n case Event.UNLOAD:\n return VideoStartFailedReason.PAGE_CLOSED;\n case Event.MANUAL_SOURCE_CHANGE:\n return VideoStartFailedReason.PAGE_CLOSED;\n case Event.SOURCE_UNLOADED:\n return VideoStartFailedReason.PAGE_CLOSED;\n case Event.VIDEOSTART_TIMEOUT:\n return VideoStartFailedReason.TIMEOUT;\n\n default:\n return VideoStartFailedReason.UNKNOWN;\n }\n}\n","import {isNotNullish} from '../utils/Utils';\n\nimport {FeatureConfig} from './FeatureConfig';\n\nexport abstract class Feature<TConfigContainer, TConfig extends FeatureConfig> {\n private _config?: TConfig = undefined;\n private _isEnabled = true;\n\n get config(): TConfig | undefined {\n return this._config;\n }\n\n get isEnabled(): boolean {\n return this._isEnabled;\n }\n\n abstract reset(): void;\n abstract enabled(): void;\n abstract disabled(): void;\n abstract configured(authenticated: boolean, config?: TConfig): void;\n\n disable() {\n this._isEnabled = false;\n this.disabled();\n }\n\n configure(authenticated: boolean, configContainer?: TConfigContainer): TConfig | undefined {\n if (isNotNullish(configContainer)) {\n this._config = this.extractConfig(configContainer);\n }\n this.configured(authenticated, this._config);\n return this._config;\n }\n\n abstract extractConfig(configContainer: TConfigContainer): TConfig | undefined;\n}\n","import {logger} from '../utils/Logger';\n\nimport {Feature} from './Feature';\nimport {FeatureConfig} from './FeatureConfig';\n\nexport class FeatureManager<TConfigContainer> {\n private features: Array<Feature<TConfigContainer, FeatureConfig>> = [];\n\n registerFeatures(features: Array<Feature<TConfigContainer, FeatureConfig>>) {\n this.features = features;\n }\n\n unregisterFeatures() {\n this.features.forEach((feature) => feature.disable());\n this.features = [];\n }\n\n resetFeatures() {\n this.features.forEach((feature) => feature.reset());\n }\n\n configureFeatures(authenticated: boolean, featureConfigs?: TConfigContainer) {\n this.features = this.features.filter((feature) => {\n const config = feature.configure(authenticated, featureConfigs);\n if (!authenticated || config?.enabled !== true) {\n logger.log(`Disabling feature ${feature.constructor.name} as it isn't enabled according to license callback.`);\n feature.disable();\n return false;\n }\n return true;\n });\n this.features.forEach((feature) => feature.enabled());\n }\n}\n","import {CollectorConfig} from '../../types/AnalyticsConfig';\nimport {post} from '../../utils/Http';\nimport {ANALYTICS_BACKEND_BASE_URL} from '../../utils/Settings';\nimport {isNotNullish, joinUrls} from '../../utils/Utils';\nimport {HttpRequest} from '../httprequesttracking/HttpRequest';\n\nimport {ErrorData} from './ErrorData';\nimport {ErrorDetail} from './ErrorDetail';\n\nexport class ErrorDetailBackend {\n get queue(): ReadonlyArray<ErrorDetail> {\n return this._queue;\n }\n\n get enabled(): boolean {\n return this._enabled;\n }\n\n set enabled(value: boolean) {\n this._enabled = value;\n }\n\n static copyErrorDetailTruncateStringsAndUrls(\n errorDetail: ErrorDetail,\n maxStringLength: number,\n maxUrlLength: number,\n ): ErrorDetail {\n return {\n ...errorDetail,\n message: errorDetail.message?.substr(0, maxStringLength),\n data: this.copyErrorDataTruncateStrings(errorDetail.data, maxStringLength),\n httpRequests: errorDetail.httpRequests?.map((request) => this.copyHttpRequestTruncateUrls(request, maxUrlLength)),\n };\n }\n\n static copyHttpRequestTruncateUrls(httpRequest: HttpRequest, maxLength: number): HttpRequest {\n return {\n ...httpRequest,\n url: httpRequest.url?.substr(0, maxLength),\n lastRedirectLocation: httpRequest.lastRedirectLocation?.substr(0, maxLength),\n };\n }\n\n static copyErrorDataTruncateStrings(errorData: ErrorData, maxStringLength: number): ErrorData {\n return {\n ...errorData,\n exceptionMessage: errorData.exceptionMessage?.substr(0, maxStringLength),\n additionalData: errorData.additionalData?.substr(0, maxStringLength),\n };\n }\n\n static copyErrorDetailTruncateHttpRequests(errorDetail: ErrorDetail, maxRequests: number): ErrorDetail {\n return {\n ...errorDetail,\n httpRequests: errorDetail.httpRequests?.slice(-maxRequests),\n };\n }\n\n // We use these as upper limits to avoid clients bombing us with data, actual truncation to documented limits is\n // happening in ingress\n private static MAX_URL_LENGTH = 450;\n private static MAX_STRING_LENGTH = 2000;\n\n private readonly backendUrl: string;\n private readonly _queue: ErrorDetail[] = [];\n private _enabled = false;\n\n constructor(collectorConfig: CollectorConfig | undefined) {\n this.backendUrl = joinUrls(collectorConfig?.backendUrl ?? ANALYTICS_BACKEND_BASE_URL, '/analytics/error');\n }\n\n limitHttpRequestsOfQueuedErrorDetails(max: number) {\n this._queue.forEach((value, index) => {\n this._queue[index] = ErrorDetailBackend.copyErrorDetailTruncateHttpRequests(value, max);\n });\n }\n\n send(errorDetail: ErrorDetail) {\n const errorDetailCopy = ErrorDetailBackend.copyErrorDetailTruncateStringsAndUrls(\n errorDetail,\n ErrorDetailBackend.MAX_STRING_LENGTH,\n ErrorDetailBackend.MAX_URL_LENGTH,\n );\n if (this.enabled) {\n post(this.backendUrl, errorDetailCopy, () => undefined);\n } else {\n this._queue.push(errorDetailCopy);\n }\n }\n\n flush() {\n const copy = [...this._queue];\n let element = copy.shift();\n while (isNotNullish(element)) {\n this.removeFromQueue(element);\n this.send(element);\n element = copy.shift();\n }\n }\n\n clear() {\n this._queue.splice(0, this._queue.length);\n }\n\n private removeFromQueue(element: ErrorDetail) {\n const index = this._queue.findIndex((value) => value === element);\n if (index >= 0) {\n this._queue.splice(index, 1);\n }\n }\n}\n","import {Subscribable} from '../../core/EventDispatcher';\nimport {CollectorConfig} from '../../types/AnalyticsConfig';\nimport {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport {logger} from '../../utils/Logger';\nimport {getCurrentTimestamp, isNullish, tryJSONStringify} from '../../utils/Utils';\nimport {VERSION} from '../../utils/Version';\nimport {Feature} from '../Feature';\nimport {HttpRequestTracking} from '../httprequesttracking/HttpRequestTracking';\n\nimport {ErrorDetail} from './ErrorDetail';\nimport {ErrorDetailBackend} from './ErrorDetailBackend';\nimport {ErrorDetailTrackingConfig} from './ErrorDetailTrackingConfig';\nimport {OnErrorDetailEventObject} from './OnErrorDetailEventObject';\n\nexport interface ErrorDetailTrackingSettingsProvider {\n readonly licenseKey: string;\n readonly domain: string;\n readonly impressionId: string;\n readonly collectorConfig?: CollectorConfig;\n}\n\nexport class ErrorDetailTracking extends Feature<FeatureConfigContainer, ErrorDetailTrackingConfig> {\n private errorIndex = 0;\n\n constructor(\n private settingsProvider: ErrorDetailTrackingSettingsProvider,\n private backend: ErrorDetailBackend,\n private subscribables: Array<Subscribable<OnErrorDetailEventObject>>,\n private httpRequestTracking: HttpRequestTracking | undefined,\n ) {\n super();\n subscribables.forEach((subscribable) => subscribable.subscribe(this.onErrorHandler));\n }\n\n reset(): void {\n this.httpRequestTracking?.reset();\n this.errorIndex = 0;\n }\n\n enabled(): void {\n this.backend.enabled = true;\n this.backend.flush();\n }\n\n disabled(): void {\n this.errorIndex = 0;\n this.httpRequestTracking?.disable();\n this.backend.clear();\n this.subscribables.forEach((subscribable) => subscribable.unsubscribe(this.onErrorHandler));\n }\n\n configured(_authenticated: boolean, config?: ErrorDetailTrackingConfig): void {\n const maxRequests = Math.max(config?.numberOfHttpRequests ?? 0, 0);\n this.httpRequestTracking?.configure(maxRequests);\n this.backend.limitHttpRequestsOfQueuedErrorDetails(maxRequests);\n }\n\n extractConfig(configContainer: FeatureConfigContainer): ErrorDetailTrackingConfig | undefined {\n return configContainer.errorDetails;\n }\n\n private onErrorHandler = (event: OnErrorDetailEventObject) => {\n try {\n if (!this.isEnabled) {\n return;\n }\n\n const httpRequests = this.httpRequestTracking?.httpRequests;\n const httpRequestsCopy = isNullish(httpRequests) ? undefined : [...httpRequests];\n const errorIndex = this.errorIndex;\n this.errorIndex++;\n\n const errorDetail: ErrorDetail = {\n platform: 'web',\n licenseKey: this.settingsProvider.licenseKey,\n domain: this.settingsProvider.domain,\n impressionId: this.settingsProvider.impressionId,\n analyticsVersion: VERSION,\n errorId: errorIndex,\n timestamp: getCurrentTimestamp(),\n code: event.code,\n message: event.message,\n data: event.errorData ?? {\n additionalData: undefined,\n exceptionMessage: undefined,\n exceptionStacktrace: undefined,\n },\n httpRequests: httpRequestsCopy,\n severity: event.severity,\n };\n\n logger.log(`ErrorDetailTracking.onError: ${tryJSONStringify(errorDetail)}`);\n this.backend.send(errorDetail);\n } catch (error) {\n logger.error(`ErrorDetailTracking.onError: Error in handler`, error);\n }\n };\n}\n","import {Subscribable} from '../../core/EventDispatcher';\nimport {logger} from '../../utils/Logger';\nimport {Queue} from '../../utils/Queue';\n\nimport {HttpRequest} from './HttpRequest';\nimport {OnDownloadFinishedEventObject} from './OnDownloadFinishedEventObject';\n\nexport class HttpRequestTracking {\n private static DEFAULT_MAX_REQUESTS = 10;\n private _maxRequests: number = HttpRequestTracking.DEFAULT_MAX_REQUESTS;\n private _httpRequestQueue = new Queue<HttpRequest>();\n\n get maxRequests(): number {\n return this._maxRequests;\n }\n\n get httpRequests(): ReadonlyArray<HttpRequest> {\n return this._httpRequestQueue.items;\n }\n\n constructor(private subscribables: Array<Subscribable<OnDownloadFinishedEventObject>>) {\n subscribables.forEach((subscribable) => subscribable.subscribe(this.onDownloadFinishedHandler));\n }\n\n configure(maxRequests: number) {\n this._maxRequests = maxRequests;\n this._httpRequestQueue.limit(maxRequests);\n }\n\n disable() {\n this.subscribables.forEach((subscribable) => subscribable.unsubscribe(this.onDownloadFinishedHandler));\n this._httpRequestQueue.clear();\n }\n\n reset() {\n this._httpRequestQueue.clear();\n }\n\n private onDownloadFinishedHandler = (event: OnDownloadFinishedEventObject) => {\n try {\n this.addRequest(event.httpRequest);\n } catch (error) {\n logger.error(`HttpRequestTracking.onDownloadFinished: Error in handler`, error);\n }\n };\n\n private addRequest(httpRequest: HttpRequest) {\n this._httpRequestQueue.offer(httpRequest);\n this._httpRequestQueue.limit(this._maxRequests);\n }\n}\n","/**\n * This enum is supposed to represent the type of HTTP request made by any player,\n * and should be used to categorize the requests in the {@link OnDownloadFinishedEventObject} events.\n *\n * @remarks\n *\n * Instead of creating our own categorization of HTTP request types, we decided to copy the `HttpRequestType` enum\n * from Bitmovin8 Player. This way, we can directly use the `downloadType` value from the `DownloadFinishedEvent`\n * without needing to map it to our own types, and we can ensure that the categorization is consistent with what the\n * player provides. In the case of other players, we can still map their request types to this enum as much as possible,\n * and use `UNKNOWN` for any types that don't fit into the existing categories.\n *\n * @see https://github.com/bitmovin-engineering/bitdash/blob/development/src/core/NetworkAPI.ts#L11\n */\nexport enum HttpRequestType {\n /* eslint-disable perfectionist/sort-enums */\n\n MANIFEST_DASH = 'manifest/dash',\n MANIFEST_HLS_MASTER = 'manifest/hls/master',\n MANIFEST_HLS_VARIANT = 'manifest/hls/variant',\n MANIFEST_SMOOTH = 'manifest/smooth',\n MANIFEST_ADS = 'manifest/ads',\n\n MEDIA_AUDIO = 'media/audio',\n MEDIA_VIDEO = 'media/video',\n MEDIA_SUBTITLES = 'media/subtitles',\n MEDIA_THUMBNAILS = 'media/thumbnails',\n MEDIA_SEGMENTINDEX = 'media/segmentindex',\n\n DRM_LICENSE_WIDEVINE = 'drm/license/widevine',\n DRM_LICENSE_PLAYREADY = 'drm/license/playready',\n DRM_LICENSE_FAIRPLAY = 'drm/license/fairplay',\n DRM_LICENSE_PRIMETIME = 'drm/license/primetime',\n DRM_LICENSE_CLEARKEY = 'drm/license/clearkey',\n DRM_LICENSE_TVKEY = 'drm/license/tvkey',\n\n DRM_CERTIFICATE_FAIRPLAY = 'drm/certificate/fairplay',\n\n HLS_INTERSTITIALS_ASSET_LIST = 'hls/interstitials/asset-list',\n\n KEY_HLS_AES = 'key/hls/aes',\n\n TIME_SYNC = 'time/sync',\n\n WEBRTC_SDP_REQUEST = 'webrtc/sdp/request',\n WEBRTC_SDP_ANSWER = 'webrtc/sdp/answer',\n WEBRTC_SDP_OFFER = 'webrtc/sdp/offer',\n\n UNKNOWN = 'unknown',\n\n INTERNAL = 'internal',\n\n /* eslint-enable perfectionist/sort-enums */\n}\n","import * as Utils from '../utils/Utils';\n\nimport {CustomDataValues} from './CustomDataValues';\nimport {Sample} from './Sample';\n\nexport class AdAnalyticsSample implements CustomDataValues {\n adModule?: string;\n adModuleVersion?: string;\n videoImpressionId?: string;\n userAgent?: string;\n language?: string;\n cdnProvider?: string;\n customData1?: string;\n customData2?: string;\n customData3?: string;\n customData4?: string;\n customData5?: string;\n customData6?: string;\n customData7?: string;\n customData8?: string;\n customData9?: string;\n customData10?: string;\n customData11?: string;\n customData12?: string;\n customData13?: string;\n customData14?: string;\n customData15?: string;\n customData16?: string;\n customData17?: string;\n customData18?: string;\n customData19?: string;\n customData20?: string;\n customData21?: string;\n customData22?: string;\n customData23?: string;\n customData24?: string;\n customData25?: string;\n customUserId?: string;\n experimentName?: string;\n domain?: string;\n key?: string;\n path?: string;\n player?: string;\n playerKey?: string;\n playerTech?: string;\n screenHeight?: number;\n screenWidth?: number;\n version?: string;\n size?: string;\n userId?: string;\n videoId?: string;\n videoTitle?: string;\n videoWindowHeight?: number;\n videoWindowWidth?: number;\n playerStartupTime?: number;\n analyticsVersion?: string;\n pageLoadTime?: number;\n pageLoadType?: number;\n autoplay?: boolean;\n platform = 'web';\n audioCodec?: string;\n videoCodec?: string;\n\n constructor(sample?: Sample) {\n if (!sample) {\n return;\n }\n this.videoImpressionId = sample.impressionId;\n this.userAgent = sample.userAgent;\n this.language = sample.language;\n this.cdnProvider = sample.cdnProvider;\n\n Utils.transferCustomDataFields(sample, this);\n\n this.customUserId = sample.customUserId;\n this.domain = sample.domain;\n this.experimentName = sample.experimentName;\n this.key = sample.key;\n this.path = sample.path;\n this.player = sample.player;\n this.playerKey = sample.playerKey;\n this.playerTech = sample.playerTech;\n this.screenHeight = sample.screenHeight;\n this.screenWidth = sample.screenWidth;\n this.version = sample.version;\n this.size = sample.size;\n this.userId = sample.userId;\n this.videoId = sample.videoId;\n this.videoTitle = sample.videoTitle;\n this.videoWindowHeight = sample.videoWindowHeight;\n this.videoWindowWidth = sample.videoWindowWidth;\n this.audioCodec = sample.audioCodec;\n this.videoCodec = sample.videoCodec;\n }\n}\n","import {isFiniteNumber} from '../utils/numberUtils';\nimport {calculateTime, calculateTimeWithUndefined, isNotNullish, isNullish} from '../utils/Utils';\n\nimport {AdBreakInfo} from './ads/AdBreakInfo';\nimport {ErrorSeverity} from './AnalyticsConfig';\n\nexport class AdBreakSample {\n adPosition?: string;\n adOffset?: string;\n adScheduleTime?: number;\n adReplaceContentDuration?: number;\n adPreloadOffset?: number;\n adTagPath?: string;\n adTagServer?: string;\n adTagType?: string;\n adTagUrl?: string;\n adIsPersistent?: boolean;\n adIdPlayer?: string;\n manifestDownloadTime?: number;\n errorCode?: number;\n errorData?: string;\n errorMessage?: string;\n errorSeverity?: ErrorSeverity;\n adFallbackIndex = 0;\n\n constructor(adBreakInfo?: AdBreakInfo) {\n if (isNullish(adBreakInfo)) {\n return;\n }\n\n this.adIdPlayer = adBreakInfo.id;\n this.adReplaceContentDuration = calculateTimeWithUndefined(adBreakInfo.replaceContentDuration);\n this.adIsPersistent = adBreakInfo.persistent;\n this.adTagType = adBreakInfo.tagType;\n this.adTagUrl = adBreakInfo.tagUrl;\n this.adPreloadOffset = calculateTimeWithUndefined(adBreakInfo.preloadOffset);\n this.adFallbackIndex = adBreakInfo.fallbackIndex ?? 0;\n this.manifestDownloadTime = calculateTimeWithUndefined(adBreakInfo.manifestDownloadTime);\n\n if (adBreakInfo.position === 'pre' || adBreakInfo.position === 'post') {\n this.adPosition = adBreakInfo.position;\n } else if (isNotNullish(adBreakInfo.position)) {\n this.adPosition = 'mid';\n this.adOffset = adBreakInfo.position;\n }\n\n if (isNotNullish(this.adTagUrl)) {\n try {\n const adTagUrl = new URL(this.adTagUrl);\n this.adTagServer = adTagUrl.hostname;\n this.adTagPath = adTagUrl.pathname;\n } catch {\n // Invalid URL, leave fields undefined\n }\n }\n\n if (isFiniteNumber(adBreakInfo.scheduleTime)) {\n this.adScheduleTime = calculateTime(adBreakInfo.scheduleTime);\n }\n }\n}\n","import {calculateTime, calculateTimeWithUndefined, isNotNullish, isNullish} from '../utils/Utils';\n\nimport {AdInfo} from './ads/AdInfo';\n\nexport class AdSample {\n wrapperAdsCount?: number;\n adSkipAfter?: number;\n adSkippable?: boolean;\n adClickthroughUrl?: string;\n adDescription?: string;\n adDuration?: number;\n adId?: string;\n adImpressionId?: string;\n adPlaybackHeight?: number;\n adPlaybackWidth?: number;\n adStartupTime?: number;\n adSystem?: string;\n adTitle?: string;\n advertiserName?: string;\n apiFramework?: string;\n audioBitrate?: number;\n clicked = 0;\n clickPosition?: number;\n closed = 0;\n closePosition?: number;\n completed = 0;\n creativeAdId?: string;\n creativeId?: string;\n dealId?: string;\n isLinear?: boolean;\n mediaPath?: string;\n mediaServer?: string;\n mediaUrl?: string;\n midpoint = 0;\n minSuggestedDuration?: number;\n percentageInViewport?: number;\n quartile1 = 0;\n quartile3 = 0;\n skipped = 0;\n skipPosition?: number;\n started = 0;\n streamFormat?: string;\n surveyUrl?: string;\n time?: number;\n timeHovered?: number;\n timeInViewport?: number;\n timePlayed?: number;\n timeUntilHover?: number;\n universalAdIdRegistry?: string;\n universalAdIdValue?: string;\n videoBitrate?: number;\n adPodPosition?: number;\n exitPosition?: number;\n playPercentage?: number;\n skipPercentage?: number;\n clickPercentage?: number;\n closePercentage?: number;\n errorPosition?: number;\n errorPercentage?: number;\n timeToContent?: number;\n timeFromContent?: number;\n\n constructor(ad?: AdInfo) {\n if (isNullish(ad)) {\n return;\n }\n\n this.adClickthroughUrl = ad.clickThroughUrl;\n this.adId = ad.id;\n this.mediaUrl = ad.mediaUrl;\n this.isLinear = ad.isLinear;\n this.adPlaybackHeight = ad.height;\n this.adPlaybackWidth = ad.width;\n this.streamFormat = ad.mimeType;\n if (isNotNullish(this.mediaUrl)) {\n try {\n const mediaUrl = new URL(this.mediaUrl);\n this.mediaPath = mediaUrl.pathname;\n this.mediaServer = mediaUrl.hostname;\n } catch {\n // Invalid URL, leave fields undefined\n }\n }\n\n if (isNotNullish(ad.bitrate)) {\n this.videoBitrate = ad.bitrate * 1000;\n }\n\n const vastData = ad.vastData;\n if (isNotNullish(vastData)) {\n this.adSystem = vastData.adSystem;\n this.advertiserName = vastData.advertiserName;\n this.apiFramework = vastData.apiFramework;\n this.creativeAdId = vastData.creativeAdId;\n this.creativeId = vastData.creativeId;\n this.universalAdIdRegistry = vastData.universalAdIdRegistry;\n this.universalAdIdValue = vastData.universalAdIdValue;\n this.adDescription = vastData.adDescription;\n this.minSuggestedDuration = calculateTimeWithUndefined(vastData.minSuggestedDuration);\n this.surveyUrl = vastData.surveyUrl;\n this.adTitle = vastData.adTitle;\n this.wrapperAdsCount = vastData.wrapperAdsCount;\n }\n\n this.adSkipAfter = parseSkipAfter(ad.skippableAfter);\n this.adSkippable = ad.skippable ?? (isNotNullish(this.adSkipAfter) ? this.adSkipAfter >= 0 : undefined);\n this.adDuration = calculateTimeWithUndefined(ad.duration);\n }\n}\n\nfunction parseSkipAfter(skipAfter?: number) {\n if (skipAfter === undefined) {\n return undefined;\n }\n if (skipAfter === -1) {\n return skipAfter;\n }\n return calculateTime(skipAfter);\n}\n","import {getCustomDataString, transferCustomDataFields} from '../utils/Utils';\n\nexport interface CustomDataValues {\n customData1?: string;\n customData2?: string;\n customData3?: string;\n customData4?: string;\n customData5?: string;\n customData6?: string;\n customData7?: string;\n customData8?: string;\n customData9?: string;\n customData10?: string;\n customData11?: string;\n customData12?: string;\n customData13?: string;\n customData14?: string;\n customData15?: string;\n customData16?: string;\n customData17?: string;\n customData18?: string;\n customData19?: string;\n customData20?: string;\n customData21?: string;\n customData22?: string;\n customData23?: string;\n customData24?: string;\n customData25?: string;\n customData26?: string;\n customData27?: string;\n customData28?: string;\n customData29?: string;\n customData30?: string;\n customData31?: string;\n customData32?: string;\n customData33?: string;\n customData34?: string;\n customData35?: string;\n customData36?: string;\n customData37?: string;\n customData38?: string;\n customData39?: string;\n customData40?: string;\n customData41?: string;\n customData42?: string;\n customData43?: string;\n customData44?: string;\n customData45?: string;\n customData46?: string;\n customData47?: string;\n customData48?: string;\n customData49?: string;\n customData50?: string;\n customData51?: string;\n customData52?: string;\n customData53?: string;\n customData54?: string;\n customData55?: string;\n customData56?: string;\n customData57?: string;\n customData58?: string;\n customData59?: string;\n customData60?: string;\n customData61?: string;\n customData62?: string;\n customData63?: string;\n customData64?: string;\n customData65?: string;\n customData66?: string;\n customData67?: string;\n customData68?: string;\n customData69?: string;\n customData70?: string;\n customData71?: string;\n customData72?: string;\n customData73?: string;\n customData74?: string;\n customData75?: string;\n customData76?: string;\n customData77?: string;\n customData78?: string;\n customData79?: string;\n customData80?: string;\n customData81?: string;\n customData82?: string;\n customData83?: string;\n customData84?: string;\n customData85?: string;\n customData86?: string;\n customData87?: string;\n customData88?: string;\n customData89?: string;\n customData90?: string;\n customData91?: string;\n customData92?: string;\n customData93?: string;\n customData94?: string;\n customData95?: string;\n customData96?: string;\n customData97?: string;\n customData98?: string;\n customData99?: string;\n customData100?: string;\n experimentName?: string;\n}\n\n/**\n * Lists all keys of the {@see CustomDataValues} interface.\n */\nexport const customDataValuesKeys: Array<keyof CustomDataValues> = [\n 'customData1',\n 'customData2',\n 'customData3',\n 'customData4',\n 'customData5',\n 'customData6',\n 'customData7',\n 'customData8',\n 'customData9',\n 'customData10',\n 'customData11',\n 'customData12',\n 'customData13',\n 'customData14',\n 'customData15',\n 'customData16',\n 'customData17',\n 'customData18',\n 'customData19',\n 'customData20',\n 'customData21',\n 'customData22',\n 'customData23',\n 'customData24',\n 'customData25',\n 'customData26',\n 'customData27',\n 'customData28',\n 'customData29',\n 'customData30',\n 'customData31',\n 'customData32',\n 'customData33',\n 'customData34',\n 'customData35',\n 'customData36',\n 'customData37',\n 'customData38',\n 'customData39',\n 'customData40',\n 'customData41',\n 'customData42',\n 'customData43',\n 'customData44',\n 'customData45',\n 'customData46',\n 'customData47',\n 'customData48',\n 'customData49',\n 'customData50',\n 'customData51',\n 'customData52',\n 'customData53',\n 'customData54',\n 'customData55',\n 'customData56',\n 'customData57',\n 'customData58',\n 'customData59',\n 'customData60',\n 'customData61',\n 'customData62',\n 'customData63',\n 'customData64',\n 'customData65',\n 'customData66',\n 'customData67',\n 'customData68',\n 'customData69',\n 'customData70',\n 'customData71',\n 'customData72',\n 'customData73',\n 'customData74',\n 'customData75',\n 'customData76',\n 'customData77',\n 'customData78',\n 'customData79',\n 'customData80',\n 'customData81',\n 'customData82',\n 'customData83',\n 'customData84',\n 'customData85',\n 'customData86',\n 'customData87',\n 'customData88',\n 'customData89',\n 'customData90',\n 'customData91',\n 'customData92',\n 'customData93',\n 'customData94',\n 'customData95',\n 'customData96',\n 'customData97',\n 'customData98',\n 'customData99',\n 'customData100',\n\n 'experimentName',\n];\n\n/**\n * The number of CustomDataXX fields in {@see CustomDataValues}.\n */\nexport const customDataFieldCount = customDataValuesKeys.filter((i) => i.match('customData\\\\d+')).length;\n\n/**\n * We are extracting the customData fields explicitly to make sure that there is not a different object passed\n */\nexport const extractCustomDataFieldsOnly = (input: CustomDataValues): CustomDataValues => {\n const retVal: CustomDataValues = {};\n customDataValuesKeys.forEach((key) => {\n if (input[key]) {\n retVal[key] = input[key];\n }\n });\n return retVal;\n};\n\nexport const sanitizeCustomDataValues = (customDataValues: CustomDataValues): CustomDataValues => {\n const extracted = extractCustomDataFieldsOnly(customDataValues);\n\n const sanitizedCustomDataValues: CustomDataValues = {};\n transferCustomDataFields(extracted, sanitizedCustomDataValues);\n // fix a bug of transferCustomDataFields that does not transfer 'experimentName' field, because it is not named 'customDataXX'\n // should be fixed with https://bitmovin.atlassian.net/browse/AN-5182\n sanitizedCustomDataValues.experimentName = getCustomDataString(extracted.experimentName);\n\n return sanitizedCustomDataValues;\n};\n","import {FeatureConfigContainer} from './FeatureConfigContainer';\n\nexport interface LicensingRequest {\n key?: string;\n domain: string;\n version: string;\n}\n\nexport enum LicensingResult {\n Denied = 'denied',\n Granted = 'granted',\n Skip = 'skip',\n}\n\nexport interface LicensingResponse {\n status: LicensingResult;\n message: string;\n features?: FeatureConfigContainer;\n}\n\nexport type LicenseCallFunc = (\n key: string,\n domain: string,\n version: string,\n baseUrl: string,\n) => Promise<LicensingResponse>;\n","import {PlayerSize} from '../enums/PlayerSize';\nimport {StreamTypes} from '../enums/StreamTypes';\nimport {isNullish} from '../utils/Utils';\n\nexport interface PlaybackInfo {\n audioBitrate?: number;\n audioCodec?: string;\n audioLanguage?: string;\n castTech?: string;\n droppedFrames: number;\n isCasting?: boolean;\n isLive?: boolean;\n isMuted?: boolean;\n m3u8Url?: string;\n mpdUrl?: string;\n playerTech?: string;\n progUrl?: string;\n screenHeight?: number;\n screenWidth?: number;\n size?: PlayerSize;\n streamFormat?: string;\n subtitleEnabled?: boolean;\n subtitleLanguage?: string;\n videoBitrate?: number;\n videoCodec?: string;\n videoDuration?: number;\n videoPlaybackHeight?: number;\n videoPlaybackWidth?: number;\n videoTitle?: string;\n videoWindowHeight?: number;\n videoWindowWidth?: number;\n}\n\nexport function normalizeVideoDuration(playerVideoDuration: number | null | undefined): number {\n // This covers Live streams and any case in which the duration is not known\n // which should report 0 as videoDuration\n if (isNullish(playerVideoDuration) || Number.isNaN(playerVideoDuration) || playerVideoDuration === Infinity) {\n return 0;\n }\n return playerVideoDuration;\n}\n\nexport function buildPlaybackInfoStreamTypeFields(\n streamType: StreamTypes | undefined,\n streamUrl: string | undefined,\n): Pick<PlaybackInfo, 'm3u8Url' | 'mpdUrl' | 'progUrl' | 'streamFormat'> {\n const DEFAULT_RESULT = {\n // set the stream type as it is (except null, that should be converted to undefined)\n streamFormat: streamType ?? undefined,\n // If the stream url is there, set it as \"progUrl\", even when the stream type is not recognized (unknown / nullish).\n // Why?\n // There was no clear reason why when this utility fn was created, it was just current written code/behavior\n // of our adapters, and for that reason it was copy&pasted here.\n progUrl: streamUrl,\n };\n\n if (isNullish(streamType)) {\n return DEFAULT_RESULT;\n }\n\n if (streamType === StreamTypes.dash) {\n return {streamFormat: streamType, mpdUrl: streamUrl};\n }\n if (streamType === StreamTypes.hls) {\n return {streamFormat: streamType, m3u8Url: streamUrl};\n }\n if (streamType === StreamTypes.prog) {\n return {streamFormat: streamType, progUrl: streamUrl};\n }\n\n return DEFAULT_RESULT;\n}\n","import {logger} from '../utils/Logger';\nimport {isValidString} from '../utils/stringUtils';\nimport {isBoolean, isNotNullish, isNullish, isPlainObject} from '../utils/Utils';\n\nimport {CustomDataValues, sanitizeCustomDataValues} from './CustomDataValues';\n\nexport interface SourceMetadata {\n readonly title?: string;\n readonly videoId?: string;\n readonly cdnProvider?: string;\n readonly path?: string;\n readonly isLive?: boolean;\n readonly customData?: CustomDataValues;\n}\n\nexport function hasValidSourceMetadataStructure(anything: unknown): anything is SourceMetadata | null | undefined {\n // \"nullish\" is considered to be valid SourceMetadata, because we will then use an empty object as a default value\n if (isNullish(anything)) {\n return true;\n }\n\n // invalid, when value was defined, but not as a plain object\n if (!isPlainObject(anything as object)) {\n logger.errorMessageToUser('Invalid SourceMetadata: not a plain object');\n return false;\n }\n\n const maybeSourceMetadata = anything as SourceMetadata;\n\n if (isNotNullish(maybeSourceMetadata.customData) && !isPlainObject(maybeSourceMetadata.customData)) {\n logger.errorMessageToUser(\"Invalid SourceMetadata: 'customData' property is not a plain object\");\n return false;\n }\n\n return true;\n}\n\nexport function sanitizeSourceMetadata(sourceMetadata: SourceMetadata | null | undefined): SourceMetadata {\n // \"nullish\" is considered to be valid SourceMetadata\n if (isNullish(sourceMetadata)) {\n // sanitize to be not \"nullish\"\n return {};\n }\n\n let result: SourceMetadata = {};\n if ('title' in sourceMetadata) {\n result = {\n ...result,\n title: isValidString(sourceMetadata.title) ? sourceMetadata.title : undefined,\n };\n }\n\n if ('videoId' in sourceMetadata) {\n result = {\n ...result,\n videoId: isValidString(sourceMetadata.videoId) ? sourceMetadata.videoId : undefined,\n };\n }\n\n if ('cdnProvider' in sourceMetadata) {\n result = {\n ...result,\n cdnProvider: isValidString(sourceMetadata.cdnProvider) ? sourceMetadata.cdnProvider : undefined,\n };\n }\n\n if ('path' in sourceMetadata) {\n result = {\n ...result,\n path: isValidString(sourceMetadata.path) ? sourceMetadata.path : undefined,\n };\n }\n\n if ('isLive' in sourceMetadata) {\n result = {\n ...result,\n isLive: isBoolean(sourceMetadata.isLive) ? sourceMetadata.isLive : undefined,\n };\n }\n\n if ('customData' in sourceMetadata) {\n result = {\n ...result,\n customData: isNotNullish(sourceMetadata.customData)\n ? sanitizeCustomDataValues(sourceMetadata.customData)\n : undefined,\n };\n }\n\n return result;\n}\n","import type {VideoStartFailedReason} from '../enums/VideoStartFailedReason';\n\nimport type {AnalyticsConfig} from './AnalyticsConfig';\nimport type {AnalyticsEventBase, CustomDataValuesEvent, ErrorEvent, QualityChangeEvent} from './EventData';\nimport type {Sample} from './Sample';\nimport type {SourceMetadata} from './SourceMetadata';\n\nexport type HeartbeatPayload = {\n buffered?: Sample['buffered'];\n /**\n * Flag indicating that the event was triggered by a program change.\n *\n * `true` if the event was triggered by a program change, `undefined` otherwise to not set it as a property in the sample.\n */\n isProgramChange?: true;\n played?: Sample['played'];\n /** Flag indicating that the event was triggered by SSAI */\n triggeredBySsai?: boolean;\n};\n\nexport interface StateMachineCallbacks {\n setup: (duration: number, state: string) => void;\n startup: (duration: number, state: string) => void;\n /** Should reset the analytics, update the source metadata, and send a \"program change startup sample\" */\n programChange: (sourceMetadata: SourceMetadata) => void;\n /** Should only update the source metadata in the analytics module, but without sending any sample. */\n updateSourceMetadata: (sourceMetadata: SourceMetadata) => void;\n playing: (duration: number, state: string) => void;\n heartbeat: (duration: number, state: 'playing' | 'rebuffering', payload: HeartbeatPayload) => void;\n /**\n * Should send a sample with state \"qualitychange\" and duration 0\n */\n qualitychange: (event: QualityChangeEvent) => void;\n /**\n * Should update the qualityInfo on the current sample but not send any sample, e.g when a qualityChange occurs during\n * pause, seeking or buffering or when the QUALITY_CHANGE_THRESHOLD was hit\n */\n updateSampleQualityInfo: (event: QualityChangeEvent) => void;\n audiotrack_changing: () => void;\n pause: (duration: number, state: string) => void;\n /**\n * Should send a sample with `state: \"seeking\"` and `duration` set to the duration of the seeking.\n */\n seeking: (duration: number) => void;\n rebuffering: (duration: number, state: string) => void;\n error: (event: Readonly<ErrorEvent>) => void;\n /**\n * @deprecated should not be used at all.\n *\n * Instead, the \"end\" player event should transition state machine to PAUSE state\n *\n * https://bitmovin.atlassian.net/browse/AN-5134\n */\n end: (duration: number, state: string) => void;\n unload: (duration: number, state: string) => void;\n ad: (duration: number, state: string) => void;\n mute: () => void;\n unMute: () => void;\n subtitle_changing: () => void;\n setVideoTimeEndFromEvent: (analyticsEventBase: AnalyticsEventBase) => void;\n setVideoTimeStartFromEvent: (analyticsEventBase: AnalyticsEventBase) => void;\n videoStartFailed: (duration: number, reason: VideoStartFailedReason) => void;\n startCasting: (duration: number, event: any) => void;\n casting: (duration: number, event: any) => void;\n manualSourceChange: (event: {config: AnalyticsConfig}) => void;\n initialSourceChange: (event: {config: AnalyticsConfig}) => void;\n muting_ready: (duration: number, state: string, event: any) => void;\n /**\n * Should change {@link CustomDataValues} of analytics module.\n *\n * @remarks\n *\n * It is called via the default \"onleavestate\" state machine callback, and because of that:\n * - it has to match the state name \"CUSTOMDATACHANGE\"\n * - each parameter has to of `undefined` type (unintentionally, it can be called at any time, from any state)\n */\n customdatachange: (\n duration: number | undefined,\n state: string | undefined,\n eventData: CustomDataValuesEvent | undefined,\n ) => void;\n\n /** shuts down the collection and removes/clears all timeouts, intervals, event listeners */\n release: () => void;\n}\n\n/**\n * {@link StateMachineCallbacks} object with each callback set to be empty function (doing nothing).\n *\n * Why?:\n * We need to set it as default value in {@link InternalAdapter} for use case, when {@link InternalAdapter}\n * is already created and listen to player events, but {@link Analytics} was not instantiated/initialized yet (that\n * should set correct {@link StateMachineCallbacks} implementation)\n */\nexport const defaultStateMachineCallbacks: StateMachineCallbacks = {\n setup: () => {},\n startup: () => {},\n programChange: () => {},\n updateSourceMetadata: () => {},\n playing: () => {},\n heartbeat: () => {},\n qualitychange: () => {},\n updateSampleQualityInfo: () => {},\n audiotrack_changing: () => {},\n pause: () => {},\n seeking: () => {},\n rebuffering: () => {},\n error: () => {},\n end: () => {},\n unload: () => {},\n ad: () => {},\n mute: () => {},\n unMute: () => {},\n subtitle_changing: () => {},\n setVideoTimeEndFromEvent: () => {},\n setVideoTimeStartFromEvent: () => {},\n videoStartFailed: () => {},\n startCasting: () => {},\n casting: () => {},\n manualSourceChange: () => {},\n initialSourceChange: () => {},\n muting_ready: () => {},\n customdatachange: () => {},\n release: () => {},\n};\n","import {isNotNullish, isNullish} from '../utils/Utils';\n\nexport interface SubtitleInfo {\n /**\n * Indicates if subtitles are displayed.\n */\n enabled: boolean;\n /**\n * The selected subtitle/captions language.\n */\n language?: string;\n}\n\nexport const isDifferentSubtitleInfo = (info1?: SubtitleInfo, info2?: SubtitleInfo): boolean => {\n if (isNullish(info1) && isNullish(info2)) {\n return false;\n }\n return !(\n isNotNullish(info1) &&\n isNotNullish(info2) &&\n info1.enabled === info2.enabled &&\n info1.language === info2.language\n );\n};\n","import {appendSsaiRoutingParam, isSsaiRelatedSample} from '../core/ssai/ssaiUtils';\nimport type {AdSample, Sample} from '../types/Sample';\n\nimport {globalScope} from './globalScope';\nimport {post} from './Http';\nimport {joinUrls, noOp} from './Utils';\n\nexport class AnalyticsCall {\n private readonly analyticsServerUrl: string;\n private readonly adAnalyticsServerUrl: string;\n\n constructor(baseUrl: string) {\n this.analyticsServerUrl = joinUrls(baseUrl, 'analytics');\n this.adAnalyticsServerUrl = joinUrls(baseUrl, 'analytics/a');\n }\n\n sendRequest(sample: Sample, callback: () => void) {\n let analyticsUrl = this.analyticsServerUrl;\n if (isSsaiRelatedSample(sample)) {\n analyticsUrl = appendSsaiRoutingParam(analyticsUrl);\n }\n\n post(analyticsUrl, sample, callback);\n }\n\n sendUnloadRequest(sample: Sample) {\n const sendBeaconFallback = (data: Sample) => this.sendRequestSynchronous(data, noOp);\n\n let analyticsUrl = this.analyticsServerUrl;\n if (isSsaiRelatedSample(sample)) {\n analyticsUrl = appendSsaiRoutingParam(analyticsUrl);\n }\n\n this.trySendBeacon(sendBeaconFallback, analyticsUrl, sample);\n }\n\n private trySendBeacon(\n fallbackFunction: (data: any) => void,\n url: string,\n data: unknown,\n requestHeaders: {[headerName: string]: string} = {},\n ) {\n if (typeof globalScope.navigator?.sendBeacon === 'undefined') {\n fallbackFunction(data);\n } else {\n /**\n * With a Blob we can send payload but also http headers\n * @see https://stackoverflow.com/questions/40523469/navigator-sendbeacon-to-pass-header-information\n */\n const blob = new Blob([JSON.stringify(data)], requestHeaders);\n const success = globalScope.navigator.sendBeacon(url, blob);\n if (!success) {\n fallbackFunction(data);\n }\n }\n }\n\n sendRequestSynchronous(sample: Sample, callback: () => void) {\n let analyticsUrl = this.analyticsServerUrl;\n if (isSsaiRelatedSample(sample)) {\n analyticsUrl = appendSsaiRoutingParam(analyticsUrl);\n }\n\n post(analyticsUrl, sample, callback, false);\n }\n\n sendAdRequest(adSample: AdSample) {\n let adAnalyticsUrl = this.adAnalyticsServerUrl;\n if (isSsaiRelatedSample(adSample)) {\n adAnalyticsUrl = appendSsaiRoutingParam(adAnalyticsUrl);\n }\n\n const sendBeaconFallback = (data: AdSample) => post(adAnalyticsUrl, data, noOp);\n this.trySendBeacon(sendBeaconFallback, adAnalyticsUrl, adSample);\n }\n}\n","import {ProgressiveSourceConfig} from '../types/ProgressiveSourceConfig';\nimport {ProgressiveSourceInfo} from '../types/SourceInfo';\n\nimport {isNotNullish} from './Utils';\n\nexport const getSourceInfoFromBitmovinSourceConfig = (\n progressive: ProgressiveSourceConfig,\n player: any,\n): ProgressiveSourceInfo => {\n if (!progressive) {\n return {\n progBitrate: undefined,\n progUrl: undefined,\n };\n }\n\n if (typeof progressive === 'string') {\n return {\n progBitrate: 0,\n progUrl: progressive,\n };\n }\n\n if (Array.isArray(progressive) && progressive.length > 0) {\n const playbackVideoData = player.getPlaybackVideoData();\n let progressiveArrayIndex = 0;\n\n if (isNotNullish(playbackVideoData) && !isNaN(+playbackVideoData.id)) {\n progressiveArrayIndex = +playbackVideoData.id;\n }\n\n return {\n progBitrate: progressive[progressiveArrayIndex].bitrate || 0,\n progUrl: progressive[progressiveArrayIndex].url,\n };\n }\n\n if (typeof progressive === 'object' && !Array.isArray(progressive)) {\n return {\n progBitrate: progressive.bitrate || 0,\n progUrl: progressive.url,\n };\n }\n\n return {\n progBitrate: undefined,\n progUrl: undefined,\n };\n};\n","import {globalScope} from './globalScope';\nimport {isFunction, isNullish} from './Utils';\n\nconst videoFormatCodecMap: {[format: string]: string[]} = {\n avc: ['video/mp4; codecs=\"avc1.42000a\"'],\n vp9: ['video/mp4; codecs=\"vp09.00.50.08\"'],\n av1: ['video/mp4; codecs=\"av01.0.08M.08\"'],\n hevc: ['video/mp4; codecs=\"hev1.1.6.L93.B0\"'],\n};\n\nexport class CodecHelper {\n static get supportedVideoFormats(): string[] | undefined {\n if (isNullish(globalScope.MediaSource?.isTypeSupported) || !isFunction(globalScope.MediaSource.isTypeSupported)) {\n return undefined;\n }\n return Object.getOwnPropertyNames(videoFormatCodecMap).filter((format) =>\n videoFormatCodecMap[format].some((codec) => globalScope.MediaSource.isTypeSupported(codec)),\n );\n }\n}\n","export class Converter {\n static bytesToBits(bytes: number): number {\n return bytes * 8;\n }\n static bitsToBytes(bits: number): number {\n return Math.round(bits / 8);\n }\n static kiloBitsToBits(kiloBits: number): number {\n return kiloBits * 1000;\n }\n}\n","export class EventDebugging {\n event: string | undefined;\n from: string | undefined;\n to: string | undefined;\n timestamp: number;\n eventObject: any;\n\n constructor(\n event: string | undefined,\n from: string | undefined,\n to: string | undefined,\n timestamp: number,\n eventObject: any,\n ) {\n this.event = event;\n this.from = from;\n this.to = to;\n this.timestamp = timestamp;\n this.eventObject = eventObject;\n }\n}\n","import {globalScope} from './globalScope';\nimport {logger} from './Logger';\nimport {isReactNative} from './Utils';\n\nexport function post(url: string, body: any, callback: any, async = true): void {\n // React Native doesn't support synchronous XMLHttpRequest\n // Force async mode in React Native environments\n if (isReactNative() && !async) {\n async = true;\n }\n\n let xhttp: any;\n let isLegacyXDomainRequestUsed = false;\n\n if (globalScope.XDomainRequest) {\n // XDomainRequest is the only way of having an XHR that supports CORS in IE8 and 9. At the time of IE8,\n // Microsoft decided to come up with their own CORS XHR instead of the standard CORS XMLHttpRequest\n // which is now used in IE10.\n // Since IE10, XDomainRequest has been deprecated and since IE11 removed.\n xhttp = new globalScope.XDomainRequest();\n isLegacyXDomainRequestUsed = true;\n } else {\n xhttp = new XMLHttpRequest();\n }\n\n const responseCallback = () => {\n if (xhttp.readyState == XMLHttpRequest.DONE) {\n if (xhttp.responseText <= 0) {\n return;\n }\n\n const sampleResponse = JSON.parse(xhttp.responseText);\n\n callback(sampleResponse);\n }\n };\n\n if (isLegacyXDomainRequestUsed) {\n xhttp.onload = responseCallback;\n } else {\n xhttp.onreadystatechange = responseCallback;\n }\n\n try {\n xhttp.open('POST', url, async);\n\n // XDomainRequest restriction: No custom headers may be added to the request\n // https://learn.microsoft.com/en-us/archive/blogs/ieinternals/xdomainrequest-restrictions-limitations-and-workarounds\n if (!isLegacyXDomainRequestUsed) {\n xhttp.setRequestHeader('Content-Type', 'text/plain');\n }\n\n xhttp.send(JSON.stringify(body));\n } catch (e) {\n logger.error('Failed to send POST request.', e);\n }\n}\n","import {LicensingResponse} from '../types/LicensingRequest';\n\nimport {post} from './Http';\nimport {joinUrls} from './Utils';\n\nexport function LicenseCall(key: string, domain: string, version: string, baseUrl: string): Promise<LicensingResponse> {\n const licenseServerUrl = joinUrls(baseUrl, '/licensing');\n const licensingRequest = {\n analyticsVersion: version,\n domain,\n key,\n };\n return new Promise<LicensingResponse>((resolve) => {\n post(licenseServerUrl, licensingRequest, (response) => {\n resolve(response);\n });\n });\n}\n","import {AnalyticsConfig} from '../types/AnalyticsConfig';\n\n/**\n * Uses a Singleton design pattern.\n *\n * We want to ensure that only one object of its kind exists and provides a single point of access to it,\n * to be able to control enabled/disabled `console` logs for customer in whole code base.\n */\nclass Logger {\n private static instance: Logger;\n\n static getInstance(): Logger {\n if (!Logger.instance) {\n Logger.instance = new Logger();\n }\n\n return Logger.instance;\n }\n\n private analyticsDebugConfig: Readonly<AnalyticsConfig['debug']>;\n\n private constructor() {}\n\n initialize(analyticsDebugConfig: AnalyticsConfig['debug']) {\n this.analyticsDebugConfig = analyticsDebugConfig;\n }\n\n //#region Console API\n log(message?: unknown, ...optionalParams: unknown[]) {\n if (!this.enabled) {\n return;\n }\n console.log(message, optionalParams); //eslint-disable-line no-console\n }\n\n table(tabularData: unknown, properties?: readonly string[]) {\n if (!this.enabled) {\n return;\n }\n console.table(tabularData, properties); //eslint-disable-line no-console\n }\n\n warn(message?: unknown, ...optionalParams: unknown[]) {\n if (!this.enabled) {\n return;\n }\n console.warn(message, optionalParams); //eslint-disable-line no-console\n }\n\n error(message?: unknown, ...optionalParams: unknown[]) {\n if (!this.enabled) {\n return;\n }\n console.error(message, optionalParams); //eslint-disable-line no-console\n }\n\n /**\n * Outputs an error message to user/customer console.\n *\n * Does not relay on {@link Logger#enabled}! because it should deliver the error information to user/customer.\n */\n errorMessageToUser(message?: unknown, ...optionalParams: unknown[]) {\n console.error(message, ...optionalParams); //eslint-disable-line no-console\n }\n //#endregion\n\n /** `true` if {@link AnalyticsConfig#debug} was set */\n private get enabled() {\n return (this.analyticsDebugConfig as boolean) || false;\n }\n}\n\nexport const padRight = (str: string | undefined, length: number) => {\n const padStr = new Array(length).join(' ');\n return (str + padStr).slice(0, length);\n};\n\nexport const logger = Logger.getInstance();\n","export class Queue<T> {\n private readonly _items: T[] = [];\n\n get items(): ReadonlyArray<T> {\n return this._items;\n }\n\n get length() {\n return this._items.length;\n }\n\n offer(item: T) {\n this._items.push(item);\n }\n\n poll(): T | undefined {\n return this._items.shift();\n }\n\n clear() {\n this._items.splice(0);\n }\n\n limit(maxElements: number) {\n while (this._items.length > maxElements) {\n this.poll();\n }\n }\n}\n","export const MESSAGE_NAMESPACE = 'urn:x-cast:com.bitmovin.analytics.cast';\nexport const ANALYTICS_BACKEND_BASE_URL = 'https://analytics-ingress-global.bitmovin.com';\n\nexport const ANALYTICS_LICENSECALL_TIMEOUT = 1000 * 60;\nexport const ANALYTICS_VIDEOSTART_TIMEOUT = 1000 * 60; // in milliseconds\n\nexport const ANALYTICS_QUALITY_CHANGE_COUNT_THRESHOLD = 50;\nexport const ANALYTICS_QUALITY_CHANGE_COUNT_RESET_INTERVAL = 60 * 60 * 1000;\n\n/**\n * Time (in milliseconds) of consecutive buffering until a REBUFFER_TIMEOUT_ERROR is raised.\n */\nexport const ANALYTICS_REBUFFER_TIMEOUT = 1000 * 60 * 2;\n\n/**\n * minimal time (in seconds) a seek event should have in order to be recogniced as seek\n */\nexport const ANALYTICS_MIN_SEEK_DIFFERENCE_THRESHOLD = 3;\n\n/**\n * Has to be greater or equal than Ingress side limit (currently 1000).\n */\nexport const SEQUENCE_NUMBER_LIMIT = 1000;\n","import {PAGE_LOAD_TYPE} from '../enums/PageLoadType';\nimport {ErrorSeverity} from '../types/AnalyticsConfig';\nimport type {CustomDataValues} from '../types/CustomDataValues';\nimport * as CustomDataUtils from '../types/CustomDataValues';\n\nimport {isDocumentHidden} from './documentUtils';\nimport {getGlobalNavigatorProduct} from './globalScopeUtils';\nimport {endsWith, startsWith} from './stringUtils';\n\n/**\n * Performs a loose equality check (==), which means it checks for both null and undefined.\n *\n * @returns {value is null | undefined} `true` if the given value is `null` or `undefined`.\n */\nexport const isNullish = (value: unknown): value is null | undefined => value == null;\n\n/**\n *\n * @returns {value is Exclude<unknown, null | undefined>} `true` if the given value is not `null` and is not `undefined`.\n */\nexport const isNotNullish = <T = unknown>(value: T): value is Exclude<T, null | undefined> => !isNullish(value);\n\n/**\n * @returns {value is boolean} `true` if the given value is {@link isNotNullish} and is type of `boolean`.\n */\nexport const isBoolean = (value: unknown): value is boolean => !isNullish(value) && typeof value === 'boolean';\n\nexport const toBoolean = (value: unknown): boolean => Boolean(value).valueOf();\n\n/**\n * Checks if a value is a non-null object.\n *\n * We must exclude `null` explicitly, because `typeof null === \"object\"`\n *\n * @returns {value is Record<string, unknown>} `true` if the value is a non-null object, otherwise `false`.\n */\nexport const isObject = <T extends object>(value: T): value is T => {\n return isNotNullish(value) && typeof value === 'object';\n};\n\n/**\n * Checks if a value is a plain object (not an array, function, or built-in instance).\n *\n * @returns {value is Record<string, unknown>} `true` if the value is a plain object, otherwise `false`.\n */\nexport const isPlainObject = <T extends object>(value: T): value is T => {\n return Object.prototype.toString.call(value) === '[object Object]';\n};\n\n/**\n * Checks if a value is a function.\n *\n * @returns {value is function} `true` if the value is a function, otherwise `false`.\n */\nexport const isFunction = <T extends (...args: unknown[]) => unknown>(value: unknown): value is T =>\n typeof value === 'function';\n\n/**\n * Checks if a value is of type ErrorSeverity.\n *\n * @returns {value is ErrorSeverity} `true` if the value is of type ErrorSeverity, otherwise `false`.\n */\nexport function isErrorSeverity(anything: unknown): anything is ErrorSeverity {\n // invalid, when not defined as one of string values we expect\n return anything === 'CRITICAL' || anything === 'INFO';\n}\n\n/** Remove trailing slash from a path, if it exists. */\nexport const removeTrailingSlash = (path: string): string => {\n return path.replace(/\\/$/g, '');\n};\n\n/** Take a time in seconds and return a value that represents a time in milliseconds, rounded to the nearest integer */\nexport const calculateTime = (timeInSeconds: number) => Math.round(timeInSeconds * 1000);\n\n/** Same as {@link calculateTime} but if time is \"nullish\", then the return value is `undefined` */\nexport const calculateTimeWithUndefined = (timeInSeconds: number | null | undefined): number | undefined => {\n if (isNullish(timeInSeconds)) {\n return undefined;\n }\n return calculateTime(timeInSeconds);\n};\n\n/**\n * @deprecated Use directly `Date.now()` instead\n *\n * Return the current time in milliseconds.\n */\nexport const getCurrentTimestamp = (): number => {\n return Date.now();\n};\n\n/**\n * Empty function returns undefined\n *\n * @deprecated\n */\nexport const noOp = () => undefined;\n\nexport const getCustomDataString = (customData: any): string | undefined => {\n if (typeof customData === 'object') {\n return tryJSONStringify(customData);\n } else if (isFunction(customData)) {\n return getCustomDataString(customData());\n } else if (typeof customData === 'undefined') {\n return customData;\n } else if (typeof customData !== 'string') {\n return String(customData);\n }\n\n return customData;\n};\n\nexport const transferCustomDataFields = (fromConfig: CustomDataValues, toConfig: CustomDataValues) => {\n for (let i = 1; i <= CustomDataUtils.customDataFieldCount; i++) {\n const customDataField = `customData${i}`;\n toConfig[customDataField] = getCustomDataString(fromConfig[customDataField]);\n }\n};\n\n/**\n * Determine if the page was loaded in the foreground or background\n */\nexport function getPageLoadType(): PAGE_LOAD_TYPE {\n if (isDocumentHidden()) {\n return PAGE_LOAD_TYPE.BACKGROUND;\n }\n return PAGE_LOAD_TYPE.FOREGROUND;\n}\n\nexport const calculatePercentage = (numerator?: number, denominator?: number): number | undefined => {\n if (denominator === undefined || denominator === 0) {\n return undefined;\n }\n return Math.round(((numerator || 0) / denominator) * 100);\n};\n\nexport const getURLResourceName = (url: string): string => {\n if (url.length === 0) {\n return '';\n }\n return url.split('/').pop() || '';\n};\n\nexport const joinUrls = (...args: string[]): string => {\n return args.reduce((prev, current) => {\n const prevUrlValue = endsWith(prev, '/') && current !== undefined ? prev.substr(0, prev.length - 1) : prev;\n const nextUrlValue = startsWith(current, '/') ? current.substr(1) : current;\n return prevUrlValue + '/' + nextUrlValue;\n });\n};\n\n/**\n * Detect if running in a React Native environment using navigator.product\n * https://github.com/facebook/react-native/commit/3c65e62183ce05893be0822da217cb803b121c61\n * https://github.com/facebook/react-native/issues/1331\n * https://stackoverflow.com/questions/39468022/how-do-i-know-if-my-code-is-running-as-react-native\n * navigator object from vega os simulator {\"product\":\"ReactNative\",\"userAgent\":\"ReactNative\"}\n */\nexport const isReactNative = (): boolean => {\n return getGlobalNavigatorProduct() === 'ReactNative';\n};\n\n/**\n * Determine if the audio is muted based on the player muted state and current volume.\n *\n * @param playerIsMuted `true` means muted and `false` means not muted.\n * @param playerVolume A double values must fall between 0 and 1, where 0 is effectively muted and 1 is the loudest possible value.\n */\nexport const isAudioMuted = (playerIsMuted: boolean, playerVolume: number) => {\n /** Audio volume below this delta is considered zero. */\n const VOLUME_DELTA = 0.01;\n\n return playerIsMuted || playerVolume < VOLUME_DELTA;\n};\n\nexport const tryJSONStringify = (obj: unknown): string | undefined => {\n if (isNullish(obj)) {\n return undefined;\n }\n\n try {\n return JSON.stringify(obj);\n } catch {\n return undefined;\n }\n};\n\n/**\n * Checks if a value is an `ArrayBuffer` instance.\n *\n * Uses `Object.prototype.toString` for reliable detection across different\n * execution contexts (e.g. iframes, workers) where `instanceof ArrayBuffer` may fail.\n *\n * @returns {value is ArrayBuffer} `true` if the value is an `ArrayBuffer`, otherwise `false`.\n */\nexport function isArrayBuffer(value: unknown): value is ArrayBuffer {\n return Object.prototype.toString.call(value) === '[object ArrayBuffer]';\n}\n","declare global {\n /** Variable is defined by webpack.DefinePlugin during the build process. */\n const __VERSION__: string;\n}\n\nexport const VERSION: string = __VERSION__;\n","import {addDocumentEventListener, getDocumentPropertyWithPrefix, removeDocumentEventListener} from './documentUtils';\nimport {globalScope} from './globalScope';\nimport {logger} from './Logger';\nimport {isValidString} from './stringUtils';\nimport {isNullish} from './Utils';\n\nexport class ViewportTracker {\n private onIntersectionChanged: () => void;\n private observer?: IntersectionObserver;\n private element: HTMLElement;\n private inViewport?: boolean = undefined;\n private threshold: number;\n private hiddenPropertyName: string | undefined;\n private visibilityChange?: string;\n\n constructor(element: HTMLElement, onIntersectionChanged: () => void, threshold = 1.0) {\n this.threshold = threshold;\n this.onIntersectionChanged = onIntersectionChanged;\n this.element = element;\n\n try {\n const options: IntersectionObserverInit = {\n root: null,\n rootMargin: '0px',\n threshold,\n };\n this.observer = new IntersectionObserver((entries, observer) => this.handleIntersect(entries, observer), options);\n this.observer.observe(element);\n } catch (_error) {\n logger.log(\"Couldn't create instance of IntersectionObserver. timeInViewport will always be reported as 100%.\");\n }\n\n this.hiddenPropertyName = getDocumentPropertyWithPrefix('hidden');\n if (this.hiddenPropertyName) {\n this.visibilityChange = this.hiddenPropertyName.replace('hidden', '') + 'visibilitychange';\n addDocumentEventListener(\n this.visibilityChange,\n (this.handleVisibilityChange = this.handleVisibilityChange.bind(this)),\n false,\n );\n }\n }\n\n isHidden() {\n if (isNullish(globalScope.document) || !isValidString(this.hiddenPropertyName)) {\n return false;\n }\n\n return globalScope.document[this.hiddenPropertyName] === true;\n }\n\n isInViewport(): boolean {\n return !this.isHidden() && (isNullish(this.inViewport) ? true : this.inViewport);\n }\n\n dispose() {\n if (this.observer) {\n this.observer.unobserve(this.element);\n this.observer.disconnect();\n }\n if (this.visibilityChange) {\n removeDocumentEventListener(this.visibilityChange, this.handleVisibilityChange, false);\n }\n }\n\n private handleVisibilityChange() {\n this.onIntersectionChanged();\n }\n\n private handleIntersect(entries: IntersectionObserverEntry[], _observer: IntersectionObserver) {\n entries.forEach((i) => {\n if (i.target === this.element) {\n this.inViewport = !(i.intersectionRatio < this.threshold);\n }\n });\n this.onIntersectionChanged();\n }\n}\n","import {getGlobalWebOSApi} from './globalScopeUtils';\nimport {isBlank, isValidString} from './stringUtils';\n\n// Declaration merging to extend the Window interface with WebOS API\n// see: https://webostv.developer.lge.com/develop/references/webostvjs-webos\ndeclare global {\n interface Window {\n /**\n * @deprecated In webOS TV 4.x or lower, only PalmSystem is supported, and in webOS TV 5.0 or higher,\n * both PalmSystem and webOSSystem are supported. Although PalmSystem is still supported for backward compatibility,\n * future support is not guaranteed so it is strongly recommended that you use webOSSystem in webOS TV 5.0 or higher.\n *\n * @see https://webostv.developer.lge.com/develop/guides/app-lifecycle-management\n */\n PalmSystem?: {\n deviceInfo?: string;\n };\n\n /**\n * Represents the current system interface that should be used on webOS TV 5.0 or higher.\n *\n * @see https://webostv.developer.lge.com/develop/references/webostvjs-webos\n */\n webOSSystem?: {\n /**\n * @see https://webostv.developer.lge.com/develop/references/webostvjs-webos#deviceinfo\n */\n deviceInfo?: string;\n };\n }\n}\n\ntype WebOSDeviceInfo = {modelName: string};\n\nexport function getWebOSTVModelName(): string | undefined {\n try {\n const {webOSSystem, PalmSystem} = getGlobalWebOSApi();\n const info: WebOSDeviceInfo | undefined = webOSSystem?.deviceInfo\n ? JSON.parse(webOSSystem.deviceInfo)\n : PalmSystem?.deviceInfo && JSON.parse(PalmSystem.deviceInfo);\n if (isValidString(info?.modelName) && !isBlank(info?.modelName)) {\n return info.modelName;\n }\n return undefined;\n } catch {\n return undefined;\n }\n}\n","import {addGlobalEventListener, removeGlobalEventListener} from './globalScopeUtils';\n\ninterface EventListener {\n eventName: string;\n func: EventListenerOrEventListenerObject;\n}\n\nexport class WindowEventTracker {\n private trackedObjects: EventListener[] = [];\n\n addEventListener(eventName: string, func: EventListenerOrEventListenerObject) {\n this.trackedObjects.push({eventName, func});\n addGlobalEventListener(eventName, func);\n }\n\n release() {\n while (this.trackedObjects.length !== 0) {\n const obj = this.trackedObjects.pop();\n if (obj === undefined) {\n continue;\n }\n\n removeGlobalEventListener(obj.eventName, obj.func);\n }\n }\n}\n","import type {AnalyticsConfig, CollectorConfig} from '../types/AnalyticsConfig';\nimport {extractCustomDataFieldsOnly} from '../types/CustomDataValues';\nimport type {Sample} from '../types/Sample';\nimport type {SourceMetadata} from '../types/SourceMetadata';\n\nimport {getGlobalLocationHostname} from './globalScopeUtils';\nimport {logger} from './Logger';\nimport {isBlank, isValidString} from './stringUtils';\nimport * as Utils from './Utils';\nimport {isFunction, isNotNullish, isNullish} from './Utils';\n\n/**\n * Sanitize {@link AnalyticsConfig} to not be null/undefined\n *\n * Why we return the same config (same reference) passed to function as an argument?\n * Because in the past, we made a mistake and forget to prevent changing `AnalyticsConfig` vie kept reference\n * from outside. Now our customers are using this bug/feature, and we need to keep it for backward compatibility.\n * This should be fixed and changed in the future major release as part of `Collector API v3` changes.\n *\n * @returns A new empty config `{}`, if it was `null/undefined`, otherwise the same config (same reference).\n *\n */\nexport function sanitizeAnalyticsConfig(config: AnalyticsConfig | null | undefined): AnalyticsConfig {\n if (isNullish(config)) {\n return {};\n }\n\n if (!Utils.isBoolean(config.isLive)) {\n config.isLive = undefined;\n }\n\n if (isNotNullish(config.config) && isNotNullish(config.config.errorTransformerCallback)) {\n if (!isFunction(config.config!.errorTransformerCallback!.transform)) {\n config.config.errorTransformerCallback = undefined;\n }\n }\n\n return config;\n}\n\n/**\n * Log error with {@link logger}, if the new configuration is missing `title` property, but old configuration had one.\n */\nexport function guardConfigChangeAgainstMissingTitle(oldConfig: AnalyticsConfig, newConfig: AnalyticsConfig) {\n if (isNullish(oldConfig) || isNullish(newConfig)) {\n // handle undefined values even when argument type does not specify them\n // (defensive approach, because of old code from past and step by step refactorings)\n return;\n }\n\n if (oldConfig.title && isBlank(newConfig.title)) {\n logger.error('The new analytics configuration does not contain the field `title`');\n }\n}\n\n/**\n * Log error with {@link logger}, if the new configuration is missing `isLive` property, but old configuration had one.\n */\nexport function guardConfigChangeAgainstMissingIsLive(oldConfig: AnalyticsConfig, newConfig: AnalyticsConfig) {\n if (isNullish(oldConfig) || isNullish(newConfig)) {\n // handle undefined values even when argument type does not specify them\n // (defensive approach, because of old code from past and step by step refactorings)\n return;\n }\n\n if (oldConfig.isLive && isNullish(newConfig.isLive)) {\n logger.error(\n 'The new analytics configuration does not contain the field `isLive`. It will default to `false` which might be unintended? Once stream playback information is available the type will be populated.',\n );\n }\n}\n\n/**\n * Log warning with {@link logger}, if both `customUserId` and `userId` are set in the configuration.\n */\nexport function guardAgainstDuplicatedUserId(config: AnalyticsConfig) {\n if (isNullish(config)) {\n // handle undefined values even when argument type does not specify them\n // (defensive approach, because of old code from past and step by step refactorings)\n return;\n }\n\n if (isNotNullish(config.customUserId) && isNotNullish(config.userId)) {\n logger.warn(\n 'Configuration Warning: \\n' +\n 'CustomUserId and UserId are set in the config \\n' +\n 'Value of UserId will be used in sample \\n' +\n 'Please only use one configuration field to set your userId',\n );\n }\n}\n\nexport function getDeviceInformationFromAnalyticsConfig(\n config: AnalyticsConfig,\n): Sample['deviceInformation'] | undefined {\n if (isNullish(config)) {\n // handle undefined values even when argument type does not specify them\n // (defensive approach, because of old code from past and step by step refactorings)\n return undefined;\n }\n\n const deviceInformation: Sample['deviceInformation'] = {};\n\n if (isValidString(config.deviceType) && !isBlank(config.deviceType)) {\n // we are using `deviceInformation.model` field to pass `config.deviceType`, because of ingress\n // and how deviceInformation processing is implemented there.\n deviceInformation.model = config.deviceType;\n }\n\n if (isValidString(config.deviceClass) && !isBlank(config.deviceClass)) {\n deviceInformation.deviceClass = config.deviceClass;\n }\n\n if (Object.keys(deviceInformation).length === 0) {\n return undefined;\n }\n\n return deviceInformation;\n}\n\n/**\n * Get {@link CollectorConfig} `origin` field (if any), otherwise return sanitized hostname.\n */\nexport function getDomainFromAnalyticsConfig(config: AnalyticsConfig): string {\n const hostname = getGlobalLocationHostname();\n const fallbackDomain = hostname ? Utils.removeTrailingSlash(hostname) : '';\n return config?.config?.origin ?? fallbackDomain;\n}\n\nfunction removeSourceRelatedFields(config: AnalyticsConfig): AnalyticsConfig {\n const sourceSpecificProperties = ['cdnProvider', 'videoId', 'title', 'isLive', 'experimentName'];\n const customDataFieldsRegex = /customData\\d{1,3}$/g;\n\n for (const key in config) {\n if (isNotNullish(key.match(customDataFieldsRegex)) || sourceSpecificProperties.includes(key)) {\n delete config[key];\n }\n }\n\n return config;\n}\n\nfunction mergeCollectorConfig(\n oldCollectorConfig: CollectorConfig | undefined,\n newCollectorConfig: CollectorConfig | undefined,\n): CollectorConfig {\n if (isNotNullish(newCollectorConfig)) {\n // merging new config should enable the collector by default (unless explicitly disabled in the new config)\n return {...oldCollectorConfig, enabled: true, ...newCollectorConfig};\n }\n return oldCollectorConfig ?? {};\n}\n\nexport function mergeAnalyticsConfig(oldConfig: AnalyticsConfig, newConfig: AnalyticsConfig): AnalyticsConfig {\n const oldConfigWithoutSourceRelatedFields = removeSourceRelatedFields(oldConfig);\n const mergedCollectorConfig = mergeCollectorConfig(oldConfig.config, newConfig.config);\n\n return {\n ...oldConfigWithoutSourceRelatedFields,\n ...newConfig,\n config: mergedCollectorConfig,\n };\n}\n\nexport function applySourceMetadataToAnalyticsConfig(\n config: AnalyticsConfig,\n sourceMetadata: SourceMetadata,\n): AnalyticsConfig {\n let newConfig: AnalyticsConfig = {...config}; // create a new config object to avoid mutating the original one\n\n if (isNotNullish(sourceMetadata.title)) {\n newConfig.title = sourceMetadata.title;\n }\n\n if (isNotNullish(sourceMetadata.videoId)) {\n newConfig.videoId = sourceMetadata.videoId;\n }\n\n if (isNotNullish(sourceMetadata.cdnProvider)) {\n newConfig.cdnProvider = sourceMetadata.cdnProvider;\n }\n\n if (isNotNullish(sourceMetadata.isLive)) {\n newConfig.isLive = sourceMetadata.isLive;\n }\n\n if (isNotNullish(sourceMetadata.customData)) {\n // same style how to set custom data fields like we do in Analytics module\n newConfig = {\n ...newConfig,\n ...extractCustomDataFieldsOnly(sourceMetadata.customData),\n };\n }\n\n return newConfig;\n}\n","import type {AnalyticsConfig} from '../types/AnalyticsConfig';\n\nimport {getDomainFromAnalyticsConfig} from './analyticsConfigUtils';\nimport {logger} from './Logger';\nimport {isBlank} from './stringUtils';\n\n/**\n * Checks if the environment and config is set up correctly to allow proper collector initialization\n * @param config The analytics config to check\n * @returns true if setup is correct and full initialization possible\n */\nexport function areCollectorRequirementsValid(config: AnalyticsConfig): boolean {\n const errorMessages: string[] = [];\n\n // domain available - needed for license calls (authorization)\n const isDomainMissing = isBlank(getDomainFromAnalyticsConfig(config));\n if (isDomainMissing) {\n errorMessages.push(\n 'no `domain` value found (neither from `window.location` object nor provided by `AnalyticsConfig.config.origin`). Without this value, we cannot verify the origin of your analytics data. Please provide the registered domain via the config during collector creation.',\n );\n }\n\n if (errorMessages.length > 0) {\n const fullErrorMessage = 'Collector setup failed:' + errorMessages.join(' -- ');\n logger.errorMessageToUser(fullErrorMessage);\n }\n\n return !isDomainMissing;\n}\n","/**\n * documentUtils provides standalone functions for accessing browser document APIs.\n * This improves testability by allowing easy mocking of document-dependent functionality.\n */\n\nimport {logger} from './Logger';\nimport {isValidString} from './stringUtils';\nimport {isFunction, isNullish} from './Utils';\n\n/**\n * Get a property from document with vendor prefix support\n * Tries the standard property name first, then with webkit/moz/ms/o prefixes\n */\nexport const getDocumentPropertyWithPrefix = (prop: string): string | undefined => {\n if (isNullish(document)) {\n return undefined;\n }\n\n if (prop in document) {\n return prop;\n }\n\n const prefixes = ['webkit', 'moz', 'ms', 'o'];\n const pascalCase = prop.charAt(0).toUpperCase() + prop.slice(1);\n for (const prefix of prefixes) {\n const prefixedProp = prefix + pascalCase;\n if (prefixedProp in document) {\n return prefixedProp;\n }\n }\n\n return undefined;\n};\n\n/**\n * Check if the document is currently hidden (page visibility API)\n */\nexport const isDocumentHidden = (): boolean => {\n const hiddenProp = getDocumentPropertyWithPrefix('hidden');\n if (!isValidString(hiddenProp)) {\n return false;\n }\n\n return document[hiddenProp] === true;\n};\n\n/**\n * Check if a video element is currently in fullscreen mode\n */\nexport const isVideoInFullscreen = (): boolean => {\n const fullscreenProp = getDocumentPropertyWithPrefix('fullscreenElement');\n if (!isValidString(fullscreenProp)) {\n return false;\n }\n\n return document[fullscreenProp]?.nodeName === 'VIDEO';\n};\n\n/**\n * Add event listener to document\n *\n * Use this for document-level events that relate to the DOM structure and document state.\n * Some events ONLY fire on document (not on window):\n * - visibilitychange (& vendor-prefixed variants): tab/page visibility state\n * - fullscreenchange/fullscreenerror: fullscreen mode changes\n * - DOMContentLoaded: DOM parsed and ready (fires before window 'load')\n * - readystatechange: document.readyState changes\n *\n * Important: This function cannot be replaced with window.addEventListener because\n * the above events are document-specific and will not fire on window.\n *\n * We use vendor-prefixed events (webkitvisibilitychange, mozvisibilitychange, etc.)\n * for cross-browser compatibility, especially on older browsers and Smart TVs.\n */\nexport const addDocumentEventListener = (\n event: string,\n handler: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n): void => {\n if (isNullish(document) || !isFunction(document.addEventListener) || isNullish(handler)) {\n return;\n }\n\n // any-wrap needed to not confirm to type checks\n // we use vendor-prefixed events that are not part of the interface\n (document.addEventListener as any)(event, handler, options);\n};\n\n/**\n * Remove event listener from document\n *\n * @see addDocumentEventListener for details on when to use document vs window event listeners\n */\nexport const removeDocumentEventListener = (\n event: string,\n handler: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n): void => {\n if (isNullish(document) || !isFunction(document.removeEventListener) || isNullish(handler)) {\n return;\n }\n\n // any-wrap needed to not confirm to type checks\n // we use vendor-prefixed events that are not part of the interface\n (document.removeEventListener as any)(event, handler, options);\n};\n\n/**\n * Get a cookie value by name\n * @see https://www.w3schools.com/js/js_cookies.asp\n */\nexport const getCookie = (name: string): string | undefined => {\n if (isNullish(document)) {\n return undefined;\n }\n\n let allCookies: string[];\n try {\n allCookies = document.cookie.split(';');\n } catch (_error) {\n logger.log('failed to access cookie objects on document', _error);\n return undefined;\n }\n\n const cookieName = name + '=';\n for (const c of allCookies) {\n let cookie = c;\n while (cookie.charAt(0) === ' ') {\n cookie = cookie.substring(1); // trim spaces (if any) between ';' and next attribute\n }\n if (cookie.indexOf(cookieName) === 0) {\n return cookie.substring(cookieName.length, cookie.length);\n }\n }\n return '';\n};\n\n/**\n * Set a cookie with optional attributes\n */\nexport const setCookie = (\n name: string,\n value: string,\n attributes?: {domain?: string; expires?: string; maxAge?: number},\n): void => {\n if (isNullish(document)) {\n return;\n }\n\n let newCookie = name + '=' + value + '; path=/';\n\n if (attributes?.domain) {\n newCookie += `; domain=${attributes.domain}`;\n }\n\n if (attributes?.expires) {\n newCookie += `; expires=${attributes.expires}`;\n }\n\n if (attributes?.maxAge) {\n newCookie += `; max-age=${attributes.maxAge}`;\n }\n\n try {\n document.cookie = newCookie;\n } catch (_error) {\n logger.log('failed to set cookie object on document', _error);\n return;\n }\n};\n\n/**\n * Delete a cookie by name\n * @see https://www.w3schools.com/js/js_cookies.asp\n */\nexport const deleteCookie = (name: string): void => {\n if (isNullish(document)) {\n return;\n }\n\n try {\n document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;\n } catch (_error) {\n logger.log('failed to delete cookies from document', _error);\n return;\n }\n};\n","function getGlobalThis(): typeof globalThis {\n // eslint-disable-next-line no-restricted-globals\n if (typeof globalThis !== 'undefined') return globalThis;\n // eslint-disable-next-line unicorn/prefer-global-this\n if (typeof window !== 'undefined') return window as any;\n // eslint-disable-next-line unicorn/prefer-global-this\n if (typeof global !== 'undefined') return global as any;\n // eslint-disable-next-line unicorn/prefer-global-this\n if (typeof self !== 'undefined') return self as any;\n throw new Error('Unable to locate global object');\n}\n\n/**\n * Provides a safe reference to the global object APIs across all environments.\n *\n * `globalThis` is a standard built-in JavaScript object that always refers to the global object of the current\n * environment, regardless of whether your code runs in a browser, Node.js, a worker, or a module.\n *\n * But `globalThis` was introduced in ES2020, and older platforms like Tizen 2016 (Chromium ~2015-2016) do not support\n * it. Rather than bundling a full polyfill into the library, this helper resolves the global object at runtime by\n * checking the available global references in order: `globalThis` → `window` → `global` → `self`.\n *\n * This improves:\n * - compatibility with various environments where the `window` global variable may not be available (VegaOS, React Native)\n * - testability by allowing easy mocking of global object functionality.\n */\nexport const globalScope = getGlobalThis();\n","import {globalScope} from './globalScope';\nimport {isNumber} from './numberUtils';\nimport {isValidString} from './stringUtils';\nimport {isFunction, isNullish} from './Utils';\n\n/**\n * Get `globalScope.devicePixelRatio` (defaults to `1` if not available)\n */\nexport const getGlobalDevicePixelRatio = (): number => {\n if (isNullish(globalScope.devicePixelRatio)) {\n return 1;\n }\n return globalScope.devicePixelRatio > 0 ? globalScope.devicePixelRatio : 1;\n};\n\n/**\n * Get `globalScope.screen` dimensions with {@link getGlobalDevicePixelRatio} applied\n */\nexport const getGlobalScreenDimensions = (): {height: number; scale: number; width: number} | undefined => {\n if (isNullish(globalScope.screen)) {\n return undefined;\n }\n\n if (!isNumber(globalScope.screen.width) || !isNumber(globalScope.screen.height)) {\n return undefined;\n }\n\n const scale = getGlobalDevicePixelRatio();\n const width = globalScope.screen.width * scale;\n const height = globalScope.screen.height * scale;\n\n if (!isFinite(width) || !isFinite(height) || width <= 0 || height <= 0) {\n return undefined;\n }\n\n return {width, height, scale};\n};\n\n/**\n * Add global event listener\n *\n * Use this for window-level events that relate to the browser viewport/tab:\n * - resize: viewport size changes\n * - scroll: page scroll (when listening at window level)\n * - load/unload/beforeunload: page lifecycle\n * - focus/blur: window/tab focus state\n * - hashchange/popstate: navigation events\n * - storage: localStorage changes from other tabs\n *\n * Note: Events bubble up from target → document → window, so window receives\n * many events that also fire on document, but not vice versa.\n */\nexport const addGlobalEventListener = (event: string, handler: EventListenerOrEventListenerObject): void => {\n if (isNullish(globalScope.addEventListener) || !isFunction(globalScope.addEventListener) || isNullish(handler)) {\n return;\n }\n // any-wrap needed to not confirm to type checks\n // we use vendor-prefixed events that are not part of the interface\n globalScope.addEventListener(event, handler);\n};\n\n/**\n * Remove global event listener\n *\n * @see addWindowEventListener for details on when to use window vs document event listeners\n */\nexport const removeGlobalEventListener = (event: string, handler: EventListenerOrEventListenerObject): void => {\n if (\n isNullish(globalScope.removeEventListener) ||\n !isFunction(globalScope.removeEventListener) ||\n isNullish(handler)\n ) {\n return;\n }\n\n // any-wrap needed to not confirm to type checks\n // we use vendor-prefixed events that are not part of the interface\n globalScope.removeEventListener(event, handler);\n};\n\n/**\n * Get `globalScope.location.hostname`\n */\nexport const getGlobalLocationHostname = (): string | undefined => {\n if (isNullish(globalScope.location)) {\n return undefined;\n }\n\n if (!isValidString(globalScope.location.hostname)) {\n return undefined;\n }\n\n return globalScope.location.hostname;\n};\n\n/**\n * Get `globalScope.location.pathname`\n */\nexport const getGlobalLocationPathname = (): string | undefined => {\n if (isNullish(globalScope.location)) {\n return undefined;\n }\n\n if (!isValidString(globalScope.location.pathname)) {\n return undefined;\n }\n\n return globalScope.location.pathname;\n};\n\n/**\n * Get `globalScope.performance.now()` or `undefined` if not available\n *\n * Note: `performance.now()` is preferred over `Date.now()` for measuring time intervals because it provides higher\n * precision and is not affected by changes to the system clock.\n */\nexport const getGlobalPerformanceNow = (): DOMHighResTimeStamp | undefined => {\n if (isNullish(globalScope.performance?.now) || !isFunction(globalScope.performance.now)) {\n return undefined;\n }\n\n // performance.now() returns a DOMHighResTimeStamp, which is a number representing milliseconds with microsecond precision\n return globalScope.performance.now();\n};\n\n/**\n * Get from `global object` the WebOS-specific API objects (for WebOS TV support)\n */\nexport const getGlobalWebOSApi = (): {PalmSystem?: any; webOSSystem?: any} => {\n return {\n webOSSystem: globalScope.webOSSystem,\n PalmSystem: globalScope.PalmSystem,\n };\n};\n\n/**\n * Check if WebOS API is available (for WebOS TV support)\n */\nexport const hasGlobalWebOSApi = (): boolean => {\n const {webOSSystem, PalmSystem} = getGlobalWebOSApi();\n return !isNullish(webOSSystem) || !isNullish(PalmSystem);\n};\n\n/**\n * Get `globalScope.navigator.language` (with fallback to `globalScope.navigator.userLanguage` for IE)\n */\nexport const getGlobalNavigatorLanguage = (): string | undefined => {\n if (isNullish(globalScope.navigator)) {\n return undefined;\n }\n\n return globalScope.navigator.language || (globalScope.navigator as any).userLanguage;\n};\n\n/**\n * Get `globalScope.navigator.product`\n */\nexport const getGlobalNavigatorProduct = (): string | undefined => {\n if (isNullish(globalScope.navigator)) {\n return undefined;\n }\n\n // navigator.product is deprecated, but it remains the standard way to detect some environments like React Native\n return globalScope.navigator.product;\n};\n\n/**\n * Get `globalScope.navigator.userAgent`\n */\nexport const getGlobalNavigatorUserAgent = (): string | undefined => {\n if (isNullish(globalScope.navigator) || !isValidString(globalScope.navigator.userAgent)) {\n return undefined;\n }\n\n return globalScope.navigator.userAgent;\n};\n\n/**\n * Get `globalScope.videojs.VERSION`\n */\nexport const getGlobalVideojsVersion = (): string | undefined => {\n if (isNullish(globalScope.videojs)) {\n return undefined;\n }\n\n return globalScope.videojs['VERSION'];\n};\n\n/**\n * Get `globalScope.THEOplayer.VERSION`\n */\nexport const getGlobalTheoPlayerVersion = (): string | undefined => {\n if (isNullish(globalScope.THEOplayer)) {\n return undefined;\n }\n\n return globalScope.THEOplayer.version;\n};\n","import {isFunction, isNullish} from './Utils';\n\n/**\n * @returns {value is number} `true` if the given value is {@link isNotNullish} and is type of `number`.\n */\nexport const isNumber = (value: unknown): value is number => !isNullish(value) && typeof value === 'number';\n\n/**\n * Checks if a value is a finite number (not NaN, not Infinity, and not -Infinity).\n *\n * This function should be used instead of directly calling `Number.isFinite` or the global `isFinite`\n * because it provides ES5 compatibility and proper type checking.\n *\n * **Why not use `Number.isFinite` directly?**\n * `Number.isFinite` is an ES6 method and does not exist in ES5 environments. Calling it directly\n * would throw a `TypeError` at runtime in older environments.\n *\n * **Key difference between `Number.isFinite` and global `isFinite`:**\n * - `Number.isFinite(value)` does NOT coerce the value — it returns `true` only if the value is\n * already a number and is finite. For example, `Number.isFinite(\"123\")` returns `false`.\n * - Global `isFinite(value)` DOES coerce the value to a number before checking. For example,\n * `isFinite(\"123\")` returns `true` because `\"123\"` is coerced to `123`.\n *\n * This function avoids the coercion risk by first checking the type with `isNumber`, making both\n * implementations behave consistently regardless of the environment.\n *\n * @param value - The value to check\n * @returns `true` if the value is a finite number, `false` otherwise (including NaN, Infinity, -Infinity, null, undefined, or non-numeric types)\n *\n * @example\n * isFiniteNumber(123) // true\n * isFiniteNumber(0) // true\n * isFiniteNumber(-456.78) // true\n * isFiniteNumber(NaN) // false\n * isFiniteNumber(Infinity) // false\n * isFiniteNumber(-Infinity) // false\n * isFiniteNumber(\"123\") // false (string, not coerced)\n * isFiniteNumber(null) // false\n * isFiniteNumber(undefined) // false\n */\nexport const isFiniteNumber = (value: unknown): value is number => {\n if (!isNumber(value)) {\n return false;\n }\n\n // our target is ES5, so we can't use Number.isFinite without checking for it\n if (isFunction(Number.isFinite)) {\n return Number.isFinite(value);\n }\n\n // Fallback implementation for environments that do not support Number.isFinite\n return isFinite(value);\n};\n\n/**\n * Converts a string to an integer using native `parseInt` and returns `undefined` if the result is not a finite number\n */\nexport const parseIntOrUndefined = (value: string): number | undefined => {\n const result = parseInt(value, 10);\n return isFiniteNumber(result) ? result : undefined;\n};\n","/** Polyfill for ES2017 'Object.values' */\nexport const objectValues = (obj: any) => {\n return Object.keys(obj).map(function (key) {\n return obj[key];\n });\n};\n","import type {InternalAdapterAPI} from '../adapters/internal/InternalAdapterAPI';\nimport type {Analytics} from '../core/Analytics';\n\nimport {logger} from './Logger';\nimport {isNullish} from './Utils';\n\nexport const BITMOVIN_ANALYTICS_AUGMENTED_MARKER = '__bitmovinAnalyticsHasBeenSetup';\n\n/**\n * Checks if analytics has already been initialized on this player instance,\n * aka. if {@link BITMOVIN_ANALYTICS_AUGMENTED_MARKER} is present on the player instance.\n *\n * @param player\n */\nexport function hasPlayerAlreadyBeenAugmented(player: any): boolean {\n return player[BITMOVIN_ANALYTICS_AUGMENTED_MARKER] === true;\n}\n\n/**\n * Marks the player instance as already instrumented by analytics,\n * aka. sets {@link BITMOVIN_ANALYTICS_AUGMENTED_MARKER} on the player instance.\n */\nexport function markPlayerInstanceAsAugmented(player: any) {\n player[BITMOVIN_ANALYTICS_AUGMENTED_MARKER] = true;\n}\n\n/**\n * In context of player augmentation, if player was already augmented, adapter properties\n * {@link Analytics} or {@link InternalAdapterAPI} will stay `undefined`, this type guard\n * is utility to help us check if the instance is defined.\n */\nexport function isDefined<T extends Analytics | InternalAdapterAPI>(instance: T | null | undefined): instance is T {\n if (isNullish(instance)) {\n logger.log(\"Bitmovin Analytics: Adapter hasn't been initialized yet\");\n return false;\n }\n\n return true;\n}\n","import {SSAI_RELATED_SAMPLE_MARKER} from '../core/ssai/ssaiUtils';\nimport type {Sample} from '../types/Sample';\n\nimport {getGlobalLocationPathname} from './globalScopeUtils';\nimport {isValidString} from './stringUtils';\nimport {removeTrailingSlash} from './Utils';\n\n/**\n * Clear all \"state\" values from the sample (all values that describe \"playing sample\", \"startup sample\" ...).\n */\nexport function clearSampleStateValues(sample: Sample): void {\n sample.ad = 0;\n sample.adId = undefined;\n sample.adIndex = undefined;\n sample.adPosition = undefined;\n sample.adSystem = undefined;\n sample.autoplay = undefined;\n sample.buffered = 0;\n sample.castTech = undefined;\n sample.completed = undefined;\n sample.drmLoadTime = undefined;\n sample.droppedFrames = 0;\n sample.duration = 0;\n sample.errorCode = undefined;\n sample.errorData = undefined;\n sample.errorMessage = undefined;\n sample.errorSegments = undefined;\n sample.errorSeverity = undefined;\n sample.isProgramChange = undefined;\n sample.pageLoadTime = 0;\n sample.paused = 0;\n sample.played = 0;\n sample.playerStartupTime = 0;\n sample.seeked = 0;\n sample.startupTime = 0;\n sample.state = undefined;\n sample.videoStartFailed = undefined;\n sample.videoStartFailedReason = undefined;\n sample.videoStartupTime = 0;\n\n sample[SSAI_RELATED_SAMPLE_MARKER] = undefined;\n}\n\nexport function getDefaultSamplePath(): string | undefined {\n const pathname = getGlobalLocationPathname();\n return isValidString(pathname) ? removeTrailingSlash(pathname) : undefined;\n}\n","import {isFunction, isNotNullish, isNullish} from './Utils';\n\nexport const isValidString = (s: unknown): s is string => isNotNullish(s) && typeof s === 'string';\n\nexport const isEmpty = (s: string | null | undefined): boolean => isNullish(s) || s.length === 0;\n\nexport const isBlank = (s: string | null | undefined): boolean => isEmpty(s) || isEmpty(s?.trim());\n\nexport const endsWith = (s: string, suffix: string): boolean => {\n if (!isValidString(s) || !isValidString(suffix)) {\n return false;\n }\n\n // our target is ES5, so we can't use String.prototype.endsWith without checking for it\n if (isFunction(String.prototype.endsWith)) {\n return s.endsWith(suffix);\n }\n\n // Fallback implementation for environments that do not support String.prototype.endsWith\n return s.substring(s.length - suffix.length) === suffix;\n};\n\nexport const startsWith = (s: string, prefix: string): boolean => {\n if (!isValidString(s) || !isValidString(prefix)) {\n return false;\n }\n\n // our target is ES5, so we can't use String.prototype.startsWith without checking for it\n if (isFunction(String.prototype.startsWith)) {\n return s.startsWith(prefix);\n }\n\n // Fallback implementation for environments that do not support String.prototype.startsWith\n return s.substring(0, prefix.length) === prefix;\n};\n","export const generateUUID = (): string => {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n};\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","import {AmazonIVSAdapter} from './adapters/amazonIVS/AmazonIVSAdapter';\nimport {Bitmovin8Adapter} from './adapters/bitmovin8/Bitmovin8Adapter';\nimport {PlayerModule} from './adapters/bitmovin8/playerModule';\nimport {BitmovinPwxAnalyticsPackage} from './adapters/bitmovinPwx/BitmovinPwxAnalyticsPackage';\nimport {CAFv3Adapter} from './adapters/cafv3/CAFv3Adapter';\nimport {DashjsAdapter} from './adapters/dashjs/DashjsAdapter';\nimport {HlsAdapter} from './adapters/hlsjs/HlsAdapter';\nimport {HTMLVideoElementAdapter} from './adapters/html5/HTMLVideoElementAdapter';\nimport {ShakaAdapter} from './adapters/shaka/ShakaAdapter';\nimport {THEOplayerAdapter} from './adapters/theo/THEOplayerAdapter';\nimport {VideojsAdapter} from './adapters/videojs/VideoJsAdapter';\nimport {CdnProvider} from './enums/CDNProvider';\nimport {Player} from './enums/Player';\nimport {VERSION} from './utils/Version';\n\nexport {VERSION as version};\n\nexport type {AnalyticsConfig} from './types/AnalyticsConfig';\n\nexport {Player as Players};\nexport {CdnProvider as CdnProviders};\n\nexport {AmazonIVSAdapter};\nexport {Bitmovin8Adapter};\nexport {CAFv3Adapter};\nexport {DashjsAdapter};\nexport {HTMLVideoElementAdapter};\nexport {HlsAdapter};\nexport {ShakaAdapter};\nexport {THEOplayerAdapter};\nexport {VideojsAdapter};\n\nexport const adapters = {\n AmazonIVSAdapter,\n Bitmovin8Adapter,\n CAFv3Adapter,\n DashjsAdapter,\n HTMLVideoElementAdapter,\n HlsAdapter,\n ShakaAdapter,\n THEOplayerAdapter,\n VideojsAdapter,\n};\n\nexport {BitmovinPwxAnalyticsPackage};\n\nexport {PlayerModule};\n\nexport default {\n PlayerModule: PlayerModule,\n};\n"],"names":["root","factory","exports","module","define","amd","self","StateMachine","VERSION","Result","SUCCEEDED","NOTRANSITION","CANCELLED","PENDING","Error","INVALID_TRANSITION","PENDING_TRANSITION","INVALID_CALLBACK","WILDCARD","ASYNC","create","cfg","target","initial","state","terminal","fsm","events","callbacks","map","transitions","add","e","from","Array","isArray","name","n","length","push","to","event","hasOwnProperty","buildEvent","current","is","indexOf","this","can","transition","undefined","cannot","concat","isFinished","error","args","msg","states","Object","keys","sort","defer","doCallback","func","apply","beforeAnyEvent","afterAnyEvent","leaveAnyState","enterAnyState","changeState","beforeThisEvent","afterThisEvent","leaveThisState","enterThisState","beforeEvent","afterEvent","leaveState","specific","general","enterState","prototype","slice","call","arguments","cancel","leave","config","player","opts","hasPlayerAlreadyBeenAugmented","logger","errorMessageToUser","markPlayerInstanceAsAugmented","sanitizedConfig","sanitizeAnalyticsConfig","areCollectorRequirementsValid","guardAgainstDuplicatedUserId","sourceUrlProvider","SourceUrlProvider","internalAdapter","AmazonIVSInternalAdapter","analytics","Analytics","wrapPlayerLoad","originalLoad","load","m3u8Url","getCurrentImpressionId","isDefined","getUserId","setCustomData","values","setCustomDataOnce","sourceChange","_config","version","AmazonIVSAdapter","getPlayerVersion","getVersion","getPlayerName","Player","AMAZON_IVS","getPlayerTech","getAutoPlay","isAutoplay","playingHeartbeatService","HeartbeatService","currentTime","stateMachine","AmazonIVSStateMachine","stateMachineCallbacks","setListener","playerContext","AmazonIVSPlayerContext","listener","AmazonIVSPlayerEventListener","qualityChangeService","playerStatisticsProvider","getHTMLVideoElement","windowEventListener","WindowEventListener","windowEventTracker","initialize","_analytics","startMonitoring","RELEASE","subscribe","release","getPosition","resetSourceRelatedState","drmPerformanceInfo","reset","getCurrentPlaybackInfo","videoElement","droppedFrames","getDroppedFrames","isLive","getDuration","Infinity","isMuted","playerTech","videoWindowWidth","clientWidth","videoWindowHeight","clientHeight","videoPlaybackHeight","videoHeight","videoPlaybackWidth","videoWidth","videoBitrate","getQuality","bitrate","videoDuration","normalizeVideoDuration","size","isVideoInFullscreen","PlayerSize","Fullscreen","Window","getVideoAndAudioCodecs","getCommonPlaybackInfo","streamFormat","StreamTypes","hls","codecs","split","videoCodec","audioCodec","InternalAdapter","dispatcher","onError","payload","errorEvent","position","code","message","originalError","data","exceptionMessage","exceptionStacktrace","source","eventCallback","Event","ERROR","ErrorService","State","EVENT_DELAY_MS","IDLE","cancelPause","PAUSE_SCHEDULED","PAUSE_CANCELLED","schedulePauseEvent","eventObject","setTimeout","triggerPause","PAUSE","PauseEventDispatcher","pauseDispatcher","ignorePause","onStartupPlaying","onPause","onPlaying","playing","onRebuffering","startBuffering","onQualityChange","qualityChange","onSeek","seek","onSeeked","seeked","START_BUFFERING","PLAYING","shouldAllowVideoQualityChange","setVideoBitrate","VIDEO_CHANGE","type","width","height","codec","SEEK","SEEKED","PlaybackService","StartupState","SETUP","STARTUP_FINISHED","onInitialized","finishSetup","onPlay","startStartup","finishStartup","READY","STARTUP","PLAY","resetValues","setStartupHasFinished","VideoStartupService","videoStartupService","playbackService","errorService","log","onDurationChanged","tryJSONStringify","finishedStartup","onQualityChanged","onTimeUpdate","AmazonIVSPlayerEventHandler","IVS_PLAYER_EVENT","DURATION_CHANGED","INITIALIZED","QUALITY_CHANGED","REBUFFERING","SEEK_COMPLETED","TIME_UPDATE","PLAYBACK_RATE_CHANGED","PLAYBACK_BLOCKED","eventHandler","startMonitoringIVSPlayer","startMonitoringHTMLVideoElement","video","addEventListener","bind","COLLECTOR_EVENTS","observer","trigger","forEach","handler","eventBus","CollectorEventBus","CollectorEvents","onPageUnload","UNLOAD","UNLOADED","adCallbacks","AdCallbacks","isLinearAdActive","ads","getContainer","getAdModuleInfo","getModuleInfo","getCurrentTime","register","on","PlayerEvent","Play","issuer","Paused","AdStarted","onAdStarted","mapBitmovinAd","ad","AdFinished","onAdFinished","AdBreakStarted","onAdBreakStarted","mapBitmovinAdBreak","adBreak","AdBreakFinished","onAdBreakFinished","AdClicked","onAdClicked","clickThroughUrl","AdQuartile","onAdQuartile","quartile","AdSkipped","onAdSkipped","AdError","onAdError","mapBitmovinAdError","getActiveAd","id","AdManifestLoaded","adTagConfig","adConfig","isVmap","tag","adBreakInfo","isNotNullish","manifestDownloadTime","downloadTiming","downloadTime","onAdManifestLoaded","handlePageClose","onBeforeUnload","Bitmovin8AdModule","ssai","adBreakStart","adBreakMetadata","adBreakMetadataWithValidAdPosition","sanitizeBitmovin8AdapterSsaiAdBreakMetadataAdPosition","hasValidSsaiAdBreakMetadataStructure","sanitizedAdBreakMetadata","simplySanitizeSsaiAdBreakMetadata","ssaiService","adStart","adMetadata","hasValidSsaiAdMetadataStructure","sanitizedAdMetadata","simplySanitizeSsaiAdMetadata","setConfigParameters","setAutoDetectedDeviceInformation","adQuartileFinished","adQuartile","adQuartileMetadata","hasValidSsaiAdQuartileStructure","sanitizedSsaiAdQuartileMetadata","sanitizeSsaiAdQuartileMetadata","adBreakEnd","playerConfig","getConfig","playerKey","key","Bitmovin8InternalAdapter","analyticsConfig","trackLoadstartWithAutoplay","Bitmovin8Adapter","ViewMode","speedMeter","segmentTracker","videoCompletionTracker","httpRequestTrackingAdapter","sourceInfoFallbackService","onBeforeUnLoadEvent","BITMOVIN","getPlayerType","getDrmPerformanceInfo","_videoCompletionTracker","Bitmovin8AnalyticsStateMachine","isAdPlaying","warn","lastTrackedCurrentTime","currentAd","_adModule","registerPlayerEventListeners","registerUnloadEventListeners","activate","getPlayerCurrentTime","reportEngagementInteraction","ssaiEngagementInteractionData","sendSsaiEngagementAdSample","reportPlaybackInteraction","timestamp","playerCurrentTime","sendPlayingSample","requestTracking","HttpRequestTracking","ErrorDetailTracking","errorDetailTrackingSettingsProvider","ErrorDetailBackend","collectorConfig","errorDetailSubscribable","container","info","getViewMode","getStreamType","offsetWidth","offsetHeight","isCasting","audioLanguage","getAudio","lang","subtitleEnabled","getSource","getDroppedVideoFrames","applySubtitleProperties","applyPlaybackQualityProperties","applyCastingProperties","applySourceProperties","isNullish","applyStreamFormat","getSegmentInfo","getSegments","getDownloadSpeedInfo","getInfo","resetDownloadSpeedInfoMeasures","LOADSTART_AUTOPLAY","SourceUnloaded","_event","SOURCE_UNLOADED","SourceLoaded","setVideoDuration","setStreamFormat","SOURCE_LOADED","CastStarted","START_CAST","CastStopped","END_CAST","Playing","TimeChanged","TIMECHANGED","Seek","allowSeeking","Seeked","StallStarted","StallEnded","END_BUFFERING","AudioPlaybackQualityChanged","eventData","audioQualityChangedData","sourceQuality","targetQuality","qualityEventInfo","shouldAllowAudioQualityChange","AUDIO_CHANGE","setAudioBitrate","updateSampleQualityInfo","VideoPlaybackQualityChanged","videoQualityChangedData","ViewModeChanged","START_FULLSCREEN","END_FULLSCREEN","START_AD","END_AD","Muted","MUTE","Unmuted","UN_MUTE","legacyData","additionalData","ErrorCode","BITMOVIN_PLAYER_LICENSING_ERROR","SETUP_MISSING_LICENSE_WHITELIST","onLicenseCallFailed","dispatch","sendAdEngagementErrorSample","severity","PlaybackFinished","END","DownloadFinished","downloadType","drmType","replace","drmLoadTime","AudioChanged","AUDIOTRACK_CHANGED","SubtitleEnabled","SUBTITLE_CHANGE","SubtitleDisabled","LicenseValidated","onLicenseKeyReceived","licenseKey","handleCollectorUnload","Destroy","videoTitle","title","mpdUrl","dash","progSourceInfo","getSourceInfoFromBitmovinSourceConfig","progressive","progUrl","progBitrate","enabledSubtitle","subtitles","list","find","s","enabled","subtitleLanguage","videoQuality","getPlaybackVideoData","audioQuality","getPlaybackAudioData","audioBitrate","isAirplayActive","castTech","CastTech","AirPlay","remoteControlConfig","getPlayerConfig","remotecontrol","GoogleCast","WebSocket","seekEvent","Math","abs","seekTarget","AnalyticsSettings","ANALYTICS_MIN_SEEK_DIFFERENCE_THRESHOLD","SpeedMeterAdapter","DownloadSpeedMeter","getDownloadSpeedMeter","SegmentTrackerAdapter","SegmentTracker","getSegmentTracker","HttpRequestTrackingAdapter","SourceInfoFallbackService","activeAdId","adErrorPayload","errorData","adInfo","isLinear","linearAd","duration","skippable","skippableAfter","mediaUrl","mediaFileUrl","vastData","mimeType","adSystem","advertiserName","advertiser","apiFramework","creativeAdId","creative","adId","creativeId","universalAdIdRegistry","universalAdId","idRegistry","universalAdIdValue","value","adDescription","adTitle","wrapperAdsCount","wrapperAdIds","surveyUrl","survey","uri","minSuggestedDuration","replaceContentDuration","fallbackIndex","getFallbackIndex","scheduleTime","resolveEffectiveAdTag","tagUrl","tagType","persistent","preloadOffset","directTag","url","fallbackTags","fallbackTag","rawFallbackIndex","currentFallbackIndex","anything","maybeSsaiAdBreakMetadata","adPosition","eventDispatcher","EventDispatcher","playerExports","onDownloadFinished","callback","unsubscribe","httpRequest","calculateTimeWithUndefined","httpStatus","success","getCurrentTimestamp","timeToFirstByte","mapHttpRequestType","httpRequestTypeValue","objectValues","HttpRequestType","includes","UNKNOWN","handleSegmentPlaybackEvent","removeSegment","handleOnDownloadFinishEvent","SegmentPlayback","segment","Utils","getURLResourceName","addSegment","meter","addMeasurement","Date","PlayerModule","hooks","setup","isConfigMissing","isAnalyticsDisabled","Promise","resolve","analyticsModuleInstance","analyticsBitmovin8Adapter","playback","autoplay","_e","context","BitmovinPwxInternalAdapter","dispose","BitmovinPwxAdapter","onAdd","dependencies","BitmovinPwxAnalyticsPackage","_","baseContext","registry","get","CoreExportNames","CoreEffects","EventListenerEffectFactory","StateEffectFactory","using","BundleExportNames","Logger","SourceExportNames","SourceState","PlayerConfig","adapter","abortSignal","removeEventListener","Constants","CoreStateAtoms","SourcesApiExportNames","SourceEventBus","PlaybackApiEventsPackageExportNames","PlaybackEvent","_name","enabledDebugging","debuggingStates","createStateMachine","JSM_INITIAL_EVENT","customStateMachineErrorCallback","stayIn","VIDEOSTART_FAILED","getAllStatesBut","stopHeartbeat","onleavestate","eventTimestamp","logStateMachineTransition","addStatesToLog","stateDuration","onEnterStateTimestamp","isStartup","maybeSetOrClearVideoStartTimeouts","startup","toLowerCase","lowerCaseFrom","String","unload","clearVideoStartTimeout","defaultStateMachineCallbackFn","isFunction","logMissingCallbackWarning","startHeartbeat","onenterstate","_eventData","now","isNumber","starttime","_from","_to","_eventTimestamp","EventDebugging","getStates","setEnabledDebugging","setVideoStartTimeout","AnalyticsStateMachine","BitmovinPwxAnalyticsStateMachine","playhead","sourceConfig","resources","filter","v","videoRect","element","getBoundingClientRect","round","muted","stream","BITMOVIN_PWX","Version","registerEventListeners","sourceEventBus","playbackAtom","Ready","VideoAttached","Ended","abortListener","abortSignalReason","reason","CreateSourceStateAtom","CreateSourceReference","SourceReferences","SourceApiManager","VideoElementUtils","castReceiverContext","CAFv3InternalAdapter","CAFv3Adapter","activeTextTracks","cast","framework","CHROMECAST_SHAKA","playerManager","getQueueManager","getCurrentItem","getPlayerManager","getCurrentTimeSec","CAFv3AnalyticsStateMachine","registerCastFrameworkEventListeners","registerWindowUnloadEventListeners","stats","getStats","subtitleLanguages","t","language","detectCAFv3PlaybackInfoStreamTypeFields","activeTract","getAudioTracksManager","getActiveTrack","audioTrackInfo","_error","detectCAFv3PlaybackInfoAudioFields","detectIsLive","getMediaInformation","join","CastFrameworkEvent","LOADED_METADATA","PLAYER_LOAD_COMPLETE","textTracksManager","getTextTracksManager","getActiveTracks","currentMediaTime","detailedErrorCode","SEEKING","BUFFERING","isBuffering","REQUEST_LOAD","handleWindowUnloadEvent","streamType","getLiveSeekableRange","contentUrl","isBlank","contentId","getStreamTypesFromURL","buildPlaybackInfoStreamTypeFields","ALL","STALLED","DashjsInternalAdapter","DashjsAdapter","mediaPlayer","DASHJS","videoEl","getVideoElement","setMediaElement","registerMediaElementEventsForDashJS","mediaElement","listenToMediaElementEvent","needsFirstPlayIntent","html5PlaybackInfo","playbackInfo","codecInfo","getCodecInfo","applyAndStoreCodecInfo","getMIMEType","MIMETypes","DASH","getStreamURL","toString","getCurrentQualityLevelInfo","getQualityLevelInfo","HTML5InternalAdapter","hasApiV4ToGetQualityLevelInfo","currentVideoQuality","getBitrateInfoListFor","getQualityFor","currentVideoRepresentation","getCurrentRepresentationForType","bitrateInKbit","Converter","kiloBitsToBits","codecsRegExp","RegExp","rawVideoCodec","getCurrentTrackFor","isValidString","matches","exec","rawAudioCodec","HlsInternalAdapter","HlsAdapter","HLSJS","constructor","currentLevelObj","getHlsCurrentLevel","details","live","onDestroying","HlsSpeedMeterAdapter","registerHlsEvents","selectedSubtitle","getSelectedSubtitleLanguage","getSelectedAudioLanguage","getHlsCodecInfo","HLS","HLS_PLAYER_EVENT","MEDIA_ATTACHING","onMediaAttaching","MEDIA_DETACHING","onMediaDetaching","MANIFEST_LOADING","onManifestLoading","AUDIO_TRACK_SWITCHED","onAudioTrackSwitched","SUBTITLE_TRACK_SWITCH","onSubtitleLanguageSwitched","DESTROYING","onHlsError","media","registerMediaElement","onMaybeReady","unregisterMediaElement","errorName","fatal","errorMessage","getErrorCodeFromHlsErrorType","_data","audioTrack","audioTracks","subtitleDisplay","isSubtitleDisplayed","subtitleTrack","subtitleTracks","subtitleTrackController","getSelectedSubtitleFromMediaElement","levels","currentLevel","PlaylistLevelType","Events","FRAG_LOADED","_eventName","handleFragmentLoadedEvent","frag","networkDetails","status","loadingDuration","loading","end","start","first","measurement","total","isPaused","isSeeking","previousMediaTimeInSeconds","previousMutedValue","HTML5","isNaN","HTML5AnalyticsStateMachine","mediaElementEventHandlers","mediaElementOriginalLoadFn","bufferingTimeout","previousClientTime","needsReadyEvent","registerWindowEvents","qualityInfo","clearTimeout","streamUrl","getMIMETypeFromFileExtension","mimetype","getStreamTypeFromMIMEType","src","readyState","checkQualityLevelAttributes","onPaused","registerMediaElementErrorEvent","volume","isAudioMuted","checkSeeking","checkPlayheadProgress","onBuffering","boundHandler","item","originalLoadFunc","onPageClose","silent","qualityLevelInfo","textTracks","attr","mode","paused","ended","BUFFERING_TIMECHANGED_TIMEOUT_IN_MS","currentMediaTimeInSeconds","playbackPositionDeltaInSeconds","clientTimeProgressInSeconds","playbackRate","msgTime","toISOString","substring","prefix","logMsg","sourceMetadata","HTMLVideoElementInternalAdapter","setAudioLanguage","sessionData","sanitizeSessionMetadataAudioLanguage","setSubtitleEnabled","sanitizeSessionMetadataSubtitleEnabled","setSubtitleLanguage","sanitizeSessionMetadataSubtitleLanguage","HTMLVideoElementAdapter","currentSrc","previousTotalDroppedFrames","getVideoPlaybackQuality","droppedVideoFrames","currentDroppedFrames","SsaiService","defaultStateMachineCallbacks","WindowEventTracker","resetIntervals","callEvent","dimensions","getGlobalScreenDimensions","screenHeight","screenWidth","segmentsDownloadCount","segmentsDownloadSize","segmentsDownloadTime","avgDownloadSpeed","minDownloadSpeed","maxDownloadSpeed","avgTimeToFirstByte","previousState","currentState","customDataValues","customdatachange","CUSTOM_DATA_CHANGE","MANUAL_SOURCE_CHANGE","programChange","isSsaiActive","isInActiveState","_ad","_adBreak","ShakaInternalAdapter","playerPrototype","getPrototypeOf","loadPropertyDescriptor","getOwnPropertyDescriptor","writable","set","thatInternalAdapter","reject","then","result","catch","category","ShakaAdapter","getMediaElement","SHAKA","ShakaPlayerEvent","detail","stack","ONSTATECHANGE","getShakaCodecInfo","getShakaStreamFormat","getAssetUri","activeVideoTrack","getVariantTracks","track","active","videoId","videoBandwidth","bandwidth","activeTrack","manifestType","getManifestType","getLoadMode","prog","UNLOADING","STATECHANGED","isDrmLicenseType","extractDrmType","DRM_LICENSE_WIDEVINE","DRM_LICENSE_FAIRPLAY","DRM_LICENSE_PLAYREADY","DRM_LICENSE_CLEARKEY","requestType","match","DrmPerformanceService","THEOplayerInternalAdapter","hasValidSourceMetadataStructure","sanitizedSourceMetadata","sanitizeSourceMetadata","THEOplayerAdapter","delayedEventDispatcher","DelayedEventDispatcher","drmPerformanceService","videoTrackListeners","Map","audioTrackListeners","networkInterceptor","THEOplayerNetworkInterceptor","speedMeasurement","createSpeedMeasurementFromEvent","THEOplayerAnalyticsStateMachine","THEOplayerAdModule","httpRequestTracking","errorDetailTracking","windowTHEOplayerVersion","getGlobalTheoPlayerVersion","THEOPLAYER","videoTracks","activeAudioTrack","activeTextTrack","airplay","chromecast","detectPlaybackInfoStreamTypeFieldsFromSource","currentSource","activeQuality","casting","isFinite","presentation","currentMode","clear","dispatchEvent","handleVideoQualityChanged","qualityEvent","quality","handleAudioQualityChanged","mediaTrack","delete","Number","maybeMessage","cause","maybeStacktrace","stacktrace","errorAsData","errorObject","MEDIA_VIDEO","MEDIA_AUDIO","STALE_REQUEST_TIMEOUT_MS","pendingRequests","onRequest","request","performanceNow","getGlobalPerformanceNow","cleanupStaleRequests","pendingRequest","startTime","subType","mediaType","existing","onResponse","response","pendingArray","shift","endTime","extractResponseSize","network","addRequestInterceptor","addResponseInterceptor","filtered","pending","contentLength","headers","parsed","parseIntOrUndefined","body","isArrayBuffer","byteLength","requestSubType","KEY_HLS_AES","DRM_CERTIFICATE_FAIRPLAY","endsWith","MANIFEST_DASH","MANIFEST_HLS_MASTER","MEDIA_SUBTITLES","clickThrough","skipOffset","googleAd","integration","contentType","universalAdIds","adIdRegistry","adIdValue","description","timeOffset","isFiniteNumber","deltaTimeOffsetVideoDuration","mapTheoAdBreak","mapTheoAd","errorPayload","isAdErrorEvent","errorCode","adManifestPayload","sourceAds","currentAdBreak","CALLBACK_SCHEDULER_TIMEOUT_DELAY_MS","timeout","schedule","isScheduled","execute","CallbackScheduler","scenarios","scheduler","delayEvent","inState","cancelOnEvent","AD_PLAYBACK","activeScenario","matchingScenario","findMatchingScenario","scenario","VideojsInternalAdapter","VideojsAdapter","_subtitleInfo","previousTime","playerInstanceVersion","windowVideoJsVersion","getGlobalVideojsVersion","VIDEOJS","VideojsAnalyticsStateMachine","selectedAudioLanguage","getSelectedAudioTrackLanguage","tech","IWillNotUseThisInPlugins","detectVideoJsPlaybackInfoStreamTypeFields","isFullscreen","currentVideoJsQualityLevel","that","ready","getSubtitleInfo","seeking","newSubtitleInfo","hasInfoChanged","isDifferentSubtitleInfo","newSelectedAudioLanguage","vhs","mediaAttributes","getMediaAttributes","sourceHandler","playlists","selectedPlaylist","attributes","BANDWIDTH","RESOLUTION","CODECS","CodecHelper","isVideoCodec","isAudioCodec","videoJsPlayer","streamMimeType","currentType","REBUFFERING_HEARTBEAT_INTERVALS","videoStartupTimeoutMs","Settings","ANALYTICS_VIDEOSTART_TIMEOUT","rebufferTimeoutMs","ANALYTICS_REBUFFER_TIMEOUT","currentRebufferingIntervalIndex","stateMachineEventMethod","clearRebufferingTimeoutHandle","clearRebufferingHeartbeatHandle","startRebufferingHeartbeatInterval","resetRebufferingHelpers","startRebufferingTimeoutHandle","rebufferingHeartbeatIntervalHandle","setInterval","getTime","heartbeat","buffered","min","clearInterval","rebufferingTimeoutHandle","BUFFERING_TIMEOUT_REACHED","videoStartTimeout","VIDEOSTART_TIMEOUT","onHeartbeat","triggeredBySsai","triggeredByProgramChange","setVideoTimeEndFromEvent","played","isProgramChange","SSAI_RELATED_SAMPLE_MARKER","resetCurrentStateStart","stateEnterTimestamp","setVideoTimeStartFromEvent","programChangeTimestamp","updateSourceMetadata","whileIn","passOver","SEEKING_IN_PAUSE","SOURCE_CHANGING","CUSTOMDATACHANGE","videoStartFailed","createVideoStartFailedReason","manualSourceChange","getAllStates","i","SETUP_SOURCE_CHANGE","QUALITY_CHANGE","FINISH_QUALITY_CHANGE","PAUSED_SEEKING","SUBTITLE_CHANGING","AUDIOTRACK_CHANGING","AD","MUTING_READY","MUTING_PLAY","MUTING_PAUSE","CASTING","pause","mute","unMute","qualitychange","startCasting","onafterevent","FINISH_MUTING","AD_PLAYBACK_IN_STARTUP","VideoStartFailedReason","PAGE_CLOSED","rebuffering","seekTimestamp","seekedTimestamp","PLAY_SEEKING","END_PLAY_SEEKING","AUDIOTRACK_CHANGED_PLAYING","SUBTITLE_CHANGED_PLAYING","seekDuration","FINISH_AUDIOTRACK_CHANGING","FINISH_SUBTITLE_CHANGING","getStateHandler","CustomEvents","sourceLoadedDuringAutoplayStartup","INITIAL_SOURCE_CHANGE","AD_STARTUP","STARTUP_AUTOPLAY","PAUSE_BEFORE_SOURCE_LOADED","PAUSE_AFTER_SOURCE_LOADED","AD_READY","AD_PAUSE","AD_PLAYING","seekStartTimestamp","lastTrackedVideoEndObject","noOp","initialSourceChange","excludedStates","stateEnumObj","stateMachineEventDefBuilderFn","runEventCallbacksFor","eventName","_ex","loggerMessage","loggerMessageData","ignoreStates","ignoredState","stateStringEnumObj","padRight","toBoolean","isPlaying","adPodPosition","viewportTracker","ViewportTracker","onIntersectionChanged","clearCurrentTimeInterval","adManifestDownloadTime","activeAdSample","isContainerInViewport","enterViewportTimestamp","timeInViewport","isInViewport","beginPlayingTimestamp","updatePlayingTime","sendAnalyticsRequest","AdBreakSample","activeAdBreakSample","adStartupTimestamp","resetActiveAd","AdSample","adStartupTime","startAd","adSample","completed","completeAd","adDuration","skipped","skipPosition","skipPercentage","calculatePercentage","errorPosition","adBreakSample","transformedError","transformError","errorSeverity","errorPercentage","adClickthroughUrl","clicked","clickPosition","clickPercentage","FIRST_QUARTILE","quartile1","MIDPOINT","midpoint","THIRD_QUARTILE","quartile3","closed","closePosition","closePercentage","createNewAdAnalyticsSample","analyticsSample","moduleInfo","AdAnalyticsSample","analyticsVersion","adModule","adModuleVersion","pageLoadType","getPageLoadType","sample","time","adImpressionId","generateUUID","percentageInViewport","timePlayed","backend","sendAdRequest","started","currentTimeInterval","calculateTime","max","AdAnalytics","TIMEOUT_CURRENT_TIME_INTERVAL","exitPosition","playPercentage","MODULE_NAME","initialAnalyticsConfig","backendFactory","sessionHandler","featureManager","onErrorDetailEventDispatcher","identicalErrorReportingLimiter","hasSentStartupSample","droppedSampleFrames","playerStartupTime","authenticationCallback","authenticationCompleted","featureConfigs","configureFeatures","guardConfigChangeAgainstMissingTitle","guardConfigChangeAgainstMissingIsLive","newConfig","mergeAnalyticsConfig","oldConfig","setState","sendSample","impressionId","userId","changeCustomData","extractCustomDataFieldsOnly","SessionPersistenceHandler","domain","getDomainFromAnalyticsConfig","licenseKeyReceivedUnsubscriber","eventArgs","buildInitialSample","init","setupStateMachineCallbacks","features","registerFeatures","adAnalytics","supportsDeferredLicenseLoading","debug","resetFeatures","createBackend","deviceInformation","getDeviceInformationFromAnalyticsConfig","cdnProvider","customUserId","transferCustomDataFields","experimentName","model","hasGlobalWebOSApi","modelName","getWebOSTVModelName","setDuration","navigationStart","globalScope","performance","timing","pageLoadTime","supportedVideoCodecs","supportedVideoFormats","sanitizeVideoStartupTime","videoStartupTime","startupTime","drmPerformance","applySourceMetadataToAnalyticsConfig","path","getDefaultSamplePath","setCompletionValues","videoStartForClosedState","videoTimeStart","videoTimeEnd","sendUnloadRequest","clearSampleStateValues","setVideoTimeStart","setVideoTimeEnd","heartbeatPayload","startResetInterval","increaseCounter","hasExceededQualityChangeThreshold","QUALITY_CHANGE_THRESHOLD_EXCEEDED","audiotrack_changing","videoStartFailedReason","PLAYER_ERROR","TIMEOUT","VIDEO_STARTUP_TIMEOUT_REACHED","shouldReportError","errorSegments","AD_TYPE","CSAI","subtitle_changing","analyticsEventBase","NoOpBackend","stopResetInterval","_duration","_state","setPlaybackInfoFromAdapter","isBoolean","customDataOnceValues","downloadSpeedInfo","manipulate","setQualityInfoOnSample","copySample","sendRequest","ssaiEngagementTrackingEnabled","isSsaiEngagementStartedData","ssaiAdSample","createStartedAdSample","isSsaiEngagementQuartileData","createQuartileAdSample","isSsaiEngagementErrorData","analyticsError","ssaiErrorAdSample","createErrorAdSample","addWatched","completedTotal","getCompletionPercentage","errorTransformerCallback","transform","isErrorSeverity","screenDimensions","getGlobalNavigatorLanguage","platform","userAgent","getGlobalNavigatorUserAgent","BackendFactory","FeatureManager","IdenticalErrorReportingLimiter","licensingRequest","isEnabled","inner","createInnerBackend","decorateWithDebuggingBackend","DebuggingBackend","decorateWithBackendFromConfigIfAvailable","innerBackend","wrapBackend","backendUrl","ANALYTICS_BACKEND_BASE_URL","LicenseCheckingBackend","LicenseCall","sequenceNumberAssigningBackend","SequenceNumberBackend","LongPlaytimeFilteringBackend","underlying","fields","debugFields","printFields","sendRequestSynchronous","f","table","measures","measure","Measure","threshold","bitsToBytes","speed","m","reduce","ceil","totalTime","avgSpeed","minSpeed","maxSpeed","a","b","totalSpeed","speeds","numMeasurements","bytePerSecondToBitPerSecond","bps","bytesToBits","avg","index","splice","DEFAULT_HEARTBEAT_INTERVAL_MS","heartbeatInterval","clearHeartbeat","_currentErrorCount","_lastErrorCode","_lastErrorSeverity","MAX_IDENTICAL_ERROR_REPORTING","licenseCall","backendBaseUrl","licenseKeyReceived","licenseLazyLoadingTimeoutHandle","unsubscribeFromAdapter","promise","wrapLicenseCheckPromiseWithCallback","performLicenseCheck","licenseCallFailed","licenseLazyLoadingTimeout","QueueBackend","ANALYTICS_LICENSECALL_TIMEOUT","LicensingResult","Denied","Granted","remoteBackend","RemoteBackend","flushTo","err","next","nextBackend","isPlayedAboveThreshold","download","_sample","qualityChangeCountThreshold","ANALYTICS_QUALITY_CHANGE_COUNT_THRESHOLD","qualityChangeCount","previousVideoBitrate","previousAudioBitrate","startupHasFinished","QUALITY_CHANGE_COUNT_THRESHOLD","startupVideoBitrate","startupAudioBitrate","newBitrate","qualityChangeCountResetIntervalId","ANALYTICS_QUALITY_CHANGE_COUNT_RESET_INTERVAL","queue","unloadQueue","syncQueue","adQueue","hasAdModule","analyticsCall","AnalyticsCall","segments","sequenceNumber","updateSampleBeforeSending","isSequenceNumberAboveThreshold","SEQUENCE_NUMBER_LIMIT","COOKIE_NAME_BITMOVIN_ANALYTICS_UUID","COOKIE_DEFAULT_MAX_AGE","cookiesEnabled","deleteCookie","existingUserId","getCookie","cookieDomain","validateCookieDomainValue","cookiesDomain","cookieMaxAge","validateCookieMaxAgeValue","cookiesMaxAge","nowMillis","cookieExpires","toUTCString","setCookie","expires","maxAge","encodeURIComponent","TimespanOverlappingType","watched","overlappingTimespan","mergeWatched","w","time1","k","time2","overlapType","getOverlappingType","Overlapping","mergeAndReplace","getOverlappingTimespan","FirstContainedInSecond","SecondContainedInFirst","None","second","isMomentInTimespan","moment","timespan","firstIndex","secondIndex","newWatchedTimespan","SsaiState","adIndex","isFirstSampleOfAd","sentAdQuartiles","errorSent","isActivated","AD_BREAK_STARTED","currentAdMetadata","ACTIVE","resetAdData","customData","currentAdImpressionId","timestampOfAdStart","getCurrentMonotonicTimestampInMs","quartileMetadata","timeSinceAdStartedInMs","getMonotonicTimestampInMsSince","resetAdBreakData","SSAI","customDataValuesKeys","isPlainObject","isAdPosition","maybeSsaiAdMetadata","ssaiAdMetadata","sanitizedCustomDataValues","sanitizeCustomDataValues","isSsaiAdQuartile","ssaiAdQuartileMetadata","failedBeaconUrl","adType","ROUTING_URL_PARAM","ROUTING_URL_PARAM_VALUE_SSAI","playbackSample","ssaiEngagementErrorData","buildAdSample","ssaiEngagementStartedData","ssaiEngagementQuartileData","timestampInMs","adEngagementSample","adPlaybackHeight","adPlaybackWidth","customData1","customData2","customData3","customData4","customData5","customData6","customData7","customData8","customData9","customData10","customData11","customData12","customData13","customData14","customData15","customData16","customData17","customData18","customData19","customData20","customData21","customData22","customData23","customData24","customData25","customData26","customData27","customData28","customData29","customData30","customData31","customData32","customData33","customData34","customData35","customData36","customData37","customData38","customData39","customData40","customData41","customData42","customData43","customData44","customData45","customData46","customData47","customData48","customData49","customData50","customData51","customData52","customData53","customData54","customData55","customData56","customData57","customData58","customData59","customData60","customData61","customData62","customData63","customData64","customData65","customData66","customData67","customData68","customData69","customData70","customData71","customData72","customData73","customData74","customData75","customData76","customData77","customData78","customData79","customData80","customData81","customData82","customData83","customData84","customData85","customData86","customData87","customData88","customData89","customData90","customData91","customData92","customData93","customData94","customData95","customData96","customData97","customData98","customData99","customData100","videoImpressionId","quartile1FailedBeaconUrl","midpointFailedBeaconUrl","quartile3FailedBeaconUrl","completedFailedBeaconUrl","floor","CdnProvider","videoCodecs","findIndex","startsWith","audioCodecs","urlPath","MP4","WEBM","PAGE_LOAD_TYPE","stateMachineEvent","_isEnabled","disable","disabled","configure","authenticated","configContainer","extractConfig","configured","Feature","unregisterFeatures","feature","_queue","_enabled","joinUrls","copyErrorDetailTruncateStringsAndUrls","errorDetail","maxStringLength","maxUrlLength","substr","copyErrorDataTruncateStrings","httpRequests","copyHttpRequestTruncateUrls","maxLength","lastRedirectLocation","copyErrorDetailTruncateHttpRequests","maxRequests","limitHttpRequestsOfQueuedErrorDetails","send","errorDetailCopy","MAX_STRING_LENGTH","MAX_URL_LENGTH","post","flush","copy","removeFromQueue","settingsProvider","subscribables","errorIndex","onErrorHandler","httpRequestsCopy","errorId","subscribable","_authenticated","numberOfHttpRequests","errorDetails","_maxRequests","DEFAULT_MAX_REQUESTS","_httpRequestQueue","Queue","onDownloadFinishedHandler","addRequest","items","limit","offer","adFallbackIndex","adIdPlayer","adReplaceContentDuration","adIsPersistent","adTagType","adTagUrl","adPreloadOffset","adOffset","URL","adTagServer","hostname","adTagPath","pathname","adScheduleTime","mediaPath","mediaServer","adSkipAfter","skipAfter","parseSkipAfter","adSkippable","customDataFieldCount","input","retVal","extracted","getCustomDataString","playerVideoDuration","DEFAULT_RESULT","maybeSourceMetadata","muting_ready","info1","info2","baseUrl","analyticsServerUrl","adAnalyticsServerUrl","analyticsUrl","isSsaiRelatedSample","appendSsaiRoutingParam","trySendBeacon","fallbackFunction","requestHeaders","navigator","sendBeacon","blob","Blob","JSON","stringify","adAnalyticsUrl","playbackVideoData","progressiveArrayIndex","videoFormatCodecMap","avc","vp9","av1","hevc","MediaSource","isTypeSupported","getOwnPropertyNames","format","some","bytes","bits","kiloBits","async","isReactNative","xhttp","isLegacyXDomainRequestUsed","XDomainRequest","XMLHttpRequest","responseCallback","DONE","responseText","sampleResponse","parse","onload","onreadystatechange","open","setRequestHeader","licenseServerUrl","getInstance","instance","analyticsDebugConfig","console","optionalParams","tabularData","properties","str","_items","poll","maxElements","MESSAGE_NAMESPACE","isDocumentHidden","BACKGROUND","FOREGROUND","Boolean","valueOf","isObject","removeTrailingSlash","timeInSeconds","fromConfig","toConfig","CustomDataUtils","customDataField","numerator","denominator","pop","prev","getGlobalNavigatorProduct","playerIsMuted","playerVolume","obj","inViewport","options","rootMargin","IntersectionObserver","entries","handleIntersect","observe","hiddenPropertyName","getDocumentPropertyWithPrefix","visibilityChange","addDocumentEventListener","handleVisibilityChange","isHidden","document","unobserve","disconnect","removeDocumentEventListener","_observer","intersectionRatio","getGlobalWebOSApi","webOSSystem","PalmSystem","deviceInfo","trackedObjects","addGlobalEventListener","removeGlobalEventListener","deviceType","deviceClass","getGlobalLocationHostname","fallbackDomain","origin","oldConfigWithoutSourceRelatedFields","sourceSpecificProperties","customDataFieldsRegex","removeSourceRelatedFields","mergedCollectorConfig","oldCollectorConfig","newCollectorConfig","mergeCollectorConfig","errorMessages","isDomainMissing","fullErrorMessage","prop","pascalCase","charAt","toUpperCase","prefixedProp","hiddenProp","fullscreenProp","nodeName","allCookies","cookie","cookieName","newCookie","globalThis","window","g","getGlobalThis","getGlobalDevicePixelRatio","devicePixelRatio","screen","scale","location","getGlobalLocationPathname","userLanguage","product","videojs","THEOplayer","parseInt","BITMOVIN_ANALYTICS_AUGMENTED_MARKER","isEmpty","trim","suffix","c","r","random","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","__webpack_modules__","Function","adapters"],"sourceRoot":""}
1
+ {"version":3,"file":"bitmovin-analytics.js","mappings":";;;;;;;;;;CAAA,SAA2CA,EAAMC,GAC1B,iBAAZC,SAA0C,iBAAXC,OACxCA,OAAOD,QAAUD,IACQ,mBAAXG,QAAyBA,OAAOC,IAC9CD,OAAO,GAAIH,GACe,iBAAZC,QACdA,QAAkB,SAAID,KAEtBD,EAAe,SAAIA,EAAe,UAAK,CAAC,EAAGA,EAAe,SAAa,UAAIC,IAC5E,CATD,CASGK,MAAM,WACT,O,qCCDC,IAEKC,IAAe,CAIjBC,QAAS,QAITC,OAAQ,CACNC,UAAc,EACdC,aAAc,EACdC,UAAc,EACdC,QAAc,GAGhBC,MAAO,CACLC,mBAAoB,IACpBC,mBAAoB,IACpBC,iBAAoB,KAGtBC,SAAU,IACVC,MAAO,QAIPC,OAAQ,SAASC,EAAKC,GAEpB,IAAIC,EAAsC,iBAAfF,EAAIE,QAAuB,CAAEC,MAAOH,EAAIE,SAAYF,EAAIE,QAC/EE,EAAeJ,EAAII,UAAYJ,EAAW,MAC1CK,EAAeJ,GAAUD,EAAIC,QAAW,CAAC,EACzCK,EAAeN,EAAIM,QAAU,GAC7BC,EAAeP,EAAIO,WAAa,CAAC,EACjCC,EAAe,CAAC,EAChBC,EAAe,CAAC,EAEhBC,EAAM,SAASC,GACjB,IAAIC,EAAOC,MAAMC,QAAQH,EAAEC,MAAQD,EAAEC,KAAQD,EAAEC,KAAO,CAACD,EAAEC,MAAQ,CAAC1B,EAAaW,UAC/EW,EAAIG,EAAEI,MAAQP,EAAIG,EAAEI,OAAS,CAAC,EAC9B,IAAK,IAAIC,EAAI,EAAIA,EAAIJ,EAAKK,OAASD,IACjCP,EAAYG,EAAKI,IAAMP,EAAYG,EAAKI,KAAO,GAC/CP,EAAYG,EAAKI,IAAIE,KAAKP,EAAEI,MAE5BP,EAAIG,EAAEI,MAAMH,EAAKI,IAAML,EAAEQ,IAAMP,EAAKI,GAElCL,EAAEQ,KACJV,EAAYE,EAAEQ,IAAMV,EAAYE,EAAEQ,KAAO,GAC7C,EAEIjB,IACFA,EAAQkB,MAAQlB,EAAQkB,OAAS,UACjCV,EAAI,CAAEK,KAAMb,EAAQkB,MAAOR,KAAM,OAAQO,GAAIjB,EAAQC,SAGvD,IAAI,IAAIa,EAAI,EAAIA,EAAIV,EAAOW,OAASD,IAClCN,EAAIJ,EAAOU,IAEb,IAAI,IAAID,KAAQP,EACVA,EAAIa,eAAeN,KACrBV,EAAIU,GAAQ7B,EAAaoC,WAAWP,EAAMP,EAAIO,KAGlD,IAAI,IAAIA,KAAQR,EACVA,EAAUc,eAAeN,KAC3BV,EAAIU,GAAQR,EAAUQ,IAe1B,OAZAV,EAAIkB,QAAc,OAClBlB,EAAImB,GAAc,SAASrB,GAAS,OAAOU,MAAMC,QAAQX,GAAUA,EAAMsB,QAAQC,KAAKH,UAAY,EAAMG,KAAKH,UAAYpB,CAAQ,EACjIE,EAAIsB,IAAc,SAASP,GAAS,OAAQM,KAAKE,iBAA8BC,IAAfrB,EAAIY,KAA0BZ,EAAIY,GAAOC,eAAeK,KAAKH,UAAYf,EAAIY,GAAOC,eAAenC,EAAaW,UAAY,EAC5LQ,EAAIyB,OAAc,SAASV,GAAS,OAAQM,KAAKC,IAAIP,EAAQ,EAC7Df,EAAII,YAAc,WAAkB,OAAQA,EAAYiB,KAAKH,UAAY,IAAIQ,OAAOtB,EAAYvB,EAAaW,WAAa,GAAK,EAC/HQ,EAAI2B,WAAc,WAAkB,OAAON,KAAKF,GAAGpB,EAAW,EAC9DC,EAAI4B,MAAcjC,EAAIiC,OAAS,SAASlB,EAAMH,EAAMO,EAAIe,EAAMD,EAAOE,EAAKxB,GAAK,MAAMA,GAAKwB,CAAK,EAC/F9B,EAAI+B,OAAc,WAAa,OAAOC,OAAOC,KAAK7B,GAAa8B,MAAO,EAElErC,IAAYA,EAAQsC,OACtBnC,EAAIH,EAAQkB,SAEPf,CAET,EAIAoC,WAAY,SAASpC,EAAKqC,EAAM3B,EAAMH,EAAMO,EAAIe,GAC9C,GAAIQ,EACF,IACE,OAAOA,EAAKC,MAAMtC,EAAK,CAACU,EAAMH,EAAMO,GAAIY,OAAOG,GACjD,CACA,MAAMvB,GACJ,OAAON,EAAI4B,MAAMlB,EAAMH,EAAMO,EAAIe,EAAMhD,EAAaO,MAAMG,iBAAkB,+DAAgEe,EAC9I,CAEJ,EAEAiC,eAAiB,SAASvC,EAAKU,EAAMH,EAAMO,EAAIe,GAAQ,OAAOhD,EAAauD,WAAWpC,EAAKA,EAAmB,cAAyBU,EAAMH,EAAMO,EAAIe,EAAO,EAC9JW,cAAiB,SAASxC,EAAKU,EAAMH,EAAMO,EAAIe,GAAQ,OAAOhD,EAAauD,WAAWpC,EAAKA,EAAkB,cAAKA,EAAa,QAAQU,EAAMH,EAAMO,EAAIe,EAAO,EAC9JY,cAAiB,SAASzC,EAAKU,EAAMH,EAAMO,EAAIe,GAAQ,OAAOhD,EAAauD,WAAWpC,EAAKA,EAAkB,aAA0BU,EAAMH,EAAMO,EAAIe,EAAO,EAC9Ja,cAAiB,SAAS1C,EAAKU,EAAMH,EAAMO,EAAIe,GAAQ,OAAOhD,EAAauD,WAAWpC,EAAKA,EAAkB,cAAKA,EAAa,QAAQU,EAAMH,EAAMO,EAAIe,EAAO,EAC9Jc,YAAiB,SAAS3C,EAAKU,EAAMH,EAAMO,EAAIe,GAAQ,OAAOhD,EAAauD,WAAWpC,EAAKA,EAAmB,cAAyBU,EAAMH,EAAMO,EAAIe,EAAO,EAE9Je,gBAAiB,SAAS5C,EAAKU,EAAMH,EAAMO,EAAIe,GAAQ,OAAOhD,EAAauD,WAAWpC,EAAKA,EAAI,WAAaU,GAA2BA,EAAMH,EAAMO,EAAIe,EAAO,EAC9JgB,eAAiB,SAAS7C,EAAKU,EAAMH,EAAMO,EAAIe,GAAQ,OAAOhD,EAAauD,WAAWpC,EAAKA,EAAI,UAAaU,IAASV,EAAI,KAAOU,GAAOA,EAAMH,EAAMO,EAAIe,EAAO,EAC9JiB,eAAiB,SAAS9C,EAAKU,EAAMH,EAAMO,EAAIe,GAAQ,OAAOhD,EAAauD,WAAWpC,EAAKA,EAAI,UAAaO,GAA2BG,EAAMH,EAAMO,EAAIe,EAAO,EAC9JkB,eAAiB,SAAS/C,EAAKU,EAAMH,EAAMO,EAAIe,GAAQ,OAAOhD,EAAauD,WAAWpC,EAAKA,EAAI,UAAac,IAASd,EAAI,KAAOc,GAAOJ,EAAMH,EAAMO,EAAIe,EAAO,EAE9JmB,YAAa,SAAShD,EAAKU,EAAMH,EAAMO,EAAIe,GACzC,IAAK,IAAUhD,EAAa+D,gBAAgB5C,EAAKU,EAAMH,EAAMO,EAAIe,KAC5D,IAAUhD,EAAa0D,eAAgBvC,EAAKU,EAAMH,EAAMO,EAAIe,GAC/D,OAAO,CACX,EAEAoB,WAAY,SAASjD,EAAKU,EAAMH,EAAMO,EAAIe,GACxChD,EAAagE,eAAe7C,EAAKU,EAAMH,EAAMO,EAAIe,GACjDhD,EAAa2D,cAAexC,EAAKU,EAAMH,EAAMO,EAAIe,EACnD,EAEAqB,WAAY,SAASlD,EAAKU,EAAMH,EAAMO,EAAIe,GACxC,IAAIsB,EAAWtE,EAAaiE,eAAe9C,EAAKU,EAAMH,EAAMO,EAAIe,GAC5DuB,EAAWvE,EAAa4D,cAAezC,EAAKU,EAAMH,EAAMO,EAAIe,GAChE,OAAK,IAAUsB,IAAc,IAAUC,IAE7BvE,EAAaY,QAAU0D,GAActE,EAAaY,QAAU2D,EAC7DvE,EAAaY,WADjB,EAEP,EAEA4D,WAAY,SAASrD,EAAKU,EAAMH,EAAMO,EAAIe,GACxChD,EAAakE,eAAe/C,EAAKU,EAAMH,EAAMO,EAAIe,GACjDhD,EAAa6D,cAAe1C,EAAKU,EAAMH,EAAMO,EAAIe,EACnD,EAIAZ,WAAY,SAASP,EAAMP,GACzB,OAAO,WAEL,IAAII,EAAQc,KAAKH,QACbJ,EAAQX,EAAII,KAAUJ,EAAItB,EAAaW,WAAaX,EAAaW,SAAWW,EAAItB,EAAaW,UAAYe,IAASA,EAClHsB,EAAQrB,MAAM8C,UAAUC,MAAMC,KAAKC,WAEvC,GAAIpC,KAAKE,WACP,OAAOF,KAAKO,MAAMlB,EAAMH,EAAMO,EAAIe,EAAMhD,EAAaO,MAAME,mBAAoB,SAAWoB,EAAO,+DAEnG,GAAIW,KAAKI,OAAOf,GACd,OAAOW,KAAKO,MAAMlB,EAAMH,EAAMO,EAAIe,EAAMhD,EAAaO,MAAMC,mBAAoB,SAAWqB,EAAO,mCAAqCW,KAAKH,SAE7I,IAAI,IAAUrC,EAAamE,YAAY3B,KAAMX,EAAMH,EAAMO,EAAIe,GAC3D,OAAOhD,EAAaE,OAAOG,UAE7B,GAAIqB,IAASO,EAEX,OADAjC,EAAaoE,WAAW5B,KAAMX,EAAMH,EAAMO,EAAIe,GACvChD,EAAaE,OAAOE,aAI7B,IAAIe,EAAMqB,KACVA,KAAKE,WAAa,WAMhB,OALAvB,EAAIuB,WAAa,KACjBvB,EAAIkB,QAAUJ,EACdjC,EAAawE,WAAYrD,EAAKU,EAAMH,EAAMO,EAAIe,GAC9ChD,EAAa8D,YAAY3C,EAAKU,EAAMH,EAAMO,EAAIe,GAC9ChD,EAAaoE,WAAYjD,EAAKU,EAAMH,EAAMO,EAAIe,GACvChD,EAAaE,OAAOC,SAC7B,EACAqC,KAAKE,WAAWmC,OAAS,WACvB1D,EAAIuB,WAAa,KACjB1C,EAAaoE,WAAWjD,EAAKU,EAAMH,EAAMO,EAAIe,EAC/C,EAEA,IAAI8B,EAAQ9E,EAAaqE,WAAW7B,KAAMX,EAAMH,EAAMO,EAAIe,GAC1D,OAAI,IAAU8B,GACZtC,KAAKE,WAAa,KACX1C,EAAaE,OAAOG,WAEpBL,EAAaY,QAAUkE,EACvB9E,EAAaE,OAAOI,QAGvBkC,KAAKE,WACAF,KAAKE,kBADd,CAIJ,CACF,GAUqC9C,EAAOD,UAC1CA,EAAUC,EAAOD,QAAUK,GAE7BL,EAAQK,aAAeA,C,+GC9M3B,cAEA,UAEA,UAEA,UAEA,aAGE,WACU+E,EACAC,GAFV,WACU,KAAAD,OAAAA,EACA,KAAAC,mBAAAA,EAJV,KAAAC,YAAc,IAAI,EAAAC,YASlB,KAAAC,iBAAmB,iBAAM,OAA8B,QAA9B,IAAKJ,OAAOI,0BAAkB,QAAS,EAChE,KAAAC,aAAe,WAAM,SAAKL,OAAOK,cAAZ,EACrB,KAAAC,gBAAkB,iBAAM,OAA6B,QAA7B,IAAKN,OAAOM,yBAAiB,QAAI,CAACxD,UAAMc,EAAW2C,aAAS3C,EAAU,EAC9F,KAAA4C,YAAc,iBAAM,OAA4B,QAA5B,IAAKR,OAAOS,wBAAgB,QAAI,CAAC,EANnDhD,KAAKiD,UACP,CA8DF,OAxDE,YAAAC,YAAA,W,MACE,OAA2B,QAApB,EAAAlD,KAAKuC,OAAOY,gBAAQ,QAC7B,EAEQ,YAAAF,SAAR,sBACEjD,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBC,MAAM,SAACrE,GAC1B,oBAAbA,EAAEsE,QACJ,EAAKd,YAAYe,QAErB,IACAxD,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBI,QAAQ,SAACxE,GAC5B,oBAAbA,EAAEsE,QACJ,EAAKd,YAAYiB,SAErB,IACA1D,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBM,WAAW,SAACjE,GAChD,EAAK+C,YAAYmB,aAAY,IAAAC,eAAcnE,EAAMoE,IACnD,IACA9D,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBU,YAAY,SAACrE,GACjD,EAAK+C,YAAYuB,cAAa,IAAAH,eAAcnE,EAAMoE,IACpD,IACA9D,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBY,gBAAgB,SAACvE,GACrD,EAAK+C,YAAYyB,kBAAiB,IAAAC,oBAAmBzE,EAAM0E,SAC7D,IACApE,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBgB,iBAAiB,SAAC3E,GACtD,EAAK+C,YAAY6B,mBAAkB,IAAAH,oBAAmBzE,EAAM0E,SAC9D,IACApE,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBkB,WAAW,SAAC7E,GAChD,EAAK+C,YAAY+B,YAAY,CAACC,gBAAiB/E,EAAM+E,iBACvD,IACAzE,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBqB,YAAY,SAAChF,GACjD,EAAK+C,YAAYkC,aAAa,CAACC,SAAUlF,EAAMkF,UACjD,IACA5E,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBwB,WAAW,SAACnF,GAChD,EAAK+C,YAAYqC,aAAY,IAAAjB,eAAcnE,EAAMoE,IACnD,IACA9D,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuB0B,SAAS,SAACrF,G,MAC9C,EAAK+C,YAAYuC,WAAU,IAAAC,oBAAmBvF,EAAgC,QAAzB,IAAK6C,OAAO2C,qBAAa,eAAEC,IAClF,IACAnF,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuB+B,kBAAkB,SAAC1F,G,QACjD2F,EAAc3F,EAAM4F,SACpBC,EAAoC,UAAX,QAAhB,EAAAF,aAAW,EAAXA,EAAaG,WAAG,eAAEC,MAC3BC,GAAc,IAAAC,cAAajG,EAAM4F,WAAY,IAAAnB,oBAAmBzE,EAAM4F,eAAYnF,EAClFyF,EAA2C,QAApB,EAAAlG,EAAMmG,sBAAc,eAAEC,aACnD,EAAKrD,YAAYsD,mBAAmB,CAClCL,YAAW,EACXE,qBAAoB,EACpBL,OAAM,GAEV,IACA,IAAMS,EAAkB,WACtB,EAAKvD,YAAYwD,gBACnB,EACAjG,KAAKwC,mBAAmB0D,iBAAiB,eAAgBF,GACzDhG,KAAKwC,mBAAmB0D,iBAAiB,SAAUF,EACrD,EACF,EAtEA,GAAa,EAAAG,kBAAAA,C,+GCAb,cACA,UAWA,UACA,UACA,UACA,UAKA,UAGA,UACA,UACA,UAEA,aAIE,WAAY5D,EAAa6D,GAAzB,I,EAAA,OACE,GA4BO,KAAAC,KAAgB,CACvBC,aAAc,SAACC,GACb,IAAK,IAAAC,WAAU,EAAKC,iBAApB,CASA,IAAMC,GAAqC,IAAAC,uDAAsDJ,GAEjG,IAAK,IAAAK,sCAAqCF,GAA1C,CAKA,IAAMG,GAA2B,IAAAC,mCAAkCJ,GAEnE,EAAKD,gBAAgBM,YAAYT,aAAaO,EAJ9C,CAd4C,CAmB9C,EAEAG,QAAS,SAACC,GACR,IAAK,IAAAT,WAAU,EAAKU,aACf,IAAAV,WAAU,EAAKC,mBAEf,IAAAU,iCAAgCF,GAArC,CAKA,IAAMG,GAAsB,IAAAC,8BAA6BJ,GAEzD,EAAKR,gBAAgBM,YAAYC,QAAQI,GAMzC,EAAKF,UAAUI,sBACf,EAAKJ,UAAUK,kCAXf,CAYF,EAEAC,mBAAoB,SAACC,EAA4BC,GAC/C,IAAK,IAAAlB,WAAU,EAAKU,aACf,IAAAV,WAAU,EAAKC,mBAEf,IAAAkB,iCAAgCF,GAArC,CAKA,IAAMG,GAAkC,IAAAC,gCAA+BH,GAEvE,EAAKjB,gBAAgBM,YAAYS,mBAAmBC,EAAYG,EAJhE,CAKF,EAEAE,WAAY,YACL,IAAAtB,WAAU,EAAKU,aACf,IAAAV,WAAU,EAAKC,mBAEpB,EAAKA,gBAAgBM,YAAYe,aAEjC,EAAKZ,UAAUI,sBACf,EAAKJ,UAAUK,mCACjB,IA9FI,IAAAQ,+BAA8BxF,GAChC,EAAAyF,OAAOC,mBAAmB,uEAD5B,EAIA,IAAAC,+BAA8B3F,GAE9B,IAAM4F,EAA8B5F,EAAqB6F,YACnDC,GAAkB,IAAAC,yBAAwBH,EAAajB,WAC7D,IAAK,IAAAqB,+BAA8BF,GAAnC,EAIA,IAAAG,8BAA6BH,GAE7BA,EAAgBI,UAAqC,QAAzB,EAAAJ,EAAgBI,iBAAS,QAAIN,EAAaO,IAEtE,IAAMjC,EAAkB,EAAAkC,yBAAyBtK,OAAO,IAAI,EAAAuK,qBAAqBrG,GAAS6D,GAC1FpG,KAAKyG,gBAAkBA,EACvBzG,KAAKkH,UAAY,EAAA2B,UAAUxK,OAAOgK,EAAiBrI,KAAKyG,iBAKxDlE,EAAO2E,UAAYlH,KAEnBA,KAAK8I,eAAevG,EAAQvC,KAAKkH,UAAWT,EAf5C,CAPA,CAuBF,CA2HF,OAjDU,YAAAqC,eAAR,SAAuBvG,EAAmB2E,EAAsBT,GAC9D,IAAMsC,EAAexG,EAAOyG,KAC5BzG,EAAOyG,KAAO,W,IAAC,sDACb,GAAIxI,EAAKjB,OAAS,EAAG,CACnB,IAAM0J,EAAmBzI,EAAK,GAAW0G,UAEzCA,EAAUgC,aAAaD,EACzB,CAGA,OAFAxC,EAAgB0C,6BAETJ,EAAa9H,MAAMsB,EAAQ/B,EACpC,CACF,EAIA,sBAAI,sBAAO,C,IAAX,WACE,OAAO,EAAA/C,OACT,E,gCAEA,YAAA2L,uBAAA,WACE,IAAK,IAAA5C,WAAUxG,KAAKkH,WAEpB,OAAOlH,KAAKkH,UAAUkC,wBACxB,EAEA,YAAAC,UAAA,WACE,IAAK,IAAA7C,WAAUxG,KAAKkH,WAEpB,OAAOlH,KAAKkH,UAAUmC,WACxB,EAEA,YAAAC,cAAA,SAAcC,IACP,IAAA/C,WAAUxG,KAAKyG,kBAEpBzG,KAAKyG,gBAAgB6C,cAAcC,EACrC,EAEA,YAAAC,kBAAA,SAAkBD,IACX,IAAA/C,WAAUxG,KAAKkH,YAEpBlH,KAAKkH,UAAUsC,kBAAkBD,EACnC,EAEA,YAAAL,aAAA,SAAaO,IACN,IAAAjD,WAAUxG,KAAKkH,YAEpBlH,KAAKkH,UAAUgC,aAAaO,EAC9B,EAlCgB,EAAA3G,QAAkB,EAAArF,QAmCpC,C,CA1JA,GAAa,EAAAiM,iBAAAA,C,2zBC7Bb,IAsCKC,EAtCL,UAEA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,SACA,UACA,UACA,UAGA,UAMA,UAEA,UACA,UACA,UAEA,UAGA,SAEA,UACA,UACA,UACA,UAEA,SAAKA,GACH,0BACA,kBACA,qCACD,CAJD,CAAKA,IAAAA,EAAQ,KAMb,kBAaE,WACEpH,EACAqH,EACAC,EACAC,EACAC,EACAC,EACA5D,GAEA,QAAK,UAACA,IAAK,KApBL,EAAA6D,qBAAsB,EA2G9B,EAAAC,iBAAmB,iBAAM,OAAmB,QAAnB,IAAK3H,OAAOO,eAAO,QAAI,SAAS,EACzD,EAAAqH,cAAgB,WAAM,SAAAC,OAAOC,QAAP,EACtB,EAAAC,cAAgB,iBAAM,OAA2B,QAA3B,IAAK/H,OAAOgI,uBAAe,QAAI,SAAS,EAIrD,EAAAC,sBAAwB,WAAsC,SAAKC,kBAAL,EA5FrE,EAAKV,2BAA6BA,EAClC,EAAKW,wBAA0BZ,EAC/B,EAAKD,eAAiBA,EACtB,EAAKD,WAAaA,EAClB,EAAKrH,OAASA,EACd,IAAMoI,EAA0B,IAAI,EAAAC,kBAClC,mBAAM,OAA2D,QAA3D,EAA4B,QAA5B,IAAKrI,OAAOS,wBAAgB,QAAI,EAAK6H,8BAAsB,QAAI,CAAC,IAElEC,EAAe,IAAI,EAAAC,+BACvB,EAAKC,sBACLL,EACA,EAAKvE,M,OAEPuE,EAAwBM,YAAYH,GACpC,EAAKd,0BAA4BA,EAEjC,EAAKc,aAAeA,E,CACtB,CA8eF,OAthB8C,OA0C5C,sBAAc,0BAAW,C,IAAzB,WAIE,OAAI,IAAAnF,cAAa3F,KAAKuC,OAAOS,oBAAsBhD,KAAKkL,YAC/ClL,KAAKuC,OAAOS,iBAEdhD,KAAK6K,uBAAyB7K,KAAK6K,uBAAyB,CACrE,E,gCAEA,sBAAY,0BAAW,C,IAAvB,WACE,OAAO,IAAAlF,cAAa3F,KAAKuC,OAAO2C,cAClC,E,gCAEA,sBAAI,6CAA8B,C,IAAlC,WACE,OAAO,CACT,E,gCAEA,sBAAI,uBAAQ,C,IAAZ,WACE,OAAOlF,KAAKmL,SACd,E,gCAEA,sBAAI,qCAAsB,C,IAA1B,WACE,OAAOnL,KAAK0K,uBACd,E,gCAEA,YAAAU,WAAA,SAAWlE,GAAX,WACElH,KAAKqL,+BAOLrL,KAAKmL,UAAY,IAAI,EAAAhF,kBAAkBnG,KAAKuC,OAAQvC,KAAKwC,oBAEzDxC,KAAKsL,+BAELtL,KAAK+G,YAAYwE,SAAS,CACxBC,qBAAsB,WAAM,SAAKzI,WAAL,EAC5B0I,4BAA6B,SAACC,GAC5BxE,EAAUyE,2BAA2BD,EACvC,EACAE,0BAA2B,SAACC,EAAmBC,GAK7C,EAAKhB,aAAaiB,kBAAkBF,EAAWC,GAAmB,EACpE,IAGF,IAAME,EAAkB,IAAI,EAAAC,oBAAoB,CAACjM,KAAK+J,6BAOtD,MAAO,CANqB,IAAI,EAAAmC,oBAC9BhF,EAAUiF,oCACV,IAAI,EAAAC,mBAAmBlF,EAAUiF,oCAAoCE,iBACrE,CAACnF,EAAUoF,yBACXN,GAGJ,EAES,YAAAO,wBAAT,WACEvM,KAAK+G,YAAYwF,0BACjB,YAAMA,wBAAuB,UAC/B,EAKA,YAAArJ,YAAA,W,MACE,OAA2B,QAApB,EAAAlD,KAAKuC,OAAOY,gBAAQ,QAC7B,EAEA,YAAAqJ,uBAAA,W,QACQC,EAAYzM,KAAKuC,OAAOK,eACxB8J,EAAI,OACL,YAAMC,sBAAqB,YAAE,CAChCC,KAAM5M,KAAKuC,OAAOsK,gBAAkBlD,EAASmD,WAAa,EAAAC,WAAWD,WAAa,EAAAC,WAAWC,OAC7FC,WAAYjN,KAAKsK,gBACjB4C,OAAQlN,KAAKuC,OAAO2K,SACpBC,eAAe,IAAAC,wBAAuBpN,KAAKmN,eAC3CE,aAAcrN,KAAKuC,OAAO+K,gBAC1BC,iBAAkBd,aAAS,EAATA,EAAWe,YAC7BC,kBAAmBhB,aAAS,EAATA,EAAWiB,aAC9BC,QAAS3N,KAAKuC,OAAOoL,UACrBC,UAAW5N,KAAKuC,OAAOqL,YACvBC,cAAqC,QAAtB,EAAA7N,KAAKuC,OAAOuL,kBAAU,eAAEC,KACvCC,iBAAiB,EACjBC,eAAe,IAAAtI,cAAa3F,KAAKuC,OAAO2L,cAAmD,QAAnC,EAAAlO,KAAKuC,OAAO4L,+BAAuB,QAAS,IActG,OAXAnO,KAAKoO,wBAAwB1B,GAC7B1M,KAAKqO,+BAA+B3B,GACpC1M,KAAKsO,uBAAuB5B,GAC5B1M,KAAKuO,sBAAsB7B,KAEvB,IAAA8B,WAAU9B,EAAKW,eAAuC,YAAtBX,EAAKW,eAGvCrN,KAAKgK,0BAA0ByE,kBAAkB/B,GAG5CA,CACT,EACS,YAAAgC,eAAT,WACE,OAAO1O,KAAK6J,eAAe8E,aAC7B,EACS,YAAAC,qBAAT,WACE,OAAO5O,KAAK4J,WAAWiF,SACzB,EACS,YAAAC,+BAAT,WACE9O,KAAK4J,WAAWmF,OAClB,EAEA,YAAAC,QAAA,WACEhP,KAAK6J,eAAekF,OACtB,EAEA,YAAA5F,2BAAA,WACMnJ,KAAKkD,eACPlD,KAAKiP,cAAc,EAAAC,MAAMC,mBAAoB,CAACpM,YAAa/C,KAAK+C,aAEpE,EAEQ,YAAAsI,6BAAR,sBACErL,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuB+L,gBAAgB,SAACC,GACrD,EAAKxF,eAAekF,QACpB,EAAKE,cAAc,EAAAC,MAAMI,gBAAiB,CACxCvM,YAAa,EAAKA,aAEtB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBkM,cAAc,SAACF,G,MACnD,EAAK3E,wBAAwBqE,QAC7B,EAAK5B,cAAgB,EAAK5K,OAAOiN,cACjC,EAAK9E,wBAAwB+E,iBAA0C,QAAzB,IAAKlN,OAAOiN,qBAAa,QAAI,GAC3E,EAAKxF,0BAA0B0F,gBAAgB,EAAKnN,OAAO+K,iBAC3D,EAAK2B,cAAc,EAAAC,MAAMS,cAAe,CAAC,EAC3C,IAEA3P,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBuM,aAAa,SAAClQ,GAClD,EAAKuP,cAAc,EAAAC,MAAMW,WAAYnQ,EACvC,IAEAM,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuByM,aAAa,WACjD,EAAKb,cAAc,EAAAC,MAAMa,SAAU,CACjChN,YAAa,EAAKA,aAEtB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBC,MAAM,SAACrE,GAC1B,YAAbA,EAAEsE,QACJ,EAAK0L,cAAc,EAAAC,MAAMc,KAAM,CAC7BjN,YAAa,EAAKA,aAGxB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuB4M,SAAS,SAAChR,GAC7B,oBAAbA,EAAEsE,QACJ,EAAK0L,cAAc,EAAAC,MAAMgB,QAAS,CAChCnN,YAAa,EAAKA,aAGxB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBI,QAAQ,SAACxE,GAC5B,YAAbA,EAAEsE,QACJ,EAAK0L,cAAc,EAAAC,MAAMiB,MAAO,CAC9BpN,YAAa,EAAKA,aAGxB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuB+M,aAAa,SAACf,GAC7C,EAAKnE,cACR,EAAKL,uBAAyB,EAAKtI,OAAOS,kBAE5C,EAAKiM,cAAc,EAAAC,MAAMmB,YAAa,CACpCtN,YAAa,EAAK8H,wBAEtB,IAEA7K,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBiN,MAAM,SAACrR,GACvC,EAAKsR,aAAatR,IACpB,EAAKgQ,cAAc,EAAAC,MAAMsB,KAAM,CAC7BzN,YAAa,EAAKA,aAGxB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBoN,QAAQ,WAC5C,EAAKxB,cAAc,EAAAC,MAAMwB,OAAQ,CAC/B3N,YAAa,EAAKA,aAEtB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBsN,cAAc,WAClD,EAAK1B,cAAc,EAAAC,MAAM0B,gBAAiB,CACxC7N,YAAa,EAAKA,aAEtB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBwN,YAAY,WAChD,EAAK5B,cAAc,EAAAC,MAAM4B,cAAe,CACtC/N,YAAa,EAAKA,aAEtB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuB0N,6BAA6B,SAACC,GAClE,IAAMC,EAA0BD,EAC1BE,EAAgBD,EAAwBC,cACxCC,EAAgBF,EAAwBE,cAE9C,KAAI,IAAA3C,WAAU2C,GAAd,CAIA,IAAMC,EAAuC,CAC3C3L,KAAM,QACN4L,QAASF,EAAcE,QACvBtO,YAAa,EAAKA,YAClBuO,MAAQH,EAAsBG,QAK9B,IAAA3L,cAAauL,IACb,EAAKK,qBAAqBC,8BAA8BL,EAAcE,UAEtE,EAAKpC,cAAc,EAAAC,MAAMuC,aAAcL,GAGzC,EAAKG,qBAAqBG,gBAAgBP,EAAcE,SACxD,EAAKrG,sBAAsB2G,wBAAwBP,EAlBnD,CAmBF,IAEApR,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBuO,6BAA6B,SAACZ,GAClE,IAAMa,EAA0Bb,EAC1BE,EAAgBW,EAAwBX,cACxCC,EAAgBU,EAAwBV,cAK9C,KAAI,IAAA3C,WAAU2C,GAAd,CAIA,IAAMC,EAAuC,CAC3C3L,KAAM,QACNqM,MAAOX,EAAcW,MACrBC,OAAQZ,EAAcY,OACtBV,QAASF,EAAcE,QACvBtO,YAAa,EAAKA,YAClBuO,MAAQH,EAAsBG,QAK9B,IAAA3L,cAAauL,IACb,EAAKK,qBAAqBS,8BAA8Bb,EAAcE,UAEtE,EAAKpC,cAAc,EAAAC,MAAM+C,aAAcb,GAGzC,EAAKG,qBAAqBW,gBAAgBf,EAAcE,SACxD,EAAKrG,sBAAsB2G,wBAAwBP,EApBnD,CAqBF,IAEApR,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuB8O,iBAAiB,SAAClT,GACzC,eAATA,EAAEQ,GACJ,EAAKwP,cAAc,EAAAC,MAAMkD,iBAAkB,CACzCrP,YAAa,EAAKA,cAEA,eAAX9D,EAAEC,MACX,EAAK+P,cAAc,EAAAC,MAAMmD,eAAgB,CACvCtP,YAAa,EAAKA,aAGxB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBM,WAAW,SAAC0L,GAChD,EAAKJ,cAAc,EAAAC,MAAMoD,SAAU,CACjCvP,YAAa,EAAKA,aAEtB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBU,YAAY,SAACsL,GACjD,EAAKJ,cAAc,EAAAC,MAAMqD,OAAQ,CAC/BxP,YAAa,EAAKA,aAEtB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBwB,WAAW,SAACwK,GAChD,EAAKJ,cAAc,EAAAC,MAAMqD,OAAQ,CAC/BxP,YAAa,EAAKA,aAEtB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuB0B,SAAS,SAACsK,GAC9C,EAAKJ,cAAc,EAAAC,MAAMqD,OAAQ,CAC/BxP,YAAa,EAAKA,aAEtB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBmP,OAAO,WAC3C,EAAKvD,cAAc,EAAAC,MAAMuD,KAAM,CAC7B1P,YAAa,EAAKA,aAEtB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBqP,SAAS,WAC7C,EAAKzD,cAAc,EAAAC,MAAMyD,QAAS,CAChC5P,YAAa,EAAKA,aAEtB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBtF,OAAO,SAAC2B,GAC5C,EAAKuP,cAAc,EAAAC,MAAM0D,MAAO,CAC9BC,KAAMnT,EAAMmT,KACZC,QAASpT,EAAML,KACf0T,WAAYrT,EAAMsT,KAClBjQ,YAAa,EAAKA,YAClBkQ,cAAevT,EACfsT,KAAM,CACJE,gBAAgB,IAAAC,kBAAiBzT,EAAMsT,SAIzCtT,EAAMmT,OAAS,EAAAO,UAAUC,gCAAgCR,MACzDnT,EAAMmT,OAAS,EAAAO,UAAUE,gCAAgCT,MAEzD,EAAKU,oBAAoBC,SAAS,CAAC,GAErC,EAAKzM,YAAY0M,4BACf,CAACZ,KAAMnT,EAAMmT,KAAMC,QAASpT,EAAML,KAAMqU,SAAU,YAClDhU,EAEJ,IAEAM,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBsQ,kBAAkB,WACtD,EAAK1E,cAAc,EAAAC,MAAM0E,IAAK,CAAC7Q,YAAa,EAAKA,aACnD,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBwQ,kBAAkB,SAACnU,GACJ,IAA/CA,EAAMoU,aAAa/T,QAAQ,kBAC7B,EAAK0K,mBAAqB,CACxBsJ,QAASrU,EAAMoU,aAAaE,QAAQ,eAAgB,IACpDC,YAAkC,IAArBvU,EAAMoG,cAGzB,IAEA9F,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuB6Q,cAAc,SAAC7E,GACnD,EAAKJ,cAAc,EAAAC,MAAMiF,mBAAoB,CAC3CpR,YAAa,EAAKA,aAEtB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuB+Q,iBAAiB,SAAC/E,GACtD,EAAKJ,cAAc,EAAAC,MAAMmF,gBAAiB,CACxCtR,YAAa,EAAKA,aAEtB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBiR,kBAAkB,SAACjF,GACvD,EAAKJ,cAAc,EAAAC,MAAMmF,gBAAiB,CACxCtR,YAAa,EAAKA,aAEtB,IAEA/C,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBkR,kBAAkB,SAAC7U,GACnDA,EAAMsT,KAAK9L,gBAA0C/G,IAA7BT,EAAMsT,KAAK9L,UAAUwB,IAC/C,EAAK8L,qBAAqBhB,SAAS,CAACiB,WAAY/U,EAAMsT,KAAK9L,UAAUwB,MAErE,EAAK6K,oBAAoBC,SAAS,CAAC,EAEvC,GACF,EAEQ,YAAAlI,6BAAR,sBAEQoJ,EAAwB,WAC5B,IAAK,EAAKzK,oBAAqB,CAC7B,EAAKA,qBAAsB,EAE3B,IAAMlH,EAAc,EAAK8H,uBACzB,EAAKoE,cAAc,EAAAC,MAAMyF,OAAQ,CAAC5R,YAAW,GAC/C,CACA,EAAK6R,SACP,EAEA5U,KAAKuC,OAAOa,GAAG,EAAAC,uBAAuBwR,QAASH,GAC/C1U,KAAKwC,mBAAmB0D,iBAAiB,eAAgBwO,GACzD1U,KAAKwC,mBAAmB0D,iBAAiB,SAAUwO,EACrD,EAEQ,YAAAnG,sBAAR,SAA8B7B,GAC5B,IAAMoI,EAAS9U,KAAKuC,OAAO2L,YAC3B,KAAI,IAAAM,WAAUsG,GAAd,CAIApI,EAAKqI,WAAaD,EAAOE,MACzBtI,EAAKuI,OAASH,EAAOI,KACrBxI,EAAKyI,QAAUL,EAAOM,IAEtB,IAAMC,GAAiB,IAAAC,uCAAsCR,EAAOS,YAAavV,KAAKuC,QACtFmK,EAAK8I,QAAUH,EAAeG,QACM,gBAAhCxV,KAAKuC,OAAO+K,kBACdZ,EAAK+I,aAAeJ,EAAeK,YATrC,CAWF,EAEQ,YAAAtH,wBAAR,SAAgC1B,G,MACxBiJ,EAA+C,QAA7B,EAAA3V,KAAKuC,OAAOqT,yBAAiB,eAAEC,MAAK,SAACC,GAAW,OAAc,IAAdA,EAAEC,OAAF,IAExErJ,EAAKsB,iBAAkB,IAAArI,cAAagQ,GACpCjJ,EAAKsJ,kBAAmB,IAAArQ,cAAagQ,GAAmBA,EAAgB5H,UAAO5N,CACjF,EAEQ,YAAAkO,+BAAR,SAAuC3B,GACrC,IAAMuJ,EAAejW,KAAKuC,OAAO2T,wBAC7B,IAAAvQ,cAAasQ,KACfvJ,EAAK+I,aAAeQ,EAAa5E,QACjC3E,EAAKyJ,oBAAsBF,EAAalE,OACxCrF,EAAK0J,mBAAqBH,EAAanE,MACvCpF,EAAK2J,WAAcJ,EAAqB3E,OAG1C,IAAMgF,EAAetW,KAAKuC,OAAOgU,wBAC7B,IAAA5Q,cAAa2Q,KACf5J,EAAK8J,aAAeF,EAAajF,QACjC3E,EAAK+J,WAAcH,EAAqBhF,MAE5C,EAEQ,YAAAhD,uBAAR,SAA+B5B,GAC7B,IAAMkB,EAAY5N,KAAKuC,OAAOqL,aAAe5N,KAAKuC,OAAOmU,oBAAqB,EAE9E,GADAhK,EAAKkB,UAAYA,EACZA,EAKL,GAAI5N,KAAKuC,OAAOmU,kBACdhK,EAAKiK,SAAW,EAAAC,SAASC,YAD3B,CAMA,IAAMC,EAAsB9W,KAAKuC,OAAOuU,oBACxC,KAAI,IAAAtI,WAAUsI,GAId,OAAQA,EAAoBrR,MAC1B,IAAK,aACHiH,EAAKiK,SAAW,EAAAC,SAASG,WACzB,MACF,IAAK,YACHrK,EAAKiK,SAAW,EAAAC,SAASI,UAb7B,CAgBF,EAIQ,YAAAzG,aAAR,SAAqBtR,GACnB,IAAMgY,EAAYhY,EAElB,OADuBiY,KAAKC,IAAIF,EAAUG,SAAWH,EAAUI,YACvCC,EAAkBC,uCAC5C,EAEO,EAAAlZ,OAAP,SAAckE,EAA8B6D,GAC1C,IAAMwD,EAAa,IAAI,EAAA4N,kBAAkBjV,EAAQ,IAAI,EAAAkV,oBAAsBC,wBACrE7N,EAAiB,IAAI,EAAA8N,sBAAsBpV,EAAQ,IAAI,EAAAqV,gBAAkBC,oBACzE9N,EAA6B,IAAI,EAAA+N,2BAA2BvV,GAGlE,OAAO,IAAIoG,EACTpG,EACAqH,EACAC,EAL6B,IAAI,UAOjCE,EANgC,IAAI,EAAAgO,0BAQpC3R,EAEJ,EACF,EAthBA,CAA8C,EAAA4R,iBAAjC,EAAArP,yBAAAA,C,mHC9Cb,cAEA,aACE,WAA6BsP,GAA7B,WAA6B,KAAAA,UAAAA,EAE7B,KAAA7U,GAAsB,SAAC8U,EAAWC,IAChC,IAAAC,aAAW,WAAM,SAAKH,UAAU7U,GAAG8U,EAAWC,EAA7B,GACnB,EAEA,KAAAnV,eAA2D,SAACqV,GAC1D,WAAAD,aAAW,WAAM,SAAKH,UAAUjV,eAAeqV,EAA9B,GAAjB,EAEF,KAAA7I,YAAqD,WAAM,WAAA4I,aAAW,WAAM,SAAKH,UAAUzI,aAAf,GAAjB,EAM3D,KAAAjF,cAAyD,WAAM,WAAA6N,aAAW,WAAM,SAAKH,UAAU1N,eAAf,GAAjB,EAE/D,KAAAsC,YAAqD,WAAM,WAAAuL,aAAW,WAAM,SAAKH,UAAUpL,aAAf,GAAjB,EAE3D,KAAAjK,aAAuD,WAAM,WAAAwV,aAAW,WAAM,SAAKH,UAAUrV,cAAf,GAAjB,EAE7D,KAAAsK,OAA2C,WAAM,WAAAkL,aAAW,WAAM,SAAKH,UAAU/K,QAAf,GAAjB,EAEjD,KAAAI,cAAyD,WAAM,WAAA8K,aAAW,WAAM,SAAKH,UAAU3K,eAAf,GAAjB,EAE/D,KAAAK,QAA6C,WAAM,WAAAyK,aAAW,WAAM,SAAKH,UAAUtK,SAAf,GAAjB,EAEnD,KAAAC,UAAiD,WAAM,WAAAwK,aAAW,WAAM,SAAKH,UAAUrK,WAAf,GAAjB,EAEvD,KAAA8I,gBAA6D,WAAM,WAAA0B,aAAW,WAAM,SAAKH,UAAUvB,iBAAf,GAAjB,EAEnE,KAAA5I,SAA+C,WAAM,WAAAsK,aAAW,WAAM,SAAKH,UAAUnK,UAAf,GAAjB,EAErD,KAAAI,UAAiD,WAAM,WAAAkK,aAAW,WAAM,SAAKH,UAAU/J,WAAf,GAAjB,EAEvD,KAAAC,sBAAyE,WACvE,WAAAiK,aAAW,WAAM,SAAKH,UAAU9J,uBAAf,GAAjB,EAEF,KAAA+H,qBAAuE,WACrE,WAAAkC,aAAW,WAAM,SAAKH,UAAU/B,sBAAf,GAAjB,EAEF,KAAAK,qBAAuE,WACrE,WAAA6B,aAAW,WAAM,SAAKH,UAAU1B,sBAAf,GAAjB,EAEF,KAAAnO,UAAiD,WAAM,WAAAgQ,aAAW,WAAM,SAAKH,UAAU7P,WAAf,GAAjB,EAMvD,KAAAwN,gBAA2D,WAAM,WAAAwC,aAAW,iBAAM,OAAwB,QAAxB,IAAKH,UAAUK,iBAAS,eAAEC,MAAM,GAAjD,EAEjE,KAAA5V,iBAA0E,WACxE,WAAAyV,aAAW,iBAAM,OAAkB,QAAlB,IAAKH,UAAUO,WAAG,eAAE7V,kBAAkB,GAAvD,EAEF,KAAAuC,YAAgE,WAC9D,WAAAkT,aAAW,iBAAM,OAAkB,QAAlB,IAAKH,UAAUO,WAAG,eAAEtT,aAAa,GAAlD,EAEF,KAAArC,gBAAsE,WACpE,WAAAuV,aAAW,iBAAM,OAAkB,QAAlB,IAAKH,UAAUO,WAAG,eAAEC,eAAe,GAApD,CA3DkD,CAgEtD,OArDE,sBAAI,sBAAO,C,IAAX,sBACE,OAAO,IAAAL,aAAW,WAAM,SAAKH,UAAUnV,OAAf,GAC1B,E,gCAiCA,sBAAI,kCAAmB,C,IAAvB,W,MACE,OAAuB,QAAhB,EAAA9C,KAAKoI,mBAAW,eAAEsQ,aAC3B,E,gCAaA,sBAAI,uBAAQ,C,IAAZ,W,QACE,OAAiC,QAA1B,EAAgB,QAAhB,EAAA1Y,KAAKoI,mBAAW,eAAEuQ,gBAAQ,eAAExV,QACrC,E,gCACF,EAjEA,GAAa,EAAAyF,qBAAAA,C,qFCQb,8BAAmClJ,EAAwBkZ,G,MACnDC,EAAiC,CACrCD,WAAU,GAGNE,EAAapZ,EACbqZ,EAAYD,EAAW9F,KAC7B,IAAI,IAAArN,cAAaoT,KACfF,EAAehG,KAAOkG,EAAUlG,MAAQiG,EAAWjG,KACnDgG,EAAe/F,QAAUiG,EAAUjG,SAAWgG,EAAWzZ,KAErD,YAAa0Z,GAAa,aAAcA,GAAW,CACrD,IAAMC,EAA0B,QAAjB,EAAAD,EAAU3U,eAAO,QAAI2U,EAAUzT,SAC9CuT,EAAenT,YAAcvB,EAAmB6U,EAClD,CAGF,OAAOH,CACT,EAEA,yBAA8B/U,G,0BACtBkV,EAAiB,CACrB7T,GAAIrB,EAAGqB,GACP8T,SAAUnV,EAAGmV,SACbxU,gBAAiBX,EAAGW,gBACpBqN,MAAOhO,EAAGgO,MACVC,OAAQjO,EAAGiO,QAGPmH,EAAWpV,EAAGmV,SAAYnV,OAAwB3D,GACpD,IAAAwF,cAAauT,KACfF,EAAOG,SAAWD,EAASC,SAC3BH,EAAOI,WAAY,IAAAzT,cAAauT,EAASG,gBACzCL,EAAOK,eAAiBH,EAASG,eACjCL,EAAOM,SAAWJ,EAASK,cAG7B,IAAMC,EAAW1V,EAAGkP,MAChB,IAAArN,cAAa6T,KACfR,EAAO3H,QAAUmI,EAASnI,QAC1B2H,EAAOS,SAAWD,EAASC,SAC3BT,EAAOQ,SAAW,CAChBE,SAA2B,QAAjB,EAAAF,EAASE,gBAAQ,eAAEra,KAC7Bsa,eAAmC,QAAnB,EAAAH,EAASI,kBAAU,eAAEva,KACrCwa,aAAcL,EAASK,aACvBC,aAA+B,QAAjB,EAAAN,EAASO,gBAAQ,eAAEC,KACjCC,WAA6B,QAAjB,EAAAT,EAASO,gBAAQ,eAAE5U,GAC/B+U,sBAAuD,QAAhC,EAAiB,QAAjB,EAAAV,EAASO,gBAAQ,eAAEI,qBAAa,eAAEC,WACzDC,mBAAoD,QAAhC,EAAiB,QAAjB,EAAAb,EAASO,gBAAQ,eAAEI,qBAAa,eAAEG,MACtDC,cAAef,EAASe,cACxBC,QAAShB,EAASgB,QAClBC,gBAA8C,QAA7B,EAAqB,QAArB,EAAAjB,EAASkB,oBAAY,eAAEnb,cAAM,QAAI,EAClDob,UAA0B,QAAf,EAAAnB,EAASoB,cAAM,eAAEC,IAC5BC,qBAAsBtB,EAASsB,uBAInC,OAAO9B,CACT,EAEA,uBA0BA,0BA2BA,qBApHA,cA+DA,SAAgB7U,EAAmBmB,GACjC,IAAMI,EAA2B,CAC/BqV,uBAAwBzV,EAASyV,uBACjCC,cAAeC,EAAiB3V,IAIlCI,EAAYP,GAAK,OAAQG,EAAWA,EAASH,QAAKhF,EAClDuF,EAAYwV,aAAe,iBAAkB5V,EAAWA,EAAS4V,kBAAe/a,EAGhF,IAAMkF,EAAcC,EACd,EAAoB6V,EAAsB9V,GAAzC+V,EAAM,SAAEC,EAAO,UAOtB,OANA3V,EAAY0V,OAASA,EACrB1V,EAAY2V,QAAUA,EACtB3V,EAAY4V,WAAa,eAAgBhW,EAAWD,EAAYiW,gBAAanb,EAC7EuF,EAAY0R,SAAW,aAAc9R,EAAYA,EAAiC8R,cAAWjX,EAC7FuF,EAAY6V,cAAgB,kBAAmBjW,EAAYA,EAAiCiW,mBAAgBpb,EAErGuF,CACT,CAMA,SAAgByV,EAAsB9V,GACpC,IAAI,IAAAmJ,WAAUnJ,EAAYG,KACxB,MAAO,CAAC,EAGV,IAAMwV,EAAgBC,EAAiB5V,GACjCmW,EAAY,CAACH,QAAShW,EAAYG,IAAIC,KAAM2V,OAAQ/V,EAAYG,IAAIiW,KAC1E,IAAI,IAAAjN,WAAUnJ,EAAYqW,eAAiBV,GAAiB,GAAK3V,EAAYqW,aAAanc,OAASyb,EACjG,OAAOQ,EAGT,IAAMG,EAActW,EAAYqW,aAAaV,EAAgB,GAC7D,MAAO,CAACK,QAASM,EAAYlW,KAAM2V,OAAQO,EAAYF,IACzD,CAcA,SAAgBR,EAAiB3V,GAC/B,IAAMsW,EAAoBtW,EAAiBuW,qBAE3C,OAAI,IAAArN,WAAUoN,GACL,EAGFA,CACT,C,oJCxIA,cAWa,EAAAjV,sDAAwD,SAAcmV,GACjF,IAAMC,EAA2BD,EAYjC,OAVI,IAAAnW,cAAaoW,aAAwB,EAAxBA,EAA0BC,cACe,aAAnDD,EAAyBC,WAC5BD,EAAyBC,WAAa,UACuB,aAAnDD,EAAyBC,WACnCD,EAAyBC,WAAa,UACwB,eAApDD,aAAwB,EAAxBA,EAA0BC,cACpCD,EAAyBC,WAAa,aAInCD,CACT,C,mHCRa,EAAA1Y,uBAAyB,CACpCgB,gBAAiB,kBACjBJ,eAAgB,iBAChBM,UAAW,YACXQ,QAAS,UACThB,WAAY,aACZqB,iBAAkB,mBAClBV,WAAY,aACZG,UAAW,YACXlB,UAAW,YACXuQ,aAAc,eACdnD,4BAA6B,8BAC7BnB,YAAa,cACbE,YAAa,cACb+E,QAAS,UACThB,iBAAkB,mBAClB9V,MAAO,QACPwW,iBAAkB,mBAClB/B,MAAO,QACP/O,OAAQ,SACRH,KAAM,OACNqQ,iBAAkB,mBAClB1D,QAAS,UACTK,KAAM,OACNG,OAAQ,SACRwL,gBAAiB,kBACjB1M,aAAc,eACdH,eAAgB,iBAChByB,WAAY,aACZF,aAAc,eACdP,YAAa,cACbkE,iBAAkB,mBAClBF,gBAAiB,kBACjB1B,QAAS,UACTd,4BAA6B,8BAC7BO,gBAAiB,kB,yHCNnB,uBA7CA,aACA,UAEA,UACA,UAGA,UAEA,aAGE,WAAY5P,GAAZ,WAFQ,KAAA2Z,gBAAkB,IAAI,EAAAC,gBAG5B5Z,EAAOa,GAAG,EAAAC,uBAAuBwQ,kBAAkB,SAACnU,GAClD,SAAK0c,mBAAmB1c,EAAxB,GAEJ,CAwBF,OAtBE,YAAA2c,UAAA,SAAUlE,GACR,OAAOnY,KAAKkc,gBAAgBG,UAAUlE,EACxC,EAEA,YAAAmE,YAAA,SAAYnE,GACVnY,KAAKkc,gBAAgBI,YAAYnE,EACnC,EAEQ,YAAAiE,mBAAR,SAA2B1c,G,UACzBM,KAAKkc,gBAAgB1I,SAAS,CAC5B+I,YAAa,CACXzW,aAA6D,QAA/C,OAAA0W,4BAA2B9c,aAAK,EAALA,EAAOoG,qBAAa,QAAI,EACjE2W,WAA6B,QAAjB,EAAA/c,aAAK,EAALA,EAAO+c,kBAAU,QAAI,EACjCC,QAAuB,QAAd,EAAAhd,aAAK,EAALA,EAAOgd,eAAO,SACvB7Q,WAAW,IAAA8Q,uBACXlB,IAAK/b,aAAK,EAALA,EAAO+b,IACZ7O,KAAMlN,aAAK,EAALA,EAAOkN,KACbgQ,iBAAiB,IAAAJ,4BAA2B9c,aAAK,EAALA,EAAOkd,iBACnDnX,KAAMoX,EAAmBnd,aAAK,EAALA,EAAOoU,gBAGtC,EACF,EA/BA,GAoCA,SAAgB+I,EAAmBC,GACjC,OAAI,IAAAC,cAAa,EAAAC,iBAAiBC,SAASH,GAClCA,EAKF,EAAAE,gBAAgBE,OACzB,CA5Ca,EAAApF,2BAAAA,C,oHCTb,cAGA,UAyBA,aAGE,WAAYvV,EAA8BsH,GAA1C,WAuBA,KAAAsT,2BAA6B,SAACzd,GAC5B,EAAKmK,eAAeuT,cAAc1d,EAAM+b,IAC1C,EAxBEzb,KAAK6J,eAAiBA,EAEtBtH,EAAOa,GAAG,EAAAC,uBAAuBwQ,kBAAkB,SAACnU,GAAU,SAAK2d,4BAA4B3d,EAAjC,IAC9D6C,EAAOa,GAAG,EAAAC,uBAAuB4Y,iBAAiB,SAACvc,GAAU,SAAKyd,2BAA2Bzd,EAAhC,GAC/D,CAqBF,OAnBE,YAAAmY,kBAAA,WACE,OAAO7X,KAAK6J,cACd,EAEA,YAAAwT,4BAAA,SAA4B3d,GAC1B,GAAkD,IAA9CA,EAAMoU,aAAa/T,QAAQ,eAAsB,CACnD,IAAM0b,EAAM/b,EAAM+b,IACZ6B,EAAuB,CAC3Bje,KAAMke,EAAMC,mBAAmB/B,GAC/BA,IAAG,EACH5P,UAAWnM,EAAMmM,WAEnB7L,KAAK6J,eAAe4T,WAAWH,EACjC,CACF,EAKF,EA7BA,GAAa,EAAA3F,sBAAAA,C,+GC3Bb,cAEA,aAGE,WAAYpV,EAA8Bmb,GAA1C,WACE1d,KAAK0d,MAAQA,EACbnb,EAAOa,GAAG,EAAAC,uBAAuBwQ,kBAAkB,SAACnU,GAAU,SAAK2d,4BAA4B3d,EAAjC,GAChE,CAoBF,OAlBE,YAAAgY,sBAAA,WACE,OAAO1X,KAAK0d,KACd,EAEA,YAAAL,4BAAA,SAA4B3d,GACrBA,EAAMgd,SAGuC,IAA9Chd,EAAMoU,aAAa/T,QAAQ,gBAC7BC,KAAK0d,MAAMC,eAAe,CACxBxE,SAAUzZ,EAAMoG,aAChB8G,KAAMlN,EAAMkN,KACZgQ,gBAAiBld,EAAMkd,gBACvB/Q,UAAW,IAAI+R,KACfnB,WAAY/c,EAAM+c,YAGxB,EACF,EA1BA,GAAa,EAAAjF,kBAAAA,C,0GCLb,cAKa,EAAAqG,aAAe,CAC1Bxe,KAAM,YACNjC,OAAQ,CACNyL,UAAW,EAAAa,kBAEboU,MAAO,CACLC,MAAO,SAAC3gB,EAAamF,GACnB,IAAMkH,EAASlH,EAAO6F,YAChB4V,GAAmBvU,EACnBwU,GAA4C,KAAtBxU,aAAM,EAANA,EAAQvC,WAEpC,GAAI8W,GAAmBC,EACrB,OAAOC,QAAQC,UAGjB,IACMC,EAA0B,IAAIC,EADFjhB,EAAOyL,WACqBtG,GAC9D,OAAO2b,QAAQC,QAAQC,EACzB,G,iHCpBJ,cAEA,UACA,UACA,UAEA,QAGA,aAIE,WAAYE,EAA2B7U,GAAvC,WAyBA,KAAAL,uBAAyB,WAAM,SAAKlC,UAAUkC,wBAAf,EAE/B,KAAAC,UAAY,WAAM,SAAKnC,UAAUmC,WAAf,EAElB,KAAAC,cAAgB,SAACC,GAA6B,SAAK9C,gBAAgB6C,cAAcC,EAAnC,EAE9C,KAAAC,kBAAoB,SAACD,GAA6B,SAAKrC,UAAUsC,kBAAkBD,EAAjC,EAElD,KAAAL,aAAe,SAACqV,GAed,MAAM,IAAIxgB,MAAM,0BAClB,EA7CE,IAAMsK,GAAkB,IAAAC,yBAAwBmB,GAChD,KAAK,IAAAlB,+BAA8BF,GACjC,MAAM,IAAItK,MAAM,4DAGlB,IAAAyK,8BAA6BH,GAE7BrI,KAAKyG,gBAAkB,IAAI,EAAA+X,2BAA2BF,GACtDte,KAAKkH,UAAY,EAAA2B,UAAUxK,OAAOgK,EAAiBrI,KAAKyG,gBAC1D,CAqCF,OAnCE,YAAAgY,QAAA,WACEze,KAAKyG,gBAAgBmO,SACvB,EAIA,sBAAI,sBAAO,C,IAAX,WACE,OAAO,EAAAnX,OACT,E,gCAJgB,EAAAqF,QAAkB,EAAArF,QA+BpC,C,CAtDA,GAAa,EAAAihB,mBAAAA,C,0HCTb,IAoBwCrf,EAAMsf,EAAOC,EApBrD,UAEA,UACA,UA0Ba,EAAAC,6BAT2Bxf,EAUtC,oBAV4Csf,EAW5C,SAACG,EAAGC,G,QAOI,EAAmDA,EAAYC,SAASC,IAAI,EAAAC,gBAAgBC,aAA3FC,EAA0B,6BAAEC,EAAkB,qBAC/Cf,EAAUS,EAAYO,MAAMF,EAA4BC,GACxDrX,EAASsW,EAAQU,SAASC,IAAI,EAAAM,kBAAkBC,QAChD1K,EAASwJ,EAAQU,SAASC,IAAI,EAAAQ,kBAAkBC,aAChDvX,EAAemW,EAAQU,SAASC,IAAI,EAAAM,kBAAkBI,cACtD1W,EAAwC,QAAtB,EAAAd,EAAajB,iBAAS,QAAI,CAAC,EAEnD+B,EAAgBR,UAAqC,QAAzB,EAAAQ,EAAgBR,iBAAS,QAAIN,EAAaO,IAEtEV,EAAO4X,IAAI,qCAA6B,IAAAzM,kBAAiBlK,KACzD,IAAM4W,EAAU,IAAI,EAAAnB,mBAAmBJ,EAASrV,GAEhDjB,EAAO4X,IAAI,8CAAuC9K,EAAO2G,IAAG,SAE5D,IAAMqE,EAAW,WACfxB,EAAQyB,YAAYC,oBAAoB,QAASF,GACjD9X,EAAO4X,IAAI,2CAAoC9K,EAAO2G,IAAG,MACzDoE,EAAQpB,SACV,EAEAH,EAAQyB,YAAY7Z,iBAAiB,QAAS4Z,EAChD,EAvCmDlB,EAwCnD,CACE,EAAAW,kBAAkBC,OAClB,EAAAD,kBAAkBI,aAClB,EAAAT,gBAAgBe,UAChB,EAAAf,gBAAgBC,YAChB,EAAAD,gBAAgBgB,eAChB,EAAAT,kBAAkBC,YAClB,EAAAS,sBAAsBC,eACtB,EAAAC,oCAAoCC,eA/CrC3B,EAAc4B,MAAQlhB,EAEhB,CACLsf,MAAK,EACLC,aAAY,G,smBC5BhB,IAmBY4B,EAnBZ,UAEA,UACA,UAQA,UAGA,UACA,UACA,UACA,WAEA,SAAYA,GACV,YACA,gBACA,gBACA,oBACA,gBACA,gBACA,gCACA,oBACA,uCACD,CAVD,CAAYA,IAAK,QAALA,EAAK,KAYjB,kBAIE,WACExV,EACAL,EACAvE,GAEA,QAAK,UAAC4E,EAAuBL,EAAyBvE,IAAK,K,OARrD,EAAAqa,kBAAmB,EACnB,EAAAC,gBAAoC,G,CAQ5C,CA+KF,OAzLsD,OAY3C,YAAAC,mBAAT,SAA4Bva,G,MAA5B,OACE,OAAO,EAAA5I,aAAaa,OAAO,CAGzBG,QAAS,CAACC,MAAO+hB,EAAMI,MAAOlhB,MAAO,EAAAmhB,mBACrCtgB,MAAO,EAAAugB,gCACPliB,OAAQ,CACN,CACES,KAAM,EAAA6P,MAAMS,cACZzQ,KAAM,CAACshB,EAAMI,MAAOJ,EAAM5N,OAC1BnT,GAAI+gB,EAAMO,QAEZ,IAAA3d,IAAG,EAAA8L,MAAM6R,OAAOC,OAAOR,EAAMO,QAC7B,IAAA3d,IAAG,EAAA8L,MAAMiB,OAAO6Q,OAAOR,EAAMO,QAC7B,IAAA3d,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMO,OACnC,CAAC1hB,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAMO,MAAOthB,GAAI+gB,EAAMS,SAChD,CAAC5hB,KAAM,EAAA6P,MAAMgB,QAAShR,KAAMshB,EAAMO,MAAOthB,GAAI+gB,EAAMtQ,UAEnD,IAAA9M,IAAG,EAAA8L,MAAMc,MAAMgR,OAAOR,EAAMS,UAC5B,IAAA7d,IAAG,EAAA8L,MAAMgB,SAAS8Q,OAAOR,EAAMS,SAC/B,CAAC5hB,KAAM,EAAA6P,MAAMmB,YAAanR,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMtQ,UACzD,IAAA9M,IAAG,EAAA8L,MAAM6R,OAAOC,OAAOR,EAAMS,SAC7B,CAAC5hB,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMO,QAEnD,IAAA3d,IAAG,EAAA8L,MAAMgB,SAAS8Q,OAAOR,EAAMtQ,UAC/B,IAAA9M,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMtQ,SAEnC,CAAC7Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMrQ,QACnD,IAAA/M,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMrQ,QACnC,IAAA/M,IAAG,EAAA8L,MAAMiB,OAAO6Q,OAAOR,EAAMrQ,OAC7B,CAAC9Q,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMtQ,SAChD,CAAC7Q,KAAM,EAAA6P,MAAMgB,QAAShR,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMtQ,SAEnD,CAAC7Q,KAAM,EAAA6P,MAAM0E,IAAK1U,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAM5M,KACjD,CAACvU,KAAM,EAAA6P,MAAM0E,IAAK1U,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAM5M,KAG/C,CAACvU,KAAM,EAAA6P,MAAMgB,QAAShR,KAAMshB,EAAM5M,IAAKnU,GAAI+gB,EAAMS,UAEjD,IAAA7d,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAM5M,MACnC,IAAAxQ,IAAG,EAAA8L,MAAM0E,KAAKoN,OAAOR,EAAM5M,KAE3B,CAACvU,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAM5M,IAAKnU,GAAI+gB,EAAMS,SAC9C,CAAC5hB,KAAM,EAAA6P,MAAM0D,MAAO1T,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMU,mBACnD,CAAC7hB,KAAM,EAAA6P,MAAM0D,MAAO1T,MAAM,IAAAiiB,iBAAgB,CAACX,EAAMS,SAAUT,GAAQ/gB,GAAI+gB,EAAM5N,OAE7E,CAACvT,KAAM,EAAA6P,MAAMyF,OAAQzV,MAAM,IAAAiiB,iBAAgB,CAACX,EAAMS,SAAUT,GAAQ/gB,GAAI+gB,EAAM5M,KAC9E,CAACvU,KAAM,EAAA6P,MAAMyF,OAAQzV,KAAM,CAACshB,EAAMS,SAAUxhB,GAAI+gB,EAAMU,oBAUxDriB,WAAS,KACP,EAAC,iBAAU2hB,EAAMtQ,UAAY,WAC3B,EAAKvF,wBAAwByW,eAC/B,EAEA,EAAAC,aAAc,SAAC3hB,EAAOR,EAAMO,EAAI6hB,EAAgBtQ,GAM9C,IALA,IAAAuQ,2BAA0B,QAAS7hB,EAAOR,EAAMO,GAK5CC,IAAU,EAAAmhB,mBAQTS,EAAL,CAIA,EAAKE,eAAe9hB,EAAOR,EAAMO,EAAI6hB,EAAgBtQ,GACrD,IAAMyQ,EAAgBH,EAAiB,EAAKI,sBACtCC,EAAYziB,IAASshB,EAAMS,SAAWxhB,IAAO+gB,EAAMtQ,QACzD,EAAK0R,kCAAkC1iB,EAAMO,GAEzCkiB,GACF,EAAK3W,sBAAsB6W,QAAQJ,EAAejB,EAAMS,QAAQa,eAGlE,IAAMC,EAAgBC,OAAO9iB,GAAM4iB,cACnC,GAAIpiB,IAAU,EAAAwP,MAAMyF,OAClB,EAAK3J,sBAAsBiX,OAAOR,EAAeM,QAC5C,GAAI7iB,IAASshB,EAAMI,MAGxB,EAAK5V,sBAAsB+S,MAAM,EAAGyC,EAAMI,MAAMkB,oBAC3C,GAAIpiB,IAAU,EAAAwP,MAAMiB,OAASjR,IAASshB,EAAMS,SAAWxhB,IAAO+gB,EAAMO,MAGzE,EAAKmB,8BACA,GAAIhjB,IAASshB,EAAM5N,QAAU+O,EAAW,CAK7C,IAAMQ,EAAgC,EAAKnX,sBAAsB+W,GACjE,IAAI,IAAAK,YAAWD,GAEb,IACEA,EAA8BV,EAAeM,EAAe/Q,EAC9D,CAAE,MAAO/R,GACP,EAAA+I,OAAOzH,MAAM,gDAAkDwhB,EAAe/Q,EAAW/R,EAC3F,MAOA,IAAAojB,2BAA0BnjB,EAAM,CAACshB,EAAMO,OAE3C,CA3CA,CA4CF,EAEA,EAAC,iBAAUP,EAAMtQ,UAAY,WAC3B,EAAKvF,wBAAwB2X,gBAC/B,EAEA,EAAAC,aAAc,SAAC7iB,EAAOR,EAAMO,EAAI6hB,EAAgBkB,IAC9C,IAAAjB,2BAA0B,QAAS7hB,EAAOR,EAAMO,GAEhD,EAAKiiB,sBAAwBJ,QAAAA,EAAkB1D,KAAK6E,OAGhD,IAAAC,UAAStc,EAAKuc,YAAcjjB,IAAU,EAAAmhB,oBACxC,EAAKa,sBAAwBtb,EAAKuc,UAEtC,EAEA,EAAC,iBAAU,EAAAzT,MAAM0D,QAAU,SAACvD,EAAQuT,EAAOC,EAAKC,EAAiB9R,GAC/D,EAAKhG,sBAAsBzK,MAAMyQ,EACnC,E,IAGN,EAEA,YAAAwQ,eAAA,SACE9hB,EACAR,EACAO,EACAoM,EACAkX,GAEI/iB,KAAKygB,kBACPzgB,KAAK0gB,gBAAgBlhB,KAAK,IAAI,EAAAwjB,eAAetjB,EAAOR,EAAMO,EAAIoM,EAAWkX,GAE7E,EAEA,YAAAE,UAAA,WACE,OAAOjjB,KAAK0gB,eACd,EAEA,YAAAwC,oBAAA,SAAoBnN,GAClB/V,KAAKygB,iBAAmB1K,CAC1B,EAEQ,YAAA6L,kCAAR,SAA0C1iB,EAA0BO,GAC9DP,IAASshB,EAAMO,OAASthB,IAAO+gB,EAAMS,QACvCjhB,KAAKmjB,uBACIjkB,IAASshB,EAAMS,SAAWxhB,IAAO+gB,EAAMtQ,SAChDlQ,KAAKkiB,wBAET,EACF,EAzLA,CAAsD,EAAAkB,uBAAzC,EAAAC,iCAAAA,C,2zBC9Bb,cACA,UACA,SACA,UACA,UACA,UAKA,UACA,UAGA,UACA,UAUA,cAME,WAAY/E,EAA2BlY,GACrC,QAAK,UAACA,IAAK,KALL,EAAA6D,qBAAsB,EAM5B,EAAKqU,QAAUA,EACf,IAAM3T,EAA0B,IAAI,EAAAC,kBAAiB,WAAM,SAAK7H,WAAL,IACrD+H,EAAe,IAAI,EAAAuY,iCACvB,EAAKrY,sBACLL,EACA,EAAKvE,M,OAEPuE,EAAwBM,YAAYH,GACpC,EAAKA,aAAeA,E,CACtB,CA4IF,OA7JgD,OAmBtC,YAAAoD,UAAR,WACE,OAAOlO,KAAKse,QAAQU,SAASC,IAAI,EAAAQ,kBAAkBC,YACrD,EAEA,sBAAc,0BAAW,C,IAAzB,WACE,OAAO1f,KAAKkO,YAAYyK,SAAS2K,SAASlM,QAC5C,E,gCAEA,YAAAlU,YAAA,WACE,OAAOlD,KAAKkO,YAAYzE,OAAOkP,SAASxV,QAC1C,EAEA,YAAAqJ,uBAAA,W,kBACQ4I,EAAuF,QAAjF,EAAApV,KAAKkO,YAAYqV,aAAaC,UAAUC,QAAO,SAACC,GAAM,OAAAA,EAAEjI,IAAIwB,SAAS,QAAf,IAAyB,UAAE,eAAExB,IACzFvG,EAAuF,QAAhF,EAAAlV,KAAKkO,YAAYqV,aAAaC,UAAUC,QAAO,SAACC,GAAM,OAAAA,EAAEjI,IAAIwB,SAAS,OAAf,IAAwB,UAAE,eAAExB,IAEzFkI,EAA0C,QAA9B,EAAA3jB,KAAKkO,YAAY0V,MAAMC,eAAO,eAAEC,wBAC5CC,EAAa7M,KAAK8M,MAAsB,QAAhB,EAAAL,aAAS,EAATA,EAAW7R,aAAK,QAAI,GAC5CmS,EAAc/M,KAAK8M,MAAuB,QAAjB,EAAAL,aAAS,EAATA,EAAW5R,cAAM,QAAI,GAEhD1E,OAAwClN,EAQ5C,OAPIiV,EACF/H,EAAe,EAAA6W,YAAY9O,IAClBF,IACT7H,EAAe,EAAA6W,YAAYhP,MAItB,EAAP,KACKlV,KAAK2M,yBAAuB,CAC/BsB,cAAe,EACfN,QAAuC,QAA9B,EAAA3N,KAAKkO,YAAY0V,MAAMC,eAAO,eAAEM,MACzCjX,OAAyC,SAAjClN,KAAKkO,YAAYkW,OAAO3e,KAChCgI,kBAAmBwW,EACnB1W,iBAAkBwW,EAClB5W,eAAe,IAAAC,wBAAqD,QAA9B,EAAApN,KAAKkO,YAAY0V,MAAMC,eAAO,eAAE1K,UACtEhD,oBAAqB8N,EACrB7N,mBAAoB2N,EACpB5O,QAASC,EACTH,OAAQC,EACR7H,aAAY,EACZgJ,gBAAYlW,EACZsW,gBAAYtW,EACZsV,aAAc,EACde,aAAc,GAElB,EAEA,YAAArM,cAAA,WACE,OAAO,EAAAC,OAAOia,YAChB,EAEA,YAAA/Z,cAAA,WACE,MAAO,YACT,EAEA,YAAAJ,iBAAA,WACE,OAAOlK,KAAKse,QAAQU,SAASC,IAAI,EAAAC,gBAAgBe,WAAWqE,OAC9D,EAEA,YAAAlZ,WAAA,SAAWlE,GAWT,OAVAlH,KAAKukB,yBACLvkB,KAAKsL,+BASE,CAPqB,IAAI,EAAAY,oBAC9BhF,EAAUiF,oCACV,IAAI,EAAAC,mBAAmBlF,EAAUiF,oCAAoCE,iBACrE,CAACnF,EAAUoF,8BACXnM,GAIJ,EAEQ,YAAAmL,6BAAR,sBACMoJ,EAAwB,WAC1B,IAAK,EAAKzK,oBAAqB,CAC7B,EAAKA,qBAAsB,EAC3B,IAAMlH,EAAc,EAAKub,QAAQU,SAASC,IAAI,EAAAQ,kBAAkBC,aAAa/G,SAAS2K,SAASlM,SAC/F,EAAKnI,cAAc,EAAAC,MAAMyF,OAAQ,CAAC5R,YAAW,GAC/C,CACA,EAAK6R,SACP,EACAF,EAAwBA,EAAsB8P,MAAK,GAEnDxkB,KAAKse,QAAQyB,YAAY7Z,iBAAiB,QAASwO,GACnD1U,KAAKwC,mBAAmB0D,iBAAiB,eAAgBwO,GACzD1U,KAAKwC,mBAAmB0D,iBAAiB,SAAUwO,EACrD,EAEQ,YAAA6P,uBAAR,sBAEQE,EAAiBzkB,KAAKse,QAAQU,SAASC,IAAI,EAAAkB,sBAAsBC,gBACjEsE,EAAe1kB,KAAKse,QAAQU,SAASC,IAAI,EAAAQ,kBAAkBC,aAAa/G,SACxE2H,EAAgBtgB,KAAKse,QAAQU,SAASC,IAAI,EAAAoB,oCAAoCC,eAEpFmE,EAAerhB,GAAGkd,EAAcqE,OAAO,WACrC,EAAK1V,cAAc,EAAAC,MAAMS,cAAe,CAAC5M,YAAa2hB,EAAapB,SAASlM,UAC9E,IACAqN,EAAerhB,GAAGkd,EAAchd,MAAM,WACpC,EAAK2L,cAAc,EAAAC,MAAMc,KAAM,CAACjN,YAAa2hB,EAAapB,SAASlM,UACrE,IACAqN,EAAerhB,GAAGkd,EAAcrQ,SAAS,WACvC,EAAKhB,cAAc,EAAAC,MAAMgB,QAAS,CAACnN,YAAa2hB,EAAapB,SAASlM,UACxE,IACAqN,EAAerhB,GAAGkd,EAAc7c,QAAQ,WACtC,EAAKwL,cAAc,EAAAC,MAAMiB,MAAO,CAACpN,YAAa2hB,EAAapB,SAASlM,UACtE,IACAqN,EAAerhB,GAAGkd,EAAclQ,aAAa,WAC3C,EAAKnB,cAAc,EAAAC,MAAMmB,YAAa,CAACtN,YAAa2hB,EAAapB,SAASlM,UAC5E,IACAqN,EAAerhB,GAAGkd,EAAcsE,eAAe,WAC7C,EAAK3V,cAAc,EAAAC,MAAMS,cAAe,CAAC5M,YAAa2hB,EAAapB,SAASlM,UAC9E,IAEAqN,EAAerhB,GAAGkd,EAAcuE,OAAO,WACrC,EAAK5V,cAAc,EAAAC,MAAM0E,IAAK,CAAC7Q,YAAa2hB,EAAapB,SAASlM,UACpE,IAEA,IAAM0N,EAAgB,WACpB,IAAMC,EAAoB,EAAKzG,QAAQyB,YAAYiF,OACpB,uBAA3BD,EAAkB1lB,MAA4D,2BAA3B0lB,EAAkB1lB,KACvE,EAAK4P,cAAc,EAAAC,MAAMI,gBAAiB,CAACvM,YAAa2hB,EAAapB,SAASlM,WAE9E,EAAKnI,cAAc,EAAAC,MAAM0D,MAAO,CAC9B7P,YAAa2hB,EAAapB,SAASlM,SACnCvE,KAnJmB,KAoJnBC,QAASiS,EAAkBjS,QAC3BE,KAAM+R,EACN9R,cAAe8R,IAInB,EAAKzG,QAAQyB,YAAYC,oBAAoB,QAAS8E,EACxD,EAEA9kB,KAAKse,QAAQyB,YAAY7Z,iBAAiB,QAAS4e,EACrD,EACF,EA7JA,CAAgD,EAAA9M,iBAAnC,EAAAwG,2BAAAA,C,kNCTA,EAAAe,kBAAoB,CAC/BC,OAHyE,SAIzEG,aAH+E,iBAUpE,EAAAT,gBAAkB,CAC7B3B,MALoE,QAMpE0C,UALwE,YAMxEd,YAL0E,eAM1Ee,eAL6E,oBAUlE,EAAAG,oCAAsC,CACjDC,cAFA,kBASW,EAAAb,kBAAoB,CAC/BwF,sBALwF,2BAMxFC,sBALwF,0BAMxFC,iBALmF,oBAMnFzF,YAL8E,qBAWnE,EAAAS,sBAAwB,CACnCiF,iBAJ0F,qBAK1FC,kBAJ2F,sBAK3FjF,eAJwF,mB,2GCnD1F,cAIA,UACA,UACA,UACA,UAKA,UAGA,UAEA,aAIE,WAAY3W,EAAyB6b,EAA0Blf,GAC7D,IAAI,IAAA2B,+BAA8Bud,GAChC,EAAAtd,OAAOC,mBAAmB,oFAD5B,EAIA,IAAAC,+BAA8Bod,GAE9B,IAAMjd,GAAkB,IAAAC,yBAAwBmB,IAC3C,IAAAlB,+BAA8BF,MAInC,IAAAG,8BAA6BH,GAE7BrI,KAAKyG,gBAAkB,IAAI,EAAA8e,qBAAqBD,EAAqBlf,GACrEpG,KAAKkH,UAAY,EAAA2B,UAAUxK,OAAOgK,EAAiBrI,KAAKyG,iBAXxD,CAYF,CAqCF,OAjCE,sBAAI,sBAAO,C,IAAX,WACE,OAAO,EAAAhJ,OACT,E,gCAEA,YAAA2L,uBAAA,WACE,IAAK,IAAA5C,WAAUxG,KAAKkH,WAEpB,OAAOlH,KAAKkH,UAAUkC,wBACxB,EAEA,YAAAC,UAAA,WACE,IAAK,IAAA7C,WAAUxG,KAAKkH,WAEpB,OAAOlH,KAAKkH,UAAUmC,WACxB,EAEA,YAAAC,cAAA,SAAcC,IACP,IAAA/C,WAAUxG,KAAKyG,kBAEpBzG,KAAKyG,gBAAgB6C,cAAcC,EACrC,EAEA,YAAAC,kBAAA,SAAkBD,IACX,IAAA/C,WAAUxG,KAAKkH,YAEpBlH,KAAKkH,UAAUsC,kBAAkBD,EACnC,EAEA,YAAAL,aAAA,SAAaO,IACN,IAAAjD,WAAUxG,KAAKkH,YAEpBlH,KAAKkH,UAAUgC,aAAaO,EAC9B,EAlCgB,EAAA3G,QAAkB,EAAArF,QAmCpC,C,CAzDA,GAAa,EAAA+nB,aAAAA,C,uzBCyLb,4CAxMA,cAEA,UACA,UACA,SACA,UACA,UACA,UAMA,UACA,UACA,UACA,UAGA,SACA,UAEA,cAOE,WAAYF,EAA0Clf,GACpD,QAAK,UAACA,IAAK,KAJL,EAAA6D,qBAAsB,EACtB,EAAAwb,iBAA4B,GA0BpC,EAAAvb,iBAAmB,mBAAM,OAAwB,QAAxB,EAAe,QAAf,EAAI,OAAJwb,WAAI,IAAJA,UAAI,EAAJA,KAAMC,iBAAS,eAAEloB,eAAO,QAAI,SAAS,EAC9D,EAAA0M,cAAgB,WAAM,SAAAC,OAAOwb,gBAAP,EACtB,EAAAtb,cAAgB,WAAM,eACtB,EAAApH,YAAc,qBAAM,OAAgE,QAAhE,EAAsD,QAAtD,EAAoC,QAApC,IAAK2iB,cAAcC,yBAAiB,eAAEC,wBAAgB,eAAE5iB,gBAAQ,QAAS,EACpF,EAAAqH,sBAAwB,WAAsC,SAAKC,kBAAL,EA1BrE,IAAME,EAA0B,IAAI,EAAAC,kBAAiB,WACnD,OAAA0a,EAAoBU,mBAAmBC,mBAAvC,IAEInb,EAAe,IAAI,EAAAob,2BAA2B,EAAKlb,sBAAuBL,EAAyB,EAAKvE,M,OAC9GuE,EAAwBM,YAAYH,GACpC,EAAK+a,cAAgB,IAAI,EAAAM,iBAAiBb,EAAoBU,oBAC9D,EAAKlb,aAAeA,E,CACtB,CAgJF,OAhK0C,OAkBxC,YAAAM,WAAA,SAAWlE,GAUT,OATAlH,KAAKomB,sCACLpmB,KAAKqmB,qCAQE,CANqB,IAAI,EAAAna,oBAC9BhF,EAAUiF,oCACV,IAAI,EAAAC,mBAAmBlF,EAAUiF,oCAAoCE,iBACrE,CAACnF,EAAUoF,8BACXnM,GAGJ,EAOA,YAAAqM,uBAAA,W,UACQ8Z,EAAQtmB,KAAK6lB,cAAcU,WAG3BC,EAAyC,QAArB,EAAAxmB,KAAKylB,wBAAgB,eAAE3mB,KAAI,SAAC2nB,GAAM,OAAAA,EAAEC,QAAF,IAAYjD,OAAO,EAAA9d,cAE/E,OAAO,EAAP,SACK3F,KAAK2M,yBACLga,EAAwC3mB,KAAK6lB,gBAsJtD,SACEA,G,MAEA,IACE,IAAMe,EAAqBf,EAAcgB,wBAGnCC,EAAcF,aAAkB,EAAlBA,EAAoBG,iBAExC,MAAO,CACLlZ,cAAeiZ,aAAW,EAAXA,EAAaJ,SAC5BjQ,WAAuC,QAA3B,EAAAqQ,aAAW,EAAXA,EAAaE,sBAAc,eAAEvQ,WACzCD,kBAAcrW,EAElB,CAAE,MAAO8mB,GAGP,MAAO,CAAC,CACV,CACF,CAxKSC,CAAmClnB,KAAK6lB,gBAAc,CACzD3Y,OAAQia,EAAannB,KAAK6lB,eAC1B5Y,WAAYjN,KAAKsK,gBACjB6C,eAAe,IAAAC,wBAAyE,QAAlD,EAAwC,QAAxC,EAAApN,KAAK6lB,cAAcuB,6BAAqB,eAAEjO,gBAAQ,QAAI,GAC5FhD,oBAAqBmQ,aAAK,EAALA,EAAOvU,OAC5BqE,mBAAoBkQ,aAAK,EAALA,EAAOxU,MAC3BkE,iBAAkBwQ,EAAoBA,EAAkBa,KAAK,UAAOlnB,EAGpE8N,cAAe,GAEnB,EAEA,sBAAc,0BAAW,C,IAAzB,W,MACE,OAA6C,QAAtC,EAAAjO,KAAK6lB,cAAcI,2BAAmB,QAAI,CACnD,E,gCAEQ,YAAAG,oCAAR,sBAQEpmB,KAAK6lB,cAAc3f,iBAAiB,EAAAohB,mBAAmBC,iBAAiB,SAAClY,GACvE,EAAKJ,cAAc,EAAAC,MAAMS,cAAe,CAAC,EAC3C,IAGA3P,KAAK6lB,cAAc3f,iBAAiB,EAAAohB,mBAAmBE,sBAAsB,WAE3E,IAAMC,EAAoB,EAAK5B,cAAc6B,wBACzC,IAAA/hB,cAAa8hB,KACf,EAAKhC,iBAAmBgC,EAAkBE,mBAG5C,EAAK1Y,cAAc,EAAAC,MAAM6R,MAAO,CAAC,EACnC,IAGA/gB,KAAK6lB,cAAc3f,iBAAiB,EAAAohB,mBAAmBtX,MAAM,SAACtQ,GAC5D,EAAKuP,cAAc,EAAAC,MAAMc,KAAM,CAACjN,YAAarD,EAAMkoB,kBACrD,IAGA5nB,KAAK6lB,cAAc3f,iBAAiB,EAAAohB,mBAAmBpX,SAAS,SAACb,GAC/D,EAAKJ,cAAc,EAAAC,MAAMgB,QAAS,CAACnN,YAAa,EAAKA,aACvD,IAGA/C,KAAK6lB,cAAc3f,iBAAiB,EAAAohB,mBAAmBO,aAAa,SAACnoB,GACnE,EAAKuP,cAAc,EAAAC,MAAMmB,YAAa,CAACtN,YAAarD,EAAMkoB,kBAC5D,IAGA5nB,KAAK6lB,cAAc3f,iBAAiB,EAAAohB,mBAAmBnX,OAAO,SAACd,GAC7D,EAAKJ,cAAc,EAAAC,MAAMiB,MAAO,CAACpN,YAAa,EAAKA,aACrD,IAGA/C,KAAK6lB,cAAc3f,iBAAiB,EAAAohB,mBAAmB1U,OAAO,SAAClT,GAC7D,IAAMqZ,GAAY,IAAApT,cAAajG,EAAMa,OAASb,EAAMa,WAAQJ,EAC5D,EAAK8O,cAAc,EAAAC,MAAM0D,MAAO,CAC9B7P,YAAa,EAAK8iB,cAAcI,oBAChCpT,KAAMnT,EAAMooB,kBACZhV,QAASpT,EAAMslB,OACfjS,WAAYgG,EACZ9F,cAAevT,EACfsT,KAAM,CAACE,gBAAgB,IAAAC,kBAAiB4F,KAE5C,IAGA/Y,KAAK6lB,cAAc3f,iBAAiB,EAAAohB,mBAAmBS,SAAS,SAACroB,GAC/D,EAAKuP,cAAc,EAAAC,MAAMsB,KAAM,CAACzN,YAAarD,EAAMkoB,kBACrD,IAGA5nB,KAAK6lB,cAAc3f,iBAAiB,EAAAohB,mBAAmB5W,QAAQ,SAAChR,GAC9D,EAAKuP,cAAc,EAAAC,MAAMwB,OAAQ,CAAC3N,YAAarD,EAAMkoB,kBACvD,IAEA5nB,KAAK6lB,cAAc3f,iBAAiB,EAAAohB,mBAAmBU,WAAW,SAACtoB,GAC7DA,EAAMuoB,aACR,EAAKhZ,cAAc,EAAAC,MAAM0B,gBAAiB,CAAC7N,YAAa,EAAKA,aAEjE,IAWA/C,KAAK6lB,cAAc3f,iBAAiB,EAAAohB,mBAAmBY,cAAc,SAAC7Y,GACpE,EAAKnG,aAAa,CAAC,EACrB,GACF,EAEQ,YAAAmd,mCAAR,sBACQ8B,EAA0B,WACzB,EAAKle,sBACR,EAAKA,qBAAsB,EAC3B,EAAKgF,cAAc,EAAAC,MAAMyF,OAAQ,CAAC5R,YAAa,EAAKA,eAEtD,EAAK6R,SACP,EAEA5U,KAAKwC,mBAAmB0D,iBAAiB,eAAgBiiB,GACzDnoB,KAAKwC,mBAAmB0D,iBAAiB,SAAUiiB,EACrD,EACF,EAhKA,CAA0C,EAAAnQ,iBAkK1C,SAASmP,EAAatB,G,MAEpB,MAAwD,UAAjB,QAAnC,EAAAA,EAAcuB,6BAAqB,eAAEgB,gBAKfvC,EAAcwC,6BAExC,EAKF,CAEA,SAAgB1B,EACdd,G,QAKIpK,EAAyC,QAAnC,EAAAoK,EAAcuB,6BAAqB,eAAEkB,aAC3C,IAAA9Z,WAAUiN,KAAQ,IAAA8M,SAAQ9M,MAC5BA,EAAyC,QAAnC,EAAAoK,EAAcuB,6BAAqB,eAAEoB,WAG7C,IAAMJ,GAAa,IAAAK,uBAAsBhN,GAEzC,OAAO,IAAAiN,mCAAkCN,EAAY3M,EACvD,CAhMa,EAAA8J,qBAAAA,C,8GCvBb,cAEA,EACE,SAA6BtN,GAA7B,WAA6B,KAAAA,UAAAA,EAE7B,KAAA/R,iBAAmB,W,IAAE,uDACnB,IAAAkS,aAAW,W,MAAM,WAAKH,WAAU/R,iBAAgB,QAAI1F,EAAnC,GAClB,EAED,KAAAylB,kBAAoB,WAAM,WAAA7N,aAAW,WAAM,SAAKH,UAAUgO,mBAAf,GAAjB,EAE1B,KAAAM,SAAW,WAAM,WAAAnO,aAAW,WAAM,SAAKH,UAAUsO,UAAf,GAAjB,EAEjB,KAAAa,oBAAsB,WAAM,WAAAhP,aAAW,WAAM,SAAKH,UAAUmP,qBAAf,GAAjB,EAE5B,KAAAiB,qBAAuB,WAAM,WAAAjQ,aAAW,WAAM,SAAKH,UAAUoQ,sBAAf,GAAjB,EAE7B,KAAAX,qBAAuB,WAAM,WAAAtP,aAAW,WAAM,SAAKH,UAAUyP,sBAAf,GAAjB,EAE7B,KAAA5B,gBAAkB,WAAM,WAAA1N,aAAW,WAAM,SAAKH,UAAU6N,iBAAf,GAAjB,EAExB,KAAAe,sBAAwB,WAAM,WAAAzO,aAAW,WAAM,SAAKH,UAAU4O,uBAAf,GAAjB,CAlB0B,EAD7C,EAAAV,iBAAAA,C,+GCWA,EAAAmB,mBAAqB,CAChCqB,IAAK,IACLX,UAAW,YACXpV,MAAO,QACP2U,gBAAiB,kBACjBpX,MAAO,QACPH,KAAM,OACNE,QAAS,UACTsX,qBAAsB,uBACtBU,aAAc,eACdxX,OAAQ,SACRqX,QAAS,UACTa,QAAS,UACTf,YAAa,c,yGC3Bf,cAIA,UACA,UACA,UACA,UAKA,UAGA,UACA,UAEA,aAIE,WAAYpe,EAAyBlH,EAAa6D,GAChD,IAAI,IAAA2B,+BAA8BxF,GAChC,EAAAyF,OAAOC,mBAAmB,uEAD5B,EAIA,IAAAC,+BAA8B3F,GAE9B,IAAM8F,GAAkB,IAAAC,yBAAwBmB,IAC3C,IAAAlB,+BAA8BF,MAInC,IAAAG,8BAA6BH,GAE7BrI,KAAKyG,gBAAkB,IAAI,EAAAoiB,mBAAmB,IAAI,EAAAC,iBAAiBvmB,GAAS6D,GAC5EpG,KAAKkH,UAAY,EAAA2B,UAAUxK,OAAOgK,EAAiBrI,KAAKyG,iBAXxD,CAYF,CAqCF,OAjCE,sBAAI,sBAAO,C,IAAX,WACE,OAAO,EAAAhJ,OACT,E,gCAEA,YAAA2L,uBAAA,WACE,IAAK,IAAA5C,WAAUxG,KAAKkH,WAEpB,OAAOlH,KAAKkH,UAAUkC,wBACxB,EAEA,YAAAC,UAAA,WACE,IAAK,IAAA7C,WAAUxG,KAAKkH,WAEpB,OAAOlH,KAAKkH,UAAUmC,WACxB,EAEA,YAAAC,cAAA,SAAcC,IACP,IAAA/C,WAAUxG,KAAKyG,kBAEpBzG,KAAKyG,gBAAgB6C,cAAcC,EACrC,EAEA,YAAAC,kBAAA,SAAkBD,IACX,IAAA/C,WAAUxG,KAAKkH,YAEpBlH,KAAKkH,UAAUsC,kBAAkBD,EACnC,EAEA,YAAAL,aAAA,SAAaO,IACN,IAAAjD,WAAUxG,KAAKkH,YAEpBlH,KAAKkH,UAAUgC,aAAaO,EAC9B,EAlCgB,EAAA3G,QAAkB,EAAArF,QAmCpC,C,CAzDA,GAAa,EAAAsrB,WAAAA,C,41BChBb,cACA,UACA,UACA,SACA,UACA,UAUA,UACA,UACA,UACA,UAIA,UACA,UAEA,cAIE,WAAY3T,EAAuBhP,GACjC,QAAK,eAACjG,EAAWiG,IAAK,K,OAiBf,EAAA+D,cAAgB,WAAM,SAAAC,OAAO4e,KAAP,EAE/B,EAAA9e,iBAAmB,iBAAM,OAAgB,QAAhB,IAAKkL,IAAItS,eAAO,QAAI,SAAS,EAyC7C,EAAAoK,OAAS,WAChB,IAAM+b,GAAkB,IAAAC,oBAAmB,EAAK9T,KAEhD,KAAI,IAAA5G,WAAUya,aAAe,EAAfA,EAAiBE,SAI/B,OAAOF,EAAgBE,QAAQC,IACjC,EAmGQ,EAAAC,aAAe,WACrB,EAAKpa,cAAc,EAAAC,MAAMI,gBAAiB,CAAC,GAC3C,EAAKsF,SACP,EAzKE,EAAKQ,IAAMA,EACX,EAAKxL,WAAa,IAAI,EAAA0f,qBAAqBlU,EAAK,IAAI,EAAAqC,oBAAsBC,wB,CAC5E,CA8NF,OAtOwC,OAU7B,YAAAtM,WAAT,SAAoBlE,GASlB,OARA,YAAMkE,WAAU,UAAClE,GACjBlH,KAAKupB,oBAOE,CANqB,IAAI,EAAArd,oBAC9BhF,EAAUiF,oCACV,IAAI,EAAAC,mBAAmBlF,EAAUiF,oCAAoCE,iBACrE,CAACnF,EAAUoF,8BACXnM,GAGJ,EAMS,YAAAqM,uBAAT,WACE,IAAMgd,EAAmBxpB,KAAKypB,8BAExBC,EAAY,OACb,YAAMld,uBAAsB,YAAE,CACjCqB,cAAe7N,KAAK2pB,2BACpB3b,iBAAiB,IAAArI,cAAa6jB,GAAoBA,EAAiBzT,aAAU5V,EAC7E6V,kBAAkB,IAAArQ,cAAa6jB,GAAoBA,EAAiB9C,cAAWvmB,IAG3EypB,GAAY,IAAAC,iBAAgB7pB,KAAKoV,KAGvC,OAFApV,KAAKgK,0BAA0B8f,uBAAuBJ,EAAcE,GAE7DF,CACT,EACS,YAAA9a,qBAAT,WACE,OAAO5O,KAAK4J,WAAWiF,SACzB,EACS,YAAAC,+BAAT,WACE9O,KAAK4J,WAAWmF,OAClB,EAEA,YAAAgb,2BAAA,WACE,IAAMd,GAAkB,IAAAC,oBAAmBlpB,KAAKoV,KAChD,OAAK6T,EAQE,CACL5X,QALc4X,EAAgB5X,QAM9BS,MALYmX,EAAgBnX,MAM5BC,OALakX,EAAgBlX,QALtB,IAYX,EAYS,YAAAiY,YAAT,WACE,OAAO,EAAAC,UAAUC,GACnB,EAES,YAAAC,aAAT,W,MACE,OAAmB,QAAZ,EAAAnqB,KAAKoV,IAAIqG,WAAG,aAAItb,CACzB,EAEA,YAAAopB,kBAAA,WACEvpB,KAAKoV,IAAIhS,GAAG,EAAAgnB,iBAAiBC,gBAAiBrqB,KAAKsqB,iBAAiB9F,KAAKxkB,OACzEA,KAAKoV,IAAIhS,GAAG,EAAAgnB,iBAAiBG,gBAAiBvqB,KAAKwqB,iBAAiBhG,KAAKxkB,OACzEA,KAAKoV,IAAIhS,GAAG,EAAAgnB,iBAAiBK,iBAAkBzqB,KAAK0qB,kBAAkBlG,KAAKxkB,OAC3EA,KAAKoV,IAAIhS,GAAG,EAAAgnB,iBAAiBO,qBAAsB3qB,KAAK4qB,qBAAqBpG,KAAKxkB,OAClFA,KAAKoV,IAAIhS,GAAG,EAAAgnB,iBAAiBS,sBAAuB7qB,KAAK8qB,2BAA2BtG,KAAKxkB,OACzFA,KAAKoV,IAAIhS,GAAG,EAAAgnB,iBAAiBW,WAAY/qB,KAAKqpB,aAAa7E,KAAKxkB,OAChEA,KAAKoV,IAAIhS,GAAG,EAAAgnB,iBAAiBxX,MAAO5S,KAAKgrB,WAAWxG,KAAKxkB,OAOrDA,KAAKoV,IAAI6V,QACXjrB,KAAKsqB,mBACLtqB,KAAK0qB,oBAET,EAEA,YAAAJ,iBAAA,WAGMtqB,KAAKkrB,eAITlrB,KAAKkrB,aAAe,IAAI,EAAAC,sBAAsBnrB,KAAKoV,IAAI6V,OAEvDjrB,KAAKorB,uBACLprB,KAAKqrB,eACP,EAEA,YAAAb,iBAAA,WACExqB,KAAKsrB,wBACP,EAEA,YAAAZ,kBAAA,WACE1qB,KAAKqrB,cACP,EAMA,YAAAL,WAAA,SAAWO,EAAWxS,GAEpB,IADgBA,GAAYA,EAAUyS,MACzB,CACX,IAAMN,EAAelrB,KAAKkrB,aACtBnoB,OAAW,GACX,IAAA4C,cAAaulB,KACfnoB,EAAcmoB,EAAanoB,aAG7B,IAAM0oB,GAAe,IAAA9lB,cAAaoT,GAAa,UAAGA,EAAUtT,KAAI,aAAKsT,EAAUoQ,cAAYhpB,EAC3FH,KAAKiP,cAAc,EAAAC,MAAM0D,MAAO,CAC9B7P,YAAW,EACX8P,KAAM7S,KAAK0rB,6BAA6B3S,EAAUtT,MAClDqN,QAAS2Y,EACTxY,cAAe8F,EACf/F,KAAM,CAAC,GAEX,CACF,EAEA,YAAA4X,qBAAA,SAAqBvb,EAAgBsc,GACnC,IACI5oB,EADEmoB,EAAelrB,KAAKkrB,cAEtB,IAAAvlB,cAAaulB,KACfnoB,EAAcmoB,EAAanoB,aAG7B/C,KAAKiP,cAAc,EAAAC,MAAMiF,mBAAoB,CAC3CpR,YAAW,GAEf,EAEA,YAAA+nB,2BAAA,SAA2Bzb,EAAgBsc,GACzC,IACI5oB,EADEmoB,EAAelrB,KAAKkrB,cAEtB,IAAAvlB,cAAaulB,KACfnoB,EAAcmoB,EAAanoB,aAG7B/C,KAAKiP,cAAc,EAAAC,MAAMmF,gBAAiB,CACxCtR,YAAW,GAEf,EAWQ,YAAA2oB,6BAAR,SAAqCjmB,GACnC,OAAQA,GACN,IAAK,eACH,OAAO,EACT,IAAK,aACH,OAAO,EACT,IAAK,iBACH,OAAO,EACT,IAAK,WACH,OAAO,EAET,QACE,OAAO,EAEb,EAEQ,YAAAkkB,yBAAR,WACE,IAAMiC,EAAa5rB,KAAKoV,IAAIwW,WAC5B,MAAI,IAAApd,WAAUod,IAAeA,EAAa,GAA1C,CAGA,IAAMC,EAAc7rB,KAAKoV,IAAIyW,YAC7B,KAAI,IAAArd,WAAUqd,IAAuC,IAAvBA,EAAYtsB,OAG1C,OAAOssB,EAAYD,GAAY7d,IAL/B,CAMF,EAEQ,YAAA0b,4BAAR,W,QAEE,IAAI,IAAA9jB,cAAa3F,KAAKoV,IAAI0W,iBAAkB,CAC1C,IAAMC,EAAqB/rB,KAAKoV,IAAI4W,cAC9BC,GACJ,IAAAtmB,cAAaomB,IAAuBA,GAAsB,GAAK/rB,KAAKoV,IAAI0W,gBAI1E,MAAO,CACL/V,QAASkW,EACTvF,SAJeuF,EAAmE,QAA7C,EAAuB,QAAvB,EAAAjsB,KAAKoV,IAAI8W,sBAAc,eAAGH,UAAmB,eAAEhe,UAAO5N,EAM/F,CACS,IAAAgsB,EAA2BnsB,KAAKoV,IAAU,wBACjD,IAAI,IAAAzP,cAAawmB,KAA4B,IAAAxmB,cAAawmB,EAAwBlB,OAChF,OAAOjrB,KAAKosB,oCAAoCD,EAAwBlB,MAI9E,EACF,EAtOA,CAAwC,EAAAoB,sBAA3B,EAAAxD,mBAAAA,EAwOA,EAAAgB,gBAAkB,SAACzU,GAC9B,IAAM6T,GAAkB,IAAAC,oBAAmB9T,GAC3C,GAAK6T,EAIL,MAAO,CACL5S,WAAY4S,EAAgB5S,WAC5BI,WAAYwS,EAAgBxS,WAEhC,EAEa,EAAAyS,mBAAqB,SAAC9T,GACjC,IAAMkX,EAASlX,EAAIkX,OACbC,EAAenX,EAAImX,aACzB,KAAI,IAAA/d,WAAU8d,IAA6B,IAAlBA,EAAO/sB,SAI3B,IAAAmjB,UAAS6J,MAAiBA,EAAe,GAI9C,OAAOD,EAAOC,EAChB,C,+GC1RA,cAEA,aACE,WAA6BtU,GAA7B,WAA6B,KAAAA,UAAAA,EAE7B,KAAA7U,GAAK,W,IAAC,sDAAmC,WAAAgV,aAAW,W,MAAM,WAAKH,WAAU7U,GAAE,QAAI5C,EAArB,GAAjB,CAFK,CA2ChD,OAvCE,sBAAI,oBAAK,C,IAAT,sBACE,OAAO,IAAA4X,aAAW,WAAM,SAAKH,UAAUgT,KAAf,GAC1B,E,gCAEA,sBAAI,kBAAG,C,IAAP,sBACE,OAAO,IAAA7S,aAAW,WAAM,SAAKH,UAAUwD,GAAf,GAC1B,E,gCAEA,sBAAI,qBAAM,C,IAAV,sBACE,OAAO,IAAArD,aAAW,WAAM,SAAKH,UAAUqU,MAAf,GAC1B,E,gCAEA,sBAAI,2BAAY,C,IAAhB,sBACE,OAAO,IAAAlU,aAAW,WAAM,SAAKH,UAAUsU,YAAf,GAC1B,E,gCAEA,sBAAI,yBAAU,C,IAAd,sBACE,OAAO,IAAAnU,aAAW,WAAM,SAAKH,UAAU2T,UAAf,GAC1B,E,gCAEA,sBAAI,0BAAW,C,IAAf,sBACE,OAAO,IAAAxT,aAAW,WAAM,SAAKH,UAAU4T,WAAf,GAC1B,E,gCAEA,sBAAI,8BAAe,C,IAAnB,sBACE,OAAO,IAAAzT,aAAW,WAAM,SAAKH,UAAU6T,eAAf,GAC1B,E,gCAEA,sBAAI,4BAAa,C,IAAjB,sBACE,OAAO,IAAA1T,aAAW,WAAM,SAAKH,UAAU+T,aAAf,GAC1B,E,gCAEA,sBAAI,6BAAc,C,IAAlB,sBACE,OAAO,IAAA5T,aAAW,WAAM,SAAKH,UAAUiU,cAAf,GAC1B,E,gCAEA,sBAAI,sBAAO,C,IAAX,sBACE,OAAO,IAAA9T,aAAW,WAAM,OAAC,EAAKH,UAAkBuU,YAAY1pB,OAApC,GAC1B,E,gCACF,EA5CA,GAAa,EAAAgmB,iBAAAA,C,kCCmBb,IAAY2D,E,+FAAZ,SAAYA,GACV,gBACA,cACA,qBACD,CAJD,CAAYA,IAAiB,oBAAjBA,EAAiB,KAkChB,EAAArC,iBAAmB,CAC9BC,gBAAiB,oBACjBE,gBAAiB,oBACjBE,iBAAkB,qBAClBE,qBAAsB,wBACtBE,sBAAuB,yBACvBE,WAAY,gBACZnY,MAAO,WACP8Z,YAAa,gB,mHChEf,cAIA,UAEA,aAGE,WAAYtX,EAAuBsI,GAAnC,WACE1d,KAAK0d,MAAQA,EACbtI,EAAIhS,GAAG,EAAAgnB,iBAAiBsC,aAAa,SAACC,EAAY3Z,GAAS,SAAK4Z,0BAA0B5Z,EAA/B,GAC7D,CAkCF,OAhCE,YAAA0E,sBAAA,WACE,OAAO1X,KAAK0d,KACd,EAEA,YAAAkP,0BAAA,SAA0B5b,GACxB,GAA4B,SAAxBA,EAAU6b,KAAKpnB,KAAnB,CAKA,IAAMgX,GAAa,IAAA9W,cAAaqL,EAAU8b,gBACrC9b,EAAU8b,eAAoCC,YAC/C5sB,EACJ,KAAI,IAAAqO,WAAUiO,GAAd,CAKA,IAAM6J,EAAQtV,EAAU6b,KAAKvG,MACvB0G,GAAmB1G,EAAM2G,QAAQC,IAAM5G,EAAM2G,QAAQE,OAAS,IAC9DvQ,GAAmB0J,EAAM2G,QAAQG,MAAQ9G,EAAM2G,QAAQE,OAAS,IAEhEE,EAAc,CAClBlU,SAAU6T,EACVpgB,KAAM0Z,EAAMgH,MACZ1Q,gBAAiBA,EACjB/Q,UAAW,IAAI+R,KACfnB,WAAU,GAGZzc,KAAK0d,MAAMC,eAAe0P,EAd1B,CARA,CAuBF,EACF,EAxCA,GAAa,EAAA/D,qBAAAA,C,uzBCPb,cAEA,UACA,UACA,UACA,UACA,SACA,UACA,UAOA,UAGA,UACA,UACA,UACA,UAIA,UAEA,cA0BE,WAAsB4B,EAAiD9kB,GACrE,QAAK,UAACA,IAAK,KAjBH,EAAAmnB,sBAAgC,EAElC,EAAAtjB,qBAAsB,EAGtB,EAAAge,aAAuB,EACvB,EAAAuF,UAAoB,EACpB,EAAAC,WAAqB,EAErB,EAAAC,2BAAqC,EAIrC,EAAAC,oBAAqB,EA2C7B,EAAAxjB,cAAgB,WAAM,SAAAC,OAAOwjB,KAAP,EACtB,EAAAtjB,cAAgB,WAAM,eACtB,EAAApH,YAAc,mBAAM,OAA2B,QAA3B,EAAiB,QAAjB,IAAKgoB,oBAAY,eAAE/nB,gBAAQ,QAAS,EAC/C,EAAAqH,sBAAwB,WAAsC,SAAKC,kBAAL,EAoEvE,EAAAyC,OAAS,WACP,GAAK,EAAKge,aAAV,CAIA,IAAM/d,EAAgB,EAAK+d,aAAa/R,SACxC,OAAO,IAAA3K,WAAUrB,IAAkB0gB,MAAM1gB,QAAiBhN,EAAYgN,IAAkB2gB,GAHxF,CAIF,EApHE,IAAMnjB,EAA0B,IAAI,EAAAC,kBAClC,iBAAM,OAAyB,QAAzB,EAAAsgB,aAAY,EAAZA,EAAcnoB,mBAAW,QAAI,EAAK2qB,0BAA0B,IAE9D5iB,EAAe,IAAI,EAAAijB,2BAA2B,EAAK/iB,sBAAuBL,EAAyB,EAAKvE,M,OAC9GuE,EAAwBM,YAAYH,GACpC,EAAKA,aAAeA,EAEpB,EAAKogB,aAAeA,EACpB,EAAK8C,0BAA4B,GACjC,EAAKC,gCAA6B9tB,EAElC,EAAK+tB,sBAAmB/tB,EACxB,EAAK8nB,aAAc,EACnB,EAAKuF,UAAW,EAChB,EAAKC,WAAY,EACjB,EAAKC,2BAA6B,EAClC,EAAKS,mBAAqB,EAC1B,EAAKC,iBAAkB,EACvB,EAAKb,sBAAuB,EAC5B,EAAK7iB,wBAA0B,IAAI,UACnC,EAAK2jB,yBAA2B,IAAI,UAAmCnD,G,CACzE,CA6mBF,OA9pBmD,OAmDjD,sBAAI,qCAAsB,C,IAA1B,WACE,OAAOlrB,KAAK0K,uBACd,E,gCAEA,YAAAU,WAAA,SAAWkjB,GAOT,OANItuB,KAAKkrB,cAGPlrB,KAAKuuB,kBAEPvuB,KAAKwuB,uBACE,EACT,EAOA,YAAAhiB,uBAAA,WACE,IAAM4b,EAAapoB,KAAKsN,iBACpB,IAAA3H,cAAayiB,IACfpoB,KAAKgK,0BAA0B0F,gBAAgB0Y,GAGjD,IAAI1b,EAAI,SACH1M,KAAK2M,0BACL,IAAA+b,mCAAkCN,EAAYpoB,KAAKmqB,iBAAe,CACrEjd,OAAQlN,KAAKkN,SACbN,MAAM,IAAA6hB,uBAAwB,EAAA1hB,WAAWD,WAAa,EAAAC,WAAWC,OACjEC,WAAYjN,KAAKsK,gBACjB2D,cAAejO,KAAKquB,yBAAyBK,qBAM3C1uB,KAAKkrB,eACPxe,EAAO,EAAH,KACCA,GAAI,CACPS,eAAe,IAAAC,wBAAuBpN,KAAKkrB,aAAa/R,UACxDxL,QAAS3N,KAAKkrB,aAAa/G,MAC3B1W,kBAAmBzN,KAAKkrB,aAAanZ,OACrCxE,iBAAkBvN,KAAKkrB,aAAapZ,SAIxC,IAAM6c,EAAc3uB,KAAK+pB,6BAYzB,OAXI4E,IACFjiB,EAAO,EAAH,KACCA,GAAI,CACPyJ,oBAAqBwY,EAAY5c,OACjCqE,mBAAoBuY,EAAY7c,MAChC2D,aAAckZ,EAAYtd,WAI9BrR,KAAKgK,0BAA0ByE,kBAAkB/B,GAE1CA,CACT,EAES,YAAAH,wBAAT,WACE,YAAMA,wBAAuB,WAC7BvM,KAAKquB,yBAAyBtf,QAC9B/O,KAAKutB,sBAAuB,EAC5BvtB,KAAKioB,aAAc,EACnBjoB,KAAKwtB,UAAW,EAChBxtB,KAAKytB,WAAY,EACjBztB,KAAK0tB,2BAA6B,EAClCkB,aAAa5uB,KAAKkuB,iBACpB,EAEA,sBAAc,0BAAW,C,IAAzB,W,MACE,IAAKluB,KAAKkrB,aACR,MAAM,IAAIntB,MAAM,qBAGlB,OAAoC,QAA7B,EAAAiC,KAAKkrB,aAAanoB,mBAAW,QAAI/C,KAAK0tB,0BAC/C,E,gCAES,YAAA9Y,QAAT,WACE5U,KAAKsrB,yBACL,YAAM1W,QAAO,UACf,EA6BA,YAAA2Z,gBAAA,SAAgBrD,GAgBd,QAhBc,IAAAA,IAAAA,EAAA,MAEVA,IAEElrB,KAAKkrB,cACPlrB,KAAKsrB,yBAIPtrB,KAAKkrB,aAAeA,IAOjBlrB,KAAKkrB,aACR,MAAM,IAAIntB,MAAM,0BAIlB,GAAIiC,KAAKguB,0BAA0BzuB,OAAS,EAC1C,MAAM,IAAIxB,MAAM,mDAGlBiC,KAAKorB,uBACLprB,KAAKqrB,cACP,EAYA,YAAArB,YAAA,WACE,IAAM6E,EAAY7uB,KAAKmqB,eACvB,KAAI,IAAA3b,WAAUqgB,GAGd,OAAO,IAAAC,8BAA6BD,EACtC,EAMA,YAAAvhB,cAAA,WACE,IAAMyhB,EAAW/uB,KAAKgqB,cACtB,GAAI+E,EACF,OAAO,IAAAC,2BAA0BD,EAIrC,EAMA,YAAA5E,aAAA,WACE,IAAMe,EAAelrB,KAAKkrB,aAC1B,GAAKA,EAIL,OAAOA,EAAa+D,GACtB,EAEA,YAAA7D,qBAAA,sBACQF,EAAelrB,KAAKkrB,aAC1B,GAAKA,EAAL,CAKAlrB,KAAKiuB,2BAA6B/C,EAAagE,eAAelmB,KAC9D,IAAMD,EAAe/I,KAAKiuB,2BAC1B/C,EAAagE,eAAelmB,KAAO,W,IAAC,sDAClC,EAAKE,aAAa,CAAC,GACnBH,EAAa9H,MAAMiqB,EAAagE,eAAgB1uB,EAClD,EAEAR,KAAKmvB,0BAA0B,aAAa,WAC1CvP,EAAI,oBAAasL,EAAanoB,cAC9B,EAAKmG,aAAa,CAAC,EACrB,IAEAlJ,KAAKmvB,0BAA0B,kBAAkB,W,QAC/CvP,EAAI,8BAAuBsL,EAAanoB,YAAW,0BAAkBmoB,EAAakE,aAGlF,EAAKC,6BAA4B,GAIjC,IAAMhiB,EAAe,EAAKC,iBACtB,IAAA3H,cAAa0H,IACf,EAAKrD,0BAA0B0F,gBAAgBrC,IAG7C,IAAA1H,cAAa,EAAKulB,gBACpB,EAAKxgB,wBAAwBqE,QAC7B,EAAKrE,wBAAwB+E,iBAA2C,QAA1B,IAAKyb,aAAa/R,gBAAQ,QAAI,GAC5E,EAAKwU,mBAA4C,QAAvB,IAAKzC,aAAa/G,aAAK,UAEnD,EAAKlV,cAAc,EAAAC,MAAMS,cAAe,CAAC,EAC3C,IAIA3P,KAAKmvB,0BAA0B,QAAQ,W,MACrCvP,EAAI,eAAQsL,EAAanoB,cACzB,IAAMA,EAAsC,QAAxB,EAAAmoB,EAAanoB,mBAAW,QAAI,EAAK2qB,2BAEjD,EAAKH,uBACP,EAAKG,2BAA6B3qB,GAEpC,EAAKwqB,sBAAuB,EAE5B,EAAKte,cAAc,EAAAC,MAAMc,KAAM,CAACjN,YAAW,GAC7C,IAEA/C,KAAKmvB,0BAA0B,SAAS,WACtCvP,EAAI,gBAASsL,EAAanoB,cAC1B,EAAKusB,UACP,IAEAtvB,KAAKmvB,0BAA0B,WAAW,WACxCvP,EAAI,kBAAWsL,EAAanoB,cAC5B6rB,aAAa,EAAKV,kBAClB,EAAKV,UAAW,EAIhB,EAAKD,sBAAuB,CAC9B,IAEAvtB,KAAKuvB,+BAA+BrE,GACpClrB,KAAKmvB,0BAA0B,gBAAgB,W,MAC7CvP,EAAI,uBAAgBsL,EAAanoB,cAEjC,IAAMohB,EAAQ+G,EAAa/G,MACrBqL,EAAStE,EAAasE,OAC5B,KAAI,IAAAhhB,WAAU2V,MAAU,IAAA3V,WAAUghB,GAAlC,CAIA,IAAMzsB,EAAsC,QAAxB,EAAAmoB,EAAanoB,mBAAW,QAAI,EAAK2qB,2BAC/C/f,GAAU,IAAA8hB,cAAatL,EAAOqL,GAEhC,EAAK7B,qBAAuBhgB,IAC1BA,EACF,EAAKsB,cAAc,EAAAC,MAAMuD,KAAM,CAAC1P,YAAW,IAE3C,EAAKkM,cAAc,EAAAC,MAAMyD,QAAS,CAAC5P,YAAW,IAEhD,EAAK4qB,mBAAqBhgB,EAX5B,CAaF,IAEA3N,KAAKmvB,0BAA0B,WAAW,WACxCvP,EAAI,kBAAWsL,EAAanoB,cACrB,IAAAA,EAAemoB,EAAY,YAElC,EAAKjc,cAAc,EAAAC,MAAMsB,KAAM,CAACzN,YAAW,GAC7C,IAEA/C,KAAKmvB,0BAA0B,UAAU,WACvCvP,EAAI,iBAAUsL,EAAanoB,cACpB,IAAAA,EAAemoB,EAAY,YAElC0D,aAAa,EAAKV,kBAElB,EAAKjf,cAAc,EAAAC,MAAMwB,OAAQ,CAAC3N,YAAW,GAC/C,IAEA/C,KAAKmvB,0BAA0B,cAAc,W,MACrCpsB,EAAsC,QAAxB,EAAAmoB,EAAanoB,mBAAW,QAAI,EAMhD,GAJA,EAAKklB,aAAc,EACnB,EAAKwF,WAAY,GAGb,EAAKF,qBAAT,CAIA,IAAK,EAAKC,SAMgF,IAA1DtW,KAAKC,IAAIpU,EAAc,EAAK2qB,4BAC9B,GAC1B,EAAKze,cAAc,EAAAC,MAAMmB,YAAa,CAACtN,YAAW,IAItD,EAAKssB,8BAEL,EAAKK,eAML,EAAKC,wBAEL,EAAKjC,2BAA6B3qB,CAxBlC,CAyBF,IAKA/C,KAAKmvB,0BAA0B,WAAW,WAM1C,IAIAnvB,KAAKmvB,0BAA0B,WAAW,WAGxCvP,EAAI,kBAAWsL,EAAanoB,cAC5B,EAAK2sB,eACL,EAAKE,aACP,GA/JA,CAgKF,EAEU,YAAAL,+BAAV,SAAyCrE,GAAzC,WACElrB,KAAKmvB,0BAA0B,SAAS,W,UACtCvP,EAAI,gBAASsL,EAAanoB,cAC1B,IAAMxC,EAAQ2qB,EAAa3qB,MAC3B,EAAK0O,cAAc,EAAAC,MAAM0D,MAAO,CAC9B7P,YAAqC,QAAxB,EAAAmoB,EAAanoB,mBAAW,QAAI,EAAK2qB,2BAE9C7a,KAAiB,QAAX,EAAAtS,aAAK,EAALA,EAAOsS,YAAI,aAAI1S,EACrB2S,QAAuB,QAAd,EAAAvS,aAAK,EAALA,EAAOuS,eAAO,aAAI3S,EAC3B8S,cAAe1S,EACfyS,KAAM,CAAC,GAEX,GACF,EAKA,YAAAmc,0BAAA,SAA0BzvB,EAAYmwB,GACpC,IAAK7vB,KAAKkrB,aACR,MAAM,IAAIntB,MAAM,qBAGlB,IAAM+xB,EAAeD,EAAQrL,KAAKxkB,MAElCA,KAAKguB,0BAA0BxuB,KAAK,CAACE,MAAK,EAAEmwB,QAASC,IACrD9vB,KAAKkrB,aAAahlB,iBAAiBxG,EAAOowB,GAAc,EAC1D,EAEA,YAAAzE,aAAA,W,MACOrrB,KAAKouB,iBAAoBpuB,KAAKkrB,eAInClrB,KAAKouB,iBAAkB,EAEvBpuB,KAAKwM,yBAELxM,KAAK0K,wBAAwBqE,QAC7B/O,KAAK0K,wBAAwB+E,iBAA2C,QAA1B,EAAAzP,KAAKkrB,aAAa/R,gBAAQ,QAAI,GAC9E,EAMU,YAAAmS,uBAAV,WACE,IAAKtrB,KAAKkrB,aACR,MAAM,IAAIntB,MAAM,6BAGlB,IAAMmtB,EAAelrB,KAAKkrB,aAE1BlrB,KAAKguB,0BAA0B+B,SAAQ,SAACC,GACtC9E,EAAalL,oBAAoBgQ,EAAKtwB,MAAOswB,EAAKH,QACpD,IAGA,IAAMI,EAAmBjwB,KAAKiuB,4BAC1B,IAAAtoB,cAAasqB,KACf/E,EAAagE,eAAelmB,KAAOinB,GAGrCjwB,KAAKkrB,kBAAe/qB,EACpBH,KAAKguB,0BAA4B,GACjChuB,KAAKiuB,gCAA6B9tB,EAGlCyuB,aAAa5uB,KAAKkuB,iBACpB,EAEA,YAAAM,qBAAA,WACExuB,KAAKwC,mBAAmB0D,iBAAiB,eAAgBlG,KAAKkwB,YAAY1L,KAAKxkB,OAC/EA,KAAKwC,mBAAmB0D,iBAAiB,SAAUlG,KAAKkwB,YAAY1L,KAAKxkB,MAC3E,EAEA,YAAAkwB,YAAA,W,MACE,IAAKlwB,KAAKiK,oBAAqB,CAC7BjK,KAAKiK,qBAAsB,EAC3B,IAAMihB,EAAelrB,KAAKkrB,aACtBnoB,OAAW,GACX,IAAA4C,cAAaulB,KACfnoB,EAAsC,QAAxB,EAAAmoB,EAAanoB,mBAAW,QAAI/C,KAAK0tB,4BAEjD1tB,KAAKiP,cAAc,EAAAC,MAAMyF,OAAQ,CAAC5R,YAAW,GAC/C,CACA/C,KAAK4U,SACP,EAEA,YAAAya,4BAAA,SAA4Bc,G,MAC1B,QAD0B,IAAAA,IAAAA,GAAA,IACrBnwB,KAAKkrB,aACR,MAAM,IAAIntB,MAAM,qBAGlB,IAAMmtB,EAAelrB,KAAKkrB,aAEpBkF,EAAmBpwB,KAAK+pB,6BAC9B,GAAKqG,EAAL,CAIO,IAAA/e,EAA0B+e,EAAgB,QAAjCte,EAAiBse,EAAgB,MAA1Bre,EAAUqe,EAAgB,OAEjD,IAAI,IAAAzqB,cAAa0L,GAAU,CACzB,IAAML,EAAgC,CACpCvL,KAAM,QACNqM,MAAK,EACLC,OAAM,EACNV,QAAO,EACPtO,YAAqC,QAAxB,EAAAmoB,EAAanoB,mBAAW,QAAI/C,KAAK0tB,4BAE5C1tB,KAAKuR,qBAAqBS,8BAA8BX,KACrD8e,GACHnwB,KAAKiP,cAAc,EAAAC,MAAM+C,aAAcjB,IAI3ChR,KAAKuR,qBAAqBW,gBAAgBb,GAC1CrR,KAAKgL,sBAAsB2G,wBAAwBX,EACrD,CApBA,CAqBF,EAEA,YAAAob,oCAAA,SAAoClB,GAClC,KAAI,IAAA1c,WAAU0c,EAAamF,YAA3B,CAIA,IADA,IACmB,MADGnF,EAAamF,WAChB,eAAe,CAA7B,IAAMC,EAAI,KACb,IAAI,IAAA3qB,cAAa2qB,EAAKjY,OAAuB,YAAdiY,EAAKjY,KAAoB,CACtD,IAAM4T,GAAsB,IAAAtmB,cAAa2qB,EAAK5J,WAAa4J,EAAK5J,SAASnnB,OAAS,EAClF,MAAO,CACLwW,QAASkW,EACTvF,SAAUuF,EAAsBqE,EAAK5J,cAAWvmB,EAEpD,CACF,CACA,MAAO,CACL4V,SAAS,EAZX,CAcF,EAEQ,YAAAuZ,SAAR,SAAiBvsB,G,MACf,IAAI/C,KAAKwtB,SAAT,CAGA,IAAKxtB,KAAKkrB,aACR,MAAM,IAAIntB,MAAM,qBAGbgF,IACHA,EAA2C,QAA7B,EAAA/C,KAAKkrB,aAAanoB,mBAAW,QAAI/C,KAAK0tB,4BAGtD1tB,KAAKiP,cAAc,EAAAC,MAAMiB,MAAO,CAACpN,YAAW,IAE5C/C,KAAKwtB,UAAW,CAXhB,CAYF,EAEQ,YAAAoC,YAAR,WACE,IAAK5vB,KAAKkrB,aACR,MAAM,IAAIntB,MAAM,qBAEX,IAAAgF,EAAe/C,KAAKkrB,aAAY,YAKnClrB,KAAKioB,aAAgBjoB,KAAKwtB,WAAaxtB,KAAKytB,YAI5CztB,KAAKytB,UACPztB,KAAKiP,cAAc,EAAAC,MAAMsB,KAAM,CAACzN,YAAW,IAE3C/C,KAAKiP,cAAc,EAAAC,MAAM0B,gBAAiB,CAAC7N,YAAW,IAExD/C,KAAKioB,aAAc,EACrB,EAEQ,YAAA0H,sBAAR,sBACE,IAAK3vB,KAAKkrB,aACR,MAAM,IAAIntB,MAAM,qBAElB,IAAMmtB,EAAelrB,KAAKkrB,aACtBA,EAAaqF,QACfvwB,KAAKsvB,WAGPV,aAAa5uB,KAAKkuB,kBAElBluB,KAAKkuB,iBAAmBsC,YAAW,W,MAC3BztB,EAAsC,QAAxB,EAAAmoB,EAAanoB,mBAAW,QAAI,EAAK2qB,2BACjDxC,EAAaqF,QAAWrF,EAAauF,QAAU,EAAKxI,aAU1BllB,EAAc,EAAK2qB,2BAMNrB,EAAqBqE,oCAAsC,IAAQ,IAI5G,EAAKd,aAET,GAAGvD,EAAqBqE,oCAC1B,EASQ,YAAAhB,aAAR,WACE,IAAK1vB,KAAKkrB,aACR,MAAM,IAAIntB,MAAM,qBAElB,IAAM4yB,EAA4B3wB,KAAKkrB,aAAanoB,YAC9C6tB,EAAe5wB,KAAKkrB,aAAa0F,aAEvC,KAAI,IAAApiB,WAAUmiB,MAA8B,IAAAniB,WAAUoiB,GAAtD,CAKA,IAAMC,EAAiC3Z,KAAKC,IAAIwZ,EAA4B3wB,KAAK0tB,4BAKjF,GAAImD,EAAiC,EACnC7wB,KAAKmuB,mBAAqBvQ,KAAK6E,UADjC,CAKA,IAGMqO,GAH4BlT,KAAK6E,MAG0BziB,KAAKmuB,oBAAsB,IAWxF0C,EAJ+BC,GADTF,EAAe,MAMvC5wB,KAAKytB,WAAY,EACjBztB,KAAKsvB,SAAStvB,KAAK0tB,2BAA6BoD,IAGlD9wB,KAAKmuB,mBAAqBvQ,KAAK6E,KArB/B,CAXA,CAiCF,EA5pBe,EAAAiO,oCAAsC,IA6pBvD,C,CA9pBA,CAAmD,EAAA1Y,iBAA7B,EAAAqU,qBAAAA,EAgqBtB,IAAMzM,EAAM,SAACnf,GACX,IAAMswB,GAAU,IAAInT,MAAOoT,cAAcC,UAAU,IAC7CC,EAAS,UAAGH,EAAO,0BACnBI,EAAS,UAAGD,EAAM,aAAKzwB,GAC7B,EAAAuH,OAAO4X,IAAIuR,EACb,C,qHC/rBA,cAKA,UAIA,UACA,UACA,UACA,UAKA,UAGA,UACA,UAEA,aAIE,WACE1nB,EACAlH,EACA6D,EAEAgrB,GAOA,IAAI,IAAArpB,+BAA8BxF,GAChC,EAAAyF,OAAOC,mBAAmB,uEAD5B,EAIA,IAAAC,+BAA8B3F,GAE9B,IAAM8F,GAAkB,IAAAC,yBAAwBmB,IAC3C,IAAAlB,+BAA8BF,MAGnC,IAAAG,8BAA6BH,GAE7BrI,KAAKyG,gBAAkB,IAAI,EAAA4qB,gCAAgC,IAAI,EAAAlG,sBAAsB5oB,GAAS6D,EAAMgrB,GACpGpxB,KAAKkH,UAAY,EAAA2B,UAAUxK,OAAOgK,EAAiBrI,KAAKyG,iBAVxD,CAWF,CAuEF,OArEE,sBAAI,8BAAe,C,IAAnB,WACE,IAAMA,EAAkBzG,KAAKyG,gBAE7B,MAAO,CACL6qB,iBAAgB,SAACzjB,GACfpH,EAAgB8qB,YAAY1jB,eAAgB,IAAA2jB,sCAAqC3jB,EACnF,EACA4jB,mBAAkB,SAAC1b,GACjBtP,EAAgB8qB,YAAYvjB,iBAAkB,IAAA0jB,wCAAuC3b,EACvF,EACA4b,oBAAmB,SAAC3b,GAClBvP,EAAgB8qB,YAAYvb,kBAAmB,IAAA4b,yCAAwC5b,EACzF,EAEJ,E,gCAIA,sBAAI,sBAAO,C,IAAX,WACE,OAAO,EAAAvY,OACT,E,gCAEA,YAAA2L,uBAAA,WACE,IAAK,IAAA5C,WAAUxG,KAAKkH,WAEpB,OAAOlH,KAAKkH,UAAUkC,wBACxB,EAEA,YAAAC,UAAA,WACE,IAAK,IAAA7C,WAAUxG,KAAKkH,WAEpB,OAAOlH,KAAKkH,UAAUmC,WACxB,EAEA,YAAAC,cAAA,SAAcC,IACP,IAAA/C,WAAUxG,KAAKyG,kBAEpBzG,KAAKyG,gBAAgB6C,cAAcC,EACrC,EAEA,YAAAC,kBAAA,SAAkBD,IACX,IAAA/C,WAAUxG,KAAKkH,YAEpBlH,KAAKkH,UAAUsC,kBAAkBD,EACnC,EAEA,YAAAL,aAAA,SACEO,EAIA2nB,GAOA,IAAK,IAAA5qB,WAAUxG,KAAKkH,aACf,IAAAV,WAAUxG,KAAKyG,iBAApB,CAEAzG,KAAKkH,UAAUgC,aAAaO,GAE5B,IAAMhD,EAAkBzG,KAAKyG,gBAC7BA,EAAgB8qB,YAAYlkB,aAAe+jB,aAAc,EAAdA,EAAgB/jB,aAC3D5G,EAAgB8qB,YAAY9a,WAAa2a,aAAc,EAAdA,EAAgB3a,WACzDhQ,EAAgB8qB,YAAYlb,WAAa+a,aAAc,EAAdA,EAAgB/a,WACzD5P,EAAgB8qB,YAAY1jB,cAAgBujB,aAAc,EAAdA,EAAgBvjB,aARhB,CAS9C,EApDgB,EAAA/K,QAAkB,EAAArF,QAqDpC,C,CArGA,GAAa,EAAAo0B,wBAAAA,C,6lBCxBb,aASA,cAGE,WACE3G,EACA9kB,EACAgrB,GAOA,QAAK,UAAClG,EAAc9kB,IAAK,K,OAZ3B,EAAAmrB,YAAwC,CAAC,EAqBzC,EAAArnB,iBAAmB,WAEjB,MAAO,EACT,EACS,EAAAC,cAAgB,WAAM,SAAAC,OAAOwjB,KAAP,EAV7B,EAAK2D,YAAYlkB,aAAe+jB,aAAc,EAAdA,EAAgB/jB,aAChD,EAAKkkB,YAAY9a,WAAa2a,aAAc,EAAdA,EAAgB3a,WAC9C,EAAK8a,YAAYlb,WAAa+a,aAAc,EAAdA,EAAgB/a,WAC9C,EAAKkb,YAAY1jB,cAAgBujB,aAAc,EAAdA,EAAgBvjB,c,CACnD,CA0CF,OA9DqD,OA2B1C,YAAArB,uBAAT,W,gBACQE,EAAO,YAAMF,uBAAsB,WAGzCE,EAAKW,aAA4C,QAA7B,EAAArN,KAAKuxB,YAAYlkB,oBAAY,QAAIX,EAAKW,aAC1DX,EAAK+J,WAAwC,QAA3B,EAAAzW,KAAKuxB,YAAY9a,kBAAU,QAAI/J,EAAK+J,WACtD/J,EAAK2J,WAAwC,QAA3B,EAAArW,KAAKuxB,YAAYlb,kBAAU,QAAI3J,EAAK2J,WAGtD3J,EAAKsB,gBAAkD,QAAhC,EAAAhO,KAAKuxB,YAAYvjB,uBAAe,QAAItB,EAAKsB,gBAEhE,IAAMgI,EAAoD,QAAjC,EAAAhW,KAAKuxB,YAAYvb,wBAAgB,QAAItJ,EAAKsJ,iBAKnE,OAJAtJ,EAAKsJ,kBAA4C,IAAzBtJ,EAAKsB,gBAA2BgI,OAAmB7V,EAE3EuM,EAAKmB,cAA8C,QAA9B,EAAA7N,KAAKuxB,YAAY1jB,qBAAa,QAAInB,EAAKmB,cAErDnB,CACT,EAES,YAAAH,wBAAT,WACE,YAAMA,wBAAuB,WAC7BvM,KAAKuxB,YAAc,CAAC,CACtB,EAES,YAAApH,aAAT,WACE,OAAOnqB,KAAKkrB,aAAelrB,KAAKkrB,aAAa4G,gBAAa3xB,CAC5D,EAEA,YAAA4pB,2BAAA,WACE,MAAO,CACL1Y,aAASlR,EACT2R,MAAO9R,KAAKkrB,aAAelrB,KAAKkrB,aAAanH,gBAAa5jB,EAC1D4R,OAAQ/R,KAAKkrB,aAAelrB,KAAKkrB,aAAajH,iBAAc9jB,EAEhE,EACF,EA9DA,CAHA,QAGqDksB,sBAAxC,EAAAgF,gCAAAA,C,oHCTb,cAEA,aACE,WAA6BpZ,GAA7B,WAA6B,KAAAA,UAAAA,EA4E7B,KAAA/R,iBAAmB,W,IAAC,uDAClB,IAAAkS,aAAW,W,MAAM,WAAKH,WAAU/R,iBAAgB,QAAI1F,EAAnC,GACnB,EAEA,KAAAwf,oBAAsB,W,IAAC,uDACrB,IAAA5H,aAAW,W,MAAM,WAAKH,WAAU+H,oBAAmB,QAAIxf,EAAtC,GACnB,CAlF2D,CA2F7D,OAzFE,sBAAI,0BAAW,C,IAAf,sBACE,OAAO,IAAA4X,aAAW,WAAM,SAAKH,UAAUlV,WAAf,GAC1B,E,gCAEA,sBAAI,uBAAQ,C,IAAZ,sBACE,OAAO,IAAAqV,aAAW,WAAM,SAAKH,UAAUkB,QAAf,GAC1B,E,gCAEA,sBAAI,oBAAK,C,IAAT,sBACE,OAAO,IAAAf,aAAW,WAAM,SAAKH,UAAUkM,KAAf,GAC1B,E,gCAEA,sBAAI,qBAAM,C,IAAV,sBACE,OAAO,IAAA/L,aAAW,WAAM,SAAKH,UAAUlG,MAAf,GAC1B,E,gCAEA,sBAAI,oBAAK,C,IAAT,sBACE,OAAO,IAAAqG,aAAW,WAAM,SAAKH,UAAUnG,KAAf,GAC1B,E,gCAEA,sBAAI,uBAAQ,C,IAAZ,sBACE,OAAO,IAAAsG,aAAW,WAAM,SAAKH,UAAU9U,QAAf,GAC1B,E,gCAEA,sBAAI,kBAAG,C,IAAP,sBACE,OAAO,IAAAiV,aAAW,WAAM,SAAKH,UAAUgX,GAAf,GAC1B,E,gCAEA,sBAAI,yBAAU,C,IAAd,sBACE,OAAO,IAAA7W,aAAW,WAAM,SAAKH,UAAU6Z,UAAf,GAC1B,E,gCAEA,sBAAI,yBAAU,C,IAAd,sBACE,OAAO,IAAA1Z,aAAW,WAAM,SAAKH,UAAUmX,UAAf,GAC1B,E,gCAEA,sBAAI,qBAAM,C,IAAV,sBACE,OAAO,IAAAhX,aAAW,WAAM,SAAKH,UAAUuX,MAAf,GAC1B,E,gCAEA,sBAAI,oBAAK,C,IAAT,sBACE,OAAO,IAAApX,aAAW,WAAM,SAAKH,UAAU1X,KAAf,GAC1B,E,gCAEA,sBAAI,yBAAU,C,IAAd,sBACE,OAAO,IAAA6X,aAAW,WAAM,SAAKH,UAAUoY,UAAf,GAC1B,E,gCAEA,sBAAI,qBAAM,C,IAAV,sBACE,OAAO,IAAAjY,aAAW,WAAM,SAAKH,UAAUsY,MAAf,GAC1B,E,gCAEA,sBAAI,oBAAK,C,IAAT,sBACE,OAAO,IAAAnY,aAAW,WAAM,SAAKH,UAAUwY,KAAf,GAC1B,E,gCAEA,sBAAI,2BAAY,C,IAAhB,sBACE,OAAO,IAAArY,aAAW,WAAM,SAAKH,UAAU2Y,YAAf,GAC1B,E,gCAEA,sBAAI,yBAAU,C,IAAd,sBACE,OAAO,IAAAxY,aAAW,WAAM,SAAKH,UAAU8L,UAAf,GAC1B,E,gCAEA,sBAAI,0BAAW,C,IAAf,sBACE,OAAO,IAAA3L,aAAW,WAAM,SAAKH,UAAUgM,WAAf,GAC1B,E,gCAEA,YAAA8N,wBAAA,sBAGE,OAAO,IAAA3Z,aAAW,mBAAM,OAAsC,QAAtC,OAAKH,WAAU8Z,+BAAuB,sBAAI,GACpE,EAcA,YAAA7C,aAAA,WACE,OAAOlvB,KAAKiY,SACd,EACF,EA5FA,GAAa,EAAAkT,sBAAAA,C,qFCFb,cAGA,aAGE,WAAoB6G,GAAA,KAAAA,aAAAA,EAFZ,KAAAC,2BAA6B,CAEiC,CAoBxE,OAlBE,YAAAvD,iBAAA,WACE,GAAyBvuB,MAArBH,KAAKgyB,aACP,OAAO,EAGT,IAAME,EAAkBlyB,KAAKgyB,aAAaD,0BAC1C,IAAI,IAAAvjB,WAAU0jB,GACZ,OAAO,EAGT,IAAMjkB,EAAgBikB,EAAgBC,mBAChCC,EAAuBnkB,EAAgBjO,KAAKiyB,2BAElD,OADAjyB,KAAKiyB,2BAA6BhkB,EAC3BmkB,CACT,EACA,YAAArjB,MAAA,WACE/O,KAAKiyB,2BAA6B,CACpC,EACF,EAvBA,G,kWCFA,aACA,UACA,UACA,UACA,UAUA,UACA,UACA,UACA,UACA,UAIA,aAeE,WAAY7rB,GAdH,KAAAoO,qBAA8D,IAAI,EAAA2H,gBAClE,KAAA5I,oBAA4C,IAAI,EAAA4I,gBAChD,KAAA5K,qBAA6C,IAAI,UACjD,KAAAxK,YAAc,IAAI,EAAAsrB,YAClB,KAAArnB,sBAAqB,KAA8B,EAAAsnB,8BAIlD,KAAAtoB,0BAAuD,IAAI,EAAA+N,0BAC3D,KAAAtN,wBAAqDtK,EAC5C,KAAAqC,mBAAyC,IAAI,EAAA+vB,mBAKzDnsB,IACHA,EAAO,CACLuc,eAAWxiB,IAGViG,EAAKuc,YACRvc,EAAKuc,WAAY,IAAAhG,wBAGnB3c,KAAKoG,KAAOA,CACd,CA2FF,OAzFE,YAAAwO,QAAA,WACE5U,KAAK8K,aAAa0nB,iBAClBxyB,KAAKgL,sBAAsB4J,UAC3B5U,KAAKuM,0BACLvM,KAAKwC,mBAAmBoS,SAC1B,EAEA,YAAA3F,cAAA,SACEvP,EACAsR,EACAsQ,QAAA,IAAAA,IAAAA,EAAyB1D,KAAK6E,OAE9BzR,EAAYA,GAAa,CAAC,EACrBhR,KAAK8K,aAGR9K,KAAK8K,aAAa2nB,UAAU/yB,EAAOsR,EAAWsQ,GAF9C,EAAAtZ,OAAO4X,IAAI,mDAIf,EAEA,YAAAjT,sBAAA,WACE,IAAM+lB,GAAa,IAAAC,6BAEnB,MAAO,CACLC,aAAcF,aAAU,EAAVA,EAAY3gB,OAC1B8gB,YAAaH,aAAU,EAAVA,EAAY5gB,MAE7B,EAEA,YAAAtH,sBAAA,WAEA,EAEA,YAAAkE,eAAA,WACE,MAAO,EACT,EAEA,YAAAE,qBAAA,WACE,MAAO,CACLkkB,sBAAuB,EACvBC,qBAAsB,EACtBC,qBAAsB,EACtBC,iBAAkB,EAClBC,iBAAkB,EAClBC,iBAAkB,EAClBC,mBAAoB,EAExB,EAEA,YAAAtkB,+BAAA,WAEA,EAEA,YAAAxF,cAAA,SAAcC,GACZ,IAAM8pB,EAAgBrzB,KAAK8K,aAAawoB,aAClCtiB,EAAmC,CAACuiB,iBAAkBhqB,EAAQxG,YAAa/C,KAAK+C,cAGpF/C,KAAK8K,aAAawoB,cACkB,UAAnCtzB,KAAK8K,aAAawoB,cAA+D,YAAnCtzB,KAAK8K,aAAawoB,aAajEtzB,KAAKgL,sBAAsBwoB,sBAAiBrzB,OAAWA,EAAW6Q,IATlEhR,KAAKiP,cAAc,EAAAC,MAAMukB,mBAAoB,CAAC1wB,YAAa/C,KAAK+C,cAIhE/C,KAAKiP,cAAc,EAAAC,MAAMmkB,GAAgBriB,GAO7C,EAEA,YAAA9H,aAAA,SAAaD,GACXjJ,KAAKiP,cAAc,EAAAC,MAAMwkB,qBAAsB,CAAC3wB,YAAa/C,KAAK+C,YAAa0G,OAAQR,GACzF,EAEA,YAAAsD,wBAAA,WACEvM,KAAKgK,0BAA0B+E,QAC/B/O,KAAKyK,wBAAqBtK,CAC5B,EAEA,YAAAwzB,cAAA,SAAcvC,GACZ,IAAMwC,EAAe5zB,KAAK+G,YAAY8sB,kBACtC7zB,KAAK8K,aAAa6oB,cAAc3zB,KAAK+C,YAAa6wB,EAAcxC,EAClE,EACF,EArHA,GAAsB,EAAApZ,gBAAAA,C,qHCpBtB,IAyCYtT,EAzCZ,aACE,KAAAd,YAAc,SAACkwB,GAAsB,EACrC,KAAA9vB,aAAe,SAAC8vB,GAAsB,EACtC,KAAA5vB,iBAAmB,SAAC6vB,GAAgC,EACpD,KAAAzvB,kBAAoB,SAACyvB,GAAgC,EACrD,KAAAvvB,YAAc,SAAC6K,GAAmC,EAClD,KAAArK,UAAY,SAACqK,GAAiC,EAC9C,KAAAtJ,mBAAqB,SAACsJ,GAA0C,EAChE,KAAA1K,aAAe,SAAC0K,GAAoC,EACpD,KAAAvK,YAAc,SAACgvB,GAAsB,EACrC,KAAAtwB,OAAS,WAAY,EACrB,KAAAE,QAAU,WAAY,EACtB,KAAAuC,eAAiB,WAAY,CAC/B,EAba,EAAAvD,YAAAA,EAyCb,SAAYgC,GACV,iCACA,sBACA,gCACD,CAJD,CAAYA,IAAU,aAAVA,EAAU,I,2GC3CtB,cACA,UAIA,UACA,UACA,UACA,UAKA,UACA,UAGA,UACA,UAEA,aAIE,WAAY+E,EAAyBlH,EAAa6D,GAChD,IAAI,IAAA2B,+BAA8BxF,GAChC,EAAAyF,OAAOC,mBAAmB,uEAD5B,EAIA,IAAAC,+BAA8B3F,GAE9B,IAAM8F,GAAkB,IAAAC,yBAAwBmB,IAC3C,IAAAlB,+BAA8BF,MAInC,IAAAG,8BAA6BH,GAE7BrI,KAAKyG,gBAAkB,IAAI,EAAAutB,qBAAqB,IAAI,EAAAC,iBAAiB1xB,GAAS6D,GAC9EpG,KAAKkH,UAAY,EAAA2B,UAAUxK,OAAOgK,EAAiBrI,KAAKyG,iBACxDzG,KAAK8I,eAAevG,GAZpB,CAaF,CA2FF,OAtFU,YAAAuG,eAAR,SAAuBvG,G,MAEf2xB,EAAkBvzB,OAAOwzB,eAAe5xB,GACxC6xB,EAC2C,QAA/C,EAAAzzB,OAAO0zB,yBAAyB9xB,EAAQ,eAAO,QAAI5B,OAAO0zB,yBAAyBH,EAAiB,QACtG,IAAyC,KAArCE,aAAsB,EAAtBA,EAAwBE,gBAAqDn0B,KAAhCi0B,aAAsB,EAAtBA,EAAwBG,KAAzE,CAUA,IAAMxrB,EAAexG,EAAOyG,KAWtBwrB,EAAsBx0B,KAAKyG,gBAEjClE,EAAOyG,KAAO,W,IAAC,sDACb,WAAIkV,SAAQ,SAACC,EAASsW,GACpB1rB,EACG9H,MAAMsB,EAAQ/B,GACdk0B,MAAK,SAACC,GAAW,OAAAxW,EAAQwW,EAAR,IACjBC,OAAM,SAACr0B,G,MACAwiB,EAAc,CAClBhgB,YAAa,EAEb8P,KAAiB,QAAX,EAAAtS,aAAK,EAALA,EAAOsS,YAAI,aAAI1S,EACrB2S,SAAS,IAAAK,kBAAiB,CAAC0hB,SAAUt0B,aAAK,EAALA,EAAOs0B,SAAUnhB,SAAUnT,aAAK,EAALA,EAAOmT,WACvEV,KAAM,CAACE,gBAAgB,IAAAC,kBAAiB5S,aAAK,EAALA,EAAOyS,OAC/CC,cAAe1S,GAGjBi0B,EAAoBvlB,cAAc,EAAAC,MAAM0D,MAAOmQ,GAG/C0R,EAAOl0B,EACT,GACJ,GAnBA,CAhBF,MALE,EAAAyH,OAAOC,mBACL,2NAwCN,EAIA,sBAAI,sBAAO,C,IAAX,WACE,OAAO,EAAAxK,OACT,E,gCAEA,YAAA2L,uBAAA,WACE,IAAK,IAAA5C,WAAUxG,KAAKkH,WAEpB,OAAOlH,KAAKkH,UAAUkC,wBACxB,EAEA,YAAAC,UAAA,WACE,IAAK,IAAA7C,WAAUxG,KAAKkH,WAEpB,OAAOlH,KAAKkH,UAAUmC,WACxB,EAEA,YAAAC,cAAA,SAAcC,IACP,IAAA/C,WAAUxG,KAAKyG,kBAEpBzG,KAAKyG,gBAAgB6C,cAAcC,EACrC,EAEA,YAAAC,kBAAA,SAAkBD,IACX,IAAA/C,WAAUxG,KAAKkH,YAEpBlH,KAAKkH,UAAUsC,kBAAkBD,EACnC,EAEA,YAAAL,aAAA,SAAaO,IACN,IAAAjD,WAAUxG,KAAKkH,YAEpBlH,KAAKkH,UAAUgC,aAAaO,EAC9B,EAlCgB,EAAA3G,QAAkB,EAAArF,QAmCpC,C,CAhHA,GAAa,EAAAq3B,aAAAA,C,k2BCpBb,cACA,SACA,UACA,UACA,UAQA,UACA,UACA,UACA,UAIA,UAEA,cAGE,WAAYvyB,EAA0B6D,GAAtC,WACQ8kB,EAAe3oB,EAAOwyB,kB,OAC5B,IAAK,UAAC7J,EAAe,IAAI,EAAAC,sBAAsBD,QAAoC/qB,EAAWiG,IAAK,MA0D5F+D,cAAgB,WAAM,SAAAC,OAAO4qB,KAAP,EAE/B,EAAA9qB,iBAAmB,iBAAM,OAAyB,QAAzB,IAAK3H,OAAO0yB,qBAAa,QAAI,SAAS,EAEtD,EAAA/nB,OAAS,WAChB,OAAO,EAAK3K,OAAS,EAAKA,OAAO2K,cAAW/M,CAC9C,EAoDS,EAAAovB,+BAAiC,SAACzQ,GACzC,EAAKvc,OAAO2D,iBAAiB,EAAAgvB,iBAAiBtiB,OAAO,SAAClT,G,0BACpD,EAAKuP,cAAc,EAAAC,MAAM0D,MAAO,CAC9B7P,YAA2C,QAA9B,EAAiB,QAAjB,IAAKmoB,oBAAY,eAAEnoB,mBAAW,QAAI,EAC/C8P,KAAwB,QAAlB,EAAY,QAAZ,EAAAnT,EAAMy1B,cAAM,eAAEtiB,YAAI,aAAI1S,EAC5B2S,QAA8B,QAArB,EAAY,QAAZ,EAAApT,EAAMy1B,cAAM,eAAEriB,eAAO,aAAI3S,EAClC8S,cAAevT,EACfsT,KAAM,CACJE,gBAAgB,IAAAC,kBAAiBzT,EAAMy1B,QACvCC,iBAAuC,QAArB,EAAY,QAAZ,EAAA11B,EAAMy1B,cAAM,eAAEriB,eAAO,aAAI3S,EAC3Ck1B,oBAAqD,QAAhC,EAAmB,QAAnB,EAAY,QAAZ,EAAA31B,EAAMy1B,cAAM,eAAEG,aAAK,eAAEC,MAAM,aAAK,aAAIp1B,IAG/D,GACF,EAjIE,EAAKoC,OAASA,E,CAChB,CAiIF,OAxI0C,OAS/B,YAAA6I,WAAT,SAAoBlE,GAApB,I,EAAA,OACE,YAAMkE,WAAU,UAAClE,GAEjB,IAAM8qB,EAAkE,QAAlD,EAAAhyB,KAAKuC,OAAOwyB,yBAAsC,aAAI50B,EAE5E,IAAI,IAAAwF,cAAaqsB,GACfhyB,KAAKuuB,gBAAgB,IAAI,EAAApD,sBAAsB6G,QAC1C,CAIL,IAAM,EAAwC,SAACtyB,GAC7C,GAAoB,iBAAhBA,EAAMjB,MACR,IACE,EAAK8D,OAAOyd,oBAAoB,EAAAkV,iBAAiBM,cAAe,GAEhE,IAAMtK,EAAe,EAAK3oB,OAAOwyB,kBACjC,EAAKxG,iBAAgB,IAAA5oB,cAAaulB,GAAgB,IAAI,EAAAC,sBAAsBD,QAAgB/qB,EAC9F,CAAE,MAAOlB,GACP,EAAA+I,OAAOC,mBACL,4IACAhJ,GAEF,EAAK2V,SACP,CAEJ,EAEA5U,KAAKuC,OAAO2D,iBAAiB,EAAAgvB,iBAAiBM,cAAe,EAC/D,CAsBA,OAnBAx1B,KAAKuC,OAAO2D,iBAAiB,EAAAgvB,iBAAiBlN,WAAW,SAAClJ,GACxD,EAAKuQ,6BACP,IAEArvB,KAAKuC,OAAO2D,iBAAiB,EAAAgvB,iBAAiBM,eAAe,SAAC91B,GACxC,WAAhBA,EAAMjB,QAGR,EAAKwQ,cAAc,EAAAC,MAAMyF,OAAQ,CAAC,GAClC,EAAKC,UAET,IAQO,CANqB,IAAI,EAAA1I,oBAC9BhF,EAAUiF,oCACV,IAAI,EAAAC,mBAAmBlF,EAAUiF,oCAAoCE,iBACrE,CAACnF,EAAUoF,8BACXnM,GAGJ,EAUS,YAAAqM,uBAAT,WACE,IAAMkd,EAAY,KACb,YAAMld,uBAAsB,YAG3Bod,GAAY,IAAA6L,mBAAkBz1B,KAAKuC,QAGzC,OAFAvC,KAAKgK,0BAA0B8f,uBAAuBJ,EAAcE,GAE7DF,CACT,EAES,YAAApc,cAAT,WACE,OAAO,IAAAooB,sBAAqB11B,KAAKuC,OACnC,EAES,YAAA4nB,aAAT,W,MACE,OAAgC,QAAzB,EAAAnqB,KAAKuC,OAAOozB,qBAAa,aAAIx1B,CACtC,EAES,YAAA4pB,2BAAT,WACE,IAAM6L,EAAgB51B,KAAKuC,OAAOszB,mBAElC,IAAI,IAAArnB,WAAUonB,GAEZ,OAAO,KAGT,IAAME,EAAmBF,EACtBnS,QAAO,SAACsS,GAAe,OAAAA,EAAMC,MAAN,IACvBvS,QAAO,SAACsS,GAAe,OAAAA,EAAM1f,iBAAgClW,IAAlB41B,EAAME,OAA1B,IAAiD,GAE3E,OAAKH,EASE,CACLzkB,QALcykB,EAAiBI,gBAAkBJ,EAAiBK,UAMlErkB,MALYgkB,EAAiBhkB,MAM7BC,OALa+jB,EAAiB/jB,QALvB,IAYX,EAoBF,EAxIA,CAA0C,EAAAsa,sBAA7B,EAAA2H,qBAAAA,EA0IA,EAAAyB,kBAAoB,SAAClzB,GAChC,IACM6zB,EADgB7zB,EAAOszB,mBACKhgB,MAAK,SAACkgB,GAAe,OAAAA,EAAMC,MAAN,IAEvD,MAAO,CACL3f,WAAY+f,aAAW,EAAXA,EAAa/f,WACzBI,WAAY2f,aAAW,EAAXA,EAAa3f,WAE7B,EAEa,EAAAif,qBAAuB,SAACnzB,G,MAC7B8zB,EAAuC,QAAxB,EAAA9zB,EAAO+zB,yBAAiB,eAAExU,cAE/C,GAAIuU,IAAiB,EAAAnS,YAAYhP,KAC/B,OAAO,EAAAgP,YAAYhP,KACd,GAAImhB,IAAiB,EAAAnS,YAAY9O,IACtC,OAAO,EAAA8O,YAAY9O,IAWrB,OAAI,IAAA5G,WAAU6nB,IAPe,IAOE9zB,EAAOg0B,gBAA0C,IAAA5wB,cAAapD,EAAOozB,eAC3F,EAAAzR,YAAYsS,UADrB,CAKF,C,+GChMA,cAEA,aAQE,WAA6Bve,GAA7B,WAA6B,KAAAA,UAAAA,EAE7B,KAAA/R,iBAAmB,SAACT,EAAMqa,IACxB,IAAA1H,aAAW,WAAM,SAAKH,UAAU/R,iBAAiBT,EAAMqa,EAAtC,GACnB,EAEA,KAAAE,oBAAsB,SAACva,EAAMqa,IAC3B,IAAA1H,aAAW,WAAM,SAAKH,UAAU+H,oBAAoBva,EAAMqa,EAAzC,GACnB,EAEA,KAAAiV,gBAAkB,WAAM,WAAA3c,aAAW,WAAM,SAAKH,UAAU8c,iBAAf,GAAjB,EAExB,KAAA7nB,OAAS,WAAM,WAAAkL,aAAW,WAAM,SAAKH,UAAU/K,QAAf,GAAjB,EAEf,KAAAyoB,YAAc,WAAM,WAAAvd,aAAW,WAAM,SAAKH,UAAU0d,aAAf,GAAjB,EAEpB,KAAAE,iBAAmB,WAAM,WAAAzd,aAAW,WAAM,SAAKH,UAAU4d,kBAAf,GAAjB,EAEzB,KAAAS,gBAAkB,WAEhB,OAAO,IAAAle,aAAW,mBAAM,OAA8B,QAA9B,OAAKH,WAAUqe,uBAAe,sBAAI,GAC5D,EAEA,KAAAC,YAAc,WAAM,WAAAne,aAAW,mBAAM,OAA0B,QAA1B,OAAKH,WAAUse,mBAAW,sBAAI,GAA/C,CAvB0B,CA4BhD,OAHE,sBAAI,4BAAa,C,IAAjB,sBACE,OAAO,IAAAne,aAAW,WAAM,SAAKH,UAAUuU,YAAY1pB,OAA3B,GAC1B,E,gCACF,EApCA,GAAa,EAAAmxB,iBAAAA,C,6GCWA,EAAAiB,iBAAmB,CAK9BuB,UAAW,YAKXjB,cAAe,gBAKfkB,aAAc,eAKd1O,UAAW,YAKXpV,MAAO,Q,oHCcT,qBASA,mBA7DA,cAGA,UASA,qCACU,KAAAnI,wBAAqDtK,EAkB7D,KAAAic,mBAAqB,SAAC1c,GACpB,IAAM6c,EAAc7c,EAAM6c,YAG1B,GAAKA,EAAYG,WAKb,IAAA/W,cAAa,EAAK8E,qBAAwBksB,EAAiBpa,EAAY9W,MAA3E,CAIA,IAAMsO,EAAU6iB,EAAera,EAAY9W,MAC3C,EAAKgF,mBAAqB,CACxBsJ,QAASA,EACTE,YAAasI,EAAYzW,aAL3B,CAOF,CACF,QA/BE,YAAA+I,QAAA,WACE,OAAO7O,KAAKyK,kBACd,EAMA,YAAAsE,MAAA,WACE/O,KAAKyK,wBAAqBtK,CAC5B,EAqBF,EAtCA,GAwCA,SAAgBw2B,EAAiBlxB,GAC/B,OACEA,IAAS,EAAAuX,gBAAgB6Z,sBACzBpxB,IAAS,EAAAuX,gBAAgB8Z,sBACzBrxB,IAAS,EAAAuX,gBAAgB+Z,uBACzBtxB,IAAS,EAAAuX,gBAAgBga,oBAE7B,CAEA,SAAgBJ,EAAeK,GAE7B,IAAMC,EAAQD,EAAYC,MAAM,sBAChC,OAAOA,EAAQA,EAAM,GAAK,SAC5B,CArDa,EAAAC,sBAAAA,C,6HCPb,8BA+CA,QAtCE,YAAAC,sBAAA,SAAsB9V,EAAwBve,GAE5C,QAAgC5C,IAA5BH,KAAKq3B,yBAA6Dl3B,IAAzBH,KAAKs3B,gBAGhD,OAFAt3B,KAAKq3B,mBAAqB/V,EAC1BthB,KAAKs3B,gBAAkBv0B,GAChB,EAGT,IACMw0B,GADYjW,EAAiBthB,KAAKq3B,oBACT,IACzBG,EAAmBz0B,EAAc/C,KAAKs3B,gBAG5C,GAAIC,GAAc,GAAKC,EAAmB,EAGxC,OAFAx3B,KAAKq3B,mBAAqB/V,EAC1BthB,KAAKs3B,gBAAkBv0B,GAChB,EAKT,IAEM00B,EAAkBD,GAFQ,GAAbD,GAEuCC,GAD1B,EAAbD,EAMnB,OAHAv3B,KAAKq3B,mBAAqB/V,EAC1BthB,KAAKs3B,gBAAkBv0B,EAEhB00B,CACT,EAKA,YAAA1oB,MAAA,WACE/O,KAAKq3B,wBAAqBl3B,EAC1BH,KAAKs3B,qBAAkBn3B,CACzB,EACF,EA/CA,GAAa,EAAAu3B,iCAAAA,C,gHCGb,cACA,UAWA,UACA,UACA,UACA,UACA,UAKA,UAGA,UACA,UAEA,aAIE,WAAYjuB,EAAyBlH,EAAa6D,GAAlD,WACE,GAmBO,KAAAC,KAAgB,CACvBC,aAAc,SAACC,GACb,IAAK,IAAAC,WAAU,EAAKC,mBAEf,IAAAG,sCAAqCL,GAA1C,CAKA,IAAMM,GAA2B,IAAAC,mCAAkCP,GAEnE,EAAKE,gBAAgBM,YAAYT,aAAaO,EAJ9C,CAKF,EAEAG,QAAS,SAACC,GACR,IAAK,IAAAT,WAAU,EAAKU,aACf,IAAAV,WAAU,EAAKC,mBAEf,IAAAU,iCAAgCF,GAArC,CAKA,IAAMG,GAAsB,IAAAC,8BAA6BJ,GAEzD,EAAKR,gBAAgBM,YAAYC,QAAQI,GAMzC,EAAKF,UAAUI,sBACf,EAAKJ,UAAUK,kCAXf,CAYF,EAEAC,mBAAoB,SAACC,EAA4BC,GAC/C,IAAK,IAAAlB,WAAU,EAAKU,aACf,IAAAV,WAAU,EAAKC,mBAEf,IAAAkB,iCAAgCF,GAArC,CAKA,IAAMG,GAAkC,IAAAC,gCAA+BH,GAEvE,EAAKjB,gBAAgBM,YAAYS,mBAAmBC,EAAYG,EAJhE,CAKF,EAEAE,WAAY,YACL,IAAAtB,WAAU,EAAKU,aACf,IAAAV,WAAU,EAAKC,mBAEpB,EAAKA,gBAAgBM,YAAYe,aAEjC,EAAKZ,UAAUI,sBACf,EAAKJ,UAAUK,mCACjB,IA5EI,IAAAQ,+BAA8BxF,EAAOshB,SACvC,EAAA7b,OAAOC,mBAAmB,uEAD5B,EAMA,IAAAC,+BAA8B3F,EAAOshB,SAErC,IAAMxb,GAAkB,IAAAC,yBAAwBmB,IAC3C,IAAAlB,+BAA8BF,MAInC,IAAAG,8BAA6BH,GAE7BrI,KAAKyG,gBAAkB,IAAI,EAAAkxB,0BAA0B,IAAI,EAAAC,gBAAgBr1B,GAAS6D,GAClFpG,KAAKkH,UAAY,EAAA2B,UAAUxK,OAAOgK,EAAiBrI,KAAKyG,iBAbxD,CAcF,CAuHF,OAvDE,sBAAI,sBAAO,C,IAAX,WACE,OAAO,EAAAhJ,OACT,E,gCAEA,YAAA2L,uBAAA,WACE,IAAK,IAAA5C,WAAUxG,KAAKkH,WAEpB,OAAOlH,KAAKkH,UAAUkC,wBACxB,EAEA,YAAAC,UAAA,WACE,IAAK,IAAA7C,WAAUxG,KAAKkH,WAEpB,OAAOlH,KAAKkH,UAAUmC,WACxB,EAEA,YAAAC,cAAA,SAAcC,IACP,IAAA/C,WAAUxG,KAAKyG,kBAEpBzG,KAAKyG,gBAAgB6C,cAAcC,EACrC,EAEA,YAAAC,kBAAA,SAAkBD,IACX,IAAA/C,WAAUxG,KAAKkH,YAEpBlH,KAAKkH,UAAUsC,kBAAkBD,EACnC,EAEA,YAAAL,aAAA,SAAaO,IACN,IAAAjD,WAAUxG,KAAKkH,YAEpBlH,KAAKkH,UAAUgC,aAAaO,EAC9B,EAEA,YAAAkqB,cAAA,SAAcvC,GAUZ,IAAK,IAAAyG,iCAAgCzG,GAArC,CAKA,IAAM0G,GAA0B,IAAAC,wBAAuB3G,IAElD,IAAA5qB,WAAUxG,KAAKyG,kBAEpBzG,KAAKyG,gBAAgBktB,cAAcmE,EANnC,CAOF,EAxDgB,EAAAh1B,QAAkB,EAAArF,QAyDpC,C,CA7IA,GAAa,EAAAu6B,kBAAAA,C,4zBC4ab,iDAkBA,oCA/dA,aAEA,UACA,UACA,UACA,UACA,SACA,UACA,UACA,UACA,UAGA,UACA,UAQA,UAEA,UACA,UACA,UACA,UACA,UACA,UAGA,UACA,UACA,UACA,UACA,SAGA,cAoBE,WAAYz1B,EAAyB6D,GACnC,QAAK,UAACA,IAAK,KAlBI,EAAAwD,WAAiC,IAAI,EAAA6N,mBACrC,EAAAwgB,uBAAiD,EAAAC,uBAAuB75B,SACxE,EAAA85B,sBAA+C,IAAI,EAAAhB,sBACnD,EAAAiB,iCACf,IAAI,EAAAV,iCAIE,EAAAztB,qBAAsB,EAMtB,EAAAouB,oBAA8F,IAAIC,IAClG,EAAAC,oBAA8F,IAAID,IA0FjG,EAAA9tB,sBAAwB,WAAsC,SAAK2tB,sBAAsBtpB,SAA3B,EAtFrE,EAAKtM,OAASA,EACd,EAAKi2B,mBAAqB,IAAI,EAAAC,6BAA6Bl2B,GAC3D,EAAKi2B,mBAAmBnc,WAAU,SAAC3c,GAEjC,IAAMg5B,EAAmBC,EAAgCj5B,IACrD,IAAAiG,cAAa+yB,IACf,EAAK9uB,WAAW+T,eAAe+a,GAIjC,EAAKP,sBAAsB/b,mBAAmB1c,EAChD,IAEA,IAAMiL,EAA0B,IAAI,EAAAC,kBAAiB,WAAM,SAAK7H,WAAL,I,OAC3D,EAAK+H,aAAe,IAAI,EAAA8tB,gCACtB,EAAK5tB,sBACLL,EACA,EAAKvE,MAEPuE,EAAwBM,YAAY,EAAKH,cAEzC,EAAKvI,OAASA,E,CAChB,CAwXF,OApa+C,OA8C7C,sBAAI,uBAAQ,C,IAAZ,WACE,OAAOvC,KAAKmL,SACd,E,gCAEA,YAAAC,WAAA,SAAWlE,GAAX,WACElH,KAAKukB,yBAOLvkB,KAAKmL,UAAY,IAAI,EAAA0tB,mBAAmB74B,KAAKuC,OAAQvC,KAAKwC,oBAE1DxC,KAAKsL,+BAELtL,KAAK+G,YAAYwE,SAAS,CACxBC,qBAAsB,WAAM,SAAKzI,WAAL,EAC5B0I,4BAA6B,SAACC,GAC5BxE,EAAUyE,2BAA2BD,EACvC,EACAE,0BAA2B,SAACC,EAAmBC,GAK7C,EAAKhB,aAAaiB,kBAAkBF,EAAWC,GAAmB,EACpE,IAGF,IAAMgtB,EAAsB,IAAI,EAAA7sB,oBAAoB,CAACjM,KAAKw4B,qBACpDO,EAAsB,IAAI,EAAA7sB,oBAC9BhF,EAAUiF,oCACV,IAAI,EAAAC,mBAAmBlF,EAAUiF,oCAAoCE,iBACrE,CAACnF,EAAUoF,yBACXwsB,GAKF,OAFA94B,KAAKiP,cAAc,EAAAC,MAAM6R,MAAO,CAAChe,YAAa/C,KAAK+C,cAE5C,CAACg2B,EACV,EAEA,YAAA7uB,iBAAA,WAEE,IAAM8uB,GAA0B,IAAAC,8BAChC,OAAI,IAAAC,eAAcF,MAA6B,IAAAzQ,SAAQyQ,GAC9CA,EAGF,SACT,EACA,YAAA7uB,cAAA,WACE,OAAO,EAAAC,OAAW+uB,UACpB,EACA,YAAA7uB,cAAA,WACE,MAAO,OACT,EACA,YAAApH,YAAA,W,MACE,OAA2B,QAApB,EAAAlD,KAAKuC,OAAOY,gBAAQ,QAC7B,EAIA,YAAAqJ,uBAAA,W,gCACQspB,EAA0C,QAAvB,EAAA91B,KAAKuC,OAAO62B,mBAAW,eAAEvjB,MAAK,SAAC4Q,GAAM,OAAAA,EAAE1Q,OAAF,IACxDsjB,EAA0C,QAAvB,EAAAr5B,KAAKuC,OAAOspB,mBAAW,eAAEhW,MAAK,SAAC4Q,GAAM,OAAAA,EAAE1Q,OAAF,IACxDujB,EAAwC,QAAtB,EAAAt5B,KAAKuC,OAAO8tB,kBAAU,eAAExa,MAAK,SAAC4Q,GAAM,MAAW,YAAXA,EAAEpO,IAAF,IAExD1B,OAAiCxW,GACjC,IAAAwF,cAAsC,QAAzB,EAAgB,QAAhB,EAAA3F,KAAKuC,OAAOmjB,YAAI,eAAE6T,eAAO,eAAEC,SAC1C7iB,EAAW,EAAAC,SAASC,SACX,IAAAlR,cAAyC,QAA5B,EAAgB,QAAhB,EAAA3F,KAAKuC,OAAOmjB,YAAI,eAAE+T,kBAAU,eAAED,WACpD7iB,EAAW,EAAAC,SAASG,YAGtB,IAAM2iB,EAAiB15B,KAAKuC,OAAO4W,SAEnC,OAAO,SACFnZ,KAAK2M,yBACLgtB,EAA6C35B,KAAK45B,gBAAc,CACnEpjB,aAA6C,QAA/B,EAAA6iB,aAAgB,EAAhBA,EAAkBQ,qBAAa,eAAE1D,UAC/C1f,WAA2C,QAA/B,EAAA4iB,aAAgB,EAAhBA,EAAkBQ,qBAAa,eAAEC,OAC7CjsB,cAAewrB,aAAgB,EAAhBA,EAAkB3S,SACjC/P,SAAUA,EACV1I,cAAe,EACfL,WAAW,IAAAjI,cAAagR,GACxBzJ,SAAS,IAAAsB,WAAUkrB,KAAoBK,SAASL,GAChD/rB,QAAS3N,KAAKuC,OAAO4hB,MACrBlX,WAAYjN,KAAKsK,gBACjBsC,KAAgD,gBAAlB,QAAxB,EAAA5M,KAAKuC,OAAOy3B,oBAAY,eAAEC,aAA+B,EAAAltB,WAAWD,WAAa,EAAAC,WAAWC,OAClGgB,iBAAiB,IAAArI,cAAa2zB,GAC9BtjB,iBAAkBsjB,aAAe,EAAfA,EAAiB5S,SACnCjR,aAA6C,QAA/B,EAAAqgB,aAAgB,EAAhBA,EAAkB+D,qBAAa,eAAE1D,UAC/C9f,WAA2C,QAA/B,EAAAyf,aAAgB,EAAhBA,EAAkB+D,qBAAa,eAAEC,OAC7C3sB,eAAe,IAAAC,wBAAuBssB,GACtCvjB,oBAAqBnW,KAAKuC,OAAO0hB,YACjC7N,mBAAoBpW,KAAKuC,OAAOwhB,WAChCtW,kBAAsC,QAAnB,EAAAzN,KAAKuC,OAAOshB,eAAO,eAAEnW,aACxCH,iBAAqC,QAAnB,EAAAvN,KAAKuC,OAAOshB,eAAO,eAAErW,aAE3C,EAEA,sBAAuB,0BAAW,C,IAAlC,W,MACE,OAA8B,QAAvB,EAAAxN,KAAKuC,OAAOQ,mBAAW,QAAI,CACpC,E,gCAES,YAAA6L,qBAAT,WACE,OAAO5O,KAAK4J,WAAWiF,SACzB,EAES,YAAAC,+BAAT,WACE9O,KAAK4J,WAAWmF,OAClB,EAES,YAAAxC,wBAAT,WACE,YAAMA,wBAAuB,WAC7BvM,KAAK+G,YAAYwF,0BAEjBvM,KAAKq4B,oBAAoBtI,SAAQ,SAACjQ,EAAUiW,GAC1CA,EAAM/V,oBAAoB,uBAAwBF,EACpD,IACA9f,KAAKq4B,oBAAoB6B,QAEzBl6B,KAAKu4B,oBAAoBxI,SAAQ,SAACjQ,EAAUiW,GAC1CA,EAAM/V,oBAAoB,uBAAwBF,EACpD,IACA9f,KAAKu4B,oBAAoB2B,QAEzBl6B,KAAK6K,4BAAyB1K,EAC9BH,KAAK45B,mBAAgBz5B,EACrBH,KAAK4J,WAAWmF,QAChB/O,KAAKm4B,sBAAsBppB,QAC3B/O,KAAKw4B,mBAAmBzpB,QACxB/O,KAAKo4B,iCAAiCrpB,OACxC,EAES,YAAAE,cAAT,SAGEvP,EAA0BsR,GAC1BhR,KAAKi4B,uBAAuBkC,cAC1Bz6B,EACAsR,EACAhR,KAAK8K,aAAawoB,aAClB,YAAMrkB,cAAcuV,KAAKxkB,MAE7B,EAEQ,YAAAo6B,0BAAR,SAAkCC,GAIhC,IAAMpkB,EAAeokB,EAAaC,QAE5BlpB,EAAuC,CAC3C3L,KAAM,QACNqM,MAAOmE,EAAanE,MACpBC,OAAQkE,EAAalE,OACrBV,QAAS4E,EAAakgB,UACtBpzB,YAAa/C,KAAK+C,aAGhB/C,KAAKuR,qBAAqBS,8BAA8BiE,EAAakgB,YACvEn2B,KAAKiP,cAAc,EAAAC,MAAM+C,aAAcb,GAGzCpR,KAAKuR,qBAAqBW,gBAAgB+D,EAAakgB,WACvDn2B,KAAKgL,sBAAsB2G,wBAAwBP,EACrD,EAEQ,YAAAmpB,0BAAR,SAAkCF,GAChC,IAAMC,EAAUD,EAAaC,QAEvBlpB,EAAuC,CAC3C3L,KAAM,QACN4L,QAASipB,EAAQnE,UACjBpzB,YAAa/C,KAAK+C,aAGhB/C,KAAKuR,qBAAqBC,8BAA8B8oB,EAAQnE,YAClEn2B,KAAKiP,cAAc,EAAAC,MAAMuC,aAAcL,GAGzCpR,KAAKuR,qBAAqBG,gBAAgB4oB,EAAQnE,WAClDn2B,KAAKgL,sBAAsB2G,wBAAwBP,EACrD,EAEQ,YAAAmT,uBAAR,e,gBAAA,OACEvkB,KAAKuC,OAAO2D,iBAAiB,gBAAgB,SAACmJ,GAY5C,EAAKJ,cAAc,EAAAC,MAAM6R,MAAO,CAAC,EACnC,IAEA/gB,KAAKuC,OAAO2D,iBAAiB,uBAAuB,SAACxG,IAE/C,IAAAiG,cAAa,EAAKi0B,gBAIpB,EAAK3qB,cAAc,EAAAC,MAAMwkB,qBAAsB,CAAC3wB,YAAa,EAAK8H,uBAAwBpB,OAAQ,CAAC,IAErG,EAAKmwB,cAAgBl6B,EAAMk6B,aAC7B,IAEA55B,KAAKuC,OAAO2D,iBAAiB,QAAQ,SAACxG,GACpC,EAAKuP,cAAc,EAAAC,MAAMc,KAAM,CAACjN,YAAarD,EAAMqD,aACrD,IAEA/C,KAAKuC,OAAO2D,iBAAiB,SAAS,SAACxG,GACrC,EAAKuP,cAAc,EAAAC,MAAMiB,MAAO,CAACpN,YAAarD,EAAMqD,aACtD,IAEuB,QAAvB,EAAA/C,KAAKuC,OAAO62B,mBAAW,SAAElzB,iBAAiB,YAAY,SAACxG,GAGrD,IAAM86B,EAAa96B,EAAMq2B,MAEnBjW,EAAW,SAACua,GAChB,EAAKD,0BAA0BC,EACjC,EACAG,EAAWt0B,iBAAiB,uBAAwB4Z,GACpD,EAAKuY,oBAAoB9D,IAAIiG,EAAY1a,EAC3C,IAEuB,QAAvB,EAAA9f,KAAKuC,OAAO62B,mBAAW,SAAElzB,iBAAiB,eAAe,SAACxG,GAGxD,IAAM86B,EAAa96B,EAAMq2B,MAEnBjW,EAAW,EAAKuY,oBAAoBpZ,IAAIub,GAC1C1a,IACF0a,EAAWxa,oBAAoB,uBAAwBF,GACvD,EAAKuY,oBAAoBoC,OAAOD,GAEpC,IAGA,IAAoB,UAAuB,QAAvB,EAAAx6B,KAAKuC,OAAO62B,mBAAW,QAAI,GAA3B,eAA+B,CAA9C,IACGtZ,EAAW,SAACua,GAChB,EAAKD,0BAA0BC,EACjC,GAHStE,EAAK,MAIR7vB,iBAAiB,uBAAwB4Z,GAC/C9f,KAAKq4B,oBAAoB9D,IAAIwB,EAAOjW,EACtC,CAEuB,QAAvB,EAAA9f,KAAKuC,OAAOspB,mBAAW,SAAE3lB,iBAAiB,YAAY,SAACxG,GAGrD,IAAM86B,EAAa96B,EAAMq2B,MAEnBjW,EAAW,SAACua,GAChB,EAAKE,0BAA0BF,EACjC,EACAG,EAAWt0B,iBAAiB,uBAAwB4Z,GACpD,EAAKyY,oBAAoBhE,IAAIiG,EAAY1a,EAC3C,IAEuB,QAAvB,EAAA9f,KAAKuC,OAAOspB,mBAAW,SAAE3lB,iBAAiB,eAAe,SAACxG,GAGxD,IAAM86B,EAAa96B,EAAMq2B,MAEnBjW,EAAW,EAAKyY,oBAAoBtZ,IAAIub,GAC1C1a,IACF0a,EAAWxa,oBAAoB,uBAAwBF,GACvD,EAAKyY,oBAAoBkC,OAAOD,GAEpC,IAGA,IAAoB,UAAuB,QAAvB,EAAAx6B,KAAKuC,OAAOspB,mBAAW,QAAI,GAA3B,eAA+B,CAA9C,IAAMkK,EACHjW,EAAW,SAACua,GAChB,EAAKE,0BAA0BF,EACjC,GAHStE,EAAK,MAIR7vB,iBAAiB,uBAAwB4Z,GAC/C9f,KAAKu4B,oBAAoBhE,IAAIwB,EAAOjW,EACtC,CAEA9f,KAAKuC,OAAO2D,iBAAiB,WAAW,SAACmJ,GAGvC,EAAKJ,cAAc,EAAAC,MAAMsB,KAAM,CAACzN,YAAa,EAAK8H,wBACpD,IAEA7K,KAAKuC,OAAO2D,iBAAiB,cAAc,SAACxG,GAC1C,EAAKmL,uBAAyBnL,EAAMqD,YAUG,YAAnC,EAAK+H,aAAawoB,cAChB,EAAK8E,iCAAiChB,sBAAsB13B,EAAMg7B,KAAKC,UAAWj7B,EAAMqD,eAC1F,EAAAiF,OAAO4X,IACL,gHAAyGlgB,EAAMg7B,KAAKC,UAAS,iCAAyBj7B,EAAMqD,cAE9J,EAAKkM,cAAc,EAAAC,MAAMgB,QAAS,CAACnN,YAAarD,EAAMqD,cAG5D,IAEA/C,KAAKuC,OAAO2D,iBAAiB,WAAW,SAACxG,GACvC,EAAKuP,cAAc,EAAAC,MAAMgB,QAAS,CAACnN,YAAarD,EAAMqD,aACxD,IAEA/C,KAAKuC,OAAO2D,iBAAiB,WAAW,SAACxG,GACvC,EAAKuP,cAAc,EAAAC,MAAM0B,gBAAiB,CAAC7N,YAAarD,EAAMqD,aAChE,IAEA/C,KAAKuC,OAAO2D,iBAAiB,SAAS,SAACxG,GACrC,EAAKuP,cAAc,EAAAC,MAAM0E,IAAK,CAAC7Q,YAAarD,EAAMqD,aACpD,IAEA/C,KAAKuC,OAAO2D,iBAAiB,SAAS,SAACxG,G,QAC/BmT,EAAOnT,EAAMk7B,YAAY/nB,KACzBC,EAAUpT,EAAMk7B,YAAY9nB,QAC5BG,EAAgBvT,EAAMk7B,YAAYC,MAClCC,GAAc,IAAA3nB,kBAAiBzT,EAAMk7B,aAE3C,EAAK3rB,cAAc,EAAAC,MAAM0D,MAAO,CAC9BC,KAAMA,EACNC,QAASA,EACTC,WAAY+nB,EACZ/3B,YAAa,EAAKA,YAClBkQ,cAAeA,EACfD,KAAM,CACJoiB,iBAAkBtiB,EAClBuiB,oBAAyD,QAApC,EAAuB,QAAvB,EAAA31B,EAAMk7B,YAAYtF,aAAK,eAAEC,MAAM,aAAK,aAAIp1B,EAC7D+S,eAAgB4nB,KAIpB,EAAK/zB,YAAY0M,4BAA4B,CAACZ,KAAMA,EAAMC,QAASA,EAASY,SAAU,YAAahU,EACrG,IAEe,QAAf,EAAAM,KAAKuC,OAAOiW,WAAG,SAAEtS,iBAAiB,gBAAgB,SAACmJ,GACjD,EAAKJ,cAAc,EAAAC,MAAMoD,SAAU,CAACvP,YAAa,EAAKA,aACxD,IACe,QAAf,EAAA/C,KAAKuC,OAAOiW,WAAG,SAAEtS,iBAAiB,cAAc,SAACmJ,GAC/C,EAAKJ,cAAc,EAAAC,MAAMqD,OAAQ,CAACxP,YAAa,EAAKA,aACtD,GACF,EAEQ,YAAAuI,6BAAR,sBAEQoJ,EAAwB,WAC5B,IAAK,EAAKzK,oBAAqB,CAC7B,EAAKA,qBAAsB,EAE3B,IAAMlH,EAAc,EAAK8H,uBACzB,EAAKoE,cAAc,EAAAC,MAAMyF,OAAQ,CAAC5R,YAAW,GAC/C,CACA,EAAK6R,SACP,EAEA5U,KAAKuC,OAAO2D,iBAAiB,UAAWwO,GACxC1U,KAAKwC,mBAAmB0D,iBAAiB,eAAgBwO,GACzD1U,KAAKwC,mBAAmB0D,iBAAiB,SAAUwO,EACrD,EACF,EApaA,CAA+C,EAAAsD,iBAsa/C,SAAgB2hB,EACd7kB,GAEA,IAAI,IAAAtG,WAAUsG,GACZ,MAAO,CAAC,EAGV,IAAIsT,OAAsCjoB,EAQ1C,OAPK,IAAAqO,WAAUsG,EAAOrP,QACpB2iB,GAAa,IAAA4G,2BAA0Bla,EAAOrP,QAE5C,IAAA+I,WAAU4Z,KACZA,GAAa,IAAAK,uBAAsB3T,EAAOma,OAGrC,IAAAvG,mCAAkCN,EAAYtT,EAAOma,IAC9D,CAEA,SAAgB0J,EAAgCj5B,GAC9C,IAAM6c,EAAc7c,EAAM6c,YAE1B,GAAKA,EAAYG,UAIbH,EAAY9W,OAAS,EAAAuX,gBAAgB+d,aAAexe,EAAY9W,OAAS,EAAAuX,gBAAgBge,aAI7F,MAAO,CACL7hB,SAAUoD,EAAYzW,aAAe,IACrC8G,MAAM,IAAA8V,UAASnG,EAAY3P,MAAQ2P,EAAY3P,KAAO,EACtDgQ,iBAAiB,IAAAjX,cAAa4W,EAAYK,iBAAmBL,EAAYK,gBAAkB,IAAO,EAClG/Q,UAAW,IAAI+R,KACfnB,WAAYF,EAAYE,WAE5B,CA1ca,EAAAkb,0BAAAA,C,qJCwHb,wBAqBA,uBApLA,aACA,UAEA,UACA,UACA,UACA,UACA,UAIa,EAAAsD,yBAA2B,KAiBxC,iBAIE,WAAoB14B,GAApB,WAAoB,KAAAA,OAAAA,EAHZ,KAAA2Z,gBAAkB,IAAI,EAAAC,gBACtB,KAAA+e,gBAAkB,IAAI5C,IAwBtB,KAAA6C,UAAY,SAACC,GACnB,IACE,IAAM3f,EAAM2f,EAAQ3f,IAGpB,KAAK,IAAAyd,eAAczd,KAAQ,IAAA8M,SAAQ9M,GACjC,OAGF,IAAM4f,GAAiB,IAAAC,2BACjB7Y,EAAM4Y,QAAAA,EAAkBzd,KAAK6E,MAKnC,EAAK8Y,qBAAqB9Y,GAE1B,IAAM+Y,EAAiC,CACrC/f,IAAKA,EACLggB,UAAWhZ,EACXhd,KAAM21B,EAAQ31B,KACdi2B,QAASN,EAAQM,QACjBC,UAAWP,EAAQO,WAGfC,EAAW,EAAKV,gBAAgBjc,IAAIxD,IACtC,IAAAjN,WAAUotB,GACZ,EAAKV,gBAAgB3G,IAAI9Y,EAAK,CAAC+f,IAE/BI,EAASp8B,KAAKg8B,EAElB,CAAE,MAAOj7B,GACP,EAAAyH,OAAOzH,MAAM,6DAA8DA,EAC7E,CACF,EAEQ,KAAAs7B,WAAa,SAACC,GACpB,IACE,IAAMV,EAAUU,EAASV,QAEzB,IAAI,IAAA5sB,WAAU4sB,GACZ,OAGF,IAAM3f,EAAM2f,EAAQ3f,IAGpB,KAAK,IAAAyd,eAAczd,KAAQ,IAAA8M,SAAQ9M,GACjC,OAGF,IAAMsgB,EAAe,EAAKb,gBAAgBjc,IAAIxD,GAC9C,IAAI,IAAAjN,WAAUutB,IAAyC,IAAxBA,EAAax8B,OAC1C,OAIF,IAAM,EAAUw8B,EAAaC,QAED,IAAxBD,EAAax8B,QACf,EAAK27B,gBAAgBT,OAAOhf,GAG9B,IAAM4f,GAAiB,IAAAC,2BACjBW,EAAUZ,QAAAA,EAAkBzd,KAAK6E,MAGjC3c,EAAeoR,KAAK8M,MAAMiY,EAAU,EAAQR,WAE5C7uB,EAAOsvB,EAAoBJ,GAC3Brf,GAAqB,IAAAiG,UAASoZ,EAAS/O,QAAU+O,EAAS/O,OAAS,EACnErQ,EAAUD,GAAc,KAAOA,EAAa,IAElD,EAAKP,gBAAgB1I,SAAS,CAC5B+I,YAAa,CACXzW,aAAcA,EACd2W,WAAYA,EACZC,QAASA,EACT7Q,UAAW+R,KAAK6E,MAChBhH,IAAKA,EACL7O,KAAMA,EACNgQ,qBAAiBzc,EACjBsF,KAAMoX,EAAmB,EAAQpX,KAAM,EAAQi2B,QAAS,EAAQC,UAAWlgB,KAGjF,CAAE,MAAOlb,GACP,EAAAyH,OAAOzH,MAAM,8DAA+DA,EAC9E,CACF,GA7GM,IAAAiO,WAAUxO,KAAKuC,OAAO45B,SACxB,EAAAn0B,OAAOo0B,KAAK,kEAIdp8B,KAAKuC,OAAO45B,QAAQE,sBAAsBr8B,KAAKm7B,WAC/Cn7B,KAAKuC,OAAO45B,QAAQG,uBAAuBt8B,KAAK67B,YAClD,CAqHF,OAnHE,YAAAxf,UAAA,SAAUlE,GACR,OAAOnY,KAAKkc,gBAAgBG,UAAUlE,EACxC,EAEA,YAAAmE,YAAA,SAAYnE,GACVnY,KAAKkc,gBAAgBI,YAAYnE,EACnC,EAEA,YAAApJ,MAAA,WACE/O,KAAKk7B,gBAAgBhB,OACvB,EA4FQ,YAAAqB,qBAAR,SAA6B9Y,GAA7B,WACEziB,KAAKk7B,gBAAgBnL,SAAQ,SAACgM,EAAgCtgB,GAC5D,IAAM8gB,EAAWR,EAAatY,QAC5B,SAAC+Y,GAA4B,OAAA/Z,EAAM+Z,EAAQf,WAAa,EAAAR,wBAA3B,IAGP,IAApBsB,EAASh9B,OACX,EAAK27B,gBAAgBT,OAAOhf,GACnB8gB,EAASh9B,SAAWw8B,EAAax8B,QAC1C,EAAK27B,gBAAgB3G,IAAI9Y,EAAK8gB,EAElC,GACF,EACF,EAjIA,GAmIA,SAAgBL,EAAoBJ,G,UAC5BW,EAAoD,QAApC,EAAgB,QAAhB,EAAAX,EAASY,eAAO,eAAG,yBAAiB,QAAoB,QAAhB,EAAAZ,EAASY,eAAO,eAAG,kBACjF,IAAI,IAAA/2B,cAAa82B,GAAgB,CAC/B,IAAME,GAAS,IAAAC,qBAAoBH,GACnC,IAAI,IAAA92B,cAAag3B,GACf,OAAOA,CAEX,CAEA,IAAI,IAAAh3B,cAAam2B,EAASe,MAAO,CAC/B,IAAI,IAAA3D,eAAc4C,EAASe,MACzB,OAAOf,EAASe,KAAKt9B,OAEvB,IAAI,IAAAu9B,eAAchB,EAASe,QAAS,IAAAna,UAASoZ,EAASe,KAAKE,YACzD,OAAOjB,EAASe,KAAKE,UAEzB,CAGF,CAEA,SAAgBlgB,EACdoa,EACA+F,EACArB,EACAlgB,GAGA,GAAoB,uBAAhBwb,EACF,OAAQ+F,GACN,IAAK,mBACH,OAAO,EAAAhgB,gBAAgB6Z,qBACzB,IAAK,mBACH,OAAO,EAAA7Z,gBAAgB8Z,qBACzB,IAAK,oBACH,OAAO,EAAA9Z,gBAAgB+Z,sBACzB,IAAK,mBACH,OAAO,EAAA/Z,gBAAgBga,qBACzB,IAAK,aACH,OAAO,EAAAha,gBAAgBigB,YACzB,IAAK,uBACH,OAAO,EAAAjgB,gBAAgBkgB,yBAIzB,QACE,OAAO,EAAAlgB,gBAAgBE,QAK7B,MAAoB,aAAhB+Z,GACE,IAAAkG,UAAS1hB,EAAK,QACT,EAAAuB,gBAAgBogB,eAErB,IAAAD,UAAS1hB,EAAK,SACT,EAAAuB,gBAAgBqgB,oBAElB,EAAArgB,gBAAgBE,QAIP,UAAdye,EACK,EAAA3e,gBAAgB+d,YAEP,UAAdY,EACK,EAAA3e,gBAAgBge,YAEP,SAAdW,EACK,EAAA3e,gBAAgBsgB,iBAIrB,IAAAH,UAAS1hB,EAAK,QACT,EAAAuB,gBAAgBogB,eAErB,IAAAD,UAAS1hB,EAAK,SACT,EAAAuB,gBAAgBqgB,oBAGlB,EAAArgB,gBAAgBE,OACzB,CApNa,EAAAub,6BAAAA,C,8GC5Bb,cAEA,aACE,WAA6BxgB,GAA7B,WAA6B,KAAAA,UAAAA,EAE7B,KAAA/R,iBAAyD,SAACT,EAAMqa,IAC9D,IAAA1H,aAAW,WAAM,SAAKH,UAAU/R,iBAAiBT,EAAMqa,EAAtC,GACnB,CAJ2D,CAqE7D,OA/DE,sBAAI,0BAAW,C,IAAf,sBACE,OAAO,IAAA1H,aAAW,WAAM,SAAKH,UAAUlV,WAAf,GAC1B,E,gCAEA,sBAAI,uBAAQ,C,IAAZ,sBACE,OAAO,IAAAqV,aAAW,WAAM,SAAKH,UAAUkB,QAAf,GAC1B,E,gCAEA,sBAAI,uBAAQ,C,IAAZ,sBACE,OAAO,IAAAf,aAAW,WAAM,SAAKH,UAAU9U,QAAf,GAC1B,E,gCAEA,sBAAI,oBAAK,C,IAAT,sBACE,OAAO,IAAAiV,aAAW,WAAM,SAAKH,UAAUkM,KAAf,GAC1B,E,gCAEA,sBAAI,0BAAW,C,IAAf,sBACE,OAAO,IAAA/L,aAAW,WAAM,SAAKH,UAAUgM,WAAf,GAC1B,E,gCAEA,sBAAI,yBAAU,C,IAAd,sBACE,OAAO,IAAA7L,aAAW,WAAM,SAAKH,UAAU8L,UAAf,GAC1B,E,gCAEA,sBAAI,0BAAW,C,IAAf,sBACE,OAAO,IAAA3L,aAAW,WAAM,SAAKH,UAAU2iB,WAAf,GAC1B,E,gCAEA,sBAAI,sBAAO,C,IAAX,sBACE,OAAO,IAAAxiB,aAAW,WAAM,SAAKH,UAAU4L,OAAf,GAC1B,E,gCAEA,sBAAI,qBAAM,C,IAAV,sBACE,OAAO,IAAAzL,aAAW,WAAM,SAAKH,UAAUnD,MAAf,GAC1B,E,gCAEA,sBAAI,mBAAI,C,IAAR,sBACE,OAAO,IAAAsD,aAAW,WAAM,SAAKH,UAAUyN,IAAf,GAC1B,E,gCAEA,sBAAI,2BAAY,C,IAAhB,sBACE,OAAO,IAAAtN,aAAW,WAAM,SAAKH,UAAU+hB,YAAf,GAC1B,E,gCAEA,sBAAI,0BAAW,C,IAAf,sBACE,OAAO,IAAA5hB,aAAW,WAAM,SAAKH,UAAUmhB,WAAf,GAC1B,E,gCAEA,sBAAI,0BAAW,C,IAAf,sBACE,OAAO,IAAAhhB,aAAW,WAAM,SAAKH,UAAU4T,WAAf,GAC1B,E,gCAEA,sBAAI,yBAAU,C,IAAd,sBACE,OAAO,IAAAzT,aAAW,WAAM,SAAKH,UAAUoY,UAAf,GAC1B,E,gCAEA,sBAAI,kBAAG,C,IAAP,sBACE,OAAO,IAAAjY,aAAW,WAAM,SAAKH,UAAUO,GAAf,GAC1B,E,gCAEA,sBAAI,sBAAO,C,IAAX,sBACE,OAAO,IAAAJ,aAAW,WAAM,SAAKH,UAAUkkB,OAAf,GAC1B,E,gCACF,EAtEA,GAAa,EAAAvE,gBAAAA,C,oFCUb,qBAA0B9zB,GACxB,IAAMmV,EAAuB,WAAZnV,EAAG2B,KAEduT,EAAiB,CACrB7T,GAAIrB,EAAGqB,GACP8T,SAAQ,EACRxU,gBAAiBX,EAAGy5B,aACpBzrB,MAAOhO,EAAGgO,MACVC,OAAQjO,EAAGiO,QAGPmH,EAAWD,EAAYnV,OAAwB3D,GACjD,IAAAwF,cAAauT,KACfF,EAAOM,SAAWJ,EAASI,WAGzB,IAAA3T,cAAa7B,EAAG05B,cAClBxkB,EAAOI,WAA+B,IAAnBtV,EAAG05B,WACtBxkB,EAAOK,eAAiBvV,EAAG05B,aAGzB,IAAA73B,cAAa7B,EAAGqV,YAClBH,EAAOG,SAAWrV,EAAGqV,UAGvB,IACMskB,EADiC,eAAnB35B,EAAG45B,aAAmD,eAAnB55B,EAAG45B,YAC1B55B,OAA2B3D,GACvD,IAAAwF,cAAa83B,KACfzkB,EAAO3H,SAAU,IAAA1L,cAAa83B,EAASpsB,SAAWosB,EAASpsB,QAAU,SAAOlR,EAC5E6Y,EAAOS,SAAWgkB,EAASE,aAG7B3kB,EAAOQ,SAAW,CAChBE,SAAU5V,EAAG4V,SACbO,WAAYnW,EAAGmW,YAGjB,IAAME,EAAgBrW,EAAG85B,gBAAkB95B,EAAG85B,eAAer+B,OAAS,EAAIuE,EAAG85B,eAAe,QAAKz9B,GAC7F,IAAAwF,cAAawU,KACfnB,EAAOQ,SAASU,sBAAwBC,EAAc0jB,aACtD7kB,EAAOQ,SAASa,mBAAqBF,EAAc2jB,YAGjD,IAAAn4B,cAAa83B,KACfzkB,EAAOQ,SAASK,aAAe4jB,EAAS5jB,aACxCb,EAAOQ,SAASe,cAAgBkjB,EAASM,YACzC/kB,EAAOQ,SAASgB,QAAUijB,EAASzoB,MACnCgE,EAAOQ,SAASiB,iBAAkB,IAAA9U,cAAa83B,EAAS/iB,cAAgB+iB,EAAS/iB,aAAanb,YAASY,GAGzG,OAAO6Y,CACT,EAEA,0BAA+B5U,EAAwB+I,GACrD,IAAM6wB,EAAa55B,EAAQ45B,WAC3B,KAAK,IAAAC,gBAAeD,IAAeA,EAAa,EAC9C,MAAO,CAAC5mB,cAAUjX,EAAW+a,kBAAc/a,GAG7C,GAAmB,IAAf69B,EACF,MAAO,CAAC5mB,SAAU,MAAO8D,aAAc,GAKzC,IACMgjB,GAA+B,IAAAv4B,cAAawH,GAAiB+J,KAAKC,IAAI6mB,EAAa7wB,QAAiBhN,EAC1G,IAAI,IAAAwF,cAAau4B,IAAiCA,GAFtB,EAG1B,MAAO,CAAC9mB,SAAU,OAAQ8D,aAAc/N,GAI1C,MAAO,CAACiK,SAAU4K,OAAOgc,GAAa9iB,aAAc8iB,EACtD,EAEA,0BAA+Bt+B,GAC7B,OAAO,IAAAiG,cAAajG,IAAU,cAAeA,CAC/C,EAjFA,cACA,S,iHCXA,cACA,UAEA,UAGA,SAEA,aAUE,WAAY6C,EAAyBC,GAArC,WATA,KAAAC,YAAc,IAAI,EAAAC,YAclB,KAAAC,iBAAmB,W,MACX6V,EAAM,EAAKjW,OAAOiW,IACxB,QAAI,IAAAhK,WAAUgK,KAGI,QAAX,EAAAA,EAAI2lB,eAAO,SACpB,EAEA,KAAAv7B,aAAe,WAA+B,SAAKL,OAAOshB,OAAZ,EAE9C,KAAAhhB,gBAAkB,WAChB,MAAO,CAACxD,KAAM,WAAYyD,aAAS3C,EACrC,EAEA,KAAA4C,YAAc,iBAAc,OAAuB,QAAvB,IAAKR,OAAOQ,mBAAW,QAAI,CAAC,EAExD,KAAAG,YAAc,iBAAe,OAAoB,QAApB,IAAKX,OAAOY,gBAAQ,QAAS,EApBxDnD,KAAKuC,OAASA,EACdvC,KAAKiD,SAAST,EAChB,CA0GF,OAtFU,YAAAS,SAAR,SAAiBT,GAAjB,WACQgW,EAAMxY,KAAKuC,OAAOiW,IACxB,KAAI,IAAAhK,WAAUgK,GAAd,CAIAA,EAAItS,iBAAiB,gBAAgB,SAACxG,GACpC,EAAK+C,YAAYyB,kBAAiB,IAAAk6B,gBAAe1+B,EAAM0E,QAAS,EAAK+I,eACvE,IACAqL,EAAItS,iBAAiB,cAAc,SAACxG,GAClC,EAAK+C,YAAY6B,mBAAkB,IAAA85B,gBAAe1+B,EAAM0E,QAAS,EAAK+I,eACxE,IACAqL,EAAItS,iBAAiB,WAAW,SAACxG,GAC/B,EAAK+C,YAAYmB,aAAY,IAAAy6B,WAAU3+B,EAAMoE,IAC/C,IACA0U,EAAItS,iBAAiB,SAAS,SAACxG,GAC7B,EAAK+C,YAAYuB,cAAa,IAAAq6B,WAAU3+B,EAAMoE,IAChD,IACA0U,EAAItS,iBAAiB,UAAU,SAACxG,GAC9B,EAAK+C,YAAYqC,aAAY,IAAAu5B,WAAU3+B,EAAMoE,IAC/C,IACA0U,EAAItS,iBAAiB,WAAW,SAACxG,GAC/B,IAAM4+B,EAA+B,CAAC,GAElC,IAAAC,gBAAe7+B,KACjB4+B,EAAazrB,KAAOnT,EAAM8+B,UAC1BF,EAAaxrB,QAAUpT,EAAMoT,SAI/B,IAAM8nB,EAAc,EAAKr4B,OAAOq4B,aAC5B,IAAAj1B,cAAai1B,KAAgB,IAAApsB,WAAU8vB,EAAazrB,QACtDyrB,EAAazrB,KAAO+nB,EAAY/nB,KAChCyrB,EAAaxrB,QAAU8nB,EAAY9nB,SAErC,EAAKrQ,YAAYuC,UAAUs5B,EAC7B,IACA9lB,EAAItS,iBAAiB,YAAY,SAACmJ,G,QAC1BqqB,EAAiB,EAAKn3B,OAAO4W,UAC/B,IAAA8kB,gBAAevE,IAAmB,EAAKvsB,gBAAkBusB,IAC3D,EAAKvsB,cAAgBusB,GAGvB,IAAM+E,EAA6C,CACjDl5B,QAAQ,GAGJm5B,EAA8B,QAAlB,IAAKn8B,OAAOuS,cAAM,eAAE0D,KAClC,IAAA7S,cAAa+4B,IAAcA,EAAUn/B,OAAS,IAEhDk/B,EAAkBl5B,OAAoD,SAA1Cm5B,EAAU,GAAuBj5B,MAG/D,IAAMk5B,EAAgC,QAAf,IAAKp8B,OAAOiW,WAAG,eAAEmmB,gBACpC,IAAAh5B,cAAag5B,KACfF,EAAkB/4B,aAAc,IAAA04B,gBAAeO,EAAgBjF,IAGjE,EAAKj3B,YAAYsD,mBAAmB04B,EACtC,IAEAz+B,KAAKuC,OAAO2D,iBAAiB,WAAW,WAClC,EAAKvD,oBACP,EAAKF,YAAYe,QAErB,IACAxD,KAAKuC,OAAO2D,iBAAiB,SAAS,WAChC,EAAKvD,oBACP,EAAKF,YAAYiB,SAErB,IAUA,IAAMsC,EAAkB,WACtB,EAAKvD,YAAYwD,gBACnB,EACAzD,EAAmB0D,iBAAiB,eAAgBF,GACpDxD,EAAmB0D,iBAAiB,SAAUF,EAhF9C,CAiFF,EACF,EAvHA,GAAa,EAAA6yB,mBAAAA,C,qJCRb,cAEa,EAAA+F,oCAAsC,GAEnD,8BACU,KAAAC,aAAqD1+B,CA6B/D,QA1BE,YAAA2+B,SAAA,SAAS3mB,GAAT,YACM,IAAAxS,cAAa3F,KAAK6+B,WAItB7+B,KAAKmY,SAAWA,EAChBnY,KAAK6+B,QAAUrO,YAAW,W,MACX,QAAb,IAAKrY,gBAAQ,iBACb,EAAK9V,QACP,GAAG,EAAAu8B,qCACL,EAEA,YAAAG,YAAA,WACE,OAAO,IAAAp5B,cAAa3F,KAAK6+B,QAC3B,EAEA,YAAAG,QAAA,W,MACe,QAAb,EAAAh/B,KAAKmY,gBAAQ,oBACbnY,KAAKqC,QACP,EAEA,YAAAA,OAAA,WACEusB,aAAa5uB,KAAK6+B,SAClB7+B,KAAK6+B,aAAU1+B,EACfH,KAAKmY,cAAWhY,CAClB,EACF,EA9BA,GAAa,EAAA8+B,kBAAAA,C,qHCJb,aACA,UAEA,UAEA,SAWA,aAiBE,WAAqCC,GAAA,KAAAA,UAAAA,EAhBpB,KAAAC,UAA+B,IAAI,EAAAF,iBAgBc,CAmDpE,OAhES,EAAA5gC,OAAP,WACE,OAAO,IAAI65B,EAAuB,CAEhC,CAACkH,WAAY,EAAAlwB,MAAMiB,MAAOkvB,QAAS,EAAA7e,MAAMS,QAASqe,cAAe,EAAApwB,MAAM0D,OAGvE,CAACwsB,WAAY,EAAAlwB,MAAMiB,MAAOkvB,QAAS,EAAA7e,MAAMtQ,QAASovB,cAAe,EAAApwB,MAAMsB,MAGvE,CAAC4uB,WAAY,EAAAlwB,MAAMqD,OAAQ8sB,QAAS,EAAA7e,MAAM+e,YAAaD,cAAe,EAAApwB,MAAM0E,MAEhF,EAIA,YAAAumB,cAAA,SACEz6B,EACAsR,EACAvS,EACA+U,GAJF,WAUMxT,KAAKm/B,UAAUJ,eAAwC,MAAvB/+B,KAAKw/B,iBACnCx/B,KAAKw/B,eAAeF,gBAAkB5/B,GACxC,EAAAsI,OAAO4X,IACL,4DAAqDoC,OAAOhiB,KAAKw/B,eAAeJ,YAAW,kCAA0Bpd,OAAOtiB,GAAM,MAEpIM,KAAKm/B,UAAU98B,SACfrC,KAAKw/B,oBAAiBr/B,IAEtB,EAAA6H,OAAO4X,IACL,0DAAmDoC,OAAOhiB,KAAKw/B,eAAeJ,YAAW,sCAA8Bpd,OAAOtiB,GAAM,cAEtIM,KAAKm/B,UAAUH,UACfh/B,KAAKw/B,oBAAiBr/B,IAI1B,IAAMs/B,EAAmBz/B,KAAK0/B,qBAAqBhgC,EAAOjB,GAC1D,GAAwB,MAApBghC,EAA0B,CAC5B,IAAM,EAAiB7hB,KAAK6E,MAO5B,OANAziB,KAAKw/B,eAAiBC,EACtB,EAAAz3B,OAAO4X,IAAI,iDAA0CoC,OAAOtiB,GAAM,uBAAejB,EAAK,WACtFuB,KAAKm/B,UAAUL,UAAS,WACtB,EAAKU,oBAAiBr/B,EACtBqT,EAAS9T,EAAOsR,EAAW,EAC7B,GAEF,CAEAwC,EAAS9T,EAAOsR,EAClB,EAEQ,YAAA0uB,qBAAR,SAA6BhgC,EAAuBjB,GAClD,IAAuB,UAAAuB,KAAKk/B,UAAL,eAAgB,CAAlC,IAAMS,EAAQ,KACjB,GAAIA,EAASP,aAAe1/B,GAASigC,EAASN,UAAY5gC,EACxD,OAAOkhC,CAEX,CAEF,EACF,EApEA,GAAa,EAAAzH,uBAAAA,C,6GCfb,cAIA,UACA,UACA,UACA,UAKA,UAGA,UACA,UAEA,aAIE,WAAYzuB,EAAyBlH,EAAa6D,GAChD,IAAI,IAAA2B,+BAA8BxF,GAChC,EAAAyF,OAAOC,mBAAmB,uEAD5B,EAIA,IAAAC,+BAA8B3F,GAE9B,IAAM8F,GAAkB,IAAAC,yBAAwBmB,IAC3C,IAAAlB,+BAA8BF,MAInC,IAAAG,8BAA6BH,GAE7BrI,KAAKyG,gBAAkB,IAAI,EAAAm5B,uBAAuB,IAAI,EAAAC,mBAAmBt9B,GAAS6D,GAClFpG,KAAKkH,UAAY,EAAA2B,UAAUxK,OAAOgK,EAAiBrI,KAAKyG,iBAXxD,CAYF,CAqCF,OAjCE,sBAAI,sBAAO,C,IAAX,WACE,OAAO,EAAAhJ,OACT,E,gCAEA,YAAA2L,uBAAA,WACE,IAAK,IAAA5C,WAAUxG,KAAKkH,WAEpB,OAAOlH,KAAKkH,UAAUkC,wBACxB,EAEA,YAAAC,UAAA,WACE,IAAK,IAAA7C,WAAUxG,KAAKkH,WAEpB,OAAOlH,KAAKkH,UAAUmC,WACxB,EAEA,YAAAC,cAAA,SAAcC,IACP,IAAA/C,WAAUxG,KAAKyG,kBAEpBzG,KAAKyG,gBAAgB6C,cAAcC,EACrC,EAEA,YAAAC,kBAAA,SAAkBD,IACX,IAAA/C,WAAUxG,KAAKkH,YAEpBlH,KAAKkH,UAAUsC,kBAAkBD,EACnC,EAEA,YAAAL,aAAA,SAAaO,IACN,IAAAjD,WAAUxG,KAAKkH,YAEpBlH,KAAKkH,UAAUgC,aAAaO,EAC9B,EAlCgB,EAAA3G,QAAkB,EAAArF,QAmCpC,C,CAzDA,GAAa,EAAAqiC,eAAAA,C,yzBC6Zb,8CAhbA,cAEA,UACA,UACA,UACA,UACA,SACA,UACA,UACA,UACA,UAQA,UAEA,SACA,UACA,UACA,UAmBA,cAWE,WAAYv9B,EAA4B6D,GACtC,QAAK,UAACA,IAAK,KAPL,EAAA25B,cAA8B,CAAChqB,SAAS,GAGxC,EAAA9L,qBAAsB,EACtB,EAAA+1B,aAAe,EAoCvB,EAAA91B,iBAAmB,W,UAGX+1B,EAA+C,QAAvB,EAAmB,QAAnB,OAAK19B,QAAOO,eAAO,8BAAI,eAAG,YACxD,IAAI,IAAAo2B,eAAc+G,MAA2B,IAAA1X,SAAQ0X,GACnD,OAAOA,EAIT,IAAMC,GAAuB,IAAAC,2BAC7B,OAAI,IAAAjH,eAAcgH,MAA0B,IAAA3X,SAAQ2X,GAC3CA,EAGF,SACT,EACA,EAAA/1B,cAAgB,WAAM,SAAAC,OAAOg2B,OAAP,EACtB,EAAA91B,cAAgB,WAAM,eACtB,EAAApH,YAAc,WAAM,OAA2B,IAA3B,EAAKX,OAAOY,UAAZ,EACX,EAAAqH,sBAAwB,WAAsC,SAAKC,kBAAL,EAnDrE,EAAKlI,OAASA,EACd,IAAMoI,EAA0B,IAAI,EAAAC,kBAAiB,WAAM,SAAK7H,WAAL,IACrD+H,EAAe,IAAI,EAAAu1B,6BACvB,EAAKr1B,sBACLL,EACA,EAAKvE,M,OAEPuE,EAAwBM,YAAYH,GACpC,EAAKA,aAAeA,EAEpB,EAAKhB,uBAAyB,IAAI,U,CACpC,CAqWF,OA7X4C,OA0BjC,YAAAyC,wBAAT,W,MACE,YAAMA,wBAAuB,WAE7BvM,KAAK8J,uBAAuBiF,QAC5B/O,KAAK8J,uBAAuB2F,iBAAuC,QAAtB,EAAAzP,KAAKuC,OAAO4W,kBAAU,QAAI,GACvEnZ,KAAKggC,aAAe,CACtB,EAEA,YAAA50B,WAAA,SAAWlE,GAQT,OAPAlH,KAAKiD,WAOE,CANqB,IAAI,EAAAiJ,oBAC9BhF,EAAUiF,oCACV,IAAI,EAAAC,mBAAmBlF,EAAUiF,oCAAoCE,iBACrE,CAACnF,EAAUoF,8BACXnM,GAGJ,EAuBA,YAAAqM,uBAAA,W,UACExM,KAAKsgC,sBAAwBtgC,KAAKugC,8BAA8BvgC,KAAKuC,QACrE,IAAMqnB,EAAY5pB,KAAKwgC,aAAaxgC,KAAKuC,OAAOk+B,KAAK,CAACC,0BAA0B,KAC1EhH,EAAiB15B,KAAKuC,OAAO4W,WAE7BzM,EAAI,SACL1M,KAAK2M,yBACLg0B,EAA0C3gC,KAAKuC,SAAO,CACzD2K,QAAQ,IAAAsB,WAAUkrB,IAAmB7L,MAAM6L,QAAkBv5B,EAAYu5B,IAAmB5L,IAC5FlhB,KAAM5M,KAAKuC,OAAOq+B,eAAiB,EAAA7zB,WAAWD,WAAa,EAAAC,WAAWC,OACtEC,WAAYjN,KAAKsK,gBACjBqD,QAAS3N,KAAKuC,OAAO4hB,QACrBhX,eAAe,IAAAC,wBAAuBssB,GACtCjsB,kBAAmBzN,KAAKuC,OAAOwP,SAC/BxE,iBAAkBvN,KAAKuC,OAAOuP,QAC9BqE,oBAAqBnW,KAAKuC,OAAO0hB,cACjC7N,mBAAoBpW,KAAKuC,OAAOwhB,aAChClW,cAAe7N,KAAKsgC,sBACpBtyB,gBAAiBhO,KAAK+/B,cAAchqB,QACpCC,iBAAkBhW,KAAK+/B,cAAcrZ,SACrCrQ,WAAYuT,aAAS,EAATA,EAAWvT,WACvBI,WAAYmT,aAAS,EAATA,EAAWnT,WACvBxI,cAAe,IAMX0gB,EAAc3uB,KAAK+pB,6BAOzB,OANI4E,IACFjiB,EAAK0J,mBAAsC,QAAjB,EAAAuY,EAAY7c,aAAK,QAAIpF,EAAK0J,mBACpD1J,EAAKyJ,oBAAwC,QAAlB,EAAAwY,EAAY5c,cAAM,QAAIrF,EAAKyJ,oBACtDzJ,EAAK+I,aAAkC,QAAnB,EAAAkZ,EAAYtd,eAAO,QAAI3E,EAAK+I,cAG3C/I,CACT,EAEA,YAAAqd,2BAAA,WACE,OAAO/pB,KAAK6gC,4BACd,EAEA,YAAA59B,SAAA,e,EAAA,OAEQ69B,EAAO9gC,KAMbA,KAAKuC,OAAOa,GAAG,aAAa,WAC1B09B,EAAK7xB,cAAc,EAAAC,MAAMwkB,qBAAsB,CAACjqB,OAAQ,CAAC,GAC3D,IACAzJ,KAAKuC,OAAOa,GAAG,kBAAkB,WAC/B09B,EAAKh3B,uBAAuBiF,QAC5B+xB,EAAKh3B,uBAAuB2F,iBAAiBzP,KAAKmZ,YAClD2nB,EAAKd,aAAe,EACpBc,EAAK7xB,cAAc,EAAAC,MAAMS,cAAe,CAAC,EAC3C,IACA3P,KAAKuC,OAAOw+B,OAAM,WAChBD,EAAKf,cAAgBe,EAAKE,gBAAgBhhC,MAC1C8gC,EAAK7xB,cAAc,EAAAC,MAAM6R,MAAO,CAAC,EACnC,IACA/gB,KAAKuC,OAAOa,GAAG,QAAQ,WACrB09B,EAAK7xB,cAAc,EAAAC,MAAMc,KAAM,CAC7BjN,YAAa/C,KAAK+C,eAEtB,IACA/C,KAAKuC,OAAOa,GAAG,SAAS,WACjBpD,KAAKihC,WACRH,EAAK7xB,cAAc,EAAAC,MAAMiB,MAAO,CAC9BpN,YAAa/C,KAAK+C,eAGxB,IACA/C,KAAKuC,OAAOa,GAAG,SAAS,WACtB,IAAM7C,EAAoBP,KAAKO,QAC/BugC,EAAK7xB,cAAc,EAAAC,MAAM0D,MAAO,CAC9B7P,YAAa/C,KAAK+C,cAClB8P,KAAMtS,EAAMsS,KACZC,QAASvS,EAAMuS,QACfG,cAAe1S,EACfyS,KAAM,CAAC,GAEX,IACAhT,KAAKuC,OAAOa,GAAG,gBAAgB,WAC7B,IAAM+gB,EAAQnkB,KAAKmkB,QACbqL,EAASxvB,KAAKwvB,SACd7hB,GAAU,IAAA8hB,cAAatL,EAAOqL,GAEhCxvB,KAAK2tB,qBAAuBhgB,IAC1BA,EACFmzB,EAAK7xB,cAAc,EAAAC,MAAMuD,KAAM,CAC7B1P,YAAa/C,KAAK+C,gBAGpB+9B,EAAK7xB,cAAc,EAAAC,MAAMyD,QAAS,CAChC5P,YAAa/C,KAAK+C,gBAGtB/C,KAAK2tB,mBAAqBhgB,EAE9B,IACA3N,KAAKuC,OAAOa,GAAG,WAAW,WACxB09B,EAAK7xB,cAAc,EAAAC,MAAMsB,KAAM,CAC7BzN,aAAa,IAAA4C,cAAam7B,EAAKd,cAAgBc,EAAKd,aAAehgC,KAAK+C,eAE5E,IACA/C,KAAKuC,OAAOa,GAAG,UAAU,WACvB09B,EAAK7xB,cAAc,EAAAC,MAAMwB,OAAQ,CAC/B3N,YAAa/C,KAAK+C,eAEtB,IAEA/C,KAAKuC,OAAOa,GAAG,mBAAmB,WAChC,IAAM89B,EAAkBJ,EAAKE,gBAAgBhhC,MACvCmhC,KAAiB,IAAA3yB,WAAUsyB,EAAKf,iBAElC,IAAAqB,yBAAwBN,EAAKf,cAAemB,GAChDJ,EAAKf,cAAgBmB,EAEjBC,GACFL,EAAK7xB,cAAc,EAAAC,MAAMmF,gBAAiB,CACxCtR,YAAa/C,KAAK+C,eAGxB,IAEyB,QAAzB,EAAA/C,KAAKuC,OAAOspB,qBAAa,SAAEzoB,GAAG,UAAU,WACtC,IAAMi+B,EAA2BP,EAAKP,8BAA8BO,EAAKv+B,SACrE,IAAAoD,cAAa07B,IAA6BA,IAA6BP,EAAKR,uBAC9EQ,EAAK7xB,cAAc,EAAAC,MAAMiF,mBAAoB,CAC3CpR,YAAa+9B,EAAKv+B,OAAOQ,eAG/B,IAEA/C,KAAKuC,OAAOa,GAAG,WAAW,WACxB09B,EAAK7xB,cAAc,EAAAC,MAAM0B,gBAAiB,CACxC7N,YAAa/C,KAAK+C,eAEtB,IACA/C,KAAKuC,OAAOa,GAAG,WAAW,WACxB09B,EAAK7xB,cAAc,EAAAC,MAAM0B,gBAAiB,CACxC7N,YAAa/C,KAAK+C,eAEtB,IACA/C,KAAKuC,OAAOa,GAAG,cAAc,WACtBpD,KAAKihC,YACRH,EAAKd,aAAehgC,KAAK+C,eAE3B+9B,EAAK7xB,cAAc,EAAAC,MAAMmB,YAAa,CACpCtN,YAAa/C,KAAK+C,gBAGpB,IAAM4rB,EAAcmS,EAAKD,6BACzB,IAAIlS,aAAW,EAAXA,EAAa5c,UAAU4c,aAAW,EAAXA,EAAa7c,SAAS6c,aAAW,EAAXA,EAAatd,SAAS,CACrE,IAAM0R,EAAkC,CACtCtd,KAAM,QACN4L,QAASsd,EAAYtd,QACrBU,OAAQ4c,EAAY5c,OACpBD,MAAO6c,EAAY7c,MACnB/O,YAAa/C,KAAK+C,eAEhB+9B,EAAKvvB,qBAAqBS,8BAA8B2c,EAAYtd,UACtEyvB,EAAK7xB,cAAc,EAAAC,MAAM+C,aAAc8Q,GAGzC+d,EAAKvvB,qBAAqBW,gBAAgByc,EAAYtd,SACtDyvB,EAAK91B,sBAAsB2G,wBAAwBoR,EACrD,CACF,IAEA,IAAI/c,EAAkB,WACpB,IAAK,EAAKiE,oBAAqB,CAC7B,EAAKA,qBAAsB,EAC3B,IAAIlH,OAAW,GACX,IAAA4C,cAAa,EAAKpD,UACpBQ,EAAc,EAAKR,OAAOQ,eAE5B,EAAKkM,cAAc,EAAAC,MAAMyF,OAAQ,CAC/B5R,YAAW,GAEf,CACA,EAAK6R,SACP,EAEA5O,EAAkBA,EAAgBwe,KAAKxkB,MAEvCA,KAAKuC,OAAOa,GAAG,UAAW4C,GAC1BhG,KAAKwC,mBAAmB0D,iBAAiB,eAAgBF,GACzDhG,KAAKwC,mBAAmB0D,iBAAiB,SAAUF,EACrD,EAEA,sBAAc,0BAAW,C,IAAzB,W,MACE,OAAgC,QAAzB,EAAAhG,KAAKuC,OAAOQ,qBAAa,QAAI,CACtC,E,gCAEQ,YAAAw9B,8BAAR,SAAsCh+B,GACpC,IAAoB,UAAAA,EAAOspB,cAAP,eAAsB,CAArC,IAAMkK,EAAK,KACd,GAAIA,EAAMhgB,QACR,OAAOggB,EAAMrP,QAEjB,CAEF,EAEQ,YAAAsa,gBAAR,SAAwBz+B,GAItB,IAHA,IAEImkB,EADA3Q,GAAU,EAEM,MAHDxT,EAAO8tB,cAAgB,GAGtB,eAAY,CAA3B,IAAM0F,EAAK,KACd,GAAmB,YAAfA,EAAM1d,KAAoB,CAC5BtC,GAAU,EACV2Q,EAAWqP,EAAMrP,SACjB,KACF,CACF,CACA,MAAO,CACL3Q,QAAO,EACP2Q,SAAQ,EAEZ,EAEQ,YAAAma,2BAAR,WAME,IAAMJ,EAAOzgC,KAAKuC,OAAOk+B,KAAK,CAACC,0BAA0B,IAEzD,IAAI,IAAAlyB,WAAUiyB,GACZ,OAAO,KAGT,IAAI,IAAAjyB,WAAUiyB,EAAKa,OAAQ,IAAA9yB,WAAUiyB,EAAKrrB,KACxC,OAAO,KAGT,IAAMmsB,EAAkBvhC,KAAKwhC,mBAAmBf,GAEhD,OAAKc,GAAoBA,EAAgBlwB,QAIlC,CACLA,QAASkwB,EAAgBlwB,QACzBS,MAAOyvB,EAAgBzvB,MACvBC,OAAQwvB,EAAgBxvB,QANjB,IAQX,EAKQ,YAAAyvB,mBAAR,SAA2Bv0B,GAMzB,IAAIw0B,EALJ,GAAKx0B,IAMDA,EAAWq0B,IACbG,EAAgBx0B,EAAWq0B,IAClBr0B,EAAWmI,MAEpBqsB,EAAgBx0B,EAAWmI,KAKxBqsB,GAAkBA,EAAcC,YAAc,IAAAtf,YAAWqf,EAAcC,UAAUzW,QAAtF,CAKA,IAAM0W,EAAmBF,EAAcC,UAAUzW,QAEjD,GAAK0W,EAAL,CAIO,IAAAC,EAAcD,EAAgB,WAErC,GAAKC,GAAiD,IAAnCjhC,OAAOC,KAAKghC,GAAYriC,OAI3C,MAAO,CACL8R,QAASuwB,EAAWC,UACpB/vB,OAAQ8vB,EAAWE,YAAc,CAAC,GAAGhwB,MACrCC,QAAS6vB,EAAWE,YAAc,CAAC,GAAG/vB,OACtC+nB,OAAQ8H,EAAWG,OAZrB,CAPA,CAqBF,EAEQ,YAAAvB,aAAR,SAAqBvzB,GACnB,IAAMs0B,EAAkBvhC,KAAKwhC,mBAAmBv0B,GAEhD,GAAKs0B,GAAoBA,EAAgBzH,OAAzC,CAIA,IAAMA,EAASyH,EAAgBzH,OAAOvE,MAAM,KAE5C,GAAKuE,EAIL,MAAO,CACLzjB,WAAYyjB,EAAOjkB,MAAK,SAACvE,GAAkB,OAAA0wB,EAAYC,aAAa3wB,EAAzB,IAC3CmF,WAAYqjB,EAAOjkB,MAAK,SAACvE,GAAkB,OAAA0wB,EAAYE,aAAa5wB,EAAzB,IAV7C,CAYF,EACF,EA7XA,CAlBA,QAkB4C0G,iBAsY5C,SAAgB2oB,EACdwB,G,MAEM1mB,EAAM0mB,EAAcrQ,aAEtB1J,GAAa,IAAAK,uBAAsBhN,GACvC,IAAI,IAAAjN,WAAU4Z,GAAa,CAEzB,IAAMga,EAA0C,QAAzB,EAAAD,EAAcE,mBAAW,uBAC5CD,IACFha,GAAa,IAAA4G,2BAA0BoT,GAE3C,CAEA,OAAO,IAAA1Z,mCAAkCN,EAAY3M,EACvD,CArZa,EAAAmkB,uBAAAA,C,iHCxCb,cAEA,EACE,SAA6B3nB,GAA7B,WAA6B,KAAAA,UAAAA,EAE7B,KAAA7U,GAAK,W,IAAC,uDACJ,IAAAgV,aAAW,W,MAAM,WAAKH,WAAU7U,GAAE,QAAI5C,EAArB,GACnB,EAEA,KAAAugC,MAAQ,W,IAAC,sDAAgD,WAAA3oB,aAAW,W,MAAM,WAAKH,WAAU8oB,MAAK,QAAIvgC,EAAxB,GAAjB,EAEzD,KAAA2Y,SAAW,WAAM,WAAAf,aAAW,WAAM,SAAKH,UAAUkB,UAAf,GAAjB,EAEjB,KAAApW,YAAc,WAAM,WAAAqV,aAAW,WAAM,SAAKH,UAAUlV,aAAf,GAAjB,EAEpB,KAAA+uB,WAAa,WAAM,WAAA1Z,aAAW,WAAM,SAAKH,UAAU6Z,YAAf,GAAjB,EAEnB,KAAAuQ,YAAc,WAAM,WAAAjqB,aAAW,WAAM,SAAKH,UAAUoqB,aAAf,GAAjB,EAEpB,KAAAl/B,SAAW,WAAM,WAAAiV,aAAW,WAAM,SAAKH,UAAU9U,UAAf,GAAjB,EAEjB,KAAAghB,MAAQ,WAAM,WAAA/L,aAAW,WAAM,SAAKH,UAAUkM,OAAf,GAAjB,EAEd,KAAApS,OAAS,WAAM,WAAAqG,aAAW,WAAM,SAAKH,UAAUlG,QAAf,GAAjB,EAEf,KAAAD,MAAQ,WAAM,WAAAsG,aAAW,WAAM,SAAKH,UAAUnG,OAAf,GAAjB,EAEd,KAAAmS,YAAc,WAAM,WAAA7L,aAAW,WAAM,SAAKH,UAAUgM,aAAf,GAAjB,EAEpB,KAAAF,WAAa,WAAM,WAAA3L,aAAW,WAAM,SAAKH,UAAU8L,YAAf,GAAjB,EAEnB,KAAA6c,aAAe,WAAM,WAAAxoB,aAAW,WAAM,SAAKH,UAAU2oB,cAAf,GAAjB,EAErB,KAAA/U,YAAc,WAAM,WAAAzT,aAAW,WAAM,SAAKH,UAAU4T,aAAf,GAAjB,EAEpB,KAAA4U,KAAO,SAAC6B,GAAsB,WAAAlqB,aAAW,WAAM,SAAKH,UAAUwoB,KAAK6B,EAApB,GAAjB,EAE9B,KAAAx/B,QAAU,WAAM,WAAAsV,aAAW,mBAAM,OAAsB,QAAtB,OAAKH,WAAUnV,eAAO,sBAAI,GAA3C,CAlCwC,EAD7C,EAAA+8B,mBAAAA,C,6VCFb,cACA,UACA,UAKA,UACA,UACA,UACA,UAEM0C,EAAgC,CAAC,IAAM,IAAM,IAAO,IAAO,OAEjE,aAaE,WACYv3B,EACVL,EACAvE,GAFU,KAAA4E,sBAAAA,EAZF,KAAA0W,sBAAwB,EAEf,KAAA8gB,sBAAgCC,EAASC,6BACzC,KAAAC,gBAA0BF,EAASG,yBAI9C,KAAAC,8BAAgC,EAStC7iC,KAAK8K,aAAe9K,KAAK2gB,mBAAmBva,GAC5CpG,KAAK2K,wBAA0BA,CACjC,CA6NF,OAzNE,YAAA8nB,UAAA,SACE/yB,EACAsR,EACAsQ,GAEA,IAAMwhB,EAA0B9iC,KAAK8K,aAAapL,GAElD,GAA+B,MAA3BojC,EAQJ,IASEA,EAAwB3gC,KAAKnC,KAAK8K,aAAcwW,EAAgBtQ,EAClE,CAAE,MAAO/R,GACP,EAAA+I,OAAOzH,MACL,sCAA+Bb,EAAK,yEAAiEM,KAAKszB,aAAY,KACtHtiB,EACAsQ,EACAriB,EAEJ,MArBE,EAAA+I,OAAOo0B,KAAK,sCAA+B18B,EAAK,sCAAsCsR,EAAWsQ,EAsBrG,EAEA,sBAAI,2BAAY,C,IAAhB,WACE,OAAOthB,KAAK8K,aAAajL,OAC3B,E,gCAEA,YAAA2yB,eAAA,WACExyB,KAAKkiB,yBACLliB,KAAK+iC,6BAA4B,GACjC/iC,KAAKgjC,+BACP,EAIU,YAAAC,gCAAV,SAA0Cl0B,GAA1C,gBAA0C,IAAAA,IAAAA,GAAA,GACxC/O,KAAKkjC,sBAAsBn0B,GAE3B/O,KAAKmjC,8BAELnjC,KAAKojC,iCAAmCC,aAAY,WAClD,IAAM5kC,EAAQ,EAAKqM,aAAajL,QAAQiiB,cACxC,GAAc,cAAVrjB,EAAJ,CAIA,IAAMoN,GAAY,IAAI+R,MAAO+c,UACvBlZ,EAAgB5V,EAAY,EAAK6V,sBACvC,EAAK1W,sBAAsBs4B,UAAU7hB,EAAehjB,EAAO,CAAC8kC,SAAU9hB,IACtE,EAAKC,sBAAwB7V,EAC7B,EAAKg3B,8BAAgC3rB,KAAKssB,IACxC,EAAKX,8BAAgC,EACrCN,EAA8BhjC,OAAS,GAEzC,EAAK0jC,iCAAgC,EATrC,MAFE,EAAKC,uBAYT,GAAGX,EAA8BviC,KAAK6iC,+BACxC,EAEU,YAAAK,sBAAV,SAAgCn0B,QAAA,IAAAA,IAAAA,GAAA,GAC1BA,IACF/O,KAAK6iC,8BAAgC,GAEvC7iC,KAAKgjC,gCACLhjC,KAAK+iC,4BAA4Bh0B,EACnC,EAEU,YAAAi0B,8BAAV,YACM,IAAAr9B,cAAa3F,KAAKojC,oCACpBK,cAAczjC,KAAKojC,kCACnBpjC,KAAKojC,sCAAmCjjC,EAE5C,EAEQ,YAAAgjC,4BAAR,sBACMnjC,KAAK6iC,8BAAgC,IAGzC7iC,KAAK0jC,uBAAyBlT,YAAW,WACvC,EAAKiC,UACH,EAAAvjB,MAAM0D,MAAK,OAEN,EAAAQ,UAAUuwB,2BAAyB,CACtC3wB,KAAM,CACJE,eAAgB,uCAAgC,EAAKyvB,gBAAe,oCAGxEplB,EAAMZ,uBAER,EAAK3R,sBAAsB4J,SAC7B,GAAG5U,KAAK2iC,iBACV,EAEU,YAAAI,4BAAV,SAAsCh0B,GAChCA,IAAS,IAAApJ,cAAa3F,KAAK0jC,0BAC7B9U,aAAa5uB,KAAK0jC,wBAClB1jC,KAAK0jC,4BAAyBvjC,EAElC,EAIU,YAAAgjB,qBAAV,uBACM,IAAAxd,cAAa3F,KAAK4jC,oBACpB5jC,KAAKkiB,yBAEPliB,KAAK4jC,kBAAoBpT,YAAW,WAClC,EAAKiC,UAAU,EAAAvjB,MAAM20B,mBAAoB,CAAC,EAAGjmB,KAAK6E,OAClD,EAAKzX,sBAAsB4J,SAC7B,GAAG5U,KAAKwiC,sBACV,EAEU,YAAAtgB,uBAAV,WACE0M,aAAa5uB,KAAK4jC,mBAClB5jC,KAAK4jC,uBAAoBzjC,CAC3B,EAGA,YAAA2jC,YAAA,SAAYh4B,GACV9L,KAAK+L,kBAAkB6R,KAAK6E,MAAO3W,EACrC,EAmBA,YAAAC,kBAAA,SACEF,EACAC,EACAi4B,EACAC,QADA,IAAAD,IAAAA,GAAA,QACA,IAAAC,IAAAA,GAAA,GAEA,IAAMvlC,EAAQuB,KAAK8K,aAAajL,QAAQiiB,cAGxC,GAAc,YAAVrjB,EAAJ,CAQAuB,KAAKgL,sBAAsBi5B,yBAAyB,CAAClhC,YAAa+I,IAElE,IAAM2V,EAAgB5V,EAAY7L,KAAK0hB,sBACjCwiB,EAA4B,CAChCC,OAAQ1iB,EACR2iB,kBAAiBJ,QAAkC7jC,GAGjD4jC,IACFG,EAAQ,EAAAG,6BAA8B,GAGxCrkC,KAAKgL,sBAAsBs4B,UAAU7hB,EAAehjB,EAAOylC,GAE3DlkC,KAAKskC,uBAAuBz4B,EAAWC,EAhBvC,MAFE,EAAA9D,OAAOo0B,KAAK,gFAAyE39B,EAAK,WAmB9F,EAEQ,YAAA6lC,uBAAR,SAA+BC,EAA6Bz4B,GAC1D9L,KAAK0hB,sBAAwB6iB,EAC7BvkC,KAAKgL,sBAAsBw5B,2BAA2B,CAACzhC,YAAa+I,GACtE,EAEA,YAAA6nB,cAAA,SAAc7nB,EAA2B8nB,EAAuBxC,GAI9D,GACgC,UAA9BpxB,KAAK8K,aAAajL,SACY,UAA9BG,KAAK8K,aAAajL,SACY,YAA9BG,KAAK8K,aAAajL,SACY,qBAA9BG,KAAK8K,aAAajL,QAJpB,CAUA,IAAM4kC,EAAyB7mB,KAAK6E,MAIF,YAA9BziB,KAAK8K,aAAajL,QACpBG,KAAK+L,kBAAkB04B,EAAwB34B,EAAmB8nB,GAAc,GAIhF5zB,KAAKskC,uBAAuBG,EAAwB34B,GAGtD9L,KAAKgL,sBAAsB2oB,cAAcvC,EAdzC,MAFEpxB,KAAKgL,sBAAsB05B,qBAAqBtT,EAiBpD,EACF,EAjPA,GAAsB,EAAAhO,sBAAAA,C,4zBChBtB,IAmBY5C,EAnBZ,UAEA,UACA,UAGA,UACA,UACA,UAEA,UACA,WAQA,SAAYA,GAKV,wBAWA,sCACA,gBACA,gBACA,oBACA,gBAKA,oBAgBA,sCACA,gBACA,oCACA,oBAIA,sBACA,uCACD,CAlDD,CAAYA,IAAK,QAALA,EAAK,KAoDjB,+B,8CA+PA,QA/PgD,OACrC,YAAAG,mBAAT,SAA4Bva,G,MAA5B,OACE,OAAO,IAAA/H,QAAO,CAGZG,QAAS,CAACC,MAAO+hB,EAAMI,MAAOlhB,MAAO,EAAAmhB,mBACrCtgB,MAAO,EAAAugB,gCACPliB,OAAQ,EAAF,8BACD,IAAA+lC,SAAQnkB,EAAMI,OAAOgkB,SAEtB,EAAA11B,MAAM0B,kBACP,IAED,CAACvR,KAAM,EAAA6P,MAAMS,cAAezQ,KAAMshB,EAAMI,MAAOnhB,GAAI+gB,EAAMO,OACzD,CAAC1hB,KAAM,EAAA6P,MAAM6R,MAAO7hB,KAAMshB,EAAMI,MAAOnhB,GAAI+gB,EAAMO,S,IAE9C,IAAA4jB,SAAQnkB,EAAMO,OAAO6jB,SACtB,EAAA11B,MAAM6R,MAEN,EAAA7R,MAAM0B,gBACN,EAAA1B,MAAM4B,cAEN,EAAA5B,MAAMmB,YACN,EAAAnB,MAAMsB,KACN,EAAAtB,MAAMwB,SACP,IAED,CAACrR,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAMO,MAAOthB,GAAI+gB,EAAMS,SAEhD,CAAC5hB,KAAM,EAAA6P,MAAM0D,MAAO1T,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMU,mBACnD,CAAC7hB,KAAM,EAAA6P,MAAMyF,OAAQzV,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMU,mBACpD,CAAC7hB,KAAM,EAAA6P,MAAM20B,mBAAoB3kC,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMU,mBAEhE,CAAC7hB,KAAM,EAAA6P,MAAM0D,MAAO1T,MAAM,IAAAiiB,iBAAgB,CAACX,EAAMS,SAAUT,GAAQ/gB,GAAI+gB,EAAM5N,OAC7E,CAACvT,KAAM,EAAA6P,MAAMyF,OAAQzV,MAAM,IAAAiiB,iBAAgB,CAACX,EAAMS,SAAUT,GAAQ/gB,GAAI+gB,EAAMqkB,UAM9E,CAACxlC,KAAM,EAAA6P,MAAMmB,YAAanR,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMtQ,W,IACtD,IAAAy0B,SAAQnkB,EAAMtQ,SAAS00B,SAAS,EAAA11B,MAAMmB,cAAY,IAErD,CAAChR,KAAM,EAAA6P,MAAM0B,gBAAiB1R,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMwH,WAU7D,CAAC3oB,KAAM,EAAA6P,MAAMmB,YAAanR,KAAMshB,EAAMwH,UAAWvoB,GAAI+gB,EAAMtQ,SAE3D,CAAC7Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMrQ,OACnD,CAAC9Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMwH,UAAWvoB,GAAI+gB,EAAMrQ,OAGrD,CAAC9Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMuH,QAAStoB,GAAI+gB,EAAMrQ,S,IAChD,IAAAw0B,SAAQnkB,EAAMrQ,OAAOy0B,SAEtB,EAAA11B,MAAM0B,gBACN,EAAA1B,MAAM4B,gBACP,IAQD,CAACzR,KAAM,EAAA6P,MAAMgB,QAAShR,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMtQ,SAEnD,CAAC7Q,KAAM,EAAA6P,MAAMsB,KAAMtR,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMskB,oB,IAC7C,IAAAH,SAAQnkB,EAAMskB,kBAAkBF,SACjC,EAAA11B,MAAMsB,KAEN,EAAAtB,MAAM0B,gBACN,EAAA1B,MAAM4B,cAEN,EAAA5B,MAAMmB,cACP,IACD,CAAChR,KAAM,EAAA6P,MAAMwB,OAAQxR,KAAMshB,EAAMskB,iBAAkBrlC,GAAI+gB,EAAMrQ,OAE7D,CAAC9Q,KAAM,EAAA6P,MAAMsB,KAAMtR,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMuH,W,IAC/C,IAAA4c,SAAQnkB,EAAMuH,SAAS6c,SACxB,EAAA11B,MAAMsB,KAEN,EAAAtB,MAAM0B,gBACN,EAAA1B,MAAM4B,cAEN,EAAA5B,MAAMmB,cACP,IACD,CAAChR,KAAM,EAAA6P,MAAMwB,OAAQxR,KAAMshB,EAAMuH,QAAStoB,GAAI+gB,EAAMtQ,SAEpD,CACE7Q,KAAM,EAAA6P,MAAMwkB,qBAEZx0B,MAAM,IAAAiiB,iBAAgB,CAACX,EAAMI,OAAQJ,GACrC/gB,GAAI+gB,EAAMukB,mB,IAET,IAAAJ,SAAQnkB,EAAMukB,iBAAiBH,SAAS,EAAA11B,MAAM0B,gBAAiB,EAAA1B,MAAMmB,cAAY,IAEpF,CAAChR,KAAM,EAAA6P,MAAMS,cAAezQ,KAAMshB,EAAMukB,gBAAiBtlC,GAAI+gB,EAAMO,OAMnE,CAAC1hB,KAAM,EAAA6P,MAAMukB,mBAAoBv0B,KAAM,CAACshB,EAAMtQ,QAASsQ,EAAMrQ,OAAQ1Q,GAAI+gB,EAAMwkB,kBAC/E,CAAC3lC,KAAM,EAAA6P,MAAMgB,QAAShR,KAAMshB,EAAMwkB,iBAAkBvlC,GAAI+gB,EAAMtQ,SAC9D,CAAC7Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMwkB,iBAAkBvlC,GAAI+gB,EAAMrQ,S,GAG9DtR,WAAS,KACP,EAAC,iBAAU2hB,EAAMtQ,UAAY,WAC3B,EAAKvF,wBAAwByW,eAC/B,EAEA,EAAC,iBAAUZ,EAAMS,UAAY,WAC3B,EAAKiB,wBACP,EAEA,EAAAb,aAAc,SAAC3hB,EAAOR,EAAMO,EAAI6hB,EAAwBtQ,GAMtD,IALA,IAAAuQ,2BAA0B,QAAS7hB,EAAOR,EAAMO,GAK5CC,IAAU,EAAAmhB,oBAIV3hB,IAASshB,EAAMwH,WACjB,EAAKkb,wBAOF5hB,GAMDpiB,IAASshB,EAAM5N,SAOhB1T,IAASshB,EAAMrQ,OAAS1Q,IAAO+gB,EAAMskB,kBACrC5lC,IAASshB,EAAMskB,kBAAoBrlC,IAAO+gB,EAAMrQ,QAFnD,CAQIa,GACF,EAAKhG,sBAAsBi5B,yBAAyBjzB,GAGtD,IAAMyQ,EAAgBH,EAAiB,EAAKI,sBACtCK,EAAgBC,OAAO9iB,GAAM4iB,cAGnC,GAAI5iB,IAASshB,EAAMS,SAAWxhB,IAAO+gB,EAAMU,kBAM3C,GAAIhiB,IAASshB,EAAMuH,QAMnB,GAAIroB,IAAU,EAAAwP,MAAMyF,OAApB,CASA,IAAMwN,EAAgC,EAAKnX,sBAAsB+W,GACjE,IAAI,IAAAK,YAAWD,GAEb,IACEA,EAA8BV,EAAeM,EAAe/Q,EAC9D,CAAE,MAAO/R,GACP,EAAA+I,OAAOzH,MAAM,gDAAkDwhB,EAAe/Q,EAAW/R,EAC3F,MAOA,IAAAojB,2BAA0BnjB,EAAM,CAACshB,EAAMO,MAAOP,EAAMukB,iBApBtD,MAFE,EAAK/5B,sBAAsBiX,OAAOR,EAAeM,QANjD,EAAK/W,sBAAsBi2B,QAAQxf,QANnC,EAAKzW,sBAAsBi6B,iBAAiBxjB,GAAe,IAAAyjB,8BAA6BxlC,GAZ1F,CAgDF,EAEA,EAAC,iBAAU8gB,EAAMtQ,UAAY,WAC3B,EAAKvF,wBAAwB2X,gBAC/B,EAEA,EAAC,iBAAU9B,EAAMukB,kBAAoB,SAAC11B,EAAQuT,EAAOC,EAAKC,EAAiB9R,GACzE,EAAKhG,sBAAsBm6B,mBAAmBn0B,EAChD,EAEA,EAAC,iBAAUwP,EAAMS,UAAY,WAC3B,EAAKkC,sBACP,EAEA,EAAAZ,aAAc,SAAC7iB,EAAOR,EAAMO,EAAI6hB,EAAwBtQ,IACtD,IAAAuQ,2BAA0B,QAAS7hB,EAAOR,EAAMO,GAK7CP,IAASshB,EAAMrQ,OAAS1Q,IAAO+gB,EAAMskB,kBACrC5lC,IAASshB,EAAMskB,kBAAoBrlC,IAAO+gB,EAAMrQ,QAKnD,EAAKuR,sBAAwBJ,QAAAA,EAAkB1D,KAAK6E,OAGhD,IAAAC,UAAStc,EAAKuc,YAAcjjB,IAAU,EAAAmhB,oBACxC,EAAKa,sBAAwBtb,EAAKuc,WAGhC3R,GACF,EAAKhG,sBAAsBw5B,2BAA2BxzB,GAGpDvR,IAAO+gB,EAAMwH,WACf,EAAKib,kCAET,EAEA,EAAC,iBAAU,EAAA/zB,MAAM0D,QAAU,SAACvD,EAAQuT,EAAOC,EAAKC,EAAiB9R,GAC/D,EAAKhG,sBAAsBzK,MAAMyQ,EACnC,E,IAGN,EACF,EA/PA,CAAgD,EAAAoS,uBAAnC,EAAA8C,2BAAAA,C,ozBCvEb,IAoBK1F,EApBL,UAGA,UACA,UAGA,UACA,UACA,UAEA,UACA,WAQA,SAAKA,GACH,UACA,4CACA,wBACA,oBAWA,sCACA,YACA,gBACA,8BACA,4BACA,8BACA,gBACA,kCACA,oBACA,kCACA,gBACA,gBACA,4CACA,oCACA,oBACA,wCACA,uCACD,CAhCD,CAAKA,IAAAA,EAAK,KAkCV,kBACE,WACExV,EACAL,EACAvE,GAEA,QAAK,UAAC4E,EAAuBL,EAAyBvE,IAAK,K,OAE3D,EAAKua,mBAAmBva,G,CAC1B,CA6TF,OAtUgD,OAW9C,YAAAg/B,aAAA,WACE,OAAO,EAAP,GAAWzkC,OAAOC,KAAK4f,GAAO1hB,KAAI,SAAC4J,GAAQ,OAAA8X,EAAM9X,EAAN,KAAW,EACxD,EAEA,YAAAyY,gBAAA,SAAgBzgB,GACd,OAAOV,KAAKolC,eAAe3hB,QAAO,SAAC4hB,GAAM,OAAA3kC,EAAOX,QAAQslC,GAAK,CAApB,GAC3C,EAES,YAAA1kB,mBAAT,SAA4Bva,G,MAA5B,OACE,OAAO5I,EAAaa,OAAO,CAGzBG,QAAS,CAACC,MAAO+hB,EAAMI,MAAOlhB,MAAO,EAAAmhB,mBACrCtgB,MAAO,EAAAugB,gCACPliB,OAAQ,EAAF,yBACJ,CACES,KAAM,EAAA6P,MAAMS,cACZzQ,KAAM,CAACshB,EAAMI,MAAOJ,EAAM8kB,oBAAqB9kB,EAAMukB,iBACrDtlC,GAAI+gB,EAAMO,SAIT,IAAA4jB,SAAQnkB,EAAMO,OAAO6jB,SAAS,EAAA11B,MAAMsB,KAAM,EAAAtB,MAAMwB,SAAO,KAE1D,IAAAtN,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMI,QACnC,IAAAxd,IAAG,EAAA8L,MAAMS,eAAeqR,OAAOR,EAAMO,OAErC,CAAC1hB,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAMO,MAAOthB,GAAI+gB,EAAMS,SAEhD,CAAC5hB,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAMukB,gBAAiBtlC,GAAI+gB,EAAMS,SAE1D,CAAC5hB,KAAM,EAAA6P,MAAM0D,MAAO1T,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMU,mBACnD,CAAC7hB,KAAM,EAAA6P,MAAMyF,OAAQzV,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMU,mBACpD,CAAC7hB,KAAM,EAAA6P,MAAM20B,mBAAoB3kC,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMU,qB,IAE7D,IAAAyjB,SAAQnkB,EAAMS,SAAS2jB,SACxB,EAAA11B,MAAMS,cACN,EAAAT,MAAM0B,gBACN,EAAA1B,MAAM4B,cACN,EAAA5B,MAAM+C,aACN,EAAA/C,MAAMuC,aACN,EAAAvC,MAAMsB,KACN,EAAAtB,MAAMwB,SACP,IAED,CAACrR,KAAM,EAAA6P,MAAMmB,YAAanR,KAAMshB,EAAMO,MAAOthB,GAAI+gB,EAAMS,SACvD,CAAC5hB,KAAM,EAAA6P,MAAMmB,YAAanR,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMtQ,W,IACtD,IAAAy0B,SAAQnkB,EAAMtQ,SAAS00B,SAAS,EAAA11B,MAAMmB,cAAY,KAErD,IAAAjN,IAAG,EAAA8L,MAAMwB,QAAQsQ,OAAOR,EAAMrQ,QAE9B,IAAA/M,IAAG,EAAA8L,MAAM4B,eAAekQ,OAAOR,EAAMtQ,SACrC,CAAC7Q,KAAM,EAAA6P,MAAM0B,gBAAiB1R,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMwH,YAC7D,IAAA5kB,IAAG,EAAA8L,MAAM0B,iBAAiBoQ,OAAOR,EAAMwH,WAEvC,CAAC3oB,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAMwH,UAAWvoB,GAAI+gB,EAAMtQ,SACpD,CAAC7Q,KAAM,EAAA6P,MAAMmB,YAAanR,KAAMshB,EAAMwH,UAAWvoB,GAAI+gB,EAAMtQ,SAE3D,CAAC7Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMrQ,OACnD,CAAC9Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMwH,UAAWvoB,GAAI+gB,EAAMrQ,OAErD,CAAC9Q,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMtQ,SAChD,CAAC7Q,KAAM,EAAA6P,MAAMmB,YAAanR,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMtQ,SAEvD,CAAC7Q,KAAM,EAAA6P,MAAM+C,aAAc/S,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAM+kB,gBAC1D,CAAClmC,KAAM,EAAA6P,MAAMuC,aAAcvS,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAM+kB,gBAC1D,CAAClmC,KAAM,EAAA6P,MAAMs2B,sBAAuBtmC,KAAMshB,EAAM+kB,eAAgB9lC,GAAI+gB,EAAMtQ,SAE1E,CAAC7Q,KAAM,EAAA6P,MAAMsB,KAAMtR,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMilB,kB,IAC7C,IAAAd,SAAQnkB,EAAMilB,gBAAgBb,SAAS,EAAA11B,MAAMc,KAAM,EAAAd,MAAMsB,KAAM,EAAAtB,MAAM0B,gBAAiB,EAAA1B,MAAM4B,gBAAc,IAE7G,CAACzR,KAAM,EAAA6P,MAAMwB,OAAQxR,KAAMshB,EAAMilB,eAAgBhmC,GAAI+gB,EAAMrQ,OAC3D,CAAC9Q,KAAM,EAAA6P,MAAMmB,YAAanR,KAAMshB,EAAMilB,eAAgBhmC,GAAI+gB,EAAMtQ,SAChE,CAAC7Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMilB,eAAgBhmC,GAAI+gB,EAAMrQ,OAE1D,CAAC9Q,KAAM,EAAA6P,MAAM0E,IAAK1U,KAAMshB,EAAMilB,eAAgBhmC,GAAI+gB,EAAM5M,KACxD,CAACvU,KAAM,EAAA6P,MAAM0E,IAAK1U,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAM5M,KACjD,CAACvU,KAAM,EAAA6P,MAAM0E,IAAK1U,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAM5M,O,IAC5C,IAAA+wB,SAAQnkB,EAAM5M,KAAKgxB,SACpB,EAAA11B,MAAMiB,MACN,EAAAjB,MAAMsB,KACN,EAAAtB,MAAMwB,OACN,EAAAxB,MAAMmB,YACN,EAAAnB,MAAM4B,cACN,EAAA5B,MAAM0B,gBACN,EAAA1B,MAAM0E,MACP,IAGE,IAAA+wB,SAAQnkB,EAAMtQ,SAAS00B,SAAS,EAAA11B,MAAMsB,KAAM,EAAAtB,MAAMwB,SAAO,IAE5D,CAACrR,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAM5M,IAAKnU,GAAI+gB,EAAMtQ,SAE9C,CAAC7Q,KAAM,EAAA6P,MAAM0D,MAAO1T,KAAMc,KAAKmhB,gBAAgB,CAACX,EAAMS,UAAWxhB,GAAI+gB,EAAM5N,OAC3E,CAACvT,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAM5N,MAAOnT,GAAI+gB,EAAM5N,OAEjD,CAACvT,KAAM,EAAA6P,MAAMyF,OAAQzV,KAAMc,KAAKmhB,gBAAgB,CAACX,EAAMS,UAAWxhB,GAAI+gB,EAAM5M,KAE5E,CAACvU,KAAM,EAAA6P,MAAMmF,gBAAiBnV,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMklB,oBAE7D,IAAAtiC,IAAG,EAAA8L,MAAMmF,iBAAiB2M,OAAOR,EAAMrQ,QACvC,IAAA/M,IAAG,EAAA8L,MAAMmF,iBAAiB2M,OAAOR,EAAMO,QACvC,IAAA3d,IAAG,EAAA8L,MAAMmF,iBAAiB2M,OAAOR,EAAMS,UACvC,IAAA7d,IAAG,EAAA8L,MAAMmF,iBAAiB2M,OAAOR,EAAMwH,YACvC,IAAA5kB,IAAG,EAAA8L,MAAMmF,iBAAiB2M,OAAOR,EAAMklB,mBAEvC,CAACrmC,KAAM,EAAA6P,MAAMmB,YAAanR,KAAMshB,EAAMklB,kBAAmBjmC,GAAI+gB,EAAMtQ,SAEnE,CAAC7Q,KAAM,EAAA6P,MAAMiF,mBAAoBjV,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMmlB,sBAEhE,IAAAviC,IAAG,EAAA8L,MAAMiF,oBAAoB6M,OAAOR,EAAMrQ,QAC1C,IAAA/M,IAAG,EAAA8L,MAAMiF,oBAAoB6M,OAAOR,EAAMO,QAC1C,IAAA3d,IAAG,EAAA8L,MAAMiF,oBAAoB6M,OAAOR,EAAMS,UAC1C,IAAA7d,IAAG,EAAA8L,MAAMiF,oBAAoB6M,OAAOR,EAAMwH,YAC1C,IAAA5kB,IAAG,EAAA8L,MAAMiF,oBAAoB6M,OAAOR,EAAMmlB,qBAC1C,CAACtmC,KAAM,EAAA6P,MAAMmB,YAAanR,KAAMshB,EAAMmlB,oBAAqBlmC,GAAI+gB,EAAMtQ,SAErE,CAAC7Q,KAAM,EAAA6P,MAAMoD,SAAUpT,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMolB,IACtD,CAACvmC,KAAM,EAAA6P,MAAMqD,OAAQrT,KAAMshB,EAAMolB,GAAInmC,GAAI+gB,EAAMtQ,SAE/C,CAAC7Q,KAAM,EAAA6P,MAAMuD,KAAMvT,KAAMshB,EAAMO,MAAOthB,GAAI+gB,EAAMqlB,cAChD,CAACxmC,KAAM,EAAA6P,MAAMyD,QAASzT,KAAMshB,EAAMO,MAAOthB,GAAI+gB,EAAMqlB,cACnD,CAACxmC,KAAM,gBAAiBH,KAAMshB,EAAMqlB,aAAcpmC,GAAI+gB,EAAMO,OAE5D,CAAC1hB,KAAM,EAAA6P,MAAMuD,KAAMvT,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMslB,aAClD,CAACzmC,KAAM,EAAA6P,MAAMyD,QAASzT,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMslB,aACrD,CAACzmC,KAAM,gBAAiBH,KAAMshB,EAAMslB,YAAarmC,GAAI+gB,EAAMtQ,SAE3D,CAAC7Q,KAAM,EAAA6P,MAAMuD,KAAMvT,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMulB,cAChD,CAAC1mC,KAAM,EAAA6P,MAAMyD,QAASzT,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMulB,cACnD,CAAC1mC,KAAM,gBAAiBH,KAAMshB,EAAMulB,aAActmC,GAAI+gB,EAAMrQ,OAE5D,CAAC9Q,KAAM,EAAA6P,MAAMW,WAAY3Q,KAAM,CAACshB,EAAMO,MAAOP,EAAMrQ,OAAQ1Q,GAAI+gB,EAAMwlB,W,IAClE,IAAArB,SAAQnkB,EAAMwlB,SAASpB,SACxB,EAAA11B,MAAMiB,MACN,EAAAjB,MAAMc,KACN,EAAAd,MAAMmB,YACN,EAAAnB,MAAMuD,KACN,EAAAvD,MAAMsB,KACN,EAAAtB,MAAMwB,SACP,IAED,CAACrR,KAAM,EAAA6P,MAAMa,SAAU7Q,KAAMshB,EAAMwlB,QAASvmC,GAAI+gB,EAAMO,OAEtD,CAAC1hB,KAAM,EAAA6P,MAAMwkB,qBAAsBx0B,KAAMshB,EAAMI,MAAOnhB,GAAI+gB,EAAM8kB,sBAChE,IAAAliC,IAAG,EAAA8L,MAAMwkB,sBAAsB1S,OAAOR,EAAM8kB,qBAC5C,CACEjmC,KAAM,EAAA6P,MAAMwkB,qBACZx0B,KAAMc,KAAKmhB,gBAAgB,CAACX,EAAMI,MAAOJ,EAAM8kB,sBAC/C7lC,GAAI+gB,EAAMukB,iBAEZ,CAAC1lC,KAAM,EAAA6P,MAAMI,gBAAiBpQ,KAAMc,KAAKolC,eAAgB3lC,GAAI+gB,EAAMukB,kBAEnE,IAAA3hC,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMukB,kBACnC,IAAA3hC,IAAG,EAAA8L,MAAMiB,OAAO6Q,OAAOR,EAAMukB,iBAM7B,CAAC1lC,KAAM,EAAA6P,MAAMukB,mBAAoBv0B,KAAM,CAACshB,EAAMtQ,QAASsQ,EAAMrQ,OAAQ1Q,GAAI+gB,EAAMwkB,kBAC/E,CAAC3lC,KAAM,EAAA6P,MAAMgB,QAAShR,KAAMshB,EAAMwkB,iBAAkBvlC,GAAI+gB,EAAMtQ,SAC9D,CAAC7Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMwkB,iBAAkBvlC,GAAI+gB,EAAMrQ,S,GAU9DtR,WAAS,KACP,EAAC,iBAAU2hB,EAAMtQ,UAAY,SAACb,EAAQuT,EAAOC,EAAKC,EAAiBN,GACjE,EAAK7X,wBAAwByW,eAC/B,EAEA,EAAC,iBAAUZ,EAAMS,UAAY,SAAC5R,EAAQuT,EAAOC,EAAKC,EAAiBN,GACjE,EAAKN,wBACP,EAEA,EAAAb,aAAc,SAAC3hB,EAAOR,EAAMO,EAAI6hB,EAAgBtQ,GAM9C,IALA,IAAAuQ,2BAA0B,QAAS7hB,EAAOR,EAAMO,GAK5CC,IAAU,EAAAmhB,oBAIV3hB,IAASshB,EAAMwH,WACjB,EAAKkb,wBAOF5hB,IAMDpiB,IAASshB,EAAM5N,OAAUlT,IAAU,EAAAwP,MAAMwkB,sBAAwBh0B,IAAU,EAAAwP,MAAMI,kBAArF,CAIA,IAAMmS,EAAgBH,EAAiB,EAAKI,sBAExC1Q,GAAavR,IAAO+gB,EAAMilB,gBAC5B,EAAKz6B,sBAAsBi5B,yBAAyBjzB,GAGtD,IAAM+Q,EAAgBC,OAAO9iB,GAAM4iB,cACnC,GAAIriB,IAAO+gB,EAAMU,kBACf,EAAKgB,yBACL,EAAKlX,sBAAsBi6B,iBAAiBxjB,GAAe,IAAAyjB,8BAA6BxlC,SACnF,GAAIR,IAASshB,EAAMilB,eACxB,EAAKz6B,sBAAsBi2B,QAAQxf,QAC9B,GAAI/hB,IAAU,EAAAwP,MAAMyF,OACzB,EAAK3J,sBAAsBiX,OAAOR,EAAeM,QAC5C,GAAI7iB,IAASshB,EAAMrQ,OAAS1Q,IAAO+gB,EAAMilB,eAC9C,EAAKz6B,sBAAsBi7B,MAAMxkB,EAAeM,OAC3C,CAKL,IAAMI,EAAgC,EAAKnX,sBAAsB+W,GACjE,IAAI,IAAAK,YAAWD,GAEb,IACEA,EAA8BV,EAAeM,EAAe/Q,EAC9D,CAAE,MAAO/R,GACP,EAAA+I,OAAOzH,MAAM,gDAAkDwhB,EAAe/Q,EAAW/R,EAC3F,MAOA,IAAAojB,2BAA0BnjB,EAAM,CAACshB,EAAMO,MAAOP,EAAMukB,gBAAiBvkB,EAAM8kB,qBAE/E,CAEIt0B,GAAavR,IAAO+gB,EAAMilB,gBAC5B,EAAKz6B,sBAAsBw5B,2BAA2BxzB,GAGpDtR,IAAU,EAAAwP,MAAMuD,KAClB,EAAKzH,sBAAsBk7B,OAClBxmC,IAAU,EAAAwP,MAAMyD,SACzB,EAAK3H,sBAAsBm7B,QAhD7B,CAkDF,EAEA,EAAC,iBAAU3lB,EAAMtQ,UAAY,SAACb,EAAQuT,EAAOC,EAAKvB,EAAgBkB,GAChE,EAAKd,sBAAwBJ,EAC7B,EAAK3W,wBAAwB2X,gBAC/B,EAEA,EAAC,iBAAU9B,EAAMukB,kBAAoB,SAACrlC,EAAOkjB,EAAOC,EAAKC,EAAiB9R,GACpEtR,IAAU,EAAAwP,MAAMwkB,sBAClB,EAAK1oB,sBAAsBm6B,mBAAmBn0B,EAElD,EAEA,EAAC,iBAAUwP,EAAMS,UAAY,SAAC5R,EAAQuT,EAAOC,EAAKC,EAAiBN,GACjE,EAAKW,sBACP,EAEA,EAAC,iBAAU3C,EAAM+kB,iBAAmB,SAACl2B,EAAQuT,EAAOC,EAAKvB,EAAgBtQ,GAEvE,EAAKhG,sBAAsBo7B,cAAcp1B,GACzC,EAAKlG,aAAa,EAAAoE,MAAMs2B,uBAAuBlkB,EACjD,EAEA,EAAAiB,aAAc,SAAC7iB,EAAOR,EAAMO,EAAI6hB,EAAwBtQ,IACtD,IAAAuQ,2BAA0B,QAAS7hB,EAAOR,EAAMO,GAEhD,EAAKiiB,sBAAwBJ,QAAAA,EAAkB1D,KAAK6E,OAGhD,IAAAC,UAAStc,EAAKuc,YAAcjjB,IAAU,EAAAmhB,oBACxC,EAAKa,sBAAwBtb,EAAKuc,WAGhC3R,GAAavR,IAAO+gB,EAAMilB,gBAC5B,EAAKz6B,sBAAsBw5B,2BAA2BxzB,GAGpDtR,IAAU,EAAAwP,MAAMW,YAAcpQ,IAAO+gB,EAAMwlB,SAC7C,EAAKh7B,sBAAsBq7B,aAAa/kB,EAAgBtQ,GAGtDvR,IAAO+gB,EAAMwH,WACf,EAAKib,iCAET,EAEA,EAAC,iBAAU,EAAA/zB,MAAM0D,QAAU,SAACvD,EAAQuT,EAAOC,EAAKC,EAAiB9R,GAC/D,EAAKhG,sBAAsBzK,MAAMyQ,EACnC,EAEA,EAAAs1B,aAAc,SAACj3B,EAAQuT,EAAOnjB,EAAI6hB,EAAgBkB,GAC5C/iB,IAAO+gB,EAAMqlB,cAAgBpmC,IAAO+gB,EAAMslB,aAAermC,IAAO+gB,EAAMulB,cACxE,EAAKj7B,aAAay7B,cAAcjlB,EAEpC,E,IAGN,EACF,EAtUA,CAAgD,EAAA8B,uBAAnC,EAAA2K,2BAAAA,C,omBCtDb,IAaYvN,EAbZ,UAGA,UACA,UAIA,UAEA,UACA,WAEA,SAAYA,GAEV,4BAEA,kDAMA,wBAWA,sCACA,gBACA,gBACA,oBACA,kCACA,gBAKA,oBACA,gBACA,oCACA,oBACA,sBACA,uCACD,CArCD,CAAYA,IAAK,QAALA,EAAK,KAuCjB,kBACE,WACExV,EACAL,EACAvE,GAEA,SAAK,UAAC4E,EAAuBL,EAAyBvE,IAAK,IAC7D,CAoUF,OA3UqD,OAS1C,YAAAua,mBAAT,SAA4Bva,G,MAA5B,OACE,OAAO,IAAA/H,QAAO,CAGZG,QAAS,CAACC,MAAO+hB,EAAMI,MAAOlhB,MAAO,EAAAmhB,mBACrCtgB,MAAO,EAAAugB,gCACPliB,OAAQ,CACN,CAACS,KAAM,EAAA6P,MAAM6R,MAAO7hB,KAAMshB,EAAMI,MAAOnhB,GAAI+gB,EAAMO,OAEjD,CAAC1hB,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAMO,MAAOthB,GAAI+gB,EAAMS,SAkBhD,CAAC5hB,KAAM,EAAA6P,MAAMgB,QAAShR,KAAMshB,EAAMO,MAAOthB,GAAI+gB,EAAMtQ,SAanD,CAAC7Q,KAAM,EAAA6P,MAAM0D,MAAO1T,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMU,mBACnD,CAAC7hB,KAAM,EAAA6P,MAAMwkB,qBAAsBx0B,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMU,mBAClE,CAAC7hB,KAAM,EAAA6P,MAAM20B,mBAAoB3kC,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMU,mBAEhE,CAAC7hB,KAAM,EAAA6P,MAAM6R,MAAO7hB,KAAMshB,EAAMU,kBAAmBzhB,GAAI+gB,EAAMO,OAK7D,CAAC1hB,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMO,OAKnD,CAAC1hB,KAAM,EAAA6P,MAAMgB,QAAShR,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMtQ,SAUrD,CAAC7Q,KAAM,EAAA6P,MAAMoD,SAAUpT,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMgmB,wBACtD,CAACnnC,KAAM,EAAA6P,MAAMqD,OAAQrT,KAAMshB,EAAMgmB,uBAAwB/mC,GAAI+gB,EAAMS,SAwBnE,CAAC5hB,KAAM,EAAA6P,MAAMoD,SAAUpT,MAAM,IAAAiiB,iBAAgB,CAACX,EAAMS,SAAUT,GAAQ/gB,GAAI+gB,EAAM+e,aAChF,CAAClgC,KAAM,EAAA6P,MAAMqD,OAAQrT,KAAMshB,EAAM+e,YAAa9/B,GAAI+gB,EAAMtQ,SAExD,CAAC7Q,KAAM,EAAA6P,MAAM0E,IAAK1U,KAAMshB,EAAM+e,YAAa9/B,GAAI+gB,EAAMrQ,OAErD,CAAC9Q,KAAM,EAAA6P,MAAM0B,gBAAiB1R,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMwH,WAC7D,CAAC3oB,KAAM,EAAA6P,MAAMgB,QAAShR,KAAMshB,EAAMwH,UAAWvoB,GAAI+gB,EAAMtQ,SACvD,CAAC7Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMwH,UAAWvoB,GAAI+gB,EAAMrQ,OAErD,CAAC9Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMrQ,OACnD,CAAC9Q,KAAM,EAAA6P,MAAMgB,QAAShR,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMtQ,SAGnD,CAAC7Q,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMtQ,SAkBhD,CAAC7Q,KAAM,EAAA6P,MAAMsB,KAAMtR,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMuH,SAClD,CAAC1oB,KAAM,EAAA6P,MAAMgB,QAAShR,KAAMshB,EAAMuH,QAAStoB,GAAI+gB,EAAMtQ,SAErD,CAAC7Q,KAAM,EAAA6P,MAAM+C,aAAc/S,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAM+kB,gBAC1D,CAAClmC,KAAM,EAAA6P,MAAMuC,aAAcvS,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAM+kB,gBAC1D,CAAClmC,KAAM,EAAA6P,MAAMs2B,sBAAuBtmC,KAAMshB,EAAM+kB,eAAgB9lC,GAAI+gB,EAAMtQ,SAE1E,CACE7Q,KAAM,EAAA6P,MAAMwkB,qBACZx0B,MAAM,IAAAiiB,iBAAgB,CAACX,EAAMS,SAAUT,GACvC/gB,GAAI+gB,EAAMukB,iBAEZ,CAAC1lC,KAAM,EAAA6P,MAAM6R,MAAO7hB,KAAMshB,EAAMukB,gBAAiBtlC,GAAI+gB,EAAMO,OAE3D,CAAC1hB,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAMukB,gBAAiBtlC,GAAI+gB,EAAMS,SAM1D,CAAC5hB,KAAM,EAAA6P,MAAMukB,mBAAoBv0B,KAAM,CAACshB,EAAMtQ,QAASsQ,EAAMrQ,OAAQ1Q,GAAI+gB,EAAMwkB,kBAC/E,CAAC3lC,KAAM,EAAA6P,MAAMgB,QAAShR,KAAMshB,EAAMwkB,iBAAkBvlC,GAAI+gB,EAAMtQ,SAC9D,CAAC7Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMwkB,iBAAkBvlC,GAAI+gB,EAAMrQ,OAE5D,CAAC9Q,KAAM,EAAA6P,MAAM0D,MAAO1T,MAAM,IAAAiiB,iBAAgB,CAACX,EAAMS,QAAST,EAAMU,mBAAoBV,GAAQ/gB,GAAI+gB,EAAM5N,OAItG,CAACvT,KAAM,EAAA6P,MAAMyF,OAAQzV,KAAM,IAAKO,GAAI+gB,EAAMqkB,WAU5ChmC,WAAS,KACP,EAAC,kBAAW,EAAAqQ,MAAMyF,SAAW,SAACjV,EAAOR,EAAMO,EAAI6hB,EAAwBtQ,GACrE,EAAKhG,sBAAsBi5B,yBAAyBjzB,GACpD,IAAMmI,EAAWmI,EAAiB,EAAKI,sBAYvC,OAVIxiB,IAASshB,EAAMS,QACjB,EAAKjW,sBAAsBi6B,iBAAiB9rB,EAAU,EAAAstB,uBAAuBC,aAE7E,EAAK17B,sBAAsBiX,OAAO9I,EAAU6I,OAAO9iB,GAAM4iB,gBAOpD,CACT,EAEA,EAAC,iBAAUtB,EAAMgmB,yBAA2B,SAC1C9mC,EACAR,EACAO,EACA6hB,EACAtQ,GAGA,EAAKhG,sBAAsBi5B,yBAAyBjzB,GACpD,IAAMmI,EAAWmI,EAAiB,EAAKI,sBACvC,EAAK1W,sBAAsBlH,GAAGqV,EAAU,KAC1C,EAEA,EAAC,iBAAUqH,EAAM+e,cAAgB,SAAC7/B,EAAOR,EAAMO,EAAI6hB,EAAwBtQ,GACzE,EAAKhG,sBAAsBi5B,yBAAyBjzB,GACpD,IAAMmI,EAAWmI,EAAiB,EAAKI,sBACvC,EAAK1W,sBAAsBlH,GAAGqV,EAAU,KAC1C,EAEA,EAAC,iBAAUqH,EAAMwkB,mBAAqB,SACpC31B,EACAuT,EACAC,EACAC,EACA9R,GAEA,EAAKhG,sBAAsBwoB,sBAAiBrzB,OAAWA,EAAW6Q,EACpE,EAEA,EAAC,iBAAUwP,EAAMrQ,QAAU,SAACzQ,EAAOR,EAAMO,EAAI6hB,EAAwBtQ,GACnE,EAAKhG,sBAAsBi5B,yBAAyBjzB,GACpD,IAAMmI,EAAWmI,EAAiB,EAAKI,sBACvC,EAAK1W,sBAAsBi7B,MAAM9sB,EAAU,QAC7C,EAEA,EAAC,iBAAUqH,EAAMtQ,UAAY,SAACxQ,EAAOR,EAAMO,EAAI6hB,EAAwBtQ,GACrE,EAAKrG,wBAAwByW,gBAE7B,EAAKpW,sBAAsBi5B,yBAAyBjzB,GACpD,IAAMmI,EAAWmI,EAAiB,EAAKI,sBACvC,EAAK1W,sBAAsBmzB,QAAQhlB,EAAU,UAC/C,EAEA,EAAC,iBAAUqH,EAAMwH,YAAc,SAACtoB,EAAOR,EAAMO,EAAI6hB,EAAwBtQ,GACvE,EAAKkyB,wBAEL,EAAKl4B,sBAAsBi5B,yBAAyBjzB,GACpD,IAAMmI,EAAWmI,EAAiB,EAAKI,sBACvC,EAAK1W,sBAAsB27B,UAAUxtB,EAAU,YACjD,EAEA,EAAC,iBAAUqH,EAAMO,QAAU,SAACrhB,EAAOR,EAAMO,EAAIqjB,EAAyB9R,GAEpE,GAAItR,IAAU,EAAAwP,MAAMgB,SAAWzQ,IAAO+gB,EAAMtQ,QAG1C,OAFA,EAAKlF,sBAAsBi5B,yBAAyBjzB,QACpD,EAAKhG,sBAAsB6W,QAAQ,EAAG,UAG1C,EAEA,EAAC,iBAAUrB,EAAMuH,UAAY,SAACroB,EAAOR,EAAMO,EAAI6hB,EAAwBtQ,GACrE,EAAKhG,sBAAsBi5B,yBAAyBjzB,GACpD,IAAMmI,EAAWmI,EAAiB,EAAKI,sBACvC,EAAK1W,sBAAsBi2B,QAAQ9nB,EACrC,EAEA,EAAC,iBAAUqH,EAAMI,QAAU,SAAClhB,EAAOR,EAAMO,EAAI6hB,EAAwBtQ,GACnE,EAAKhG,sBAAsBi5B,yBAAyBjzB,GAKpD,EAAKhG,sBAAsB+S,MAAM,EAAG,QACtC,EAEA,EAAC,iBAAUyC,EAAMS,UAAY,SAACvhB,EAAOR,EAAMO,EAAI6hB,EAAwBtQ,GAKrE,GAJA,EAAKkR,yBAIDziB,IAAO+gB,EAAMO,OAObthB,IAAO+gB,EAAMgmB,uBAAjB,CAIA,EAAKx7B,sBAAsBi5B,yBAAyBjzB,GACpD,IAAMmI,EAAWmI,EAAiB,EAAKI,sBACnCjiB,IAAO+gB,EAAMU,kBAKjB,EAAKlW,sBAAsB6W,QAAQ1I,EAAU,WAJ3C,EAAKnO,sBAAsBi6B,iBAAiB9rB,GAAU,IAAA+rB,8BAA6BxlC,GALrF,CAUF,EAEA,EAAA2hB,aAAc,SAAC3hB,EAAOR,EAAMO,IAC1B,IAAA8hB,2BAA0B,QAAS7hB,EAAOR,EAAMO,EAClD,EAEA,EAAC,iBAAU+gB,EAAMtQ,UAAY,WAC3B,EAAKvF,wBAAwB2X,gBAC/B,EAEA,EAAC,iBAAU9B,EAAMwH,YAAc,WAC7B,EAAKib,iCACP,EAEA,EAAC,iBAAUziB,EAAMS,UAAY,WAC3B,EAAKkC,sBACP,EAEA,EAAC,iBAAU3C,EAAM+kB,iBAAmB,SAACl2B,EAAQuT,EAAOC,EAAKvB,EAAgBtQ,GAEvE,EAAKhG,sBAAsBo7B,cAAcp1B,GACzC,EAAKlG,aAAa,EAAAoE,MAAMs2B,uBAAuBlkB,EACjD,EAEA,EAAAiB,aAAc,SAAC7iB,EAAOR,EAAMO,EAAI6hB,EAAwBtQ,IACtD,IAAAuQ,2BAA0B,QAAS7hB,EAAOR,EAAMO,GAEhD,EAAKiiB,sBAAwBJ,QAAAA,EAAkB1D,KAAK6E,OAGhD,IAAAC,UAAStc,EAAKuc,YAAcjjB,IAAU,EAAAmhB,oBACxC,EAAKa,sBAAwBtb,EAAKuc,WAGpC,EAAK3X,sBAAsBw5B,2BAA2BxzB,EACxD,EAEA,EAAC,iBAAU,EAAA9B,MAAMwkB,uBAAyB,SAACh0B,EAAOkjB,EAAOC,EAAKC,EAAiB9R,GAC7E,EAAKhG,sBAAsBm6B,mBAAmBn0B,EAChD,EAEA,EAAC,iBAAU,EAAA9B,MAAM0D,QAAU,SAACvD,EAAQuT,EAAOC,EAAKC,EAAiB9R,GAC/D,EAAKhG,sBAAsBzK,MAAMyQ,EACnC,E,IAGN,EACF,EA3UA,CAAqD,EAAAoS,uBAAxC,EAAAwV,gCAAAA,C,szBCpDb,IAmBKpY,EAnBL,UAGA,UACA,UAGA,UACA,UACA,UAEA,UACA,WAOA,SAAKA,GACH,UACA,0DACA,4CACA,wBACA,oBAWA,sCACA,YACA,sCACA,gBACA,8BACA,4BACA,8BACA,gBACA,kCACA,8BACA,oBACA,kCACA,gBACA,gBACA,oCACA,oBACA,sDACA,wCACA,uCACD,CAnCD,CAAKA,IAAAA,EAAK,KAqCV,kBAIE,WACExV,EACAL,EACAvE,GAEA,QAAK,UAAC4E,EAAuBL,EAAyBvE,IAAK,K,OAE3D,EAAKwgC,cAAgB,EACrB,EAAKC,gBAAkB,E,CACzB,CA+WF,OA5XkD,OAehD,YAAAzB,aAAA,WACE,OAAO,EAAP,KAAWzkC,OAAOC,KAAK4f,GAAO1hB,KAAI,SAAC4J,GAAQ,OAAA8X,EAAM9X,EAAN,KAAa,GAAF,CAAE,sBAAuB,cAAW,EAC5F,EAEA,YAAAyY,gBAAA,SAAgB1iB,GACd,OAAOuB,KAAKolC,eAAe3hB,QAAO,SAAC4hB,GAAM,OAAAA,IAAM5mC,CAAN,GAC3C,EAES,YAAAkiB,mBAAT,SAA4Bva,G,MAA5B,OACE,OAAO5I,EAAaa,OAAO,CAGzBG,QAAS,CAACC,MAAO+hB,EAAMI,MAAOlhB,MAAO,EAAAmhB,mBACrCtgB,MAAO,EAAAugB,gCACPliB,OAAQ,CACN,CAACS,KAAM,EAAA6P,MAAMS,cAAezQ,KAAM,CAACshB,EAAMI,MAAOJ,EAAM5N,MAAO4N,EAAMukB,iBAAkBtlC,GAAI+gB,EAAMO,QAC/F,IAAA3d,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMI,QACnC,IAAAxd,IAAG,EAAA8L,MAAMS,eAAeqR,OAAOR,EAAMO,OACrC,CAAC1hB,KAAM,EAAA6P,MAAM6R,MAAO7hB,KAAM,CAACshB,EAAMI,MAAOJ,EAAM5N,OAAQnT,GAAI+gB,EAAMO,OAChE,CAAC1hB,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAMO,MAAOthB,GAAI+gB,EAAMS,SAEhD,CAAC5hB,KAAM,EAAA6P,MAAM0D,MAAO1T,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMU,mBACnD,CAAC7hB,KAAM,EAAA6P,MAAMyF,OAAQzV,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMU,mBACpD,CAAC7hB,KAAM,EAAA6P,MAAM20B,mBAAoB3kC,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMU,oBAEhE,IAAA9d,IAAG,EAAA8L,MAAM0B,iBAAiBoQ,OAAOR,EAAMS,UACvC,IAAA7d,IAAG,EAAA8L,MAAM4B,eAAekQ,OAAOR,EAAMS,SACrC,CAAC5hB,KAAM,EAAA6P,MAAMmB,YAAanR,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMtQ,UAEzD,IAAA9M,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMtQ,UACnC,IAAA9M,IAAG,EAAA8L,MAAM4B,eAAekQ,OAAOR,EAAMtQ,SACrC,CAAC7Q,KAAM,EAAA6P,MAAM0B,gBAAiB1R,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMwH,YAC7D,IAAA5kB,IAAG,EAAA8L,MAAM0B,iBAAiBoQ,OAAOR,EAAMwH,WACvC,CAAC3oB,KAAM,EAAA6P,MAAMmB,YAAanR,KAAMshB,EAAMwH,UAAWvoB,GAAI+gB,EAAMtQ,UAG3D,IAAA9M,IAAG,EAAA8L,MAAMsB,MAAMwQ,OAAOR,EAAMS,SAC5B,CAAC5hB,KAAM,EAAA6P,MAAMsB,KAAMtR,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMsmB,eAClD,IAAA1jC,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMsmB,eACnC,IAAA1jC,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMilB,gBAEnC,CAACpmC,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMrQ,OACnD,CAAC9Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMwH,UAAWvoB,GAAI+gB,EAAMrQ,QACrD,IAAA/M,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMrQ,OACnC,CAAC9Q,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMtQ,SAEhD,CAAC7Q,KAAM,EAAA6P,MAAM+C,aAAc/S,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAM+kB,gBAC1D,CAAClmC,KAAM,EAAA6P,MAAMuC,aAAcvS,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAM+kB,gBAC1D,CAAClmC,KAAM,EAAA6P,MAAMs2B,sBAAuBtmC,KAAMshB,EAAM+kB,eAAgB9lC,GAAI+gB,EAAMtQ,SAE1E,CAAC7Q,KAAM,EAAA6P,MAAMsB,KAAMtR,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMilB,iBAChD,IAAAriC,IAAG,EAAA8L,MAAMsB,MAAMwQ,OAAOR,EAAMilB,iBAC5B,IAAAriC,IAAG,EAAA8L,MAAM0B,iBAAiBoQ,OAAOR,EAAMilB,iBACvC,IAAAriC,IAAG,EAAA8L,MAAM4B,eAAekQ,OAAOR,EAAMilB,gBACrC,CAACpmC,KAAM,EAAA6P,MAAMwB,OAAQxR,KAAMshB,EAAMilB,eAAgBhmC,GAAI+gB,EAAMrQ,OAC3D,CAAC9Q,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAMilB,eAAgBhmC,GAAI+gB,EAAMtQ,SACzD,CAAC7Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMilB,eAAgBhmC,GAAI+gB,EAAMrQ,OAE1D,CAAC9Q,KAAM,YAAaH,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMsmB,cACjD,CAACznC,KAAM,YAAaH,KAAMshB,EAAMilB,eAAgBhmC,GAAI+gB,EAAMsmB,eAC1D,IAAA1jC,IAAG,aAAa4d,OAAOR,EAAMsmB,eAC7B,IAAA1jC,IAAG,EAAA8L,MAAMsB,MAAMwQ,OAAOR,EAAMsmB,eAC5B,IAAA1jC,IAAG,EAAA8L,MAAM0B,iBAAiBoQ,OAAOR,EAAMsmB,eACvC,IAAA1jC,IAAG,EAAA8L,MAAM4B,eAAekQ,OAAOR,EAAMsmB,eACrC,IAAA1jC,IAAG,EAAA8L,MAAMwB,QAAQsQ,OAAOR,EAAMsmB,cAG9B,CAACznC,KAAM,EAAA6P,MAAMwB,OAAQxR,KAAMshB,EAAMsmB,aAAcrnC,GAAI+gB,EAAMumB,mBAEzD,IAAA3jC,IAAG,EAAA8L,MAAM0B,iBAAiBoQ,OAAOR,EAAMumB,mBACvC,IAAA3jC,IAAG,EAAA8L,MAAM4B,eAAekQ,OAAOR,EAAMumB,mBACrC,IAAA3jC,IAAG,EAAA8L,MAAMwB,QAAQsQ,OAAOR,EAAMumB,kBAC9B,CAAC1nC,KAAM,EAAA6P,MAAMmB,YAAanR,KAAMshB,EAAMumB,iBAAkBtnC,GAAI+gB,EAAMtQ,SAElE,CAAC7Q,KAAM,EAAA6P,MAAM0E,IAAK1U,KAAMshB,EAAMsmB,aAAcrnC,GAAI+gB,EAAM5M,KACtD,CAACvU,KAAM,EAAA6P,MAAM0E,IAAK1U,KAAMshB,EAAMilB,eAAgBhmC,GAAI+gB,EAAM5M,KACxD,CAACvU,KAAM,EAAA6P,MAAM0E,IAAK1U,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAM5M,KACjD,CAACvU,KAAM,EAAA6P,MAAM0E,IAAK1U,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAM5M,MAC/C,IAAAxQ,IAAG,EAAA8L,MAAMsB,MAAMwQ,OAAOR,EAAM5M,MAC5B,IAAAxQ,IAAG,EAAA8L,MAAMwB,QAAQsQ,OAAOR,EAAM5M,MAC9B,IAAAxQ,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAM5M,MACnC,IAAAxQ,IAAG,EAAA8L,MAAM4B,eAAekQ,OAAOR,EAAM5M,MACrC,IAAAxQ,IAAG,EAAA8L,MAAM0B,iBAAiBoQ,OAAOR,EAAM5M,MACvC,IAAAxQ,IAAG,EAAA8L,MAAM0E,KAAKoN,OAAOR,EAAM5M,MAG3B,IAAAxQ,IAAG,EAAA8L,MAAMwB,QAAQsQ,OAAOR,EAAMtQ,SAE9B,CAAC7Q,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAM5M,IAAKnU,GAAI+gB,EAAMtQ,SAE9C,CAAC7Q,KAAM,EAAA6P,MAAM0D,MAAO1T,KAAMc,KAAKmhB,gBAAgBX,EAAMS,SAAUxhB,GAAI+gB,EAAM5N,OACzE,CAACvT,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAM5N,MAAOnT,GAAI+gB,EAAM5N,OAEjD,CAACvT,KAAM,EAAA6P,MAAMsB,KAAMtR,KAAMshB,EAAMumB,iBAAkBtnC,GAAI+gB,EAAMsmB,cAC3D,CAACznC,KAAM,sBAAuBH,KAAMshB,EAAMumB,iBAAkBtnC,GAAI+gB,EAAMtQ,SAEtE,CAAC7Q,KAAM,EAAA6P,MAAMyF,OAAQzV,KAAMc,KAAKmhB,gBAAgBX,EAAMS,SAAUxhB,GAAI+gB,EAAM5M,KAE1E,CAACvU,KAAM,EAAA6P,MAAMoD,SAAUpT,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMolB,IACtD,CAACvmC,KAAM,EAAA6P,MAAMqD,OAAQrT,KAAMshB,EAAMolB,GAAInmC,GAAI+gB,EAAMtQ,UAI/C,IAAA9M,IAAG,EAAA8L,MAAMuD,MAAMuO,OAAOR,EAAMI,OAE5B,CAACvhB,KAAM,EAAA6P,MAAMuD,KAAMvT,KAAMshB,EAAMO,MAAOthB,GAAI+gB,EAAMqlB,cAChD,CAACxmC,KAAM,EAAA6P,MAAMyD,QAASzT,KAAMshB,EAAMO,MAAOthB,GAAI+gB,EAAMqlB,cACnD,CAACxmC,KAAM,gBAAiBH,KAAMshB,EAAMqlB,aAAcpmC,GAAI+gB,EAAMO,OAE5D,CAAC1hB,KAAM,EAAA6P,MAAMuD,KAAMvT,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMslB,aAClD,CAACzmC,KAAM,EAAA6P,MAAMyD,QAASzT,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMslB,aACrD,CAACzmC,KAAM,gBAAiBH,KAAMshB,EAAMslB,YAAarmC,GAAI+gB,EAAMtQ,SAE3D,CAAC7Q,KAAM,EAAA6P,MAAMuD,KAAMvT,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMulB,cAChD,CAAC1mC,KAAM,EAAA6P,MAAMyD,QAASzT,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMulB,cACnD,CAAC1mC,KAAM,gBAAiBH,KAAMshB,EAAMulB,aAActmC,GAAI+gB,EAAMrQ,OAE5D,CAAC9Q,KAAM,EAAA6P,MAAMW,WAAY3Q,KAAM,CAACshB,EAAMO,MAAOP,EAAMrQ,OAAQ1Q,GAAI+gB,EAAMwlB,UACrE,IAAA5iC,IAAG,EAAA8L,MAAMiB,OAAO6Q,OAAOR,EAAMwlB,UAC7B,IAAA5iC,IAAG,EAAA8L,MAAMc,MAAMgR,OAAOR,EAAMwlB,UAC5B,IAAA5iC,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMwlB,UACnC,IAAA5iC,IAAG,EAAA8L,MAAMuD,MAAMuO,OAAOR,EAAMwlB,UAC5B,IAAA5iC,IAAG,EAAA8L,MAAMsB,MAAMwQ,OAAOR,EAAMwlB,UAC5B,IAAA5iC,IAAG,EAAA8L,MAAMwB,QAAQsQ,OAAOR,EAAMwlB,SAC9B,CAAC3mC,KAAM,EAAA6P,MAAMa,SAAU7Q,KAAMshB,EAAMwlB,QAASvmC,GAAI+gB,EAAMO,QAEtD,IAAA3d,IAAG,EAAA8L,MAAMsB,MAAMwQ,OAAOR,EAAMO,QAC5B,IAAA3d,IAAG,EAAA8L,MAAMwB,QAAQsQ,OAAOR,EAAMO,OAC9B,CAAC1hB,KAAM,EAAA6P,MAAMwB,OAAQxR,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMS,SAEpD,CAAC5hB,KAAM,EAAA6P,MAAMiF,mBAAoBjV,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMwmB,4BAChE,CAAC3nC,KAAM,6BAA8BH,KAAMshB,EAAMwmB,2BAA4BvnC,GAAI+gB,EAAMtQ,UAEvF,IAAA9M,IAAG,EAAA8L,MAAMiF,oBAAoB6M,OAAOR,EAAMrQ,QAC1C,IAAA/M,IAAG,EAAA8L,MAAMiF,oBAAoB6M,OAAOR,EAAMO,QAC1C,IAAA3d,IAAG,EAAA8L,MAAMiF,oBAAoB6M,OAAOR,EAAMwH,YAC1C,IAAA5kB,IAAG,EAAA8L,MAAMiF,oBAAoB6M,OAAOR,EAAMumB,kBAC1C,CAAC1nC,KAAM,EAAA6P,MAAMiF,mBAAoBjV,KAAMshB,EAAMmlB,oBAAqBlmC,GAAI+gB,EAAMmlB,qBAE5E,CAACtmC,KAAM,EAAA6P,MAAMmF,gBAAiBnV,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMymB,0BAC7D,CAAC5nC,KAAM,2BAA4BH,KAAMshB,EAAMymB,yBAA0BxnC,GAAI+gB,EAAMtQ,UAEnF,IAAA9M,IAAG,EAAA8L,MAAMmF,iBAAiB2M,OAAOR,EAAMrQ,QACvC,IAAA/M,IAAG,EAAA8L,MAAMmF,iBAAiB2M,OAAOR,EAAMO,QACvC,IAAA3d,IAAG,EAAA8L,MAAMmF,iBAAiB2M,OAAOR,EAAMwH,YACvC,IAAA5kB,IAAG,EAAA8L,MAAMmF,iBAAiB2M,OAAOR,EAAMumB,mBACvC,IAAA3jC,IAAG,EAAA8L,MAAMmF,iBAAiB2M,OAAOR,EAAMukB,kBACvC,IAAA3hC,IAAG,EAAA8L,MAAMmF,iBAAiB2M,OAAOR,EAAMklB,mBAEvC,CAACrmC,KAAM,EAAA6P,MAAMwkB,qBAAsBx0B,KAAMc,KAAKmhB,gBAAgBX,EAAMO,OAAQthB,GAAI+gB,EAAMukB,kBACtF,IAAA3hC,IAAG,EAAA8L,MAAMwkB,sBAAsB1S,OAAOR,EAAMO,QAC5C,IAAA3d,IAAG,EAAA8L,MAAMwkB,sBAAsB1S,OAAOR,EAAMI,QAC5C,IAAAxd,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMukB,iBAanC,CAAC1lC,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAMukB,gBAAiBtlC,GAAI+gB,EAAMS,UAM1D,IAAA7d,IAAG,EAAA8L,MAAMS,eAAeqR,OAAOR,EAAMS,SAMrC,CAAC5hB,KAAM,EAAA6P,MAAMukB,mBAAoBv0B,KAAM,CAACshB,EAAMtQ,QAASsQ,EAAMrQ,OAAQ1Q,GAAI+gB,EAAMwkB,kBAC/E,CAAC3lC,KAAM,EAAA6P,MAAMgB,QAAShR,KAAMshB,EAAMwkB,iBAAkBvlC,GAAI+gB,EAAMtQ,SAC9D,CAAC7Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMwkB,iBAAkBvlC,GAAI+gB,EAAMrQ,QAU9DtR,WAAS,KACP,EAAC,iBAAU2hB,EAAMtQ,UAAY,WAC3B,EAAKvF,wBAAwByW,eAC/B,EAEA,EAAAC,aAAc,SAAC3hB,EAAOR,EAAMO,EAAI6hB,EAAgBtQ,GAM9C,IALA,IAAAuQ,2BAA0B,QAAS7hB,EAAOR,EAAMO,GAK5CC,IAAU,EAAAmhB,oBAIV3hB,IAASshB,EAAMwH,WACjB,EAAKkb,wBAOF5hB,GAAL,CAIA,IAAMG,EAAgBH,EAAiB,EAAKI,sBAM5C,GAJI1Q,GAAavR,IAAO+gB,EAAMilB,gBAAkBhmC,IAAO+gB,EAAMumB,kBAC3D,EAAK/7B,sBAAsBi5B,yBAAyBjzB,GAGxC,cAAVtR,GAAyBR,IAASshB,EAAMrQ,MAC1C,OAAO,EAGLjR,IAASshB,EAAMO,OAASthB,IAAO+gB,EAAMS,QACvC,EAAKkC,uBACIjkB,IAASshB,EAAMS,SAAYxhB,IAAO+gB,EAAMtQ,SAAWzQ,IAAO+gB,EAAMU,mBACzE,EAAKgB,yBAGP,IAAMH,EAAgBC,OAAO9iB,GAAM4iB,cACnC,GAAIriB,IAAO+gB,EAAMU,kBACf,EAAKgB,yBACL,EAAKlX,sBAAsBi6B,iBAAiBxjB,GAAe,IAAAyjB,8BAA6BxlC,SACnF,GAAIR,IAASshB,EAAMilB,eAAgB,CACxC,IAAMyB,EAAe5lB,EAAiB,EAAKslB,cAC3C,EAAK57B,sBAAsBi2B,QAAQiG,EACrC,MAAO,GAAIhoC,IAASshB,EAAMumB,iBAAkB,CACpCG,EAAe,EAAKL,gBAAkB,EAAKD,cACjD,EAAK57B,sBAAsBi2B,QAAQiG,EACrC,MAAO,GAAIxnC,IAAU,EAAAwP,MAAMyF,OACzB,EAAK3J,sBAAsBiX,OAAOR,EAAeM,QAC5C,GAAI7iB,IAASshB,EAAMrQ,OAAS1Q,IAAO+gB,EAAMilB,eAC9C,EAAKz6B,sBAAsBi7B,MAAMxkB,EAAeM,OAC3C,CAKL,IAAMI,EAAgC,EAAKnX,sBAAsB+W,GACjE,IAAI,IAAAK,YAAWD,GAEb,IACEA,EAA8BV,EAAeM,EAAe/Q,EAC9D,CAAE,MAAO/R,GACP,EAAA+I,OAAOzH,MAAM,gDAAkDwhB,EAAe/Q,EAAW/R,EAC3F,MAOA,IAAAojB,2BAA0BnjB,EAAM,CAC9BshB,EAAMO,MACNP,EAAMukB,gBACNvkB,EAAMulB,aACNvlB,EAAMslB,YACNtlB,EAAMwmB,2BACNxmB,EAAMymB,0BAGZ,CAEIj2B,GAAavR,IAAO+gB,EAAMilB,gBAAkBhmC,IAAO+gB,EAAMsmB,cAAgBrnC,IAAO+gB,EAAMumB,kBACxF,EAAK/7B,sBAAsBw5B,2BAA2BxzB,GAGpDtR,IAAU,EAAAwP,MAAMuD,KAClB,EAAKzH,sBAAsBk7B,OAClBxmC,IAAU,EAAAwP,MAAMyD,QACzB,EAAK3H,sBAAsBm7B,SAClBzmC,IAAU,EAAAwP,MAAMwkB,sBACzB,EAAK1oB,sBAAsBm6B,mBAAmBn0B,EAvEhD,CAyEF,EAEA,EAAC,iBAAUwP,EAAMtQ,UAAY,WAC3B,EAAKvF,wBAAwB2X,gBAC/B,EAEA,EAAC,iBAAU9B,EAAM+kB,iBAAmB,SAACl2B,EAAQuT,EAAOC,EAAKvB,EAAgBtQ,GAEvE,EAAKhG,sBAAsBo7B,cAAcp1B,GACzC,EAAKlG,aAAa,EAAAoE,MAAMs2B,uBAAuBlkB,EACjD,EAEA,EAAAiB,aAAc,SAAC7iB,EAAOR,EAAMO,EAAI6hB,EAAgBtQ,IAC9C,IAAAuQ,2BAA0B,QAAS7hB,EAAOR,EAAMO,GAEhD,EAAKiiB,sBAAwBJ,QAAAA,EAAkB1D,KAAK6E,OAGhD,IAAAC,UAAStc,EAAKuc,YAAcjjB,IAAU,EAAAmhB,oBACxC,EAAKa,sBAAwBtb,EAAKuc,WAGhC3R,GAAavR,IAAO+gB,EAAMilB,gBAAkBhmC,IAAO+gB,EAAMsmB,cAAgBrnC,IAAO+gB,EAAMumB,kBACxF,EAAK/7B,sBAAsBw5B,2BAA2BxzB,GAGpDtR,IAAU,EAAAwP,MAAMsB,MAClB,EAAKxF,sBAAsBw5B,2BAA2BxzB,GAGpDtR,IAAU,EAAAwP,MAAMwB,QAClB,EAAK1F,sBAAsBi5B,yBAAyBjzB,GAI1C,cAAVtR,GACAD,IAAO+gB,EAAMsmB,cACbrnC,IAAO+gB,EAAMsmB,cACbrnC,IAAO+gB,EAAMumB,mBAEb,EAAKH,cAAgB,EAAKllB,uBAGxBhiB,IAAU,EAAAwP,MAAMW,YAAcpQ,IAAO+gB,EAAMwlB,SAC7C,EAAKh7B,sBAAsBq7B,aAAa/kB,EAAgBtQ,GAGtDvR,IAAO+gB,EAAMwH,WACf,EAAKib,iCAET,EAEA,EAAC,iBAAU,EAAA/zB,MAAM0D,QAAU,SAACvD,EAAQuT,EAAOC,EAAKC,EAAiB9R,GAC/D,EAAKhG,sBAAsBzK,MAAMyQ,EACnC,EAEA,EAAC,iBAAU,EAAA9B,MAAMsB,OAAS,SAACnB,EAAQuT,EAAOC,EAAKvB,EAAgBkB,GAC7D,EAAKokB,cAAgBtlB,CACvB,EAEA,EAAC,iBAAU,EAAApS,MAAMwB,SAAW,SAACrB,EAAQuT,EAAOC,EAAKvB,EAAgBkB,GAC/D,EAAKqkB,gBAAkBvlB,CACzB,EAEA,EAAAglB,aAAc,SAACj3B,EAAQuT,EAAOnjB,EAAI6hB,EAAgBkB,GAC5C/iB,IAAO+gB,EAAMqlB,cAAgBpmC,IAAO+gB,EAAMslB,aAAermC,IAAO+gB,EAAMulB,cACxE,EAAKj7B,aAAay7B,cAAcjlB,GAE9B7hB,IAAO+gB,EAAMwmB,4BACf,EAAKl8B,aAAaq8B,2BAA2B7lB,GAE3C7hB,IAAO+gB,EAAMymB,0BACf,EAAKn8B,aAAas8B,yBAAyB9lB,EAE/C,E,IAGN,EACF,EA5XA,CAAkD,EAAA8B,uBAArC,EAAAid,6BAAAA,C,wzBCxDb,IAqBK7f,EAiEA6mB,EAtFL,UAGA,UACA,UAIA,UACA,UACA,UACA,UACA,UACA,WAQA,SAAK7mB,GACH,sBACA,0BACA,sBAEA,0BACA,4CACA,wBACA,oBAWA,sCACA,YAEA,sCACA,gBACA,gDACA,8BACA,4BACA,8BACA,gBAQA,8BACA,oBACA,kCAIA,gBACA,gBACA,oCACA,oBAcA,sCACA,wCACA,uCACD,CA9DD,CAAKA,IAAAA,EAAK,KAiEV,SAAK6mB,GACH,wDACA,yDACD,CAHD,CAAKA,IAAAA,EAAY,KAKjB,kBAuCE,WACEr8B,EACAL,EACAvE,GAEA,QAAK,UAAC4E,EAAuBL,EAAyBvE,IAAK,K,OA3CrD,EAAAsa,gBAAoC,GACpC,EAAAD,kBAAmB,EAmCnB,EAAA6mB,mCAAoC,E,CAQ5C,CA+jBF,OA5mBoD,OA+ClD,YAAAnmB,gBAAA,SAAgBzgB,GACd,OAAOV,KAAKolC,eAAe3hB,QAAO,SAAC4hB,GAAM,OAAA3kC,EAAOX,QAAQslC,GAAK,CAApB,GAC3C,EAEA,YAAAD,aAAA,WACE,OAAOzkC,OAAOC,KAAK4f,GAAO1hB,KAAI,SAAC4J,GAAQ,OAAA8X,EAAM9X,EAAN,GACzC,EAES,YAAAiY,mBAAT,SAA4Bva,G,MAA5B,OACE,OAAO5I,EAAaa,OAAO,CAGzBG,QAAS,CAACC,MAAO+hB,EAAMI,MAAOlhB,MAAO,EAAAmhB,mBACrCtgB,MAAO,EAAAugB,gCACPliB,OAAQ,EAAF,GACJ,CACES,KAAM,EAAA6P,MAAMS,cACZzQ,KAAM,CAACshB,EAAMI,MAAOJ,EAAM5N,MAAO4N,EAAMukB,gBAAiBvkB,EAAM+mB,uBAC9D9nC,GAAI+gB,EAAMO,OAGZ,CAAC1hB,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAMO,MAAOthB,GAAI+gB,EAAMS,SAChD,CAAC5hB,KAAM,EAAA6P,MAAMgB,QAAShR,KAAMshB,EAAMO,MAAOthB,GAAI+gB,EAAMtQ,UACnD,IAAA9M,IAAG,EAAA8L,MAAM6R,OAAOC,OAAOR,EAAMO,OAG7B,CACE1hB,KAAM,EAAA6P,MAAM0D,MACZ1T,KAAM,CAACshB,EAAMS,QAAST,EAAMgnB,WAAYhnB,EAAMinB,kBAC9ChoC,GAAI+gB,EAAMU,mBAEZ,CACE7hB,KAAM,EAAA6P,MAAMyF,OACZzV,KAAM,CAACshB,EAAMS,QAAST,EAAMgnB,WAAYhnB,EAAMinB,kBAC9ChoC,GAAI+gB,EAAMU,mBAEZ,CAAC7hB,KAAM,EAAA6P,MAAM20B,mBAAoB3kC,KAAM,CAACshB,EAAMS,QAAST,EAAMinB,kBAAmBhoC,GAAI+gB,EAAMU,mBAC1F,CAAC7hB,KAAM,EAAA6P,MAAMI,gBAAiBpQ,KAAM,CAACshB,EAAMS,QAAST,EAAMinB,kBAAmBhoC,GAAI+gB,EAAMU,mBACvF,CAAC7hB,KAAM,EAAA6P,MAAMwkB,qBAAsBx0B,KAAM,CAACshB,EAAMS,QAAST,EAAMinB,kBAAmBhoC,GAAI+gB,EAAMU,mBAI5F,CAAC7hB,KAAM,EAAA6P,MAAMmB,YAAanR,KAAM,CAACshB,EAAMS,QAAST,EAAMinB,kBAAmBhoC,GAAI+gB,EAAMtQ,UACnF,IAAA9M,IAAG,EAAA8L,MAAMc,MAAMgR,OAAOR,EAAMS,UAC5B,IAAA7d,IAAG,EAAA8L,MAAMgB,SAAS8Q,OAAOR,EAAMS,UAC/B,IAAA7d,IAAG,EAAA8L,MAAM0B,iBAAiBoQ,OAAOR,EAAMS,UACvC,IAAA7d,IAAG,EAAA8L,MAAM4B,eAAekQ,OAAOR,EAAMS,UACrC,IAAA7d,IAAG,EAAA8L,MAAM+C,cAAc+O,OAAOR,EAAMS,UACpC,IAAA7d,IAAG,EAAA8L,MAAMuC,cAAcuP,OAAOR,EAAMS,UACpC,IAAA7d,IAAG,EAAA8L,MAAM6R,OAAOC,OAAOR,EAAMS,SAC7B,CAAC5hB,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMO,OAGnD,CACE1hB,KAAM,EAAA6P,MAAMC,mBACZjQ,KAAM,CAACshB,EAAMI,MAAOJ,EAAMukB,gBAAiBvkB,EAAM+mB,uBACjD9nC,GAAI+gB,EAAMinB,kBAEZ,CAACpoC,KAAMgoC,EAAaK,2BAA4BxoC,KAAMshB,EAAMinB,iBAAkBhoC,GAAI+gB,EAAM+mB,uBACxF,CAACloC,KAAMgoC,EAAaM,0BAA2BzoC,KAAMshB,EAAMinB,iBAAkBhoC,GAAI+gB,EAAMO,SACpF,IAAA4jB,SAAQnkB,EAAMinB,kBAAkB7C,SAEjC,EAAA11B,MAAMiB,MAEN,EAAAjB,MAAMS,gBACP,KAGD,IAAAvM,IAAG,EAAA8L,MAAMgB,SAAS8Q,OAAOR,EAAMtQ,UAC/B,IAAA9M,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMtQ,UACnC,IAAA9M,IAAG,EAAA8L,MAAM4B,eAAekQ,OAAOR,EAAMtQ,SACrC,CAAC7Q,KAAM,EAAA6P,MAAM0B,gBAAiB1R,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMwH,WAC7D,CAAC3oB,KAAM,EAAA6P,MAAM4B,cAAe5R,KAAMshB,EAAMwH,UAAWvoB,GAAI+gB,EAAMtQ,UAC7D,IAAA9M,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMwH,WAEnC,CAAC3oB,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMrQ,OACnD,CAAC9Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMwH,UAAWvoB,GAAI+gB,EAAMrQ,OACrD,CAAC9Q,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMtQ,SAEhD,CAAC7Q,KAAM,EAAA6P,MAAM+C,aAAc/S,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAM+kB,gBAC1D,CAAClmC,KAAM,EAAA6P,MAAMuC,aAAcvS,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAM+kB,gBAC1D,CAAClmC,KAAM,EAAA6P,MAAMs2B,sBAAuBtmC,KAAMshB,EAAM+kB,eAAgB9lC,GAAI+gB,EAAMtQ,SAK1E,CAAC7Q,KAAM,EAAA6P,MAAMsB,KAAMtR,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMsmB,cAGlD,CAACznC,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAMsmB,aAAcrnC,GAAI+gB,EAAMumB,kBACvD,CAAC1nC,KAAM,EAAA6P,MAAMgB,QAAShR,KAAMshB,EAAMsmB,aAAcrnC,GAAI+gB,EAAMumB,kBAC1D,CAAC1nC,KAAM,EAAA6P,MAAMwB,OAAQxR,KAAMshB,EAAMsmB,aAAcrnC,GAAI+gB,EAAMumB,kBAGzD,CAAC1nC,KAAM,EAAA6P,MAAMsB,KAAMtR,KAAMshB,EAAMumB,iBAAkBtnC,GAAI+gB,EAAMsmB,cAG3D,CAACznC,KAAM,EAAA6P,MAAMgB,QAAShR,KAAMshB,EAAMumB,iBAAkBtnC,GAAI+gB,EAAMtQ,SAC9D,CAAC7Q,KAAM,EAAA6P,MAAMmB,YAAanR,KAAMshB,EAAMumB,iBAAkBtnC,GAAI+gB,EAAMtQ,SAGlE,CAAC7Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAM,CAACshB,EAAMsmB,aAActmB,EAAMumB,kBAAmBtnC,GAAI+gB,EAAMrQ,QAIlF,IAAA/M,IAAG,EAAA8L,MAAMsB,MAAMwQ,OAAOR,EAAMsmB,eAC5B,IAAA1jC,IAAG,EAAA8L,MAAM0B,iBAAiBoQ,OAAOR,EAAMsmB,eACvC,IAAA1jC,IAAG,EAAA8L,MAAM4B,eAAekQ,OAAOR,EAAMsmB,eAGrC,IAAA1jC,IAAG,EAAA8L,MAAM0B,iBAAiBoQ,OAAOR,EAAMumB,mBACvC,IAAA3jC,IAAG,EAAA8L,MAAM4B,eAAekQ,OAAOR,EAAMumB,mBACrC,IAAA3jC,IAAG,EAAA8L,MAAMwB,QAAQsQ,OAAOR,EAAMumB,mBAC9B,IAAA3jC,IAAG,EAAA8L,MAAMc,MAAMgR,OAAOR,EAAMumB,mBAG5B,IAAA3jC,IAAG,EAAA8L,MAAMsB,MAAMwQ,OAAOR,EAAMrQ,QAC5B,IAAA/M,IAAG,EAAA8L,MAAMwB,QAAQsQ,OAAOR,EAAMrQ,QAG9B,IAAA/M,IAAG,EAAA8L,MAAMwB,QAAQsQ,OAAOR,EAAMtQ,SAK9B,CAAC7Q,KAAM,EAAA6P,MAAM0E,IAAK1U,KAAMshB,EAAMsmB,aAAcrnC,GAAI+gB,EAAM5M,KACtD,CAACvU,KAAM,EAAA6P,MAAM0E,IAAK1U,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAM5M,KACjD,CAACvU,KAAM,EAAA6P,MAAM0E,IAAK1U,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAM5M,MAE/C,IAAAxQ,IAAG,EAAA8L,MAAMsB,MAAMwQ,OAAOR,EAAM5M,MAC5B,IAAAxQ,IAAG,EAAA8L,MAAMwB,QAAQsQ,OAAOR,EAAM5M,MAC9B,IAAAxQ,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAM5M,MACnC,IAAAxQ,IAAG,EAAA8L,MAAM4B,eAAekQ,OAAOR,EAAM5M,MACrC,IAAAxQ,IAAG,EAAA8L,MAAM0B,iBAAiBoQ,OAAOR,EAAM5M,MACvC,IAAAxQ,IAAG,EAAA8L,MAAM0E,KAAKoN,OAAOR,EAAM5M,KAE3B,CAACvU,KAAM,EAAA6P,MAAMc,KAAM9Q,KAAMshB,EAAM5M,IAAKnU,GAAI+gB,EAAMS,SAE9C,CAAC5hB,KAAM,EAAA6P,MAAM0D,MAAO1T,KAAMc,KAAKmhB,gBAAgB,CAACX,EAAMS,QAAST,EAAMinB,mBAAoBhoC,GAAI+gB,EAAM5N,OAEnG,CACEvT,KAAM,EAAA6P,MAAMyF,OACZzV,KAAMc,KAAKmhB,gBAAgB,CAACX,EAAMS,QAAST,EAAMinB,iBAAkBjnB,EAAMgnB,aACzE/nC,GAAI+gB,EAAM5M,KAGZ,CAACvU,KAAM,EAAA6P,MAAMmF,gBAAiBnV,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMklB,oBAC7D,IAAAtiC,IAAG,EAAA8L,MAAMmF,iBAAiB2M,OAAOR,EAAMrQ,QACvC,IAAA/M,IAAG,EAAA8L,MAAMmF,iBAAiB2M,OAAOR,EAAMwH,YACvC,IAAA5kB,IAAG,EAAA8L,MAAMmF,iBAAiB2M,OAAOR,EAAMumB,mBACvC,IAAA3jC,IAAG,EAAA8L,MAAMmF,iBAAiB2M,OAAOR,EAAMklB,mBACvC,CAACrmC,KAAM,EAAA6P,MAAMmB,YAAanR,KAAMshB,EAAMklB,kBAAmBjmC,GAAI+gB,EAAMtQ,SAEnE,CAAC7Q,KAAM,EAAA6P,MAAMiF,mBAAoBjV,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMmlB,sBAChE,IAAAviC,IAAG,EAAA8L,MAAMiF,oBAAoB6M,OAAOR,EAAMrQ,QAC1C,IAAA/M,IAAG,EAAA8L,MAAMiF,oBAAoB6M,OAAOR,EAAMwH,YAC1C,IAAA5kB,IAAG,EAAA8L,MAAMiF,oBAAoB6M,OAAOR,EAAMumB,mBAC1C,IAAA3jC,IAAG,EAAA8L,MAAMiF,oBAAoB6M,OAAOR,EAAMmlB,qBAC1C,CAACtmC,KAAM,EAAA6P,MAAMmB,YAAanR,KAAMshB,EAAMmlB,oBAAqBlmC,GAAI+gB,EAAMtQ,SAGrE,CAAC7Q,KAAM,EAAA6P,MAAMoD,SAAUpT,KAAMshB,EAAMS,QAASxhB,GAAI+gB,EAAMgnB,YACtD,CAACnoC,KAAM,EAAA6P,MAAMqD,OAAQrT,KAAMshB,EAAMgnB,WAAY/nC,GAAI+gB,EAAMS,UACvD,IAAA7d,IAAG,EAAA8L,MAAMc,MAAMgR,OAAOR,EAAMgnB,aAC5B,IAAApkC,IAAG,EAAA8L,MAAMiB,OAAO6Q,OAAOR,EAAMgnB,YAE7B,CAACnoC,KAAM,EAAA6P,MAAMoD,SAAUpT,KAAMshB,EAAMO,MAAOthB,GAAI+gB,EAAMonB,UAEpD,CAACvoC,KAAM,EAAA6P,MAAMqD,OAAQrT,KAAMshB,EAAMonB,SAAUnoC,GAAI+gB,EAAMS,UACrD,IAAA7d,IAAG,EAAA8L,MAAMc,MAAMgR,OAAOR,EAAMonB,WAC5B,IAAAxkC,IAAG,EAAA8L,MAAMiB,OAAO6Q,OAAOR,EAAMonB,UAE7B,CAACvoC,KAAM,EAAA6P,MAAMoD,SAAUpT,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMqnB,UACpD,CAACxoC,KAAM,EAAA6P,MAAMqD,OAAQrT,KAAMshB,EAAMqnB,SAAUpoC,GAAI+gB,EAAMrQ,QACrD,IAAA/M,IAAG,EAAA8L,MAAMc,MAAMgR,OAAOR,EAAMqnB,WAC5B,IAAAzkC,IAAG,EAAA8L,MAAMiB,OAAO6Q,OAAOR,EAAMqnB,UAE7B,CAACxoC,KAAM,EAAA6P,MAAMoD,SAAUpT,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMsnB,YACtD,CAACzoC,KAAM,EAAA6P,MAAMqD,OAAQrT,KAAMshB,EAAMsnB,WAAYroC,GAAI+gB,EAAMtQ,UACvD,IAAA9M,IAAG,EAAA8L,MAAMc,MAAMgR,OAAOR,EAAMsnB,aAC5B,IAAA1kC,IAAG,EAAA8L,MAAMiB,OAAO6Q,OAAOR,EAAMsnB,YAC7B,CAACzoC,KAAM,EAAA6P,MAAM0E,IAAK1U,KAAMshB,EAAMsnB,WAAYroC,GAAI+gB,EAAM5M,MAGpD,IAAAxQ,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMgnB,aACnC,IAAApkC,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMonB,WACnC,IAAAxkC,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMqnB,WACnC,IAAAzkC,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMsnB,aAGnC,IAAA1kC,IAAG,EAAA8L,MAAMqD,QAAQyO,OAAOR,EAAMtQ,UAC9B,IAAA9M,IAAG,EAAA8L,MAAMqD,QAAQyO,OAAOR,EAAMrQ,QAC9B,IAAA/M,IAAG,EAAA8L,MAAMqD,QAAQyO,OAAOR,EAAMO,QAC9B,IAAA3d,IAAG,EAAA8L,MAAMqD,QAAQyO,OAAOR,EAAMS,SAG9B,CAAC5hB,KAAM,EAAA6P,MAAMuD,KAAMvT,KAAMshB,EAAMO,MAAOthB,GAAI+gB,EAAMqlB,cAChD,CAACxmC,KAAM,EAAA6P,MAAMyD,QAASzT,KAAMshB,EAAMO,MAAOthB,GAAI+gB,EAAMqlB,cACnD,CAACxmC,KAAM,gBAAiBH,KAAMshB,EAAMqlB,aAAcpmC,GAAI+gB,EAAMO,OAE5D,CAAC1hB,KAAM,EAAA6P,MAAMuD,KAAMvT,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMslB,aAClD,CAACzmC,KAAM,EAAA6P,MAAMyD,QAASzT,KAAMshB,EAAMtQ,QAASzQ,GAAI+gB,EAAMslB,aACrD,CAACzmC,KAAM,gBAAiBH,KAAMshB,EAAMslB,YAAarmC,GAAI+gB,EAAMtQ,SAE3D,CAAC7Q,KAAM,EAAA6P,MAAMuD,KAAMvT,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMulB,cAChD,CAAC1mC,KAAM,EAAA6P,MAAMyD,QAASzT,KAAMshB,EAAMrQ,MAAO1Q,GAAI+gB,EAAMulB,cACnD,CAAC1mC,KAAM,gBAAiBH,KAAMshB,EAAMulB,aAActmC,GAAI+gB,EAAMrQ,OAE5D,CAAC9Q,KAAM,EAAA6P,MAAMW,WAAY3Q,KAAM,CAACshB,EAAMO,MAAOP,EAAMrQ,MAAOqQ,EAAMtQ,SAAUzQ,GAAI+gB,EAAMwlB,UACpF,IAAA5iC,IAAG,EAAA8L,MAAMiB,OAAO6Q,OAAOR,EAAMwlB,UAC7B,IAAA5iC,IAAG,EAAA8L,MAAMc,MAAMgR,OAAOR,EAAMwlB,UAC5B,IAAA5iC,IAAG,EAAA8L,MAAMgB,SAAS8Q,OAAOR,EAAMwlB,UAC/B,IAAA5iC,IAAG,EAAA8L,MAAMmB,aAAa2Q,OAAOR,EAAMwlB,UACnC,IAAA5iC,IAAG,EAAA8L,MAAMuD,MAAMuO,OAAOR,EAAMwlB,UAC5B,IAAA5iC,IAAG,EAAA8L,MAAMyD,SAASqO,OAAOR,EAAMwlB,UAC/B,IAAA5iC,IAAG,EAAA8L,MAAMsB,MAAMwQ,OAAOR,EAAMwlB,UAC5B,IAAA5iC,IAAG,EAAA8L,MAAMwB,QAAQsQ,OAAOR,EAAMwlB,SAC9B,CAAC3mC,KAAM,EAAA6P,MAAMa,SAAU7Q,KAAMshB,EAAMwlB,QAASvmC,GAAI+gB,EAAMO,QAEtD,IAAA3d,IAAG,EAAA8L,MAAMsB,MAAMwQ,OAAOR,EAAMO,QAC5B,IAAA3d,IAAG,EAAA8L,MAAMwB,QAAQsQ,OAAOR,EAAMO,QAC9B,IAAA3d,IAAG,EAAA8L,MAAMwB,QAAQsQ,OAAOR,EAAMS,SAE9B,CACE5hB,KAAM,EAAA6P,MAAMwkB,qBACZx0B,KAAMc,KAAKmhB,gBAAgB,CAACX,EAAMI,MAAOJ,EAAMS,QAAST,EAAMinB,mBAC9DhoC,GAAI+gB,EAAMukB,iBAEZ,CAAC1lC,KAAM,EAAA6P,MAAMwkB,qBAAsBx0B,KAAMshB,EAAMI,MAAOnhB,GAAI+gB,EAAM+mB,uBAChE,CACEloC,KAAM,EAAA6P,MAAMI,gBACZpQ,KAAMc,KAAKmhB,gBAAgB,CAACX,EAAMS,QAAST,EAAMinB,mBACjDhoC,GAAI+gB,EAAMukB,iBASZ,CAAC1lC,KAAM,EAAA6P,MAAMukB,mBAAoBv0B,KAAM,CAACshB,EAAMtQ,QAASsQ,EAAMrQ,OAAQ1Q,GAAI+gB,EAAMwkB,kBAC/E,CAAC3lC,KAAM,EAAA6P,MAAMgB,QAAShR,KAAMshB,EAAMwkB,iBAAkBvlC,GAAI+gB,EAAMtQ,SAC9D,CAAC7Q,KAAM,EAAA6P,MAAMiB,MAAOjR,KAAMshB,EAAMwkB,iBAAkBvlC,GAAI+gB,EAAMrQ,S,GAU9DtR,WAAS,KACP,EAAC,kBAAW,EAAAqQ,MAAMS,gBAAkB,SAClCN,EACAnQ,EACA2jB,EACAC,EACAN,GAEItjB,IAASshB,EAAMinB,mBACjB,EAAKH,mCAAoC,EAE7C,EAEA,EAAC,kBAAW,EAAAp4B,MAAMI,kBAAoB,SACpCD,EACAnQ,EACA2jB,EACAC,EACAN,GASA,QAAItjB,IAASshB,EAAMinB,mBAAqB,EAAKH,kCAK/C,EAEA,EAAC,kBAAW,EAAAp4B,MAAMiB,QAAU,SAACd,EAAQnQ,EAAM2jB,EAAKvB,EAAwBtQ,GAGtE,OAAI9R,IAASshB,EAAMinB,mBACb,EAAKH,kCAEP,EAAKx8B,aAAau8B,EAAaM,2BAA2BrmB,EAAgBtQ,GAG1E,EAAKlG,aAAau8B,EAAaK,4BAA4BpmB,EAAgBtQ,IAEtE,EAIX,EAEA,EAAC,iBAAUwP,EAAMumB,mBAAqB,SACpC13B,EACAuT,EACAnjB,EACA6hB,EACAtQ,G,MAEA,GAAIvR,IAAO+gB,EAAMsmB,aAAjB,CAMA,IAAMI,EAAe5lB,GAAyC,QAAvB,IAAKymB,0BAAkB,QAAIzmB,GAClE,EAAKymB,wBAAqB5nC,EAC1B,EAAK6K,sBAAsBi5B,yBAAyBjzB,GACpD,EAAKhG,sBAAsBi2B,QAAQiG,EANnC,CAOF,EAEA,EAAC,iBAAU1mB,EAAMtQ,UAAY,WAC3B,EAAKvF,wBAAwByW,eAC/B,EAEA,EAAC,iBAAUZ,EAAMinB,mBAAqB,WACpC,EAAKH,mCAAoC,EACzC,EAAKplB,wBACP,EAEA,EAAC,iBAAU1B,EAAMsmB,eAAiB,SAACz3B,EAAQuT,EAAOnjB,EAAI6hB,EAAwBkB,G,MAC5E,GAAI/iB,IAAO+gB,EAAMumB,iBAAjB,CAMA,IAAMG,EAAe5lB,GAAyC,QAAvB,IAAKymB,0BAAkB,QAAIzmB,GAClE,EAAKymB,wBAAqB5nC,EAC1B,EAAK6K,sBAAsBi2B,QAAQiG,EALnC,CAMF,EAEA,EAAA7lB,aAAc,SAAC3hB,EAAOR,EAAMO,EAAI6hB,EAAgBtQ,GAM9C,IALA,IAAAuQ,2BAA0B,QAAS7hB,EAAOR,EAAMO,GAK5CC,IAAU,EAAAmhB,oBAIV3hB,IAASshB,EAAMwH,WACjB,EAAKkb,wBAOF5hB,GAAL,CAIA,EAAKE,eAAe9hB,EAAOR,EAAMO,EAAI6hB,EAAgBtQ,GACrD,IAAMyQ,EAAgBH,EAAiB,EAAKI,sBAExC1Q,GAAavR,IAAO+gB,EAAMumB,kBAC5B,EAAK/7B,sBAAsBi5B,yBAAyBjzB,GAGlDA,GAAatR,IAAU,EAAAwP,MAAMqD,SAC/B,EAAKy1B,0BAA4Bh3B,GAG9B9R,IAASshB,EAAMO,OAAS7hB,IAASshB,EAAMgnB,YAAe/nC,IAAO+gB,EAAMS,QAE7D/hB,IAASshB,EAAMS,SAAYxhB,IAAO+gB,EAAMtQ,SAAWzQ,IAAO+gB,EAAMgnB,YACzE,EAAKtlB,yBAFL,EAAKiB,uBAKP,IAAMpB,EAAgBC,OAAO9iB,GAAM4iB,cACnC,GAAIriB,IAAO+gB,EAAMU,kBACf,EAAKgB,yBACL,EAAKlX,sBAAsBi6B,iBAAiBxjB,GAAe,IAAAyjB,8BAA6BxlC,SACnF,GAAIR,IAASshB,EAAMumB,kBAGxB,IAAAkB,aACK,GAAIvoC,IAAU,EAAAwP,MAAMyF,OACzB,EAAK3J,sBAAsBiX,OAAOR,EAAeM,QAC5C,GACL7iB,IAASshB,EAAMqnB,UACf3oC,IAASshB,EAAMonB,UACf1oC,IAASshB,EAAMsnB,YACf5oC,IAASshB,EAAMgnB,YAEX,IAAA7hC,cAAa,EAAKqiC,6BACpB,EAAKh9B,sBAAsBw5B,2BAA2B,EAAKwD,2BAC3D,EAAKh9B,sBAAsBi5B,yBAAyB,EAAK+D,4BAE3D,EAAKh9B,sBAAsBlH,GAAG2d,EAAe,WACxC,GAAI/hB,IAAU,EAAAwP,MAAMoD,UAAYpT,IAASshB,EAAMS,SACpD,IAAAgnB,aACK,GAAIvoC,IAAU,EAAAwP,MAAMS,eAAiBzQ,IAASshB,EAAM+mB,uBACzD,IAAAU,aACK,GAAI/oC,IAASshB,EAAMI,MAGxB,EAAK5V,sBAAsB+S,MAAM,EAAGyC,EAAMI,MAAMkB,oBAC3C,GACJpiB,IAAU,EAAAwP,MAAMiB,OAASjR,IAASshB,EAAMS,SAAWxhB,IAAO+gB,EAAMO,OAChErhB,IAAU2nC,EAAaK,4BACtBxoC,IAASshB,EAAMinB,kBACfhoC,IAAO+gB,EAAM+mB,uBACd7nC,IAAU2nC,EAAaM,2BAA6BzoC,IAASshB,EAAMinB,kBAAoBhoC,IAAO+gB,EAAMO,MAIrG,EAAKmB,8BACA,GAAIhjB,IAASshB,EAAMinB,iBAExB,EAAKz8B,sBAAsB6W,QAAQJ,EAAejB,EAAMS,QAAQa,oBAC3D,GAAI5iB,IAASshB,EAAM5N,MAAO,CAK/B,IAAMuP,EAAgC,EAAKnX,sBAAsB+W,GACjE,IAAI,IAAAK,YAAWD,GAEb,IACEA,EAA8BV,EAAeM,EAAe/Q,EAC9D,CAAE,MAAO/R,GACP,EAAA+I,OAAOzH,MAAM,gDAAkDwhB,EAAe/Q,EAAW/R,EAC3F,MAOA,IAAAojB,2BAA0BnjB,EAAM,CAACshB,EAAMO,MAAOP,EAAMukB,iBAExD,CAGE/zB,GACAvR,IAAO+gB,EAAMumB,kBACb7nC,IAASshB,EAAMsmB,cACfrnC,IAAO+gB,EAAMsmB,cACb5nC,IAASshB,EAAMgnB,YACftoC,IAASshB,EAAMonB,UACf1oC,IAASshB,EAAMsnB,YACf5oC,IAASshB,EAAMqnB,UAEf,EAAK78B,sBAAsBw5B,2BAA2BxzB,GAGpDtR,IAAU,EAAAwP,MAAMuD,KAClB,EAAKzH,sBAAsBk7B,OAClBxmC,IAAU,EAAAwP,MAAMyD,SACzB,EAAK3H,sBAAsBm7B,QApG7B,CAsGF,EAEA,EAAC,iBAAU3lB,EAAMinB,mBAAqB,WACpC,EAAKtkB,sBACP,EAEA,EAAC,iBAAU3C,EAAMtQ,UAAY,WAC3B,EAAKvF,wBAAwB2X,gBAC/B,EAEA,EAAC,iBAAU9B,EAAMsmB,eAAiB,SAACpnC,EAAOR,EAAM2jB,EAAKvB,EAAwBkB,GACvEtjB,IAASshB,EAAMumB,mBAKnB,EAAKgB,mBAAqBzmB,EAC5B,EAEA,EAAC,iBAAUd,EAAM+kB,iBAAmB,SAACl2B,EAAQuT,EAAOC,EAAKvB,EAAgBtQ,GAEvE,EAAKhG,sBAAsBo7B,cAAcp1B,GACzC,EAAKlG,aAAa,EAAAoE,MAAMs2B,uBAAuBlkB,EACjD,EAEA,EAAAiB,aAAc,SAAC7iB,EAAOR,EAAMO,EAAI6hB,EAAwBtQ,IACtD,IAAAuQ,2BAA0B,QAAS7hB,EAAOR,EAAMO,GAEhD,EAAKiiB,sBAAwBJ,QAAAA,EAAkB1D,KAAK6E,OAGhD,IAAAC,UAAStc,EAAKuc,YAAcjjB,IAAU,EAAAmhB,oBACxC,EAAKa,sBAAwBtb,EAAKuc,YAIlC3R,GACAvR,IAAO+gB,EAAMumB,kBACb7nC,IAASshB,EAAMsmB,cACf5nC,IAASshB,EAAMgnB,YACftoC,IAASshB,EAAMonB,UACf1oC,IAASshB,EAAMsnB,YACf5oC,IAASshB,EAAMqnB,UACbnoC,IAAU,EAAAwP,MAAMsB,MAAQtR,IAASshB,EAAMumB,kBAEzC,EAAK/7B,sBAAsBw5B,2BAA2BxzB,GAGpDtR,IAAU,EAAAwP,MAAMW,YAAcpQ,IAAO+gB,EAAMwlB,SAC7C,EAAKh7B,sBAAsBq7B,aAAa/kB,EAAgBtQ,GAGtDvR,IAAO+gB,EAAMwH,WACf,EAAKib,iCAET,EAEA,EAAC,iBAAU,EAAA/zB,MAAM0D,QAAU,SAACvD,EAAQuT,EAAOC,EAAKC,EAAiB9R,GAC/D,EAAKhG,sBAAsBzK,MAAMyQ,EACnC,EAEA,EAAC,iBAAU,EAAA9B,MAAMI,kBAAoB,SACnCD,EACAuT,EACAC,EACAC,EACAN,GAIA,EAAK8kB,mCAAoC,CAC3C,EAEA,EAAAhB,aAAc,SAAC5mC,EAAOR,EAAMO,EAAI6hB,EAAwBtQ,GAClDtR,IAAU,EAAAwP,MAAMwkB,sBAAwBx0B,IAASshB,EAAMI,MACzD,EAAK5V,sBAAsBk9B,oBAAoBl3B,GACtCtR,IAAU,EAAAwP,MAAMwkB,sBACzB,EAAK1oB,sBAAsBm6B,mBAAmBn0B,GAG5CvR,IAAO+gB,EAAMqlB,cAAgBpmC,IAAO+gB,EAAMslB,aAAermC,IAAO+gB,EAAMulB,cACxE,EAAKj7B,aAAay7B,cAAcjlB,EAEpC,E,IAGN,EAEA,YAAA2B,UAAA,WACE,OAAOjjB,KAAK0gB,eACd,EAEA,YAAAwC,oBAAA,SAAoBnN,GAClB/V,KAAKygB,iBAAmB1K,CAC1B,EAEQ,YAAAyL,eAAR,SACE9hB,EACAR,EACAO,EACAoM,EACAkX,GAEI/iB,KAAKygB,kBACPzgB,KAAK0gB,gBAAgBlhB,KAAK,IAAI,EAAAwjB,eAAetjB,EAAOR,EAAMO,EAAIoM,EAAWkX,GAE7E,EACF,EA5mBA,CAAoD,EAAAK,uBAAvC,EAAArY,+BAAAA,C,qMC0Eb,iBAIA,2BACEo9B,EACAC,GAEA,OAAOhD,EAAagD,GAAc3kB,QAAO,SAAC3N,GAAM,OAAAqyB,EAAepoC,QAAQ+V,GAAK,CAA5B,GAClD,EA9KA,cAMA,UACA,UACA,UAOa,EAAA1S,GAAK,SAAC1D,GAAqE,OACtFshB,OAAQ,SAACviB,GAAkB,OAAEY,KAAMK,EAAOR,KAAMT,EAAOgB,GAAIhB,EAAhC,EAD2D,EAyD3E,EAAAkmC,QAAU,SAAClmC,GACtB,IAAM4pC,EAAgC,W,IAAC,sDACrC,OAAAzpC,EAAOE,KAAI,SAACY,GAAU,OAAEL,KAAMK,EAAOR,KAAMT,EAAOgB,GAAIhB,EAAhC,GAAtB,EACF,MAAO,CAAC6pC,qBAAsBD,EAA+BzD,SAAUyD,EACzE,EAca,EAAAvnB,gCAA6D,SACxEynB,EACArpC,EACAO,EACAe,EACAg+B,EACA/S,EACA+c,GAEA,IAAMC,EAAgB,sCAA+BF,EAAS,cAAM9c,GAC9Did,EAAoB,CACxBH,UAAS,EACTrpC,KAAI,EACJO,GAAE,EACFe,MAAM,IAAA2S,kBAAiB3S,GACvBg+B,UAAS,EACT/S,aAAY,GAIV+S,IAAc,QAAsBxgC,mBAWxC,EAAAgK,OAAOzH,MAAMkoC,EAAeC,GAJ1B,EAAA1gC,OAAO4X,IAAI6oB,EAAeC,EAK9B,EAMa,EAAArmB,0BAA4B,SAAC5jB,EAA2BkqC,SAAA,IAAAA,IAAAA,EAAA,KAC/D,IAAAn6B,WAAU/P,MAIsB,IAAA+P,WAAUm6B,EAAa9yB,MAAK,SAAC+yB,GAAiB,OAAAnqC,IAAUmqC,CAAV,MAEhF,EAAA5gC,OAAOo0B,KAAK,qDAAuD39B,EAEvE,EA4BA,SAAgB2mC,EAAgDyD,GAC9D,OAAO,IAAA9rB,cAAa8rB,EACtB,CA3Ba,EAAAtnB,0BAA4B,SACvCrhB,EACAR,EACAR,EACAO,GAEmB,UAAfS,EACF,EAAA8H,OAAO4X,IAAI,mBAAW,IAAAkpB,UAASrpC,EAAI,IAAG,oBAAW,IAAAqpC,UAASppC,EAAO,IAAG,kBAAS,IAAAopC,UAAS5pC,EAAM,MAE5F,EAAA8I,OAAO4X,IAAI,mBAAW,IAAAkpB,UAAS5pC,EAAM,IAAG,oBAAW,IAAA4pC,UAASppC,EAAO,IAAG,gBAAO,IAAAopC,UAASrpC,EAAI,KAE9F,C,qFCrJA,gDAAqDqc,GAEnD,IAAI,IAAAtN,WAAUsN,GAEZ,OAGF,OAAOkG,OAAOlG,GAAUmV,UAAU,EAAG,GACvC,EAEA,kDAAuDnV,GAErD,IAAI,IAAAtN,WAAUsN,GAEZ,OAGF,OAAO,IAAAitB,WAAUjtB,EACnB,EAEA,mDAAwDA,GAEtD,IAAI,IAAAtN,WAAUsN,GAEZ,OAGF,OAAOkG,OAAOlG,GAAUmV,UAAU,EAAG,IACvC,EA9BA,a,mVC8WA,mCAgGA,8BA9cA,cAWA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UAIA,aAsBE,WAAY/pB,EAAsB2Y,GAAlC,WAjBQ,KAAA5V,qBAAsB,EAYtB,KAAA++B,WAAY,EAGZ,KAAAC,cAAgB,EAGtBjpC,KAAKkH,UAAYA,EACjBlH,KAAK6f,QAAUA,EAEf7f,KAAK6f,QAAQpd,YAAYmB,YAAc,SAAClE,GAAU,SAAKkE,YAAYlE,EAAjB,EAClDM,KAAK6f,QAAQpd,YAAYuB,aAAe,SAACtE,GAAU,SAAKsE,aAAatE,EAAlB,EACnDM,KAAK6f,QAAQpd,YAAYyB,iBAAmB,SAACxE,GAAU,SAAKwE,iBAAiBxE,EAAtB,EACvDM,KAAK6f,QAAQpd,YAAY6B,kBAAoB,SAAC5E,GAAU,SAAK4E,kBAAkB5E,EAAvB,EACxDM,KAAK6f,QAAQpd,YAAY+B,YAAc,SAAC9E,GAAU,SAAK8E,YAAY9E,EAAjB,EAClDM,KAAK6f,QAAQpd,YAAYuC,UAAY,SAACtF,GAAU,SAAKsF,UAAUtF,EAAf,EAChDM,KAAK6f,QAAQpd,YAAYsD,mBAAqB,SAACrG,GAAU,SAAKqG,mBAAmBrG,EAAxB,EACzDM,KAAK6f,QAAQpd,YAAYe,OAAS,WAAM,SAAKA,QAAL,EACxCxD,KAAK6f,QAAQpd,YAAYiB,QAAU,WAAM,SAAKA,SAAL,EACzC1D,KAAK6f,QAAQpd,YAAYwD,eAAiB,WAAM,SAAKA,gBAAL,EAChDjG,KAAK6f,QAAQpd,YAAYqC,YAAc,SAACpF,GAAU,SAAKoF,YAAYpF,EAAjB,EAClDM,KAAK6f,QAAQpd,YAAYkC,aAAe,SAACjF,GAAU,SAAKiF,aAAajF,EAAlB,EAEnD,IAAM+M,EAAYzM,KAAK6f,QAAQjd,gBAC3B,IAAA+C,cAAa8G,KACfzM,KAAKkpC,gBAAkB,IAAI,EAAAC,gBAAgB18B,GAAW,WAAM,SAAK28B,uBAAL,GAA8B,IAE9F,CAiRF,OA/QE,YAAAx0B,QAAA,W,MACE5U,KAAKqpC,2BACe,QAApB,EAAArpC,KAAKkpC,uBAAe,SAAEzqB,UACtBze,KAAKspC,4BAAyBnpC,CAChC,EAEA,YAAAipC,sBAAA,WACOppC,KAAKupC,gBAGNvpC,KAAKwpC,wBACPxpC,KAAKypC,uBAAyB7rB,KAAK6E,MAE/BziB,KAAKypC,yBACPzpC,KAAKupC,cAAcG,gBAChB1pC,KAAKupC,cAAcG,gBAAkB,GAAK9rB,KAAK6E,MAAQziB,KAAKypC,wBAGrE,EAEA,YAAAD,sBAAA,WACE,OAAOxpC,KAAKkpC,iBAAkBlpC,KAAKkpC,gBAAgBS,cACrD,EAEA,YAAAnmC,OAAA,WACE,GAAIxD,KAAK6f,SAAW7f,KAAK6f,QAAQld,oBAAsB3C,KAAKupC,cAAe,CACzE,IAAM19B,EAAY+R,KAAK6E,MACvBziB,KAAK4pC,sBAAwB/9B,EAC7B7L,KAAKypC,uBAAyB59B,EAC9B7L,KAAKgpC,WAAY,CACnB,CACF,EAEA,YAAAtlC,QAAA,WACM1D,KAAK6f,SAAW7f,KAAK6f,QAAQld,oBAAsB3C,KAAKupC,gBAC1DvpC,KAAK6pC,kBAAkB7pC,KAAKupC,eAC5BvpC,KAAKgpC,WAAY,EAErB,EAEA,YAAAjjC,mBAAA,SAAmBm+B,GACbA,EAAQ3+B,OACVvF,KAAK8pC,qBAAqBC,EAA+B7F,EAAQx+B,cAInE1F,KAAKspC,uBAAyBpF,EAAQt+B,oBACxC,EAEA,YAAA1B,iBAAA,SAAiBE,GACfpE,KAAKipC,cAAgB,EACrBjpC,KAAKgqC,mBAAqBD,EAA+B,EAAD,KACnD3lC,GAAO,CACVwB,qBAAsB5F,KAAKspC,iCAEtBtpC,KAAKspC,uBACZtpC,KAAKiqC,mBAAqBrsB,KAAK6E,KACjC,EAEA,YAAAne,kBAAA,SAAkByvB,GAChB/zB,KAAKkqC,gBACLlqC,KAAKgqC,wBAAqB7pC,CAC5B,EAEA,YAAAyD,YAAA,SAAYoV,GACLA,EAAOC,WAIZjZ,KAAKkqC,gBACLlqC,KAAKupC,cAAgBY,EAA0BnxB,GAC/ChZ,KAAK+C,iBAAc5C,EACnBH,KAAKupC,cAAca,cAAgBpqC,KAAKiqC,mBAAqBrsB,KAAK6E,MAAQziB,KAAKiqC,wBAAqB9pC,EAEpGH,KAAKqqC,QAAQrqC,KAAKupC,eACpB,EAEA,YAAAvlC,aAAA,SAAa8vB,GACX,GAAK9zB,KAAKgqC,oBAAuBhqC,KAAKupC,cAAtC,CAIA,IAAMe,EAAoB,EAAH,GAAOtqC,KAAKupC,eACnCe,EAAkBC,UAAY,EAC9BvqC,KAAKkqC,gBACLlqC,KAAKwqC,WAAWxqC,KAAKgqC,mBAAoBM,EAAmBA,EAAkBG,WAL9E,CAMF,EAEA,YAAA3lC,YAAA,SAAYgvB,GACV,GAAK9zB,KAAKgqC,oBAAuBhqC,KAAKupC,cAAtC,CAIA,IAAMe,EAAoB,EAAH,GAAOtqC,KAAKupC,eACnCe,EAAkBI,QAAU,EAC5BJ,EAAkBK,aAAe3qC,KAAK+C,YACtCunC,EAAkBM,eAAiBrtB,EAAMstB,oBACvCP,EAAkBK,aAClB3qC,KAAKupC,cAAckB,YAErBzqC,KAAKkqC,gBACLlqC,KAAKwqC,WAAWxqC,KAAKgqC,mBAAoBM,EAAmBA,EAAkBK,aAV9E,CAWF,EAEA,YAAA3lC,UAAA,SAAUk/B,GACR,IAYIqF,EACAuB,EAbEC,EAAgBhB,EAA+B7F,EAAQx+B,aAEvDslC,EAAmBhrC,KAAKkH,UAAU+jC,eACtC,CAACp4B,KAAMqxB,EAAQrxB,KAAMC,QAASoxB,EAAQpxB,QAASY,SAAU,YACzDwwB,GAGF6G,EAAcvM,UAAYwM,EAAiBn4B,KAC3Ck4B,EAAchyB,WAAY,IAAA5F,kBAAiB,CAACN,KAAMqxB,EAAQrxB,KAAMC,QAASoxB,EAAQpxB,UACjFi4B,EAActf,aAAeuf,EAAiBl4B,QAC9Ci4B,EAAcG,cAAgBF,EAAiBt3B,SAI3C1T,KAAKupC,eAAiBrF,EAAQtrB,YAAc5Y,KAAKupC,cAAcvvB,OAASkqB,EAAQtrB,aAClF2wB,EAAgBvpC,KAAKupC,cACrBuB,EAAe9qC,KAAK+C,YACpBwmC,EAAc4B,cAAgBnrC,KAAK+C,YACnCwmC,EAAc6B,gBAAkB7tB,EAAMstB,oBAAoBtB,EAAc4B,cAAe5B,EAAckB,aAEvGzqC,KAAKwqC,WAAWO,EAAexB,EAAeuB,EAChD,EAEA,YAAAtmC,YAAA,SAAY0/B,GACLlkC,KAAKupC,gBAGVvpC,KAAKupC,cAAc8B,kBAAoBnH,EAAQz/B,gBAC/CzE,KAAKupC,cAAc+B,QAAU,EAC7BtrC,KAAKupC,cAAcgC,cAAgBvrC,KAAK+C,YACxC/C,KAAKupC,cAAciC,gBAAkBjuB,EAAMstB,oBACzC7qC,KAAKupC,cAAcgC,cACnBvrC,KAAKupC,cAAckB,YAEvB,EAEA,YAAA9lC,aAAA,SAAau/B,GACNlkC,KAAKupC,gBAGNrF,EAAQt/B,WAAa,EAAAF,WAAW+mC,eAClCzrC,KAAKupC,cAAcmC,UAAY,EACtBxH,EAAQt/B,WAAa,EAAAF,WAAWinC,SACzC3rC,KAAKupC,cAAcqC,SAAW,EACrB1H,EAAQt/B,WAAa,EAAAF,WAAWmnC,iBACzC7rC,KAAKupC,cAAcuC,UAAY,GAEnC,EAEA,YAAA7lC,eAAA,WACE,IAAIjG,KAAKiK,sBAGTjK,KAAKiK,qBAAsB,EACtBjK,KAAKupC,eAAkBvpC,KAAKgqC,oBAAjC,CAIA,IAAMM,EAAoB,EAAH,GAAOtqC,KAAKupC,eACnCe,EAAkByB,OAAS,EAC3BzB,EAAkB0B,cAAgBhsC,KAAK+C,YACvCunC,EAAkB2B,gBAAkB1uB,EAAMstB,oBACxCP,EAAkB0B,cAClB1B,EAAkBG,YAEpBzqC,KAAKkqC,gBACLlqC,KAAKwqC,WAAWxqC,KAAKgqC,mBAAoBM,EAAmBA,EAAkB0B,cAV9E,CAWF,EAEQ,YAAAlC,qBAAR,SAA6BE,EAAwCT,GACnE,IAAM2C,EAAQ,UAET,IAAAC,eAAcnsC,KAAKkH,UAAUklC,SAE7BpC,GAECT,GAAiBY,KAGjBkC,EAAarsC,KAAK6f,QAAQhd,kBAChCqpC,EAASI,SAAW,MACpBJ,EAASK,iBAAmB,EAAA9uC,QAC5ByuC,EAASM,SAAWH,EAAWhtC,KAC/B6sC,EAASO,gBAAkBJ,EAAWvpC,QACtCopC,EAAS/oC,SAAWnD,KAAK6f,QAAQ3c,cACjCgpC,EAASQ,aAAenvB,EAAMovB,kBAE9BT,EAASU,KAAOhvB,KAAK6E,MACrBypB,EAASW,gBAAiB,IAAAC,gBAC1BZ,EAASa,qBAAuBxvB,EAAMstB,oBAAoBqB,EAASxC,eAAgBwC,EAASc,YAC5FhtC,KAAKkH,UAAU+lC,QAAQC,cAAchB,EACvC,EAEQ,YAAArC,kBAAR,SAA0BN,GACxB,IAAM19B,EAAY+R,KAAK6E,MACnBziB,KAAK4pC,uBAAyB5pC,KAAKgpC,iBACJ7oC,IAA7BopC,EAAcyD,aAChBzD,EAAcyD,YAAcnhC,EAAY7L,KAAK4pC,uBAE3C5pC,KAAKwpC,yBAA2BxpC,KAAKypC,6BAA2DtpC,IAAjCopC,EAAcG,iBAC/EH,EAAcG,gBAAkB79B,EAAY7L,KAAKypC,wBAGvD,EAEQ,YAAAY,QAAR,SAAgBd,GAAhB,WACEA,EAAc4D,QAAU,EACxB5D,EAAcyD,WAAa,EAC3BzD,EAAcG,eAAiB,EAC/BH,EAAcN,cAAgBjpC,KAAKipC,cACnC,IAAMp9B,EAAY+R,KAAK6E,MACvBziB,KAAK4pC,sBAAwB/9B,EAC7B7L,KAAKypC,uBAAyBzpC,KAAKwpC,wBAA0B39B,OAAY1L,EACzEH,KAAKgpC,WAAY,EACjBhpC,KAAK+C,YAAc,EACnB/C,KAAKipC,gBACLjpC,KAAKotC,oBAAsB/J,aAAY,WACrC,IACmC,OAA7BkG,aAAa,EAAbA,EAAekB,aAAsBlB,EAAckB,WAAa,GAAK,EAAK5qB,QAAQld,qBACpF,EAAKI,YAAcwa,EAAM8vB,cAAcn2B,KAAKo2B,IAAI,EAAKztB,QAAQ9c,cAAe,IAEhF,CAAE,MAAO9D,GACP,EAAA+I,OAAO4X,IAAI,uDAAwD3gB,GACnE,EAAKirC,eACP,CACF,GAAGqD,EAAYC,8BACjB,EAEQ,YAAAhD,WAAR,SACER,EACAT,EACAuB,QADA,IAAAvB,IAAAA,EAA+BY,KAG/BZ,EAAcuB,aAAeA,EAC7BvB,EAAckE,eAAiBlwB,EAAMstB,oBAAoBtB,EAAcuB,aAAcvB,EAAckB,aAI/F,IAAA9kC,cAAa4jC,EAAckE,kBACG,IAA5BlE,EAAcmC,WAAmBnC,EAAckE,gBAAkB,KACnElE,EAAcmC,UAAY,GAEG,IAA3BnC,EAAcqC,UAAkBrC,EAAckE,gBAAkB,KAClElE,EAAcqC,SAAW,GAEK,IAA5BrC,EAAcuC,WAAmBvC,EAAckE,gBAAkB,KACnElE,EAAcuC,UAAY,IAK9B9rC,KAAKiqC,mBAAqBrsB,KAAK6E,MAC/BziB,KAAK6pC,kBAAkBN,GACvBvpC,KAAKgpC,WAAY,EACjBhpC,KAAK8pC,qBAAqBE,EAAoBT,EAChD,EAEQ,YAAAW,cAAR,WACElqC,KAAKqpC,2BACLrpC,KAAKupC,mBAAgBppC,CACvB,EAEQ,YAAAkpC,yBAAR,WACE5F,cAAczjC,KAAKotC,4BACZptC,KAAK+C,WACd,EA1TgB,EAAA2qC,YAAc,MACN,EAAAF,8BAAgC,IA0T1D,C,CA5TA,GAwVA,SAAgBzD,EAA+BrkC,G,MACvCjH,EAA4B,CAACkvC,gBAAiB,GAEpD,IAAI,IAAAn/B,WAAU9I,GACZ,OAAOjH,EAmBT,GAhBAA,EAAMmvC,WAAaloC,EAAYP,GAC/B1G,EAAMovC,yBAA2BtwB,EAAMf,2BAA2B9W,EAAYqV,wBAC9Etc,EAAMqvC,eAAiBpoC,EAAY4V,WACnC7c,EAAMsvC,UAAYroC,EAAY2V,QAC9B5c,EAAMuvC,SAAWtoC,EAAY0V,OAC7B3c,EAAMwvC,gBAAkB1wB,EAAMf,2BAA2B9W,EAAY6V,eACrE9c,EAAMkvC,gBAA2C,QAAzB,EAAAjoC,EAAYsV,qBAAa,QAAI,EACrDvc,EAAMmH,qBAAuB2X,EAAMf,2BAA2B9W,EAAYE,sBAE7C,QAAzBF,EAAY0R,UAA+C,SAAzB1R,EAAY0R,SAChD3Y,EAAMud,WAAatW,EAAY0R,UACtB,IAAAzR,cAAaD,EAAY0R,YAClC3Y,EAAMud,WAAa,MACnBvd,EAAMyvC,SAAWxoC,EAAY0R,WAG3B,IAAAzR,cAAalH,EAAMuvC,UACrB,IACE,IAAMA,EAAW,IAAIG,IAAI1vC,EAAMuvC,UAC/BvvC,EAAM2vC,YAAcJ,EAASK,SAC7B5vC,EAAM6vC,UAAYN,EAASO,QAC7B,CAAE,SAEF,CAOF,OAJI,IAAAtQ,gBAAev4B,EAAYwV,gBAC7Bzc,EAAM+vC,eAAiBjxB,EAAM8vB,cAAc3nC,EAAYwV,eAGlDzc,CACT,CA0DA,SAAgB0rC,EAA0BnxB,G,MAClCva,EAAuB,CAC3B6sC,QAAS,EACTS,OAAQ,EACRxB,UAAW,EACXqB,SAAU,EACVF,UAAW,EACXI,UAAW,EACXpB,QAAS,EACTyC,QAAS,GAGX,IAAI,IAAA3+B,WAAUwK,GACZ,OAAOva,EAWT,GARAA,EAAM4sC,kBAAoBryB,EAAOvU,gBACjChG,EAAMub,KAAOhB,EAAO7T,GACpB1G,EAAM6a,SAAWN,EAAOM,SACxB7a,EAAMwa,SAAWD,EAAOC,SACxBxa,EAAMgwC,iBAAmBz1B,EAAOjH,OAChCtT,EAAMiwC,gBAAkB11B,EAAOlH,MAC/BrT,EAAM4O,aAAe2L,EAAOS,UAExB,IAAA9T,cAAalH,EAAM6a,UACrB,IACE,IAAMA,EAAW,IAAI60B,IAAI1vC,EAAM6a,UAC/B7a,EAAMkwC,UAAYr1B,EAASi1B,SAC3B9vC,EAAMmwC,YAAct1B,EAAS+0B,QAC/B,CAAE,SAEF,EAGE,IAAA1oC,cAAaqT,EAAO3H,WACtB5S,EAAMgX,aAAgC,IAAjBuD,EAAO3H,SAG9B,IAAMmI,EAAWR,EAAOQ,SAwBxB,OAvBI,IAAA7T,cAAa6T,KACf/a,EAAMib,SAAWF,EAASE,SAC1Bjb,EAAMkb,eAAiBH,EAASG,eAChClb,EAAMob,aAAeL,EAASK,aAC9Bpb,EAAMqb,aAAeN,EAASM,aAC9Brb,EAAMwb,WAAaT,EAASS,WAC5Bxb,EAAMyb,sBAAwBV,EAASU,sBACvCzb,EAAM4b,mBAAqBb,EAASa,mBACpC5b,EAAM8b,cAAgBf,EAASe,cAC/B9b,EAAMqc,qBAAuByC,EAAMf,2BAA2BhD,EAASsB,sBACvErc,EAAMkc,UAAYnB,EAASmB,UAC3Blc,EAAM+b,QAAUhB,EAASgB,QACzB/b,EAAMgc,gBAAkBjB,EAASiB,kBAG/B,IAAA9U,cAAaqT,EAAOK,kBACtB5a,EAAMowC,aACuB,IAA3B71B,EAAOK,eAAwBL,EAAOK,eAAiBkE,EAAM8vB,cAAcr0B,EAAOK,iBAGtF5a,EAAMqwC,YAA8B,QAAhB,EAAA91B,EAAOI,iBAAS,SAAK,IAAAzT,cAAalH,EAAMowC,aAAepwC,EAAMowC,aAAe,OAAI1uC,EACpG1B,EAAMgsC,WAAaltB,EAAMf,2BAA2BxD,EAAOG,UAEpD1a,CACT,CAvfa,EAAA8uC,YAAAA,C,iVC+3Bb,2BAp5BA,cACA,UACA,UACA,UAGA,UAGA,UAQA,UASA,SACA,UACA,UAMA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UAEA,UAEA,UACA,SACA,UACA,UACA,SACA,UAMA,UAEA,aA8BE,WACEwB,EACiBlvB,EACAmvB,EACAC,EACAC,EACAC,EACAC,GAPnB,WAEmB,KAAAvvB,QAAAA,EACA,KAAAmvB,eAAAA,EACA,KAAAC,eAAAA,EACA,KAAAC,eAAAA,EACA,KAAAC,6BAAAA,EACA,KAAAC,+BAAAA,EA1BX,KAAAC,sBAAuB,EAKvB,KAAAC,oBAAsB,EAKtB,KAAAC,kBAAoB,EAEX,KAAAC,uBAAiD,CAChEC,wBAAyB,SAAC/yB,EAAkBgzB,GAC1C,EAAKR,eAAeS,kBAAkBjzB,EAASgzB,EACjD,GA2fF,KAAAxmC,aAAe,SAACO,GAEd,GADA,EAAAzB,OAAO4X,IAAI,yCAA0CnW,IACjD,IAAA+E,WAAU/E,GACZ,EAAKoW,QAAQ3W,aAAa,EAAKO,YADjC,EAKA,IAAAmmC,sCAAqC,EAAKnmC,OAAQA,IAClD,IAAAomC,uCAAsC,EAAKpmC,OAAQA,IACnD,IAAAjB,8BAA6BiB,GAE7B,IAAMqmC,GAAY,IAAAC,sBAAqB,EAAKtmC,OAAQA,GACpD,EAAKoW,QAAQ3W,aAAa4mC,EAP1B,CAQF,EAEA,KAAAtmC,kBAAoB,SAACD,GAEnB,IAAMymC,EAAY,EAAH,GAAO,EAAKvmC,QAE3B,EAAKwmC,SAAS,oBAEd,EAAKC,WAAW3mC,GAKhB,EAAKE,OAAS,EAAH,GAAOumC,GAClB,EAAK1oC,sBACL,EAAKC,kCACP,EAEA,KAAA+B,cAAgB,SAACC,GACf,EAAKsW,QAAQvW,cAAcC,EAC7B,EAEA,KAAAH,uBAAyB,WACvB,OAAO,EAAKgjC,OAAO+D,YACrB,EAEA,KAAA9mC,UAAY,WACV,OAAO,EAAK4lC,eAAemB,MAC7B,EAkKQ,KAAAC,iBAAmB,SAAC9mC,GAC1B,EAAKE,OAAS,EAAH,KACN,EAAKA,SACL,IAAA6mC,6BAA4B/mC,IAEjC,EAAKjC,sBACL,EAAKC,kCACP,EAhsBEvH,KAAKyJ,OAASslC,EACd/uC,KAAKivC,eAAiB,IAAI,EAAAsB,0BAA0BvwC,KAAKyJ,QAGzD,IAAMq3B,EAAO9gC,KACbA,KAAKmM,oCAAsC,CACzC,UAAIqkC,GACF,OAAO,IAAAC,8BAA6B3P,EAAKr3B,OAC3C,EACA,cAAIgL,G,MACF,OAAsB,QAAf,EAAAqsB,EAAKr3B,OAAOf,WAAG,QAAI,EAC5B,EACA,gBAAIynC,G,MACF,OAAoC,QAA7B,EAAArP,EAAK13B,gCAAwB,QAAI,EAC1C,EACA,mBAAIiD,GACF,OAAOy0B,EAAKr3B,OAAOA,MACrB,GAGF,IAAMinC,EAAiC1wC,KAAK6f,QAAQrL,qBAAqB6H,WACvE,SAACs0B,GACM,EAAKlnC,OAAOf,MACf,EAAKe,OAAOf,IAAMioC,EAAUl8B,YAE9Bi8B,GACF,IAGF1wC,KAAKosC,OAASpsC,KAAK4wC,qBACnB5wC,KAAKsvC,oBAAsB,EAC3BtvC,KAAK6wC,OACL7wC,KAAK8wC,6BAGL,IAAMC,EAAW/wC,KAAK6f,QAAQzU,WAAWpL,MACzCA,KAAKkvC,eAAe8B,iBAAiBD,GAEjC/wC,KAAK6f,QAAQ2sB,WAEfxsC,KAAKixC,YAAc,IAAI,EAAA1D,YAAYvtC,KAAMA,KAAK6f,QAAQ2sB,UAE1D,CAqwBF,OAr1BE,sBAAI,sBAAO,C,IAAX,WACE,OAAO,EAAA/uC,OACT,E,gCAgFA,sBAAI,sCAAuB,C,IAA3B,WACE,OAAOuC,KAAKmvC,4BACd,E,gCAEA,YAAA0B,KAAA,WACE,IACkD,IAAhD7wC,KAAK6f,QAAQqxB,iCACX,IAAAhY,eAAcl5B,KAAKyJ,OAAOf,QAAQ,IAAA6f,SAAQvoB,KAAKyJ,OAAOf,KAF1D,CAQA,EAAAV,OAAOoD,WAAWpL,KAAKyJ,OAAO0nC,OAE9BnxC,KAAKkvC,eAAekC,gBAEpB,IAAMZ,GAAS,IAAAC,8BAA6BzwC,KAAKyJ,QACjDzJ,KAAKitC,QAAUjtC,KAAKgvC,eAAeqC,cACjCrxC,KAAKyJ,OACL,CAACf,IAAK1I,KAAKyJ,OAAOf,IAAK8nC,OAAM,EAAE1tC,QAAS,EAAArF,SACxCuC,KAAK6f,QACL7f,KAAKwvC,wBAGPxvC,KAAKqvC,sBAAuB,EAC5BrvC,KAAKovC,+BAA+BrgC,QAEpC/O,KAAKsH,sBACLtH,KAAKuH,mCACLvH,KAAKosC,OAAO+D,cAAe,IAAArD,gBAC3B9sC,KAAKosC,OAAOgE,OAASpwC,KAAKivC,eAAemB,OAErCpwC,KAAK6f,QAAQ/V,wBACf9J,KAAK6f,QAAQ/V,uBAAuBiF,QAGtC/O,KAAK6f,QAAQtO,qBAAqB+/B,cAClCtxC,KAAK6f,QAAQ9Y,YAAYwF,yBA3BzB,MAFE,EAAAvE,OAAOC,mBAAmB,yCA8B9B,EAEA,YAAAX,oBAAA,W,MACEtH,KAAKosC,OAAO1jC,IAAM1I,KAAKyJ,OAAOf,IAC9B1I,KAAKosC,OAAO3jC,UAAYzI,KAAKyJ,OAAOhB,UAChCzI,KAAKyJ,OAAOlH,SACdvC,KAAKosC,OAAO7pC,OAASvC,KAAKyJ,OAAOlH,QAEnCvC,KAAKosC,OAAOoE,QAAS,IAAAC,8BAA6BzwC,KAAKyJ,QAEvDzJ,KAAKosC,OAAOmF,mBAAoB,IAAAC,yCAAwCxxC,KAAKyJ,QAE7EzJ,KAAKosC,OAAOl/B,UAAS,IAAAvH,cAAa3F,KAAKyJ,OAAOyD,SAAUlN,KAAKyJ,OAAOyD,OAEpElN,KAAKosC,OAAOqF,YAAczxC,KAAKyJ,OAAOgoC,YACtCzxC,KAAKosC,OAAOnW,QAAUj2B,KAAKyJ,OAAOwsB,QAClCj2B,KAAKosC,OAAOr3B,WAAa/U,KAAKyJ,OAAOuL,MACrChV,KAAKosC,OAAOsF,aAAiC,QAAlB,EAAA1xC,KAAKyJ,OAAO2mC,cAAM,QAAIpwC,KAAKyJ,OAAOioC,aAE7Dn0B,EAAMo0B,yBAAyB3xC,KAAKyJ,OAAQzJ,KAAKosC,QAEjDpsC,KAAKosC,OAAOwF,eAAiB5xC,KAAKyJ,OAAOmoC,cAC3C,EAEA,YAAArqC,iCAAA,W,QAEE,KAAI,IAAA5B,cAA0C,QAA7B,EAAA3F,KAAKosC,OAAOmF,yBAAiB,eAAEM,SAI3C,IAAAC,qBAAL,CAEA,IAAMC,GAAY,IAAAC,wBACd,IAAAxjC,WAAUujC,KAEd/xC,KAAKosC,OAAOmF,kBAAiD,QAA7B,EAAAvxC,KAAKosC,OAAOmF,yBAAiB,QAAI,CAAC,EAClEvxC,KAAKosC,OAAOmF,kBAAkBM,MAAQE,EANN,CAOlC,EAEQ,YAAAjB,2BAAR,sBAGE9wC,KAAK6f,QAAQ7U,sBAAsB+S,MAAQ,SAAC5E,EAAkB1a,G,QAC5D,EAAAuJ,OAAO4X,IACL,4BAA8B,EAAKwsB,OAAOG,iBAAmB,uBAAyB,EAAKH,OAAO+D,cAGpG,EAAK8B,YAAY94B,GACjB,EAAK82B,SAASxxC,GACd,EAAK2tC,OAAOmD,kBAAoBp2B,EAChC,EAAKo2B,kBAAoB,EAAKnD,OAAOmD,kBAErC,IAAM2C,EAAiD,QAA/B,EAAuB,QAAvB,IAAAC,YAAYC,mBAAW,eAAEC,cAAM,eAAEH,gBACzD,IAAI,IAAAvsC,cAAausC,KAAoB,IAAAjU,gBAAeiU,GAAkB,CAEpE,IAAMI,EAAep7B,KAAK8M,MAAMpG,KAAK6E,MAAQ,EAAA0vB,YAAYC,YAAYC,OAAOH,iBAC5E,EAAK9F,OAAOkG,aAAeA,CAC7B,CAEA,EAAKpC,YACP,EAEAlwC,KAAK6f,QAAQ7U,sBAAsB6W,QAAU,SAAC1I,EAAkB1a,GAC9D,EAAKwxC,SAASxxC,GACd,EAAK2tC,OAAOmG,qBAAuB,EAAAvQ,YAAYwQ,sBAG/C,IAAMC,EAA2Bv7B,KAAKo2B,IAAIn0B,EAAU,GACpD,EAAK84B,YAAYQ,GACjB,EAAKrG,OAAOsG,iBAAmBD,EAC/B,EAAKrG,OAAOuG,aAAe,EAAKpD,mBAAqB,GAAKkD,EAE1D,EAAKrG,OAAOjpC,SAAW,EAAK0c,QAAQ3c,cAEpC,IAAM0vC,EAAiB,EAAK/yB,QAAQrV,yBAChC,IAAA7E,cAAaitC,KACf,EAAKxG,OAAOr4B,QAAU6+B,EAAe7+B,QACrC,EAAKq4B,OAAOn4B,YAAc2+B,EAAe3+B,aAGrC,MAA+B,EAAK4L,QAAQrT,yBAA3CiJ,EAAY,eAAEe,EAAY,eAGjC,EAAKqJ,QAAQtO,qBAAqBshC,sBAAsBp9B,EAAce,GAEtE,EAAK64B,sBAAuB,EAE5B,EAAKa,YACP,EAEAlwC,KAAK6f,QAAQ7U,sBAAsB2oB,cAAgB,SAACvC,GAGlD,EAAKme,kBAAoB,EAGzB,EAAK9lC,QAAS,IAAAqpC,sCAAqC,EAAKrpC,OAAQ2nB,GAGhE,EAAKgb,OAAS,EAAKwE,qBAEnB,EAAKxE,OAAO2G,MAAO,IAAA7Z,eAAc9H,EAAe2hB,MAAQ3hB,EAAe2hB,MAAO,IAAAC,wBAG9E,EAAKnC,OAGL,EAAKZ,SAAS,iBACd,EAAK7D,OAAOhI,iBAAkB,EAC9B,EAAKgI,OAAOmG,qBAAuB,EAAAvQ,YAAYwQ,sBAI/C,EAAKP,YADiC,GAEtC,EAAK7F,OAAOsG,iBAF0B,EAGtC,EAAKtG,OAAOuG,YAH0B,EAKtC,EAAKvG,OAAOjpC,SAAW,EAAK0c,QAAQ3c,cAIpC,EAAKkpC,OAAOr4B,aAAU5T,EACtB,EAAKisC,OAAOn4B,iBAAc9T,EAEpB,MAA+B,EAAK0f,QAAQrT,yBAA3CiJ,EAAY,eAAEe,EAAY,eAGjC,EAAKqJ,QAAQtO,qBAAqBshC,sBAAsBp9B,EAAce,GAEtE,EAAK64B,sBAAuB,EAE5B,EAAKa,YACP,EAEAlwC,KAAK6f,QAAQ7U,sBAAsB05B,qBAAuB,SAACtT,GAEzD,EAAK3nB,QAAS,IAAAqpC,sCAAqC,EAAKrpC,OAAQ2nB,GAEhE,EAAK9pB,sBACL,EAAKC,mCAEL,EAAK6kC,OAAO2G,MAAO,IAAA7Z,eAAc9H,EAAe2hB,MAAQ3hB,EAAe2hB,MAAO,IAAAC,uBAChF,EAEAhzC,KAAK6f,QAAQ7U,sBAAsBmzB,QAAU,SAAChlB,EAAkB1a,GAC9D,EAAKwzC,YAAY94B,GACjB,EAAK82B,SAASxxC,GACd,EAAK2tC,OAAOjI,OAAShrB,EACrB,EAAK85B,sBACL,EAAK/C,YACP,EAEAlwC,KAAK6f,QAAQ7U,sBAAsBiX,OAAS,SAAC9I,EAAkB1a,GAC7D,IAAIy0C,EAA2B,EAAK9G,OAAO+G,eAC7B,YAAV10C,IACF,EAAKwzC,YAAY94B,GACjB,EAAK82B,SAASxxC,GACd,EAAK2tC,OAAOjI,OAAShrB,EACrB,EAAK85B,uBACD,IAAAvwB,UAAS,EAAK0pB,OAAOgH,gBACvBF,EAA2B,EAAK9G,OAAOgH,cAGzC,EAAKnG,QAAQoG,kBAAkB,EAAKjH,SACpC,IAAAkH,wBAAuB,EAAKlH,SAG1B,EAAKiD,uBACP,EAAKkE,kBAAkBL,GACvB,EAAKM,gBAAgBN,GACrB,EAAKjD,SAAS,UAEd,EAAKhD,QAAQoG,kBAAkB,EAAKjH,SACpC,IAAAkH,wBAAuB,EAAKlH,QAEhC,EAEApsC,KAAK6f,QAAQ7U,sBAAsBs4B,UAAY,SAACnqB,EAAU1a,EAAOg1C,GAC/D,EAAKxD,SAASxxC,GACd,EAAKwzC,YAAY94B,GAEjB,EAAKizB,OAAS,EAAH,KACN,EAAKA,QACLqH,GAGS,YAAVh1C,GACF,EAAKw0C,sBAGP,EAAK/C,YACP,EAEAlwC,KAAK6f,QAAQ7U,sBAAsBo7B,cAAgB,SAAC1mC,GAClD,EAAKmgB,QAAQtO,qBAAqBmiC,qBAClC,EAAK7zB,QAAQtO,qBAAqBoiC,kBAE9B,EAAK9zB,QAAQtO,qBAAqBqiC,oCACpC,EAAK/zB,QAAQ7U,sBAAsBzK,MAAM,CACvCsS,KAAM,EAAAO,UAAUygC,kCAAkChhC,KAClDC,QAAS,EAAAM,UAAUygC,kCAAkC/gC,QACrDo4B,cAAe,EAAA93B,UAAUygC,kCAAkC3I,cAC3Dn4B,gBAAY5S,EACZ6S,KAAM,CAAC,EACPjQ,YAAarD,EAAMqD,eAKvB,EAAKktC,SAAS,iBACd,EAAKgC,YAAY,GACjB,EAAKpyB,QAAQ7U,sBAAsBi5B,yBAAyBvkC,GAC5D,EAAKmgB,QAAQ7U,sBAAsBw5B,2BAA2B9kC,GAC9D,EAAKmgB,QAAQ7U,sBAAsB2G,wBAAwBjS,GAE3D,EAAKwwC,aACP,EAEAlwC,KAAK6f,QAAQ7U,sBAAsB2G,wBAA0B,SAACjS,GACzC,UAAfA,EAAM+F,OACJ,IAAAid,UAAShjB,EAAM2R,WACjB,EAAK+6B,OAAO51B,aAAe9W,EAAM2R,UAE/B,IAAA6nB,eAAcx5B,EAAM4R,SACtB,EAAK86B,OAAO31B,WAAa/W,EAAM4R,QAET,UAAf5R,EAAM+F,QACX,IAAAid,UAAShjB,EAAM2R,WACjB,EAAK+6B,OAAO32B,aAAe/V,EAAM2R,UAE/B,IAAA6nB,eAAcx5B,EAAM4R,SACtB,EAAK86B,OAAO/1B,WAAa3W,EAAM4R,QAE7B,IAAAoR,UAAShjB,EAAMqS,UACjB,EAAKq6B,OAAOj2B,oBAAsBzW,EAAMqS,SAEtC,IAAA2Q,UAAShjB,EAAMoS,SACjB,EAAKs6B,OAAOh2B,mBAAqB1W,EAAMoS,OAG7C,EAEA9R,KAAK6f,QAAQ7U,sBAAsB8oC,oBAAsB,WACvD,EAAK5D,YACP,EAEAlwC,KAAK6f,QAAQ7U,sBAAsBi7B,MAAQ,SAAC9sB,EAAkB1a,GAC5D,EAAKwzC,YAAY94B,GACjB,EAAK82B,SAASxxC,GAEd,EAAK2tC,OAAO7b,OAASpX,EAErB,EAAK+2B,YACP,EAEAlwC,KAAK6f,QAAQ7U,sBAAsBi2B,QAAU,SAAC9nB,GAC5C,EAAK84B,YAAY94B,GACjB,EAAK82B,SAAS,WACd,EAAK7D,OAAO2H,OAAS56B,EACrB,EAAK+2B,YACP,EAEAlwC,KAAK6f,QAAQ7U,sBAAsB27B,UAAY,SAACxtB,EAAkB1a,GAChE,EAAKwzC,YAAY94B,GACjB,EAAK82B,SAASxxC,GAEd,EAAK2tC,OAAO7I,SAAWpqB,EAEvB,EAAK+2B,YACP,EAEAlwC,KAAK6f,QAAQ7U,sBAAsBi6B,iBAAmB,SAAC9rB,EAAU6L,GAC/D,EAAKirB,SAAS,WACd,EAAK7D,OAAOnH,kBAAmB,EAC/B,EAAKmH,OAAO4H,uBAAyBhvB,EACrC,EAAKonB,OAAOjzB,SAAWA,EAEnB6L,IAAW,EAAAyhB,uBAAuBwN,eAKlCjvB,IAAW,EAAAyhB,uBAAuByN,UACpC,EAAK9H,OAAO5N,UAAY,EAAAprB,UAAU+gC,8BAA8BthC,KAChE,EAAKu5B,OAAO3gB,aAAe,EAAArY,UAAU+gC,8BAA8BrhC,QACnE,EAAKs5B,OAAOlB,cAAgB,EAAA93B,UAAU+gC,8BAA8BjJ,cAEpE,EAAKiE,6BAA6B37B,SAAS,CACzCX,KAAM,EAAAO,UAAU+gC,8BAA8BthC,KAC9CC,QAAS,EAAAM,UAAU+gC,8BAA8BrhC,QACjDY,SAAU,EAAAN,UAAU+gC,8BAA8BjJ,iBAItD,EAAKgF,aACP,EAEAlwC,KAAK6f,QAAQ7U,sBAAsBzK,MAAQ,SAACb,G,MACpCa,EAAQ,EAAK0qC,eACjB,CAACp4B,KAAMnT,EAAMmT,KAAMC,QAASpT,EAAMoT,QAASY,SAA6B,QAAnB,EAAAhU,EAAMwrC,qBAAa,QAAI,YAC5ExrC,EAAMuT,gBAGJ1S,EAAMsS,MAAS,EAAKu8B,+BAA+BgF,kBAAkB7zC,EAAMsS,KAAMtS,EAAMmT,WAO3F,EAAKmM,QAAQ7U,sBAAsBi5B,yBAAyBvkC,GAC5D,EAAKmgB,QAAQ7U,sBAAsBw5B,2BAA2B9kC,GAE9D,EAAKuwC,SAAS,SACd,EAAKgC,YAAY,GACjB,EAAK7F,OAAO5N,UAAYj+B,EAAMsS,KAC9B,EAAKu5B,OAAO3gB,aAAelrB,EAAMuS,QACjC,EAAKs5B,OAAOlB,cAAgB3qC,EAAMmT,SAClC,EAAK04B,OAAOrzB,WAAY,IAAA5F,kBAAiBzT,EAAMqT,YAC/C,EAAKq5B,OAAOiI,cAAgB,EAAKx0B,QAAQnR,iBAAiB5P,KAAI,SAACgX,GAAM,OAAAA,EAAEzW,IAAF,IAEjE,EAAKwgB,QAAQ7Q,SACf,EAAK6Q,QAAQ7Q,UAGf,EAAKmgC,6BAA6B37B,SAAS,CACzCX,KAAMtS,EAAMsS,KACZC,QAASvS,EAAMuS,QACfY,SAAUnT,EAAMmT,SAChBqF,UAAWrZ,EAAMsT,OAGnB,EAAKk9B,cA5BH,EAAAloC,OAAO4X,IACL,gEAAyDrf,EAAMsS,KAAI,sDA4BzE,EAEA7S,KAAK6f,QAAQ7U,sBAAsBlH,GAAK,SAACqV,EAAkB1a,GACzD,EAAKwzC,YAAY94B,GACjB,EAAK82B,SAASxxC,GACd,EAAK2tC,OAAOtoC,GAAK,EAAAwwC,QAAQC,KACzB,EAAKrE,YACP,EAEAlwC,KAAK6f,QAAQ7U,sBAAsBk7B,KAAO,WACxC,EAAKkG,OAAOz+B,SAAU,CACxB,EAEA3N,KAAK6f,QAAQ7U,sBAAsBm7B,OAAS,WAC1C,EAAKiG,OAAOz+B,SAAU,CACxB,EAEA3N,KAAK6f,QAAQ7U,sBAAsBwpC,kBAAoB,WACrD,EAAKtE,YACP,EAEAlwC,KAAK6f,QAAQ7U,sBAAsBi5B,yBAA2B,SAACwQ,IAExD,IAAA/xB,UAAS+xB,aAAkB,EAAlBA,EAAoB1xC,cAIlC,EAAKywC,gBAAgBj2B,EAAM8vB,cAAcoH,EAAmB1xC,aAC9D,EAEA/C,KAAK6f,QAAQ7U,sBAAsBw5B,2BAA6B,SAACiQ,IAE1D,IAAA/xB,UAAS+xB,aAAkB,EAAlBA,EAAoB1xC,cAIlC,EAAKwwC,kBAAkBh2B,EAAM8vB,cAAcoH,EAAmB1xC,aAChE,EAEA/C,KAAK6f,QAAQ7U,sBAAsBm6B,mBAAqB,SAACzlC,GACvD,EAAKmgB,QAAQtT,0BACb,EAAK6/B,OAAS,EAAKwE,qBACnB,EAAKtB,oBAAsB,EAC3B,EAAKC,kBAAoB,EACzB,EAAK9lC,OAAS9I,OAAOC,KAAKlB,EAAM+J,QAAQlK,OAAS,EAAIG,EAAM+J,OAAS,EAAKA,OACzE,EAAKonC,MACP,EAEA7wC,KAAK6f,QAAQ7U,sBAAsBk9B,oBAAsB,SAACxoC,GACxD,EAAK+J,OAAS/J,EAAM+J,OACpB,EAAKnC,sBACL,EAAKC,kCACP,EAGAvH,KAAK6f,QAAQ7U,sBAAsBkiB,IAAM,WAGvC,EAAKkf,OAAS,EAAKwE,qBACnB,EAAKtB,oBAAsB,EAC3B,EAAKC,kBAAoB,EACzB,EAAKsB,MACP,EAEA7wC,KAAK6f,QAAQ7U,sBAAsB4J,QAAU,W,MAC3C,EAAKq4B,QAAU,IAAI,EAAAyH,YACH,QAAhB,IAAKzD,mBAAW,SAAEr8B,UAClB,EAAKiL,QAAQtO,qBAAqBojC,oBAClC,EAAKvF,+BAA+BrgC,OACtC,EAEA/O,KAAK6f,QAAQ7U,sBAAsBwoB,iBAAmB,SAACohB,EAAWC,EAAQ7jC,IACpE,IAAArL,cAAaqL,aAAS,EAATA,EAAWuiB,mBAC1B,EAAK8c,iBAAiBr/B,EAAUuiB,iBAEpC,CACF,EA6CA,YAAA0e,YAAA,SAAY94B,GACVnZ,KAAKosC,OAAOjzB,SAAWA,CACzB,EAEA,YAAA82B,SAAA,SAASxxC,GACPuB,KAAKosC,OAAO3tC,MAAQA,CACtB,EAEA,YAAAq2C,2BAAA,WACE,IAAMpoC,EAAO1M,KAAK6f,QAAQrT,yBACrBE,IAKL1M,KAAKosC,OAAOl/B,QAAS,IAAAvH,cAAa3F,KAAKyJ,OAAOyD,QAAUlN,KAAKyJ,OAAOyD,OAASR,EAAKQ,QAE9E,IAAAsB,WAAUxO,KAAKosC,OAAOl/B,UACxBlN,KAAKosC,OAAOl/B,QAAS,IAGnB,IAAAgsB,eAAcxsB,EAAKE,QACrB5M,KAAKosC,OAAOx/B,KAAOF,EAAKE,OAEtB,IAAAssB,eAAcxsB,EAAKO,cACrBjN,KAAKosC,OAAOn/B,WAAaP,EAAKO,aAE5B,IAAAyV,UAAShW,EAAKS,iBAChBnN,KAAKosC,OAAOj/B,cAAgBoQ,EAAM8vB,cAAc3gC,EAAKS,eAAiB,KAEpE,IAAA+rB,eAAcxsB,EAAKW,gBACrBrN,KAAKosC,OAAO/+B,aAAeX,EAAKW,eAE9B,IAAA6rB,eAAcxsB,EAAKuI,UACrBjV,KAAKosC,OAAOn3B,OAASvI,EAAKuI,SAExB,IAAAikB,eAAcxsB,EAAKyI,WACrBnV,KAAKosC,OAAOj3B,QAAUzI,EAAKyI,UAEzB,IAAA+jB,eAAcxsB,EAAK8I,WACrBxV,KAAKosC,OAAO52B,QAAU9I,EAAK8I,UAEzB,IAAAkN,UAAShW,EAAKa,oBAChBvN,KAAKosC,OAAO7+B,iBAAmBb,EAAKa,mBAElC,IAAAmV,UAAShW,EAAKe,qBAChBzN,KAAKosC,OAAO3+B,kBAAoBf,EAAKe,oBAEnC,IAAAiV,UAAShW,EAAKkmB,gBAChB5yB,KAAKosC,OAAOxZ,aAAelmB,EAAKkmB,eAE9B,IAAAlQ,UAAShW,EAAKmmB,eAChB7yB,KAAKosC,OAAOvZ,YAAcnmB,EAAKmmB,aAE7BtV,EAAMw3B,UAAUroC,EAAKiB,WACvB3N,KAAKosC,OAAOz+B,QAAUjB,EAAKiB,SAEzB4P,EAAMw3B,UAAUroC,EAAKkB,aACvB5N,KAAKosC,OAAOx+B,UAAYlB,EAAKkB,YAE3B,IAAAsrB,eAAcxsB,EAAKiK,YACrB3W,KAAKosC,OAAOz1B,SAAWjK,EAAKiK,WAE1B,IAAAuiB,eAAcxsB,EAAKqI,cAAgB/U,KAAKyJ,OAAOuL,QACjDhV,KAAKosC,OAAOr3B,WAAarI,EAAKqI,aAE5B,IAAAmkB,eAAcxsB,EAAK+J,cACrBzW,KAAKosC,OAAO31B,WAAa/J,EAAK+J,aAE5B,IAAAyiB,eAAcxsB,EAAK2J,cACrBrW,KAAKosC,OAAO/1B,WAAa3J,EAAK2J,aAE5B,IAAA6iB,eAAcxsB,EAAKmB,iBACrB7N,KAAKosC,OAAOv+B,cAAgBnB,EAAKmB,eAE/B0P,EAAMw3B,UAAUroC,EAAKsB,mBACvBhO,KAAKosC,OAAOp+B,gBAAkBtB,EAAKsB,kBAEjC,IAAAkrB,eAAcxsB,EAAKsJ,kBACrBhW,KAAKosC,OAAOp2B,iBAAmBtJ,EAAKsJ,iBAEpChW,KAAKosC,OAAOp2B,sBAAmB7V,GAE7B,IAAAuiB,UAAShW,EAAKuB,iBAChBjO,KAAKosC,OAAOn+B,cAAgBiJ,KAAKo2B,IAAI5gC,EAAKuB,cAAgBjO,KAAKsvC,oBAAqB,GACpFtvC,KAAKsvC,oBAAsB5iC,EAAKuB,eAEpC,EAEA,YAAAiiC,WAAA,SAAW8E,GAuBT,GAtBAh1C,KAAK80C,6BACL90C,KAAKosC,OAAOQ,KAAOrvB,EAAMZ,sBAGzB3c,KAAKosC,OAAO6I,kBAAoBj1C,KAAK6f,QAAQjR,uBAG7C5O,KAAK6f,QAAQ/Q,iCAEb9O,KAAK6f,QAAQ9Y,YAAYmuC,WAAWl1C,KAAKosC,QAIb,MAAxB4I,GACFh1C,KAAKqwC,iBAAiB2E,IAQpB,IAAAxmC,WAAUxO,KAAKosC,OAAO32B,eAAiBzV,KAAKosC,OAAO32B,cAAgB,EAAG,CACxE0/B,EAAuBn1C,KAAKosC,OAAQpsC,KAAK6f,QAAQrT,0BACjD,IAAM4oC,EAAa,EAAH,GAAOp1C,KAAKosC,QAC5BpsC,KAAKitC,QAAQoI,YAAYD,EAC3B,KAAO,CACCA,EAAa,EAAH,GAAOp1C,KAAKosC,QAC5BpsC,KAAKitC,QAAQoI,YAAYD,GACzBD,EAAuBn1C,KAAKosC,OAAQpsC,KAAK6f,QAAQrT,yBACnD,EAGA,IAAA8mC,wBAAuBtzC,KAAKosC,OAC9B,EAEA,YAAAzgC,2BAAA,SAA2BqH,G,MACzB,IAA0D,KAApC,QAAlB,EAAAhT,KAAKyJ,OAAOA,cAAM,eAAE6rC,+BAKxB,IAAI,IAAAC,6BAA4BviC,GAAhC,CACE,IAAMwiC,GAAe,IAAAC,uBAAsBz1C,KAAKosC,OAAQp5B,GAExDhT,KAAKitC,QAAQC,cAAcsI,EAE7B,MAEA,IAAI,IAAAE,8BAA6B1iC,GAAjC,CACQwiC,GAAe,IAAAG,wBAAuB31C,KAAKosC,OAAQp5B,GAEzDhT,KAAKitC,QAAQC,cAAcsI,EAE7B,MAEA,IAAI,IAAAI,2BAA0B5iC,GAA9B,CACEA,EAAK6iC,eAAiB71C,KAAKirC,eAAej4B,EAAK6iC,eAAgB7iC,EAAKC,eAEpE,IAAM6iC,GAAoB,IAAAC,qBAAoB/1C,KAAKosC,OAAQp5B,GAE3DhT,KAAKitC,QAAQC,cAAc4I,EAE7B,MACF,EAeQ,YAAA7C,oBAAR,WACE,GAAIjzC,KAAK6f,QAAQ/V,uBAAwB,CACvC,IAAMygC,EAAYvqC,KAAK6f,QAAQ/V,uBAAuBksC,WAAW,CAC/D7oB,MAAOntB,KAAKosC,OAAO+G,eACnBjmB,IAAKltB,KAAKosC,OAAOgH,eAEb6C,EAAiBj2C,KAAK6f,QAAQ/V,uBAAuBosC,0BAEtDC,OAAOtoB,MAAM0c,IAAe4L,OAAOtoB,MAAMooB,KAC5Cj2C,KAAKosC,OAAO7B,UAAYA,EACxBvqC,KAAKosC,OAAO6J,eAAiBA,EAEjC,CACF,EAEQ,YAAA1C,kBAAR,SAA0Bj5B,GACxBta,KAAKosC,OAAO+G,eAAiB74B,CAC/B,EAEQ,YAAAk5B,gBAAR,SAAwBl5B,GACtBta,KAAKosC,OAAOgH,aAAe94B,CAC7B,EAEA,YAAA2wB,eAAA,SAAe1qC,EAAuB0S,G,QAC9B4iC,EAAiB,CACrBhjC,KAAMtS,EAAMsS,KACZC,QAASvS,EAAMuS,QACfY,SAAUnT,EAAMmT,UAGlB,IACE,IAAMs3B,EAA+D,QAA5C,EAAkB,QAAlB,EAAAhrC,KAAKyJ,OAAOA,cAAM,eAAE2sC,gCAAwB,eAAEC,UAAUR,EAAgB,CAC/F5iC,cAAeA,IAGjB4iC,EAAehjC,MAAO,IAAA6P,UAASsoB,aAAgB,EAAhBA,EAAkBn4B,MAAQm4B,aAAgB,EAAhBA,EAAkBn4B,KAAOgjC,EAAehjC,KACjGgjC,EAAe/iC,SAAU,IAAAomB,eAAc8R,aAAgB,EAAhBA,EAAkBl4B,SACrDk4B,aAAgB,EAAhBA,EAAkBl4B,QAClB+iC,EAAe/iC,QACnB+iC,EAAeniC,UACb,IAAAwlB,eAAc8R,aAAgB,EAAhBA,EAAkBt3B,YAAa,IAAA4iC,iBAAgBtL,aAAgB,EAAhBA,EAAkBt3B,UAC3Es3B,EAAkBt3B,SAClBmiC,EAAeniC,QACvB,CAAE,MAAOnT,GACP,EAAAyH,OAAOzH,MAAM,oCAAqCA,EACpD,CAEA,OAAOs1C,CACT,EAEQ,YAAAjF,mBAAR,W,MACQruC,EAASvC,KAAKyJ,OAAOlH,QAAUvC,KAAK6f,QAAQ1V,gBAC5CosC,GAAmB,IAAA5jB,6BAEzB,MAAO,CACL7uB,GAAI,EACJyoC,iBAAkB,EAAA9uC,QAClB+Y,aAAc,EACd+sB,SAAU,EACV0S,eAAgB,EAChBhoC,cAAe,EACfkL,SAAU,EACVjM,OAA0B,QAAlB,EAAAlN,KAAKyJ,OAAOyD,cAAM,SAC1BwZ,UAAU,IAAA8vB,8BACVlE,aAAc,EACd5F,aAAcnvB,EAAMovB,kBACpBoG,MAAM,IAAAC,wBACNziB,OAAQ,EACR+b,SAAU,MACVnI,OAAQ,EACR5hC,OAAM,EACNgtC,kBAAmB,EACnBtiC,WAAYjN,KAAK6f,QAAQvV,gBACzBsoB,aAAc2jB,aAAgB,EAAhBA,EAAkBxkC,OAChC8gB,YAAa0jB,aAAgB,EAAhBA,EAAkBzkC,MAC/BiiC,OAAQ,EACRnnC,KAAM,EAAAG,WAAWC,OACjB2lC,YAAa,EACb/F,KAAM,EACN6J,WAAW,IAAAC,+BACX5zC,QAASP,EAAS,IAAMvC,KAAK6f,QAAQ3V,mBACrCuL,aAAc,EACdtI,cAAe,EACfgJ,oBAAqB,EACrBC,mBAAoB,EACpBs8B,iBAAkB,EAClBU,aAAc,EACdD,eAAgB,EAChB1lC,kBAAmB,EACnBF,iBAAkB,EAEtB,EAEO,EAAAlP,OAAP,SAAcoL,EAAyBoW,GAMrC,OAAO,IAAIhX,EACTY,EACAoW,EAPqC,IAAI,EAAA82B,eACO,IAAI,EAAApG,0BAA0B9mC,GACzD,IAAI,EAAAmtC,eACU,IAAI,EAAAz6B,gBACF,IAAI,EAAA06B,+BAU7C,EAh1BO,EAAA/zC,QAAkB,EAAArF,QAi1B3B,C,CAt1BA,GAy1BA,SAAgB03C,EAAuB/I,EAAgB1iB,IACjD,IAAAhH,UAASgH,EAAavT,uBACxBi2B,EAAOj2B,oBAAsBuT,EAAavT,sBAExC,IAAAuM,UAASgH,EAAatT,sBACxBg2B,EAAOh2B,mBAAqBsT,EAAatT,qBAEvC,IAAAsM,UAASgH,EAAajU,gBACxB22B,EAAO32B,aAAeiU,EAAajU,eAEjC,IAAAiN,UAASgH,EAAalT,gBACxB41B,EAAO51B,aAAekT,EAAalT,aAEvC,CAt2Ba,EAAA3N,UAAAA,C,6GCxDb,cACA,UAGA,UACA,UACA,SACA,UACA,UAcA,0BAwDA,QAvDE,YAAAwoC,cAAA,SACEpoC,EACA6tC,EACAj3B,EACA2vB,GAEA,IAAKxvC,KAAK+2C,UAAU9tC,GAClB,OAAO,IAAI,EAAAyrC,YAEb,IAAMsC,EAAQh3C,KAAKi3C,mBAAmBhuC,EAAiB6tC,EAAkBj3B,EAAS2vB,GAClF,OAAOxvC,KAAKk3C,6BAA6BjuC,EAAiB+tC,EAC5D,EAEQ,YAAAE,6BAAR,SAAqCztC,EAAyBwjC,GAC5D,OAAIxjC,EAAO0nC,MACF,IAAI,EAAAgG,iBAAiB1tC,EAAQwjC,GAE/BA,CACT,EAEQ,YAAAmK,yCAAR,SAAiDnuC,EAAkCouC,GACjF,YACsBl3C,IAApB8I,QAC2B9I,IAA3B8I,EAAgBQ,aACoDtJ,IAAnE8I,EAAgBQ,OAAmC6tC,YAE5CruC,EAAgBQ,OAAmC6tC,YAAYD,GAGlEA,CACT,EAEQ,YAAAN,UAAR,SAAkB9tC,GAChB,YAAkC9I,IAA3B8I,EAAgBQ,SAA2D,IAAnCR,EAAgBQ,OAAOsM,OACxE,EAEQ,YAAAkhC,mBAAR,SACEhuC,EACA6tC,EACAj3B,EACA2vB,GAEA,IAAM+H,EAActuC,EAAgBQ,QAAUR,EAAgBQ,OAAO8tC,YAAe,EAAAC,2BAChFH,EAAwB,IAAI,EAAAI,uBAC9BX,EACA,EAAAY,YACAH,EACA13B,EACA2vB,GAEF6H,EAAer3C,KAAKo3C,yCAAyCnuC,EAAiBouC,GAE9E,IAAMM,EAAiC,IAAI,EAAAC,sBAAsBP,GACjE,OAAO,IAAI,EAAAQ,6BAA6BF,EAC1C,EACF,EAxDA,GAAa,EAAAhB,eAAAA,C,+GCvBb,cAaA,aAIE,WAAYltC,EAAyBquC,GACnC93C,KAAK83C,WAAaA,EACdruC,EAAO0nC,OAAU1nC,EAAO0nC,MAA+B4G,SACzD/3C,KAAKg4C,YAAevuC,EAAO0nC,MAA+B4G,OAE9D,CAuBF,OArBE,YAAA1C,YAAA,SAAYjJ,GACVpsC,KAAKi4C,YAAY7L,GACjBpsC,KAAK83C,WAAWzC,YAAYjJ,EAC9B,EAEA,YAAAiH,kBAAA,SAAkBjH,GAChBpsC,KAAKi4C,YAAY7L,GACjBpsC,KAAK83C,WAAWzE,kBAAkBjH,EACpC,EAEA,YAAAc,cAAA,SAAchB,GACZlsC,KAAK83C,WAAW5K,cAAchB,EAChC,EAEQ,YAAA+L,YAAR,SAAoB7L,GAClB,GAAIpsC,KAAKg4C,aAAeh4C,KAAKg4C,YAAYz4C,OAAQ,CAC/C,IAAM,EAAS,CAAC,EAChBS,KAAKg4C,YAAYjoB,SAAQ,SAACmoB,GAAM,OAAC,EAAOA,GAAK9L,EAAO8L,EAApB,IAChC,EAAAlwC,OAAOmwC,MAAM,CAAC,GAChB,CACF,EACF,EAhCA,GAAa,EAAAhB,iBAAAA,C,iHCdb,cAEA,UAEA,aAGE,aACEn3C,KAAKo4C,SAAW,EAClB,CA2FF,OAzFE,YAAArpC,MAAA,WACE/O,KAAKo4C,SAAW,EAClB,EAEA,YAAAz6B,eAAA,SAAe0P,GACb,KAAIA,EAAY5Q,YAAc,KAA9B,CAGA,IAAM47B,EAAU,IAAI,EAAAC,QAAQjrB,GAEtBkrB,EAAY,EAAAC,UAAUC,YAAY,KACpCJ,EAAQK,OAASH,GAIrBv4C,KAAKo4C,SAAS54C,KAAK64C,EARnB,CASF,EAEA,YAAAxpC,QAAA,WACE,MAAO,CACLikB,sBAAuB9yB,KAAKo4C,SAAS74C,OACrCwzB,qBAAsB/yB,KAAKo4C,SAASt5C,KAAI,SAAC65C,GAAM,OAAAA,EAAE/rC,IAAF,IAAQgsC,OAAO54C,KAAKhB,IAAK,GACxEg0B,qBAAsB9b,KAAK2hC,KAAwB,IAAnB74C,KAAK84C,aACrC7lB,iBAAkBjzB,KAAK+4C,WACvB7lB,iBAAkBlzB,KAAKg5C,WACvB7lB,iBAAkBnzB,KAAKi5C,WACvB7lB,mBAAoBpzB,KAAKozB,qBAE7B,EAEQ,YAAAp0B,IAAR,SAAYk6C,EAAWC,GACrB,OAAOD,EAAIC,CACb,EAEQ,YAAAJ,SAAR,WACE,GAA6B,IAAzB/4C,KAAKo4C,SAAS74C,OAChB,OAAO,EAET,IAAM65C,EAAap5C,KAAKq5C,SAAST,QAAO,SAACM,EAAGC,GAC1C,OAAOD,EAAIC,CACb,GAAG,GACGG,EAAkBt5C,KAAKo4C,SAAS74C,OACtC,OAAOS,KAAKu5C,4BAA4BH,EAAaE,EACvD,EAEQ,YAAAC,4BAAR,SAAoCC,GAClC,OAAO,EAAAhB,UAAUiB,YAAYD,EAC/B,EAEQ,YAAAR,SAAR,WACE,OAA6B,IAAzBh5C,KAAKo4C,SAAS74C,OACT,EAEFS,KAAKu5C,4BAA4BriC,KAAKssB,IAAG,MAARtsB,KAAYlX,KAAKq5C,UAC3D,EAEQ,YAAAA,OAAR,WACE,OAAOr5C,KAAKo4C,SAASt5C,KAAI,SAAC65C,GACxB,OAAOA,EAAED,KACX,GACF,EAEQ,YAAAO,SAAR,WACE,OAA6B,IAAzBj5C,KAAKo4C,SAAS74C,OACT,EAEFS,KAAKu5C,4BAA4BriC,KAAKo2B,IAAG,MAARp2B,KAAYlX,KAAKq5C,UAC3D,EAEQ,YAAAP,UAAR,WACE,OAA6B,IAAzB94C,KAAKo4C,SAAS74C,OACT,EAEFS,KAAKo4C,SAASQ,QAAO,SAACM,EAAGC,GAC9B,OAAOD,EAAIC,EAAEhgC,QACf,GAAG,EACL,EAEQ,YAAAia,mBAAR,WACE,GAA6B,IAAzBpzB,KAAKo4C,SAAS74C,OAChB,OAAO,EAET,IAAMm6C,EACJ15C,KAAKo4C,SAASQ,QAAO,SAACM,EAAGC,GACvB,OAAOD,EAAwB,IAApBC,EAAEv8B,eACf,GAAG,GAAK5c,KAAKo4C,SAAS74C,OAExB,OAAO2X,KAAK2hC,KAAKa,EACnB,EACF,EAhGA,GAAa,EAAAjiC,mBAAAA,C,2GCCb,8BACU,KAAA5Y,UAAwC,EAyBlD,QAvBE,YAAAwd,UAAA,SAAUlE,GAAV,WAGE,OAFAnY,KAAKnB,UAAUW,KAAK2Y,GAEb,WAAM,SAAKmE,YAAYnE,EAAjB,CACf,EAEA,YAAA3E,SAAA,SAAShT,GACWR,KAAKnB,UAAUqD,MAAM,GAC7B6tB,SAAQ,SAAC5X,GACjBA,EAAS3X,EACX,GACF,EAEA,YAAA8b,YAAA,SAAYnE,GACV,IAAMwhC,EAAQ35C,KAAKnB,UAAUkB,QAAQoY,GACjCwhC,GAAS,GACX35C,KAAKnB,UAAU+6C,OAAOD,EAAO,EAEjC,EAEA,sBAAI,8BAAe,C,IAAnB,WACE,OAAO35C,KAAKnB,UAAUU,MACxB,E,gCACF,EA1BA,GAAa,EAAA4c,gBAAAA,C,6ICPA,EAAA09B,8BAAgC,MAY7C,iBAKE,WAAYruC,GACVxL,KAAKwL,qBAAuBA,CAC9B,CAuBF,OArBE,YAAAP,YAAA,SAAY6U,GACV9f,KAAK8f,SAAWA,CAClB,EAEA,YAAAwC,eAAA,2BACiCniB,IAA3BH,KAAK85C,mBACP95C,KAAK+5C,iBAEP/5C,KAAK85C,kBAAoBzW,aAAY,W,MACtB,QAAb,IAAKvjB,gBAAQ,SAAEgkB,YAAY,EAAKt4B,uBAClC,GAAG,EAAAquC,8BACL,EAEA,YAAAz4B,cAAA,WACEphB,KAAK+5C,gBACP,EAEQ,YAAAA,eAAR,WACEnrB,aAAa5uB,KAAK85C,mBAClB95C,KAAK85C,uBAAoB35C,CAC3B,EACF,EA9BA,GAAa,EAAAyK,iBAAAA,C,2HCLb,8BAMU,KAAAovC,mBAAqB,CA2B/B,QAjBE,YAAA5F,kBAAA,SAAkB5V,EAAmB0M,GACnC,OAAI1M,IAAcx+B,KAAKi6C,gBAAkB/O,IAAkBlrC,KAAKk6C,oBAC9Dl6C,KAAKg6C,qBACEh6C,KAAKg6C,oBAAsBnD,EAA+BsD,gCAGnEn6C,KAAKi6C,eAAiBzb,EACtBx+B,KAAKk6C,mBAAqBhP,EAC1BlrC,KAAKg6C,mBAAqB,GACnB,EACT,EAEA,YAAAjrC,MAAA,WACE/O,KAAKi6C,oBAAiB95C,EACtBH,KAAKk6C,wBAAqB/5C,EAC1BH,KAAKg6C,mBAAqB,CAC5B,EA9Be,EAAAG,8BAAgC,EA+BjD,C,CAjCA,GAAa,EAAAtD,+BAAAA,C,8VCJb,cAEA,UACA,UAGA,UACA,UACA,UAYA,aAME,WACEnqC,EACQ0tC,EACAC,EACAx6B,EACA2vB,GALV,WAEU,KAAA4K,YAAAA,EACA,KAAAC,eAAAA,EACA,KAAAx6B,QAAAA,EACA,KAAA2vB,uBAAAA,EAgEF,KAAA8K,mBAAqB,SAAC3J,GAC5B/hB,aAAa,EAAK2rB,iCAClB,EAAKC,yBACL,EAAK9tC,KAAKhE,IAAMioC,EAAUl8B,WAC1B,EAAKgmC,QAAU,EAAKC,oCAAoC,EAAKC,sBAAuB,EAAKnL,uBAC3F,EAEQ,KAAAoL,kBAAoB,WAC1BhsB,aAAa,EAAK2rB,iCAClB,EAAKC,yBACL,EAAKvN,QAAU,IAAI,EAAAyH,YACnB,EAAKlF,uBAAuBC,yBAAwB,OAAOtvC,EAC7D,EAEQ,KAAA06C,0BAA4B,WAClC,EAAKL,yBACL,EAAKvN,QAAU,IAAI,EAAAyH,YACnB,EAAKlF,uBAAuBC,yBAAwB,OAAOtvC,EAC7D,EAhFEH,KAAK0M,KAAO,EAAH,GAAOA,GAChB1M,KAAKitC,QAAU,IAAI,EAAA6N,aACnB96C,KAAKo6C,YAAcA,OAEFj6C,IAAbuM,EAAKhE,KAAkC,KAAbgE,EAAKhE,IACjC1I,KAAKy6C,QAAUz6C,KAAK06C,oCAAoC16C,KAAK26C,sBAAuB36C,KAAKwvC,yBACrC,IAA3C3vB,EAAQqxB,gCACjBrxB,EAAQrL,qBAAqB6H,UAAUrc,KAAKs6C,oBAC5Cz6B,EAAQtM,oBAAoB8I,UAAUrc,KAAK46C,mBAC3C56C,KAAKu6C,gCAAkC/pB,WAAWxwB,KAAK66C,0BAA2B,EAAAE,iCAElFvL,EAAuBC,yBAAwB,OAAOtvC,GACtDH,KAAKitC,QAAU,IAAI,EAAAyH,YAEvB,CAkFF,OAhFE,YAAAiG,oBAAA,sBACQ,EAAyB36C,KAAK0M,KAA7BhE,EAAG,MAAE8nC,EAAM,SAAE1tC,EAAO,UAC3B,IAAK4F,GAAe,KAARA,EAAY,CACtB,IAAMnI,EAA2B,CAC/BwsB,OAAQ,EAAAiuB,gBAAgBC,OACxBnoC,QAAS,2BAGX,OADA9S,KAAKitC,QAAU,IAAI,EAAAyH,YACZx2B,QAAQC,QAAQ5d,EACzB,CAEA,OAAOP,KAAKo6C,YAAY1xC,EAAK8nC,EAAQ1tC,EAAS9C,KAAKq6C,gBAChD3lB,MAAK,SAACC,GACL,GAAIA,EAAO5H,SAAW,EAAAiuB,gBAAgBE,QAKpC,MAAM,IAAIn9C,MAAM42B,EAAO7hB,SAJvB,IAAMqoC,EAAgB,IAAI,EAAAC,cAAc,EAAKf,eAAgB3xC,GAM/D,OALG,EAAKukC,QAAyBoO,QAAQF,GACvC,EAAKlO,QAAUkO,EAIVxmB,CACT,IACCC,OAAM,SAAC0mB,GAON,MANoB,oDAAhBA,EAAIxoC,QACN,EAAA9K,OAAOzH,MAAM,yDAA0D+6C,GAEvE,EAAAtzC,OAAOC,mBAAmB,yDAA0DqzC,GAEtF,EAAKrO,QAAU,IAAI,EAAAyH,YACZ,CACL3nB,OAAQ,EAAAiuB,gBAAgBC,OACxBnoC,QAASwoC,EAAIxoC,QAEjB,GACJ,EAEA,YAAAuiC,YAAA,SAAYjJ,GACVpsC,KAAKitC,QAAQoI,YAAYjJ,EAC3B,EACA,YAAAiH,kBAAA,SAAkBjH,GAChBpsC,KAAKitC,QAAQoG,kBAAkBjH,EACjC,EACA,YAAAc,cAAA,SAAchB,GACZlsC,KAAKitC,QAAQC,cAAchB,EAC7B,EAsBQ,YAAAsO,uBAAR,WACEx6C,KAAK6f,QAAQrL,qBAAqB8H,YAAYtc,KAAKs6C,oBACnDt6C,KAAK6f,QAAQtM,oBAAoB+I,YAAYtc,KAAK46C,kBACpD,EAEQ,YAAAF,oCAAR,SACED,EACAjL,GAEA,OAAOiL,EAAQ/lB,MAAK,SAACoH,GAEnB,OADA0T,EAAuBC,wBAAwB3T,EAAS/O,SAAW,EAAAiuB,gBAAgBE,QAASpf,EAASiV,UAC9FjV,CACT,GACF,EACF,EA7GA,GAAa,EAAA2b,uBAAAA,C,0HCrBb,cAaA,aAGE,WAAY8D,GACVv7C,KAAKw7C,YAAcD,CACrB,CAuBF,OArBE,YAAAlG,YAAA,SAAYjJ,GACNpsC,KAAKy7C,uBAAuBrP,IAGhCpsC,KAAKw7C,YAAYnG,YAAYjJ,EAC/B,EAEA,YAAAiH,kBAAA,SAAkBjH,GACZpsC,KAAKy7C,uBAAuBrP,IAGhCpsC,KAAKw7C,YAAYnI,kBAAkBjH,EACrC,EAEA,YAAAc,cAAA,SAAchB,GACZlsC,KAAKw7C,YAAYtO,cAAchB,EACjC,EAEQ,YAAAuP,uBAAR,SAA+BrP,GAC7B,QAAQ,IAAA59B,WAAU49B,EAAOjI,QAAU,EAAIiI,EAAOjI,SAAW,GAC3D,EACF,EA5BA,GAAa,EAAA0T,6BAAAA,C,oGCbb,iBAuBE,WAAY6D,GACV17C,KAAK07C,SAAWA,CAClB,CACF,OAvBE,sBAAI,oBAAK,C,IAAT,WACE,OAAO17C,KAAK07C,SAAS9uC,KAAO5M,KAAK07C,SAASviC,QAC5C,E,gCACA,sBAAI,uBAAQ,C,IAAZ,WACE,OAAOnZ,KAAK07C,SAASviC,QACvB,E,gCACA,sBAAI,mBAAI,C,IAAR,WACE,OAAOnZ,KAAK07C,SAAS9uC,IACvB,E,gCACA,sBAAI,8BAAe,C,IAAnB,WACE,OAAO5M,KAAK07C,SAAS9+B,eACvB,E,gCACA,sBAAI,wBAAS,C,IAAb,WACE,OAAO5c,KAAK07C,SAAS7vC,SACvB,E,gCAEA,sBAAI,yBAAU,C,IAAd,WACE,OAAO7L,KAAK07C,SAASj/B,UACvB,E,gCAKF,EA1BA,GAAa,EAAA67B,QAAAA,C,wGCab,8BAUA,QATE,YAAAjD,YAAA,SAAYsG,GAEZ,EACA,YAAAtI,kBAAA,SAAkBsI,GAElB,EACA,YAAAzO,cAAA,SAAc0O,GACZ,MAAM,IAAI79C,MAAM,0BAClB,EACF,EAVA,GAAa,EAAA22C,YAAAA,C,qFCfb,cACA,UAaA,aAcE,WAAYmH,QAAA,IAAAA,IAAAA,EAAsCpZ,EAASqZ,0CAZnD,KAAAC,mBAbY,EAkBZ,KAAAC,qBAlBY,EAoBZ,KAAAC,qBApBY,EAuBZ,KAAAC,oBAAqB,EAG3Bl8C,KAAKm8C,+BAAiCN,CACxC,CA6FF,OA3FE,YAAAvK,YAAA,WACEtxC,KAAK+7C,mBA9Ba,EA+BlB/7C,KAAK20C,oBAEL30C,KAAKg8C,qBAjCa,EAkClBh8C,KAAKi8C,qBAlCa,EAoClBj8C,KAAKk8C,oBAAqB,CAC5B,EAEA,YAAAvI,gBAAA,WACE3zC,KAAK+7C,oBACP,EAEA,YAAAnI,kCAAA,WACE,OAAO5zC,KAAK+7C,mBAAqB/7C,KAAKm8C,8BACxC,EAEA,YAAAtJ,sBAAA,SAAsBuJ,EAAyCC,GAC7Dr8C,KAAKk8C,oBAAqB,GAGtB,IAAAje,gBAAeme,KACjBp8C,KAAKg8C,qBAAuBI,IAG1B,IAAAne,gBAAeoe,KACjBr8C,KAAKi8C,qBAAuBI,EAEhC,EAEA,YAAArqC,8BAAA,SAA8BsqC,GAC5B,OAEEt8C,KAAKk8C,qBAEL,IAAAje,gBAAeqe,IAjEC,IAmEhBt8C,KAAKg8C,sBAELh8C,KAAKg8C,uBAAyBM,IAE7Bt8C,KAAK4zC,mCAEV,EAEA,YAAA1hC,gBAAA,SAAgBoqC,GACVt8C,KAAKk8C,qBACPl8C,KAAKg8C,qBAAuBM,EAEhC,EAEA,YAAA9qC,8BAAA,SAA8B8qC,GAC5B,OAEEt8C,KAAKk8C,qBAEL,IAAAje,gBAAeqe,IAtFC,IAwFhBt8C,KAAKi8C,sBAELj8C,KAAKi8C,uBAAyBK,IAE7Bt8C,KAAK4zC,mCAEV,EAEA,YAAAliC,gBAAA,SAAgB4qC,GACVt8C,KAAKk8C,qBACPl8C,KAAKi8C,qBAAuBK,EAEhC,EAEA,YAAA5I,mBAAA,2BACiDvzC,IAA3CH,KAAKu8C,oCAITv8C,KAAKu8C,kCAAoClZ,aAAY,WACnD,EAAK0Y,mBAAqB,CAC5B,GAAGtZ,EAAS+Z,+CACd,EAEA,YAAA7H,kBAAA,gBACiDx0C,IAA3CH,KAAKu8C,oCAIT9Y,cAAczjC,KAAKu8C,0CACZv8C,KAAKu8C,kCACd,EACF,EA7GA,G,oHCAA,8BACmB,KAAAE,MAAkB,GAClB,KAAAC,YAAwB,GACxB,KAAAC,QAAsB,EAuBzC,QArBE,YAAAtH,YAAA,SAAYjJ,GACVpsC,KAAKy8C,MAAMj9C,KAAK4sC,EAClB,EACA,YAAAiH,kBAAA,SAAkBjH,GAChBpsC,KAAK08C,YAAYl9C,KAAK4sC,EACxB,EACA,YAAAc,cAAA,SAAchB,GACZlsC,KAAK28C,QAAQn9C,KAAK0sC,EACpB,EAEA,YAAAmP,QAAA,SAAQpO,GACNjtC,KAAKy8C,MAAM1sB,SAAQ,SAAC9wB,GAClBguC,EAAQoI,YAAYp2C,EACtB,IACAe,KAAK08C,YAAY3sB,SAAQ,SAAC9wB,GACxBguC,EAAQoG,kBAAkBp0C,EAC5B,IACAe,KAAK28C,QAAQ5sB,SAAQ,SAAC9wB,GACpBguC,EAAQC,cAAcjuC,EACxB,GACF,EACF,EA1BA,GAAa,EAAA67C,aAAAA,C,4GCZb,cAUA,aAIE,WAAYT,EAAwB5lC,GAClCzU,KAAK48C,cAAgB,IAAI,EAAAC,cAAcxC,GACvCr6C,KAAKyU,WAAaA,CACpB,CAgBF,OAdE,YAAA4gC,YAAA,SAAYjJ,GACVA,EAAO1jC,IAAM1I,KAAKyU,WAClBzU,KAAK48C,cAAcvH,YAAYjJ,EACjC,EAEA,YAAAiH,kBAAA,SAAkBjH,GAChBA,EAAO1jC,IAAM1I,KAAKyU,WAClBzU,KAAK48C,cAAcvJ,kBAAkBjH,EACvC,EAEA,YAAAc,cAAA,SAAchB,GACZA,EAASxjC,IAAM1I,KAAKyU,WACpBzU,KAAK48C,cAAc1P,cAAchB,EACnC,EACF,EAvBA,GAAa,EAAAkP,cAAAA,C,2GCVb,iBAGE,aACEp7C,KAAK88C,SAAW,EAClB,CAiBF,OAfE,YAAA/tC,MAAA,WACE/O,KAAK88C,SAAW,EAClB,EAEA,YAAAr/B,WAAA,SAAWH,GACTtd,KAAK88C,SAASt9C,KAAK8d,EACrB,EAEA,YAAAF,cAAA,SAAc3B,GACZzb,KAAK88C,SAAW98C,KAAK88C,SAASr5B,QAAO,SAAC3N,GAAM,OAAAA,EAAE2F,MAAQA,CAAV,GAC9C,EAEA,YAAA9M,YAAA,WACE,OAAO3O,KAAK88C,QACd,EACF,EAtBA,GAAa,EAAAllC,eAAAA,C,oHCAb,cAaA,aAIE,WAAYkgC,GAFZ,KAAAiF,eAAiB,EAGf/8C,KAAKw7C,YAAc1D,CACrB,CAgCF,OA9BE,YAAAzC,YAAA,SAAYjJ,GACVpsC,KAAKg9C,0BAA0B5Q,GAC3BpsC,KAAKi9C,+BAA+B7Q,IAGxCpsC,KAAKw7C,YAAYnG,YAAYjJ,EAC/B,EAEA,YAAAiH,kBAAA,SAAkBjH,GAChBpsC,KAAKg9C,0BAA0B5Q,GAC3BpsC,KAAKi9C,+BAA+B7Q,IAGxCpsC,KAAKw7C,YAAYnI,kBAAkBjH,EACrC,EAEA,YAAAc,cAAA,SAAchB,GACRlsC,KAAKi9C,+BAA+B/Q,IAGxClsC,KAAKw7C,YAAYtO,cAAchB,EACjC,EAEQ,YAAA8Q,0BAAR,SAAkC5Q,GAChCA,EAAO2Q,eAAiB/8C,KAAK+8C,gBAC/B,EAEQ,YAAAE,+BAAR,SAAuC7Q,G,MACrC,OAA6B,QAArB,EAAAA,EAAO2Q,sBAAc,QAAI,GAAK,EAAAG,qBACxC,EACF,EAtCA,GAAa,EAAAtF,sBAAAA,C,8OCdb,cACA,UACA,UACA,UACA,UAEa,EAAAuF,oCAAsC,0BAEtC,EAAAC,uBAAyB,QAEtC,MAGE,SAAY3zC,GACV,IAAM4C,EAAkB5C,EAAOA,OAI/B,IAFgE,KAApC4C,aAAe,EAAfA,EAAiBgxC,gBAK3C,OAFA,IAAAC,cAAa,EAAAH,0CACbn9C,KAAKowC,QAAS,IAAAtD,iBAIhB,IAAMyQ,GAAiB,IAAAC,WAAU,EAAAL,qCACjCn9C,KAAKowC,QAAS,IAAAzqC,cAAa43C,MAAoB,IAAAh1B,SAAQg1B,GAAkBA,GAAiB,IAAAzQ,gBAE1F,IAAM2Q,GAAe,IAAAC,2BAA0BrxC,aAAe,EAAfA,EAAiBsxC,eAC1DC,GAAe,IAAAC,2BAA0BxxC,aAAe,EAAfA,EAAiByxC,eAG1DC,EAAYngC,KAAK6E,MAEjBu7B,EADiB,IAAIpgC,KAAKmgC,EAA2B,IAAfH,GACPK,eAErC,IAAAC,WAAU,EAAAf,oCAAqCn9C,KAAKowC,OAAQ,CAC1DI,OAAQiN,EACRU,QAASH,EACTI,OAAQR,GAEZ,EA9BW,EAAArN,0BAAAA,EAiCA,EAAAmN,0BAA4B,SAACpjC,GACxC,KAAI,IAAA9L,WAAU8L,KAIT,IAAA4e,eAAc5e,MAIf,IAAAiO,SAAQjO,GAIZ,OAAO+jC,mBAAmB/jC,EAC5B,EAEa,EAAAujC,0BAA4B,SAACvjC,GACxC,OAAI,IAAA9L,WAAU8L,GACL,EAAA8iC,wBAGJ,IAAA16B,UAASpI,GAIPA,EAHE,EAAA8iC,sBAIX,C,wHCpEA,cACA,UAMA,0BAyCA,QApCE,YAAAruC,MAAA,WACE/O,KAAKqN,kBAAelN,EACpBH,KAAKyW,gBAAatW,EAClBH,KAAKqW,gBAAalW,CACpB,EAEA,YAAAuP,gBAAA,SAAgBrC,GACdrN,KAAKqN,aAAeA,CACtB,EAEA,YAAAoB,kBAAA,SAAkBib,IACZ,IAAAnB,SAAQvoB,KAAKqN,gBAGjBqc,EAAarc,aAAerN,KAAKqN,aACnC,EAMA,YAAAyc,uBAAA,SAAuBJ,EAA4BE,IAC7C,IAAAjkB,cAAaikB,aAAS,EAATA,EAAWnT,cAC1BzW,KAAKyW,WAAamT,EAAUnT,aAE1B,IAAA9Q,cAAaikB,aAAS,EAATA,EAAWvT,cAC1BrW,KAAKqW,WAAauT,EAAUvT,aAGzB,IAAAkS,SAAQvoB,KAAKyW,cAChBiT,EAAajT,WAAazW,KAAKyW,aAE5B,IAAA8R,SAAQvoB,KAAKqW,cAChBqT,EAAarT,WAAarW,KAAKqW,WAEnC,EACF,EAzCA,GAAa,EAAA0B,0BAAAA,C,qFCRb,IAEKumC,EAFL,WAEA,SAAKA,GACH,mBACA,iCACA,uDACA,sDACD,CALD,CAAKA,IAAAA,EAAuB,KAO5B,8BACU,KAAAC,QAAsB,GACtB,KAAApxC,cAA+B,IA+GzC,QA7GE,YAAA4B,MAAA,WACE/O,KAAKu+C,QAAU,EACjB,EAMA,YAAA9uC,iBAAA,SAAiBtC,GACfnN,KAAKmN,cAAgC,IAAhBA,CACvB,EAOA,YAAA6oC,WAAA,SAAWuI,GACT,IAAI,IAAA/vC,WAAUxO,KAAKmN,eACjB,MAAM,IAAIpP,MAAM,gDAGlBiC,KAAKu+C,QAAQ/+C,KAAK++C,GAClB,IAAMC,EAAsBx+C,KAAKy+C,aAAaz+C,KAAKu+C,SACnD,OAAQv+C,KAAKwP,YAAY+uC,GAAWC,GAAuBx+C,KAAKmN,aAClE,EAKA,YAAA+oC,wBAAA,WACE,IAAI,IAAA1nC,WAAUxO,KAAKmN,eACjB,MAAM,IAAIpP,MAAM,gDAIlB,IADA,IAAIwgD,EAAU,EACE,MAAAv+C,KAAKu+C,QAAL,eAAc,CAAzB,IAAMG,EAAC,KACVH,GAAWv+C,KAAKwP,YAAYkvC,EAC9B,CACA,OAAOH,EAAUv+C,KAAKmN,aACxB,EAQQ,YAAAsxC,aAAR,SAAqBF,GACnB,IAAK,IAAIlZ,EAAI,EAAGA,EAAIkZ,EAAQh/C,OAAQ8lC,IAElC,IADA,IAAMsZ,EAAQJ,EAAQlZ,GACbuZ,EAAIvZ,EAAI,EAAGuZ,EAAIL,EAAQh/C,OAAQq/C,IAAK,CAC3C,IAAMC,EAAQN,EAAQK,GAClBJ,EAAsB,EACpBM,EAAc9+C,KAAK++C,mBAAmBJ,EAAOE,GAYnD,GAVIC,IAAgBR,EAAwBU,aAC1Ch/C,KAAKi/C,gBAAgBN,EAAOtZ,EAAGwZ,EAAOD,GACtCJ,EAAsBx+C,KAAKk/C,uBAAuBP,EAAOE,IAChDC,IAAgBR,EAAwBa,wBACjDn/C,KAAKu+C,QAAQ3E,OAAOvU,EAAG,GACvBmZ,EAAsBx+C,KAAKwP,YAAYmvC,IAC9BG,IAAgBR,EAAwBc,yBACjDp/C,KAAKu+C,QAAQ3E,OAAOgF,EAAG,GACvBJ,EAAsBx+C,KAAKwP,YAAYqvC,IAErCC,IAAgBR,EAAwBe,KAC1C,OAAOb,EAAsBx+C,KAAKy+C,aAAaz+C,KAAKu+C,QAExD,CAEF,OAAO,CACT,EAEQ,YAAAQ,mBAAR,SAA2B3xB,EAAiBkyB,GAC1C,OACGt/C,KAAKu/C,mBAAmBnyB,EAAMF,IAAKoyB,IAAWlyB,EAAMD,MAAQmyB,EAAOnyB,OACnEntB,KAAKu/C,mBAAmBnyB,EAAMD,MAAOmyB,IAAWlyB,EAAMF,IAAMoyB,EAAOpyB,IAE7DoxB,EAAwBU,YACtBh/C,KAAKu/C,mBAAmBnyB,EAAMD,MAAOmyB,IAAWt/C,KAAKu/C,mBAAmBnyB,EAAMF,IAAKoyB,GACrFhB,EAAwBa,uBACtBn/C,KAAKu/C,mBAAmBD,EAAOnyB,MAAOC,IAAUptB,KAAKu/C,mBAAmBD,EAAOpyB,IAAKE,GACtFkxB,EAAwBc,uBAE1Bd,EAAwBe,IACjC,EAEQ,YAAAE,mBAAR,SAA2BC,EAAgBC,GACzC,OAAOD,GAAUC,EAAStyB,OAASqyB,EAASC,EAASvyB,GACvD,EAEQ,YAAA+xB,gBAAR,SAAwB7xB,EAAiBsyB,EAAoBJ,EAAkBK,GAC7E,IAAMzyB,EAAME,EAAMF,IAAMoyB,EAAOpyB,IAAME,EAAMF,IAAMoyB,EAAOpyB,IAElD0yB,EAA+B,CAACzyB,MADxBC,EAAMD,MAAQmyB,EAAOnyB,MAAQC,EAAMD,MAAQmyB,EAAOnyB,MACnBD,IAAG,GAChDltB,KAAKu+C,QAAQ3E,OAAO8F,EAAY,EAAGE,GACnC5/C,KAAKu+C,QAAQ3E,OAAO+F,EAAa,EACnC,EAEQ,YAAAT,uBAAR,SAA+B9xB,EAAiBkyB,GAG9C,OAFYlyB,EAAMF,IAAMoyB,EAAOpyB,IAAME,EAAMF,IAAMoyB,EAAOpyB,MAC1CE,EAAMD,OAASmyB,EAAOnyB,MAAQC,EAAMD,MAAQmyB,EAAOnyB,MAEnE,EAEQ,YAAA3d,YAAR,SAAoB+uC,GAClB,OAAOrnC,KAAKC,IAAIonC,EAAQrxB,IAAMqxB,EAAQpxB,MACxC,EACF,EAjHA,G,8VCTA,IAqBK0yB,EArBL,UACA,UAEA,UAEA,UACA,UAGA,WAYA,SAAKA,GACH,2CACA,uBACA,kBACD,CAJD,CAAKA,IAAAA,EAAS,KAQd,IAEA,0BAEU,KAAAC,kBAA6C3/C,EAG7C,KAAA4/C,SAPqB,EASrB,KAAAthD,MAAmBohD,EAAUG,KAC7B,KAAAC,mBAAoB,EAepB,KAAAC,gBAAoC,GAMpC,KAAAC,WAAqB,CAmN/B,QA1ME,YAAA50C,SAAA,SAASu0C,GACP9/C,KAAK8/C,aAAeA,CACtB,EAEA,YAAAx5C,aAAA,SAAaC,GACN65C,EAAYpgD,KAAK8/C,eAKlB9/C,KAAKvB,OAASohD,EAAUG,OAI5BhgD,KAAKvB,MAAQohD,EAAUQ,iBACvBrgD,KAAKsgD,kBAAoB,EAAH,GACjB/5C,GAEP,EAEA,YAAAS,QAAA,SAAQC,G,MACN,GAAKm5C,EAAYpgD,KAAK8/C,eAKlB9/C,KAAKvB,OAASohD,EAAUG,KAA5B,CAIA,IAAMn0C,GAAY,IAAI+R,MAAO+c,UACvB7uB,EAAoB9L,KAAK8/C,aAAat0C,uBAK5CxL,KAAK8/C,aAAal0C,0BAA0BC,EAAWC,GAEvD9L,KAAKvB,MAAQohD,EAAUU,OAEvBvgD,KAAKigD,mBAAoB,EACzBjgD,KAAK+/C,UAEL//C,KAAKwgD,cAELxgD,KAAKsgD,kBAAoB,CACvBtkC,WAAkC,QAAtB,EAAAhc,KAAKsgD,yBAAiB,eAAEtkC,WACpChC,KAAM/S,aAAU,EAAVA,EAAY+S,KAClBN,SAAUzS,aAAU,EAAVA,EAAYyS,SACtB+mC,WAAYx5C,aAAU,EAAVA,EAAYw5C,YAG1BzgD,KAAK0gD,uBAAwB,IAAA5T,gBAC7B9sC,KAAK2gD,oBAAqB,IAAAC,oCAG1B5gD,KAAK8/C,aAAar0C,4BAA4B,CAC5ChG,KAAM,UACNs6C,QAAS//C,KAAK+/C,QACdW,sBAAuB1gD,KAAK0gD,sBAC5BJ,mBAAmB,IAAA36C,cAAa3F,KAAKsgD,mBAAqBtgD,KAAKsgD,kBAAoB,CAAC,GAhCtF,CAkCF,EAEA,YAAA94C,mBAAA,SAAmBC,EAA4BC,GACxC04C,EAAYpgD,KAAK8/C,eAKlB9/C,KAAKvB,OAASohD,EAAUU,SAIxBvgD,KAAKkgD,gBAAgBjjC,SAASxV,KAKlCzH,KAAK8/C,aAAar0C,4BAA4B,CAC5ChG,KAAM,WACNs6C,QAAS//C,KAAK+/C,QACdW,sBAAuB1gD,KAAK0gD,sBAC5BJ,mBAAmB,IAAA36C,cAAa3F,KAAKsgD,mBAAqBtgD,KAAKsgD,kBAAoB,CAAC,EACpF17C,SAAU6C,EACVo5C,iBAAkBn5C,EAClBo5C,wBAAwB,IAAAC,gCAA+B/gD,KAAK2gD,sBAE9D3gD,KAAKkgD,gBAAgB1gD,KAAKiI,IAC5B,EAEA,YAAAK,WAAA,WACE,GAAKs4C,EAAYpgD,KAAK8/C,eAKlB9/C,KAAKvB,OAASohD,EAAUG,KAA5B,CAIA,GAAIhgD,KAAKvB,OAASohD,EAAUU,OAAQ,CAClC,IAAM10C,GAAY,IAAI+R,MAAO+c,UACvB7uB,EAAoB9L,KAAK8/C,aAAat0C,uBAC5CxL,KAAK8/C,aAAal0C,0BAA0BC,EAAWC,EACzD,CAEA9L,KAAKghD,kBARL,CASF,EAEA,YAAA9L,WAAA,SAAW9I,G,YACT,GAAKgU,EAAYpgD,KAAK8/C,eAKlB9/C,KAAKvB,OAASohD,EAAUU,OAA5B,CAIAnU,EAAOtoC,GAAK,EAAAwwC,QAAQ2M,KACpB7U,EAAOpyB,KAA6B,QAAtB,EAAAha,KAAKsgD,yBAAiB,eAAEtmC,KACtCoyB,EAAO1yB,SAAiC,QAAtB,EAAA1Z,KAAKsgD,yBAAiB,eAAE5mC,SAC1C0yB,EAAOpwB,WAAmC,QAAtB,EAAAhc,KAAKsgD,yBAAiB,eAAEtkC,WAGxChc,KAAKigD,oBACP7T,EAAO2T,QAAU//C,KAAK+/C,QACtB//C,KAAKigD,mBAAoB,GAG3B,IAAMQ,EAAmC,QAAtB,EAAAzgD,KAAKsgD,yBAAiB,eAAEG,YACvC,IAAA96C,cAAa86C,IACf,EAAAS,qBAAqBnxB,SAAQ,SAACrnB,GACxB+3C,EAAW/3C,KACb0jC,EAAO1jC,GAAO+3C,EAAW/3C,GAE7B,IAGF0jC,EAAO,EAAA/H,6BAA8B,CAtBrC,CAuBF,EAEA,YAAA5wB,4BAAA,SAA4BlT,EAAuB0S,GAC5CmtC,EAAYpgD,KAAK8/C,eAKlB9/C,KAAKvB,QAAUohD,EAAUU,SAKzBvgD,KAAKmgD,WAOL5/C,EAAMsS,OAAS,EAAAO,UAAUygC,kCAAkChhC,OAI/D7S,KAAK8/C,aAAar0C,4BAA4B,CAC5ChG,KAAM,QACNs6C,QAAS//C,KAAK+/C,QACdW,sBAAuB1gD,KAAK0gD,sBAC5BJ,mBAAmB,IAAA36C,cAAa3F,KAAKsgD,mBAAqBtgD,KAAKsgD,kBAAoB,CAAC,EACpFzK,eAAgBt1C,EAChB0S,cAAeA,EACf6tC,wBAAwB,IAAAC,gCAA+B/gD,KAAK2gD,sBAE9D3gD,KAAKmgD,WAAY,GACnB,EAEA,YAAAtsB,gBAAA,WACE,OAAO7zB,KAAKvB,QAAUohD,EAAUU,MAClC,EAEA,YAAAh0C,wBAAA,WACEvM,KAAKghD,mBACLhhD,KAAK+/C,SA/NsB,CAgO7B,EAEQ,YAAAiB,iBAAR,WACEhhD,KAAKvB,MAAQohD,EAAUG,KACvBhgD,KAAKigD,mBAAoB,SAClBjgD,KAAKsgD,kBACZtgD,KAAKwgD,aACP,EAEQ,YAAAA,YAAR,W,UAC+B,QAAtB,EAAAxgD,KAAKsgD,yBAAiB,gBAAEG,WACF,QAAtB,EAAAzgD,KAAKsgD,yBAAiB,gBAAEtmC,KACF,QAAtB,EAAAha,KAAKsgD,yBAAiB,gBAAE5mC,SAC/B1Z,KAAKmgD,WAAY,EACjBngD,KAAK0gD,2BAAwBvgD,EAC7BH,KAAKkgD,gBAAkB,GACvBlgD,KAAK2gD,wBAAqBxgD,CAC5B,EACF,EAhPA,GAkPA,SAASigD,EAAYN,GACnB,OAAO,IAAAn6C,cAAam6C,EACtB,CApPa,EAAAztB,YAAAA,C,qFCpBb,iBAMA,gDACEvW,GAGA,IAAI,IAAAtN,WAAUsN,GAAW,OAAO,EAGhC,KAAK,IAAAqlC,eAAcrlC,GAEjB,OADA,EAAA9T,OAAOC,mBAAmB,oDACnB,EAGT,IAAM8T,EAA2BD,EAGjC,IAAI,IAAAnW,cAAaoW,EAAyBC,cAAgBolC,EAAarlC,EAAyBC,YAE9F,OADA,EAAAhU,OAAOC,mBAAmB,oEACnB,EAGT,OAAO,CACT,EAYA,6CACE1B,GAGA,IAAI,IAAAiI,WAAUjI,GAEZ,OAIF,MAAO,CACLyV,WAAYzV,EAAgByV,WAEhC,EAGA,2CAAgDF,GAE9C,IAAI,IAAAtN,WAAUsN,GACZ,OAAO,EAIT,KAAK,IAAAqlC,eAAcrlC,GAEjB,OADA,EAAA9T,OAAOC,mBAAmB,+CACnB,EAGT,IAAMo5C,EAAsBvlC,EAG5B,IAAI,IAAAnW,cAAa07C,EAAoBrnC,SAAU,IAAAkf,eAAcmoB,EAAoBrnC,MAE/E,OADA,EAAAhS,OAAOC,mBAAmB,0DACnB,EAIT,IAAI,IAAAtC,cAAa07C,EAAoB3nC,aAAc,IAAAwf,eAAcmoB,EAAoB3nC,UAEnF,OADA,EAAA1R,OAAOC,mBAAmB,8DACnB,EAIT,IAAI,IAAAtC,cAAa07C,EAAoBZ,eAAgB,IAAAU,eAAcE,EAAoBZ,YAErF,OADA,EAAAz4C,OAAOC,mBAAmB,wEACnB,EAGT,OAAO,CACT,EAYA,wCAA6Cq5C,GAE3C,IAAI,IAAA9yC,WAAU8yC,GAEZ,OAGF,IAAIC,OAA0DphD,GAC1D,IAAAwF,cAAa27C,EAAeb,cAC9Bc,GAA4B,IAAAC,0BAAyBF,EAAeb,aAItE,MAAO,CACLzmC,KAAMsnC,EAAetnC,KACrBN,SAAU4nC,EAAe5nC,SACzB+mC,WAAYc,EAEhB,EAEA,qBAKA,2CAAgDzlC,GAC9C,IAAK2lC,EAAiB3lC,GAEpB,OADA,EAAA9T,OAAOC,mBAAmB,2BACnB,EAGT,OAAO,CACT,EAeA,0CAA+C6T,GAC7C,IAAI,IAAAtN,WAAUsN,GAGZ,MAAO,CAAC,EAGV,KAAK,IAAAqlC,eAAcrlC,GAGjB,OADA,EAAA9T,OAAOC,mBAAmB,sDACnB,CAAC,EAGV,IAGMy5C,EAAiD,CACrDC,gBAJkC7lC,EAIW6lC,kBAG1C,IAAAzoB,eAAcwoB,EAAuBC,iBAIxCD,EAAuBC,gBAAkBD,EAAuBC,gBAAgB1wB,UAAU,EAAG,MAH7F,EAAAjpB,OAAOC,mBAAmB,4EAC1By5C,EAAuBC,qBAAkBxhD,GAK3C,OAAOuhD,CACT,EApLA,cACA,UACA,UACA,UAEA,SAAgBN,EAAatlC,GAE3B,MAAoB,YAAbA,GAAuC,YAAbA,GAAuC,aAAbA,CAC7D,CAqHA,SAAgB2lC,EAAiB3lC,GAC/B,MAAoB,UAAbA,GAAqC,aAAbA,GAAwC,UAAbA,GAAqC,cAAbA,CACpF,C,mFCnHA,qCAA0C9I,GACxC,MAAqB,UAAdA,EAAKvN,IACd,EASA,wCAA6CuN,GAC3C,MAAqB,aAAdA,EAAKvN,IACd,EAIA,uCAA4CuN,GAC1C,MAAqB,YAAdA,EAAKvN,IACd,C,qZCPA,+BAAoC2mC,GAClC,GAAIA,EAAO,EAAA/H,4BAET,cADO+H,EAAO,EAAA/H,6BACP,EACF,GAAoC,IAA/B+H,EAAoBwV,OAC9B,OAAO,EAGT,OAAO,CACT,EAUA,kCAAuCnmC,GACrC,MAAO,UAAGA,EAAG,YAAI,EAAAomC,kBAAiB,YAAI,EAAAC,6BACxC,EAuIA,+BACEC,EACAC,GAEA,OAAO7V,EAAc,CACnB4V,eAAc,EACdrB,sBAAuBsB,EAAwBtB,sBAC/CX,QAASiC,EAAwBjC,QACjCO,kBAAmB0B,EAAwB1B,kBAC3C17C,cAAUzE,EACV0gD,sBAAkB1gD,EAClBq+B,UAAWwjB,EAAwBnM,eAAehjC,KAClD4Y,aAAcu2B,EAAwBnM,eAAe/iC,QACrDo4B,cAAe8W,EAAwBnM,eAAeniC,SACtDotC,uBAAwBkB,EAAwBlB,wBAEpD,EAEA,iCACEiB,EACAE,GAEA,OAAO9V,EAAc,CACnB4V,eAAc,EACdrB,sBAAuBuB,EAA0BvB,sBACjDX,QAASkC,EAA0BlC,QACnCO,kBAAmB2B,EAA0B3B,kBAC7C17C,SAAU,UACVi8C,sBAAkB1gD,EAClBq+B,eAAWr+B,EACXsrB,kBAActrB,EACd+qC,mBAAe/qC,EACf2gD,4BAAwB3gD,GAE5B,EAEA,kCACE4hD,EACAG,GAEA,OAAO/V,EAAc,CACnB4V,eAAc,EACdrB,sBAAuBwB,EAA2BxB,sBAClDX,QAASmC,EAA2BnC,QACpCO,kBAAmB4B,EAA2B5B,kBAC9C17C,SAAUs9C,EAA2Bt9C,SACrCi8C,iBAAkBqB,EAA2BrB,iBAC7CC,uBAAwBoB,EAA2BpB,uBACnDtiB,eAAWr+B,EACXsrB,kBAActrB,EACd+qC,mBAAe/qC,GAEnB,EAoFA,qCAUA,0CAA+CgiD,GAC7C,IAAI,IAAA3zC,WAAU2zC,GACZ,OAGF,OAAOvB,IAAqCuB,CAC9C,EAhVA,cAEA,UACA,UA2OA,SAAShW,EAAc,G,IA3LWC,EA4LhC2V,EAAc,iBACdrB,EAAqB,wBACrBX,EAAO,UACPO,EAAiB,oBACjB17C,EAAQ,WACRi8C,EAAgB,mBAChBriB,EAAS,YACT/S,EAAY,eACZyf,EAAa,gBACb4V,EAAsB,yBAahBsB,EAAkB,OAjNjB,CACL5rC,aAAc41B,OAFgBA,EAmNF2V,QAjNR,EAAN3V,EAAQ51B,aACtB+1B,iBAAkBH,aAAM,EAANA,EAAQG,iBAC1BkC,iBAAkBrC,aAAM,EAANA,EAAQj2B,oBAC1Bu4B,gBAAiBtC,aAAM,EAANA,EAAQh2B,mBACzBq7B,YAAarF,aAAM,EAANA,EAAQqF,YACrB4Q,YAAajW,aAAM,EAANA,EAAQiW,YACrBC,YAAalW,aAAM,EAANA,EAAQkW,YACrBC,YAAanW,aAAM,EAANA,EAAQmW,YACrBC,YAAapW,aAAM,EAANA,EAAQoW,YACrBC,YAAarW,aAAM,EAANA,EAAQqW,YACrBC,YAAatW,aAAM,EAANA,EAAQsW,YACrBC,YAAavW,aAAM,EAANA,EAAQuW,YACrBC,YAAaxW,aAAM,EAANA,EAAQwW,YACrBC,YAAazW,aAAM,EAANA,EAAQyW,YACrBC,aAAc1W,aAAM,EAANA,EAAQ0W,aACtBC,aAAc3W,aAAM,EAANA,EAAQ2W,aACtBC,aAAc5W,aAAM,EAANA,EAAQ4W,aACtBC,aAAc7W,aAAM,EAANA,EAAQ6W,aACtBC,aAAc9W,aAAM,EAANA,EAAQ8W,aACtBC,aAAc/W,aAAM,EAANA,EAAQ+W,aACtBC,aAAchX,aAAM,EAANA,EAAQgX,aACtBC,aAAcjX,aAAM,EAANA,EAAQiX,aACtBC,aAAclX,aAAM,EAANA,EAAQkX,aACtBC,aAAcnX,aAAM,EAANA,EAAQmX,aACtBC,aAAcpX,aAAM,EAANA,EAAQoX,aACtBC,aAAcrX,aAAM,EAANA,EAAQqX,aACtBC,aAActX,aAAM,EAANA,EAAQsX,aACtBC,aAAcvX,aAAM,EAANA,EAAQuX,aACtBC,aAAcxX,aAAM,EAANA,EAAQwX,aACtBC,aAAczX,aAAM,EAANA,EAAQyX,aACtBC,aAAc1X,aAAM,EAANA,EAAQ0X,aACtBC,aAAc3X,aAAM,EAANA,EAAQ2X,aACtBC,aAAc5X,aAAM,EAANA,EAAQ4X,aACtBC,aAAc7X,aAAM,EAANA,EAAQ6X,aACtBC,aAAc9X,aAAM,EAANA,EAAQ8X,aACtBC,aAAc/X,aAAM,EAANA,EAAQ+X,aACtBC,aAAchY,aAAM,EAANA,EAAQgY,aACtBC,aAAcjY,aAAM,EAANA,EAAQiY,aACtBC,aAAclY,aAAM,EAANA,EAAQkY,aACtBC,aAAcnY,aAAM,EAANA,EAAQmY,aACtBC,aAAcpY,aAAM,EAANA,EAAQoY,aACtBC,aAAcrY,aAAM,EAANA,EAAQqY,aACtBC,aAActY,aAAM,EAANA,EAAQsY,aACtBC,aAAcvY,aAAM,EAANA,EAAQuY,aACtBC,aAAcxY,aAAM,EAANA,EAAQwY,aACtBC,aAAczY,aAAM,EAANA,EAAQyY,aACtBC,aAAc1Y,aAAM,EAANA,EAAQ0Y,aACtBC,aAAc3Y,aAAM,EAANA,EAAQ2Y,aACtBC,aAAc5Y,aAAM,EAANA,EAAQ4Y,aACtBC,aAAc7Y,aAAM,EAANA,EAAQ6Y,aACtBC,aAAc9Y,aAAM,EAANA,EAAQ8Y,aACtBC,aAAc/Y,aAAM,EAANA,EAAQ+Y,aACtBC,aAAchZ,aAAM,EAANA,EAAQgZ,aACtBC,aAAcjZ,aAAM,EAANA,EAAQiZ,aACtBC,aAAclZ,aAAM,EAANA,EAAQkZ,aACtBC,aAAcnZ,aAAM,EAANA,EAAQmZ,aACtBC,aAAcpZ,aAAM,EAANA,EAAQoZ,aACtBC,aAAcrZ,aAAM,EAANA,EAAQqZ,aACtBC,aAActZ,aAAM,EAANA,EAAQsZ,aACtBC,aAAcvZ,aAAM,EAANA,EAAQuZ,aACtBC,aAAcxZ,aAAM,EAANA,EAAQwZ,aACtBC,aAAczZ,aAAM,EAANA,EAAQyZ,aACtBC,aAAc1Z,aAAM,EAANA,EAAQ0Z,aACtBC,aAAc3Z,aAAM,EAANA,EAAQ2Z,aACtBC,aAAc5Z,aAAM,EAANA,EAAQ4Z,aACtBC,aAAc7Z,aAAM,EAANA,EAAQ6Z,aACtBC,aAAc9Z,aAAM,EAANA,EAAQ8Z,aACtBC,aAAc/Z,aAAM,EAANA,EAAQ+Z,aACtBC,aAAcha,aAAM,EAANA,EAAQga,aACtBC,aAAcja,aAAM,EAANA,EAAQia,aACtBC,aAAcla,aAAM,EAANA,EAAQka,aACtBC,aAAcna,aAAM,EAANA,EAAQma,aACtBC,aAAcpa,aAAM,EAANA,EAAQoa,aACtBC,aAAcra,aAAM,EAANA,EAAQqa,aACtBC,aAActa,aAAM,EAANA,EAAQsa,aACtBC,aAAcva,aAAM,EAANA,EAAQua,aACtBC,aAAcxa,aAAM,EAANA,EAAQwa,aACtBC,aAAcza,aAAM,EAANA,EAAQya,aACtBC,aAAc1a,aAAM,EAANA,EAAQ0a,aACtBC,aAAc3a,aAAM,EAANA,EAAQ2a,aACtBC,aAAc5a,aAAM,EAANA,EAAQ4a,aACtBC,aAAc7a,aAAM,EAANA,EAAQ6a,aACtBC,aAAc9a,aAAM,EAANA,EAAQ8a,aACtBC,aAAc/a,aAAM,EAANA,EAAQ+a,aACtBC,aAAchb,aAAM,EAANA,EAAQgb,aACtBC,aAAcjb,aAAM,EAANA,EAAQib,aACtBC,aAAclb,aAAM,EAANA,EAAQkb,aACtBC,aAAcnb,aAAM,EAANA,EAAQmb,aACtBC,aAAcpb,aAAM,EAANA,EAAQob,aACtBC,aAAcrb,aAAM,EAANA,EAAQqb,aACtBC,aAActb,aAAM,EAANA,EAAQsb,aACtBC,aAAcvb,aAAM,EAANA,EAAQub,aACtBC,aAAcxb,aAAM,EAANA,EAAQwb,aACtBC,aAAczb,aAAM,EAANA,EAAQyb,aACtBC,aAAc1b,aAAM,EAANA,EAAQ0b,aACtBC,aAAc3b,aAAM,EAANA,EAAQ2b,aACtBC,aAAc5b,aAAM,EAANA,EAAQ4b,aACtBC,aAAc7b,aAAM,EAANA,EAAQ6b,aACtBC,aAAc9b,aAAM,EAANA,EAAQ8b,aACtBC,aAAc/b,aAAM,EAANA,EAAQ+b,aACtBC,aAAchc,aAAM,EAANA,EAAQgc,aACtBC,aAAcjc,aAAM,EAANA,EAAQic,aACtBC,aAAclc,aAAM,EAANA,EAAQkc,aACtBC,aAAcnc,aAAM,EAANA,EAAQmc,aACtBC,cAAepc,aAAM,EAANA,EAAQoc,cACvB9W,aAActF,aAAM,EAANA,EAAQsF,aACtBlB,OAAQpE,aAAM,EAANA,EAAQoE,OAChBoB,eAAgBxF,aAAM,EAANA,EAAQwF,eACxBlpC,IAAK0jC,aAAM,EAANA,EAAQ1jC,IACbge,SAAU0lB,aAAM,EAANA,EAAQ1lB,SAClBqsB,KAAM3G,aAAM,EAANA,EAAQ2G,KACdzG,SAAUF,aAAM,EAANA,EAAQE,SAClB/pC,OAAQ6pC,aAAM,EAANA,EAAQ7pC,OAChBkG,UAAW2jC,aAAM,EAANA,EAAQ3jC,UACnBwE,WAAYm/B,aAAM,EAANA,EAAQn/B,WACpBL,KAAMw/B,aAAM,EAANA,EAAQx/B,KACdgmB,aAAcwZ,aAAM,EAANA,EAAQxZ,aACtBC,YAAauZ,aAAM,EAANA,EAAQvZ,YACrBxlB,aAAc++B,aAAM,EAANA,EAAQ/+B,aACtBopC,UAAWrK,aAAM,EAANA,EAAQqK,UACnBrG,OAAQhE,aAAM,EAANA,EAAQgE,OAChBttC,QAASspC,aAAM,EAANA,EAAQtpC,QACjB2S,aAAc22B,aAAM,EAANA,EAAQ32B,aACtBwgB,QAASmW,aAAM,EAANA,EAAQnW,QACjBwyB,kBAAmBrc,aAAM,EAANA,EAAQ+D,aAC3Bp7B,WAAYq3B,aAAM,EAANA,EAAQr3B,WACpBtH,kBAAmB2+B,aAAM,EAANA,EAAQ3+B,kBAC3BF,iBAAkB6+B,aAAM,EAANA,EAAQ7+B,mBAkFiB,CAC3CyM,KAAMsmC,aAAiB,EAAjBA,EAAmBtmC,KACzB6yB,eAAgB6T,EAChBX,QAASA,EACT/jC,WAAYskC,aAAiB,EAAjBA,EAAmBtkC,WAC/BtC,SAAU4mC,aAAiB,EAAjBA,EAAmB5mC,SAC7BkoC,OAAQ,EACRpjB,UAAWA,EACX/S,aAAcA,EACdyf,cAAeA,EACf0B,KAAMhvB,KAAK6E,MACXq+B,uBAAwBA,IAI1B,OAAQl8C,GACN,IAAK,UACHw9C,EAAmBjV,QAAU,EAC7B,MACF,IAAK,QACHiV,EAAmB1W,UAAY,EAC/B0W,EAAmBsG,yBAA2B7H,aAAgB,EAAhBA,EAAkBc,gBAChE,MACF,IAAK,WACHS,EAAmBxW,SAAW,EAC9BwW,EAAmBuG,wBAA0B9H,aAAgB,EAAhBA,EAAkBc,gBAC/D,MACF,IAAK,QACHS,EAAmBtW,UAAY,EAC/BsW,EAAmBwG,yBAA2B/H,aAAgB,EAAhBA,EAAkBc,gBAChE,MACF,IAAK,YACHS,EAAmB7X,UAAY,EAC/B6X,EAAmByG,yBAA2BhI,aAAgB,EAAhBA,EAAkBc,gBAKpE,IAAMlB,EAAaH,aAAiB,EAAjBA,EAAmBG,WAStC,OARI,IAAA96C,cAAa86C,IACf,EAAAS,qBAAqBnxB,SAAQ,SAACrnB,GACxB+3C,EAAW/3C,KACb05C,EAAmB15C,GAAO+3C,EAAW/3C,GAEzC,IAGK05C,CACT,CAUA,SAAgBxB,IACd,IAAMvlB,GAAiB,IAAAC,2BACvB,OAAI,IAAA9sB,WAAU6sB,GACLzd,KAAK6E,MAIPvL,KAAK4xC,MAAMztB,EACpB,CA9Sa,EAAAgJ,2BAA6B,kBAkB7B,EAAAwd,kBAAoB,eACpB,EAAAC,6BAA+B,M,kCChD5C,IAAYxN,E,kEAAZ,SAAYA,GACV,qBACA,mBACA,kBACD,CAJD,CAAYA,IAAO,UAAPA,EAAO,I,kCCAnB,IAAYyU,E,sEAAZ,SAAYA,GACV,kBACA,0BACA,0BACA,0BACA,0BACA,kBACA,iBACD,CARD,CAAYA,IAAW,cAAXA,EAAW,I,kCCAvB,IAAYnyC,E,mEAAZ,SAAYA,GACV,oBACA,0BACA,uBACD,CAJD,CAAYA,IAAQ,WAARA,EAAQ,I,mFCIpB,wBAA6BtF,GAC3B,IAAKA,EACH,OAAO,EAGT,OAAkB,IADJ03C,EAAYC,WAAU,SAAC5yC,GAAe,OAAA/E,EAAM43C,WAAW7yC,EAAjB,GAEtD,EAEA,wBAA6B/E,GAC3B,IAAKA,EACH,OAAO,EAGT,OAAkB,IADJ63C,EAAYF,WAAU,SAAC5yC,GAAe,OAAA/E,EAAM43C,WAAW7yC,EAAjB,GAEtD,EAlBA,IAAM2yC,EAAc,CAAC,OAAQ,OAAQ,OAAQ,OAAQ,MAAO,OAAQ,OAE9DG,EAAc,CAAC,OAAQ,OAAQ,OAAQ,OAAQ,Y,sGCArD,iBAWE,WACWt2C,EACAC,EACAo4B,QAAA,IAAAA,IAAAA,EAAA,YAFA,KAAAr4B,KAAAA,EACA,KAAAC,QAAAA,EACA,KAAAo4B,cAAAA,CACR,CACL,OAfS,EAAA73B,gCAAkC,IAAID,EAAU,KAAM,IACtD,EAAAE,gCAAkC,IAAIF,EAAU,KAAM,IACtD,EAAAygC,kCAAoC,IAAIzgC,EAC7C,IACA,8CACA,QAEK,EAAAuwB,0BAA4B,IAAIvwB,EAAU,MAAO,uCACjD,EAAA+gC,8BAAgC,IAAI/gC,EAAU,MAAO,wCAO9D,C,CAhBA,GAAa,EAAAA,UAAAA,C,kCCmBb,IAAYlE,E,oFAFC,EAAA2R,kBAAoB,cAEjC,SAAY3R,GACV,6BACA,yCACA,wCAIA,YACA,iBACA,+BACA,wBACA,iCACA,sBAKA,8CAQA,yCACA,qDACA,cACA,gBACA,cACA,oBAIA,gBACA,yBACA,cACA,kBACA,+BACA,mCACA,qBACA,mCACA,4BACA,qCACA,mCACA,4BACA,mBAIA,kBACA,6BACA,yCACD,CArDD,CAAYA,IAAK,QAALA,EAAK,I,wGCCjB,wCAA6CuM,GAC3C,IAAM2tC,EAAU3tC,EAAI8Z,MAAM,QAAQ,GAAGzT,cAErC,IAAI,IAAAqb,UAASisB,EAAS,SACpB,OAAO,EAAAn/B,UAAUC,IAEnB,IAAI,IAAAiT,UAASisB,EAAS,UAAW,IAAAjsB,UAASisB,EAAS,UAAW,IAAAjsB,UAASisB,EAAS,QAC9E,OAAO,EAAAn/B,UAAUo/B,IAEnB,IAAI,IAAAlsB,UAASisB,EAAS,SACpB,OAAO,EAAAn/B,UAAUq/B,KAEnB,IAAI,IAAAnsB,UAASisB,EAAS,QACpB,OAAO,EAAAn/B,UAAUs/B,KAGnB,MACF,EAvCA,cAEa,EAAAt/B,UAAY,CACvBo/B,IAAK,YACLC,KAAM,aACNp/B,IAAK,wBACLq/B,KAAM,uB,kCCNR,IAAYC,E,yEAAZ,SAAYA,GACV,+BACA,8BACD,CAHD,CAAYA,IAAc,iBAAdA,EAAc,I,iCCA1B,IAAYp/C,E,iEAAZ,SAAYA,GACV,sBACA,8BACA,sCACA,gBACA,gBACA,UACA,oBACA,gBACA,0BACA,mBACD,CAXD,CAAYA,IAAM,SAANA,EAAM,I,kCCAlB,IAAY2C,E,qEAAZ,SAAYA,GACV,0BACA,iBACD,CAHD,CAAYA,IAAU,aAAVA,EAAU,I,0GCWtB,iCAAsC0O,GACpC,IAAI,IAAAjN,WAAUiN,KAAQ,IAAA8M,SAAQ9M,GAC5B,OAGF,IAAM2tC,EAAU3tC,EAAI8Z,MAAM,QAAQ,GAAGzT,cAErC,IAAI,IAAAqb,UAASisB,EAAS,SACpB,OAAOllC,EAAY9O,IAErB,IAAI,IAAA+nB,UAASisB,EAAS,UAAW,IAAAjsB,UAASisB,EAAS,UAAW,IAAAjsB,UAASisB,EAAS,QAC9E,OAAOllC,EAAYsS,KAErB,IAAI,IAAA2G,UAASisB,EAAS,SACpB,OAAOllC,EAAYsS,KAErB,IAAI,IAAA2G,UAASisB,EAAS,QACpB,OAAOllC,EAAYhP,KAGrB,MACF,EAEA,qCAA0CuE,G,MAQxC,QAPkC,MAC/B,EAAAwQ,UAAUo/B,KAAMnlC,EAAYsS,KAC7B,EAAC,EAAAvM,UAAUq/B,MAAOplC,EAAYsS,KAC9B,EAAC,EAAAvM,UAAUC,KAAMhG,EAAY9O,IAC7B,EAAC,EAAA6U,UAAUs/B,MAAOrlC,EAAYhP,K,GAGIuE,EACtC,EA3CA,IAKYyK,EALZ,UACA,UAEA,WAEA,SAAYA,GACV,cACA,YACA,oBACD,CAJD,CAAYA,IAAW,cAAXA,EAAW,I,qHCIvB,wCAA6CulC,GAC3C,OAAQA,GACN,KAAK,EAAAv6C,MAAM0D,MACT,OAAO6zB,EAAuBwN,aAChC,KAAK,EAAA/kC,MAAMyF,OAEX,KAAK,EAAAzF,MAAMwkB,qBAEX,KAAK,EAAAxkB,MAAMI,gBACT,OAAOm3B,EAAuBC,YAChC,KAAK,EAAAx3B,MAAM20B,mBACT,OAAO4C,EAAuByN,QAEhC,QACE,OAAOzN,EAAuBvpB,QAEpC,EAzBA,IAEYupB,EAFZ,WAEA,SAAYA,GACV,4BACA,8BACA,oBACA,mBACD,CALD,CAAYA,IAAsB,yBAAtBA,EAAsB,I,qGCFlC,cAIA,0BACU,KAAAloB,aAAoBpe,EACpB,KAAAupD,YAAa,CA6BvB,QA3BE,sBAAI,qBAAM,C,IAAV,WACE,OAAO1pD,KAAKue,OACd,E,gCAEA,sBAAI,wBAAS,C,IAAb,WACE,OAAOve,KAAK0pD,UACd,E,gCAOA,YAAAC,QAAA,WACE3pD,KAAK0pD,YAAa,EAClB1pD,KAAK4pD,UACP,EAEA,YAAAC,UAAA,SAAUC,EAAwBC,GAKhC,OAJI,IAAApkD,cAAaokD,KACf/pD,KAAKue,QAAUve,KAAKgqD,cAAcD,IAEpC/pD,KAAKiqD,WAAWH,EAAe9pD,KAAKue,SAC7Bve,KAAKue,OACd,EAGF,EA/BA,GAAsB,EAAA2rC,QAAAA,C,6GCJtB,cAKA,0BACU,KAAAnZ,SAA4D,EA2BtE,QAzBE,YAAAC,iBAAA,SAAiBD,GACf/wC,KAAK+wC,SAAWA,CAClB,EAEA,YAAAoZ,mBAAA,WACEnqD,KAAK+wC,SAAShhB,SAAQ,SAACq6B,GAAY,OAAAA,EAAQT,SAAR,IACnC3pD,KAAK+wC,SAAW,EAClB,EAEA,YAAAK,cAAA,WACEpxC,KAAK+wC,SAAShhB,SAAQ,SAACq6B,GAAY,OAAAA,EAAQr7C,OAAR,GACrC,EAEA,YAAA4gC,kBAAA,SAAkBma,EAAwBpa,GACxC1vC,KAAK+wC,SAAW/wC,KAAK+wC,SAASttB,QAAO,SAAC2mC,GACpC,IAAM3gD,EAAS2gD,EAAQP,UAAUC,EAAepa,GAChD,SAAKoa,IAAqC,KAApBrgD,aAAM,EAANA,EAAQsM,YAC5B,EAAA/N,OAAO4X,IAAI,4BAAqBwqC,EAAQ59B,YAAYntB,KAAI,wDACxD+qD,EAAQT,WACD,EAGX,IACA3pD,KAAK+wC,SAAShhB,SAAQ,SAACq6B,GAAY,OAAAA,EAAQr0C,SAAR,GACrC,EACF,EA5BA,GAAa,EAAA6gC,eAAAA,C,sjBCJb,YACA,UACA,UAMA,aA0DE,WAAYvqC,G,MAHK,KAAAg+C,OAAwB,GACjC,KAAAC,UAAW,EAGjBtqD,KAAKu3C,YAAa,IAAAgT,UAAoC,QAA3B,EAAAl+C,aAAe,EAAfA,EAAiBkrC,kBAAU,QAAI,EAAAC,2BAA4B,mBACxF,CAyCF,OApGE,sBAAI,oBAAK,C,IAAT,WACE,OAAOx3C,KAAKqqD,MACd,E,gCAEA,sBAAI,sBAAO,C,IAAX,WACE,OAAOrqD,KAAKsqD,QACd,E,IAEA,SAAYhwC,GACVta,KAAKsqD,SAAWhwC,CAClB,E,gCAEO,EAAAkwC,sCAAP,SACEC,EACAC,EACAC,GAHF,I,IAAA,OAKE,OAAO,EAAP,KACKF,GAAW,CACd33C,QAA4B,QAAnB,EAAA23C,EAAY33C,eAAO,eAAE83C,OAAO,EAAGF,GACxC13C,KAAMhT,KAAK6qD,6BAA6BJ,EAAYz3C,KAAM03C,GAC1DI,aAAsC,QAAxB,EAAAL,EAAYK,oBAAY,eAAEhsD,KAAI,SAACs8B,GAAY,SAAK2vB,4BAA4B3vB,EAASuvB,EAA1C,KAE7D,EAEO,EAAAI,4BAAP,SAAmCxuC,EAA0ByuC,G,QAC3D,OAAO,EAAP,KACKzuC,GAAW,CACdd,IAAoB,QAAf,EAAAc,EAAYd,WAAG,eAAEmvC,OAAO,EAAGI,GAChCC,qBAAsD,QAAhC,EAAA1uC,EAAY0uC,4BAAoB,eAAEL,OAAO,EAAGI,IAEtE,EAEO,EAAAH,6BAAP,SAAoC9xC,EAAsB2xC,G,QACxD,OAAO,EAAP,KACK3xC,GAAS,CACZqc,iBAA4C,QAA1B,EAAArc,EAAUqc,wBAAgB,eAAEw1B,OAAO,EAAGF,GACxDx3C,eAAwC,QAAxB,EAAA6F,EAAU7F,sBAAc,eAAE03C,OAAO,EAAGF,IAExD,EAEO,EAAAQ,oCAAP,SAA2CT,EAA0BU,G,MACnE,OAAO,EAAP,KACKV,GAAW,CACdK,aAAsC,QAAxB,EAAAL,EAAYK,oBAAY,eAAE5oD,OAAOipD,IAEnD,EAeA,YAAAC,sCAAA,SAAsC9d,GAAtC,WACEttC,KAAKqqD,OAAOt6B,SAAQ,SAACzV,EAAOq/B,GAC1B,EAAK0Q,OAAO1Q,GAASvtC,EAAmB8+C,oCAAoC5wC,EAAOgzB,EACrF,GACF,EAEA,YAAA+d,KAAA,SAAKZ,GACH,IAAMa,EAAkBl/C,EAAmBo+C,sCACzCC,EACAr+C,EAAmBm/C,kBACnBn/C,EAAmBo/C,gBAEjBxrD,KAAK+V,SACP,IAAA01C,MAAKzrD,KAAKu3C,WAAY+T,GAEtBtrD,KAAKqqD,OAAO7qD,KAAK8rD,EAErB,EAEA,YAAAI,MAAA,WAGE,IAFA,IAAMC,EAAO,EAAH,GAAO3rD,KAAKqqD,QAAM,GACxBxmC,EAAU8nC,EAAK3vB,SACZ,IAAAr2B,cAAake,IAClB7jB,KAAK4rD,gBAAgB/nC,GACrB7jB,KAAKqrD,KAAKxnC,GACVA,EAAU8nC,EAAK3vB,OAEnB,EAEA,YAAA9B,MAAA,WACEl6B,KAAKqqD,OAAOzQ,OAAO,EAAG55C,KAAKqqD,OAAO9qD,OACpC,EAEQ,YAAAqsD,gBAAR,SAAwB/nC,GACtB,IAAM81B,EAAQ35C,KAAKqqD,OAAOpB,WAAU,SAAC3uC,GAAU,OAAAA,IAAUuJ,CAAV,IAC3C81B,GAAS,GACX35C,KAAKqqD,OAAOzQ,OAAOD,EAAO,EAE9B,EAjDe,EAAA6R,eAAiB,IACjB,EAAAD,kBAAoB,IAiDrC,C,CArGA,GAAa,EAAAn/C,mBAAAA,C,6yBCNb,cACA,UACA,UAgBA,cAGE,WACUy/C,EACA5e,EACA6e,EACAhzB,GAER,QAAK,YAAE,K,OALC,EAAA+yB,iBAAAA,EACA,EAAA5e,QAAAA,EACA,EAAA6e,cAAAA,EACA,EAAAhzB,oBAAAA,EANF,EAAAizB,WAAa,EAuCb,EAAAC,eAAiB,SAACtsD,G,QACxB,IACE,IAAK,EAAKq3C,UACR,OAGF,IAAM+T,EAAuC,QAAxB,IAAKhyB,2BAAmB,eAAEgyB,aACzCmB,GAAmB,IAAAz9C,WAAUs8C,QAAgB3qD,EAAY,EAAD,GAAK2qD,GAAY,GACzEiB,EAAa,EAAKA,WACxB,EAAKA,aAEL,IAAMtB,EAA2B,CAC/Bne,SAAU,MACV73B,WAAY,EAAKo3C,iBAAiBp3C,WAClC+7B,OAAQ,EAAKqb,iBAAiBrb,OAC9BL,aAAc,EAAK0b,iBAAiB1b,aACpC5D,iBAAkB,EAAA9uC,QAClByuD,QAASH,EACTlgD,WAAW,IAAA8Q,uBACX9J,KAAMnT,EAAMmT,KACZC,QAASpT,EAAMoT,QACfE,KAAqB,QAAf,EAAAtT,EAAMqZ,iBAAS,QAAI,CACvB7F,oBAAgB/S,EAChBi1B,sBAAkBj1B,EAClBk1B,yBAAqBl1B,GAEvB2qD,aAAcmB,EACdv4C,SAAUhU,EAAMgU,UAGlB,EAAA1L,OAAO4X,IAAI,wCAAgC,IAAAzM,kBAAiBs3C,KAC5D,EAAKxd,QAAQoe,KAAKZ,EACpB,CAAE,MAAOlqD,GACP,EAAAyH,OAAOzH,MAAM,gDAAiDA,EAChE,CACF,EAjEEurD,EAAc/7B,SAAQ,SAACo8B,GAAiB,OAAAA,EAAa9vC,UAAU,EAAK2vC,eAA5B,I,CAC1C,CAiEF,OA5EyC,OAavC,YAAAj9C,MAAA,W,MAC0B,QAAxB,EAAA/O,KAAK84B,2BAAmB,SAAE/pB,QAC1B/O,KAAK+rD,WAAa,CACpB,EAEA,YAAAh2C,QAAA,WACE/V,KAAKitC,QAAQl3B,SAAU,EACvB/V,KAAKitC,QAAQye,OACf,EAEA,YAAA9B,SAAA,e,EAAA,OACE5pD,KAAK+rD,WAAa,EACM,QAAxB,EAAA/rD,KAAK84B,2BAAmB,SAAE6wB,UAC1B3pD,KAAKitC,QAAQ/S,QACbl6B,KAAK8rD,cAAc/7B,SAAQ,SAACo8B,GAAiB,OAAAA,EAAa7vC,YAAY,EAAK0vC,eAA9B,GAC/C,EAEA,YAAA/B,WAAA,SAAWmC,EAAyB3iD,G,QAC5B0hD,EAAcj0C,KAAKo2B,IAAgC,QAA5B,EAAA7jC,aAAM,EAANA,EAAQ4iD,4BAAoB,QAAI,EAAG,GACxC,QAAxB,EAAArsD,KAAK84B,2BAAmB,SAAE+wB,UAAUsB,GACpCnrD,KAAKitC,QAAQme,sCAAsCD,EACrD,EAEA,YAAAnB,cAAA,SAAcD,GACZ,OAAOA,EAAgBuC,YACzB,EAsCF,EA5EA,CAfA,OAeyCpC,SAA5B,EAAAh+C,oBAAAA,C,kHCpBb,cACA,UAKA,aAaE,WAAoB4/C,GAApB,WAAoB,KAAAA,cAAAA,EAXZ,KAAAS,aAAuBtgD,EAAoBugD,qBAC3C,KAAAC,kBAAoB,IAAI,EAAAC,MA4BxB,KAAAC,0BAA4B,SAACjtD,GACnC,IACE,EAAKktD,WAAWltD,EAAM6c,YACxB,CAAE,MAAOhc,GACP,EAAAyH,OAAOzH,MAAM,2DAA4DA,EAC3E,CACF,EAvBEurD,EAAc/7B,SAAQ,SAACo8B,GAAiB,OAAAA,EAAa9vC,UAAU,EAAKswC,0BAA5B,GAC1C,CA4BF,OAtCE,sBAAI,0BAAW,C,IAAf,WACE,OAAO3sD,KAAKusD,YACd,E,gCAEA,sBAAI,2BAAY,C,IAAhB,WACE,OAAOvsD,KAAKysD,kBAAkBI,KAChC,E,gCAMA,YAAAhD,UAAA,SAAUsB,GACRnrD,KAAKusD,aAAepB,EACpBnrD,KAAKysD,kBAAkBK,MAAM3B,EAC/B,EAEA,YAAAxB,QAAA,sBACE3pD,KAAK8rD,cAAc/7B,SAAQ,SAACo8B,GAAiB,OAAAA,EAAa7vC,YAAY,EAAKqwC,0BAA9B,IAC7C3sD,KAAKysD,kBAAkBvyB,OACzB,EAEA,YAAAnrB,MAAA,WACE/O,KAAKysD,kBAAkBvyB,OACzB,EAUQ,YAAA0yB,WAAR,SAAmBrwC,GACjBvc,KAAKysD,kBAAkBM,MAAMxwC,GAC7Bvc,KAAKysD,kBAAkBK,MAAM9sD,KAAKusD,aACpC,EAzCe,EAAAC,qBAAuB,GA0CxC,C,CA3CA,GAAa,EAAAvgD,oBAAAA,C,kCCOb,IAAY+Q,E,0EAAZ,SAAYA,GAGV,gCACA,4CACA,8CACA,oCACA,8BAEA,4BACA,4BACA,oCACA,sCACA,0CAEA,8CACA,gDACA,8CACA,gDACA,8CACA,wCAEA,sDAEA,8DAEA,4BAEA,wBAEA,0CACA,wCACA,sCAEA,oBAEA,qBAGD,CAvCD,CAAYA,IAAe,kBAAfA,EAAe,I,mMCd3B,cA6Ga,EAAAkkC,qBAAsD,CACjE,cACA,cACA,cACA,cACA,cACA,cACA,cACA,cACA,cACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,gBAEA,kBAMW,EAAA8L,qBAAuB,EAAA9L,qBAAqBz9B,QAAO,SAAC4hB,GAAM,OAAAA,EAAEnO,MAAM,iBAAR,IAA2B33B,OAKrF,EAAA+wC,4BAA8B,SAAC2c,GAC1C,IAAMC,EAA2B,CAAC,EAMlC,OALA,EAAAhM,qBAAqBnxB,SAAQ,SAACrnB,GACxBukD,EAAMvkD,KACRwkD,EAAOxkD,GAAOukD,EAAMvkD,GAExB,IACOwkD,CACT,EAEa,EAAA1L,yBAA2B,SAACjuB,GACvC,IAAM45B,GAAY,IAAA7c,6BAA4B/c,GAExCguB,EAA8C,CAAC,EAMrD,OALA,IAAA5P,0BAAyBwb,EAAW5L,GAGpCA,EAA0B3P,gBAAiB,IAAAwb,qBAAoBD,EAAUvb,gBAElE2P,CACT,C,kCC1OA,IAAYvG,E,0EAAZ,SAAYA,GACV,kBACA,oBACA,aACD,CAJD,CAAYA,IAAe,kBAAfA,EAAe,I,qF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","sources":["webpack://bitmovin.analytics/webpack/universalModuleDefinition","webpack://bitmovin.analytics/./node_modules/javascript-state-machine/state-machine.js","webpack://bitmovin.analytics/./src/adapters/bitmovin8/Bitmovin8AdModule.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/Bitmovin8Adapter.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/Bitmovin8InternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/Bitmovin8PlayerProxy.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/ads/AdUtils.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/bitmovin8AdapterSsaiApiSanitizeUtils.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/player/Bitmovin8PlayerTypes.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/player/HttpRequestTrackingAdapter.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/player/SegmentTrackerAdapter.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/player/SpeedMeterAdapter.ts","webpack://bitmovin.analytics/./src/adapters/bitmovin8/playerModule.ts","webpack://bitmovin.analytics/./src/adapters/bitmovinPwx/BitmovinPwxAdapter.ts","webpack://bitmovin.analytics/./src/adapters/bitmovinPwx/BitmovinPwxAnalyticsPackage.ts","webpack://bitmovin.analytics/./src/adapters/bitmovinPwx/BitmovinPwxAnalyticsStateMachine.ts","webpack://bitmovin.analytics/./src/adapters/bitmovinPwx/BitmovinPwxInternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/bitmovinPwx/ExportNames.ts","webpack://bitmovin.analytics/./src/adapters/cafv3/CAFv3Adapter.ts","webpack://bitmovin.analytics/./src/adapters/cafv3/CAFv3InternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/cafv3/CAFv3PlayerProxy.ts","webpack://bitmovin.analytics/./src/adapters/cafv3/castFrameworkTypes.ts","webpack://bitmovin.analytics/./src/adapters/hlsjs/HlsAdapter.ts","webpack://bitmovin.analytics/./src/adapters/hlsjs/HlsInternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/hlsjs/HlsjsPlayerProxy.ts","webpack://bitmovin.analytics/./src/adapters/hlsjs/player/HlsJsPlayerTypes.ts","webpack://bitmovin.analytics/./src/adapters/hlsjs/player/HlsSpeedMeterAdapter.ts","webpack://bitmovin.analytics/./src/adapters/html5/HTML5InternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/html5/HTMLVideoElementAdapter.ts","webpack://bitmovin.analytics/./src/adapters/html5/HTMLVideoElementInternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/html5/HTMLVideoElementProxy.ts","webpack://bitmovin.analytics/./src/adapters/html5/player/HTMLVideoElementStatisticsProvider.ts","webpack://bitmovin.analytics/./src/adapters/internal/InternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/internal/ads/AdModuleAPI.ts","webpack://bitmovin.analytics/./src/adapters/shaka/ShakaAdapter.ts","webpack://bitmovin.analytics/./src/adapters/shaka/ShakaInternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/shaka/ShakaPlayerProxy.ts","webpack://bitmovin.analytics/./src/adapters/shaka/shakaPlayerTypes.ts","webpack://bitmovin.analytics/./src/adapters/theo/DrmPerformanceService.ts","webpack://bitmovin.analytics/./src/adapters/theo/PlaybackProgressDetectionService.ts","webpack://bitmovin.analytics/./src/adapters/theo/THEOplayerAdapter.ts","webpack://bitmovin.analytics/./src/adapters/theo/THEOplayerInternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/theo/THEOplayerNetworkInterceptor.ts","webpack://bitmovin.analytics/./src/adapters/theo/THEOplayerProxy.ts","webpack://bitmovin.analytics/./src/adapters/theo/ads/AdUtils.ts","webpack://bitmovin.analytics/./src/adapters/theo/ads/THEOplayerAdModule.ts","webpack://bitmovin.analytics/./src/adapters/theo/playback/CallbackScheduler.ts","webpack://bitmovin.analytics/./src/adapters/theo/playback/DelayedEventDispatcher.ts","webpack://bitmovin.analytics/./src/adapters/videojs/VideoJsAdapter.ts","webpack://bitmovin.analytics/./src/adapters/videojs/VideojsInternalAdapter.ts","webpack://bitmovin.analytics/./src/adapters/videojs/VideojsPlayerProxy.ts","webpack://bitmovin.analytics/./src/analyticsStateMachines/AnalyticsStateMachine.ts","webpack://bitmovin.analytics/./src/analyticsStateMachines/CAFv3AnalyticsStateMachine.ts","webpack://bitmovin.analytics/./src/analyticsStateMachines/HTML5AnalyticsStateMachine.ts","webpack://bitmovin.analytics/./src/analyticsStateMachines/THEOplayerAnalyticsStateMachine.ts","webpack://bitmovin.analytics/./src/analyticsStateMachines/VideoJsAnalyticsStateMachine.ts","webpack://bitmovin.analytics/./src/analyticsStateMachines/bitmovin8/Bitmovin8AnalyticsStateMachine.ts","webpack://bitmovin.analytics/./src/analyticsStateMachines/stateMachineUtils.ts","webpack://bitmovin.analytics/./src/api/adapterApiUtils.ts","webpack://bitmovin.analytics/./src/core/AdAnalytics.ts","webpack://bitmovin.analytics/./src/core/Analytics.ts","webpack://bitmovin.analytics/./src/core/BackendFactory.ts","webpack://bitmovin.analytics/./src/core/DebuggingBackend.ts","webpack://bitmovin.analytics/./src/core/DownloadSpeedMeter.ts","webpack://bitmovin.analytics/./src/core/EventDispatcher.ts","webpack://bitmovin.analytics/./src/core/HeartbeatService.ts","webpack://bitmovin.analytics/./src/core/IdenticalErrorReportingLimiter.ts","webpack://bitmovin.analytics/./src/core/LicenseCheckingBackend.ts","webpack://bitmovin.analytics/./src/core/LongPlaytimeFilteringBackend.ts","webpack://bitmovin.analytics/./src/core/Measure.ts","webpack://bitmovin.analytics/./src/core/NoOpBackend.ts","webpack://bitmovin.analytics/./src/core/QualityChangeService.ts","webpack://bitmovin.analytics/./src/core/QueueBackend.ts","webpack://bitmovin.analytics/./src/core/RemoteBackend.ts","webpack://bitmovin.analytics/./src/core/SegmentTracker.ts","webpack://bitmovin.analytics/./src/core/SequenceNumberBackend.ts","webpack://bitmovin.analytics/./src/core/SessionPersistenceHandler.ts","webpack://bitmovin.analytics/./src/core/SourceInfoFallbackService.ts","webpack://bitmovin.analytics/./src/core/VideoCompletionTracker.ts","webpack://bitmovin.analytics/./src/core/ssai/SsaiService.ts","webpack://bitmovin.analytics/./src/core/ssai/ssaiApiUtils.ts","webpack://bitmovin.analytics/./src/core/ssai/ssaiEngagementInteractionData.ts","webpack://bitmovin.analytics/./src/core/ssai/ssaiUtils.ts","webpack://bitmovin.analytics/./src/enums/AdType.ts","webpack://bitmovin.analytics/./src/enums/CDNProvider.ts","webpack://bitmovin.analytics/./src/enums/CastTech.ts","webpack://bitmovin.analytics/./src/enums/Codecs.ts","webpack://bitmovin.analytics/./src/enums/ErrorCode.ts","webpack://bitmovin.analytics/./src/enums/Event.ts","webpack://bitmovin.analytics/./src/enums/MIMETypes.ts","webpack://bitmovin.analytics/./src/enums/PageLoadType.ts","webpack://bitmovin.analytics/./src/enums/Player.ts","webpack://bitmovin.analytics/./src/enums/PlayerSize.ts","webpack://bitmovin.analytics/./src/enums/StreamTypes.ts","webpack://bitmovin.analytics/./src/enums/VideoStartFailedReason.ts","webpack://bitmovin.analytics/./src/features/Feature.ts","webpack://bitmovin.analytics/./src/features/FeatureManager.ts","webpack://bitmovin.analytics/./src/features/errordetails/ErrorDetailBackend.ts","webpack://bitmovin.analytics/./src/features/errordetails/ErrorDetailTracking.ts","webpack://bitmovin.analytics/./src/features/httprequesttracking/HttpRequestTracking.ts","webpack://bitmovin.analytics/./src/features/httprequesttracking/HttpRequestType.ts","webpack://bitmovin.analytics/./src/types/CustomDataValues.ts","webpack://bitmovin.analytics/./src/types/LicensingRequest.ts","webpack://bitmovin.analytics/./src/types/PlaybackInfo.ts","webpack://bitmovin.analytics/./src/types/SourceMetadata.ts","webpack://bitmovin.analytics/./src/types/StateMachineCallbacks.ts","webpack://bitmovin.analytics/./src/types/SubtitleInfo.ts","webpack://bitmovin.analytics/./src/utils/AnalyticsCall.ts","webpack://bitmovin.analytics/./src/utils/BitmovinProgressiveSourceHelper.ts","webpack://bitmovin.analytics/./src/utils/CodecHelper.ts","webpack://bitmovin.analytics/./src/utils/Converter.ts","webpack://bitmovin.analytics/./src/utils/EventDebugging.ts","webpack://bitmovin.analytics/./src/utils/Http.ts","webpack://bitmovin.analytics/./src/utils/LicenseCall.ts","webpack://bitmovin.analytics/./src/utils/Logger.ts","webpack://bitmovin.analytics/./src/utils/Queue.ts","webpack://bitmovin.analytics/./src/utils/Settings.ts","webpack://bitmovin.analytics/./src/utils/Utils.ts","webpack://bitmovin.analytics/./src/utils/Version.ts","webpack://bitmovin.analytics/./src/utils/ViewportTracker.ts","webpack://bitmovin.analytics/./src/utils/WebOSUtils.ts","webpack://bitmovin.analytics/./src/utils/WindowEventTracker.ts","webpack://bitmovin.analytics/./src/utils/analyticsConfigUtils.ts","webpack://bitmovin.analytics/./src/utils/collectorRequirementChecks.ts","webpack://bitmovin.analytics/./src/utils/documentUtils.ts","webpack://bitmovin.analytics/./src/utils/globalScope.ts","webpack://bitmovin.analytics/./src/utils/globalScopeUtils.ts","webpack://bitmovin.analytics/./src/utils/numberUtils.ts","webpack://bitmovin.analytics/./src/utils/objectUtils.ts","webpack://bitmovin.analytics/./src/utils/playerAugmentationUtils.ts","webpack://bitmovin.analytics/./src/utils/sampleUtils.ts","webpack://bitmovin.analytics/./src/utils/stringUtils.ts","webpack://bitmovin.analytics/./src/utils/uuidUtils.ts","webpack://bitmovin.analytics/webpack/bootstrap","webpack://bitmovin.analytics/webpack/runtime/global","webpack://bitmovin.analytics/./src/bitmovin-analytics.ts"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"bitmovin\"] = factory();\n\telse\n\t\troot[\"bitmovin\"] = root[\"bitmovin\"] || {}, root[\"bitmovin\"][\"analytics\"] = factory();\n})(self, function() {\nreturn ","/*\n\n Javascript State Machine Library - https://github.com/jakesgordon/javascript-state-machine\n\n Copyright (c) 2012, 2013, 2014, 2015, Jake Gordon and contributors\n Released under the MIT license - https://github.com/jakesgordon/javascript-state-machine/blob/master/LICENSE\n\n*/\n\n(function () {\n\n var StateMachine = {\n\n //---------------------------------------------------------------------------\n\n VERSION: \"2.4.0\",\n\n //---------------------------------------------------------------------------\n\n Result: {\n SUCCEEDED: 1, // the event transitioned successfully from one state to another\n NOTRANSITION: 2, // the event was successfull but no state transition was necessary\n CANCELLED: 3, // the event was cancelled by the caller in a beforeEvent callback\n PENDING: 4 // the event is asynchronous and the caller is in control of when the transition occurs\n },\n\n Error: {\n INVALID_TRANSITION: 100, // caller tried to fire an event that was innapropriate in the current state\n PENDING_TRANSITION: 200, // caller tried to fire an event while an async transition was still pending\n INVALID_CALLBACK: 300 // caller provided callback function threw an exception\n },\n\n WILDCARD: '*',\n ASYNC: 'async',\n\n //---------------------------------------------------------------------------\n\n create: function(cfg, target) {\n\n var initial = (typeof cfg.initial == 'string') ? { state: cfg.initial } : cfg.initial; // allow for a simple string, or an object with { state: 'foo', event: 'setup', defer: true|false }\n var terminal = cfg.terminal || cfg['final'];\n var fsm = target || cfg.target || {};\n var events = cfg.events || [];\n var callbacks = cfg.callbacks || {};\n var map = {}; // track state transitions allowed for an event { event: { from: [ to ] } }\n var transitions = {}; // track events allowed from a state { state: [ event ] }\n\n var add = function(e) {\n var from = Array.isArray(e.from) ? e.from : (e.from ? [e.from] : [StateMachine.WILDCARD]); // allow 'wildcard' transition if 'from' is not specified\n map[e.name] = map[e.name] || {};\n for (var n = 0 ; n < from.length ; n++) {\n transitions[from[n]] = transitions[from[n]] || [];\n transitions[from[n]].push(e.name);\n\n map[e.name][from[n]] = e.to || from[n]; // allow no-op transition if 'to' is not specified\n }\n if (e.to)\n transitions[e.to] = transitions[e.to] || [];\n };\n\n if (initial) {\n initial.event = initial.event || 'startup';\n add({ name: initial.event, from: 'none', to: initial.state });\n }\n\n for(var n = 0 ; n < events.length ; n++)\n add(events[n]);\n\n for(var name in map) {\n if (map.hasOwnProperty(name))\n fsm[name] = StateMachine.buildEvent(name, map[name]);\n }\n\n for(var name in callbacks) {\n if (callbacks.hasOwnProperty(name))\n fsm[name] = callbacks[name]\n }\n\n fsm.current = 'none';\n fsm.is = function(state) { return Array.isArray(state) ? (state.indexOf(this.current) >= 0) : (this.current === state); };\n fsm.can = function(event) { return !this.transition && (map[event] !== undefined) && (map[event].hasOwnProperty(this.current) || map[event].hasOwnProperty(StateMachine.WILDCARD)); }\n fsm.cannot = function(event) { return !this.can(event); };\n fsm.transitions = function() { return (transitions[this.current] || []).concat(transitions[StateMachine.WILDCARD] || []); };\n fsm.isFinished = function() { return this.is(terminal); };\n fsm.error = cfg.error || function(name, from, to, args, error, msg, e) { throw e || msg; }; // default behavior when something unexpected happens is to throw an exception, but caller can override this behavior if desired (see github issue #3 and #17)\n fsm.states = function() { return Object.keys(transitions).sort() };\n\n if (initial && !initial.defer)\n fsm[initial.event]();\n\n return fsm;\n\n },\n\n //===========================================================================\n\n doCallback: function(fsm, func, name, from, to, args) {\n if (func) {\n try {\n return func.apply(fsm, [name, from, to].concat(args));\n }\n catch(e) {\n return fsm.error(name, from, to, args, StateMachine.Error.INVALID_CALLBACK, \"an exception occurred in a caller-provided callback function\", e);\n }\n }\n },\n\n beforeAnyEvent: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onbeforeevent'], name, from, to, args); },\n afterAnyEvent: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onafterevent'] || fsm['onevent'], name, from, to, args); },\n leaveAnyState: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onleavestate'], name, from, to, args); },\n enterAnyState: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onenterstate'] || fsm['onstate'], name, from, to, args); },\n changeState: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onchangestate'], name, from, to, args); },\n\n beforeThisEvent: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onbefore' + name], name, from, to, args); },\n afterThisEvent: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onafter' + name] || fsm['on' + name], name, from, to, args); },\n leaveThisState: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onleave' + from], name, from, to, args); },\n enterThisState: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onenter' + to] || fsm['on' + to], name, from, to, args); },\n\n beforeEvent: function(fsm, name, from, to, args) {\n if ((false === StateMachine.beforeThisEvent(fsm, name, from, to, args)) ||\n (false === StateMachine.beforeAnyEvent( fsm, name, from, to, args)))\n return false;\n },\n\n afterEvent: function(fsm, name, from, to, args) {\n StateMachine.afterThisEvent(fsm, name, from, to, args);\n StateMachine.afterAnyEvent( fsm, name, from, to, args);\n },\n\n leaveState: function(fsm, name, from, to, args) {\n var specific = StateMachine.leaveThisState(fsm, name, from, to, args),\n general = StateMachine.leaveAnyState( fsm, name, from, to, args);\n if ((false === specific) || (false === general))\n return false;\n else if ((StateMachine.ASYNC === specific) || (StateMachine.ASYNC === general))\n return StateMachine.ASYNC;\n },\n\n enterState: function(fsm, name, from, to, args) {\n StateMachine.enterThisState(fsm, name, from, to, args);\n StateMachine.enterAnyState( fsm, name, from, to, args);\n },\n\n //===========================================================================\n\n buildEvent: function(name, map) {\n return function() {\n\n var from = this.current;\n var to = map[from] || (map[StateMachine.WILDCARD] != StateMachine.WILDCARD ? map[StateMachine.WILDCARD] : from) || from;\n var args = Array.prototype.slice.call(arguments); // turn arguments into pure array\n\n if (this.transition)\n return this.error(name, from, to, args, StateMachine.Error.PENDING_TRANSITION, \"event \" + name + \" inappropriate because previous transition did not complete\");\n\n if (this.cannot(name))\n return this.error(name, from, to, args, StateMachine.Error.INVALID_TRANSITION, \"event \" + name + \" inappropriate in current state \" + this.current);\n\n if (false === StateMachine.beforeEvent(this, name, from, to, args))\n return StateMachine.Result.CANCELLED;\n\n if (from === to) {\n StateMachine.afterEvent(this, name, from, to, args);\n return StateMachine.Result.NOTRANSITION;\n }\n\n // prepare a transition method for use EITHER lower down, or by caller if they want an async transition (indicated by an ASYNC return value from leaveState)\n var fsm = this;\n this.transition = function() {\n fsm.transition = null; // this method should only ever be called once\n fsm.current = to;\n StateMachine.enterState( fsm, name, from, to, args);\n StateMachine.changeState(fsm, name, from, to, args);\n StateMachine.afterEvent( fsm, name, from, to, args);\n return StateMachine.Result.SUCCEEDED;\n };\n this.transition.cancel = function() { // provide a way for caller to cancel async transition if desired (issue #22)\n fsm.transition = null;\n StateMachine.afterEvent(fsm, name, from, to, args);\n }\n\n var leave = StateMachine.leaveState(this, name, from, to, args);\n if (false === leave) {\n this.transition = null;\n return StateMachine.Result.CANCELLED;\n }\n else if (StateMachine.ASYNC === leave) {\n return StateMachine.Result.PENDING;\n }\n else {\n if (this.transition) // need to check in case user manually called transition() but forgot to return StateMachine.ASYNC\n return this.transition();\n }\n\n };\n }\n\n }; // StateMachine\n\n //===========================================================================\n\n //======\n // NODE\n //======\n if (typeof exports !== 'undefined') {\n if (typeof module !== 'undefined' && module.exports) {\n exports = module.exports = StateMachine;\n }\n exports.StateMachine = StateMachine;\n }\n //============\n // AMD/REQUIRE\n //============\n else if (typeof define === 'function' && define.amd) {\n define(function(require) { return StateMachine; });\n }\n //========\n // BROWSER\n //========\n else if (typeof window !== 'undefined') {\n window.StateMachine = StateMachine;\n }\n //===========\n // WEB WORKER\n //===========\n else if (typeof self !== 'undefined') {\n self.StateMachine = StateMachine;\n }\n\n}());\n","import type {AdTagConfig, PlayerEventBase, UserInteractionEvent} from 'bitmovin-player';\n\nimport {isNotNullish} from '../../utils/Utils';\nimport {WindowEventTracker} from '../../utils/WindowEventTracker';\nimport {AdCallbacks, AdModuleAPI} from '../internal/ads/AdModuleAPI';\n\nimport {mapBitmovinAd, mapBitmovinAdBreak, mapBitmovinAdError} from './ads/AdUtils';\nimport {Bitmovin8PlayerProxy} from './Bitmovin8PlayerProxy';\nimport {BITMOVIN8_PLAYER_EVENT} from './player/Bitmovin8PlayerTypes';\n\nexport class Bitmovin8AdModule implements AdModuleAPI {\n adCallbacks = new AdCallbacks();\n\n constructor(\n private player: Bitmovin8PlayerProxy,\n private windowEventTracker: WindowEventTracker,\n ) {\n this.register();\n }\n\n isLinearAdActive = () => this.player.isLinearAdActive() ?? false;\n getContainer = () => this.player.getContainer();\n getAdModuleInfo = () => this.player.getAdModuleInfo() ?? {name: undefined, version: undefined};\n currentTime = () => this.player.getCurrentTime() ?? 0;\n getAutoPlay(): boolean {\n return this.player.autoplay ?? false;\n }\n\n private register() {\n this.player.on(BITMOVIN8_PLAYER_EVENT.Play, (e: UserInteractionEvent) => {\n if (e.issuer === 'advertising-api') {\n this.adCallbacks.onPlay();\n }\n });\n this.player.on(BITMOVIN8_PLAYER_EVENT.Paused, (e: UserInteractionEvent) => {\n if (e.issuer === 'advertising-api') {\n this.adCallbacks.onPause();\n }\n });\n this.player.on(BITMOVIN8_PLAYER_EVENT.AdStarted, (event: any) => {\n this.adCallbacks.onAdStarted(mapBitmovinAd(event.ad));\n });\n this.player.on(BITMOVIN8_PLAYER_EVENT.AdFinished, (event: any) => {\n this.adCallbacks.onAdFinished(mapBitmovinAd(event.ad));\n });\n this.player.on(BITMOVIN8_PLAYER_EVENT.AdBreakStarted, (event: any) => {\n this.adCallbacks.onAdBreakStarted(mapBitmovinAdBreak(event.adBreak));\n });\n this.player.on(BITMOVIN8_PLAYER_EVENT.AdBreakFinished, (event: any) => {\n this.adCallbacks.onAdBreakFinished(mapBitmovinAdBreak(event.adBreak));\n });\n this.player.on(BITMOVIN8_PLAYER_EVENT.AdClicked, (event: any) => {\n this.adCallbacks.onAdClicked({clickThroughUrl: event.clickThroughUrl});\n });\n this.player.on(BITMOVIN8_PLAYER_EVENT.AdQuartile, (event: any) => {\n this.adCallbacks.onAdQuartile({quartile: event.quartile});\n });\n this.player.on(BITMOVIN8_PLAYER_EVENT.AdSkipped, (event: any) => {\n this.adCallbacks.onAdSkipped(mapBitmovinAd(event.ad));\n });\n this.player.on(BITMOVIN8_PLAYER_EVENT.AdError, (event: PlayerEventBase) => {\n this.adCallbacks.onAdError(mapBitmovinAdError(event, this.player.getActiveAd()?.id));\n });\n this.player.on(BITMOVIN8_PLAYER_EVENT.AdManifestLoaded, (event: any) => {\n const adTagConfig = event.adConfig as AdTagConfig;\n const isVmap = adTagConfig?.tag?.type === 'vmap';\n const adBreakInfo = isNotNullish(event.adConfig) ? mapBitmovinAdBreak(event.adConfig) : undefined;\n const manifestDownloadTime = event.downloadTiming?.downloadTime;\n this.adCallbacks.onAdManifestLoaded({\n adBreakInfo,\n manifestDownloadTime,\n isVmap,\n });\n });\n const handlePageClose = () => {\n this.adCallbacks.onBeforeUnload();\n };\n this.windowEventTracker.addEventListener('beforeunload', handlePageClose);\n this.windowEventTracker.addEventListener('unload', handlePageClose);\n }\n}\n","import type {PlayerAPI, PlayerConfig} from 'bitmovin-player';\n\nimport type {\n AdapterAPI,\n SsaiAdBreakMetadata,\n SsaiAdMetadata,\n SsaiAdQuartile,\n SsaiAdQuartileMetadata,\n SsaiApi,\n} from '../../api/AdapterAPI';\nimport {Analytics} from '../../core/Analytics';\nimport {\n hasValidSsaiAdBreakMetadataStructure,\n hasValidSsaiAdMetadataStructure,\n hasValidSsaiAdQuartileStructure,\n sanitizeSsaiAdQuartileMetadata,\n simplySanitizeSsaiAdBreakMetadata,\n simplySanitizeSsaiAdMetadata,\n} from '../../core/ssai/ssaiApiUtils';\nimport type {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {logger} from '../../utils/Logger';\nimport {\n hasPlayerAlreadyBeenAugmented,\n isDefined,\n markPlayerInstanceAsAugmented,\n} from '../../utils/playerAugmentationUtils';\nimport {VERSION} from '../../utils/Version';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {sanitizeBitmovin8AdapterSsaiAdBreakMetadataAdPosition} from './bitmovin8AdapterSsaiApiSanitizeUtils';\nimport {Bitmovin8InternalAdapter} from './Bitmovin8InternalAdapter';\nimport {Bitmovin8PlayerProxy} from './Bitmovin8PlayerProxy';\n\nexport class Bitmovin8Adapter implements AdapterAPI {\n private readonly internalAdapter: InternalAdapterAPI | undefined;\n private readonly analytics: Analytics | undefined;\n\n constructor(player: any, opts?: AnalyticsStateMachineOptions) {\n if (hasPlayerAlreadyBeenAugmented(player)) {\n logger.errorMessageToUser('Bitmovin Analytics is already hooked up to this player instance');\n return;\n }\n markPlayerInstanceAsAugmented(player);\n\n const playerConfig: PlayerConfig = (player as PlayerAPI).getConfig();\n const sanitizedConfig = sanitizeAnalyticsConfig(playerConfig.analytics as AnalyticsConfig);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n return;\n }\n\n guardAgainstDuplicatedUserId(sanitizedConfig);\n // if the player key is not set in analytics config, use the one from player config\n sanitizedConfig.playerKey = sanitizedConfig.playerKey ?? playerConfig.key;\n\n const internalAdapter = Bitmovin8InternalAdapter.create(new Bitmovin8PlayerProxy(player), opts);\n this.internalAdapter = internalAdapter;\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n\n // We do this here in order to put the reference of the adapter onto the player\n // customer using the bitmovin adapter standalone might not know that they need to\n // hold a reference\n player.analytics = this;\n\n this.wrapPlayerLoad(player, this.analytics, internalAdapter);\n }\n\n readonly ssai: SsaiApi = {\n adBreakStart: (adBreakMetadata?: SsaiAdBreakMetadata) => {\n if (!isDefined(this.internalAdapter)) return;\n\n // Bitmovin8Adapter v2.39.0 quick fix: Missing validation for adPosition values\n //\n // We need to apply this quick fix only here, because at the time when the SSAI feature was introduced:\n // - the customers started to use it right away with adPosition values that were not valid, and we did not want\n // to break their implementation.\n // - this feature was implemented only in the Bitmovin8 adapter, so other adapters are not affected by this issue,\n // once they will implement SSAI, they should implement proper validation from the beginning.\n const adBreakMetadataWithValidAdPosition = sanitizeBitmovin8AdapterSsaiAdBreakMetadataAdPosition(adBreakMetadata);\n\n if (!hasValidSsaiAdBreakMetadataStructure(adBreakMetadataWithValidAdPosition)) {\n // if we don't have valid ad break metadata, we don't want to proceed and use SSAI API\n return;\n }\n\n const sanitizedAdBreakMetadata = simplySanitizeSsaiAdBreakMetadata(adBreakMetadataWithValidAdPosition);\n\n this.internalAdapter.ssaiService.adBreakStart(sanitizedAdBreakMetadata);\n },\n\n adStart: (adMetadata?: SsaiAdMetadata) => {\n if (!isDefined(this.analytics)) return;\n if (!isDefined(this.internalAdapter)) return;\n\n if (!hasValidSsaiAdMetadataStructure(adMetadata)) {\n // if we don't have valid ad metadata, we don't want to proceed and use SSAI API\n return;\n }\n\n const sanitizedAdMetadata = simplySanitizeSsaiAdMetadata(adMetadata);\n\n this.internalAdapter.ssaiService.adStart(sanitizedAdMetadata);\n // we need to call this here to revert the customData values to the values before the adBreak\n // this is mainly needed to have clear transitions between ads, and we don't\n // copy over customData values from the first ad into the second ad\n // the adMetadata is applied after this call in the manipulate method when a sample is sent\n // it is a bit of a hack, but it is necessary right now due to the way how samples are created\n this.analytics.setConfigParameters();\n this.analytics.setAutoDetectedDeviceInformation();\n },\n\n adQuartileFinished: (adQuartile: SsaiAdQuartile, adQuartileMetadata?: SsaiAdQuartileMetadata) => {\n if (!isDefined(this.analytics)) return;\n if (!isDefined(this.internalAdapter)) return;\n\n if (!hasValidSsaiAdQuartileStructure(adQuartile)) {\n // if we don't have valid ad quartile, we don't want to proceed and use SSAI API\n return;\n }\n\n const sanitizedSsaiAdQuartileMetadata = sanitizeSsaiAdQuartileMetadata(adQuartileMetadata);\n\n this.internalAdapter.ssaiService.adQuartileFinished(adQuartile, sanitizedSsaiAdQuartileMetadata);\n },\n\n adBreakEnd: () => {\n if (!isDefined(this.analytics)) return;\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.ssaiService.adBreakEnd();\n // we need to call this here to revert the customData values to the values we had before the ad\n this.analytics.setConfigParameters();\n this.analytics.setAutoDetectedDeviceInformation();\n },\n };\n\n /*\n * intercept `player.load` with automated sourceChange handling and correct autoplay video startup time detection\n */\n private wrapPlayerLoad(player: PlayerAPI, analytics: Analytics, internalAdapter: Bitmovin8InternalAdapter) {\n const originalLoad = player.load;\n player.load = (...args: Parameters<typeof player.load>): Promise<void> => {\n if (args.length > 0) {\n const analyticsConfig = (args[0] as any).analytics;\n // we reset the analytics and reload with a new config\n analytics.sourceChange(analyticsConfig);\n }\n internalAdapter.trackLoadstartWithAutoplay();\n\n return originalLoad.apply(player, args);\n };\n }\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getCurrentImpressionId();\n }\n\n getUserId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getUserId();\n }\n\n setCustomData(values: CustomDataValues) {\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.setCustomData(values);\n }\n\n setCustomDataOnce(values: CustomDataValues) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.setCustomDataOnce(values);\n }\n\n sourceChange(config: AnalyticsConfig) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.sourceChange(config);\n }\n}\n","import type {\n AudioPlaybackQualityChangedEvent,\n PlayerEventBase,\n SeekEvent,\n UserInteractionEvent,\n VideoPlaybackQualityChangedEvent,\n} from 'bitmovin-player';\n\nimport {Bitmovin8AnalyticsStateMachine} from '../../analyticsStateMachines/bitmovin8/Bitmovin8AnalyticsStateMachine';\nimport {Analytics} from '../../core/Analytics';\nimport {DownloadSpeedMeter} from '../../core/DownloadSpeedMeter';\nimport {HeartbeatService} from '../../core/HeartbeatService';\nimport {SegmentTracker} from '../../core/SegmentTracker';\nimport {SourceInfoFallbackService} from '../../core/SourceInfoFallbackService';\nimport VideoCompletionTracker from '../../core/VideoCompletionTracker';\nimport {CastTech} from '../../enums/CastTech';\nimport {ErrorCode} from '../../enums/ErrorCode';\nimport {Event} from '../../enums/Event';\nimport {Player} from '../../enums/Player';\nimport {PlayerSize} from '../../enums/PlayerSize';\nimport {ErrorDetailBackend} from '../../features/errordetails/ErrorDetailBackend';\nimport {ErrorDetailTracking} from '../../features/errordetails/ErrorDetailTracking';\nimport {Feature} from '../../features/Feature';\nimport {FeatureConfig} from '../../features/FeatureConfig';\nimport {HttpRequestTracking} from '../../features/httprequesttracking/HttpRequestTracking';\nimport {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport {DownloadSpeedInfo} from '../../types/DownloadSpeedInfo';\nimport {DrmPerformanceInfo} from '../../types/DrmPerformanceInfo';\nimport type {QualityChangeEvent} from '../../types/EventData';\nimport {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport {normalizeVideoDuration, PlaybackInfo} from '../../types/PlaybackInfo';\nimport {SegmentInfo} from '../../types/SegmentInfo';\nimport {getSourceInfoFromBitmovinSourceConfig} from '../../utils/BitmovinProgressiveSourceHelper';\nimport * as AnalyticsSettings from '../../utils/Settings';\nimport {isNotNullish, isNullish, tryJSONStringify} from '../../utils/Utils';\nimport {AdModuleAPI} from '../internal/ads/AdModuleAPI';\nimport {InternalAdapter} from '../internal/InternalAdapter';\nimport {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {Bitmovin8AdModule} from './Bitmovin8AdModule';\nimport {Bitmovin8PlayerProxy} from './Bitmovin8PlayerProxy';\nimport {BITMOVIN8_PLAYER_EVENT} from './player/Bitmovin8PlayerTypes';\nimport {HttpRequestTrackingAdapter} from './player/HttpRequestTrackingAdapter';\nimport {SegmentTrackerAdapter} from './player/SegmentTrackerAdapter';\nimport {SpeedMeterAdapter} from './player/SpeedMeterAdapter';\n\nenum ViewMode {\n Fullscreen = 'fullscreen',\n Inline = 'inline',\n PictureInPicture = 'pictureinpicture',\n}\n\nexport class Bitmovin8InternalAdapter extends InternalAdapter implements InternalAdapterAPI {\n /** Boolean flag to prevent multiple calls of the {@link Event.UNLOAD} event */\n private onBeforeUnLoadEvent = false;\n private _adModule?: AdModuleAPI;\n private readonly _videoCompletionTracker: VideoCompletionTracker;\n private lastTrackedCurrentTime: number | undefined;\n private videoDuration: number | undefined;\n\n private readonly player: Bitmovin8PlayerProxy;\n private readonly speedMeter: DownloadSpeedMeter;\n private readonly segmentTracker: SegmentTracker;\n private readonly httpRequestTrackingAdapter: HttpRequestTrackingAdapter;\n\n constructor(\n player: Bitmovin8PlayerProxy,\n speedMeter: DownloadSpeedMeter,\n segmentTracker: SegmentTracker,\n videoCompletionTracker: VideoCompletionTracker,\n httpRequestTrackingAdapter: HttpRequestTrackingAdapter,\n sourceInfoFallbackService: SourceInfoFallbackService,\n opts?: AnalyticsStateMachineOptions,\n ) {\n super(opts);\n this.httpRequestTrackingAdapter = httpRequestTrackingAdapter;\n this._videoCompletionTracker = videoCompletionTracker;\n this.segmentTracker = segmentTracker;\n this.speedMeter = speedMeter;\n this.player = player;\n const playingHeartbeatService = new HeartbeatService(\n () => this.player.getCurrentTime() ?? this.lastTrackedCurrentTime ?? 0,\n );\n const stateMachine = new Bitmovin8AnalyticsStateMachine(\n this.stateMachineCallbacks,\n playingHeartbeatService,\n this.opts,\n );\n playingHeartbeatService.setListener(stateMachine);\n this.sourceInfoFallbackService = sourceInfoFallbackService;\n\n this.stateMachine = stateMachine;\n }\n\n protected get currentTime(): number {\n // during ad this.player.getCurrentTime() returns time of ad and not video\n // this then messes with videotime_start and videotime_end measurements of video\n // we don't track videotimes for ads\n if (isNotNullish(this.player.getCurrentTime()) && !this.isAdPlaying) {\n return this.player.getCurrentTime()!;\n }\n return this.lastTrackedCurrentTime ? this.lastTrackedCurrentTime : 0;\n }\n\n private get isAdPlaying(): boolean {\n return isNotNullish(this.player.getActiveAd());\n }\n\n get supportsDeferredLicenseLoading(): boolean {\n return true;\n }\n\n get adModule(): AdModuleAPI | undefined {\n return this._adModule;\n }\n\n get videoCompletionTracker(): VideoCompletionTracker | undefined {\n return this._videoCompletionTracker;\n }\n\n initialize(analytics: Analytics): Array<Feature<FeatureConfigContainer, FeatureConfig>> {\n this.registerPlayerEventListeners();\n\n // We need to create an AdModule AFTER we have already registered player event listeners, because they set\n // the up-to-date player information on the current Sample that is later used to form AdSample.\n // But we need to create this AdModule BEFORE we register unload event listeners, because otherwise we would\n // release the internal adapter (together with this AdModule) before the \"unload\" event listeners in AdModule would\n // be executed.\n this._adModule = new Bitmovin8AdModule(this.player, this.windowEventTracker);\n\n this.registerUnloadEventListeners();\n\n this.ssaiService.activate({\n getPlayerCurrentTime: () => this.currentTime,\n reportEngagementInteraction: (ssaiEngagementInteractionData) => {\n analytics.sendSsaiEngagementAdSample(ssaiEngagementInteractionData);\n },\n reportPlaybackInteraction: (timestamp: number, playerCurrentTime: number) => {\n // Because ssai playback interaction can happen before Ssai Service is active (e.g. first ssai startAd call),\n // we need to manually mark sample as triggered by ssai\n //\n // This is also including the last sample marking, before a ssai ad block (due to ssai being spiky by design)\n this.stateMachine.sendPlayingSample(timestamp, playerCurrentTime, true);\n },\n });\n\n const requestTracking = new HttpRequestTracking([this.httpRequestTrackingAdapter]);\n const errorDetailTracking = new ErrorDetailTracking(\n analytics.errorDetailTrackingSettingsProvider,\n new ErrorDetailBackend(analytics.errorDetailTrackingSettingsProvider.collectorConfig),\n [analytics.errorDetailSubscribable],\n requestTracking,\n );\n return [errorDetailTracking];\n }\n\n override resetSourceRelatedState(): void {\n this.ssaiService.resetSourceRelatedState();\n super.resetSourceRelatedState();\n }\n\n getPlayerVersion = () => this.player.version ?? 'unknown';\n getPlayerName = () => Player.BITMOVIN;\n getPlayerTech = () => this.player.getPlayerType() ?? 'unknown';\n getAutoPlay(): boolean {\n return this.player.autoplay ?? false;\n }\n override getDrmPerformanceInfo = (): DrmPerformanceInfo | undefined => this.drmPerformanceInfo;\n getCurrentPlaybackInfo(): PlaybackInfo {\n const container = this.player.getContainer();\n const info: PlaybackInfo = {\n ...super.getCommonPlaybackInfo(),\n size: this.player.getViewMode() === ViewMode.Fullscreen ? PlayerSize.Fullscreen : PlayerSize.Window,\n playerTech: this.getPlayerTech(),\n isLive: this.player.isLive(),\n videoDuration: normalizeVideoDuration(this.videoDuration),\n streamFormat: this.player.getStreamType(),\n videoWindowWidth: container?.offsetWidth,\n videoWindowHeight: container?.offsetHeight,\n isMuted: this.player.isMuted(),\n isCasting: this.player.isCasting(),\n audioLanguage: this.player.getAudio()?.lang,\n subtitleEnabled: false,\n droppedFrames: isNotNullish(this.player.getSource()) ? (this.player.getDroppedVideoFrames() ?? 0) : 0,\n };\n\n this.applySubtitleProperties(info);\n this.applyPlaybackQualityProperties(info);\n this.applyCastingProperties(info);\n this.applySourceProperties(info);\n\n if (isNullish(info.streamFormat) || info.streamFormat === 'unknown') {\n // in case we cannot detect the streamFormat directly from\n // the player, we use the stored streamFormat as a fallback\n this.sourceInfoFallbackService.applyStreamFormat(info);\n }\n\n return info;\n }\n override getSegmentInfo(): SegmentInfo[] {\n return this.segmentTracker.getSegments();\n }\n override getDownloadSpeedInfo(): DownloadSpeedInfo {\n return this.speedMeter.getInfo();\n }\n override resetDownloadSpeedInfoMeasures(): void {\n this.speedMeter.reset();\n }\n\n onError(): void {\n this.segmentTracker.reset();\n }\n\n trackLoadstartWithAutoplay(): void {\n if (this.getAutoPlay()) {\n this.eventCallback(Event.LOADSTART_AUTOPLAY, {currentTime: this.currentTime});\n }\n }\n\n private registerPlayerEventListeners() {\n this.player.on(BITMOVIN8_PLAYER_EVENT.SourceUnloaded, (_event: any) => {\n this.segmentTracker.reset();\n this.eventCallback(Event.SOURCE_UNLOADED, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.SourceLoaded, (_event: any) => {\n this._videoCompletionTracker.reset();\n this.videoDuration = this.player.getDuration();\n this._videoCompletionTracker.setVideoDuration(this.player.getDuration() ?? 0);\n this.sourceInfoFallbackService.setStreamFormat(this.player.getStreamType());\n this.eventCallback(Event.SOURCE_LOADED, {});\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.CastStarted, (event: any) => {\n this.eventCallback(Event.START_CAST, event);\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.CastStopped, () => {\n this.eventCallback(Event.END_CAST, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.Play, (e: UserInteractionEvent) => {\n if (e.issuer !== 'ui-seek') {\n this.eventCallback(Event.PLAY, {\n currentTime: this.currentTime,\n });\n }\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.Playing, (e: UserInteractionEvent) => {\n if (e.issuer !== 'advertising-api') {\n this.eventCallback(Event.PLAYING, {\n currentTime: this.currentTime,\n });\n }\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.Paused, (e: UserInteractionEvent) => {\n if (e.issuer !== 'ui-seek') {\n this.eventCallback(Event.PAUSE, {\n currentTime: this.currentTime,\n });\n }\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.TimeChanged, (_event: PlayerEventBase) => {\n if (!this.isAdPlaying) {\n this.lastTrackedCurrentTime = this.player.getCurrentTime();\n }\n this.eventCallback(Event.TIMECHANGED, {\n currentTime: this.lastTrackedCurrentTime,\n });\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.Seek, (e: UserInteractionEvent) => {\n if (this.allowSeeking(e)) {\n this.eventCallback(Event.SEEK, {\n currentTime: this.currentTime,\n });\n }\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.Seeked, () => {\n this.eventCallback(Event.SEEKED, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.StallStarted, () => {\n this.eventCallback(Event.START_BUFFERING, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.StallEnded, () => {\n this.eventCallback(Event.END_BUFFERING, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.AudioPlaybackQualityChanged, (eventData) => {\n const audioQualityChangedData = eventData as AudioPlaybackQualityChangedEvent;\n const sourceQuality = audioQualityChangedData.sourceQuality;\n const targetQuality = audioQualityChangedData.targetQuality;\n\n if (isNullish(targetQuality)) {\n return;\n }\n\n const qualityEventInfo: QualityChangeEvent = {\n type: 'audio',\n bitrate: targetQuality.bitrate,\n currentTime: this.currentTime,\n codec: (targetQuality as any).codec,\n };\n\n // for initial quality changes (no target quality set) we do not want to send a qualitychange sample\n if (\n isNotNullish(sourceQuality) &&\n this.qualityChangeService.shouldAllowAudioQualityChange(targetQuality.bitrate)\n ) {\n this.eventCallback(Event.AUDIO_CHANGE, qualityEventInfo);\n }\n\n this.qualityChangeService.setAudioBitrate(targetQuality.bitrate);\n this.stateMachineCallbacks.updateSampleQualityInfo(qualityEventInfo);\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.VideoPlaybackQualityChanged, (eventData) => {\n const videoQualityChangedData = eventData as VideoPlaybackQualityChangedEvent;\n const sourceQuality = videoQualityChangedData.sourceQuality;\n const targetQuality = videoQualityChangedData.targetQuality;\n\n // if targetQuality is null we just ignore the event\n // this is probably and outlier or the end of a session\n // where we don't want to track quality changes\n if (isNullish(targetQuality)) {\n return;\n }\n\n const qualityEventInfo: QualityChangeEvent = {\n type: 'video',\n width: targetQuality.width,\n height: targetQuality.height,\n bitrate: targetQuality.bitrate,\n currentTime: this.currentTime,\n codec: (targetQuality as any).codec,\n };\n\n // for initial quality changes (no target quality set) we do not want to send a qualitychange sample\n if (\n isNotNullish(sourceQuality) &&\n this.qualityChangeService.shouldAllowVideoQualityChange(targetQuality.bitrate)\n ) {\n this.eventCallback(Event.VIDEO_CHANGE, qualityEventInfo);\n }\n\n this.qualityChangeService.setVideoBitrate(targetQuality.bitrate);\n this.stateMachineCallbacks.updateSampleQualityInfo(qualityEventInfo);\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.ViewModeChanged, (e: any) => {\n if (e.to === 'fullscreen') {\n this.eventCallback(Event.START_FULLSCREEN, {\n currentTime: this.currentTime,\n });\n } else if (e.from === 'fullscreen') {\n this.eventCallback(Event.END_FULLSCREEN, {\n currentTime: this.currentTime,\n });\n }\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.AdStarted, (_event: any) => {\n this.eventCallback(Event.START_AD, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.AdFinished, (_event: any) => {\n this.eventCallback(Event.END_AD, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.AdSkipped, (_event: any) => {\n this.eventCallback(Event.END_AD, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.AdError, (_event: any) => {\n this.eventCallback(Event.END_AD, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.Muted, () => {\n this.eventCallback(Event.MUTE, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.Unmuted, () => {\n this.eventCallback(Event.UN_MUTE, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.Error, (event: any) => {\n this.eventCallback(Event.ERROR, {\n code: event.code,\n message: event.name,\n legacyData: event.data,\n currentTime: this.currentTime,\n originalError: event,\n data: {\n additionalData: tryJSONStringify(event.data),\n },\n });\n if (\n event.code === ErrorCode.BITMOVIN_PLAYER_LICENSING_ERROR.code ||\n event.code === ErrorCode.SETUP_MISSING_LICENSE_WHITELIST.code\n ) {\n this.onLicenseCallFailed.dispatch({});\n }\n this.ssaiService.sendAdEngagementErrorSample(\n {code: event.code, message: event.name, severity: 'CRITICAL'},\n event,\n );\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.PlaybackFinished, () => {\n this.eventCallback(Event.END, {currentTime: this.currentTime});\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.DownloadFinished, (event: any) => {\n if (event.downloadType.indexOf('drm/license/') === 0) {\n this.drmPerformanceInfo = {\n drmType: event.downloadType.replace('drm/license/', ''),\n drmLoadTime: event.downloadTime * 1000,\n };\n }\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.AudioChanged, (_event: any) => {\n this.eventCallback(Event.AUDIOTRACK_CHANGED, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.SubtitleEnabled, (_event: any) => {\n this.eventCallback(Event.SUBTITLE_CHANGE, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.SubtitleDisabled, (_event: any) => {\n this.eventCallback(Event.SUBTITLE_CHANGE, {\n currentTime: this.currentTime,\n });\n });\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.LicenseValidated, (event: any) => {\n if (event.data.analytics && event.data.analytics.key !== undefined) {\n this.onLicenseKeyReceived.dispatch({licenseKey: event.data.analytics.key});\n } else {\n this.onLicenseCallFailed.dispatch({});\n }\n });\n }\n\n private registerUnloadEventListeners() {\n // handler has to be defined as an arrow function to capture the correct \"this\"\n const handleCollectorUnload = () => {\n if (!this.onBeforeUnLoadEvent) {\n this.onBeforeUnLoadEvent = true;\n // we use here the last tracked video time as we cannot be sure if the player is still working at this place\n const currentTime = this.lastTrackedCurrentTime;\n this.eventCallback(Event.UNLOAD, {currentTime});\n }\n this.release();\n };\n\n this.player.on(BITMOVIN8_PLAYER_EVENT.Destroy, handleCollectorUnload);\n this.windowEventTracker.addEventListener('beforeunload', handleCollectorUnload);\n this.windowEventTracker.addEventListener('unload', handleCollectorUnload);\n }\n\n private applySourceProperties(info: PlaybackInfo) {\n const source = this.player.getSource();\n if (isNullish(source)) {\n return;\n }\n\n info.videoTitle = source.title;\n info.mpdUrl = source.dash;\n info.m3u8Url = source.hls;\n\n const progSourceInfo = getSourceInfoFromBitmovinSourceConfig(source.progressive, this.player);\n info.progUrl = progSourceInfo.progUrl;\n if (this.player.getStreamType() === 'progressive') {\n info.videoBitrate = progSourceInfo.progBitrate;\n }\n }\n\n private applySubtitleProperties(info: PlaybackInfo) {\n const enabledSubtitle = this.player.getSubtitleList()?.find((s: any) => s.enabled === true);\n\n info.subtitleEnabled = isNotNullish(enabledSubtitle);\n info.subtitleLanguage = isNotNullish(enabledSubtitle) ? enabledSubtitle.lang : undefined;\n }\n\n private applyPlaybackQualityProperties(info: PlaybackInfo) {\n const videoQuality = this.player.getPlaybackVideoData();\n if (isNotNullish(videoQuality)) {\n info.videoBitrate = videoQuality.bitrate;\n info.videoPlaybackHeight = videoQuality.height;\n info.videoPlaybackWidth = videoQuality.width;\n info.videoCodec = (videoQuality as any).codec;\n }\n\n const audioQuality = this.player.getPlaybackAudioData();\n if (isNotNullish(audioQuality)) {\n info.audioBitrate = audioQuality.bitrate;\n info.audioCodec = (audioQuality as any).codec;\n }\n }\n\n private applyCastingProperties(info: PlaybackInfo) {\n const isCasting = this.player.isCasting() || this.player.isAirplayActive() || false;\n info.isCasting = isCasting;\n if (!isCasting) {\n return;\n }\n\n // AirPlay\n if (this.player.isAirplayActive()) {\n info.castTech = CastTech.AirPlay;\n return;\n }\n\n // Casting Tech from RemoteControlConfig\n const remoteControlConfig = this.player.remoteControlConfig;\n if (isNullish(remoteControlConfig)) {\n return;\n }\n\n switch (remoteControlConfig.type) {\n case 'googlecast':\n info.castTech = CastTech.GoogleCast;\n break;\n case 'websocket':\n info.castTech = CastTech.WebSocket;\n break;\n }\n }\n\n // with this check we ignore seek events which are smaller than the Threshold\n // mainly to ignore keyboard triggered seeks\n private allowSeeking(e: UserInteractionEvent): boolean {\n const seekEvent = e as SeekEvent;\n const seekDifference = Math.abs(seekEvent.position - seekEvent.seekTarget);\n return seekDifference > AnalyticsSettings.ANALYTICS_MIN_SEEK_DIFFERENCE_THRESHOLD;\n }\n\n static create(player: Bitmovin8PlayerProxy, opts?: AnalyticsStateMachineOptions): Bitmovin8InternalAdapter {\n const speedMeter = new SpeedMeterAdapter(player, new DownloadSpeedMeter()).getDownloadSpeedMeter();\n const segmentTracker = new SegmentTrackerAdapter(player, new SegmentTracker()).getSegmentTracker();\n const httpRequestTrackingAdapter = new HttpRequestTrackingAdapter(player);\n const videoCompletionTracker = new VideoCompletionTracker();\n const sourceInfoFallbackService = new SourceInfoFallbackService();\n return new Bitmovin8InternalAdapter(\n player,\n speedMeter,\n segmentTracker,\n videoCompletionTracker,\n httpRequestTrackingAdapter,\n sourceInfoFallbackService,\n opts,\n );\n }\n}\n","import type {PlayerAPI, PlayerConfig, TimeMode} from 'bitmovin-player';\nimport type {PlayerAdvertisingAPI} from 'bitmovin-player/types/advertising/API';\nimport type {PlaybackConfig} from 'bitmovin-player/types/core/PlayerConfigAPI';\nimport type {PlayerSubtitlesAPI} from 'bitmovin-player/types/subtitles/API';\n\nimport type {MaybeReturn} from '../../types/MaybeReturn';\nimport {safeAccess} from '../../utils/objectUtils';\n\nexport class Bitmovin8PlayerProxy {\n constructor(private readonly rawPlayer: PlayerAPI) {}\n\n on: PlayerAPI['on'] = (eventType, callback) => {\n safeAccess(() => this.rawPlayer.on(eventType, callback));\n };\n\n getCurrentTime: MaybeReturn<PlayerAPI['getCurrentTime']> = (mode?: TimeMode) =>\n safeAccess(() => this.rawPlayer.getCurrentTime(mode));\n\n getDuration: MaybeReturn<PlayerAPI['getDuration']> = () => safeAccess(() => this.rawPlayer.getDuration());\n\n get version(): PlayerAPI['version'] | undefined {\n return safeAccess(() => this.rawPlayer.version);\n }\n\n getPlayerType: MaybeReturn<PlayerAPI['getPlayerType']> = () => safeAccess(() => this.rawPlayer.getPlayerType());\n\n getViewMode: MaybeReturn<PlayerAPI['getViewMode']> = () => safeAccess(() => this.rawPlayer.getViewMode());\n\n getContainer: MaybeReturn<PlayerAPI['getContainer']> = () => safeAccess(() => this.rawPlayer.getContainer());\n\n isLive: MaybeReturn<PlayerAPI['isLive']> = () => safeAccess(() => this.rawPlayer.isLive());\n\n getStreamType: MaybeReturn<PlayerAPI['getStreamType']> = () => safeAccess(() => this.rawPlayer.getStreamType());\n\n isMuted: MaybeReturn<PlayerAPI['isMuted']> = () => safeAccess(() => this.rawPlayer.isMuted());\n\n isCasting: MaybeReturn<PlayerAPI['isCasting']> = () => safeAccess(() => this.rawPlayer.isCasting());\n\n isAirplayActive: MaybeReturn<PlayerAPI['isAirplayActive']> = () => safeAccess(() => this.rawPlayer.isAirplayActive());\n\n getAudio: MaybeReturn<PlayerAPI['getAudio']> = () => safeAccess(() => this.rawPlayer.getAudio());\n\n getSource: MaybeReturn<PlayerAPI['getSource']> = () => safeAccess(() => this.rawPlayer.getSource());\n\n getDroppedVideoFrames: MaybeReturn<PlayerAPI['getDroppedVideoFrames']> = () =>\n safeAccess(() => this.rawPlayer.getDroppedVideoFrames());\n\n getPlaybackVideoData: MaybeReturn<PlayerAPI['getPlaybackVideoData']> = () =>\n safeAccess(() => this.rawPlayer.getPlaybackVideoData());\n\n getPlaybackAudioData: MaybeReturn<PlayerAPI['getPlaybackAudioData']> = () =>\n safeAccess(() => this.rawPlayer.getPlaybackAudioData());\n\n getConfig: MaybeReturn<PlayerAPI['getConfig']> = () => safeAccess(() => this.rawPlayer.getConfig());\n\n get remoteControlConfig(): PlayerConfig['remotecontrol'] | undefined {\n return this.getConfig()?.remotecontrol;\n }\n\n getSubtitleList: MaybeReturn<PlayerSubtitlesAPI['list']> = () => safeAccess(() => this.rawPlayer.subtitles?.list());\n\n isLinearAdActive: MaybeReturn<PlayerAdvertisingAPI['isLinearAdActive']> = () =>\n safeAccess(() => this.rawPlayer.ads?.isLinearAdActive());\n\n getActiveAd: MaybeReturn<PlayerAdvertisingAPI['getActiveAd']> = () =>\n safeAccess(() => this.rawPlayer.ads?.getActiveAd());\n\n getAdModuleInfo: MaybeReturn<PlayerAdvertisingAPI['getModuleInfo']> = () =>\n safeAccess(() => this.rawPlayer.ads?.getModuleInfo());\n\n get autoplay(): PlaybackConfig['autoplay'] | undefined {\n return this.getConfig()?.playback?.autoplay;\n }\n}\n","import type {\n Ad as PlayerAd,\n AdBreak as PlayerAdBreak,\n AdBreakConfig as PlayerAdBreakConfig,\n AdTagConfig as PlayerAdTagConfig,\n ErrorEvent as PlayerErrorEvent,\n PlayerEventBase,\n LinearAd as PlayerLinearAd,\n VastAdData as PlayerVastAdData,\n} from 'bitmovin-player';\n\nimport type {AdBreakInfo} from '../../../types/ads/AdBreakInfo';\nimport type {AdInfo} from '../../../types/ads/AdInfo';\nimport {isNotNullish, isNullish} from '../../../utils/Utils';\nimport type {AdErrorPayload} from '../../internal/ads/AdModuleAPI';\n\nexport function mapBitmovinAdError(event: PlayerEventBase, activeAdId?: string): AdErrorPayload {\n const adErrorPayload: AdErrorPayload = {\n activeAdId,\n };\n\n const errorEvent = event as PlayerErrorEvent;\n const errorData = errorEvent.data;\n if (isNotNullish(errorData)) {\n adErrorPayload.code = errorData.code || errorEvent.code;\n adErrorPayload.message = errorData.message || errorEvent.name;\n\n if ('adBreak' in errorData || 'adConfig' in errorData) {\n const adInfo = errorData.adBreak ?? errorData.adConfig;\n adErrorPayload.adBreakInfo = mapBitmovinAdBreak(adInfo);\n }\n }\n\n return adErrorPayload;\n}\n\nexport function mapBitmovinAd(ad: PlayerAd): AdInfo {\n const adInfo: AdInfo = {\n id: ad.id,\n isLinear: ad.isLinear,\n clickThroughUrl: ad.clickThroughUrl,\n width: ad.width,\n height: ad.height,\n };\n\n const linearAd = ad.isLinear ? (ad as PlayerLinearAd) : undefined;\n if (isNotNullish(linearAd)) {\n adInfo.duration = linearAd.duration;\n adInfo.skippable = isNotNullish(linearAd.skippableAfter);\n adInfo.skippableAfter = linearAd.skippableAfter;\n adInfo.mediaUrl = linearAd.mediaFileUrl;\n }\n\n const vastData = ad.data as PlayerVastAdData | undefined;\n if (isNotNullish(vastData)) {\n adInfo.bitrate = vastData.bitrate;\n adInfo.mimeType = vastData.mimeType;\n adInfo.vastData = {\n adSystem: vastData.adSystem?.name,\n advertiserName: vastData.advertiser?.name,\n apiFramework: vastData.apiFramework,\n creativeAdId: vastData.creative?.adId,\n creativeId: vastData.creative?.id,\n universalAdIdRegistry: vastData.creative?.universalAdId?.idRegistry,\n universalAdIdValue: vastData.creative?.universalAdId?.value,\n adDescription: vastData.adDescription,\n adTitle: vastData.adTitle,\n wrapperAdsCount: vastData.wrapperAdIds?.length ?? 0,\n surveyUrl: vastData.survey?.uri,\n minSuggestedDuration: vastData.minSuggestedDuration,\n };\n }\n\n return adInfo;\n}\n\nexport function mapBitmovinAdBreak(adConfig: PlayerAdBreak | PlayerAdTagConfig): AdBreakInfo {\n const adBreakInfo: AdBreakInfo = {\n replaceContentDuration: adConfig.replaceContentDuration,\n fallbackIndex: getFallbackIndex(adConfig),\n };\n\n // AdBreak\n adBreakInfo.id = 'id' in adConfig ? adConfig.id : undefined;\n adBreakInfo.scheduleTime = 'scheduleTime' in adConfig ? adConfig.scheduleTime : undefined;\n\n // AdTagConfig / AdBreakConfig\n const adTagConfig = adConfig as PlayerAdTagConfig;\n const {tagUrl, tagType} = resolveEffectiveAdTag(adTagConfig);\n adBreakInfo.tagUrl = tagUrl;\n adBreakInfo.tagType = tagType;\n adBreakInfo.persistent = 'persistent' in adConfig ? adTagConfig.persistent : undefined;\n adBreakInfo.position = 'position' in adConfig ? (adConfig as PlayerAdBreakConfig).position : undefined;\n adBreakInfo.preloadOffset = 'preloadOffset' in adConfig ? (adConfig as PlayerAdBreakConfig).preloadOffset : undefined;\n\n return adBreakInfo;\n}\n\n/**\n * Resolves the effective ad tag URL and type, applying the fallback tag\n * if `fallbackIndex` indicates a fallback is active.\n */\nexport function resolveEffectiveAdTag(adTagConfig: PlayerAdTagConfig): {tagType?: string; tagUrl?: string} {\n if (isNullish(adTagConfig.tag)) {\n return {};\n }\n\n const fallbackIndex = getFallbackIndex(adTagConfig);\n const directTag = {tagType: adTagConfig.tag.type, tagUrl: adTagConfig.tag.url};\n if (isNullish(adTagConfig.fallbackTags) || fallbackIndex <= 0 || adTagConfig.fallbackTags.length < fallbackIndex) {\n return directTag;\n }\n\n const fallbackTag = adTagConfig.fallbackTags[fallbackIndex - 1];\n return {tagType: fallbackTag.type, tagUrl: fallbackTag.url};\n}\n\n/**\n * Maps the Bitmovin player's internal `currentFallbackIndex` to the analytics `adFallbackIndex`.\n *\n * Player convention (ImaAdBreak.currentFallbackIndex):\n * - absent/null → no fallback tracking (treat as primary ad)\n * - `0` → primary ad is playing\n * - `1` → first fallback tag (`fallbackTags[0]`) is playing\n * - `2` → second fallback tag (`fallbackTags[1]`) is playing\n *\n * Analytics convention matches 1:1, so the mapping is an identity for defined values.\n * Both absent and `0` map to `adFallbackIndex = 0` (primary ad, no fallback used).\n */\nexport function getFallbackIndex(adConfig: PlayerAdBreak | PlayerAdTagConfig): number {\n const rawFallbackIndex = (adConfig as any).currentFallbackIndex;\n\n if (isNullish(rawFallbackIndex)) {\n return 0;\n }\n\n return rawFallbackIndex;\n}\n","import type {SsaiAdBreakMetadata} from '../../api/AdapterAPI';\nimport {isNotNullish} from '../../utils/Utils';\n\n/**\n * Utility function to sanitize the adPosition value in the SsaiAdBreakMetadata object passed to Bitmovin8Adapter.\n *\n * Needed, because we have introduced SSAI API in `Bitmovin8Adapter` in v2.39.0, without doing proper validation of\n * the passed adPosition value and customer started to use us with invalid values (having `-` in string in JavaScript).\n * Because we did not want to break the customer's implementation, we decided to sanitize the value to the correct one.\n *\n * @deprecated This function will be removed in v3\n */\nexport const sanitizeBitmovin8AdapterSsaiAdBreakMetadataAdPosition = <T = unknown>(anything: T): T => {\n const maybeSsaiAdBreakMetadata = anything as SsaiAdBreakMetadata;\n\n if (isNotNullish(maybeSsaiAdBreakMetadata?.adPosition)) {\n if ((maybeSsaiAdBreakMetadata.adPosition as string) === 'pre-roll') {\n maybeSsaiAdBreakMetadata.adPosition = 'preroll';\n } else if ((maybeSsaiAdBreakMetadata.adPosition as string) === 'mid-roll') {\n maybeSsaiAdBreakMetadata.adPosition = 'midroll';\n } else if ((maybeSsaiAdBreakMetadata?.adPosition as string) === 'post-roll') {\n maybeSsaiAdBreakMetadata.adPosition = 'postroll';\n }\n }\n\n return maybeSsaiAdBreakMetadata as T;\n};\n","/*!\n * This file was created to avoid \"values imports\" (constants/enums/classes/etc.) from the `bitmovin-player@8.252.0`\n * which would include the whole package in our distribution code.\n *\n * We should still use \"type imports\" (`import type {}`) from the library!\n *\n * Unit test should cover \"copies of the library values\" to be sure they are up to date with the library!\n */\nimport type {PlayerEvent} from 'bitmovin-player';\n\n/**\n * Map of Bitmovin Player events that we listen to, each should be of type {@link PlayerEvent}.\n *\n * Why: This way, we don't need to import string enum {@link PlayerEvent} from 'bitmovin-player' directly,\n * aka. compile/include it (as value) in our distribution code\n *\n * @see https://github.com/bitmovin-engineering/bitdash/blob/v8.252.0/src/core/Events.ts\n */\nexport const BITMOVIN8_PLAYER_EVENT = {\n AdBreakFinished: 'adbreakfinished' as PlayerEvent.AdBreakFinished,\n AdBreakStarted: 'adbreakstarted' as PlayerEvent.AdBreakStarted,\n AdClicked: 'adclicked' as PlayerEvent.AdClicked,\n AdError: 'aderror' as PlayerEvent.AdError,\n AdFinished: 'adfinished' as PlayerEvent.AdFinished,\n AdManifestLoaded: 'admanifestloaded' as PlayerEvent.AdManifestLoaded,\n AdQuartile: 'adquartile' as PlayerEvent.AdQuartile,\n AdSkipped: 'adskipped' as PlayerEvent.AdSkipped,\n AdStarted: 'adstarted' as PlayerEvent.AdStarted,\n AudioChanged: 'audiochanged' as PlayerEvent.AudioChanged,\n AudioPlaybackQualityChanged: 'audioplaybackqualitychanged' as PlayerEvent.AudioPlaybackQualityChanged,\n CastStarted: 'caststarted' as PlayerEvent.CastStarted,\n CastStopped: 'caststopped' as PlayerEvent.CastStopped,\n Destroy: 'destroy' as PlayerEvent.Destroy,\n DownloadFinished: 'downloadfinished' as PlayerEvent.DownloadFinished,\n Error: 'error' as PlayerEvent.Error,\n LicenseValidated: 'licensevalidated' as PlayerEvent.LicenseValidated,\n Muted: 'muted' as PlayerEvent.Muted,\n Paused: 'paused' as PlayerEvent.Paused,\n Play: 'play' as PlayerEvent.Play,\n PlaybackFinished: 'playbackfinished' as PlayerEvent.PlaybackFinished,\n Playing: 'playing' as PlayerEvent.Playing,\n Seek: 'seek' as PlayerEvent.Seek,\n Seeked: 'seeked' as PlayerEvent.Seeked,\n SegmentPlayback: 'segmentplayback' as PlayerEvent.SegmentPlayback,\n SourceLoaded: 'sourceloaded' as PlayerEvent.SourceLoaded,\n SourceUnloaded: 'sourceunloaded' as PlayerEvent.SourceUnloaded,\n StallEnded: 'stallended' as PlayerEvent.StallEnded,\n StallStarted: 'stallstarted' as PlayerEvent.StallStarted,\n TimeChanged: 'timechanged' as PlayerEvent.TimeChanged,\n SubtitleDisabled: 'subtitledisabled' as PlayerEvent.SubtitleDisabled,\n SubtitleEnabled: 'subtitleenabled' as PlayerEvent.SubtitleEnabled,\n Unmuted: 'unmuted' as PlayerEvent.Unmuted,\n VideoPlaybackQualityChanged: 'videoplaybackqualitychanged' as PlayerEvent.VideoPlaybackQualityChanged,\n ViewModeChanged: 'viewmodechanged' as PlayerEvent.ViewModeChanged,\n} as const;\n","import type {DownloadFinishedEvent} from 'bitmovin-player';\n\nimport {EventDispatcher, Subscribable} from '../../../core/EventDispatcher';\nimport {HttpRequestType} from '../../../features/httprequesttracking/HttpRequestType';\nimport {OnDownloadFinishedEventObject} from '../../../features/httprequesttracking/OnDownloadFinishedEventObject';\nimport {objectValues} from '../../../utils/objectUtils';\nimport {calculateTimeWithUndefined, getCurrentTimestamp} from '../../../utils/Utils';\nimport {Bitmovin8PlayerProxy} from '../Bitmovin8PlayerProxy';\n\nimport {BITMOVIN8_PLAYER_EVENT} from './Bitmovin8PlayerTypes';\n\nexport class HttpRequestTrackingAdapter implements Subscribable<OnDownloadFinishedEventObject> {\n private eventDispatcher = new EventDispatcher<OnDownloadFinishedEventObject>();\n\n constructor(player: Bitmovin8PlayerProxy) {\n player.on(BITMOVIN8_PLAYER_EVENT.DownloadFinished, (event) =>\n this.onDownloadFinished(event as DownloadFinishedEvent),\n );\n }\n\n subscribe(callback: (args: OnDownloadFinishedEventObject) => void): () => void {\n return this.eventDispatcher.subscribe(callback);\n }\n\n unsubscribe(callback: (args: OnDownloadFinishedEventObject) => void) {\n this.eventDispatcher.unsubscribe(callback);\n }\n\n private onDownloadFinished(event?: DownloadFinishedEvent) {\n this.eventDispatcher.dispatch({\n httpRequest: {\n downloadTime: calculateTimeWithUndefined(event?.downloadTime) ?? 0,\n httpStatus: event?.httpStatus ?? 0,\n success: event?.success ?? false,\n timestamp: getCurrentTimestamp(),\n url: event?.url,\n size: event?.size,\n timeToFirstByte: calculateTimeWithUndefined(event?.timeToFirstByte),\n type: mapHttpRequestType(event?.downloadType),\n },\n });\n }\n}\n\n/**\n * Map Bitmovin8 player `HttpRequestType` to the analytics {@link HttpRequestType} enum, defaulting to `UNKNOWN` for unmapped values.\n */\nexport function mapHttpRequestType(httpRequestTypeValue: string | undefined): HttpRequestType {\n if (objectValues(HttpRequestType).includes(httpRequestTypeValue)) {\n return httpRequestTypeValue as HttpRequestType;\n }\n // For unmapped values (including undefined), return UNKNOWN. This ensures that the analytics system receives a valid\n // enum value and can handle it appropriately.\n // The unmapped value itself should be detected by unit tests, once the bitmovin player dependency is updated in the project.\n return HttpRequestType.UNKNOWN;\n}\n","import {SegmentTracker} from '../../../core/SegmentTracker';\nimport {SegmentInfo} from '../../../types/SegmentInfo';\nimport * as Utils from '../../../utils/Utils';\nimport {Bitmovin8PlayerProxy} from '../Bitmovin8PlayerProxy';\n\nimport {BITMOVIN8_PLAYER_EVENT} from './Bitmovin8PlayerTypes';\n\ninterface DownloadFinishedEvent {\n attempt?: number;\n downloadType?: string;\n httpStatus: number;\n mimeType?: string;\n success: boolean;\n timestamp: number;\n type: string;\n url: string;\n}\n\ninterface SegmentPlaybackEvent {\n duration?: number;\n mediaInfo?: any;\n mimeType?: string;\n playbackTime?: number;\n representationId?: string;\n timestamp?: number;\n type?: string;\n uid?: string;\n url?: string;\n}\n\nexport class SegmentTrackerAdapter {\n private segmentTracker: SegmentTracker;\n\n constructor(player: Bitmovin8PlayerProxy, segmentTracker: SegmentTracker) {\n this.segmentTracker = segmentTracker;\n\n player.on(BITMOVIN8_PLAYER_EVENT.DownloadFinished, (event) => this.handleOnDownloadFinishEvent(event));\n player.on(BITMOVIN8_PLAYER_EVENT.SegmentPlayback, (event) => this.handleSegmentPlaybackEvent(event));\n }\n\n getSegmentTracker(): SegmentTracker {\n return this.segmentTracker;\n }\n\n handleOnDownloadFinishEvent(event: any & DownloadFinishedEvent) {\n if (event.downloadType.indexOf('media/video') === 0) {\n const url = event.url;\n const segment: SegmentInfo = {\n name: Utils.getURLResourceName(url),\n url,\n timestamp: event.timestamp,\n };\n this.segmentTracker.addSegment(segment);\n }\n }\n\n handleSegmentPlaybackEvent = (event: any & SegmentPlaybackEvent) => {\n this.segmentTracker.removeSegment(event.url);\n };\n}\n","import {DownloadSpeedMeter} from '../../../core/DownloadSpeedMeter';\nimport {Bitmovin8PlayerProxy} from '../Bitmovin8PlayerProxy';\n\nimport {BITMOVIN8_PLAYER_EVENT} from './Bitmovin8PlayerTypes';\n\nexport class SpeedMeterAdapter {\n private meter: DownloadSpeedMeter;\n\n constructor(player: Bitmovin8PlayerProxy, meter: DownloadSpeedMeter) {\n this.meter = meter;\n player.on(BITMOVIN8_PLAYER_EVENT.DownloadFinished, (event) => this.handleOnDownloadFinishEvent(event));\n }\n\n getDownloadSpeedMeter(): DownloadSpeedMeter {\n return this.meter;\n }\n\n handleOnDownloadFinishEvent(event: any) {\n if (!event.success) {\n return;\n }\n if (event.downloadType.indexOf('media/video') === 0) {\n this.meter.addMeasurement({\n duration: event.downloadTime,\n size: event.size,\n timeToFirstByte: event.timeToFirstByte,\n timestamp: new Date(),\n httpStatus: event.httpStatus,\n });\n }\n }\n}\n","import {Bitmovin8Adapter} from './Bitmovin8Adapter';\n\n/*\n * @see https://github.com/bitmovin-engineering/bitdash/blob/ccd3227dac82d1416a471711b40ee0f65d7f9ddb/src/ModuleDefinition.ts#L17\n */\nexport const PlayerModule = {\n name: 'analytics',\n module: {\n Analytics: Bitmovin8Adapter,\n },\n hooks: {\n setup: (module: any, player: any) => {\n const config = player.getConfig();\n const isConfigMissing = !config;\n const isAnalyticsDisabled = config?.analytics === false;\n\n if (isConfigMissing || isAnalyticsDisabled) {\n return Promise.resolve();\n }\n\n const analyticsBitmovin8Adapter = module.Analytics;\n const analyticsModuleInstance = new analyticsBitmovin8Adapter(player);\n return Promise.resolve(analyticsModuleInstance);\n },\n },\n} as const;\n","import type {AnalyticsConfig} from 'bitmovin-player';\n\nimport type {AdapterAPI} from '../../api/AdapterAPI';\nimport {Analytics} from '../../core/Analytics';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {VERSION} from '../../utils/Version';\n\nimport {BitmovinPwxInternalAdapter} from './BitmovinPwxInternalAdapter';\nimport type {AnalyticsContext} from './Types';\n\nexport class BitmovinPwxAdapter implements AdapterAPI {\n private readonly internalAdapter: BitmovinPwxInternalAdapter;\n private readonly analytics: Analytics;\n\n constructor(context: AnalyticsContext, config: AnalyticsConfig) {\n // no need to check for player augmentation, if analytics has already been initialized on this player instance,\n // because this adapter is created only once with BitmovinPwxAnalyticsPackage\n\n const sanitizedConfig = sanitizeAnalyticsConfig(config);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n throw new Error('Failed to create BitmovinPwxAdapter: domain is required');\n }\n\n guardAgainstDuplicatedUserId(sanitizedConfig);\n\n this.internalAdapter = new BitmovinPwxInternalAdapter(context);\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n }\n\n dispose() {\n this.internalAdapter.release();\n }\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId = () => this.analytics.getCurrentImpressionId();\n\n getUserId = () => this.analytics.getUserId();\n\n setCustomData = (values: CustomDataValues) => this.internalAdapter.setCustomData(values);\n\n setCustomDataOnce = (values: CustomDataValues) => this.analytics.setCustomDataOnce(values);\n\n sourceChange = (_config: AnalyticsConfig) => {\n // Every time a source is added, a new instance of analytics package is triggered. So technically there are\n // no source changes. Also, a single player instance can handle infinite amount of sources at once.\n //\n // We are aware, at the moment we are handling it as \"every source = one session\". We will need to do\n // some additional work in the future (once we figure out how this part should work) to handle multiple\n // sources in one session (e.g. ads).\n //\n // What we mean by \"no source changes\", is that you do not have API to change \"current playing\" source\n // to something else. You would need to add new source and remove old one (or keep it). One instance can\n // have infinite amount of sources, each source for us is a new analytics session (for now, in certain cases\n // they should be tied together - e.g. ads)\n //\n // @see https://github.com/bitmovin-engineering/bitmovin-analytics-collector/pull/867#discussion_r1660699646\n\n throw new Error('Method not implemented.');\n };\n}\n","import type {EmptyObject} from '@bitmovin/player-web-x/framework-types/BaseTypes';\nimport type {AnyPackage} from '@bitmovin/player-web-x/framework-types/package-api/PackageApi';\n\nimport {tryJSONStringify} from '../../utils/Utils';\n\nimport {BitmovinPwxAdapter} from './BitmovinPwxAdapter';\nimport {\n BundleExportNames,\n CoreExportNames,\n PlaybackApiEventsPackageExportNames,\n SourceExportNames,\n SourcesApiExportNames,\n} from './ExportNames';\nimport type {AnalyticsContext, CreatePackage} from './Types';\n\n/**\n * Copy&pasted from `@bitmovin/player-web-x` !\n *\n * We need `createPackage` function from util file to create a PWX package, but because `@bitmovin/player-web-x` is not\n * ES5 compliant, we had to copy it here.\n *\n * @see https://github.com/bitmovin-engineering/player-web-phoenix-framework/blob/main/src/package-api/PackageApiUtils.ts#L9\n */\nconst createPackageFn: CreatePackage = (name, onAdd, dependencies) => {\n (onAdd as any)._name = name;\n\n return {\n onAdd,\n dependencies,\n } as unknown as AnyPackage<EmptyObject>;\n};\n\nexport const BitmovinPwxAnalyticsPackage = createPackageFn(\n 'analytics-package',\n (_, baseContext) => {\n /*\n Player Web X analytics package.\n It is being run for every source added - so there is no actual source switching per analytics instance.\n Package is instantiating the adapter, and making sure it is disposed once package is aborted.\n */\n\n const {EventListenerEffectFactory, StateEffectFactory} = baseContext.registry.get(CoreExportNames.CoreEffects);\n const context = baseContext.using(EventListenerEffectFactory, StateEffectFactory) as unknown as AnalyticsContext;\n const logger = context.registry.get(BundleExportNames.Logger);\n const source = context.registry.get(SourceExportNames.SourceState);\n const playerConfig = context.registry.get(BundleExportNames.PlayerConfig);\n const analyticsConfig = playerConfig.analytics ?? {};\n // if the player key is not set in analytics config, use the one from player config\n analyticsConfig.playerKey = analyticsConfig.playerKey ?? playerConfig.key;\n\n logger.log(`Applying analytics config ${tryJSONStringify(analyticsConfig)}`);\n const adapter = new BitmovinPwxAdapter(context, analyticsConfig);\n\n logger.log(`Analytics package initializing for \"${source.url}\"...`);\n\n const listener = () => {\n context.abortSignal.removeEventListener('abort', listener);\n logger.log(`Analytics package disposing for \"${source.url}\"`);\n adapter.dispose();\n };\n\n context.abortSignal.addEventListener('abort', listener);\n },\n [\n BundleExportNames.Logger,\n BundleExportNames.PlayerConfig,\n CoreExportNames.Constants,\n CoreExportNames.CoreEffects,\n CoreExportNames.CoreStateAtoms,\n SourceExportNames.SourceState,\n SourcesApiExportNames.SourceEventBus,\n PlaybackApiEventsPackageExportNames.PlaybackEvent,\n ],\n) as any; // we cast package as any to prevent DTS bundle type merging\n","import {StateMachine} from 'javascript-state-machine';\n\nimport {AnalyticsStateMachine} from '../../analyticsStateMachines/AnalyticsStateMachine';\nimport {\n customStateMachineErrorCallback,\n getAllStatesBut,\n logMissingCallbackWarning,\n logStateMachineTransition,\n on,\n} from '../../analyticsStateMachines/stateMachineUtils';\nimport type {HeartbeatService} from '../../core/HeartbeatService';\nimport {Event, JSM_INITIAL_EVENT} from '../../enums/Event';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {StateMachineCallbacks} from '../../types/StateMachineCallbacks';\nimport {EventDebugging} from '../../utils/EventDebugging';\nimport {logger} from '../../utils/Logger';\nimport {isNumber} from '../../utils/numberUtils';\nimport {isFunction} from '../../utils/Utils';\n\nexport enum State {\n END = 'END',\n ERROR = 'ERROR',\n PAUSE = 'PAUSE',\n PLAYING = 'PLAYING',\n READY = 'READY',\n SETUP = 'SETUP',\n SOURCE_LOADED = 'SOURCE_LOADED',\n STARTUP = 'STARTUP',\n VIDEOSTART_FAILED = 'VIDEOSTART_FAILED',\n}\n\nexport class BitmovinPwxAnalyticsStateMachine extends AnalyticsStateMachine {\n private enabledDebugging = false;\n private debuggingStates: EventDebugging[] = [];\n\n constructor(\n stateMachineCallbacks: StateMachineCallbacks,\n playingHeartbeatService: HeartbeatService,\n opts: AnalyticsStateMachineOptions,\n ) {\n super(stateMachineCallbacks, playingHeartbeatService, opts);\n }\n\n override createStateMachine(opts: AnalyticsStateMachineOptions): StateMachine {\n return StateMachine.create({\n // custom initial state and custom JSM initial event name\n // initial event is used by JSM for the initial state transition 'none' -> 'SETUP'\n initial: {state: State.SETUP, event: JSM_INITIAL_EVENT},\n error: customStateMachineErrorCallback,\n events: [\n {\n name: Event.SOURCE_LOADED,\n from: [State.SETUP, State.ERROR],\n to: State.READY,\n },\n on(Event.READY).stayIn(State.READY),\n on(Event.PAUSE).stayIn(State.READY),\n on(Event.TIMECHANGED).stayIn(State.READY),\n {name: Event.PLAY, from: State.READY, to: State.STARTUP},\n {name: Event.PLAYING, from: State.READY, to: State.PLAYING},\n\n on(Event.PLAY).stayIn(State.STARTUP),\n on(Event.PLAYING).stayIn(State.STARTUP),\n {name: Event.TIMECHANGED, from: State.STARTUP, to: State.PLAYING},\n on(Event.READY).stayIn(State.STARTUP),\n {name: Event.PAUSE, from: State.STARTUP, to: State.READY},\n\n on(Event.PLAYING).stayIn(State.PLAYING),\n on(Event.TIMECHANGED).stayIn(State.PLAYING),\n\n {name: Event.PAUSE, from: State.PLAYING, to: State.PAUSE},\n on(Event.TIMECHANGED).stayIn(State.PAUSE),\n on(Event.PAUSE).stayIn(State.PAUSE),\n {name: Event.PLAY, from: State.PAUSE, to: State.PLAYING},\n {name: Event.PLAYING, from: State.PAUSE, to: State.PLAYING},\n\n {name: Event.END, from: State.PLAYING, to: State.END},\n {name: Event.END, from: State.PAUSE, to: State.END},\n // when replay is triggered (play button is clicked once video finished),\n // we should start a new session, so we should go to STARTUP state\n {name: Event.PLAYING, from: State.END, to: State.STARTUP},\n\n on(Event.TIMECHANGED).stayIn(State.END),\n on(Event.END).stayIn(State.END),\n\n {name: Event.PLAY, from: State.END, to: State.STARTUP},\n {name: Event.ERROR, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.ERROR, from: getAllStatesBut([State.STARTUP], State), to: State.ERROR},\n\n {name: Event.UNLOAD, from: getAllStatesBut([State.STARTUP], State), to: State.END},\n {name: Event.UNLOAD, from: [State.STARTUP], to: State.VIDEOSTART_FAILED},\n ],\n\n // Keep callbacks sorted by order in which they are called by JSM library (and after order, sorted by name)\n //\n // Do not use convenience, shortened callbacks\n // - instead of `onEVENT` use `onafterEVENT`\n // - instead of `onSTATE` use `onenterSTATE`\n //\n // see: https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#callbacks\n callbacks: {\n [`onleave${State.PLAYING}`]: () => {\n this.playingHeartbeatService.stopHeartbeat();\n },\n\n onleavestate: (event, from, to, eventTimestamp, eventData) => {\n logStateMachineTransition('LEAVE', event, from, to);\n\n // Skip this JSM callback for JSM initial event\n // This event is fired when the state machine is constructed,\n // to transition us from 'none' to custom initial 'SETUP' state\n if (event === JSM_INITIAL_EVENT) {\n return;\n }\n\n // Skip this JSM callback when an JSM event without a timestamp is called,\n // because it would cause NPE in analytics code (state duration calculation etc.).\n // This probably has happened because the state machine was not used correctly,\n // aka. JSM event was not called via `callEvent` method as it should be!\n if (!eventTimestamp) {\n return;\n }\n\n this.addStatesToLog(event, from, to, eventTimestamp, eventData);\n const stateDuration = eventTimestamp - this.onEnterStateTimestamp;\n const isStartup = from === State.STARTUP && to === State.PLAYING;\n this.maybeSetOrClearVideoStartTimeouts(from, to);\n\n if (isStartup) {\n this.stateMachineCallbacks.startup(stateDuration, State.STARTUP.toLowerCase());\n }\n\n const lowerCaseFrom = String(from).toLowerCase();\n if (event === Event.UNLOAD) {\n this.stateMachineCallbacks.unload(stateDuration, lowerCaseFrom);\n } else if (from === State.SETUP) {\n // Setting Player Startup Time to fixed value of 1ms.\n // We can not get correct Player Startup Time from PWX player, because it does not have an \"onInitialized\" event\n this.stateMachineCallbacks.setup(1, State.SETUP.toLowerCase());\n } else if (event === Event.PAUSE && from === State.STARTUP && to === State.READY) {\n // fired PAUSE event in STARTUP state indicates we are moving back to READY,\n // so we have to clean setTimeout, and we should not call any stateMachineCallbacks\n this.clearVideoStartTimeout();\n } else if (from !== State.ERROR && !isStartup) {\n // Default \"onleavestate\" state machine callback\n //\n // Every time, when we leave a state, we should try to call \"state\" callback,\n // to be able to make \"a cut\" and send analytics sample (if necessary)\n const defaultStateMachineCallbackFn = this.stateMachineCallbacks[lowerCaseFrom];\n if (isFunction(defaultStateMachineCallbackFn)) {\n // a try-catch block to add more resilience against callback errors\n try {\n defaultStateMachineCallbackFn(stateDuration, lowerCaseFrom, eventData);\n } catch (e) {\n logger.error('Exception occurred in State Machine callback ' + lowerCaseFrom, eventData, e);\n }\n } else {\n // if callback is not defined, log a warning to indicate to the developer that\n // - a new callback function needs to be implemented to relay on this default state machine callback\n // - or if no callback is needed, we should\n // - early return from this JSM callback\n // - or add this state to the ignored list\n logMissingCallbackWarning(from, [State.READY]);\n }\n }\n },\n\n [`onenter${State.PLAYING}`]: () => {\n this.playingHeartbeatService.startHeartbeat();\n },\n\n onenterstate: (event, from, to, eventTimestamp, _eventData) => {\n logStateMachineTransition('ENTER', event, from, to);\n\n this.onEnterStateTimestamp = eventTimestamp ?? Date.now();\n // if customer set custom \"start time\" timestamp in AnalyticsStateMachineOptions of adapter constructor,\n // use it and override `onEnterStateTimestamp` during JSM initialization (transition to initial SETUP state)\n if (isNumber(opts.starttime) && event === JSM_INITIAL_EVENT) {\n this.onEnterStateTimestamp = opts.starttime;\n }\n },\n\n [`onafter${Event.ERROR}`]: (_event, _from, _to, _eventTimestamp, eventData) => {\n this.stateMachineCallbacks.error(eventData);\n },\n },\n });\n }\n\n addStatesToLog(\n event: string | undefined,\n from: string | undefined,\n to: string | undefined,\n timestamp: number,\n eventObject: any,\n ) {\n if (this.enabledDebugging) {\n this.debuggingStates.push(new EventDebugging(event, from, to, timestamp, eventObject));\n }\n }\n\n getStates() {\n return this.debuggingStates;\n }\n\n setEnabledDebugging(enabled: boolean) {\n this.enabledDebugging = enabled;\n }\n\n private maybeSetOrClearVideoStartTimeouts(from: string | undefined, to: string | undefined) {\n if (from === State.READY && to === State.STARTUP) {\n this.setVideoStartTimeout();\n } else if (from === State.STARTUP && to === State.PLAYING) {\n this.clearVideoStartTimeout();\n }\n }\n}\n","import type {Analytics} from '../../core/Analytics';\nimport {HeartbeatService} from '../../core/HeartbeatService';\nimport {Event} from '../../enums/Event';\nimport {Player} from '../../enums/Player';\nimport {StreamTypes} from '../../enums/StreamTypes';\nimport {ErrorDetailBackend} from '../../features/errordetails/ErrorDetailBackend';\nimport {ErrorDetailTracking} from '../../features/errordetails/ErrorDetailTracking';\nimport type {Feature} from '../../features/Feature';\nimport type {FeatureConfig} from '../../features/FeatureConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport {normalizeVideoDuration, PlaybackInfo} from '../../types/PlaybackInfo';\nimport {InternalAdapter} from '../internal/InternalAdapter';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {BitmovinPwxAnalyticsStateMachine} from './BitmovinPwxAnalyticsStateMachine';\nimport {\n CoreExportNames,\n PlaybackApiEventsPackageExportNames,\n SourceExportNames,\n SourcesApiExportNames,\n} from './ExportNames';\nimport {AnalyticsContext} from './Types';\n\nconst PWX_ABORT_ERROR_CODE = 1007;\n\nexport class BitmovinPwxInternalAdapter extends InternalAdapter implements InternalAdapterAPI {\n /** Boolean flag to prevent multiple calls of the {@link Event.UNLOAD} event */\n private onBeforeUnLoadEvent = false;\n\n private readonly context: AnalyticsContext;\n\n constructor(context: AnalyticsContext, opts?: AnalyticsStateMachineOptions) {\n super(opts);\n this.context = context;\n const playingHeartbeatService = new HeartbeatService(() => this.currentTime);\n const stateMachine = new BitmovinPwxAnalyticsStateMachine(\n this.stateMachineCallbacks,\n playingHeartbeatService,\n this.opts,\n );\n playingHeartbeatService.setListener(stateMachine);\n this.stateMachine = stateMachine;\n }\n\n private getSource() {\n return this.context.registry.get(SourceExportNames.SourceState);\n }\n\n protected get currentTime(): number {\n return this.getSource().playback.playhead.position;\n }\n\n getAutoPlay(): boolean {\n return this.getSource().config.playback.autoplay;\n }\n\n getCurrentPlaybackInfo(): PlaybackInfo {\n const hls = this.getSource().sourceConfig.resources.filter((v) => v.url.includes('.m3u8'))[0]?.url;\n const dash = this.getSource().sourceConfig.resources.filter((v) => v.url.includes('.mpd'))[0]?.url;\n\n const videoRect = this.getSource().video.element?.getBoundingClientRect();\n const videoWidth = Math.round(videoRect?.width ?? 1);\n const videoHeight = Math.round(videoRect?.height ?? 1);\n\n let streamFormat: StreamTypes | undefined = undefined;\n if (hls) {\n streamFormat = StreamTypes.hls;\n } else if (dash) {\n streamFormat = StreamTypes.dash;\n }\n\n // height, width, codecs and bitrate are fixed until we have quality api\n return {\n ...this.getCommonPlaybackInfo(),\n droppedFrames: 0,\n isMuted: this.getSource().video.element?.muted,\n isLive: this.getSource().stream.type === 'live',\n videoWindowHeight: videoHeight,\n videoWindowWidth: videoWidth,\n videoDuration: normalizeVideoDuration(this.getSource().video.element?.duration),\n videoPlaybackHeight: videoHeight,\n videoPlaybackWidth: videoWidth,\n m3u8Url: hls,\n mpdUrl: dash,\n streamFormat,\n videoCodec: undefined, // not tracked yet\n audioCodec: undefined, // not tracked yet\n videoBitrate: 0, // not tracked yet\n audioBitrate: 0, // not tracked yet\n };\n }\n\n getPlayerName(): string {\n return Player.BITMOVIN_PWX;\n }\n\n getPlayerTech(): string {\n return 'webx:html5';\n }\n\n getPlayerVersion(): string {\n return this.context.registry.get(CoreExportNames.Constants).Version;\n }\n\n initialize(analytics: Analytics): Array<Feature<FeatureConfigContainer, FeatureConfig>> {\n this.registerEventListeners();\n this.registerUnloadEventListeners();\n\n const errorDetailTracking = new ErrorDetailTracking(\n analytics.errorDetailTrackingSettingsProvider,\n new ErrorDetailBackend(analytics.errorDetailTrackingSettingsProvider.collectorConfig),\n [analytics.errorDetailSubscribable],\n undefined,\n );\n\n return [errorDetailTracking];\n }\n\n private registerUnloadEventListeners() {\n let handleCollectorUnload = () => {\n if (!this.onBeforeUnLoadEvent) {\n this.onBeforeUnLoadEvent = true;\n const currentTime = this.context.registry.get(SourceExportNames.SourceState).playback.playhead.position;\n this.eventCallback(Event.UNLOAD, {currentTime});\n }\n this.release();\n };\n handleCollectorUnload = handleCollectorUnload.bind(true);\n\n this.context.abortSignal.addEventListener('abort', handleCollectorUnload);\n this.windowEventTracker.addEventListener('beforeunload', handleCollectorUnload);\n this.windowEventTracker.addEventListener('unload', handleCollectorUnload);\n }\n\n private registerEventListeners() {\n // The context might not be same so a different source event bus is available\n const sourceEventBus = this.context.registry.get(SourcesApiExportNames.SourceEventBus);\n const playbackAtom = this.context.registry.get(SourceExportNames.SourceState).playback;\n const PlaybackEvent = this.context.registry.get(PlaybackApiEventsPackageExportNames.PlaybackEvent);\n\n sourceEventBus.on(PlaybackEvent.Ready, () => {\n this.eventCallback(Event.SOURCE_LOADED, {currentTime: playbackAtom.playhead.position});\n });\n sourceEventBus.on(PlaybackEvent.Play, () => {\n this.eventCallback(Event.PLAY, {currentTime: playbackAtom.playhead.position});\n });\n sourceEventBus.on(PlaybackEvent.Playing, () => {\n this.eventCallback(Event.PLAYING, {currentTime: playbackAtom.playhead.position});\n });\n sourceEventBus.on(PlaybackEvent.Paused, () => {\n this.eventCallback(Event.PAUSE, {currentTime: playbackAtom.playhead.position});\n });\n sourceEventBus.on(PlaybackEvent.TimeChanged, () => {\n this.eventCallback(Event.TIMECHANGED, {currentTime: playbackAtom.playhead.position});\n });\n sourceEventBus.on(PlaybackEvent.VideoAttached, () => {\n this.eventCallback(Event.SOURCE_LOADED, {currentTime: playbackAtom.playhead.position});\n });\n\n sourceEventBus.on(PlaybackEvent.Ended, () => {\n this.eventCallback(Event.END, {currentTime: playbackAtom.playhead.position});\n });\n\n const abortListener = () => {\n const abortSignalReason = this.context.abortSignal.reason;\n if (abortSignalReason.name === 'SourceRemovedError' || abortSignalReason.name === 'FrameworkDisposedError') {\n this.eventCallback(Event.SOURCE_UNLOADED, {currentTime: playbackAtom.playhead.position});\n } else {\n this.eventCallback(Event.ERROR, {\n currentTime: playbackAtom.playhead.position,\n code: PWX_ABORT_ERROR_CODE,\n message: abortSignalReason.message,\n data: abortSignalReason,\n originalError: abortSignalReason,\n });\n }\n\n this.context.abortSignal.removeEventListener('abort', abortListener);\n };\n\n this.context.abortSignal.addEventListener('abort', abortListener);\n }\n}\n","/*!\n * This file was created to provide Bitmovin Player Web X \"export names\" as constants,\n * because they are exported as enums in 'd.ts' files, that we can't import as value in this project.\n *\n * Once `@bitmovin/player-web-x` bundle will provide these enums in way we could import them, we could remove/simplify this file.\n */\n\nimport type {BundleExportNames as BundleExportNamesEnum} from '@bitmovin/player-web-x/types/bundles/Types';\nimport type {CoreExportNames as CoreExportNamesEnum} from '@bitmovin/player-web-x/types/packages/core/Types';\nimport type {PlaybackApiEventsPackageExportNames as PlaybackApiEventsPackageExportNamesEnum} from '@bitmovin/player-web-x/types/packages/playback-api/playback-api-events/Types';\nimport type {SourceExportNames as SourceExportNamesEnum} from '@bitmovin/player-web-x/types/packages/source/Types';\nimport type {SourcesApiExportNames as SourcesApiExportNameEnum} from '@bitmovin/player-web-x/types/packages/sources-api/Types';\n\nimport type {EnumAsUnion} from '../../utils/EnumAsUnion';\n\nconst BundleExportNamesLogger: EnumAsUnion<typeof BundleExportNamesEnum> = 'logger';\nconst BundleExportNamesPlayerConfig: EnumAsUnion<typeof BundleExportNamesEnum> = 'player-config';\nexport const BundleExportNames = {\n Logger: BundleExportNamesLogger,\n PlayerConfig: BundleExportNamesPlayerConfig,\n};\n\nconst CoreExportNamesUtils: EnumAsUnion<typeof CoreExportNamesEnum> = 'utils';\nconst CoreExportNamesConstants: EnumAsUnion<typeof CoreExportNamesEnum> = 'constants';\nconst CoreExportNamesCoreEffects: EnumAsUnion<typeof CoreExportNamesEnum> = 'core-effects';\nconst CoreExportNamesCoreStateAtoms: EnumAsUnion<typeof CoreExportNamesEnum> = 'core-state-atoms';\nexport const CoreExportNames = {\n Utils: CoreExportNamesUtils,\n Constants: CoreExportNamesConstants,\n CoreEffects: CoreExportNamesCoreEffects,\n CoreStateAtoms: CoreExportNamesCoreStateAtoms,\n} as const;\n\nconst PlaybackApiEventsPackageExportNamesPlaybackEvent: EnumAsUnion<typeof PlaybackApiEventsPackageExportNamesEnum> =\n 'playback-event';\nexport const PlaybackApiEventsPackageExportNames = {\n PlaybackEvent: PlaybackApiEventsPackageExportNamesPlaybackEvent,\n} as const;\n\nconst SourceExportNamesCreateSourceStateAtom: EnumAsUnion<typeof SourceExportNamesEnum> = 'create-source-state-atom';\nconst SourceExportNamesCreateSourceReference: EnumAsUnion<typeof SourceExportNamesEnum> = 'create-source-reference';\nconst SourceExportNamesSourceReferences: EnumAsUnion<typeof SourceExportNamesEnum> = 'source-references';\nconst SourceExportNamesSourceState: EnumAsUnion<typeof SourceExportNamesEnum> = 'source-state-atom';\nexport const SourceExportNames = {\n CreateSourceStateAtom: SourceExportNamesCreateSourceStateAtom,\n CreateSourceReference: SourceExportNamesCreateSourceReference,\n SourceReferences: SourceExportNamesSourceReferences,\n SourceState: SourceExportNamesSourceState,\n} as const;\n\nconst SourcesApiExportNamesSourceApiManager: EnumAsUnion<typeof SourcesApiExportNameEnum> = 'source-api-manager';\nconst SourcesApiExportNamesVideoElementUtils: EnumAsUnion<typeof SourcesApiExportNameEnum> = 'video-element-utils';\nconst SourcesApiExportNamesSourceEventBus: EnumAsUnion<typeof SourcesApiExportNameEnum> = 'source-event-bus';\nexport const SourcesApiExportNames = {\n SourceApiManager: SourcesApiExportNamesSourceApiManager,\n VideoElementUtils: SourcesApiExportNamesVideoElementUtils,\n SourceEventBus: SourcesApiExportNamesSourceEventBus,\n} as const;\n","import type {AdapterAPI} from '../../api/AdapterAPI';\nimport {Analytics} from '../../core/Analytics';\nimport type {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {logger} from '../../utils/Logger';\nimport {\n hasPlayerAlreadyBeenAugmented,\n isDefined,\n markPlayerInstanceAsAugmented,\n} from '../../utils/playerAugmentationUtils';\nimport {VERSION} from '../../utils/Version';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {CAFv3InternalAdapter} from './CAFv3InternalAdapter';\n\nexport class CAFv3Adapter implements AdapterAPI {\n private readonly internalAdapter: InternalAdapterAPI | undefined;\n private readonly analytics: Analytics | undefined;\n\n constructor(config: AnalyticsConfig, castReceiverContext: any, opts?: AnalyticsStateMachineOptions) {\n if (hasPlayerAlreadyBeenAugmented(castReceiverContext)) {\n logger.errorMessageToUser('Bitmovin Analytics is already hooked up to this CastReceiverContext instance');\n return;\n }\n markPlayerInstanceAsAugmented(castReceiverContext);\n\n const sanitizedConfig = sanitizeAnalyticsConfig(config);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n return;\n }\n\n guardAgainstDuplicatedUserId(sanitizedConfig);\n\n this.internalAdapter = new CAFv3InternalAdapter(castReceiverContext, opts);\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n }\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getCurrentImpressionId();\n }\n\n getUserId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getUserId();\n }\n\n setCustomData(values: CustomDataValues) {\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.setCustomData(values);\n }\n\n setCustomDataOnce(values: CustomDataValues) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.setCustomDataOnce(values);\n }\n\n sourceChange(config: AnalyticsConfig) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.sourceChange(config);\n }\n}\n","import type {CastReceiverContext} from 'chromecast-caf-receiver/cast.framework';\nimport type {Track} from 'chromecast-caf-receiver/cast.framework.messages';\n\nimport {CAFv3AnalyticsStateMachine} from '../../analyticsStateMachines/CAFv3AnalyticsStateMachine';\nimport type {Analytics} from '../../core/Analytics';\nimport {HeartbeatService} from '../../core/HeartbeatService';\nimport {Event} from '../../enums/Event';\nimport {Player} from '../../enums/Player';\nimport {getStreamTypesFromURL} from '../../enums/StreamTypes';\nimport {ErrorDetailBackend} from '../../features/errordetails/ErrorDetailBackend';\nimport {ErrorDetailTracking} from '../../features/errordetails/ErrorDetailTracking';\nimport type {Feature} from '../../features/Feature';\nimport type {FeatureConfig} from '../../features/FeatureConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {DrmPerformanceInfo} from '../../types/DrmPerformanceInfo';\nimport type {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport {buildPlaybackInfoStreamTypeFields, normalizeVideoDuration, PlaybackInfo} from '../../types/PlaybackInfo';\nimport {isBlank} from '../../utils/stringUtils';\nimport {isNotNullish, isNullish, tryJSONStringify} from '../../utils/Utils';\nimport {InternalAdapter} from '../internal/InternalAdapter';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {CAFv3PlayerProxy} from './CAFv3PlayerProxy';\nimport {CastFrameworkEvent} from './castFrameworkTypes';\n\nexport class CAFv3InternalAdapter extends InternalAdapter implements InternalAdapterAPI {\n private readonly playerManager: CAFv3PlayerProxy;\n\n /** Boolean flag to prevent multiple calls of the {@link Event.UNLOAD} event */\n private onBeforeUnLoadEvent = false;\n private activeTextTracks: Track[] = [];\n\n constructor(castReceiverContext: CastReceiverContext, opts?: AnalyticsStateMachineOptions) {\n super(opts);\n const playingHeartbeatService = new HeartbeatService(() =>\n castReceiverContext.getPlayerManager().getCurrentTimeSec(),\n );\n const stateMachine = new CAFv3AnalyticsStateMachine(this.stateMachineCallbacks, playingHeartbeatService, this.opts);\n playingHeartbeatService.setListener(stateMachine);\n this.playerManager = new CAFv3PlayerProxy(castReceiverContext.getPlayerManager());\n this.stateMachine = stateMachine;\n }\n\n initialize(analytics: Analytics): Array<Feature<FeatureConfigContainer, FeatureConfig>> {\n this.registerCastFrameworkEventListeners();\n this.registerWindowUnloadEventListeners();\n\n const errorDetailTracking = new ErrorDetailTracking(\n analytics.errorDetailTrackingSettingsProvider,\n new ErrorDetailBackend(analytics.errorDetailTrackingSettingsProvider.collectorConfig),\n [analytics.errorDetailSubscribable],\n undefined,\n );\n return [errorDetailTracking];\n }\n\n getPlayerVersion = () => cast?.framework?.VERSION ?? 'unknown';\n getPlayerName = () => Player.CHROMECAST_SHAKA;\n getPlayerTech = () => 'html5';\n getAutoPlay = () => this.playerManager.getQueueManager()?.getCurrentItem()?.autoplay ?? false;\n override getDrmPerformanceInfo = (): DrmPerformanceInfo | undefined => this.drmPerformanceInfo;\n getCurrentPlaybackInfo(): PlaybackInfo {\n const stats = this.playerManager.getStats();\n\n // filter out undefined and null values\n const subtitleLanguages = this.activeTextTracks?.map((t) => t.language).filter(isNotNullish);\n\n return {\n ...this.getCommonPlaybackInfo(),\n ...detectCAFv3PlaybackInfoStreamTypeFields(this.playerManager),\n ...detectCAFv3PlaybackInfoAudioFields(this.playerManager),\n isLive: detectIsLive(this.playerManager),\n playerTech: this.getPlayerTech(),\n videoDuration: normalizeVideoDuration(this.playerManager.getMediaInformation()?.duration ?? 0),\n videoPlaybackHeight: stats?.height,\n videoPlaybackWidth: stats?.width,\n subtitleLanguage: subtitleLanguages ? subtitleLanguages.join(',') : undefined,\n // TODO: Implement `droppedFrames` tracking in CAFv3\n // - https://developers.google.com/cast/docs/reference/web_receiver/cast.framework.stats.Stats#droppedFrames\n droppedFrames: 0,\n };\n }\n\n protected get currentTime(): number {\n return this.playerManager.getCurrentTimeSec() ?? 0;\n }\n\n private registerCastFrameworkEventListeners() {\n // This is a special identifier, which can be used to listen for all events (mostly used for debugging purposes)\n // see: https://developers.google.com/cast/docs/reference/web_receiver/cast.framework.events#.EventType\n // this.playerManager.addEventListener(CastFrameworkEvent.ALL, (event) => {\n // console.log(`⭐ [${event.type}]`, JSON.stringify(event));\n // });\n\n // Fired when the browser has finished loading the metadata for a clip. This event is forwarded from the MediaElement, and has been wrapped.\n this.playerManager.addEventListener(CastFrameworkEvent.LOADED_METADATA, (_event) => {\n this.eventCallback(Event.SOURCE_LOADED, {});\n });\n\n // Fired when the player has finished processing a load request and is ready to play.\n this.playerManager.addEventListener(CastFrameworkEvent.PLAYER_LOAD_COMPLETE, () => {\n // captions\n const textTracksManager = this.playerManager.getTextTracksManager();\n if (isNotNullish(textTracksManager)) {\n this.activeTextTracks = textTracksManager.getActiveTracks();\n }\n\n this.eventCallback(Event.READY, {});\n });\n\n // Fired when playback is ready to start (ie: after being paused). This event is forwarded from the MediaElement, and has been wrapped.\n this.playerManager.addEventListener(CastFrameworkEvent.PLAY, (event) => {\n this.eventCallback(Event.PLAY, {currentTime: event.currentMediaTime});\n });\n\n // Fired when playback has started. This event is forwarded from the MediaElement, and has been wrapped in a cast.framework.events.MediaElementEvent.\n this.playerManager.addEventListener(CastFrameworkEvent.PLAYING, (_event) => {\n this.eventCallback(Event.PLAYING, {currentTime: this.currentTime});\n });\n\n // Fired periodically while the media is playing. This will fire whenever the currentTime attribute changes\n this.playerManager.addEventListener(CastFrameworkEvent.TIME_UPDATE, (event) => {\n this.eventCallback(Event.TIMECHANGED, {currentTime: event.currentMediaTime});\n });\n\n // Fired when playback is paused. This event is forwarded from the MediaElement, and has been wrapped.\n this.playerManager.addEventListener(CastFrameworkEvent.PAUSE, (_event) => {\n this.eventCallback(Event.PAUSE, {currentTime: this.currentTime});\n });\n\n // Fired when an error occurs\n this.playerManager.addEventListener(CastFrameworkEvent.ERROR, (event) => {\n const errorData = isNotNullish(event.error) ? event.error : undefined;\n this.eventCallback(Event.ERROR, {\n currentTime: this.playerManager.getCurrentTimeSec(),\n code: event.detailedErrorCode,\n message: event.reason,\n legacyData: errorData,\n originalError: event,\n data: {additionalData: tryJSONStringify(errorData)},\n });\n });\n\n // Fired when the media is being seeked. This event is forwarded from the MediaElement, and has been wrapped.\n this.playerManager.addEventListener(CastFrameworkEvent.SEEKING, (event) => {\n this.eventCallback(Event.SEEK, {currentTime: event.currentMediaTime});\n });\n\n // Fired when a seek has finished. This will not be fired in case seeking finishes when the media is paused. This event is forwarded from the MediaElement, and has been wrapped.\n this.playerManager.addEventListener(CastFrameworkEvent.SEEKED, (event) => {\n this.eventCallback(Event.SEEKED, {currentTime: event.currentMediaTime});\n });\n\n this.playerManager.addEventListener(CastFrameworkEvent.BUFFERING, (event) => {\n if (event.isBuffering) {\n this.eventCallback(Event.START_BUFFERING, {currentTime: this.currentTime});\n }\n });\n\n // Fired when a LOAD message is received\n //\n // Why REQUEST_LOAD and not LOAD_START like in HTML5 adapters?\n // Later after the REQUEST_LOAD, also the LOAD_START event is always called. However, we use REQUEST_LOAD,\n // because TIME_UPDATE event happens between before the LOAD_START, and that would wrongly move us to PLAYING state.\n // For example:\n // If we would be in PAUSE state and relay on LOAD_START event, at first the TIME_UPDATE would happen\n // and move us to PLAYING state and only after that we would call sourceChange and be SOURCE_CHANGE state,\n // but this would generate short playing sample before the source change from PAUSE state.\n this.playerManager.addEventListener(CastFrameworkEvent.REQUEST_LOAD, (_event) => {\n this.sourceChange({});\n });\n }\n\n private registerWindowUnloadEventListeners() {\n const handleWindowUnloadEvent = () => {\n if (!this.onBeforeUnLoadEvent) {\n this.onBeforeUnLoadEvent = true;\n this.eventCallback(Event.UNLOAD, {currentTime: this.currentTime});\n }\n this.release();\n };\n\n this.windowEventTracker.addEventListener('beforeunload', handleWindowUnloadEvent);\n this.windowEventTracker.addEventListener('unload', handleWindowUnloadEvent);\n }\n}\n\nfunction detectIsLive(playerManager: CAFv3PlayerProxy): true | undefined {\n // needs to be explicitly set to \"LIVE\" by customers in their receiver implementation\n if (playerManager.getMediaInformation()?.streamType === 'LIVE') {\n return true;\n }\n\n // hack because the object exists only for live streams\n const liveSeekableRange = playerManager.getLiveSeekableRange();\n\n if (liveSeekableRange) {\n return true;\n }\n\n return undefined;\n}\n\nexport function detectCAFv3PlaybackInfoStreamTypeFields(\n playerManager: CAFv3PlayerProxy,\n): Pick<PlaybackInfo, 'm3u8Url' | 'mpdUrl' | 'progUrl' | 'streamFormat'> {\n // Optional media URL, to allow using contentId for the actual ID. If contentUrl is provided, it is used as\n // the media URL. Otherwise, the contentId is used as the media URL.\n // see: https://developers.google.com/cast/docs/reference/web_receiver/cast.framework.messages.MediaInformation#contentUrl\n let url = playerManager.getMediaInformation()?.contentUrl;\n if (isNullish(url) || isBlank(url)) {\n url = playerManager.getMediaInformation()?.contentId;\n }\n\n const streamType = getStreamTypesFromURL(url);\n\n return buildPlaybackInfoStreamTypeFields(streamType, url);\n}\n\nfunction detectCAFv3PlaybackInfoAudioFields(\n playerManager: CAFv3PlayerProxy,\n): Pick<PlaybackInfo, 'audioBitrate' | 'audioCodec' | 'audioLanguage'> {\n try {\n const audioTracksManager = playerManager.getAudioTracksManager();\n\n // getActiveTrack() can throw error if there is no video loaded yet, or no active audio track\n const activeTract = audioTracksManager?.getActiveTrack();\n\n return {\n audioLanguage: activeTract?.language,\n audioCodec: activeTract?.audioTrackInfo?.audioCodec,\n audioBitrate: undefined, // bitrate is not available in CAFv3\n };\n } catch (_error) {\n // no action needed\n // active track is not available, so we cannot get audio fields\n return {};\n }\n}\n","import type {PlayerManager} from 'chromecast-caf-receiver/cast.framework';\n\nimport {safeAccess} from '../../utils/objectUtils';\n\nexport class CAFv3PlayerProxy {\n constructor(private readonly rawPlayer: PlayerManager) {}\n\n addEventListener = ((...args: Parameters<PlayerManager['addEventListener']>) => {\n safeAccess(() => this.rawPlayer.addEventListener(...args));\n }) as PlayerManager['addEventListener']; // casting is needed because caf has many type definitions of this listener\n\n getCurrentTimeSec = () => safeAccess(() => this.rawPlayer.getCurrentTimeSec());\n\n getStats = () => safeAccess(() => this.rawPlayer.getStats());\n\n getMediaInformation = () => safeAccess(() => this.rawPlayer.getMediaInformation());\n\n getLiveSeekableRange = () => safeAccess(() => this.rawPlayer.getLiveSeekableRange());\n\n getTextTracksManager = () => safeAccess(() => this.rawPlayer.getTextTracksManager());\n\n getQueueManager = () => safeAccess(() => this.rawPlayer.getQueueManager());\n\n getAudioTracksManager = () => safeAccess(() => this.rawPlayer.getAudioTracksManager());\n}\n","/*!\n * This file was created to avoid usage of \"global `cast.framework` values\" (constants/enums/classes/etc.) that should be\n * defined by JavaScript file `cast_receiver_framework.js` imported by the Web Cast Receiver app. We should not relay on it,\n * and instead, we should define our own necessary primitive values and constants we need.\n *\n * We should still use \"type imports\" (`import type {}`) from the `@types/chromecast-caf-receiver` package!\n *\n * Cypress test should cover \"copies of the library values\" to be sure they are up to date with the library!\n */\n\nimport type {EventType} from 'chromecast-caf-receiver/cast.framework.events';\n\n/**\n * https://developers.google.com/cast/docs/reference/web_receiver/cast.framework.events#.EventType\n */\nexport const CastFrameworkEvent = {\n ALL: '*' as EventType.ALL,\n BUFFERING: 'BUFFERING' as EventType.BUFFERING,\n ERROR: 'ERROR' as EventType.ERROR,\n LOADED_METADATA: 'LOADED_METADATA' as EventType.LOADED_METADATA,\n PAUSE: 'PAUSE' as EventType.PAUSE,\n PLAY: 'PLAY' as EventType.PLAY,\n PLAYING: 'PLAYING' as EventType.PLAYING,\n PLAYER_LOAD_COMPLETE: 'PLAYER_LOAD_COMPLETE' as EventType.PLAYER_LOAD_COMPLETE,\n REQUEST_LOAD: 'REQUEST_LOAD' as EventType.REQUEST_LOAD,\n SEEKED: 'SEEKED' as EventType.SEEKED,\n SEEKING: 'SEEKING' as EventType.SEEKING,\n STALLED: 'STALLED' as EventType.STALLED,\n TIME_UPDATE: 'TIME_UPDATE' as EventType.TIME_UPDATE,\n} as const;\n","import type {AdapterAPI} from '../../api/AdapterAPI';\nimport {Analytics} from '../../core/Analytics';\nimport type {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {logger} from '../../utils/Logger';\nimport {\n hasPlayerAlreadyBeenAugmented,\n isDefined,\n markPlayerInstanceAsAugmented,\n} from '../../utils/playerAugmentationUtils';\nimport {VERSION} from '../../utils/Version';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {HlsInternalAdapter} from './HlsInternalAdapter';\nimport {HlsjsPlayerProxy} from './HlsjsPlayerProxy';\n\nexport class HlsAdapter implements AdapterAPI {\n private readonly internalAdapter: InternalAdapterAPI | undefined;\n private readonly analytics: Analytics | undefined;\n\n constructor(config: AnalyticsConfig, player: any, opts?: AnalyticsStateMachineOptions) {\n if (hasPlayerAlreadyBeenAugmented(player)) {\n logger.errorMessageToUser('Bitmovin Analytics is already hooked up to this player instance');\n return;\n }\n markPlayerInstanceAsAugmented(player);\n\n const sanitizedConfig = sanitizeAnalyticsConfig(config);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n return;\n }\n\n guardAgainstDuplicatedUserId(sanitizedConfig);\n\n this.internalAdapter = new HlsInternalAdapter(new HlsjsPlayerProxy(player), opts);\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n }\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getCurrentImpressionId();\n }\n\n getUserId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getUserId();\n }\n\n setCustomData(values: CustomDataValues) {\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.setCustomData(values);\n }\n\n setCustomDataOnce(values: CustomDataValues) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.setCustomDataOnce(values);\n }\n\n sourceChange(config: AnalyticsConfig) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.sourceChange(config);\n }\n}\n","import type {AudioTrackSwitchedData, Level, SubtitleTrackSwitchData} from 'hls.js';\n\nimport {Analytics} from '../../core/Analytics';\nimport {DownloadSpeedMeter} from '../../core/DownloadSpeedMeter';\nimport {Event} from '../../enums/Event';\nimport {MIMETypes} from '../../enums/MIMETypes';\nimport {Player} from '../../enums/Player';\nimport {ErrorDetailBackend} from '../../features/errordetails/ErrorDetailBackend';\nimport {ErrorDetailTracking} from '../../features/errordetails/ErrorDetailTracking';\nimport {Feature} from '../../features/Feature';\nimport {FeatureConfig} from '../../features/FeatureConfig';\nimport {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport {CodecInfo} from '../../types/CodecInfo';\nimport {DownloadSpeedInfo} from '../../types/DownloadSpeedInfo';\nimport {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport {PlaybackInfo} from '../../types/PlaybackInfo';\nimport {QualityLevelInfo} from '../../types/QualityLevelInfo';\nimport {SubtitleInfo} from '../../types/SubtitleInfo';\nimport {isNumber} from '../../utils/numberUtils';\nimport {isNotNullish, isNullish} from '../../utils/Utils';\nimport {HTML5InternalAdapter} from '../html5/HTML5InternalAdapter';\nimport {HTMLVideoElementProxy} from '../html5/HTMLVideoElementProxy';\nimport {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {HlsjsPlayerProxy} from './HlsjsPlayerProxy';\nimport {HLS_PLAYER_EVENT} from './player/HlsJsPlayerTypes';\nimport {HlsSpeedMeterAdapter} from './player/HlsSpeedMeterAdapter';\n\nexport class HlsInternalAdapter extends HTML5InternalAdapter implements InternalAdapterAPI {\n private readonly hls: HlsjsPlayerProxy;\n private speedMeter: DownloadSpeedMeter;\n\n constructor(hls: HlsjsPlayerProxy, opts?: AnalyticsStateMachineOptions) {\n super(undefined, opts);\n this.hls = hls;\n this.speedMeter = new HlsSpeedMeterAdapter(hls, new DownloadSpeedMeter()).getDownloadSpeedMeter();\n }\n\n override initialize(analytics: Analytics): Array<Feature<FeatureConfigContainer, FeatureConfig>> {\n super.initialize(analytics);\n this.registerHlsEvents();\n const errorDetailTracking = new ErrorDetailTracking(\n analytics.errorDetailTrackingSettingsProvider,\n new ErrorDetailBackend(analytics.errorDetailTrackingSettingsProvider.collectorConfig),\n [analytics.errorDetailSubscribable],\n undefined,\n );\n return [errorDetailTracking];\n }\n\n override getPlayerName = () => Player.HLSJS;\n\n getPlayerVersion = () => this.hls.version ?? 'unknown';\n\n override getCurrentPlaybackInfo(): PlaybackInfo {\n const selectedSubtitle = this.getSelectedSubtitleLanguage();\n\n const playbackInfo: PlaybackInfo = {\n ...super.getCurrentPlaybackInfo(),\n audioLanguage: this.getSelectedAudioLanguage(),\n subtitleEnabled: isNotNullish(selectedSubtitle) ? selectedSubtitle.enabled : undefined,\n subtitleLanguage: isNotNullish(selectedSubtitle) ? selectedSubtitle.language : undefined,\n };\n\n const codecInfo = getHlsCodecInfo(this.hls);\n this.sourceInfoFallbackService.applyAndStoreCodecInfo(playbackInfo, codecInfo);\n\n return playbackInfo;\n }\n override getDownloadSpeedInfo(): DownloadSpeedInfo {\n return this.speedMeter.getInfo();\n }\n override resetDownloadSpeedInfoMeasures() {\n this.speedMeter.reset();\n }\n\n getCurrentQualityLevelInfo(): QualityLevelInfo | null {\n const currentLevelObj = getHlsCurrentLevel(this.hls);\n if (!currentLevelObj) {\n return null;\n }\n\n const bitrate = currentLevelObj.bitrate;\n const width = currentLevelObj.width;\n const height = currentLevelObj.height;\n\n return {\n bitrate: bitrate,\n width: width,\n height: height,\n };\n }\n\n override isLive = () => {\n const currentLevelObj = getHlsCurrentLevel(this.hls);\n\n if (isNullish(currentLevelObj?.details)) {\n return undefined;\n }\n\n return currentLevelObj.details.live;\n };\n\n override getMIMEType() {\n return MIMETypes.HLS;\n }\n\n override getStreamURL(): string | undefined {\n return this.hls.url ?? undefined;\n }\n\n registerHlsEvents() {\n this.hls.on(HLS_PLAYER_EVENT.MEDIA_ATTACHING, this.onMediaAttaching.bind(this));\n this.hls.on(HLS_PLAYER_EVENT.MEDIA_DETACHING, this.onMediaDetaching.bind(this));\n this.hls.on(HLS_PLAYER_EVENT.MANIFEST_LOADING, this.onManifestLoading.bind(this));\n this.hls.on(HLS_PLAYER_EVENT.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched.bind(this));\n this.hls.on(HLS_PLAYER_EVENT.SUBTITLE_TRACK_SWITCH, this.onSubtitleLanguageSwitched.bind(this));\n this.hls.on(HLS_PLAYER_EVENT.DESTROYING, this.onDestroying.bind(this));\n this.hls.on(HLS_PLAYER_EVENT.ERROR, this.onHlsError.bind(this));\n\n // media is already attached, event has been triggered before\n // or we are in the event handler of this event itself.\n // we can not know how the stacktrace to this constructor will look like.\n // therefore we will guard from this case in\n // the onMediaAttaching method (avoid running it twice)\n if (this.hls.media) {\n this.onMediaAttaching();\n this.onManifestLoading();\n }\n }\n\n onMediaAttaching() {\n // in case we are called again (when we are triggering this ourselves\n // but from the event handler of MEDIA_ATTACHING) we should not run again.\n if (this.mediaElement) {\n return;\n }\n\n this.mediaElement = new HTMLVideoElementProxy(this.hls.media as HTMLVideoElement);\n\n this.registerMediaElement();\n this.onMaybeReady();\n }\n\n onMediaDetaching() {\n this.unregisterMediaElement();\n }\n\n onManifestLoading() {\n this.onMaybeReady();\n }\n\n /**\n * errorData: { type : error type, details : error details, fatal : if true, hls.js cannot/will not try to recover, if false, hls.js will try to recover,other error specific data }\n * https://hls-js.netlify.com/api-docs/file/src/events.js.html#lineNumber98\n */\n onHlsError(errorName, errorData) {\n const isFatal = errorData ? errorData.fatal : true;\n if (isFatal) {\n const mediaElement = this.mediaElement;\n let currentTime;\n if (isNotNullish(mediaElement)) {\n currentTime = mediaElement.currentTime;\n }\n\n const errorMessage = isNotNullish(errorData) ? `${errorData.type}: ${errorData.details}` : undefined;\n this.eventCallback(Event.ERROR, {\n currentTime,\n code: this.getErrorCodeFromHlsErrorType(errorData.type),\n message: errorMessage,\n originalError: errorData,\n data: {},\n });\n }\n }\n\n onAudioTrackSwitched(_event: string, _data: AudioTrackSwitchedData) {\n const mediaElement = this.mediaElement;\n let currentTime;\n if (isNotNullish(mediaElement)) {\n currentTime = mediaElement.currentTime;\n }\n\n this.eventCallback(Event.AUDIOTRACK_CHANGED, {\n currentTime,\n });\n }\n\n onSubtitleLanguageSwitched(_event: string, _data: SubtitleTrackSwitchData) {\n const mediaElement = this.mediaElement;\n let currentTime;\n if (isNotNullish(mediaElement)) {\n currentTime = mediaElement.currentTime;\n }\n\n this.eventCallback(Event.SUBTITLE_CHANGE, {\n currentTime,\n });\n }\n\n private onDestroying = () => {\n this.eventCallback(Event.SOURCE_UNLOADED, {});\n this.release();\n };\n\n /**\n * returns mapped error code for Hlsjs ErrorTypes\n * @param type one of the ErrorTypes according to https://github.com/video-dev/hls.js/blob/v1.5.1/src/errors.ts#L1\n */\n private getErrorCodeFromHlsErrorType(type: string): number {\n switch (type) {\n case 'networkError':\n return 2;\n case 'mediaError':\n return 3;\n case 'keySystemError':\n return 4;\n case 'muxError':\n return 5;\n // default equals `otherError`\n default:\n return 1;\n }\n }\n\n private getSelectedAudioLanguage(): string | undefined {\n const audioTrack = this.hls.audioTrack;\n if (isNullish(audioTrack) || audioTrack < 0) {\n return undefined;\n }\n const audioTracks = this.hls.audioTracks;\n if (isNullish(audioTracks) || audioTracks.length === 0) {\n return undefined;\n }\n return audioTracks[audioTrack].lang;\n }\n\n private getSelectedSubtitleLanguage(): SubtitleInfo | undefined {\n // Check if function is supported (in latest hls version), otherwise use fallback option\n if (isNotNullish(this.hls.subtitleDisplay)) {\n const subtitleTrackValue = this.hls.subtitleTrack;\n const isSubtitleDisplayed =\n isNotNullish(subtitleTrackValue) && subtitleTrackValue >= 0 && this.hls.subtitleDisplay;\n\n const language = isSubtitleDisplayed ? this.hls.subtitleTracks?.[subtitleTrackValue]?.lang : undefined;\n\n return {\n enabled: isSubtitleDisplayed,\n language,\n };\n } else {\n const {subtitleTrackController} = this.hls as any;\n if (isNotNullish(subtitleTrackController) && isNotNullish(subtitleTrackController.media)) {\n return this.getSelectedSubtitleFromMediaElement(subtitleTrackController.media);\n }\n }\n return undefined;\n }\n}\n\nexport const getHlsCodecInfo = (hls: HlsjsPlayerProxy): CodecInfo | undefined => {\n const currentLevelObj = getHlsCurrentLevel(hls);\n if (!currentLevelObj) {\n return undefined;\n }\n\n return {\n videoCodec: currentLevelObj.videoCodec,\n audioCodec: currentLevelObj.audioCodec,\n };\n};\n\nexport const getHlsCurrentLevel = (hls: HlsjsPlayerProxy): Level | undefined => {\n const levels = hls.levels;\n const currentLevel = hls.currentLevel;\n if (isNullish(levels) || levels.length === 0) {\n return undefined;\n }\n\n if (!isNumber(currentLevel) || currentLevel < 0) {\n return undefined;\n }\n\n return levels[currentLevel];\n};\n","import type {default as Hls} from 'hls.js';\n\nimport {safeAccess} from '../../utils/objectUtils';\n\nexport class HlsjsPlayerProxy {\n constructor(private readonly rawPlayer: Hls) {}\n\n on = (...args: Parameters<Hls['on']>) => safeAccess(() => this.rawPlayer.on(...args));\n\n get media() {\n return safeAccess(() => this.rawPlayer.media);\n }\n\n get url() {\n return safeAccess(() => this.rawPlayer.url);\n }\n\n get levels() {\n return safeAccess(() => this.rawPlayer.levels);\n }\n\n get currentLevel() {\n return safeAccess(() => this.rawPlayer.currentLevel);\n }\n\n get audioTrack() {\n return safeAccess(() => this.rawPlayer.audioTrack);\n }\n\n get audioTracks() {\n return safeAccess(() => this.rawPlayer.audioTracks);\n }\n\n get subtitleDisplay() {\n return safeAccess(() => this.rawPlayer.subtitleDisplay);\n }\n\n get subtitleTrack() {\n return safeAccess(() => this.rawPlayer.subtitleTrack);\n }\n\n get subtitleTracks() {\n return safeAccess(() => this.rawPlayer.subtitleTracks);\n }\n\n get version(): string | undefined {\n return safeAccess(() => (this.rawPlayer as any).constructor.version);\n }\n}\n","/*!\n * This file was created to only avoid \"values imports\" (constants/enums/classes/etc.) from the `hls.js@1.6.2`\n * to avoid including the whole package in our distribution code.\n *\n * We should still use \"type imports\" (`import type {}`) from the library!\n *\n * Unit test should cover \"copies of the library values\" to be sure they are up to date with the library!\n */\nimport type {Events} from 'hls.js';\n\n/**\n * Partial copy from Hls.js repository\n * @see https://github.com/video-dev/hls.js/blob/v1.6.2/src/types/events.ts#L390\n */\nexport interface FragLoadedData {\n frag: Fragment;\n networkDetails: unknown;\n}\n\n/**\n * Partial copy from Hls.js repository\n * @see https://github.com/video-dev/hls.js/blob/v1.6.2/src/types/loader.ts#L175\n */\nexport enum PlaylistLevelType {\n AUDIO = 'audio',\n MAIN = 'main',\n SUBTITLE = 'subtitle',\n}\n\n/**\n * Partial copy from Hls.js repository\n * @see https://github.com/video-dev/hls.js/blob/v1.6.2/src/loader/fragment.ts#L163\n */\ninterface Fragment {\n stats: LoaderStats; // `get stats()` in `BaseSegment`\n readonly type: PlaylistLevelType;\n}\n\n/**\n * Partial copy from Hls.js repository\n * @see https://github.com/video-dev/hls.js/blob/v1.6.2/src/types/loader.ts#L73\n */\ninterface LoaderStats {\n total: number;\n loading: {\n end: number;\n first: number;\n start: number;\n };\n}\n\n/**\n * Map of Hls Player events that we listen to, each should be type of {@link Events}.\n *\n * Why: This way, we don't need to import string enum {@link Events} from 'hls.js' directly,\n * aka. compile/include it (as value) in our distribution code\n */\nexport const HLS_PLAYER_EVENT = {\n MEDIA_ATTACHING: 'hlsMediaAttaching' as Events.MEDIA_ATTACHING,\n MEDIA_DETACHING: 'hlsMediaDetaching' as Events.MEDIA_DETACHING,\n MANIFEST_LOADING: 'hlsManifestLoading' as Events.MANIFEST_LOADING,\n AUDIO_TRACK_SWITCHED: 'hlsAudioTrackSwitched' as Events.AUDIO_TRACK_SWITCHED,\n SUBTITLE_TRACK_SWITCH: 'hlsSubtitleTrackSwitch' as Events.SUBTITLE_TRACK_SWITCH,\n DESTROYING: 'hlsDestroying' as Events.DESTROYING,\n ERROR: 'hlsError' as Events.ERROR,\n FRAG_LOADED: 'hlsFragLoaded' as Events.FRAG_LOADED,\n} as const;\n","import {DownloadSpeedMeter} from '../../../core/DownloadSpeedMeter';\nimport {isNotNullish, isNullish} from '../../../utils/Utils';\nimport {HlsjsPlayerProxy} from '../HlsjsPlayerProxy';\n\nimport type {FragLoadedData} from './HlsJsPlayerTypes';\nimport {HLS_PLAYER_EVENT} from './HlsJsPlayerTypes';\n\nexport class HlsSpeedMeterAdapter {\n private meter: DownloadSpeedMeter;\n\n constructor(hls: HlsjsPlayerProxy, meter: DownloadSpeedMeter) {\n this.meter = meter;\n hls.on(HLS_PLAYER_EVENT.FRAG_LOADED, (_eventName, data) => this.handleFragmentLoadedEvent(data));\n }\n\n getDownloadSpeedMeter(): DownloadSpeedMeter {\n return this.meter;\n }\n\n handleFragmentLoadedEvent(eventData: FragLoadedData) {\n if (eventData.frag.type !== 'main') {\n // ignore non-video fragments\n return;\n }\n\n const httpStatus = isNotNullish(eventData.networkDetails)\n ? (eventData.networkDetails as {status: number}).status\n : undefined;\n if (isNullish(httpStatus)) {\n // ignore fragments that https status is undefined (networkDetails are null)\n return;\n }\n\n const stats = eventData.frag.stats;\n const loadingDuration = (stats.loading.end - stats.loading.start) / 1000;\n const timeToFirstByte = (stats.loading.first - stats.loading.start) / 1000;\n\n const measurement = {\n duration: loadingDuration,\n size: stats.total,\n timeToFirstByte: timeToFirstByte,\n timestamp: new Date(),\n httpStatus,\n };\n\n this.meter.addMeasurement(measurement);\n }\n}\n","import {HTML5AnalyticsStateMachine} from '../../analyticsStateMachines/HTML5AnalyticsStateMachine';\nimport {Analytics} from '../../core/Analytics';\nimport {HeartbeatService} from '../../core/HeartbeatService';\nimport VideoCompletionTracker from '../../core/VideoCompletionTracker';\nimport {Event} from '../../enums/Event';\nimport {getMIMETypeFromFileExtension} from '../../enums/MIMETypes';\nimport {Player} from '../../enums/Player';\nimport {PlayerSize} from '../../enums/PlayerSize';\nimport {getStreamTypeFromMIMEType, StreamTypes} from '../../enums/StreamTypes';\nimport {Feature} from '../../features/Feature';\nimport {FeatureConfig} from '../../features/FeatureConfig';\nimport {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport {DrmPerformanceInfo} from '../../types/DrmPerformanceInfo';\nimport {QualityChangeEvent} from '../../types/EventData';\nimport {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport {buildPlaybackInfoStreamTypeFields, normalizeVideoDuration, PlaybackInfo} from '../../types/PlaybackInfo';\nimport {QualityLevelInfo} from '../../types/QualityLevelInfo';\nimport {SubtitleInfo} from '../../types/SubtitleInfo';\nimport {isVideoInFullscreen} from '../../utils/documentUtils';\nimport {logger} from '../../utils/Logger';\nimport {isAudioMuted, isNotNullish, isNullish} from '../../utils/Utils';\nimport {InternalAdapter} from '../internal/InternalAdapter';\nimport {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {HTMLVideoElementProxy} from './HTMLVideoElementProxy';\nimport HTMLVideoElementStatisticsProvider from './player/HTMLVideoElementStatisticsProvider';\n\nexport abstract class HTML5InternalAdapter extends InternalAdapter implements InternalAdapterAPI {\n private static BUFFERING_TIMECHANGED_TIMEOUT_IN_MS = 1000;\n\n protected mediaElement: HTMLVideoElementProxy | undefined;\n private mediaElementEventHandlers: Array<{event: string; handler: any}>;\n /** holds reference of original mediaElement.load */\n private mediaElementOriginalLoadFn?: () => void;\n\n private readonly _videoCompletionTracker: VideoCompletionTracker;\n\n protected needsFirstPlayIntent: boolean = true;\n /** Boolean flag to prevent multiple calls of the {@link Event.UNLOAD} event */\n private onBeforeUnLoadEvent = false;\n\n private bufferingTimeout?: ReturnType<typeof setTimeout>;\n private isBuffering: boolean = false;\n private isPaused: boolean = false;\n private isSeeking: boolean = false;\n /** Previous media element time in seconds */\n private previousMediaTimeInSeconds: number = 0;\n /** Previous client time in milliseconds */\n private previousClientTime: number;\n private needsReadyEvent: boolean;\n private previousMutedValue = false;\n private playerStatisticsProvider: HTMLVideoElementStatisticsProvider;\n\n protected constructor(mediaElement: HTMLVideoElementProxy | undefined, opts?: AnalyticsStateMachineOptions) {\n super(opts);\n const playingHeartbeatService = new HeartbeatService(\n () => mediaElement?.currentTime ?? this.previousMediaTimeInSeconds,\n );\n const stateMachine = new HTML5AnalyticsStateMachine(this.stateMachineCallbacks, playingHeartbeatService, this.opts);\n playingHeartbeatService.setListener(stateMachine);\n this.stateMachine = stateMachine;\n\n this.mediaElement = mediaElement;\n this.mediaElementEventHandlers = [];\n this.mediaElementOriginalLoadFn = undefined;\n\n this.bufferingTimeout = undefined;\n this.isBuffering = false;\n this.isPaused = false;\n this.isSeeking = false;\n this.previousMediaTimeInSeconds = 0;\n this.previousClientTime = 0;\n this.needsReadyEvent = true;\n this.needsFirstPlayIntent = true;\n this._videoCompletionTracker = new VideoCompletionTracker();\n this.playerStatisticsProvider = new HTMLVideoElementStatisticsProvider(mediaElement);\n }\n\n get videoCompletionTracker(): VideoCompletionTracker | undefined {\n return this._videoCompletionTracker;\n }\n\n initialize(_analytics: Analytics): Array<Feature<FeatureConfigContainer, FeatureConfig>> {\n if (this.mediaElement) {\n // calling `setMediaElement` with `null` argument on purpose to register all media element event\n // listeners with existing/already set media element during adapter initialization.\n this.setMediaElement();\n }\n this.registerWindowEvents();\n return [];\n }\n\n abstract getPlayerVersion(): string;\n getPlayerName = () => Player.HTML5;\n getPlayerTech = () => 'html5';\n getAutoPlay = () => this.mediaElement?.autoplay ?? false;\n override getDrmPerformanceInfo = (): DrmPerformanceInfo | undefined => this.drmPerformanceInfo;\n getCurrentPlaybackInfo(): PlaybackInfo {\n const streamType = this.getStreamType();\n if (isNotNullish(streamType)) {\n this.sourceInfoFallbackService.setStreamFormat(streamType);\n }\n\n let info: PlaybackInfo = {\n ...this.getCommonPlaybackInfo(),\n ...buildPlaybackInfoStreamTypeFields(streamType, this.getStreamURL()),\n isLive: this.isLive(),\n size: isVideoInFullscreen() ? PlayerSize.Fullscreen : PlayerSize.Window,\n playerTech: this.getPlayerTech(),\n droppedFrames: this.playerStatisticsProvider.getDroppedFrames(),\n // TODO: Implement `audioBitrate`\n // TODO: Implement `isCasting`\n // TODO: Implement getting `videoTitle` from player (currently only from the analytics config)\n };\n\n if (this.mediaElement) {\n info = {\n ...info,\n videoDuration: normalizeVideoDuration(this.mediaElement.duration),\n isMuted: this.mediaElement.muted,\n videoWindowHeight: this.mediaElement.height,\n videoWindowWidth: this.mediaElement.width,\n };\n }\n\n const qualityInfo = this.getCurrentQualityLevelInfo();\n if (qualityInfo) {\n info = {\n ...info,\n videoPlaybackHeight: qualityInfo.height,\n videoPlaybackWidth: qualityInfo.width,\n videoBitrate: qualityInfo.bitrate,\n };\n }\n\n this.sourceInfoFallbackService.applyStreamFormat(info);\n\n return info;\n }\n\n override resetSourceRelatedState() {\n super.resetSourceRelatedState();\n this.playerStatisticsProvider.reset();\n this.needsFirstPlayIntent = true;\n this.isBuffering = false;\n this.isPaused = false;\n this.isSeeking = false;\n this.previousMediaTimeInSeconds = 0;\n clearTimeout(this.bufferingTimeout);\n }\n\n protected get currentTime(): number {\n if (!this.mediaElement) {\n throw new Error('No media attached');\n }\n\n return this.mediaElement.currentTime ?? this.previousMediaTimeInSeconds;\n }\n\n override release() {\n this.unregisterMediaElement();\n super.release();\n }\n\n isLive = () => {\n if (!this.mediaElement) {\n return undefined;\n }\n\n const videoDuration = this.mediaElement.duration;\n return isNullish(videoDuration) || isNaN(videoDuration) ? undefined : videoDuration === Infinity;\n };\n\n /**\n * Used to setup against the media element.\n * We need this method to desynchronize construction of this class\n * and the actual initialization against the media element.\n * That is because at construction some media engine\n * may not already have the media element attached, for example\n * when passing in the DOM element is happening at once with passing the source URL\n * and can not be decoupled.\n * We are then awaiting an event from the engine and calling this with the media element\n * as argument from our sub-class.\n *\n * This method can also be called without arguments and then it will perform\n * initialization against the existing media element (should only be called once, will throw an error otherwise)\n *\n * It can also be used to replace the element.\n *\n *\n */\n setMediaElement(mediaElement: HTMLVideoElementProxy | null = null) {\n // if called with argument (new media element)\n if (mediaElement) {\n // if we already have one, we need to unregister current one before replacing it\n if (this.mediaElement) {\n this.unregisterMediaElement();\n }\n\n // set the new media element\n this.mediaElement = mediaElement;\n }\n\n // if called without argument (and that is feature of function),\n // we assume media element is already set and ready to be registered\n\n // ...if not, we throw an error\n if (!this.mediaElement) {\n throw new Error('No media element owned');\n }\n\n // ...if it was already registered, we throw an error\n if (this.mediaElementEventHandlers.length > 0) {\n throw new Error('Media element already set (only call this once)');\n }\n\n this.registerMediaElement();\n this.onMaybeReady();\n }\n\n /**\n * Implemented by sub-class to deliver current quality-level info specific to media-engine.\n */\n abstract getCurrentQualityLevelInfo(): QualityLevelInfo | null;\n\n /**\n * Can be overriden by sub-classes\n * @returns {string}\n *\n */\n getMIMEType(): string | undefined {\n const streamUrl = this.getStreamURL();\n if (isNullish(streamUrl)) {\n return;\n }\n return getMIMETypeFromFileExtension(streamUrl);\n }\n\n /**\n * Can be overriden by sub-classes\n * @returns {string}\n */\n getStreamType(): StreamTypes | undefined {\n const mimetype = this.getMIMEType();\n if (mimetype) {\n return getStreamTypeFromMIMEType(mimetype);\n }\n\n return undefined;\n }\n\n /**\n * Can be overriden by subclasses.\n * @returns {string}\n */\n getStreamURL(): string | undefined {\n const mediaElement = this.mediaElement;\n if (!mediaElement) {\n return;\n }\n\n return mediaElement.src;\n }\n\n registerMediaElement() {\n const mediaElement = this.mediaElement;\n if (!mediaElement) {\n return;\n }\n\n // wrap the original Media Element `load` function\n this.mediaElementOriginalLoadFn = mediaElement.getRawPlayer().load;\n const originalLoad = this.mediaElementOriginalLoadFn;\n mediaElement.getRawPlayer().load = (...args: Parameters<HTMLVideoElement['load']>): void => {\n this.sourceChange({});\n originalLoad.apply(mediaElement.getRawPlayer(), args);\n };\n\n this.listenToMediaElementEvent('loadstart', () => {\n log(`loadstart ${mediaElement.currentTime}`);\n this.sourceChange({});\n });\n\n this.listenToMediaElementEvent('loadedmetadata', () => {\n log(`loadedmetadata time:${mediaElement.currentTime} / readyState: ${mediaElement.readyState}`);\n\n // silent\n this.checkQualityLevelAttributes(true);\n\n // set streamFormat if possible,\n // loadedMetadata seems to be the first event where this could be available\n const streamFormat = this.getStreamType();\n if (isNotNullish(streamFormat)) {\n this.sourceInfoFallbackService.setStreamFormat(streamFormat);\n }\n\n if (isNotNullish(this.mediaElement)) {\n this._videoCompletionTracker.reset();\n this._videoCompletionTracker.setVideoDuration(this.mediaElement.duration ?? 0);\n this.previousMutedValue = this.mediaElement.muted ?? false;\n }\n this.eventCallback(Event.SOURCE_LOADED, {});\n });\n\n // We need the PLAY event to indicate the intent to play\n // NOTE: use TIMECHANGED event on 'playing' and trigger PLAY as intended in states.dot graph\n this.listenToMediaElementEvent('play', () => {\n log(`play ${mediaElement.currentTime}`);\n const currentTime = mediaElement.currentTime ?? this.previousMediaTimeInSeconds;\n\n if (this.needsFirstPlayIntent) {\n this.previousMediaTimeInSeconds = currentTime;\n }\n this.needsFirstPlayIntent = false;\n\n this.eventCallback(Event.PLAY, {currentTime});\n });\n\n this.listenToMediaElementEvent('pause', () => {\n log(`pause ${mediaElement.currentTime}`);\n this.onPaused();\n });\n\n this.listenToMediaElementEvent('playing', () => {\n log(`playing ${mediaElement.currentTime}`);\n clearTimeout(this.bufferingTimeout);\n this.isPaused = false;\n\n // when the play attempt was before we have been attached to the player\n // no play event will set this to false -> collector is stuck in READY state\n this.needsFirstPlayIntent = false;\n });\n\n this.registerMediaElementErrorEvent(mediaElement);\n this.listenToMediaElementEvent('volumechange', () => {\n log(`volumechange ${mediaElement.currentTime}`);\n\n const muted = mediaElement.muted;\n const volume = mediaElement.volume;\n if (isNullish(muted) || isNullish(volume)) {\n return;\n }\n\n const currentTime = mediaElement.currentTime ?? this.previousMediaTimeInSeconds;\n const isMuted = isAudioMuted(muted, volume);\n\n if (this.previousMutedValue !== isMuted) {\n if (isMuted) {\n this.eventCallback(Event.MUTE, {currentTime});\n } else {\n this.eventCallback(Event.UN_MUTE, {currentTime});\n }\n this.previousMutedValue = isMuted;\n }\n });\n\n this.listenToMediaElementEvent('seeking', () => {\n log(`seeking ${mediaElement.currentTime}`);\n const {currentTime} = mediaElement;\n\n this.eventCallback(Event.SEEK, {currentTime});\n });\n\n this.listenToMediaElementEvent('seeked', () => {\n log(`seeked ${mediaElement.currentTime}`);\n const {currentTime} = mediaElement;\n\n clearTimeout(this.bufferingTimeout);\n\n this.eventCallback(Event.SEEKED, {currentTime});\n });\n\n this.listenToMediaElementEvent('timeupdate', () => {\n const currentTime = mediaElement.currentTime ?? 0;\n\n this.isBuffering = false;\n this.isSeeking = false;\n\n // silence events if we have not yet intended play\n if (this.needsFirstPlayIntent) {\n return;\n }\n\n if (!this.isPaused) {\n // This check ensures that the 'TIMECHANGED' event is only triggered when there is a measurable\n // change in 'currentTime'.\n // On Tizen and WebOS platforms, we observed cases where the 'timeupdate' event was triggered without\n // any actual change in the 'currentTime'. During bufferings this caused buffering - playing loops\n // with over 900 samples sent under one minute. (https://bitmovin.atlassian.net/browse/AN-4546)\n const absoluteTimeDeltaInMs = Math.abs(currentTime - this.previousMediaTimeInSeconds) * 1000;\n if (absoluteTimeDeltaInMs > 0) {\n this.eventCallback(Event.TIMECHANGED, {currentTime});\n }\n }\n\n this.checkQualityLevelAttributes();\n\n this.checkSeeking();\n\n // We are doing this in case we can not rely\n // on the \"stalled\" or \"waiting\" events in a specific browser\n // and to detect intrinsinc paused states (when we do not get a paused event)\n // but the player is paused already before attach or is paused from initialization on.\n this.checkPlayheadProgress();\n\n this.previousMediaTimeInSeconds = currentTime;\n });\n\n // The stalled event is fired when the user agent is trying to fetch media data,\n // but data is unexpectedly not forthcoming.\n // https://developer.mozilla.org/en-US/docs/Web/Events/stalled\n this.listenToMediaElementEvent('stalled', () => {\n // this event doesn't indicate buffering by definition (interupted playback),\n // only that data throughput to playout buffers is not as high as expected\n // It happens on Chrome every once in a while as SourceBuffer's are not fed\n // as fast as the underlying native player may prefer (but it does not lead to\n // interruption).\n });\n\n // The waiting event is fired when playback has stopped because of a temporary lack of data.\n // See https://developer.mozilla.org/en-US/docs/Web/Events/waiting\n this.listenToMediaElementEvent('waiting', () => {\n // we check here for seeking because a programmatically seek where just\n // the currentTime has been changed does not trigger a proper seek event\n log(`waiting ${mediaElement.currentTime}`);\n this.checkSeeking();\n this.onBuffering();\n });\n }\n\n protected registerMediaElementErrorEvent(mediaElement: HTMLVideoElementProxy) {\n this.listenToMediaElementEvent('error', () => {\n log(`error ${mediaElement.currentTime}`);\n const error = mediaElement.error;\n this.eventCallback(Event.ERROR, {\n currentTime: mediaElement.currentTime ?? this.previousMediaTimeInSeconds,\n // See https://developer.mozilla.org/en-US/docs/Web/API/MediaError\n code: error?.code ?? undefined,\n message: error?.message ?? undefined,\n originalError: error,\n data: {},\n });\n });\n }\n\n /**\n * Should only be calld when a mediaElement is attached\n */\n listenToMediaElementEvent(event: any, handler: any) {\n if (!this.mediaElement) {\n throw new Error('No media attached');\n }\n\n const boundHandler = handler.bind(this);\n\n this.mediaElementEventHandlers.push({event, handler: boundHandler});\n this.mediaElement.addEventListener(event, boundHandler, false);\n }\n\n onMaybeReady() {\n if (!this.needsReadyEvent || !this.mediaElement) {\n return;\n }\n\n this.needsReadyEvent = false;\n\n this.getCurrentPlaybackInfo();\n\n this._videoCompletionTracker.reset();\n this._videoCompletionTracker.setVideoDuration(this.mediaElement.duration ?? 0);\n }\n\n /**\n * unregister the mediaElement and removes it from the class\n * will also remove all references to this adapter instance (listener, interceptor)\n */\n protected unregisterMediaElement() {\n if (!this.mediaElement) {\n throw new Error('No media element attached');\n }\n\n const mediaElement = this.mediaElement;\n\n this.mediaElementEventHandlers.forEach((item: {event: string; handler: any}) => {\n mediaElement.removeEventListener(item.event, item.handler);\n });\n\n // assign the original load func to the html video element remove references to `this`\n const originalLoadFunc = this.mediaElementOriginalLoadFn;\n if (isNotNullish(originalLoadFunc)) {\n mediaElement.getRawPlayer().load = originalLoadFunc;\n }\n\n this.mediaElement = undefined;\n this.mediaElementEventHandlers = [];\n this.mediaElementOriginalLoadFn = undefined;\n\n // we can clear `checkPlayheadProgress` timeout, as it is not needed anymore\n clearTimeout(this.bufferingTimeout);\n }\n\n registerWindowEvents() {\n this.windowEventTracker.addEventListener('beforeunload', this.onPageClose.bind(this));\n this.windowEventTracker.addEventListener('unload', this.onPageClose.bind(this));\n }\n\n onPageClose() {\n if (!this.onBeforeUnLoadEvent) {\n this.onBeforeUnLoadEvent = true;\n const mediaElement = this.mediaElement;\n let currentTime: number | undefined;\n if (isNotNullish(mediaElement)) {\n currentTime = mediaElement.currentTime ?? this.previousMediaTimeInSeconds;\n }\n this.eventCallback(Event.UNLOAD, {currentTime});\n }\n this.release();\n }\n\n checkQualityLevelAttributes(silent = false) {\n if (!this.mediaElement) {\n throw new Error('No media attached');\n }\n\n const mediaElement = this.mediaElement;\n\n const qualityLevelInfo = this.getCurrentQualityLevelInfo();\n if (!qualityLevelInfo) {\n return;\n }\n\n const {bitrate, width, height} = qualityLevelInfo;\n\n if (isNotNullish(bitrate)) {\n const eventData: QualityChangeEvent = {\n type: 'video',\n width,\n height,\n bitrate,\n currentTime: mediaElement.currentTime ?? this.previousMediaTimeInSeconds,\n };\n if (this.qualityChangeService.shouldAllowVideoQualityChange(bitrate)) {\n if (!silent) {\n this.eventCallback(Event.VIDEO_CHANGE, eventData);\n }\n }\n\n this.qualityChangeService.setVideoBitrate(bitrate);\n this.stateMachineCallbacks.updateSampleQualityInfo(eventData);\n }\n }\n\n getSelectedSubtitleFromMediaElement(mediaElement: any): SubtitleInfo | undefined {\n if (isNullish(mediaElement.textTracks)) {\n return undefined;\n }\n const textTrackList = mediaElement.textTracks;\n for (const attr of textTrackList) {\n if (isNotNullish(attr.mode) && attr.mode === 'showing') {\n const isSubtitleDisplayed = isNotNullish(attr.language) && attr.language.length > 0;\n return {\n enabled: isSubtitleDisplayed,\n language: isSubtitleDisplayed ? attr.language : undefined,\n };\n }\n }\n return {\n enabled: false,\n };\n }\n\n private onPaused(currentTime?: number) {\n if (this.isPaused) {\n return;\n }\n if (!this.mediaElement) {\n throw new Error('No media attached');\n }\n\n if (!currentTime) {\n currentTime = this.mediaElement.currentTime ?? this.previousMediaTimeInSeconds;\n }\n\n this.eventCallback(Event.PAUSE, {currentTime});\n\n this.isPaused = true;\n }\n\n private onBuffering() {\n if (!this.mediaElement) {\n throw new Error('No media attached');\n }\n const {currentTime} = this.mediaElement;\n\n // this handler may be called multiple times\n // for one actual buffering-event occuring so lets guard from\n // triggering this event redundantly.\n if (this.isBuffering || (this.isPaused && !this.isSeeking)) {\n return;\n }\n\n if (this.isSeeking) {\n this.eventCallback(Event.SEEK, {currentTime});\n } else {\n this.eventCallback(Event.START_BUFFERING, {currentTime});\n }\n this.isBuffering = true;\n }\n\n private checkPlayheadProgress() {\n if (!this.mediaElement) {\n throw new Error('No media attached');\n }\n const mediaElement = this.mediaElement;\n if (mediaElement.paused) {\n this.onPaused();\n }\n\n clearTimeout(this.bufferingTimeout);\n\n this.bufferingTimeout = setTimeout(() => {\n const currentTime = mediaElement.currentTime ?? this.previousMediaTimeInSeconds;\n if (mediaElement.paused || (mediaElement.ended && !this.isBuffering)) {\n return;\n }\n\n // Calculate the playback time difference (delta) to later verify if playback progress\n // has halted or slowed down. The \"timeupdate\" event in HTML5 media elements is\n // not reliable, especially on slower devices like TVs or when the JavaScript\n // main thread is blocked. These scenarios can lead to delays in\n // \"timeupdate\" event emissions, even though playback progresses normally in\n // the video rendering pipeline.\n const playingDeltaInSeconds = currentTime - this.previousMediaTimeInSeconds;\n\n // Minimum playback progress threshold to avoid incorrectly reporting buffering events.\n // A 20% margin is applied in relation to the Timeout to account for timing inaccuracies\n // and short stalling events. This is a tradeoff between overreporting and underreporting\n // buffering events as well as preventing buffering -> playing loops. (https://bitmovin.atlassian.net/browse/AN-4572)\n const minPlayingDeltaThresholdInSeconds = (HTML5InternalAdapter.BUFFERING_TIMECHANGED_TIMEOUT_IN_MS / 1000) * 0.8;\n\n // If the playback progress is less than the threshold, treat it as buffering.\n if (playingDeltaInSeconds < minPlayingDeltaThresholdInSeconds) {\n this.onBuffering();\n }\n }, HTML5InternalAdapter.BUFFERING_TIMECHANGED_TIMEOUT_IN_MS);\n }\n\n /**\n * Method to detect seeking events on platforms where seeking events are not reliable\n * This code is currently called in timeUpdate event and waiting event.\n * - We can't rely on the `seeking` and 'seeked' events on certain platforms (Tizen, WebOs, Safari, etc.)\n * - Another limitation is that we cannot rely on the time update event to be fired in regular intervals\n * The time between two timeupdate events can be 1ms or 250ms for example. This code needs to handle this variance.\n */\n private checkSeeking() {\n if (!this.mediaElement) {\n throw new Error('No media attached');\n }\n const currentMediaTimeInSeconds = this.mediaElement.currentTime;\n const playbackRate = this.mediaElement.playbackRate;\n // If we don't have currentTime nor playbackRate beneath calculation does not make sense, player was probably destroyed.\n if (isNullish(currentMediaTimeInSeconds) || isNullish(playbackRate)) {\n return;\n }\n\n // absolut difference of playback position compared with last call of method\n const playbackPositionDeltaInSeconds = Math.abs(currentMediaTimeInSeconds - this.previousMediaTimeInSeconds);\n\n // If the playback position has not changed more than 1 second we ignore it, to avoid\n // issuing of micro seeks. If not ignored the progressThreshold below might be too low, in order to\n // be reliable for such minor seeks. This is a tradeoff between overreporting and underreporting of seek events.\n if (playbackPositionDeltaInSeconds < 1) {\n this.previousClientTime = Date.now();\n return;\n }\n\n const currentClientTimeInMillis = Date.now();\n\n // Real time delta of method calls. How much time has passed since last call (in seconds)\n const clientTimeProgressInSeconds = (currentClientTimeInMillis - this.previousClientTime) / 1000;\n\n // we have to consider the playbackRate when calculating the threshold to trigger seeks\n // playbackRate of 3 progresses the playback triple the speed so the playbackPositionDelta\n // is also higher. This needs to be considered here\n // Adding 0.5 is a safety margin to avoid over reporting of seek events\n const thresholdModifier = playbackRate + 0.5;\n const progressThresholdInSeconds = clientTimeProgressInSeconds * thresholdModifier;\n\n // If the media time (current position of the playback) progresses much faster than real time\n // we consider this a time jump/seek\n if (playbackPositionDeltaInSeconds > progressThresholdInSeconds) {\n this.isSeeking = true;\n this.onPaused(this.previousMediaTimeInSeconds + clientTimeProgressInSeconds);\n }\n\n this.previousClientTime = Date.now();\n }\n}\n\nconst log = (msg: string) => {\n const msgTime = new Date().toISOString().substring(11);\n const prefix = `${msgTime}[HTML5InternalAdapter]`;\n const logMsg = `${prefix}: ${msg}`;\n logger.log(logMsg);\n};\n","import type {AdapterAPI, SessionMetadataAPI} from '../../api/AdapterAPI';\nimport {\n sanitizeSessionMetadataAudioLanguage,\n sanitizeSessionMetadataSubtitleEnabled,\n sanitizeSessionMetadataSubtitleLanguage,\n} from '../../api/adapterApiUtils';\nimport {Analytics} from '../../core/Analytics';\nimport type {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {logger} from '../../utils/Logger';\nimport {\n hasPlayerAlreadyBeenAugmented,\n isDefined,\n markPlayerInstanceAsAugmented,\n} from '../../utils/playerAugmentationUtils';\nimport {VERSION} from '../../utils/Version';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {HTMLVideoElementInternalAdapter} from './HTMLVideoElementInternalAdapter';\nimport {HTMLVideoElementProxy} from './HTMLVideoElementProxy';\n\nexport class HTMLVideoElementAdapter implements AdapterAPI {\n private readonly internalAdapter: InternalAdapterAPI | undefined;\n private readonly analytics: Analytics | undefined;\n\n constructor(\n config: AnalyticsConfig,\n player: HTMLVideoElement,\n opts?: AnalyticsStateMachineOptions,\n // anonymous type for source metadata to not create any public named interface, until we stabilize the adapter API and provided typings\n sourceMetadata?: {\n audioCodec?: string;\n audioLanguage?: string;\n streamFormat?: string;\n videoCodec?: string;\n },\n ) {\n if (hasPlayerAlreadyBeenAugmented(player)) {\n logger.errorMessageToUser('Bitmovin Analytics is already hooked up to this player instance');\n return;\n }\n markPlayerInstanceAsAugmented(player);\n\n const sanitizedConfig = sanitizeAnalyticsConfig(config);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n return;\n }\n guardAgainstDuplicatedUserId(sanitizedConfig);\n\n this.internalAdapter = new HTMLVideoElementInternalAdapter(new HTMLVideoElementProxy(player), opts, sourceMetadata);\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n }\n\n get sessionMetadata() {\n const internalAdapter = this.internalAdapter as HTMLVideoElementInternalAdapter;\n\n return {\n setAudioLanguage(audioLanguage: string) {\n internalAdapter.sessionData.audioLanguage = sanitizeSessionMetadataAudioLanguage(audioLanguage);\n },\n setSubtitleEnabled(enabled: boolean) {\n internalAdapter.sessionData.subtitleEnabled = sanitizeSessionMetadataSubtitleEnabled(enabled);\n },\n setSubtitleLanguage(subtitleLanguage: string) {\n internalAdapter.sessionData.subtitleLanguage = sanitizeSessionMetadataSubtitleLanguage(subtitleLanguage);\n },\n } satisfies SessionMetadataAPI;\n }\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getCurrentImpressionId();\n }\n\n getUserId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getUserId();\n }\n\n setCustomData(values: CustomDataValues) {\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.setCustomData(values);\n }\n\n setCustomDataOnce(values: CustomDataValues) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.setCustomDataOnce(values);\n }\n\n sourceChange(\n config: AnalyticsConfig,\n /*\n * Custom implementation adds 2nd argument to support session data feature only on HTML5 for now.\n */\n sourceMetadata?: {\n audioCodec?: string;\n audioLanguage?: string;\n streamFormat?: string;\n videoCodec?: string;\n },\n ) {\n if (!isDefined(this.analytics)) return;\n if (!isDefined(this.internalAdapter)) return;\n\n this.analytics.sourceChange(config);\n\n const internalAdapter = this.internalAdapter as HTMLVideoElementInternalAdapter;\n internalAdapter.sessionData.streamFormat = sourceMetadata?.streamFormat;\n internalAdapter.sessionData.audioCodec = sourceMetadata?.audioCodec;\n internalAdapter.sessionData.videoCodec = sourceMetadata?.videoCodec;\n internalAdapter.sessionData.audioLanguage = sourceMetadata?.audioLanguage;\n }\n}\n","import {Player} from '../../enums/Player';\nimport {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport {PlaybackInfo} from '../../types/PlaybackInfo';\nimport {QualityLevelInfo} from '../../types/QualityLevelInfo';\nimport {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {HTML5InternalAdapter} from './HTML5InternalAdapter';\nimport {HTMLVideoElementProxy} from './HTMLVideoElementProxy';\n\nexport class HTMLVideoElementInternalAdapter extends HTML5InternalAdapter implements InternalAdapterAPI {\n sessionData: InternalHTML5SessionData = {};\n\n constructor(\n mediaElement: HTMLVideoElementProxy,\n opts?: AnalyticsStateMachineOptions,\n sourceMetadata?: {\n audioCodec?: string;\n audioLanguage?: string;\n streamFormat?: string;\n videoCodec?: string;\n },\n ) {\n super(mediaElement, opts);\n\n // source metadata\n this.sessionData.streamFormat = sourceMetadata?.streamFormat;\n this.sessionData.audioCodec = sourceMetadata?.audioCodec;\n this.sessionData.videoCodec = sourceMetadata?.videoCodec;\n this.sessionData.audioLanguage = sourceMetadata?.audioLanguage;\n }\n\n getPlayerVersion = () => {\n // player version is set by ingress for html5 player, thus we only return empty string here\n return '';\n };\n override getPlayerName = () => Player.HTML5;\n override getCurrentPlaybackInfo(): PlaybackInfo {\n const info = super.getCurrentPlaybackInfo();\n\n // source metadata\n info.streamFormat = this.sessionData.streamFormat ?? info.streamFormat;\n info.audioCodec = this.sessionData.audioCodec ?? info.audioCodec;\n info.videoCodec = this.sessionData.videoCodec ?? info.videoCodec;\n\n // language info\n info.subtitleEnabled = this.sessionData.subtitleEnabled ?? info.subtitleEnabled;\n // only set if enabled\n const subtitleLanguage = this.sessionData.subtitleLanguage ?? info.subtitleLanguage;\n info.subtitleLanguage = info.subtitleEnabled === true ? subtitleLanguage : undefined;\n\n info.audioLanguage = this.sessionData.audioLanguage ?? info.audioLanguage;\n\n return info;\n }\n\n override resetSourceRelatedState() {\n super.resetSourceRelatedState();\n this.sessionData = {};\n }\n\n override getStreamURL() {\n return this.mediaElement ? this.mediaElement.currentSrc : undefined;\n }\n\n getCurrentQualityLevelInfo(): QualityLevelInfo | null {\n return {\n bitrate: undefined,\n width: this.mediaElement ? this.mediaElement.videoWidth : undefined,\n height: this.mediaElement ? this.mediaElement.videoHeight : undefined,\n };\n }\n}\n\n/** Represents the internal html5-only adapter state, holding the source and session metadata. */\ninterface InternalHTML5SessionData {\n streamFormat?: string;\n audioCodec?: string;\n videoCodec?: string;\n audioLanguage?: string;\n subtitleEnabled?: boolean;\n subtitleLanguage?: string;\n}\n","import {safeAccess} from '../../utils/objectUtils';\n\nexport class HTMLVideoElementProxy {\n constructor(private readonly rawPlayer: HTMLVideoElement) {}\n\n get currentTime() {\n return safeAccess(() => this.rawPlayer.currentTime);\n }\n\n get duration() {\n return safeAccess(() => this.rawPlayer.duration);\n }\n\n get muted() {\n return safeAccess(() => this.rawPlayer.muted);\n }\n\n get height() {\n return safeAccess(() => this.rawPlayer.height);\n }\n\n get width() {\n return safeAccess(() => this.rawPlayer.width);\n }\n\n get autoplay() {\n return safeAccess(() => this.rawPlayer.autoplay);\n }\n\n get src() {\n return safeAccess(() => this.rawPlayer.src);\n }\n\n get currentSrc() {\n return safeAccess(() => this.rawPlayer.currentSrc);\n }\n\n get readyState() {\n return safeAccess(() => this.rawPlayer.readyState);\n }\n\n get volume() {\n return safeAccess(() => this.rawPlayer.volume);\n }\n\n get error() {\n return safeAccess(() => this.rawPlayer.error);\n }\n\n get textTracks() {\n return safeAccess(() => this.rawPlayer.textTracks);\n }\n\n get paused() {\n return safeAccess(() => this.rawPlayer.paused);\n }\n\n get ended() {\n return safeAccess(() => this.rawPlayer.ended);\n }\n\n get playbackRate() {\n return safeAccess(() => this.rawPlayer.playbackRate);\n }\n\n get videoWidth() {\n return safeAccess(() => this.rawPlayer.videoWidth);\n }\n\n get videoHeight() {\n return safeAccess(() => this.rawPlayer.videoHeight);\n }\n\n getVideoPlaybackQuality() {\n // this API is not supported in all browsers (especially on iOS Safari it was added quite late)\n // reference: https://developer.mozilla.org/en-US/docs/Web/API/VideoPlaybackQuality\n return safeAccess(() => this.rawPlayer.getVideoPlaybackQuality?.());\n }\n\n addEventListener = (...args: Parameters<HTMLVideoElement['addEventListener']>) => {\n safeAccess(() => this.rawPlayer.addEventListener(...args));\n };\n\n removeEventListener = (...args: Parameters<HTMLVideoElement['removeEventListener']>) => {\n safeAccess(() => this.rawPlayer.removeEventListener(...args));\n };\n\n /**\n * Returns the underlying raw HTMLVideoElement.\n * Used only for overwriting original load function. Should not be used otherwise.\n */\n getRawPlayer(): HTMLVideoElement {\n return this.rawPlayer;\n }\n}\n","import {isNullish} from '../../../utils/Utils';\nimport {HTMLVideoElementProxy} from '../HTMLVideoElementProxy';\n\nexport default class HTMLVideoElementStatisticsProvider {\n private previousTotalDroppedFrames = 0;\n\n constructor(private videoElement: HTMLVideoElementProxy | undefined) {}\n\n getDroppedFrames(): number {\n if (this.videoElement == undefined) {\n return 0;\n }\n\n const playbackQuality = this.videoElement.getVideoPlaybackQuality();\n if (isNullish(playbackQuality)) {\n return 0;\n }\n\n const droppedFrames = playbackQuality.droppedVideoFrames;\n const currentDroppedFrames = droppedFrames - this.previousTotalDroppedFrames;\n this.previousTotalDroppedFrames = droppedFrames;\n return currentDroppedFrames;\n }\n reset() {\n this.previousTotalDroppedFrames = 0;\n }\n}\n","import {AnalyticsStateMachine} from '../../analyticsStateMachines/AnalyticsStateMachine';\nimport {EventDispatcher} from '../../core/EventDispatcher';\nimport QualityChangeService from '../../core/QualityChangeService';\nimport {SourceInfoFallbackService} from '../../core/SourceInfoFallbackService';\nimport {SsaiService} from '../../core/ssai/SsaiService';\nimport {Event, EventMap} from '../../enums/Event';\nimport {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport {CustomDataValues} from '../../types/CustomDataValues';\nimport {DownloadSpeedInfo} from '../../types/DownloadSpeedInfo';\nimport {DrmPerformanceInfo} from '../../types/DrmPerformanceInfo';\nimport type {CustomDataValuesEvent} from '../../types/EventData';\nimport {NoExtraProperties} from '../../types/NoExtraProperties';\nimport {SegmentInfo} from '../../types/SegmentInfo';\nimport type {SourceMetadata} from '../../types/SourceMetadata';\nimport {defaultStateMachineCallbacks, StateMachineCallbacks} from '../../types/StateMachineCallbacks';\nimport {getGlobalScreenDimensions} from '../../utils/globalScopeUtils';\nimport {logger} from '../../utils/Logger';\nimport {getCurrentTimestamp} from '../../utils/Utils';\nimport {WindowEventTracker} from '../../utils/WindowEventTracker';\n\nimport {EventCallbackDispatcher} from './EventCallbackDispatcher';\n\nexport abstract class InternalAdapter implements EventCallbackDispatcher {\n readonly onLicenseKeyReceived: EventDispatcher<{licenseKey: string}> = new EventDispatcher();\n readonly onLicenseCallFailed: EventDispatcher<any> = new EventDispatcher();\n readonly qualityChangeService: QualityChangeService = new QualityChangeService();\n readonly ssaiService = new SsaiService();\n readonly stateMachineCallbacks: StateMachineCallbacks = {...defaultStateMachineCallbacks};\n\n protected stateMachine!: AnalyticsStateMachine;\n protected opts: AnalyticsStateMachineOptions;\n protected sourceInfoFallbackService: SourceInfoFallbackService = new SourceInfoFallbackService();\n protected drmPerformanceInfo: DrmPerformanceInfo | undefined = undefined;\n protected readonly windowEventTracker: WindowEventTracker = new WindowEventTracker();\n\n protected abstract get currentTime(): number;\n\n constructor(opts?: AnalyticsStateMachineOptions) {\n if (!opts) {\n opts = {\n starttime: undefined,\n };\n }\n if (!opts.starttime) {\n opts.starttime = getCurrentTimestamp();\n }\n\n this.opts = opts;\n }\n\n release() {\n this.stateMachine.resetIntervals();\n this.stateMachineCallbacks.release();\n this.resetSourceRelatedState();\n this.windowEventTracker.release();\n }\n\n eventCallback<StateMachineEvent extends keyof EventMap, StateMachineEventData extends EventMap[StateMachineEvent]>(\n event: StateMachineEvent,\n eventData: NoExtraProperties<EventMap[StateMachineEvent], StateMachineEventData>,\n eventTimestamp: number = Date.now(),\n ) {\n eventData = eventData || {};\n if (!this.stateMachine) {\n logger.log(\"Bitmovin Analytics: StateMachine isn't ready yet\");\n } else {\n this.stateMachine.callEvent(event, eventData, eventTimestamp);\n }\n }\n\n getCommonPlaybackInfo() {\n const dimensions = getGlobalScreenDimensions();\n\n return {\n screenHeight: dimensions?.height,\n screenWidth: dimensions?.width,\n };\n }\n\n getDrmPerformanceInfo(): DrmPerformanceInfo | undefined {\n return undefined;\n }\n\n getSegmentInfo(): SegmentInfo[] {\n return [];\n }\n\n getDownloadSpeedInfo(): DownloadSpeedInfo {\n return {\n segmentsDownloadCount: 0,\n segmentsDownloadSize: 0,\n segmentsDownloadTime: 0,\n avgDownloadSpeed: 0,\n minDownloadSpeed: 0,\n maxDownloadSpeed: 0,\n avgTimeToFirstByte: 0,\n };\n }\n\n resetDownloadSpeedInfoMeasures(): void {\n // noop by default\n }\n\n setCustomData(values: CustomDataValues) {\n const previousState = this.stateMachine.currentState;\n const eventData: CustomDataValuesEvent = {customDataValues: values, currentTime: this.currentTime};\n\n if (\n this.stateMachine.currentState &&\n (this.stateMachine.currentState === 'PAUSE' || this.stateMachine.currentState === 'PLAYING')\n ) {\n // If we are in State.PAUSE or State.PLAYING, we want to make \"a cut\" of the current state\n // to trigger sample sending with current custom data values.\n this.eventCallback(Event.CUSTOM_DATA_CHANGE, {currentTime: this.currentTime});\n // Then we have to call this \"previous state\" event to return back\n // to the previous state and to set new custom data values.\n // !! here we relay on the fact that we have `PAUSE` and `PLAYING` events with the same name as the states above !!\n this.eventCallback(Event[previousState], eventData);\n }\n // ... else, for any other states, we don't care, and we will just set new custom data values asap, so they will\n // be sent with the upcoming sample\n else {\n this.stateMachineCallbacks.customdatachange(undefined, undefined, eventData);\n }\n }\n\n sourceChange(analyticsConfig: AnalyticsConfig): void {\n this.eventCallback(Event.MANUAL_SOURCE_CHANGE, {currentTime: this.currentTime, config: analyticsConfig});\n }\n\n resetSourceRelatedState(): void {\n this.sourceInfoFallbackService.reset();\n this.drmPerformanceInfo = undefined;\n }\n\n programChange(sourceMetadata: SourceMetadata): void {\n const isSsaiActive = this.ssaiService.isInActiveState();\n this.stateMachine.programChange(this.currentTime, isSsaiActive, sourceMetadata);\n }\n}\n","import {AdBreakInfo} from '../../../types/ads/AdBreakInfo';\nimport {AdInfo} from '../../../types/ads/AdInfo';\n\nexport class AdCallbacks {\n onAdStarted = (_ad: AdInfo): void => undefined;\n onAdFinished = (_ad: AdInfo): void => undefined;\n onAdBreakStarted = (_adBreak: AdBreakInfo): void => undefined;\n onAdBreakFinished = (_adBreak: AdBreakInfo): void => undefined;\n onAdClicked = (_event: AdClickedPayload): void => undefined;\n onAdError = (_event: AdErrorPayload): void => undefined;\n onAdManifestLoaded = (_event: AdManifestLoadedPayload): void => undefined;\n onAdQuartile = (_event: AdQuartilePayload): void => undefined;\n onAdSkipped = (_ad: AdInfo): void => undefined;\n onPlay = (): void => undefined;\n onPause = (): void => undefined;\n onBeforeUnload = (): void => undefined;\n}\n\nexport interface AdModuleAPI {\n readonly adCallbacks: AdCallbacks;\n isLinearAdActive: () => boolean;\n getContainer: () => HTMLElement | undefined;\n getAdModuleInfo: () => {name?: string; version?: string};\n currentTime: () => number;\n getAutoPlay(): boolean;\n}\n\nexport interface AdClickedPayload {\n clickThroughUrl?: string;\n}\n\nexport interface AdErrorPayload {\n code?: number;\n message?: string;\n adBreakInfo?: AdBreakInfo;\n activeAdId?: string;\n}\n\nexport interface AdManifestLoadedPayload {\n adBreakInfo?: AdBreakInfo;\n manifestDownloadTime?: number;\n isVmap: boolean;\n}\n\nexport enum AdQuartile {\n FIRST_QUARTILE = 'firstQuartile',\n MIDPOINT = 'midpoint',\n THIRD_QUARTILE = 'thirdQuartile',\n}\n\nexport interface AdQuartilePayload {\n quartile: AdQuartile;\n}\n","import type {AdapterAPI} from '../../api/AdapterAPI';\nimport {Analytics} from '../../core/Analytics';\nimport {Event} from '../../enums/Event';\nimport type {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {logger} from '../../utils/Logger';\nimport {\n hasPlayerAlreadyBeenAugmented,\n isDefined,\n markPlayerInstanceAsAugmented,\n} from '../../utils/playerAugmentationUtils';\nimport {tryJSONStringify} from '../../utils/Utils';\nimport {VERSION} from '../../utils/Version';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {ShakaInternalAdapter} from './ShakaInternalAdapter';\nimport {ShakaPlayerProxy} from './ShakaPlayerProxy';\n\nexport class ShakaAdapter implements AdapterAPI {\n private readonly internalAdapter: InternalAdapterAPI | undefined;\n private readonly analytics: Analytics | undefined;\n\n constructor(config: AnalyticsConfig, player: any, opts?: AnalyticsStateMachineOptions) {\n if (hasPlayerAlreadyBeenAugmented(player)) {\n logger.errorMessageToUser('Bitmovin Analytics is already hooked up to this player instance');\n return;\n }\n markPlayerInstanceAsAugmented(player);\n\n const sanitizedConfig = sanitizeAnalyticsConfig(config);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n return;\n }\n\n guardAgainstDuplicatedUserId(sanitizedConfig);\n\n this.internalAdapter = new ShakaInternalAdapter(new ShakaPlayerProxy(player), opts);\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n this.wrapPlayerLoad(player);\n }\n\n // The Shaka player's `load()` method does not trigger error events for exceptions thrown while loading the manifest.\n // Therefore, we wrap this method and catch exceptions and forward them to analytics.\n // TODO [AN-4149]: this needs to be reevaluated, since the cypress test with a none existing manifest is not working\n private wrapPlayerLoad(player: any) {\n // Check if `player.load` can be overwritten\n const playerPrototype = Object.getPrototypeOf(player); // in the case of the player proxy, the load method is in the prototype\n const loadPropertyDescriptor =\n Object.getOwnPropertyDescriptor(player, 'load') ?? Object.getOwnPropertyDescriptor(playerPrototype, 'load');\n if (loadPropertyDescriptor?.writable !== true && loadPropertyDescriptor?.set === undefined) {\n // The player instance might be a proxy (e.g., from Shaka UI Library), making `player.load` a getter-only accessor.\n // This prevents us to override `load` function with our error interception logic.\n logger.errorMessageToUser(\n 'Bitmovin Analytics is unable to intercept player.load method. The provided Shaka player instance appears to be a ' +\n 'proxy object (e.g. created via Shaka UI Library). Ensure you provide the local player instance instead.',\n );\n return;\n }\n\n const originalLoad = player.load;\n /**\n * Avoid passing `this` (the adapter reference) to an interceptor or its error handler.\n *\n * Reason:\n * Passing `this` can lead to memory leaks. When that shaka player is destroyed, it does not clean up the `player.load`\n * method, which we intercept. This leaves the old adapter and interceptor still referenced, even though the shaka player\n * has been destroyed. If a new adapter is then created for the same shaka player, a new interceptor will also be created.\n * This new interceptor will wrap the `player.load` method again, which was already wrapped by the previous adapter,\n * leading to unnecessary memory usage and potential memory leaks.\n */\n const thatInternalAdapter = this.internalAdapter as ShakaInternalAdapter;\n\n player.load = (...args) =>\n new Promise((resolve, reject) => {\n originalLoad\n .apply(player, args)\n .then((result) => resolve(result))\n .catch((error) => {\n const eventObject = {\n currentTime: 0,\n // See https://github.com/shaka-project/shaka-player/blob/main/lib/util/error.js\n code: error?.code ?? undefined,\n message: tryJSONStringify({category: error?.category, severity: error?.severity}),\n data: {additionalData: tryJSONStringify(error?.data)},\n originalError: error,\n };\n\n thatInternalAdapter.eventCallback(Event.ERROR, eventObject);\n\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n reject(error);\n });\n });\n }\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getCurrentImpressionId();\n }\n\n getUserId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getUserId();\n }\n\n setCustomData(values: CustomDataValues) {\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.setCustomData(values);\n }\n\n setCustomDataOnce(values: CustomDataValues) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.setCustomDataOnce(values);\n }\n\n sourceChange(config: AnalyticsConfig) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.sourceChange(config);\n }\n}\n","import type {Analytics} from '../../core/Analytics';\nimport {Event} from '../../enums/Event';\nimport {Player} from '../../enums/Player';\nimport {StreamTypes} from '../../enums/StreamTypes';\nimport {ErrorDetailBackend} from '../../features/errordetails/ErrorDetailBackend';\nimport {ErrorDetailTracking} from '../../features/errordetails/ErrorDetailTracking';\nimport type {Feature} from '../../features/Feature';\nimport type {FeatureConfig} from '../../features/FeatureConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CodecInfo} from '../../types/CodecInfo';\nimport type {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport type {PlaybackInfo} from '../../types/PlaybackInfo';\nimport type {QualityLevelInfo} from '../../types/QualityLevelInfo';\nimport {logger} from '../../utils/Logger';\nimport {isNotNullish, isNullish, tryJSONStringify} from '../../utils/Utils';\nimport {HTML5InternalAdapter} from '../html5/HTML5InternalAdapter';\nimport {HTMLVideoElementProxy} from '../html5/HTMLVideoElementProxy';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {ShakaPlayerProxy} from './ShakaPlayerProxy';\nimport {ShakaErrorEvent, ShakaPlayerEvent} from './shakaPlayerTypes';\n\nexport class ShakaInternalAdapter extends HTML5InternalAdapter implements InternalAdapterAPI {\n private readonly player: ShakaPlayerProxy;\n\n constructor(player: ShakaPlayerProxy, opts?: AnalyticsStateMachineOptions) {\n const mediaElement = player.getMediaElement();\n super(mediaElement ? new HTMLVideoElementProxy(mediaElement as HTMLVideoElement) : undefined, opts);\n this.player = player;\n }\n\n override initialize(analytics: Analytics): Array<Feature<FeatureConfigContainer, FeatureConfig>> {\n super.initialize(analytics);\n // we expect to receive the HTMLVideoElement from ShakaPlayer\n const videoElement = (this.player.getMediaElement() as HTMLVideoElement) ?? undefined;\n\n if (isNotNullish(videoElement)) {\n this.setMediaElement(new HTMLVideoElementProxy(videoElement));\n } else {\n // if we don't have video/media element from shaka player during initialization (shaka behaviour:\n // it has not loaded content yet), we need to wait for the `media-source` state change event and\n // then try to get the media element.\n const handleOnStateChangeAndSetMediaElement = (event: {state: string}) => {\n if (event.state === 'media-source') {\n try {\n this.player.removeEventListener(ShakaPlayerEvent.ONSTATECHANGE, handleOnStateChangeAndSetMediaElement);\n // we expect to receive the HTMLVideoElement from ShakaPlayer\n const mediaElement = this.player.getMediaElement() as HTMLVideoElement;\n this.setMediaElement(isNotNullish(mediaElement) ? new HTMLVideoElementProxy(mediaElement) : undefined);\n } catch (e) {\n logger.errorMessageToUser(\n 'Something went wrong while getting underlying HTMLVideoElement. Not possible to attach adapter and initialize Bitmovin Analytics. Error: ',\n e,\n );\n this.release();\n }\n }\n };\n\n this.player.addEventListener(ShakaPlayerEvent.ONSTATECHANGE, handleOnStateChangeAndSetMediaElement);\n }\n\n // With shaka a qualitychange only triggers a buffering, so to catch a qualitychange in time, we need to check qualityinfo on bufferings as well.\n this.player.addEventListener(ShakaPlayerEvent.BUFFERING, (_) => {\n this.checkQualityLevelAttributes();\n });\n\n this.player.addEventListener(ShakaPlayerEvent.ONSTATECHANGE, (event: {state: string}) => {\n if (event.state === 'detach') {\n // Detach the player from the current media element. Leaves the player in a state where\n // it cannot play media, until it has been attached to something else.\n this.eventCallback(Event.UNLOAD, {});\n this.release();\n }\n });\n\n const errorDetailTracking = new ErrorDetailTracking(\n analytics.errorDetailTrackingSettingsProvider,\n new ErrorDetailBackend(analytics.errorDetailTrackingSettingsProvider.collectorConfig),\n [analytics.errorDetailSubscribable],\n undefined,\n );\n return [errorDetailTracking];\n }\n\n override getPlayerName = () => Player.SHAKA;\n\n getPlayerVersion = () => this.player.playerVersion ?? 'unknown';\n\n override isLive = () => {\n return this.player ? this.player.isLive() : undefined;\n };\n\n override getCurrentPlaybackInfo(): PlaybackInfo {\n const playbackInfo: PlaybackInfo = {\n ...super.getCurrentPlaybackInfo(),\n };\n\n const codecInfo = getShakaCodecInfo(this.player);\n this.sourceInfoFallbackService.applyAndStoreCodecInfo(playbackInfo, codecInfo);\n\n return playbackInfo;\n }\n\n override getStreamType(): StreamTypes | undefined {\n return getShakaStreamFormat(this.player);\n }\n\n override getStreamURL() {\n return this.player.getAssetUri() ?? undefined;\n }\n\n override getCurrentQualityLevelInfo(): QualityLevelInfo | null {\n const variantTracks = this.player.getVariantTracks();\n\n if (isNullish(variantTracks)) {\n // possibly can happen when player is destroyed\n return null;\n }\n\n const activeVideoTrack = variantTracks\n .filter((track: any) => track.active)\n .filter((track: any) => track.videoCodec || track.videoId !== undefined)[0];\n\n if (!activeVideoTrack) {\n // can only happen for audio-only streams\n return null;\n }\n\n const bitrate = activeVideoTrack.videoBandwidth || activeVideoTrack.bandwidth;\n const width = activeVideoTrack.width;\n const height = activeVideoTrack.height;\n\n return {\n bitrate: bitrate,\n width: width,\n height: height,\n };\n }\n\n /** override html5 adapter function to not listen to native media element \"error\" event,\n * but instead use shaka player \"error\" event\n */\n override registerMediaElementErrorEvent = (_: HTMLVideoElementProxy) => {\n this.player.addEventListener(ShakaPlayerEvent.ERROR, (event: {detail: ShakaErrorEvent}) => {\n this.eventCallback(Event.ERROR, {\n currentTime: this.mediaElement?.currentTime ?? 0,\n code: event.detail?.code ?? undefined,\n message: event.detail?.message ?? undefined,\n originalError: event,\n data: {\n additionalData: tryJSONStringify(event.detail),\n exceptionMessage: event.detail?.message ?? undefined,\n exceptionStacktrace: event.detail?.stack?.split('\\n') ?? undefined,\n },\n });\n });\n };\n}\n\nexport const getShakaCodecInfo = (player: any): CodecInfo | undefined => {\n const variantTracks = player.getVariantTracks();\n const activeTrack = variantTracks.find((track: any) => track.active);\n\n return {\n videoCodec: activeTrack?.videoCodec,\n audioCodec: activeTrack?.audioCodec,\n };\n};\n\nexport const getShakaStreamFormat = (player: ShakaPlayerProxy): StreamTypes | undefined => {\n const manifestType = player.getManifestType()?.toLowerCase();\n\n if (manifestType === StreamTypes.dash) {\n return StreamTypes.dash;\n } else if (manifestType === StreamTypes.hls) {\n return StreamTypes.hls;\n }\n\n // https://shaka-player-demo.appspot.com/docs/api/shaka.Player.html#.LoadMode\n const LOAD_MODE_SRC_EQUALS = 3;\n\n // Fallback to progressive if no manifest type is available.\n // In order to avoid over-reporting of progressive when the source is not loaded yet\n // (where getManifestType is also null similar to when a progressive source is used)\n // we check that the load mode is SRC_EQUALS which indicates native player usage\n // and make sure that the asset is already loaded through check if the uri is available\n if (isNullish(manifestType) && player.getLoadMode() === LOAD_MODE_SRC_EQUALS && isNotNullish(player.getAssetUri())) {\n return StreamTypes.prog;\n }\n\n return undefined;\n};\n","import {safeAccess} from '../../utils/objectUtils';\n\nexport class ShakaPlayerProxy {\n // We use any here because `shaka-player` npm package is not installed, because it has bad TypeScript definitions\n // @see https://github.com/shaka-project/shaka-player/issues/6442)\n // - we can't use \"type imports\" (`import type {}`),\n // - we can't cover copies of the library values with unit tests\n //\n // Shaka discussion about migration to TypeScript\n // @see https://github.com/shaka-project/shaka-player/issues/8262\n constructor(private readonly rawPlayer: any) {}\n\n addEventListener = (type, listener) => {\n safeAccess(() => this.rawPlayer.addEventListener(type, listener));\n };\n\n removeEventListener = (type, listener) => {\n safeAccess(() => this.rawPlayer.removeEventListener(type, listener));\n };\n\n getMediaElement = () => safeAccess(() => this.rawPlayer.getMediaElement());\n\n isLive = () => safeAccess(() => this.rawPlayer.isLive());\n\n getAssetUri = () => safeAccess(() => this.rawPlayer.getAssetUri());\n\n getVariantTracks = () => safeAccess(() => this.rawPlayer.getVariantTracks());\n\n getManifestType = () => {\n // `getManifestType` is only available in shaka v4.4.0 and later (we need to support 4.0.0)\n return safeAccess(() => this.rawPlayer.getManifestType?.());\n };\n\n getLoadMode = () => safeAccess(() => this.rawPlayer.getLoadMode?.());\n\n get playerVersion(): string | undefined {\n return safeAccess(() => this.rawPlayer.constructor.version);\n }\n}\n","/*!\n * This file was created to avoid \"values imports\" (constants/enums/classes/etc.) from the `shaka-player@4.16.0`\n * to avoid including the whole package in our distribution code.\n *\n * Because `shaka-player` npm package is not installed, because it has bad TypeScript definitions\n * @see https://github.com/shaka-project/shaka-player/issues/6442)\n * - we can't use \"type imports\" (`import type {}`),\n * - we can't cover copies of the library values with unit tests\n *\n * Shaka discussion about migration to TypeScript\n * @see https://github.com/shaka-project/shaka-player/issues/8262\n */\n\nexport const ShakaPlayerEvent = {\n /**\n * Fired when the player unloads or fails to load. Used by the Cast receiver to determine idle state.\n * @see https://shaka-player-demo.appspot.com/docs/api/shaka.Player.html#.event:UnloadingEvent\n */\n UNLOADING: 'unloading',\n /**\n * Fired when the player changes load states.\n * @see https://shaka-player-demo.appspot.com/docs/api/shaka.Player.html#.event:StateChangeEvent\n */\n ONSTATECHANGE: 'onstatechange',\n /**\n * Fired when player state is changed.\n * @see https://shaka-player-demo.appspot.com/docs/api/shaka.Player.html#.event:StateChanged\n */\n STATECHANGED: 'statechanged',\n /**\n * Fired when the player's buffering state changes.\n * @see https://shaka-player-demo.appspot.com/docs/api/shaka.Player.html#.event:BufferingEvent\n */\n BUFFERING: 'buffering',\n /**\n * Fired when a playback error occurs.\n * @see https://shaka-player-demo.appspot.com/docs/api/shaka.Player.html#.event:ErrorEvent\n */\n ERROR: 'error',\n} as const;\n\n/**\n * @see https://shaka-player-demo.appspot.com/docs/api/shaka.util.Error.html\n */\nexport type ShakaErrorEvent = Error & {\n category: number;\n code: number;\n severity: number;\n};\n","import {HttpRequestType} from '../../features/httprequesttracking/HttpRequestType';\nimport type {OnDownloadFinishedEventObject} from '../../features/httprequesttracking/OnDownloadFinishedEventObject';\nimport type {DrmPerformanceInfo} from '../../types/DrmPerformanceInfo';\nimport {isNotNullish} from '../../utils/Utils';\n\n/**\n * Service that subscribes to network download events and tracks\n * DRM license acquisition performance.\n *\n * Only the first successful DRM license request is tracked,\n * capturing the DRM type and load time.\n */\nexport class DrmPerformanceService {\n private drmPerformanceInfo: DrmPerformanceInfo | undefined = undefined;\n\n /**\n * Returns the captured DRM performance information.\n * @returns DrmPerformanceInfo if a license was tracked, undefined otherwise\n */\n getInfo(): DrmPerformanceInfo | undefined {\n return this.drmPerformanceInfo;\n }\n\n /**\n * Resets the service state for a new playback session.\n * Clears tracked DRM info and allows tracking of the next license request.\n */\n reset(): void {\n this.drmPerformanceInfo = undefined;\n }\n\n onDownloadFinished = (event: OnDownloadFinishedEventObject): void => {\n const httpRequest = event.httpRequest;\n\n // Only track successful requests\n if (!httpRequest.success) {\n return;\n }\n\n // Only track the first DRM license request (not certificates)\n if (isNotNullish(this.drmPerformanceInfo) || !isDrmLicenseType(httpRequest.type)) {\n return;\n }\n\n const drmType = extractDrmType(httpRequest.type);\n this.drmPerformanceInfo = {\n drmType: drmType,\n drmLoadTime: httpRequest.downloadTime,\n };\n };\n}\n\nexport function isDrmLicenseType(type: HttpRequestType): boolean {\n return (\n type === HttpRequestType.DRM_LICENSE_WIDEVINE ||\n type === HttpRequestType.DRM_LICENSE_FAIRPLAY ||\n type === HttpRequestType.DRM_LICENSE_PLAYREADY ||\n type === HttpRequestType.DRM_LICENSE_CLEARKEY\n );\n}\n\nexport function extractDrmType(requestType: HttpRequestType): string {\n // Extract 'widevine' from 'drm/license/widevine'\n const match = requestType.match(/drm\\/license\\/(.+)/);\n return match ? match[1] : 'unknown';\n}\n","/**\n * Service that detects if playback is progressing at a normal rate.\n *\n * This accounts for various playback rates without needing to know the actual playback rate.\n */\nexport class PlaybackProgressDetectionService {\n private lastEventTimestamp: number | undefined;\n private lastCurrentTime: number | undefined;\n\n /**\n * @param eventTimestamp ISO 8601 timestamp string when the timeupdate event fired\n * @param currentTime Player's current playback position in seconds\n * @returns true if currentTime delta is within 0.5x to 4x of elapsed real time, false otherwise\n */\n hasPlaybackProgressed(eventTimestamp: number, currentTime: number): boolean {\n // First event: establish baseline\n if (this.lastEventTimestamp === undefined || this.lastCurrentTime === undefined) {\n this.lastEventTimestamp = eventTimestamp;\n this.lastCurrentTime = currentTime;\n return false;\n }\n\n const elapsedMs = eventTimestamp - this.lastEventTimestamp;\n const elapsedSec = elapsedMs / 1000;\n const currentTimeDelta = currentTime - this.lastCurrentTime;\n\n // No elapsed time or backwards playback (seek): can't determine\n if (elapsedSec <= 0 || currentTimeDelta < 0) {\n this.lastEventTimestamp = eventTimestamp;\n this.lastCurrentTime = currentTime;\n return false;\n }\n\n // Check if currentTime delta is within 0.5x to 4x of elapsed time\n // This range accounts for common playback rates (0.5x, 1x, 2x, 4x) without knowing actual rate\n const lowerBound = elapsedSec * 0.5;\n const upperBound = elapsedSec * 4;\n const isValidProgress = currentTimeDelta >= lowerBound && currentTimeDelta <= upperBound;\n\n this.lastEventTimestamp = eventTimestamp;\n this.lastCurrentTime = currentTime;\n\n return isValidProgress;\n }\n\n /**\n * Resets the service state, clearing baseline data.\n */\n reset(): void {\n this.lastEventTimestamp = undefined;\n this.lastCurrentTime = undefined;\n }\n}\n","import type {\n AdapterAPI,\n SsaiAdBreakMetadata,\n SsaiAdMetadata,\n SsaiAdQuartile,\n SsaiAdQuartileMetadata,\n SsaiApi,\n} from '../../api/AdapterAPI';\nimport {Analytics} from '../../core/Analytics';\nimport {\n hasValidSsaiAdBreakMetadataStructure,\n hasValidSsaiAdMetadataStructure,\n hasValidSsaiAdQuartileStructure,\n sanitizeSsaiAdQuartileMetadata,\n simplySanitizeSsaiAdBreakMetadata,\n simplySanitizeSsaiAdMetadata,\n} from '../../core/ssai/ssaiApiUtils';\nimport type {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {hasValidSourceMetadataStructure, sanitizeSourceMetadata} from '../../types/SourceMetadata';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {logger} from '../../utils/Logger';\nimport {\n hasPlayerAlreadyBeenAugmented,\n isDefined,\n markPlayerInstanceAsAugmented,\n} from '../../utils/playerAugmentationUtils';\nimport {VERSION} from '../../utils/Version';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {THEOplayerInternalAdapter} from './THEOplayerInternalAdapter';\nimport {THEOplayerProxy} from './THEOplayerProxy';\n\nexport class THEOplayerAdapter implements AdapterAPI {\n private readonly internalAdapter: InternalAdapterAPI | undefined;\n private readonly analytics: Analytics | undefined;\n\n constructor(config: AnalyticsConfig, player: any, opts?: AnalyticsStateMachineOptions) {\n if (hasPlayerAlreadyBeenAugmented(player.element)) {\n logger.errorMessageToUser('Bitmovin Analytics is already hooked up to this player instance');\n return;\n }\n // Since the THEOplayer instance is a frozen object, we can't directly add properties to it.\n // To work around this, we add the augmentation marker to the player's HTML element.\n markPlayerInstanceAsAugmented(player.element);\n\n const sanitizedConfig = sanitizeAnalyticsConfig(config);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n return;\n }\n\n guardAgainstDuplicatedUserId(sanitizedConfig);\n\n this.internalAdapter = new THEOplayerInternalAdapter(new THEOplayerProxy(player), opts);\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n }\n\n readonly ssai: SsaiApi = {\n adBreakStart: (adBreakMetadata?: SsaiAdBreakMetadata) => {\n if (!isDefined(this.internalAdapter)) return;\n\n if (!hasValidSsaiAdBreakMetadataStructure(adBreakMetadata)) {\n // if we don't have valid ad break metadata, we don't want to proceed and use SSAI API\n return;\n }\n\n const sanitizedAdBreakMetadata = simplySanitizeSsaiAdBreakMetadata(adBreakMetadata);\n\n this.internalAdapter.ssaiService.adBreakStart(sanitizedAdBreakMetadata);\n },\n\n adStart: (adMetadata?: SsaiAdMetadata) => {\n if (!isDefined(this.analytics)) return;\n if (!isDefined(this.internalAdapter)) return;\n\n if (!hasValidSsaiAdMetadataStructure(adMetadata)) {\n // if we don't have valid ad metadata, we don't want to proceed and use SSAI API\n return;\n }\n\n const sanitizedAdMetadata = simplySanitizeSsaiAdMetadata(adMetadata);\n\n this.internalAdapter.ssaiService.adStart(sanitizedAdMetadata);\n // we need to call this here to revert the customData values to the values before the adBreak\n // this is mainly needed to have clear transitions between ads, and we don't\n // copy over customData values from the first ad into the second ad\n // the adMetadata is applied after this call in the manipulate method when a sample is sent\n // it is a bit of a hack, but it is necessary right now due to the way how samples are created\n this.analytics.setConfigParameters();\n this.analytics.setAutoDetectedDeviceInformation();\n },\n\n adQuartileFinished: (adQuartile: SsaiAdQuartile, adQuartileMetadata?: SsaiAdQuartileMetadata) => {\n if (!isDefined(this.analytics)) return;\n if (!isDefined(this.internalAdapter)) return;\n\n if (!hasValidSsaiAdQuartileStructure(adQuartile)) {\n // if we don't have valid ad quartile, we don't want to proceed and use SSAI API\n return;\n }\n\n const sanitizedSsaiAdQuartileMetadata = sanitizeSsaiAdQuartileMetadata(adQuartileMetadata);\n\n this.internalAdapter.ssaiService.adQuartileFinished(adQuartile, sanitizedSsaiAdQuartileMetadata);\n },\n\n adBreakEnd: () => {\n if (!isDefined(this.analytics)) return;\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.ssaiService.adBreakEnd();\n // we need to call this here to revert the customData values to the values we had before the ad\n this.analytics.setConfigParameters();\n this.analytics.setAutoDetectedDeviceInformation();\n },\n };\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getCurrentImpressionId();\n }\n\n getUserId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getUserId();\n }\n\n setCustomData(values: CustomDataValues) {\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.setCustomData(values);\n }\n\n setCustomDataOnce(values: CustomDataValues) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.setCustomDataOnce(values);\n }\n\n sourceChange(config: AnalyticsConfig) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.sourceChange(config);\n }\n\n programChange(sourceMetadata: {\n /* eslint-disable perfectionist/sort-object-types */\n title?: string;\n videoId?: string;\n cdnProvider?: string;\n path?: string;\n isLive?: boolean;\n customData?: CustomDataValues;\n /* eslint-enable perfectionist/sort-object-types */\n }) {\n if (!hasValidSourceMetadataStructure(sourceMetadata)) {\n // if we don't have valid source metadata, we don't want to proceed\n return;\n }\n\n const sanitizedSourceMetadata = sanitizeSourceMetadata(sourceMetadata);\n\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.programChange(sanitizedSourceMetadata);\n }\n}\n","import type {MediaTrack, QualityEvent, TypedSource, VideoQuality} from 'theoplayer';\n\nimport {THEOplayerAnalyticsStateMachine} from '../../analyticsStateMachines/THEOplayerAnalyticsStateMachine';\nimport type {Analytics} from '../../core/Analytics';\nimport {DownloadSpeedMeter} from '../../core/DownloadSpeedMeter';\nimport {HeartbeatService} from '../../core/HeartbeatService';\nimport {CastTech} from '../../enums/CastTech';\nimport {Event, EventMap} from '../../enums/Event';\nimport {Player as PlayerEnum} from '../../enums/Player';\nimport {PlayerSize} from '../../enums/PlayerSize';\nimport {getStreamTypeFromMIMEType, getStreamTypesFromURL, StreamTypes} from '../../enums/StreamTypes';\nimport {ErrorDetailBackend} from '../../features/errordetails/ErrorDetailBackend';\nimport {ErrorDetailTracking} from '../../features/errordetails/ErrorDetailTracking';\nimport type {Feature} from '../../features/Feature';\nimport type {FeatureConfig} from '../../features/FeatureConfig';\nimport {HttpRequestTracking} from '../../features/httprequesttracking/HttpRequestTracking';\nimport {HttpRequestType} from '../../features/httprequesttracking/HttpRequestType';\nimport type {OnDownloadFinishedEventObject} from '../../features/httprequesttracking/OnDownloadFinishedEventObject';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {DownloadSpeedInfo} from '../../types/DownloadSpeedInfo';\nimport type {DrmPerformanceInfo} from '../../types/DrmPerformanceInfo';\nimport type {QualityChangeEvent} from '../../types/EventData';\nimport type {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport type {NoExtraProperties} from '../../types/NoExtraProperties';\nimport {buildPlaybackInfoStreamTypeFields, normalizeVideoDuration, PlaybackInfo} from '../../types/PlaybackInfo';\nimport type {SpeedMeasurement} from '../../types/SpeedMeasurement';\nimport {getGlobalTheoPlayerVersion} from '../../utils/globalScopeUtils';\nimport {logger} from '../../utils/Logger';\nimport {isNumber} from '../../utils/numberUtils';\nimport {isBlank, isValidString} from '../../utils/stringUtils';\nimport {isNotNullish, isNullish, tryJSONStringify} from '../../utils/Utils';\nimport {InternalAdapter} from '../internal/InternalAdapter';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {THEOplayerAdModule} from './ads/THEOplayerAdModule';\nimport {DrmPerformanceService} from './DrmPerformanceService';\nimport {DelayedEventDispatcher} from './playback/DelayedEventDispatcher';\nimport {PlaybackProgressDetectionService} from './PlaybackProgressDetectionService';\nimport {THEOplayerNetworkInterceptor} from './THEOplayerNetworkInterceptor';\nimport {THEOplayerProxy} from './THEOplayerProxy';\n\nexport class THEOplayerInternalAdapter extends InternalAdapter implements InternalAdapterAPI {\n private readonly player: THEOplayerProxy;\n private readonly networkInterceptor: THEOplayerNetworkInterceptor;\n private readonly speedMeter: DownloadSpeedMeter = new DownloadSpeedMeter();\n private readonly delayedEventDispatcher: DelayedEventDispatcher = DelayedEventDispatcher.create();\n private readonly drmPerformanceService: DrmPerformanceService = new DrmPerformanceService();\n private readonly playbackProgressDetectionService: PlaybackProgressDetectionService =\n new PlaybackProgressDetectionService();\n private _adModule: THEOplayerAdModule | undefined;\n\n /** Boolean flag to prevent multiple calls of the {@link Event.UNLOAD} event */\n private onBeforeUnLoadEvent = false;\n\n private lastTrackedCurrentTime: number | undefined;\n\n private currentSource: TypedSource | undefined;\n\n private videoTrackListeners: Map<MediaTrack, (event: QualityEvent<'activequalitychanged'>) => void> = new Map();\n private audioTrackListeners: Map<MediaTrack, (event: QualityEvent<'activequalitychanged'>) => void> = new Map();\n\n constructor(player: THEOplayerProxy, opts?: AnalyticsStateMachineOptions) {\n super(opts);\n this.player = player;\n this.networkInterceptor = new THEOplayerNetworkInterceptor(player);\n this.networkInterceptor.subscribe((event) => {\n // SpeedMeter\n const speedMeasurement = createSpeedMeasurementFromEvent(event);\n if (isNotNullish(speedMeasurement)) {\n this.speedMeter.addMeasurement(speedMeasurement);\n }\n\n // DrmPerformanceService\n this.drmPerformanceService.onDownloadFinished(event);\n });\n\n const playingHeartbeatService = new HeartbeatService(() => this.currentTime);\n this.stateMachine = new THEOplayerAnalyticsStateMachine(\n this.stateMachineCallbacks,\n playingHeartbeatService,\n this.opts,\n );\n playingHeartbeatService.setListener(this.stateMachine);\n\n this.player = player;\n }\n\n get adModule(): THEOplayerAdModule | undefined {\n return this._adModule;\n }\n\n initialize(analytics: Analytics): Array<Feature<FeatureConfigContainer, FeatureConfig>> {\n this.registerEventListeners();\n\n // We need to create an AdModule AFTER we have already registered player event listeners, because they set\n // the up-to-date player information on the current Sample that is later used to form AdSample.\n // But we need to create this AdModule BEFORE we register unload event listeners, because otherwise we would\n // release the internal adapter (together with this AdModule) before the \"unload\" event listeners in AdModule would\n // be executed.\n this._adModule = new THEOplayerAdModule(this.player, this.windowEventTracker);\n\n this.registerUnloadEventListeners();\n\n this.ssaiService.activate({\n getPlayerCurrentTime: () => this.currentTime,\n reportEngagementInteraction: (ssaiEngagementInteractionData) => {\n analytics.sendSsaiEngagementAdSample(ssaiEngagementInteractionData);\n },\n reportPlaybackInteraction: (timestamp: number, playerCurrentTime: number) => {\n // Because ssai playback interaction can happen before Ssai Service is active (e.g. first ssai startAd call),\n // we need to manually mark sample as triggered by ssai\n //\n // This is also including the last sample marking, before a ssai ad block (due to ssai being spiky by design)\n this.stateMachine.sendPlayingSample(timestamp, playerCurrentTime, true);\n },\n });\n\n const httpRequestTracking = new HttpRequestTracking([this.networkInterceptor]);\n const errorDetailTracking = new ErrorDetailTracking(\n analytics.errorDetailTrackingSettingsProvider,\n new ErrorDetailBackend(analytics.errorDetailTrackingSettingsProvider.collectorConfig),\n [analytics.errorDetailSubscribable],\n httpRequestTracking,\n );\n\n this.eventCallback(Event.READY, {currentTime: this.currentTime});\n\n return [errorDetailTracking];\n }\n\n getPlayerVersion(): string {\n // try to get the version from the global `window.THEOplayer` (if npm module is used, it doesn't exist)\n const windowTHEOplayerVersion = getGlobalTheoPlayerVersion();\n if (isValidString(windowTHEOplayerVersion) && !isBlank(windowTHEOplayerVersion)) {\n return windowTHEOplayerVersion;\n }\n\n return 'unknown';\n }\n getPlayerName(): string {\n return PlayerEnum.THEOPLAYER;\n }\n getPlayerTech(): string {\n return 'html5';\n }\n getAutoPlay(): boolean {\n return this.player.autoplay ?? false;\n }\n\n override getDrmPerformanceInfo = (): DrmPerformanceInfo | undefined => this.drmPerformanceService.getInfo();\n\n getCurrentPlaybackInfo(): PlaybackInfo {\n const activeVideoTrack = this.player.videoTracks?.find((t) => t.enabled);\n const activeAudioTrack = this.player.audioTracks?.find((t) => t.enabled);\n const activeTextTrack = this.player.textTracks?.find((t) => t.mode === 'showing');\n\n let castTech: CastTech | undefined = undefined;\n if (isNotNullish(this.player.cast?.airplay?.casting)) {\n castTech = CastTech.AirPlay;\n } else if (isNotNullish(this.player.cast?.chromecast?.casting)) {\n castTech = CastTech.GoogleCast;\n }\n\n const playerDuration = this.player.duration;\n\n return {\n ...this.getCommonPlaybackInfo(),\n ...detectPlaybackInfoStreamTypeFieldsFromSource(this.currentSource),\n audioBitrate: activeAudioTrack?.activeQuality?.bandwidth,\n audioCodec: activeAudioTrack?.activeQuality?.codecs,\n audioLanguage: activeAudioTrack?.language,\n castTech: castTech,\n droppedFrames: 0,\n isCasting: isNotNullish(castTech),\n isLive: !isNullish(playerDuration) && !isFinite(playerDuration),\n isMuted: this.player.muted,\n playerTech: this.getPlayerTech(),\n size: this.player.presentation?.currentMode === 'fullscreen' ? PlayerSize.Fullscreen : PlayerSize.Window,\n subtitleEnabled: isNotNullish(activeTextTrack),\n subtitleLanguage: activeTextTrack?.language,\n videoBitrate: activeVideoTrack?.activeQuality?.bandwidth,\n videoCodec: activeVideoTrack?.activeQuality?.codecs,\n videoDuration: normalizeVideoDuration(playerDuration),\n videoPlaybackHeight: this.player.videoHeight,\n videoPlaybackWidth: this.player.videoWidth,\n videoWindowHeight: this.player.element?.offsetHeight,\n videoWindowWidth: this.player.element?.offsetWidth,\n } as PlaybackInfo;\n }\n\n protected override get currentTime(): number {\n return this.player.currentTime ?? 0;\n }\n\n override getDownloadSpeedInfo(): DownloadSpeedInfo {\n return this.speedMeter.getInfo();\n }\n\n override resetDownloadSpeedInfoMeasures(): void {\n this.speedMeter.reset();\n }\n\n override resetSourceRelatedState(): void {\n super.resetSourceRelatedState();\n this.ssaiService.resetSourceRelatedState();\n\n this.videoTrackListeners.forEach((listener, track) => {\n track.removeEventListener('activequalitychanged', listener);\n });\n this.videoTrackListeners.clear();\n\n this.audioTrackListeners.forEach((listener, track) => {\n track.removeEventListener('activequalitychanged', listener);\n });\n this.audioTrackListeners.clear();\n\n this.lastTrackedCurrentTime = undefined;\n this.currentSource = undefined;\n this.speedMeter.reset();\n this.drmPerformanceService.reset();\n this.networkInterceptor.reset();\n this.playbackProgressDetectionService.reset();\n }\n\n override eventCallback<\n StateMachineEvent extends keyof EventMap,\n StateMachineEventData extends EventMap[StateMachineEvent],\n >(event: StateMachineEvent, eventData: NoExtraProperties<EventMap[StateMachineEvent], StateMachineEventData>) {\n this.delayedEventDispatcher.dispatchEvent(\n event,\n eventData,\n this.stateMachine.currentState,\n super.eventCallback.bind(this),\n );\n }\n\n private handleVideoQualityChanged(qualityEvent: QualityEvent<'activequalitychanged'>): void {\n // The issue is that the quality from the activequalitychanged event has a generic type Quality, which only has\n // the base properties. But the actual object has more properties for video tracks, so we need to narrow the type\n // to VideoQuality to access them.\n const videoQuality = qualityEvent.quality as VideoQuality;\n\n const qualityEventInfo: QualityChangeEvent = {\n type: 'video',\n width: videoQuality.width,\n height: videoQuality.height,\n bitrate: videoQuality.bandwidth,\n currentTime: this.currentTime,\n };\n\n if (this.qualityChangeService.shouldAllowVideoQualityChange(videoQuality.bandwidth)) {\n this.eventCallback(Event.VIDEO_CHANGE, qualityEventInfo);\n }\n\n this.qualityChangeService.setVideoBitrate(videoQuality.bandwidth);\n this.stateMachineCallbacks.updateSampleQualityInfo(qualityEventInfo);\n }\n\n private handleAudioQualityChanged(qualityEvent: QualityEvent<'activequalitychanged'>): void {\n const quality = qualityEvent.quality;\n\n const qualityEventInfo: QualityChangeEvent = {\n type: 'audio',\n bitrate: quality.bandwidth,\n currentTime: this.currentTime,\n };\n\n if (this.qualityChangeService.shouldAllowAudioQualityChange(quality.bandwidth)) {\n this.eventCallback(Event.AUDIO_CHANGE, qualityEventInfo);\n }\n\n this.qualityChangeService.setAudioBitrate(quality.bandwidth);\n this.stateMachineCallbacks.updateSampleQualityInfo(qualityEventInfo);\n }\n\n private registerEventListeners() {\n this.player.addEventListener('sourcechange', (_event) => {\n // We use the 'sourcechange' event to indicate that the player that was in State.SOURCE_CHANGING is ready\n // with a new source and should move to State.READY. It doesn't mean that the source is fully loaded, it\n // only means that the player is ready to play (play button is enabled), and a video source can be loaded\n // later as part of the startup.\n //\n // Why not use the 'loadedmetadata' event?\n // Because we need to support also player setup without preload (preload=\"none\"), where 'loadedmetadata'\n // is not fired, but the player is already able to trigger \"play\" action (play button or API call is available)\n // aka. the player should already leave State.SOURCE_CHANGING and be in State.READY, because if a \"play\" action\n // is triggered, we should transition to State.STARTUP. Without preload, 'loadedmetadata' is fired later, and\n // we track a whole source loading time as part of startup.\n this.eventCallback(Event.READY, {});\n });\n\n this.player.addEventListener('currentsourcechange', (event) => {\n // prevents MANUAL_SOURCE_CHANGE on the first occurrence - in the beginning the player is setting up the first video\n if (isNotNullish(this.currentSource)) {\n // Why not use the 'loadstart' event?\n // Because with THEOplayer, the load of the video can actually happen after startup (especially without preload: on)\n // and using 'loadstart' to indicate the start of the source change would send startup failure instead of normal startup.\n this.eventCallback(Event.MANUAL_SOURCE_CHANGE, {currentTime: this.lastTrackedCurrentTime, config: {}});\n }\n this.currentSource = event.currentSource;\n });\n\n this.player.addEventListener('play', (event) => {\n this.eventCallback(Event.PLAY, {currentTime: event.currentTime});\n });\n\n this.player.addEventListener('pause', (event) => {\n this.eventCallback(Event.PAUSE, {currentTime: event.currentTime});\n });\n\n this.player.videoTracks?.addEventListener('addtrack', (event) => {\n // The issue is that the track from the addtrack event is typed as the base Track interface,\n // which only has TrackEventMap — not MediaTrackEventMap. We need to narrow the type to MediaTrack\n const mediaTrack = event.track as MediaTrack;\n\n const listener = (qualityEvent: QualityEvent<'activequalitychanged'>) => {\n this.handleVideoQualityChanged(qualityEvent);\n };\n mediaTrack.addEventListener('activequalitychanged', listener);\n this.videoTrackListeners.set(mediaTrack, listener);\n });\n\n this.player.videoTracks?.addEventListener('removetrack', (event) => {\n // The issue is that the track from the removetrack event is typed as the base Track interface,\n // which only has TrackEventMap — not MediaTrackEventMap. We need to narrow the type to MediaTrack\n const mediaTrack = event.track as MediaTrack;\n\n const listener = this.videoTrackListeners.get(mediaTrack);\n if (listener) {\n mediaTrack.removeEventListener('activequalitychanged', listener);\n this.videoTrackListeners.delete(mediaTrack);\n }\n });\n\n // add listeners to all already added/existing video tracks\n for (const track of this.player.videoTracks ?? []) {\n const listener = (qualityEvent: QualityEvent<'activequalitychanged'>) => {\n this.handleVideoQualityChanged(qualityEvent);\n };\n track.addEventListener('activequalitychanged', listener);\n this.videoTrackListeners.set(track, listener);\n }\n\n this.player.audioTracks?.addEventListener('addtrack', (event) => {\n // The issue is that the track from the addtrack event is typed as the base Track interface,\n // which only has TrackEventMap — not MediaTrackEventMap. We need to narrow the type to MediaTrack\n const mediaTrack = event.track as MediaTrack;\n\n const listener = (qualityEvent: QualityEvent<'activequalitychanged'>) => {\n this.handleAudioQualityChanged(qualityEvent);\n };\n mediaTrack.addEventListener('activequalitychanged', listener);\n this.audioTrackListeners.set(mediaTrack, listener);\n });\n\n this.player.audioTracks?.addEventListener('removetrack', (event) => {\n // The issue is that the track from the removetrack event is typed as the base Track interface,\n // which only has TrackEventMap — not MediaTrackEventMap. We need to narrow the type to MediaTrack\n const mediaTrack = event.track as MediaTrack;\n\n const listener = this.audioTrackListeners.get(mediaTrack);\n if (listener) {\n mediaTrack.removeEventListener('activequalitychanged', listener);\n this.audioTrackListeners.delete(mediaTrack);\n }\n });\n\n // add listeners to all already added/existing audio tracks\n for (const track of this.player.audioTracks ?? []) {\n const listener = (qualityEvent: QualityEvent<'activequalitychanged'>) => {\n this.handleAudioQualityChanged(qualityEvent);\n };\n track.addEventListener('activequalitychanged', listener);\n this.audioTrackListeners.set(track, listener);\n }\n\n this.player.addEventListener('seeking', (_event) => {\n // we have to send the last tracked time as currentTime here,\n // because at this point the event.currentTime is already set to the new seeked time\n this.eventCallback(Event.SEEK, {currentTime: this.lastTrackedCurrentTime});\n });\n\n this.player.addEventListener('timeupdate', (event) => {\n this.lastTrackedCurrentTime = event.currentTime;\n\n // For unknown reasons/in unknown cases THEOPlayer seems to sometimes not send \"playing\" event after start\n // attempt, leading to elevated VideoStartFailures as our state machine will be stuck in \"startup state\".\n // This is a best effort workaround where we check the eventTime and the video currentTime for playback progress\n // when in Startup state, to be able to transition out of Startup state when video playback is detected but player\n // did not send the Playing event.\n // This workaround might lead to a little higher startup times than the playback actually showcased, since we need\n // 2 events to be able to reliably tell if the playback progressed and the normal interval between timeupdate\n // events is 250ms.\n if (this.stateMachine.currentState === 'STARTUP') {\n if (this.playbackProgressDetectionService.hasPlaybackProgressed(event.date.getTime(), event.currentTime)) {\n logger.log(\n `[PlaybackProgressDetectionService] Playback progress detected based on \"timeupdate\" event, eventTime: ${event.date.getTime()}, player currentTime: ${event.currentTime}`,\n );\n this.eventCallback(Event.PLAYING, {currentTime: event.currentTime});\n }\n }\n });\n\n this.player.addEventListener('playing', (event) => {\n this.eventCallback(Event.PLAYING, {currentTime: event.currentTime});\n });\n\n this.player.addEventListener('waiting', (event) => {\n this.eventCallback(Event.START_BUFFERING, {currentTime: event.currentTime});\n });\n\n this.player.addEventListener('ended', (event) => {\n this.eventCallback(Event.END, {currentTime: event.currentTime});\n });\n\n this.player.addEventListener('error', (event) => {\n const code = event.errorObject.code;\n const message = event.errorObject.message;\n const originalError = event.errorObject.cause;\n const errorAsData = tryJSONStringify(event.errorObject);\n\n this.eventCallback(Event.ERROR, {\n code: code,\n message: message,\n legacyData: errorAsData,\n currentTime: this.currentTime,\n originalError: originalError,\n data: {\n exceptionMessage: message,\n exceptionStacktrace: event.errorObject.stack?.split('\\n') ?? undefined,\n additionalData: errorAsData,\n },\n });\n\n this.ssaiService.sendAdEngagementErrorSample({code: code, message: message, severity: 'CRITICAL'}, event);\n });\n\n this.player.ads?.addEventListener('adbreakbegin', (_event) => {\n this.eventCallback(Event.START_AD, {currentTime: this.currentTime});\n });\n this.player.ads?.addEventListener('adbreakend', (_event) => {\n this.eventCallback(Event.END_AD, {currentTime: this.currentTime});\n });\n }\n\n private registerUnloadEventListeners() {\n // handler has to be defined as an arrow function to capture the correct \"this\"\n const handleCollectorUnload = () => {\n if (!this.onBeforeUnLoadEvent) {\n this.onBeforeUnLoadEvent = true;\n // we use here the last tracked video time as we cannot be sure if the player is still working at this place\n const currentTime = this.lastTrackedCurrentTime;\n this.eventCallback(Event.UNLOAD, {currentTime});\n }\n this.release();\n };\n\n this.player.addEventListener('destroy', handleCollectorUnload);\n this.windowEventTracker.addEventListener('beforeunload', handleCollectorUnload);\n this.windowEventTracker.addEventListener('unload', handleCollectorUnload);\n }\n}\n\nexport function detectPlaybackInfoStreamTypeFieldsFromSource(\n source: TypedSource | undefined,\n): Pick<PlaybackInfo, 'm3u8Url' | 'mpdUrl' | 'progUrl' | 'streamFormat'> {\n if (isNullish(source)) {\n return {};\n }\n\n let streamType: StreamTypes | undefined = undefined;\n if (!isNullish(source.type)) {\n streamType = getStreamTypeFromMIMEType(source.type);\n }\n if (isNullish(streamType)) {\n streamType = getStreamTypesFromURL(source.src);\n }\n\n return buildPlaybackInfoStreamTypeFields(streamType, source.src);\n}\n\nexport function createSpeedMeasurementFromEvent(event: OnDownloadFinishedEventObject): SpeedMeasurement | undefined {\n const httpRequest = event.httpRequest;\n\n if (!httpRequest.success) {\n return undefined;\n }\n\n if (httpRequest.type !== HttpRequestType.MEDIA_VIDEO && httpRequest.type !== HttpRequestType.MEDIA_AUDIO) {\n return undefined;\n }\n\n return {\n duration: httpRequest.downloadTime / 1000,\n size: isNumber(httpRequest.size) ? httpRequest.size : 0,\n timeToFirstByte: isNotNullish(httpRequest.timeToFirstByte) ? httpRequest.timeToFirstByte / 1000 : 0,\n timestamp: new Date(),\n httpStatus: httpRequest.httpStatus,\n };\n}\n","import type {InterceptableRequest, InterceptableResponse} from 'theoplayer';\n\nimport {EventDispatcher, Subscribable} from '../../core/EventDispatcher';\nimport {HttpRequestType} from '../../features/httprequesttracking/HttpRequestType';\nimport {OnDownloadFinishedEventObject} from '../../features/httprequesttracking/OnDownloadFinishedEventObject';\nimport {getGlobalPerformanceNow} from '../../utils/globalScopeUtils';\nimport {logger} from '../../utils/Logger';\nimport {isNumber, parseIntOrUndefined} from '../../utils/numberUtils';\nimport {endsWith, isBlank, isValidString} from '../../utils/stringUtils';\nimport {isArrayBuffer, isNotNullish, isNullish} from '../../utils/Utils';\n\nimport {THEOplayerProxy} from './THEOplayerProxy';\n\nexport const STALE_REQUEST_TIMEOUT_MS = 3 * 60 * 1_000; // three minutes\n\ninterface PendingRequest {\n url: string;\n startTime: number;\n type: string | undefined;\n subType: string | undefined;\n mediaType: string | undefined;\n}\n\n/**\n * Unified network interceptor for THEOplayer that captures HTTP request/response data\n * and publishes standardized {@link OnDownloadFinishedEventObject} events.\n *\n * This allows both {@link DownloadSpeedMeter} and {@link HttpRequestTracking} to subscribe\n * to a single source of network events.\n */\nexport class THEOplayerNetworkInterceptor implements Subscribable<OnDownloadFinishedEventObject> {\n private eventDispatcher = new EventDispatcher<OnDownloadFinishedEventObject>();\n private pendingRequests = new Map<string, PendingRequest[]>();\n\n constructor(private player: THEOplayerProxy) {\n if (isNullish(this.player.network)) {\n logger.warn('THEOplayerNetworkInterceptor: player.network is not available');\n return;\n }\n\n this.player.network.addRequestInterceptor(this.onRequest);\n this.player.network.addResponseInterceptor(this.onResponse);\n }\n\n subscribe(callback: (args: OnDownloadFinishedEventObject) => void): () => void {\n return this.eventDispatcher.subscribe(callback);\n }\n\n unsubscribe(callback: (args: OnDownloadFinishedEventObject) => void): void {\n this.eventDispatcher.unsubscribe(callback);\n }\n\n reset(): void {\n this.pendingRequests.clear();\n }\n\n private onRequest = (request: InterceptableRequest): void => {\n try {\n const url = request.url;\n // we need to double-check the url as a valid string, because our implementation is using it as a key in the map,\n // and if it's invalid, it can cause issues\n if (!isValidString(url) || isBlank(url)) {\n return;\n }\n\n const performanceNow = getGlobalPerformanceNow();\n const now = performanceNow ?? Date.now();\n\n // clean up any stale pending requests that have been pending for too long before adding the new request\n // to prevent map overflow in case of missing responses or other issues\n // No need for logic with timeout here, let's keep it simple\n this.cleanupStaleRequests(now);\n\n const pendingRequest: PendingRequest = {\n url: url,\n startTime: now,\n type: request.type,\n subType: request.subType,\n mediaType: request.mediaType,\n };\n\n const existing = this.pendingRequests.get(url);\n if (isNullish(existing)) {\n this.pendingRequests.set(url, [pendingRequest]);\n } else {\n existing.push(pendingRequest);\n }\n } catch (error) {\n logger.error('THEOplayerNetworkInterceptor: Error in request interceptor', error);\n }\n };\n\n private onResponse = (response: InterceptableResponse): void => {\n try {\n const request = response.request;\n // if the original request is missing, we can't correlate the response to a pending request, so we skip processing\n if (isNullish(request)) {\n return;\n }\n\n const url = request.url;\n // we need to double-check the url as a valid string, because our implementation is using it as a key in the map,\n // and if it's invalid, it can cause issues\n if (!isValidString(url) || isBlank(url)) {\n return;\n }\n\n const pendingArray = this.pendingRequests.get(url);\n if (isNullish(pendingArray) || pendingArray.length === 0) {\n return;\n }\n\n // Use FIFO: remove the oldest (first) pending request\n const pending = pendingArray.shift()!;\n\n if (pendingArray.length === 0) {\n this.pendingRequests.delete(url);\n }\n\n const performanceNow = getGlobalPerformanceNow();\n const endTime = performanceNow ?? Date.now();\n\n // round the final download time to a whole number to avoid unnecessary precision (performance.now() returns a high-precision timestamp as double)\n const downloadTime = Math.round(endTime - pending.startTime);\n\n const size = extractResponseSize(response);\n const httpStatus: number = isNumber(response.status) ? response.status : 0;\n const success = httpStatus >= 200 && httpStatus < 400;\n\n this.eventDispatcher.dispatch({\n httpRequest: {\n downloadTime: downloadTime,\n httpStatus: httpStatus,\n success: success,\n timestamp: Date.now(),\n url: url,\n size: size,\n timeToFirstByte: undefined, // missing in THEOplayer network API\n type: mapHttpRequestType(pending.type, pending.subType, pending.mediaType, url),\n },\n });\n } catch (error) {\n logger.error('THEOplayerNetworkInterceptor: Error in response interceptor', error);\n }\n };\n\n private cleanupStaleRequests(now: number): void {\n this.pendingRequests.forEach((pendingArray: PendingRequest[], url: string) => {\n const filtered = pendingArray.filter(\n (pending: PendingRequest) => now - pending.startTime <= STALE_REQUEST_TIMEOUT_MS,\n );\n\n if (filtered.length === 0) {\n this.pendingRequests.delete(url);\n } else if (filtered.length !== pendingArray.length) {\n this.pendingRequests.set(url, filtered);\n }\n });\n }\n}\n\nexport function extractResponseSize(response: InterceptableResponse): number | undefined {\n const contentLength = response.headers?.['content-length'] ?? response.headers?.['Content-Length'];\n if (isNotNullish(contentLength)) {\n const parsed = parseIntOrUndefined(contentLength);\n if (isNotNullish(parsed)) {\n return parsed;\n }\n }\n\n if (isNotNullish(response.body)) {\n if (isValidString(response.body)) {\n return response.body.length;\n }\n if (isArrayBuffer(response.body) && isNumber(response.body.byteLength)) {\n return response.body.byteLength;\n }\n }\n\n return undefined;\n}\n\nexport function mapHttpRequestType(\n requestType: string | undefined,\n requestSubType: string | undefined,\n mediaType: string | undefined,\n url: string,\n): HttpRequestType {\n // Check for content protection (DRM) requests first\n if (requestType === 'content-protection') {\n switch (requestSubType) {\n case 'widevine-license':\n return HttpRequestType.DRM_LICENSE_WIDEVINE;\n case 'fairplay-license':\n return HttpRequestType.DRM_LICENSE_FAIRPLAY;\n case 'playready-license':\n return HttpRequestType.DRM_LICENSE_PLAYREADY;\n case 'clearkey-license':\n return HttpRequestType.DRM_LICENSE_CLEARKEY;\n case 'aes128-key':\n return HttpRequestType.KEY_HLS_AES;\n case 'fairplay-certificate':\n return HttpRequestType.DRM_CERTIFICATE_FAIRPLAY;\n case 'widevine-certificate':\n // no enum value for this category on HttpRequestType - needs update from player team\n return HttpRequestType.UNKNOWN;\n default:\n return HttpRequestType.UNKNOWN;\n }\n }\n\n // Check for manifest requests based on URL extension\n if (requestType === 'manifest') {\n if (endsWith(url, '.mpd')) {\n return HttpRequestType.MANIFEST_DASH;\n }\n if (endsWith(url, '.m3u8')) {\n return HttpRequestType.MANIFEST_HLS_MASTER;\n }\n return HttpRequestType.UNKNOWN;\n }\n\n // Check for media segment requests based on mediaType\n if (mediaType === 'video') {\n return HttpRequestType.MEDIA_VIDEO;\n }\n if (mediaType === 'audio') {\n return HttpRequestType.MEDIA_AUDIO;\n }\n if (mediaType === 'text') {\n return HttpRequestType.MEDIA_SUBTITLES;\n }\n\n // Fallback: check URL extension for manifests even without explicit type\n if (endsWith(url, '.mpd')) {\n return HttpRequestType.MANIFEST_DASH;\n }\n if (endsWith(url, '.m3u8')) {\n return HttpRequestType.MANIFEST_HLS_MASTER;\n }\n\n return HttpRequestType.UNKNOWN;\n}\n","import type {ChromelessPlayer} from 'theoplayer';\n\nimport {safeAccess} from '../../utils/objectUtils';\n\nexport class THEOplayerProxy {\n constructor(private readonly rawPlayer: ChromelessPlayer) {}\n\n addEventListener: ChromelessPlayer['addEventListener'] = (type, listener) => {\n safeAccess(() => this.rawPlayer.addEventListener(type, listener));\n };\n\n get currentTime(): ChromelessPlayer['currentTime'] | undefined {\n return safeAccess(() => this.rawPlayer.currentTime);\n }\n\n get duration(): ChromelessPlayer['duration'] | undefined {\n return safeAccess(() => this.rawPlayer.duration);\n }\n\n get autoplay(): ChromelessPlayer['autoplay'] | undefined {\n return safeAccess(() => this.rawPlayer.autoplay);\n }\n\n get muted(): ChromelessPlayer['muted'] | undefined {\n return safeAccess(() => this.rawPlayer.muted);\n }\n\n get videoHeight(): ChromelessPlayer['videoHeight'] | undefined {\n return safeAccess(() => this.rawPlayer.videoHeight);\n }\n\n get videoWidth(): ChromelessPlayer['videoWidth'] | undefined {\n return safeAccess(() => this.rawPlayer.videoWidth);\n }\n\n get errorObject(): ChromelessPlayer['errorObject'] | undefined {\n return safeAccess(() => this.rawPlayer.errorObject);\n }\n\n get element(): ChromelessPlayer['element'] | undefined {\n return safeAccess(() => this.rawPlayer.element);\n }\n\n get source(): ChromelessPlayer['source'] | undefined {\n return safeAccess(() => this.rawPlayer.source);\n }\n\n get cast(): ChromelessPlayer['cast'] | undefined {\n return safeAccess(() => this.rawPlayer.cast);\n }\n\n get presentation(): ChromelessPlayer['presentation'] | undefined {\n return safeAccess(() => this.rawPlayer.presentation);\n }\n\n get videoTracks(): ChromelessPlayer['videoTracks'] | undefined {\n return safeAccess(() => this.rawPlayer.videoTracks);\n }\n\n get audioTracks(): ChromelessPlayer['audioTracks'] | undefined {\n return safeAccess(() => this.rawPlayer.audioTracks);\n }\n\n get textTracks(): ChromelessPlayer['textTracks'] | undefined {\n return safeAccess(() => this.rawPlayer.textTracks);\n }\n\n get ads(): ChromelessPlayer['ads'] | undefined {\n return safeAccess(() => this.rawPlayer.ads);\n }\n\n get network(): ChromelessPlayer['network'] | undefined {\n return safeAccess(() => this.rawPlayer.network);\n }\n}\n","import type {\n Ad as PlayerAd,\n AdBreak as PlayerAdBreak,\n Event as PlayerEvent,\n GoogleImaAd as PlayerGoogleImaAd,\n LinearAd as PlayerLinearAd,\n} from 'theoplayer';\n\nimport type {AdBreakInfo} from '../../../types/ads/AdBreakInfo';\nimport type {AdInfo} from '../../../types/ads/AdInfo';\nimport {isFiniteNumber} from '../../../utils/numberUtils';\nimport {isNotNullish} from '../../../utils/Utils';\nimport {PlayerAdErrorEvent} from '../THEOplayerTypes';\n\nexport function mapTheoAd(ad: PlayerAd): AdInfo {\n const isLinear = ad.type === 'linear';\n\n const adInfo: AdInfo = {\n id: ad.id,\n isLinear,\n clickThroughUrl: ad.clickThrough,\n width: ad.width,\n height: ad.height,\n };\n\n const linearAd = isLinear ? (ad as PlayerLinearAd) : undefined;\n if (isNotNullish(linearAd)) {\n adInfo.mediaUrl = linearAd.mediaUrl;\n }\n\n if (isNotNullish(ad.skipOffset)) {\n adInfo.skippable = ad.skipOffset !== -1;\n adInfo.skippableAfter = ad.skipOffset;\n }\n\n if (isNotNullish(ad.duration)) {\n adInfo.duration = ad.duration;\n }\n\n const isGoogleIma = ad.integration === 'google-ima' || ad.integration === 'google-dai';\n const googleAd = isGoogleIma ? (ad as PlayerGoogleImaAd) : undefined;\n if (isNotNullish(googleAd)) {\n adInfo.bitrate = isNotNullish(googleAd.bitrate) ? googleAd.bitrate / 1000 : undefined;\n adInfo.mimeType = googleAd.contentType;\n }\n\n adInfo.vastData = {\n adSystem: ad.adSystem,\n creativeId: ad.creativeId,\n };\n\n const universalAdId = ad.universalAdIds && ad.universalAdIds.length > 0 ? ad.universalAdIds[0] : undefined;\n if (isNotNullish(universalAdId)) {\n adInfo.vastData.universalAdIdRegistry = universalAdId.adIdRegistry;\n adInfo.vastData.universalAdIdValue = universalAdId.adIdValue;\n }\n\n if (isNotNullish(googleAd)) {\n adInfo.vastData.apiFramework = googleAd.apiFramework;\n adInfo.vastData.adDescription = googleAd.description;\n adInfo.vastData.adTitle = googleAd.title;\n adInfo.vastData.wrapperAdsCount = isNotNullish(googleAd.wrapperAdIds) ? googleAd.wrapperAdIds.length : undefined;\n }\n\n return adInfo;\n}\n\nexport function mapTheoAdBreak(adBreak: PlayerAdBreak, videoDuration?: number): AdBreakInfo {\n const timeOffset = adBreak.timeOffset;\n if (!isFiniteNumber(timeOffset) || timeOffset < 0) {\n return {position: undefined, scheduleTime: undefined};\n }\n\n if (timeOffset === 0) {\n return {position: 'pre', scheduleTime: 0};\n }\n\n // checks if timeOffset (aka ad schedule time) is close to video duration (aka end of video)\n // the 1sec delta threshold is an arbitrary number that accounts for small errors in the reported numbers.\n const DELTA_THRESHOLD_SEC = 1;\n const deltaTimeOffsetVideoDuration = isNotNullish(videoDuration) ? Math.abs(timeOffset - videoDuration) : undefined;\n if (isNotNullish(deltaTimeOffsetVideoDuration) && deltaTimeOffsetVideoDuration <= DELTA_THRESHOLD_SEC) {\n return {position: 'post', scheduleTime: videoDuration};\n }\n\n // default to midroll\n return {position: String(timeOffset), scheduleTime: timeOffset};\n}\n\nexport function isAdErrorEvent(event: PlayerEvent<'aderror'>): event is PlayerAdErrorEvent {\n return isNotNullish(event) && 'errorCode' in event;\n}\n","import {isFiniteNumber} from '../../../utils/numberUtils';\nimport {isNotNullish, isNullish} from '../../../utils/Utils';\nimport {WindowEventTracker} from '../../../utils/WindowEventTracker';\nimport {AdCallbacks, AdErrorPayload, AdManifestLoadedPayload, AdModuleAPI} from '../../internal/ads/AdModuleAPI';\nimport {THEOplayerProxy} from '../THEOplayerProxy';\n\nimport {isAdErrorEvent, mapTheoAd, mapTheoAdBreak} from './AdUtils';\n\nexport class THEOplayerAdModule implements AdModuleAPI {\n adCallbacks = new AdCallbacks();\n /**\n * this field stores the duration of the video.\n * during active ad the property `player.duration` shows the duration of the ad.\n */\n private videoDuration: number | undefined;\n\n private readonly player: THEOplayerProxy;\n\n constructor(player: THEOplayerProxy, windowEventTracker: WindowEventTracker) {\n this.player = player;\n this.register(windowEventTracker);\n }\n\n isLinearAdActive = (): boolean => {\n const ads = this.player.ads;\n if (isNullish(ads)) {\n return false;\n }\n return ads.playing ?? false;\n };\n\n getContainer = (): HTMLElement | undefined => this.player.element;\n\n getAdModuleInfo = (): {name?: string; version?: string} => {\n return {name: 'theo-ads', version: undefined};\n };\n\n currentTime = (): number => this.player.currentTime ?? 0;\n\n getAutoPlay = (): boolean => this.player.autoplay ?? false;\n\n private register(windowEventTracker: WindowEventTracker) {\n const ads = this.player.ads;\n if (isNullish(ads)) {\n return;\n }\n\n ads.addEventListener('adbreakbegin', (event) => {\n this.adCallbacks.onAdBreakStarted(mapTheoAdBreak(event.adBreak, this.videoDuration));\n });\n ads.addEventListener('adbreakend', (event) => {\n this.adCallbacks.onAdBreakFinished(mapTheoAdBreak(event.adBreak, this.videoDuration));\n });\n ads.addEventListener('adbegin', (event) => {\n this.adCallbacks.onAdStarted(mapTheoAd(event.ad));\n });\n ads.addEventListener('adend', (event) => {\n this.adCallbacks.onAdFinished(mapTheoAd(event.ad));\n });\n ads.addEventListener('adskip', (event) => {\n this.adCallbacks.onAdSkipped(mapTheoAd(event.ad));\n });\n ads.addEventListener('aderror', (event) => {\n const errorPayload: AdErrorPayload = {};\n\n if (isAdErrorEvent(event)) {\n errorPayload.code = event.errorCode;\n errorPayload.message = event.message;\n }\n\n // fallback to player recorded error if event does not provide error info\n const errorObject = this.player.errorObject;\n if (isNotNullish(errorObject) && isNullish(errorPayload.code)) {\n errorPayload.code = errorObject.code;\n errorPayload.message = errorObject.message;\n }\n this.adCallbacks.onAdError(errorPayload);\n });\n ads.addEventListener('adloaded', (_event) => {\n const playerDuration = this.player.duration;\n if (isFiniteNumber(playerDuration) && this.videoDuration !== playerDuration) {\n this.videoDuration = playerDuration;\n }\n\n const adManifestPayload: AdManifestLoadedPayload = {\n isVmap: false,\n };\n\n const sourceAds = this.player.source?.ads;\n if (isNotNullish(sourceAds) && sourceAds.length > 0) {\n // if VMAP is set up only one ad will be defined and that's the vmap definition.\n adManifestPayload.isVmap = (sourceAds[0] as {type?: string}).type === 'vmap';\n }\n\n const currentAdBreak = this.player.ads?.currentAdBreak;\n if (isNotNullish(currentAdBreak)) {\n adManifestPayload.adBreakInfo = mapTheoAdBreak(currentAdBreak, playerDuration);\n }\n\n this.adCallbacks.onAdManifestLoaded(adManifestPayload);\n });\n\n this.player.addEventListener('playing', () => {\n if (this.isLinearAdActive()) {\n this.adCallbacks.onPlay();\n }\n });\n this.player.addEventListener('pause', () => {\n if (this.isLinearAdActive()) {\n this.adCallbacks.onPause();\n }\n });\n\n // Note: THEOplayer doesn't emit quartile events for CSAI ads.\n // We tried to use them, but at the moment we don't see them emitted in the THEOplayer@10.12.0. We relay on fallback\n // in the AdAnalytics module that calculates it from play percentage.\n //\n // ads.addEventListener('adfirstquartile', (_event) => {});\n // ads.addEventListener('admidpoint', (_event) => {});\n // ads.addEventListener('adthirdquartile', (_event) => {});\n\n const handlePageClose = () => {\n this.adCallbacks.onBeforeUnload();\n };\n windowEventTracker.addEventListener('beforeunload', handlePageClose);\n windowEventTracker.addEventListener('unload', handlePageClose);\n }\n}\n","import {isNotNullish} from '../../../utils/Utils';\n\nexport const CALLBACK_SCHEDULER_TIMEOUT_DELAY_MS = 50;\n\nexport class CallbackScheduler {\n private timeout: ReturnType<typeof setTimeout> | undefined = undefined;\n private callback: (() => void) | undefined;\n\n schedule(callback: () => void) {\n if (isNotNullish(this.timeout)) {\n return;\n }\n\n this.callback = callback;\n this.timeout = setTimeout(() => {\n this.callback?.();\n this.cancel();\n }, CALLBACK_SCHEDULER_TIMEOUT_DELAY_MS);\n }\n\n isScheduled() {\n return isNotNullish(this.timeout);\n }\n\n execute() {\n this.callback?.();\n this.cancel();\n }\n\n cancel() {\n clearTimeout(this.timeout);\n this.timeout = undefined;\n this.callback = undefined;\n }\n}\n","import {State} from '../../../analyticsStateMachines/THEOplayerAnalyticsStateMachine';\nimport {Event, EventMap} from '../../../enums/Event';\nimport type {NoExtraProperties} from '../../../types/NoExtraProperties';\nimport {logger} from '../../../utils/Logger';\n\nimport {CallbackScheduler} from './CallbackScheduler';\n\nexport interface DelayScenario {\n /** The event to delay dispatching */\n delayEvent: Event;\n /** Only delay when the state machine is in this state */\n inState: string;\n /** If this event arrives while the delayed event is pending, cancel it */\n cancelOnEvent: Event;\n}\n\nexport class DelayedEventDispatcher {\n private readonly scheduler: CallbackScheduler = new CallbackScheduler();\n private activeScenario: DelayScenario | undefined;\n\n static create(): DelayedEventDispatcher {\n return new DelayedEventDispatcher([\n // Delayed PAUSE event execution to handle the case: PRECEDING \"PAUSE\" EVENT ON STARTUP ERRORS\n {delayEvent: Event.PAUSE, inState: State.STARTUP, cancelOnEvent: Event.ERROR},\n\n // Delayed PAUSE event execution to handle the case: PRECEDING \"PAUSE\" EVENT BEFORE \"SEEK\" WHEN SEEKING VIA UI PROGRESS BAR\n {delayEvent: Event.PAUSE, inState: State.PLAYING, cancelOnEvent: Event.SEEK},\n\n // Delayed END_AD event execution to handle the case: MIDROLL & POSTROLL ADS DETERMINATION\n {delayEvent: Event.END_AD, inState: State.AD_PLAYBACK, cancelOnEvent: Event.END},\n ]);\n }\n\n private constructor(private readonly scenarios: DelayScenario[]) {}\n\n dispatchEvent<StateMachineEvent extends keyof EventMap, StateMachineEventData extends EventMap[StateMachineEvent]>(\n event: StateMachineEvent,\n eventData: NoExtraProperties<EventMap[StateMachineEvent], StateMachineEventData>,\n state: string,\n dispatch: (\n event: StateMachineEvent,\n eventData: NoExtraProperties<EventMap[StateMachineEvent], StateMachineEventData>,\n eventTimestamp?: number,\n ) => void,\n ) {\n if (this.scheduler.isScheduled() && this.activeScenario != null) {\n if (this.activeScenario.cancelOnEvent === event) {\n logger.log(\n `⏳ [DelayedEventDispatcher] 🚫 Cancelling delayed '${String(this.activeScenario.delayEvent)}' — canceled by event '${String(event)}'`,\n );\n this.scheduler.cancel();\n this.activeScenario = undefined;\n } else {\n logger.log(\n `⏳ [DelayedEventDispatcher] ✅ Executing delayed '${String(this.activeScenario.delayEvent)}' early — unrelated event '${String(event)}' arrived`,\n );\n this.scheduler.execute();\n this.activeScenario = undefined;\n }\n }\n\n const matchingScenario = this.findMatchingScenario(event, state);\n if (matchingScenario != null) {\n const eventTimestamp = Date.now();\n this.activeScenario = matchingScenario;\n logger.log(`⏳ [DelayedEventDispatcher] ➕ Delaying '${String(event)}' in state '${state}'`);\n this.scheduler.schedule(() => {\n this.activeScenario = undefined;\n dispatch(event, eventData, eventTimestamp);\n });\n return;\n }\n\n dispatch(event, eventData);\n }\n\n private findMatchingScenario(event: keyof EventMap, state: string): DelayScenario | undefined {\n for (const scenario of this.scenarios) {\n if (scenario.delayEvent === event && scenario.inState === state) {\n return scenario;\n }\n }\n return undefined;\n }\n}\n","import type {AdapterAPI} from '../../api/AdapterAPI';\nimport {Analytics} from '../../core/Analytics';\nimport type {AnalyticsConfig} from '../../types/AnalyticsConfig';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport type {CustomDataValues} from '../../types/CustomDataValues';\nimport {guardAgainstDuplicatedUserId, sanitizeAnalyticsConfig} from '../../utils/analyticsConfigUtils';\nimport {areCollectorRequirementsValid} from '../../utils/collectorRequirementChecks';\nimport {logger} from '../../utils/Logger';\nimport {\n hasPlayerAlreadyBeenAugmented,\n isDefined,\n markPlayerInstanceAsAugmented,\n} from '../../utils/playerAugmentationUtils';\nimport {VERSION} from '../../utils/Version';\nimport type {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {VideojsInternalAdapter} from './VideojsInternalAdapter';\nimport {VideojsPlayerProxy} from './VideojsPlayerProxy';\n\nexport class VideojsAdapter implements AdapterAPI {\n private readonly internalAdapter: InternalAdapterAPI | undefined;\n private readonly analytics: Analytics | undefined;\n\n constructor(config: AnalyticsConfig, player: any, opts?: AnalyticsStateMachineOptions) {\n if (hasPlayerAlreadyBeenAugmented(player)) {\n logger.errorMessageToUser('Bitmovin Analytics is already hooked up to this player instance');\n return;\n }\n markPlayerInstanceAsAugmented(player);\n\n const sanitizedConfig = sanitizeAnalyticsConfig(config);\n if (!areCollectorRequirementsValid(sanitizedConfig)) {\n return;\n }\n\n guardAgainstDuplicatedUserId(sanitizedConfig);\n\n this.internalAdapter = new VideojsInternalAdapter(new VideojsPlayerProxy(player), opts);\n this.analytics = Analytics.create(sanitizedConfig, this.internalAdapter);\n }\n\n static readonly version: string = VERSION;\n\n get version(): string {\n return VERSION;\n }\n\n getCurrentImpressionId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getCurrentImpressionId();\n }\n\n getUserId(): string | undefined {\n if (!isDefined(this.analytics)) return;\n\n return this.analytics.getUserId();\n }\n\n setCustomData(values: CustomDataValues) {\n if (!isDefined(this.internalAdapter)) return;\n\n this.internalAdapter.setCustomData(values);\n }\n\n setCustomDataOnce(values: CustomDataValues) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.setCustomDataOnce(values);\n }\n\n sourceChange(config: AnalyticsConfig) {\n if (!isDefined(this.analytics)) return;\n\n this.analytics.sourceChange(config);\n }\n}\n","import {VideojsAnalyticsStateMachine} from '../../analyticsStateMachines/VideoJsAnalyticsStateMachine';\nimport {Analytics} from '../../core/Analytics';\nimport {HeartbeatService} from '../../core/HeartbeatService';\nimport VideoCompletionTracker from '../../core/VideoCompletionTracker';\nimport * as CodecHelper from '../../enums/Codecs';\nimport {Event} from '../../enums/Event';\nimport {Player} from '../../enums/Player';\nimport {PlayerSize} from '../../enums/PlayerSize';\nimport {getStreamTypeFromMIMEType, getStreamTypesFromURL} from '../../enums/StreamTypes';\nimport {ErrorDetailBackend} from '../../features/errordetails/ErrorDetailBackend';\nimport {ErrorDetailTracking} from '../../features/errordetails/ErrorDetailTracking';\nimport {Feature} from '../../features/Feature';\nimport {FeatureConfig} from '../../features/FeatureConfig';\nimport {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport {CodecInfo} from '../../types/CodecInfo';\nimport {DrmPerformanceInfo} from '../../types/DrmPerformanceInfo';\nimport {QualityChangeEvent} from '../../types/EventData';\nimport {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport {buildPlaybackInfoStreamTypeFields, normalizeVideoDuration, PlaybackInfo} from '../../types/PlaybackInfo';\nimport {QualityLevelInfo} from '../../types/QualityLevelInfo';\nimport {isDifferentSubtitleInfo, SubtitleInfo} from '../../types/SubtitleInfo';\nimport {getGlobalVideojsVersion} from '../../utils/globalScopeUtils';\nimport {isBlank, isValidString} from '../../utils/stringUtils';\nimport {isAudioMuted, isFunction, isNotNullish, isNullish} from '../../utils/Utils';\nimport {InternalAdapter} from '../internal/InternalAdapter';\nimport {InternalAdapterAPI} from '../internal/InternalAdapterAPI';\n\nimport {VideojsPlayerProxy} from './VideojsPlayerProxy';\n\n// Declaration merging to extend the VideoJsPlayer interface.\n// @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html\ndeclare module 'video.js' {\n interface VideoJsPlayer {\n // Extend the VideoJsPlayer interface with missing `version` function, introduced in 8.10.0\n // by https://github.com/videojs/video.js/pull/8543/files, but not present in `@types/video.js@7.3.58` yet.\n //\n // Function set as nullable to be able to covert older VideoJs players\n //\n // see: https://github.com/videojs/video.js/blob/6fe68e5dad6853d8f0eaf45534873607c1b32277/src/js/player.js#L1345\n version?(): {'video.js': string};\n }\n}\nexport class VideojsInternalAdapter extends InternalAdapter implements InternalAdapterAPI {\n readonly videoCompletionTracker: VideoCompletionTracker;\n\n private readonly player: VideojsPlayerProxy;\n\n private _subtitleInfo: SubtitleInfo = {enabled: false};\n private selectedAudioLanguage?: string;\n /** Boolean flag to prevent multiple calls of the {@link Event.UNLOAD} event */\n private onBeforeUnLoadEvent = false;\n private previousTime = 0;\n\n constructor(player: VideojsPlayerProxy, opts?: AnalyticsStateMachineOptions) {\n super(opts);\n this.player = player;\n const playingHeartbeatService = new HeartbeatService(() => this.currentTime);\n const stateMachine = new VideojsAnalyticsStateMachine(\n this.stateMachineCallbacks,\n playingHeartbeatService,\n this.opts,\n );\n playingHeartbeatService.setListener(stateMachine);\n this.stateMachine = stateMachine;\n\n this.videoCompletionTracker = new VideoCompletionTracker();\n }\n\n override resetSourceRelatedState() {\n super.resetSourceRelatedState();\n\n this.videoCompletionTracker.reset();\n this.videoCompletionTracker.setVideoDuration(this.player.duration() ?? 0);\n this.previousTime = 0;\n }\n\n initialize(analytics: Analytics): Array<Feature<FeatureConfigContainer, FeatureConfig>> {\n this.register();\n const errorDetailTracking = new ErrorDetailTracking(\n analytics.errorDetailTrackingSettingsProvider,\n new ErrorDetailBackend(analytics.errorDetailTrackingSettingsProvider.collectorConfig),\n [analytics.errorDetailSubscribable],\n undefined,\n );\n return [errorDetailTracking];\n }\n\n getPlayerVersion = () => {\n // try to get the version from the player instance\n // - `VideoJsPlayer.version()` was introduced in 8.10.0, so we need to check for it\n const playerInstanceVersion = this.player.version?.()?.['video.js'];\n if (isValidString(playerInstanceVersion) && !isBlank(playerInstanceVersion)) {\n return playerInstanceVersion;\n }\n\n // try to get the version from the global `window` variable (if npm module is used, it doesn't exist)\n const windowVideoJsVersion = getGlobalVideojsVersion();\n if (isValidString(windowVideoJsVersion) && !isBlank(windowVideoJsVersion)) {\n return windowVideoJsVersion;\n }\n\n return 'unknown';\n };\n getPlayerName = () => Player.VIDEOJS;\n getPlayerTech = () => 'html5';\n getAutoPlay = () => this.player.autoplay() === true;\n override getDrmPerformanceInfo = (): DrmPerformanceInfo | undefined => this.drmPerformanceInfo;\n\n getCurrentPlaybackInfo(): PlaybackInfo {\n this.selectedAudioLanguage = this.getSelectedAudioTrackLanguage(this.player);\n const codecInfo = this.getCodecInfo(this.player.tech({IWillNotUseThisInPlugins: true}));\n const playerDuration = this.player.duration();\n\n const info: PlaybackInfo = {\n ...this.getCommonPlaybackInfo(),\n ...detectVideoJsPlaybackInfoStreamTypeFields(this.player),\n isLive: isNullish(playerDuration) || isNaN(playerDuration) ? undefined : playerDuration === Infinity,\n size: this.player.isFullscreen() ? PlayerSize.Fullscreen : PlayerSize.Window,\n playerTech: this.getPlayerTech(),\n isMuted: this.player.muted(),\n videoDuration: normalizeVideoDuration(playerDuration),\n videoWindowHeight: this.player.height(),\n videoWindowWidth: this.player.width(),\n videoPlaybackHeight: this.player.videoHeight(),\n videoPlaybackWidth: this.player.videoWidth(),\n audioLanguage: this.selectedAudioLanguage,\n subtitleEnabled: this._subtitleInfo.enabled,\n subtitleLanguage: this._subtitleInfo.language,\n videoCodec: codecInfo?.videoCodec,\n audioCodec: codecInfo?.audioCodec,\n droppedFrames: 0, // TODO\n // TODO audioBitrate:\n // TODO isCasting:\n // TODO videoTitle: (currently only from the analytics config)\n };\n\n const qualityInfo = this.getCurrentQualityLevelInfo();\n if (qualityInfo) {\n info.videoPlaybackWidth = qualityInfo.width ?? info.videoPlaybackWidth;\n info.videoPlaybackHeight = qualityInfo.height ?? info.videoPlaybackHeight;\n info.videoBitrate = qualityInfo.bitrate ?? info.videoBitrate;\n }\n\n return info;\n }\n\n getCurrentQualityLevelInfo(): QualityLevelInfo | null {\n return this.currentVideoJsQualityLevel();\n }\n\n register() {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const that = this;\n\n // if one source is being played and we load new source and start playing it\n // we need to reset all session related data and initialize new session\n // videojs does not provide a way for figuring out when current source or player is unloaded\n // so we need to reset everything with \"manualSourceChange\" event every time new source is loaded\n this.player.on('loadstart', function (this: any) {\n that.eventCallback(Event.MANUAL_SOURCE_CHANGE, {config: {}});\n });\n this.player.on('loadedmetadata', function (this: any) {\n that.videoCompletionTracker.reset();\n that.videoCompletionTracker.setVideoDuration(this.duration());\n that.previousTime = 0;\n that.eventCallback(Event.SOURCE_LOADED, {});\n });\n this.player.ready(function (this: any) {\n that._subtitleInfo = that.getSubtitleInfo(this);\n that.eventCallback(Event.READY, {});\n });\n this.player.on('play', function (this: any) {\n that.eventCallback(Event.PLAY, {\n currentTime: this.currentTime(),\n });\n });\n this.player.on('pause', function (this: any) {\n if (!this.seeking()) {\n that.eventCallback(Event.PAUSE, {\n currentTime: this.currentTime(),\n });\n }\n });\n this.player.on('error', function (this: any) {\n const error: MediaError = this.error();\n that.eventCallback(Event.ERROR, {\n currentTime: this.currentTime(),\n code: error.code,\n message: error.message,\n originalError: error,\n data: {},\n });\n });\n this.player.on('volumechange', function (this: any) {\n const muted = this.muted();\n const volume = this.volume();\n const isMuted = isAudioMuted(muted, volume);\n\n if (this.previousMutedValue !== isMuted) {\n if (isMuted) {\n that.eventCallback(Event.MUTE, {\n currentTime: this.currentTime(),\n });\n } else {\n that.eventCallback(Event.UN_MUTE, {\n currentTime: this.currentTime(),\n });\n }\n this.previousMutedValue = isMuted;\n }\n });\n this.player.on('seeking', function (this: any) {\n that.eventCallback(Event.SEEK, {\n currentTime: isNotNullish(that.previousTime) ? that.previousTime : this.currentTime(),\n });\n });\n this.player.on('seeked', function (this: any) {\n that.eventCallback(Event.SEEKED, {\n currentTime: this.currentTime(),\n });\n });\n\n this.player.on('texttrackchange', function (this: any) {\n const newSubtitleInfo = that.getSubtitleInfo(this);\n const hasInfoChanged = isNullish(that._subtitleInfo)\n ? true\n : isDifferentSubtitleInfo(that._subtitleInfo, newSubtitleInfo);\n that._subtitleInfo = newSubtitleInfo;\n\n if (hasInfoChanged) {\n that.eventCallback(Event.SUBTITLE_CHANGE, {\n currentTime: this.currentTime(),\n });\n }\n });\n\n this.player.audioTracks()?.on('change', () => {\n const newSelectedAudioLanguage = that.getSelectedAudioTrackLanguage(that.player);\n if (isNotNullish(newSelectedAudioLanguage) && newSelectedAudioLanguage !== that.selectedAudioLanguage) {\n that.eventCallback(Event.AUDIOTRACK_CHANGED, {\n currentTime: that.player.currentTime(),\n });\n }\n });\n\n this.player.on('stalled', function (this: any) {\n that.eventCallback(Event.START_BUFFERING, {\n currentTime: this.currentTime(),\n });\n });\n this.player.on('waiting', function (this: any) {\n that.eventCallback(Event.START_BUFFERING, {\n currentTime: this.currentTime(),\n });\n });\n this.player.on('timeupdate', function (this: any) {\n if (!this.seeking()) {\n that.previousTime = this.currentTime();\n }\n that.eventCallback(Event.TIMECHANGED, {\n currentTime: this.currentTime(),\n });\n\n const qualityInfo = that.currentVideoJsQualityLevel();\n if (qualityInfo?.height && qualityInfo?.width && qualityInfo?.bitrate) {\n const eventObject: QualityChangeEvent = {\n type: 'video',\n bitrate: qualityInfo.bitrate,\n height: qualityInfo.height,\n width: qualityInfo.width,\n currentTime: this.currentTime(),\n };\n if (that.qualityChangeService.shouldAllowVideoQualityChange(qualityInfo.bitrate)) {\n that.eventCallback(Event.VIDEO_CHANGE, eventObject);\n }\n\n that.qualityChangeService.setVideoBitrate(qualityInfo.bitrate);\n that.stateMachineCallbacks.updateSampleQualityInfo(eventObject);\n }\n });\n\n let handlePageClose = () => {\n if (!this.onBeforeUnLoadEvent) {\n this.onBeforeUnLoadEvent = true;\n let currentTime: number | undefined;\n if (isNotNullish(this.player)) {\n currentTime = this.player.currentTime();\n }\n this.eventCallback(Event.UNLOAD, {\n currentTime,\n });\n }\n this.release();\n };\n\n handlePageClose = handlePageClose.bind(this);\n\n this.player.on('dispose', handlePageClose);\n this.windowEventTracker.addEventListener('beforeunload', handlePageClose);\n this.windowEventTracker.addEventListener('unload', handlePageClose);\n }\n\n protected get currentTime(): number {\n return this.player.currentTime() ?? 0;\n }\n\n private getSelectedAudioTrackLanguage(player: any): string | undefined {\n for (const track of player.audioTracks()) {\n if (track.enabled) {\n return track.language;\n }\n }\n return undefined;\n }\n\n private getSubtitleInfo(player: any): SubtitleInfo {\n const textTracks = player.textTracks() || [];\n let enabled = false;\n let language;\n for (const track of textTracks) {\n if (track.mode === 'showing') {\n enabled = true;\n language = track.language;\n break;\n }\n }\n return {\n enabled,\n language,\n };\n }\n\n private currentVideoJsQualityLevel(): QualityLevelInfo | null {\n // Check for HLS source-handler (http-streaming)\n // When we just use Videojs without any specific source-handler (not using MSE API based engine)\n // but just native technology (HTML5/Flash) to do for example \"progressive download\" with plain Webm/Mp4\n // or use native HLS on Safari this may not be present. In that case Videojs is just\n // a wrapper around the respective playback tech (HTML or Flash).\n const tech = this.player.tech({IWillNotUseThisInPlugins: true}) as any;\n\n if (isNullish(tech)) {\n return null;\n }\n\n if (isNullish(tech.vhs) && isNullish(tech.hls)) {\n return null;\n }\n\n const mediaAttributes = this.getMediaAttributes(tech);\n\n if (!mediaAttributes || !mediaAttributes.bitrate) {\n return null;\n }\n\n return {\n bitrate: mediaAttributes.bitrate,\n width: mediaAttributes.width,\n height: mediaAttributes.height,\n };\n }\n\n // more detailed info from segment can be obtained using\n // https://github.com/videojs/http-streaming#segment-metadata\n // but some properties are not available in older videojs versions\n private getMediaAttributes(playerTech: any): MediaAttributes | undefined {\n if (!playerTech) {\n return;\n }\n\n // From here we are going onto Videojs-HLS source-handler specific API\n let sourceHandler;\n if (playerTech.vhs) {\n sourceHandler = playerTech.vhs;\n } else if (playerTech.hls) {\n // older videojs versions don't have vhs property\n sourceHandler = playerTech.hls;\n }\n\n // Maybe we have the HLS source-handler initialized, but it is\n // not actually activated and used (just wrapping HTML5 built-in HLS playback like in Safari)\n if (!sourceHandler || !sourceHandler.playlists || !isFunction(sourceHandler.playlists.media)) {\n return;\n }\n\n // Check for current media playlist\n const selectedPlaylist = sourceHandler.playlists.media();\n\n if (!selectedPlaylist) {\n return;\n }\n\n const {attributes} = selectedPlaylist;\n\n if (!attributes || Object.keys(attributes).length === 0) {\n return;\n }\n\n return {\n bitrate: attributes.BANDWIDTH,\n width: (attributes.RESOLUTION || {}).width,\n height: (attributes.RESOLUTION || {}).height,\n codecs: attributes.CODECS,\n };\n }\n\n private getCodecInfo(playerTech: any): CodecInfo | undefined {\n const mediaAttributes = this.getMediaAttributes(playerTech);\n\n if (!mediaAttributes || !mediaAttributes.codecs) {\n return;\n }\n\n const codecs = mediaAttributes.codecs.split(',');\n\n if (!codecs) {\n return;\n }\n\n return {\n videoCodec: codecs.find((codec: string) => CodecHelper.isVideoCodec(codec)),\n audioCodec: codecs.find((codec: string) => CodecHelper.isAudioCodec(codec)),\n };\n }\n}\n\nexport interface MediaAttributes {\n codecs: string | undefined;\n bitrate: number | undefined;\n width: number | undefined;\n height: number | undefined;\n}\n\nexport function detectVideoJsPlaybackInfoStreamTypeFields(\n videoJsPlayer: VideojsPlayerProxy,\n): Pick<PlaybackInfo, 'm3u8Url' | 'mpdUrl' | 'progUrl' | 'streamFormat'> {\n const url = videoJsPlayer.currentSrc();\n\n let streamType = getStreamTypesFromURL(url);\n if (isNullish(streamType)) {\n // if we could not detect a stream type from URL, we will try to detect it from a MIME type\n const streamMimeType = videoJsPlayer.currentType?.();\n if (streamMimeType) {\n streamType = getStreamTypeFromMIMEType(streamMimeType);\n }\n }\n\n return buildPlaybackInfoStreamTypeFields(streamType, url);\n}\n","import type {VideoJsPlayer} from 'video.js';\n\nimport {safeAccess} from '../../utils/objectUtils';\n\nexport class VideojsPlayerProxy {\n constructor(private readonly rawPlayer: VideoJsPlayer) {}\n\n on = (...args: Parameters<VideoJsPlayer['on']>) => {\n safeAccess(() => this.rawPlayer.on(...args));\n };\n\n ready = (...args: Parameters<VideoJsPlayer['ready']>) => safeAccess(() => this.rawPlayer.ready(...args));\n\n duration = () => safeAccess(() => this.rawPlayer.duration());\n\n currentTime = () => safeAccess(() => this.rawPlayer.currentTime());\n\n currentSrc = () => safeAccess(() => this.rawPlayer.currentSrc());\n\n currentType = () => safeAccess(() => this.rawPlayer.currentType());\n\n autoplay = () => safeAccess(() => this.rawPlayer.autoplay());\n\n muted = () => safeAccess(() => this.rawPlayer.muted());\n\n height = () => safeAccess(() => this.rawPlayer.height());\n\n width = () => safeAccess(() => this.rawPlayer.width());\n\n videoHeight = () => safeAccess(() => this.rawPlayer.videoHeight());\n\n videoWidth = () => safeAccess(() => this.rawPlayer.videoWidth());\n\n isFullscreen = () => safeAccess(() => this.rawPlayer.isFullscreen());\n\n audioTracks = () => safeAccess(() => this.rawPlayer.audioTracks());\n\n tech = (options?: unknown) => safeAccess(() => this.rawPlayer.tech(options));\n\n version = () => safeAccess(() => this.rawPlayer.version?.());\n}\n","import type {HeartbeatListener} from '../core/HeartbeatService';\nimport {HeartbeatService} from '../core/HeartbeatService';\nimport {SSAI_RELATED_SAMPLE_MARKER} from '../core/ssai/ssaiUtils';\nimport {ErrorCode} from '../enums/ErrorCode';\nimport {Event, EventMap} from '../enums/Event';\nimport type {AnalyticsStateMachineOptions} from '../types/AnalyticsStateMachineOptions';\nimport type {NoExtraProperties} from '../types/NoExtraProperties';\nimport type {SourceMetadata} from '../types/SourceMetadata';\nimport {HeartbeatPayload, StateMachineCallbacks} from '../types/StateMachineCallbacks';\nimport {logger} from '../utils/Logger';\nimport * as Settings from '../utils/Settings';\nimport * as Utils from '../utils/Utils';\nimport {isNotNullish} from '../utils/Utils';\n\nconst BUFFERING_HEARTBEAT_INTERVALS = [3000, 5000, 10000, 30000, 59700];\n\nexport abstract class AnalyticsStateMachine implements HeartbeatListener {\n protected stateMachine: StateMachine.StateMachine & {[key: string]: any};\n protected onEnterStateTimestamp = 0;\n\n protected readonly videoStartupTimeoutMs: number = Settings.ANALYTICS_VIDEOSTART_TIMEOUT;\n protected readonly bufferTimeoutMs: number = Settings.ANALYTICS_BUFFER_TIMEOUT;\n protected readonly playingHeartbeatService: HeartbeatService;\n\n private bufferingHeartbeatIntervalHandle?: ReturnType<typeof setInterval>;\n private currentBufferingIntervalIndex = 0;\n private bufferingTimeoutHandle?: ReturnType<typeof setTimeout>;\n private videoStartTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(\n protected stateMachineCallbacks: StateMachineCallbacks,\n playingHeartbeatService: HeartbeatService,\n opts: AnalyticsStateMachineOptions,\n ) {\n this.stateMachine = this.createStateMachine(opts);\n this.playingHeartbeatService = playingHeartbeatService;\n }\n\n abstract createStateMachine(opts: AnalyticsStateMachineOptions): StateMachine.StateMachine;\n\n callEvent<StateMachineEvent extends keyof EventMap, StateMachineEventData extends EventMap[StateMachineEvent]>(\n event: StateMachineEvent,\n eventData: NoExtraProperties<EventMap[StateMachineEvent], StateMachineEventData>,\n eventTimestamp: number,\n ): void {\n const stateMachineEventMethod = this.stateMachine[event];\n\n if (stateMachineEventMethod == null) {\n // If the event (aka. the event method) is not defined in the JSM, we log a warning,\n // because it means that we are explicitly trying to call that JSM event from our code (probably adapter),\n // but it was not defined in the JSM at all. Either we are missing it or it should not be called at all!\n logger.warn(`StateMachine ignored event \"${event}\" call, because it was not defined`, eventData, eventTimestamp);\n return;\n }\n\n try {\n // By default, if you try to call an event method not allowed in the current state, the state machine will throw an exception.\n // see: https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#handling-failures\n //\n // This JSM library behavior can be changed by providing \"a custom error handler\" in the `create()`\n // method of the state machine, and we do that in every state machine!\n //\n // But we still want to have here a try-catch block, in case of unexpected state machine code,\n // to avoid propagating the exception to the rest of the application (and breaking customer app).\n stateMachineEventMethod.call(this.stateMachine, eventTimestamp, eventData);\n } catch (e) {\n logger.error(\n `StateMachine ignored event \"${event}\" call, because it has thrown exception in the current state \"${this.currentState}\"`,\n eventData,\n eventTimestamp,\n e,\n );\n }\n }\n\n get currentState(): string {\n return this.stateMachine.current;\n }\n\n resetIntervals() {\n this.clearVideoStartTimeout();\n this.clearBufferingTimeoutHandle(true);\n this.clearBufferingHeartbeatHandle();\n }\n\n //#region buffer timeout\n\n protected startBufferingHeartbeatInterval(reset = true) {\n this.resetBufferingHelpers(reset);\n\n this.startBufferingTimeoutHandle();\n\n this.bufferingHeartbeatIntervalHandle = setInterval(() => {\n const state = this.stateMachine.current.toLowerCase();\n if (state !== 'buffering') {\n this.resetBufferingHelpers();\n return;\n }\n const timestamp = new Date().getTime();\n const stateDuration = timestamp - this.onEnterStateTimestamp;\n this.stateMachineCallbacks.heartbeat(stateDuration, state, {buffered: stateDuration});\n this.onEnterStateTimestamp = timestamp;\n this.currentBufferingIntervalIndex = Math.min(\n this.currentBufferingIntervalIndex + 1,\n BUFFERING_HEARTBEAT_INTERVALS.length - 1,\n );\n this.startBufferingHeartbeatInterval(false);\n }, BUFFERING_HEARTBEAT_INTERVALS[this.currentBufferingIntervalIndex]);\n }\n\n protected resetBufferingHelpers(reset = true) {\n if (reset) {\n this.currentBufferingIntervalIndex = 0;\n }\n this.clearBufferingHeartbeatHandle();\n this.clearBufferingTimeoutHandle(reset);\n }\n\n protected clearBufferingHeartbeatHandle() {\n if (isNotNullish(this.bufferingHeartbeatIntervalHandle)) {\n clearInterval(this.bufferingHeartbeatIntervalHandle);\n this.bufferingHeartbeatIntervalHandle = undefined;\n }\n }\n\n private startBufferingTimeoutHandle() {\n if (this.currentBufferingIntervalIndex > 0) {\n return;\n }\n this.bufferingTimeoutHandle = setTimeout(() => {\n this.callEvent(\n Event.ERROR,\n {\n ...ErrorCode.BUFFERING_TIMEOUT_REACHED,\n data: {\n additionalData: `StateMachine timed out after ${this.bufferTimeoutMs} ms of consecutive buffering.`,\n },\n },\n Utils.getCurrentTimestamp(),\n );\n this.stateMachineCallbacks.release();\n }, this.bufferTimeoutMs);\n }\n\n protected clearBufferingTimeoutHandle(reset: boolean) {\n if (reset && isNotNullish(this.bufferingTimeoutHandle)) {\n clearTimeout(this.bufferingTimeoutHandle);\n this.bufferingTimeoutHandle = undefined;\n }\n }\n //#endregion\n\n //#region videoStartupFailed\n protected setVideoStartTimeout() {\n if (isNotNullish(this.videoStartTimeout)) {\n this.clearVideoStartTimeout();\n }\n this.videoStartTimeout = setTimeout(() => {\n this.callEvent(Event.VIDEOSTART_TIMEOUT, {}, Date.now());\n this.stateMachineCallbacks.release();\n }, this.videoStartupTimeoutMs);\n }\n\n protected clearVideoStartTimeout() {\n clearTimeout(this.videoStartTimeout);\n this.videoStartTimeout = undefined;\n }\n //#endregion\n\n onHeartbeat(playerCurrentTime: number): void {\n this.sendPlayingSample(Date.now(), playerCurrentTime);\n }\n\n /**\n * Should be used in the \"PLAYING\" state only, and only by \"SSAI\", \"ProgramChange\" and \"Playing Heartbeat\" features,\n * otherwise it will log a warning and do nothing!\n *\n * It calls the {@link StateMachineCallbacks.heartbeat} callback, to send out the current playing sample (it cuts\n * current PLAYING state) and resets time measurements to set a new start of PLAYING state again with new timestamp\n * and video time. So the next sample will be sent with the duration from the last cut.\n *\n * We have chosen to use {@link StateMachineCallbacks.heartbeat} callback here, because it was the easiest and the\n * fastest way to trigger 'playing' sample sending (with additional properties like \"ssai marker\"), without changing\n * and refactoring too much code, in future this code should be refactored with better naming.\n *\n * @param timestamp current timestamp\n * @param playerCurrentTime the current player playback time of the video in seconds\n * @param triggeredBySsai boolean to mark the sample as SSAI triggered\n * @param triggeredByProgramChange boolean to mark the sample as ProgramChange triggered\n */\n sendPlayingSample(\n timestamp: number,\n playerCurrentTime: number,\n triggeredBySsai = false,\n triggeredByProgramChange = false,\n ) {\n const state = this.stateMachine.current.toLowerCase();\n // We don't allow this in any other state because it could interrupt the natural flow of the states.\n // Only PLAYING is considered a state which we can interrupt/cut by heartbeat or SSAI interaction.\n if (state !== 'playing') {\n // our logic for \"SSAI\" and \"playing heartbeat\" is built on the assumption that we send only 'playing' samples,\n // but that \"if\" restriction is spread across the codebase, so we need to log a warning here, to see a potential\n // problems in our logic, if reported by from customer and report will contain these logs\n logger.warn(`Unexpected call of \"sendPlayingSample\" in AnalyticsStateMachine from \"${state}\" state`);\n return;\n }\n\n this.stateMachineCallbacks.setVideoTimeEndFromEvent({currentTime: playerCurrentTime});\n\n const stateDuration = timestamp - this.onEnterStateTimestamp;\n const payload: HeartbeatPayload = {\n played: stateDuration,\n isProgramChange: triggeredByProgramChange ? true : undefined,\n };\n\n if (triggeredBySsai) {\n payload[SSAI_RELATED_SAMPLE_MARKER] = true;\n }\n\n this.stateMachineCallbacks.heartbeat(stateDuration, state, payload);\n\n this.resetCurrentStateStart(timestamp, playerCurrentTime);\n }\n\n private resetCurrentStateStart(stateEnterTimestamp: number, playerCurrentTime: number): void {\n this.onEnterStateTimestamp = stateEnterTimestamp;\n this.stateMachineCallbacks.setVideoTimeStartFromEvent({currentTime: playerCurrentTime});\n }\n\n programChange(playerCurrentTime: number, isSsaiActive: boolean, sourceMetadata: SourceMetadata): void {\n // if program change happens before or during STARTUP (or other \"startup state\", like bitmovin8 STARTUP_AUTOPLAY),\n // we don't want to do any \"cut\", because it has not started yet, we just want to update source metadata\n // and wait for the natural start\n if (\n this.stateMachine.current === 'SETUP' ||\n this.stateMachine.current === 'READY' ||\n this.stateMachine.current === 'STARTUP' ||\n this.stateMachine.current === 'STARTUP_AUTOPLAY'\n ) {\n this.stateMachineCallbacks.updateSourceMetadata(sourceMetadata);\n return;\n }\n\n const programChangeTimestamp = Date.now();\n\n // If the program change happens during PLAYING state, we want to \"cut it\" and send asap last playing sample\n // of the previous program (session) with the duration from the start of PLAYING state to the program change\n if (this.stateMachine.current === 'PLAYING') {\n this.sendPlayingSample(programChangeTimestamp, playerCurrentTime, isSsaiActive, true);\n }\n // ... else in any other state, we just want to reset time measurements to set a new start of the current state\n else {\n this.resetCurrentStateStart(programChangeTimestamp, playerCurrentTime);\n }\n\n this.stateMachineCallbacks.programChange(sourceMetadata);\n }\n}\n","import {create} from 'javascript-state-machine';\n\nimport {Event, JSM_INITIAL_EVENT} from '../enums/Event';\nimport {createVideoStartFailedReason} from '../enums/VideoStartFailedReason';\nimport type {AnalyticsStateMachineOptions} from '../types/AnalyticsStateMachineOptions';\nimport {AnalyticsEventBase} from '../types/EventData';\nimport {logger} from '../utils/Logger';\nimport {isNumber} from '../utils/numberUtils';\nimport {isFunction} from '../utils/Utils';\n\nimport {AnalyticsStateMachine} from './AnalyticsStateMachine';\nimport {\n customStateMachineErrorCallback,\n getAllStatesBut,\n logMissingCallbackWarning,\n logStateMachineTransition,\n whileIn,\n} from './stateMachineUtils';\n\nexport enum State {\n /**\n * We track and consider the buffering state only when it comes from the {@link State.PLAYING},\n * aka. when the video was playing and stopped because it started to buffer.\n */\n BUFFERING = 'BUFFERING',\n /**\n * This state was created only to be able to \"cut\" the {@link State.PLAYING} and {@link State.PAUSE}\n * and send playing/pause sample with current custom data, while calling {@link AdapterAPI.setCustomData} function\n * and setting the new custom data values.\n *\n * @remarks\n *\n * Our implementation relays on a specific state name \"CUSTOMDATACHANGE\" because it should call the\n * default \"onleavestate\" state machine callback {@link stateMachineCallbacks.customdatachange}.\n */\n CUSTOMDATACHANGE = 'CUSTOMDATACHANGE',\n ERROR = 'ERROR',\n PAUSE = 'PAUSE',\n PLAYING = 'PLAYING',\n READY = 'READY',\n /**\n * We track and consider the \"seeking\" state only when it comes from the {@link State.PLAYING},\n * aka. when the video has already started to play and is already playing.\n */\n SEEKING = 'SEEKING',\n /**\n * We do not track the \"seeking\" while the playback is paused!\n *\n * We should not produce a \"seeking\" sample, but rather we should just extend the existing \"pause\" sample.\n *\n * Why do we recognize this state?\n * - because during the seeking, {@link Event.TIMECHANGED} is fired and if we would just use {@link State.PAUSE},\n * it would trigger a JSM transition to {@link State.PLAYING} and break the tracking of current pause.\n * - because once seeking is finished, we need to transition the JSM back to {@link State.PAUSE}\n *\n * @remarks\n *\n * To be sure state machine works correctly, we need to be sure only calling {@link Event.SEEK} from\n * {@link State.PAUSE} should transition JSM to {@link State.SEEKING_IN_PAUSE}!\n */\n SEEKING_IN_PAUSE = 'SEEKING_IN_PAUSE',\n SETUP = 'SETUP',\n SOURCE_CHANGING = 'SOURCE_CHANGING',\n STARTUP = 'STARTUP',\n /**\n * The browser window was closed (window 'unload' event), aka. sender has stopped the casting\n */\n UNLOADED = 'UNLOADED',\n VIDEOSTART_FAILED = 'VIDEOSTART_FAILED',\n}\n\nexport class CAFv3AnalyticsStateMachine extends AnalyticsStateMachine {\n override createStateMachine(opts: AnalyticsStateMachineOptions): StateMachine.StateMachine {\n return create({\n // custom initial state and custom JSM initial event name\n // initial event is used by JSM for the initial state transition 'none' -> 'SETUP'\n initial: {state: State.SETUP, event: JSM_INITIAL_EVENT},\n error: customStateMachineErrorCallback,\n events: [\n ...whileIn(State.SETUP).passOver(\n // We track and consider the buffering state only when it comes from the State.PLAYING\n Event.START_BUFFERING,\n ),\n\n {name: Event.SOURCE_LOADED, from: State.SETUP, to: State.READY},\n {name: Event.READY, from: State.SETUP, to: State.READY},\n\n ...whileIn(State.READY).passOver(\n Event.READY,\n // We track and consider the buffering state only when it comes from the State.PLAYING\n Event.START_BUFFERING,\n Event.END_BUFFERING,\n // this will fire whenever the currentTime attribute changes\n Event.TIMECHANGED,\n Event.SEEK,\n Event.SEEKED,\n ),\n\n {name: Event.PLAY, from: State.READY, to: State.STARTUP},\n\n {name: Event.ERROR, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.UNLOAD, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.VIDEOSTART_TIMEOUT, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n\n {name: Event.ERROR, from: getAllStatesBut([State.STARTUP], State), to: State.ERROR},\n {name: Event.UNLOAD, from: getAllStatesBut([State.STARTUP], State), to: State.UNLOADED},\n\n // We need to wait for the 'TIME_UPDATE' event to also include startup video buffering in State.STARTUP time.\n //\n // We shouldn't use 'PLAYING' event, because that event is fired immediately, followed by buffering events that\n // would cut State.STARTUP sooner, then move us to State.PLAYING and then even to State.BUFFERING.\n {name: Event.TIMECHANGED, from: State.STARTUP, to: State.PLAYING},\n ...whileIn(State.PLAYING).passOver(Event.TIMECHANGED),\n\n {name: Event.START_BUFFERING, from: State.PLAYING, to: State.BUFFERING},\n // While in State.BUFFERING, we are waiting for 'TIME_UPDATE' event to be able to recognize end of the\n // buffering and to return back to State.PLAYING. The relay also on fact that State.BUFFERING can only\n // start from State.PLAYING.\n //\n // We tried to use the 'BUFFERING' event containing `isBuffering: false`, but that was not reliable,\n // because of a scenario when the 'error' event would happen while buffering (because of buffering timeout\n // or Shaka player throwing error). Because this 'BUFFERING' event is also fired when player throws error, and\n // it would transition us to State.PLAYING and then it would send the short \"playing\" sample, before 'ERROR'\n // event would be fired and would move us to State.ERROR.\n {name: Event.TIMECHANGED, from: State.BUFFERING, to: State.PLAYING},\n\n {name: Event.PAUSE, from: State.PLAYING, to: State.PAUSE},\n {name: Event.PAUSE, from: State.BUFFERING, to: State.PAUSE},\n // if a 'PAUSE' event happens during State.SEEKING, we need to transition to State.PAUSE\n // instead of recovering back State.PLAYING (where State.SEEKING was started from)\n {name: Event.PAUSE, from: State.SEEKING, to: State.PAUSE},\n ...whileIn(State.PAUSE).passOver(\n // We track and consider the buffering state only when it comes from the State.PLAYING\n Event.START_BUFFERING,\n Event.END_BUFFERING,\n ),\n // We use Event.PLAYING because it is more reliable for tracking transition from State.PAUSE to State.PLAYING.\n //\n // We shouldn't use 'TIME_UPDATE' to interrupt State.PAUSE, because that event is fired when the time indicated\n // by the currentTime property has been updated.\n // Example: this happens when a user clicks 'PAUSE' during the seeking. Our state machine should move to\n // State.PAUSE asap, but later because of the seeking, the events 'SEEKED' and 'TIME_UPDATE' are still fired,\n // and that would break our state machine as we would end up in State.PLAYING\n {name: Event.PLAYING, from: State.PAUSE, to: State.PLAYING},\n\n {name: Event.SEEK, from: State.PAUSE, to: State.SEEKING_IN_PAUSE},\n ...whileIn(State.SEEKING_IN_PAUSE).passOver(\n Event.SEEK,\n // We track and consider the buffering state only when it comes from the State.PLAYING\n Event.START_BUFFERING,\n Event.END_BUFFERING,\n // this will fire whenever the currentTime attribute changes\n Event.TIMECHANGED,\n ),\n {name: Event.SEEKED, from: State.SEEKING_IN_PAUSE, to: State.PAUSE},\n\n {name: Event.SEEK, from: State.PLAYING, to: State.SEEKING},\n ...whileIn(State.SEEKING).passOver(\n Event.SEEK,\n // We track and consider the buffering state only when it comes from the State.PLAYING\n Event.START_BUFFERING,\n Event.END_BUFFERING,\n // this will fire whenever the currentTime attribute changes\n Event.TIMECHANGED,\n ),\n {name: Event.SEEKED, from: State.SEEKING, to: State.PLAYING},\n\n {\n name: Event.MANUAL_SOURCE_CHANGE,\n // We dont track source change during SETUP\n from: getAllStatesBut([State.SETUP], State),\n to: State.SOURCE_CHANGING,\n },\n ...whileIn(State.SOURCE_CHANGING).passOver(Event.START_BUFFERING, Event.TIMECHANGED),\n // Once the source is loaded, we are READY to receive play interaction\n {name: Event.SOURCE_LOADED, from: State.SOURCE_CHANGING, to: State.READY},\n\n // Because of this state transition, we are able to male \"a cut\" in the current PLAYING / PAUSE state\n // and send \"playing\" / \"pause\" sample with the current custom data values. The new changed custom data values\n // will be set on upcoming samples after we transition back from the CUSTOMDATACHANGE state.\n // For any other states, we don't care, because InternalAdapter is not emitting the event.\n {name: Event.CUSTOM_DATA_CHANGE, from: [State.PLAYING, State.PAUSE], to: State.CUSTOMDATACHANGE},\n {name: Event.PLAYING, from: State.CUSTOMDATACHANGE, to: State.PLAYING},\n {name: Event.PAUSE, from: State.CUSTOMDATACHANGE, to: State.PAUSE},\n ],\n\n callbacks: {\n [`onleave${State.PLAYING}`]: () => {\n this.playingHeartbeatService.stopHeartbeat();\n },\n\n [`onleave${State.STARTUP}`]: () => {\n this.clearVideoStartTimeout();\n },\n\n onleavestate: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n logStateMachineTransition('LEAVE', event, from, to);\n\n // Skip this JSM callback for JSM initial event\n // This event is fired when the state machine is constructed,\n // to transition us from 'none' to custom initial 'SETUP' state\n if (event === JSM_INITIAL_EVENT) {\n return;\n }\n\n if (from === State.BUFFERING) {\n this.resetBufferingHelpers();\n }\n\n // Skip this JSM callback when an JSM event without a timestamp is called,\n // because it would cause NPE in analytics code (state duration calculation etc.).\n // This probably has happened because the state machine was not used correctly,\n // aka. JSM event was not called via `callEvent` method as it should be!\n if (!eventTimestamp) {\n return;\n }\n\n // Skip \"default onleavestate analytics state machine callback\" when leaving ERROR state,\n // because we call \"error\" state machine callback asap in \"onafterEVENT\" handler\n if (from === State.ERROR) {\n return;\n }\n\n // Skip, because we should ignore and do not track the \"seeking\" while the playback is paused\n // This means we should not use any callbacks, nor set any state properties\n if (\n (from === State.PAUSE && to === State.SEEKING_IN_PAUSE) ||\n (from === State.SEEKING_IN_PAUSE && to === State.PAUSE)\n ) {\n return;\n }\n\n // When leaving a state, before calling any callback (sending sample), we should set a correct sample `videoTimeEnd`\n if (eventData) {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n }\n\n const stateDuration = eventTimestamp - this.onEnterStateTimestamp;\n const lowerCaseFrom = String(from).toLowerCase();\n\n // Calling a custom callback when leaving STARTUP into STARTUP_FAILURE\n if (from === State.STARTUP && to === State.VIDEOSTART_FAILED) {\n this.stateMachineCallbacks.videoStartFailed(stateDuration, createVideoStartFailedReason(event));\n return;\n }\n\n // Calling a custom callback when leaving SEEKING (started in the PAUSE/PLAY state)\n if (from === State.SEEKING) {\n this.stateMachineCallbacks.seeking(stateDuration);\n return;\n }\n\n // Calling a custom callback handling UNLOAD event\n if (event === Event.UNLOAD) {\n this.stateMachineCallbacks.unload(stateDuration, lowerCaseFrom);\n return;\n }\n\n // Default \"onleavestate\" state machine callback\n //\n // Every time, when we leave a state, we should try to call \"state\" callback,\n // to be able to make \"a cut\" and send analytics sample (if necessary)\n const defaultStateMachineCallbackFn = this.stateMachineCallbacks[lowerCaseFrom];\n if (isFunction(defaultStateMachineCallbackFn)) {\n // a try-catch block to add more resilience against callback errors\n try {\n defaultStateMachineCallbackFn(stateDuration, lowerCaseFrom, eventData);\n } catch (e) {\n logger.error('Exception occurred in State Machine callback ' + lowerCaseFrom, eventData, e);\n }\n } else {\n // if callback is not defined, log a warning to indicate to the developer that\n // - a new callback function needs to be implemented to relay on this default state machine callback\n // - or if no callback is needed, we should\n // - early return from this JSM callback\n // - or add this state to the ignored list\n logMissingCallbackWarning(from, [State.READY, State.SOURCE_CHANGING]);\n }\n },\n\n [`onenter${State.PLAYING}`]: () => {\n this.playingHeartbeatService.startHeartbeat();\n },\n\n [`onenter${State.SOURCE_CHANGING}`]: (_event, _from, _to, _eventTimestamp, eventData) => {\n this.stateMachineCallbacks.manualSourceChange(eventData);\n },\n\n [`onenter${State.STARTUP}`]: () => {\n this.setVideoStartTimeout();\n },\n\n onenterstate: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n logStateMachineTransition('ENTER', event, from, to);\n\n // Skip, because we should ignore and do not track the \"seeking\" while the playback is paused\n // This means we should not use any callbacks, nor set any state properties\n if (\n (from === State.PAUSE && to === State.SEEKING_IN_PAUSE) ||\n (from === State.SEEKING_IN_PAUSE && to === State.PAUSE)\n ) {\n return;\n }\n\n this.onEnterStateTimestamp = eventTimestamp ?? Date.now();\n // if customer set custom \"start time\" timestamp in AnalyticsStateMachineOptions of adapter constructor,\n // use it and override `onEnterStateTimestamp` during JSM initialization (transition to initial SETUP state)\n if (isNumber(opts.starttime) && event === JSM_INITIAL_EVENT) {\n this.onEnterStateTimestamp = opts.starttime;\n }\n\n if (eventData) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n }\n\n if (to === State.BUFFERING) {\n this.startBufferingHeartbeatInterval();\n }\n },\n\n [`onafter${Event.ERROR}`]: (_event, _from, _to, _eventTimestamp, eventData) => {\n this.stateMachineCallbacks.error(eventData);\n },\n },\n });\n }\n}\n","import * as StateMachine from 'javascript-state-machine';\n\nimport type {HeartbeatService} from '../core/HeartbeatService';\nimport {Event, JSM_INITIAL_EVENT} from '../enums/Event';\nimport {createVideoStartFailedReason} from '../enums/VideoStartFailedReason';\nimport type {AnalyticsStateMachineOptions} from '../types/AnalyticsStateMachineOptions';\nimport type {StateMachineCallbacks} from '../types/StateMachineCallbacks';\nimport {logger} from '../utils/Logger';\nimport {isNumber} from '../utils/numberUtils';\nimport {isFunction} from '../utils/Utils';\n\nimport {AnalyticsStateMachine} from './AnalyticsStateMachine';\nimport {\n customStateMachineErrorCallback,\n logMissingCallbackWarning,\n logStateMachineTransition,\n on,\n whileIn,\n} from './stateMachineUtils';\n\nenum State {\n AD = 'AD',\n AUDIOTRACK_CHANGING = 'AUDIOTRACK_CHANGING',\n BUFFERING = 'BUFFERING',\n CASTING = 'CASTING',\n /**\n * This state was created only to be able to \"cut\" the {@link State.PLAYING} and {@link State.PAUSE}\n * and send playing/pause sample with current custom data, while calling {@link AdapterAPI.setCustomData} function\n * and setting the new custom data values.\n *\n * @remarks\n *\n * Our implementation relays on a specific state name \"CUSTOMDATACHANGE\" because it should call the\n * default \"onleavestate\" state machine callback {@link stateMachineCallbacks.customdatachange}.\n */\n CUSTOMDATACHANGE = 'CUSTOMDATACHANGE',\n END = 'END',\n ERROR = 'ERROR',\n MUTING_PAUSE = 'MUTING_PAUSE',\n MUTING_PLAY = 'MUTING_PLAY',\n MUTING_READY = 'MUTING_READY',\n PAUSE = 'PAUSE',\n PAUSED_SEEKING = 'PAUSED_SEEKING',\n PLAYING = 'PLAYING',\n QUALITY_CHANGE = 'QUALITY_CHANGE',\n READY = 'READY',\n SETUP = 'SETUP',\n SETUP_SOURCE_CHANGE = 'SETUP_SOURCE_CHANGE',\n SOURCE_CHANGING = 'SOURCE_CHANGING',\n STARTUP = 'STARTUP',\n SUBTITLE_CHANGING = 'SUBTITLE_CHANGING',\n VIDEOSTART_FAILED = 'VIDEOSTART_FAILED',\n}\n\nexport class HTML5AnalyticsStateMachine extends AnalyticsStateMachine {\n constructor(\n stateMachineCallbacks: StateMachineCallbacks,\n playingHeartbeatService: HeartbeatService,\n opts: AnalyticsStateMachineOptions,\n ) {\n super(stateMachineCallbacks, playingHeartbeatService, opts);\n\n this.createStateMachine(opts);\n }\n\n getAllStates() {\n return [...Object.keys(State).map((key) => State[key])];\n }\n\n getAllStatesBut(states: string[]) {\n return this.getAllStates().filter((i) => states.indexOf(i) < 0);\n }\n\n override createStateMachine(opts: AnalyticsStateMachineOptions) {\n return StateMachine.create({\n // custom initial state and custom JSM initial event name\n // initial event is used by JSM for the initial state transition 'none' -> 'SETUP'\n initial: {state: State.SETUP, event: JSM_INITIAL_EVENT},\n error: customStateMachineErrorCallback,\n events: [\n {\n name: Event.SOURCE_LOADED,\n from: [State.SETUP, State.SETUP_SOURCE_CHANGE, State.SOURCE_CHANGING],\n to: State.READY,\n },\n\n // just passing since it's pushed in a live stream\n ...whileIn(State.READY).passOver(Event.SEEK, Event.SEEKED),\n\n on(Event.TIMECHANGED).stayIn(State.SETUP),\n on(Event.SOURCE_LOADED).stayIn(State.READY),\n\n {name: Event.PLAY, from: State.READY, to: State.STARTUP},\n // play attempt during sourceChanging\n {name: Event.PLAY, from: State.SOURCE_CHANGING, to: State.STARTUP},\n\n {name: Event.ERROR, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.UNLOAD, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.VIDEOSTART_TIMEOUT, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n\n ...whileIn(State.STARTUP).passOver(\n Event.SOURCE_LOADED, // when we have autoplay we will receive SOURCE_LOADED after we enter the STARTUP state\n Event.START_BUFFERING,\n Event.END_BUFFERING,\n Event.VIDEO_CHANGE,\n Event.AUDIO_CHANGE,\n Event.SEEK, // just passing since it's pushed in a live stream\n Event.SEEKED, // just passing since it's pushed in a live stream\n ),\n\n {name: Event.TIMECHANGED, from: State.READY, to: State.STARTUP},\n {name: Event.TIMECHANGED, from: State.STARTUP, to: State.PLAYING},\n ...whileIn(State.PLAYING).passOver(Event.TIMECHANGED),\n\n on(Event.SEEKED).stayIn(State.PAUSE),\n\n on(Event.END_BUFFERING).stayIn(State.PLAYING),\n {name: Event.START_BUFFERING, from: State.PLAYING, to: State.BUFFERING},\n on(Event.START_BUFFERING).stayIn(State.BUFFERING),\n\n {name: Event.PLAY, from: State.BUFFERING, to: State.PLAYING},\n {name: Event.TIMECHANGED, from: State.BUFFERING, to: State.PLAYING},\n\n {name: Event.PAUSE, from: State.PLAYING, to: State.PAUSE},\n {name: Event.PAUSE, from: State.BUFFERING, to: State.PAUSE},\n\n {name: Event.PLAY, from: State.PAUSE, to: State.PLAYING},\n {name: Event.TIMECHANGED, from: State.PAUSE, to: State.PLAYING},\n\n {name: Event.VIDEO_CHANGE, from: State.PLAYING, to: State.QUALITY_CHANGE},\n {name: Event.AUDIO_CHANGE, from: State.PLAYING, to: State.QUALITY_CHANGE},\n {name: Event.FINISH_QUALITY_CHANGE, from: State.QUALITY_CHANGE, to: State.PLAYING},\n\n {name: Event.SEEK, from: State.PAUSE, to: State.PAUSED_SEEKING},\n ...whileIn(State.PAUSED_SEEKING).passOver(Event.PLAY, Event.SEEK, Event.START_BUFFERING, Event.END_BUFFERING),\n\n {name: Event.SEEKED, from: State.PAUSED_SEEKING, to: State.PAUSE},\n {name: Event.TIMECHANGED, from: State.PAUSED_SEEKING, to: State.PLAYING},\n {name: Event.PAUSE, from: State.PAUSED_SEEKING, to: State.PAUSE},\n\n {name: Event.END, from: State.PAUSED_SEEKING, to: State.END},\n {name: Event.END, from: State.PLAYING, to: State.END},\n {name: Event.END, from: State.PAUSE, to: State.END},\n ...whileIn(State.END).passOver(\n Event.PAUSE,\n Event.SEEK,\n Event.SEEKED,\n Event.TIMECHANGED,\n Event.END_BUFFERING,\n Event.START_BUFFERING,\n Event.END,\n ),\n\n // just passing since it's pushed in a live stream\n ...whileIn(State.PLAYING).passOver(Event.SEEK, Event.SEEKED),\n\n {name: Event.PLAY, from: State.END, to: State.PLAYING},\n\n {name: Event.ERROR, from: this.getAllStatesBut([State.STARTUP]), to: State.ERROR},\n {name: Event.PAUSE, from: State.ERROR, to: State.ERROR},\n\n {name: Event.UNLOAD, from: this.getAllStatesBut([State.STARTUP]), to: State.END},\n\n {name: Event.SUBTITLE_CHANGE, from: State.PLAYING, to: State.SUBTITLE_CHANGING},\n\n on(Event.SUBTITLE_CHANGE).stayIn(State.PAUSE),\n on(Event.SUBTITLE_CHANGE).stayIn(State.READY),\n on(Event.SUBTITLE_CHANGE).stayIn(State.STARTUP),\n on(Event.SUBTITLE_CHANGE).stayIn(State.BUFFERING),\n on(Event.SUBTITLE_CHANGE).stayIn(State.SUBTITLE_CHANGING),\n\n {name: Event.TIMECHANGED, from: State.SUBTITLE_CHANGING, to: State.PLAYING},\n\n {name: Event.AUDIOTRACK_CHANGED, from: State.PLAYING, to: State.AUDIOTRACK_CHANGING},\n\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.PAUSE),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.READY),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.STARTUP),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.BUFFERING),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.AUDIOTRACK_CHANGING),\n {name: Event.TIMECHANGED, from: State.AUDIOTRACK_CHANGING, to: State.PLAYING},\n\n {name: Event.START_AD, from: State.PLAYING, to: State.AD},\n {name: Event.END_AD, from: State.AD, to: State.PLAYING},\n\n {name: Event.MUTE, from: State.READY, to: State.MUTING_READY},\n {name: Event.UN_MUTE, from: State.READY, to: State.MUTING_READY},\n {name: 'FINISH_MUTING', from: State.MUTING_READY, to: State.READY},\n\n {name: Event.MUTE, from: State.PLAYING, to: State.MUTING_PLAY},\n {name: Event.UN_MUTE, from: State.PLAYING, to: State.MUTING_PLAY},\n {name: 'FINISH_MUTING', from: State.MUTING_PLAY, to: State.PLAYING},\n\n {name: Event.MUTE, from: State.PAUSE, to: State.MUTING_PAUSE},\n {name: Event.UN_MUTE, from: State.PAUSE, to: State.MUTING_PAUSE},\n {name: 'FINISH_MUTING', from: State.MUTING_PAUSE, to: State.PAUSE},\n\n {name: Event.START_CAST, from: [State.READY, State.PAUSE], to: State.CASTING},\n ...whileIn(State.CASTING).passOver(\n Event.PAUSE,\n Event.PLAY,\n Event.TIMECHANGED,\n Event.MUTE,\n Event.SEEK,\n Event.SEEKED,\n ),\n\n {name: Event.END_CAST, from: State.CASTING, to: State.READY},\n\n {name: Event.MANUAL_SOURCE_CHANGE, from: State.SETUP, to: State.SETUP_SOURCE_CHANGE},\n on(Event.MANUAL_SOURCE_CHANGE).stayIn(State.SETUP_SOURCE_CHANGE),\n {\n name: Event.MANUAL_SOURCE_CHANGE,\n from: this.getAllStatesBut([State.SETUP, State.SETUP_SOURCE_CHANGE]),\n to: State.SOURCE_CHANGING,\n },\n {name: Event.SOURCE_UNLOADED, from: this.getAllStates(), to: State.SOURCE_CHANGING},\n\n on(Event.TIMECHANGED).stayIn(State.SOURCE_CHANGING),\n on(Event.PAUSE).stayIn(State.SOURCE_CHANGING),\n\n // Because of this state transition, we are able to male \"a cut\" in the current PLAYING / PAUSE state\n // and send \"playing\" / \"pause\" sample with the current custom data values. The new changed custom data values\n // will be set on upcoming samples after we transition back from the CUSTOMDATACHANGE state.\n // For any other states, we don't care, because InternalAdapter is not emitting the event.\n {name: Event.CUSTOM_DATA_CHANGE, from: [State.PLAYING, State.PAUSE], to: State.CUSTOMDATACHANGE},\n {name: Event.PLAYING, from: State.CUSTOMDATACHANGE, to: State.PLAYING},\n {name: Event.PAUSE, from: State.CUSTOMDATACHANGE, to: State.PAUSE},\n ],\n\n // Keep callbacks sorted by order in which they are called by JSM library (and after order, sorted by name)\n //\n // Do not use convenience, shortened callbacks\n // - instead of `onEVENT` use `onafterEVENT`\n // - instead of `onSTATE` use `onenterSTATE`\n //\n // see: https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#callbacks\n callbacks: {\n [`onleave${State.PLAYING}`]: (_event, _from, _to, _eventTimestamp, _eventData) => {\n this.playingHeartbeatService.stopHeartbeat();\n },\n\n [`onleave${State.STARTUP}`]: (_event, _from, _to, _eventTimestamp, _eventData) => {\n this.clearVideoStartTimeout();\n },\n\n onleavestate: (event, from, to, eventTimestamp, eventData) => {\n logStateMachineTransition('LEAVE', event, from, to);\n\n // Skip this JSM callback for JSM initial event\n // This event is fired when the state machine is constructed,\n // to transition us from 'none' to custom initial 'SETUP' state\n if (event === JSM_INITIAL_EVENT) {\n return;\n }\n\n if (from === State.BUFFERING) {\n this.resetBufferingHelpers();\n }\n\n // Skip this JSM callback when an JSM event without a timestamp is called,\n // because it would cause NPE in analytics code (state duration calculation etc.).\n // This probably has happened because the state machine was not used correctly,\n // aka. JSM event was not called via `callEvent` method as it should be!\n if (!eventTimestamp) {\n return;\n }\n\n // player errors will be sent via eventCallback() -> callEvent() -> onPlayerError() function chain\n // if then sourceChange is called same error will be sent second time\n if (from === State.ERROR && (event === Event.MANUAL_SOURCE_CHANGE || event === Event.SOURCE_UNLOADED)) {\n return;\n }\n\n const stateDuration = eventTimestamp - this.onEnterStateTimestamp;\n\n if (eventData && to !== State.PAUSED_SEEKING) {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n }\n\n const lowerCaseFrom = String(from).toLowerCase();\n if (to === State.VIDEOSTART_FAILED) {\n this.clearVideoStartTimeout();\n this.stateMachineCallbacks.videoStartFailed(stateDuration, createVideoStartFailedReason(event));\n } else if (from === State.PAUSED_SEEKING) {\n this.stateMachineCallbacks.seeking(stateDuration);\n } else if (event === Event.UNLOAD) {\n this.stateMachineCallbacks.unload(stateDuration, lowerCaseFrom);\n } else if (from === State.PAUSE && to !== State.PAUSED_SEEKING) {\n this.stateMachineCallbacks.pause(stateDuration, lowerCaseFrom);\n } else {\n // Default \"onleavestate\" state machine callback\n //\n // Every time, when we leave a state, we should try to call \"state\" callback,\n // to be able to make \"a cut\" and send analytics sample (if necessary)\n const defaultStateMachineCallbackFn = this.stateMachineCallbacks[lowerCaseFrom];\n if (isFunction(defaultStateMachineCallbackFn)) {\n // a try-catch block to add more resilience against callback errors\n try {\n defaultStateMachineCallbackFn(stateDuration, lowerCaseFrom, eventData);\n } catch (e) {\n logger.error('Exception occurred in State Machine callback ' + lowerCaseFrom, eventData, e);\n }\n } else {\n // if callback is not defined, log a warning to indicate to the developer that\n // - a new callback function needs to be implemented to relay on this default state machine callback\n // - or if no callback is needed, we should\n // - early return from this JSM callback\n // - or add this state to the ignored list\n logMissingCallbackWarning(from, [State.READY, State.SOURCE_CHANGING, State.SETUP_SOURCE_CHANGE]);\n }\n }\n\n if (eventData && to !== State.PAUSED_SEEKING) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n }\n\n if (event === Event.MUTE) {\n this.stateMachineCallbacks.mute();\n } else if (event === Event.UN_MUTE) {\n this.stateMachineCallbacks.unMute();\n }\n },\n\n [`onenter${State.PLAYING}`]: (_event, _from, _to, eventTimestamp, _eventData) => {\n this.onEnterStateTimestamp = eventTimestamp;\n this.playingHeartbeatService.startHeartbeat();\n },\n\n [`onenter${State.SOURCE_CHANGING}`]: (event, _from, _to, _eventTimestamp, eventData) => {\n if (event === Event.MANUAL_SOURCE_CHANGE) {\n this.stateMachineCallbacks.manualSourceChange(eventData);\n }\n },\n\n [`onenter${State.STARTUP}`]: (_event, _from, _to, _eventTimestamp, _eventData) => {\n this.setVideoStartTimeout();\n },\n\n [`onenter${State.QUALITY_CHANGE}`]: (_event, _from, _to, eventTimestamp, eventData) => {\n // Quality change should produce a \"signal sample\" and immediately transition us back to PLAYING state\n this.stateMachineCallbacks.qualitychange(eventData);\n this.stateMachine[Event.FINISH_QUALITY_CHANGE](eventTimestamp);\n },\n\n onenterstate: (event, from, to, eventTimestamp: number, eventData) => {\n logStateMachineTransition('ENTER', event, from, to);\n\n this.onEnterStateTimestamp = eventTimestamp ?? Date.now();\n // if customer set custom \"start time\" timestamp in AnalyticsStateMachineOptions of adapter constructor,\n // use it and override `onEnterStateTimestamp` during JSM initialization (transition to initial SETUP state)\n if (isNumber(opts.starttime) && event === JSM_INITIAL_EVENT) {\n this.onEnterStateTimestamp = opts.starttime;\n }\n\n if (eventData && to !== State.PAUSED_SEEKING) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n }\n\n if (event === Event.START_CAST && to === State.CASTING) {\n this.stateMachineCallbacks.startCasting(eventTimestamp, eventData);\n }\n\n if (to === State.BUFFERING) {\n this.startBufferingHeartbeatInterval();\n }\n },\n\n [`onafter${Event.ERROR}`]: (_event, _from, _to, _eventTimestamp, eventData) => {\n this.stateMachineCallbacks.error(eventData);\n },\n\n onafterevent: (_event, _from, to, eventTimestamp, _eventData) => {\n if (to === State.MUTING_READY || to === State.MUTING_PLAY || to === State.MUTING_PAUSE) {\n this.stateMachine.FINISH_MUTING(eventTimestamp);\n }\n },\n },\n });\n }\n}\n","import {create, StateMachine} from 'javascript-state-machine';\n\nimport type {HeartbeatService} from '../core/HeartbeatService';\nimport {Event, JSM_INITIAL_EVENT} from '../enums/Event';\nimport {createVideoStartFailedReason, VideoStartFailedReason} from '../enums/VideoStartFailedReason';\nimport type {AnalyticsStateMachineOptions} from '../types/AnalyticsStateMachineOptions';\nimport type {AnalyticsEventBase, CustomDataValuesEvent, ErrorEvent, QualityChangeEvent} from '../types/EventData';\nimport type {StateMachineCallbacks} from '../types/StateMachineCallbacks';\nimport {isNumber} from '../utils/numberUtils';\n\nimport {AnalyticsStateMachine} from './AnalyticsStateMachine';\nimport {customStateMachineErrorCallback, getAllStatesBut, logStateMachineTransition} from './stateMachineUtils';\n\nexport enum State {\n // handles ads in the middle of playback (midroll & postroll ads)\n AD_PLAYBACK = 'AD_PLAYBACK',\n // handles ad that occur during startup aka preroll ads\n AD_PLAYBACK_IN_STARTUP = 'AD_PLAYBACK_IN_STARTUP',\n\n /**\n * We track and consider the buffering state only when it comes from the {@link State.PLAYING},\n * aka. when the video was playing and stopped because it started to buffer.\n */\n BUFFERING = 'BUFFERING',\n /**\n * This state was created only to be able to \"cut\" the {@link State.PLAYING} and {@link State.PAUSE}\n * and send playing/pause sample with current custom data, while calling {@link AdapterAPI.setCustomData} function\n * and setting the new custom data values.\n *\n * @remarks\n *\n * Our implementation relays on a specific state name \"CUSTOMDATACHANGE\" because it should call the\n * default \"onleavestate\" state machine callback {@link stateMachineCallbacks.customdatachange}.\n */\n CUSTOMDATACHANGE = 'CUSTOMDATACHANGE',\n ERROR = 'ERROR',\n PAUSE = 'PAUSE',\n PLAYING = 'PLAYING',\n QUALITY_CHANGE = 'QUALITY_CHANGE',\n READY = 'READY',\n /**\n * We track and consider the \"seeking\" state only when it comes from the {@link State.PLAYING},\n * aka. when the video has already started to play and is already playing.\n */\n SEEKING = 'SEEKING',\n SETUP = 'SETUP',\n SOURCE_CHANGING = 'SOURCE_CHANGING',\n STARTUP = 'STARTUP',\n UNLOADED = 'UNLOADED',\n VIDEOSTART_FAILED = 'VIDEOSTART_FAILED',\n}\n\nexport class THEOplayerAnalyticsStateMachine extends AnalyticsStateMachine {\n constructor(\n stateMachineCallbacks: StateMachineCallbacks,\n playingHeartbeatService: HeartbeatService,\n opts: AnalyticsStateMachineOptions,\n ) {\n super(stateMachineCallbacks, playingHeartbeatService, opts);\n }\n\n override createStateMachine(opts: AnalyticsStateMachineOptions): StateMachine {\n return create({\n // custom initial state and custom JSM initial event name\n // initial event is used by JSM for the initial state transition 'none' -> 'SETUP'\n initial: {state: State.SETUP, event: JSM_INITIAL_EVENT},\n error: customStateMachineErrorCallback,\n events: [\n {name: Event.READY, from: State.SETUP, to: State.READY},\n\n {name: Event.PLAY, from: State.READY, to: State.STARTUP},\n // Fallback transition: to handle a missing \"play\" event and a missing transition from READY to STARTUP\n //\n // Case: MISSING \"PLAY\" EVENT FROM A PLAY ATTEMPT DURING SLOW SOURCE CHANGE.\n // Problem:\n // When the source change was triggered, the player started to load the video (probably on slow network),\n // and we were in the SOURCE_CHANGING state. But when `player.play()` was called during that state, the player\n // did not fire \"play\" (player bug?), so this play attempt was not recognized by us, and we have not\n // transitioned to the STARTUP state. Once the source was loaded, we transitioned to the READY state, but\n // the player remembered the play attempt from before, so the video actually started to play. But because\n // of the missing transition to STARTUP, we got stuck in the READY state.\n // Solution:\n // If we are still in the READY state and there was a \"playing\" event, it means that the play attempt was not\n // recognized by us, but the video actually started to play, so we will immediately transition to the PLAYING\n // state. But before that, we will trigger the \"startup\" sample with a fixed duration of 1ms, when leaving\n // the READY state.\n // Found on:\n // theoplayer@10.10.0\n {name: Event.PLAYING, from: State.READY, to: State.PLAYING},\n\n // Case: PRECEDING \"PAUSE\" EVENT ON STARTUP ERRORS\n // Problem:\n // In case of a player \"error\" event during the STARTUP state, we see that the player fires a \"pause\" event\n // automatically before the actual \"error\" event. This messes with our state machine, to not be able to track\n // the error as a startup failure, because such the preceding PAUSE event would first get us into the PAUSE\n // state, where the following \"error\" event would be considered as a normal error during the PAUSE state.\n // Solution:\n // To handle this case, we delay the PAUSE event execution to see if an ERROR event is fired right after, and\n // if so, we give the ERROR event the priority to be executed first, and we cancel the delayed PAUSE event,\n // so that the state machine can correctly track the startup failure. If there is no ERROR event fired right\n // after, we execute the delayed PAUSE event as if nothing happened.\n {name: Event.ERROR, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.MANUAL_SOURCE_CHANGE, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.VIDEOSTART_TIMEOUT, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n\n {name: Event.READY, from: State.VIDEOSTART_FAILED, to: State.READY},\n\n // cover the case when a user double-click the play button.\n // aka. when after the first play click, a video starts to load, and we are in the startup state,\n // but during the loading a user clicks the play button again to pause the video\n {name: Event.PAUSE, from: State.STARTUP, to: State.READY},\n\n // We can't use a player 'timeupdate' event, because it is fired asap after the play button is hit\n // with currentTime: 0, just to set playback state to beginning / to initial state, and THEOplayer is\n // still loading the asset (a specific THEOplayer behavior)\n {name: Event.PLAYING, from: State.STARTUP, to: State.PLAYING},\n\n // Case: PREROLL AD\n // Problem:\n // In the case of preroll Ads, they always start when we have already entered the STARTUP state.\n // Solution:\n // We had to create a specific AD_PLAYBACK_IN_STARTUP state:\n // - to not affect STARTUP state and the startup time calculation with the preroll ad time.\n // - to be able to send an \"ad\" sample for preroll ads in onleaveSTATE callback.\n // - to be able to return us back to STARTUP state after the preroll ad is finished, to continue the normal startup.\n {name: Event.START_AD, from: State.STARTUP, to: State.AD_PLAYBACK_IN_STARTUP},\n {name: Event.END_AD, from: State.AD_PLAYBACK_IN_STARTUP, to: State.STARTUP},\n\n // Case: MIDROLL & POSTROLL ADS DETERMINATION\n // Problem:\n // Player event \"adbreakbegin\" for both midroll and postroll Ad, can theoretically happen at any of our states\n // (PLAYING, SEEKING, maybe also BUFFERING etc.), and it is hard to determine to which state we should return\n // back after the ad is finished. An additional problem to that is that we can't clearly detect a postroll ad,\n // because the THEOplayer will start it before emitting a player \"end\" event, so in the same way as a midroll ad.\n // Solution:\n // - We will transition to the AD_PLAYBACK state on \"adbreakbegin\" no matter in which state it happens, and when\n // it ends, we will return to the PLAYING state. Why PLAYING? Because we could see THEOplayer behavior that\n // after midroll ad (for postroll we did special handling), the video continues to play automatically no\n // matter from what state Ads has started. For example, the use case, when we seeked, or paused and seeked\n // the video over the Ad position.\n // - For the postroll ads we have a special handling! We will rely on the fact that after the postroll ad has\n // finished, THEOplayer will always emit a player \"end\" event (because playback is/was at the end of the video).\n // So what we need to do is to always delay END_AD event execution! If we see that an END event is fired\n // right after, it means that the ad that just finished was a postroll ad, so we will cancel the END_AD event\n // and transition directly to the PAUSE state. If no END event follows, it means that it was a midroll ad,\n // so we will execute the END_AD event as normal and transition back to PLAYING state.\n // Without this, we would be tracking postroll ads as normal midroll ones, and we would be returning back to\n // PLAYING state that would be tracked as \"micro-short playing sample\" as the player \"end\" event came soon.\n // Found on:\n // theoplayer@10.12.0\n {name: Event.START_AD, from: getAllStatesBut([State.STARTUP], State), to: State.AD_PLAYBACK},\n {name: Event.END_AD, from: State.AD_PLAYBACK, to: State.PLAYING},\n // to support the case: MIDROLL & POSTROLL ADS DETERMINATION\n {name: Event.END, from: State.AD_PLAYBACK, to: State.PAUSE},\n\n {name: Event.START_BUFFERING, from: State.PLAYING, to: State.BUFFERING},\n {name: Event.PLAYING, from: State.BUFFERING, to: State.PLAYING},\n {name: Event.PAUSE, from: State.BUFFERING, to: State.PAUSE},\n\n {name: Event.PAUSE, from: State.PLAYING, to: State.PAUSE},\n {name: Event.PLAYING, from: State.PAUSE, to: State.PLAYING},\n // PAUSE state should be also interrupted with the \"play\" player event\n // to already start PLAYING state tracking with \"attempt to play\"\n {name: Event.PLAY, from: State.PAUSE, to: State.PLAYING},\n\n // Case: PRECEDING \"PAUSE\" EVENT BEFORE \"SEEK\" WHEN SEEKING VIA UI PROGRESS BAR\n // Problem:\n // When the user seeks via the UI progress bar while the video is playing, THEOplayer fires a \"pause\" event\n // immediately before the \"seeking\" event. This causes our state machine to transition from PLAYING → PAUSE,\n // which sends a spurious \"pause sample\" and loses the seek tracking — the SEEK event is then ignored because\n // the state machine is no longer in the PLAYING state. (Only PLAYING → SEEKING is a valid transition.)\n //\n // That THEOplayer behavior is a feature for UI, not a bug! Response from THEOplayer team: Both default UI\n // (based off video.js 5 UI) and the Web Open Video UI pause when scrubbing. This is done so that if you hover\n // somewhere still while scrubbing without releasing, the player doesn't suddenly start playing again while\n // you're still scrubbing, until the scrubbing action is stopped by releasing the mouse and the playback resumes.\n //\n // Solution:\n // To handle this case, we delay the PAUSE event to see if a SEEK event is fired right after. If a SEEK event\n // arrives while the PAUSE is pending, we cancel the PAUSE and let the SEEK be dispatched normally, so the\n // state machine correctly tracks PLAYING → SEEKING. If no SEEK follows, the PAUSE is dispatched as normal.\n {name: Event.SEEK, from: State.PLAYING, to: State.SEEKING},\n {name: Event.PLAYING, from: State.SEEKING, to: State.PLAYING},\n\n {name: Event.VIDEO_CHANGE, from: State.PLAYING, to: State.QUALITY_CHANGE},\n {name: Event.AUDIO_CHANGE, from: State.PLAYING, to: State.QUALITY_CHANGE},\n {name: Event.FINISH_QUALITY_CHANGE, from: State.QUALITY_CHANGE, to: State.PLAYING},\n\n {\n name: Event.MANUAL_SOURCE_CHANGE,\n from: getAllStatesBut([State.STARTUP], State),\n to: State.SOURCE_CHANGING,\n },\n {name: Event.READY, from: State.SOURCE_CHANGING, to: State.READY},\n // play attempt during sourceChanging\n {name: Event.PLAY, from: State.SOURCE_CHANGING, to: State.STARTUP},\n\n // Because of this state transition, we are able to make \"a cut\" in the current PLAYING / PAUSE state\n // and send \"playing\" / \"pause\" sample with the current custom data values. The new changed custom data values\n // will be set on upcoming samples after we transition back from the CUSTOMDATACHANGE state.\n // For any other states, we don't care, because InternalAdapter is not emitting the event.\n {name: Event.CUSTOM_DATA_CHANGE, from: [State.PLAYING, State.PAUSE], to: State.CUSTOMDATACHANGE},\n {name: Event.PLAYING, from: State.CUSTOMDATACHANGE, to: State.PLAYING},\n {name: Event.PAUSE, from: State.CUSTOMDATACHANGE, to: State.PAUSE},\n\n {name: Event.ERROR, from: getAllStatesBut([State.STARTUP, State.VIDEOSTART_FAILED], State), to: State.ERROR},\n\n // Special case to handle unload from any state\n // Transition is canceled in 'onbefore' callback and handled there.\n {name: Event.UNLOAD, from: '*', to: State.UNLOADED},\n ],\n\n // Keep callbacks sorted by order in which they are called by JSM library (and after order, sorted by name)\n //\n // Do not use convenience, shortened callbacks\n // - instead of `onEVENT` use `onafterEVENT`\n // - instead of `onSTATE` use `onenterSTATE`\n //\n // see: https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#callbacks\n callbacks: {\n [`onbefore${Event.UNLOAD}`]: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n const duration = eventTimestamp - this.onEnterStateTimestamp;\n\n if (from === State.STARTUP) {\n this.stateMachineCallbacks.videoStartFailed(duration, VideoStartFailedReason.PAGE_CLOSED);\n } else {\n this.stateMachineCallbacks.unload(duration, String(from).toLowerCase());\n }\n\n // Return false to cancel the event (and state transition) to avoid other 'onleaveXXX' callbacks calls.\n // We have to handle these special cases\n // - when the page is unloaded, the browser can't make a standard http requests (we need sendBeacon)\n // - when the player is destroyed, we can't access it to fill all sample properties\n return false;\n },\n\n [`onleave${State.AD_PLAYBACK_IN_STARTUP}`]: (\n event,\n from,\n to,\n eventTimestamp: number,\n eventData: AnalyticsEventBase,\n ) => {\n // To support the transition for the case: PREROLL AD\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n const duration = eventTimestamp - this.onEnterStateTimestamp;\n this.stateMachineCallbacks.ad(duration, 'ad');\n },\n\n [`onleave${State.AD_PLAYBACK}`]: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n const duration = eventTimestamp - this.onEnterStateTimestamp;\n this.stateMachineCallbacks.ad(duration, 'ad');\n },\n\n [`onleave${State.CUSTOMDATACHANGE}`]: (\n _event,\n _from,\n _to,\n _eventTimestamp: number,\n eventData: CustomDataValuesEvent,\n ) => {\n this.stateMachineCallbacks.customdatachange(undefined, undefined, eventData);\n },\n\n [`onleave${State.PAUSE}`]: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n const duration = eventTimestamp - this.onEnterStateTimestamp;\n this.stateMachineCallbacks.pause(duration, 'pause');\n },\n\n [`onleave${State.PLAYING}`]: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n this.playingHeartbeatService.stopHeartbeat();\n\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n const duration = eventTimestamp - this.onEnterStateTimestamp;\n this.stateMachineCallbacks.playing(duration, 'playing');\n },\n\n [`onleave${State.BUFFERING}`]: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n this.resetBufferingHelpers();\n\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n const duration = eventTimestamp - this.onEnterStateTimestamp;\n this.stateMachineCallbacks.buffering(duration, 'buffering');\n },\n\n [`onleave${State.READY}`]: (event, from, to, _eventTimestamp: number, eventData: AnalyticsEventBase) => {\n // To support the fallback transition for the case: MISSING \"PLAY\" EVENT FROM A PLAY ATTEMPT DURING SLOW SOURCE CHANGE.\n if (event === Event.PLAYING && to === State.PLAYING) {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n this.stateMachineCallbacks.startup(1, 'startup');\n return;\n }\n },\n\n [`onleave${State.SEEKING}`]: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n const duration = eventTimestamp - this.onEnterStateTimestamp;\n this.stateMachineCallbacks.seeking(duration);\n },\n\n [`onleave${State.SETUP}`]: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n // Setting player setup duration to fixed value of 1ms.\n // We can't get a correct setup duration from player, because it does not have an \"onInitialized\" event,\n // and we can't relay on the video 'loadedmetadata' event, because it is not fired in all cases, like when\n // player is initialized without source preloading (THEOplayer default behavior).\n this.stateMachineCallbacks.setup(1, 'setup');\n },\n\n [`onleave${State.STARTUP}`]: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n this.clearVideoStartTimeout();\n\n // if we are transitioning from STARTUP to READY state, it means that playback was not started (such as when\n // a user clicked pause during video loading), so we do not send a startup sample in that case\n if (to === State.READY) {\n return;\n }\n\n // To support the case: PREROLL AD\n // if we are transitioning from STARTUP to AD_PLAYBACK_IN_STARTUP state, it means that preroll ad has started,\n // so we do not want to send a startup sample in that case\n if (to === State.AD_PLAYBACK_IN_STARTUP) {\n return;\n }\n\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n const duration = eventTimestamp - this.onEnterStateTimestamp;\n if (to === State.VIDEOSTART_FAILED) {\n this.stateMachineCallbacks.videoStartFailed(duration, createVideoStartFailedReason(event));\n return;\n }\n\n this.stateMachineCallbacks.startup(duration, 'startup');\n },\n\n onleavestate: (event, from, to) => {\n logStateMachineTransition('LEAVE', event, from, to);\n },\n\n [`onenter${State.PLAYING}`]: () => {\n this.playingHeartbeatService.startHeartbeat();\n },\n\n [`onenter${State.BUFFERING}`]: () => {\n this.startBufferingHeartbeatInterval();\n },\n\n [`onenter${State.STARTUP}`]: () => {\n this.setVideoStartTimeout();\n },\n\n [`onenter${State.QUALITY_CHANGE}`]: (_event, _from, _to, eventTimestamp, eventData: QualityChangeEvent) => {\n // Quality change should produce a \"signal sample\" and immediately transition us back to PLAYING state\n this.stateMachineCallbacks.qualitychange(eventData);\n this.stateMachine[Event.FINISH_QUALITY_CHANGE](eventTimestamp);\n },\n\n onenterstate: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n logStateMachineTransition('ENTER', event, from, to);\n\n this.onEnterStateTimestamp = eventTimestamp ?? Date.now();\n // if customer set custom \"start time\" timestamp in AnalyticsStateMachineOptions of adapter constructor,\n // use it and override `onEnterStateTimestamp` during JSM initialization (transition to initial SETUP state)\n if (isNumber(opts.starttime) && event === JSM_INITIAL_EVENT) {\n this.onEnterStateTimestamp = opts.starttime;\n }\n\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n },\n\n [`onafter${Event.MANUAL_SOURCE_CHANGE}`]: (event, _from, _to, _eventTimestamp, eventData) => {\n this.stateMachineCallbacks.manualSourceChange(eventData);\n },\n\n [`onafter${Event.ERROR}`]: (_event, _from, _to, _eventTimestamp, eventData: ErrorEvent) => {\n this.stateMachineCallbacks.error(eventData);\n },\n },\n });\n }\n}\n","import * as StateMachine from 'javascript-state-machine';\n\nimport type {HeartbeatService} from '../core/HeartbeatService';\nimport {Event, JSM_INITIAL_EVENT} from '../enums/Event';\nimport {createVideoStartFailedReason} from '../enums/VideoStartFailedReason';\nimport type {AnalyticsStateMachineOptions} from '../types/AnalyticsStateMachineOptions';\nimport type {StateMachineCallbacks} from '../types/StateMachineCallbacks';\nimport {logger} from '../utils/Logger';\nimport {isNumber} from '../utils/numberUtils';\nimport {isFunction} from '../utils/Utils';\n\nimport {AnalyticsStateMachine} from './AnalyticsStateMachine';\nimport {\n customStateMachineErrorCallback,\n logMissingCallbackWarning,\n logStateMachineTransition,\n on,\n} from './stateMachineUtils';\n\nenum State {\n AD = 'AD',\n AUDIOTRACK_CHANGED_PLAYING = 'AUDIOTRACK_CHANGED_PLAYING',\n AUDIOTRACK_CHANGING = 'AUDIOTRACK_CHANGING',\n BUFFERING = 'BUFFERING',\n CASTING = 'CASTING',\n /**\n * This state was created only to be able to \"cut\" the {@link State.PLAYING} and {@link State.PAUSE}\n * and send playing/pause sample with current custom data, while calling {@link AdapterAPI.setCustomData} function\n * and setting the new custom data values.\n *\n * @remarks\n *\n * Our implementation relays on a specific state name \"CUSTOMDATACHANGE\" because it should call the\n * default \"onleavestate\" state machine callback {@link stateMachineCallbacks.customdatachange}.\n */\n CUSTOMDATACHANGE = 'CUSTOMDATACHANGE',\n END = 'END',\n END_PLAY_SEEKING = 'END_PLAY_SEEKING',\n ERROR = 'ERROR',\n MUTING_PAUSE = 'MUTING_PAUSE',\n MUTING_PLAY = 'MUTING_PLAY',\n MUTING_READY = 'MUTING_READY',\n PAUSE = 'PAUSE',\n PAUSED_SEEKING = 'PAUSED_SEEKING',\n PLAY_SEEKING = 'PLAY_SEEKING',\n PLAYING = 'PLAYING',\n QUALITY_CHANGE = 'QUALITY_CHANGE',\n READY = 'READY',\n SETUP = 'SETUP',\n SOURCE_CHANGING = 'SOURCE_CHANGING',\n STARTUP = 'STARTUP',\n SUBTITLE_CHANGED_PLAYING = 'SUBTITLE_CHANGED_PLAYING',\n SUBTITLE_CHANGING = 'SUBTITLE_CHANGING',\n VIDEOSTART_FAILED = 'VIDEOSTART_FAILED',\n}\n\nexport class VideojsAnalyticsStateMachine extends AnalyticsStateMachine {\n private seekTimestamp: number;\n private seekedTimestamp: number;\n\n constructor(\n stateMachineCallbacks: StateMachineCallbacks,\n playingHeartbeatService: HeartbeatService,\n opts: AnalyticsStateMachineOptions,\n ) {\n super(stateMachineCallbacks, playingHeartbeatService, opts);\n\n this.seekTimestamp = 0;\n this.seekedTimestamp = 0;\n }\n\n getAllStates() {\n return [...Object.keys(State).map((key) => State[key]), 'FINISH_PLAY_SEEKING', 'PLAY_SEEK'];\n }\n\n getAllStatesBut(state: string) {\n return this.getAllStates().filter((i) => i !== state);\n }\n\n override createStateMachine(opts: AnalyticsStateMachineOptions) {\n return StateMachine.create({\n // custom initial state and custom JSM initial event name\n // initial event is used by JSM for the initial state transition 'none' -> 'SETUP'\n initial: {state: State.SETUP, event: JSM_INITIAL_EVENT},\n error: customStateMachineErrorCallback,\n events: [\n {name: Event.SOURCE_LOADED, from: [State.SETUP, State.ERROR, State.SOURCE_CHANGING], to: State.READY},\n on(Event.TIMECHANGED).stayIn(State.SETUP),\n on(Event.SOURCE_LOADED).stayIn(State.READY),\n {name: Event.READY, from: [State.SETUP, State.ERROR], to: State.READY},\n {name: Event.PLAY, from: State.READY, to: State.STARTUP},\n\n {name: Event.ERROR, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.UNLOAD, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n {name: Event.VIDEOSTART_TIMEOUT, from: State.STARTUP, to: State.VIDEOSTART_FAILED},\n\n on(Event.START_BUFFERING).stayIn(State.STARTUP),\n on(Event.END_BUFFERING).stayIn(State.STARTUP),\n {name: Event.TIMECHANGED, from: State.STARTUP, to: State.PLAYING},\n\n on(Event.TIMECHANGED).stayIn(State.PLAYING),\n on(Event.END_BUFFERING).stayIn(State.PLAYING),\n {name: Event.START_BUFFERING, from: State.PLAYING, to: State.BUFFERING},\n on(Event.START_BUFFERING).stayIn(State.BUFFERING),\n {name: Event.TIMECHANGED, from: State.BUFFERING, to: State.PLAYING},\n\n // Ignoring since it's pushed in a live stream\n on(Event.SEEK).stayIn(State.STARTUP),\n {name: Event.SEEK, from: State.PLAYING, to: State.PLAY_SEEKING},\n on(Event.TIMECHANGED).stayIn(State.PLAY_SEEKING),\n on(Event.TIMECHANGED).stayIn(State.PAUSED_SEEKING),\n\n {name: Event.PAUSE, from: State.PLAYING, to: State.PAUSE},\n {name: Event.PAUSE, from: State.BUFFERING, to: State.PAUSE},\n on(Event.TIMECHANGED).stayIn(State.PAUSE),\n {name: Event.PLAY, from: State.PAUSE, to: State.PLAYING},\n\n {name: Event.VIDEO_CHANGE, from: State.PLAYING, to: State.QUALITY_CHANGE},\n {name: Event.AUDIO_CHANGE, from: State.PLAYING, to: State.QUALITY_CHANGE},\n {name: Event.FINISH_QUALITY_CHANGE, from: State.QUALITY_CHANGE, to: State.PLAYING},\n\n {name: Event.SEEK, from: State.PAUSE, to: State.PAUSED_SEEKING},\n on(Event.SEEK).stayIn(State.PAUSED_SEEKING),\n on(Event.START_BUFFERING).stayIn(State.PAUSED_SEEKING),\n on(Event.END_BUFFERING).stayIn(State.PAUSED_SEEKING),\n {name: Event.SEEKED, from: State.PAUSED_SEEKING, to: State.PAUSE},\n {name: Event.PLAY, from: State.PAUSED_SEEKING, to: State.PLAYING},\n {name: Event.PAUSE, from: State.PAUSED_SEEKING, to: State.PAUSE},\n\n {name: 'PLAY_SEEK', from: State.PAUSE, to: State.PLAY_SEEKING},\n {name: 'PLAY_SEEK', from: State.PAUSED_SEEKING, to: State.PLAY_SEEKING},\n on('PLAY_SEEK').stayIn(State.PLAY_SEEKING),\n on(Event.SEEK).stayIn(State.PLAY_SEEKING),\n on(Event.START_BUFFERING).stayIn(State.PLAY_SEEKING),\n on(Event.END_BUFFERING).stayIn(State.PLAY_SEEKING),\n on(Event.SEEKED).stayIn(State.PLAY_SEEKING),\n\n // We are ending the seek\n {name: Event.SEEKED, from: State.PLAY_SEEKING, to: State.END_PLAY_SEEKING},\n\n on(Event.START_BUFFERING).stayIn(State.END_PLAY_SEEKING),\n on(Event.END_BUFFERING).stayIn(State.END_PLAY_SEEKING),\n on(Event.SEEKED).stayIn(State.END_PLAY_SEEKING),\n {name: Event.TIMECHANGED, from: State.END_PLAY_SEEKING, to: State.PLAYING},\n\n {name: Event.END, from: State.PLAY_SEEKING, to: State.END},\n {name: Event.END, from: State.PAUSED_SEEKING, to: State.END},\n {name: Event.END, from: State.PLAYING, to: State.END},\n {name: Event.END, from: State.PAUSE, to: State.END},\n on(Event.SEEK).stayIn(State.END),\n on(Event.SEEKED).stayIn(State.END),\n on(Event.TIMECHANGED).stayIn(State.END),\n on(Event.END_BUFFERING).stayIn(State.END),\n on(Event.START_BUFFERING).stayIn(State.END),\n on(Event.END).stayIn(State.END),\n\n // Ignored - Livestreams do a Seek during startup and SEEKED once playback started\n on(Event.SEEKED).stayIn(State.PLAYING),\n\n {name: Event.PLAY, from: State.END, to: State.PLAYING},\n\n {name: Event.ERROR, from: this.getAllStatesBut(State.STARTUP), to: State.ERROR},\n {name: Event.PAUSE, from: State.ERROR, to: State.ERROR},\n\n {name: Event.SEEK, from: State.END_PLAY_SEEKING, to: State.PLAY_SEEKING},\n {name: 'FINISH_PLAY_SEEKING', from: State.END_PLAY_SEEKING, to: State.PLAYING},\n\n {name: Event.UNLOAD, from: this.getAllStatesBut(State.STARTUP), to: State.END},\n\n {name: Event.START_AD, from: State.PLAYING, to: State.AD},\n {name: Event.END_AD, from: State.AD, to: State.PLAYING},\n\n // in scenario, where VideoJS player is initialized with `muted: true` option, VideoJS player\n // triggers PlayerEvent `volumechange` before PlayerEvent `ready`\n on(Event.MUTE).stayIn(State.SETUP),\n\n {name: Event.MUTE, from: State.READY, to: State.MUTING_READY},\n {name: Event.UN_MUTE, from: State.READY, to: State.MUTING_READY},\n {name: 'FINISH_MUTING', from: State.MUTING_READY, to: State.READY},\n\n {name: Event.MUTE, from: State.PLAYING, to: State.MUTING_PLAY},\n {name: Event.UN_MUTE, from: State.PLAYING, to: State.MUTING_PLAY},\n {name: 'FINISH_MUTING', from: State.MUTING_PLAY, to: State.PLAYING},\n\n {name: Event.MUTE, from: State.PAUSE, to: State.MUTING_PAUSE},\n {name: Event.UN_MUTE, from: State.PAUSE, to: State.MUTING_PAUSE},\n {name: 'FINISH_MUTING', from: State.MUTING_PAUSE, to: State.PAUSE},\n\n {name: Event.START_CAST, from: [State.READY, State.PAUSE], to: State.CASTING},\n on(Event.PAUSE).stayIn(State.CASTING),\n on(Event.PLAY).stayIn(State.CASTING),\n on(Event.TIMECHANGED).stayIn(State.CASTING),\n on(Event.MUTE).stayIn(State.CASTING),\n on(Event.SEEK).stayIn(State.CASTING),\n on(Event.SEEKED).stayIn(State.CASTING),\n {name: Event.END_CAST, from: State.CASTING, to: State.READY},\n\n on(Event.SEEK).stayIn(State.READY),\n on(Event.SEEKED).stayIn(State.READY),\n {name: Event.SEEKED, from: State.STARTUP, to: State.STARTUP},\n\n {name: Event.AUDIOTRACK_CHANGED, from: State.PLAYING, to: State.AUDIOTRACK_CHANGED_PLAYING},\n {name: 'FINISH_AUDIOTRACK_CHANGING', from: State.AUDIOTRACK_CHANGED_PLAYING, to: State.PLAYING},\n // States which should ignore audioTrack changes\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.PAUSE),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.READY),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.BUFFERING),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.END_PLAY_SEEKING),\n {name: Event.AUDIOTRACK_CHANGED, from: State.AUDIOTRACK_CHANGING, to: State.AUDIOTRACK_CHANGING},\n\n {name: Event.SUBTITLE_CHANGE, from: State.PLAYING, to: State.SUBTITLE_CHANGED_PLAYING},\n {name: 'FINISH_SUBTITLE_CHANGING', from: State.SUBTITLE_CHANGED_PLAYING, to: State.PLAYING},\n // States which should ignore subtitle changes\n on(Event.SUBTITLE_CHANGE).stayIn(State.PAUSE),\n on(Event.SUBTITLE_CHANGE).stayIn(State.READY),\n on(Event.SUBTITLE_CHANGE).stayIn(State.BUFFERING),\n on(Event.SUBTITLE_CHANGE).stayIn(State.END_PLAY_SEEKING),\n on(Event.SUBTITLE_CHANGE).stayIn(State.SOURCE_CHANGING),\n on(Event.SUBTITLE_CHANGE).stayIn(State.SUBTITLE_CHANGING),\n\n {name: Event.MANUAL_SOURCE_CHANGE, from: this.getAllStatesBut(State.READY), to: State.SOURCE_CHANGING},\n on(Event.MANUAL_SOURCE_CHANGE).stayIn(State.READY),\n on(Event.MANUAL_SOURCE_CHANGE).stayIn(State.SETUP),\n on(Event.TIMECHANGED).stayIn(State.SOURCE_CHANGING),\n\n // Context: videojs `play()` can be called before source is loaded\n //\n // This means that we should transition to STARTUP state already, even while source is still loading,\n // to be able to measure the startup time correctly. Because once video is loaded, it will start playing\n // and player event 'timeupdate' will be emitted.\n //\n // If we would not do this state transition, player event 'loadedmetadata' (SOURCE_LOADED) would move us\n // to READY state, which would be incorrect, because:\n // - the most important, we would not be able to measure the time from play() to first frame as startup time\n // - we would be stuck in READY state, and not able to move to state PLAYING, on emitted player event\n // 'timeupdate', because such transition doesn't exist in the state machine (STARTUP state is required)\n {name: Event.PLAY, from: State.SOURCE_CHANGING, to: State.STARTUP},\n // Context: videojs `play()` can be called before source is loaded\n //\n // This means that when source is loaded, and `play()` was already called, so we are in STARTUP state and\n // measuring startup time, we should stay in STARTUP state, because player event 'timeupdate' will be emitted,\n // and it will move us to PLAYING state later.\n on(Event.SOURCE_LOADED).stayIn(State.STARTUP),\n\n // Because of this state transition, we are able to male \"a cut\" in the current PLAYING / PAUSE state\n // and send \"playing\" / \"pause\" sample with the current custom data values. The new changed custom data values\n // will be set on upcoming samples after we transition back from the CUSTOMDATACHANGE state.\n // For any other states, we don't care, because InternalAdapter is not emitting the event.\n {name: Event.CUSTOM_DATA_CHANGE, from: [State.PLAYING, State.PAUSE], to: State.CUSTOMDATACHANGE},\n {name: Event.PLAYING, from: State.CUSTOMDATACHANGE, to: State.PLAYING},\n {name: Event.PAUSE, from: State.CUSTOMDATACHANGE, to: State.PAUSE},\n ],\n\n // Keep callbacks sorted by order in which they are called by JSM library (and after order, sorted by name)\n //\n // Do not use convenience, shortened callbacks\n // - instead of `onEVENT` use `onafterEVENT`\n // - instead of `onSTATE` use `onenterSTATE`\n //\n // see: https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#callbacks\n callbacks: {\n [`onleave${State.PLAYING}`]: () => {\n this.playingHeartbeatService.stopHeartbeat();\n },\n\n onleavestate: (event, from, to, eventTimestamp, eventData): any => {\n logStateMachineTransition('LEAVE', event, from, to);\n\n // Skip this JSM callback for JSM initial event\n // This event is fired when the state machine is constructed,\n // to transition us from 'none' to custom initial 'SETUP' state\n if (event === JSM_INITIAL_EVENT) {\n return;\n }\n\n if (from === State.BUFFERING) {\n this.resetBufferingHelpers();\n }\n\n // Skip this JSM callback when an JSM event without a timestamp is called,\n // because it would cause NPE in analytics code (state duration calculation etc.).\n // This probably has happened because the state machine was not used correctly,\n // aka. JSM event was not called via `callEvent` method as it should be!\n if (!eventTimestamp) {\n return;\n }\n\n const stateDuration = eventTimestamp - this.onEnterStateTimestamp;\n\n if (eventData && to !== State.PAUSED_SEEKING && to !== State.END_PLAY_SEEKING) {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n }\n\n if (event === 'PLAY_SEEK' && from === State.PAUSE) {\n return true;\n }\n\n if (from === State.READY && to === State.STARTUP) {\n this.setVideoStartTimeout();\n } else if (from === State.STARTUP && (to === State.PLAYING || to === State.VIDEOSTART_FAILED)) {\n this.clearVideoStartTimeout();\n }\n\n const lowerCaseFrom = String(from).toLowerCase();\n if (to === State.VIDEOSTART_FAILED) {\n this.clearVideoStartTimeout();\n this.stateMachineCallbacks.videoStartFailed(stateDuration, createVideoStartFailedReason(event));\n } else if (from === State.PAUSED_SEEKING) {\n const seekDuration = eventTimestamp - this.seekTimestamp;\n this.stateMachineCallbacks.seeking(seekDuration);\n } else if (from === State.END_PLAY_SEEKING) {\n const seekDuration = this.seekedTimestamp - this.seekTimestamp;\n this.stateMachineCallbacks.seeking(seekDuration);\n } else if (event === Event.UNLOAD) {\n this.stateMachineCallbacks.unload(stateDuration, lowerCaseFrom);\n } else if (from === State.PAUSE && to !== State.PAUSED_SEEKING) {\n this.stateMachineCallbacks.pause(stateDuration, lowerCaseFrom);\n } else {\n // Default \"onleavestate\" state machine callback\n //\n // Every time, when we leave a state, we should try to call \"state\" callback,\n // to be able to make \"a cut\" and send analytics sample (if necessary)\n const defaultStateMachineCallbackFn = this.stateMachineCallbacks[lowerCaseFrom];\n if (isFunction(defaultStateMachineCallbackFn)) {\n // a try-catch block to add more resilience against callback errors\n try {\n defaultStateMachineCallbackFn(stateDuration, lowerCaseFrom, eventData);\n } catch (e) {\n logger.error('Exception occurred in State Machine callback ' + lowerCaseFrom, eventData, e);\n }\n } else {\n // if callback is not defined, log a warning to indicate to the developer that\n // - a new callback function needs to be implemented to relay on this default state machine callback\n // - or if no callback is needed, we should\n // - early return from this JSM callback\n // - or add this state to the ignored list\n logMissingCallbackWarning(from, [\n State.READY,\n State.SOURCE_CHANGING,\n State.MUTING_PAUSE,\n State.MUTING_PLAY,\n State.AUDIOTRACK_CHANGED_PLAYING,\n State.SUBTITLE_CHANGED_PLAYING,\n ]);\n }\n }\n\n if (eventData && to !== State.PAUSED_SEEKING && to !== State.PLAY_SEEKING && to !== State.END_PLAY_SEEKING) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n }\n\n if (event === Event.MUTE) {\n this.stateMachineCallbacks.mute();\n } else if (event === Event.UN_MUTE) {\n this.stateMachineCallbacks.unMute();\n } else if (event === Event.MANUAL_SOURCE_CHANGE) {\n this.stateMachineCallbacks.manualSourceChange(eventData);\n }\n },\n\n [`onenter${State.PLAYING}`]: () => {\n this.playingHeartbeatService.startHeartbeat();\n },\n\n [`onenter${State.QUALITY_CHANGE}`]: (_event, _from, _to, eventTimestamp, eventData) => {\n // Quality change should produce a \"signal sample\" and immediately transition us back to PLAYING state\n this.stateMachineCallbacks.qualitychange(eventData);\n this.stateMachine[Event.FINISH_QUALITY_CHANGE](eventTimestamp);\n },\n\n onenterstate: (event, from, to, eventTimestamp, eventData) => {\n logStateMachineTransition('ENTER', event, from, to);\n\n this.onEnterStateTimestamp = eventTimestamp ?? Date.now();\n // if customer set custom \"start time\" timestamp in AnalyticsStateMachineOptions of adapter constructor,\n // use it and override `onEnterStateTimestamp` during JSM initialization (transition to initial SETUP state)\n if (isNumber(opts.starttime) && event === JSM_INITIAL_EVENT) {\n this.onEnterStateTimestamp = opts.starttime;\n }\n\n if (eventData && to !== State.PAUSED_SEEKING && to !== State.PLAY_SEEKING && to !== State.END_PLAY_SEEKING) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n }\n\n if (event === Event.SEEK) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n }\n\n if (event === Event.SEEKED) {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n }\n\n if (\n event === 'PLAY_SEEK' &&\n to === State.PLAY_SEEKING &&\n to !== State.PLAY_SEEKING &&\n to !== State.END_PLAY_SEEKING\n ) {\n this.seekTimestamp = this.onEnterStateTimestamp;\n }\n\n if (event === Event.START_CAST && to === State.CASTING) {\n this.stateMachineCallbacks.startCasting(eventTimestamp, eventData);\n }\n\n if (to === State.BUFFERING) {\n this.startBufferingHeartbeatInterval();\n }\n },\n\n [`onafter${Event.ERROR}`]: (_event, _from, _to, _eventTimestamp, eventData) => {\n this.stateMachineCallbacks.error(eventData);\n },\n\n [`onafter${Event.SEEK}`]: (_event, _from, _to, eventTimestamp, _eventData) => {\n this.seekTimestamp = eventTimestamp;\n },\n\n [`onafter${Event.SEEKED}`]: (_event, _from, _to, eventTimestamp, _eventData) => {\n this.seekedTimestamp = eventTimestamp;\n },\n\n onafterevent: (_event, _from, to, eventTimestamp, _eventData) => {\n if (to === State.MUTING_READY || to === State.MUTING_PLAY || to === State.MUTING_PAUSE) {\n this.stateMachine.FINISH_MUTING(eventTimestamp);\n }\n if (to === State.AUDIOTRACK_CHANGED_PLAYING) {\n this.stateMachine.FINISH_AUDIOTRACK_CHANGING(eventTimestamp);\n }\n if (to === State.SUBTITLE_CHANGED_PLAYING) {\n this.stateMachine.FINISH_SUBTITLE_CHANGING(eventTimestamp);\n }\n },\n },\n });\n }\n}\n","import * as StateMachine from 'javascript-state-machine';\n\nimport {HeartbeatService} from '../../core/HeartbeatService';\nimport {Event, JSM_INITIAL_EVENT} from '../../enums/Event';\nimport {createVideoStartFailedReason} from '../../enums/VideoStartFailedReason';\nimport type {AnalyticsStateMachineOptions} from '../../types/AnalyticsStateMachineOptions';\nimport {AnalyticsEventBase, ErrorEvent} from '../../types/EventData';\nimport type {StateMachineCallbacks} from '../../types/StateMachineCallbacks';\nimport {EventDebugging} from '../../utils/EventDebugging';\nimport {logger} from '../../utils/Logger';\nimport {isNumber} from '../../utils/numberUtils';\nimport {isFunction, isNotNullish, noOp} from '../../utils/Utils';\nimport {AnalyticsStateMachine} from '../AnalyticsStateMachine';\nimport {\n customStateMachineErrorCallback,\n logMissingCallbackWarning,\n logStateMachineTransition,\n on,\n whileIn,\n} from '../stateMachineUtils';\n\nenum State {\n AD_PAUSE = 'AD_PAUSE',\n AD_PLAYING = 'AD_PLAYING',\n AD_READY = 'AD_READY',\n /** This event is called when an ad is played directly after the player startup phase */\n AD_STARTUP = 'AD_STARTUP',\n AUDIOTRACK_CHANGING = 'AUDIOTRACK_CHANGING',\n BUFFERING = 'BUFFERING',\n CASTING = 'CASTING',\n /**\n * This state was created only to be able to \"cut\" the {@link State.PLAYING} and {@link State.PAUSE}\n * and send playing/pause sample with current custom data, while calling {@link AdapterAPI.setCustomData} function\n * and setting the new custom data values.\n *\n * @remarks\n *\n * Our implementation relays on a specific state name \"CUSTOMDATACHANGE\" because it should call the\n * default \"onleavestate\" state machine callback {@link stateMachineCallbacks.customdatachange}.\n */\n CUSTOMDATACHANGE = 'CUSTOMDATACHANGE',\n END = 'END',\n /** see {@link State.PLAY_SEEKING} */\n END_PLAY_SEEKING = 'END_PLAY_SEEKING',\n ERROR = 'ERROR',\n INITIAL_SOURCE_CHANGE = 'INITIAL_SOURCE_CHANGE',\n MUTING_PAUSE = 'MUTING_PAUSE',\n MUTING_PLAY = 'MUTING_PLAY',\n MUTING_READY = 'MUTING_READY',\n PAUSE = 'PAUSE',\n /**\n * THE Seeking state.\n * Seeking tracking = time spend in PLAY_SEEKING + END_PLAY_SEEKING.\n * - PLAY_SEEKING - THE seeking state for tracking time spend in seeking.\n * - END_PLAY_SEEKING - part of seeking time, where we wait `in between` seeking and continuing with other states.\n * - usually we are in this state when holding the mouse while seeking -> this will produce multiple connected seeks.\n */\n PLAY_SEEKING = 'PLAY_SEEKING',\n PLAYING = 'PLAYING',\n QUALITY_CHANGE = 'QUALITY_CHANGE',\n /**\n * Being in the READY state means that a source was loaded successfully\n */\n READY = 'READY',\n SETUP = 'SETUP',\n SOURCE_CHANGING = 'SOURCE_CHANGING',\n STARTUP = 'STARTUP',\n /**\n * Special state for tracking startup when autoplay is enabled.\n *\n * A dedicated state is required because the normal STARTUP state has custom transitions that would compromise\n * the semantic meaning of the READY state (which should indicate \"source successfully loaded\").\n *\n * Problem: In normal startup, a PAUSE event during startup transitions back to READY.\n * If we reused STARTUP for autoplay, this would break the invariant that READY always means\n * \"source was successfully loaded\" - because autoplay startup can PAUSE before the source is loaded.\n *\n * Solution: STARTUP_AUTOPLAY maintains separate transition logic and tracking of whether\n * the source has been loaded, allowing correct startup time calculation and state semantics.\n */\n STARTUP_AUTOPLAY = 'STARTUP_AUTOPLAY',\n SUBTITLE_CHANGING = 'SUBTITLE_CHANGING',\n VIDEOSTART_FAILED = 'VIDEOSTART_FAILED',\n}\n\n// Custom internal state machine events\nenum CustomEvents {\n PAUSE_AFTER_SOURCE_LOADED = 'PAUSE_AFTER_SOURCE_LOADED',\n PAUSE_BEFORE_SOURCE_LOADED = 'PAUSE_BEFORE_SOURCE_LOADED',\n}\n\nexport class Bitmovin8AnalyticsStateMachine extends AnalyticsStateMachine {\n private debuggingStates: EventDebugging[] = [];\n private enabledDebugging = false;\n\n private seekStartTimestamp: number | undefined;\n /**\n * Used for ads, because when AdFinished event is fired and a call to state machine is made,\n * data from player indicate that video is playing from beginning even if ad is in the middle of video\n */\n private lastTrackedVideoEndObject?: AnalyticsEventBase;\n\n /**\n * Tracks whether a source was successfully loaded during the STARTUP_AUTOPLAY state.\n *\n * This flag is critical for handling two edge cases during autoplay startup:\n *\n * **Case 1: SOURCE_UNLOADED event handling**\n * In autoplay, the transition to STARTUP_AUTOPLAY happens immediately after player.load() is called.\n * During a source change, SOURCE_UNLOADED may be fired to clean up the previous source,\n * but this can occur BEFORE SOURCE_LOADED for the new source and AFTER the transition to STARTUP_AUTOPLAY.\n *\n * - If flag=false (no source loaded yet): SOURCE_UNLOADED is cleanup of old source → ignore\n * Example: PLAYING → SOURCE_CHANGING → LOADSTART_AUTOPLAY → STARTUP_AUTOPLAY → SOURCE_UNLOADED (ignored)\n *\n * - If flag=true (source is loaded): SOURCE_UNLOADED is an error condition → trigger VIDEOSTART_FAILED\n * Example: PLAYING → SOURCE_CHANGING → LOADSTART_AUTOPLAY → STARTUP_AUTOPLAY → SOURCE_LOADED → SOURCE_UNLOADED (error)\n *\n * **Case 2: PAUSE event handling**\n * In normal startup, PAUSE returns to READY state (safe because source is loaded).\n * In autoplay startup, we must transition based on whether source is loaded:\n *\n * - If flag=false (no source loaded yet): PAUSE → INITIAL_SOURCE_CHANGE (no sample)\n * Example: SETUP → STARTUP_AUTOPLAY → PAUSE → INITIAL_SOURCE_CHANGE\n *\n * - If flag=true (source is loaded): PAUSE → READY (no sample, source is loaded)\n * Example: SETUP → STARTUP_AUTOPLAY → SOURCE_LOADED → PAUSE → READY\n */\n private sourceLoadedDuringAutoplayStartup = false;\n\n constructor(\n stateMachineCallbacks: StateMachineCallbacks,\n playingHeartbeatService: HeartbeatService,\n opts: AnalyticsStateMachineOptions,\n ) {\n super(stateMachineCallbacks, playingHeartbeatService, opts);\n }\n\n getAllStatesBut(states: string[]) {\n return this.getAllStates().filter((i) => states.indexOf(i) < 0);\n }\n\n getAllStates() {\n return Object.keys(State).map((key) => State[key]);\n }\n\n override createStateMachine(opts: AnalyticsStateMachineOptions): StateMachine.StateMachine {\n return StateMachine.create({\n // custom initial state and custom JSM initial event name\n // initial event is used by JSM for the initial state transition 'none' -> 'SETUP'\n initial: {state: State.SETUP, event: JSM_INITIAL_EVENT},\n error: customStateMachineErrorCallback,\n events: [\n {\n name: Event.SOURCE_LOADED,\n from: [State.SETUP, State.ERROR, State.SOURCE_CHANGING, State.INITIAL_SOURCE_CHANGE],\n to: State.READY,\n },\n\n {name: Event.PLAY, from: State.READY, to: State.STARTUP},\n {name: Event.PLAYING, from: State.READY, to: State.PLAYING},\n on(Event.READY).stayIn(State.READY),\n\n //#region VIDEOSTART_FAILED\n {\n name: Event.ERROR,\n from: [State.STARTUP, State.AD_STARTUP, State.STARTUP_AUTOPLAY],\n to: State.VIDEOSTART_FAILED,\n },\n {\n name: Event.UNLOAD,\n from: [State.STARTUP, State.AD_STARTUP, State.STARTUP_AUTOPLAY],\n to: State.VIDEOSTART_FAILED,\n },\n {name: Event.VIDEOSTART_TIMEOUT, from: [State.STARTUP, State.STARTUP_AUTOPLAY], to: State.VIDEOSTART_FAILED},\n {name: Event.SOURCE_UNLOADED, from: [State.STARTUP, State.STARTUP_AUTOPLAY], to: State.VIDEOSTART_FAILED},\n {name: Event.MANUAL_SOURCE_CHANGE, from: [State.STARTUP, State.STARTUP_AUTOPLAY], to: State.VIDEOSTART_FAILED},\n //#endregion VIDEOSTART_FAILED\n\n //#region STARTUP and STARTUP_AUTOPLAY\n {name: Event.TIMECHANGED, from: [State.STARTUP, State.STARTUP_AUTOPLAY], to: State.PLAYING},\n on(Event.PLAY).stayIn(State.STARTUP),\n on(Event.PLAYING).stayIn(State.STARTUP),\n on(Event.START_BUFFERING).stayIn(State.STARTUP),\n on(Event.END_BUFFERING).stayIn(State.STARTUP),\n on(Event.VIDEO_CHANGE).stayIn(State.STARTUP),\n on(Event.AUDIO_CHANGE).stayIn(State.STARTUP),\n on(Event.READY).stayIn(State.STARTUP),\n {name: Event.PAUSE, from: State.STARTUP, to: State.READY},\n\n // ready state transition is not needed because the player.load() will always happen before the SOURCE_LOADED event\n {\n name: Event.LOADSTART_AUTOPLAY,\n from: [State.SETUP, State.SOURCE_CHANGING, State.INITIAL_SOURCE_CHANGE],\n to: State.STARTUP_AUTOPLAY,\n },\n {name: CustomEvents.PAUSE_BEFORE_SOURCE_LOADED, from: State.STARTUP_AUTOPLAY, to: State.INITIAL_SOURCE_CHANGE},\n {name: CustomEvents.PAUSE_AFTER_SOURCE_LOADED, from: State.STARTUP_AUTOPLAY, to: State.READY},\n ...whileIn(State.STARTUP_AUTOPLAY).passOver(\n // Custom behaviour in the onbeforePause callback\n Event.PAUSE,\n // Custom behaviour in the onbeforeSourceLoaded callback\n Event.SOURCE_LOADED,\n ),\n //#endregion STARTUP and STARTUP_AUTOPLAY\n\n on(Event.PLAYING).stayIn(State.PLAYING),\n on(Event.TIMECHANGED).stayIn(State.PLAYING),\n on(Event.END_BUFFERING).stayIn(State.PLAYING),\n {name: Event.START_BUFFERING, from: State.PLAYING, to: State.BUFFERING},\n {name: Event.END_BUFFERING, from: State.BUFFERING, to: State.PLAYING},\n on(Event.TIMECHANGED).stayIn(State.BUFFERING),\n\n {name: Event.PAUSE, from: State.PLAYING, to: State.PAUSE},\n {name: Event.PAUSE, from: State.BUFFERING, to: State.PAUSE},\n {name: Event.PLAY, from: State.PAUSE, to: State.PLAYING},\n\n {name: Event.VIDEO_CHANGE, from: State.PLAYING, to: State.QUALITY_CHANGE},\n {name: Event.AUDIO_CHANGE, from: State.PLAYING, to: State.QUALITY_CHANGE},\n {name: Event.FINISH_QUALITY_CHANGE, from: State.QUALITY_CHANGE, to: State.PLAYING},\n\n //#region Seeking\n\n // start seeking\n {name: Event.SEEK, from: State.PLAYING, to: State.PLAY_SEEKING},\n\n // mark the seeked as finished\n {name: Event.PLAY, from: State.PLAY_SEEKING, to: State.END_PLAY_SEEKING},\n {name: Event.PLAYING, from: State.PLAY_SEEKING, to: State.END_PLAY_SEEKING},\n {name: Event.SEEKED, from: State.PLAY_SEEKING, to: State.END_PLAY_SEEKING},\n\n // seek while previous seek not completed\n {name: Event.SEEK, from: State.END_PLAY_SEEKING, to: State.PLAY_SEEKING},\n\n // seek completely finished and cont playing\n {name: Event.PLAYING, from: State.END_PLAY_SEEKING, to: State.PLAYING},\n {name: Event.TIMECHANGED, from: State.END_PLAY_SEEKING, to: State.PLAYING},\n\n // if PAUSE happens during the seeking (or at the end of seeking) we need to transition to PAUSE state\n {name: Event.PAUSE, from: [State.PLAY_SEEKING, State.END_PLAY_SEEKING], to: State.PAUSE},\n\n //#region Seeking disabled transitions\n // ignore transitions in PLAY_SEEKING\n on(Event.SEEK).stayIn(State.PLAY_SEEKING),\n on(Event.START_BUFFERING).stayIn(State.PLAY_SEEKING),\n on(Event.END_BUFFERING).stayIn(State.PLAY_SEEKING),\n\n // ignore transitions in END_PLAY_SEEKING\n on(Event.START_BUFFERING).stayIn(State.END_PLAY_SEEKING),\n on(Event.END_BUFFERING).stayIn(State.END_PLAY_SEEKING),\n on(Event.SEEKED).stayIn(State.END_PLAY_SEEKING),\n on(Event.PLAY).stayIn(State.END_PLAY_SEEKING),\n\n // ignore Seek events during PAUSE\n on(Event.SEEK).stayIn(State.PAUSE),\n on(Event.SEEKED).stayIn(State.PAUSE),\n\n // ignore seeked during Playing because of not allowed keyboard seeking\n on(Event.SEEKED).stayIn(State.PLAYING),\n //#endregion Seeking disabled transitions\n\n //#endregion Seeking\n\n {name: Event.END, from: State.PLAY_SEEKING, to: State.END},\n {name: Event.END, from: State.PLAYING, to: State.END},\n {name: Event.END, from: State.PAUSE, to: State.END},\n\n on(Event.SEEK).stayIn(State.END),\n on(Event.SEEKED).stayIn(State.END),\n on(Event.TIMECHANGED).stayIn(State.END),\n on(Event.END_BUFFERING).stayIn(State.END),\n on(Event.START_BUFFERING).stayIn(State.END),\n on(Event.END).stayIn(State.END),\n\n {name: Event.PLAY, from: State.END, to: State.STARTUP},\n\n {name: Event.ERROR, from: this.getAllStatesBut([State.STARTUP, State.STARTUP_AUTOPLAY]), to: State.ERROR},\n\n {\n name: Event.UNLOAD,\n from: this.getAllStatesBut([State.STARTUP, State.STARTUP_AUTOPLAY, State.AD_STARTUP]),\n to: State.END,\n },\n\n {name: Event.SUBTITLE_CHANGE, from: State.PLAYING, to: State.SUBTITLE_CHANGING},\n on(Event.SUBTITLE_CHANGE).stayIn(State.PAUSE),\n on(Event.SUBTITLE_CHANGE).stayIn(State.BUFFERING),\n on(Event.SUBTITLE_CHANGE).stayIn(State.END_PLAY_SEEKING),\n on(Event.SUBTITLE_CHANGE).stayIn(State.SUBTITLE_CHANGING),\n {name: Event.TIMECHANGED, from: State.SUBTITLE_CHANGING, to: State.PLAYING},\n\n {name: Event.AUDIOTRACK_CHANGED, from: State.PLAYING, to: State.AUDIOTRACK_CHANGING},\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.PAUSE),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.BUFFERING),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.END_PLAY_SEEKING),\n on(Event.AUDIOTRACK_CHANGED).stayIn(State.AUDIOTRACK_CHANGING),\n {name: Event.TIMECHANGED, from: State.AUDIOTRACK_CHANGING, to: State.PLAYING},\n\n // #region Ads\n {name: Event.START_AD, from: State.STARTUP, to: State.AD_STARTUP},\n {name: Event.END_AD, from: State.AD_STARTUP, to: State.STARTUP},\n on(Event.PLAY).stayIn(State.AD_STARTUP),\n on(Event.PAUSE).stayIn(State.AD_STARTUP),\n\n {name: Event.START_AD, from: State.READY, to: State.AD_READY},\n /** After the pre-rolls, the main content will always start playing, no matter if autoplay: true/false */\n {name: Event.END_AD, from: State.AD_READY, to: State.STARTUP},\n on(Event.PLAY).stayIn(State.AD_READY),\n on(Event.PAUSE).stayIn(State.AD_READY),\n\n {name: Event.START_AD, from: State.PAUSE, to: State.AD_PAUSE},\n {name: Event.END_AD, from: State.AD_PAUSE, to: State.PAUSE},\n on(Event.PLAY).stayIn(State.AD_PAUSE),\n on(Event.PAUSE).stayIn(State.AD_PAUSE),\n\n {name: Event.START_AD, from: State.PLAYING, to: State.AD_PLAYING},\n {name: Event.END_AD, from: State.AD_PLAYING, to: State.PLAYING},\n on(Event.PLAY).stayIn(State.AD_PLAYING),\n on(Event.PAUSE).stayIn(State.AD_PLAYING),\n {name: Event.END, from: State.AD_PLAYING, to: State.END},\n\n // Ignore timechanged events during ads\n on(Event.TIMECHANGED).stayIn(State.AD_STARTUP),\n on(Event.TIMECHANGED).stayIn(State.AD_READY),\n on(Event.TIMECHANGED).stayIn(State.AD_PAUSE),\n on(Event.TIMECHANGED).stayIn(State.AD_PLAYING),\n\n // Ignore End Ad events when no ad has started\n on(Event.END_AD).stayIn(State.PLAYING),\n on(Event.END_AD).stayIn(State.PAUSE),\n on(Event.END_AD).stayIn(State.READY),\n on(Event.END_AD).stayIn(State.STARTUP),\n // #endregion\n\n {name: Event.MUTE, from: State.READY, to: State.MUTING_READY},\n {name: Event.UN_MUTE, from: State.READY, to: State.MUTING_READY},\n {name: 'FINISH_MUTING', from: State.MUTING_READY, to: State.READY},\n\n {name: Event.MUTE, from: State.PLAYING, to: State.MUTING_PLAY},\n {name: Event.UN_MUTE, from: State.PLAYING, to: State.MUTING_PLAY},\n {name: 'FINISH_MUTING', from: State.MUTING_PLAY, to: State.PLAYING},\n\n {name: Event.MUTE, from: State.PAUSE, to: State.MUTING_PAUSE},\n {name: Event.UN_MUTE, from: State.PAUSE, to: State.MUTING_PAUSE},\n {name: 'FINISH_MUTING', from: State.MUTING_PAUSE, to: State.PAUSE},\n\n {name: Event.START_CAST, from: [State.READY, State.PAUSE, State.PLAYING], to: State.CASTING},\n on(Event.PAUSE).stayIn(State.CASTING),\n on(Event.PLAY).stayIn(State.CASTING),\n on(Event.PLAYING).stayIn(State.CASTING),\n on(Event.TIMECHANGED).stayIn(State.CASTING),\n on(Event.MUTE).stayIn(State.CASTING),\n on(Event.UN_MUTE).stayIn(State.CASTING),\n on(Event.SEEK).stayIn(State.CASTING),\n on(Event.SEEKED).stayIn(State.CASTING),\n {name: Event.END_CAST, from: State.CASTING, to: State.READY},\n\n on(Event.SEEK).stayIn(State.READY),\n on(Event.SEEKED).stayIn(State.READY),\n on(Event.SEEKED).stayIn(State.STARTUP),\n\n {\n name: Event.MANUAL_SOURCE_CHANGE,\n from: this.getAllStatesBut([State.SETUP, State.STARTUP, State.STARTUP_AUTOPLAY]),\n to: State.SOURCE_CHANGING,\n },\n {name: Event.MANUAL_SOURCE_CHANGE, from: State.SETUP, to: State.INITIAL_SOURCE_CHANGE},\n {\n name: Event.SOURCE_UNLOADED,\n from: this.getAllStatesBut([State.STARTUP, State.STARTUP_AUTOPLAY]),\n to: State.SOURCE_CHANGING,\n },\n\n // {name: Event.READY, from: State.SOURCE_CHANGING, to: State.READY},\n\n // Because of this state transition, we are able to make \"a cut\" in the current PLAYING / PAUSE state\n // and send \"playing\" / \"pause\" sample with the current custom data values. The new changed custom data values\n // will be set on upcoming samples after we transition back from the CUSTOMDATACHANGE state.\n // For any other states, we don't care, because InternalAdapter is not emitting the event.\n {name: Event.CUSTOM_DATA_CHANGE, from: [State.PLAYING, State.PAUSE], to: State.CUSTOMDATACHANGE},\n {name: Event.PLAYING, from: State.CUSTOMDATACHANGE, to: State.PLAYING},\n {name: Event.PAUSE, from: State.CUSTOMDATACHANGE, to: State.PAUSE},\n ],\n\n // Keep callbacks sorted by order in which they are called by JSM library (and after order, sorted by name)\n //\n // Do not use convenience, shortened callbacks\n // - instead of `onEVENT` use `onafterEVENT`\n // - instead of `onSTATE` use `onenterSTATE`\n //\n // see: https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#callbacks\n callbacks: {\n [`onbefore${Event.SOURCE_LOADED}`]: (\n _event,\n from,\n _to,\n _eventTimestamp: number,\n _eventData: AnalyticsEventBase,\n ) => {\n if (from === State.STARTUP_AUTOPLAY) {\n this.sourceLoadedDuringAutoplayStartup = true;\n }\n },\n\n [`onbefore${Event.SOURCE_UNLOADED}`]: (\n _event,\n from,\n _to,\n _eventTimestamp: number,\n _eventData: AnalyticsEventBase,\n ) => {\n // Prevent SOURCE_UNLOADED from triggering VIDEOSTART_FAILED during STARTUP_AUTOPLAY\n // if the new source hasn't been loaded yet.\n //\n // During source changes with autoplay, SOURCE_UNLOADED (cleanup of previous source)\n // may arrive AFTER player.load() is called but BEFORE SOURCE_LOADED (new source).\n // We ignore this cleanup event and only treat SOURCE_UNLOADED as an error\n // once the new source has been successfully loaded.\n if (from === State.STARTUP_AUTOPLAY && !this.sourceLoadedDuringAutoplayStartup) {\n return false;\n }\n\n return true;\n },\n\n [`onbefore${Event.PAUSE}`]: (_event, from, _to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n // Handle PAUSE during STARTUP_AUTOPLAY with special transitions based on source load status.\n // See sourceLoadedDuringAutoplayStartup documentation for detailed explanation.\n if (from === State.STARTUP_AUTOPLAY) {\n if (this.sourceLoadedDuringAutoplayStartup) {\n // Source loaded: transition to READY (normal behavior)\n this.stateMachine[CustomEvents.PAUSE_AFTER_SOURCE_LOADED](eventTimestamp, eventData);\n } else {\n // Source not loaded: transition to INITIAL_SOURCE_CHANGE (preserve READY semantics)\n this.stateMachine[CustomEvents.PAUSE_BEFORE_SOURCE_LOADED](eventTimestamp, eventData);\n }\n return false;\n }\n\n return true;\n },\n\n [`onleave${State.END_PLAY_SEEKING}`]: (\n _event,\n _from,\n to,\n eventTimestamp: number,\n eventData: AnalyticsEventBase,\n ) => {\n if (to === State.PLAY_SEEKING) {\n // seeking is not finished yet, do not send \"seeking\" sample\n return;\n }\n\n // seeking has finished / was interrupted - send out seeking sample\n const seekDuration = eventTimestamp - (this.seekStartTimestamp ?? eventTimestamp);\n this.seekStartTimestamp = undefined;\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n this.stateMachineCallbacks.seeking(seekDuration);\n },\n\n [`onleave${State.PLAYING}`]: () => {\n this.playingHeartbeatService.stopHeartbeat();\n },\n\n [`onleave${State.STARTUP_AUTOPLAY}`]: () => {\n this.sourceLoadedDuringAutoplayStartup = false;\n this.clearVideoStartTimeout();\n },\n\n [`onleave${State.PLAY_SEEKING}`]: (_event, _from, to, eventTimestamp: number, _eventData) => {\n if (to === State.END_PLAY_SEEKING) {\n // regular seek workflow preparing to end seeking\n return;\n }\n\n // seek interrupted - not regular exit of seeking\n const seekDuration = eventTimestamp - (this.seekStartTimestamp ?? eventTimestamp);\n this.seekStartTimestamp = undefined;\n this.stateMachineCallbacks.seeking(seekDuration);\n },\n\n onleavestate: (event, from, to, eventTimestamp, eventData: AnalyticsEventBase) => {\n logStateMachineTransition('LEAVE', event, from, to);\n\n // Skip this JSM callback for JSM initial event\n // This event is fired when the state machine is constructed,\n // to transition us from 'none' to custom initial 'SETUP' state\n if (event === JSM_INITIAL_EVENT) {\n return;\n }\n\n if (from === State.BUFFERING) {\n this.resetBufferingHelpers();\n }\n\n // Skip this JSM callback when an JSM event without a timestamp is called,\n // because it would cause NPE in analytics code (state duration calculation etc.).\n // This probably has happened because the state machine was not used correctly,\n // aka. JSM event was not called via `callEvent` method as it should be!\n if (!eventTimestamp) {\n return;\n }\n\n this.addStatesToLog(event, from, to, eventTimestamp, eventData);\n const stateDuration = eventTimestamp - this.onEnterStateTimestamp;\n\n if (eventData && to !== State.END_PLAY_SEEKING) {\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(eventData);\n }\n\n if (eventData && event !== Event.END_AD) {\n this.lastTrackedVideoEndObject = eventData;\n }\n\n if ((from === State.READY || from === State.AD_STARTUP) && to === State.STARTUP) {\n this.setVideoStartTimeout();\n } else if (from === State.STARTUP && (to === State.PLAYING || to === State.AD_STARTUP)) {\n this.clearVideoStartTimeout();\n }\n\n const lowerCaseFrom = String(from).toLowerCase();\n if (to === State.VIDEOSTART_FAILED) {\n this.clearVideoStartTimeout();\n this.stateMachineCallbacks.videoStartFailed(stateDuration, createVideoStartFailedReason(event));\n } else if (from === State.END_PLAY_SEEKING) {\n // NOOP - skip last else block to not send sample\n // sending of sample is handled in `on Leave Seeking` state transition handler\n noOp();\n } else if (event === Event.UNLOAD) {\n this.stateMachineCallbacks.unload(stateDuration, lowerCaseFrom);\n } else if (\n from === State.AD_PAUSE ||\n from === State.AD_READY ||\n from === State.AD_PLAYING ||\n from === State.AD_STARTUP\n ) {\n if (isNotNullish(this.lastTrackedVideoEndObject)) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(this.lastTrackedVideoEndObject);\n this.stateMachineCallbacks.setVideoTimeEndFromEvent(this.lastTrackedVideoEndObject);\n }\n this.stateMachineCallbacks.ad(stateDuration, 'ad');\n } else if (event === Event.START_AD && from === State.STARTUP) {\n noOp();\n } else if (event === Event.SOURCE_LOADED && from === State.INITIAL_SOURCE_CHANGE) {\n noOp();\n } else if (from === State.SETUP) {\n // Setting Player Startup Time to fixed value of 1ms.\n // We can not get correct Player Startup Time from bitmovin player, because it does not have an \"onInitialized\" event\n this.stateMachineCallbacks.setup(1, State.SETUP.toLowerCase());\n } else if (\n (event === Event.PAUSE && from === State.STARTUP && to === State.READY) ||\n (event === CustomEvents.PAUSE_BEFORE_SOURCE_LOADED &&\n from === State.STARTUP_AUTOPLAY &&\n to === State.INITIAL_SOURCE_CHANGE) ||\n (event === CustomEvents.PAUSE_AFTER_SOURCE_LOADED && from === State.STARTUP_AUTOPLAY && to === State.READY)\n ) {\n // fired PAUSE event in STARTUP state or STARTUP_AUTOPLAY state indicates we are moving back to READY/INITIAL_SOURCE_CHANGE,\n // so we have to clean setTimeout, and we should not call any stateMachineCallbacks\n this.clearVideoStartTimeout();\n } else if (from === State.STARTUP_AUTOPLAY) {\n // send normal startup sample when leaving STARTUP_AUTOPLAY state\n this.stateMachineCallbacks.startup(stateDuration, State.STARTUP.toLowerCase());\n } else if (from !== State.ERROR) {\n // Default \"onleavestate\" state machine callback\n //\n // Every time, when we leave a state, we should try to call \"state\" callback,\n // to be able to make \"a cut\" and send analytics sample (if necessary)\n const defaultStateMachineCallbackFn = this.stateMachineCallbacks[lowerCaseFrom];\n if (isFunction(defaultStateMachineCallbackFn)) {\n // a try-catch block to add more resilience against callback errors\n try {\n defaultStateMachineCallbackFn(stateDuration, lowerCaseFrom, eventData);\n } catch (e) {\n logger.error('Exception occurred in State Machine callback ' + lowerCaseFrom, eventData, e);\n }\n } else {\n // if callback is not defined, log a warning to indicate to the developer that\n // - a new callback function needs to be implemented to relay on this default state machine callback\n // - or if no callback is needed, we should\n // - early return from this JSM callback\n // - or add this state to the ignored list\n logMissingCallbackWarning(from, [State.READY, State.SOURCE_CHANGING]);\n }\n }\n\n if (\n eventData &&\n to !== State.END_PLAY_SEEKING &&\n from !== State.PLAY_SEEKING &&\n to !== State.PLAY_SEEKING &&\n from !== State.AD_STARTUP &&\n from !== State.AD_READY &&\n from !== State.AD_PLAYING &&\n from !== State.AD_PAUSE\n ) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n }\n\n if (event === Event.MUTE) {\n this.stateMachineCallbacks.mute();\n } else if (event === Event.UN_MUTE) {\n this.stateMachineCallbacks.unMute();\n }\n },\n\n [`onenter${State.STARTUP_AUTOPLAY}`]: () => {\n this.setVideoStartTimeout();\n },\n\n [`onenter${State.PLAYING}`]: () => {\n this.playingHeartbeatService.startHeartbeat();\n },\n\n [`onenter${State.PLAY_SEEKING}`]: (event, from, _to, eventTimestamp: number, _eventData) => {\n if (from === State.END_PLAY_SEEKING) {\n // no start of seeking -> continues to seek and we don't need to have seek start timestamp\n return;\n }\n\n this.seekStartTimestamp = eventTimestamp;\n },\n\n [`onenter${State.QUALITY_CHANGE}`]: (_event, _from, _to, eventTimestamp, eventData) => {\n // Quality change should produce a \"signal sample\" and immediately transition us back to PLAYING state\n this.stateMachineCallbacks.qualitychange(eventData);\n this.stateMachine[Event.FINISH_QUALITY_CHANGE](eventTimestamp);\n },\n\n onenterstate: (event, from, to, eventTimestamp: number, eventData: AnalyticsEventBase) => {\n logStateMachineTransition('ENTER', event, from, to);\n\n this.onEnterStateTimestamp = eventTimestamp ?? Date.now();\n // if customer set custom \"start time\" timestamp in AnalyticsStateMachineOptions of adapter constructor,\n // use it and override `onEnterStateTimestamp` during JSM initialization (transition to initial SETUP state)\n if (isNumber(opts.starttime) && event === JSM_INITIAL_EVENT) {\n this.onEnterStateTimestamp = opts.starttime;\n }\n\n if (\n eventData &&\n to !== State.END_PLAY_SEEKING &&\n from !== State.PLAY_SEEKING &&\n from !== State.AD_STARTUP &&\n from !== State.AD_READY &&\n from !== State.AD_PLAYING &&\n from !== State.AD_PAUSE &&\n !(event === Event.SEEK && from === State.END_PLAY_SEEKING)\n ) {\n this.stateMachineCallbacks.setVideoTimeStartFromEvent(eventData);\n }\n\n if (event === Event.START_CAST && to === State.CASTING) {\n this.stateMachineCallbacks.startCasting(eventTimestamp, eventData);\n }\n\n if (to === State.BUFFERING) {\n this.startBufferingHeartbeatInterval();\n }\n },\n\n [`onafter${Event.ERROR}`]: (_event, _from, _to, _eventTimestamp, eventData: ErrorEvent) => {\n this.stateMachineCallbacks.error(eventData);\n },\n\n [`onafter${Event.SOURCE_UNLOADED}`]: (\n _event,\n _from,\n _to,\n _eventTimestamp: number,\n _eventData: AnalyticsEventBase,\n ) => {\n // Reset the flag after SOURCE_UNLOADED is processed.\n // This prepares the state machine for the next source load/change cycle.\n this.sourceLoadedDuringAutoplayStartup = false;\n },\n\n onafterevent: (event, from, to, eventTimestamp: number, eventData) => {\n if (event === Event.MANUAL_SOURCE_CHANGE && from === State.SETUP) {\n this.stateMachineCallbacks.initialSourceChange(eventData);\n } else if (event === Event.MANUAL_SOURCE_CHANGE) {\n this.stateMachineCallbacks.manualSourceChange(eventData);\n }\n\n if (to === State.MUTING_READY || to === State.MUTING_PLAY || to === State.MUTING_PAUSE) {\n this.stateMachine.FINISH_MUTING(eventTimestamp);\n }\n },\n },\n });\n }\n\n getStates() {\n return this.debuggingStates;\n }\n\n setEnabledDebugging(enabled: boolean) {\n this.enabledDebugging = enabled;\n }\n\n private addStatesToLog(\n event: string | undefined,\n from: string | undefined,\n to: string | undefined,\n timestamp: number,\n eventObject: any,\n ) {\n if (this.enabledDebugging) {\n this.debuggingStates.push(new EventDebugging(event, from, to, timestamp, eventObject));\n }\n }\n}\n","import {\n StateMachineErrorCallback,\n Error as StateMachineErrorCode,\n StateMachineEventDef,\n} from 'javascript-state-machine';\n\nimport {logger, padRight} from '../utils/Logger';\nimport {objectValues} from '../utils/objectUtils';\nimport {isNullish, tryJSONStringify} from '../utils/Utils';\n\n/**\n * @deprecated use {@link whileIn} instead, to switch mindset and think about allowed events in the current state\n * instead of thinking of current event and its allowed states. Because as analytics we focus mostly on reporting\n * states or states changes.\n */\nexport const on = (event: string): {stayIn: (state: string) => StateMachineEventDef} => ({\n stayIn: (state: string) => ({name: event, from: state, to: state}),\n});\n\ntype EventsToStateMachineEventDefFn = (...events: string[]) => StateMachineEventDef[];\ntype WhileInReturnType = {\n /**\n * Create {@link StateMachineEventDef} from event(s) to be used in the state machine definition, but ONLY to indicate\n * that we want to only pass event(s) over, to avoid a log message of ignored event in the current state from\n * the state machine.\n *\n * @remarks\n *\n * If we decide in the future to ignore {@link StateMachineErrorCode.INVALID_TRANSITION} logs created in\n * {@link customStateMachineErrorCallback}, this method and JSM event definitions created with could be removed\n * from source code. Until then, we use it to make code more readable.\n */\n passOver: EventsToStateMachineEventDefFn;\n\n /**\n * Same as {@link passOver}, but used in rare cases, when it indicates that we expect the event(s) to occur\n * in the current state, aka. we want to trigger the state machine event callbacks for these event(s),\n * even if we stay in the same state.\n *\n * @remarks\n *\n * If we don't expect the event while staying in the current state, we don't expect state machine event callbacks\n * to run, we should use {@link passOver} instead!\n */\n runEventCallbacksFor: EventsToStateMachineEventDefFn;\n};\n\n/**\n * This utility is here to help us write more readable code and let us define allowed/expected events in the current state.\n *\n * ### Example:\n *\n * Instead of writing:\n *\n * ```typescript\n * {name: Event.PAUSE, from: State.END, to: State.END},\n * {name: Event.SEEK, from: State.END, to: State.END},\n * {name: Event.SEEKED, from: State.END, to: State.END},\n * {name: Event.TIMECHANGED, from: State.END, to: State.END},\n * ```\n *\n * we can write:\n *\n * ```typescript\n * ...whileIn(State.END).passOver(Event.PAUSE, Event.SEEK, Event.SEEKED, Event.TIMECHANGED),\n * // OR when we expect and react on that event occurrence:\n * ...whileIn(State.END).runEventCallbacksFor(Event.PAUSE, Event.SEEK, Event.SEEKED, Event.TIMECHANGED),\n * ```\n *\n * @see customStateMachineErrorCallback\n * @see https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#handling-failures\n */\nexport const whileIn = (state: string): WhileInReturnType => {\n const stateMachineEventDefBuilderFn = (...events: string[]) =>\n events.map((event) => ({name: event, from: state, to: state}));\n return {runEventCallbacksFor: stateMachineEventDefBuilderFn, passOver: stateMachineEventDefBuilderFn};\n};\n\n/**\n * By default, if you try to call an event method not allowed in the current state,\n * the state machine will throw an exception (not allow it).\n *\n * This JSM library behavior can be changed by providing \"a custom error handler\" in the `create()`\n * method of the state machine, and we do that in every state machine!\n *\n * This way we make code more resilient to errors, because we do not throw errors from JSM event methods,\n * but instead we handle them here and just log them with {@link logger}.\n *\n * @see https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#handling-failures\n */\nexport const customStateMachineErrorCallback: StateMachineErrorCallback = (\n eventName,\n from,\n to,\n args,\n errorCode,\n errorMessage,\n _ex,\n) => {\n const loggerMessage = `StateMachine ignored event \"${eventName}\", ${errorMessage}`;\n const loggerMessageData = {\n eventName,\n from,\n to,\n args: tryJSONStringify(args),\n errorCode,\n errorMessage,\n };\n\n // if caller tried to fire an event that was inappropriate in the current state\n if (errorCode === StateMachineErrorCode.INVALID_TRANSITION) {\n // The event itself is defined in JSM (in some other StateMachineEventDef). However, it is just not considered to\n // be appropriate in the current state.\n //\n // We should log it as a simple log. It is not an error nor a warning,\n // - because JSM will just stay in the same JSM state (and that can be considered as expected behavior)\n // - BUT it will NOT trigger JSM event callbacks like `onafterEVENT`, on `onbeforeEVENT`!\n logger.log(loggerMessage, loggerMessageData);\n return;\n }\n\n logger.error(loggerMessage, loggerMessageData);\n};\n\n/**\n * Log warning messages with {@link logger} about missing StateMachine callback,\n * if the state is not nullish and does not match any of the ignored states.\n */\nexport const logMissingCallbackWarning = (state: string | undefined, ignoreStates: string[] = []) => {\n if (isNullish(state)) {\n return;\n }\n\n const shouldReportMissingCallback = isNullish(ignoreStates.find((ignoredState) => state === ignoredState));\n if (shouldReportMissingCallback) {\n logger.warn('Could not find StateMachine callback function for ' + state);\n }\n};\n\n/** Log message with {@link logger} about StateMachine ENTER/LEAVE transition */\nexport const logStateMachineTransition = (\n transition: 'ENTER' | 'LEAVE',\n event: string | undefined,\n from: string | undefined,\n to: string | undefined,\n) => {\n if (transition === 'ENTER') {\n logger.log(`[ENTER] ${padRight(to, 20)} EVENT: ${padRight(event, 20)} from ${padRight(from, 20)}`);\n } else {\n logger.log(`[LEAVE] ${padRight(from, 20)} EVENT: ${padRight(event, 20)} to ${padRight(to, 20)}`);\n }\n};\n\n/**\n * Return all values/states of the given state string enum.\n *\n * @param stateStringEnumObj\n *\n * @remarks\n *\n * We cannot directly check at if an object is a TypeScript string enum, because enums are erased at compile time and\n * become plain objects in JavaScript. However, you can heuristically check if an object looks like a string enum\n * by verifying that all its values are strings. This checks if all values of the object are strings, which is typical\n * for a string enum. However, this is not a foolproof check, just a heuristic.\n */\nexport function getAllStates<T extends {[key: string]: string}>(stateStringEnumObj: T): Array<T[keyof T]> {\n return objectValues(stateStringEnumObj) as Array<T[keyof T]>;\n}\n\nexport function getAllStatesBut<T extends {[key: string]: string}>(\n excludedStates: Array<T[keyof T]>,\n stateEnumObj: T,\n): Array<T[keyof T]> {\n return getAllStates(stateEnumObj).filter((s) => excludedStates.indexOf(s) < 0);\n}\n","import {isNullish, toBoolean} from '../utils/Utils';\n\nexport function sanitizeSessionMetadataAudioLanguage(anything: unknown): string | undefined {\n // \"nullish\" is considered to be valid (to \"reset\" session metadata property)\n if (isNullish(anything)) {\n // sanitize to use `undefined` in code\n return undefined;\n }\n\n return String(anything).substring(0, 50);\n}\n\nexport function sanitizeSessionMetadataSubtitleEnabled(anything: unknown): boolean | undefined {\n // \"nullish\" is considered to be valid (to \"reset\" session metadata property)\n if (isNullish(anything)) {\n // sanitize to use `undefined` in code\n return undefined;\n }\n\n return toBoolean(anything);\n}\n\nexport function sanitizeSessionMetadataSubtitleLanguage(anything: unknown): string | undefined {\n // \"nullish\" is considered to be valid (to \"reset\" session metadata property)\n if (isNullish(anything)) {\n // sanitize to use `undefined` in code\n return undefined;\n }\n\n return String(anything).substring(0, 100);\n}\n","import {\n AdClickedPayload,\n AdErrorPayload,\n AdManifestLoadedPayload,\n AdModuleAPI,\n AdQuartile,\n AdQuartilePayload,\n} from '../adapters/internal/ads/AdModuleAPI';\nimport {AdBreakInfo} from '../types/ads/AdBreakInfo';\nimport {AdInfo} from '../types/ads/AdInfo';\nimport type {AdSample} from '../types/AdSample';\nimport {logger} from '../utils/Logger';\nimport {isFiniteNumber} from '../utils/numberUtils';\nimport {buildAdSample} from '../utils/sampleUtils';\nimport * as Utils from '../utils/Utils';\nimport {isNotNullish, isNullish, tryJSONStringify} from '../utils/Utils';\nimport {generateUUID} from '../utils/uuidUtils';\nimport {VERSION} from '../utils/Version';\nimport {ViewportTracker} from '../utils/ViewportTracker';\n\nimport {Analytics} from './Analytics';\n\nexport class AdAnalytics {\n static readonly MODULE_NAME = 'ads';\n private static readonly TIMEOUT_CURRENT_TIME_INTERVAL = 100;\n\n /** Boolean flag to prevent multiple calls of the {@link Event.UNLOAD} event */\n private onBeforeUnLoadEvent = false;\n private analytics: Analytics;\n private adapter: AdModuleAPI;\n private viewportTracker?: ViewportTracker;\n\n private activeAdBreakState: ActiveAdBreakState | undefined;\n private activeAdState: ActiveAdState | undefined;\n\n private adManifestDownloadTime: number | undefined;\n private adStartupTimestamp?: number;\n private beginPlayingTimestamp?: number;\n private enterViewportTimestamp?: number;\n private isPlaying = false;\n private currentTime?: number;\n private currentTimeInterval?: ReturnType<typeof setInterval>;\n private adPodPosition = 0;\n\n constructor(analytics: Analytics, adapter: AdModuleAPI) {\n this.analytics = analytics;\n this.adapter = adapter;\n\n this.adapter.adCallbacks.onAdStarted = (event) => this.onAdStarted(event);\n this.adapter.adCallbacks.onAdFinished = (event) => this.onAdFinished(event);\n this.adapter.adCallbacks.onAdBreakStarted = (event) => this.onAdBreakStarted(event);\n this.adapter.adCallbacks.onAdBreakFinished = (event) => this.onAdBreakFinished(event);\n this.adapter.adCallbacks.onAdClicked = (event) => this.onAdClicked(event);\n this.adapter.adCallbacks.onAdError = (event) => this.onAdError(event);\n this.adapter.adCallbacks.onAdManifestLoaded = (event) => this.onAdManifestLoaded(event);\n this.adapter.adCallbacks.onPlay = () => this.onPlay();\n this.adapter.adCallbacks.onPause = () => this.onPause();\n this.adapter.adCallbacks.onBeforeUnload = () => this.onBeforeUnload();\n this.adapter.adCallbacks.onAdSkipped = (event) => this.onAdSkipped(event);\n this.adapter.adCallbacks.onAdQuartile = (event) => this.onAdQuartile(event);\n\n const container = this.adapter.getContainer();\n if (isNotNullish(container)) {\n this.viewportTracker = new ViewportTracker(container, () => this.onIntersectionChanged(), 0.5);\n }\n }\n\n release() {\n this.clearCurrentTimeInterval();\n this.viewportTracker?.dispose();\n this.adManifestDownloadTime = undefined;\n }\n\n onIntersectionChanged() {\n if (!this.activeAdState) {\n return;\n }\n if (this.isContainerInViewport()) {\n this.enterViewportTimestamp = Date.now();\n } else {\n if (this.enterViewportTimestamp) {\n this.activeAdState.timeInViewport =\n (this.activeAdState.timeInViewport || 0) + Date.now() - this.enterViewportTimestamp;\n }\n }\n }\n\n isContainerInViewport(): boolean {\n return this.viewportTracker ? this.viewportTracker.isInViewport() : true;\n }\n\n onPlay() {\n if (this.adapter && this.adapter.isLinearAdActive() && this.activeAdState) {\n const timestamp = Date.now();\n this.beginPlayingTimestamp = timestamp;\n this.enterViewportTimestamp = timestamp;\n this.isPlaying = true;\n }\n }\n\n onPause() {\n if (this.adapter && this.adapter.isLinearAdActive() && this.activeAdState) {\n this.updatePlayingTime(this.activeAdState);\n this.isPlaying = false;\n }\n }\n\n onAdManifestLoaded(payload: AdManifestLoadedPayload) {\n if (payload.isVmap) {\n this.sendAnalyticsRequest(buildInitialActiveAdBreakState(payload.adBreakInfo));\n return;\n }\n\n this.adManifestDownloadTime = payload.manifestDownloadTime;\n }\n\n onAdBreakStarted(adBreak: AdBreakInfo) {\n this.adPodPosition = 0;\n this.activeAdBreakState = buildInitialActiveAdBreakState({\n ...adBreak,\n manifestDownloadTime: this.adManifestDownloadTime,\n });\n delete this.adManifestDownloadTime;\n this.adStartupTimestamp = Date.now();\n }\n\n onAdBreakFinished(_adBreak: AdBreakInfo) {\n this.resetActiveAd();\n this.activeAdBreakState = undefined;\n }\n\n onAdStarted(adInfo: AdInfo) {\n if (!adInfo.isLinear) {\n return;\n }\n\n this.resetActiveAd();\n this.activeAdState = buildInitialActiveAdState(adInfo);\n this.currentTime = undefined;\n this.activeAdState.adStartupTime = this.adStartupTimestamp ? Date.now() - this.adStartupTimestamp : undefined;\n\n this.startAd(this.activeAdState);\n }\n\n onAdFinished(_ad: AdInfo) {\n if (!this.activeAdBreakState || !this.activeAdState) {\n return;\n }\n\n const activeAdStateCopy = {...this.activeAdState};\n activeAdStateCopy.completed = 1;\n this.resetActiveAd();\n this.completeAd(this.activeAdBreakState, activeAdStateCopy, activeAdStateCopy.adDuration);\n }\n\n onAdSkipped(_ad: AdInfo) {\n if (!this.activeAdBreakState || !this.activeAdState) {\n return;\n }\n\n const activeAdStateCopy = {...this.activeAdState};\n activeAdStateCopy.skipped = 1;\n activeAdStateCopy.skipPosition = this.currentTime;\n activeAdStateCopy.skipPercentage = Utils.calculatePercentage(\n activeAdStateCopy.skipPosition,\n this.activeAdState.adDuration,\n );\n this.resetActiveAd();\n this.completeAd(this.activeAdBreakState, activeAdStateCopy, activeAdStateCopy.skipPosition);\n }\n\n onAdError(payload: AdErrorPayload) {\n const adBreakSample = buildInitialActiveAdBreakState(payload.adBreakInfo);\n\n const transformedError = this.analytics.transformError(\n {code: payload.code, message: payload.message, severity: 'CRITICAL'},\n payload,\n );\n\n adBreakSample.errorCode = transformedError.code;\n adBreakSample.errorData = tryJSONStringify({code: payload.code, message: payload.message});\n adBreakSample.errorMessage = transformedError.message;\n adBreakSample.errorSeverity = transformedError.severity;\n\n let activeAdState: ActiveAdState | undefined;\n let exitPosition: number | undefined;\n if (this.activeAdState && payload.activeAdId && this.activeAdState.adId === payload.activeAdId) {\n activeAdState = this.activeAdState;\n exitPosition = this.currentTime;\n activeAdState.errorPosition = this.currentTime;\n activeAdState.errorPercentage = Utils.calculatePercentage(activeAdState.errorPosition, activeAdState.adDuration);\n }\n this.completeAd(adBreakSample, activeAdState, exitPosition);\n }\n\n onAdClicked(payload: AdClickedPayload) {\n if (!this.activeAdState) {\n return;\n }\n this.activeAdState.adClickthroughUrl = payload.clickThroughUrl;\n this.activeAdState.clicked = 1;\n this.activeAdState.clickPosition = this.currentTime;\n this.activeAdState.clickPercentage = Utils.calculatePercentage(\n this.activeAdState.clickPosition,\n this.activeAdState.adDuration,\n );\n }\n\n onAdQuartile(payload: AdQuartilePayload) {\n if (!this.activeAdState) {\n return;\n }\n if (payload.quartile === AdQuartile.FIRST_QUARTILE) {\n this.activeAdState.quartile1 = 1;\n } else if (payload.quartile === AdQuartile.MIDPOINT) {\n this.activeAdState.midpoint = 1;\n } else if (payload.quartile === AdQuartile.THIRD_QUARTILE) {\n this.activeAdState.quartile3 = 1;\n }\n }\n\n onBeforeUnload() {\n if (this.onBeforeUnLoadEvent) {\n return;\n }\n this.onBeforeUnLoadEvent = true;\n if (!this.activeAdState || !this.activeAdBreakState) {\n return;\n }\n\n const activeAdStateCopy = {...this.activeAdState};\n activeAdStateCopy.closed = 1;\n activeAdStateCopy.closePosition = this.currentTime;\n activeAdStateCopy.closePercentage = Utils.calculatePercentage(\n activeAdStateCopy.closePosition,\n activeAdStateCopy.adDuration,\n );\n this.resetActiveAd();\n this.completeAd(this.activeAdBreakState, activeAdStateCopy, activeAdStateCopy.closePosition);\n }\n\n private sendAnalyticsRequest(activeAdBreakState: ActiveAdBreakState, activeAdState?: ActiveAdState) {\n const adSample: AdSample = {\n // set common fields from playback sample (if already created)\n ...buildAdSample(this.analytics.sample),\n // set ad break fields\n ...activeAdBreakState,\n // set ad fields (if any)\n ...(activeAdState || buildInitialActiveAdState()),\n };\n\n const moduleInfo = this.adapter.getAdModuleInfo();\n adSample.platform = 'web';\n adSample.analyticsVersion = VERSION;\n adSample.adModule = moduleInfo.name;\n adSample.adModuleVersion = moduleInfo.version;\n adSample.autoplay = this.adapter.getAutoPlay();\n adSample.pageLoadType = Utils.getPageLoadType();\n\n adSample.time = Date.now();\n adSample.adImpressionId = generateUUID();\n adSample.percentageInViewport = Utils.calculatePercentage(adSample.timeInViewport, adSample.timePlayed);\n this.analytics.backend.sendAdRequest(adSample);\n }\n\n private updatePlayingTime(activeAdState: ActiveAdState) {\n const timestamp = Date.now();\n if (this.beginPlayingTimestamp && this.isPlaying) {\n if (activeAdState.timePlayed !== undefined) {\n activeAdState.timePlayed += timestamp - this.beginPlayingTimestamp;\n }\n if (this.isContainerInViewport() && this.enterViewportTimestamp && activeAdState.timeInViewport !== undefined) {\n activeAdState.timeInViewport += timestamp - this.enterViewportTimestamp;\n }\n }\n }\n\n private startAd(activeAdState: ActiveAdState) {\n activeAdState.started = 1;\n activeAdState.timePlayed = 0;\n activeAdState.timeInViewport = 0;\n activeAdState.adPodPosition = this.adPodPosition;\n const timestamp = Date.now();\n this.beginPlayingTimestamp = timestamp;\n this.enterViewportTimestamp = this.isContainerInViewport() ? timestamp : undefined;\n this.isPlaying = true;\n this.currentTime = 0;\n this.adPodPosition++;\n this.currentTimeInterval = setInterval(() => {\n try {\n if (activeAdState?.adDuration != null && activeAdState.adDuration > 0 && this.adapter.isLinearAdActive()) {\n this.currentTime = Utils.calculateTime(Math.max(this.adapter.currentTime(), 0));\n }\n } catch (e) {\n logger.log('AdStarted monitoring interval failed and got cleared', e);\n this.resetActiveAd();\n }\n }, AdAnalytics.TIMEOUT_CURRENT_TIME_INTERVAL);\n }\n\n private completeAd(\n activeAdBreakState: ActiveAdBreakState,\n activeAdState: ActiveAdState = buildInitialActiveAdState(),\n exitPosition?: number,\n ) {\n activeAdState.exitPosition = exitPosition;\n activeAdState.playPercentage = Utils.calculatePercentage(activeAdState.exitPosition, activeAdState.adDuration);\n\n // Fallback to set quartile properties (if not set yet)\n // For players that don't emit native quartile events (THEOplayer) we calculate quartile properties based on playPercentage\n if (isNotNullish(activeAdState.playPercentage)) {\n if (activeAdState.quartile1 === 0 && activeAdState.playPercentage >= 25) {\n activeAdState.quartile1 = 1;\n }\n if (activeAdState.midpoint === 0 && activeAdState.playPercentage >= 50) {\n activeAdState.midpoint = 1;\n }\n if (activeAdState.quartile3 === 0 && activeAdState.playPercentage >= 75) {\n activeAdState.quartile3 = 1;\n }\n }\n\n // reset startupTimestamp for the next ad, in case there are multiple ads in one ad break\n this.adStartupTimestamp = Date.now();\n this.updatePlayingTime(activeAdState);\n this.isPlaying = false;\n this.sendAnalyticsRequest(activeAdBreakState, activeAdState);\n }\n\n private resetActiveAd() {\n this.clearCurrentTimeInterval();\n this.activeAdState = undefined;\n }\n\n private clearCurrentTimeInterval() {\n clearInterval(this.currentTimeInterval);\n delete this.currentTime;\n }\n}\n\n/**\n * Used to track the state of the active ad break.\n *\n * It is partial of {@link AdSample} because it's purpose is to build the final {@link AdSample}.\n */\ntype ActiveAdBreakState = Pick<\n AdSample,\n | 'adFallbackIndex'\n | 'adIdPlayer'\n | 'adIsPersistent'\n | 'adOffset'\n | 'adPosition'\n | 'adPreloadOffset'\n | 'adReplaceContentDuration'\n | 'adScheduleTime'\n | 'adTagPath'\n | 'adTagServer'\n | 'adTagType'\n | 'adTagUrl'\n | 'errorCode'\n | 'errorData'\n | 'errorMessage'\n | 'errorSeverity'\n | 'manifestDownloadTime'\n>;\n\nexport function buildInitialActiveAdBreakState(adBreakInfo?: AdBreakInfo): ActiveAdBreakState {\n const state: ActiveAdBreakState = {adFallbackIndex: 0};\n\n if (isNullish(adBreakInfo)) {\n return state;\n }\n\n state.adIdPlayer = adBreakInfo.id;\n state.adReplaceContentDuration = Utils.calculateTimeWithUndefined(adBreakInfo.replaceContentDuration);\n state.adIsPersistent = adBreakInfo.persistent;\n state.adTagType = adBreakInfo.tagType;\n state.adTagUrl = adBreakInfo.tagUrl;\n state.adPreloadOffset = Utils.calculateTimeWithUndefined(adBreakInfo.preloadOffset);\n state.adFallbackIndex = adBreakInfo.fallbackIndex ?? 0;\n state.manifestDownloadTime = Utils.calculateTimeWithUndefined(adBreakInfo.manifestDownloadTime);\n\n if (adBreakInfo.position === 'pre' || adBreakInfo.position === 'post') {\n state.adPosition = adBreakInfo.position;\n } else if (isNotNullish(adBreakInfo.position)) {\n state.adPosition = 'mid';\n state.adOffset = adBreakInfo.position;\n }\n\n if (isNotNullish(state.adTagUrl)) {\n try {\n const adTagUrl = new URL(state.adTagUrl);\n state.adTagServer = adTagUrl.hostname;\n state.adTagPath = adTagUrl.pathname;\n } catch {\n // Invalid URL, leave fields undefined\n }\n }\n\n if (isFiniteNumber(adBreakInfo.scheduleTime)) {\n state.adScheduleTime = Utils.calculateTime(adBreakInfo.scheduleTime);\n }\n\n return state;\n}\n\n/**\n * Used to track the state of the active ad in ad break.\n *\n * It is partial of {@link AdSample} because it's purpose is to build the final {@link AdSample}.\n */\ntype ActiveAdState = Pick<\n AdSample,\n | 'adClickthroughUrl'\n | 'adDescription'\n | 'adDuration'\n | 'adId'\n | 'adPlaybackHeight'\n | 'adPlaybackWidth'\n | 'adPodPosition'\n | 'adSkipAfter'\n | 'adSkippable'\n | 'adStartupTime'\n | 'adSystem'\n | 'adTitle'\n | 'advertiserName'\n | 'apiFramework'\n | 'clicked'\n | 'clickPercentage'\n | 'clickPosition'\n | 'closed'\n | 'closePercentage'\n | 'closePosition'\n | 'completed'\n | 'creativeAdId'\n | 'creativeId'\n | 'errorPercentage'\n | 'errorPosition'\n | 'exitPosition'\n | 'isLinear'\n | 'mediaPath'\n | 'mediaServer'\n | 'mediaUrl'\n | 'midpoint'\n | 'minSuggestedDuration'\n | 'playPercentage'\n | 'quartile1'\n | 'quartile3'\n | 'skipped'\n | 'skipPercentage'\n | 'skipPosition'\n | 'started'\n | 'streamFormat'\n | 'surveyUrl'\n | 'timeInViewport'\n | 'timePlayed'\n | 'universalAdIdRegistry'\n | 'universalAdIdValue'\n | 'videoBitrate'\n | 'wrapperAdsCount'\n>;\n\nexport function buildInitialActiveAdState(adInfo?: AdInfo): ActiveAdState {\n const state: ActiveAdState = {\n clicked: 0,\n closed: 0,\n completed: 0,\n midpoint: 0,\n quartile1: 0,\n quartile3: 0,\n skipped: 0,\n started: 0,\n };\n\n if (isNullish(adInfo)) {\n return state;\n }\n\n state.adClickthroughUrl = adInfo.clickThroughUrl;\n state.adId = adInfo.id;\n state.mediaUrl = adInfo.mediaUrl;\n state.isLinear = adInfo.isLinear;\n state.adPlaybackHeight = adInfo.height;\n state.adPlaybackWidth = adInfo.width;\n state.streamFormat = adInfo.mimeType;\n\n if (isNotNullish(state.mediaUrl)) {\n try {\n const mediaUrl = new URL(state.mediaUrl);\n state.mediaPath = mediaUrl.pathname;\n state.mediaServer = mediaUrl.hostname;\n } catch {\n // Invalid URL, leave fields undefined\n }\n }\n\n if (isNotNullish(adInfo.bitrate)) {\n state.videoBitrate = adInfo.bitrate * 1000;\n }\n\n const vastData = adInfo.vastData;\n if (isNotNullish(vastData)) {\n state.adSystem = vastData.adSystem;\n state.advertiserName = vastData.advertiserName;\n state.apiFramework = vastData.apiFramework;\n state.creativeAdId = vastData.creativeAdId;\n state.creativeId = vastData.creativeId;\n state.universalAdIdRegistry = vastData.universalAdIdRegistry;\n state.universalAdIdValue = vastData.universalAdIdValue;\n state.adDescription = vastData.adDescription;\n state.minSuggestedDuration = Utils.calculateTimeWithUndefined(vastData.minSuggestedDuration);\n state.surveyUrl = vastData.surveyUrl;\n state.adTitle = vastData.adTitle;\n state.wrapperAdsCount = vastData.wrapperAdsCount;\n }\n\n if (isNotNullish(adInfo.skippableAfter)) {\n state.adSkipAfter =\n adInfo.skippableAfter === -1 ? adInfo.skippableAfter : Utils.calculateTime(adInfo.skippableAfter);\n }\n\n state.adSkippable = adInfo.skippable ?? (isNotNullish(state.adSkipAfter) ? state.adSkipAfter >= 0 : undefined);\n state.adDuration = Utils.calculateTimeWithUndefined(adInfo.duration);\n\n return state;\n}\n","import {InternalAdapterAPI} from '../adapters/internal/InternalAdapterAPI';\nimport {AD_TYPE} from '../enums/AdType';\nimport {ErrorCode} from '../enums/ErrorCode';\nimport {PlayerSize} from '../enums/PlayerSize';\nimport {VideoStartFailedReason} from '../enums/VideoStartFailedReason';\nimport {ErrorDetailTrackingSettingsProvider} from '../features/errordetails/ErrorDetailTracking';\nimport {OnErrorDetailEventObject} from '../features/errordetails/OnErrorDetailEventObject';\nimport {FeatureManager} from '../features/FeatureManager';\nimport type {AnalyticsConfig, AnalyticsError} from '../types/AnalyticsConfig';\nimport {AuthenticationCallback} from '../types/AuthenticationCallback';\nimport {CustomDataValues, extractCustomDataFieldsOnly} from '../types/CustomDataValues';\nimport type {QualityChangeEvent} from '../types/EventData';\nimport * as EventData from '../types/EventData';\nimport {FeatureConfigContainer} from '../types/FeatureConfigContainer';\nimport {PlaybackInfo} from '../types/PlaybackInfo';\nimport {Sample} from '../types/Sample';\nimport type {SourceMetadata} from '../types/SourceMetadata';\nimport Timespan from '../types/Timespan';\nimport {\n applySourceMetadataToAnalyticsConfig,\n getDeviceInformationFromAnalyticsConfig,\n getDomainFromAnalyticsConfig,\n guardAgainstDuplicatedUserId,\n guardConfigChangeAgainstMissingIsLive,\n guardConfigChangeAgainstMissingTitle,\n mergeAnalyticsConfig,\n} from '../utils/analyticsConfigUtils';\nimport {CodecHelper} from '../utils/CodecHelper';\nimport {globalScope} from '../utils/globalScope';\nimport {\n getGlobalNavigatorLanguage,\n getGlobalNavigatorUserAgent,\n getGlobalScreenDimensions,\n hasGlobalWebOSApi,\n} from '../utils/globalScopeUtils';\nimport {logger} from '../utils/Logger';\nimport {isFiniteNumber, isNumber} from '../utils/numberUtils';\nimport {clearSampleStateValues, getDefaultSamplePath} from '../utils/sampleUtils';\nimport {isBlank, isValidString} from '../utils/stringUtils';\nimport * as Utils from '../utils/Utils';\nimport {isErrorSeverity, isNotNullish, isNullish, tryJSONStringify} from '../utils/Utils';\nimport {generateUUID} from '../utils/uuidUtils';\nimport {VERSION} from '../utils/Version';\nimport {getWebOSTVModelName} from '../utils/WebOSUtils';\n\nimport {AdAnalytics} from './AdAnalytics';\nimport {Backend} from './Backend';\nimport {BackendFactory} from './BackendFactory';\nimport {EventDispatcher, Subscribable} from './EventDispatcher';\nimport {IdenticalErrorReportingLimiter} from './IdenticalErrorReportingLimiter';\nimport {NoOpBackend} from './NoOpBackend';\nimport {SessionPersistenceHandler} from './SessionPersistenceHandler';\nimport {\n isSsaiEngagementErrorData,\n isSsaiEngagementQuartileData,\n isSsaiEngagementStartedData,\n SsaiEngagementInteractionData,\n} from './ssai/ssaiEngagementInteractionData';\nimport {createErrorAdSample, createQuartileAdSample, createStartedAdSample} from './ssai/ssaiUtils';\n\nexport class Analytics {\n get version(): string {\n return VERSION;\n }\n\n static version: string = VERSION;\n\n private readonly adAnalytics: AdAnalytics | undefined;\n\n sample: Sample;\n\n private hasSentStartupSample = false;\n backend!: Backend;\n readonly errorDetailTrackingSettingsProvider: ErrorDetailTrackingSettingsProvider;\n\n private config: AnalyticsConfig;\n private droppedSampleFrames = 0;\n /**\n * Used to save and store player startup time once the \"setup sample\" is created, to pick it up and use it to set\n * the \"startup sample\" property \"startupTime\" as a sum of player and video startup time.\n */\n private playerStartupTime = 0;\n\n private readonly authenticationCallback: AuthenticationCallback = {\n authenticationCompleted: (success: boolean, featureConfigs?: FeatureConfigContainer) => {\n this.featureManager.configureFeatures(success, featureConfigs);\n },\n };\n\n // used only in tests to inject mocks\n constructor(\n initialAnalyticsConfig: AnalyticsConfig,\n private readonly adapter: InternalAdapterAPI,\n private readonly backendFactory: BackendFactory,\n private readonly sessionHandler: SessionPersistenceHandler,\n private readonly featureManager: FeatureManager<FeatureConfigContainer>,\n private readonly onErrorDetailEventDispatcher: EventDispatcher<OnErrorDetailEventObject>,\n private readonly identicalErrorReportingLimiter: IdenticalErrorReportingLimiter,\n ) {\n this.config = initialAnalyticsConfig;\n this.sessionHandler = new SessionPersistenceHandler(this.config);\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const that = this;\n this.errorDetailTrackingSettingsProvider = {\n get domain() {\n return getDomainFromAnalyticsConfig(that.config);\n },\n get licenseKey() {\n return that.config.key ?? '';\n },\n get impressionId() {\n return that.getCurrentImpressionId() ?? '';\n },\n get collectorConfig() {\n return that.config.config;\n },\n };\n\n const licenseKeyReceivedUnsubscriber = this.adapter.onLicenseKeyReceived.subscribe(\n (eventArgs: {licenseKey: string}) => {\n if (!this.config.key) {\n this.config.key = eventArgs.licenseKey;\n }\n licenseKeyReceivedUnsubscriber();\n },\n );\n\n this.sample = this.buildInitialSample();\n this.droppedSampleFrames = 0;\n this.init();\n this.setupStateMachineCallbacks();\n\n // initialize adapter (start to listen to the player events and call the callbacks accordingly)\n const features = this.adapter.initialize(this);\n this.featureManager.registerFeatures(features);\n\n if (this.adapter.adModule) {\n // this needs to be called after the adapter has been initialized and has created adModule (if any)\n this.adAnalytics = new AdAnalytics(this, this.adapter.adModule);\n }\n }\n\n get errorDetailSubscribable(): Subscribable<OnErrorDetailEventObject> {\n return this.onErrorDetailEventDispatcher;\n }\n\n init() {\n if (\n this.adapter.supportsDeferredLicenseLoading !== true &&\n (!isValidString(this.config.key) || isBlank(this.config.key))\n ) {\n logger.errorMessageToUser('Invalid analytics license key provided');\n return;\n }\n\n logger.initialize(this.config.debug);\n\n this.featureManager.resetFeatures();\n\n const domain = getDomainFromAnalyticsConfig(this.config);\n this.backend = this.backendFactory.createBackend(\n this.config,\n {key: this.config.key, domain, version: VERSION},\n this.adapter,\n this.authenticationCallback,\n );\n\n this.hasSentStartupSample = false;\n this.identicalErrorReportingLimiter.reset();\n\n this.setConfigParameters();\n this.setAutoDetectedDeviceInformation();\n this.sample.impressionId = generateUUID();\n this.sample.userId = this.sessionHandler.userId;\n\n if (this.adapter.videoCompletionTracker) {\n this.adapter.videoCompletionTracker.reset();\n }\n\n this.adapter.qualityChangeService.resetValues();\n this.adapter.ssaiService.resetSourceRelatedState();\n }\n\n setConfigParameters() {\n this.sample.key = this.config.key;\n this.sample.playerKey = this.config.playerKey;\n if (this.config.player) {\n this.sample.player = this.config.player;\n }\n this.sample.domain = getDomainFromAnalyticsConfig(this.config);\n\n this.sample.deviceInformation = getDeviceInformationFromAnalyticsConfig(this.config);\n\n this.sample.isLive = isNotNullish(this.config.isLive) ? this.config.isLive : false;\n\n this.sample.cdnProvider = this.config.cdnProvider;\n this.sample.videoId = this.config.videoId;\n this.sample.videoTitle = this.config.title;\n this.sample.customUserId = this.config.userId ?? this.config.customUserId;\n\n Utils.transferCustomDataFields(this.config, this.sample);\n\n this.sample.experimentName = this.config.experimentName;\n }\n\n setAutoDetectedDeviceInformation(): void {\n // do not overwrite existing model value (set through config)\n if (isNotNullish(this.sample.deviceInformation?.model)) {\n return;\n }\n\n if (!hasGlobalWebOSApi()) return;\n\n const modelName = getWebOSTVModelName();\n if (isNullish(modelName)) return;\n\n this.sample.deviceInformation = this.sample.deviceInformation ?? {};\n this.sample.deviceInformation.model = modelName;\n }\n\n private setupStateMachineCallbacks() {\n // All of these are called in the onLeaveState Method.\n // So it's the last sample\n this.adapter.stateMachineCallbacks.setup = (duration: number, state: string) => {\n logger.log(\n 'Setup bitmovin analytics ' + this.sample.analyticsVersion + ' with impressionId: ' + this.sample.impressionId,\n );\n\n this.setDuration(duration);\n this.setState(state);\n this.sample.playerStartupTime = duration;\n this.playerStartupTime = this.sample.playerStartupTime;\n\n const navigationStart = globalScope.performance?.timing?.navigationStart;\n if (isNotNullish(navigationStart) && isFiniteNumber(navigationStart)) {\n // round the final time to a whole number to avoid unnecessary precision (performance API returns a high-precision timestamp as double)\n const pageLoadTime = Math.round(Date.now() - globalScope.performance.timing.navigationStart);\n this.sample.pageLoadTime = pageLoadTime;\n }\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.startup = (duration: number, state: string) => {\n this.setState(state);\n this.sample.supportedVideoCodecs = CodecHelper.supportedVideoFormats;\n // videoStartupTime has to be > 0 on startup sample\n // it is used to mark a successfull impression and billing depends on it\n const sanitizeVideoStartupTime = Math.max(duration, 1);\n this.setDuration(sanitizeVideoStartupTime);\n this.sample.videoStartupTime = sanitizeVideoStartupTime;\n this.sample.startupTime = (this.playerStartupTime || 0) + sanitizeVideoStartupTime;\n\n this.sample.autoplay = this.adapter.getAutoPlay();\n\n const drmPerformance = this.adapter.getDrmPerformanceInfo();\n if (isNotNullish(drmPerformance)) {\n this.sample.drmType = drmPerformance.drmType;\n this.sample.drmLoadTime = drmPerformance.drmLoadTime;\n }\n\n const {videoBitrate, audioBitrate} = this.adapter.getCurrentPlaybackInfo();\n // set the flag to allow quality change events after startup and try to set the startup bitrate values (if any)\n // as the initial ones, to be able to compare them with future quality changes\n this.adapter.qualityChangeService.setStartupHasFinished(videoBitrate, audioBitrate);\n\n this.hasSentStartupSample = true;\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.programChange = (sourceMetadata: SourceMetadata) => {\n // reset analytics\n // player is already loaded, so it is irrelevant for the program change startup sample\n this.playerStartupTime = 0;\n\n // apply source metadata to config\n this.config = applySourceMetadataToAnalyticsConfig(this.config, sourceMetadata);\n\n // reset sample to init values\n this.sample = this.buildInitialSample();\n // apply a source metadata path to the sample (if any)\n this.sample.path = isValidString(sourceMetadata.path) ? sourceMetadata.path : getDefaultSamplePath();\n\n // reinitialize to finish reset of the Analytics module\n this.init();\n\n // build startup \"programchange\" sample\n this.setState('programchange');\n this.sample.isProgramChange = true;\n this.sample.supportedVideoCodecs = CodecHelper.supportedVideoFormats;\n // videoStartupTime has to be > 0 on the startup sample\n // it is used to mark a successful impression and billing depends on it\n const programChangeVideoStartupTime = 1;\n this.setDuration(programChangeVideoStartupTime);\n this.sample.videoStartupTime = programChangeVideoStartupTime;\n this.sample.startupTime = programChangeVideoStartupTime; // is not affected now by player startup time\n\n this.sample.autoplay = this.adapter.getAutoPlay();\n\n // DRM load time is only important when we load the source, DRM request does not happen between active playback\n // so it can't happen during the program change\n this.sample.drmType = undefined;\n this.sample.drmLoadTime = undefined;\n\n const {videoBitrate, audioBitrate} = this.adapter.getCurrentPlaybackInfo();\n // set the flag to allow quality change events after startup and try to set the startup bitrate values (if any)\n // as the initial ones, to be able to compare them with future quality changes\n this.adapter.qualityChangeService.setStartupHasFinished(videoBitrate, audioBitrate);\n\n this.hasSentStartupSample = true;\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.updateSourceMetadata = (sourceMetadata: SourceMetadata) => {\n // apply source metadata to config\n this.config = applySourceMetadataToAnalyticsConfig(this.config, sourceMetadata);\n // new config should be immediately applied to the current sample\n this.setConfigParameters();\n this.setAutoDetectedDeviceInformation();\n // apply a source metadata path to the sample (if any)\n this.sample.path = isValidString(sourceMetadata.path) ? sourceMetadata.path : getDefaultSamplePath();\n };\n\n this.adapter.stateMachineCallbacks.playing = (duration: number, state: string) => {\n this.setDuration(duration);\n this.setState(state);\n this.sample.played = duration;\n this.setCompletionValues();\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.unload = (duration: number, state: string) => {\n let videoStartForClosedState = this.sample.videoTimeStart;\n if (state === 'playing') {\n this.setDuration(duration);\n this.setState(state);\n this.sample.played = duration;\n this.setCompletionValues();\n if (isNumber(this.sample.videoTimeEnd)) {\n videoStartForClosedState = this.sample.videoTimeEnd;\n }\n\n this.backend.sendUnloadRequest(this.sample);\n clearSampleStateValues(this.sample);\n }\n\n if (this.hasSentStartupSample) {\n this.setVideoTimeStart(videoStartForClosedState);\n this.setVideoTimeEnd(videoStartForClosedState);\n this.setState('closed');\n\n this.backend.sendUnloadRequest(this.sample);\n clearSampleStateValues(this.sample);\n }\n };\n\n this.adapter.stateMachineCallbacks.heartbeat = (duration, state, heartbeatPayload) => {\n this.setState(state);\n this.setDuration(duration);\n\n this.sample = {\n ...this.sample,\n ...heartbeatPayload,\n };\n\n if (state === 'playing') {\n this.setCompletionValues();\n }\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.qualitychange = (event: QualityChangeEvent) => {\n this.adapter.qualityChangeService.startResetInterval();\n this.adapter.qualityChangeService.increaseCounter();\n\n if (this.adapter.qualityChangeService.hasExceededQualityChangeThreshold()) {\n this.adapter.stateMachineCallbacks.error({\n code: ErrorCode.QUALITY_CHANGE_THRESHOLD_EXCEEDED.code,\n message: ErrorCode.QUALITY_CHANGE_THRESHOLD_EXCEEDED.message,\n errorSeverity: ErrorCode.QUALITY_CHANGE_THRESHOLD_EXCEEDED.errorSeverity,\n legacyData: undefined,\n data: {},\n currentTime: event.currentTime,\n });\n return;\n }\n\n this.setState('qualitychange');\n this.setDuration(0);\n this.adapter.stateMachineCallbacks.setVideoTimeEndFromEvent(event);\n this.adapter.stateMachineCallbacks.setVideoTimeStartFromEvent(event);\n this.adapter.stateMachineCallbacks.updateSampleQualityInfo(event);\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.updateSampleQualityInfo = (event: QualityChangeEvent) => {\n if (event.type === 'audio') {\n if (isNumber(event.bitrate)) {\n this.sample.audioBitrate = event.bitrate;\n }\n if (isValidString(event.codec)) {\n this.sample.audioCodec = event.codec;\n }\n } else if (event.type === 'video') {\n if (isNumber(event.bitrate)) {\n this.sample.videoBitrate = event.bitrate;\n }\n if (isValidString(event.codec)) {\n this.sample.videoCodec = event.codec;\n }\n if (isNumber(event.height)) {\n this.sample.videoPlaybackHeight = event.height;\n }\n if (isNumber(event.width)) {\n this.sample.videoPlaybackWidth = event.width;\n }\n }\n };\n\n this.adapter.stateMachineCallbacks.audiotrack_changing = () => {\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.pause = (duration: number, state: string) => {\n this.setDuration(duration);\n this.setState(state);\n\n this.sample.paused = duration;\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.seeking = (duration: number) => {\n this.setDuration(duration);\n this.setState('seeking');\n this.sample.seeked = duration;\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.buffering = (duration: number, state: string) => {\n this.setDuration(duration);\n this.setState(state);\n\n this.sample.buffered = duration;\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.videoStartFailed = (duration, reason) => {\n this.setState('startup');\n this.sample.videoStartFailed = true;\n this.sample.videoStartFailedReason = reason;\n this.sample.duration = duration;\n\n if (reason === VideoStartFailedReason.PLAYER_ERROR) {\n // on player error we should not send a video startup sample\n return;\n }\n\n if (reason === VideoStartFailedReason.TIMEOUT) {\n this.sample.errorCode = ErrorCode.VIDEO_STARTUP_TIMEOUT_REACHED.code;\n this.sample.errorMessage = ErrorCode.VIDEO_STARTUP_TIMEOUT_REACHED.message;\n this.sample.errorSeverity = ErrorCode.VIDEO_STARTUP_TIMEOUT_REACHED.errorSeverity;\n\n this.onErrorDetailEventDispatcher.dispatch({\n code: ErrorCode.VIDEO_STARTUP_TIMEOUT_REACHED.code,\n message: ErrorCode.VIDEO_STARTUP_TIMEOUT_REACHED.message,\n severity: ErrorCode.VIDEO_STARTUP_TIMEOUT_REACHED.errorSeverity,\n });\n }\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.error = (event: Readonly<EventData.ErrorEvent>) => {\n const error = this.transformError(\n {code: event.code, message: event.message, severity: event.errorSeverity ?? 'CRITICAL'},\n event.originalError,\n );\n\n if (error.code && !this.identicalErrorReportingLimiter.shouldReportError(error.code, error.severity)) {\n logger.log(\n `Bitmovin Analytics: Processing of the error with code ${error.code} was ignored because the error limit was exceeded.`,\n );\n return;\n }\n\n this.adapter.stateMachineCallbacks.setVideoTimeEndFromEvent(event);\n this.adapter.stateMachineCallbacks.setVideoTimeStartFromEvent(event);\n\n this.setState('error');\n this.setDuration(0);\n this.sample.errorCode = error.code;\n this.sample.errorMessage = error.message;\n this.sample.errorSeverity = error.severity;\n this.sample.errorData = tryJSONStringify(event.legacyData);\n this.sample.errorSegments = this.adapter.getSegmentInfo().map((s) => s.name);\n\n if (this.adapter.onError) {\n this.adapter.onError();\n }\n\n this.onErrorDetailEventDispatcher.dispatch({\n code: error.code,\n message: error.message,\n severity: error.severity,\n errorData: event.data,\n });\n\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.ad = (duration: number, state: string) => {\n this.setDuration(duration);\n this.setState(state);\n this.sample.ad = AD_TYPE.CSAI;\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.mute = () => {\n this.sample.isMuted = true;\n };\n\n this.adapter.stateMachineCallbacks.unMute = () => {\n this.sample.isMuted = false;\n };\n\n this.adapter.stateMachineCallbacks.subtitle_changing = () => {\n this.sendSample();\n };\n\n this.adapter.stateMachineCallbacks.setVideoTimeEndFromEvent = (analyticsEventBase) => {\n // if we don't have the current playback time, skip and do nothing\n if (!isNumber(analyticsEventBase?.currentTime)) {\n return;\n }\n\n this.setVideoTimeEnd(Utils.calculateTime(analyticsEventBase.currentTime));\n };\n\n this.adapter.stateMachineCallbacks.setVideoTimeStartFromEvent = (analyticsEventBase) => {\n // if we don't have the current playback time, skip and do nothing\n if (!isNumber(analyticsEventBase?.currentTime)) {\n return;\n }\n\n this.setVideoTimeStart(Utils.calculateTime(analyticsEventBase.currentTime));\n };\n\n this.adapter.stateMachineCallbacks.manualSourceChange = (event: {config: AnalyticsConfig}) => {\n this.adapter.resetSourceRelatedState();\n this.sample = this.buildInitialSample();\n this.droppedSampleFrames = 0;\n this.playerStartupTime = 0;\n this.config = Object.keys(event.config).length > 0 ? event.config : this.config;\n this.init();\n };\n\n this.adapter.stateMachineCallbacks.initialSourceChange = (event: {config: AnalyticsConfig}) => {\n this.config = event.config;\n this.setConfigParameters();\n this.setAutoDetectedDeviceInformation();\n };\n\n // The video has ended and we set up for a new impression\n this.adapter.stateMachineCallbacks.end = () => {\n // !!!! THIS IS OLD AND WRONG IMPLEMENTATION !!!!\n // (check deprecation comment on callback)\n this.sample = this.buildInitialSample();\n this.droppedSampleFrames = 0;\n this.playerStartupTime = 0;\n this.init();\n };\n\n this.adapter.stateMachineCallbacks.release = () => {\n this.backend = new NoOpBackend();\n this.adAnalytics?.release();\n this.adapter.qualityChangeService.stopResetInterval();\n this.identicalErrorReportingLimiter.reset();\n };\n\n this.adapter.stateMachineCallbacks.customdatachange = (_duration, _state, eventData) => {\n if (isNotNullish(eventData?.customDataValues)) {\n this.changeCustomData(eventData.customDataValues);\n }\n };\n }\n\n sourceChange = (config: AnalyticsConfig | null | undefined) => {\n logger.log('Processing Source Change for Analytics', config);\n if (isNullish(config)) {\n this.adapter.sourceChange(this.config);\n return;\n }\n\n guardConfigChangeAgainstMissingTitle(this.config, config);\n guardConfigChangeAgainstMissingIsLive(this.config, config);\n guardAgainstDuplicatedUserId(config);\n\n const newConfig = mergeAnalyticsConfig(this.config, config);\n this.adapter.sourceChange(newConfig);\n };\n\n setCustomDataOnce = (values: CustomDataValues) => {\n // save old config to be able to return previous custom data values once the sample is sent\n const oldConfig = {...this.config};\n\n this.setState('customdatachange');\n\n this.sendSample(values);\n // this method doesn't call changeCustomData() second time because in that method we have check for null values\n // to prevent overriding existing customData values with null if some field in object doesn't have value\n // because of that if some customData field had previous value null and it got changed to something else\n // it will not be possible to return it back to null using that method\n this.config = {...oldConfig};\n this.setConfigParameters();\n this.setAutoDetectedDeviceInformation();\n };\n\n setCustomData = (values: CustomDataValues) => {\n this.adapter.setCustomData(values);\n };\n\n getCurrentImpressionId = (): string | undefined => {\n return this.sample.impressionId;\n };\n\n getUserId = (): string => {\n return this.sessionHandler.userId;\n };\n\n setDuration(duration: number) {\n this.sample.duration = duration;\n }\n\n setState(state: string) {\n this.sample.state = state;\n }\n\n setPlaybackInfoFromAdapter() {\n const info = this.adapter.getCurrentPlaybackInfo();\n if (!info) {\n return;\n }\n\n // if set, we always apply `config.isLive` in favor of `info.isLive`\n this.sample.isLive = isNotNullish(this.config.isLive) ? this.config.isLive : info.isLive;\n // if `isLive` is still not defined, we set it to default `false` value\n if (isNullish(this.sample.isLive)) {\n this.sample.isLive = false;\n }\n\n if (isValidString(info.size)) {\n this.sample.size = info.size;\n }\n if (isValidString(info.playerTech)) {\n this.sample.playerTech = info.playerTech;\n }\n if (isNumber(info.videoDuration)) {\n this.sample.videoDuration = Utils.calculateTime(info.videoDuration || 0);\n }\n if (isValidString(info.streamFormat)) {\n this.sample.streamFormat = info.streamFormat;\n }\n if (isValidString(info.mpdUrl)) {\n this.sample.mpdUrl = info.mpdUrl;\n }\n if (isValidString(info.m3u8Url)) {\n this.sample.m3u8Url = info.m3u8Url;\n }\n if (isValidString(info.progUrl)) {\n this.sample.progUrl = info.progUrl;\n }\n if (isNumber(info.videoWindowWidth)) {\n this.sample.videoWindowWidth = info.videoWindowWidth;\n }\n if (isNumber(info.videoWindowHeight)) {\n this.sample.videoWindowHeight = info.videoWindowHeight;\n }\n if (isNumber(info.screenHeight)) {\n this.sample.screenHeight = info.screenHeight;\n }\n if (isNumber(info.screenWidth)) {\n this.sample.screenWidth = info.screenWidth;\n }\n if (Utils.isBoolean(info.isMuted)) {\n this.sample.isMuted = info.isMuted;\n }\n if (Utils.isBoolean(info.isCasting)) {\n this.sample.isCasting = info.isCasting;\n }\n if (isValidString(info.castTech)) {\n this.sample.castTech = info.castTech;\n }\n if (isValidString(info.videoTitle) && !this.config.title) {\n this.sample.videoTitle = info.videoTitle;\n }\n if (isValidString(info.audioCodec)) {\n this.sample.audioCodec = info.audioCodec;\n }\n if (isValidString(info.videoCodec)) {\n this.sample.videoCodec = info.videoCodec;\n }\n if (isValidString(info.audioLanguage)) {\n this.sample.audioLanguage = info.audioLanguage;\n }\n if (Utils.isBoolean(info.subtitleEnabled)) {\n this.sample.subtitleEnabled = info.subtitleEnabled;\n }\n if (isValidString(info.subtitleLanguage)) {\n this.sample.subtitleLanguage = info.subtitleLanguage;\n } else {\n this.sample.subtitleLanguage = undefined;\n }\n if (isNumber(info.droppedFrames)) {\n this.sample.droppedFrames = Math.max(info.droppedFrames - this.droppedSampleFrames, 0);\n this.droppedSampleFrames = info.droppedFrames;\n }\n }\n\n sendSample(customDataOnceValues?: CustomDataValues) {\n this.setPlaybackInfoFromAdapter();\n this.sample.time = Utils.getCurrentTimestamp();\n\n // get current download speed info from the adapter and set it on the sample before sending it\n this.sample.downloadSpeedInfo = this.adapter.getDownloadSpeedInfo();\n // reset current download speed info measures in the adapter to start fresh for the next sample,\n // so we always have the info for the current sample only\n this.adapter.resetDownloadSpeedInfoMeasures();\n\n this.adapter.ssaiService.manipulate(this.sample);\n\n // if we have received custom data from the setCustomDataOnce API call, we need to set\n // them as \"the last one\" (we need to override normal customData and SSAI custom data)\n if (customDataOnceValues != null) {\n this.changeCustomData(customDataOnceValues);\n }\n\n // Initial quality info should be available for the first sample after setup, so if there is no quality info yet, we try to set it *before* sending a sample.\n // In the general case, a qualitychange event first triggers a sample of the state we were in before the qualitychange sample itself is sent.\n // So to only report quality updates on the qualitychange sample and not the ones before it, we need to update the quality info *after* sending a sample,\n // making it available for future samples (e.g. qualitychange sample).\n // We only check videoBitrate and not audioBitrate since the latter is often reported as null/0 anyways.\n if (isNullish(this.sample.videoBitrate) || this.sample.videoBitrate <= 0) {\n setQualityInfoOnSample(this.sample, this.adapter.getCurrentPlaybackInfo());\n const copySample = {...this.sample};\n this.backend.sendRequest(copySample);\n } else {\n const copySample = {...this.sample};\n this.backend.sendRequest(copySample);\n setQualityInfoOnSample(this.sample, this.adapter.getCurrentPlaybackInfo());\n }\n\n // clear sample state values after sending a sample\n clearSampleStateValues(this.sample);\n }\n\n sendSsaiEngagementAdSample(data: SsaiEngagementInteractionData) {\n if (this.config.config?.ssaiEngagementTrackingEnabled !== true) {\n // if not enabled in config, do not send SSAI engagement AdSample\n return;\n }\n\n if (isSsaiEngagementStartedData(data)) {\n const ssaiAdSample = createStartedAdSample(this.sample, data);\n\n this.backend.sendAdRequest(ssaiAdSample);\n return;\n }\n\n if (isSsaiEngagementQuartileData(data)) {\n const ssaiAdSample = createQuartileAdSample(this.sample, data);\n\n this.backend.sendAdRequest(ssaiAdSample);\n return;\n }\n\n if (isSsaiEngagementErrorData(data)) {\n data.analyticsError = this.transformError(data.analyticsError, data.originalError);\n\n const ssaiErrorAdSample = createErrorAdSample(this.sample, data);\n\n this.backend.sendAdRequest(ssaiErrorAdSample);\n return;\n }\n }\n\n /**\n * This method sanitizes the input and updates the analytics config.\n * @param values Object containing the customData and other fields\n */\n private changeCustomData = (values: CustomDataValues) => {\n this.config = {\n ...this.config,\n ...extractCustomDataFieldsOnly(values),\n };\n this.setConfigParameters();\n this.setAutoDetectedDeviceInformation();\n };\n\n private setCompletionValues() {\n if (this.adapter.videoCompletionTracker) {\n const completed = this.adapter.videoCompletionTracker.addWatched({\n start: this.sample.videoTimeStart,\n end: this.sample.videoTimeEnd,\n } as Timespan);\n const completedTotal = this.adapter.videoCompletionTracker.getCompletionPercentage();\n\n if (!Number.isNaN(completed) && !Number.isNaN(completedTotal)) {\n this.sample.completed = completed;\n this.sample.completedTotal = completedTotal;\n }\n }\n }\n\n private setVideoTimeStart(value: number | undefined) {\n this.sample.videoTimeStart = value;\n }\n\n private setVideoTimeEnd(value: number | undefined) {\n this.sample.videoTimeEnd = value;\n }\n\n transformError(error: AnalyticsError, originalError: any): AnalyticsError {\n const analyticsError = {\n code: error.code,\n message: error.message,\n severity: error.severity,\n };\n\n try {\n const transformedError = this.config.config?.errorTransformerCallback?.transform(analyticsError, {\n originalError: originalError,\n });\n\n analyticsError.code = isNumber(transformedError?.code) ? transformedError?.code : analyticsError.code;\n analyticsError.message = isValidString(transformedError?.message)\n ? transformedError?.message\n : analyticsError.message;\n analyticsError.severity =\n isValidString(transformedError?.severity) && isErrorSeverity(transformedError?.severity)\n ? transformedError!.severity\n : analyticsError.severity;\n } catch (error) {\n logger.error('Error in errorTransformerCallback', error);\n }\n\n return analyticsError;\n }\n\n private buildInitialSample(): Sample {\n const player = this.config.player || this.adapter.getPlayerName();\n const screenDimensions = getGlobalScreenDimensions();\n\n return {\n ad: 0,\n analyticsVersion: VERSION,\n audioBitrate: 0,\n buffered: 0,\n completedTotal: 0,\n droppedFrames: 0,\n duration: 0,\n isLive: this.config.isLive ?? false,\n language: getGlobalNavigatorLanguage(),\n pageLoadTime: 0,\n pageLoadType: Utils.getPageLoadType(),\n path: getDefaultSamplePath(),\n paused: 0,\n platform: 'web',\n played: 0,\n player,\n playerStartupTime: 0,\n playerTech: this.adapter.getPlayerTech(),\n screenHeight: screenDimensions?.height,\n screenWidth: screenDimensions?.width,\n seeked: 0,\n size: PlayerSize.Window,\n startupTime: 0,\n time: 0,\n userAgent: getGlobalNavigatorUserAgent(),\n version: player + '-' + this.adapter.getPlayerVersion(),\n videoBitrate: 0,\n videoDuration: 0,\n videoPlaybackHeight: 0,\n videoPlaybackWidth: 0,\n videoStartupTime: 0,\n videoTimeEnd: 0,\n videoTimeStart: 0,\n videoWindowHeight: 0,\n videoWindowWidth: 0,\n };\n }\n\n static create(config: AnalyticsConfig, adapter: InternalAdapterAPI): Analytics {\n const backendFactory: BackendFactory = new BackendFactory();\n const sessionHandler: SessionPersistenceHandler = new SessionPersistenceHandler(config);\n const featureManager = new FeatureManager<FeatureConfigContainer>();\n const onErrorDetailEventDispatcher = new EventDispatcher<OnErrorDetailEventObject>();\n const identicalErrorReportingLimiter = new IdenticalErrorReportingLimiter();\n return new Analytics(\n config,\n adapter,\n backendFactory,\n sessionHandler,\n featureManager,\n onErrorDetailEventDispatcher,\n identicalErrorReportingLimiter,\n );\n }\n}\n\n// We separate the quality info from `setPlaybackInfoFromAdapter` to be able to explicitly set/update the quality info only when it changes.\nexport function setQualityInfoOnSample(sample: Sample, playbackInfo: PlaybackInfo) {\n if (isNumber(playbackInfo.videoPlaybackHeight)) {\n sample.videoPlaybackHeight = playbackInfo.videoPlaybackHeight;\n }\n if (isNumber(playbackInfo.videoPlaybackWidth)) {\n sample.videoPlaybackWidth = playbackInfo.videoPlaybackWidth;\n }\n if (isNumber(playbackInfo.videoBitrate)) {\n sample.videoBitrate = playbackInfo.videoBitrate;\n }\n if (isNumber(playbackInfo.audioBitrate)) {\n sample.audioBitrate = playbackInfo.audioBitrate;\n }\n}\n","import {DeferredLicenseLoadingAdapterAPI} from '../adapters/internal/DeferredLicenseLoadingAdapterAPI';\nimport {AnalyticsConfig, CollectorConfig} from '../types/AnalyticsConfig';\nimport {AuthenticationCallback} from '../types/AuthenticationCallback';\nimport {LicensingRequest} from '../types/LicensingRequest';\nimport {LicenseCall} from '../utils/LicenseCall';\nimport {ANALYTICS_BACKEND_BASE_URL} from '../utils/Settings';\n\nimport {Backend} from './Backend';\nimport {DebuggingBackend} from './DebuggingBackend';\nimport {LicenseCheckingBackend} from './LicenseCheckingBackend';\nimport {LongPlaytimeFilteringBackend} from './LongPlaytimeFilteringBackend';\nimport {NoOpBackend} from './NoOpBackend';\nimport {SequenceNumberBackend} from './SequenceNumberBackend';\n\nexport interface InternalCollectorConfig extends CollectorConfig {\n /**\n * Internal \"hidden\" collector config property.\n *\n * It is used only by the Bitmovin Player Testautomation Suite to insert \"AssertionBackend\" and to be able to intercept\n * all backend requests, thus enabling to test and verify of those requests.\n *\n * @see https://github.com/bitmovin-engineering/player-testing/blob/develop/lib/bitdashPlayerTest/analytics/AnalyticsAssertionBackend.ts\n */\n wrapBackend: (innerBackend: Backend) => Backend;\n}\n\nexport class BackendFactory {\n createBackend(\n analyticsConfig: AnalyticsConfig,\n licensingRequest: LicensingRequest,\n adapter: DeferredLicenseLoadingAdapterAPI,\n authenticationCallback: AuthenticationCallback,\n ): Backend {\n if (!this.isEnabled(analyticsConfig)) {\n return new NoOpBackend();\n }\n const inner = this.createInnerBackend(analyticsConfig, licensingRequest, adapter, authenticationCallback);\n return this.decorateWithDebuggingBackend(analyticsConfig, inner);\n }\n\n private decorateWithDebuggingBackend(config: AnalyticsConfig, backend: Backend): Backend {\n if (config.debug) {\n return new DebuggingBackend(config, backend);\n }\n return backend;\n }\n\n private decorateWithBackendFromConfigIfAvailable(analyticsConfig: AnalyticsConfig, innerBackend: Backend): Backend {\n if (\n analyticsConfig !== undefined &&\n analyticsConfig.config !== undefined &&\n (analyticsConfig.config as InternalCollectorConfig).wrapBackend !== undefined\n ) {\n return (analyticsConfig.config as InternalCollectorConfig).wrapBackend(innerBackend);\n }\n\n return innerBackend;\n }\n\n private isEnabled(analyticsConfig: AnalyticsConfig): boolean {\n return analyticsConfig.config === undefined || analyticsConfig.config.enabled !== false;\n }\n\n private createInnerBackend(\n analyticsConfig: AnalyticsConfig,\n licensingRequest: LicensingRequest,\n adapter: DeferredLicenseLoadingAdapterAPI,\n authenticationCallback: AuthenticationCallback,\n ): Backend {\n const backendUrl = (analyticsConfig.config && analyticsConfig.config.backendUrl) || ANALYTICS_BACKEND_BASE_URL;\n let innerBackend: Backend = new LicenseCheckingBackend(\n licensingRequest,\n LicenseCall,\n backendUrl,\n adapter,\n authenticationCallback,\n );\n innerBackend = this.decorateWithBackendFromConfigIfAvailable(analyticsConfig, innerBackend);\n\n const sequenceNumberAssigningBackend = new SequenceNumberBackend(innerBackend);\n return new LongPlaytimeFilteringBackend(sequenceNumberAssigningBackend);\n }\n}\n","import type {AdSample} from '../types/AdSample';\nimport type {AnalyticsConfig, AnalyticsDebugConfig} from '../types/AnalyticsConfig';\nimport type {Sample} from '../types/Sample';\nimport {logger} from '../utils/Logger';\n\nimport type {Backend} from './Backend';\n\n/**\n * The `DebuggingBackend` is responsible for printing debugging information\n * before forwarding the requests to the specified underlying backend.\n *\n * This allows for inspection of specific fields in the sample data before it is sent.\n * The fields can be specified through the {@link AnalyticsDebugConfig#fields}.\n *\n * @implements {Backend}\n * */\nexport class DebuggingBackend implements Backend {\n private readonly underlying: Backend;\n private readonly debugFields: string[] | undefined;\n\n constructor(config: AnalyticsConfig, underlying: Backend) {\n this.underlying = underlying;\n if (config.debug && (config.debug as AnalyticsDebugConfig).fields) {\n this.debugFields = (config.debug as AnalyticsDebugConfig).fields;\n }\n }\n\n sendRequest(sample: Sample): void {\n this.printFields(sample);\n this.underlying.sendRequest(sample);\n }\n\n sendUnloadRequest(sample: Sample): void {\n this.printFields(sample);\n this.underlying.sendUnloadRequest(sample);\n }\n\n sendAdRequest(adSample: AdSample): void {\n this.underlying.sendAdRequest(adSample);\n }\n\n private printFields(sample: Sample) {\n if (this.debugFields && this.debugFields.length) {\n const fields = {};\n this.debugFields.forEach((f) => (fields[f] = sample[f]));\n logger.table([fields]);\n }\n }\n}\n","import {DownloadSpeedInfo} from '../types/DownloadSpeedInfo';\nimport {SpeedMeasurement} from '../types/SpeedMeasurement';\nimport {Converter} from '../utils/Converter';\n\nimport {Measure} from './Measure';\n\nexport class DownloadSpeedMeter {\n protected measures: Measure[];\n\n constructor() {\n this.measures = [];\n }\n\n reset(): void {\n this.measures = [];\n }\n\n addMeasurement(measurement: SpeedMeasurement): void {\n if (measurement.httpStatus >= 400) {\n return;\n }\n const measure = new Measure(measurement);\n\n const threshold = Converter.bitsToBytes(300 * 1000 * 1000); // 300 Megabit per second in bytes\n if (measure.speed >= threshold) {\n return;\n }\n\n this.measures.push(measure);\n }\n\n getInfo(): DownloadSpeedInfo {\n return {\n segmentsDownloadCount: this.measures.length,\n segmentsDownloadSize: this.measures.map((m) => m.size).reduce(this.add, 0),\n segmentsDownloadTime: Math.ceil(this.totalTime() * 1000),\n avgDownloadSpeed: this.avgSpeed(),\n minDownloadSpeed: this.minSpeed(),\n maxDownloadSpeed: this.maxSpeed(),\n avgTimeToFirstByte: this.avgTimeToFirstByte(),\n };\n }\n\n private add(a: number, b: number): number {\n return a + b;\n }\n\n private avgSpeed(): number {\n if (this.measures.length === 0) {\n return 0;\n }\n const totalSpeed = this.speeds().reduce((a, b) => {\n return a + b;\n }, 0);\n const numMeasurements = this.measures.length;\n return this.bytePerSecondToBitPerSecond(totalSpeed / numMeasurements);\n }\n\n private bytePerSecondToBitPerSecond(bps: number): number {\n return Converter.bytesToBits(bps);\n }\n\n private minSpeed(): number {\n if (this.measures.length === 0) {\n return 0;\n }\n return this.bytePerSecondToBitPerSecond(Math.min(...this.speeds()));\n }\n\n private speeds(): number[] {\n return this.measures.map((m) => {\n return m.speed;\n });\n }\n\n private maxSpeed(): number {\n if (this.measures.length === 0) {\n return 0;\n }\n return this.bytePerSecondToBitPerSecond(Math.max(...this.speeds()));\n }\n\n private totalTime(): number {\n if (this.measures.length === 0) {\n return 0;\n }\n return this.measures.reduce((a, b) => {\n return a + b.duration;\n }, 0);\n }\n\n private avgTimeToFirstByte(): number {\n if (this.measures.length === 0) {\n return 0;\n }\n const avg =\n this.measures.reduce((a, b) => {\n return a + b.timeToFirstByte * 1000;\n }, 0) / this.measures.length;\n\n return Math.ceil(avg);\n }\n}\n","export interface Subscribable<TArgs> {\n subscribe(callback: EventHandler<TArgs>): () => void;\n unsubscribe(callback: EventHandler<TArgs>);\n}\n\ntype EventHandler<TArgs> = (args: TArgs) => void;\n\nexport class EventDispatcher<TArgs> implements Subscribable<TArgs> {\n private callbacks: Array<EventHandler<TArgs>> = [];\n\n subscribe(callback: EventHandler<TArgs>): () => void {\n this.callbacks.push(callback);\n\n return () => this.unsubscribe(callback);\n }\n\n dispatch(args: TArgs) {\n const callbacks = this.callbacks.slice(0);\n callbacks.forEach((callback) => {\n callback(args);\n });\n }\n\n unsubscribe(callback: EventHandler<TArgs>) {\n const index = this.callbacks.indexOf(callback);\n if (index > -1) {\n this.callbacks.splice(index, 1);\n }\n }\n\n get subscriberCount() {\n return this.callbacks.length;\n }\n}\n","export const DEFAULT_HEARTBEAT_INTERVAL_MS = 59700;\n\nexport interface HeartbeatListener {\n /**\n * @param playerCurrentTime the current player playback time of the video in seconds.\n */\n onHeartbeat: (playerCurrentTime: number) => void;\n}\n\n/** Get the current player playback time of the video in seconds. */\ntype PlayerCurrentTimeCallback = () => number;\n\nexport class HeartbeatService {\n private heartbeatInterval: ReturnType<typeof setInterval> | undefined;\n private listener: HeartbeatListener | undefined;\n private readonly getPlayerCurrentTime: PlayerCurrentTimeCallback;\n\n constructor(getPlayerCurrentTime: PlayerCurrentTimeCallback) {\n this.getPlayerCurrentTime = getPlayerCurrentTime;\n }\n\n setListener(listener: HeartbeatListener) {\n this.listener = listener;\n }\n\n startHeartbeat() {\n if (this.heartbeatInterval !== undefined) {\n this.clearHeartbeat();\n }\n this.heartbeatInterval = setInterval(() => {\n this.listener?.onHeartbeat(this.getPlayerCurrentTime());\n }, DEFAULT_HEARTBEAT_INTERVAL_MS);\n }\n\n stopHeartbeat() {\n this.clearHeartbeat();\n }\n\n private clearHeartbeat() {\n clearTimeout(this.heartbeatInterval);\n this.heartbeatInterval = undefined;\n }\n}\n","import {ErrorSeverity} from '../types/AnalyticsConfig';\n\n/**\n * This class is used to limit error reporting for identical consecutive error codes and severities per session.\n *\n * Repeated consecutive errors of the same code and severity are limited to {@link IdenticalErrorReportingLimiter.MAX_IDENTICAL_ERROR_REPORTING}.\n */\nexport class IdenticalErrorReportingLimiter {\n /** The maximum number of times the same error code and severity can be reported consecutively. */\n private static MAX_IDENTICAL_ERROR_REPORTING = 5;\n\n private _lastErrorCode: number | undefined;\n private _lastErrorSeverity: ErrorSeverity | undefined;\n private _currentErrorCount = 0;\n\n /**\n * Determines whether an error with the given errorCode and errorSeverity should be reported,\n * based on the limit of identical consecutive error reports.\n *\n * @param errorCode - The error code for which we are checking the reporting conditions.\n * @param errorSeverity - The error severity for which we are checking the reporting conditions.\n * @returns {boolean} - Returns true if the error can be reported, false if it exceeds the limits.\n */\n shouldReportError(errorCode: number, errorSeverity: ErrorSeverity): boolean {\n if (errorCode === this._lastErrorCode && errorSeverity === this._lastErrorSeverity) {\n this._currentErrorCount++;\n return this._currentErrorCount <= IdenticalErrorReportingLimiter.MAX_IDENTICAL_ERROR_REPORTING;\n }\n\n this._lastErrorCode = errorCode;\n this._lastErrorSeverity = errorSeverity;\n this._currentErrorCount = 1;\n return true;\n }\n\n reset() {\n this._lastErrorCode = undefined;\n this._lastErrorSeverity = undefined;\n this._currentErrorCount = 0;\n }\n}\n","import type {DeferredLicenseLoadingAdapterAPI} from '../adapters/internal/DeferredLicenseLoadingAdapterAPI';\nimport type {AdSample} from '../types/AdSample';\nimport type {AuthenticationCallback} from '../types/AuthenticationCallback';\nimport {LicenseCallFunc, LicensingRequest, LicensingResponse, LicensingResult} from '../types/LicensingRequest';\nimport type {Sample} from '../types/Sample';\nimport {logger} from '../utils/Logger';\nimport {ANALYTICS_LICENSECALL_TIMEOUT} from '../utils/Settings';\n\nimport type {Backend} from './Backend';\nimport {NoOpBackend} from './NoOpBackend';\nimport {QueueBackend} from './QueueBackend';\nimport {RemoteBackend} from './RemoteBackend';\n\n/**\n * The `LicenseCheckingBackend` class is responsible for sending license requests\n * and routing samples to the appropriate backend based on the license status.\n *\n * The class manages a queue of samples during the license check process, ensuring that\n * samples are not lost while the license status is being determined. Once the license\n * is validated, the queued samples are flushed to the appropriate backend.\n *\n * @implements {Backend}\n */\nexport class LicenseCheckingBackend implements Backend {\n promise?: Promise<LicensingResponse>;\n private licenseLazyLoadingTimeoutHandle?: ReturnType<typeof setTimeout>;\n private backend: Backend;\n private info: LicensingRequest;\n\n constructor(\n info: LicensingRequest,\n private licenseCall: LicenseCallFunc,\n private backendBaseUrl: string,\n private adapter: DeferredLicenseLoadingAdapterAPI,\n private authenticationCallback: AuthenticationCallback,\n ) {\n this.info = {...info};\n this.backend = new QueueBackend();\n this.licenseCall = licenseCall;\n\n if (info.key !== undefined && info.key !== '') {\n this.promise = this.wrapLicenseCheckPromiseWithCallback(this.performLicenseCheck(), this.authenticationCallback);\n } else if (adapter.supportsDeferredLicenseLoading === true) {\n adapter.onLicenseKeyReceived.subscribe(this.licenseKeyReceived);\n adapter.onLicenseCallFailed.subscribe(this.licenseCallFailed);\n this.licenseLazyLoadingTimeoutHandle = setTimeout(this.licenseLazyLoadingTimeout, ANALYTICS_LICENSECALL_TIMEOUT);\n } else {\n authenticationCallback.authenticationCompleted(false, undefined);\n this.backend = new NoOpBackend();\n }\n }\n\n performLicenseCheck(): Promise<LicensingResponse> {\n const {key, domain, version} = this.info;\n if (!key || key === '') {\n const error: LicensingResponse = {\n status: LicensingResult.Denied,\n message: 'No license key provided',\n };\n this.backend = new NoOpBackend();\n return Promise.resolve(error);\n }\n\n return this.licenseCall(key, domain, version, this.backendBaseUrl)\n .then((result) => {\n if (result.status === LicensingResult.Granted) {\n const remoteBackend = new RemoteBackend(this.backendBaseUrl, key);\n (this.backend as QueueBackend).flushTo(remoteBackend);\n this.backend = remoteBackend;\n } else {\n throw new Error(result.message);\n }\n return result;\n })\n .catch((err: Error) => {\n if (err.message === 'Ignoring Impression due to DNT Header being set') {\n logger.error('License Check for Bitmovin Analytics failed because of', err);\n } else {\n logger.errorMessageToUser('License Check for Bitmovin Analytics failed because of', err);\n }\n this.backend = new NoOpBackend();\n return {\n status: LicensingResult.Denied,\n message: err.message,\n };\n });\n }\n\n sendRequest(sample: Sample): void {\n this.backend.sendRequest(sample);\n }\n sendUnloadRequest(sample: Sample): void {\n this.backend.sendUnloadRequest(sample);\n }\n sendAdRequest(adSample: AdSample): void {\n this.backend.sendAdRequest(adSample);\n }\n\n private licenseKeyReceived = (eventArgs: {licenseKey: string}) => {\n clearTimeout(this.licenseLazyLoadingTimeoutHandle);\n this.unsubscribeFromAdapter();\n this.info.key = eventArgs.licenseKey;\n this.promise = this.wrapLicenseCheckPromiseWithCallback(this.performLicenseCheck(), this.authenticationCallback);\n };\n\n private licenseCallFailed = () => {\n clearTimeout(this.licenseLazyLoadingTimeoutHandle);\n this.unsubscribeFromAdapter();\n this.backend = new NoOpBackend();\n this.authenticationCallback.authenticationCompleted(false, undefined);\n };\n\n private licenseLazyLoadingTimeout = () => {\n this.unsubscribeFromAdapter();\n this.backend = new NoOpBackend();\n this.authenticationCallback.authenticationCompleted(false, undefined);\n };\n\n private unsubscribeFromAdapter() {\n this.adapter.onLicenseKeyReceived.unsubscribe(this.licenseKeyReceived);\n this.adapter.onLicenseCallFailed.unsubscribe(this.licenseCallFailed);\n }\n\n private wrapLicenseCheckPromiseWithCallback(\n promise: Promise<LicensingResponse>,\n authenticationCallback: AuthenticationCallback,\n ): Promise<LicensingResponse> {\n return promise.then((response) => {\n authenticationCallback.authenticationCompleted(response.status === LicensingResult.Granted, response.features);\n return response;\n });\n }\n}\n","import type {AdSample} from '../types/AdSample';\nimport type {Sample} from '../types/Sample';\nimport {isNullish} from '../utils/Utils';\n\nimport type {Backend} from './Backend';\n\n/**\n * The `LongPlaytimeFilteringBackend` is a decorator class that filters out samples\n * where the `played` time exceeds a specified threshold.\n *\n * If a sample's `played` time surpasses the threshold, it is not forwarded to the next backend.\n * Otherwise, the sample is passed along to the next backend for further processing.\n *\n * @implements {Backend}\n */\nexport class LongPlaytimeFilteringBackend implements Backend {\n readonly nextBackend: Backend;\n\n constructor(next: Backend) {\n this.nextBackend = next;\n }\n\n sendRequest(sample: Sample): void {\n if (this.isPlayedAboveThreshold(sample)) {\n return;\n }\n this.nextBackend.sendRequest(sample);\n }\n\n sendUnloadRequest(sample: Sample): void {\n if (this.isPlayedAboveThreshold(sample)) {\n return;\n }\n this.nextBackend.sendUnloadRequest(sample);\n }\n\n sendAdRequest(adSample: AdSample): void {\n this.nextBackend.sendAdRequest(adSample);\n }\n\n private isPlayedAboveThreshold(sample: Sample): boolean {\n return (isNullish(sample.played) ? 0 : sample.played) >= 90000;\n }\n}\n","import {SpeedMeasurement} from '../types/SpeedMeasurement';\n\nexport class Measure implements SpeedMeasurement {\n private download: SpeedMeasurement;\n\n get speed(): number {\n return this.download.size / this.download.duration;\n }\n get duration(): number {\n return this.download.duration;\n }\n get size(): number {\n return this.download.size;\n }\n get timeToFirstByte(): number {\n return this.download.timeToFirstByte;\n }\n get timestamp(): Date {\n return this.download.timestamp;\n }\n\n get httpStatus(): number {\n return this.download.httpStatus;\n }\n\n constructor(download: SpeedMeasurement) {\n this.download = download;\n }\n}\n","import type {AdSample} from '../types/AdSample';\nimport type {Sample} from '../types/Sample';\n\nimport type {Backend} from './Backend';\n\n/**\n * The `NoOpBackend` is a no-operation implementation of the `Backend` interface.\n * It serves as a placeholder backend when the actual `Backend` functionality is disabled or not required.\n * E.g. in scenarios such as releasing the adapter or when the Collector is disabled via {@link CollectorConfig#enabled}.\n *\n * Using `NoOpBackend` ensures that the code does not need to handle cases where `Backend` might be undefined,\n * thereby simplifying the logic and reducing the need for null or undefined checks.\n *\n * @implements {Backend}\n */\nexport class NoOpBackend implements Backend {\n sendRequest(_sample: Sample): void {\n // empty\n }\n sendUnloadRequest(_sample: Sample): void {\n // empty\n }\n sendAdRequest(_adSample: AdSample): void {\n throw new Error('Method not implemented.');\n }\n}\n","import {isFiniteNumber} from '../utils/numberUtils';\nimport * as Settings from '../utils/Settings';\n\nconst INITIAL_VALUE = 0;\n\n/**\n * This service is responsible for deciding whether a quality change event should be sent or not, based on\n * - the quality changes count that has already been sent in a certain timeframe/interval\n * - the previous video and audio bitrate values, to avoid sending the first quality change event or the following\n * events when the bitrate did not change (some players report quality changes with the same bitrate, which should\n * not be tracked)\n * - whether the startup has finished, to avoid sending quality change events for the initial bitrate values\n * that some players report before startup, which can differ from the ones that are used after startup\n */\nexport default class QualityChangeService {\n /** Flag to block quality change events when a certain threshold in a certain timeframe/interval is exceeded */\n private qualityChangeCount = INITIAL_VALUE;\n private qualityChangeCountResetIntervalId: ReturnType<typeof setInterval> | undefined;\n private readonly QUALITY_CHANGE_COUNT_THRESHOLD: number;\n\n /** Flag to block the first (initial) video quality change event or the following events when the bitrate did not change */\n private previousVideoBitrate = INITIAL_VALUE;\n /** Flag to block the first (initial) audio quality change event or the following events when the bitrate did not change */\n private previousAudioBitrate = INITIAL_VALUE;\n\n /** Flag to block quality change events until startup has finished */\n private startupHasFinished = false;\n\n constructor(qualityChangeCountThreshold: number = Settings.ANALYTICS_QUALITY_CHANGE_COUNT_THRESHOLD) {\n this.QUALITY_CHANGE_COUNT_THRESHOLD = qualityChangeCountThreshold;\n }\n\n resetValues() {\n this.qualityChangeCount = INITIAL_VALUE;\n this.stopResetInterval();\n\n this.previousVideoBitrate = INITIAL_VALUE;\n this.previousAudioBitrate = INITIAL_VALUE;\n\n this.startupHasFinished = false;\n }\n\n increaseCounter() {\n this.qualityChangeCount++;\n }\n\n hasExceededQualityChangeThreshold(): boolean {\n return this.qualityChangeCount > this.QUALITY_CHANGE_COUNT_THRESHOLD;\n }\n\n setStartupHasFinished(startupVideoBitrate: number | undefined, startupAudioBitrate: number | undefined): void {\n this.startupHasFinished = true;\n\n // check if the startup video bitrate value is known/defined and valid\n if (isFiniteNumber(startupVideoBitrate)) {\n this.previousVideoBitrate = startupVideoBitrate;\n }\n // check if the startup audio bitrate value is known/defined and valid\n if (isFiniteNumber(startupAudioBitrate)) {\n this.previousAudioBitrate = startupAudioBitrate;\n }\n }\n\n shouldAllowVideoQualityChange(newBitrate: number | undefined): boolean {\n return (\n // if the startup has finished\n this.startupHasFinished &&\n // if the new bitrate value is valid\n isFiniteNumber(newBitrate) &&\n // if the new bitrate is not the first one reported (the initial value is not still set)\n this.previousVideoBitrate !== INITIAL_VALUE &&\n // if the bitrate did change\n this.previousVideoBitrate !== newBitrate &&\n // if the quality change count threshold has not been exceeded\n !this.hasExceededQualityChangeThreshold()\n );\n }\n\n setVideoBitrate(newBitrate: number): void {\n if (this.startupHasFinished) {\n this.previousVideoBitrate = newBitrate;\n }\n }\n\n shouldAllowAudioQualityChange(newBitrate: number | undefined): boolean {\n return (\n // if the startup has finished\n this.startupHasFinished &&\n // if the new bitrate value is valid\n isFiniteNumber(newBitrate) &&\n // if the new bitrate is not the first one reported (the initial value is not still set)\n this.previousAudioBitrate !== INITIAL_VALUE &&\n // if the bitrate did change\n this.previousAudioBitrate !== newBitrate &&\n // if the quality change count threshold has not been exceeded\n !this.hasExceededQualityChangeThreshold()\n );\n }\n\n setAudioBitrate(newBitrate: number): void {\n if (this.startupHasFinished) {\n this.previousAudioBitrate = newBitrate;\n }\n }\n\n startResetInterval() {\n if (this.qualityChangeCountResetIntervalId !== undefined) {\n return;\n }\n\n this.qualityChangeCountResetIntervalId = setInterval(() => {\n this.qualityChangeCount = 0;\n }, Settings.ANALYTICS_QUALITY_CHANGE_COUNT_RESET_INTERVAL);\n }\n\n stopResetInterval() {\n if (this.qualityChangeCountResetIntervalId === undefined) {\n return;\n }\n\n clearInterval(this.qualityChangeCountResetIntervalId);\n delete this.qualityChangeCountResetIntervalId;\n }\n}\n","import type {AdSample} from '../types/AdSample';\nimport type {Sample} from '../types/Sample';\n\nimport type {Backend} from './Backend';\n\n/**\n * The `QueueBackend` class is responsible for queuing samples for deferred processing.\n * Samples are stored in different queues depending on the sample type and can be flushed\n * to another backend for further processing.\n *\n * This is useful e.g. to still collect sample data while waiting for a license call to succeed.\n *\n * @implements {Backend}\n */\nexport class QueueBackend implements Backend {\n private readonly queue: Sample[] = [];\n private readonly unloadQueue: Sample[] = [];\n private readonly adQueue: AdSample[] = [];\n\n sendRequest(sample: Sample): void {\n this.queue.push(sample);\n }\n sendUnloadRequest(sample: Sample): void {\n this.unloadQueue.push(sample);\n }\n sendAdRequest(adSample: AdSample): void {\n this.adQueue.push(adSample);\n }\n\n flushTo(backend: Backend) {\n this.queue.forEach((e) => {\n backend.sendRequest(e);\n });\n this.unloadQueue.forEach((e) => {\n backend.sendUnloadRequest(e);\n });\n this.adQueue.forEach((e) => {\n backend.sendAdRequest(e);\n });\n }\n}\n","import type {AdSample} from '../types/AdSample';\nimport type {Sample} from '../types/Sample';\nimport {AnalyticsCall} from '../utils/AnalyticsCall';\n\nimport type {Backend} from './Backend';\n\n/**\n * The `RemoteBackend` class is responsible for actually sending out the samples using the {@link AnalyticsCall} class.\n * Before each sample is sent, the `RemoteBackend` attaches a license key to the sample.\n *\n * @implements {Backend}\n */\nexport class RemoteBackend implements Backend {\n private readonly analyticsCall: AnalyticsCall;\n private readonly licenseKey: string;\n\n constructor(backendBaseUrl: string, licenseKey: string) {\n this.analyticsCall = new AnalyticsCall(backendBaseUrl);\n this.licenseKey = licenseKey;\n }\n\n sendRequest(sample: Sample): void {\n sample.key = this.licenseKey;\n this.analyticsCall.sendRequest(sample);\n }\n\n sendUnloadRequest(sample: Sample): void {\n sample.key = this.licenseKey;\n this.analyticsCall.sendUnloadRequest(sample);\n }\n\n sendAdRequest(adSample: AdSample): void {\n adSample.key = this.licenseKey;\n this.analyticsCall.sendAdRequest(adSample);\n }\n}\n","import {SegmentInfo} from '../types/SegmentInfo';\n\nexport class SegmentTracker {\n protected segments: SegmentInfo[];\n\n constructor() {\n this.segments = [];\n }\n\n reset(): void {\n this.segments = [];\n }\n\n addSegment(segment: SegmentInfo): void {\n this.segments.push(segment);\n }\n\n removeSegment(url: string): void {\n this.segments = this.segments.filter((s) => s.url !== url);\n }\n\n getSegments(): SegmentInfo[] {\n return this.segments;\n }\n}\n","import type {AdSample} from '../types/AdSample';\nimport type {Sample} from '../types/Sample';\nimport {SEQUENCE_NUMBER_LIMIT} from '../utils/Settings';\n\nimport type {Backend} from './Backend';\n\n/**\n * The `SequenceNumberBackend` is a decorator class that increments a samples sequence number and filters out samples\n * where the `sequenceNumber` exceeds a specified threshold.\n *\n * If a sample's `sequenceNumber` surpasses the threshold, it is not forwarded to the next backend.\n * Otherwise, the sample is passed along to the next backend for further processing.\n *\n * @implements {Backend}\n */\nexport class SequenceNumberBackend implements Backend {\n readonly nextBackend: Backend;\n sequenceNumber = 0;\n\n constructor(underlying: Backend) {\n this.nextBackend = underlying;\n }\n\n sendRequest(sample: Sample): void {\n this.updateSampleBeforeSending(sample);\n if (this.isSequenceNumberAboveThreshold(sample)) {\n return;\n }\n this.nextBackend.sendRequest(sample);\n }\n\n sendUnloadRequest(sample: Sample): void {\n this.updateSampleBeforeSending(sample);\n if (this.isSequenceNumberAboveThreshold(sample)) {\n return;\n }\n this.nextBackend.sendUnloadRequest(sample);\n }\n\n sendAdRequest(adSample: AdSample): void {\n if (this.isSequenceNumberAboveThreshold(adSample)) {\n return;\n }\n this.nextBackend.sendAdRequest(adSample);\n }\n\n private updateSampleBeforeSending(sample: Sample) {\n sample.sequenceNumber = this.sequenceNumber++;\n }\n\n private isSequenceNumberAboveThreshold(sample: Sample): boolean {\n return (sample.sequenceNumber ?? 0) > SEQUENCE_NUMBER_LIMIT;\n }\n}\n","import type {AnalyticsConfig} from '../types/AnalyticsConfig';\nimport {deleteCookie, getCookie, setCookie} from '../utils/documentUtils';\nimport {isNumber} from '../utils/numberUtils';\nimport {isBlank, isValidString} from '../utils/stringUtils';\nimport {isNotNullish, isNullish} from '../utils/Utils';\nimport {generateUUID} from '../utils/uuidUtils';\n\nexport const COOKIE_NAME_BITMOVIN_ANALYTICS_UUID = 'bitmovin_analytics_uuid';\n/** One year in seconds */\nexport const COOKIE_DEFAULT_MAX_AGE = 365 * 24 * 60 * 60;\n\nexport class SessionPersistenceHandler {\n readonly userId: string;\n\n constructor(config: AnalyticsConfig) {\n const collectorConfig = config.config;\n\n const shouldNotUseCookies = collectorConfig?.cookiesEnabled === false;\n\n if (shouldNotUseCookies) {\n deleteCookie(COOKIE_NAME_BITMOVIN_ANALYTICS_UUID);\n this.userId = generateUUID();\n return;\n }\n\n const existingUserId = getCookie(COOKIE_NAME_BITMOVIN_ANALYTICS_UUID);\n this.userId = isNotNullish(existingUserId) && !isBlank(existingUserId) ? existingUserId : generateUUID();\n\n const cookieDomain = validateCookieDomainValue(collectorConfig?.cookiesDomain);\n const cookieMaxAge = validateCookieMaxAgeValue(collectorConfig?.cookiesMaxAge);\n\n // we set also expires, because max-age is not supported on old browsers like IE8\n const nowMillis = Date.now();\n const expirationDate = new Date(nowMillis + cookieMaxAge * 1000);\n const cookieExpires = expirationDate.toUTCString();\n\n setCookie(COOKIE_NAME_BITMOVIN_ANALYTICS_UUID, this.userId, {\n domain: cookieDomain,\n expires: cookieExpires,\n maxAge: cookieMaxAge,\n });\n }\n}\n\nexport const validateCookieDomainValue = (value: unknown): string | undefined => {\n if (isNullish(value)) {\n return undefined;\n }\n\n if (!isValidString(value)) {\n return undefined;\n }\n\n if (isBlank(value)) {\n return undefined;\n }\n\n return encodeURIComponent(value);\n};\n\nexport const validateCookieMaxAgeValue = (value: unknown): number => {\n if (isNullish(value)) {\n return COOKIE_DEFAULT_MAX_AGE;\n }\n\n if (!isNumber(value)) {\n return COOKIE_DEFAULT_MAX_AGE;\n }\n\n return value;\n};\n","import type {CodecInfo} from '../types/CodecInfo';\nimport type {PlaybackInfo} from '../types/PlaybackInfo';\nimport {isBlank} from '../utils/stringUtils';\nimport {isNotNullish} from '../utils/Utils';\n\n/**\n * This class is used to store source specific information for the player\n * mainly as a fallback if sourceInfo cannot be determined by the player since the source is already unloaded\n */\nexport class SourceInfoFallbackService {\n private streamFormat: PlaybackInfo['streamFormat'];\n private audioCodec: PlaybackInfo['audioCodec'];\n private videoCodec: PlaybackInfo['videoCodec'];\n\n reset() {\n this.streamFormat = undefined;\n this.audioCodec = undefined;\n this.videoCodec = undefined;\n }\n\n setStreamFormat(streamFormat: PlaybackInfo['streamFormat']) {\n this.streamFormat = streamFormat;\n }\n\n applyStreamFormat(playbackInfo: PlaybackInfo) {\n if (isBlank(this.streamFormat)) {\n return;\n }\n playbackInfo.streamFormat = this.streamFormat;\n }\n\n /**\n * Apply fallback values to {@link PlaybackInfo} if available.\n * If provided {@link CodecInfo} values are available, we store them as new fallback values, before we apply them.\n */\n applyAndStoreCodecInfo(playbackInfo: PlaybackInfo, codecInfo: CodecInfo | undefined) {\n if (isNotNullish(codecInfo?.audioCodec)) {\n this.audioCodec = codecInfo.audioCodec;\n }\n if (isNotNullish(codecInfo?.videoCodec)) {\n this.videoCodec = codecInfo.videoCodec;\n }\n\n if (!isBlank(this.audioCodec)) {\n playbackInfo.audioCodec = this.audioCodec;\n }\n if (!isBlank(this.videoCodec)) {\n playbackInfo.videoCodec = this.videoCodec;\n }\n }\n}\n","import Timespan from '../types/Timespan';\nimport {isNullish} from '../utils/Utils';\n\nenum TimespanOverlappingType {\n None,\n Overlapping,\n FirstContainedInSecond,\n SecondContainedInFirst,\n}\n\nexport default class VideoCompletionTracker {\n private watched: Timespan[] = [];\n private videoDuration: number | null = null;\n\n reset(): void {\n this.watched = [];\n }\n\n /**\n * sets video Duration\n * @param videoDuration in sec\n */\n setVideoDuration(videoDuration: number): void {\n this.videoDuration = videoDuration * 1000;\n }\n\n /**\n * Adds the watched timespan to the tracker\n * @param watched watched timespan you want to add to the tracker\n * @returns how much time(video parts which have not been seen yet) was added to the tracker\n */\n addWatched(watched: Timespan): number {\n if (isNullish(this.videoDuration)) {\n throw new Error('no video duration set for completion tracker');\n }\n\n this.watched.push(watched);\n const overlappingTimespan = this.mergeWatched(this.watched);\n return (this.getDuration(watched) - overlappingTimespan) / this.videoDuration;\n }\n\n /**\n * returns the relative value of how much the user watch the content of the video\n */\n getCompletionPercentage(): number {\n if (isNullish(this.videoDuration)) {\n throw new Error('no video duration set for completion tracker');\n }\n\n let watched = 0;\n for (const w of this.watched) {\n watched += this.getDuration(w);\n }\n return watched / this.videoDuration;\n }\n\n /**\n * Recursive Method to merge All Watched Blocks\n * @param watched\n *\n * @returns how much timespan was overlapping while merging the watchBlocks\n */\n private mergeWatched(watched: Timespan[]): number {\n for (let i = 0; i < watched.length; i++) {\n const time1 = watched[i];\n for (let k = i + 1; k < watched.length; k++) {\n const time2 = watched[k];\n let overlappingTimespan = 0;\n const overlapType = this.getOverlappingType(time1, time2);\n\n if (overlapType === TimespanOverlappingType.Overlapping) {\n this.mergeAndReplace(time1, i, time2, k);\n overlappingTimespan = this.getOverlappingTimespan(time1, time2);\n } else if (overlapType === TimespanOverlappingType.FirstContainedInSecond) {\n this.watched.splice(i, 1);\n overlappingTimespan = this.getDuration(time1);\n } else if (overlapType === TimespanOverlappingType.SecondContainedInFirst) {\n this.watched.splice(k, 1);\n overlappingTimespan = this.getDuration(time2);\n }\n if (overlapType !== TimespanOverlappingType.None) {\n return overlappingTimespan + this.mergeWatched(this.watched);\n }\n }\n }\n return 0;\n }\n\n private getOverlappingType(first: Timespan, second: Timespan): TimespanOverlappingType {\n if (\n (this.isMomentInTimespan(first.end, second) && first.start < second.start) ||\n (this.isMomentInTimespan(first.start, second) && first.end > second.end)\n ) {\n return TimespanOverlappingType.Overlapping;\n } else if (this.isMomentInTimespan(first.start, second) && this.isMomentInTimespan(first.end, second)) {\n return TimespanOverlappingType.FirstContainedInSecond;\n } else if (this.isMomentInTimespan(second.start, first) && this.isMomentInTimespan(second.end, first)) {\n return TimespanOverlappingType.SecondContainedInFirst;\n }\n return TimespanOverlappingType.None;\n }\n\n private isMomentInTimespan(moment: number, timespan: Timespan): boolean {\n return moment >= timespan.start && moment < timespan.end;\n }\n\n private mergeAndReplace(first: Timespan, firstIndex: number, second: Timespan, secondIndex: number): void {\n const end = first.end > second.end ? first.end : second.end;\n const start = first.start < second.start ? first.start : second.start;\n const newWatchedTimespan: Timespan = {start, end};\n this.watched.splice(firstIndex, 1, newWatchedTimespan);\n this.watched.splice(secondIndex, 1);\n }\n\n private getOverlappingTimespan(first: Timespan, second: Timespan): number {\n const end = first.end < second.end ? first.end : second.end;\n const start = first.start >= second.start ? first.start : second.start;\n return end - start;\n }\n\n private getDuration(watched: Timespan): number {\n return Math.abs(watched.end - watched.start);\n }\n}\n","import type {SsaiAdBreakMetadata, SsaiAdMetadata, SsaiAdQuartile, SsaiAdQuartileMetadata} from '../../api/AdapterAPI';\nimport {AD_TYPE} from '../../enums/AdType';\nimport {ErrorCode} from '../../enums/ErrorCode';\nimport {AnalyticsError} from '../../types/AnalyticsConfig';\nimport {customDataValuesKeys} from '../../types/CustomDataValues';\nimport type {Sample} from '../../types/Sample';\nimport {isNotNullish} from '../../utils/Utils';\nimport {generateUUID} from '../../utils/uuidUtils';\n\nimport type {InternalSsaiMetadata, SsaiEngagementInteractionData} from './ssaiEngagementInteractionData';\nimport {\n getCurrentMonotonicTimestampInMs,\n getMonotonicTimestampInMsSince,\n SSAI_RELATED_SAMPLE_MARKER,\n} from './ssaiUtils';\n\nexport type SsaiEventHandler = {\n getPlayerCurrentTime: () => number;\n reportEngagementInteraction: (data: SsaiEngagementInteractionData) => void;\n reportPlaybackInteraction: (timestamp: number, playerCurrentTime: number) => void;\n};\n\nenum SsaiState {\n AD_BREAK_STARTED,\n ACTIVE,\n IDLE,\n}\n\n// we start with -1, to be able to increment it before sending the first sample\n// this way the current adIndex is the one of the current playing ad\nconst INITIAL_AD_INDEX_VALUE = -1;\n\nexport class SsaiService {\n /** if `undefined` then service is not active and should not do anything, why: initially we activate it only for Bitmovin8 */\n private eventHandler: SsaiEventHandler | undefined = undefined;\n\n /** Index of the current ad in the whole session */\n private adIndex: number = INITIAL_AD_INDEX_VALUE;\n\n private state: SsaiState = SsaiState.IDLE;\n private isFirstSampleOfAd = false;\n /**\n * represents the current playing ad metadata\n * is `undefined` when no ad is playing (after endAdBreak)\n * or omitted by customer\n */\n private currentAdMetadata: InternalSsaiMetadata | undefined;\n\n /**\n * The impression id for the currently playing ad\n * is undefined when no ad is playing\n */\n private currentAdImpressionId: string | undefined;\n\n /** List of quartiles already sent for the current ad */\n private sentAdQuartiles: SsaiAdQuartile[] = [];\n\n /**\n * Flags whether an error was sent during an ad to avoid sending multiple errors for one ad,\n * which would skew e.g. the ad abandonment rate.\n */\n private errorSent: boolean = false;\n\n /**\n * The timestamp marking when the `adStart` method was called.\n * This timestamp is used to calculate the time difference between the `adStart` call\n * and subsequent `adQuartileFinished` or `sendAdEngagementErrorSample` calls.\n */\n private timestampOfAdStart: number | undefined;\n\n activate(eventHandler: SsaiEventHandler) {\n this.eventHandler = eventHandler;\n }\n\n adBreakStart(adBreakMetadata?: SsaiAdBreakMetadata) {\n if (!isActivated(this.eventHandler)) {\n // nothing to do if service is not active\n return;\n }\n\n if (this.state != SsaiState.IDLE) {\n return;\n }\n\n this.state = SsaiState.AD_BREAK_STARTED;\n this.currentAdMetadata = {\n ...adBreakMetadata,\n };\n }\n\n adStart(adMetadata?: SsaiAdMetadata) {\n if (!isActivated(this.eventHandler)) {\n // nothing to do if service is not active\n return;\n }\n\n if (this.state == SsaiState.IDLE) {\n return;\n }\n\n const timestamp = new Date().getTime();\n const playerCurrentTime = this.eventHandler.getPlayerCurrentTime();\n\n // report playback sample - will be saved in our playback related data lake\n // - with the first adStart call we need to close the current normal playback sample (no ssai ad information yet because SsaiState is not yet set to active)\n // - with all following adStart calls, we will deliver previous ssai ad information (SsaiState is already set to active)\n this.eventHandler.reportPlaybackInteraction(timestamp, playerCurrentTime);\n\n this.state = SsaiState.ACTIVE;\n // to include the adIndex in the next sample which will be the first sample of this started ad\n this.isFirstSampleOfAd = true;\n this.adIndex++;\n\n this.resetAdData();\n\n this.currentAdMetadata = {\n adPosition: this.currentAdMetadata?.adPosition,\n adId: adMetadata?.adId,\n adSystem: adMetadata?.adSystem,\n customData: adMetadata?.customData,\n };\n\n this.currentAdImpressionId = generateUUID();\n this.timestampOfAdStart = getCurrentMonotonicTimestampInMs();\n\n // report engagement sample - will be saved in our ad related data lake\n this.eventHandler.reportEngagementInteraction({\n type: 'started',\n adIndex: this.adIndex,\n currentAdImpressionId: this.currentAdImpressionId,\n currentAdMetadata: isNotNullish(this.currentAdMetadata) ? this.currentAdMetadata : {},\n });\n }\n\n adQuartileFinished(adQuartile: SsaiAdQuartile, adQuartileMetadata: SsaiAdQuartileMetadata) {\n if (!isActivated(this.eventHandler)) {\n // nothing to do if service is not activated\n return;\n }\n\n if (this.state != SsaiState.ACTIVE) {\n return;\n }\n\n if (this.sentAdQuartiles.includes(adQuartile)) {\n //do nothing if adQuartile was already sent\n return;\n }\n\n this.eventHandler.reportEngagementInteraction({\n type: 'quartile',\n adIndex: this.adIndex,\n currentAdImpressionId: this.currentAdImpressionId!,\n currentAdMetadata: isNotNullish(this.currentAdMetadata) ? this.currentAdMetadata : {},\n quartile: adQuartile,\n quartileMetadata: adQuartileMetadata,\n timeSinceAdStartedInMs: getMonotonicTimestampInMsSince(this.timestampOfAdStart),\n });\n this.sentAdQuartiles.push(adQuartile);\n }\n\n adBreakEnd() {\n if (!isActivated(this.eventHandler)) {\n // nothing to do if service is not active\n return;\n }\n\n if (this.state == SsaiState.IDLE) {\n return;\n }\n\n if (this.state == SsaiState.ACTIVE) {\n const timestamp = new Date().getTime();\n const playerCurrentTime = this.eventHandler.getPlayerCurrentTime();\n this.eventHandler.reportPlaybackInteraction(timestamp, playerCurrentTime);\n }\n\n this.resetAdBreakData();\n }\n\n manipulate(sample: Sample): void {\n if (!isActivated(this.eventHandler)) {\n // nothing to do if service is not active\n return;\n }\n\n if (this.state != SsaiState.ACTIVE) {\n return;\n }\n\n sample.ad = AD_TYPE.SSAI;\n sample.adId = this.currentAdMetadata?.adId;\n sample.adSystem = this.currentAdMetadata?.adSystem;\n sample.adPosition = this.currentAdMetadata?.adPosition;\n // we only mark the first sample of an ssai ad with the index in the playback/audience data (non ad table)\n // this allows us to count the number of ads\n if (this.isFirstSampleOfAd) {\n sample.adIndex = this.adIndex;\n this.isFirstSampleOfAd = false;\n }\n\n const customData = this.currentAdMetadata?.customData;\n if (isNotNullish(customData)) {\n customDataValuesKeys.forEach((key) => {\n if (customData[key]) {\n sample[key] = customData[key];\n }\n });\n }\n\n sample[SSAI_RELATED_SAMPLE_MARKER] = true; // mark it as ssai sample\n }\n\n sendAdEngagementErrorSample(error: AnalyticsError, originalError: any) {\n if (!isActivated(this.eventHandler)) {\n // nothing to do if service is not active\n return;\n }\n\n if (this.state !== SsaiState.ACTIVE) {\n return;\n }\n\n // only send one error sample per ad\n if (this.errorSent) {\n return;\n }\n\n // This error code is related to the Analytics product and is non-fatal.\n // It is not triggered by the Player and does not interrupt or affect playback,\n // so there is no need to report an ad error sample.\n if (error.code === ErrorCode.QUALITY_CHANGE_THRESHOLD_EXCEEDED.code) {\n return;\n }\n\n this.eventHandler.reportEngagementInteraction({\n type: 'error',\n adIndex: this.adIndex,\n currentAdImpressionId: this.currentAdImpressionId!,\n currentAdMetadata: isNotNullish(this.currentAdMetadata) ? this.currentAdMetadata : {},\n analyticsError: error,\n originalError: originalError,\n timeSinceAdStartedInMs: getMonotonicTimestampInMsSince(this.timestampOfAdStart),\n });\n this.errorSent = true;\n }\n\n isInActiveState(): boolean {\n return this.state === SsaiState.ACTIVE;\n }\n\n resetSourceRelatedState() {\n this.resetAdBreakData();\n this.adIndex = INITIAL_AD_INDEX_VALUE;\n }\n\n private resetAdBreakData() {\n this.state = SsaiState.IDLE;\n this.isFirstSampleOfAd = false;\n delete this.currentAdMetadata;\n this.resetAdData();\n }\n\n private resetAdData() {\n delete this.currentAdMetadata?.customData;\n delete this.currentAdMetadata?.adId;\n delete this.currentAdMetadata?.adSystem;\n this.errorSent = false;\n this.currentAdImpressionId = undefined;\n this.sentAdQuartiles = [];\n this.timestampOfAdStart = undefined;\n }\n}\n\nfunction isActivated(eventHandler: SsaiEventHandler | undefined): eventHandler is SsaiEventHandler {\n return isNotNullish(eventHandler);\n}\n","import type {\n AdPosition,\n SsaiAdBreakMetadata,\n SsaiAdMetadata,\n SsaiAdQuartile,\n SsaiAdQuartileMetadata,\n} from '../../api/AdapterAPI';\nimport {CustomDataValues, sanitizeCustomDataValues} from '../../types/CustomDataValues';\nimport {logger} from '../../utils/Logger';\nimport {isValidString} from '../../utils/stringUtils';\nimport {isNotNullish, isNullish, isPlainObject} from '../../utils/Utils';\n\nexport function isAdPosition(anything: unknown): anything is AdPosition {\n // invalid, when not defined as one of string values we expect\n return anything === 'preroll' || anything === 'midroll' || anything === 'postroll';\n}\n\n/** User SSAI API input validation */\nexport function hasValidSsaiAdBreakMetadataStructure(\n anything: unknown,\n): anything is SsaiAdBreakMetadata | null | undefined {\n // \"nullish\" is considered to be valid (SSAI API parameter is optional)\n if (isNullish(anything)) return true;\n\n // invalid, when value was defined, but not as a plain object\n if (!isPlainObject(anything as object)) {\n logger.errorMessageToUser('Invalid SsaiAdBreakMetadata: not a plain object');\n return false;\n }\n\n const maybeSsaiAdBreakMetadata = anything as SsaiAdBreakMetadata;\n\n // invalid, when `adPosition` was defined, but not as an ad position string we expect\n if (isNotNullish(maybeSsaiAdBreakMetadata.adPosition) && !isAdPosition(maybeSsaiAdBreakMetadata.adPosition)) {\n logger.errorMessageToUser(\"Invalid SsaiAdBreakMetadata: 'adPosition' property is not valid\");\n return false;\n }\n\n return true;\n}\n\n/**\n * Simple sanitization of {@link SsaiAdBreakMetadata} without object structure check,\n * because {@link hasValidSsaiAdBreakMetadataStructure} should be called before in adapter SSAI API function!\n *\n * Sanitization:\n * - if `undefined/null` is passed, it will return `undefined`\n * - recreate a new object to avoid side effects by using same reference from outside\n *\n * @param adBreakMetadata SsaiAdBreakMetadata or `undefined` (optional SSAI API parameter)\n */\nexport function simplySanitizeSsaiAdBreakMetadata(\n adBreakMetadata: SsaiAdBreakMetadata | undefined,\n): SsaiAdBreakMetadata | undefined {\n // \"nullish\" is considered to be valid (SSAI API parameter is optional)\n if (isNullish(adBreakMetadata)) {\n // sanitize to use `undefined` in code\n return undefined;\n }\n\n // recreate a new object\n return {\n adPosition: adBreakMetadata.adPosition,\n };\n}\n\n/** User SSAI API input validation */\nexport function hasValidSsaiAdMetadataStructure(anything: unknown): anything is SsaiAdMetadata | null | undefined {\n // \"nullish\" is considered to be valid (SSAI API parameter is optional)\n if (isNullish(anything)) {\n return true;\n }\n\n // invalid, when value was defined, but not as a plain object\n if (!isPlainObject(anything as object)) {\n logger.errorMessageToUser('Invalid SsaiAdMetadata: not a plain object');\n return false;\n }\n\n const maybeSsaiAdMetadata = anything as SsaiAdMetadata;\n\n // invalid, when `adId` was defined, but not as a string\n if (isNotNullish(maybeSsaiAdMetadata.adId) && !isValidString(maybeSsaiAdMetadata.adId)) {\n logger.errorMessageToUser(\"Invalid SsaiAdMetadata: 'adId' property is not string\");\n return false;\n }\n\n // invalid, when `adSystem` was defined, but not as a string\n if (isNotNullish(maybeSsaiAdMetadata.adSystem) && !isValidString(maybeSsaiAdMetadata.adSystem)) {\n logger.errorMessageToUser(\"Invalid SsaiAdMetadata: 'adSystem' property is not string\");\n return false;\n }\n\n // invalid, when `customData` was defined, but not as an object\n if (isNotNullish(maybeSsaiAdMetadata.customData) && !isPlainObject(maybeSsaiAdMetadata.customData)) {\n logger.errorMessageToUser(\"Invalid SsaiAdMetadata: 'customData' property is not a plain object\");\n return false;\n }\n\n return true;\n}\n\n/**\n * Simple sanitization of {@link SsaiAdMetadata} without object structure check,\n * because {@link hasValidSsaiAdMetadataStructure} should be called before in adapter SSAI API function!\n *\n * Sanitization:\n * - if `undefined/null` is passed, it will return `undefined`\n * - recreate a new object to avoid side effects by using same reference from outside\n *\n * @param ssaiAdMetadata SsaiAdMetadata or `undefined` (optional SSAI API parameter)\n */\nexport function simplySanitizeSsaiAdMetadata(ssaiAdMetadata: SsaiAdMetadata | undefined): SsaiAdMetadata | undefined {\n // \"nullish\" is considered to be valid (SSAI API parameter is optional)\n if (isNullish(ssaiAdMetadata)) {\n // sanitize to use `undefined` in code\n return undefined;\n }\n\n let sanitizedCustomDataValues: CustomDataValues | undefined = undefined;\n if (isNotNullish(ssaiAdMetadata.customData)) {\n sanitizedCustomDataValues = sanitizeCustomDataValues(ssaiAdMetadata.customData);\n }\n\n // recreate a new object\n return {\n adId: ssaiAdMetadata.adId,\n adSystem: ssaiAdMetadata.adSystem,\n customData: sanitizedCustomDataValues,\n };\n}\n\nexport function isSsaiAdQuartile(anything: unknown): anything is SsaiAdQuartile {\n return anything === 'first' || anything === 'midpoint' || anything === 'third' || anything === 'completed';\n}\n\n/** User SSAI API input validation */\nexport function hasValidSsaiAdQuartileStructure(anything: unknown): anything is SsaiAdQuartile {\n if (!isSsaiAdQuartile(anything)) {\n logger.errorMessageToUser('Invalid SsaiAdQuartile');\n return false;\n }\n\n return true;\n}\n\n/**\n * Full sanitization of unknown customer input.\n * We sanitize correct object structure and print user error messages for incorrect input.\n *\n * Sanitization:\n * - if `undefined/null` is passed, it will return empty object `{}`\n * - if NOT `typeof 'object'` is passed, it will return empty object `{}` and print user error message\n * - recreate a new object to avoid side effects by using same reference from outside\n * - if `failedBeaconUrl` is not valid string, we use `undefined` and print user error message\n * - if `failedBeaconUrl` is longer than 500 characters, we cut it\n *\n * @param anything Can be anything, as it is coming from customer JavaScript code\n */\nexport function sanitizeSsaiAdQuartileMetadata(anything: unknown): SsaiAdQuartileMetadata {\n if (isNullish(anything)) {\n // \"nullish\" is considered to be valid (SSAI API parameter is optional)\n // sanitize to plain object to not use nullish value in code\n return {};\n }\n\n if (!isPlainObject(anything as object)) {\n // if NOT a plain object, we return empty plain object and print user error message\n logger.errorMessageToUser('Invalid SsaiAdQuartileMetadata: not a plain object');\n return {};\n }\n\n const maybeSsaiAdQuartileMetadata = anything as SsaiAdQuartileMetadata;\n\n // recreate a new object\n const ssaiAdQuartileMetadata: SsaiAdQuartileMetadata = {\n failedBeaconUrl: maybeSsaiAdQuartileMetadata.failedBeaconUrl,\n };\n\n if (!isValidString(ssaiAdQuartileMetadata.failedBeaconUrl)) {\n logger.errorMessageToUser(\"Invalid SsaiAdQuartileMetadata: 'failedBeaconUrl' property is not string\");\n ssaiAdQuartileMetadata.failedBeaconUrl = undefined;\n } else {\n ssaiAdQuartileMetadata.failedBeaconUrl = ssaiAdQuartileMetadata.failedBeaconUrl.substring(0, 500);\n }\n\n return ssaiAdQuartileMetadata;\n}\n","import {SsaiAdBreakMetadata, SsaiAdMetadata, SsaiAdQuartile, SsaiAdQuartileMetadata} from '../../api/AdapterAPI';\nimport {AnalyticsError} from '../../types/AnalyticsConfig';\n\nexport type InternalSsaiMetadata = SsaiAdBreakMetadata & SsaiAdMetadata;\n\ntype SsaiEngagementBaseData = {\n adIndex: number;\n currentAdImpressionId: string;\n currentAdMetadata: InternalSsaiMetadata;\n type: 'error' | 'quartile' | 'started';\n};\n\nexport type SsaiEngagementErrorData = SsaiEngagementBaseData & {\n analyticsError: AnalyticsError;\n originalError?: any;\n timeSinceAdStartedInMs: number | undefined;\n type: 'error';\n};\n\nexport function isSsaiEngagementErrorData(data: SsaiEngagementInteractionData): data is SsaiEngagementErrorData {\n return data.type === 'error';\n}\n\nexport type SsaiEngagementQuartileData = SsaiEngagementBaseData & {\n quartile: SsaiAdQuartile;\n quartileMetadata: SsaiAdQuartileMetadata;\n timeSinceAdStartedInMs: number | undefined;\n type: 'quartile';\n};\n\nexport function isSsaiEngagementQuartileData(data: SsaiEngagementInteractionData): data is SsaiEngagementQuartileData {\n return data.type === 'quartile';\n}\n\nexport type SsaiEngagementStartedData = SsaiEngagementBaseData & {type: 'started'};\n\nexport function isSsaiEngagementStartedData(data: SsaiEngagementInteractionData): data is SsaiEngagementStartedData {\n return data.type === 'started';\n}\n\nexport type SsaiEngagementInteractionData =\n | SsaiEngagementErrorData\n | SsaiEngagementQuartileData\n | SsaiEngagementStartedData;\n","import type {SsaiAdQuartile, SsaiAdQuartileMetadata} from '../../api/AdapterAPI';\nimport type {AdSample} from '../../types/AdSample';\nimport {ErrorSeverity} from '../../types/AnalyticsConfig';\nimport {customDataValuesKeys} from '../../types/CustomDataValues';\nimport type {Sample} from '../../types/Sample';\nimport {getGlobalPerformanceNow} from '../../utils/globalScopeUtils';\nimport {isNotNullish, isNullish} from '../../utils/Utils';\n\nimport type {\n InternalSsaiMetadata,\n SsaiEngagementErrorData,\n SsaiEngagementQuartileData,\n SsaiEngagementStartedData,\n} from './ssaiEngagementInteractionData';\n\n/**\n * Ssai marker property for {@link Sample} to indicate that this is \"ssai related sample\" and can cause the spike\n * on ingress side. It will be picked up in `AnalyticsCall` and used to send that \"ssai related sample\" as request\n * with ssai redirection. @see {@link ROUTING_URL_PARAM}\n *\n * What is \"ssai related sample\" ?\n * - \"last sample\" that was triggered to be sent, because of coming SSAI interaction, the SSAI ad break start (WITHOUT `sample.ad = 2`),\n * because it causes also the spike as all viewers are received same SSAI at the same time.\n * - all following samples, triggered by SSAI interaction while SSAI ad break is running (now WITH `sample.ad = 2`)\n *\n * We don't we need it with {@link AdSample} too?\n * Because all \"ssai related ad samples\" are triggered only during ssai ad break, so all have already\n * {@link AdSample#adType} property set and we can relay on that in `AnalyticsCall` to send them with ssai redirection.\n */\nexport const SSAI_RELATED_SAMPLE_MARKER = 'triggeredBySsai';\n\nexport function isSsaiRelatedSample(sample: AdSample | Sample): boolean {\n if (sample[SSAI_RELATED_SAMPLE_MARKER]) {\n delete sample[SSAI_RELATED_SAMPLE_MARKER]; // clean up the marker property that should not be present on the sample property\n return true;\n } else if ((sample as AdSample).adType === 2) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Due to ssai being spiky by design, we should mark all analytics requests (with samples / ad samples)\n * that are ssai related, with a specific URL parameter. The load balancer can then route traffic according to the URL\n * parameter to a different ingress instance, which gives us more flexibility when ssai spikes are coming in.\n */\nexport const ROUTING_URL_PARAM = 'routingParam';\nexport const ROUTING_URL_PARAM_VALUE_SSAI = 'ssai';\n\nexport function appendSsaiRoutingParam(url: string): string {\n return `${url}?${ROUTING_URL_PARAM}=${ROUTING_URL_PARAM_VALUE_SSAI}`;\n}\n\nfunction createAdSampleFromSample(sample: Sample): AdSample {\n return {\n audioBitrate: sample?.audioBitrate,\n analyticsVersion: sample?.analyticsVersion,\n adPlaybackHeight: sample?.videoPlaybackHeight,\n adPlaybackWidth: sample?.videoPlaybackWidth,\n cdnProvider: sample?.cdnProvider,\n customData1: sample?.customData1,\n customData2: sample?.customData2,\n customData3: sample?.customData3,\n customData4: sample?.customData4,\n customData5: sample?.customData5,\n customData6: sample?.customData6,\n customData7: sample?.customData7,\n customData8: sample?.customData8,\n customData9: sample?.customData9,\n customData10: sample?.customData10,\n customData11: sample?.customData11,\n customData12: sample?.customData12,\n customData13: sample?.customData13,\n customData14: sample?.customData14,\n customData15: sample?.customData15,\n customData16: sample?.customData16,\n customData17: sample?.customData17,\n customData18: sample?.customData18,\n customData19: sample?.customData19,\n customData20: sample?.customData20,\n customData21: sample?.customData21,\n customData22: sample?.customData22,\n customData23: sample?.customData23,\n customData24: sample?.customData24,\n customData25: sample?.customData25,\n customData26: sample?.customData26,\n customData27: sample?.customData27,\n customData28: sample?.customData28,\n customData29: sample?.customData29,\n customData30: sample?.customData30,\n customData31: sample?.customData31,\n customData32: sample?.customData32,\n customData33: sample?.customData33,\n customData34: sample?.customData34,\n customData35: sample?.customData35,\n customData36: sample?.customData36,\n customData37: sample?.customData37,\n customData38: sample?.customData38,\n customData39: sample?.customData39,\n customData40: sample?.customData40,\n customData41: sample?.customData41,\n customData42: sample?.customData42,\n customData43: sample?.customData43,\n customData44: sample?.customData44,\n customData45: sample?.customData45,\n customData46: sample?.customData46,\n customData47: sample?.customData47,\n customData48: sample?.customData48,\n customData49: sample?.customData49,\n customData50: sample?.customData50,\n customData51: sample?.customData51,\n customData52: sample?.customData52,\n customData53: sample?.customData53,\n customData54: sample?.customData54,\n customData55: sample?.customData55,\n customData56: sample?.customData56,\n customData57: sample?.customData57,\n customData58: sample?.customData58,\n customData59: sample?.customData59,\n customData60: sample?.customData60,\n customData61: sample?.customData61,\n customData62: sample?.customData62,\n customData63: sample?.customData63,\n customData64: sample?.customData64,\n customData65: sample?.customData65,\n customData66: sample?.customData66,\n customData67: sample?.customData67,\n customData68: sample?.customData68,\n customData69: sample?.customData69,\n customData70: sample?.customData70,\n customData71: sample?.customData71,\n customData72: sample?.customData72,\n customData73: sample?.customData73,\n customData74: sample?.customData74,\n customData75: sample?.customData75,\n customData76: sample?.customData76,\n customData77: sample?.customData77,\n customData78: sample?.customData78,\n customData79: sample?.customData79,\n customData80: sample?.customData80,\n customData81: sample?.customData81,\n customData82: sample?.customData82,\n customData83: sample?.customData83,\n customData84: sample?.customData84,\n customData85: sample?.customData85,\n customData86: sample?.customData86,\n customData87: sample?.customData87,\n customData88: sample?.customData88,\n customData89: sample?.customData89,\n customData90: sample?.customData90,\n customData91: sample?.customData91,\n customData92: sample?.customData92,\n customData93: sample?.customData93,\n customData94: sample?.customData94,\n customData95: sample?.customData95,\n customData96: sample?.customData96,\n customData97: sample?.customData97,\n customData98: sample?.customData98,\n customData99: sample?.customData99,\n customData100: sample?.customData100,\n customUserId: sample?.customUserId,\n domain: sample?.domain,\n experimentName: sample?.experimentName,\n key: sample?.key,\n language: sample?.language,\n path: sample?.path,\n platform: sample?.platform,\n player: sample?.player,\n playerKey: sample?.playerKey,\n playerTech: sample?.playerTech,\n size: sample?.size,\n screenHeight: sample?.screenHeight,\n screenWidth: sample?.screenWidth,\n streamFormat: sample?.streamFormat,\n userAgent: sample?.userAgent,\n userId: sample?.userId,\n version: sample?.version,\n videoBitrate: sample?.videoBitrate,\n videoId: sample?.videoId,\n videoImpressionId: sample?.impressionId,\n videoTitle: sample?.videoTitle,\n videoWindowHeight: sample?.videoWindowHeight,\n videoWindowWidth: sample?.videoWindowWidth,\n };\n}\n\nexport function createErrorAdSample(\n playbackSample: Sample,\n ssaiEngagementErrorData: SsaiEngagementErrorData,\n): AdSample {\n return buildAdSample({\n playbackSample,\n currentAdImpressionId: ssaiEngagementErrorData.currentAdImpressionId,\n adIndex: ssaiEngagementErrorData.adIndex,\n currentAdMetadata: ssaiEngagementErrorData.currentAdMetadata,\n quartile: undefined,\n quartileMetadata: undefined,\n errorCode: ssaiEngagementErrorData.analyticsError.code,\n errorMessage: ssaiEngagementErrorData.analyticsError.message,\n errorSeverity: ssaiEngagementErrorData.analyticsError.severity,\n timeSinceAdStartedInMs: ssaiEngagementErrorData.timeSinceAdStartedInMs,\n });\n}\n\nexport function createStartedAdSample(\n playbackSample: Sample,\n ssaiEngagementStartedData: SsaiEngagementStartedData,\n): AdSample {\n return buildAdSample({\n playbackSample,\n currentAdImpressionId: ssaiEngagementStartedData.currentAdImpressionId,\n adIndex: ssaiEngagementStartedData.adIndex,\n currentAdMetadata: ssaiEngagementStartedData.currentAdMetadata,\n quartile: 'started',\n quartileMetadata: undefined,\n errorCode: undefined,\n errorMessage: undefined,\n errorSeverity: undefined,\n timeSinceAdStartedInMs: undefined,\n });\n}\n\nexport function createQuartileAdSample(\n playbackSample: Sample,\n ssaiEngagementQuartileData: SsaiEngagementQuartileData,\n): AdSample {\n return buildAdSample({\n playbackSample,\n currentAdImpressionId: ssaiEngagementQuartileData.currentAdImpressionId,\n adIndex: ssaiEngagementQuartileData.adIndex,\n currentAdMetadata: ssaiEngagementQuartileData.currentAdMetadata,\n quartile: ssaiEngagementQuartileData.quartile,\n quartileMetadata: ssaiEngagementQuartileData.quartileMetadata,\n timeSinceAdStartedInMs: ssaiEngagementQuartileData.timeSinceAdStartedInMs,\n errorCode: undefined,\n errorMessage: undefined,\n errorSeverity: undefined,\n });\n}\n\nfunction buildAdSample({\n playbackSample,\n currentAdImpressionId,\n adIndex,\n currentAdMetadata,\n quartile,\n quartileMetadata,\n errorCode,\n errorMessage,\n errorSeverity,\n timeSinceAdStartedInMs,\n}: {\n adIndex: number;\n currentAdImpressionId: string;\n currentAdMetadata: InternalSsaiMetadata;\n errorCode: number | undefined;\n errorMessage: string | undefined;\n errorSeverity: ErrorSeverity | undefined;\n playbackSample: Sample;\n quartile: 'started' | SsaiAdQuartile | undefined;\n quartileMetadata: SsaiAdQuartileMetadata | undefined;\n timeSinceAdStartedInMs: number | undefined;\n}): AdSample {\n const adEngagementSample: AdSample = {\n ...createAdSampleFromSample(playbackSample),\n adId: currentAdMetadata?.adId,\n adImpressionId: currentAdImpressionId,\n adIndex: adIndex,\n adPosition: currentAdMetadata?.adPosition,\n adSystem: currentAdMetadata?.adSystem,\n adType: 2,\n errorCode: errorCode,\n errorMessage: errorMessage,\n errorSeverity: errorSeverity,\n time: Date.now(),\n timeSinceAdStartedInMs: timeSinceAdStartedInMs,\n };\n\n // set quartile data\n switch (quartile) {\n case 'started':\n adEngagementSample.started = 1;\n break;\n case 'first':\n adEngagementSample.quartile1 = 1;\n adEngagementSample.quartile1FailedBeaconUrl = quartileMetadata?.failedBeaconUrl;\n break;\n case 'midpoint':\n adEngagementSample.midpoint = 1;\n adEngagementSample.midpointFailedBeaconUrl = quartileMetadata?.failedBeaconUrl;\n break;\n case 'third':\n adEngagementSample.quartile3 = 1;\n adEngagementSample.quartile3FailedBeaconUrl = quartileMetadata?.failedBeaconUrl;\n break;\n case 'completed':\n adEngagementSample.completed = 1;\n adEngagementSample.completedFailedBeaconUrl = quartileMetadata?.failedBeaconUrl;\n break;\n }\n\n // set ssai customData\n const customData = currentAdMetadata?.customData;\n if (isNotNullish(customData)) {\n customDataValuesKeys.forEach((key) => {\n if (customData[key]) {\n adEngagementSample[key] = customData[key];\n }\n });\n }\n\n return adEngagementSample;\n}\n\n/**\n * Returns the current timestamp in milliseconds using the `performance.now()` method if available\n * to ensure monotonic timestamps; otherwise, it falls back to using `Date.now()`.\n *\n * Date.now() is dependent on the system clock and not monotonic, it may have been impacted by system\n * and user clock adjustments. The performance.now() method is relative to the timeOrigin property\n * which is a monotonic clock: its current time never decreases and isn't subject to adjustments.\n */\nexport function getCurrentMonotonicTimestampInMs(): number {\n const performanceNow = getGlobalPerformanceNow();\n if (isNullish(performanceNow)) {\n return Date.now();\n }\n\n // floor to return integer value (not double as performance.now() returns)\n return Math.floor(performanceNow);\n}\n\nexport function getMonotonicTimestampInMsSince(timestampInMs: number | undefined): number | undefined {\n if (isNullish(timestampInMs)) {\n return undefined;\n }\n\n return getCurrentMonotonicTimestampInMs() - timestampInMs;\n}\n","export enum AD_TYPE {\n NO_AD = 0,\n CSAI = 1,\n SSAI = 2,\n}\n","export enum CdnProvider {\n AKAMAI = 'akamai',\n BITGRAVITY = 'bitgravity',\n CHINACACHE = 'chinacache',\n CLOUDFLARE = 'cloudflare',\n CLOUDFRONT = 'cloudfront',\n FASTLY = 'fastly',\n MAXCDN = 'maxcdn',\n}\n","export enum CastTech {\n AirPlay = 'AirPlay',\n GoogleCast = 'GoogleCast',\n WebSocket = 'WebSocket',\n}\n","const videoCodecs = ['avc1', 'avc3', 'hvc1', 'av01', 'av1', 'hev1', 'vp9'];\n\nconst audioCodecs = ['mp4a', 'ec-3', 'ac-3', 'opus', 'audio/mp4'];\n\nexport function isVideoCodec(codec: string): boolean {\n if (!codec) {\n return false;\n }\n const index = videoCodecs.findIndex((videoCodec) => codec.startsWith(videoCodec));\n return index !== -1;\n}\n\nexport function isAudioCodec(codec: string): boolean {\n if (!codec) {\n return false;\n }\n const index = audioCodecs.findIndex((videoCodec) => codec.startsWith(videoCodec));\n return index !== -1;\n}\n","import {ErrorSeverity} from '../types/AnalyticsConfig';\n\nexport class ErrorCode {\n static BITMOVIN_PLAYER_LICENSING_ERROR = new ErrorCode(1103, '');\n static SETUP_MISSING_LICENSE_WHITELIST = new ErrorCode(1105, '');\n static QUALITY_CHANGE_THRESHOLD_EXCEEDED = new ErrorCode(\n 10000,\n 'ANALYTICS_QUALITY_CHANGE_THRESHOLD_EXCEEDED',\n 'INFO',\n );\n static BUFFERING_TIMEOUT_REACHED = new ErrorCode(10001, 'ANALYTICS_BUFFERING_TIMEOUT_REACHED');\n static VIDEO_STARTUP_TIMEOUT_REACHED = new ErrorCode(10002, 'ANALYTICS_VIDEOSTART_TIMEOUT_REACHED');\n\n private constructor(\n readonly code: number,\n readonly message: string,\n readonly errorSeverity: ErrorSeverity = 'CRITICAL',\n ) {}\n}\n","import type {\n AnalyticsEventBase,\n CustomDataValuesEvent,\n ErrorEvent,\n QualityChangeEvent,\n SourceChangeEvent,\n} from '../types/EventData';\n\n/**\n * If we specify the name of our initial state, then an implicit 'startup' initial event will be created by JSM\n * and fired when the state machine is constructed.\n *\n * Because that implicit JSM initial event is called 'startup', it could cause confusion with our \"STARTUP state\", so for\n * that reason we will use custom JSM initial event name, to be able to distinguish it from our other {@link Event}s.\n *\n * This event should not be used in the application code, it is only used by the JSM library!\n *\n * @see https://github.com/jakesgordon/javascript-state-machine/blob/2.4.0/README.md#initialization-options\n */\nexport const JSM_INITIAL_EVENT = 'jsm-initial';\n\nexport enum Event {\n AUDIO_CHANGE = 'audioChange',\n AUDIOTRACK_CHANGED = 'audioTrackChanged',\n CUSTOM_DATA_CHANGE = 'customDataChange',\n /**\n * Fired when the player has finished playback.\n */\n END = 'end',\n END_AD = 'adEnd',\n END_BUFFERING = 'endBuffering',\n END_CAST = 'endCasting',\n END_FULLSCREEN = 'endFullscreen',\n ERROR = 'playerError',\n /**\n * Custom Event fired by Analytics State Machine. Used to immediately transition out of the QUALITY_CHANGE State\n * back to PLAYING State where the quality change was tracked.\n */\n FINISH_QUALITY_CHANGE = 'finishQualityChange',\n /**\n * Manually fired when a source load with autoplay is detected.\n * Required for accurate VST (video startup time) measurement: Some players delay sending PLAY events until\n * manifest/content is loaded, making VST unreliable if calculated from player events alone.\n * For autoplay scenarios, VST is measured as the time from source load to the first\n * PLAYING or TIMEUPDATE event from the player.\n */\n LOADSTART_AUTOPLAY = 'loadstartAutoplay',\n MANUAL_SOURCE_CHANGE = 'manualSourceChangeInitiated',\n MUTE = 'mute',\n PAUSE = 'pause',\n PLAY = 'play',\n PLAYING = 'playing',\n /**\n * Fired when the player is ready to play.\n */\n READY = 'ready',\n SCREEN_RESIZE = 'resize',\n SEEK = 'seek',\n SEEKED = 'seeked',\n SOURCE_LOADED = 'sourceLoaded',\n SOURCE_UNLOADED = 'sourceUnloaded',\n START_AD = 'adStart',\n START_BUFFERING = 'startBuffering',\n START_CAST = 'startCasting',\n START_FULLSCREEN = 'startFullscreen',\n SUBTITLE_CHANGE = 'subtitleChange',\n TIMECHANGED = 'timechanged',\n UN_MUTE = 'unMute',\n /**\n * Fired when page with player is closed or when the player is unloaded/destroyed.\n */\n UNLOAD = 'unload',\n VIDEO_CHANGE = 'videoChange',\n VIDEOSTART_TIMEOUT = 'VIDEOSTART_TIMEOUT',\n}\n\nexport interface EventMap {\n [Event.READY]: AnalyticsEventBase;\n [Event.SOURCE_LOADED]: AnalyticsEventBase;\n [Event.PLAY]: AnalyticsEventBase;\n [Event.PLAYING]: AnalyticsEventBase | CustomDataValuesEvent;\n [Event.PAUSE]: AnalyticsEventBase | CustomDataValuesEvent;\n [Event.TIMECHANGED]: AnalyticsEventBase;\n [Event.SEEK]: AnalyticsEventBase;\n [Event.SEEKED]: AnalyticsEventBase;\n [Event.START_CAST]: AnalyticsEventBase;\n [Event.END_CAST]: AnalyticsEventBase;\n [Event.START_BUFFERING]: AnalyticsEventBase;\n [Event.END_BUFFERING]: AnalyticsEventBase;\n [Event.AUDIOTRACK_CHANGED]: AnalyticsEventBase;\n [Event.AUDIO_CHANGE]: QualityChangeEvent;\n [Event.VIDEO_CHANGE]: QualityChangeEvent;\n [Event.FINISH_QUALITY_CHANGE]: AnalyticsEventBase;\n [Event.START_FULLSCREEN]: AnalyticsEventBase;\n [Event.END_FULLSCREEN]: AnalyticsEventBase;\n [Event.START_AD]: AnalyticsEventBase;\n [Event.SUBTITLE_CHANGE]: AnalyticsEventBase;\n [Event.END_AD]: AnalyticsEventBase;\n [Event.MUTE]: AnalyticsEventBase;\n [Event.UN_MUTE]: AnalyticsEventBase;\n [Event.ERROR]: ErrorEvent;\n [Event.SCREEN_RESIZE]: AnalyticsEventBase;\n [Event.UNLOAD]: AnalyticsEventBase;\n [Event.END]: AnalyticsEventBase;\n [Event.SOURCE_UNLOADED]: AnalyticsEventBase;\n [Event.MANUAL_SOURCE_CHANGE]: SourceChangeEvent;\n [Event.VIDEOSTART_TIMEOUT]: AnalyticsEventBase;\n [Event.CUSTOM_DATA_CHANGE]: AnalyticsEventBase;\n [Event.LOADSTART_AUTOPLAY]: AnalyticsEventBase;\n}\n","import {endsWith} from '../utils/stringUtils';\n\nexport const MIMETypes = {\n MP4: 'video/mp4',\n WEBM: 'video/webm',\n HLS: 'application/x-mpegURL',\n DASH: 'application/dash+xml',\n} as const;\n\n/**\n * @deprecated use {@link getStreamTypesFromURL} directly, when we want to detect {@link StreamTypes} from URL\n *\n * @remarks\n *\n * In our current code, it is visible that detection of MIME Type is only used as \"an additional step\" between\n * stream URL and stream type:\n * - we parse stream URL to detect MIME type\n * - we parse the detected MIME type to get a stream type\n *\n * Because we are not sending the detected MIME type in sample and because we can get {@link StreamTypes} directly from\n * stream URL, we should stop using this MIME type detection code.\n */\nexport function getMIMETypeFromFileExtension(url: string): string | undefined {\n const urlPath = url.split(/[?#]/)[0].toLowerCase();\n\n if (endsWith(urlPath, '.m3u8')) {\n return MIMETypes.HLS;\n }\n if (endsWith(urlPath, '.mp4') || endsWith(urlPath, '.m4v') || endsWith(urlPath, '.m4a')) {\n return MIMETypes.MP4;\n }\n if (endsWith(urlPath, '.webm')) {\n return MIMETypes.WEBM;\n }\n if (endsWith(urlPath, '.mpd')) {\n return MIMETypes.DASH;\n }\n\n return undefined;\n}\n","export enum PAGE_LOAD_TYPE {\n FOREGROUND = 1,\n BACKGROUND = 2,\n}\n","export enum Player {\n BITMOVIN = 'bitmovin',\n BITMOVIN_PWX = 'bitmovin-pwx',\n CHROMECAST_SHAKA = 'chromecast-shaka',\n HLSJS = 'hlsjs',\n HTML5 = 'html5',\n JW = 'jw',\n RADIANT = 'radiant',\n SHAKA = 'shaka',\n THEOPLAYER = 'theoplayer',\n VIDEOJS = 'videojs',\n}\n","export enum PlayerSize {\n Fullscreen = 'FULLSCREEN',\n Window = 'WINDOW',\n}\n","import {endsWith, isBlank} from '../utils/stringUtils';\nimport {isNullish} from '../utils/Utils';\n\nimport {MIMETypes} from './MIMETypes';\n\nexport enum StreamTypes {\n dash = 'dash',\n hls = 'hls',\n prog = 'progressive',\n}\n\nexport function getStreamTypesFromURL(url: string | undefined): StreamTypes | undefined {\n if (isNullish(url) || isBlank(url)) {\n return undefined;\n }\n\n const urlPath = url.split(/[?#]/)[0].toLowerCase();\n\n if (endsWith(urlPath, '.m3u8')) {\n return StreamTypes.hls;\n }\n if (endsWith(urlPath, '.mp4') || endsWith(urlPath, '.m4v') || endsWith(urlPath, '.m4a')) {\n return StreamTypes.prog;\n }\n if (endsWith(urlPath, '.webm')) {\n return StreamTypes.prog;\n }\n if (endsWith(urlPath, '.mpd')) {\n return StreamTypes.dash;\n }\n\n return undefined;\n}\n\nexport function getStreamTypeFromMIMEType(mimeType: string): StreamTypes | undefined {\n const MIME_TYPE_TO_STREAM_TYPE_MAP = {\n [MIMETypes.MP4]: StreamTypes.prog,\n [MIMETypes.WEBM]: StreamTypes.prog,\n [MIMETypes.HLS]: StreamTypes.hls,\n [MIMETypes.DASH]: StreamTypes.dash,\n };\n\n return MIME_TYPE_TO_STREAM_TYPE_MAP[mimeType];\n}\n","import {Event} from './Event';\n\nexport enum VideoStartFailedReason {\n PAGE_CLOSED = 'PAGE_CLOSED',\n PLAYER_ERROR = 'PLAYER_ERROR',\n TIMEOUT = 'TIMEOUT',\n UNKNOWN = 'UNKNOWN',\n}\n\nexport function createVideoStartFailedReason(stateMachineEvent: string | undefined): VideoStartFailedReason {\n switch (stateMachineEvent) {\n case Event.ERROR:\n return VideoStartFailedReason.PLAYER_ERROR;\n case Event.UNLOAD:\n return VideoStartFailedReason.PAGE_CLOSED;\n case Event.MANUAL_SOURCE_CHANGE:\n return VideoStartFailedReason.PAGE_CLOSED;\n case Event.SOURCE_UNLOADED:\n return VideoStartFailedReason.PAGE_CLOSED;\n case Event.VIDEOSTART_TIMEOUT:\n return VideoStartFailedReason.TIMEOUT;\n\n default:\n return VideoStartFailedReason.UNKNOWN;\n }\n}\n","import {isNotNullish} from '../utils/Utils';\n\nimport {FeatureConfig} from './FeatureConfig';\n\nexport abstract class Feature<TConfigContainer, TConfig extends FeatureConfig> {\n private _config?: TConfig = undefined;\n private _isEnabled = true;\n\n get config(): TConfig | undefined {\n return this._config;\n }\n\n get isEnabled(): boolean {\n return this._isEnabled;\n }\n\n abstract reset(): void;\n abstract enabled(): void;\n abstract disabled(): void;\n abstract configured(authenticated: boolean, config?: TConfig): void;\n\n disable() {\n this._isEnabled = false;\n this.disabled();\n }\n\n configure(authenticated: boolean, configContainer?: TConfigContainer): TConfig | undefined {\n if (isNotNullish(configContainer)) {\n this._config = this.extractConfig(configContainer);\n }\n this.configured(authenticated, this._config);\n return this._config;\n }\n\n abstract extractConfig(configContainer: TConfigContainer): TConfig | undefined;\n}\n","import {logger} from '../utils/Logger';\n\nimport {Feature} from './Feature';\nimport {FeatureConfig} from './FeatureConfig';\n\nexport class FeatureManager<TConfigContainer> {\n private features: Array<Feature<TConfigContainer, FeatureConfig>> = [];\n\n registerFeatures(features: Array<Feature<TConfigContainer, FeatureConfig>>) {\n this.features = features;\n }\n\n unregisterFeatures() {\n this.features.forEach((feature) => feature.disable());\n this.features = [];\n }\n\n resetFeatures() {\n this.features.forEach((feature) => feature.reset());\n }\n\n configureFeatures(authenticated: boolean, featureConfigs?: TConfigContainer) {\n this.features = this.features.filter((feature) => {\n const config = feature.configure(authenticated, featureConfigs);\n if (!authenticated || config?.enabled !== true) {\n logger.log(`Disabling feature ${feature.constructor.name} as it isn't enabled according to license callback.`);\n feature.disable();\n return false;\n }\n return true;\n });\n this.features.forEach((feature) => feature.enabled());\n }\n}\n","import {CollectorConfig} from '../../types/AnalyticsConfig';\nimport {post} from '../../utils/Http';\nimport {ANALYTICS_BACKEND_BASE_URL} from '../../utils/Settings';\nimport {isNotNullish, joinUrls} from '../../utils/Utils';\nimport {HttpRequest} from '../httprequesttracking/HttpRequest';\n\nimport {ErrorData} from './ErrorData';\nimport {ErrorDetail} from './ErrorDetail';\n\nexport class ErrorDetailBackend {\n get queue(): ReadonlyArray<ErrorDetail> {\n return this._queue;\n }\n\n get enabled(): boolean {\n return this._enabled;\n }\n\n set enabled(value: boolean) {\n this._enabled = value;\n }\n\n static copyErrorDetailTruncateStringsAndUrls(\n errorDetail: ErrorDetail,\n maxStringLength: number,\n maxUrlLength: number,\n ): ErrorDetail {\n return {\n ...errorDetail,\n message: errorDetail.message?.substr(0, maxStringLength),\n data: this.copyErrorDataTruncateStrings(errorDetail.data, maxStringLength),\n httpRequests: errorDetail.httpRequests?.map((request) => this.copyHttpRequestTruncateUrls(request, maxUrlLength)),\n };\n }\n\n static copyHttpRequestTruncateUrls(httpRequest: HttpRequest, maxLength: number): HttpRequest {\n return {\n ...httpRequest,\n url: httpRequest.url?.substr(0, maxLength),\n lastRedirectLocation: httpRequest.lastRedirectLocation?.substr(0, maxLength),\n };\n }\n\n static copyErrorDataTruncateStrings(errorData: ErrorData, maxStringLength: number): ErrorData {\n return {\n ...errorData,\n exceptionMessage: errorData.exceptionMessage?.substr(0, maxStringLength),\n additionalData: errorData.additionalData?.substr(0, maxStringLength),\n };\n }\n\n static copyErrorDetailTruncateHttpRequests(errorDetail: ErrorDetail, maxRequests: number): ErrorDetail {\n return {\n ...errorDetail,\n httpRequests: errorDetail.httpRequests?.slice(-maxRequests),\n };\n }\n\n // We use these as upper limits to avoid clients bombing us with data, actual truncation to documented limits is\n // happening in ingress\n private static MAX_URL_LENGTH = 450;\n private static MAX_STRING_LENGTH = 2000;\n\n private readonly backendUrl: string;\n private readonly _queue: ErrorDetail[] = [];\n private _enabled = false;\n\n constructor(collectorConfig: CollectorConfig | undefined) {\n this.backendUrl = joinUrls(collectorConfig?.backendUrl ?? ANALYTICS_BACKEND_BASE_URL, '/analytics/error');\n }\n\n limitHttpRequestsOfQueuedErrorDetails(max: number) {\n this._queue.forEach((value, index) => {\n this._queue[index] = ErrorDetailBackend.copyErrorDetailTruncateHttpRequests(value, max);\n });\n }\n\n send(errorDetail: ErrorDetail) {\n const errorDetailCopy = ErrorDetailBackend.copyErrorDetailTruncateStringsAndUrls(\n errorDetail,\n ErrorDetailBackend.MAX_STRING_LENGTH,\n ErrorDetailBackend.MAX_URL_LENGTH,\n );\n if (this.enabled) {\n post(this.backendUrl, errorDetailCopy);\n } else {\n this._queue.push(errorDetailCopy);\n }\n }\n\n flush() {\n const copy = [...this._queue];\n let element = copy.shift();\n while (isNotNullish(element)) {\n this.removeFromQueue(element);\n this.send(element);\n element = copy.shift();\n }\n }\n\n clear() {\n this._queue.splice(0, this._queue.length);\n }\n\n private removeFromQueue(element: ErrorDetail) {\n const index = this._queue.findIndex((value) => value === element);\n if (index >= 0) {\n this._queue.splice(index, 1);\n }\n }\n}\n","import {Subscribable} from '../../core/EventDispatcher';\nimport {CollectorConfig} from '../../types/AnalyticsConfig';\nimport {FeatureConfigContainer} from '../../types/FeatureConfigContainer';\nimport {logger} from '../../utils/Logger';\nimport {getCurrentTimestamp, isNullish, tryJSONStringify} from '../../utils/Utils';\nimport {VERSION} from '../../utils/Version';\nimport {Feature} from '../Feature';\nimport {HttpRequestTracking} from '../httprequesttracking/HttpRequestTracking';\n\nimport {ErrorDetail} from './ErrorDetail';\nimport {ErrorDetailBackend} from './ErrorDetailBackend';\nimport {ErrorDetailTrackingConfig} from './ErrorDetailTrackingConfig';\nimport {OnErrorDetailEventObject} from './OnErrorDetailEventObject';\n\nexport interface ErrorDetailTrackingSettingsProvider {\n readonly licenseKey: string;\n readonly domain: string;\n readonly impressionId: string;\n readonly collectorConfig?: CollectorConfig;\n}\n\nexport class ErrorDetailTracking extends Feature<FeatureConfigContainer, ErrorDetailTrackingConfig> {\n private errorIndex = 0;\n\n constructor(\n private settingsProvider: ErrorDetailTrackingSettingsProvider,\n private backend: ErrorDetailBackend,\n private subscribables: Array<Subscribable<OnErrorDetailEventObject>>,\n private httpRequestTracking: HttpRequestTracking | undefined,\n ) {\n super();\n subscribables.forEach((subscribable) => subscribable.subscribe(this.onErrorHandler));\n }\n\n reset(): void {\n this.httpRequestTracking?.reset();\n this.errorIndex = 0;\n }\n\n enabled(): void {\n this.backend.enabled = true;\n this.backend.flush();\n }\n\n disabled(): void {\n this.errorIndex = 0;\n this.httpRequestTracking?.disable();\n this.backend.clear();\n this.subscribables.forEach((subscribable) => subscribable.unsubscribe(this.onErrorHandler));\n }\n\n configured(_authenticated: boolean, config?: ErrorDetailTrackingConfig): void {\n const maxRequests = Math.max(config?.numberOfHttpRequests ?? 0, 0);\n this.httpRequestTracking?.configure(maxRequests);\n this.backend.limitHttpRequestsOfQueuedErrorDetails(maxRequests);\n }\n\n extractConfig(configContainer: FeatureConfigContainer): ErrorDetailTrackingConfig | undefined {\n return configContainer.errorDetails;\n }\n\n private onErrorHandler = (event: OnErrorDetailEventObject) => {\n try {\n if (!this.isEnabled) {\n return;\n }\n\n const httpRequests = this.httpRequestTracking?.httpRequests;\n const httpRequestsCopy = isNullish(httpRequests) ? undefined : [...httpRequests];\n const errorIndex = this.errorIndex;\n this.errorIndex++;\n\n const errorDetail: ErrorDetail = {\n platform: 'web',\n licenseKey: this.settingsProvider.licenseKey,\n domain: this.settingsProvider.domain,\n impressionId: this.settingsProvider.impressionId,\n analyticsVersion: VERSION,\n errorId: errorIndex,\n timestamp: getCurrentTimestamp(),\n code: event.code,\n message: event.message,\n data: event.errorData ?? {\n additionalData: undefined,\n exceptionMessage: undefined,\n exceptionStacktrace: undefined,\n },\n httpRequests: httpRequestsCopy,\n severity: event.severity,\n };\n\n logger.log(`ErrorDetailTracking.onError: ${tryJSONStringify(errorDetail)}`);\n this.backend.send(errorDetail);\n } catch (error) {\n logger.error(`ErrorDetailTracking.onError: Error in handler`, error);\n }\n };\n}\n","import {Subscribable} from '../../core/EventDispatcher';\nimport {logger} from '../../utils/Logger';\nimport {Queue} from '../../utils/Queue';\n\nimport {HttpRequest} from './HttpRequest';\nimport {OnDownloadFinishedEventObject} from './OnDownloadFinishedEventObject';\n\nexport class HttpRequestTracking {\n private static DEFAULT_MAX_REQUESTS = 10;\n private _maxRequests: number = HttpRequestTracking.DEFAULT_MAX_REQUESTS;\n private _httpRequestQueue = new Queue<HttpRequest>();\n\n get maxRequests(): number {\n return this._maxRequests;\n }\n\n get httpRequests(): ReadonlyArray<HttpRequest> {\n return this._httpRequestQueue.items;\n }\n\n constructor(private subscribables: Array<Subscribable<OnDownloadFinishedEventObject>>) {\n subscribables.forEach((subscribable) => subscribable.subscribe(this.onDownloadFinishedHandler));\n }\n\n configure(maxRequests: number) {\n this._maxRequests = maxRequests;\n this._httpRequestQueue.limit(maxRequests);\n }\n\n disable() {\n this.subscribables.forEach((subscribable) => subscribable.unsubscribe(this.onDownloadFinishedHandler));\n this._httpRequestQueue.clear();\n }\n\n reset() {\n this._httpRequestQueue.clear();\n }\n\n private onDownloadFinishedHandler = (event: OnDownloadFinishedEventObject) => {\n try {\n this.addRequest(event.httpRequest);\n } catch (error) {\n logger.error(`HttpRequestTracking.onDownloadFinished: Error in handler`, error);\n }\n };\n\n private addRequest(httpRequest: HttpRequest) {\n this._httpRequestQueue.offer(httpRequest);\n this._httpRequestQueue.limit(this._maxRequests);\n }\n}\n","/**\n * This enum is supposed to represent the type of HTTP request made by any player,\n * and should be used to categorize the requests in the {@link OnDownloadFinishedEventObject} events.\n *\n * @remarks\n *\n * Instead of creating our own categorization of HTTP request types, we decided to copy the `HttpRequestType` enum\n * from Bitmovin8 Player. This way, we can directly use the `downloadType` value from the `DownloadFinishedEvent`\n * without needing to map it to our own types, and we can ensure that the categorization is consistent with what the\n * player provides. In the case of other players, we can still map their request types to this enum as much as possible,\n * and use `UNKNOWN` for any types that don't fit into the existing categories.\n *\n * @see https://github.com/bitmovin-engineering/bitdash/blob/development/src/core/NetworkAPI.ts#L11\n */\nexport enum HttpRequestType {\n /* eslint-disable perfectionist/sort-enums */\n\n MANIFEST_DASH = 'manifest/dash',\n MANIFEST_HLS_MASTER = 'manifest/hls/master',\n MANIFEST_HLS_VARIANT = 'manifest/hls/variant',\n MANIFEST_SMOOTH = 'manifest/smooth',\n MANIFEST_ADS = 'manifest/ads',\n\n MEDIA_AUDIO = 'media/audio',\n MEDIA_VIDEO = 'media/video',\n MEDIA_SUBTITLES = 'media/subtitles',\n MEDIA_THUMBNAILS = 'media/thumbnails',\n MEDIA_SEGMENTINDEX = 'media/segmentindex',\n\n DRM_LICENSE_WIDEVINE = 'drm/license/widevine',\n DRM_LICENSE_PLAYREADY = 'drm/license/playready',\n DRM_LICENSE_FAIRPLAY = 'drm/license/fairplay',\n DRM_LICENSE_PRIMETIME = 'drm/license/primetime',\n DRM_LICENSE_CLEARKEY = 'drm/license/clearkey',\n DRM_LICENSE_TVKEY = 'drm/license/tvkey',\n\n DRM_CERTIFICATE_FAIRPLAY = 'drm/certificate/fairplay',\n\n HLS_INTERSTITIALS_ASSET_LIST = 'hls/interstitials/asset-list',\n\n KEY_HLS_AES = 'key/hls/aes',\n\n TIME_SYNC = 'time/sync',\n\n WEBRTC_SDP_REQUEST = 'webrtc/sdp/request',\n WEBRTC_SDP_ANSWER = 'webrtc/sdp/answer',\n WEBRTC_SDP_OFFER = 'webrtc/sdp/offer',\n\n UNKNOWN = 'unknown',\n\n INTERNAL = 'internal',\n\n /* eslint-enable perfectionist/sort-enums */\n}\n","import {getCustomDataString, transferCustomDataFields} from '../utils/Utils';\n\nexport interface CustomDataValues {\n customData1?: string;\n customData2?: string;\n customData3?: string;\n customData4?: string;\n customData5?: string;\n customData6?: string;\n customData7?: string;\n customData8?: string;\n customData9?: string;\n customData10?: string;\n customData11?: string;\n customData12?: string;\n customData13?: string;\n customData14?: string;\n customData15?: string;\n customData16?: string;\n customData17?: string;\n customData18?: string;\n customData19?: string;\n customData20?: string;\n customData21?: string;\n customData22?: string;\n customData23?: string;\n customData24?: string;\n customData25?: string;\n customData26?: string;\n customData27?: string;\n customData28?: string;\n customData29?: string;\n customData30?: string;\n customData31?: string;\n customData32?: string;\n customData33?: string;\n customData34?: string;\n customData35?: string;\n customData36?: string;\n customData37?: string;\n customData38?: string;\n customData39?: string;\n customData40?: string;\n customData41?: string;\n customData42?: string;\n customData43?: string;\n customData44?: string;\n customData45?: string;\n customData46?: string;\n customData47?: string;\n customData48?: string;\n customData49?: string;\n customData50?: string;\n customData51?: string;\n customData52?: string;\n customData53?: string;\n customData54?: string;\n customData55?: string;\n customData56?: string;\n customData57?: string;\n customData58?: string;\n customData59?: string;\n customData60?: string;\n customData61?: string;\n customData62?: string;\n customData63?: string;\n customData64?: string;\n customData65?: string;\n customData66?: string;\n customData67?: string;\n customData68?: string;\n customData69?: string;\n customData70?: string;\n customData71?: string;\n customData72?: string;\n customData73?: string;\n customData74?: string;\n customData75?: string;\n customData76?: string;\n customData77?: string;\n customData78?: string;\n customData79?: string;\n customData80?: string;\n customData81?: string;\n customData82?: string;\n customData83?: string;\n customData84?: string;\n customData85?: string;\n customData86?: string;\n customData87?: string;\n customData88?: string;\n customData89?: string;\n customData90?: string;\n customData91?: string;\n customData92?: string;\n customData93?: string;\n customData94?: string;\n customData95?: string;\n customData96?: string;\n customData97?: string;\n customData98?: string;\n customData99?: string;\n customData100?: string;\n experimentName?: string;\n}\n\n/**\n * Lists all keys of the {@see CustomDataValues} interface.\n */\nexport const customDataValuesKeys: Array<keyof CustomDataValues> = [\n 'customData1',\n 'customData2',\n 'customData3',\n 'customData4',\n 'customData5',\n 'customData6',\n 'customData7',\n 'customData8',\n 'customData9',\n 'customData10',\n 'customData11',\n 'customData12',\n 'customData13',\n 'customData14',\n 'customData15',\n 'customData16',\n 'customData17',\n 'customData18',\n 'customData19',\n 'customData20',\n 'customData21',\n 'customData22',\n 'customData23',\n 'customData24',\n 'customData25',\n 'customData26',\n 'customData27',\n 'customData28',\n 'customData29',\n 'customData30',\n 'customData31',\n 'customData32',\n 'customData33',\n 'customData34',\n 'customData35',\n 'customData36',\n 'customData37',\n 'customData38',\n 'customData39',\n 'customData40',\n 'customData41',\n 'customData42',\n 'customData43',\n 'customData44',\n 'customData45',\n 'customData46',\n 'customData47',\n 'customData48',\n 'customData49',\n 'customData50',\n 'customData51',\n 'customData52',\n 'customData53',\n 'customData54',\n 'customData55',\n 'customData56',\n 'customData57',\n 'customData58',\n 'customData59',\n 'customData60',\n 'customData61',\n 'customData62',\n 'customData63',\n 'customData64',\n 'customData65',\n 'customData66',\n 'customData67',\n 'customData68',\n 'customData69',\n 'customData70',\n 'customData71',\n 'customData72',\n 'customData73',\n 'customData74',\n 'customData75',\n 'customData76',\n 'customData77',\n 'customData78',\n 'customData79',\n 'customData80',\n 'customData81',\n 'customData82',\n 'customData83',\n 'customData84',\n 'customData85',\n 'customData86',\n 'customData87',\n 'customData88',\n 'customData89',\n 'customData90',\n 'customData91',\n 'customData92',\n 'customData93',\n 'customData94',\n 'customData95',\n 'customData96',\n 'customData97',\n 'customData98',\n 'customData99',\n 'customData100',\n\n 'experimentName',\n];\n\n/**\n * The number of CustomDataXX fields in {@see CustomDataValues}.\n */\nexport const customDataFieldCount = customDataValuesKeys.filter((i) => i.match('customData\\\\d+')).length;\n\n/**\n * We are extracting the customData fields explicitly to make sure that there is not a different object passed\n */\nexport const extractCustomDataFieldsOnly = (input: CustomDataValues): CustomDataValues => {\n const retVal: CustomDataValues = {};\n customDataValuesKeys.forEach((key) => {\n if (input[key]) {\n retVal[key] = input[key];\n }\n });\n return retVal;\n};\n\nexport const sanitizeCustomDataValues = (customDataValues: CustomDataValues): CustomDataValues => {\n const extracted = extractCustomDataFieldsOnly(customDataValues);\n\n const sanitizedCustomDataValues: CustomDataValues = {};\n transferCustomDataFields(extracted, sanitizedCustomDataValues);\n // fix a bug of transferCustomDataFields that does not transfer 'experimentName' field, because it is not named 'customDataXX'\n // should be fixed with https://bitmovin.atlassian.net/browse/AN-5182\n sanitizedCustomDataValues.experimentName = getCustomDataString(extracted.experimentName);\n\n return sanitizedCustomDataValues;\n};\n","import {FeatureConfigContainer} from './FeatureConfigContainer';\n\nexport interface LicensingRequest {\n key?: string;\n domain: string;\n version: string;\n}\n\nexport enum LicensingResult {\n Denied = 'denied',\n Granted = 'granted',\n Skip = 'skip',\n}\n\nexport interface LicensingResponse {\n status: LicensingResult;\n message: string;\n features?: FeatureConfigContainer;\n}\n\nexport type LicenseCallFunc = (\n key: string,\n domain: string,\n version: string,\n baseUrl: string,\n) => Promise<LicensingResponse>;\n","import {PlayerSize} from '../enums/PlayerSize';\nimport {StreamTypes} from '../enums/StreamTypes';\nimport {isNullish} from '../utils/Utils';\n\nexport interface PlaybackInfo {\n audioBitrate?: number;\n audioCodec?: string;\n audioLanguage?: string;\n castTech?: string;\n droppedFrames: number;\n isCasting?: boolean;\n isLive?: boolean;\n isMuted?: boolean;\n m3u8Url?: string;\n mpdUrl?: string;\n playerTech?: string;\n progUrl?: string;\n screenHeight?: number;\n screenWidth?: number;\n size?: PlayerSize;\n streamFormat?: string;\n subtitleEnabled?: boolean;\n subtitleLanguage?: string;\n videoBitrate?: number;\n videoCodec?: string;\n videoDuration?: number;\n videoPlaybackHeight?: number;\n videoPlaybackWidth?: number;\n videoTitle?: string;\n videoWindowHeight?: number;\n videoWindowWidth?: number;\n}\n\nexport function normalizeVideoDuration(playerVideoDuration: number | null | undefined): number {\n // This covers Live streams and any case in which the duration is not known\n // which should report 0 as videoDuration\n if (isNullish(playerVideoDuration) || Number.isNaN(playerVideoDuration) || playerVideoDuration === Infinity) {\n return 0;\n }\n return playerVideoDuration;\n}\n\nexport function buildPlaybackInfoStreamTypeFields(\n streamType: StreamTypes | undefined,\n streamUrl: string | undefined,\n): Pick<PlaybackInfo, 'm3u8Url' | 'mpdUrl' | 'progUrl' | 'streamFormat'> {\n const DEFAULT_RESULT = {\n // set the stream type as it is (except null, that should be converted to undefined)\n streamFormat: streamType ?? undefined,\n // If the stream url is there, set it as \"progUrl\", even when the stream type is not recognized (unknown / nullish).\n // Why?\n // There was no clear reason why when this utility fn was created, it was just current written code/behavior\n // of our adapters, and for that reason it was copy&pasted here.\n progUrl: streamUrl,\n };\n\n if (isNullish(streamType)) {\n return DEFAULT_RESULT;\n }\n\n if (streamType === StreamTypes.dash) {\n return {streamFormat: streamType, mpdUrl: streamUrl};\n }\n if (streamType === StreamTypes.hls) {\n return {streamFormat: streamType, m3u8Url: streamUrl};\n }\n if (streamType === StreamTypes.prog) {\n return {streamFormat: streamType, progUrl: streamUrl};\n }\n\n return DEFAULT_RESULT;\n}\n","import {logger} from '../utils/Logger';\nimport {isValidString} from '../utils/stringUtils';\nimport {isBoolean, isNotNullish, isNullish, isPlainObject} from '../utils/Utils';\n\nimport {CustomDataValues, sanitizeCustomDataValues} from './CustomDataValues';\n\nexport interface SourceMetadata {\n readonly title?: string;\n readonly videoId?: string;\n readonly cdnProvider?: string;\n readonly path?: string;\n readonly isLive?: boolean;\n readonly customData?: CustomDataValues;\n}\n\nexport function hasValidSourceMetadataStructure(anything: unknown): anything is SourceMetadata | null | undefined {\n // \"nullish\" is considered to be valid SourceMetadata, because we will then use an empty object as a default value\n if (isNullish(anything)) {\n return true;\n }\n\n // invalid, when value was defined, but not as a plain object\n if (!isPlainObject(anything as object)) {\n logger.errorMessageToUser('Invalid SourceMetadata: not a plain object');\n return false;\n }\n\n const maybeSourceMetadata = anything as SourceMetadata;\n\n if (isNotNullish(maybeSourceMetadata.customData) && !isPlainObject(maybeSourceMetadata.customData)) {\n logger.errorMessageToUser(\"Invalid SourceMetadata: 'customData' property is not a plain object\");\n return false;\n }\n\n return true;\n}\n\nexport function sanitizeSourceMetadata(sourceMetadata: SourceMetadata | null | undefined): SourceMetadata {\n // \"nullish\" is considered to be valid SourceMetadata\n if (isNullish(sourceMetadata)) {\n // sanitize to be not \"nullish\"\n return {};\n }\n\n let result: SourceMetadata = {};\n if ('title' in sourceMetadata) {\n result = {\n ...result,\n title: isValidString(sourceMetadata.title) ? sourceMetadata.title : undefined,\n };\n }\n\n if ('videoId' in sourceMetadata) {\n result = {\n ...result,\n videoId: isValidString(sourceMetadata.videoId) ? sourceMetadata.videoId : undefined,\n };\n }\n\n if ('cdnProvider' in sourceMetadata) {\n result = {\n ...result,\n cdnProvider: isValidString(sourceMetadata.cdnProvider) ? sourceMetadata.cdnProvider : undefined,\n };\n }\n\n if ('path' in sourceMetadata) {\n result = {\n ...result,\n path: isValidString(sourceMetadata.path) ? sourceMetadata.path : undefined,\n };\n }\n\n if ('isLive' in sourceMetadata) {\n result = {\n ...result,\n isLive: isBoolean(sourceMetadata.isLive) ? sourceMetadata.isLive : undefined,\n };\n }\n\n if ('customData' in sourceMetadata) {\n result = {\n ...result,\n customData: isNotNullish(sourceMetadata.customData)\n ? sanitizeCustomDataValues(sourceMetadata.customData)\n : undefined,\n };\n }\n\n return result;\n}\n","import type {VideoStartFailedReason} from '../enums/VideoStartFailedReason';\n\nimport type {AnalyticsConfig} from './AnalyticsConfig';\nimport type {AnalyticsEventBase, CustomDataValuesEvent, ErrorEvent, QualityChangeEvent} from './EventData';\nimport type {Sample} from './Sample';\nimport type {SourceMetadata} from './SourceMetadata';\n\nexport type HeartbeatPayload = {\n buffered?: Sample['buffered'];\n /**\n * Flag indicating that the event was triggered by a program change.\n *\n * `true` if the event was triggered by a program change, `undefined` otherwise to not set it as a property in the sample.\n */\n isProgramChange?: true;\n played?: Sample['played'];\n /** Flag indicating that the event was triggered by SSAI */\n triggeredBySsai?: boolean;\n};\n\nexport interface StateMachineCallbacks {\n setup: (duration: number, state: string) => void;\n startup: (duration: number, state: string) => void;\n /** Should reset the analytics, update the source metadata, and send a \"program change startup sample\" */\n programChange: (sourceMetadata: SourceMetadata) => void;\n /** Should only update the source metadata in the analytics module, but without sending any sample. */\n updateSourceMetadata: (sourceMetadata: SourceMetadata) => void;\n playing: (duration: number, state: string) => void;\n heartbeat: (duration: number, state: 'buffering' | 'playing', payload: HeartbeatPayload) => void;\n /**\n * Should send a sample with state \"qualitychange\" and duration 0\n */\n qualitychange: (event: QualityChangeEvent) => void;\n /**\n * Should update the qualityInfo on the current sample but not send any sample, e.g when a qualityChange occurs during\n * pause, seeking or buffering or when the QUALITY_CHANGE_THRESHOLD was hit\n */\n updateSampleQualityInfo: (event: QualityChangeEvent) => void;\n audiotrack_changing: () => void;\n pause: (duration: number, state: string) => void;\n /**\n * Should send a sample with `state: \"seeking\"` and `duration` set to the duration of the seeking.\n */\n seeking: (duration: number) => void;\n buffering: (duration: number, state: string) => void;\n error: (event: Readonly<ErrorEvent>) => void;\n /**\n * @deprecated should not be used at all.\n *\n * Instead, the \"end\" player event should transition state machine to PAUSE state\n *\n * https://bitmovin.atlassian.net/browse/AN-5134\n */\n end: (duration: number, state: string) => void;\n unload: (duration: number, state: string) => void;\n ad: (duration: number, state: string) => void;\n mute: () => void;\n unMute: () => void;\n subtitle_changing: () => void;\n setVideoTimeEndFromEvent: (analyticsEventBase: AnalyticsEventBase) => void;\n setVideoTimeStartFromEvent: (analyticsEventBase: AnalyticsEventBase) => void;\n videoStartFailed: (duration: number, reason: VideoStartFailedReason) => void;\n startCasting: (duration: number, event: any) => void;\n casting: (duration: number, event: any) => void;\n manualSourceChange: (event: {config: AnalyticsConfig}) => void;\n initialSourceChange: (event: {config: AnalyticsConfig}) => void;\n muting_ready: (duration: number, state: string, event: any) => void;\n /**\n * Should change {@link CustomDataValues} of analytics module.\n *\n * @remarks\n *\n * It is called via the default \"onleavestate\" state machine callback, and because of that:\n * - it has to match the state name \"CUSTOMDATACHANGE\"\n * - each parameter has to of `undefined` type (unintentionally, it can be called at any time, from any state)\n */\n customdatachange: (\n duration: number | undefined,\n state: string | undefined,\n eventData: CustomDataValuesEvent | undefined,\n ) => void;\n\n /** shuts down the collection and removes/clears all timeouts, intervals, event listeners */\n release: () => void;\n}\n\n/**\n * {@link StateMachineCallbacks} object with each callback set to be empty function (doing nothing).\n *\n * Why?:\n * We need to set it as default value in {@link InternalAdapter} for use case, when {@link InternalAdapter}\n * is already created and listen to player events, but {@link Analytics} was not instantiated/initialized yet (that\n * should set correct {@link StateMachineCallbacks} implementation)\n */\nexport const defaultStateMachineCallbacks: StateMachineCallbacks = {\n setup: () => {},\n startup: () => {},\n programChange: () => {},\n updateSourceMetadata: () => {},\n playing: () => {},\n heartbeat: () => {},\n qualitychange: () => {},\n updateSampleQualityInfo: () => {},\n audiotrack_changing: () => {},\n pause: () => {},\n seeking: () => {},\n buffering: () => {},\n error: () => {},\n end: () => {},\n unload: () => {},\n ad: () => {},\n mute: () => {},\n unMute: () => {},\n subtitle_changing: () => {},\n setVideoTimeEndFromEvent: () => {},\n setVideoTimeStartFromEvent: () => {},\n videoStartFailed: () => {},\n startCasting: () => {},\n casting: () => {},\n manualSourceChange: () => {},\n initialSourceChange: () => {},\n muting_ready: () => {},\n customdatachange: () => {},\n release: () => {},\n};\n","import {isNotNullish, isNullish} from '../utils/Utils';\n\nexport interface SubtitleInfo {\n /**\n * Indicates if subtitles are displayed.\n */\n enabled: boolean;\n /**\n * The selected subtitle/captions language.\n */\n language?: string;\n}\n\nexport const isDifferentSubtitleInfo = (info1?: SubtitleInfo, info2?: SubtitleInfo): boolean => {\n if (isNullish(info1) && isNullish(info2)) {\n return false;\n }\n return !(\n isNotNullish(info1) &&\n isNotNullish(info2) &&\n info1.enabled === info2.enabled &&\n info1.language === info2.language\n );\n};\n","import {appendSsaiRoutingParam, isSsaiRelatedSample} from '../core/ssai/ssaiUtils';\nimport type {AdSample} from '../types/AdSample';\nimport type {Sample} from '../types/Sample';\n\nimport {globalScope} from './globalScope';\nimport {post} from './Http';\nimport {joinUrls} from './Utils';\n\nexport class AnalyticsCall {\n private readonly analyticsServerUrl: string;\n private readonly adAnalyticsServerUrl: string;\n\n constructor(baseUrl: string) {\n this.analyticsServerUrl = joinUrls(baseUrl, 'analytics');\n this.adAnalyticsServerUrl = joinUrls(baseUrl, 'analytics/a');\n }\n\n sendRequest(sample: Sample) {\n let analyticsUrl = this.analyticsServerUrl;\n if (isSsaiRelatedSample(sample)) {\n analyticsUrl = appendSsaiRoutingParam(analyticsUrl);\n }\n\n post(analyticsUrl, sample);\n }\n\n sendUnloadRequest(sample: Sample) {\n const sendBeaconFallback = (data: Sample) => this.sendRequestSynchronous(data);\n\n let analyticsUrl = this.analyticsServerUrl;\n if (isSsaiRelatedSample(sample)) {\n analyticsUrl = appendSsaiRoutingParam(analyticsUrl);\n }\n\n this.trySendBeacon(sendBeaconFallback, analyticsUrl, sample);\n }\n\n private trySendBeacon(\n fallbackFunction: (data: any) => void,\n url: string,\n data: unknown,\n requestHeaders: {[headerName: string]: string} = {},\n ) {\n if (typeof globalScope.navigator?.sendBeacon === 'undefined') {\n fallbackFunction(data);\n } else {\n /**\n * With a Blob we can send payload but also http headers\n * @see https://stackoverflow.com/questions/40523469/navigator-sendbeacon-to-pass-header-information\n */\n const blob = new Blob([JSON.stringify(data)], requestHeaders);\n const success = globalScope.navigator.sendBeacon(url, blob);\n if (!success) {\n fallbackFunction(data);\n }\n }\n }\n\n sendRequestSynchronous(sample: Sample) {\n let analyticsUrl = this.analyticsServerUrl;\n if (isSsaiRelatedSample(sample)) {\n analyticsUrl = appendSsaiRoutingParam(analyticsUrl);\n }\n\n post(analyticsUrl, sample, undefined, false);\n }\n\n sendAdRequest(adSample: AdSample) {\n let adAnalyticsUrl = this.adAnalyticsServerUrl;\n if (isSsaiRelatedSample(adSample)) {\n adAnalyticsUrl = appendSsaiRoutingParam(adAnalyticsUrl);\n }\n\n const sendBeaconFallback = (data: AdSample) => post(adAnalyticsUrl, data);\n this.trySendBeacon(sendBeaconFallback, adAnalyticsUrl, adSample);\n }\n}\n","import {ProgressiveSourceConfig} from '../types/ProgressiveSourceConfig';\nimport {ProgressiveSourceInfo} from '../types/SourceInfo';\n\nimport {isNotNullish} from './Utils';\n\nexport const getSourceInfoFromBitmovinSourceConfig = (\n progressive: ProgressiveSourceConfig,\n player: any,\n): ProgressiveSourceInfo => {\n if (!progressive) {\n return {\n progBitrate: undefined,\n progUrl: undefined,\n };\n }\n\n if (typeof progressive === 'string') {\n return {\n progBitrate: 0,\n progUrl: progressive,\n };\n }\n\n if (Array.isArray(progressive) && progressive.length > 0) {\n const playbackVideoData = player.getPlaybackVideoData();\n let progressiveArrayIndex = 0;\n\n if (isNotNullish(playbackVideoData) && !isNaN(+playbackVideoData.id)) {\n progressiveArrayIndex = +playbackVideoData.id;\n }\n\n return {\n progBitrate: progressive[progressiveArrayIndex].bitrate || 0,\n progUrl: progressive[progressiveArrayIndex].url,\n };\n }\n\n if (typeof progressive === 'object' && !Array.isArray(progressive)) {\n return {\n progBitrate: progressive.bitrate || 0,\n progUrl: progressive.url,\n };\n }\n\n return {\n progBitrate: undefined,\n progUrl: undefined,\n };\n};\n","import {globalScope} from './globalScope';\nimport {isFunction, isNullish} from './Utils';\n\nconst videoFormatCodecMap: {[format: string]: string[]} = {\n avc: ['video/mp4; codecs=\"avc1.42000a\"'],\n vp9: ['video/mp4; codecs=\"vp09.00.50.08\"'],\n av1: ['video/mp4; codecs=\"av01.0.08M.08\"'],\n hevc: ['video/mp4; codecs=\"hev1.1.6.L93.B0\"'],\n};\n\nexport class CodecHelper {\n static get supportedVideoFormats(): string[] | undefined {\n if (isNullish(globalScope.MediaSource?.isTypeSupported) || !isFunction(globalScope.MediaSource.isTypeSupported)) {\n return undefined;\n }\n return Object.getOwnPropertyNames(videoFormatCodecMap).filter((format) =>\n videoFormatCodecMap[format].some((codec) => globalScope.MediaSource.isTypeSupported(codec)),\n );\n }\n}\n","export class Converter {\n static bytesToBits(bytes: number): number {\n return bytes * 8;\n }\n static bitsToBytes(bits: number): number {\n return Math.round(bits / 8);\n }\n static kiloBitsToBits(kiloBits: number): number {\n return kiloBits * 1000;\n }\n}\n","export class EventDebugging {\n event: string | undefined;\n from: string | undefined;\n to: string | undefined;\n timestamp: number;\n eventObject: any;\n\n constructor(\n event: string | undefined,\n from: string | undefined,\n to: string | undefined,\n timestamp: number,\n eventObject: any,\n ) {\n this.event = event;\n this.from = from;\n this.to = to;\n this.timestamp = timestamp;\n this.eventObject = eventObject;\n }\n}\n","import {globalScope} from './globalScope';\nimport {logger} from './Logger';\nimport {isReactNative} from './Utils';\n\n/**\n * Error-first callback for HTTP POST responses.\n *\n * Follows the Node.js error-first convention: the first argument is `null` on success\n * or an `Error` on failure, the second is the parsed JSON response body or `null` on failure.\n *\n * The callback is guaranteed to be called exactly once on every completion path — success,\n * HTTP error, network error, JSON parse failure, or XHR unavailability — so it is safe\n * to wrap in a `Promise` without risk of the Promise never settling.\n *\n * @param error - `null` when the request succeeded, an `Error` describing the failure otherwise.\n * @param response - The parsed JSON response body on success, `null` on failure.\n *\n * @remarks\n * `null` is used instead of `undefined` because `null` signals intentional absence — \"there is\n * no error\" / \"there is no response\" — whereas `undefined` is ambiguous and could mean the value\n * was never set. This matches the Node.js error-first callback convention where `callback(null, data)`\n * is the idiomatic way to indicate success.\n */\ntype PostCallback = (error: Error | null, response: any | null) => void;\n\n/**\n * Sends an HTTP POST request with JSON-serialized body using XMLHttpRequest\n * (or XDomainRequest as a legacy fallback for IE8/IE9).\n *\n * Designed for fire-and-forget analytics calls (no callback) as well as request-response flows\n * like license validation (with callback). When a callback is provided, it is guaranteed to be\n * called exactly once on every completion path.\n *\n * @param url - The endpoint URL to POST to.\n * @param body - The payload to send. Will be serialized via `JSON.stringify`.\n * @param callback - Optional error-first callback invoked when the request completes, see {@link PostCallback}.\n * @param async - Whether to send the request asynchronously. Defaults to `true`.\n * Forced to `true` in React Native (no sync XHR support) and when using legacy XDomainRequest.\n */\nexport function post(url: string, body: any, callback?: PostCallback, async = true): void {\n let xhttp: any;\n let isLegacyXDomainRequestUsed = false;\n\n // Use \"XMLHttpRequest\" by default to make a POST request\n // What about \"fetch\" API?\n // There is no reason to use \"fetch\" API, the only real gains from \"fetch\" are developer experience.\n // The performance difference is negligible in practice. Both ultimately make the same HTTP request\n // over the same network stack. The browser doesn't route fetch faster than XHR.\n if (globalScope.XMLHttpRequest) {\n xhttp = new globalScope.XMLHttpRequest();\n // check for the standard XMLHttpRequest support with CORS (IE10+, all others)\n if (!('withCredentials' in xhttp)) {\n // Context:\n // In IE8/IE9, XMLHttpRequest exists but doesn't support CORS (has no withCredentials).\n // That's exactly why XDomainRequest was invented. Without this check, IE8/IE9 would pick\n // XMLHttpRequest and fail on cross-origin requests.\n xhttp = null;\n }\n }\n\n // Fallback for IE8/IE9 cross-domain AJAX requests, where there is no support for the standard XMLHttpRequest with CORS.\n if (!xhttp && globalScope.XDomainRequest) {\n // XDomainRequest was Internet Explorer's proprietary CORS object (IE8/IE9), Microsoft decided to come up with\n // their own CORS XHR instead of the standard CORS XMLHttpRequest (which is now used in IE10 and later).\n // Since IE10, XDomainRequest has been deprecated and since IE11 removed.\n xhttp = new globalScope.XDomainRequest();\n isLegacyXDomainRequestUsed = true;\n }\n\n // In practice, this should never happen because all modern environments support XMLHttpRequest, and we have a\n // fallback to XDomainRequest for older IE versions. But this is just a safety check to avoid runtime errors in\n // case we're running in some very unusual environment where neither is available.\n if (!xhttp) {\n const message = 'Failed to create POST request, XHR implementation is missing';\n logger.error(message);\n if (callback) {\n callback(new Error(message), null);\n }\n return;\n }\n\n xhttp.onload = () => {\n // ...with XDomainRequest: status is always 0, itself \"onload\" firing is the only indicator of success\n if (isLegacyXDomainRequestUsed) {\n if (callback) {\n try {\n callback(null, JSON.parse(xhttp.responseText));\n } catch (e) {\n const message = 'Failed to parse response';\n logger.error(message, e);\n callback(new Error(message + ': ' + String(e)), null);\n }\n }\n return;\n }\n\n // ...but with XMLHttpRequest we can check the status properly\n if (xhttp.status < 200 || xhttp.status >= 300) {\n const message = 'POST error response:' + xhttp.status + ': ' + xhttp.statusText;\n logger.error(message);\n if (callback) {\n callback(new Error(message), null);\n }\n return;\n }\n\n if (callback) {\n try {\n callback(null, JSON.parse(xhttp.responseText));\n } catch (e) {\n const message = 'Failed to parse response';\n logger.error(message, e);\n callback(new Error(message + ': ' + String(e)), null);\n }\n }\n };\n\n xhttp.onerror = () => {\n const message = 'POST request failed: ' + xhttp.status + ' ' + xhttp.statusText;\n logger.error(message);\n if (callback) {\n callback(new Error(message), null);\n }\n };\n\n try {\n let openAsyncRequest = async;\n\n // React Native doesn't support synchronous XMLHttpRequest\n if (isReactNative() && !openAsyncRequest) {\n openAsyncRequest = true; // Force async mode in React Native environments\n }\n // Legacy XDomainRequest doesn't support synchronous requests\n // Passing false will either be ignored or throw an error depending on the IE version.\n if (isLegacyXDomainRequestUsed) {\n openAsyncRequest = true; // Force async mode when using legacy XDomainRequest\n }\n\n xhttp.open('POST', url, openAsyncRequest);\n\n // Legacy XDomainRequest doesn't support custom headers to be set\n // https://learn.microsoft.com/en-us/archive/blogs/ieinternals/xdomainrequest-restrictions-limitations-and-workarounds\n if (!isLegacyXDomainRequestUsed) {\n // setRequestHeader() must be called AFTER open() and BEFORE send() — calling it before open() will throw an InvalidStateError.\n xhttp.setRequestHeader('Content-Type', 'text/plain');\n }\n\n xhttp.send(JSON.stringify(body));\n } catch (e) {\n const message = 'Failed to send POST request: ' + String(e);\n logger.error(message);\n if (callback) {\n callback(new Error(message), null);\n }\n }\n}\n","import {LicensingResponse} from '../types/LicensingRequest';\n\nimport {post} from './Http';\nimport {logger} from './Logger';\nimport {ANALYTICS_LICENSECALL_TIMEOUT} from './Settings';\nimport {joinUrls} from './Utils';\n\nexport function LicenseCall(key: string, domain: string, version: string, baseUrl: string): Promise<LicensingResponse> {\n const licenseServerUrl = joinUrls(baseUrl, '/licensing');\n const licensingRequest = {\n analyticsVersion: version,\n domain,\n key,\n };\n return new Promise<LicensingResponse>((resolve, reject) => {\n // Safety net: reject the Promise if the callback is never invoked.\n // Http.post guarantees the callback is called on every completion path,\n // but this timeout protects against unforeseen edge cases (e.g., the XHR\n // silently hanging) that would leave the Promise — and with it the entire\n // analytics session — stuck forever.\n const timeout = setTimeout(() => {\n const message = 'License call POST request timed out';\n logger.error(message);\n reject(new Error(message));\n }, ANALYTICS_LICENSECALL_TIMEOUT);\n\n post(licenseServerUrl, licensingRequest, (error, response) => {\n clearTimeout(timeout);\n if (error) {\n reject(error);\n return;\n }\n resolve(response);\n });\n });\n}\n","import {AnalyticsConfig} from '../types/AnalyticsConfig';\n\n/**\n * Uses a Singleton design pattern.\n *\n * We want to ensure that only one object of its kind exists and provides a single point of access to it,\n * to be able to control enabled/disabled `console` logs for customer in whole code base.\n */\nclass Logger {\n private static instance: Logger;\n\n static getInstance(): Logger {\n if (!Logger.instance) {\n Logger.instance = new Logger();\n }\n\n return Logger.instance;\n }\n\n private analyticsDebugConfig: Readonly<AnalyticsConfig['debug']>;\n\n private constructor() {}\n\n initialize(analyticsDebugConfig: AnalyticsConfig['debug']) {\n this.analyticsDebugConfig = analyticsDebugConfig;\n }\n\n //#region Console API\n log(message?: unknown, ...optionalParams: unknown[]) {\n if (!this.enabled) {\n return;\n }\n console.log(message, optionalParams); //eslint-disable-line no-console\n }\n\n table(tabularData: unknown, properties?: readonly string[]) {\n if (!this.enabled) {\n return;\n }\n console.table(tabularData, properties); //eslint-disable-line no-console\n }\n\n warn(message?: unknown, ...optionalParams: unknown[]) {\n if (!this.enabled) {\n return;\n }\n console.warn(message, optionalParams); //eslint-disable-line no-console\n }\n\n error(message?: unknown, ...optionalParams: unknown[]) {\n if (!this.enabled) {\n return;\n }\n console.error(message, optionalParams); //eslint-disable-line no-console\n }\n\n /**\n * Outputs an error message to user/customer console.\n *\n * Does not relay on {@link Logger#enabled}! because it should deliver the error information to user/customer.\n */\n errorMessageToUser(message?: unknown, ...optionalParams: unknown[]) {\n console.error(message, ...optionalParams); //eslint-disable-line no-console\n }\n //#endregion\n\n /** `true` if {@link AnalyticsConfig#debug} was set */\n private get enabled() {\n return (this.analyticsDebugConfig as boolean) || false;\n }\n}\n\nexport const padRight = (str: string | undefined, length: number) => {\n const padStr = new Array(length).join(' ');\n return (str + padStr).slice(0, length);\n};\n\nexport const logger = Logger.getInstance();\n","export class Queue<T> {\n private readonly _items: T[] = [];\n\n get items(): ReadonlyArray<T> {\n return this._items;\n }\n\n get length() {\n return this._items.length;\n }\n\n offer(item: T) {\n this._items.push(item);\n }\n\n poll(): T | undefined {\n return this._items.shift();\n }\n\n clear() {\n this._items.splice(0);\n }\n\n limit(maxElements: number) {\n while (this._items.length > maxElements) {\n this.poll();\n }\n }\n}\n","export const MESSAGE_NAMESPACE = 'urn:x-cast:com.bitmovin.analytics.cast';\nexport const ANALYTICS_BACKEND_BASE_URL = 'https://analytics-ingress-global.bitmovin.com';\n\nexport const ANALYTICS_LICENSECALL_TIMEOUT = 1000 * 60;\nexport const ANALYTICS_VIDEOSTART_TIMEOUT = 1000 * 60; // in milliseconds\n\nexport const ANALYTICS_QUALITY_CHANGE_COUNT_THRESHOLD = 50;\nexport const ANALYTICS_QUALITY_CHANGE_COUNT_RESET_INTERVAL = 60 * 60 * 1000;\n\n/**\n * Time (in milliseconds) of consecutive buffering until a BUFFER_TIMEOUT_ERROR is raised.\n */\nexport const ANALYTICS_BUFFER_TIMEOUT = 1000 * 60 * 2;\n\n/**\n * minimal time (in seconds) a seek event should have in order to be recogniced as seek\n */\nexport const ANALYTICS_MIN_SEEK_DIFFERENCE_THRESHOLD = 3;\n\n/**\n * Has to be greater or equal than Ingress side limit (currently 1000).\n */\nexport const SEQUENCE_NUMBER_LIMIT = 1000;\n","import {PAGE_LOAD_TYPE} from '../enums/PageLoadType';\nimport {ErrorSeverity} from '../types/AnalyticsConfig';\nimport type {CustomDataValues} from '../types/CustomDataValues';\nimport * as CustomDataUtils from '../types/CustomDataValues';\n\nimport {isDocumentHidden} from './documentUtils';\nimport {getGlobalNavigatorProduct} from './globalScopeUtils';\nimport {endsWith, startsWith} from './stringUtils';\n\n/**\n * Performs a loose equality check (==), which means it checks for both null and undefined.\n *\n * @returns {value is null | undefined} `true` if the given value is `null` or `undefined`.\n */\nexport const isNullish = (value: unknown): value is null | undefined => value == null;\n\n/**\n *\n * @returns {value is Exclude<unknown, null | undefined>} `true` if the given value is not `null` and is not `undefined`.\n */\nexport const isNotNullish = <T = unknown>(value: T): value is Exclude<T, null | undefined> => !isNullish(value);\n\n/**\n * @returns {value is boolean} `true` if the given value is {@link isNotNullish} and is type of `boolean`.\n */\nexport const isBoolean = (value: unknown): value is boolean => !isNullish(value) && typeof value === 'boolean';\n\nexport const toBoolean = (value: unknown): boolean => Boolean(value).valueOf();\n\n/**\n * Checks if a value is a non-null object.\n *\n * We must exclude `null` explicitly, because `typeof null === \"object\"`\n *\n * @returns {value is Record<string, unknown>} `true` if the value is a non-null object, otherwise `false`.\n */\nexport const isObject = <T extends object>(value: T): value is T => {\n return isNotNullish(value) && typeof value === 'object';\n};\n\n/**\n * Checks if a value is a plain object (not an array, function, or built-in instance).\n *\n * @returns {value is Record<string, unknown>} `true` if the value is a plain object, otherwise `false`.\n */\nexport const isPlainObject = <T extends object>(value: T): value is T => {\n return Object.prototype.toString.call(value) === '[object Object]';\n};\n\n/**\n * Checks if a value is a function.\n *\n * @returns {value is function} `true` if the value is a function, otherwise `false`.\n */\nexport const isFunction = <T extends (...args: unknown[]) => unknown>(value: unknown): value is T =>\n typeof value === 'function';\n\n/**\n * Checks if a value is of type ErrorSeverity.\n *\n * @returns {value is ErrorSeverity} `true` if the value is of type ErrorSeverity, otherwise `false`.\n */\nexport function isErrorSeverity(anything: unknown): anything is ErrorSeverity {\n // invalid, when not defined as one of string values we expect\n return anything === 'CRITICAL' || anything === 'INFO';\n}\n\n/** Remove trailing slash from a path, if it exists. */\nexport const removeTrailingSlash = (path: string): string => {\n return path.replace(/\\/$/g, '');\n};\n\n/** Take a time in seconds and return a value that represents a time in milliseconds, rounded to the nearest integer */\nexport const calculateTime = (timeInSeconds: number) => Math.round(timeInSeconds * 1000);\n\n/** Same as {@link calculateTime} but if time is \"nullish\", then the return value is `undefined` */\nexport const calculateTimeWithUndefined = (timeInSeconds: number | null | undefined): number | undefined => {\n if (isNullish(timeInSeconds)) {\n return undefined;\n }\n return calculateTime(timeInSeconds);\n};\n\n/**\n * @deprecated Use directly `Date.now()` instead\n *\n * Return the current time in milliseconds.\n */\nexport const getCurrentTimestamp = (): number => {\n return Date.now();\n};\n\n/**\n * Empty function returns undefined\n *\n * @deprecated\n */\nexport const noOp = () => undefined;\n\nexport const getCustomDataString = (customData: any): string | undefined => {\n if (typeof customData === 'object') {\n return tryJSONStringify(customData);\n } else if (isFunction(customData)) {\n return getCustomDataString(customData());\n } else if (typeof customData === 'undefined') {\n return customData;\n } else if (typeof customData !== 'string') {\n return String(customData);\n }\n\n return customData;\n};\n\nexport const transferCustomDataFields = (fromConfig: CustomDataValues, toConfig: CustomDataValues) => {\n for (let i = 1; i <= CustomDataUtils.customDataFieldCount; i++) {\n const customDataField = `customData${i}`;\n toConfig[customDataField] = getCustomDataString(fromConfig[customDataField]);\n }\n};\n\n/**\n * Determine if the page was loaded in the foreground or background\n */\nexport function getPageLoadType(): PAGE_LOAD_TYPE {\n if (isDocumentHidden()) {\n return PAGE_LOAD_TYPE.BACKGROUND;\n }\n return PAGE_LOAD_TYPE.FOREGROUND;\n}\n\nexport const calculatePercentage = (numerator?: number, denominator?: number): number | undefined => {\n if (denominator === undefined || denominator === 0) {\n return undefined;\n }\n return Math.round(((numerator || 0) / denominator) * 100);\n};\n\nexport const getURLResourceName = (url: string): string => {\n if (url.length === 0) {\n return '';\n }\n return url.split('/').pop() || '';\n};\n\nexport const joinUrls = (...args: string[]): string => {\n return args.reduce((prev, current) => {\n const prevUrlValue = endsWith(prev, '/') && current !== undefined ? prev.substr(0, prev.length - 1) : prev;\n const nextUrlValue = startsWith(current, '/') ? current.substr(1) : current;\n return prevUrlValue + '/' + nextUrlValue;\n });\n};\n\n/**\n * Detect if running in a React Native environment using navigator.product\n * https://github.com/facebook/react-native/commit/3c65e62183ce05893be0822da217cb803b121c61\n * https://github.com/facebook/react-native/issues/1331\n * https://stackoverflow.com/questions/39468022/how-do-i-know-if-my-code-is-running-as-react-native\n * navigator object from vega os simulator {\"product\":\"ReactNative\",\"userAgent\":\"ReactNative\"}\n */\nexport const isReactNative = (): boolean => {\n return getGlobalNavigatorProduct() === 'ReactNative';\n};\n\n/**\n * Determine if the audio is muted based on the player muted state and current volume.\n *\n * @param playerIsMuted `true` means muted and `false` means not muted.\n * @param playerVolume A double values must fall between 0 and 1, where 0 is effectively muted and 1 is the loudest possible value.\n */\nexport const isAudioMuted = (playerIsMuted: boolean, playerVolume: number) => {\n /** Audio volume below this delta is considered zero. */\n const VOLUME_DELTA = 0.01;\n\n return playerIsMuted || playerVolume < VOLUME_DELTA;\n};\n\nexport const tryJSONStringify = (obj: unknown): string | undefined => {\n if (isNullish(obj)) {\n return undefined;\n }\n\n try {\n return JSON.stringify(obj);\n } catch {\n return undefined;\n }\n};\n\n/**\n * Checks if a value is an `ArrayBuffer` instance.\n *\n * Uses `Object.prototype.toString` for reliable detection across different\n * execution contexts (e.g. iframes, workers) where `instanceof ArrayBuffer` may fail.\n *\n * @returns {value is ArrayBuffer} `true` if the value is an `ArrayBuffer`, otherwise `false`.\n */\nexport function isArrayBuffer(value: unknown): value is ArrayBuffer {\n return Object.prototype.toString.call(value) === '[object ArrayBuffer]';\n}\n","declare global {\n /** Variable is defined by webpack.DefinePlugin during the build process. */\n const __VERSION__: string;\n}\n\nexport const VERSION: string = __VERSION__;\n","import {addDocumentEventListener, getDocumentPropertyWithPrefix, removeDocumentEventListener} from './documentUtils';\nimport {globalScope} from './globalScope';\nimport {logger} from './Logger';\nimport {isValidString} from './stringUtils';\nimport {isNullish} from './Utils';\n\nexport class ViewportTracker {\n private onIntersectionChanged: () => void;\n private observer?: IntersectionObserver;\n private element: HTMLElement;\n private inViewport?: boolean = undefined;\n private threshold: number;\n private hiddenPropertyName: string | undefined;\n private visibilityChange?: string;\n\n constructor(element: HTMLElement, onIntersectionChanged: () => void, threshold = 1.0) {\n this.threshold = threshold;\n this.onIntersectionChanged = onIntersectionChanged;\n this.element = element;\n\n try {\n const options: IntersectionObserverInit = {\n root: null,\n rootMargin: '0px',\n threshold,\n };\n this.observer = new IntersectionObserver((entries, observer) => this.handleIntersect(entries, observer), options);\n this.observer.observe(element);\n } catch (_error) {\n logger.log(\"Couldn't create instance of IntersectionObserver. timeInViewport will always be reported as 100%.\");\n }\n\n this.hiddenPropertyName = getDocumentPropertyWithPrefix('hidden');\n if (this.hiddenPropertyName) {\n this.visibilityChange = this.hiddenPropertyName.replace('hidden', '') + 'visibilitychange';\n addDocumentEventListener(\n this.visibilityChange,\n (this.handleVisibilityChange = this.handleVisibilityChange.bind(this)),\n false,\n );\n }\n }\n\n isHidden() {\n if (isNullish(globalScope.document) || !isValidString(this.hiddenPropertyName)) {\n return false;\n }\n\n return globalScope.document[this.hiddenPropertyName] === true;\n }\n\n isInViewport(): boolean {\n return !this.isHidden() && (isNullish(this.inViewport) ? true : this.inViewport);\n }\n\n dispose() {\n if (this.observer) {\n this.observer.unobserve(this.element);\n this.observer.disconnect();\n }\n if (this.visibilityChange) {\n removeDocumentEventListener(this.visibilityChange, this.handleVisibilityChange, false);\n }\n }\n\n private handleVisibilityChange() {\n this.onIntersectionChanged();\n }\n\n private handleIntersect(entries: IntersectionObserverEntry[], _observer: IntersectionObserver) {\n entries.forEach((i) => {\n if (i.target === this.element) {\n this.inViewport = !(i.intersectionRatio < this.threshold);\n }\n });\n this.onIntersectionChanged();\n }\n}\n","import {getGlobalWebOSApi} from './globalScopeUtils';\nimport {isBlank, isValidString} from './stringUtils';\n\n// Declaration merging to extend the Window interface with WebOS API\n// see: https://webostv.developer.lge.com/develop/references/webostvjs-webos\ndeclare global {\n interface Window {\n /**\n * @deprecated In webOS TV 4.x or lower, only PalmSystem is supported, and in webOS TV 5.0 or higher,\n * both PalmSystem and webOSSystem are supported. Although PalmSystem is still supported for backward compatibility,\n * future support is not guaranteed so it is strongly recommended that you use webOSSystem in webOS TV 5.0 or higher.\n *\n * @see https://webostv.developer.lge.com/develop/guides/app-lifecycle-management\n */\n PalmSystem?: {\n deviceInfo?: string;\n };\n\n /**\n * Represents the current system interface that should be used on webOS TV 5.0 or higher.\n *\n * @see https://webostv.developer.lge.com/develop/references/webostvjs-webos\n */\n webOSSystem?: {\n /**\n * @see https://webostv.developer.lge.com/develop/references/webostvjs-webos#deviceinfo\n */\n deviceInfo?: string;\n };\n }\n}\n\ntype WebOSDeviceInfo = {modelName: string};\n\nexport function getWebOSTVModelName(): string | undefined {\n try {\n const {webOSSystem, PalmSystem} = getGlobalWebOSApi();\n const info: WebOSDeviceInfo | undefined = webOSSystem?.deviceInfo\n ? JSON.parse(webOSSystem.deviceInfo)\n : PalmSystem?.deviceInfo && JSON.parse(PalmSystem.deviceInfo);\n if (isValidString(info?.modelName) && !isBlank(info?.modelName)) {\n return info.modelName;\n }\n return undefined;\n } catch {\n return undefined;\n }\n}\n","import {addGlobalEventListener, removeGlobalEventListener} from './globalScopeUtils';\n\ninterface EventListener {\n eventName: string;\n func: EventListenerOrEventListenerObject;\n}\n\nexport class WindowEventTracker {\n private trackedObjects: EventListener[] = [];\n\n addEventListener(eventName: string, func: EventListenerOrEventListenerObject) {\n this.trackedObjects.push({eventName, func});\n addGlobalEventListener(eventName, func);\n }\n\n release() {\n while (this.trackedObjects.length !== 0) {\n const obj = this.trackedObjects.pop();\n if (obj === undefined) {\n continue;\n }\n\n removeGlobalEventListener(obj.eventName, obj.func);\n }\n }\n}\n","import type {AnalyticsConfig, CollectorConfig} from '../types/AnalyticsConfig';\nimport {extractCustomDataFieldsOnly} from '../types/CustomDataValues';\nimport type {Sample} from '../types/Sample';\nimport type {SourceMetadata} from '../types/SourceMetadata';\n\nimport {getGlobalLocationHostname} from './globalScopeUtils';\nimport {logger} from './Logger';\nimport {isBlank, isValidString} from './stringUtils';\nimport * as Utils from './Utils';\nimport {isFunction, isNotNullish, isNullish} from './Utils';\n\n/**\n * Sanitize {@link AnalyticsConfig} to not be null/undefined\n *\n * Why we return the same config (same reference) passed to function as an argument?\n * Because in the past, we made a mistake and forget to prevent changing `AnalyticsConfig` vie kept reference\n * from outside. Now our customers are using this bug/feature, and we need to keep it for backward compatibility.\n * This should be fixed and changed in the future major release as part of `Collector API v3` changes.\n *\n * @returns A new empty config `{}`, if it was `null/undefined`, otherwise the same config (same reference).\n *\n */\nexport function sanitizeAnalyticsConfig(config: AnalyticsConfig | null | undefined): AnalyticsConfig {\n if (isNullish(config)) {\n return {};\n }\n\n if (!Utils.isBoolean(config.isLive)) {\n config.isLive = undefined;\n }\n\n if (isNotNullish(config.config) && isNotNullish(config.config.errorTransformerCallback)) {\n if (!isFunction(config.config!.errorTransformerCallback!.transform)) {\n config.config.errorTransformerCallback = undefined;\n }\n }\n\n return config;\n}\n\n/**\n * Log error with {@link logger}, if the new configuration is missing `title` property, but old configuration had one.\n */\nexport function guardConfigChangeAgainstMissingTitle(oldConfig: AnalyticsConfig, newConfig: AnalyticsConfig) {\n if (isNullish(oldConfig) || isNullish(newConfig)) {\n // handle undefined values even when argument type does not specify them\n // (defensive approach, because of old code from past and step by step refactorings)\n return;\n }\n\n if (oldConfig.title && isBlank(newConfig.title)) {\n logger.error('The new analytics configuration does not contain the field `title`');\n }\n}\n\n/**\n * Log error with {@link logger}, if the new configuration is missing `isLive` property, but old configuration had one.\n */\nexport function guardConfigChangeAgainstMissingIsLive(oldConfig: AnalyticsConfig, newConfig: AnalyticsConfig) {\n if (isNullish(oldConfig) || isNullish(newConfig)) {\n // handle undefined values even when argument type does not specify them\n // (defensive approach, because of old code from past and step by step refactorings)\n return;\n }\n\n if (oldConfig.isLive && isNullish(newConfig.isLive)) {\n logger.error(\n 'The new analytics configuration does not contain the field `isLive`. It will default to `false` which might be unintended? Once stream playback information is available the type will be populated.',\n );\n }\n}\n\n/**\n * Log warning with {@link logger}, if both `customUserId` and `userId` are set in the configuration.\n */\nexport function guardAgainstDuplicatedUserId(config: AnalyticsConfig) {\n if (isNullish(config)) {\n // handle undefined values even when argument type does not specify them\n // (defensive approach, because of old code from past and step by step refactorings)\n return;\n }\n\n if (isNotNullish(config.customUserId) && isNotNullish(config.userId)) {\n logger.warn(\n 'Configuration Warning: \\n' +\n 'CustomUserId and UserId are set in the config \\n' +\n 'Value of UserId will be used in sample \\n' +\n 'Please only use one configuration field to set your userId',\n );\n }\n}\n\nexport function getDeviceInformationFromAnalyticsConfig(\n config: AnalyticsConfig,\n): Sample['deviceInformation'] | undefined {\n if (isNullish(config)) {\n // handle undefined values even when argument type does not specify them\n // (defensive approach, because of old code from past and step by step refactorings)\n return undefined;\n }\n\n const deviceInformation: Sample['deviceInformation'] = {};\n\n if (isValidString(config.deviceType) && !isBlank(config.deviceType)) {\n // we are using `deviceInformation.model` field to pass `config.deviceType`, because of ingress\n // and how deviceInformation processing is implemented there.\n deviceInformation.model = config.deviceType;\n }\n\n if (isValidString(config.deviceClass) && !isBlank(config.deviceClass)) {\n deviceInformation.deviceClass = config.deviceClass;\n }\n\n if (Object.keys(deviceInformation).length === 0) {\n return undefined;\n }\n\n return deviceInformation;\n}\n\n/**\n * Get {@link CollectorConfig} `origin` field (if any), otherwise return sanitized hostname.\n */\nexport function getDomainFromAnalyticsConfig(config: AnalyticsConfig): string {\n const hostname = getGlobalLocationHostname();\n const fallbackDomain = hostname ? Utils.removeTrailingSlash(hostname) : '';\n return config?.config?.origin ?? fallbackDomain;\n}\n\nfunction removeSourceRelatedFields(config: AnalyticsConfig): AnalyticsConfig {\n const sourceSpecificProperties = ['cdnProvider', 'videoId', 'title', 'isLive', 'experimentName'];\n const customDataFieldsRegex = /customData\\d{1,3}$/g;\n\n for (const key in config) {\n if (isNotNullish(key.match(customDataFieldsRegex)) || sourceSpecificProperties.includes(key)) {\n delete config[key];\n }\n }\n\n return config;\n}\n\nfunction mergeCollectorConfig(\n oldCollectorConfig: CollectorConfig | undefined,\n newCollectorConfig: CollectorConfig | undefined,\n): CollectorConfig {\n if (isNotNullish(newCollectorConfig)) {\n // merging new config should enable the collector by default (unless explicitly disabled in the new config)\n return {...oldCollectorConfig, enabled: true, ...newCollectorConfig};\n }\n return oldCollectorConfig ?? {};\n}\n\nexport function mergeAnalyticsConfig(oldConfig: AnalyticsConfig, newConfig: AnalyticsConfig): AnalyticsConfig {\n const oldConfigWithoutSourceRelatedFields = removeSourceRelatedFields(oldConfig);\n const mergedCollectorConfig = mergeCollectorConfig(oldConfig.config, newConfig.config);\n\n return {\n ...oldConfigWithoutSourceRelatedFields,\n ...newConfig,\n config: mergedCollectorConfig,\n };\n}\n\nexport function applySourceMetadataToAnalyticsConfig(\n config: AnalyticsConfig,\n sourceMetadata: SourceMetadata,\n): AnalyticsConfig {\n let newConfig: AnalyticsConfig = {...config}; // create a new config object to avoid mutating the original one\n\n if (isNotNullish(sourceMetadata.title)) {\n newConfig.title = sourceMetadata.title;\n }\n\n if (isNotNullish(sourceMetadata.videoId)) {\n newConfig.videoId = sourceMetadata.videoId;\n }\n\n if (isNotNullish(sourceMetadata.cdnProvider)) {\n newConfig.cdnProvider = sourceMetadata.cdnProvider;\n }\n\n if (isNotNullish(sourceMetadata.isLive)) {\n newConfig.isLive = sourceMetadata.isLive;\n }\n\n if (isNotNullish(sourceMetadata.customData)) {\n // same style how to set custom data fields like we do in Analytics module\n newConfig = {\n ...newConfig,\n ...extractCustomDataFieldsOnly(sourceMetadata.customData),\n };\n }\n\n return newConfig;\n}\n","import type {AnalyticsConfig} from '../types/AnalyticsConfig';\n\nimport {getDomainFromAnalyticsConfig} from './analyticsConfigUtils';\nimport {logger} from './Logger';\nimport {isBlank} from './stringUtils';\n\n/**\n * Checks if the environment and config is set up correctly to allow proper collector initialization\n * @param config The analytics config to check\n * @returns true if setup is correct and full initialization possible\n */\nexport function areCollectorRequirementsValid(config: AnalyticsConfig): boolean {\n const errorMessages: string[] = [];\n\n // domain available - needed for license calls (authorization)\n const isDomainMissing = isBlank(getDomainFromAnalyticsConfig(config));\n if (isDomainMissing) {\n errorMessages.push(\n 'no `domain` value found (neither from `window.location` object nor provided by `AnalyticsConfig.config.origin`). Without this value, we cannot verify the origin of your analytics data. Please provide the registered domain via the config during collector creation.',\n );\n }\n\n if (errorMessages.length > 0) {\n const fullErrorMessage = 'Collector setup failed:' + errorMessages.join(' -- ');\n logger.errorMessageToUser(fullErrorMessage);\n }\n\n return !isDomainMissing;\n}\n","/**\n * documentUtils provides standalone functions for accessing browser document APIs.\n * This improves testability by allowing easy mocking of document-dependent functionality.\n */\n\nimport {logger} from './Logger';\nimport {isValidString} from './stringUtils';\nimport {isFunction, isNullish} from './Utils';\n\n/**\n * Get a property from document with vendor prefix support\n * Tries the standard property name first, then with webkit/moz/ms/o prefixes\n */\nexport const getDocumentPropertyWithPrefix = (prop: string): string | undefined => {\n if (isNullish(document)) {\n return undefined;\n }\n\n if (prop in document) {\n return prop;\n }\n\n const prefixes = ['webkit', 'moz', 'ms', 'o'];\n const pascalCase = prop.charAt(0).toUpperCase() + prop.slice(1);\n for (const prefix of prefixes) {\n const prefixedProp = prefix + pascalCase;\n if (prefixedProp in document) {\n return prefixedProp;\n }\n }\n\n return undefined;\n};\n\n/**\n * Check if the document is currently hidden (page visibility API)\n */\nexport const isDocumentHidden = (): boolean => {\n const hiddenProp = getDocumentPropertyWithPrefix('hidden');\n if (!isValidString(hiddenProp)) {\n return false;\n }\n\n return document[hiddenProp] === true;\n};\n\n/**\n * Check if a video element is currently in fullscreen mode\n */\nexport const isVideoInFullscreen = (): boolean => {\n const fullscreenProp = getDocumentPropertyWithPrefix('fullscreenElement');\n if (!isValidString(fullscreenProp)) {\n return false;\n }\n\n return document[fullscreenProp]?.nodeName === 'VIDEO';\n};\n\n/**\n * Add event listener to document\n *\n * Use this for document-level events that relate to the DOM structure and document state.\n * Some events ONLY fire on document (not on window):\n * - visibilitychange (& vendor-prefixed variants): tab/page visibility state\n * - fullscreenchange/fullscreenerror: fullscreen mode changes\n * - DOMContentLoaded: DOM parsed and ready (fires before window 'load')\n * - readystatechange: document.readyState changes\n *\n * Important: This function cannot be replaced with window.addEventListener because\n * the above events are document-specific and will not fire on window.\n *\n * We use vendor-prefixed events (webkitvisibilitychange, mozvisibilitychange, etc.)\n * for cross-browser compatibility, especially on older browsers and Smart TVs.\n */\nexport const addDocumentEventListener = (\n event: string,\n handler: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n): void => {\n if (isNullish(document) || !isFunction(document.addEventListener) || isNullish(handler)) {\n return;\n }\n\n // any-wrap needed to not confirm to type checks\n // we use vendor-prefixed events that are not part of the interface\n (document.addEventListener as any)(event, handler, options);\n};\n\n/**\n * Remove event listener from document\n *\n * @see addDocumentEventListener for details on when to use document vs window event listeners\n */\nexport const removeDocumentEventListener = (\n event: string,\n handler: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n): void => {\n if (isNullish(document) || !isFunction(document.removeEventListener) || isNullish(handler)) {\n return;\n }\n\n // any-wrap needed to not confirm to type checks\n // we use vendor-prefixed events that are not part of the interface\n (document.removeEventListener as any)(event, handler, options);\n};\n\n/**\n * Get a cookie value by name\n * @see https://www.w3schools.com/js/js_cookies.asp\n */\nexport const getCookie = (name: string): string | undefined => {\n if (isNullish(document)) {\n return undefined;\n }\n\n let allCookies: string[];\n try {\n allCookies = document.cookie.split(';');\n } catch (_error) {\n logger.log('failed to access cookie objects on document', _error);\n return undefined;\n }\n\n const cookieName = name + '=';\n for (const c of allCookies) {\n let cookie = c;\n while (cookie.charAt(0) === ' ') {\n cookie = cookie.substring(1); // trim spaces (if any) between ';' and next attribute\n }\n if (cookie.indexOf(cookieName) === 0) {\n return cookie.substring(cookieName.length, cookie.length);\n }\n }\n return '';\n};\n\n/**\n * Set a cookie with optional attributes\n */\nexport const setCookie = (\n name: string,\n value: string,\n attributes?: {domain?: string; expires?: string; maxAge?: number},\n): void => {\n if (isNullish(document)) {\n return;\n }\n\n let newCookie = name + '=' + value + '; path=/';\n\n if (attributes?.domain) {\n newCookie += `; domain=${attributes.domain}`;\n }\n\n if (attributes?.expires) {\n newCookie += `; expires=${attributes.expires}`;\n }\n\n if (attributes?.maxAge) {\n newCookie += `; max-age=${attributes.maxAge}`;\n }\n\n try {\n document.cookie = newCookie;\n } catch (_error) {\n logger.log('failed to set cookie object on document', _error);\n return;\n }\n};\n\n/**\n * Delete a cookie by name\n * @see https://www.w3schools.com/js/js_cookies.asp\n */\nexport const deleteCookie = (name: string): void => {\n if (isNullish(document)) {\n return;\n }\n\n try {\n document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;\n } catch (_error) {\n logger.log('failed to delete cookies from document', _error);\n return;\n }\n};\n","function getGlobalThis(): typeof globalThis {\n // eslint-disable-next-line no-restricted-globals\n if (typeof globalThis !== 'undefined') return globalThis;\n // eslint-disable-next-line unicorn/prefer-global-this\n if (typeof window !== 'undefined') return window as any;\n // eslint-disable-next-line unicorn/prefer-global-this\n if (typeof global !== 'undefined') return global as any;\n // eslint-disable-next-line unicorn/prefer-global-this\n if (typeof self !== 'undefined') return self as any;\n throw new Error('Unable to locate global object');\n}\n\n/**\n * Provides a safe reference to the global object APIs across all environments.\n *\n * `globalThis` is a standard built-in JavaScript object that always refers to the global object of the current\n * environment, regardless of whether your code runs in a browser, Node.js, a worker, or a module.\n *\n * But `globalThis` was introduced in ES2020, and older platforms like Tizen 2016 (Chromium ~2015-2016) do not support\n * it. Rather than bundling a full polyfill into the library, this helper resolves the global object at runtime by\n * checking the available global references in order: `globalThis` → `window` → `global` → `self`.\n *\n * This improves:\n * - compatibility with various environments where the `window` global variable may not be available (VegaOS, React Native)\n * - testability by allowing easy mocking of global object functionality.\n */\nexport const globalScope = getGlobalThis();\n","import {globalScope} from './globalScope';\nimport {isNumber} from './numberUtils';\nimport {isValidString} from './stringUtils';\nimport {isFunction, isNullish} from './Utils';\n\n/**\n * Get `globalScope.devicePixelRatio` (defaults to `1` if not available)\n */\nexport const getGlobalDevicePixelRatio = (): number => {\n if (isNullish(globalScope.devicePixelRatio)) {\n return 1;\n }\n return globalScope.devicePixelRatio > 0 ? globalScope.devicePixelRatio : 1;\n};\n\n/**\n * Get `globalScope.screen` dimensions with {@link getGlobalDevicePixelRatio} applied\n */\nexport const getGlobalScreenDimensions = (): {height: number; scale: number; width: number} | undefined => {\n if (isNullish(globalScope.screen)) {\n return undefined;\n }\n\n if (!isNumber(globalScope.screen.width) || !isNumber(globalScope.screen.height)) {\n return undefined;\n }\n\n const scale = getGlobalDevicePixelRatio();\n const width = globalScope.screen.width * scale;\n const height = globalScope.screen.height * scale;\n\n if (!isFinite(width) || !isFinite(height) || width <= 0 || height <= 0) {\n return undefined;\n }\n\n return {width, height, scale};\n};\n\n/**\n * Add global event listener\n *\n * Use this for window-level events that relate to the browser viewport/tab:\n * - resize: viewport size changes\n * - scroll: page scroll (when listening at window level)\n * - load/unload/beforeunload: page lifecycle\n * - focus/blur: window/tab focus state\n * - hashchange/popstate: navigation events\n * - storage: localStorage changes from other tabs\n *\n * Note: Events bubble up from target → document → window, so window receives\n * many events that also fire on document, but not vice versa.\n */\nexport const addGlobalEventListener = (event: string, handler: EventListenerOrEventListenerObject): void => {\n if (isNullish(globalScope.addEventListener) || !isFunction(globalScope.addEventListener) || isNullish(handler)) {\n return;\n }\n // any-wrap needed to not confirm to type checks\n // we use vendor-prefixed events that are not part of the interface\n globalScope.addEventListener(event, handler);\n};\n\n/**\n * Remove global event listener\n *\n * @see addWindowEventListener for details on when to use window vs document event listeners\n */\nexport const removeGlobalEventListener = (event: string, handler: EventListenerOrEventListenerObject): void => {\n if (\n isNullish(globalScope.removeEventListener) ||\n !isFunction(globalScope.removeEventListener) ||\n isNullish(handler)\n ) {\n return;\n }\n\n // any-wrap needed to not confirm to type checks\n // we use vendor-prefixed events that are not part of the interface\n globalScope.removeEventListener(event, handler);\n};\n\n/**\n * Get `globalScope.location.hostname`\n */\nexport const getGlobalLocationHostname = (): string | undefined => {\n if (isNullish(globalScope.location)) {\n return undefined;\n }\n\n if (!isValidString(globalScope.location.hostname)) {\n return undefined;\n }\n\n return globalScope.location.hostname;\n};\n\n/**\n * Get `globalScope.location.pathname`\n */\nexport const getGlobalLocationPathname = (): string | undefined => {\n if (isNullish(globalScope.location)) {\n return undefined;\n }\n\n if (!isValidString(globalScope.location.pathname)) {\n return undefined;\n }\n\n return globalScope.location.pathname;\n};\n\n/**\n * Get `globalScope.performance.now()` or `undefined` if not available\n *\n * Note: `performance.now()` is preferred over `Date.now()` for measuring time intervals because it provides higher\n * precision and is not affected by changes to the system clock.\n */\nexport const getGlobalPerformanceNow = (): DOMHighResTimeStamp | undefined => {\n if (isNullish(globalScope.performance?.now) || !isFunction(globalScope.performance.now)) {\n return undefined;\n }\n\n // performance.now() returns a DOMHighResTimeStamp, which is a number representing milliseconds with microsecond precision\n return globalScope.performance.now();\n};\n\n/**\n * Get from `global object` the WebOS-specific API objects (for WebOS TV support)\n */\nexport const getGlobalWebOSApi = (): {PalmSystem?: any; webOSSystem?: any} => {\n return {\n webOSSystem: globalScope.webOSSystem,\n PalmSystem: globalScope.PalmSystem,\n };\n};\n\n/**\n * Check if WebOS API is available (for WebOS TV support)\n */\nexport const hasGlobalWebOSApi = (): boolean => {\n const {webOSSystem, PalmSystem} = getGlobalWebOSApi();\n return !isNullish(webOSSystem) || !isNullish(PalmSystem);\n};\n\n/**\n * Get `globalScope.navigator.language` (with fallback to `globalScope.navigator.userLanguage` for IE)\n */\nexport const getGlobalNavigatorLanguage = (): string | undefined => {\n if (isNullish(globalScope.navigator)) {\n return undefined;\n }\n\n return globalScope.navigator.language || (globalScope.navigator as any).userLanguage;\n};\n\n/**\n * Get `globalScope.navigator.product`\n */\nexport const getGlobalNavigatorProduct = (): string | undefined => {\n if (isNullish(globalScope.navigator)) {\n return undefined;\n }\n\n // navigator.product is deprecated, but it remains the standard way to detect some environments like React Native\n return globalScope.navigator.product;\n};\n\n/**\n * Get `globalScope.navigator.userAgent`\n */\nexport const getGlobalNavigatorUserAgent = (): string | undefined => {\n if (isNullish(globalScope.navigator) || !isValidString(globalScope.navigator.userAgent)) {\n return undefined;\n }\n\n return globalScope.navigator.userAgent;\n};\n\n/**\n * Get `globalScope.videojs.VERSION`\n */\nexport const getGlobalVideojsVersion = (): string | undefined => {\n if (isNullish(globalScope.videojs)) {\n return undefined;\n }\n\n return globalScope.videojs['VERSION'];\n};\n\n/**\n * Get `globalScope.THEOplayer.VERSION`\n */\nexport const getGlobalTheoPlayerVersion = (): string | undefined => {\n if (isNullish(globalScope.THEOplayer)) {\n return undefined;\n }\n\n return globalScope.THEOplayer.version;\n};\n","import {isFunction, isNullish} from './Utils';\n\n/**\n * @returns {value is number} `true` if the given value is {@link isNotNullish} and is type of `number`.\n */\nexport const isNumber = (value: unknown): value is number => !isNullish(value) && typeof value === 'number';\n\n/**\n * Checks if a value is a finite number (not NaN, not Infinity, and not -Infinity).\n *\n * This function should be used instead of directly calling `Number.isFinite` or the global `isFinite`\n * because it provides ES5 compatibility and proper type checking.\n *\n * **Why not use `Number.isFinite` directly?**\n * `Number.isFinite` is an ES6 method and does not exist in ES5 environments. Calling it directly\n * would throw a `TypeError` at runtime in older environments.\n *\n * **Key difference between `Number.isFinite` and global `isFinite`:**\n * - `Number.isFinite(value)` does NOT coerce the value — it returns `true` only if the value is\n * already a number and is finite. For example, `Number.isFinite(\"123\")` returns `false`.\n * - Global `isFinite(value)` DOES coerce the value to a number before checking. For example,\n * `isFinite(\"123\")` returns `true` because `\"123\"` is coerced to `123`.\n *\n * This function avoids the coercion risk by first checking the type with `isNumber`, making both\n * implementations behave consistently regardless of the environment.\n *\n * @param value - The value to check\n * @returns `true` if the value is a finite number, `false` otherwise (including NaN, Infinity, -Infinity, null, undefined, or non-numeric types)\n *\n * @example\n * isFiniteNumber(123) // true\n * isFiniteNumber(0) // true\n * isFiniteNumber(-456.78) // true\n * isFiniteNumber(NaN) // false\n * isFiniteNumber(Infinity) // false\n * isFiniteNumber(-Infinity) // false\n * isFiniteNumber(\"123\") // false (string, not coerced)\n * isFiniteNumber(null) // false\n * isFiniteNumber(undefined) // false\n */\nexport const isFiniteNumber = (value: unknown): value is number => {\n if (!isNumber(value)) {\n return false;\n }\n\n // our target is ES5, so we can't use Number.isFinite without checking for it\n if (isFunction(Number.isFinite)) {\n return Number.isFinite(value);\n }\n\n // Fallback implementation for environments that do not support Number.isFinite\n return isFinite(value);\n};\n\n/**\n * Converts a string to an integer using native `parseInt` and returns `undefined` if the result is not a finite number\n */\nexport const parseIntOrUndefined = (value: string): number | undefined => {\n const result = parseInt(value, 10);\n return isFiniteNumber(result) ? result : undefined;\n};\n","import {logger} from './Logger';\n\n/** Polyfill for ES2017 'Object.values' */\nexport const objectValues = (obj: any) => {\n return Object.keys(obj).map(function (key) {\n return obj[key];\n });\n};\n\n/**\n * Wraps property access with try/catch\n */\nexport function safeAccess<T>(access: () => T): T | undefined {\n try {\n return access();\n } catch (error) {\n logger.log(`safeAccess catched failed access on property: `, error);\n return undefined;\n }\n}\n","import type {InternalAdapterAPI} from '../adapters/internal/InternalAdapterAPI';\nimport type {Analytics} from '../core/Analytics';\n\nimport {logger} from './Logger';\nimport {isNullish} from './Utils';\n\nexport const BITMOVIN_ANALYTICS_AUGMENTED_MARKER = '__bitmovinAnalyticsHasBeenSetup';\n\n/**\n * Checks if analytics has already been initialized on this player instance,\n * aka. if {@link BITMOVIN_ANALYTICS_AUGMENTED_MARKER} is present on the player instance.\n *\n * @param player\n */\nexport function hasPlayerAlreadyBeenAugmented(player: any): boolean {\n return player[BITMOVIN_ANALYTICS_AUGMENTED_MARKER] === true;\n}\n\n/**\n * Marks the player instance as already instrumented by analytics,\n * aka. sets {@link BITMOVIN_ANALYTICS_AUGMENTED_MARKER} on the player instance.\n */\nexport function markPlayerInstanceAsAugmented(player: any) {\n player[BITMOVIN_ANALYTICS_AUGMENTED_MARKER] = true;\n}\n\n/**\n * In context of player augmentation, if player was already augmented, adapter properties\n * {@link Analytics} or {@link InternalAdapterAPI} will stay `undefined`, this type guard\n * is utility to help us check if the instance is defined.\n */\nexport function isDefined<T extends Analytics | InternalAdapterAPI>(instance: T | null | undefined): instance is T {\n if (isNullish(instance)) {\n logger.log(\"Bitmovin Analytics: Adapter hasn't been initialized yet\");\n return false;\n }\n\n return true;\n}\n","import {SSAI_RELATED_SAMPLE_MARKER} from '../core/ssai/ssaiUtils';\nimport type {AdSample} from '../types/AdSample';\nimport type {Sample} from '../types/Sample';\n\nimport {getGlobalLocationPathname} from './globalScopeUtils';\nimport {isValidString} from './stringUtils';\nimport * as Utils from './Utils';\nimport {isNullish, removeTrailingSlash} from './Utils';\n\n/**\n * Clear all \"state\" values from the sample (all values that describe \"playing sample\", \"startup sample\" ...).\n */\nexport function clearSampleStateValues(sample: Sample): void {\n sample.ad = 0;\n sample.adId = undefined;\n sample.adIndex = undefined;\n sample.adPosition = undefined;\n sample.adSystem = undefined;\n sample.autoplay = undefined;\n sample.buffered = 0;\n sample.castTech = undefined;\n sample.completed = undefined;\n sample.drmLoadTime = undefined;\n sample.droppedFrames = 0;\n sample.duration = 0;\n sample.errorCode = undefined;\n sample.errorData = undefined;\n sample.errorMessage = undefined;\n sample.errorSegments = undefined;\n sample.errorSeverity = undefined;\n sample.isProgramChange = undefined;\n sample.pageLoadTime = 0;\n sample.paused = 0;\n sample.played = 0;\n sample.playerStartupTime = 0;\n sample.seeked = 0;\n sample.startupTime = 0;\n sample.state = undefined;\n sample.videoStartFailed = undefined;\n sample.videoStartFailedReason = undefined;\n sample.videoStartupTime = 0;\n\n sample[SSAI_RELATED_SAMPLE_MARKER] = undefined;\n}\n\nexport function getDefaultSamplePath(): string | undefined {\n const pathname = getGlobalLocationPathname();\n return isValidString(pathname) ? removeTrailingSlash(pathname) : undefined;\n}\n\nexport function buildAdSample(sample?: Sample): AdSample {\n const adSample: AdSample = {};\n\n if (isNullish(sample)) {\n return adSample;\n }\n\n adSample.cdnProvider = sample.cdnProvider;\n adSample.customUserId = sample.customUserId;\n adSample.domain = sample.domain;\n adSample.key = sample.key;\n adSample.language = sample.language;\n adSample.path = sample.path;\n adSample.player = sample.player;\n adSample.playerKey = sample.playerKey;\n adSample.playerTech = sample.playerTech;\n adSample.screenHeight = sample.screenHeight;\n adSample.screenWidth = sample.screenWidth;\n adSample.size = sample.size;\n adSample.userAgent = sample.userAgent;\n adSample.userId = sample.userId;\n adSample.version = sample.version;\n adSample.videoId = sample.videoId;\n adSample.videoImpressionId = sample.impressionId;\n adSample.videoTitle = sample.videoTitle;\n adSample.videoWindowHeight = sample.videoWindowHeight;\n adSample.videoWindowWidth = sample.videoWindowWidth;\n\n Utils.transferCustomDataFields(sample, adSample);\n adSample.experimentName = sample.experimentName;\n\n return adSample;\n}\n","import {isFunction, isNotNullish, isNullish} from './Utils';\n\nexport const isValidString = (s: unknown): s is string => isNotNullish(s) && typeof s === 'string';\n\nexport const isEmpty = (s: string | null | undefined): boolean => isNullish(s) || s.length === 0;\n\nexport const isBlank = (s: string | null | undefined): boolean => isEmpty(s) || isEmpty(s?.trim());\n\nexport const endsWith = (s: string, suffix: string): boolean => {\n if (!isValidString(s) || !isValidString(suffix)) {\n return false;\n }\n\n // our target is ES5, so we can't use String.prototype.endsWith without checking for it\n if (isFunction(String.prototype.endsWith)) {\n return s.endsWith(suffix);\n }\n\n // Fallback implementation for environments that do not support String.prototype.endsWith\n return s.substring(s.length - suffix.length) === suffix;\n};\n\nexport const startsWith = (s: string, prefix: string): boolean => {\n if (!isValidString(s) || !isValidString(prefix)) {\n return false;\n }\n\n // our target is ES5, so we can't use String.prototype.startsWith without checking for it\n if (isFunction(String.prototype.startsWith)) {\n return s.startsWith(prefix);\n }\n\n // Fallback implementation for environments that do not support String.prototype.startsWith\n return s.substring(0, prefix.length) === prefix;\n};\n","export const generateUUID = (): string => {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n};\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","import {Bitmovin8Adapter} from './adapters/bitmovin8/Bitmovin8Adapter';\nimport {PlayerModule} from './adapters/bitmovin8/playerModule';\nimport {BitmovinPwxAnalyticsPackage} from './adapters/bitmovinPwx/BitmovinPwxAnalyticsPackage';\nimport {CAFv3Adapter} from './adapters/cafv3/CAFv3Adapter';\nimport {HlsAdapter} from './adapters/hlsjs/HlsAdapter';\nimport {HTMLVideoElementAdapter} from './adapters/html5/HTMLVideoElementAdapter';\nimport {ShakaAdapter} from './adapters/shaka/ShakaAdapter';\nimport {THEOplayerAdapter} from './adapters/theo/THEOplayerAdapter';\nimport {VideojsAdapter} from './adapters/videojs/VideoJsAdapter';\nimport {CdnProvider} from './enums/CDNProvider';\nimport {Player} from './enums/Player';\nimport {VERSION} from './utils/Version';\n\nexport {VERSION as version};\n\nexport type {AnalyticsConfig} from './types/AnalyticsConfig';\n\nexport {Player as Players};\nexport {CdnProvider as CdnProviders};\n\nexport {Bitmovin8Adapter};\nexport {CAFv3Adapter};\nexport {HTMLVideoElementAdapter};\nexport {HlsAdapter};\nexport {ShakaAdapter};\nexport {THEOplayerAdapter};\nexport {VideojsAdapter};\n\nexport const adapters = {\n Bitmovin8Adapter,\n CAFv3Adapter,\n HTMLVideoElementAdapter,\n HlsAdapter,\n ShakaAdapter,\n THEOplayerAdapter,\n VideojsAdapter,\n};\n\nexport {BitmovinPwxAnalyticsPackage};\n\nexport {PlayerModule};\n\nexport default {\n PlayerModule: PlayerModule,\n};\n"],"names":["root","factory","exports","module","define","amd","self","StateMachine","VERSION","Result","SUCCEEDED","NOTRANSITION","CANCELLED","PENDING","Error","INVALID_TRANSITION","PENDING_TRANSITION","INVALID_CALLBACK","WILDCARD","ASYNC","create","cfg","target","initial","state","terminal","fsm","events","callbacks","map","transitions","add","e","from","Array","isArray","name","n","length","push","to","event","hasOwnProperty","buildEvent","current","is","indexOf","this","can","transition","undefined","cannot","concat","isFinished","error","args","msg","states","Object","keys","sort","defer","doCallback","func","apply","beforeAnyEvent","afterAnyEvent","leaveAnyState","enterAnyState","changeState","beforeThisEvent","afterThisEvent","leaveThisState","enterThisState","beforeEvent","afterEvent","leaveState","specific","general","enterState","prototype","slice","call","arguments","cancel","leave","player","windowEventTracker","adCallbacks","AdCallbacks","isLinearAdActive","getContainer","getAdModuleInfo","version","currentTime","getCurrentTime","register","getAutoPlay","autoplay","on","BITMOVIN8_PLAYER_EVENT","Play","issuer","onPlay","Paused","onPause","AdStarted","onAdStarted","mapBitmovinAd","ad","AdFinished","onAdFinished","AdBreakStarted","onAdBreakStarted","mapBitmovinAdBreak","adBreak","AdBreakFinished","onAdBreakFinished","AdClicked","onAdClicked","clickThroughUrl","AdQuartile","onAdQuartile","quartile","AdSkipped","onAdSkipped","AdError","onAdError","mapBitmovinAdError","getActiveAd","id","AdManifestLoaded","adTagConfig","adConfig","isVmap","tag","type","adBreakInfo","isNotNullish","manifestDownloadTime","downloadTiming","downloadTime","onAdManifestLoaded","handlePageClose","onBeforeUnload","addEventListener","Bitmovin8AdModule","opts","ssai","adBreakStart","adBreakMetadata","isDefined","internalAdapter","adBreakMetadataWithValidAdPosition","sanitizeBitmovin8AdapterSsaiAdBreakMetadataAdPosition","hasValidSsaiAdBreakMetadataStructure","sanitizedAdBreakMetadata","simplySanitizeSsaiAdBreakMetadata","ssaiService","adStart","adMetadata","analytics","hasValidSsaiAdMetadataStructure","sanitizedAdMetadata","simplySanitizeSsaiAdMetadata","setConfigParameters","setAutoDetectedDeviceInformation","adQuartileFinished","adQuartile","adQuartileMetadata","hasValidSsaiAdQuartileStructure","sanitizedSsaiAdQuartileMetadata","sanitizeSsaiAdQuartileMetadata","adBreakEnd","hasPlayerAlreadyBeenAugmented","logger","errorMessageToUser","markPlayerInstanceAsAugmented","playerConfig","getConfig","sanitizedConfig","sanitizeAnalyticsConfig","areCollectorRequirementsValid","guardAgainstDuplicatedUserId","playerKey","key","Bitmovin8InternalAdapter","Bitmovin8PlayerProxy","Analytics","wrapPlayerLoad","originalLoad","load","analyticsConfig","sourceChange","trackLoadstartWithAutoplay","getCurrentImpressionId","getUserId","setCustomData","values","setCustomDataOnce","config","Bitmovin8Adapter","ViewMode","speedMeter","segmentTracker","videoCompletionTracker","httpRequestTrackingAdapter","sourceInfoFallbackService","onBeforeUnLoadEvent","getPlayerVersion","getPlayerName","Player","BITMOVIN","getPlayerTech","getPlayerType","getDrmPerformanceInfo","drmPerformanceInfo","_videoCompletionTracker","playingHeartbeatService","HeartbeatService","lastTrackedCurrentTime","stateMachine","Bitmovin8AnalyticsStateMachine","stateMachineCallbacks","setListener","isAdPlaying","_adModule","initialize","registerPlayerEventListeners","registerUnloadEventListeners","activate","getPlayerCurrentTime","reportEngagementInteraction","ssaiEngagementInteractionData","sendSsaiEngagementAdSample","reportPlaybackInteraction","timestamp","playerCurrentTime","sendPlayingSample","requestTracking","HttpRequestTracking","ErrorDetailTracking","errorDetailTrackingSettingsProvider","ErrorDetailBackend","collectorConfig","errorDetailSubscribable","resetSourceRelatedState","getCurrentPlaybackInfo","container","info","getCommonPlaybackInfo","size","getViewMode","Fullscreen","PlayerSize","Window","playerTech","isLive","videoDuration","normalizeVideoDuration","streamFormat","getStreamType","videoWindowWidth","offsetWidth","videoWindowHeight","offsetHeight","isMuted","isCasting","audioLanguage","getAudio","lang","subtitleEnabled","droppedFrames","getSource","getDroppedVideoFrames","applySubtitleProperties","applyPlaybackQualityProperties","applyCastingProperties","applySourceProperties","isNullish","applyStreamFormat","getSegmentInfo","getSegments","getDownloadSpeedInfo","getInfo","resetDownloadSpeedInfoMeasures","reset","onError","eventCallback","Event","LOADSTART_AUTOPLAY","SourceUnloaded","_event","SOURCE_UNLOADED","SourceLoaded","getDuration","setVideoDuration","setStreamFormat","SOURCE_LOADED","CastStarted","START_CAST","CastStopped","END_CAST","PLAY","Playing","PLAYING","PAUSE","TimeChanged","TIMECHANGED","Seek","allowSeeking","SEEK","Seeked","SEEKED","StallStarted","START_BUFFERING","StallEnded","END_BUFFERING","AudioPlaybackQualityChanged","eventData","audioQualityChangedData","sourceQuality","targetQuality","qualityEventInfo","bitrate","codec","qualityChangeService","shouldAllowAudioQualityChange","AUDIO_CHANGE","setAudioBitrate","updateSampleQualityInfo","VideoPlaybackQualityChanged","videoQualityChangedData","width","height","shouldAllowVideoQualityChange","VIDEO_CHANGE","setVideoBitrate","ViewModeChanged","START_FULLSCREEN","END_FULLSCREEN","START_AD","END_AD","Muted","MUTE","Unmuted","UN_MUTE","ERROR","code","message","legacyData","data","originalError","additionalData","tryJSONStringify","ErrorCode","BITMOVIN_PLAYER_LICENSING_ERROR","SETUP_MISSING_LICENSE_WHITELIST","onLicenseCallFailed","dispatch","sendAdEngagementErrorSample","severity","PlaybackFinished","END","DownloadFinished","downloadType","drmType","replace","drmLoadTime","AudioChanged","AUDIOTRACK_CHANGED","SubtitleEnabled","SUBTITLE_CHANGE","SubtitleDisabled","LicenseValidated","onLicenseKeyReceived","licenseKey","handleCollectorUnload","UNLOAD","release","Destroy","source","videoTitle","title","mpdUrl","dash","m3u8Url","hls","progSourceInfo","getSourceInfoFromBitmovinSourceConfig","progressive","progUrl","videoBitrate","progBitrate","enabledSubtitle","getSubtitleList","find","s","enabled","subtitleLanguage","videoQuality","getPlaybackVideoData","videoPlaybackHeight","videoPlaybackWidth","videoCodec","audioQuality","getPlaybackAudioData","audioBitrate","audioCodec","isAirplayActive","castTech","CastTech","AirPlay","remoteControlConfig","GoogleCast","WebSocket","seekEvent","Math","abs","position","seekTarget","AnalyticsSettings","ANALYTICS_MIN_SEEK_DIFFERENCE_THRESHOLD","SpeedMeterAdapter","DownloadSpeedMeter","getDownloadSpeedMeter","SegmentTrackerAdapter","SegmentTracker","getSegmentTracker","HttpRequestTrackingAdapter","SourceInfoFallbackService","InternalAdapter","rawPlayer","eventType","callback","safeAccess","mode","subtitles","list","ads","getModuleInfo","remotecontrol","playback","activeAdId","adErrorPayload","errorEvent","errorData","adInfo","isLinear","linearAd","duration","skippable","skippableAfter","mediaUrl","mediaFileUrl","vastData","mimeType","adSystem","advertiserName","advertiser","apiFramework","creativeAdId","creative","adId","creativeId","universalAdIdRegistry","universalAdId","idRegistry","universalAdIdValue","value","adDescription","adTitle","wrapperAdsCount","wrapperAdIds","surveyUrl","survey","uri","minSuggestedDuration","replaceContentDuration","fallbackIndex","getFallbackIndex","scheduleTime","resolveEffectiveAdTag","tagUrl","tagType","persistent","preloadOffset","directTag","url","fallbackTags","fallbackTag","rawFallbackIndex","currentFallbackIndex","anything","maybeSsaiAdBreakMetadata","adPosition","SegmentPlayback","eventDispatcher","EventDispatcher","onDownloadFinished","subscribe","unsubscribe","httpRequest","calculateTimeWithUndefined","httpStatus","success","getCurrentTimestamp","timeToFirstByte","mapHttpRequestType","httpRequestTypeValue","objectValues","HttpRequestType","includes","UNKNOWN","handleSegmentPlaybackEvent","removeSegment","handleOnDownloadFinishEvent","segment","Utils","getURLResourceName","addSegment","meter","addMeasurement","Date","PlayerModule","hooks","setup","isConfigMissing","isAnalyticsDisabled","Promise","resolve","analyticsModuleInstance","analyticsBitmovin8Adapter","context","_config","BitmovinPwxInternalAdapter","dispose","BitmovinPwxAdapter","onAdd","dependencies","BitmovinPwxAnalyticsPackage","_","baseContext","registry","get","CoreExportNames","CoreEffects","EventListenerEffectFactory","StateEffectFactory","using","BundleExportNames","Logger","SourceExportNames","SourceState","PlayerConfig","log","adapter","listener","abortSignal","removeEventListener","Constants","CoreStateAtoms","SourcesApiExportNames","SourceEventBus","PlaybackApiEventsPackageExportNames","PlaybackEvent","_name","State","enabledDebugging","debuggingStates","createStateMachine","SETUP","JSM_INITIAL_EVENT","customStateMachineErrorCallback","READY","stayIn","STARTUP","VIDEOSTART_FAILED","getAllStatesBut","stopHeartbeat","onleavestate","eventTimestamp","logStateMachineTransition","addStatesToLog","stateDuration","onEnterStateTimestamp","isStartup","maybeSetOrClearVideoStartTimeouts","startup","toLowerCase","lowerCaseFrom","String","unload","clearVideoStartTimeout","defaultStateMachineCallbackFn","isFunction","logMissingCallbackWarning","startHeartbeat","onenterstate","_eventData","now","isNumber","starttime","_from","_to","_eventTimestamp","eventObject","EventDebugging","getStates","setEnabledDebugging","setVideoStartTimeout","AnalyticsStateMachine","BitmovinPwxAnalyticsStateMachine","playhead","sourceConfig","resources","filter","v","videoRect","video","element","getBoundingClientRect","videoWidth","round","videoHeight","StreamTypes","muted","stream","BITMOVIN_PWX","Version","registerEventListeners","bind","sourceEventBus","playbackAtom","Ready","VideoAttached","Ended","abortListener","abortSignalReason","reason","CreateSourceStateAtom","CreateSourceReference","SourceReferences","SourceApiManager","VideoElementUtils","castReceiverContext","CAFv3InternalAdapter","CAFv3Adapter","activeTextTracks","cast","framework","CHROMECAST_SHAKA","playerManager","getQueueManager","getCurrentItem","getPlayerManager","getCurrentTimeSec","CAFv3AnalyticsStateMachine","CAFv3PlayerProxy","registerCastFrameworkEventListeners","registerWindowUnloadEventListeners","stats","getStats","subtitleLanguages","t","language","detectCAFv3PlaybackInfoStreamTypeFields","audioTracksManager","getAudioTracksManager","activeTract","getActiveTrack","audioTrackInfo","_error","detectCAFv3PlaybackInfoAudioFields","detectIsLive","getMediaInformation","join","CastFrameworkEvent","LOADED_METADATA","PLAYER_LOAD_COMPLETE","textTracksManager","getTextTracksManager","getActiveTracks","currentMediaTime","TIME_UPDATE","detailedErrorCode","SEEKING","BUFFERING","isBuffering","REQUEST_LOAD","handleWindowUnloadEvent","streamType","getLiveSeekableRange","contentUrl","isBlank","contentId","getStreamTypesFromURL","buildPlaybackInfoStreamTypeFields","ALL","STALLED","HlsInternalAdapter","HlsjsPlayerProxy","HlsAdapter","HLSJS","currentLevelObj","getHlsCurrentLevel","details","live","onDestroying","HlsSpeedMeterAdapter","registerHlsEvents","selectedSubtitle","getSelectedSubtitleLanguage","playbackInfo","getSelectedAudioLanguage","codecInfo","getHlsCodecInfo","applyAndStoreCodecInfo","getCurrentQualityLevelInfo","getMIMEType","MIMETypes","HLS","getStreamURL","HLS_PLAYER_EVENT","MEDIA_ATTACHING","onMediaAttaching","MEDIA_DETACHING","onMediaDetaching","MANIFEST_LOADING","onManifestLoading","AUDIO_TRACK_SWITCHED","onAudioTrackSwitched","SUBTITLE_TRACK_SWITCH","onSubtitleLanguageSwitched","DESTROYING","onHlsError","media","mediaElement","HTMLVideoElementProxy","registerMediaElement","onMaybeReady","unregisterMediaElement","errorName","fatal","errorMessage","getErrorCodeFromHlsErrorType","_data","audioTrack","audioTracks","subtitleDisplay","subtitleTrackValue","subtitleTrack","isSubtitleDisplayed","subtitleTracks","subtitleTrackController","getSelectedSubtitleFromMediaElement","HTML5InternalAdapter","levels","currentLevel","constructor","PlaylistLevelType","FRAG_LOADED","_eventName","handleFragmentLoadedEvent","frag","networkDetails","status","loadingDuration","loading","end","start","first","measurement","total","needsFirstPlayIntent","isPaused","isSeeking","previousMediaTimeInSeconds","previousMutedValue","HTML5","isNaN","Infinity","HTML5AnalyticsStateMachine","mediaElementEventHandlers","mediaElementOriginalLoadFn","bufferingTimeout","previousClientTime","needsReadyEvent","playerStatisticsProvider","_analytics","setMediaElement","registerWindowEvents","isVideoInFullscreen","getDroppedFrames","qualityInfo","clearTimeout","streamUrl","getMIMETypeFromFileExtension","mimetype","getStreamTypeFromMIMEType","src","getRawPlayer","listenToMediaElementEvent","readyState","checkQualityLevelAttributes","onPaused","registerMediaElementErrorEvent","volume","isAudioMuted","checkSeeking","checkPlayheadProgress","onBuffering","handler","boundHandler","forEach","item","originalLoadFunc","onPageClose","silent","qualityLevelInfo","textTracks","attr","paused","setTimeout","ended","BUFFERING_TIMECHANGED_TIMEOUT_IN_MS","currentMediaTimeInSeconds","playbackRate","playbackPositionDeltaInSeconds","clientTimeProgressInSeconds","msgTime","toISOString","substring","prefix","logMsg","sourceMetadata","HTMLVideoElementInternalAdapter","setAudioLanguage","sessionData","sanitizeSessionMetadataAudioLanguage","setSubtitleEnabled","sanitizeSessionMetadataSubtitleEnabled","setSubtitleLanguage","sanitizeSessionMetadataSubtitleLanguage","HTMLVideoElementAdapter","currentSrc","getVideoPlaybackQuality","videoElement","previousTotalDroppedFrames","playbackQuality","droppedVideoFrames","currentDroppedFrames","SsaiService","defaultStateMachineCallbacks","WindowEventTracker","resetIntervals","callEvent","dimensions","getGlobalScreenDimensions","screenHeight","screenWidth","segmentsDownloadCount","segmentsDownloadSize","segmentsDownloadTime","avgDownloadSpeed","minDownloadSpeed","maxDownloadSpeed","avgTimeToFirstByte","previousState","currentState","customDataValues","customdatachange","CUSTOM_DATA_CHANGE","MANUAL_SOURCE_CHANGE","programChange","isSsaiActive","isInActiveState","_ad","_adBreak","ShakaInternalAdapter","ShakaPlayerProxy","playerPrototype","getPrototypeOf","loadPropertyDescriptor","getOwnPropertyDescriptor","writable","set","thatInternalAdapter","reject","then","result","catch","category","ShakaAdapter","getMediaElement","SHAKA","playerVersion","ShakaPlayerEvent","detail","exceptionMessage","exceptionStacktrace","stack","split","ONSTATECHANGE","getShakaCodecInfo","getShakaStreamFormat","getAssetUri","variantTracks","getVariantTracks","activeVideoTrack","track","active","videoId","videoBandwidth","bandwidth","activeTrack","manifestType","getManifestType","getLoadMode","prog","UNLOADING","STATECHANGED","isDrmLicenseType","extractDrmType","DRM_LICENSE_WIDEVINE","DRM_LICENSE_FAIRPLAY","DRM_LICENSE_PLAYREADY","DRM_LICENSE_CLEARKEY","requestType","match","DrmPerformanceService","hasPlaybackProgressed","lastEventTimestamp","lastCurrentTime","elapsedSec","currentTimeDelta","isValidProgress","PlaybackProgressDetectionService","THEOplayerInternalAdapter","THEOplayerProxy","hasValidSourceMetadataStructure","sanitizedSourceMetadata","sanitizeSourceMetadata","THEOplayerAdapter","delayedEventDispatcher","DelayedEventDispatcher","drmPerformanceService","playbackProgressDetectionService","videoTrackListeners","Map","audioTrackListeners","networkInterceptor","THEOplayerNetworkInterceptor","speedMeasurement","createSpeedMeasurementFromEvent","THEOplayerAnalyticsStateMachine","THEOplayerAdModule","httpRequestTracking","errorDetailTracking","windowTHEOplayerVersion","getGlobalTheoPlayerVersion","isValidString","THEOPLAYER","videoTracks","activeAudioTrack","activeTextTrack","airplay","casting","chromecast","playerDuration","detectPlaybackInfoStreamTypeFieldsFromSource","currentSource","activeQuality","codecs","isFinite","presentation","currentMode","clear","dispatchEvent","handleVideoQualityChanged","qualityEvent","quality","handleAudioQualityChanged","mediaTrack","delete","date","getTime","errorObject","cause","errorAsData","MEDIA_VIDEO","MEDIA_AUDIO","STALE_REQUEST_TIMEOUT_MS","pendingRequests","onRequest","request","performanceNow","getGlobalPerformanceNow","cleanupStaleRequests","pendingRequest","startTime","subType","mediaType","existing","onResponse","response","pendingArray","shift","endTime","extractResponseSize","network","warn","addRequestInterceptor","addResponseInterceptor","filtered","pending","contentLength","headers","parsed","parseIntOrUndefined","body","isArrayBuffer","byteLength","requestSubType","KEY_HLS_AES","DRM_CERTIFICATE_FAIRPLAY","endsWith","MANIFEST_DASH","MANIFEST_HLS_MASTER","MEDIA_SUBTITLES","clickThrough","skipOffset","googleAd","integration","contentType","universalAdIds","adIdRegistry","adIdValue","description","timeOffset","isFiniteNumber","deltaTimeOffsetVideoDuration","playing","mapTheoAdBreak","mapTheoAd","errorPayload","isAdErrorEvent","errorCode","adManifestPayload","sourceAds","currentAdBreak","CALLBACK_SCHEDULER_TIMEOUT_DELAY_MS","timeout","schedule","isScheduled","execute","CallbackScheduler","scenarios","scheduler","delayEvent","inState","cancelOnEvent","AD_PLAYBACK","activeScenario","matchingScenario","findMatchingScenario","scenario","VideojsInternalAdapter","VideojsPlayerProxy","VideojsAdapter","_subtitleInfo","previousTime","playerInstanceVersion","windowVideoJsVersion","getGlobalVideojsVersion","VIDEOJS","VideojsAnalyticsStateMachine","selectedAudioLanguage","getSelectedAudioTrackLanguage","getCodecInfo","tech","IWillNotUseThisInPlugins","detectVideoJsPlaybackInfoStreamTypeFields","isFullscreen","currentVideoJsQualityLevel","that","ready","getSubtitleInfo","seeking","newSubtitleInfo","hasInfoChanged","isDifferentSubtitleInfo","newSelectedAudioLanguage","vhs","mediaAttributes","getMediaAttributes","sourceHandler","playlists","selectedPlaylist","attributes","BANDWIDTH","RESOLUTION","CODECS","CodecHelper","isVideoCodec","isAudioCodec","videoJsPlayer","streamMimeType","currentType","options","BUFFERING_HEARTBEAT_INTERVALS","videoStartupTimeoutMs","Settings","ANALYTICS_VIDEOSTART_TIMEOUT","bufferTimeoutMs","ANALYTICS_BUFFER_TIMEOUT","currentBufferingIntervalIndex","stateMachineEventMethod","clearBufferingTimeoutHandle","clearBufferingHeartbeatHandle","startBufferingHeartbeatInterval","resetBufferingHelpers","startBufferingTimeoutHandle","bufferingHeartbeatIntervalHandle","setInterval","heartbeat","buffered","min","clearInterval","bufferingTimeoutHandle","BUFFERING_TIMEOUT_REACHED","videoStartTimeout","VIDEOSTART_TIMEOUT","onHeartbeat","triggeredBySsai","triggeredByProgramChange","setVideoTimeEndFromEvent","payload","played","isProgramChange","SSAI_RELATED_SAMPLE_MARKER","resetCurrentStateStart","stateEnterTimestamp","setVideoTimeStartFromEvent","programChangeTimestamp","updateSourceMetadata","whileIn","passOver","UNLOADED","SEEKING_IN_PAUSE","SOURCE_CHANGING","CUSTOMDATACHANGE","videoStartFailed","createVideoStartFailedReason","manualSourceChange","getAllStates","i","SETUP_SOURCE_CHANGE","QUALITY_CHANGE","FINISH_QUALITY_CHANGE","PAUSED_SEEKING","SUBTITLE_CHANGING","AUDIOTRACK_CHANGING","AD","MUTING_READY","MUTING_PLAY","MUTING_PAUSE","CASTING","pause","mute","unMute","qualitychange","startCasting","onafterevent","FINISH_MUTING","AD_PLAYBACK_IN_STARTUP","VideoStartFailedReason","PAGE_CLOSED","buffering","seekTimestamp","seekedTimestamp","PLAY_SEEKING","END_PLAY_SEEKING","AUDIOTRACK_CHANGED_PLAYING","SUBTITLE_CHANGED_PLAYING","seekDuration","FINISH_AUDIOTRACK_CHANGING","FINISH_SUBTITLE_CHANGING","CustomEvents","sourceLoadedDuringAutoplayStartup","INITIAL_SOURCE_CHANGE","AD_STARTUP","STARTUP_AUTOPLAY","PAUSE_BEFORE_SOURCE_LOADED","PAUSE_AFTER_SOURCE_LOADED","AD_READY","AD_PAUSE","AD_PLAYING","seekStartTimestamp","lastTrackedVideoEndObject","noOp","initialSourceChange","excludedStates","stateEnumObj","stateMachineEventDefBuilderFn","runEventCallbacksFor","eventName","_ex","loggerMessage","loggerMessageData","ignoreStates","ignoredState","stateStringEnumObj","padRight","toBoolean","isPlaying","adPodPosition","viewportTracker","ViewportTracker","onIntersectionChanged","clearCurrentTimeInterval","adManifestDownloadTime","activeAdState","isContainerInViewport","enterViewportTimestamp","timeInViewport","isInViewport","beginPlayingTimestamp","updatePlayingTime","sendAnalyticsRequest","buildInitialActiveAdBreakState","activeAdBreakState","adStartupTimestamp","resetActiveAd","buildInitialActiveAdState","adStartupTime","startAd","activeAdStateCopy","completed","completeAd","adDuration","skipped","skipPosition","skipPercentage","calculatePercentage","exitPosition","adBreakSample","transformedError","transformError","errorSeverity","errorPosition","errorPercentage","adClickthroughUrl","clicked","clickPosition","clickPercentage","FIRST_QUARTILE","quartile1","MIDPOINT","midpoint","THIRD_QUARTILE","quartile3","closed","closePosition","closePercentage","adSample","buildAdSample","sample","moduleInfo","platform","analyticsVersion","adModule","adModuleVersion","pageLoadType","getPageLoadType","time","adImpressionId","generateUUID","percentageInViewport","timePlayed","backend","sendAdRequest","started","currentTimeInterval","calculateTime","max","AdAnalytics","TIMEOUT_CURRENT_TIME_INTERVAL","playPercentage","MODULE_NAME","adFallbackIndex","adIdPlayer","adReplaceContentDuration","adIsPersistent","adTagType","adTagUrl","adPreloadOffset","adOffset","URL","adTagServer","hostname","adTagPath","pathname","adScheduleTime","adPlaybackHeight","adPlaybackWidth","mediaPath","mediaServer","adSkipAfter","adSkippable","initialAnalyticsConfig","backendFactory","sessionHandler","featureManager","onErrorDetailEventDispatcher","identicalErrorReportingLimiter","hasSentStartupSample","droppedSampleFrames","playerStartupTime","authenticationCallback","authenticationCompleted","featureConfigs","configureFeatures","guardConfigChangeAgainstMissingTitle","guardConfigChangeAgainstMissingIsLive","newConfig","mergeAnalyticsConfig","oldConfig","setState","sendSample","impressionId","userId","changeCustomData","extractCustomDataFieldsOnly","SessionPersistenceHandler","domain","getDomainFromAnalyticsConfig","licenseKeyReceivedUnsubscriber","eventArgs","buildInitialSample","init","setupStateMachineCallbacks","features","registerFeatures","adAnalytics","supportsDeferredLicenseLoading","debug","resetFeatures","createBackend","resetValues","deviceInformation","getDeviceInformationFromAnalyticsConfig","cdnProvider","customUserId","transferCustomDataFields","experimentName","model","hasGlobalWebOSApi","modelName","getWebOSTVModelName","setDuration","navigationStart","globalScope","performance","timing","pageLoadTime","supportedVideoCodecs","supportedVideoFormats","sanitizeVideoStartupTime","videoStartupTime","startupTime","drmPerformance","setStartupHasFinished","applySourceMetadataToAnalyticsConfig","path","getDefaultSamplePath","setCompletionValues","videoStartForClosedState","videoTimeStart","videoTimeEnd","sendUnloadRequest","clearSampleStateValues","setVideoTimeStart","setVideoTimeEnd","heartbeatPayload","startResetInterval","increaseCounter","hasExceededQualityChangeThreshold","QUALITY_CHANGE_THRESHOLD_EXCEEDED","audiotrack_changing","seeked","videoStartFailedReason","PLAYER_ERROR","TIMEOUT","VIDEO_STARTUP_TIMEOUT_REACHED","shouldReportError","errorSegments","AD_TYPE","CSAI","subtitle_changing","analyticsEventBase","NoOpBackend","stopResetInterval","_duration","_state","setPlaybackInfoFromAdapter","isBoolean","customDataOnceValues","downloadSpeedInfo","manipulate","setQualityInfoOnSample","copySample","sendRequest","ssaiEngagementTrackingEnabled","isSsaiEngagementStartedData","ssaiAdSample","createStartedAdSample","isSsaiEngagementQuartileData","createQuartileAdSample","isSsaiEngagementErrorData","analyticsError","ssaiErrorAdSample","createErrorAdSample","addWatched","completedTotal","getCompletionPercentage","Number","errorTransformerCallback","transform","isErrorSeverity","screenDimensions","getGlobalNavigatorLanguage","userAgent","getGlobalNavigatorUserAgent","BackendFactory","FeatureManager","IdenticalErrorReportingLimiter","licensingRequest","isEnabled","inner","createInnerBackend","decorateWithDebuggingBackend","DebuggingBackend","decorateWithBackendFromConfigIfAvailable","innerBackend","wrapBackend","backendUrl","ANALYTICS_BACKEND_BASE_URL","LicenseCheckingBackend","LicenseCall","sequenceNumberAssigningBackend","SequenceNumberBackend","LongPlaytimeFilteringBackend","underlying","fields","debugFields","printFields","f","table","measures","measure","Measure","threshold","Converter","bitsToBytes","speed","m","reduce","ceil","totalTime","avgSpeed","minSpeed","maxSpeed","a","b","totalSpeed","speeds","numMeasurements","bytePerSecondToBitPerSecond","bps","bytesToBits","avg","index","splice","DEFAULT_HEARTBEAT_INTERVAL_MS","heartbeatInterval","clearHeartbeat","_currentErrorCount","_lastErrorCode","_lastErrorSeverity","MAX_IDENTICAL_ERROR_REPORTING","licenseCall","backendBaseUrl","licenseKeyReceived","licenseLazyLoadingTimeoutHandle","unsubscribeFromAdapter","promise","wrapLicenseCheckPromiseWithCallback","performLicenseCheck","licenseCallFailed","licenseLazyLoadingTimeout","QueueBackend","ANALYTICS_LICENSECALL_TIMEOUT","LicensingResult","Denied","Granted","remoteBackend","RemoteBackend","flushTo","err","next","nextBackend","isPlayedAboveThreshold","download","_sample","_adSample","qualityChangeCountThreshold","ANALYTICS_QUALITY_CHANGE_COUNT_THRESHOLD","qualityChangeCount","previousVideoBitrate","previousAudioBitrate","startupHasFinished","QUALITY_CHANGE_COUNT_THRESHOLD","startupVideoBitrate","startupAudioBitrate","newBitrate","qualityChangeCountResetIntervalId","ANALYTICS_QUALITY_CHANGE_COUNT_RESET_INTERVAL","queue","unloadQueue","adQueue","analyticsCall","AnalyticsCall","segments","sequenceNumber","updateSampleBeforeSending","isSequenceNumberAboveThreshold","SEQUENCE_NUMBER_LIMIT","COOKIE_NAME_BITMOVIN_ANALYTICS_UUID","COOKIE_DEFAULT_MAX_AGE","cookiesEnabled","deleteCookie","existingUserId","getCookie","cookieDomain","validateCookieDomainValue","cookiesDomain","cookieMaxAge","validateCookieMaxAgeValue","cookiesMaxAge","nowMillis","cookieExpires","toUTCString","setCookie","expires","maxAge","encodeURIComponent","TimespanOverlappingType","watched","overlappingTimespan","mergeWatched","w","time1","k","time2","overlapType","getOverlappingType","Overlapping","mergeAndReplace","getOverlappingTimespan","FirstContainedInSecond","SecondContainedInFirst","None","second","isMomentInTimespan","moment","timespan","firstIndex","secondIndex","newWatchedTimespan","SsaiState","eventHandler","adIndex","IDLE","isFirstSampleOfAd","sentAdQuartiles","errorSent","isActivated","AD_BREAK_STARTED","currentAdMetadata","ACTIVE","resetAdData","customData","currentAdImpressionId","timestampOfAdStart","getCurrentMonotonicTimestampInMs","quartileMetadata","timeSinceAdStartedInMs","getMonotonicTimestampInMsSince","resetAdBreakData","SSAI","customDataValuesKeys","isPlainObject","isAdPosition","maybeSsaiAdMetadata","ssaiAdMetadata","sanitizedCustomDataValues","sanitizeCustomDataValues","isSsaiAdQuartile","ssaiAdQuartileMetadata","failedBeaconUrl","adType","ROUTING_URL_PARAM","ROUTING_URL_PARAM_VALUE_SSAI","playbackSample","ssaiEngagementErrorData","ssaiEngagementStartedData","ssaiEngagementQuartileData","timestampInMs","adEngagementSample","customData1","customData2","customData3","customData4","customData5","customData6","customData7","customData8","customData9","customData10","customData11","customData12","customData13","customData14","customData15","customData16","customData17","customData18","customData19","customData20","customData21","customData22","customData23","customData24","customData25","customData26","customData27","customData28","customData29","customData30","customData31","customData32","customData33","customData34","customData35","customData36","customData37","customData38","customData39","customData40","customData41","customData42","customData43","customData44","customData45","customData46","customData47","customData48","customData49","customData50","customData51","customData52","customData53","customData54","customData55","customData56","customData57","customData58","customData59","customData60","customData61","customData62","customData63","customData64","customData65","customData66","customData67","customData68","customData69","customData70","customData71","customData72","customData73","customData74","customData75","customData76","customData77","customData78","customData79","customData80","customData81","customData82","customData83","customData84","customData85","customData86","customData87","customData88","customData89","customData90","customData91","customData92","customData93","customData94","customData95","customData96","customData97","customData98","customData99","customData100","videoImpressionId","quartile1FailedBeaconUrl","midpointFailedBeaconUrl","quartile3FailedBeaconUrl","completedFailedBeaconUrl","floor","CdnProvider","videoCodecs","findIndex","startsWith","audioCodecs","urlPath","MP4","WEBM","DASH","PAGE_LOAD_TYPE","stateMachineEvent","_isEnabled","disable","disabled","configure","authenticated","configContainer","extractConfig","configured","Feature","unregisterFeatures","feature","_queue","_enabled","joinUrls","copyErrorDetailTruncateStringsAndUrls","errorDetail","maxStringLength","maxUrlLength","substr","copyErrorDataTruncateStrings","httpRequests","copyHttpRequestTruncateUrls","maxLength","lastRedirectLocation","copyErrorDetailTruncateHttpRequests","maxRequests","limitHttpRequestsOfQueuedErrorDetails","send","errorDetailCopy","MAX_STRING_LENGTH","MAX_URL_LENGTH","post","flush","copy","removeFromQueue","settingsProvider","subscribables","errorIndex","onErrorHandler","httpRequestsCopy","errorId","subscribable","_authenticated","numberOfHttpRequests","errorDetails","_maxRequests","DEFAULT_MAX_REQUESTS","_httpRequestQueue","Queue","onDownloadFinishedHandler","addRequest","items","limit","offer","customDataFieldCount","input","retVal","extracted","getCustomDataString","playerVideoDuration","DEFAULT_RESULT","maybeSourceMetadata","muting_ready","info1","info2","baseUrl","analyticsServerUrl","adAnalyticsServerUrl","analyticsUrl","isSsaiRelatedSample","appendSsaiRoutingParam","trySendBeacon","sendRequestSynchronous","fallbackFunction","requestHeaders","navigator","sendBeacon","blob","Blob","JSON","stringify","adAnalyticsUrl","playbackVideoData","progressiveArrayIndex","videoFormatCodecMap","avc","vp9","av1","hevc","MediaSource","isTypeSupported","getOwnPropertyNames","format","some","bytes","bits","kiloBitsToBits","kiloBits","async","xhttp","isLegacyXDomainRequestUsed","XMLHttpRequest","XDomainRequest","onload","parse","responseText","statusText","onerror","openAsyncRequest","isReactNative","open","setRequestHeader","licenseServerUrl","getInstance","instance","analyticsDebugConfig","console","optionalParams","tabularData","properties","str","_items","poll","maxElements","MESSAGE_NAMESPACE","isDocumentHidden","BACKGROUND","FOREGROUND","toString","Boolean","valueOf","isObject","removeTrailingSlash","timeInSeconds","fromConfig","toConfig","CustomDataUtils","customDataField","numerator","denominator","pop","prev","getGlobalNavigatorProduct","playerIsMuted","playerVolume","obj","inViewport","rootMargin","observer","IntersectionObserver","entries","handleIntersect","observe","hiddenPropertyName","getDocumentPropertyWithPrefix","visibilityChange","addDocumentEventListener","handleVisibilityChange","isHidden","document","unobserve","disconnect","removeDocumentEventListener","_observer","intersectionRatio","getGlobalWebOSApi","webOSSystem","PalmSystem","deviceInfo","trackedObjects","addGlobalEventListener","removeGlobalEventListener","deviceType","deviceClass","getGlobalLocationHostname","fallbackDomain","origin","oldConfigWithoutSourceRelatedFields","sourceSpecificProperties","customDataFieldsRegex","removeSourceRelatedFields","mergedCollectorConfig","oldCollectorConfig","newCollectorConfig","mergeCollectorConfig","errorMessages","isDomainMissing","fullErrorMessage","prop","pascalCase","charAt","toUpperCase","prefixedProp","hiddenProp","fullscreenProp","nodeName","allCookies","cookie","cookieName","newCookie","globalThis","window","g","getGlobalThis","getGlobalDevicePixelRatio","devicePixelRatio","screen","scale","location","getGlobalLocationPathname","userLanguage","product","videojs","THEOplayer","parseInt","access","BITMOVIN_ANALYTICS_AUGMENTED_MARKER","isEmpty","trim","suffix","c","r","random","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","__webpack_modules__","Function","adapters"],"sourceRoot":""}