public OrderSummary GetCompressedOres(ReprocessingSkills reprocessingSkills, MineralList mineralList)
        {
            var oreGroups = GetOreGroups(reprocessingSkills);
            var minerals  = GetMinerals();

            var optimizedOres = OptimizeOres(minerals, oreGroups, mineralList, reprocessingSkills);

            var finalOres = optimizedOres.Where(o => o.Qty > 0).ToList();

            var currentMinerals = new MineralList();

            foreach (var ore in finalOres)
            {
                foreach (MineralType mineral in Enum.GetValues(typeof(MineralType)))
                {
                    currentMinerals[mineral] += ore.GetMineralQty(mineral, reprocessingSkills.CalculateReprocessingRate(ore.ReprocessingType));
                }
            }

            var generatedMinerals = new List <Mineral>();

            foreach (var mineral in minerals)
            {
                mineral.Qty        = currentMinerals[mineral.MineralType];
                mineral.DesiredQty = mineralList[mineral.MineralType];

                generatedMinerals.Add(mineral);
            }

            return(GetOrderSummary(finalOres, generatedMinerals, mineralList));
        }
        public List <OreGroup> GetOreGroups(ReprocessingSkills reprocessingSkills)
        {
            var oreCategory = _eveDb.invCategories.Single(c => c.categoryName == "Asteroid" && true == c.published);

            var oreGroups = oreCategory.invGroups.Where(g => g.groupName != "Ice" && true == g.published)
                            .Select(g => new OreGroup
            {
                ReprocessingType = (ReprocessingType)
                                   Enum.Parse(typeof(ReprocessingType), g.groupName.Replace(" ", ""), true),
                GroupName = g.groupName,
                Ores      = g.invTypes.Where(t => true == t.published && t.portionSize == 1 && t.marketGroupID > 0)
                            .OrderBy(t => t.basePrice)
                            .Select((t, i) =>
                {
                    var yieldBonus       = i * .05;
                    var reprocessingType =
                        (ReprocessingType)
                        Enum.Parse(typeof(ReprocessingType), g.groupName.Replace(" ", ""), true);
                    return(new OreMinerals
                    {
                        Id = t.typeID,
                        Name = t.typeName,
                        ReprocessingType = reprocessingType,
                        ReprocessingRate = reprocessingSkills.CalculateReprocessingRate(reprocessingType),
                        YieldModifier = yieldBonus,
                        Volume = t.volume,
                        Pricing = GetCurrentItemPricing(t.typeID),
                        ReprocessedMinerals = new MineralList
                        {
                            Tritanium = t[MineralType.Tritanium],
                            Pyerite = t[MineralType.Pyerite],
                            Mexallon = t[MineralType.Mexallon],
                            Isogen = t[MineralType.Isogen],
                            Nocxium = t[MineralType.Nocxium],
                            Zydrine = t[MineralType.Zydrine],
                            Megacyte = t[MineralType.Megacyte],
                            Morphite = t[MineralType.Morphite],
                        }
                    });
                }).ToList()
            });

            return(oreGroups.ToList());
        }
        protected List <OreMinerals> OptimizeOres(List <Mineral> minerals, List <OreGroup> oreGroups, MineralList mineralList, ReprocessingSkills reprocessingSkills)
        {
            foreach (var mineral in minerals.OrderBy(o => o.ReprocessingOrder))
            {
                var mineralType     = mineral.MineralType;
                var primaryOreGroup = oreGroups.Single(o => o.ReprocessingType == mineral.PrimaryOreReprocessingType);

                var desiredMineralQty = mineralList[mineralType];

                foreach (var ore in oreGroups.SelectMany(o => o.Ores).Where(o => o.Qty > 0))
                {
                    desiredMineralQty -= ore.GetMineralQty(mineralType, ore.ReprocessingRate);
                }

                foreach (var order in primaryOreGroup.OptimizedMarketOrders)
                {
                    if (desiredMineralQty <= 0)
                    {
                        break;
                    }

                    var oreMineralYield = order.AssociatedOre.ReprocessedMinerals[mineralType] *
                                          order.AssociatedOre.ReprocessingRate;

                    var desiredOrderQty = Math.Ceiling(Math.Min(order.Volume, desiredMineralQty / oreMineralYield));

                    desiredMineralQty -= desiredOrderQty * oreMineralYield;
                    primaryOreGroup.Ores.Single(o => o.Id == order.AssociatedOre.Id).Qty += desiredOrderQty;
                }
            }

            return(oreGroups.SelectMany(og => og.Ores.Where(o => o.Qty > 0)).ToList());
        }