diff --git a/tests/test_basic.py b/tests/test_basic.py index cc0a80fc..68918cdd 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -271,6 +271,14 @@ def test_download_code_found(): assert response.status_code == 200 +from utils.recommender import SCORING_WEIGHTS + +def test_scoring_weights_has_all_keys(): + """SCORING_WEIGHTS must contain exactly the four expected keys.""" + expected_keys = {"skill", "level", "interest", "time"} + assert set(SCORING_WEIGHTS.keys()) == expected_keys + + # ============================================================ # Run tests directly (no pytest required) # ============================================================ diff --git a/utils/recommender.py b/utils/recommender.py index e96f0524..308c14f4 100644 --- a/utils/recommender.py +++ b/utils/recommender.py @@ -10,10 +10,12 @@ # Scoring weights used by the recommendation engine. # Higher weights mean that criterion has more influence # on the final recommendation score. -WEIGHT_SKILL = 3 # highest because they best reflect project compatibility -WEIGHT_LEVEL = 2 # helps avoid projects that are too easy or too difficult -WEIGHT_INTEREST = 2 # Interest alignment improves recommendation relevance -WEIGHT_TIME = 1 # Time availability acts as a smaller tie-breaker factor +SCORING_WEIGHTS = { + "skill": 3, + "level": 2, + "interest": 2, + "time": 1, +} # Common aliases and abbreviations for skills @@ -74,17 +76,17 @@ def score_single_project( matched_skills = sum(1 for skill in user_skills if skill in project_skills) # Add weighted points based on the number of matching skills. # More overlapping skills result in a higher recommendation score. - score += matched_skills * WEIGHT_SKILL + score += matched_skills * SCORING_WEIGHTS["skill"] # Award points for each additional matching criterion if project.get("level", "").lower() == level.lower(): - score += WEIGHT_LEVEL + score += SCORING_WEIGHTS["level"] if project.get("interest", "").lower() == interest.lower(): - score += WEIGHT_INTEREST + score += SCORING_WEIGHTS["interest"] if project.get("time", "").lower() == time_availability.lower(): - score += WEIGHT_TIME + score += SCORING_WEIGHTS["time"] return score