File size: 7,086 Bytes
6cc5288
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
from flask import Flask, render_template, request, session, redirect, url_for
import joblib
import numpy as np
import tensorflow as tf

app = Flask(__name__)
app.secret_key = "verysecretkey"

# Load model & preprocessors
scaler = joblib.load('preprocessing/scaler.joblib')
le_gender = joblib.load('preprocessing/le_gender.joblib')
le_edu = joblib.load('preprocessing/le_edu.joblib')
le_interest = joblib.load('preprocessing/le_interest.joblib')
le_personality = joblib.load('preprocessing/le_personality.joblib')
deep_model = tf.keras.models.load_model('model/deep_mbti_model.h5')

mbti_descriptions = {
    'ENTJ': 'The Commander: Strategic leaders, motivated to organize change',
    'INTJ': 'The Mastermind: Analytical problem-solvers, eager to improve systems and processes',
    'ENTP': 'The Visionary: Inspired innovators, seeking new solutions to challenging problems',
    'INTP': 'The Architect: Philosophical innovators, fascinated by logical analysis',
    'ENFJ': 'The Teacher: Idealist organizers, driven to do what is best for humanity',
    'INFJ': 'The Counselor: Creative nurturers, driven by a strong sense of personal integrity',
    'ENFP': 'The Champion: People-centered creators, motivated by possibilities and potential',
    'INFP': 'The Healer: Imaginative idealists, guided by their own values and beliefs',
    'ESTJ': 'The Supervisor: Hardworking traditionalists, taking charge to get things done',
    'ISTJ': 'The Inspector: Responsible organizers, driven to create order out of chaos',
    'ESFJ': 'The Provider: Conscientious helpers, dedicated to their duties to others',
    'ISFJ': 'The Protector: Industrious caretakers, loyal to traditions and institutions',
    'ESTP': 'The Dynamo: Energetic thrillseekers, ready to push boundaries and dive into action',
    'ISTP': 'The Craftsperson: Observant troubleshooters, solving practical problems',
    'ESFP': 'The Entertainer: Vivacious entertainers, loving life and charming those around them',
    'ISFP': 'The Composer: Gentle caretakers, enjoying the moment with low-key enthusiasm'
}

# Mapping for MCQ answers (A/B/C/D) to numeric scores (customize as needed)
MCQ_MAP = {'A': 10, 'B': 7, 'C': 4, 'D': 1}

# MCQ config: 4 MBTI traits, 5 Qs each
TRAITS = [
    ('extroversion', "Extroversion (E/I)", [
        "Are you comfortable with public speaking?",
        "Do you enjoy being the center of attention?",
        "Do you thrive in group settings?",
        "Do you make friends easily at new places?",
        "Do group activities energize you more than being alone?"
    ]),
    ('sensing', "Sensing vs Intuition (S/N)", [
        "Do you focus more on immediate details than the big picture?",
        "Do you trust experience over theories?",
        "Do you prefer practical applications over abstract concepts?",
        "Do you rely on your five senses rather than gut feelings?",
        "Do you prefer dealing with practical facts rather than imaginative ideas?"
    ]),
    ('thinking', "Thinking vs Feeling (T/F)", [
        "Do you prioritize logic over emotions when deciding?",
        "Do you value objective truth over social harmony?",
        "Are you comfortable giving critical feedback?",
        "Do you analyze problems objectively rather than considering people's feelings first?",
        "Is it more important for you to be fair than to be compassionate?"
    ]),
    ('judging', "Judging vs Perceiving (J/P)", [
        "Do you prefer planned activities over spontaneous ones?",
        "Do you enjoy making schedules and to-do lists?",
        "Are you uncomfortable with last-minute changes?",
        "Do you prefer closure and completion over keeping options open?",
        "Do you prefer having a structured plan rather than keeping options open?"
    ])
]

# Step 0: Demographics collection
@app.route('/', methods=['GET', 'POST'])
def demographics():
    if request.method == 'POST':
        session['demographics'] = {
            'age': request.form['age'],
            'gender': request.form['gender'],
            'education': request.form['education'],
            'interest': request.form['interest']
        }
        return redirect(url_for('mcq', step=1))
    return render_template('index.html',
                           gender_classes=le_gender.classes_,
                           edu_classes=le_edu.classes_,
                           interest_classes=le_interest.classes_)

# Step 1-N: MCQ stepper for MBTI traits
@app.route('/mcq/<int:step>', methods=['GET', 'POST'])
def mcq(step):
    total_steps = len(TRAITS)
    if request.method == 'POST' and step > 1:
        prev_trait_key = TRAITS[step - 2][0]
        session[prev_trait_key] = [
            request.form.get(f'{prev_trait_key}_q{i}', None) for i in range(1, 6)
        ]
    if step > total_steps:
        return redirect(url_for('results'))
    trait_key, trait_label, questions = TRAITS[step - 1]
    return render_template('mcq_step.html',
                          trait_key=trait_key,
                          trait_label=trait_label,
                          questions=questions,
                          step=step,
                          total_steps=total_steps)

# Final: Results calculation and personality prediction
@app.route('/results')
def results():
    try:
        data = session.get('demographics', {})
        age = float(data.get('age', 25))
        gender = le_gender.transform([data.get('gender', le_gender.classes_[0])])[0]
        education = le_edu.transform([data.get('education', le_edu.classes_[0])])[0]
        interest = le_interest.transform([data.get('interest', le_interest.classes_[0])])[0]

        # Collect trait scores, average each over 5 MCQs
        trait_keys = ['extroversion', 'sensing', 'thinking', 'judging']
        trait_scores = []
        for trait_key in trait_keys:
            answers = session.get(trait_key, ['C'] * 5)  # default 5 'C'
            numeric_scores = [MCQ_MAP.get(ans, 4) for ans in answers]
            trait_scores.append(float(sum(numeric_scores)) / 5)

        # Features: [age, gender, education, extroversion, sensing, thinking, judging, interest]
        features = np.array([[age, gender, education] + trait_scores + [interest]])
        features_scaled = scaler.transform(features)
        pred_proba = deep_model.predict(features_scaled)
        pred_class = np.argmax(pred_proba)
        mbti_pred = le_personality.inverse_transform([pred_class])[0]
        class_probs = dict(zip(le_personality.classes_, pred_proba[0].round(3)))
        description = mbti_descriptions.get(mbti_pred, '')
    except Exception as e:
        mbti_pred, class_probs, description = None, None, f"Error: {e}"
    session.clear()
    return render_template('results.html',
                          mbti_pred=mbti_pred,
                          class_probs=class_probs,
                          description=description)

if __name__ == '__main__':
    app.run(debug=True)