# Filtering Guide

Universal filter syntax for all queryable objects in PY-Tarot.

## Basic Filtering (AND Logic)

Multiple filters use AND logic - all conditions must match.

### Cards - Basic

```python
from tarot import Tarot

# Single filter
Tarot.deck.card.filter(suit="Cups")
# → All Cups cards (1-14)

# Multiple filters (AND)
Tarot.deck.card.filter(suit="Cups", type="Court")
# → Knight, Prince, Princess, Queen of Cups (4 cards)

# Filter by pip number
Tarot.deck.card.filter(pip=3)
# → 3 of Cups, Pentacles, Swords, Wands (4 cards)

# Filter Aces
Tarot.deck.card.filter(type="Ace")
# → Ace of Cups, Pentacles, Swords, Wands (4 cards)

# Filter specific court rank
Tarot.deck.card.filter(court_rank="Knight")
# → All 4 Knights (all suits)

# Combine: Knights of Cups
Tarot.deck.card.filter(court_rank="Knight", suit="Cups")
# → Knight of Cups (1 card)
```

### Cards - By Card Type

```python
# All Major Arcana
Tarot.deck.card.filter(type="Major")
# → The Fool through The World (22 cards)

# All Court Cards
Tarot.deck.card.filter(type="Court")
# → 16 cards (4 ranks × 4 suits)

# All Pips (2-10)
Tarot.deck.card.filter(type="Pip")
# → 36 cards

# All Aces
Tarot.deck.card.filter(type="Ace")
# → 4 cards

# Specific pip type + suit
Tarot.deck.card.filter(type="Pip", pip=5, suit="Wands")
# → 5 of Wands (1 card)
```

### Cards - Court Cards

```python
# All Knights
Tarot.deck.card.filter(type="Court", court_rank="Knight")
# → Knight of Cups, Pentacles, Swords, Wands (4 cards)

# All Queens
Tarot.deck.card.filter(type="Court", court_rank="Queen")
# → Queen of Cups, Pentacles, Swords, Wands (4 cards)

# Queen of specific element
Tarot.deck.card.filter(type="Court", court_rank="Queen", suit="Wands")
# → Queen of Wands (1 card)

# All Princes
Tarot.deck.card.filter(court_rank="Prince")
# → Prince of Cups, Pentacles, Swords, Wands (4 cards)

# All Princesses
Tarot.deck.card.filter(court_rank="Princess")
# → Princess of Cups, Pentacles, Swords, Wands (4 cards)
```

## Advanced Filtering

### Multiple Values (OR Logic)

Use `filter()` multiple times and combine results:

```python
# Aces OR Pips with value 3
aces = Tarot.deck.card.filter(type="Ace")
threes = Tarot.deck.card.filter(pip=3)
result = aces + threes
# → Ace of all suits + 3 of all suits (8 cards)

# Wands OR Pentacles
wands = Tarot.deck.card.filter(suit="Wands")
pentacles = Tarot.deck.card.filter(suit="Pentacles")
result = wands + pentacles
# → All Wands + all Pentacles (28 cards)

# Knights OR Queens
knights = Tarot.deck.card.filter(court_rank="Knight")
queens = Tarot.deck.card.filter(court_rank="Queen")
result = knights + queens
# → All Knights + all Queens (8 cards)
```

### Complex Queries

```python
# All Cups court cards
cups_court = Tarot.deck.card.filter(suit="Cups", type="Court")
# → Knight, Prince, Princess, Queen of Cups (4 cards)

# All water element (Cups and lower pips)
water_cards = Tarot.deck.card.filter(suit="Cups")
# → All 14 Cups cards

# Fire element court cards
fire_court = Tarot.deck.card.filter(suit="Wands", type="Court")
# → Knight, Prince, Princess, Queen of Wands (4 cards)

# All numbered cards from 2-10 (pips) in specific suits
fives_in_water_earth = (
    Tarot.deck.card.filter(pip=5, suit="Cups") +
    Tarot.deck.card.filter(pip=5, suit="Pentacles")
)
# → 5 of Cups + 5 of Pentacles (2 cards)
```

## Available Filter Fields

### All Cards
- `type` → "Major", "Pip", "Ace", "Court"
- `arcana` → "Major", "Minor"
- `number` → Card's position in deck (1-78)
- `name` → Full card name (case-insensitive)

### Minor Arcana Only
- `suit` → "Cups", "Pentacles", "Swords", "Wands"
- `pip` → 1-10 (1 for Ace, 2-10 for pips)
- `court_rank` → "Knight", "Prince", "Princess", "Queen"

### Court Cards Only
- `court_rank` → "Knight", "Prince", "Princess", "Queen"
- `associated_element` → Element object for the court rank

### Major Arcana Only
- `kabbalistic_number` → 0-21

## Display Results

```python
# Print as formatted list
cards = Tarot.deck.card.filter(suit="Cups")
print(cards)

# Print nicely formatted
cards_str = Tarot.deck.card.display_filter(suit="Cups")
print(cards_str)

# Access individual cards
cups = Tarot.deck.card.filter(suit="Cups")
first_cup = cups[0]  # Ace of Cups
print(f"{first_cup.number}. {first_cup.name}")
```

## Case Sensitivity

All filters are case-insensitive:

```python
Tarot.deck.card.filter(suit="cups")      # Works
Tarot.deck.card.filter(suit="CUPS")      # Works
Tarot.deck.card.filter(suit="Cups")      # Works
Tarot.deck.card.filter(type="ace")       # Works
Tarot.deck.card.filter(type="ACE")       # Works
Tarot.deck.card.filter(type="Ace")       # Works
```

## Tips

- Use `type` to filter by card class (Major, Pip, Ace, Court)
- Use `suit` to filter by element (Cups/Water, Pentacles/Earth, Swords/Air, Wands/Fire)
- Multiple kwargs = AND logic
- For OR logic, call `filter()` separately and combine lists with `+`
- All string comparisons are case-insensitive
