private async void SkillOffered(object sender, Career.SkillOfferedEventArgs e)
        {
            var skill  = e.OfferedSkill;
            var level  = skill.Level;
            var skills = e.OfferedSkill.ResolveSkill();

            // TODO: Work out why this is needed
            if (skill.Name.Equals("Prole") || skill.Name.Equals("Talent") || skill.Name.Equals("Psi"))
            {
                return;
            }
            await semaphore.WaitAsync();

            try
            {
                if (skills.Count > 1)
                {
                    var names  = skills.Select(s => s.Name).Distinct().OrderBy(s => s);
                    var result = await DisplayActionSheet(string.Format(Properties.Resources.Prompt_Select_Cascade, skill.Name), null, null, names.ToArray());

                    if (!string.IsNullOrEmpty(result))
                    {
                        skill = skills.Where(s => s.Name == result).First();
                    }
                }
                else
                {
                    skill = skills[0];
                }
                if (skill.Class == Skill.SkillClass.AttributeChange)
                {
                    if (GenerationConfiguration.VerboseSkills)
                    {
                        await DisplayAlert(Properties.Resources.Title_App, string.Format(Properties.Resources.Msg_Attribute_Raised, skill.Name, skill.Level), Properties.Resources.Button_OK);
                    }
                    e.Owner.AddAttribute(skill.Name, level);
                }
                else
                {
                    if (GenerationConfiguration.VerboseSkills)
                    {
                        await DisplayAlert(Properties.Resources.Title_App, string.Format(Properties.Resources.Msg_Skill_Received, skill.Name, skill.Level), Properties.Resources.Button_OK);
                    }
                    // Make sure that when resolving a cascade the added skill is
                    // at the level of the top level skill
                    skill.Level = level;
                    e.Owner.AddSkill(skill);
                }
            }
            finally
            {
                semaphore.Release();
            }
        }
        private async Task ResolveBasicCareer(Character character, BasicCareer career)
        {
            var keepGoing = true;

            do
            {
                var survivalResult = career.Survival();
                if (survivalResult == BasicCareer.SurvivalResult.Survived)
                {
                    if (career.Commission())
                    {
                        career.Promotion();
                    }
                }
                else if (survivalResult == BasicCareer.SurvivalResult.Died)
                {
                    character.Died = true;
                    character.Journal.Add(string.Format(Properties.Resources.Jrn_Killed, character.Age));
                    await DisplayAlert(Properties.Resources.Title_App, string.Format(Properties.Resources.Msg_Killed, character.Age), Properties.Resources.Button_OK);

                    keepGoing = false;
                    break;
                }
                else
                {
                    character.Journal.Add(string.Format("Discharged at age {0}", character.Age));
                    await DisplayAlert(Properties.Resources.Title_App, string.Format("Discharged at age {0}", character.Age), Properties.Resources.Button_OK);

                    break;
                }

                for (var i = 0; i < career.TermSkills; i++)
                {
                    career.CheckTableAvailablity();
                    var        tables = new List <string>();
                    SkillTable table  = null;
                    for (var j = 0; j < career.SkillTables.Length; j++)
                    {
                        if (career.SkillTables[j].Available)
                        {
                            tables.Add(career.SkillTables[j].Name);
                            table = career.SkillTables[j];
                        }
                    }

                    if (tables.Count > 1)
                    {
                        var result = string.Empty;
                        await semaphore.WaitAsync();

                        try
                        {
                            result = await DisplayActionSheet(Properties.Resources.Prompt_Select_Skill_Table, null, null, tables.ToArray());
                        }
                        finally
                        {
                            semaphore.Release();
                        }
                        for (var j = 0; j < career.SkillTables.Length; j++)
                        {
                            if (career.SkillTables[j].Available && career.SkillTables[j].Name.Equals(result))
                            {
                                table = career.SkillTables[j];
                                break;
                            }
                        }
                    }

                    Skill offeredSkill;
                    var   count = 0;
                    do
                    {
                        count++;
                        var die  = new Dice(6);
                        var roll = die.roll() - 1 + selectedCulture.TableModifier(character, career, table);
                        roll = roll.Clamp(0, 5);
                        // Because culture rules can modify the skill "on the fly" we work with a clone
                        offeredSkill = table.Skills[roll].Clone();
                    } while (!selectedCulture.CheckSkill(character, offeredSkill, count));

                    var args = new Career.SkillOfferedEventArgs()
                    {
                        OfferedSkill = offeredSkill,
                        Owner        = character
                    };
                    SkillOffered(this, args);
                }

                career.EndTerm();
                if (!character.AgingCheck())
                {
                    character.Died = true;
                    character.Journal.Add(string.Format(Properties.Resources.Jrn_Died, character.Age));
                    await DisplayAlert(Properties.Resources.Title_App, string.Format(Properties.Resources.Msg_Died, character.Age), Properties.Resources.Button_OK);

                    break;
                }

                var reup = career.CanRenlist();
                if (reup == BasicCareer.Renlistment.Must)
                {
                    career.HandleRenlist(true);
                }
                else if (reup == BasicCareer.Renlistment.Can)
                {
                    await semaphore.WaitAsync();

                    var result = false;
                    try
                    {
                        // Ask if they want to renlist
                        result = await DisplayAlert(Properties.Resources.Title_App,
                                                    string.Format(Properties.Resources.Prompt_Renlist, character.Age),
                                                    Properties.Resources.Button_Yes,
                                                    Properties.Resources.Button_No);
                    }
                    finally
                    {
                        semaphore.Release();
                    }
                    if (result)
                    {
                        career.HandleRenlist(true);
                    }
                    else
                    {
                        keepGoing = false;
                        career.HandleRenlist(false);
                    }
                }
                else
                {
                    keepGoing = false;
                    career.HandleRenlist(false);
                }
            } while (keepGoing);

            career.MusterOut();
            var muster = career.MusterOutRolls();

            if (muster > 0)
            {
                var maxCashRolls = career.MaxCashRolls();
                var cashRolls    = muster.Clamp(0, maxCashRolls);
                if (cashRolls > 0)
                {
                    await DisplayAlert(Properties.Resources.Title_App, string.Format(Properties.Resources.Prompt_Benefit_Rolls, muster, cashRolls), Properties.Resources.Button_OK);
                }
                for (var i = 0; i < muster; i++)
                {
                    if (cashRolls > 0)
                    {
                        var result = await DisplayActionSheet(Properties.Resources.Prompt_Select_Benefit_Table,
                                                              null, null, Properties.Resources.Benefit_Cash, Properties.Resources.Benefit_Material);

                        if (result.Equals(Properties.Resources.Benefit_Cash))
                        {
                            cashRolls--;
                            career.ResolveCashBenefit();
                        }
                        else
                        {
                            var picks = career.ResolveMaterialBenefit();
                            if (picks.pick.HasFlag(Career.BenefitPick.Skill) && picks.pick.HasFlag(Career.BenefitPick.Weapon))
                            {
                                // need to decide between skill or weapon
                                var picked = await DisplayAlert(Properties.Resources.Title_App, Properties.Resources.Prompt_Weapon_Skill, Properties.Resources.Button_Yes, Properties.Resources.Button_No);

                                var list  = Benefit.GetWeaponList(picks.benefit);
                                var title = string.Empty;
                                if (picked)
                                {
                                    title = Properties.Resources.Prompt_Select_Skill;
                                }
                                else
                                {
                                    title = Properties.Resources.Prompt_Select_Weapon;
                                }
                                var selected = await DisplayActionSheet(title, null, null, list.ToArray());

                                if (picked)
                                {
                                    character.AddSkill(new Skill()
                                    {
                                        Level = 1, Name = selected
                                    });
                                }
                                else
                                {
                                    character.AddBenefit(new Benefit()
                                    {
                                        Name = selected, TypeOfBenefit = Benefit.BenefitType.Weapon, Value = 1
                                    });
                                }
                            }
                            else if (picks.pick == Career.BenefitPick.Skill)
                            {
                                var list     = Benefit.GetWeaponList(picks.benefit);
                                var selected = await DisplayActionSheet(Properties.Resources.Prompt_Select_Skill, null, null, list.ToArray());

                                character.AddSkill(new Skill()
                                {
                                    Level = 1, Name = selected
                                });
                            }
                            else if (picks.pick == Career.BenefitPick.Weapon)
                            {
                                // select a class of weapon
                                var list     = Benefit.GetWeaponList(picks.benefit);
                                var selected = await DisplayActionSheet(Properties.Resources.Prompt_Select_Weapon, null, null, list.ToArray());

                                character.AddBenefit(new Benefit()
                                {
                                    Name = selected, TypeOfBenefit = Benefit.BenefitType.Weapon, Value = 1
                                });
                            }
                        }
                    }
                    else
                    {
                        career.ResolveMaterialBenefit();
                    }
                }
            }
        }