from typing import Dict, List, Union, Any, Optional, Callable from urllib.parse import quote def get_akc_breeds_link(breed: str) -> str: """Generate AKC breed page URL with intelligent name handling.""" breed_name = breed.lower() breed_name = breed_name.replace('_', '-') breed_name = breed_name.replace("'", '') breed_name = breed_name.replace(" ", '-') special_cases = { 'mexican-hairless': 'xoloitzcuintli', 'brabancon-griffon': 'brussels-griffon', 'bull-mastiff': 'bullmastiff', 'walker-hound': 'treeing-walker-coonhound' } breed_name = special_cases.get(breed_name, breed_name) return f"https://www.akc.org/dog-breeds/{breed_name}/" def get_color_scheme(is_single_dog: bool) -> Union[str, List[str]]: """Get color scheme for dog detection visualization.""" single_dog_color = '#34C759' # 清爽的綠色作為單狗顏色 color_list = [ '#FF5733', # 珊瑚紅 '#28A745', # 深綠色 '#3357FF', # 寶藍色 '#FF33F5', # 粉紫色 '#FFB733', # 橙黃色 '#33FFF5', # 青藍色 '#A233FF', # 紫色 '#FF3333', # 紅色 '#33FFB7', # 青綠色 '#FFE033' # 金黃色 ] return single_dog_color if is_single_dog else color_list def format_warning_html(message: str) -> str: """Format warning messages in a consistent style.""" return f''' <div class="dog-info-card"> <div class="breed-info"> <p class="warning-message"> <span class="icon">⚠️</span> {message} </p> </div> </div> ''' def format_error_message(color: str, index: int) -> str: """Format error message when confidence is too low.""" return f''' <div class="dog-info-card" style="border-left: 8px solid {color};"> <div class="dog-info-header" style="background-color: {color}10;"> <span class="dog-label" style="color: {color};">Dog {index}</span> </div> <div class="breed-info"> <div class="warning-message"> <span class="icon">⚠️</span> The image is unclear or the breed is not in the dataset. Please upload a clearer image. </div> </div> </div> ''' def format_description_html(description: Dict[str, Any], breed: str) -> str: """Format basic breed description with tooltips.""" if not isinstance(description, dict): return f"<p>{description}</p>" fields_order = [ "Size", "Lifespan", "Temperament", "Exercise Needs", "Grooming Needs", "Care Level", "Good with Children", "Description" ] html_parts = [] for field in fields_order: if field in description: value = description[field] tooltip_html = format_tooltip(field, value) html_parts.append(f'<li style="margin-bottom: 10px;">{tooltip_html}</li>') # Add any remaining fields for key, value in description.items(): if key not in fields_order and key != "Breed": html_parts.append(f'<li style="margin-bottom: 10px;"><strong>{key}:</strong> {value}</li>') return f'<ul style="list-style-type: none; padding-left: 0;">{" ".join(html_parts)}</ul>' def format_tooltip(key: str, value: str) -> str: """Format tooltip with content for each field.""" tooltip_contents = { "Size": { "title": "Size Categories", "items": [ "Small: Under 20 pounds", "Medium: 20-60 pounds", "Large: Over 60 pounds", "Giant: Over 100 pounds", "Varies: Depends on variety" ] }, "Exercise Needs": { "title": "Exercise Needs", "items": [ "Low: Short walks and play sessions", "Moderate: 1-2 hours of daily activity", "High: Extensive exercise (2+ hours/day)", "Very High: Constant activity and mental stimulation needed" ] }, "Grooming Needs": { "title": "Grooming Requirements", "items": [ "Low: Basic brushing, occasional baths", "Moderate: Weekly brushing, occasional grooming", "High: Daily brushing, frequent professional grooming needed", "Professional care recommended for all levels" ] }, "Care Level": { "title": "Care Level Explained", "items": [ "Low: Basic care and attention needed", "Moderate: Regular care and routine needed", "High: Significant time and attention needed", "Very High: Extensive care, training and attention required" ] }, "Good with Children": { "title": "Child Compatibility", "items": [ "Yes: Excellent with kids, patient and gentle", "Moderate: Good with older children", "No: Better suited for adult households" ] }, "Lifespan": { "title": "Average Lifespan", "items": [ "Short: 6-8 years", "Average: 10-15 years", "Long: 12-20 years", "Varies by size: Larger breeds typically have shorter lifespans" ] }, "Temperament": { "title": "Temperament Guide", "items": [ "Describes the dog's natural behavior and personality", "Important for matching with owner's lifestyle", "Can be influenced by training and socialization" ] } } tooltip = tooltip_contents.get(key, {"title": key, "items": []}) tooltip_content = "<br>".join([f"• {item}" for item in tooltip["items"]]) return f''' <span class="tooltip"> <strong>{key}:</strong> <span class="tooltip-icon">ⓘ</span> <span class="tooltip-text"> <strong>{tooltip["title"]}:</strong><br> {tooltip_content} </span> </span> {value} ''' def format_single_dog_result(breed: str, description: Dict[str, Any], color: str = "#34C759") -> str: """Format single dog detection result into HTML.""" return f''' <div class="dog-info-card" style="border-left: 8px solid {color};"> <div class="dog-info-header" style="background-color: {color}10;"> <span class="dog-label" style="color: {color};"> <span class="icon">🐾</span> {breed} </span> </div> <div class="breed-info"> <h2 class="section-title"> <span class="icon">📋</span> BASIC INFORMATION </h2> <div class="info-section"> <div class="info-item"> <span class="tooltip tooltip-left"> <span class="icon">📏</span> <span class="label">Size:</span> <span class="tooltip-icon">ⓘ</span> <span class="tooltip-text"> <strong>Size Categories:</strong><br> • Small: Under 20 pounds<br> • Medium: 20-60 pounds<br> • Large: Over 60 pounds<br> • Giant: Over 100 pounds<br> • Varies: Depends on variety </span> </span> <span class="value">{description['Size']}</span> </div> <div class="info-item"> <span class="tooltip"> <span class="icon">⏳</span> <span class="label">Lifespan:</span> <span class="tooltip-icon">ⓘ</span> <span class="tooltip-text"> <strong>Average Lifespan:</strong><br> • Short: 6-8 years<br> • Average: 10-15 years<br> • Long: 12-20 years<br> • Varies by size: Larger breeds typically have shorter lifespans </span> </span> <span class="value">{description['Lifespan']}</span> </div> </div> <h2 class="section-title"> <span class="icon">🐕</span> TEMPERAMENT & PERSONALITY </h2> <div class="temperament-section"> <span class="tooltip"> <span class="value">{description['Temperament']}</span> <span class="tooltip-icon">ⓘ</span> <span class="tooltip-text"> <strong>Temperament Guide:</strong><br> • Describes the dog's natural behavior and personality<br> • Important for matching with owner's lifestyle<br> • Can be influenced by training and socialization </span> </span> </div> <h2 class="section-title"> <span class="icon">💪</span> CARE REQUIREMENTS </h2> <div class="care-section"> <div class="info-item"> <span class="tooltip tooltip-left"> <span class="icon">🏃</span> <span class="label">Exercise:</span> <span class="tooltip-icon">ⓘ</span> <span class="tooltip-text"> <strong>Exercise Needs:</strong><br> • Low: Short walks and play sessions<br> • Moderate: 1-2 hours of daily activity<br> • High: Extensive exercise (2+ hours/day)<br> • Very High: Constant activity and mental stimulation needed </span> </span> <span class="value">{description['Exercise Needs']}</span> </div> <div class="info-item"> <span class="tooltip"> <span class="icon">✂️</span> <span class="label">Grooming:</span> <span class="tooltip-icon">ⓘ</span> <span class="tooltip-text"> <strong>Grooming Requirements:</strong><br> • Low: Basic brushing, occasional baths<br> • Moderate: Weekly brushing, occasional grooming<br> • High: Daily brushing, frequent professional grooming needed<br> • Professional care recommended for all levels </span> </span> <span class="value">{description['Grooming Needs']}</span> </div> <div class="info-item"> <span class="tooltip"> <span class="icon">⭐</span> <span class="label">Care Level:</span> <span class="tooltip-icon">ⓘ</span> <span class="tooltip-text"> <strong>Care Level Explained:</strong><br> • Low: Basic care and attention needed<br> • Moderate: Regular care and routine needed<br> • High: Significant time and attention needed<br> • Very High: Extensive care, training and attention required </span> </span> <span class="value">{description['Care Level']}</span> </div> </div> <h2 class="section-title"> <span class="icon">👨👩👧👦</span> FAMILY COMPATIBILITY </h2> <div class="family-section"> <div class="info-item"> <span class="tooltip"> <span class="icon"></span> <span class="label">Good with Children:</span> <span class="tooltip-icon">ⓘ</span> <span class="tooltip-text"> <strong>Child Compatibility:</strong><br> • Yes: Excellent with kids, patient and gentle<br> • Moderate: Good with older children<br> • No: Better suited for adult households </span> </span> <span class="value">{description['Good with Children']}</span> </div> </div> <h2 class="section-title"> <span class="icon">📝</span> <span class="tooltip"> DESCRIPTION <span class="tooltip-icon">ⓘ</span> <span class="tooltip-text"> <strong>About This Description:</strong><br> • Comprehensive breed overview<br> • Personality and characteristics<br> • Historical background<br> • Typical behaviors and traits </span> </span> </h2> <div class="description-section"> <p>{description.get('Description', '')}</p> </div> <div class="action-section"> <a href="{get_akc_breeds_link(breed)}" target="_blank" class="akc-button"> <span class="icon">🌐</span> Learn more about {breed} on AKC website </a> </div> </div> </div> ''' def format_multiple_breeds_result( topk_breeds: List[str], relative_probs: List[str], color: str, index: int, get_dog_description: Callable ) -> str: """Format multiple breed predictions into HTML with complete information.""" result = f''' <div class="dog-info-card" style="border-left: 8px solid {color};"> <div class="dog-info-header" style="background-color: {color}10;"> <span class="dog-label" style="color: {color};">Dog {index+1}</span> </div> <div class="breed-info"> <div class="model-uncertainty-note"> <span class="icon">ℹ️</span> Note: The model is showing some uncertainty in its predictions. Here are the most likely breeds based on the available visual features. </div> <div class="breeds-list"> ''' for j, (breed, prob) in enumerate(zip(topk_breeds, relative_probs)): description = get_dog_description(breed) result += f''' <div class="breed-option uncertainty-mode"> <div class="breed-header" style="background-color: {color}10;"> <span class="option-number">Option {j+1}</span> <span class="breed-name">{breed}</span> <span class="confidence-badge" style="background-color: {color}20; color: {color};"> Confidence: {prob} </span> </div> <div class="breed-content"> <div class="breed-info"> <!-- BASIC INFORMATION --> <h2 class="section-title"> <span class="icon">📋</span> BASIC INFORMATION </h2> <div class="info-section"> <div class="info-item"> <span class="tooltip tooltip-left"> <span class="icon">📏</span> <span class="label">Size:</span> <span class="tooltip-icon">ⓘ</span> <span class="tooltip-text"> <strong>Size Categories:</strong><br> • Small: Under 20 pounds<br> • Medium: 20-60 pounds<br> • Large: Over 60 pounds<br> • Giant: Over 100 pounds<br> • Varies: Depends on variety </span> </span> <span class="value">{description['Size']}</span> </div> <div class="info-item"> <span class="tooltip"> <span class="icon">⏳</span> <span class="label">Lifespan:</span> <span class="tooltip-icon">ⓘ</span> <span class="tooltip-text"> <strong>Average Lifespan:</strong><br> • Short: 6-8 years<br> • Average: 10-15 years<br> • Long: 12-20 years<br> • Varies by size: Larger breeds typically have shorter lifespans </span> </span> <span class="value">{description['Lifespan']}</span> </div> </div> <!-- TEMPERAMENT & PERSONALITY --> <h2 class="section-title"> <span class="icon">🐕</span> TEMPERAMENT & PERSONALITY </h2> <div class="temperament-section"> <span class="tooltip"> <span class="value">{description['Temperament']}</span> <span class="tooltip-icon">ⓘ</span> <span class="tooltip-text"> <strong>Temperament Guide:</strong><br> • Describes the dog's natural behavior and personality<br> • Important for matching with owner's lifestyle<br> • Can be influenced by training and socialization </span> </span> </div> <!-- CARE REQUIREMENTS --> <h2 class="section-title"> <span class="icon">💪</span> CARE REQUIREMENTS </h2> <div class="care-section"> <div class="info-item"> <span class="tooltip tooltip-left"> <span class="icon">🏃</span> <span class="label">Exercise:</span> <span class="tooltip-icon">ⓘ</span> <span class="tooltip-text"> <strong>Exercise Needs:</strong><br> • Low: Short walks and play sessions<br> • Moderate: 1-2 hours of daily activity<br> • High: Extensive exercise (2+ hours/day)<br> • Very High: Constant activity and mental stimulation needed </span> </span> <span class="value">{description['Exercise Needs']}</span> </div> <div class="info-item"> <span class="tooltip"> <span class="icon">✂️</span> <span class="label">Grooming:</span> <span class="tooltip-icon">ⓘ</span> <span class="tooltip-text"> <strong>Grooming Requirements:</strong><br> • Low: Basic brushing, occasional baths<br> • Moderate: Weekly brushing, occasional grooming<br> • High: Daily brushing, frequent professional grooming needed<br> • Professional care recommended for all levels </span> </span> <span class="value">{description['Grooming Needs']}</span> </div> <div class="info-item"> <span class="tooltip"> <span class="icon">⭐</span> <span class="label">Care Level:</span> <span class="tooltip-icon">ⓘ</span> <span class="tooltip-text"> <strong>Care Level Explained:</strong><br> • Low: Basic care and attention needed<br> • Moderate: Regular care and routine needed<br> • High: Significant time and attention needed<br> • Very High: Extensive care, training and attention required </span> </span> <span class="value">{description['Care Level']}</span> </div> </div> <!-- FAMILY COMPATIBILITY --> <h2 class="section-title"> <span class="icon">👨👩👧👦</span> FAMILY COMPATIBILITY </h2> <div class="family-section"> <div class="info-item"> <span class="tooltip"> <span class="icon"></span> <span class="label">Good with Children:</span> <span class="tooltip-icon">ⓘ</span> <span class="tooltip-text"> <strong>Child Compatibility:</strong><br> • Yes: Excellent with kids, patient and gentle<br> • Moderate: Good with older children<br> • No: Better suited for adult households </span> </span> <span class="value">{description['Good with Children']}</span> </div> </div> <!-- DESCRIPTION --> <h2 class="section-title"> <span class="icon">📝</span> <span class="tooltip"> DESCRIPTION <span class="tooltip-icon">ⓘ</span> <span class="tooltip-text"> <strong>About This Description:</strong><br> • Comprehensive breed overview<br> • Personality and characteristics<br> • Historical background<br> • Typical behaviors and traits </span> </span> </h2> <div class="description-section"> <p>{description.get('Description', '')}</p> </div> <!-- ACTION SECTION --> <div class="action-section"> <a href="{get_akc_breeds_link(breed)}" target="_blank" class="akc-button"> <span class="icon">🌐</span> Learn more about {breed} on AKC website </a> </div> </div> </div> </div> ''' result += '</div></div></div>' return result def format_multi_dog_container(dogs_info: str) -> str: """Wrap multiple dog detection results in a container.""" return f""" <div class="dog-info-card"> {dogs_info} </div> """ def format_breed_details_html(description: Dict[str, Any], breed: str) -> str: """Format breed details for the show_details_html function.""" return f""" <div class="dog-info"> <h2>{breed}</h2> <div class="breed-details"> {format_description_html(description, breed)} <div class="action-section"> <a href="{get_akc_breeds_link(breed)}" target="_blank" class="akc-button"> <span class="icon">🌐</span> Learn more about {breed} on AKC website </a> </div> </div> </div> """ def format_comparison_result(breed1: str, breed2: str, comparison_data: Dict) -> str: """Format breed comparison results into HTML.""" return f""" <div class="comparison-container"> <div class="comparison-header"> <h3>Comparison: {breed1} vs {breed2}</h3> </div> <div class="comparison-content"> <div class="breed-column"> <h4>{breed1}</h4> {format_comparison_details(comparison_data[breed1])} </div> <div class="breed-column"> <h4>{breed2}</h4> {format_comparison_details(comparison_data[breed2])} </div> </div> </div> """ def format_comparison_details(breed_data: Dict) -> str: """Format individual breed details for comparison.""" original_data = breed_data.get('Original_Data', {}) return f""" <div class="comparison-details"> <p><strong>Size:</strong> {original_data.get('Size', 'N/A')}</p> <p><strong>Exercise Needs:</strong> {original_data.get('Exercise Needs', 'N/A')}</p> <p><strong>Care Level:</strong> {original_data.get('Care Level', 'N/A')}</p> <p><strong>Grooming Needs:</strong> {original_data.get('Grooming Needs', 'N/A')}</p> <p><strong>Good with Children:</strong> {original_data.get('Good with Children', 'N/A')}</p> <p><strong>Temperament:</strong> {original_data.get('Temperament', 'N/A')}</p> </div> """ def format_header_html() -> str: """Format the application header HTML.""" return """ <header style='text-align: center; padding: 20px; margin-bottom: 20px;'> <h1 style='font-size: 2.5em; margin-bottom: 10px; color: #2D3748;'> 🐾 PawMatch AI </h1> <h2 style='font-size: 1.2em; font-weight: normal; color: #4A5568; margin-top: 5px;'> Your Smart Dog Breed Guide </h2> <div style='width: 50px; height: 3px; background: linear-gradient(90deg, #4299e1, #48bb78); margin: 15px auto;'></div> <p style='color: #718096; font-size: 0.9em;'> Powered by AI • Breed Recognition • Smart Matching • Companion Guide </p> </header> """