{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "0ed000fc-5884-4d56-a94c-c6bf2722c173",
      "name": "Webhook - Upload Test Paper",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -1872,
        -464
      ],
      "parameters": {
        "path": "grade-assignment",
        "options": {
          "rawBody": true
        },
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "14bf826a-9bba-410c-9482-2578ea26b949",
      "name": "Extract Text from Test Paper",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -1648,
        -464
      ],
      "parameters": {
        "options": {},
        "operation": "pdf"
      },
      "typeVersion": 1
    },
    {
      "id": "7acd4df7-f43b-480c-a7a3-2ea497c6ad2e",
      "name": "Prepare Assignment Data",
      "type": "n8n-nodes-base.set",
      "position": [
        -1424,
        -464
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "studentName",
              "name": "studentName",
              "type": "string",
              "value": "={{ $json.body.studentName || 'Unknown Student' }}"
            },
            {
              "id": "assignmentTitle",
              "name": "assignmentTitle",
              "type": "string",
              "value": "={{ $json.body.assignmentTitle || 'Engineering Assignment' }}"
            },
            {
              "id": "testPaperText",
              "name": "testPaperText",
              "type": "string",
              "value": "={{ $('Extract Text from Test Paper').item.json.data }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "243a790d-0757-4814-83d0-4d3733dc15aa",
      "name": "Load Answer Script",
      "type": "n8n-nodes-base.set",
      "position": [
        -1200,
        -464
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "answerScript",
              "name": "answerScript",
              "type": "string",
              "value": "=Question 1: Explain Ohm's Law and its applications (10 marks)\nAnswer: Ohm's Law states V=IR where V is voltage, I is current, R is resistance. Applications include circuit design, electrical troubleshooting, power calculations.\n\nQuestion 2: Describe the working principle of a DC motor (15 marks)\nAnswer: DC motor converts electrical energy to mechanical energy using electromagnetic induction. Current through armature creates magnetic field that interacts with stator field causing rotation.\n\nQuestion 3: Calculate stress in a beam under load (20 marks)\nAnswer: Stress = Force/Area. For bending stress: \u03c3 = My/I where M is moment, y is distance from neutral axis, I is moment of inertia.\n\nQuestion 4: Explain thermodynamic cycles (15 marks)\nAnswer: Common cycles include Carnot, Otto, Diesel, Rankine. Each involves heat addition, expansion, heat rejection, compression stages for energy conversion.\n\nQuestion 5: Discuss Boolean algebra and logic gates (10 marks)\nAnswer: Boolean algebra uses AND, OR, NOT operations. Logic gates implement these: AND gate outputs 1 only when all inputs are 1, OR gate outputs 1 when any input is 1."
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "a3932528-d56a-49c1-9242-c26cf539f43f",
      "name": "AI Agent - Grade Assignment",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -976,
        -464
      ],
      "parameters": {
        "text": "=You are an expert engineering professor grading student assignments. \n\nANSWER SCRIPT (Correct Answers with Marks):\n{{ $json.answerScript }}\n\nSTUDENT SUBMISSION:\n{{ $json.testPaperText }}\n\nGrade this engineering assignment by:\n1. Comparing student answers against the answer script\n2. Award marks based on correctness, completeness, and technical accuracy\n3. Provide detailed feedback for each question\n4. Calculate total marks obtained\n\nProvide output in this JSON format:\n{\n  \"questions\": [\n    {\n      \"questionNumber\": 1,\n      \"maxMarks\": 10,\n      \"marksObtained\": 8,\n      \"feedback\": \"Good explanation of Ohm's Law but missing practical examples\"\n    }\n  ],\n  \"totalMarks\": 70,\n  \"totalObtained\": 55,\n  \"percentage\": 78.57,\n  \"grade\": \"B+\",\n  \"overallFeedback\": \"Strong understanding of core concepts with room for improvement in practical applications\"\n}",
        "options": {
          "systemMessage": "You are a precise grading assistant. Always return valid JSON only."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.7
    },
    {
      "id": "27d5f8e7-2af0-4df9-9420-0eca38b94e04",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        -832,
        -240
      ],
      "parameters": {},
      "typeVersion": 1.2
    },
    {
      "id": "95194943-b7c5-4a0c-a2f5-a0a9ab3243b9",
      "name": "Generate Results Table",
      "type": "n8n-nodes-base.code",
      "position": [
        -624,
        -464
      ],
      "parameters": {
        "jsCode": "const gradingResult = $input.first().json;\nconst studentName = $('Prepare Assignment Data').first().json.studentName;\nconst assignmentTitle = $('Prepare Assignment Data').first().json.assignmentTitle;\n\n// Create HTML table\nlet htmlTable = `\n<h2>Grading Report: ${assignmentTitle}</h2>\n<h3>Student: ${studentName}</h3>\n<table border=\"1\" cellpadding=\"10\" cellspacing=\"0\" style=\"border-collapse: collapse; width: 100%;\">\n  <thead>\n    <tr style=\"background-color: #4CAF50; color: white;\">\n      <th>Question</th>\n      <th>Max Marks</th>\n      <th>Marks Obtained</th>\n      <th>Feedback</th>\n    </tr>\n  </thead>\n  <tbody>\n`;\n\ngradingResult.questions.forEach(q => {\n  htmlTable += `\n    <tr>\n      <td>Question ${q.questionNumber}</td>\n      <td>${q.maxMarks}</td>\n      <td>${q.marksObtained}</td>\n      <td>${q.feedback}</td>\n    </tr>\n  `;\n});\n\nhtmlTable += `\n  </tbody>\n  <tfoot>\n    <tr style=\"background-color: #f2f2f2; font-weight: bold;\">\n      <td>TOTAL</td>\n      <td>${gradingResult.totalMarks}</td>\n      <td>${gradingResult.totalObtained}</td>\n      <td>Grade: ${gradingResult.grade} (${gradingResult.percentage.toFixed(2)}%)</td>\n    </tr>\n  </tfoot>\n</table>\n<p><strong>Overall Feedback:</strong> ${gradingResult.overallFeedback}</p>\n`;\n\n// Create CSV data\nlet csvData = \"Question,Max Marks,Marks Obtained,Feedback\\n\";\ngradingResult.questions.forEach(q => {\n  csvData += `\"Question ${q.questionNumber}\",${q.maxMarks},${q.marksObtained},\"${q.feedback.replace(/\"/g, '\"\"')}\"\\n`;\n});\ncsvData += `\"TOTAL\",${gradingResult.totalMarks},${gradingResult.totalObtained},\"Grade: ${gradingResult.grade} (${gradingResult.percentage.toFixed(2)}%)\"\\n`;\n\nreturn {\n  studentName,\n  assignmentTitle,\n  htmlTable,\n  csvData,\n  gradingResult,\n  summary: `${studentName} scored ${gradingResult.totalObtained}/${gradingResult.totalMarks} (${gradingResult.percentage.toFixed(2)}%) - Grade: ${gradingResult.grade}`\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "26226c89-7643-472c-9fea-b14e2370eb63",
      "name": "Convert to CSV File",
      "type": "n8n-nodes-base.convertToFile",
      "position": [
        -176,
        -464
      ],
      "parameters": {
        "options": {},
        "binaryPropertyName": "=result-{{ $json.body.studentName || 'Unknown Student' }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "da46bbc9-f392-4c18-b2e8-2c84506854dd",
      "name": "Prepare CSV Data",
      "type": "n8n-nodes-base.set",
      "position": [
        -400,
        -464
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "data",
              "name": "data",
              "type": "string",
              "value": "={{ $('Generate Results Table').first().json.csvData }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "2eb6444f-ec80-4d99-9cda-16f3ffdb908b",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        -976,
        -240
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "2d334fb3-448f-4bcf-b6ee-5516c1aef5ae",
      "name": "Upload file",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        48,
        -464
      ],
      "parameters": {
        "name": "=result-{{ $json.body.studentName || 'Unknown Student' }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "root",
          "cachedResultName": "/ (Root folder)"
        },
        "inputDataFieldName": "result-{{ $json.body.studentName || 'Unknown Student' }}"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "9b832100-ecbc-4d17-bba2-5039bdfa4157",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2560,
        -768
      ],
      "parameters": {
        "width": 560,
        "height": 464,
        "content": "## AI Assignment Grader\n\n\n### How it works\n1. The workflow triggers when a student's test paper is uploaded via a webhook.\n2. It extracts text from the uploaded PDF and loads a predefined answer script.\n3. An AI model compares the student's submission against the correct answers, providing detailed feedback, marks per question, and a total score.\n4. A comprehensive grading report is generated in both HTML and CSV formats.\n5. The CSV grading report is then uploaded to your specified Google Drive folder.\n\n\n### Setup\n- [ ] Connect your Google Gemini account.\n- [ ] Connect your Google Drive account.\n- [ ] Configure the Webhook URL to receive test paper submissions.\n- [ ] Adjust the 'Load Answer Script' node with your specific assignment's correct answers and marking scheme.\n- [ ] Select the target Google Drive folder for saving graded reports."
      },
      "typeVersion": 1
    },
    {
      "id": "3f2f4532-bb4b-4f3a-8593-52f998c2b1de",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1936,
        -544
      ],
      "parameters": {
        "color": 7,
        "width": 656,
        "height": 288,
        "content": "## Get question paper\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b85e3a83-db4b-4b30-943c-c1a5521a275c",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1216,
        -544
      ],
      "parameters": {
        "color": 7,
        "width": 736,
        "height": 464,
        "content": "## check answers "
      },
      "typeVersion": 1
    },
    {
      "id": "a63b898a-15a8-4c45-a741-6aaffc075733",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -464,
        -544
      ],
      "parameters": {
        "color": 7,
        "width": 704,
        "height": 256,
        "content": "## upload result to drive"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Prepare CSV Data": {
      "main": [
        [
          {
            "node": "Convert to CSV File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load Answer Script": {
      "main": [
        [
          {
            "node": "AI Agent - Grade Assignment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to CSV File": {
      "main": [
        [
          {
            "node": "Upload file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Results Table": {
      "main": [
        [
          {
            "node": "Prepare CSV Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Assignment Data": {
      "main": [
        [
          {
            "node": "Load Answer Script",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent - Grade Assignment",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent - Grade Assignment",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent - Grade Assignment": {
      "main": [
        [
          {
            "node": "Generate Results Table",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook - Upload Test Paper": {
      "main": [
        [
          {
            "node": "Extract Text from Test Paper",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Text from Test Paper": {
      "main": [
        [
          {
            "node": "Prepare Assignment Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}