Skip to content

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 returned

Production 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 params

Code 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 output

Submission 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.py

Session 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

Released under the MIT License.