2025-03-27 17:57:27 +00:00

116 lines
3.7 KiB
Python

from typing import Dict, Optional, List, Union
from datetime import datetime
from sqlalchemy.orm import Session
import re
from models.project import Project
from schemas.project import ProjectCreate, ProjectUpdate
def validate_github_link(github_link: str) -> bool:
"""
Validate GitHub repository URL format.
Args:
github_link: GitHub URL to validate
Returns:
bool: True if URL format is valid, False otherwise
"""
pattern = r'^https?:\/\/github\.com\/[\w-]+\/[\w-]+(?:\.git)?$'
return bool(re.match(pattern, github_link))
def validate_project_data(project_data: ProjectCreate) -> Dict[str, str]:
"""
Validate project data before creation.
Args:
project_data: Project data to validate
Returns:
Dict containing validation errors if any
"""
errors = {}
if len(project_data.title) > 255:
errors["title"] = "Title must not exceed 255 characters"
if not project_data.description:
errors["description"] = "Description is required"
if project_data.year < 2000 or project_data.year > datetime.now().year:
errors["year"] = "Invalid year"
if project_data.github_link and not validate_github_link(project_data.github_link):
errors["github_link"] = "Invalid GitHub repository URL"
return errors
def get_projects_by_technology(db: Session, technology: str) -> List[Project]:
"""
Get all projects that use a specific technology.
Args:
db: Database session
technology: Technology to search for
Returns:
List of projects using the specified technology
"""
return db.query(Project).filter(Project.technologies_used.ilike(f'%{technology}%')).all()
def get_department_statistics(db: Session) -> Dict[str, Dict[str, Union[int, float]]]:
"""
Get project statistics by department.
Args:
db: Database session
Returns:
Dictionary containing department statistics
"""
departments = db.query(Project.department).distinct().all()
stats = {}
for dept in departments:
dept_name = dept[0]
dept_projects = db.query(Project).filter(Project.department == dept_name).all()
published_count = sum(1 for p in dept_projects if p.is_published)
avg_grade = sum(float(p.grade) for p in dept_projects if p.grade) / len(dept_projects) if dept_projects else 0
stats[dept_name] = {
"total_projects": len(dept_projects),
"published_projects": published_count,
"average_grade": round(avg_grade, 2)
}
return stats
def format_project_response(project: Project) -> Dict[str, Any]:
"""
Format project data for API response.
Args:
project: Project object to format
Returns:
Formatted project data dictionary
"""
technologies = project.technologies_used.split(',') if project.technologies_used else []
return {
"id": project.id,
"title": project.title,
"description": project.description,
"student_name": project.student_name,
"supervisor_name": project.supervisor_name,
"department": project.department,
"year": project.year,
"status": project.status,
"technologies": technologies,
"github_link": project.github_link,
"documentation_link": project.documentation_link,
"grade": project.grade,
"is_published": project.is_published,
"created_at": project.created_at.isoformat() if project.created_at else None,
"updated_at": project.updated_at.isoformat() if project.updated_at else None
}