Files changed (5) hide show
  1. README.md +4 -5
  2. app.py +106 -0
  3. gitattributes +35 -0
  4. index.html +363 -0
  5. requirements.txt +2 -0
README.md CHANGED
@@ -1,11 +1,10 @@
1
  ---
2
  title: Mind Mirror
3
- emoji: 📈
4
- colorFrom: indigo
5
- colorTo: purple
6
  sdk: gradio
7
- sdk_version: 6.16.0
8
- python_version: '3.13'
9
  app_file: app.py
10
  pinned: false
11
  license: apache-2.0
 
1
  ---
2
  title: Mind Mirror
3
+ emoji: 🦀
4
+ colorFrom: purple
5
+ colorTo: green
6
  sdk: gradio
7
+ sdk_version: 6.9.0
 
8
  app_file: app.py
9
  pinned: false
10
  license: apache-2.0
app.py ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ import uvicorn
4
+ import urllib.request
5
+ import urllib.error
6
+ from fastapi import FastAPI, Request
7
+ from fastapi.responses import HTMLResponse, JSONResponse
8
+
9
+ app = FastAPI()
10
+
11
+
12
+ def call_gemini(prompt: str) -> str:
13
+ api_key = os.environ.get("GEMINI_API_KEY", "")
14
+ if not api_key:
15
+ raise ValueError("GEMINI_API_KEY is not set in environment variables")
16
+
17
+ url = (
18
+ "https://generativelanguage.googleapis.com/v1beta/models/"
19
+ "gemini-1.5-flash:generateContent?key=" + api_key
20
+ )
21
+
22
+ payload = json.dumps({
23
+ "contents": [{"parts": [{"text": prompt}]}],
24
+ "generationConfig": {
25
+ "temperature": 0.7,
26
+ "maxOutputTokens": 1000
27
+ }
28
+ }).encode("utf-8")
29
+
30
+ req = urllib.request.Request(
31
+ url,
32
+ data=payload,
33
+ headers={"Content-Type": "application/json"},
34
+ method="POST"
35
+ )
36
+
37
+ try:
38
+ with urllib.request.urlopen(req, timeout=30) as resp:
39
+ data = json.loads(resp.read().decode("utf-8"))
40
+ except urllib.error.HTTPError as e:
41
+ error_body = e.read().decode("utf-8")
42
+ raise ValueError("Gemini HTTP error " + str(e.code) + ": " + error_body)
43
+
44
+ return data["candidates"][0]["content"]["parts"][0]["text"]
45
+
46
+
47
+ @app.post("/analyze")
48
+ async def analyze(request: Request):
49
+ try:
50
+ body = await request.json()
51
+ user_data = body["user_data"]
52
+ answers = body["answers"]
53
+ scores = body["scores"]
54
+
55
+ answers_text = ""
56
+ for a in answers:
57
+ answers_text += "- [" + a["category"] + "] " + a["question"][:60] + "... Answer: " + a["answer"][:50] + "\n"
58
+
59
+ prompt = (
60
+ "You are an expert psychologist and intelligence analyst.\n"
61
+ "Analyze these test results and return a JSON report.\n\n"
62
+ "User: " + user_data["name"] + ", Age " + str(user_data["age"]) + ", " + user_data["edu"] + ", likes " + user_data["interest"] + "\n\n"
63
+ "Scores: Logical=" + str(scores["logical"]) + " Creative=" + str(scores["creative"]) +
64
+ " Spatial=" + str(scores["spatial"]) + " Verbal=" + str(scores["verbal"]) + " Emotional=" + str(scores["emotional"]) + "\n\n"
65
+ "Answers:\n" + answers_text + "\n"
66
+ "Return ONLY valid JSON, no markdown, no backticks, no extra text:\n"
67
+ '{"intel_type":"3-4 sentences about dominant intelligence","scientist_name":"matching historical scientist","scientist_title":"their field","scientist_icon":"emoji","scientist_reason":"2-3 sentences why similar","jobs":["job1","job2","job3","job4"],"jobs_reason":"2 sentences why suitable","advice":"2-3 sentences personal advice"}'
68
+ )
69
+
70
+ text = call_gemini(prompt)
71
+ text = text.replace("```json", "").replace("```", "").strip()
72
+
73
+ # Find JSON in response
74
+ start = text.find("{")
75
+ end = text.rfind("}") + 1
76
+ if start == -1 or end == 0:
77
+ raise ValueError("No JSON found in response: " + text[:200])
78
+
79
+ result = json.loads(text[start:end])
80
+ return JSONResponse(content=result)
81
+
82
+ except Exception as e:
83
+ return JSONResponse(content={"error": str(e)}, status_code=500)
84
+
85
+
86
+ @app.get("/", response_class=HTMLResponse)
87
+ async def root():
88
+ try:
89
+ with open("index.html", "r", encoding="utf-8") as f:
90
+ return f.read()
91
+ except FileNotFoundError:
92
+ return HTMLResponse("<h1>index.html not found</h1>", status_code=404)
93
+
94
+
95
+ @app.get("/health")
96
+ async def health():
97
+ key = os.environ.get("GEMINI_API_KEY", "")
98
+ return {
99
+ "status": "ok",
100
+ "gemini_key_set": bool(key),
101
+ "key_preview": key[:10] + "..." if key else "NOT SET"
102
+ }
103
+
104
+
105
+ if __name__ == "__main__":
106
+ uvicorn.run(app, host="0.0.0.0", port=7860)
gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
index.html ADDED
@@ -0,0 +1,363 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Mind Mirror</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700;900&family=DM+Sans:wght@300;400;500;700&display=swap" rel="stylesheet">
8
+ <style>
9
+ * { margin: 0; padding: 0; box-sizing: border-box; }
10
+ html, body { width: 100%; min-height: 100%; }
11
+ body { background: #0a0a0f; color: #f5f0e8; font-family: 'DM Sans', sans-serif; overflow-x: hidden; }
12
+ body::before {
13
+ content: ''; position: fixed; inset: 0;
14
+ background: radial-gradient(ellipse 80% 50% at 20% 20%, rgba(201,168,76,0.06) 0%, transparent 60%),
15
+ radial-gradient(ellipse 60% 80% at 80% 80%, rgba(100,60,140,0.08) 0%, transparent 60%);
16
+ pointer-events: none; z-index: 0;
17
+ }
18
+ .screen { display: none; position: relative; z-index: 1; min-height: 100vh; padding: 40px 20px; }
19
+ .screen.active { display: flex; flex-direction: column; align-items: center; justify-content: center; }
20
+ #screen-intro { text-align: center; gap: 32px; }
21
+ .logo-ring { width: 100px; height: 100px; border-radius: 50%; border: 2px solid #c9a84c; display: flex; align-items: center; justify-content: center; margin: 0 auto; position: relative; animation: pulse 3s ease-in-out infinite; }
22
+ .logo-ring::before { content: ''; position: absolute; inset: 8px; border-radius: 50%; border: 1px solid rgba(201,168,76,0.3); }
23
+ .logo-icon { font-size: 38px; }
24
+ @keyframes pulse { 0%,100%{box-shadow:0 0 0 0 rgba(201,168,76,0.3)}50%{box-shadow:0 0 0 20px rgba(201,168,76,0)} }
25
+ h1 { font-family: 'Playfair Display', serif; font-size: clamp(2.2rem,6vw,3.5rem); font-weight: 900; line-height: 1.1; color: #f5f0e8; }
26
+ h1 span { color: #c9a84c; }
27
+ .tagline { font-size: 1.1rem; color: #6b6478; max-width: 420px; line-height: 1.7; font-weight: 300; }
28
+ .pills { display: flex; gap: 16px; flex-wrap: wrap; justify-content: center; }
29
+ .pill { background: rgba(255,255,255,0.04); border: 1px solid rgba(201,168,76,0.25); border-radius: 100px; padding: 8px 20px; font-size: 0.85rem; color: #e8d5a0; }
30
+ #screen-form { gap: 24px; max-width: 480px; width: 100%; }
31
+ .form-title { font-family: 'Playfair Display', serif; font-size: 1.8rem; font-weight: 700; text-align: center; color: #f5f0e8; }
32
+ .fg { display: flex; flex-direction: column; gap: 8px; width: 100%; }
33
+ .fg label { font-size: 0.9rem; color: #e8d5a0; font-weight: 500; }
34
+ .fg input, .fg select { background: rgba(255,255,255,0.05); border: 1px solid rgba(201,168,76,0.25); border-radius: 12px; padding: 14px 18px; color: #f5f0e8; font-family: 'DM Sans', sans-serif; font-size: 1rem; outline: none; transition: border-color 0.2s; width: 100%; }
35
+ .fg input:focus, .fg select:focus { border-color: #c9a84c; }
36
+ .fg select option { background: #1a1520; color: #f5f0e8; }
37
+ .btn { background: #c9a84c; color: #0a0a0f; border: none; border-radius: 12px; padding: 16px 40px; font-family: 'DM Sans', sans-serif; font-size: 1.05rem; font-weight: 700; cursor: pointer; transition: all 0.2s; }
38
+ .btn:hover { background: #e8d5a0; transform: translateY(-2px); box-shadow: 0 8px 30px rgba(201,168,76,0.3); }
39
+ .btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }
40
+ #screen-quiz { gap: 32px; max-width: 600px; width: 100%; }
41
+ .prog-wrap { width: 100%; background: rgba(255,255,255,0.06); border-radius: 100px; height: 4px; overflow: hidden; }
42
+ .prog-fill { height: 100%; background: linear-gradient(90deg,#c9a84c,#e8d5a0); border-radius: 100px; transition: width 0.5s ease; }
43
+ .qmeta { display: flex; justify-content: space-between; align-items: center; font-size: 0.82rem; color: #6b6478; }
44
+ .qcat { background: rgba(201,168,76,0.12); border: 1px solid rgba(201,168,76,0.25); color: #c9a84c; padding: 4px 14px; border-radius: 100px; font-size: 0.8rem; }
45
+ .qcard { background: rgba(255,255,255,0.03); border: 1px solid rgba(201,168,76,0.25); border-radius: 20px; padding: 32px; width: 100%; }
46
+ .qtext { font-size: 1.15rem; font-weight: 500; line-height: 1.7; margin-bottom: 24px; color: #f5f0e8; }
47
+ .opts { display: flex; flex-direction: column; gap: 12px; }
48
+ .opt { background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.1); border-radius: 12px; padding: 14px 20px; color: #f5f0e8; font-family: 'DM Sans', sans-serif; font-size: 0.97rem; cursor: pointer; text-align: left; transition: all 0.2s; line-height: 1.5; }
49
+ .opt:hover { border-color: #c9a84c; background: rgba(201,168,76,0.08); }
50
+ .opt.selected { border-color: #c9a84c; background: rgba(201,168,76,0.15); color: #e8d5a0; }
51
+ #screen-loading { gap: 28px; text-align: center; }
52
+ .orb { width: 80px; height: 80px; border-radius: 50%; border: 2px solid transparent; border-top-color: #c9a84c; border-left-color: rgba(201,168,76,0.3); animation: spin 1.2s linear infinite; margin: 0 auto; }
53
+ @keyframes spin { to { transform: rotate(360deg); } }
54
+ .steps { display: flex; flex-direction: column; gap: 10px; }
55
+ .step { font-size: 0.9rem; color: #6b6478; display: flex; align-items: center; gap: 10px; justify-content: center; transition: color 0.4s; }
56
+ .step.done { color: #e8d5a0; }
57
+ .dot { width: 6px; height: 6px; border-radius: 50%; background: #6b6478; transition: background 0.4s; flex-shrink: 0; }
58
+ .step.done .dot { background: #c9a84c; }
59
+ #screen-result { gap: 28px; max-width: 640px; width: 100%; animation: fadeup 0.7s ease; padding-top: 60px; padding-bottom: 60px; }
60
+ @keyframes fadeup { from{opacity:0;transform:translateY(30px)}to{opacity:1;transform:translateY(0)} }
61
+ .rhead { text-align: center; }
62
+ .rhead h2 { font-family: 'Playfair Display', serif; font-size: 2rem; font-weight: 700; color: #c9a84c; margin-bottom: 8px; }
63
+ .rhead p { color: #6b6478; font-size: 0.95rem; }
64
+ .rcard { background: rgba(255,255,255,0.03); border: 1px solid rgba(201,168,76,0.25); border-radius: 20px; padding: 28px 32px; width: 100%; }
65
+ .rcard h3 { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.15em; color: #c9a84c; margin-bottom: 14px; display: flex; align-items: center; gap: 8px; }
66
+ .rcard h3::after { content: ''; flex: 1; height: 1px; background: rgba(201,168,76,0.25); }
67
+ .rcontent { font-size: 1rem; line-height: 1.85; color: rgba(245,240,232,0.85); font-weight: 300; }
68
+ .sci-badge { display: flex; align-items: center; gap: 18px; background: rgba(201,168,76,0.07); border: 1px solid rgba(201,168,76,0.2); border-radius: 16px; padding: 16px 20px; margin-bottom: 14px; }
69
+ .sci-icon { font-size: 2.4rem; }
70
+ .sci-name { font-family: 'Playfair Display', serif; font-size: 1.3rem; font-weight: 700; color: #c9a84c; }
71
+ .sci-title { font-size: 0.85rem; color: #6b6478; margin-top: 4px; }
72
+ .jobs { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 16px; }
73
+ .job { background: rgba(255,255,255,0.05); border: 1px solid rgba(201,168,76,0.25); border-radius: 100px; padding: 6px 16px; font-size: 0.88rem; color: #f5f0e8; }
74
+ .score-bars { display: flex; flex-direction: column; gap: 12px; }
75
+ .score-row { display: flex; align-items: center; gap: 12px; }
76
+ .score-label { font-size: 0.85rem; color: #e8d5a0; width: 80px; flex-shrink: 0; }
77
+ .score-bar-wrap { flex: 1; background: rgba(255,255,255,0.06); border-radius: 100px; height: 8px; overflow: hidden; }
78
+ .score-bar-fill { height: 100%; background: linear-gradient(90deg,#c9a84c,#e8d5a0); border-radius: 100px; transition: width 1s ease; }
79
+ .score-val { font-size: 0.82rem; color: #6b6478; width: 28px; text-align: right; flex-shrink: 0; }
80
+ .btn-out { background: transparent; border: 1px solid rgba(201,168,76,0.25); border-radius: 12px; padding: 12px 32px; color: #e8d5a0; font-family: 'DM Sans', sans-serif; font-size: 0.95rem; cursor: pointer; transition: all 0.2s; }
81
+ .btn-out:hover { border-color: #c9a84c; background: rgba(201,168,76,0.08); }
82
+ </style>
83
+ </head>
84
+ <body>
85
+
86
+ <div id="screen-intro" class="screen active">
87
+ <div class="logo-ring"><span class="logo-icon">&#x1F9F7;</span></div>
88
+ <div><h1>Mind<br><span>Mirror</span></h1></div>
89
+ <p class="tagline">Discover your intelligence type and find out which legendary scientist thinks like you.</p>
90
+ <div class="pills">
91
+ <div class="pill">&#x23F1; 5 minutes</div>
92
+ <div class="pill">&#x1F9E0; 15 questions</div>
93
+ <div class="pill">&#x2728; Instant results</div>
94
+ </div>
95
+ <button class="btn" onclick="go('form')">Start the Test</button>
96
+ </div>
97
+
98
+ <div id="screen-form" class="screen">
99
+ <p class="form-title">Before we begin</p>
100
+ <div class="fg"><label>Your Name</label><input type="text" id="iname" placeholder="Enter your name"/></div>
101
+ <div class="fg"><label>Your Age</label><input type="number" id="iage" placeholder="e.g. 25" min="10" max="80"/></div>
102
+ <div class="fg"><label>Education Level</label>
103
+ <select id="iedu">
104
+ <option value="">Select...</option>
105
+ <option>High School</option>
106
+ <option>Bachelor Degree</option>
107
+ <option>Postgraduate</option>
108
+ </select>
109
+ </div>
110
+ <div class="fg"><label>What do you enjoy most?</label>
111
+ <select id="iint">
112
+ <option value="">Select...</option>
113
+ <option>Reading and Research</option>
114
+ <option>Art and Creativity</option>
115
+ <option>Technology and Programming</option>
116
+ <option>People and Communication</option>
117
+ <option>Sports and Physical Activity</option>
118
+ <option>Business and Entrepreneurship</option>
119
+ </select>
120
+ </div>
121
+ <button class="btn" onclick="startQ()">Let us Go</button>
122
+ </div>
123
+
124
+ <div id="screen-quiz" class="screen">
125
+ <div class="prog-wrap"><div class="prog-fill" id="prog" style="width:0%"></div></div>
126
+ <div class="qmeta"><span id="qnum">Question 1 of 15</span><span class="qcat" id="qcat">Logic</span></div>
127
+ <div class="qcard"><p class="qtext" id="qtext"></p><div class="opts" id="qopts"></div></div>
128
+ <button class="btn" id="btnNext" disabled onclick="nextQ()">Next</button>
129
+ </div>
130
+
131
+ <div id="screen-loading" class="screen">
132
+ <div class="orb"></div>
133
+ <div>
134
+ <h2 style="font-family:'Playfair Display',serif;font-size:1.5rem;text-align:center;margin-bottom:8px;color:#f5f0e8">Analysing your mind...</h2>
135
+ <p style="color:#6b6478;text-align:center;font-size:0.9rem">Processing your answers</p>
136
+ </div>
137
+ <div class="steps">
138
+ <div class="step" id="s1"><div class="dot"></div>Detecting patterns</div>
139
+ <div class="step" id="s2"><div class="dot"></div>Identifying intelligence type</div>
140
+ <div class="step" id="s3"><div class="dot"></div>Matching with scientists</div>
141
+ <div class="step" id="s4"><div class="dot"></div>Generating your personal report</div>
142
+ </div>
143
+ </div>
144
+
145
+ <div id="screen-result" class="screen">
146
+ <div class="rhead"><h2 id="rname">Your Results</h2><p>Personalised intelligence analysis</p></div>
147
+
148
+ <div class="rcard">
149
+ <h3>Your Intelligence Scores</h3>
150
+ <div class="score-bars" id="score-bars"></div>
151
+ </div>
152
+
153
+ <div class="rcard"><h3>Your Intelligence Type</h3><div class="rcontent" id="rintel"></div></div>
154
+
155
+ <div class="rcard">
156
+ <h3>Your Mind Resembles</h3>
157
+ <div class="sci-badge">
158
+ <div class="sci-icon" id="rsicon"></div>
159
+ <div><div class="sci-name" id="rsname"></div><div class="sci-title" id="rstitle"></div></div>
160
+ </div>
161
+ <div class="rcontent" id="rsreason"></div>
162
+ </div>
163
+
164
+ <div class="rcard">
165
+ <h3>Best Career Matches</h3>
166
+ <div class="jobs" id="rjobs"></div>
167
+ <div class="rcontent" id="rjreason"></div>
168
+ </div>
169
+
170
+ <div class="rcard"><h3>Personal Advice</h3><div class="rcontent" id="radvice"></div></div>
171
+
172
+ <button class="btn-out" onclick="location.reload()">&#x21A9; Restart</button>
173
+ </div>
174
+
175
+ <script>
176
+ var QS = [
177
+ {c:"Logic",t:"You have 3 boxes: one apples only, one oranges only, one mixed. All labels are wrong. You open the mixed-label box and find an apple. Can you identify all boxes?",o:[{t:"Yes, since all labels are wrong I deduce the rest logically.",s:{logical:3}},{t:"No, I need to open another box.",s:{logical:1}},{t:"Not sure, not enough information.",s:{logical:1}},{t:"Maybe, I need more time to think.",s:{logical:2}}]},
178
+ {c:"Creativity",t:"A 5-year-old asks: What is time? How do you explain it?",o:[{t:"Time is what passes while you wait for dinner.",s:{creative:3,verbal:2}},{t:"I show a clock and explain the hands.",s:{logical:2}},{t:"Time is the space between waking up and going to sleep.",s:{creative:2,verbal:2}},{t:"I say they are too young to understand.",s:{logical:1}}]},
179
+ {c:"Spatial",t:"You are standing facing south. Which hand points north?",o:[{t:"My left hand.",s:{spatial:3}},{t:"My right hand.",s:{spatial:1}},{t:"I am not sure, I need a compass.",s:{spatial:0}},{t:"It depends on which way I am walking.",s:{spatial:1}}]},
180
+ {c:"Verbal",t:"Best way to convince someone with a very different opinion?",o:[{t:"Find common ground first, then present evidence calmly.",s:{verbal:3,emotional:2}},{t:"Use strong facts and statistics.",s:{logical:2,verbal:1}},{t:"Ask questions that guide them to the answer.",s:{verbal:3,emotional:3}},{t:"Stay confident and repeat my point firmly.",s:{verbal:1}}]},
181
+ {c:"Emotional",t:"Your friend failed something important and is discouraged. First thing you do?",o:[{t:"Listen carefully before saying anything.",s:{emotional:3}},{t:"Point out their mistakes so they can improve.",s:{logical:2,emotional:1}},{t:"Share stories of people who succeeded after failure.",s:{verbal:2,emotional:2}},{t:"Suggest a practical action plan immediately.",s:{logical:3,emotional:1}}]},
182
+ {c:"Logic",t:"All Bloops are Razzies. All Razzies are Lazzies. Are all Bloops definitely Lazzies?",o:[{t:"Yes, always.",s:{logical:3}},{t:"No, not necessarily.",s:{logical:0}},{t:"Sometimes.",s:{logical:1}},{t:"Not enough information.",s:{logical:1}}]},
183
+ {c:"Creativity",t:"If you could add a sixth human sense, what would it be?",o:[{t:"Detecting lies, so society would be more honest.",s:{creative:3,verbal:2}},{t:"Sensing magnetic fields to always know direction.",s:{creative:2,spatial:2}},{t:"Reading hidden emotions in others.",s:{creative:3,emotional:3}},{t:"Nothing, five senses are enough.",s:{logical:1}}]},
184
+ {c:"Spatial",t:"A room has 4 corners. A cat in one corner sees 3 cats in every other corner. How many cats total?",o:[{t:"4 cats.",s:{spatial:3,logical:3}},{t:"13 cats.",s:{spatial:0}},{t:"3 cats.",s:{spatial:1}},{t:"That is impossible.",s:{logical:1}}]},
185
+ {c:"Verbal",t:"Which sentence has the best style?",o:[{t:"A great book does not just add information, it changes how you think.",s:{verbal:3}},{t:"Books are very useful and contain a lot of information.",s:{verbal:1}},{t:"You should read books because they are important.",s:{verbal:0}},{t:"Reading is one of the important types of learning.",s:{verbal:1}}]},
186
+ {c:"Emotional",t:"A friend whose mood changes very frequently. Your first interpretation?",o:[{t:"They are probably under stress or going through something difficult.",s:{emotional:3}},{t:"That is just their personality, hard to change.",s:{emotional:0}},{t:"They might have a health issue.",s:{logical:2}},{t:"They might be seeking attention.",s:{verbal:1}}]},
187
+ {c:"Logic",t:"If you multiply all numbers from 1 to 10, how many zeros does the result end with?",o:[{t:"Two zeros.",s:{logical:3}},{t:"One zero.",s:{logical:1}},{t:"Ten zeros.",s:{logical:0}},{t:"I cannot calculate that.",s:{logical:0}}]},
188
+ {c:"Creativity",t:"If your life were a movie, what genre?",o:[{t:"A deep psychological drama full of inner conflict.",s:{creative:3,emotional:3}},{t:"An action thriller packed with challenges and victories.",s:{creative:2}},{t:"A social comedy with a diverse cast.",s:{creative:2,verbal:2}},{t:"A structured scientific documentary.",s:{logical:3}}]},
189
+ {c:"Spatial",t:"If you fold a square paper diagonally in half, what shape do you get?",o:[{t:"A right-angled triangle.",s:{spatial:3}},{t:"A rectangle.",s:{spatial:0}},{t:"A trapezoid.",s:{spatial:1}},{t:"I am not sure.",s:{spatial:0}}]},
190
+ {c:"Verbal",t:"Emailing your manager to request a day off. Most important element?",o:[{t:"A clear reason plus a solution for pending work.",s:{verbal:3,logical:2}},{t:"A respectful and polished tone.",s:{verbal:2}},{t:"Keeping it short and to the point.",s:{logical:2,verbal:1}},{t:"Reminding them of my dedication and rights.",s:{verbal:1}}]},
191
+ {c:"Emotional",t:"During a heated argument, what do you usually do?",o:[{t:"Try to understand the other person even if I disagree.",s:{emotional:3,verbal:2}},{t:"Focus on logic and arguments, setting emotions aside.",s:{logical:3}},{t:"Try to calm things down and find a compromise.",s:{emotional:3,verbal:2}},{t:"Get energized and defend my position with full force.",s:{verbal:2}}]}
192
+ ];
193
+
194
+ // ── Intelligence profiles ─────────────────────────────────────────────────────
195
+ var PROFILES = {
196
+ logical: {
197
+ name: "Analytical Thinker",
198
+ desc: "You have a powerful logical mind that thrives on patterns, systems, and structured reasoning. You approach problems methodically and enjoy uncovering hidden truths through evidence and deduction. Your mind is wired to see cause-and-effect relationships others often miss. This makes you exceptionally effective in situations that require precision and critical thinking.",
199
+ scientist: "Albert Einstein", title: "Theoretical Physicist", icon: "&#x1F9EA;",
200
+ reason: "Like Einstein, you are driven by deep curiosity and the need to find elegant, logical explanations for complex phenomena. You prefer working with abstract ideas and systems rather than surface-level observations.",
201
+ jobs: ["Data Scientist", "Software Engineer", "Financial Analyst", "Research Scientist"],
202
+ jobs_reason: "Your logical precision and systematic thinking make you exceptional at roles that require analysis, problem-solving, and working with complex data or systems.",
203
+ advice: "Challenge yourself with complex puzzles and abstract problems regularly. Your logical strength grows when you apply it to unfamiliar domains, so seek out interdisciplinary challenges."
204
+ },
205
+ creative: {
206
+ name: "Creative Visionary",
207
+ desc: "Your mind is a generator of original ideas, bold connections, and imaginative solutions. You see the world through a unique lens, often perceiving possibilities where others see limitations. Creative intelligence drives your thinking, making you naturally innovative and expressive. You are drawn to aesthetics, storytelling, and original thought.",
208
+ scientist: "Leonardo da Vinci", title: "Renaissance Polymath", icon: "&#x1F3A8;",
209
+ reason: "Like da Vinci, you blend artistic vision with intellectual curiosity. You are never satisfied with conventional answers and consistently seek new, inventive ways to understand and express the world around you.",
210
+ jobs: ["UX Designer", "Creative Director", "Product Innovator", "Art Director"],
211
+ jobs_reason: "Your imaginative thinking and ability to generate original ideas make you invaluable in roles that require innovation, design, and bringing new concepts to life.",
212
+ advice: "Keep a daily journal of your ideas, no matter how wild they seem. Your best breakthroughs often come from combining unrelated concepts, so expose yourself to diverse fields and experiences."
213
+ },
214
+ spatial: {
215
+ name: "Spatial Navigator",
216
+ desc: "You possess a rare ability to perceive, manipulate, and reason about objects and space with exceptional clarity. Your mind naturally constructs mental maps and three-dimensional models of the world. This spatial intelligence allows you to excel in environments that require precision, visualization, and physical understanding. You have an intuitive grasp of how things fit together.",
217
+ scientist: "Nikola Tesla", title: "Inventor and Engineer", icon: "&#x26A1;",
218
+ reason: "Like Tesla, you can visualize complex machines and systems entirely in your mind before building them. Your spatial reasoning allows you to mentally simulate how things work in three dimensions.",
219
+ jobs: ["Architect", "Civil Engineer", "3D Artist", "Surgeon"],
220
+ jobs_reason: "Your ability to visualize and mentally manipulate spatial information makes you exceptional in fields that require precise three-dimensional thinking and technical design.",
221
+ advice: "Practice sketching your ideas visually and explore design or engineering challenges. Your spatial gifts are amplified when you combine them with hands-on building and experimentation."
222
+ },
223
+ verbal: {
224
+ name: "Verbal Communicator",
225
+ desc: "You wield language as both a tool and an art form, expressing complex ideas with clarity, precision, and impact. Your verbal intelligence enables you to persuade, inspire, and connect deeply through words. You are naturally drawn to reading, writing, debate, and storytelling. People listen when you speak because your communication resonates on multiple levels.",
226
+ scientist: "Marie Curie", title: "Physicist and Chemist", icon: "&#x1F52C;",
227
+ reason: "Like Curie, you combine intellectual rigor with the ability to communicate your insights clearly and persuasively. You can translate complex ideas into language that others can understand and be moved by.",
228
+ jobs: ["Lawyer", "Journalist", "Professor", "Marketing Strategist"],
229
+ jobs_reason: "Your mastery of language and communication makes you naturally suited for roles where the power of words, persuasion, and clear expression drive outcomes.",
230
+ advice: "Write every day, even briefly. The more you practice expressing complex thoughts clearly, the sharper your verbal intelligence becomes. Consider public speaking to amplify your natural gift."
231
+ },
232
+ emotional: {
233
+ name: "Empathetic Leader",
234
+ desc: "You have a profound ability to sense, understand, and respond to the emotions of yourself and others. Your emotional intelligence makes you a natural connector, healer, and leader of people. You read social situations with remarkable accuracy and know how to bring out the best in those around you. People trust you because they feel genuinely understood in your presence.",
235
+ scientist: "Carl Jung", title: "Psychologist and Psychiatrist", icon: "&#x1F9D8;",
236
+ reason: "Like Jung, you have a deep fascination with the inner world of human experience. You intuitively understand what drives people and can navigate the complexities of relationships and emotions with wisdom.",
237
+ jobs: ["Psychologist", "Human Resources Director", "Social Worker", "Life Coach"],
238
+ jobs_reason: "Your empathy and emotional insight make you invaluable in roles centered on people, well-being, and human connection. You thrive where emotional intelligence is the key skill.",
239
+ advice: "Trust your intuition about people while continuing to learn about emotional psychology. Your gift grows when you combine natural empathy with structured knowledge about human behavior."
240
+ }
241
+ };
242
+
243
+ var ud = {}, ans = [], cq = 0, sel = null;
244
+
245
+ function go(id) {
246
+ document.querySelectorAll('.screen').forEach(function(s) { s.classList.remove('active'); });
247
+ document.getElementById('screen-' + id).classList.add('active');
248
+ window.scrollTo(0, 0);
249
+ }
250
+
251
+ function startQ() {
252
+ var n = document.getElementById('iname').value.trim();
253
+ var a = document.getElementById('iage').value;
254
+ var e = document.getElementById('iedu').value;
255
+ var i = document.getElementById('iint').value;
256
+ if (!n || !a || !e || !i) { alert('Please fill in all fields.'); return; }
257
+ ud = { name: n, age: a, edu: e, interest: i };
258
+ ans = []; cq = 0; showQ(); go('quiz');
259
+ }
260
+
261
+ function showQ() {
262
+ var q = QS[cq]; sel = null;
263
+ document.getElementById('btnNext').disabled = true;
264
+ document.getElementById('qnum').textContent = 'Question ' + (cq+1) + ' of ' + QS.length;
265
+ document.getElementById('qcat').textContent = q.c;
266
+ document.getElementById('qtext').textContent = q.t;
267
+ document.getElementById('prog').style.width = ((cq / QS.length) * 100) + '%';
268
+ var c = document.getElementById('qopts'); c.innerHTML = '';
269
+ q.o.forEach(function(opt, i) {
270
+ var b = document.createElement('button');
271
+ b.className = 'opt'; b.textContent = opt.t;
272
+ b.onclick = function() {
273
+ document.querySelectorAll('.opt').forEach(function(x) { x.classList.remove('selected'); });
274
+ b.classList.add('selected'); sel = i;
275
+ document.getElementById('btnNext').disabled = false;
276
+ };
277
+ c.appendChild(b);
278
+ });
279
+ }
280
+
281
+ function nextQ() {
282
+ if (sel === null) return;
283
+ var q = QS[cq];
284
+ ans.push({ score: q.o[sel].s });
285
+ cq++;
286
+ if (cq < QS.length) { showQ(); }
287
+ else {
288
+ document.getElementById('prog').style.width = '100%';
289
+ go('loading');
290
+ ['s1','s2','s3','s4'].forEach(function(id, i) {
291
+ setTimeout(function() { document.getElementById(id).classList.add('done'); }, i * 800 + 400);
292
+ });
293
+ setTimeout(showResult, 3800);
294
+ }
295
+ }
296
+
297
+ function showResult() {
298
+ // Calculate scores
299
+ var sc = { logical: 0, creative: 0, spatial: 0, verbal: 0, emotional: 0 };
300
+ ans.forEach(function(a) {
301
+ for (var k in a.score) { sc[k] = (sc[k] || 0) + a.score[k]; }
302
+ });
303
+
304
+ // Max possible per category
305
+ var maxScores = { logical: 9, creative: 9, spatial: 9, verbal: 9, emotional: 9 };
306
+
307
+ // Find dominant intelligence
308
+ var dominant = 'logical';
309
+ var maxVal = 0;
310
+ for (var k in sc) {
311
+ if (sc[k] > maxVal) { maxVal = sc[k]; dominant = k; }
312
+ }
313
+
314
+ // Adjust based on interest
315
+ var interestMap = {
316
+ 'Reading and Research': 'verbal',
317
+ 'Art and Creativity': 'creative',
318
+ 'Technology and Programming': 'logical',
319
+ 'People and Communication': 'emotional',
320
+ 'Sports and Physical Activity': 'spatial',
321
+ 'Business and Entrepreneurship': 'logical'
322
+ };
323
+ var interestBoost = interestMap[ud.interest];
324
+ if (interestBoost && sc[interestBoost] + 2 >= sc[dominant]) {
325
+ dominant = interestBoost;
326
+ }
327
+
328
+ var p = PROFILES[dominant];
329
+
330
+ // Score bars
331
+ var barsHTML = '';
332
+ var labels = { logical: 'Logical', creative: 'Creative', spatial: 'Spatial', verbal: 'Verbal', emotional: 'Emotional' };
333
+ for (var key in sc) {
334
+ var pct = Math.round((sc[key] / maxScores[key]) * 100);
335
+ if (pct > 100) pct = 100;
336
+ barsHTML += '<div class="score-row">' +
337
+ '<span class="score-label">' + labels[key] + '</span>' +
338
+ '<div class="score-bar-wrap"><div class="score-bar-fill" style="width:' + pct + '%"></div></div>' +
339
+ '<span class="score-val">' + pct + '%</span>' +
340
+ '</div>';
341
+ }
342
+ document.getElementById('score-bars').innerHTML = barsHTML;
343
+
344
+ // Fill result
345
+ document.getElementById('rname').textContent = ud.name + "'s Results";
346
+ document.getElementById('rintel').textContent = p.desc;
347
+ document.getElementById('rsicon').innerHTML = p.icon;
348
+ document.getElementById('rsname').textContent = p.scientist;
349
+ document.getElementById('rstitle').textContent = p.title;
350
+ document.getElementById('rsreason').textContent = p.reason;
351
+ document.getElementById('radvice').textContent = p.advice;
352
+ document.getElementById('rjreason').textContent = p.jobs_reason;
353
+
354
+ var jl = document.getElementById('rjobs'); jl.innerHTML = '';
355
+ p.jobs.forEach(function(j) {
356
+ var t = document.createElement('div'); t.className = 'job'; t.textContent = j; jl.appendChild(t);
357
+ });
358
+
359
+ go('result');
360
+ }
361
+ </script>
362
+ </body>
363
+ </html>
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastapi
2
+ uvicorn