public PrTabViewModel(SimulationOptions simulationOptions) : base("ІПРАЙ")
        {
            var logger = Logger.New(typeof(PrTabViewModel));

            using (logger.LogPerf("Init"))
            {
                m_SimulationOptions = simulationOptions;

                m_Simulator = new PrSimulator(m_SimulationOptions);

                m_VisualizationProvider = GridDataVisualizationProvider.Table();

                m_Player = new Player(() =>
                {
                    using (logger.LogPerf("Step simulation"))
                    {
                        m_Simulator.SimulateSteps();
                    }
                }, () =>
                {
                    using (logger.LogPerf("Auto simulation"))
                    {
                        m_Simulator.SimulateSteps(5);
                    }
                }, () =>
                {
                    UpdateVisualization.Execute().Subscribe();
                }, TimeSpan.FromMilliseconds(10), DispatcherPriority.ContextIdle);

                UpdateVisualization = ReactiveCommand.Create(() =>
                {
                    using (logger.LogPerf("Visualization"))
                    {
                        Visualization  = m_VisualizationProvider.ProvideVisualization(m_Simulator.GetData());
                        SimulationInfo = m_Simulator.SimulationInfo;
                    }
                });

                var notRunningOrPlaying = m_Player.WhenAny(x => x.RunningOrPlaying, r => !r.Value);

                var notSingleStepRunning = m_Player.WhenAny(x => x.SingleStepRunning, r => !r.Value);

                Step = ReactiveCommand.Create(() =>
                {
                    m_Player.StepOnce();
                }, notRunningOrPlaying);

                PlayPause = new ReactivePlayPauseCommand("Програти", "Пауза", notSingleStepRunning);

                PlayPause.Subscribe(p =>
                {
                    if (p)
                    {
                        m_Player.Start();
                    }
                    else
                    {
                        m_Player.Stop();
                    }
                });

                Restart = ReactiveCommand.Create(() =>
                {
                    m_Simulator.Reset();
                }, notRunningOrPlaying);

                Restart.InvokeCommand(UpdateVisualization);

                VisualTypeSelector = new ReactiveSelectorCommand <string>(x => (string)x, "Table");

                VisualTypeSelector.Selected
                .Subscribe(option =>
                {
                    switch (option)
                    {
                    case "Table":
                        m_VisualizationProvider = GridDataVisualizationProvider.Table();
                        break;

                    case "2D":
                        m_VisualizationProvider = GridDataVisualizationProvider.Color();
                        break;

                    case "3D":
                        m_VisualizationProvider = GridDataVisualizationProvider.Model3D(m_SimulationOptions.Size);
                        break;
                    }
                });

                VisualTypeSelector.Selected
                .ToSignal()
                .InvokeCommand(UpdateVisualization);

                OpenSimulationOptions = ReactiveCommand.Create(() =>
                {
                    SimulationOptionsDialog dialog = new SimulationOptionsDialog(m_SimulationOptions);
                    dialog.ShowDialog();

                    if (!dialog.DialogResult.GetValueOrDefault(false))
                    {
                        return;
                    }

                    m_SimulationOptions     = dialog.SimulationOptions;
                    m_Simulator             = new PrSimulator(m_SimulationOptions);
                    m_VisualizationProvider = m_VisualizationProvider.Copy(m_SimulationOptions.Size);
                }, notRunningOrPlaying);

                OpenSimulationOptions
                .InvokeCommand(UpdateVisualization);

                ExportToCsv = ReactiveCommand.Create(() =>
                {
                    SaveFileDialog saveFileDialog = new SaveFileDialog()
                    {
                        Filter = "Файл CSV (*.csv)|*.csv"
                    };
                    if (saveFileDialog.ShowDialog(Application.Current.MainWindow).GetValueOrDefault())
                    {
                        CsvUtil.ExportToFile(m_Simulator.GetData(), saveFileDialog.FileName);
                    }
                });

                Settings.SettingsChange
                .InvokeCommand(UpdateVisualization);

                Settings.SettingsChange
                .Subscribe(_ =>
                {
                    Pallete = Settings.Current.VisualizationOptions.Pallete;
                });

                Pallete = Settings.Current.VisualizationOptions.Pallete;
            }
        }
        public CpTabViewModel(SimulationOptions options) : base("Порівняння")
        {
            var logger = Logger.New(typeof(CpTabViewModel));

            using (logger.LogPerf("Init"))
            {
                InitComponents(options);

                m_Player = new Player(() =>
                {
                    Simulate(0.05d);
                }, () =>
                {
                    for (int i = 0; i < 50; i++)
                    {
                        Simulate();
                    }
                }, () =>
                {
                    UpdateVisualization.Execute().Subscribe();
                }, TimeSpan.FromMilliseconds(10), DispatcherPriority.ContextIdle);

                UpdateVisualization = ReactiveCommand.Create(() =>
                {
                    using (logger.LogPerf("Visualization"))
                    {
                        PrVisualization   = m_Visualizer.GenerateTableVisualization(m_PrSimulator.GetData());
                        StVisualization   = m_Visualizer.GenerateEdgeTableVisualization(m_StSimulator.GetData());
                        DiffVisualization = m_Visualizer.GenerateEdgeTableVisualization(m_DiffGenerator.GetData());

                        PrSimulationInfo = m_PrSimulator.SimulationInfo;
                        StSimulationInfo = m_StSimulator.SimulationInfo;
                    }
                });

                var notRunningOrPlaying = m_Player.WhenAny(x => x.RunningOrPlaying, r => !r.Value);

                var notSingleStepRunning = m_Player.WhenAny(x => x.SingleStepRunning, r => !r.Value);

                SimulateStep = ReactiveCommand.Create(() =>
                {
                    m_Player.StepOnce();
                }, notRunningOrPlaying);

                PlayPause = new ReactivePlayPauseCommand("Програти", "Пауза", notSingleStepRunning);

                PlayPause.Subscribe(p =>
                {
                    if (p)
                    {
                        m_Player.Start();
                    }
                    else
                    {
                        m_Player.Stop();
                    }
                });

                Restart = ReactiveCommand.Create(() =>
                {
                    m_PrSimulator.Reset();
                    m_StSimulator.Reset();
                }, notRunningOrPlaying);

                Restart.InvokeCommand(UpdateVisualization);

                OpenSimualationOptions = ReactiveCommand.Create(() =>
                {
                    SimulationOptionsDialog dialog = new SimulationOptionsDialog(SimulationOptions.FromSimulator(m_PrSimulator));
                    dialog.ShowDialog();

                    if (dialog.DialogResult.GetValueOrDefault(false))
                    {
                        SimulationOptions result = dialog.SimulationOptions;
                        InitComponents(result);
                    }
                }, notRunningOrPlaying);

                OpenSimualationOptions.InvokeCommand(UpdateVisualization);

                Settings.SettingsChange
                .InvokeCommand(UpdateVisualization);

                UpdateVisualization.Execute().Subscribe();
            }
        }