Sommar / profile_data_provider.py
KSAklfszf921
Enhance profile functionality with real data integration
a460813
import json
from datetime import datetime
import re
class ProfileDataProvider:
"""Tillhandahåller riktig profildata för sommarpratare"""
def __init__(self, data_file, image_matcher):
self.data_file = data_file
self.image_matcher = image_matcher
self.episodes = []
self._load_data()
def _load_data(self):
"""Ladda episoddata"""
try:
with open(self.data_file, 'r', encoding='utf-8') as f:
self.episodes = json.load(f)
except Exception as e:
print(f"Fel vid laddning av profildata: {e}")
self.episodes = []
def get_profile_data(self, name, year=None):
"""Hämta komplett profildata för en person"""
# Hitta alla episoder för denna person
matching_episodes = []
for episode in self.episodes:
episode_title = episode.get('episode_title', '')
if self._names_match(name, episode_title):
matching_episodes.append(episode)
if not matching_episodes:
return None
# Välj rätt episod baserat på år om angivet
selected_episode = self._select_best_episode(matching_episodes, year)
# Hämta matchande bilder
images = []
if self.image_matcher:
images = self.image_matcher.find_images_for_episode(selected_episode)
# Bygg profildata
profile = {
'name': name,
'year': year,
'episodes': matching_episodes,
'selected_episode': selected_episode,
'images': images,
'stats': self._calculate_person_stats(matching_episodes),
'biography': self._generate_biography(name, matching_episodes),
'career_span': self._get_career_span(matching_episodes)
}
return profile
def _select_best_episode(self, episodes, target_year):
"""Välj bästa episod baserat på år"""
if not episodes:
return None
if not target_year:
# Returnera senaste episoden
return max(episodes, key=lambda ep: ep.get('episode_date', ''))
# Hitta episod närmast målåret
target_year = int(target_year)
best_episode = episodes[0]
min_diff = float('inf')
for episode in episodes:
date_str = episode.get('episode_date', '')
if date_str:
try:
ep_year = int(date_str.split('-')[0])
diff = abs(ep_year - target_year)
if diff < min_diff:
min_diff = diff
best_episode = episode
except:
continue
return best_episode
def _names_match(self, name1, name2):
"""Kontrollera om två namn matchar"""
if not name1 or not name2:
return False
# Normalisera namn
norm1 = self._normalize_name(name1)
norm2 = self._normalize_name(name2)
# Exakt matchning
if norm1 == norm2:
return True
# Kontrollera om det ena namnet innehåller det andra
if norm1 in norm2 or norm2 in norm1:
return True
# Kontrollera för- och efternamn
parts1 = norm1.split()
parts2 = norm2.split()
if len(parts1) >= 2 and len(parts2) >= 2:
# Jämför förnamn och efternamn
if parts1[0] == parts2[0] and parts1[-1] == parts2[-1]:
return True
return False
def _normalize_name(self, name):
"""Normalisera namn för jämförelse"""
# Ta bort extra tecken och gör lowercase
normalized = re.sub(r'[^\w\s]', '', name.lower())
# Ta bort extra whitespace
normalized = re.sub(r'\s+', ' ', normalized).strip()
return normalized
def _calculate_person_stats(self, episodes):
"""Beräkna statistik för en person"""
if not episodes:
return {'episodes': 0, 'songs': 0, 'years_active': 0}
total_songs = sum(len(ep.get('songs', [])) for ep in episodes)
# Beräkna aktiva år
years = []
for episode in episodes:
date_str = episode.get('episode_date', '')
if date_str:
try:
year = int(date_str.split('-')[0])
years.append(year)
except:
continue
years_active = max(years) - min(years) + 1 if years else 0
return {
'episodes': len(episodes),
'songs': total_songs,
'years_active': years_active,
'first_year': min(years) if years else None,
'last_year': max(years) if years else None
}
def _generate_biography(self, name, episodes):
"""Generera en kort biografi baserat på episoddata"""
if not episodes:
return f"{name} är en svensk kulturpersonlighet som har delat sina berättelser i Sommar i P1."
stats = self._calculate_person_stats(episodes)
bio_parts = [f"{name} har varit sommarpratare i Sveriges Radio"]
if stats['episodes'] > 1:
bio_parts.append(f"vid {stats['episodes']} tillfällen")
if stats['first_year'] and stats['last_year']:
if stats['first_year'] == stats['last_year']:
bio_parts.append(f"år {stats['first_year']}")
else:
bio_parts.append(f"mellan {stats['first_year']} och {stats['last_year']}")
bio = " ".join(bio_parts) + "."
# Lägg till information om musikval
if stats['songs'] > 0:
bio += f" Genom {stats['songs']} låtar har {name.split()[0]} delat sin musiksmak och sina minnen med svenska lyssnare."
# Lägg till reflektion om betydelse
if stats['episodes'] > 2:
bio += f" Som återkommande sommarpratare har {name.split()[0]} blivit en viktig röst i programmet och format många svenska sommrar."
return bio
def _get_career_span(self, episodes):
"""Få karriärspann för personen"""
if not episodes:
return None
years = []
for episode in episodes:
date_str = episode.get('episode_date', '')
if date_str:
try:
year = int(date_str.split('-')[0])
years.append(year)
except:
continue
if not years:
return None
return {
'start': min(years),
'end': max(years),
'span': max(years) - min(years) + 1
}
def get_all_profiles_summary(self):
"""Få sammanfattning av alla profiler"""
people = {}
for episode in self.episodes:
name = episode.get('episode_title', '').strip()
if name:
if name not in people:
people[name] = []
people[name].append(episode)
summary = {
'total_people': len(people),
'multiple_episodes': sum(1 for eps in people.values() if len(eps) > 1),
'most_episodes': max((len(eps) for eps in people.values()), default=0),
'people_by_decade': self._group_by_decade(people)
}
return summary
def _group_by_decade(self, people):
"""Gruppera personer efter årtionde"""
decades = {}
for name, episodes in people.items():
for episode in episodes:
date_str = episode.get('episode_date', '')
if date_str:
try:
year = int(date_str.split('-')[0])
decade = f"{year//10*10}s"
if decade not in decades:
decades[decade] = set()
decades[decade].add(name)
except:
continue
# Konvertera sets till counts
return {decade: len(names) for decade, names in decades.items()}
def create_profile_provider():
"""Skapa och returnera en ProfileDataProvider instans"""
data_file = '/Users/isakskogstad/Desktop/p1_sommar_space/hf_sommar_space/data.json'
try:
from image_matcher import SommarImageMatcher
image_matcher = SommarImageMatcher('images', data_file)
except:
image_matcher = None
return ProfileDataProvider(data_file, image_matcher)
if __name__ == "__main__":
# Test funktionaliteten
provider = create_profile_provider()
# Testa med en känd sommarpratare
profile = provider.get_profile_data("Jonas Gardell", "1992")
if profile:
print(f"Profil för {profile['name']}:")
print(f"Episoder: {profile['stats']['episodes']}")
print(f"Låtar: {profile['stats']['songs']}")
print(f"Biografi: {profile['biography']}")
else:
print("Ingen profil hittad")
# Visa sammanfattning
summary = provider.get_all_profiles_summary()
print(f"\nSammanfattning:")
print(f"Totalt antal personer: {summary['total_people']}")
print(f"Personer med flera episoder: {summary['multiple_episodes']}")
print(f"Mest episoder: {summary['most_episodes']}")