# Auto-Submit Expired Exams - Documentation

## Overview

This feature automatically submits exam attempts that have exceeded their duration time. This ensures that exams are properly completed even if:
- A student closes the browser tab during the exam
- The device loses power or internet connection
- The student navigates away from the exam page

## How It Works

### 1. Laravel Command: `AutoSubmitExpiredExams`

**Location**: `app/Console/Commands/AutoSubmitExpiredExams.php`

**Command**: `php artisan exams:auto-submit-expired`

**Frequency**: Every minute (via Laravel Scheduler)

### 2. Process Flow

1. Every minute, the command runs via Laravel Scheduler
2. It queries all `exam_attempts` with status `in_progress`
3. For each attempt, it calculates:
   - Elapsed time: `now() - attempt.start_time`
   - Duration: `exam.duration * 60` (converted to seconds)
4. If `elapsed_time >= duration`, the exam is auto-submitted
5. Uses existing `SiswaCBTService::submitExam()` method
6. Logs all actions (success/failure) to Laravel Log

### 3. Student Experience

#### Scenario 1: Normal Flow (Device OK)
1. Student starts exam
2. Student closes tab or navigates away
3. Student returns to exam page **before** time expires
4. **Result**: Exam resumes normally ✅

#### Scenario 2: Device Failure (Power Outage/Network)
1. Student starts exam
2. Device loses power/connection
3. Device is restored **after** exam duration
4. **Result**: Exam is auto-submitted by cron, student redirected to history ✅

#### Scenario 3: Time Expires Normally
1. Student's timer reaches 00:00
2. Frontend auto-submits via `forceSubmitExam()`
3. Cron job runs as backup (if frontend failed)
4. **Result**: Double protection ensures submission ✅

## Setup Instructions

### Development Environment

The scheduler runs automatically when using `php artisan serve`.

To test manually:
```bash
php artisan exams:auto-submit-expired
```

### Production Environment

You need to set up a cron job on your server to trigger Laravel's scheduler every minute.

#### Linux/Mac (Cron)

Add this to your crontab (`crontab -e`):
```bash
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
```

#### Windows (Task Scheduler)

Create a task that runs every minute:
```
schtasks /create /sc minute /mo 1 /tn "Laravel Scheduler" /tr "php C:\path\to\project\artisan schedule:run"
```

### Docker Environment

If using Docker, add to your docker-compose.yml or use a separate cron container:

```yaml
cron:
  build: .
  command: php artisan schedule:run --verbose
  restart: unless-stopped
```

## Configuration

### Adjust Frequency

To change the frequency, edit `routes/console.php`:

```php
// Every minute (default)
Schedule::command('exams:auto-submit-expired')->everyMinute();

// Every 5 minutes
Schedule::command('exams:auto-submit-expired')->everyFiveMinutes();

// Every hour
Schedule::command('exams:auto-submit-expired')->hourly();
```

**Note**: Using longer intervals increases the maximum delay before auto-submit. For exams, we recommend keeping it at 1 minute.

### View Scheduled Tasks

To see all scheduled tasks:
```bash
php artisan schedule:list
```

## Logging

All auto-submit actions are logged to Laravel's log files:

### Successful Auto-Submit
```bash
tail -f storage/logs/laravel.log
```

Example log entry:
```json
{
  "message": "Auto-submitted expired exam",
  "attempt_id": 29,
  "student_id": 1,
  "exam_id": 1,
  "exam_name": "Math Test",
  "elapsed_seconds": 3600,
  "duration_seconds": 3600,
  "submitted_at": "2026-04-12 12:30:00"
}
```

### Failed Auto-Submit
```json
{
  "message": "Failed to auto-submit expired exam",
  "attempt_id": 29,
  "student_id": 1,
  "exam_id": 1,
  "error": "Unauthorized"
}
```

## Monitoring

### Check Command Output

Run manually to see current status:
```bash
php artisan exams:auto-submit-expired
```

Output example:
```
Starting auto-submit for expired exam attempts...
Found 5 attempts in progress
- Attempt ID: 25 - Still active (1800s remaining)
- Attempt ID: 26 - Still active (900s remaining)
Processing attempt ID: 27 - Time expired (3605s / 3600s)
✓ Auto-submitted attempt ID: 27

Auto-submit completed!
+------------------------+-------+
| Metric                 | Count |
+------------------------+-------+
| Processed attempts     | 1     |
| Successfully submitted | 1     |
| Failed submissions     | 0     |
+------------------------+-------+
```

### Log Monitoring

Set up log monitoring to alert on failures:
- Use Laravel's log channels
- Integrate with monitoring tools (Sentry, Bugsnag, etc.)
- Monitor for "Failed to auto-submit expired exam" messages

## Troubleshooting

### Command Not Running

1. Check if Laravel Scheduler is set up on your server
2. Verify cron job is running: `grep schedule /var/log/syslog`
3. Test manually: `php artisan schedule:run --verbose`

### Exams Not Auto-Submitting

1. Check log files for errors: `tail -f storage/logs/laravel.log`
2. Verify exam status is `in_progress` in database
3. Check if `exam.duration` is set correctly
4. Verify relationships: examParticipant → exam & student exist

### Data Integrity Issues

If you see "Missing exam or student data" warnings:
```bash
⚠ Skipping attempt ID: 29 - Missing exam or student data (data integrity issue)
```

This means:
- The exam or student record was deleted
- Foreign key constraints are broken
- Database inconsistency

Fix by checking database integrity:
```sql
SELECT ea.id, ea.exam_participant_id, ep.exam_id, ep.student_id
FROM exam_attempts ea
LEFT JOIN exam_participants ep ON ea.exam_participant_id = ep.id
WHERE ea.status = 'in_progress'
AND (ep.exam_id IS NULL OR ep.student_id IS NULL);
```

## Performance Considerations

- Command uses eager loading to minimize queries
- Only processes `in_progress` attempts
- Logs are kept minimal for performance
- Runs in background via cron, no impact on user experience

## Security

- Uses existing `submitExam()` method with same validation
- Student authorization is verified before submission
- No direct database manipulation - uses service layer
- All actions are logged for audit trail

## Future Enhancements

Potential improvements:
1. Send notification to student when exam is auto-submitted
2. Add email notification to teacher
3. Display auto-submit badge in exam history
4. Add retry mechanism for failed submissions
5. Batch processing for large number of expired exams

## Support

For issues or questions:
1. Check Laravel logs: `storage/logs/laravel.log`
2. Review this documentation
3. Test command manually: `php artisan exams:auto-submit-expired --help`