Spaces:
Sleeping
Sleeping
Merge pull request #3 from ranilmukesh/Ui13-03-2026
Browse filesfeat: show full list of missing skills in recommendations
main.py
CHANGED
|
@@ -346,108 +346,104 @@ async def whatif_analysis(data: StudentData):
|
|
| 346 |
|
| 347 |
scenarios = []
|
| 348 |
sid = 1
|
| 349 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 350 |
if routing_engine and data.skills and data.desired_role:
|
| 351 |
rec_job, _ = routing_engine.recommend(data.skills)
|
| 352 |
if rec_job:
|
| 353 |
transition = routing_engine.get_career_transition_path(rec_job, data.desired_role)
|
| 354 |
if transition and transition.get("skills_to_learn"):
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
"
|
| 360 |
-
"
|
| 361 |
-
"
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 366 |
|
| 367 |
# Add Internships
|
| 368 |
if data.Internships < 3:
|
| 369 |
mod = orig_dict.copy()
|
| 370 |
mod['Internships'] += 1
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
"
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
"risk_delta": orig_risk - mod_risk,
|
| 377 |
-
"risk_reduction_percent": ((mod_risk - orig_risk)/orig_risk*100) if orig_risk>0 else 0,
|
| 378 |
-
"icon": "πΌ", "factor_changed": "Internships",
|
| 379 |
-
"original_value": str(data.Internships), "suggested_value": str(mod['Internships'])
|
| 380 |
-
})
|
| 381 |
-
sid+=1
|
| 382 |
|
| 383 |
# Clear Backlogs
|
| 384 |
if data.HistoryOfBacklogs == 1:
|
| 385 |
mod = orig_dict.copy()
|
| 386 |
mod['HistoryOfBacklogs'] = 0
|
| 387 |
-
|
| 388 |
-
|
| 389 |
-
"
|
| 390 |
-
"
|
| 391 |
-
|
| 392 |
-
"risk_delta": orig_risk - mod_risk,
|
| 393 |
-
"risk_reduction_percent": ((mod_risk - orig_risk)/orig_risk*100) if orig_risk>0 else 0,
|
| 394 |
-
"icon": "β
", "factor_changed": "HistoryOfBacklogs",
|
| 395 |
-
"original_value": "Yes", "suggested_value": "No"
|
| 396 |
-
})
|
| 397 |
-
sid+=1
|
| 398 |
|
| 399 |
-
# Change Stream
|
| 400 |
if data.Stream != "Computer Science" and "Computer Science" in le_stream.classes_:
|
| 401 |
mod = orig_dict.copy()
|
| 402 |
mod['Stream'] = "Computer Science"
|
| 403 |
mod_risk = _predict(mod)
|
| 404 |
-
if
|
| 405 |
-
|
| 406 |
-
|
| 407 |
-
|
| 408 |
-
|
| 409 |
-
|
| 410 |
-
"risk_reduction_percent": ((mod_risk - orig_risk)/orig_risk*100) if orig_risk>0 else 0,
|
| 411 |
-
"icon": "π»", "factor_changed": "Stream",
|
| 412 |
-
"original_value": data.Stream, "suggested_value": "Computer Science"
|
| 413 |
-
})
|
| 414 |
-
sid+=1
|
| 415 |
|
| 416 |
# Stay in Hostel
|
| 417 |
if data.Hostel == 0:
|
| 418 |
mod = orig_dict.copy()
|
| 419 |
mod['Hostel'] = 1
|
| 420 |
mod_risk = _predict(mod)
|
| 421 |
-
if
|
| 422 |
-
|
| 423 |
-
|
| 424 |
-
"
|
| 425 |
-
"
|
| 426 |
-
|
| 427 |
-
|
| 428 |
-
"icon": "π’", "factor_changed": "Hostel",
|
| 429 |
-
"original_value": "No", "suggested_value": "Yes"
|
| 430 |
-
})
|
| 431 |
-
sid+=1
|
| 432 |
-
|
| 433 |
-
import math
|
| 434 |
-
for s in scenarios:
|
| 435 |
-
# Invert delta so positive = 'improvement' for the JS UI
|
| 436 |
-
s['risk_delta'] = s['modified_risk'] - s['original_risk']
|
| 437 |
-
|
| 438 |
scenarios.sort(key=lambda x: x['risk_delta'], reverse=True)
|
| 439 |
|
| 440 |
-
#
|
| 441 |
best_case = orig_dict.copy()
|
|
|
|
| 442 |
if data.Internships < 3: best_case['Internships'] += 1
|
| 443 |
if data.HistoryOfBacklogs == 1: best_case['HistoryOfBacklogs'] = 0
|
| 444 |
|
| 445 |
-
# Optional stream switch if it was a scenario that improved things
|
| 446 |
-
if data.Stream != "Computer Science" and "Computer Science" in le_stream.classes_:
|
| 447 |
-
# re-check if it's better
|
| 448 |
-
if _predict(best_case.copy()) < _predict({**best_case, 'Stream': 'Computer Science'}):
|
| 449 |
-
best_case['Stream'] = 'Computer Science'
|
| 450 |
-
|
| 451 |
combined_risk = _predict(best_case)
|
| 452 |
combined_level, _ = get_placement_level(combined_risk / 100)
|
| 453 |
|
|
|
|
| 346 |
|
| 347 |
scenarios = []
|
| 348 |
sid = 1
|
| 349 |
+
|
| 350 |
+
def add_scenario(mod_dict, title, description, change_summary, icon, factor_changed, original_value, suggested_value, mod_risk=None):
|
| 351 |
+
nonlocal sid
|
| 352 |
+
if mod_risk is None:
|
| 353 |
+
mod_risk = _predict(mod_dict)
|
| 354 |
+
scenarios.append({
|
| 355 |
+
"scenario_id": sid,
|
| 356 |
+
"title": title,
|
| 357 |
+
"description": description,
|
| 358 |
+
"change_summary": change_summary,
|
| 359 |
+
"original_risk": orig_risk,
|
| 360 |
+
"modified_risk": mod_risk,
|
| 361 |
+
"risk_delta": mod_risk - orig_risk,
|
| 362 |
+
"risk_reduction_percent": ((mod_risk - orig_risk) / (orig_risk if orig_risk > 0 else 1) * 100),
|
| 363 |
+
"icon": icon,
|
| 364 |
+
"factor_changed": factor_changed,
|
| 365 |
+
"original_value": str(original_value),
|
| 366 |
+
"suggested_value": str(suggested_value)
|
| 367 |
+
})
|
| 368 |
+
sid += 1
|
| 369 |
+
|
| 370 |
+
# PR Specific: Career Path Suggestion (from Routing Engine)
|
| 371 |
if routing_engine and data.skills and data.desired_role:
|
| 372 |
rec_job, _ = routing_engine.recommend(data.skills)
|
| 373 |
if rec_job:
|
| 374 |
transition = routing_engine.get_career_transition_path(rec_job, data.desired_role)
|
| 375 |
if transition and transition.get("skills_to_learn"):
|
| 376 |
+
# Show full list of skills to learn (do not truncate to 3)
|
| 377 |
+
skills_list = ", ".join(transition["skills_to_learn"])
|
| 378 |
+
add_scenario(
|
| 379 |
+
orig_dict, "Career Path Suggestion",
|
| 380 |
+
"Learning these skills can help you transition towards your desired role.",
|
| 381 |
+
f"Learn: {skills_list}", "π§ ", "Skills",
|
| 382 |
+
"Current Skills", skills_list, mod_risk=orig_risk
|
| 383 |
+
)
|
| 384 |
+
|
| 385 |
+
# Increase CGPA
|
| 386 |
+
if data.CGPA < 9.0:
|
| 387 |
+
mod = orig_dict.copy()
|
| 388 |
+
mod['CGPA'] = min(data.CGPA + 1.0, 10.0)
|
| 389 |
+
add_scenario(
|
| 390 |
+
mod, "+1.0 CGPA", "What if you improved your CGPA?",
|
| 391 |
+
f"CGPA: {data.CGPA} β {mod['CGPA']}", "π", "CGPA",
|
| 392 |
+
str(data.CGPA), str(mod['CGPA'])
|
| 393 |
+
)
|
| 394 |
|
| 395 |
# Add Internships
|
| 396 |
if data.Internships < 3:
|
| 397 |
mod = orig_dict.copy()
|
| 398 |
mod['Internships'] += 1
|
| 399 |
+
add_scenario(
|
| 400 |
+
mod, "Extra Internship", "What if you did one more internship?",
|
| 401 |
+
f"Internships: {data.Internships} β {mod['Internships']}", "πΌ", "Internships",
|
| 402 |
+
str(data.Internships), str(mod['Internships'])
|
| 403 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 404 |
|
| 405 |
# Clear Backlogs
|
| 406 |
if data.HistoryOfBacklogs == 1:
|
| 407 |
mod = orig_dict.copy()
|
| 408 |
mod['HistoryOfBacklogs'] = 0
|
| 409 |
+
add_scenario(
|
| 410 |
+
mod, "Clear Backlogs", "What if you had no history of backlogs?",
|
| 411 |
+
"Backlogs: Yes β No", "β
", "HistoryOfBacklogs",
|
| 412 |
+
"Yes", "No"
|
| 413 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 414 |
|
| 415 |
+
# Change Stream
|
| 416 |
if data.Stream != "Computer Science" and "Computer Science" in le_stream.classes_:
|
| 417 |
mod = orig_dict.copy()
|
| 418 |
mod['Stream'] = "Computer Science"
|
| 419 |
mod_risk = _predict(mod)
|
| 420 |
+
if mod_risk > orig_risk:
|
| 421 |
+
add_scenario(
|
| 422 |
+
mod, "Switch to CS", "What if you switched your stream to Computer Science?",
|
| 423 |
+
f"Stream: {data.Stream} β Computer Science", "π»", "Stream",
|
| 424 |
+
data.Stream, "Computer Science", mod_risk=mod_risk
|
| 425 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 426 |
|
| 427 |
# Stay in Hostel
|
| 428 |
if data.Hostel == 0:
|
| 429 |
mod = orig_dict.copy()
|
| 430 |
mod['Hostel'] = 1
|
| 431 |
mod_risk = _predict(mod)
|
| 432 |
+
if mod_risk > orig_risk:
|
| 433 |
+
add_scenario(
|
| 434 |
+
mod, "Stay in Hostel", "What if you stayed in a hostel?",
|
| 435 |
+
"Hostel: No β Yes", "π’", "Hostel",
|
| 436 |
+
"No", "Yes", mod_risk=mod_risk
|
| 437 |
+
)
|
| 438 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 439 |
scenarios.sort(key=lambda x: x['risk_delta'], reverse=True)
|
| 440 |
|
| 441 |
+
# Combined Best Case
|
| 442 |
best_case = orig_dict.copy()
|
| 443 |
+
if data.CGPA < 9.0: best_case['CGPA'] = min(data.CGPA + 1.0, 10.0)
|
| 444 |
if data.Internships < 3: best_case['Internships'] += 1
|
| 445 |
if data.HistoryOfBacklogs == 1: best_case['HistoryOfBacklogs'] = 0
|
| 446 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 447 |
combined_risk = _predict(best_case)
|
| 448 |
combined_level, _ = get_placement_level(combined_risk / 100)
|
| 449 |
|
script.js
CHANGED
|
@@ -555,7 +555,8 @@ function getRecommendations(riskLevel) {
|
|
| 555 |
const skillsRec = currentPrediction?.missing_skills && currentPrediction.missing_skills.length > 0 ? {
|
| 556 |
icon: 'π οΈ',
|
| 557 |
title: 'Skill Gaps',
|
| 558 |
-
|
|
|
|
| 559 |
} : null;
|
| 560 |
|
| 561 |
let base = [
|
|
|
|
| 555 |
const skillsRec = currentPrediction?.missing_skills && currentPrediction.missing_skills.length > 0 ? {
|
| 556 |
icon: 'π οΈ',
|
| 557 |
title: 'Skill Gaps',
|
| 558 |
+
// Show full list of missing skills rather than truncating
|
| 559 |
+
text: `Focus on mastering: ${currentPrediction.missing_skills.join(', ')}`
|
| 560 |
} : null;
|
| 561 |
|
| 562 |
let base = [
|