private IObservable <FeaturePlanViewModel> AddFeatureImpl()
        {
            var featureVm = new FeaturePlanViewModel();

            NewFeatures.Add(featureVm);

            return(Observable.Return(featureVm));
        }
        private void SetFromPlan(CharacterPlan plan)
        {
            EnsureTwentyLevels(plan);

            CharacterName = plan.Name;
            Alignment     = plan.Alignment;

            Race  = plan.Race;
            Speed = plan.Speed;

            Age          = plan.Age;
            HeightFeet   = plan.HeightFeet;
            HeightInches = plan.HeightInches;
            Weight       = plan.Weight;
            EyeColor     = plan.EyeColor;
            HairColor    = plan.HairColor;
            SkinColor    = plan.SkinColor;

            CharacterBackground = plan.Background;

            ClassPlan.ClassName = plan.ClassPlan.ClassName;

            ClassPlan.ArmorProficiencies  = string.Join(", ", plan.ClassPlan.ArmorProficiencies ?? new string[0]);
            ClassPlan.WeaponProficiencies = string.Join(", ", plan.ClassPlan.WeaponProficiencies ?? new string[0]);
            ClassPlan.ToolProficiencies   = string.Join(", ", plan.ClassPlan.ToolProficiencies ?? new string[0]);

            var saveProfs = plan.ClassPlan.SaveProficiencies ?? new string[0];

            foreach (var saveProfVm in ClassPlan.SaveProficiencies)
            {
                saveProfVm.IsProficient = saveProfs.Contains(saveProfVm.Ability.Abbreviation);
            }

            var skillProfs = plan.ClassPlan.SkillProficiencies ?? new string[0];

            foreach (var skillProfVm in ClassPlan.SkillProficiencies)
            {
                skillProfVm.IsProficient = skillProfs.Contains(skillProfVm.Skill.SkillName);
            }

            LevelPlans.Clear();
            foreach (var lp in plan.LevelPlans)
            {
                var levelPlanVm = new LevelPlanViewModel
                {
                    Level = lp.Level
                };
                levelPlanVm.AbilityScoreImprovements.AddRange(
                    Ability.All.Select(a => new AbilityScoreImprovementViewModel
                {
                    Ability = a,
                }));


                foreach (var kvp in lp.AbilityScoreImprovements ?? new Dictionary <string, int>())
                {
                    var asiVm = levelPlanVm.AbilityScoreImprovements.First(asivm => asivm.Ability.Abbreviation == kvp.Key);
                    asiVm.Improvement = kvp.Value;
                }

                foreach (var feature in lp.FeaturePlans ?? new FeaturePlan[0])
                {
                    var featureVm = new FeaturePlanViewModel()
                    {
                        FeatureName = feature.Name,
                        Description = feature.Description,
                    };

                    levelPlanVm.NewFeatures.Add(featureVm);
                }

                LevelPlans.Add(levelPlanVm);
            }

            Armor.Clear();
            foreach (var armor in plan.Armor ?? new Armor[0])
            {
                Armor.Add(new ArmorViewModel()
                {
                    ArmorName                = armor.Name,
                    ArmorClass               = armor.ArmorClass,
                    ProficiencyGroup         = armor.ProficiencyGroup,
                    MaximumDexterityModifier = armor.MaximumDexterityModifier
                });
            }

            Weapons.Clear();
            foreach (var weapon in plan.Weapons ?? new Weapon[0])
            {
                Weapons.Add(new WeaponViewModel
                {
                    Name             = weapon.Name,
                    ProficiencyGroup = weapon.ProficiencyGroup,
                    DamageDice       = weapon.DamageDice,
                    DamageType       = weapon.DamageType,

                    NormalRange  = weapon.NormalRange,
                    MaximumRange = weapon.MaximumRange,

                    HasAmmunition = weapon.HasAmmunition,
                    IsLight       = weapon.IsLight
                });
            }

            // Set snapshot level last so that the SnapshotMarkdown property is
            // set correctly. Otherwise it will try to render at a level that
            // isn't in the list yet.
            SnapshotLevel = plan.SnapshotLevel;
        }