From 7c5acbd823ebbd98fc49b8d0627a03a4dd9695fa Mon Sep 17 00:00:00 2001 From: ectasy663 Date: Thu, 9 Jul 2026 18:03:35 +0530 Subject: [PATCH] Fix admin tests endpoint to create_manual and fix language enum from EN to English --- admin_json_samples.md | 116 +++++++++++++++++++++++++++++++++++ generate_jee_json.py | 60 ++++++++++++++++++ src/app/admin/tests/page.tsx | 4 +- 3 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 admin_json_samples.md create mode 100644 generate_jee_json.py diff --git a/admin_json_samples.md b/admin_json_samples.md new file mode 100644 index 0000000..960815f --- /dev/null +++ b/admin_json_samples.md @@ -0,0 +1,116 @@ +# Question JSON Format Documentation + +When uploading a full JSON structure for an Examination from the Admin Panel, the `questions` array inside each section must be perfectly structured. This document illustrates how to structure questions for different types: **Single Choice**, **Multiple Choice (Multi-Correct)**, **Numerical**, and **Subjective**. + +> [!WARNING] +> The database strictly expects `correct_answer` to be a JSON object, usually in the format `{"value": }`. Do not provide a raw string or array. + +## 1. Single Choice (Objective) +The standard four-option multiple choice question with one correct answer. + +```json +{ + "id": "q1-uuid-here", + "topic": "Physics", + "subtopic": "Kinematics", + "subject": "Physics", + "type": "Single_Choice", + "question_text": "A car accelerates from rest to 20 m/s in 5 seconds. What is its acceleration?", + "question_text_hi": "एक कार 5 सेकंड में आराम से 20 मीटर/सेकंड तक गति पकड़ती है। इसका त्वरण क्या है?", + "options": { + "A": "4 m/s²", + "B": "5 m/s²", + "C": "2 m/s²", + "D": "10 m/s²" + }, + "options_hi": { + "A": "4 m/s²", + "B": "5 m/s²", + "C": "2 m/s²", + "D": "10 m/s²" + }, + "correct_answer": { + "value": "A" + }, + "solution_text": "Using v = u + at, we get 20 = 0 + a(5) => a = 4 m/s².", + "solution_text_hi": "v = u + at का उपयोग करने पर, हमें 20 = 0 + a(5) => a = 4 m/s² प्राप्त होता है।", + "language": "English" +} +``` + +## 2. Multiple Choice (Multi-Correct) +A question where more than one option is correct. The user will be able to select multiple checkboxes. + +```json +{ + "id": "q2-uuid-here", + "topic": "Mathematics", + "subtopic": "Calculus", + "subject": "Mathematics", + "type": "Multiple_Choice", + "question_text": "Which of the following functions are continuous at $x = 0$?", + "question_text_hi": "निम्नलिखित में से कौन से फलन $x = 0$ पर सतत हैं?", + "options": { + "A": "$f(x) = |x|$", + "B": "$f(x) = \\frac{1}{x}$", + "C": "$f(x) = x^2$", + "D": "$f(x) = \\tan(x)$" + }, + "options_hi": { + "A": "$f(x) = |x|$", + "B": "$f(x) = \\frac{1}{x}$", + "C": "$f(x) = x^2$", + "D": "$f(x) = \\tan(x)$" + }, + "correct_answer": { + "value": ["A", "C", "D"] + }, + "solution_text": "$|x|$, $x^2$, and $\\tan(x)$ are continuous at $x = 0$. $\\frac{1}{x}$ is undefined.", + "language": "English" +} +``` + +## 3. Numerical (Fill in the blanks) +A question expecting a purely numerical value as an answer. The UI renders a single-line input box. + +```json +{ + "id": "q3-uuid-here", + "topic": "Chemistry", + "subtopic": "Thermodynamics", + "subject": "Chemistry", + "type": "Numerical", + "question_text": "Calculate the work done (in Joules) when a gas expands from 1L to 3L against a constant external pressure of 1 atm. (Use $1 L \\cdot atm = 101.3 J$)", + "question_text_hi": "1 atm के निरंतर बाहरी दबाव के खिलाफ 1L से 3L तक गैस के विस्तार पर किए गए कार्य (जूल में) की गणना करें।", + "options": null, + "options_hi": null, + "correct_answer": { + "value": "-202.6" + }, + "solution_text": "$W = -P_{ext} \\Delta V = -1 \\text{ atm} \\times (3L - 1L) = -2 \\text{ L atm} = -202.6 \\text{ J}$", + "language": "English" +} +``` + +## 4. Subjective +A question expecting a long descriptive text or derivation. The UI renders a large text area. +Note: For subjective questions, the backend awards points if the submitted text is greater than 5 characters (since manual grading is required for strict correctness). + +```json +{ + "id": "q4-uuid-here", + "topic": "Physics", + "subtopic": "Electromagnetism", + "subject": "Physics", + "type": "Subjective", + "question_text": "State Gauss's Law in electrostatics and derive the electric field due to an infinitely long straight charged wire.", + "question_text_hi": "स्थिरविद्युतिकी में गॉस के नियम को बताएँ और एक असीमित लंबे सीधे आवेशित तार के कारण विद्युत क्षेत्र व्युत्पन्न करें।", + "options": null, + "options_hi": null, + "correct_answer": { + "value": "Subjective" + }, + "solution_text": "Gauss's law states that the net electric flux through any closed surface is equal to $\\frac{1}{\\varepsilon_0}$ times the net electric charge enclosed within that closed surface...", + "language": "English" +} +``` diff --git a/generate_jee_json.py b/generate_jee_json.py new file mode 100644 index 0000000..21a5d44 --- /dev/null +++ b/generate_jee_json.py @@ -0,0 +1,60 @@ +import json +import uuid +import random + +subjects = ["Physics", "Chemistry", "Mathematics"] +types = ["Single_Choice", "Multiple_Choice", "Numerical"] + +questions = [] + +for subject in subjects: + for i in range(30): + q_type = types[i % 3] # Distribute 10 Single, 10 Multi, 10 Num + + q = { + "id": str(uuid.uuid4()), + "section": "General", + "subject": subject, + "topic": f"{subject} Topic {i//5 + 1}", + "subtopic": f"{subject} Subtopic {(i%5) + 1}", + "difficulty": random.choice(["Medium", "Hard"]), + "type": q_type, + "language": "English" + } + + if q_type == "Single_Choice": + q["question_text"] = f"A sample Single Choice question for {subject} #{i+1}." + q["options"] = { + "A": "Option 1", + "B": "Option 2", + "C": "Option 3", + "D": "Option 4" + } + q["correct_answer"] = {"value": "A"} + q["solution_text"] = "Explanation for this single choice question." + + elif q_type == "Multiple_Choice": + q["question_text"] = f"Which of the following are correct for {subject} #{i+1}?" + q["options"] = { + "A": "Statement P is correct", + "B": "Statement Q is incorrect", + "C": "Statement R is correct", + "D": "Statement S is incorrect" + } + q["correct_answer"] = {"value": ["A", "C"]} + q["solution_text"] = "A and C are correct because..." + + elif q_type == "Numerical": + q["question_text"] = f"Calculate the required value for {subject} #{i+1}." + q["options"] = None + q["correct_answer"] = {"value": "42.5"} + q["solution_text"] = "Applying the formula yields 42.5." + + questions.append(q) + +payload = questions + +with open("jee_advanced_full_90q.json", "w") as f: + json.dump(payload, f, indent=2) + +print("Generated jee_advanced_full_90q.json") diff --git a/src/app/admin/tests/page.tsx b/src/app/admin/tests/page.tsx index a78a561..b1e6b1b 100644 --- a/src/app/admin/tests/page.tsx +++ b/src/app/admin/tests/page.tsx @@ -45,7 +45,7 @@ export default function AdminTestsPage() { const handleToggle = async (testId: string) => { try { - const res = await fetch(`http://localhost:8000/api/admin/tests/${testId}/toggle`, { + const res = await fetch(`/api/admin/tests/${testId}/toggle`, { method: "PUT" }) if (res.ok) { @@ -83,7 +83,7 @@ export default function AdminTestsPage() { }; try { - const res = await fetch("/api/admin/tests/upload", { + const res = await fetch("/api/admin/tests/create_manual", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload)