Пример #1
0
        private CollectionSnapshot convertV2Collection(CollectionSnapshot collection)
        {
            var deck      = Deck.Create(collection.CountById, collection.CountById.Keys.ToList(), null, null, null, null);
            var converted = _deckMigrator.ConvertV2Deck(deck);

            return(new CollectionSnapshot
            {
                CountById = converted.MainDeck.Count
            });
        }
Пример #2
0
        public DeckModel(Deck originalDeck, CardRepository repo, CollectionSnapshot collection, CollectedCardsDeckTransformation transformation)
        {
            int countInMain(Card c) => Deck.MainDeck.Count.TryGet(c.Id);
            int countTotal(Card c, int countInDeck) => countInDeck;
            int countCollected(Card c, int countInDeck) => Math.Min(countInDeck, Collection.GetCount(c));
            int countCollectedSide(Card c, int countInDeck) => (Collection.GetCount(c) - countInMain(c)).WithinRange(0, countInDeck);

            float priceTotal(Card c, int countInDeck) => countInDeck * (c.PriceMid ?? 0f);
            float priceCollected(Card c, int countInDeck) => countCollected(c, countInDeck) * (c.PriceMid ?? 0f);
            float priceCollectedSide(Card c, int countInDeck) => countCollectedSide(c, countInDeck) * (c.PriceMid ?? 0f);

            IList <string> generatedMana(Card c, int countInDeck) => c.GeneratedManaArr;

            float f0() => 0f;
            int i0() => 0;
            float fSum(float a, float b) => a + b;
            int iSum(int a, int b) => a + b;
            float fE(float a) => a;
            int iE(int a) => a;
            Deck deck() => Deck;

            _priceTotalCache =
                new DeckAggregateCache <float, float, float>(repo, deck, f0, fSum, priceTotal, fE);

            _countTotalCache =
                new DeckAggregateCache <int, int, int>(repo, deck, i0, iSum, countTotal, iE);

            _priceCollectedCache =
                new DeckAggregateCache <float, float, float>(repo, deck, f0, fSum, priceCollected, fE);

            _countCollectedCache =
                new DeckAggregateCache <int, int, int>(repo, deck, i0, iSum, countCollected, iE);

            _priceCollectedSideCache =
                new DeckAggregateCache <float, float, float>(repo, deck, f0, fSum, priceCollectedSide, fE);

            _countCollectedSideCache =
                new DeckAggregateCache <int, int, int>(repo, deck, i0, iSum, countCollectedSide, iE);

            _generatedManaCache = new DeckAggregateCache <IList <string>, Dictionary <string, int>, string>(
                repo,
                () => OriginalDeck,
                () => new Dictionary <string, int>(Str.Comparer),
                (a, b) =>
            {
                foreach (string s in b)
                {
                    a.TryGetValue(s, out int count);
                    count++;
                    a[s] = count;
                }

                return(a);
            },
                generatedMana,
                a => string.Concat(a.Keys.OrderBy(s => KeywordDefinitions.GeneratedMana.IndexOf(s, Str.Comparer))));

            _filterNone           = c => true;
            _filterPriceIsUnknown = c => !c.PriceMid.HasValue;

            _filterIsCreature   = c => c.TypesArr.IndexOf("creature", Str.Comparer) >= 0;
            _filterIsLand       = c => c.TypesArr.IndexOf("land", Str.Comparer) >= 0;
            _filterIsOtherSpell = c => !_filterIsCreature(c) && !_filterIsLand(c);

            _filterIsLandAndPriceIsUnknown       = c => _filterIsLand(c) && _filterPriceIsUnknown(c);
            _filterIsCreatureAndPriceIsUnknown   = c => _filterIsCreature(c) && _filterPriceIsUnknown(c);
            _filterIsOtherSpellAndPriceIsUnknown = c => _filterIsOtherSpell(c) && _filterPriceIsUnknown(c);

            Collection      = collection;
            _repo           = repo;
            _transformation = transformation;
            OriginalDeck    = originalDeck;
        }
        public Deck Transform(
            Deck original,
            CollectionSnapshot collection,
            Deck previousTransformed       = null,
            HashSet <string> affectedNames = null)
        {
            if (!_priceRepo.IsLoadingPriceComplete.Signaled)
            {
                return(original);
            }

            var target = Deck.Create();

            target.Name = original.Name + " transformed";

            var usedCountById = new Dictionary <string, int>();

            void use(Card card, int count, DeckZone targetZone)
            {
                var id = card.Id;

                usedCountById.TryGetValue(id, out int currentTotalCount);
                usedCountById[id] = currentTotalCount + count;

                if (!targetZone.Count.TryGetValue(id, out var currentZoneCount))
                {
                    targetZone.Order.Add(id);
                }

                targetZone.Count[id] = currentZoneCount + count;
            }

            int getUsedCount(Card c)
            {
                usedCountById.TryGetValue(c.Id, out int count);
                return(count);
            }

            void transform(Card card, int count, DeckZone targetZone)
            {
                var candidates = card.Namesakes
                                 .Select(c => (Card: c, AvailableCount: collection.GetCount(c) - getUsedCount(c)))
                                 .OrderBy(_ => _.AvailableCount <= 0)
                                 .ThenBy(_ => _.Card.Price == null)
                                 .ThenBy(_ => _.Card.Price)
                                 .ToList();

                for (int i = 0; i < candidates.Count; i++)
                {
                    var candidate = candidates[i];
                    if (candidate.AvailableCount <= 0)
                    {
                        var bestNotCollectedCandidate = candidates
                                                        .AtMin(_ => _.Card.Price == null)
                                                        .ThenAtMin(_ => _.Card.Price ?? 0)
                                                        .Find();

                        use(bestNotCollectedCandidate.Card, count, targetZone);
                        return;
                    }

                    int takeCount = i < candidates.Count - 1
                                                ? Math.Min(count, candidate.AvailableCount)
                                                : count;

                    count -= takeCount;
                    use(candidate.Card, takeCount, targetZone);

                    if (count == 0)
                    {
                        return;
                    }
                }
            }

            var zones         = new[] { original.MainDeck, original.Sideboard, original.Maybeboard };
            var previousZones = new[] { previousTransformed?.MainDeck, previousTransformed?.Sideboard, previousTransformed?.Maybeboard };
            var resultZones   = new[] { target.MainDeck, target.Sideboard, target.Maybeboard };

            for (int i = 0; i < zones.Length; i++)
            {
                bool transformPrevious = previousTransformed != null && affectedNames != null;

                var zone = transformPrevious
                                        ? previousZones[i]
                                        : zones[i];

                var targetZone = resultZones[i];

                foreach (string id in zone.Order)
                {
                    var card = _repo.CardsById.TryGet(id);
                    if (card == null)
                    {
                        continue;
                    }

                    int count = zone.Count[id];
                    if (transformPrevious && !affectedNames.Contains(card.NameEn))
                    {
                        use(card, count, targetZone);
                    }
                    else
                    {
                        transform(card, count, targetZone);
                    }
                }
            }

            return(target);
        }