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/', 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)