Spaces:
Runtime error
Runtime error
| from typing import List, Optional | |
| from fastapi import APIRouter, Depends, Query | |
| from sqlalchemy.orm import Session | |
| from backend.app.core.database import get_db | |
| from backend.app.repositories.users import UserRepository | |
| from backend.app.schemas.auth import WorkerSearchResult | |
| router = APIRouter(prefix="/workers", tags=["workers"]) | |
| def calculate_ai_score( | |
| rating: float, | |
| completion_rate: int, | |
| distance: float, | |
| online: bool, | |
| verified: bool | |
| ) -> int: | |
| """ | |
| Simulated AI ranking score calculation. | |
| Formula: rating * 7 + completion_rate * 0.25 + online (25 pts) + verified (15 pts) + distance (max 25 - distance * 3) | |
| """ | |
| online_score = 25 if online else 0 | |
| verified_score = 15 if verified else 0 | |
| distance_score = max(0.0, 25.0 - float(distance) * 3.0) | |
| score = (float(rating) * 7.0) + (int(completion_rate) * 0.25) + online_score + verified_score + distance_score | |
| return round(score) | |
| def search_workers( | |
| skill: Optional[str] = Query("All", description="Filter by worker skill type"), | |
| radius: Optional[float] = Query(5.0, description="Max search radius in kilometers"), | |
| online: Optional[str] = Query("yes", description="Filter: 'yes' for online only, 'all' for all"), | |
| q: Optional[str] = Query("", alias="query", description="Search by name or skill query text"), | |
| db: Session = Depends(get_db) | |
| ): | |
| """ | |
| Search and rank construction workers using the location-aware AI ranking algorithm. | |
| """ | |
| user_repo = UserRepository(db) | |
| # Resolve online boolean filter | |
| online_only = (online == "yes") | |
| # Query database workers matching filters | |
| workers = user_repo.get_all_workers( | |
| skill=skill, | |
| radius=radius, | |
| online_only=online_only | |
| ) | |
| results = [] | |
| text_filter = q.strip().lower() | |
| for user in workers: | |
| prof = user.worker_profile | |
| if not prof: | |
| continue | |
| # Text query filtering (by name or skill) | |
| if text_filter and text_filter not in f"{user.name} {prof.skill}".lower(): | |
| continue | |
| # Compute dynamic match score | |
| score = calculate_ai_score( | |
| rating=prof.rating, | |
| completion_rate=prof.completion_rate, | |
| distance=prof.distance, | |
| online=prof.online, | |
| verified=prof.verified | |
| ) | |
| results.append( | |
| WorkerSearchResult( | |
| id=user.id, | |
| name=user.name, | |
| phone=user.phone, | |
| city=user.city, | |
| skill=prof.skill, | |
| rate=prof.rate, | |
| rating=prof.rating, | |
| distance=prof.distance, | |
| online=prof.online, | |
| verified=prof.verified, | |
| completed_jobs=prof.completed_jobs, | |
| completion_rate=prof.completion_rate, | |
| map_x=prof.map_x, | |
| map_y=prof.map_y, | |
| ai_score=score | |
| ) | |
| ) | |
| # Sort results in descending order of AI Match Score | |
| results.sort(key=lambda w: w.ai_score, reverse=True) | |
| return results | |