Spaces:
Running
on
Zero
Running
on
Zero
import gradio as gr | |
from dog_database import get_dog_description | |
def create_comparison_tab(dog_breeds, get_dog_description): | |
"""创建品种比较标签页 | |
Args: | |
dog_breeds: 狗品种列表 | |
get_dog_description: 获取品种描述的函数 | |
""" | |
with gr.TabItem("Breed Comparison"): | |
gr.HTML("<p style='text-align: center;'>Select two dog breeds to compare their characteristics and care requirements.</p>") | |
with gr.Row(): | |
breed1_dropdown = gr.Dropdown( | |
choices=dog_breeds, | |
label="Select First Breed", | |
value="Golden_Retriever" | |
) | |
breed2_dropdown = gr.Dropdown( | |
choices=dog_breeds, | |
label="Select Second Breed", | |
value="Border_Collie" | |
) | |
compare_btn = gr.Button("Compare Breeds") | |
comparison_output = gr.HTML(label="Comparison Results") | |
def get_comparison_styles(): | |
return """ | |
/* Comparison specific styles */ | |
.comparison-grid { | |
display: flex; | |
flex-direction: column; | |
gap: 0; | |
position: relative; | |
} | |
.breed-column { | |
padding: 24px; | |
position: relative; | |
} | |
.breed-column:first-child { | |
margin-bottom: 60px; | |
padding-bottom: 40px; | |
} | |
.breed-column:first-child::after { | |
content: ''; | |
position: absolute; | |
bottom: -30px; | |
left: 0; | |
right: 0; | |
height: 2px; | |
background: linear-gradient( | |
to right, | |
transparent, | |
#cbd5e0 10%, | |
#cbd5e0 90%, | |
transparent | |
); | |
box-shadow: 0 1px 2px rgba(0,0,0,0.1); | |
} | |
.breed-column:first-child::before { | |
content: '•••'; | |
position: absolute; | |
bottom: -38px; | |
left: 50%; | |
transform: translateX(-50%); | |
font-size: 24px; | |
letter-spacing: 8px; | |
color: #94a3b8; | |
text-align: center; | |
background: white; | |
padding: 0 20px; | |
z-index: 1; | |
} | |
.breed-column:first-child .action-section { | |
margin-bottom: 0; | |
padding-bottom: 0; | |
} | |
@media (max-width: 768px) { | |
.breed-column:first-child { | |
margin-bottom: 50px; | |
padding-bottom: 30px; | |
} | |
.breed-column:first-child::after { | |
bottom: -25px; | |
} | |
.breed-column:first-child::before { | |
bottom: -33px; | |
font-size: 20px; | |
} | |
} | |
.dog-info-card { | |
background: white; | |
position: relative; | |
z-index: 0; | |
} | |
.breed-column:nth-child(2) { | |
position: relative; | |
margin-top: 20px; | |
} | |
""" | |
def show_comparison(breed1, breed2): | |
if not breed1 or not breed2: | |
return "Please select two breeds to compare" | |
# 获取所有信息 | |
breed1_info = get_dog_description(breed1) | |
breed2_info = get_dog_description(breed2) | |
breed1_noise = breed_noise_info.get(breed1, {}).get('noise_notes', '').strip().split('\n') | |
breed2_noise = breed_noise_info.get(breed2, {}).get('noise_notes', '').strip().split('\n') | |
breed1_health = breed_health_info.get(breed1, {}).get('health_notes', '').strip().split('\n') | |
breed2_health = breed_health_info.get(breed2, {}).get('health_notes', '').strip().split('\n') | |
def format_noise_info(noise_data): | |
characteristics = [] | |
triggers = [] | |
noise_level = "Moderate" # 默认值 | |
in_characteristics = False | |
in_triggers = False | |
for line in noise_data: | |
line = line.strip() | |
if "Typical noise characteristics:" in line: | |
in_characteristics = True | |
continue | |
elif "Barking triggers:" in line: | |
in_triggers = True | |
in_characteristics = False | |
continue | |
elif "Noise level:" in line: | |
noise_level = line.split(':')[1].strip() | |
continue | |
if line.startswith('•'): | |
if in_characteristics: | |
characteristics.append(line[1:].strip()) | |
elif in_triggers: | |
triggers.append(line[1:].strip()) | |
return { | |
'characteristics': characteristics, | |
'triggers': triggers, | |
'noise_level': noise_level | |
} | |
def format_health_info(health_data): | |
considerations = [] | |
screenings = [] | |
in_considerations = False | |
in_screenings = False | |
for line in health_data: | |
line = line.strip() | |
if "Common breed-specific health considerations" in line: | |
in_considerations = True | |
in_screenings = False | |
continue | |
elif "Recommended health screenings:" in line: | |
in_screenings = True | |
in_considerations = False | |
continue | |
if line.startswith('•'): | |
if in_considerations: | |
considerations.append(line[1:].strip()) | |
elif in_screenings: | |
screenings.append(line[1:].strip()) | |
return { | |
'considerations': considerations, | |
'screenings': screenings | |
} | |
def create_breed_column(breed, info, noise_data, health_data): | |
noise_info = format_noise_info(noise_data) | |
health_info = format_health_info(health_data) | |
basic_info = f""" | |
<div class="breed-column"> | |
<h2 class="section-title"> | |
<span class="icon">🐕</span> {breed.replace('_', ' ')} | |
</h2> | |
<div class="info-section"> | |
<div class="info-item"> | |
<span class="tooltip"> | |
<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 | |
</span> | |
<span class="value">{info.get('Size', 'Not available')}</span> | |
</span> | |
</div> | |
<div class="info-item"> | |
<span class="tooltip"> | |
<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<br> | |
• Moderate: 1-2 hours daily<br> | |
• High: 2+ hours daily | |
</span> | |
<span class="value">{info.get('Exercise Needs', 'Not available')}</span> | |
</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: Occasional brushing<br> | |
• Moderate: Weekly grooming<br> | |
• High: Daily maintenance | |
</span> | |
<span class="value">{info.get('Grooming Needs', 'Not available')}</span> | |
</span> | |
</div> | |
<div class="info-item"> | |
<span class="tooltip"> | |
<span class="icon">👨👩👧👦</span> | |
<span class="label">With Children:</span> | |
<span class="tooltip-icon">ⓘ</span> | |
<span class="tooltip-text"> | |
<strong>Child Compatibility:</strong><br> | |
• Yes: Excellent with kids<br> | |
• Moderate: Good with older children<br> | |
• No: Better for adult households | |
</span> | |
<span class="value">{info.get('Good with Children', 'Not available')}</span> | |
</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 | |
</span> | |
<span class="value">{info.get('Lifespan', 'Not available')}</span> | |
</span> | |
</div> | |
</div> | |
""" | |
# Noise Section | |
noise_section = f""" | |
<div class="noise-section"> | |
<h3 class="section-header"> | |
<span class="icon">🔊</span> Noise Behavior | |
<span class="tooltip"> | |
<span class="tooltip-icon">ⓘ</span> | |
<span class="tooltip-text">Information about typical barking patterns and noise levels</span> | |
</span> | |
</h3> | |
<div class="noise-info"> | |
<div class="noise-details"> | |
<h4 class="section-header">Typical noise characteristics:</h4> | |
<div class="characteristics-list"> | |
{' '.join([f'<div class="list-item">{item}</div>' for item in noise_info['characteristics']]) or '<div class="list-item">Information not available</div>'} | |
</div> | |
<div class="noise-level-display"> | |
<h4 class="section-header">Noise level:</h4> | |
<div class="level-indicator"> | |
<span class="level-text">{noise_info['noise_level']}</span> | |
</div> | |
</div> | |
<h4 class="section-header">Barking triggers:</h4> | |
<div class="triggers-list"> | |
{' '.join([f'<div class="list-item">{item}</div>' for item in noise_info['triggers']]) or '<div class="list-item">Information not available</div>'} | |
</div> | |
</div> | |
</div> | |
</div> | |
""" | |
# Health Section | |
health_section = f""" | |
<div class="health-section"> | |
<h3 class="section-header"> | |
<span class="icon">🏥</span> Health Insights | |
<span class="tooltip"> | |
<span class="tooltip-icon">ⓘ</span> | |
<span class="tooltip-text"> | |
Health information is compiled from multiple sources including veterinary resources, | |
breed guides, and international canine health databases. | |
</span> | |
</span> | |
</h3> | |
<div class="health-info"> | |
<div class="health-details"> | |
<h4 class="section-header">Common health considerations:</h4> | |
<div class="health-grid"> | |
{' '.join([f'<div class="health-item">{item}</div>' for item in health_info['considerations']]) or '<div class="health-item">Information not available</div>'} | |
</div> | |
<h4 class="section-header">Recommended screenings:</h4> | |
<div class="health-grid"> | |
{' '.join([f'<div class="health-item screening">{item}</div>' for item in health_info['screenings']]) or '<div class="health-item screening">Information not available</div>'} | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="action-section"> | |
<a href="https://www.akc.org/dog-breeds/{breed.lower().replace('_', '-')}/" | |
target="_blank" | |
class="akc-button"> | |
<span class="icon">🌐</span> | |
Learn More about {breed.replace('_', ' ')} on AKC | |
</a> | |
</div> | |
</div> | |
""" | |
return basic_info + noise_section + health_section | |
html_output = f""" | |
<div class="dog-info-card"> | |
<div class="comparison-grid"> | |
{create_breed_column(breed1, breed1_info, breed1_noise, breed1_health)} | |
{create_breed_column(breed2, breed2_info, breed2_noise, breed2_health)} | |
</div> | |
<style> | |
{get_comparison_styles()} | |
</style> | |
</div> | |
""" | |
return html_output | |
compare_btn.click( | |
show_comparison, | |
inputs=[breed1_dropdown, breed2_dropdown], | |
outputs=comparison_output | |
) | |
return { | |
'breed1_dropdown': breed1_dropdown, | |
'breed2_dropdown': breed2_dropdown, | |
'compare_btn': compare_btn, | |
'comparison_output': comparison_output | |
} | |