# Test Series Variants - Example Queries

This document provides example queries for working with test series variants (A, B, C).

## Database Structure

After running the migration, the `testseries` table will have:
- `parent_test_id`: References the parent test (nullable)
- `set_variant`: Enum('A', 'B', 'C') indicating the variant (nullable, default: null)
- Index on `(parent_test_id, set_variant)` for efficient querying

## Example Usage Scenarios

### 1. Fetch All Variants (A, B, C) of a Test

```php
use App\Models\TestSeries;

// Method 1: Using the variants() relationship
$parentTest = TestSeries::find(1);
$variants = $parentTest->variants;

// This will return a collection of all variant tests (A, B, C)
foreach ($variants as $variant) {
    echo "Variant {$variant->set_variant}: {$variant->name}\n";
}

// Method 2: Using query builder with eager loading
$parentTest = TestSeries::with('variants')->find(1);
$allVariants = $parentTest->variants;

// Method 3: Direct query to get all variants
$testId = 1;
$variants = TestSeries::where('parent_test_id', $testId)
    ->orderBy('set_variant')
    ->get();
```

### 2. Fetch a Specific Variant

```php
// Get variant 'A' for a specific test
$testId = 1;
$variantA = TestSeries::where('parent_test_id', $testId)
    ->where('set_variant', 'A')
    ->first();

// Or using the relationship
$parentTest = TestSeries::find(1);
$variantB = $parentTest->variants()
    ->where('set_variant', 'B')
    ->first();
```

### 3. Get Parent Test from a Variant

```php
// If you have a variant test and want to get its parent
$variantTest = TestSeries::find(10); // This is a variant test
$parentTest = $variantTest->parentTest;

echo "Parent Test: {$parentTest->name}\n";
echo "This is variant: {$variantTest->set_variant}\n";
```

### 4. Check if a Test has Variants

```php
$test = TestSeries::find(1);

// Check if this test has variants
if ($test->variants()->exists()) {
    $variantCount = $test->variants()->count();
    echo "This test has {$variantCount} variants\n";
} else {
    echo "This test has no variants (single paper)\n";
}
```

### 5. Create a Test with Variants

```php
use App\Models\TestSeries;

// Step 1: Create the parent test
$parentTest = TestSeries::create([
    'user_id' => 1,
    'name' => 'JEE Main Mock Test 2025',
    'category_id' => 5,
    'total_time' => 180,
    'per_ques_mark' => 4,
    'negative_marks' => 1,
    'max_questions' => 90,
    // ... other fields
    // Note: parent_test_id and set_variant are null for parent test
]);

// Step 2: Create variant A
$variantA = TestSeries::create([
    'user_id' => 1,
    'name' => 'JEE Main Mock Test 2025 - Set A',
    'category_id' => 5,
    'parent_test_id' => $parentTest->id,
    'set_variant' => 'A',
    'total_time' => 180,
    'per_ques_mark' => 4,
    'negative_marks' => 1,
    'max_questions' => 90,
    // ... other fields
]);

// Step 3: Create variant B
$variantB = TestSeries::create([
    'user_id' => 1,
    'name' => 'JEE Main Mock Test 2025 - Set B',
    'category_id' => 5,
    'parent_test_id' => $parentTest->id,
    'set_variant' => 'B',
    'total_time' => 180,
    'per_ques_mark' => 4,
    'negative_marks' => 1,
    'max_questions' => 90,
    // ... other fields
]);

// Step 4: Create variant C
$variantC = TestSeries::create([
    'user_id' => 1,
    'name' => 'JEE Main Mock Test 2025 - Set C',
    'category_id' => 5,
    'parent_test_id' => $parentTest->id,
    'set_variant' => 'C',
    'total_time' => 180,
    'per_ques_mark' => 4,
    'negative_marks' => 1,
    'max_questions' => 90,
    // ... other fields
]);

// Verify all variants are created
$allVariants = $parentTest->variants;
echo "Total variants created: " . $allVariants->count() . "\n";
```

### 6. Fetch Test with All Variants (Complete Structure)

```php
// Get a test with all its variants and questions
$parentTest = TestSeries::with([
    'variants' => function($query) {
        $query->orderBy('set_variant');
    },
    'variants.questions',
    'user'
])->find(1);

// Display the structure
echo "Parent Test: {$parentTest->name}\n";
echo "Created by: {$parentTest->user->name}\n\n";

foreach ($parentTest->variants as $variant) {
    echo "Variant {$variant->set_variant}:\n";
    echo "  - Name: {$variant->name}\n";
    echo "  - Questions: {$variant->questions->count()}\n";
}
```

### 7. Query Tests without Variants (Single Paper Tests)

```php
// Get all tests that don't have variants
$singlePaperTests = TestSeries::whereNull('parent_test_id')
    ->whereDoesntHave('variants')
    ->get();

// Or get tests that are not variants themselves
$nonVariantTests = TestSeries::whereNull('parent_test_id')
    ->whereNull('set_variant')
    ->get();
```

### 8. Get All Parent Tests with Variant Count

```php
// Get all parent tests with their variant counts
$parentTests = TestSeries::whereNull('parent_test_id')
    ->whereNull('set_variant')
    ->withCount('variants')
    ->get();

foreach ($parentTests as $test) {
    echo "{$test->name} has {$test->variants_count} variants\n";
}
```

### 9. Assign Random Variant to Student

```php
// When a student starts a test, assign them a random variant
$testId = 1;

$variants = TestSeries::where('parent_test_id', $testId)
    ->inRandomOrder()
    ->first();

if ($variants) {
    // Assign this variant to the student
    echo "Student assigned variant: {$variants->set_variant}\n";
} else {
    // No variants, use the parent test
    $test = TestSeries::find($testId);
    echo "Single paper test (no variants)\n";
}
```

### 10. API Response Example

```php
// Example API controller method
public function getTestWithVariants($id)
{
    $test = TestSeries::with('variants')->findOrFail($id);

    return response()->json([
        'success' => true,
        'data' => [
            'id' => $test->id,
            'name' => $test->name,
            'has_variants' => $test->variants->isNotEmpty(),
            'variants' => $test->variants->map(function($variant) {
                return [
                    'id' => $variant->id,
                    'set_variant' => $variant->set_variant,
                    'name' => $variant->name,
                    'question_count' => $variant->questions()->count(),
                ];
            })
        ]
    ]);
}
```

## Important Notes

1. **Parent Test**: A test without `parent_test_id` and `set_variant` (both null) is considered a parent test.

2. **Variant Test**: A test with `parent_test_id` set and `set_variant` as 'A', 'B', or 'C' is a variant.

3. **Single Paper Test**: A test without variants has both `parent_test_id` and `set_variant` as null and has no child variants.

4. **Index Usage**: The composite index `(parent_test_id, set_variant)` ensures efficient queries when fetching variants.

5. **Cascade Delete**: When a parent test is deleted, all its variants are automatically deleted due to the foreign key constraint.

## Migration Command

To apply these changes to your database, run:

```bash
php artisan migrate
```

To rollback:

```bash
php artisan migrate:rollback
```
