public FitnessViewModel(GeneticManagement gen)
        {
            _gpContainer = gen;

            int popSize = _gpContainer._population.Count;

            if ((popSize & (popSize - 1)) == 0)
            {
                _bracketSize = popSize;
            }
            else
            {
                for (int i = popSize; (popSize & (popSize - 1)) != 0; i--)
                {
                    popSize = i;
                }
                _bracketSize = popSize;
            }


            _activeMatches          = new ObservableCollection <MatchHistory>();
            _finishedMatches        = new ObservableCollection <MatchHistory>();
            _scores                 = new Dictionary <GeneticTree, float>();
            _gpContainer._fitnesses = Enumerable.Repeat(0.5f, (int)_gpContainer._populationSize).ToList();

            BindingOperations.EnableCollectionSynchronization(_activeMatches, collectionLock);
            //BindingOperations.EnableCollectionSynchronization(_finishedMatches, collectionLock);

            foreach (var item in _gpContainer._population)
            {
                _scores.Add(item, 0);
            }

            _highlightedMatch         = null;
            _highlightedMove          = 0;
            _highlightMatchCommand    = new RelayCommand(x => { _setHighlight((MatchHistory)x); }, x => true);
            _highlightForwardCommand  = new RelayCommand(x => { _highlightMove(1); }, x => true);
            _highlightBackwardCommand = new RelayCommand(x => { _highlightMove(-1); }, x => true);
            _beginFitnessCommand      = new RelayCommand(async x => await beginFitnessEvaluation(), x => true);


            MatchHistory empty = new MatchHistory();

            empty.addNewState("................................................................");
            _highlightMatchCommand.Execute(empty);
        }
        public async Task <object> beginFitnessEvaluation()
        {
            if (_gpContainer._fitnessType == ChessTournamentType.SINGLE_ELIMINATION)
            {
                while (_bracketSize > 1)
                {
                    List <Task <int> > tasks   = new List <Task <int> >();
                    List <Pairing>     bracket = (List <Pairing>)getPairings();
                    foreach (var pairing in bracket)
                    {
                        Task <int> t = new Task <int>(() =>
                        {
                            MatchHistory hist = new MatchHistory(pairing);
                            lock (collectionLock)
                            {
                                App.Current.Dispatcher.Invoke(() => _activeMatches.Add(hist));
                                _activeMatches = new ObservableCollection <MatchHistory>(_activeMatches);
                                OnPropertyChanged("_activeMatches");
                            }
                            Process p             = new Process();
                            p.StartInfo.FileName  = "pairing.exe";
                            p.StartInfo.Arguments = $"{_gpContainer._evalDepth} \"{Board.DEFAULT_POSITION}\" \"{pairing._white._rpn}\" \"{pairing._black._rpn}\"";
                            p.StartInfo.RedirectStandardOutput = true;
                            p.StartInfo.UseShellExecute        = false;
                            p.StartInfo.CreateNoWindow         = true;
                            p.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
                            {
                                lock (collectionLock)
                                {
                                    float balance = float.NaN;
                                    bool status   = float.TryParse(e.Data, NumberStyles.Float, CultureInfo.InvariantCulture, out balance);
                                    if (status == false)
                                    {
                                        hist.addNewState(e.Data);
                                    }
                                    else
                                    {
                                        hist._materialBonus = balance;
                                    }
                                }
                            });

                            p.Start();
                            p.BeginOutputReadLine();
                            p.WaitForExit();

                            lock (collectionLock)
                            {
                                App.Current.Dispatcher.Invoke(() => _activeMatches.Remove(hist));
                                _activeMatches = new ObservableCollection <MatchHistory>(_activeMatches);
                                OnPropertyChanged("_activeMatches");

                                App.Current.Dispatcher.Invoke(() => _finishedMatches.Add(hist));
                                _finishedMatches = new ObservableCollection <MatchHistory>(_finishedMatches);
                                OnPropertyChanged("_finishedMatches");
                            }
                            int result = p.ExitCode;
                            lock (scoresLock)
                            {
                                switch (result)
                                {
                                case 1:
                                    hist._state              = MatchState.WIN_WHITE;
                                    _scores[pairing._white] += 1;
                                    break;

                                case 2:
                                    hist._state              = MatchState.WIN_BLACK;
                                    _scores[pairing._black] += 1;
                                    break;

                                case 3:
                                    hist._state              = MatchState.DRAW;
                                    _scores[pairing._white] += 0.5f;
                                    _scores[pairing._black] += 0.5f;
                                    break;
                                }
                                if (hist._materialBonus < 0)
                                {
                                    _scores[pairing._black] += Math.Abs(hist._materialBonus);
                                    _scores[pairing._black]  = (float)Math.Round(_scores[pairing._black], 1);
                                }
                                else
                                {
                                    _scores[pairing._white] += Math.Abs(hist._materialBonus);
                                    _scores[pairing._white]  = (float)Math.Round(_scores[pairing._white], 1);
                                }

                                if (hist._state == MatchState.WIN_WHITE && hist._materialBonus > 0.25f)
                                {
                                    _scores[pairing._white] += 5;
                                }
                                else if (hist._state == MatchState.WIN_BLACK && hist._materialBonus < -0.25f)
                                {
                                    _scores[pairing._black] += 5;
                                }

                                _scores = new Dictionary <GeneticTree, float>(_scores);
                                OnPropertyChanged("_scores");
                            }
                            return(0);
                        });
                        tasks.Add(t);
                        t.Start();
                    }
                    await Task.WhenAll(tasks);

                    _gpContainer._population.OrderByDescending(x => _scores[x]);
                    _gpContainer._fitnesses = _scores.Values.OrderByDescending(x => x).ToList();
                    _bracketSize           /= 2;
                }
            }
            else
            {
                List <Task <int> >     tasks   = new List <Task <int> >();
                List <List <Pairing> > bracket = (List <List <Pairing> >)getPairings();
                foreach (var pairingList in bracket)
                {
                    Task <int> t = new Task <int>(() =>
                    {
                        foreach (var pairing in pairingList)
                        {
                            MatchHistory hist = new MatchHistory(pairing);
                            lock (collectionLock)
                            {
                                App.Current.Dispatcher.Invoke(() => _activeMatches.Add(hist));
                                _activeMatches = new ObservableCollection <MatchHistory>(_activeMatches);
                                OnPropertyChanged("_activeMatches");
                            }
                            Process p             = new Process();
                            p.StartInfo.FileName  = "pairing.exe";
                            p.StartInfo.Arguments = $"{_gpContainer._evalDepth} \"{Board.DEFAULT_POSITION}\" \"{pairing._white._rpn}\" \"{pairing._black._rpn}\"";
                            p.StartInfo.RedirectStandardOutput = true;
                            p.StartInfo.UseShellExecute        = false;
                            p.StartInfo.CreateNoWindow         = true;
                            p.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
                            {
                                float balance = float.NaN;
                                bool status   = float.TryParse(e.Data, NumberStyles.Float, CultureInfo.InvariantCulture, out balance);
                                if (status == false)
                                {
                                    hist.addNewState(e.Data);
                                }
                                else
                                {
                                    hist._materialBonus = balance;
                                }
                            });

                            p.Start();
                            p.BeginOutputReadLine();
                            p.WaitForExit();

                            lock (collectionLock)
                            {
                                App.Current.Dispatcher.Invoke(() => _activeMatches.Remove(hist));
                                _activeMatches = new ObservableCollection <MatchHistory>(_activeMatches);

                                App.Current.Dispatcher.Invoke(() => _finishedMatches.Add(hist));
                                _finishedMatches = new ObservableCollection <MatchHistory>(_finishedMatches);

                                OnPropertyChanged("_activeMatches");
                                OnPropertyChanged("_finishedMatches");
                            }
                            int result = p.ExitCode;
                            lock (scoresLock)
                            {
                                switch (result)
                                {
                                case 1:
                                    hist._state              = MatchState.WIN_WHITE;
                                    _scores[pairing._white] += 1;
                                    break;

                                case 2:
                                    hist._state              = MatchState.WIN_BLACK;
                                    _scores[pairing._black] += 1;
                                    break;

                                case 3:
                                    hist._state              = MatchState.DRAW;
                                    _scores[pairing._white] += 0.5f;
                                    _scores[pairing._black] += 0.5f;
                                    break;
                                }
                                if (hist._materialBonus < 0)
                                {
                                    _scores[pairing._black] += Math.Abs(hist._materialBonus);
                                    _scores[pairing._black]  = (float)Math.Round(_scores[pairing._black], 1);
                                }
                                else
                                {
                                    _scores[pairing._white] += Math.Abs(hist._materialBonus);
                                    _scores[pairing._white]  = (float)Math.Round(_scores[pairing._white], 1);
                                }
                                _scores = new Dictionary <GeneticTree, float>(_scores);
                                OnPropertyChanged("_scores");
                            }
                        }
                        return(0);
                    });
                    tasks.Add(t);
                    t.Start();
                }
                await Task.WhenAll(tasks);

                _gpContainer._population.OrderByDescending(x => _scores[x]);
                _gpContainer._fitnesses = _scores.Values.OrderByDescending(x => x).ToList();
            }
            _gpContainer.calculatePositions();
            return(Task.FromResult <object>(null));
        }