private void _rollWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            if (!String.IsNullOrWhiteSpace(_expressionString))
            {
                (double, double, double)avgMinMax = _diceService.EvaluateExpressionAvgMinMax(_expressionString);
                _averageString = ((int)avgMinMax.Item1).ToString();
                _minString     = ((int)avgMinMax.Item2).ToString();
                _maxString     = ((int)avgMinMax.Item3).ToString();

                OnPropertyChanged(nameof(Average));
                OnPropertyChanged(nameof(Min));
                OnPropertyChanged(nameof(Max));

                int rolls    = 0;
                int maxRolls = _expressionString.ToLower().Contains("d") ? 10 : 1;
                while (rolls++ < maxRolls)
                {
                    (double, string)mainDiceResult = _diceService.EvaluateExpression(_expressionString);
                    _result = (int)mainDiceResult.Item1;
                    _resultExpressionString = mainDiceResult.Item2;

                    if (_result > 0)
                    {
                        _halfString = ((int)Math.Max(1, ((int)(_result / 2)))).ToString();
                    }
                    else
                    {
                        _halfString = "0";
                    }

                    OnPropertyChanged(nameof(Result));
                    OnPropertyChanged(nameof(ResultExpression));
                    OnPropertyChanged(nameof(Half));
                    Thread.Sleep(100);
                }
            }
        }
        private void InitializeFromMonsterModel()
        {
            if (_monsterModel != null)
            {
                Name = _monsterModel.Name;

                string hpString = _monsterModel.HP;
                if (hpString.Contains(" "))
                {
                    hpString = hpString.Split(new char[] { ' ' })[0];
                }
                int hp = 0;
                if (int.TryParse(hpString, out hp))
                {
                    MaxHP = hp;
                }

                PassivePerception = _monsterModel.PassivePerception;

                string acString = _monsterModel.AC;
                if (acString.Contains(" "))
                {
                    acString = acString.Split(new char[] { ' ' })[0];
                }
                int ac = 0;
                if (int.TryParse(acString, out ac))
                {
                    AC = ac;
                }

                InitiativeBonus = _statService.GetStatBonus(_monsterModel.Dexterity);

                _cr = _monsterModel.CR;

                List <MonsterAttackModel> attacks = new List <MonsterAttackModel>();
                foreach (MonsterActionModel monsterActionModel in _monsterModel.Actions)
                {
                    foreach (MonsterAttackModel monsterAttack in monsterActionModel.Attacks)
                    {
                        attacks.Add(monsterAttack);
                    }
                }

                int numberOfAttacks = 1;
                List <KeyValuePair <MonsterAttackModel, int> > multiattacks = new List <KeyValuePair <MonsterAttackModel, int> >();
                foreach (MonsterActionModel monsterActionModel in _monsterModel.Actions)
                {
                    if (monsterActionModel.Name.ToLower().Contains("multiattack") ||
                        monsterActionModel.Name.ToLower().Contains("multi-attack"))
                    {
                        string multiattackText = String.Join(" ", monsterActionModel.TextCollection).ToLower();
                        int    attacksIndex    = multiattackText.IndexOf("attacks");
                        if (attacksIndex != -1)
                        {
                            string upToAttacks = multiattackText.Substring(0, attacksIndex);
                            foreach (string word in upToAttacks.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Reverse())
                            {
                                if (word == "one")
                                {
                                    numberOfAttacks = 1;
                                    break;
                                }
                                else if (word == "two")
                                {
                                    numberOfAttacks = 2;
                                    break;
                                }
                                else if (word == "three")
                                {
                                    numberOfAttacks = 3;
                                    break;
                                }
                                else if (word == "four")
                                {
                                    numberOfAttacks = 4;
                                    break;
                                }
                                else if (word == "five")
                                {
                                    numberOfAttacks = 5;
                                    break;
                                }
                            }
                        }

                        foreach (MonsterAttackModel monsterAttackModel in attacks)
                        {
                            int nameIndex = multiattackText.IndexOf(monsterAttackModel.Name.ToLower());
                            if (nameIndex != -1)
                            {
                                string upToAttackName = multiattackText.Substring(0, nameIndex);
                                foreach (string word in upToAttackName.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Reverse())
                                {
                                    if (word == "one")
                                    {
                                        multiattacks.Add(new KeyValuePair <MonsterAttackModel, int>(monsterAttackModel, 1));
                                        break;
                                    }
                                    else if (word == "two")
                                    {
                                        multiattacks.Add(new KeyValuePair <MonsterAttackModel, int>(monsterAttackModel, 2));
                                        break;
                                    }
                                    else if (word == "three")
                                    {
                                        multiattacks.Add(new KeyValuePair <MonsterAttackModel, int>(monsterAttackModel, 3));
                                        break;
                                    }
                                    else if (word == "four")
                                    {
                                        multiattacks.Add(new KeyValuePair <MonsterAttackModel, int>(monsterAttackModel, 4));
                                        break;
                                    }
                                    else if (word == "five")
                                    {
                                        multiattacks.Add(new KeyValuePair <MonsterAttackModel, int>(monsterAttackModel, 5));
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }

                int averageMultiAttackDamage = 0;
                foreach (KeyValuePair <MonsterAttackModel, int> multiAttackPair in multiattacks)
                {
                    if (attacks.Contains(multiAttackPair.Key))
                    {
                        attacks.Remove(multiAttackPair.Key);
                    }

                    if (!String.IsNullOrEmpty(multiAttackPair.Key.Roll))
                    {
                        (double, double, double)avgMinMax = _diceService.EvaluateExpressionAvgMinMax(multiAttackPair.Key.Roll);
                        averageMultiAttackDamage         += (int)avgMinMax.Item1 * multiAttackPair.Value;
                    }
                }

                int averageSingleAttackDamage      = 0;
                int totalAverageSingleAttackDamage = 0;
                int attacksWithRolls = 0;
                foreach (MonsterAttackModel monsterAttackModel in attacks)
                {
                    if (!String.IsNullOrEmpty(monsterAttackModel.Roll))
                    {
                        (double, double, double)avgMinMax = _diceService.EvaluateExpressionAvgMinMax(monsterAttackModel.Roll);
                        totalAverageSingleAttackDamage   += (int)avgMinMax.Item1;
                        attacksWithRolls++;
                    }
                }
                if (attacksWithRolls > 0)
                {
                    averageSingleAttackDamage = totalAverageSingleAttackDamage / attacksWithRolls;
                }

                int averageSpellDamage      = 0;
                int totalAverageSpellDamage = 0;
                int spellsWithRolls         = 0;
                foreach (string spellName in _monsterModel.Spells)
                {
                    SpellModel spellModel = _compendium.Spells.FirstOrDefault(x => x.Name.ToLower() == spellName.ToLower());
                    if (spellModel != null && spellModel.Rolls.Any())
                    {
                        int maxRoll = 0;
                        foreach (string roll in spellModel.Rolls)
                        {
                            (double, double, double)avgMinMax = _diceService.EvaluateExpressionAvgMinMax(roll);
                            maxRoll = Math.Max((int)avgMinMax.Item1, maxRoll);
                        }
                        totalAverageSpellDamage += maxRoll;
                        spellsWithRolls++;
                    }
                }
                if (spellsWithRolls > 0)
                {
                    averageSpellDamage = totalAverageSpellDamage / spellsWithRolls;
                }

                _averageDamageTurn = Math.Max(Math.Max(averageMultiAttackDamage, averageSingleAttackDamage), averageSpellDamage);

                _damageVulnerabilities = _stringService.CapitalizeWords(_monsterModel.Vulnerabilities);

                _damageResistances = _stringService.CapitalizeWords(_monsterModel.Resistances);

                _damageImmunities = _stringService.CapitalizeWords(_monsterModel.Immunities);

                _conditionImmunities = _stringService.CapitalizeWords(_monsterModel.ConditionImmunities);
            }
            else
            {
                Name = String.Empty;
                PassivePerception  = 0;
                InitiativeBonus    = 0;
                _averageDamageTurn = 0;
                _quantity          = 1;
                _cr = String.Empty;
                _damageVulnerabilities = String.Empty;
                _damageResistances     = String.Empty;
                _damageImmunities      = String.Empty;
                _conditionImmunities   = String.Empty;
            }
        }