## HitRate@3

Competition metric HitRate@3 measures the fraction of search sessions where the correct flight appears in your top-3 predictions.

$$HitRate@3 = \frac{1}{|Q|} \sum_{i=1}^{|Q|} \mathbf{1}(rank_i \leq 3)$$

Where:
- `|Q|` is the number of search queries (unique `ranker_id` values)
- `rank_i` is the rank position you assigned to the correct flight in query `i`
- `𝟙(rank_i ≤ 3)` is 1 if the correct flight is in top-3, 0 otherwise

**Example:** If the correct flight is ranked 1st, 2nd, or 3rd, you get 1.0 points. Otherwise, you get 0 points.

**Score range:** 0 to 1, where 1 means the correct flight is always in top-3

### Important Note on Group Size Filtering
The metric evaluation will only consider groups (`ranker_id`) with **more than 10 flight options**. Groups with 10 or fewer options are excluded from the final score calculation to focus on more challenging ranking scenarios where distinguishing between options is meaningful.

However, we have intentionally kept these smaller groups in both the training and test datasets because:

- They represent real-world search scenarios
- They provide additional training signal for your models
- They help capture the full diversity of user behavior patterns

## Submission Format

### Training Data Target
In the training data, the `selected` column is **binary**:
- `1` = This flight was chosen by the traveler
- `0` = This flight was not chosen

**Important:** There is exactly one row with `selected=1` per user search request (`ranker_id`). Each row within a `ranker_id` group represents a different flight option returned by the search system for that specific route and date.

**Training data example:**
```
Id,ranker_id,selected
100,abc123,0     # Flight option 1 - not chosen
101,abc123,0     # Flight option 2 - not chosen  
102,abc123,1,    # Flight option 3 - SELECTED by user
103,abc123,0     # Flight option 4 - not chosen
```

### Submission Format
Your submission must contain **ranks** (not probabilities) for each flight option:

```
Id,ranker_id,selected
100,abc123,4
101,abc123,2
102,abc123,1
103,abc123,3
```

Where:
- `Id` matches the row identifier from the test set
- `ranker_id` is the search session identifier (same as in test.csv)
- `selected` is the **rank** you assign (1 = best option, 2 = second best, etc.)

**Important:** Maintain the exact same row order as in `test.csv`

In this example, your model predicts that:
- Row 102 (Id=102) is the best option → Rank 1
- Row 101 (Id=101) is second best → Rank 2  
- Row 103 (Id=103) is third best → Rank 3
- Row 100 (Id=100) is the worst option → Rank 4

## Submission Requirements

1. **Preserve row order:** Maintain the exact same row order as in `test.csv`
2. **Complete rankings:** For each user search request, you must rank ALL flight options returned by the search system
3. **Valid permutation:** Ranks within each `ranker_id` must be a valid permutation (1, 2, 3, ..., N) where N is the number of rows in that group
4. **No duplicate ranks:** Each row within a `ranker_id` group must have a unique rank
5. **Integer values:** All ranks must be integers ≥ 1

### Example for one user search request:
```
Training data shows:
ranker_id: abc123 → Row 102 was chosen (selected=1)

Your submission:
ranker_id: abc123
├── Row 100 → Rank 4 (worst option)
├── Row 101 → Rank 2 (second best)
├── Row 102 → Rank 1 (best - correctly predicted!)
└── Row 103 → Rank 3 (third best)

```

## Validation

Your submission will be validated for:
- Correct number of rows
- Integer rank values
- Valid rank permutations within each group
- No duplicate ranks per search session
- Basic anti-cheating measures

**Note:** The evaluation system expects you to transform your model's output (scores/probabilities) into ranks before submission. Higher model scores should correspond to lower rank numbers (1 = best).