Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
# ============================================================
Expand Down
18 changes: 10 additions & 8 deletions utils/recommender.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
Loading