diff --git a/src/routes/main_routes.py b/src/routes/main_routes.py index 4eda7694..cdce6177 100644 --- a/src/routes/main_routes.py +++ b/src/routes/main_routes.py @@ -6,6 +6,7 @@ from flask import Blueprint, render_template, request, jsonify, send_from_directory, abort, make_response, redirect, url_for, session from utils.recommender import get_recommendations, validate_recommendation_inputs +import math from utils.data_loader import find_project_by_id, load_all_projects, get_available_levels, get_project_stats, get_available_interests from utils.roadmap_comparer import load_all_career_roadmaps, compare_roadmaps from utils.file_server import read_starter_code, resolve_starter_file diff --git a/src/utils/certification.py b/src/utils/certification.py index ea48264b..08e9fdb8 100644 --- a/src/utils/certification.py +++ b/src/utils/certification.py @@ -1,7 +1,7 @@ """Learning outcome assessment and certification system.""" from typing import Dict, List, Optional -from datetime import datetime +from datetime import datetime, timezone import hashlib @@ -28,7 +28,7 @@ def create_assessment( "skill": skill, "difficulty": difficulty, "questions": questions, - "created_at": datetime.utcnow().isoformat(), + "created_at": datetime.now(timezone.utc).isoformat(), "score": None, "passed": False, "completed_at": None, @@ -48,7 +48,7 @@ def submit_assessment( assessment["score"] = score assessment["passed"] = score >= 70 - assessment["completed_at"] = datetime.utcnow().isoformat() + assessment["completed_at"] = datetime.now(timezone.utc).isoformat() if assessment["passed"]: self._issue_certificate(assessment) @@ -77,7 +77,7 @@ def _issue_certificate(self, assessment: Dict): "skill": assessment["skill"], "difficulty": assessment["difficulty"], "score": assessment["score"], - "issued_at": datetime.utcnow().isoformat(), + "issued_at": datetime.now(timezone.utc).isoformat(), "valid_until": None, "verification_code": self._generate_verification_code(cert_id), } @@ -86,7 +86,7 @@ def _issue_certificate(self, assessment: Dict): def _generate_verification_code(self, cert_id: str) -> str: """Generate unique verification code.""" - data = f"{cert_id}{datetime.utcnow().isoformat()}".encode() + data = f"{cert_id}{datetime.now(timezone.utc).isoformat()}".encode() return hashlib.sha256(data).hexdigest()[:16] def issue_digital_badge(self, user_id: str, skill: str, level: str) -> Dict: @@ -97,7 +97,7 @@ def issue_digital_badge(self, user_id: str, skill: str, level: str) -> Dict: "user_id": user_id, "skill": skill, "level": level, - "issued_at": datetime.utcnow().isoformat(), + "issued_at": datetime.now(timezone.utc).isoformat(), "icon_url": f"/badges/{skill.lower()}_{level.lower()}.png", "description": f"{level} {skill} Badge", } diff --git a/src/utils/code_review.py b/src/utils/code_review.py index 8138423d..ad4d3f7d 100644 --- a/src/utils/code_review.py +++ b/src/utils/code_review.py @@ -7,7 +7,7 @@ from typing import Dict, List, Optional from enum import Enum -from datetime import datetime +from datetime import datetime, timezone class ReviewStatus(Enum): @@ -100,7 +100,7 @@ def submit_code( "code": code, "language": language, "description": description or "", - "submitted_at": datetime.utcnow().isoformat(), + "submitted_at": datetime.now(timezone.utc).isoformat(), "review_status": ReviewStatus.PENDING.value, "review_count": 0, "metrics": {}, @@ -128,13 +128,13 @@ def start_review( raise ValueError(f"Submission {submission_id} not found") submission = self.submissions[submission_id] - review_id = f"review_{submission_id}_{datetime.utcnow().timestamp()}" + review_id = f"review_{submission_id}_{datetime.now(timezone.utc).timestamp()}" review = { "review_id": review_id, "submission_id": submission_id, "reviewer_id": reviewer_id, - "started_at": datetime.utcnow().isoformat(), + "started_at": datetime.now(timezone.utc).isoformat(), "completed_at": None, "status": ReviewStatus.IN_PROGRESS.value, "overall_score": None, @@ -178,7 +178,7 @@ def add_feedback_comment( "code_snippet": code_snippet, "feedback": feedback, "severity": severity, - "created_at": datetime.utcnow().isoformat(), + "created_at": datetime.now(timezone.utc).isoformat(), } self.feedback_comments[review_id].append(comment) @@ -249,7 +249,7 @@ def complete_review( scores = [s["score"] for s in review["category_scores"].values()] overall_score = sum(scores) / len(scores) if scores else 0 - review["completed_at"] = datetime.utcnow().isoformat() + review["completed_at"] = datetime.now(timezone.utc).isoformat() review["overall_score"] = round(overall_score, 2) review["summary"] = summary review["status"] = ( diff --git a/src/utils/recommender.py b/src/utils/recommender.py index a7d38098..d1a5d291 100644 --- a/src/utils/recommender.py +++ b/src/utils/recommender.py @@ -105,6 +105,7 @@ def clear_caches(): "ai": "artificial intelligence", "k8s": "kubernetes", "tf": "tensorflow", +} # Common aliases and abbreviations for skills # This improves recommendation accuracy by normalizing user input @@ -165,50 +166,10 @@ def parse_skill_entries(skills_string): if s.strip() # skip blanks produced by trailing / consecutive commas ] return [SKILL_SYNONYMS.get(token, token) for token in tokens] - entries = [] - for item in parsed: - if isinstance(item, dict): - skill = _normalize_skill(str(item.get("skill", ""))) - proficiency = str(item.get("proficiency", "Beginner")).strip().title() - else: - skill = _normalize_skill(str(item)) - proficiency = "Beginner" - - if skill: - entries.append( - { - "skill": SKILL_ALIASES.get(skill, skill), - "proficiency": ( - proficiency - if proficiency in ( - "Beginner", - "Intermediate", - "Advanced", - ) - else "Beginner" - ), - } - ) - return entries - except (json.JSONDecodeError, ValueError): - pass - return [ - { - "skill": SKILL_ALIASES.get(_normalize_skill(skill), _normalize_skill(skill)), - "proficiency": "Beginner", - } - for skill in skills_string.split(",") - if skill.strip() - ] -def parse_skills(skills_string): - return [entry["skill"] for entry in parse_skill_entries(skills_string)] - -def parse_skills(skills_string): - return [entry["skill"] for entry in parse_skill_entries(skills_string)] _nlp_model = None _project_embeddings_cache = {}