Esempio n. 1
0
        public void UpdateMetrics(ISolverData solverData = null)
        {
            if (solverData == null)
            {
                solverData = GetSelectedSolverData();
            }

            var metrics = new SearchMetrics
            {
                Heads  = solverData.AllHeads.Count(x => x.IsSelected),
                Chests = solverData.AllChests.Count(x => x.IsSelected),
                Gloves = solverData.AllGloves.Count(x => x.IsSelected),
                Waists = solverData.AllWaists.Count(x => x.IsSelected),
                Legs   = solverData.AllLegs.Count(x => x.IsSelected),
                Charms = solverData.AllCharms.Count(x => x.IsSelected),
            };

            if (solverData.AllJewels.Length > 0)
            {
                metrics.MinSlotSize = solverData.AllJewels.Min(x => x.Jewel.SlotSize);
                metrics.MaxSlotSize = solverData.AllJewels.Max(x => x.Jewel.SlotSize);
            }
            else
            {
                metrics.MinSlotSize = 0;
                metrics.MaxSlotSize = 0;
            }

            metrics.UpdateCombinationCount();

            SearchMetrics = metrics;
        }
Esempio n. 2
0
        public void CreateSolverData()
        {
            if (SearchResultsViewModel.IsDataLoaded == false || SelectedAbilities == null)
            {
                return;
            }

            ISolverData solverData = GetSelectedSolverData();

            var desiredAbilities = SelectedAbilities
                                   .Where(x => x.IsChecked)
                                   .Select(x => x.Ability)
                                   .ToList();

            int[] weaponSlots      = InParameters.Slots.Select(x => x.Value).ToArray();
            var   solverDataWeapon = new Weapon(-1, (WeaponType)(-1), weaponSlots, new IAbility[0], null);

            solverData.Setup(
                solverDataWeapon,
                GlobalData.Instance.Heads.Where(x => ArmorPieceMatchInParameters(x)),
                GlobalData.Instance.Chests.Where(x => ArmorPieceMatchInParameters(x)),
                GlobalData.Instance.Gloves.Where(x => ArmorPieceMatchInParameters(x)),
                GlobalData.Instance.Waists.Where(x => ArmorPieceMatchInParameters(x)),
                GlobalData.Instance.Legs.Where(x => ArmorPieceMatchInParameters(x)),
                GlobalData.Instance.Charms.Where(x => EquipmentMatchInParameters(x)),
                GlobalData.Instance.Jewels.Where(x => DecorationMatchInParameters(x)).Select(CreateSolverDataJewelModel),
                desiredAbilities
                );

            UpdateMetrics(solverData);

            UpdateAdvancedSearch();

            SearchResultsViewModel.ResetResults();
        }
Esempio n. 3
0
        public async Task <IList <ArmorSetSearchResult> > SearchArmorSets(ISolverData solverData, CancellationToken cancellationToken)
        {
            var innerCancellation = new CancellationTokenSource();

            Task updateTask = UpdateSearchProgression(innerCancellation.Token, cancellationToken);

            IList <ArmorSetSearchResult> result = await Task.Factory.StartNew(() =>
            {
                return(SearchArmorSetsInternal(
                           solverData,
                           cancellationToken
                           ));
            }, TaskCreationOptions.LongRunning).Unwrap();

            innerCancellation.Cancel();

            await updateTask;

            if (cancellationToken.IsCancellationRequested == false)
            {
                SearchProgress?.Invoke(1.0);
            }

            return(result);
        }
Esempio n. 4
0
        public ArmorSetViewModel(RootViewModel root, ISolverData solverData, IList <IArmorPiece> armorPieces, ICharmLevel charm, IEnumerable <ArmorSetJewelViewModel> jewels, int[] spareSlots)
        {
            this.root = root;

            if (armorPieces.Count(x => x == null) > 0)
            {
            }

            if (charm == null)
            {
            }

            this.armorPieces = armorPieces;
            this.charm       = charm;
            this.jewels      = jewels.OrderBy(x => x.Jewel.Id).ToList();

            DesiredAbilities = solverData.DesiredAbilities;

            SpareSlots = spareSlots;

            TotalRarity = armorPieces.Sum(x => x.Rarity);

            SpareSlotCount = SpareSlots.Count(x => x > 0);

            TotalBaseDefense      = armorPieces.Sum(x => x?.Defense.Base ?? 0);
            TotalMaxDefense       = armorPieces.Sum(x => x?.Defense.Max ?? 0);
            TotalAugmentedDefense = armorPieces.Sum(x => x?.Defense.Augmented ?? 0);

            TotalFireResistance    = armorPieces.Sum(a => a.Resistances.Fire);
            TotalWaterResistance   = armorPieces.Sum(a => a.Resistances.Water);
            TotalThunderResistance = armorPieces.Sum(a => a.Resistances.Thunder);
            TotalIceResistance     = armorPieces.Sum(a => a.Resistances.Ice);
            TotalDragonResistance  = armorPieces.Sum(a => a.Resistances.Dragon);
        }
Esempio n. 5
0
        private void EvaluateArmorSet(IEquipment[] equips, ISolverData data, List <ArmorSetSearchResult> results)
        {
            if (SolverUtils.IsAnyFullArmorSet(equips))
            {
                if (DataUtility.AreOnSameFullArmorSet(equips) == false)
                {
                    searchEquipmentsObjectPool.PutObject(equips);
                    return;
                }
            }

            ArmorSetSearchResult searchResult = IsArmorSetMatching(data.Weapon, equips);

            Interlocked.Increment(ref currentCombinations);

            if (searchResult.IsMatch)
            {
                searchResult.ArmorPieces = new IArmorPiece[]
                {
                    (IArmorPiece)equips[0],
                    (IArmorPiece)equips[1],
                    (IArmorPiece)equips[2],
                    (IArmorPiece)equips[3],
                    (IArmorPiece)equips[4],
                };
                searchResult.Charm = (ICharmLevel)equips[5];

                lock (results)
                    results.Add(searchResult);
            }

            searchEquipmentsObjectPool.PutObject(equips);
        }
        private async Task SearchArmorSetsInternal(CancellationToken cancellationToken)
        {
            ISolverData solverData = root.GetSelectedSolverData();

            if (solverData == null)
            {
                return;
            }

            var sw = Stopwatch.StartNew();

            IList <ArmorSetSearchResult> result = await root.GetSelectedSolver().SearchArmorSets(solverData, cancellationToken);

            sw.Stop();

            SearchMetrics metrics = root.SearchMetrics;

            metrics.TimeElapsed     = (int)sw.ElapsedMilliseconds;
            metrics.MatchingResults = result?.Count ?? 0;

            await Dispatcher.Yield(DispatcherPriority.SystemIdle);

            root.SearchMetrics = null;
            root.SearchMetrics = metrics;

            IsDataLoading = true;
            IsDataLoaded  = false;

            await Dispatcher.Yield(DispatcherPriority.SystemIdle);

            try
            {
                if (solverData == null)
                {
                    rawFoundArmorSets = null;
                    return;
                }

                if (result != null)
                {
                    rawFoundArmorSets = result.Where(x => x.IsMatch).Select(x => new ArmorSetViewModel(
                                                                                root,
                                                                                solverData,
                                                                                x.ArmorPieces,
                                                                                x.Charm,
                                                                                x.Jewels.Select(j => new ArmorSetJewelViewModel(j.Jewel, j.Count)),
                                                                                x.SpareSlots
                                                                                ));

                    ApplySorting(true);
                }
            }
            finally
            {
                IsDataLoading = false;
                IsDataLoaded  = true;
            }
        }
        public void CreateSolverData()
        {
            if (IsDataLoaded == false || SelectedAbilities == null)
            {
                return;
            }

            ISolverData solverData = Extensions.SolverData.SelectedValue;

            var desiredAbilities = SelectedAbilities
                                   .Where(x => x.IsChecked)
                                   .Select(x => x.Ability)
                                   .ToList();

            solverData.Setup(
                InParameters.Slots.Select(x => x.Value).ToList(),
                GlobalData.Instance.Heads.Where(x => ArmorPieceMatchInParameters(x)),
                GlobalData.Instance.Chests.Where(x => ArmorPieceMatchInParameters(x)),
                GlobalData.Instance.Gloves.Where(x => ArmorPieceMatchInParameters(x)),
                GlobalData.Instance.Waists.Where(x => ArmorPieceMatchInParameters(x)),
                GlobalData.Instance.Legs.Where(x => ArmorPieceMatchInParameters(x)),
                GlobalData.Instance.Charms.Where(x => EquipmentMatchInParameters(x)),
                GlobalData.Instance.Jewels.Where(x => DecorationMatchInParameters(x)).Select(CreateSolverDataJewelModel),
                desiredAbilities
                );

            /*************************************************************/
            var metrics = new SearchMetrics
            {
                Heads  = solverData.AllHeads.Count(x => x.IsSelected),
                Chests = solverData.AllChests.Count(x => x.IsSelected),
                Gloves = solverData.AllGloves.Count(x => x.IsSelected),
                Waists = solverData.AllWaists.Count(x => x.IsSelected),
                Legs   = solverData.AllLegs.Count(x => x.IsSelected),
                Charms = solverData.AllCharms.Count(x => x.IsSelected),
            };

            if (solverData.AllJewels.Length > 0)
            {
                metrics.MinSlotSize = solverData.AllJewels.Min(x => x.Jewel.SlotSize);
                metrics.MaxSlotSize = solverData.AllJewels.Max(x => x.Jewel.SlotSize);
            }
            else
            {
                metrics.MinSlotSize = 0;
                metrics.MaxSlotSize = 0;
            }

            metrics.UpdateCombinationCount();

            SearchMetrics = metrics;
            /*************************************************************/

            UpdateAdvancedSearch();

            rawFoundArmorSets = null;
        }
Esempio n. 8
0
        public Task <IList <ArmorSetSearchResult> > SearchArmorSets(ISolverData solverData, CancellationToken cancellationToken)
        {
            UpdateSearchProgression(cancellationToken);

            return(Task.Factory.StartNew(() =>
            {
                return SearchArmorSetsInternal(
                    solverData,
                    cancellationToken
                    );
            }, TaskCreationOptions.LongRunning).Unwrap());
        }
Esempio n. 9
0
        private void OnSolverDataChanged(ISolverData oldValue, ISolverData newValue)
        {
            root.CreateSolverData();

            GlobalData.Instance.Configuration.Extensions.SolverData = newValue.Name;
            ConfigurationManager.Save(GlobalData.Instance.Configuration);

            if (oldValue is IDisposable disposable)
            {
                disposable.Dispose();
            }
        }
Esempio n. 10
0
        public void UpdateAdvancedSearch()
        {
            ISolverData solverData = Extensions.SolverData.SelectedValue;

            var armorPieceTypesViewModels = new ArmorPieceTypesViewModel[]
            {
                new ArmorPieceTypesViewModel(EquipmentType.Head, solverData.AllHeads),
                new ArmorPieceTypesViewModel(EquipmentType.Chest, solverData.AllChests),
                new ArmorPieceTypesViewModel(EquipmentType.Gloves, solverData.AllGloves),
                new ArmorPieceTypesViewModel(EquipmentType.Waist, solverData.AllWaists),
                new ArmorPieceTypesViewModel(EquipmentType.Legs, solverData.AllLegs),
                new ArmorPieceTypesViewModel(EquipmentType.Charm, solverData.AllCharms)
            };

            AdvancedSearchViewModel.Update(armorPieceTypesViewModels);
        }
Esempio n. 11
0
            public List <IMSPoint> Run(ISolverData solverdata, double splitterAccuracy, double detalizerAccuracy)
            {
                List <IContour> contours = solverdata.GetContours();

                List <ISegment> segments = new List <ISegment>();

                foreach (var contour in contours)
                {
                    segments.AddRange(contour.GetSegments());
                }

                simplifiedModel = new Splitter().Split(solverdata.GetContours(), splitterAccuracy);
                IMSPointFinder mspointfinder = new MSPointFinder(simplifiedModel, splitterAccuracy);

                IDetailizer detailizer = new Detailizer(mspointfinder, simplifiedModel, segments, detalizerAccuracy);

                return(detailizer.Detalize());
            }
Esempio n. 12
0
        private async Task SearchArmorSetsInternal(CancellationToken cancellationToken)
        {
            ISolverData solverData = Extensions.SolverData.SelectedValue;

            if (solverData == null)
            {
                return;
            }

            var sw = Stopwatch.StartNew();

            IList <ArmorSetSearchResult> result = await Extensions.Solver.SelectedValue.SearchArmorSets(solverData, cancellationToken);

            sw.Stop();

            SearchMetrics metrics = SearchMetrics;

            metrics.TimeElapsed     = (int)sw.ElapsedMilliseconds;
            metrics.MatchingResults = result?.Count ?? 0;

            SearchMetrics = null;
            SearchMetrics = metrics;

            if (solverData == null)
            {
                rawFoundArmorSets = null;
                return;
            }

            if (result != null)
            {
                rawFoundArmorSets = result.Where(x => x.IsMatch).Select(x => new ArmorSetViewModel(
                                                                            this,
                                                                            solverData,
                                                                            x.ArmorPieces,
                                                                            x.Charm,
                                                                            x.Jewels.Select(j => new ArmorSetJewelViewModel(j.Jewel, j.Count)).ToList(),
                                                                            x.SpareSlots
                                                                            ));

                ApplySorting(true);
            }
        }
Esempio n. 13
0
        public IMidSurface Run(ISolverData solverdata)
        {
            IMidSurface midsurface = new MidSurface();

            maxLengthModel = FindMaxLength(solverdata.GetContours(), 0.01);

            BaseAlgorithm   baseAlgorithm = new BaseAlgorithm();
            List <IMSPoint> msPoints      = baseAlgorithm.Run(solverdata, splitterAccuracy * maxLengthModel,
                                                              detalizerAccuracy * maxLengthModel);

            //Graph msGraph = ConstructGraph(msPoints);
            //msGraph.RemoveCycles(maxCycleSize);

            //List<Point> points = msGraph.GetPath();

            ////Точки для работы
            //List<IMSPoint> new_mspoints = ConvertPointToMSPoint(points, msPoints);

            IJoinMSPoints jointpoints = new JoinMSPoints();

            return(jointpoints.Join(msPoints));
        }
Esempio n. 14
0
 public Task <IList <ArmorSetSearchResult> > SearchArmorSets(ISolverData solverData, CancellationToken cancellationToken)
 {
     return(Task.FromResult <IList <ArmorSetSearchResult> >(new ArmorSetSearchResult[0]));
 }
Esempio n. 15
0
        private async Task <IList <ArmorSetSearchResult> > SearchArmorSetsInternal(
            ISolverData data,
            CancellationToken cancellationToken
            )
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(null);
            }

            var allCharms = new List <ICharmLevel>();

            if (cancellationToken.IsCancellationRequested)
            {
                return(null);
            }

            var heads  = new List <IArmorPiece>();
            var chests = new List <IArmorPiece>();
            var gloves = new List <IArmorPiece>();
            var waists = new List <IArmorPiece>();
            var legs   = new List <IArmorPiece>();

            var test = new List <ArmorSetSearchResult>();

            var generator = new EquipmentCombinationGenerator(
                searchEquipmentsObjectPool,
                data.AllHeads.Where(x => x.IsSelected).Select(x => x.Equipment),
                data.AllChests.Where(x => x.IsSelected).Select(x => x.Equipment),
                data.AllGloves.Where(x => x.IsSelected).Select(x => x.Equipment),
                data.AllWaists.Where(x => x.IsSelected).Select(x => x.Equipment),
                data.AllLegs.Where(x => x.IsSelected).Select(x => x.Equipment),
                data.AllCharms.Where(x => x.IsSelected).Select(x => x.Equipment)
                );

            var sb = new StringBuilder();

            long hh = data.AllHeads.Count(x => x.IsSelected);
            long cc = data.AllChests.Count(x => x.IsSelected);
            long gg = data.AllGloves.Count(x => x.IsSelected);
            long ww = data.AllWaists.Count(x => x.IsSelected);
            long ll = data.AllLegs.Count(x => x.IsSelected);
            long ch = data.AllCharms.Count(x => x.IsSelected);

            long combinationCount =
                Math.Max(hh, 1) *
                Math.Max(cc, 1) *
                Math.Max(gg, 1) *
                Math.Max(ww, 1) *
                Math.Max(ll, 1) *
                Math.Max(ch, 1);

            await Task.Yield();

            var parallelOptions = new ParallelOptions
            {
                //MaxDegreeOfParallelism = 1, // to ease debugging
                MaxDegreeOfParallelism = Environment.ProcessorCount
            };

            currentCombinations = 0;
            totalCombinations   = combinationCount;

            ParallelLoopResult parallelResult;

            try
            {
                OrderablePartitioner <IEquipment[]> partitioner = Partitioner.Create(generator.All(cancellationToken), EnumerablePartitionerOptions.NoBuffering);

                parallelResult = Parallel.ForEach(partitioner, parallelOptions, equips =>
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        searchEquipmentsObjectPool.PutObject(equips);
                        return;
                    }

                    ArmorSetSearchResult searchResult = IsArmorSetMatching(data.WeaponSlots, equips, data.AllJewels, data.DesiredAbilities);

                    Interlocked.Increment(ref currentCombinations);

                    if (searchResult.IsMatch)
                    {
                        searchResult.ArmorPieces = new IArmorPiece[]
                        {
                            (IArmorPiece)equips[0],
                            (IArmorPiece)equips[1],
                            (IArmorPiece)equips[2],
                            (IArmorPiece)equips[3],
                            (IArmorPiece)equips[4],
                        };
                        searchResult.Charm = (ICharmLevel)equips[5];

                        lock (test)
                        {
                            test.Add(searchResult);
                        }
                    }

                    searchEquipmentsObjectPool.PutObject(equips);
                });
            }
            finally
            {
                generator.Reset();
            }

            return(test);
        }
 public CustomSolverData(ISolverData solverdata, List <bool> removed)
 {
     this.solverdata = solverdata;
     this.removed    = removed;
 }
Esempio n. 17
0
 public IMidSurface FindSurface(ISolverData solverdata)
 {
     return(algorithm.Run(solverdata));
 }
        public IMidSurface Run(ISolverData solverdata)
        {
            List <ICustomLine> simplifiedModel;
            IMidSurface        midsurface = new MidSurface();
            List <IContour>    contours   = solverdata.GetContours();

            List <ISegment> segments = new List <ISegment>();

            foreach (var contour in contours)
            {
                segments.AddRange(contour.GetSegments());
            }

            double X_Min = segments[0].GetCurvePoint(0).X, X_Max = segments[0].GetCurvePoint(0).X, Y_Min = segments[0].GetCurvePoint(0).Y, Y_Max = segments[0].GetCurvePoint(0).Y;

            foreach (var seg in segments)
            {
                for (double t = 0d; t <= 1; t += 0.1)
                {
                    if (X_Min >= seg.GetCurvePoint(t).X)
                    {
                        X_Min = seg.GetCurvePoint(t).X;
                    }
                    if (Y_Min >= seg.GetCurvePoint(t).Y)
                    {
                        Y_Min = seg.GetCurvePoint(t).Y;
                    }
                    if (X_Max <= seg.GetCurvePoint(t).X)
                    {
                        X_Max = seg.GetCurvePoint(t).X;
                    }
                    if (Y_Max <= seg.GetCurvePoint(t).Y)
                    {
                        Y_Max = seg.GetCurvePoint(t).Y;
                    }
                }
            }

            simplifiedModel = new Splitter().Split(solverdata.GetContours(), splitterAccuracy);

            List <Point> mspoints = new List <Point>();
            Point        prev     = new Point();

            for (double d = X_Min + detalizerAccuracy / 10; d <= X_Max - detalizerAccuracy / 10; d += detalizerAccuracy)
            {
                List <Point> points = GetIntersectionPoints(simplifiedModel, new Point(d, Y_Min - detalizerAccuracy), new Point(d, Y_Max + detalizerAccuracy));

                points.Sort(new ForY());
                Point center;
                int   index = 0;
                if (points.Count == 0)
                {
                    continue;
                }
                else if (points.Count == 2)
                {
                    //// midsurface.Add(new Segment(new BezierCurve(), new List<Point> { points[0], points[1] })); //DEBUG
                    index  = 0;
                    center = new Point(d, (points[index].Y + points[index + 1].Y) / 2);
                }
                //TODO: Dinar: avoid paths with intersections

                //else if (points.Count % 2 == 0)
                //{
                //    //midsurface.Add(new Segment(new BezierCurve(), new List<Point> { points[0], points[1] })); //DEBUG
                //    double MinDistance = Math.Max(X_Max - X_Min, Y_Max - Y_Min);

                //    for (int k = 0; k < points.Count - 1; k += 2)
                //    {

                //        List<Point> not_allowed = GetIntersectionPoints(simplifiedModel, prev, new Point(d, (points[k + 1].Y + points[k].Y) / 2));
                //        if (not_allowed.Count > 0) { continue; }
                //        if (Distance(prev, points[k], points[k + 1]) < MinDistance)
                //        {

                //            MinDistance = Distance(prev, points[k], points[k + 1]);
                //            index = k;
                //        }
                //    }

                //    center = new Point(d, (points[index + 1].Y + points[index].Y) / 2);
                //}
                //else if (points.Count > 0) { center = points[0]; }
                else
                {
                    continue;
                }

                ////TODO: Dinar: shift center for maximize R
                //int step_line =5;
                //double diff = Math.Abs(points[index+1].Y - points[index].Y) / (double)(step_line + 1);
                //double prevR = Math.Abs(points[index + 1].Y - points[index].Y);
                //while (step_line-- >= -1)
                //{
                //    double R = Math.Abs(points[index + 1].Y - points[index].Y);
                //    int step = 5;
                //    while (step-- > -1)
                //    {
                //        if (GetIntersecCount(simplifiedModel, center, R) > 0)
                //            R = R * 0.5;
                //        else
                //            R = R * 1.5;
                //    }
                //    if (Math.Abs(prevR - R) < 0.1)
                //    {
                //        int p1 = GetIntersecCount(simplifiedModel, new Point(d, Math.Abs(points[index + 1].Y - points[index].Y) / 5 + points[index].Y), R);
                //        int p2= GetIntersecCount(simplifiedModel, new Point(d, 4 * Math.Abs(points[index + 1].Y - points[index].Y) / 5 + points[index].Y), R);
                //        if (p1==p2) { step_line = -1; }
                //        else if (p1>p2)
                //            center.Y = 4 * Math.Abs(points[index + 1].Y - points[index].Y) / 5 + points[index].Y;

                //        else center.Y = Math.Abs(points[index + 1].Y - points[index].Y) / 5 + points[index].Y;
                //    }
                //    else
                //    if (prevR > R)
                //    {
                //        diff = -diff;
                //        center.Y += diff;
                //    }
                //    else center.Y += diff;
                //    prevR = R;
                //}
                prev = center;
                mspoints.Add(center);
            }

            for (int i = 0; i < mspoints.Count - 1; ++i)
            {
                midsurface.Add(new Segment(new BezierCurve(), new List <Point> {
                    mspoints[i], mspoints[i + 1]
                }));
            }

            return(midsurface);
        }
Esempio n. 19
0
        private async Task <IList <ArmorSetSearchResult> > SearchArmorSetsInternal(
            ISolverData data,
            CancellationToken cancellationToken
            )
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(null);
            }

            var heads     = new List <IArmorPiece>();
            var chests    = new List <IArmorPiece>();
            var gloves    = new List <IArmorPiece>();
            var waists    = new List <IArmorPiece>();
            var legs      = new List <IArmorPiece>();
            var allCharms = new List <ICharmLevel>();

            var results = new List <ArmorSetSearchResult>();

            var generator = new EquipmentCombinationGenerator(
                searchEquipmentsObjectPool,
                data.AllHeads.Where(x => x.IsSelected).Select(x => x.Equipment),
                data.AllChests.Where(x => x.IsSelected).Select(x => x.Equipment),
                data.AllGloves.Where(x => x.IsSelected).Select(x => x.Equipment),
                data.AllWaists.Where(x => x.IsSelected).Select(x => x.Equipment),
                data.AllLegs.Where(x => x.IsSelected).Select(x => x.Equipment),
                data.AllCharms.Where(x => x.IsSelected).Select(x => x.Equipment)
                );

            long hh = data.AllHeads.Count(x => x.IsSelected);
            long cc = data.AllChests.Count(x => x.IsSelected);
            long gg = data.AllGloves.Count(x => x.IsSelected);
            long ww = data.AllWaists.Count(x => x.IsSelected);
            long ll = data.AllLegs.Count(x => x.IsSelected);
            long ch = data.AllCharms.Count(x => x.IsSelected);

            long combinationCount =
                Math.Max(hh, 1) *
                Math.Max(cc, 1) *
                Math.Max(gg, 1) *
                Math.Max(ww, 1) *
                Math.Max(ll, 1) *
                Math.Max(ch, 1);

            await Task.Yield();

            var parallelOptions = new ParallelOptions
            {
                //MaxDegreeOfParallelism = 1, // to ease debugging
                MaxDegreeOfParallelism = Environment.ProcessorCount
            };

            currentCombinations = 0;
            totalCombinations   = combinationCount;

            ParallelLoopResult parallelResult;

            try
            {
                const int batchSize = 4096;

                using (var equipmentBatchObjectPool = new ObjectPool <EquipmentBatch>(() => EquipmentBatch.Create(batchSize)))
                {
                    OrderablePartitioner <EquipmentBatch> partitioner = Partitioner.Create(generator.AllBatch(equipmentBatchObjectPool, cancellationToken), EnumerablePartitionerOptions.NoBuffering);

                    parallelResult = Parallel.ForEach(partitioner, parallelOptions, equipmentBatch =>
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            equipmentBatchObjectPool.PutObject(equipmentBatch);
                            return;
                        }

                        for (int i = 0; i < equipmentBatch.Size; i++)
                        {
                            EvaluateArmorSet(equipmentBatch.Equipment[i], data, results);
                        }

                        equipmentBatchObjectPool.PutObject(equipmentBatch);
                    });
                }
            }
            finally
            {
                generator.Reset();
            }

            return(results);
        }