Beispiel #1
0
        private static LeaderPipResult DistributePips(double averageBasePips, LeaderPipModifiers leaderPipModifiers)
        {
            double remainingPips = averageBasePips;
            var    result        = new LeaderPipResult();

            while (remainingPips > 10)
            {
                remainingPips -= 4;
                result.Fire++;
                result.Shock++;
                result.Maneuver++;
                result.Siege++;
            }

            result.AddGuaranteedPips(leaderPipModifiers ?? new LeaderPipModifiers());

            // The approximation here is that these percentages don't reflect pip overflow from maxed out categories
            result.Fire     += Math.Round(0.3 * remainingPips, 2);
            result.Shock    += Math.Round(0.3 * remainingPips, 2);
            result.Maneuver += Math.Round(0.3 * remainingPips, 2);
            result.Siege    += Math.Round(0.1 * remainingPips, 2);

            result.Fire     = result.Fire > LeaderConstants.MaxPipsInCategory ? LeaderConstants.MaxPipsInCategory : result.Fire;
            result.Shock    = result.Shock > LeaderConstants.MaxPipsInCategory ? LeaderConstants.MaxPipsInCategory : result.Shock;
            result.Maneuver = result.Maneuver > LeaderConstants.MaxPipsInCategory ? LeaderConstants.MaxPipsInCategory : result.Maneuver;
            result.Siege    = result.Siege > LeaderConstants.MaxPipsInCategory ? LeaderConstants.MaxPipsInCategory : result.Siege;
            return(result);
        }
        public async Task SimulateRulerGeneralPipsAsync(
            [Summary("Army tradition (0-100)")] double tradition,
            [Summary("Ruler military skill (0-6)")] int militarySkill,
            [Summary("Guaranteed pips (0-6 in each category), formatted like 'fire=1,maneuver=2'")] LeaderPipModifiers pipModifiers = null)
        {
            if (!LeaderValidator.IsTraditionValid(tradition, out string traditionError))
            {
                await ReplyAsync($"Argument error: {traditionError}.");

                return;
            }
            if (!LeaderValidator.IsRulerMilitarySkillValid(militarySkill, out string militarySkillError))
            {
                await ReplyAsync($"Argument error: {militarySkillError}.");

                return;
            }

            var leaderPipResult = await Task.Run(() => leaderPipService.CalculateAverageLeaderPipsAsync(
                                                     tradition,
                                                     LeaderType.General,
                                                     new LeaderPipSimulationStrategy(),
                                                     pipModifiers));

            await ReplyAsync($"Average general pips: Fire {leaderPipResult.Fire}, Shock {leaderPipResult.Shock}, Maneuver {leaderPipResult.Maneuver}, Siege {leaderPipResult.Siege}");
        }
Beispiel #3
0
 public static void AddGuaranteedPips(this LeaderPipResult leaderPipResult, LeaderPipModifiers leaderPipModifiers)
 {
     AddGuaranteedPipsSingleCategory(() => leaderPipResult.Fire, x => leaderPipResult.Fire         = x, leaderPipModifiers.BonusFire);
     AddGuaranteedPipsSingleCategory(() => leaderPipResult.Shock, x => leaderPipResult.Shock       = x, leaderPipModifiers.BonusShock);
     AddGuaranteedPipsSingleCategory(() => leaderPipResult.Maneuver, x => leaderPipResult.Maneuver = x, leaderPipModifiers.BonusManeuver);
     AddGuaranteedPipsSingleCategory(() => leaderPipResult.Siege, x => leaderPipResult.Siege       = x, leaderPipModifiers.BonusSiege);
 }
        public Task <LeaderPipResult> CalculateAverageRulerLeaderPipsAsync(
            double tradition,
            int militarySkill,
            ILeaderPipDistributionStrategy leaderPipDistributionStrategy,
            LeaderPipModifiers leaderPipModifiers = null)
        {
            double effectiveTradition = CalculateRulerEffectiveTradition(tradition, militarySkill);

            return(CalculateAndDistributePips(leaderPipDistributionStrategy, leaderPipModifiers, effectiveTradition));
        }
        public Task <LeaderPipResult> CalculateAverageLeaderPipsAsync(
            double tradition,
            LeaderType leaderType,
            ILeaderPipDistributionStrategy leaderPipDistributionStrategy,
            LeaderPipModifiers leaderPipModifiers = null)
        {
            double effectiveTradition = CalculateEffectiveTradition(tradition, leaderType);

            return(CalculateAndDistributePips(leaderPipDistributionStrategy, leaderPipModifiers, effectiveTradition));
        }
Beispiel #6
0
        public override Task <TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services)
        {
            string[] tokens             = input.Split(LeaderConstants.LeaderPipModifiersCommandDelimiter, StringSplitOptions.RemoveEmptyEntries);
            var      leaderPipModifiers = new LeaderPipModifiers();

            foreach (string token in tokens)
            {
                if (!TryParseToken(token, leaderPipModifiers))
                {
                    return(Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, $"Could not parse pip modifier from token {token}.")));
                }
            }

            return(Task.FromResult(TypeReaderResult.FromSuccess(leaderPipModifiers)));
        }
Beispiel #7
0
        public static bool ArePipModifiersValid(LeaderPipModifiers leaderPipRequest, out string message)
        {
            foreach (PropertyInfo propertyInfo in typeof(LeaderPipModifiers).GetProperties())
            {
                int value = (int)propertyInfo.GetValue(leaderPipRequest);
                if (value < 0 || value > 6)
                {
                    message = $"Category {propertyInfo.Name} is out of range: {value}";
                    return(false);
                }
            }

            message = null;
            return(true);
        }
Beispiel #8
0
        private bool TryParseToken(string token, LeaderPipModifiers leaderPipModifiers)
        {
            const string tokenRegex = "(fire|shock|maneuver|siege)=(\\d)";

            Match match = Regex.Match(token, tokenRegex);

            if (!match.Success)
            {
                return(false);
            }
            if (!int.TryParse(match.Groups[2].Value, out int pipAmount))
            {
                return(false);
            }

            switch (match.Groups[1].Value)
            {
            case "fire":
                leaderPipModifiers.BonusFire = pipAmount;
                break;

            case "shock":
                leaderPipModifiers.BonusShock = pipAmount;
                break;

            case "maneuver":
                leaderPipModifiers.BonusManeuver = pipAmount;
                break;

            case "siege":
                leaderPipModifiers.BonusSiege = pipAmount;
                break;

            default:
                return(false);
            }

            return(true);
        }
        private Task <LeaderPipResult> CalculateAndDistributePips(ILeaderPipDistributionStrategy leaderPipDistributionStrategy, LeaderPipModifiers leaderPipModifiers, double effectiveTradition)
        {
            double averagePips = CalculateAveragePips(effectiveTradition);

            return(leaderPipDistributionStrategy.DistributePipsAsync(averagePips, leaderPipModifiers));
        }
Beispiel #10
0
        private static LeaderPipResult DistributePipsSimulation(double averageBasePips, LeaderPipModifiers leaderPipModifiers, Random random)
        {
            double remainingPips = averageBasePips;
            var    result        = new LeaderPipResult();

            while (remainingPips > 10)
            {
                remainingPips -= 4;
                result.Fire++;
                result.Shock++;
                result.Maneuver++;
                result.Siege++;
            }

            result.AddGuaranteedPips(leaderPipModifiers ?? new LeaderPipModifiers());

            while (remainingPips > 0)
            {
                int    which  = random.Next(0, 10);
                double amount = remainingPips >= 1 ? 1 : remainingPips;

                if (which == 0 && result.Siege < LeaderConstants.MaxPipsInCategory)
                {
                    result.Siege  += amount;
                    remainingPips -= amount;
                }
                else if (which < 4 && result.Shock < LeaderConstants.MaxPipsInCategory)
                {
                    result.Shock  += amount;
                    remainingPips -= amount;
                }
                else if (which < 7 && result.Fire < LeaderConstants.MaxPipsInCategory)
                {
                    result.Fire   += amount;
                    remainingPips -= amount;
                }
                else if (result.Maneuver < LeaderConstants.MaxPipsInCategory)
                {
                    result.Maneuver += amount;
                    remainingPips   -= amount;
                }
                // else go back to generating new which
            }

            return(result);
        }
Beispiel #11
0
        private static LeaderPipResult RunSimulation(int iterations, double averageBasePips, LeaderPipModifiers leaderPipModifiers = null)
        {
            var random = new Random(DateTime.UtcNow.Millisecond);
            var result = new LeaderPipResult();

            for (int i = 0; i < iterations; i++)
            {
                LeaderPipResult iterationResult = DistributePipsSimulation(averageBasePips, leaderPipModifiers, random);

                result.Fire     += iterationResult.Fire;
                result.Shock    += iterationResult.Shock;
                result.Maneuver += iterationResult.Maneuver;
                result.Siege    += iterationResult.Siege;
            }

            result.Fire     = Math.Round(result.Fire / iterations, RoundingDigits);
            result.Shock    = Math.Round(result.Shock / iterations, RoundingDigits);
            result.Maneuver = Math.Round(result.Maneuver / iterations, RoundingDigits);
            result.Siege    = Math.Round(result.Siege / iterations, RoundingDigits);

            return(result);
        }
Beispiel #12
0
        public async Task <LeaderPipResult> DistributePipsAsync(double averageBasePips, LeaderPipModifiers leaderPipModifiers = null)
        {
            var slaveTasks = new List <Task <LeaderPipResult> >();

            for (int i = 0; i < DegreeOfParallelism; i++)
            {
                slaveTasks.Add(Task.Run(() => RunSimulation(IterationsPerSlave, averageBasePips, leaderPipModifiers)));
            }

            await Task.WhenAll(slaveTasks);

            var result = new LeaderPipResult();

            foreach (var slaveResult in slaveTasks.Select(s => s.Result))
            {
                result.Fire     += slaveResult.Fire;
                result.Shock    += slaveResult.Shock;
                result.Maneuver += slaveResult.Maneuver;
                result.Siege    += slaveResult.Siege;
            }

            result.Fire     = Math.Round(result.Fire / DegreeOfParallelism, RoundingDigits);
            result.Shock    = Math.Round(result.Shock / DegreeOfParallelism, RoundingDigits);
            result.Maneuver = Math.Round(result.Maneuver / DegreeOfParallelism, RoundingDigits);
            result.Siege    = Math.Round(result.Siege / DegreeOfParallelism, RoundingDigits);

            return(result);
        }
Beispiel #13
0
 public Task <LeaderPipResult> DistributePipsAsync(double averageBasePips, LeaderPipModifiers leaderPipModifiers = null)
 {
     return(Task.Run(() => DistributePips(averageBasePips, leaderPipModifiers)));
 }