Skip to content

Latest commit

 

History

History
245 lines (203 loc) · 6.48 KB

File metadata and controls

245 lines (203 loc) · 6.48 KB

Judge0 Integration Fix - Before & After Comparison

Problem Analysis

Issues Fixed

  1. Hardcoded Language: Only C++ was supported (language_id='52')
  2. Incomplete Status Handling: Only handled Accepted (3) and Wrong Answer (4)
  3. No Error Handling: API failures caused crashes without user feedback
  4. Invalid Field Name: Used 'inputs' instead of 'stdin' for Judge0 API
  5. No Language Tracking: Database didn't record which language was used

Solution Overview

1. Multi-Language Support

Before:

case['language_id'] = '52'  # C++ TODO: make dynamic

After:

# 11 languages supported with dropdown selector
language_id = form.language.data  # Dynamic from user selection
case['language_id'] = language_id

Languages Added:

  • Python (71)
  • Java (62)
  • C++ (54)
  • C (50)
  • JavaScript (63)
  • Kotlin (78)
  • Go (60)
  • Ruby (72)
  • Rust (73)
  • SQL (82)
  • TypeScript (74)

2. Status Code Handling

Before:

if submission_data['status']['id'] == 3:
    results.append('Accepted')
if submission_data['status']['id'] == 4:
    results.append('Wrong Answer')

After:

# Comprehensive status handling (14 status codes)
if status_id == 3:
    results.append('Accepted')
elif status_id == 4:
    results.append('Wrong Answer')
elif status_id == 5:
    results.append('Time Limit Exceeded')
elif status_id == 6:
    results.append('Compilation Error')
elif status_id in [7, 8, 9, 10, 11, 12]:
    results.append('Runtime Error')
elif status_id == 13:
    results.append('Internal Error')
elif status_id == 14:
    results.append('Exec Format Error')

Status Indicators:

Status Before After
Accepted
Wrong Answer
Compilation Error 💥 💥
Time Limit Exceeded ⚙️ ⏱️
Runtime Error ⚙️ 💣
Internal/Format Error ⚙️
Processing ⚙️ ⚙️

3. Error Handling

Before:

# No error handling - crashes on API failure
conn.request("POST", "/submissions/batch?base64_encoded=true", payload, headers)
res = conn.getresponse()
data = res.read()
tokens = []
for d in json.loads(data.decode("utf-8")):
    if 'token' in d:
        tokens.append(d['token'])
    else:
        tokens.append(None)

After:

try:
    conn.request("POST", "/submissions/batch?base64_encoded=true", payload, headers)
    res = conn.getresponse()
    data = res.read()
    response_text = data.decode("utf-8")
    
    # Validate JSON parsing
    try:
        response_data = json.loads(response_text)
    except json.JSONDecodeError as e:
        flash('Error communicating with Judge0 API. Please try again.', 'danger')
        return redirect(url_for('show_prob', prob_id=prob_id))
    
    # Validate response structure
    if not isinstance(response_data, list):
        flash('Unexpected response from Judge0 API. Please try again.', 'danger')
        return redirect(url_for('show_prob', prob_id=prob_id))
    
    # Check for valid tokens
    if all(token is None for token in tokens):
        flash('Failed to submit code to Judge0. Please check your code and try again.', 'danger')
        return redirect(url_for('show_prob', prob_id=prob_id))

except http.client.HTTPException as e:
    flash('Connection error with Judge0 API. Please try again.', 'danger')
    return redirect(url_for('show_prob', prob_id=prob_id))
except Exception as e:
    flash('An unexpected error occurred. Please try again.', 'danger')
    return redirect(url_for('show_prob', prob_id=prob_id))

4. UI Improvements

Before:

  • No language selection
  • Code editor always in C++ mode

After:

  • Language dropdown selector
  • Dynamic editor syntax highlighting
  • Synced with selected language

JavaScript Enhancement:

// Change editor mode when language is selected
languageSelect.addEventListener('change', function() {
    var selectedLanguage = this.value;
    var mode = languageModes[selectedLanguage] || 'c_cpp';
    editor.session.setMode("ace/mode/" + mode);
});

5. Database Schema

Before:

class Submission(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, ...)
    problem_id = db.Column(db.Integer, ...)
    # No language tracking

After:

class Submission(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, ...)
    problem_id = db.Column(db.Integer, ...)
    language_id = db.Column(db.String(10), nullable=False, default='54')  # Track language

6. API Compliance

Before:

case['inputs'] = f.read()  # Wrong field name

After:

case['stdin'] = f.read()  # Correct Judge0 API field

Testing Results

All validation tests passed ✅:

  • ✓ Language field exists in Code form
  • ✓ Found 11 language choices
  • ✓ Expected languages found in choices
  • ✓ All important status codes (3-14) are mapped
  • ✓ All form languages have editor mode mappings
  • ✓ Submission model has language_id column

Impact

User Experience

  • ✅ Can now submit solutions in 11 different languages
  • ✅ Clear error messages when API fails
  • ✅ Better status indicators for different failure types
  • ✅ Syntax highlighting matches selected language

Code Quality

  • ✅ Proper exception handling prevents crashes
  • ✅ Validates API responses before processing
  • ✅ Complies with Judge0 API specification
  • ✅ Tracks submission metadata for analytics

Maintainability

  • ✅ Status codes mapped in constant dictionary
  • ✅ Language modes centralized
  • ✅ Migration script for database updates
  • ✅ Comprehensive documentation

Files Changed

  1. bemo/forms.py (+14 lines)
  2. bemo/routes.py (+150 lines, refactored submission handling)
  3. bemo/models.py (+1 field)
  4. bemo/templates/problem.html (+40 lines for language selector and JS)
  5. migrate_add_language.py (new, 28 lines)
  6. JUDGE0_IMPROVEMENTS.md (new, documentation)
  7. .gitignore (+2 lines)

Migration Path

For existing installations:

# 1. Pull changes
git pull

# 2. Run migration
python migrate_add_language.py

# 3. Restart application
python run.py

Future Enhancements

Potential improvements for later:

  • Move API key to environment variables
  • Add per-language time limits
  • Support custom test case generation
  • Add code snippet templates for each language
  • Implement language-specific linting
  • Add submission history filtering by language