Manages logo storage and retrieval using file-based matching.
| 21 | |
| 22 | |
| 23 | class LogoManager: |
| 24 | """Manages logo storage and retrieval using file-based matching.""" |
| 25 | |
| 26 | def __init__(self, base_path: str = "logo_store"): |
| 27 | """ |
| 28 | Initialize the LogoManager. |
| 29 | |
| 30 | Args: |
| 31 | base_path: Base directory for logo storage |
| 32 | """ |
| 33 | self.base_path = Path(base_path) |
| 34 | self._setup_directories() |
| 35 | |
| 36 | def _setup_directories(self): |
| 37 | """Create necessary directories for logo storage.""" |
| 38 | directories = [ |
| 39 | self.base_path, |
| 40 | self.base_path / "conferences", |
| 41 | self.base_path / "institutes", |
| 42 | self.base_path / "raw_downloads" |
| 43 | ] |
| 44 | for directory in directories: |
| 45 | directory.mkdir(parents=True, exist_ok=True) |
| 46 | |
| 47 | def _normalize_name(self, name: str) -> str: |
| 48 | """Normalize a name for matching.""" |
| 49 | # Remove common suffixes like years |
| 50 | name = re.sub(r'\s*\d{4}\s*$', '', name) |
| 51 | # Convert to lowercase and replace spaces/special chars |
| 52 | name = name.lower() |
| 53 | name = re.sub(r'[^a-z0-9]+', '_', name) |
| 54 | name = name.strip('_') |
| 55 | return name |
| 56 | |
| 57 | def _fuzzy_match(self, query: str, candidates: List[str]) -> Tuple[Optional[str], float]: |
| 58 | """ |
| 59 | Find the best fuzzy match for a query among candidates. |
| 60 | |
| 61 | Args: |
| 62 | query: The search query |
| 63 | candidates: List of candidate strings |
| 64 | |
| 65 | Returns: |
| 66 | Best matching candidate and similarity score (0-1) |
| 67 | """ |
| 68 | query_norm = self._normalize_name(query) |
| 69 | best_match = None |
| 70 | best_score = 0.0 |
| 71 | |
| 72 | for candidate in candidates: |
| 73 | # Check exact match first |
| 74 | if query_norm == candidate: |
| 75 | return candidate, 1.0 |
| 76 | |
| 77 | # Check if query is contained in candidate or vice versa |
| 78 | if query_norm in candidate or candidate in query_norm: |
| 79 | score = 0.9 |
| 80 | if score > best_score: |
no outgoing calls
no test coverage detected