232 lines
5.2 KiB
Markdown
232 lines
5.2 KiB
Markdown
# Opus Magnum Submission API Usage
|
|
|
|
## Overview
|
|
|
|
The API is built with Django Ninja and provides endpoints for managing puzzle submissions with OCR validation and S3 file storage.
|
|
|
|
## Base URL
|
|
- Development: `http://localhost:8000/api/`
|
|
- API Documentation: `http://localhost:8000/api/docs/`
|
|
|
|
## Authentication
|
|
Most endpoints support both authenticated and anonymous submissions. Admin endpoints require staff permissions.
|
|
|
|
## Environment Variables
|
|
|
|
### Required for S3 Storage
|
|
```bash
|
|
USE_S3=true
|
|
AWS_ACCESS_KEY_ID=your_access_key
|
|
AWS_SECRET_ACCESS_KEY=your_secret_key
|
|
AWS_STORAGE_BUCKET_NAME=your_bucket_name
|
|
AWS_S3_REGION_NAME=us-east-1
|
|
```
|
|
|
|
### Optional
|
|
```bash
|
|
STEAM_API_KEY=your_steam_api_key
|
|
```
|
|
|
|
## API Endpoints
|
|
|
|
### 1. Get Available Puzzles
|
|
```http
|
|
GET /api/submissions/puzzles
|
|
```
|
|
|
|
Response:
|
|
```json
|
|
[
|
|
{
|
|
"id": 1,
|
|
"steam_item_id": "3479143948",
|
|
"title": "P41-FLOC",
|
|
"author_name": "Flame Legrems",
|
|
"description": "A challenging puzzle...",
|
|
"tags": ["puzzle", "chemistry"],
|
|
"order_index": 0,
|
|
"steam_url": "https://steamcommunity.com/workshop/filedetails/?id=3479143948",
|
|
"created_at": "2025-05-29T11:19:24Z",
|
|
"updated_at": "2025-05-30T22:15:09Z"
|
|
}
|
|
]
|
|
```
|
|
|
|
### 2. Create Submission
|
|
```http
|
|
POST /api/submissions/submissions
|
|
Content-Type: multipart/form-data
|
|
```
|
|
|
|
Form Data:
|
|
- `data`: JSON with submission data
|
|
- `files`: Array of uploaded files
|
|
|
|
Example data:
|
|
```json
|
|
{
|
|
"notes": "My best solutions so far",
|
|
"responses": [
|
|
{
|
|
"puzzle_id": 1,
|
|
"puzzle_name": "P41-FLOC",
|
|
"cost": "150",
|
|
"cycles": "89",
|
|
"area": "12",
|
|
"needs_manual_validation": false,
|
|
"ocr_confidence_score": 0.95
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
Response:
|
|
```json
|
|
{
|
|
"id": "123e4567-e89b-12d3-a456-426614174000",
|
|
"user": null,
|
|
"notes": "My best solutions so far",
|
|
"responses": [
|
|
{
|
|
"id": 1,
|
|
"puzzle": 1,
|
|
"puzzle_name": "P41-FLOC",
|
|
"cost": "150",
|
|
"cycles": "89",
|
|
"area": "12",
|
|
"needs_manual_validation": false,
|
|
"files": [
|
|
{
|
|
"id": 1,
|
|
"original_filename": "solution.gif",
|
|
"file_size": 1024000,
|
|
"content_type": "image/gif",
|
|
"file_url": "https://bucket.s3.amazonaws.com/media/submissions/123.../file.gif",
|
|
"ocr_processed": false,
|
|
"created_at": "2025-10-29T00:00:00Z"
|
|
}
|
|
],
|
|
"final_cost": "150",
|
|
"final_cycles": "89",
|
|
"final_area": "12"
|
|
}
|
|
],
|
|
"total_responses": 1,
|
|
"needs_validation": false,
|
|
"is_validated": false,
|
|
"created_at": "2025-10-29T00:00:00Z"
|
|
}
|
|
```
|
|
|
|
### 3. List Submissions
|
|
```http
|
|
GET /api/submissions/submissions?limit=20&offset=0
|
|
```
|
|
|
|
### 4. Get Submission Details
|
|
```http
|
|
GET /api/submissions/submissions/{submission_id}
|
|
```
|
|
|
|
### 5. Admin: Validate Response (Staff Only)
|
|
```http
|
|
PUT /api/submissions/responses/{response_id}/validate
|
|
Content-Type: application/json
|
|
```
|
|
|
|
Body:
|
|
```json
|
|
{
|
|
"validated_cost": "150",
|
|
"validated_cycles": "89",
|
|
"validated_area": "12"
|
|
}
|
|
```
|
|
|
|
### 6. Admin: List Responses Needing Validation (Staff Only)
|
|
```http
|
|
GET /api/submissions/responses/needs-validation
|
|
```
|
|
|
|
### 7. Admin: Validate Entire Submission (Staff Only)
|
|
```http
|
|
POST /api/submissions/submissions/{submission_id}/validate
|
|
```
|
|
|
|
### 8. Get Statistics
|
|
```http
|
|
GET /api/submissions/stats
|
|
```
|
|
|
|
Response:
|
|
```json
|
|
{
|
|
"total_submissions": 150,
|
|
"total_responses": 300,
|
|
"needs_validation": 25,
|
|
"validated_submissions": 120,
|
|
"validation_rate": 0.8
|
|
}
|
|
```
|
|
|
|
## OCR Validation Logic
|
|
|
|
The system automatically flags responses for manual validation when:
|
|
|
|
1. **Incomplete OCR Data**: Missing cost, cycles, or area values
|
|
2. **Low Confidence**: OCR confidence score below threshold
|
|
3. **Manual Flag**: Explicitly marked by frontend OCR processing
|
|
|
|
### Manual Validation Workflow
|
|
|
|
1. Admin views responses needing validation: `GET /responses/needs-validation`
|
|
2. Admin reviews the uploaded files and OCR results
|
|
3. Admin provides corrected values: `PUT /responses/{id}/validate`
|
|
4. System updates `validated_*` fields and clears validation flag
|
|
5. Optional: Mark entire submission as validated: `POST /submissions/{id}/validate`
|
|
|
|
## File Storage
|
|
|
|
- **Development**: Files stored locally in `media/submissions/`
|
|
- **Production**: Files stored in S3 with path structure: `submissions/{submission_id}/{uuid}_{filename}`
|
|
- **Supported Formats**: JPEG, PNG, GIF, MP4, WebM
|
|
- **Size Limit**: 10MB per file
|
|
|
|
## Error Handling
|
|
|
|
The API returns standard HTTP status codes:
|
|
|
|
- `200`: Success
|
|
- `400`: Bad Request (validation errors)
|
|
- `401`: Unauthorized
|
|
- `403`: Forbidden (admin required)
|
|
- `404`: Not Found
|
|
- `500`: Internal Server Error
|
|
|
|
Error Response Format:
|
|
```json
|
|
{
|
|
"detail": "Error message",
|
|
"code": "error_code"
|
|
}
|
|
```
|
|
|
|
## Frontend Integration
|
|
|
|
The Vue frontend should:
|
|
|
|
1. Upload files with OCR data extracted client-side
|
|
2. Group files by detected puzzle name
|
|
3. Create one submission with multiple responses
|
|
4. Handle validation flags and display admin feedback
|
|
5. Show file upload progress and S3 URLs
|
|
|
|
## Admin Interface
|
|
|
|
Django Admin provides:
|
|
|
|
- **Submission Management**: View, validate, and manage submissions
|
|
- **Response Validation**: Bulk actions for validation workflow
|
|
- **File Management**: View uploaded files and OCR data
|
|
- **Statistics Dashboard**: Track validation rates and submission metrics
|