Code Checker is an advanced programming assessment platform powered by OpenAI's GPT models to generate, evaluate, and provide feedback on programming challenges across multiple languages and difficulty levels.
- Overview
- Features
- System Architecture
- Setup & Installation
- Configuration
- Database Setup
- Usage
- API Endpoints
- Development
- Production Deployment
- Testing
- Troubleshooting & Common Issues
- Contributing
- License
Code Checker is a Django-based web application that leverages OpenAI's GPT models to provide a comprehensive programming assessment platform. The system can generate unique coding questions, theory questions, and multiple-choice questions (MCQs) across various programming languages and difficulty levels. It evaluates submitted code, provides feedback, and tracks user progress.
The platform uses vector embeddings for semantic similarity checks to prevent duplicate questions and features a robust leaderboard system to encourage friendly competition among users.
-
User Authentication & Management
- Email-based signup with verification
- Password reset and change functionality
- Google OAuth integration
- User profile management
-
Question Generation
- AI-generated coding challenges (with automatic test case creation)
- Theory questions for conceptual understanding
- Multiple-choice questions for quick assessments
- Support for multiple programming languages
- Three difficulty levels: Easy, Medium, Hard
- Semantic duplicate detection using OpenAI embeddings
-
Quiz System
- Create customized quizzes based on language and difficulty
- Track quiz progress and completion
- Automatic or manual quiz completion
- View detailed quiz history
-
Code Evaluation
- Syntax validation for submitted code
- Secure code execution in controlled environments
- Testing against predefined test cases
- AI-powered feedback for incorrect submissions
-
Progress Tracking & Leaderboards
- Individual progress tracking
- Global leaderboards based on accuracy
- Quiz-specific leaderboards
- User submission history and review
- Friend comparison feature
The system follows a standard Django architecture with the following key components:
-
Authentication Module (built on django-rest-authemail and social-auth)
- Handles user signup, verification, and login
- Supports OAuth integration for Google login
-
Question Generation System
- Uses OpenAI GPT-4 to generate programming questions
- Implements semantic similarity checks using embeddings
- Supports multiple question types (coding, theory, MCQ)
-
Quiz Management System
- Creates and manages quizzes
- Tracks quiz progress and completion
- Handles question sequencing and scoring
-
Code Execution & Evaluation System
- Validates code syntax
- Runs code against test cases
- Provides feedback on submissions
-
Progress & Leaderboard System
- Tracks individual and comparative progress
- Generates leaderboards based on various metrics
MyUser: Extended user model for authenticationProgrammingLanguage: Supported programming languagesExpertiseLevel: Difficulty levels for questionsQuizQuestion,TheoryQuestion,MCQQuestion: Different question typesTestCase: Input/output test cases for coding questionsQuestionEmbedding: Vector embeddings for semantic similarity checksQuizandQuizQuestionResponse: Quiz management and trackingUserProgressandUserSubmission: User performance tracking
- Python 3.8+
- PostgreSQL with pgvector extension (recommended for production)
- OpenAI API key
-
Clone the repository
git clone https://github.com/yourusername/code-checker.git cd code-checker -
Create a virtual environment
python -m venv venv
-
Activate the virtual environment
- On Windows:
venv\Scripts\activate
- On macOS/Linux:
source venv/bin/activate
- On Windows:
4. **Install dependencies**
```bash
pip install -r requirements.txt
-
Create a .env file based on env-sample
cp env-sample .env
-
Update the .env file with your configuration
- Add your OpenAI API key
- Configure database settings
- Set up email settings for verification
- Add Google OAuth credentials (if using)
-
Apply migrations
python manage.py makemigrations python manage.py migrate
-
Run the server
python manage.py runserver
Edit the .env file with the following configurations:
# Django Settings
SECRET_KEY=your_secret_key
# Database Settings
DB_ENGINE=django.db.backends.postgresql
DB_NAME=code_checker_db
DB_USER=postgres
DB_PASSWORD=your_password
DB_HOST=localhost
DB_PORT=5432
# OpenAI Settings
open_ai_key=your_openai_api_key
The application can work with SQLite (default for development) or PostgreSQL (recommended for production).
-
Install PostgreSQL and pgvector extension
-
Create a database
CREATE DATABASE code_checker_db;
-
Enable pgvector extension
\c code_checker_db CREATE EXTENSION IF NOT EXISTS vector;
-
Update .env file with PostgreSQL settings
DB_ENGINE=django.db.backends.postgresql DB_NAME=code_checker_db DB_USER=your_db_user DB_PASSWORD=your_db_password DB_HOST=localhost DB_PORT=5432
To create initial programming languages and expertise levels:
python manage.py shellfrom interface.models import ProgrammingLanguage, ExpertiseLevel
# Add programming languages
languages = ["Python", "JavaScript", "Java", "C++", "C#"]
for lang in languages:
ProgrammingLanguage.objects.get_or_create(name=lang)
# Add expertise levels
levels = ["Easy", "Medium", "Hard"]
for level in levels:
ExpertiseLevel.objects.get_or_create(level=level)python manage.py runserverTo enable semantic similarity checks, generate embeddings for existing questions:
python manage.py generate_embeddings --types allOptions:
--types: Question types to process (coding,theory,mcq,all)--batch-size: Number of questions per batch (default: 50)--sleep-time: Wait time between batches in seconds (default: 10.0)--force: Regenerate embeddings for all questions
Authentication Note: Most endpoints require a JWT authentication token. Include the token in the request header as:
Authorization: Bearer <your_jwt_token>To obtain this token, use the
/api/token/endpoint.
-
POST /api/token/- Description: Obtain a JWT token for authentication
- Request Body:
{ "email": "user@example.com", "password": "your_password" } - Response:
{ "access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...", "refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." } - Authentication: None required
-
POST /api/token/refresh/- Description: Refresh an expired JWT token
- Request Body:
{ "refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." } - Response:
{ "access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." } - Authentication: None required
-
POST /api/signup/- Description: Register a new user
- Request Body:
{ "email": "user_1234@gmail.com", "password": "Test@1234", "first_name": "John", "last_name": "Doe" } - Response:
{ "email": "user_1234@gmail.com", "first_name": "John", "last_name": "Doe" } - Authentication: None required
-
POST /api/password/change/- Description: Change password (for authenticated users)
- Request Body:
{ "password": "current_password", "new_password": "new_secure_password" } - Response:
{ "success": "Password changed." } - Authentication: JWT token required
-
POST /api/generate-quiz-question/- Description: Generate a coding question
- Request Body:
{ "language_id": 1, "level_id": 2 } - Response:
{ "question_id": 48, "question": "Generated question will come here" } - Authentication: None required
-
POST /api/generate-mcq-question/- Description: Generate a multiple-choice question
- Request Body:
{ "language_id": 2, "level_id": 1 } - Response:
{ "id": 56, "question": "What is the output of the following expression 3 + 2 * 4 in Python?", "options": { "A": "14", "B": "11", "C": "10", "D": "8" }, "correct_option": "B" } - Authentication: None required
-
POST /api/generate-theory-question/- Description: Generate a theory question
- Request Body:
{ "language_id": 2, "level_id": 1 } - Response:
{ "id": 35, "question": "What is the difference between a list and a tuple in Python?" } - Authentication: None required
-
POST /api/create-quiz/- Description: Create a new quiz
- Request Body:
{ "language_id": 1, "level_id": 2, "num_questions": 5 } - Response:
{ "quiz_id": 12, "language": "PHP", "level": "Intermediate", "num_questions": 5, "available_questions": { "coding": 2, "theory": 2, "mcq": 1, "total": 5 } } - Authentication: JWT token required
-
GET /api/quiz/<quiz_id>/next-question/- Description: Get the next question in a quiz
- Path Parameters:
quiz_id- ID of the quiz - Response:
{ "question_id": 48, "question_type": "coding", "question_text": "Quiz Question" } - Authentication: JWT token required
-
POST /api/quiz/<quiz_id>/submit-answer/- Description: Submit an answer for a quiz question
- Path Parameters:
quiz_id- ID of the quiz - Request Body (for coding question):
{ "question_id": 48, "answer": "Submit Answer here", "question_type": "Type of question here", "start_time": "Current time here" } - Response:
{ "is_correct": false, "feedback": "The submitted code does not implement the required functionality. It appears to be a placeholder or an incorrect statement. The function 'wordCount' is not defined, and there is no logic to count words or handle the input string as specified in the problem description." } - Authentication: JWT token required
-
POST /api/quiz/<quiz_id>/complete/- Description: Complete a quiz
- Path Parameters:
quiz_id- ID of the quiz - Response:
{ "quiz_id": 12, "total_questions": 1, "correct_answers": 0, "score": 0, "completed_at": "2025-04-17T10:33:43.074715Z" } - Authentication: JWT token required
-
GET /api/quiz/<quiz_id>/details/- Description: Get quiz details
- Path Parameters:
quiz_id- ID of the quiz - Response:
{ "quiz_id": 12, "language": "PHP", "level": "Intermediate", "created_at": "2025-04-17T10:21:15.259850Z", "completed_at": "2025-04-17T10:33:43.074715Z", "score": 0, "total_questions": 1, "score_percentage": 0, "progress": 100, "remaining_questions": 0, "responses": [ { "id": 34, "question_type": "coding", "question_id": 48, "question_text": "Question here", "options": null, "user_response": "USer Answer here", "is_correct": false, "created_at": "2025-04-17T10:27:52.514873Z" } ], "is_completed": true } - Authentication: JWT token required
-
GET /api/quiz-history/- Description: Get user's quiz history
- Query Parameters:
page(optional): Page number for paginationpage_size(optional): Number of results per page
- Response:
[ { "quiz_id": 12, "language": "PHP", "level": "Intermediate", "created_at": "2025-04-17T10:21:15.259850Z", "completed_at": "2025-04-17T10:33:43.074715Z", "total_questions": 1, "correct_answers": 0, "score": 0, "is_completed": true } ] - Authentication: JWT token required
-
GET /api/leaderboard/- Description: Get global leaderboard
- Query Parameters:
type(optional): Metric type (accuracy, quiz_score), default is accuracyperiod(optional): Time period (all, month, week), default is all
- Response:
{ "leaderboard_type": "accuracy", "time_period": "all", "leaderboard": [ { "user_id": 2, "user_email": "dev@gmail.com", "accuracy": 78.57, "correct_answers": 11, "total_attempts": 14 } ] } - Authentication: JWT token required
-
GET /api/quiz-leaderboard/- Description: Get quiz-specific leaderboard
- Query Parameters:
language(optional): Filter by programming language ID (e.g., 1 for Python)level(optional): Filter by expertise level ID (e.g., 2 for Medium)
- Response:
{ "leaderboard": [ { "quiz_id": 1, "user_id": 2, "user_email": "dev@gmail.com", "language": "C#", "level": "Easy", "score": 5, "correct_answers": 0, "total_questions": 0, "completion_time": 0, "completed_at": "2025-04-16T16:51:55.979099Z" }, { "quiz_id": 8, "user_id": 2, "user_email": "dev@gmail.com", "language": "Python", "level": "Easy", "score": 5, "correct_answers": 0, "total_questions": 0, "completion_time": 0, "completed_at": "2025-04-16T18:05:53.717722Z" }, { "quiz_id": 9, "user_id": 2, "user_email": "dev@gmail.com", "language": "Python", "level": "Easy", "score": 1, "correct_answers": 0, "total_questions": 0, "completion_time": 0, "completed_at": "2025-04-16T18:14:28.859032Z" }, { "quiz_id": 12, "user_id": 1, "user_email": "admin@gmail.com", "language": "C#", "level": "Intermediate", "score": 0, "correct_answers": 0, "total_questions": 0, "completion_time": 0, "completed_at": "2025-04-17T10:33:43.074715Z" }, { "quiz_id": 15, "user_id": 1, "user_email": "admin@gmail.com", "language": "Python", "level": "Easy", "score": 0, "correct_answers": 0, "total_questions": 0, "completion_time": 0, "completed_at": "2025-04-24T17:14:14.381745Z" } ]
}
- **Authentication**: JWT token required -
GET /api/user-submissions/- Description: Get current user's submissions
- Query Parameters:
question_type(optional): Filter by question type (coding, theory, mcq)language(optional): Filter by programming language ID (e.g., 1 for Python)level(optional): Filter by expertise level ID (e.g., 2 for Medium)page(optional): Page number for pagination
- Response:
{ "user_id": 1, "user_email": "admin@gmail.com", "progress": { "accuracy": 0, "correct_answers": 0, "total_attempts": 0, "average_time": 0 }, "quizzes": [ { "quiz_id": 12, "language": "PHP", "level": "Intermediate", "score": 0, "created_at": "2025-04-17T10:21:15.259850Z", "completed_at": "2025-04-17T10:33:43.074715Z", "correct_answers": 0, "total_questions": 1, "duration_seconds": 0.0 } ], "recent_submissions": [ { "question_text": "Write a python code for the sum of two numbers.", "language": "Python", "level": "Easy", "time_taken": 0.0, "created_at": "2025-04-15T16:26:05.979341Z" }, { "question_text": "Write a python code for the sum of two numbers.", "language": "Python", "level": "Easy", "time_taken": 0.0, "created_at": "2025-04-15T16:23:54.128467Z" }, { "question_text": "Write a python code for the sum of two numbers.", "language": "Python", "level": "Easy", "time_taken": 0.0, "created_at": "2025-04-15T16:04:24.842718Z" }, { "question_text": "Write a python code for the sum of two numbers.", "language": "Python", "level": "Easy", "time_taken": 0.0, "created_at": "2025-04-15T13:26:54.642401Z" }, { "question_text": "What is the purpose of the \"echo\" function in PHP?", "language": "PHP", "level": "Easy", "time_taken": 0.0, "created_at": "2025-04-15T08:48:43.427989Z" } ], "language_proficiency": { "PHP": { "total": 2, "correct": 1, "proficiency": 50.0 }, "Python": { "total": 4, "correct": 4, "proficiency": 100.0 } } } - Authentication: JWT token required
-
GET /api/user-submissions/<user_id>/- Description: Get specific user's submissions
- Path Parameters:
user_id- ID of the user to view - Query Parameters: Same as
/api/user-submissions/ - Response: Same format as
/api/user-submissions/ - Authentication: JWT token required
-
POST /api/submit-answer/- Description: Submit an answer for a coding question (outside of a quiz)
- Request Body:
{ "question_id": 21, "language": "C++", "code": "Purpose of `cout` is to print output.", "start_time": "2025-04-17T08:37:33.688739Z" } - Response:
{ "submission_id": 25, "is_correct": false, "feedback": "Reason for the correct/incorrect.", "time_taken": 9302.942288, "failed_test_cases": [] } - Authentication: JWT token required
-
POST /api/submit-theory-answer/- Description: Submit an answer for a theory question (outside of a quiz)
- Request Body:
{ "question_id": 35, "answer": "Add Answer here" } - Response:
{ "feedback": "Correct Answer" } - Authentication: JWT token required
- Endpoint:
GET /api/programming-languages/ - Description: Retrieve a list of all programming languages.
- Endpoint:
POST /api/programming-languages/ - Description: Create a new programming language.
- Request Body:
{ "name": "string", }
- Endpoint:
GET /api/programming-languages/{id}/ - Description: Retrieve details of a specific programming language by ID.
- Endpoint:
PATCH /api/programming-languages/{id}/ - Description: Update an existing programming language by ID.
- Request Body:
{ "name": "C#" }- Response:
{ "id": 1, "name": "C#" }
- Response:
- Endpoint:
DELETE /api/programming-languages/{id}/ - Description: Delete a specific programming language by ID.
- Response:
{ "id": 1, "name": "C#" }
- Endpoint:
GET /api/expertise-levels/ - Description: Retrieve a list of all expertise levels.
- Response:
{ "count": 3, "next": null, "previous": null, "results": [ { "id": 1, "level": "Easy" }, { "id": 2, "level": "Intermediate" }, { "id": 3, "level": "Hard" } ] }
- Endpoint:
POST /api/expertise-levels/ - Description: Create a new expertise level.
- Request Body:
{ "level": "Expert" }
- Response:
{
"id": 6,
"level": "Expert"
}- Endpoint:
GET /api/expertise-levels/{id}/ - Description: Retrieve details of a specific expertise level by ID.
- Response:
{
"id": 1,
"level": "Easy"
}- Endpoint:
PATCH /api/expertise-levels/{id}/ - Description: Update an existing expertise level by ID.
- Request Body:
{ "level": "Begineer" }
- Response:
{
"id": 1,
"level": "Begineer"
}- Endpoint:
POST /api/assignments/generate/ - Description: Generate Assignment
- Request Body:
{ "language_id": 1, "level_id": 1 }
- Response:
{
"assignment_id": 2,
"coding_questions": [
{
"id": 55,
"question_text":"Question",
"programming_language": 1,
"expertise_level": 1,
"created_at": "2025-05-03T20:52:04.275685Z"
},
.....
],
"theory_questions": [
{
"id": 39,
"question_text": "What is the purpose of the `using` statement in C#, and how does it help in resource management?",
"programming_language": 1,
"expertise_level": 1,
"created_at": "2025-05-03T20:53:19.122515Z"
},
....
]
}
- Endpoint:
POST /api/assignments/assignment_id/submit/ - Description: Submit Assingment by ID
- Request Body:
{ "answers": [ { "question_type": "coding", "question_id": 55, "answer": "<your code string>" }, { "question_type": "coding", "question_id": 56, "answer": "<your theory answer text>" }, { "question_type": "coding", "question_id": 57, "answer": "<your theory answer text>" }, { "question_type": "coding", "question_id": 58, "answer": "<your theory answer text>" }, { "question_type": "coding", "question_id": 59, "answer": "<your theory answer text>" }, { "question_type": "coding", "question_id": 60, "answer": "<your theory answer text>" }, { "question_type": "coding", "question_id": 61, "answer": "<your theory answer text>" }, { "question_type": "coding", "question_id": 62, "answer": "<your theory answer text>" }, { "question_type": "theory", "question_id": 39, "answer": "The `using` statement in C# is used to ensure that an object implementing the `IDisposable` interface is automatically disposed of when it's no longer needed. It helps in resource management by guaranteeing that the `Dispose()` method is called, releasing unmanaged resources like file handles, database connections, or network streams as soon as they go out of scope—either normally or due to an exception. This prevents resource leaks and promotes clean, efficient code without requiring manual cleanup in `try...finally` blocks." }, { "question_type": "theory", "question_id": 40, "answer": "The using statement in C# ensures automatic disposal of objects that implement IDisposable, guaranteeing deterministic cleanup of unmanaged resources (e.g., file handles, database connections). It simplifies resource management by calling Dispose() implicitly when exiting the block, even during exceptions, avoiding leaks. Variables declared in a using block are scoped to it, preventing misuse afterward. Available as a concise statement (C# 8.0+) or traditional block syntax, it streamlines code while enforcing safe, efficient resource handling." } ] }
- Response:
{
"assignment_id": 1,
"score": 2,
"total_questions": 10,
"results": [
{
"question_id": 55,
"question_type": "coding",
"is_correct": false
},
{
"question_id": 56,
"question_type": "coding",
"is_correct": false
},
{
"question_id": 57,
"question_type": "coding",
"is_correct": false
},
{
"question_id": 58,
"question_type": "coding",
"is_correct": false
},
{
"question_id": 59,
"question_type": "coding",
"is_correct": false
},
{
"question_id": 60,
"question_type": "coding",
"is_correct": false
},
{
"question_id": 61,
"question_type": "coding",
"is_correct": false
},
{
"question_id": 62,
"question_type": "coding",
"is_correct": false
},
{
"question_id": 39,
"question_type": "theory",
"is_correct": true
},
{
"question_id": 40,
"question_type": "theory",
"is_correct": true
}
],
"evaluation_warnings": []
}- Endpoint:
GET /api/assignments/ - Description: Get all Assignments.
- Response:
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"id": 2,
"user": {
"id": 1,
"last_login": "2025-05-03T21:53:08.836757Z",
"is_superuser": true,
"first_name": "admin",
"last_name": "admin",
"email": "admin@gmail.com",
"is_staff": true,
"is_active": true,
"date_joined": "2025-04-10T20:47:32.619579Z",
"is_verified": true,
"groups": [],
"user_permissions": []
},
"programming_language": {
"id": 1,
"name": "C#"
},
"expertise_level": {
"id": 1,
"level": "Easy"
},
"created_at": "2025-05-03T22:38:36.905797Z",
"completed_at": null,
"score": 0,
"total_questions": 10,
"responses": []
},
{
"id": 1,
"user": {
"id": 1,
"last_login": "2025-05-03T21:53:08.836757Z",
"is_superuser": true,
"first_name": "admin",
"last_name": "admin",
"email": "admin@gmail.com",
"is_staff": true,
"is_active": true,
"date_joined": "2025-04-10T20:47:32.619579Z",
"is_verified": true,
"groups": [],
"user_permissions": []
},
"programming_language": {
"id": 1,
"name": "C#"
},
"expertise_level": {
"id": 1,
"level": "Easy"
},
"created_at": "2025-05-03T21:27:56.339034Z",
"completed_at": "2025-05-03T21:42:32.136650Z",
"score": 2,
"total_questions": 10,
"responses": [
{
"id": 1,
"question_type": "coding",
"question_id": 55,
"user_response": "<your code string>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 2,
"question_type": "coding",
"question_id": 56,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 3,
"question_type": "coding",
"question_id": 57,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 4,
"question_type": "coding",
"question_id": 58,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 5,
"question_type": "coding",
"question_id": 59,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 6,
"question_type": "coding",
"question_id": 60,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 7,
"question_type": "coding",
"question_id": 61,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 8,
"question_type": "coding",
"question_id": 62,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 9,
"question_type": "theory",
"question_id": 39,
"user_response": "The `using` statement in C# is used to ensure that an object implementing the `IDisposable` interface is automatically disposed of when it's no longer needed. It helps in resource management by guaranteeing that the `Dispose()` method is called, releasing unmanaged resources like file handles, database connections, or network streams as soon as they go out of scope—either normally or due to an exception. This prevents resource leaks and promotes clean, efficient code without requiring manual cleanup in `try...finally` blocks.",
"is_correct": true,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 10,
"question_type": "theory",
"question_id": 40,
"user_response": "The using statement in C# ensures automatic disposal of objects that implement IDisposable, guaranteeing deterministic cleanup of unmanaged resources (e.g., file handles, database connections). It simplifies resource management by calling Dispose() implicitly when exiting the block, even during exceptions, avoiding leaks. Variables declared in a using block are scoped to it, preventing misuse afterward. Available as a concise statement (C# 8.0+) or traditional block syntax, it streamlines code while enforcing safe, efficient resource handling.",
"is_correct": true,
"created_at": "2025-05-03T21:42:32.132651Z"
}
]
}
]
}- Endpoint:
GET /api/assignments/my/ - Description: Get assignments of the current user.
- Response:
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"user": {
"id": 1,
"last_login": "2025-05-03T21:53:08.836757Z",
"is_superuser": true,
"first_name": "admin",
"last_name": "admin",
"email": "admin@gmail.com",
"is_staff": true,
"is_active": true,
"date_joined": "2025-04-10T20:47:32.619579Z",
"is_verified": true,
"groups": [],
"user_permissions": []
},
"programming_language": {
"id": 1,
"name": "C#"
},
"expertise_level": {
"id": 1,
"level": "Easy"
},
"created_at": "2025-05-03T21:27:56.339034Z",
"completed_at": "2025-05-03T21:42:32.136650Z",
"score": 2,
"total_questions": 10,
"responses": [
{
"id": 1,
"question_type": "coding",
"question_id": 55,
"user_response": "<your code string>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 2,
"question_type": "coding",
"question_id": 56,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 3,
"question_type": "coding",
"question_id": 57,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 4,
"question_type": "coding",
"question_id": 58,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 5,
"question_type": "coding",
"question_id": 59,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 6,
"question_type": "coding",
"question_id": 60,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 7,
"question_type": "coding",
"question_id": 61,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 8,
"question_type": "coding",
"question_id": 62,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 9,
"question_type": "theory",
"question_id": 39,
"user_response": "The `using` statement in C# is used to ensure that an object implementing the `IDisposable` interface is automatically disposed of when it's no longer needed. It helps in resource management by guaranteeing that the `Dispose()` method is called, releasing unmanaged resources like file handles, database connections, or network streams as soon as they go out of scope—either normally or due to an exception. This prevents resource leaks and promotes clean, efficient code without requiring manual cleanup in `try...finally` blocks.",
"is_correct": true,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 10,
"question_type": "theory",
"question_id": 40,
"user_response": "The using statement in C# ensures automatic disposal of objects that implement IDisposable, guaranteeing deterministic cleanup of unmanaged resources (e.g., file handles, database connections). It simplifies resource management by calling Dispose() implicitly when exiting the block, even during exceptions, avoiding leaks. Variables declared in a using block are scoped to it, preventing misuse afterward. Available as a concise statement (C# 8.0+) or traditional block syntax, it streamlines code while enforcing safe, efficient resource handling.",
"is_correct": true,
"created_at": "2025-05-03T21:42:32.132651Z"
}
]
}
]
}- Endpoint:
GET /api/assignments/1/ - Description: Get Assignment scores by ID.
- Response:
{
"id": 1,
"user": {
"id": 1,
"last_login": "2025-05-03T21:53:08.836757Z",
"is_superuser": true,
"first_name": "admin",
"last_name": "admin",
"email": "admin@gmail.com",
"is_staff": true,
"is_active": true,
"date_joined": "2025-04-10T20:47:32.619579Z",
"is_verified": true,
"groups": [],
"user_permissions": []
},
"programming_language": {
"id": 1,
"name": "C#"
},
"expertise_level": {
"id": 1,
"level": "Easy"
},
"created_at": "2025-05-03T21:27:56.339034Z",
"completed_at": "2025-05-03T21:42:32.136650Z",
"score": 2,
"total_questions": 10,
"responses": [
{
"id": 1,
"question_type": "coding",
"question_id": 55,
"user_response": "<your code string>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 2,
"question_type": "coding",
"question_id": 56,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 3,
"question_type": "coding",
"question_id": 57,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 4,
"question_type": "coding",
"question_id": 58,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 5,
"question_type": "coding",
"question_id": 59,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 6,
"question_type": "coding",
"question_id": 60,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 7,
"question_type": "coding",
"question_id": 61,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 8,
"question_type": "coding",
"question_id": 62,
"user_response": "<your theory answer text>",
"is_correct": false,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 9,
"question_type": "theory",
"question_id": 39,
"user_response": "The `using` statement in C# is used to ensure that an object implementing the `IDisposable` interface is automatically disposed of when it's no longer needed. It helps in resource management by guaranteeing that the `Dispose()` method is called, releasing unmanaged resources like file handles, database connections, or network streams as soon as they go out of scope—either normally or due to an exception. This prevents resource leaks and promotes clean, efficient code without requiring manual cleanup in `try...finally` blocks.",
"is_correct": true,
"created_at": "2025-05-03T21:42:32.132651Z"
},
{
"id": 10,
"question_type": "theory",
"question_id": 40,
"user_response": "The using statement in C# ensures automatic disposal of objects that implement IDisposable, guaranteeing deterministic cleanup of unmanaged resources (e.g., file handles, database connections). It simplifies resource management by calling Dispose() implicitly when exiting the block, even during exceptions, avoiding leaks. Variables declared in a using block are scoped to it, preventing misuse afterward. Available as a concise statement (C# 8.0+) or traditional block syntax, it streamlines code while enforcing safe, efficient resource handling.",
"is_correct": true,
"created_at": "2025-05-03T21:42:32.132651Z"
}
]
}- Endpoint:
DELETE /api/expertise-levels/{id}/ - Description: Delete a specific expertise level by ID.
Set DEBUG=1 in your .env file and run:
python manage.py runserver-
interface/: Main applicationmodels.py: Database modelsviews.py: API view functionsurls.py: URL routinggeneration_utils.py: Question generation utilitiesembeddings.py: Vector embedding utilitiesmanagement/commands/: Custom management commands
-
project/: Django project configurationsettings.py: Global settingsurls.py: Root URL configuration
gunicorn project.wsgi -b 0.0.0.0:8000- Copy deployment files
cp deploy/dev/* .- Start containers with database
docker-compose -f docker-compose-sql.yml up -dOr without database if configured externally:
docker-compose -f docker-compose.yml up -d- Stop containers
docker-compose downThe project uses pytest for testing:
pytestTest configuration is in pytest.ini. Environment variables for testing can be set in .test.env.
If you encounter errors with OpenAI embeddings, check:
- Your API key is valid and has sufficient credits
- You're using the correct OpenAI library version
- For v1.0.0+: Update
embeddings.pyto use the client-based approach - For older versions: Downgrade to v0.28 with
pip install openai==1.63.2
- For v1.0.0+: Update
If you see errors like "invalid input syntax for type vector", ensure:
- The embedding format uses square brackets
[...]instead of curly braces{...} - The pgvector extension is properly installed in PostgreSQL
If quiz creation fails, check:
- Sufficient questions exist for the selected language/level
- The OpenAI API is responding correctly
- Database connections are working
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch:
git checkout -b feature-name - Commit your changes:
git commit -m 'Add some feature' - Push to the branch:
git push origin feature-name - Open a pull request
This project is licensed under the MIT License. See the LICENSE file for details.