File size: 4,277 Bytes
0222dab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <title>Score Predictor + Groq Chatbot</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <style>
    .message-enter {
      animation: fadeIn 0.3s ease-in-out;
    }
    @keyframes fadeIn {
      from { opacity: 0; transform: translateY(4px); }
      to { opacity: 1; transform: translateY(0); }
    }
  </style>
</head>
<body class="bg-gradient-to-br from-blue-100 to-white min-h-screen font-sans">
  <div class="max-w-md mx-auto py-8 px-4">
    <div id="chatbox"
         class="bg-white p-4 rounded-lg shadow-xl h-[500px] overflow-y-auto space-y-3 border border-gray-200">
    </div>

    <div class="mt-3 flex sticky bottom-0 bg-white rounded-md shadow-md">
      <input id="userInput" type="text"
             class="flex-1 p-3 border border-r-0 border-gray-300 rounded-l-md focus:outline-none focus:ring-2 focus:ring-blue-400"
             placeholder="Type your answer..." autocomplete="off" />
      <button id="sendBtn"
              class="bg-blue-600 hover:bg-blue-700 transition-colors px-5 text-white font-semibold 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 = `message-enter px-3 py-2 rounded-lg max-w-[80%] ${
        who === "bot"
          ? "bg-gray-100 text-gray-900 self-start"
          : "bg-blue-600 text-white self-end ml-auto"
      }`;
      div.innerText = txt;

      const wrapper = document.createElement("div");
      wrapper.className = "flex flex-col";
      wrapper.appendChild(div);

      chatbox.appendChild(wrapper);
      chatbox.scrollTop = chatbox.scrollHeight;
    }

    function askNext() {
      idx++;
      if (idx === 0) {
        addMessage("👋 Hello! I’ll ask 18 quick questions to predict your exam score—and then give personalized improvement tips.");
        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 ${fields[i].validation.min}${fields[i].validation.max})`;
        }
        addMessage(q);
      } else {
        addMessage("🔄 Computing your predicted score and fetching advice…");
        fetch("/predict_json", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(answers)
        })
        .then(r => r.json())
        .then(d => {
          addMessage(`🎯 Predicted Score: ${d.predicted}`);
          setTimeout(() => addMessage(`💡 Improvement Tips:\n${d.advice}`), 500);
        })
        .catch(() => {
          addMessage("⚠️ Something went wrong. Please refresh and 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(`⚠️ Please 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(`⚠️ Choose one of: ${f.options.join(", ")}`, "bot");
            input.value = "";
            return;
          }
          answers[f.name] = text;
        }
      }
      addMessage(text, "user");
      input.value = "";
      askNext();
    };

    askNext();
  </script>
</body>
</html>