Page 1 of 1

CardPrinted, Preicates and The good old fashioned filter?

PostPosted: 26 Sep 2011, 16:44
by Rob Cashwalker
As I'm about to begin revising the draft, I come up to a TODO, that says it should be converted from using heavy Card objects....

How do I filter a List<CardPrinted>? I want to pull out cards based on the AI SVars, and then filter for card types and chosen colors.

Re: CardPrinted, Preicates and The good old fashioned filter

PostPosted: 26 Sep 2011, 19:15
by Max mtg
Code: Select all
List<CardPrinted> source = getSourceList();
Predicate<CardRules> filterAllowAiDeck = CardRules.Predicates.isKeptInAiDecks;
Predicate<CardRules> filterGreen = CardRules.Predicates.Presets.isGreen;
Predicate<CardRules> filterCreatures = CardRules.Predicates.Presets.isCreature;

List<CardPrinted> cardsAiSupports = filterAllowAiDeck.select(CardDb.getAllUniqueCards(), CardPrinted.fnGetRules); // without reprints
List<CardPrinted> mightWantToPutIntoDeck = Predicate.and(filterGreen, filterCreatures).select(cardsAiSupports, CardPrinted.fnGetRules);
Predicates are like filters, but more versatile - they allow you to build an expression tree and filter the cards you need in a single pass.

Once you have built a predicate, you may filter with select method. There are some variations of select: top() - will return the 1st matching object, any() will return true as soon as a matching object is found, split() will divide objects into two lists - one with matching elements, other with non-matching ones.

There some are situations when you want to filter types that contain the one you would like to make checks about, as in this expample want to check properties of CardRules, but have a list of CardPrinted. In that case use the second overload of select which accepts a lambda besides the Iterable to be filtered. That lambda should hold a function that accesses the type the predicate was build for.

The third overload allows not only access the type inside a container, but get a list of some different types, not the container itself, for instance one can select only the names of cards that are red instants.

Re: CardPrinted, Preicates and The good old fashioned filter

PostPosted: 26 Sep 2011, 20:31
by Rob Cashwalker
So I see in the CardPrinted Object are some of the Preset Predicates for rarity and name... trying to add my own preset based on the ones present didn't compile.. complained I didn't have a constructor or something. From your example, I guess the CardRules class contains a preset to do filter by card type? isCreature is fine and dandy, but what about looking for zombies? (Note I tried to dig around in the Deck Editor filtering but it seemed like it wasn't filtered the same way.

Re: CardPrinted, Preicates and The good old fashioned filter

PostPosted: 26 Sep 2011, 20:51
by Max mtg
Yes, CardPrinted itself holds no other information, cause the rest is kept in CardRules (a common part shared by all the prints of a single card). So CardPrinted has only predicate templates for name, rarity and sets.
The cases I met frequently were moved to presets (to avoid creating the same filter over and over). To filter cards by a subtype use
Code: Select all
Predicate<CardRules> f111 = CardRules.Predicates.subType("Goblin");
do svn up for CardRules - I've just commined the version with default string operator (before that there was only a version of subType(...) with 2 parameters)

DeckEditor filters cards differently, it just takes the full type string from each card and looks for substring user typed.

Which preset were you trying to add and where?

Re: CardPrinted, Preicates and The good old fashioned filter

PostPosted: 27 Sep 2011, 00:01
by Rob Cashwalker
OK, I think I get it...

Now I know why it failed.. I was trying to add the predicate to CardPrinted, when it should be CardRules... Not that it needed to be added of course, I just couldn't find the card type as an existing predicate...

Re: CardPrinted, Preicates and The good old fashioned filter

PostPosted: 27 Sep 2011, 00:41
by Max mtg
Alright, and grats on post 2000!

The what really needs to be added to CardRules is the flag of card having two sides. Will need this for for booster generation at least.

Re: CardPrinted, Preicates and The good old fashioned filter

PostPosted: 27 Sep 2011, 04:07
by Rob Cashwalker
Still stuck....

What exact code would replace the following: (from BoosterDraftAI.choose, assume chooseFrom parameter becomes a List<CardPrinted> passed from the internals of the draft)
Code: Select all
CardList AIPlayables = chooseFrom.filter(new CardListFilter() {
            public boolean addCard(Card c) {
               if (c.getSVar("RemAIDeck").equals("True") || c.getSVar("RemRandomDeck").equals("True"))
                  return false;
                return true;
            }
        });
How are the lists sorted? How to implement a sorting method?

Re: CardPrinted, Preicates and The good old fashioned filter

PostPosted: 27 Sep 2011, 10:51
by Max mtg
Rob Cashwalker wrote:Still stuck....

What exact code would replace the following: (from BoosterDraftAI.choose, assume chooseFrom parameter becomes a List<CardPrinted> passed from the internals of the draft)
Code: Select all
CardList AIPlayables = chooseFrom.filter(new CardListFilter() {
            public boolean addCard(Card c) {
               if (c.getSVar("RemAIDeck").equals("True") || c.getSVar("RemRandomDeck").equals("True"))
                  return false;
                return true;
            }
        });
How are the lists sorted? How to implement a sorting method?
Predicate<CardRules> aiPlayablesFilter = Predicates.and(CardRules.Predicates.isKeptInAiDecks, CardRules.Predicates.isKeptInRandomDecks);
List<CardPrinted> aiPlayablesList = aiPlayablesFilter.select(someCards, CardPrinted.fnGetRules)


If you really asked about sorting, then use Collections.sort