Data Flow
How data moves through the Gradescope Submitter system.
Demo Flow (Current Implementation)
The demo flow simulates the D2L integration without requiring actual LTI setup.
┌─────────────┐
│ mockD2L.html│ User opens demo page
└──────┬──────┘
│
▼
┌─────────────┐
│ Quiz.html │ Simulated quiz with iframe
└──────┬──────┘
│
▼
┌─────────────┐
│ login.html │ Gradescope sign-in prompt
└──────┬──────┘
│ User clicks "Open Gradescope"
▼
┌─────────────────┐
│ codemirror- │ Code editor loads
│ demo.html │
└──────┬──────────┘
│
├─── Run Code ───► Pyodide executes locally
│ └─► Output displayed
│
└─── Submit ─────► POST /submit
└─► Gradescope API
└─► Submission URL returnedProduction Flow (With LTI)
The production flow uses LTI 1.3 for secure authentication.
┌─────────────────┐
│ D2L Brightspace │ Student accesses quiz
└──────┬──────────┘
│
│ LTI 1.3 Launch Request
▼
┌─────────────────┐
│ POST /lti/launch│ Server validates LTI payload
└──────┬──────────┘
│
├─── Invalid ───► Error response
│
└─── Valid ─────► Extract student info
│
▼
┌─────────────────┐
│ Check session │
└──────┬──────────┘
│
├─── No session ───► Redirect to login
│
└─── Has session ──► Redirect to editor
with context paramsCode Execution Flow
When a student clicks "Run Code":
┌─────────────┐
│ User clicks │
│ "Run Code" │
└──────┬──────┘
│
▼
┌─────────────────┐
│ Get code from │
│ CodeMirror │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Switch to │
│ Output tab │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Parse code │ Check for syntax errors
│ with AST │
└──────┬──────────┘
│
├─── Syntax Error ───► Display error, stop
│
└─── Valid ──────────► Transform input() calls
│
▼
┌─────────────────┐
│ Execute with │
│ Pyodide │
└──────┬──────────┘
│
├─── input() called ───► Show input field
│ Wait for user
│ Continue execution
│
├─── print() called ───► Append to output
│
├─── Runtime error ────► Display traceback
│
└─── Complete ─────────► Show final outputSubmission Flow
When a student clicks "Submit Code":
┌─────────────┐
│ User clicks │
│ "Submit" │
└──────┬──────┘
│
▼
┌─────────────────┐
│ Collect form │ code, email, stud_id, asg_id, file_name
│ data │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ POST /submit │ Send to Express server
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Server receives │
│ request │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Validate │ Check required fields
│ request │
└──────┬──────────┘
│
├─── Invalid ───► Return 400 error
│
└─── Valid ─────► Call submitAssg()
│
▼
┌─────────────────┐
│ Build FormData │
│ with code file │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ POST to │
│ Gradescope API │
└──────┬──────────┘
│
├─── Error ───► Return 500 with error
│
└─── Success ─► Return submission URL
│
▼
┌─────────────────┐
│ Client shows │
│ success + link │
└─────────────────┘Data Structures
Submission Request
json
{
"code": "print('Hello')",
"email": "student@school.edu",
"stud_id": "900123456",
"asg_id": "6617143",
"file_name": "program.py"
}Submission Response
json
{
"success": true,
"url": "https://gradescope.com/courses/.../submissions/..."
}LTI Claims
json
{
"sub": "user-123",
"email": "student@school.edu",
"name": "Student Name",
"https://purl.imsglobal.org/spec/lti/claim/custom": {
"asg_id": "6617143",
"file_name": "program.py"
}
}State Management
URL Parameters
Context passed via URL query string:
?email=student@school.edu&asg_id=6617143&file_name=program.py&starter=lab1.pySession Storage
Minimal server-side state:
- Student Gradescope credentials (in-memory)
- State tokens for auth flow (temporary)
No Persistent Storage
- No database
- No file-based sessions
- State reconstructed from URL on each load