public DwellTrialController(IClock clock, GazePointProvider gazePointProvider,
                                    WebBrowserAssistantParadigm.Configuration.UserConfig userConfig)
        {
            _clock                   = clock;
            _gazePointProvider       = gazePointProvider;
            _cancellable             = userConfig.CancelByMovement;
            _cursorMovementTolerance = userConfig.CursorMovementTolerance;
            _dwellToSelectDelay      = userConfig.DwellSelectionDelay;

            Reset();
        }
        public WebBrowserAssistantEngine(Session session)
        {
            var paradigm = _paradigm = (WebBrowserAssistantParadigm)session.Paradigm;

            if (!session.StreamerCollection.TryFindFirst(out _markerStreamer))
            {
                throw new UserException("Marker streamer not found");
            }
            if (!session.StreamerCollection.TryFindFirst(out _gazePointStreamer))
            {
                throw new UserException("Gaze-point streamer not found");
            }
            if (!session.StreamerCollection.TryFindFirst(out _biosignalStreamer))
            {
                throw new UserException("Biosignal streamer not found");
            }

            _server = new WebBrowserAssistantServer(session);
            _server.AddMessageHandler(this);
            _server.ActiveClientChanged += (sender, e) =>
            {
                if (e.OldValue == null)
                {
                    _hasActiveClient.Set();
                }
                else
                {
                    if (e.NewValue == null)
                    {
                        _hasActiveClient.Reset();
                    }
                    InterruptTrial();
                }
            };
            _server.ClientDimensionsChanged += (sender, e) =>
            {
                if (e.IsActiveClient)
                {
                    InterruptTrial();
                }
            };
            _server.ClientSceneChanged += (sender, e) =>
            {
                if (e.IsActiveClient)
                {
                    InterruptTrial();
                }
            };

            _modeOnSetInterceptor            = new ModeOnSetInterceptor();
            _modeOnSetInterceptor.ModeOnSet += (sender, e) => Mode = e;

            _gazePointProvider               = new GazePointProvider();
            _dwellTrialController            = new DwellTrialController(session.Clock, _gazePointProvider, paradigm.Config.User);
            _dwellTrialController.Triggered += (sender, e) => _trialStartEvent.Set();
            _dwellTrialController.Cancelled += (sender, e) => _trialCancelled.Set();

            var stimulationScheme = paradigm.Config.User.StimulationScheme;
            var samplingRate      = _biosignalStreamer.BiosignalSource.Frequency;
            var frequencies       = stimulationScheme.Frequencies;
            var interFrequencies  = new float[frequencies.Count - 1];

            for (var i = 0; i < interFrequencies.Length; i++)
            {
                interFrequencies[i] = (frequencies[i] + frequencies[i + 1]) / 2;
            }
            var frequencyPatterns = frequencies.Concat(interFrequencies).Select(f => new CompositeTemporalPattern <SinusoidalPattern>(new SinusoidalPattern(f))).ToArray();
            var bandMixingParams  = new SubBandMixingParams(1.25, 0.25);
            var channels          = paradigm.Config.System.Channels.Enumerate(1, _biosignalStreamer.BiosignalSource.ChannelNum).Select(i => (uint)(i - 1)).ToArray();

            _navigatingSsvepDetector = new HybridSsvepIdentifier(session.Clock, 4, frequencyPatterns, stimulationScheme.FilterBank, bandMixingParams,
                                                                 stimulationScheme.HarmonicCount, 0, channels, samplingRate, paradigm.Config.User.StimulationDuration.Navigating, 0);
            _spellingSsvepDetector = new HybridSsvepIdentifier(session.Clock, 4, frequencyPatterns, stimulationScheme.FilterBank, bandMixingParams,
                                                               stimulationScheme.HarmonicCount, 0, channels, samplingRate, paradigm.Config.User.StimulationDuration.Spelling, 0);
            _frequencyCount = stimulationScheme.Frequencies.Count;
        }