| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8" /> |
| <meta name="viewport" content="width=device-width,initial-scale=1" /> |
| <title>Score Predictor Chatbot</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| </head> |
| <body class="bg-gray-100"> |
| <div class="max-w-md mx-auto py-6"> |
| <div id="chatbox" |
| class="bg-white p-4 rounded-lg shadow-lg h-[500px] overflow-y-auto space-y-3"> |
| </div> |
| <div class="mt-3 flex"> |
| <input id="userInput" type="text" |
| class="flex-1 p-2 border border-gray-300 rounded-l-md" |
| placeholder="Type here…" autocomplete="off" /> |
| <button id="sendBtn" |
| class="bg-blue-600 px-4 text-white rounded-r-md"> |
| Send |
| </button> |
| </div> |
| </div> |
|
|
| <script> |
| const fields = {{ fields | tojson }}; |
| let idx = -1; |
| const answers = {}; |
| const chatbox = document.getElementById("chatbox"); |
| const input = document.getElementById("userInput"); |
| const btn = document.getElementById("sendBtn"); |
| |
| function addMessage(txt, who="bot") { |
| const div = document.createElement("div"); |
| div.className = who==="bot" |
| ? "text-left text-gray-800" |
| : "text-right text-blue-700"; |
| div.innerText = txt; |
| chatbox.appendChild(div); |
| chatbox.scrollTop = chatbox.scrollHeight; |
| } |
| |
| function askNext() { |
| idx++; |
| if (idx === 0) { |
| addMessage("👋 Welcome! I’ll ask a few quick questions to predict your final exam score. Let’s begin!"); |
| setTimeout(askNext, 800); |
| return; |
| } |
| const i = idx - 1; |
| if (i < fields.length) { |
| let q = fields[i].question; |
| if (fields[i].type==="select") { |
| q += " Options: " + fields[i].options.join(", "); |
| } |
| if (fields[i].type==="number" && fields[i].validation) { |
| q += ` (Enter a number between ${fields[i].validation.min} and ${fields[i].validation.max})`; |
| } |
| addMessage(q); |
| } else { |
| addMessage("Calculating your predicted score…"); |
| fetch("/predict_json", { |
| method: "POST", |
| headers: {"Content-Type":"application/json"}, |
| body: JSON.stringify(answers) |
| }) |
| .then(r=>r.json()) |
| .then(d=>{ |
| addMessage(`🎯 Your predicted score is: ${d.predicted}`); |
| }) |
| .catch(e=>{ |
| addMessage("⚠️ Something went wrong. Please try again."); |
| }); |
| } |
| } |
| |
| btn.onclick = () => { |
| const text = input.value.trim(); |
| if (!text) return; |
| const i = idx - 1; |
| |
| if (i >= 0 && i < fields.length) { |
| const f = fields[i]; |
| if (f.type==="number") { |
| const n = parseFloat(text); |
| if (isNaN(n) || (f.validation && (n < f.validation.min || n > f.validation.max))) { |
| addMessage(`⚠️ Enter a number between ${f.validation.min} and ${f.validation.max}.`, "bot"); |
| input.value = ""; |
| return; |
| } |
| answers[f.name] = n; |
| } else if (f.type==="select") { |
| if (!f.options.includes(text)) { |
| addMessage(`⚠️ Please choose one of: ${f.options.join(", ")}`, "bot"); |
| input.value = ""; |
| return; |
| } |
| answers[f.name] = text; |
| } |
| } |
| addMessage(text, "user"); |
| input.value = ""; |
| askNext(); |
| }; |
| |
| |
| askNext(); |
| </script> |
| </body> |
| </html> |
|
|