PawMatchAI / html_templates.py
DawnC's picture
Upload 9 files
0ef1e7a verified
raw
history blame
29.2 kB
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>
"""