Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,46 +1,80 @@
|
|
| 1 |
from flask import Flask, request, jsonify
|
| 2 |
-
|
| 3 |
-
import joblib
|
| 4 |
-
import pandas as pd
|
| 5 |
-
import os
|
| 6 |
|
| 7 |
app = Flask(__name__)
|
| 8 |
-
CORS(app)
|
| 9 |
|
| 10 |
-
#
|
| 11 |
-
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
return len(viewer_skills.intersection(target_skills))
|
| 23 |
|
| 24 |
-
|
| 25 |
-
|
|
|
|
|
|
|
| 26 |
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
from flask import Flask, request, jsonify
|
| 2 |
+
import math
|
|
|
|
|
|
|
|
|
|
| 3 |
|
| 4 |
app = Flask(__name__)
|
|
|
|
| 5 |
|
| 6 |
+
# --- New, Smarter Scoring Logic for Alumni Matching ---
|
| 7 |
+
# We define weights for skills. More technical/in-demand skills get a higher weight.
|
| 8 |
+
skill_weights = {
|
| 9 |
+
'java': 3, 'python': 3, 'react': 3, 'c++': 3, 'sql': 3, 'aws': 3, 'ai': 3, 'ml': 3,
|
| 10 |
+
'tensorflow': 3, 'nodejs': 3, 'swift': 3, 'ios': 3, 'cybersecurity': 3,
|
| 11 |
+
'devops': 3, 'docker': 3, 'go': 3, 'microservices': 3, 'qa': 3, 'selenium': 3,
|
| 12 |
+
'data science': 3, 'vhdl': 3, 'verilog': 3, 'embedded c': 3, 'rtos': 3,
|
| 13 |
+
'vlsi': 3, 'cad': 3, 'solidworks': 3, 'robotics': 3, 'staadpro': 3,
|
| 14 |
+
'html': 2, 'css': 2, 'javascript': 2, 'ui/ux': 2, 'figma': 2, 'autocad': 2,
|
| 15 |
+
'thermodynamics': 2, 'manufacturing': 2, 'signal processing': 2, 'analog design': 2,
|
| 16 |
+
}
|
| 17 |
|
| 18 |
+
# A significant bonus if the viewer's branch matches the target alumni's branch
|
| 19 |
+
BRANCH_MATCH_BONUS = 10
|
| 20 |
+
|
| 21 |
+
def calculate_alumni_score(viewer_profile, target_profile):
|
| 22 |
+
# The frontend sends skills as a string like "python|react|sql". We need to split it.
|
| 23 |
+
viewer_skills = set(str(viewer_profile.get('viewer_skills', '')).lower().split('|'))
|
| 24 |
+
target_skills = set(str(target_profile.get('target_skills', '')).lower().split('|'))
|
| 25 |
+
viewer_branch = str(viewer_profile.get('viewer_branch', '')).lower().strip()
|
| 26 |
+
target_branch = str(target_profile.get('target_branch', '')).lower().strip()
|
| 27 |
|
| 28 |
+
# 1. Calculate a score based on shared skills, using our weights
|
| 29 |
+
common_skills = viewer_skills.intersection(target_skills)
|
| 30 |
+
skill_score = sum(skill_weights.get(skill, 1) for skill in common_skills)
|
|
|
|
| 31 |
|
| 32 |
+
# 2. Add the bonus if branches match
|
| 33 |
+
branch_score = 0
|
| 34 |
+
if viewer_branch and target_branch and viewer_branch == target_branch:
|
| 35 |
+
branch_score = BRANCH_MATCH_BONUS
|
| 36 |
|
| 37 |
+
# 3. Combine the scores
|
| 38 |
+
raw_score = skill_score + branch_score
|
| 39 |
+
|
| 40 |
+
# 4. Normalize the raw score to a clean 1-10 scale for the UI
|
| 41 |
+
# This uses a logarithmic scale to make the scores feel more natural.
|
| 42 |
+
# A small match gets a score of 1-3, a good match 4-7, a great match 8-10.
|
| 43 |
+
if raw_score == 0:
|
| 44 |
+
return 0
|
| 45 |
|
| 46 |
+
normalized_score = min(10, math.log(raw_score + 1) * 2.5)
|
| 47 |
+
|
| 48 |
+
# We return a score rounded to one decimal place, like 7.5
|
| 49 |
+
return round(normalized_score, 1)
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
@app.route('/', methods=['POST'])
|
| 53 |
+
def get_match_score():
|
| 54 |
+
try:
|
| 55 |
+
data = request.get_json()
|
| 56 |
+
|
| 57 |
+
# The frontend sends data with these keys, so we match them here
|
| 58 |
+
viewer_profile = {
|
| 59 |
+
'viewer_skills': data.get('viewer_skills'),
|
| 60 |
+
'viewer_branch': data.get('viewer_branch')
|
| 61 |
+
}
|
| 62 |
+
target_profile = {
|
| 63 |
+
'target_skills': data.get('target_skills'),
|
| 64 |
+
'target_branch': data.get('target_branch')
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
if not viewer_profile or not target_profile:
|
| 68 |
+
return jsonify({"error": "Missing profile data"}), 400
|
| 69 |
+
|
| 70 |
+
final_score = calculate_alumni_score(viewer_profile, target_profile)
|
| 71 |
+
|
| 72 |
+
return jsonify({"score": final_score})
|
| 73 |
+
|
| 74 |
+
except Exception as e:
|
| 75 |
+
print(f"An error occurred: {e}")
|
| 76 |
+
return jsonify({"error": "An internal error occurred."}), 500
|
| 77 |
+
|
| 78 |
+
if __name__ == '__main__':
|
| 79 |
+
# This allows you to run the app locally for testing
|
| 80 |
+
app.run(debug=True)
|