""" Pounce Score calculation. Used across: - Market feed scoring - Auction scraper (persist score for DB-level sorting) - Listings (optional) """ from __future__ import annotations from typing import Optional def calculate_pounce_score_v2( domain: str, tld: Optional[str] = None, *, num_bids: int = 0, age_years: int = 0, is_pounce: bool = False, ) -> int: """ Pounce Score v2.0 - Enhanced scoring algorithm. Factors: - Length (shorter = more valuable) - TLD premium - Market activity (bids) - Age bonus - Pounce Direct bonus (verified listings) - Penalties (hyphens, numbers, etc.) """ score = 50 # Baseline domain = (domain or "").strip().lower() if not domain: return score name = domain.rsplit(".", 1)[0] if "." in domain else domain tld_clean = (tld or (domain.rsplit(".", 1)[-1] if "." in domain else "")).strip().lower().lstrip(".") # A) LENGTH BONUS (exponential for short domains) length_scores = {1: 50, 2: 45, 3: 40, 4: 30, 5: 20, 6: 15, 7: 10} score += length_scores.get(len(name), max(0, 15 - len(name))) # B) TLD PREMIUM tld_scores = { "com": 20, "ai": 25, "io": 18, "co": 12, "ch": 15, "de": 10, "net": 8, "org": 8, "app": 10, "dev": 10, "xyz": 5, } score += tld_scores.get(tld_clean, 0) # C) MARKET ACTIVITY (bids = demand signal) try: bids = int(num_bids or 0) except Exception: bids = 0 if bids >= 20: score += 15 elif bids >= 10: score += 10 elif bids >= 5: score += 5 elif bids >= 2: score += 2 # D) AGE BONUS (established domains) try: age = int(age_years or 0) except Exception: age = 0 if age > 15: score += 10 elif age > 10: score += 7 elif age > 5: score += 3 # E) POUNCE DIRECT BONUS (verified = trustworthy) if is_pounce: score += 10 # F) PENALTIES if "-" in name: score -= 25 if any(c.isdigit() for c in name) and len(name) > 3: score -= 20 if len(name) > 15: score -= 15 # G) CONSONANT CHECK (no gibberish like "xkqzfgh") consonants = "bcdfghjklmnpqrstvwxyz" max_streak = 0 current_streak = 0 for c in name.lower(): if c in consonants: current_streak += 1 max_streak = max(max_streak, current_streak) else: current_streak = 0 if max_streak > 4: score -= 15 return max(0, min(100, score))