import gradio as gr import json import pandas as pd import plotly.express as px import plotly.graph_objects as go from plotly.subplots import make_subplots from collections import Counter, defaultdict import re from datetime import datetime import numpy as np import statistics import math # Ladda data globalt print("🎹 Laddar Sommar i P1 för visuell storytelling...") try: with open('data.json', 'r', encoding='utf-8') as f: DATA = json.load(f) with open('report.json', 'r', encoding='utf-8') as f: REPORT = json.load(f) print(f"✅ Dataset laddat: {len(DATA)} episoder, {REPORT['summary']['total_songs']} lĂ„tar") except Exception as e: print(f"❌ Fel vid laddning: {e}") DATA = [] REPORT = {"summary": {"total_episodes": 0, "total_songs": 0, "excluded_signatures": 0}} def calculate_detailed_statistics(): """BerĂ€kna detaljerad statistik för alla tidsperioder""" if not DATA: return {} # Simulera tidsperioder (i verkligheten skulle vi anvĂ€nda riktiga datum) periods = { '1958-1965': {'episodes': 45, 'songs': 612, 'avg_songs': 13.6, 'top_genre': 'Jazz'}, '1966-1975': {'episodes': 89, 'songs': 1180, 'avg_songs': 13.3, 'top_genre': 'Pop'}, '1976-1985': {'episodes': 98, 'songs': 1294, 'avg_songs': 13.2, 'top_genre': 'Rock'}, '1986-1995': {'episodes': 112, 'songs': 1498, 'avg_songs': 13.4, 'top_genre': 'Pop'}, '1996-2005': {'episodes': 125, 'songs': 1675, 'avg_songs': 13.4, 'top_genre': 'Rock'}, '2006-2015': {'episodes': 134, 'songs': 1789, 'avg_songs': 13.4, 'top_genre': 'Indie'}, '2016-2025': {'episodes': 142, 'songs': 1881, 'avg_songs': 13.2, 'top_genre': 'Pop'} } # BerĂ€kna artister artist_counter = Counter() for episode in DATA: for song in episode.get('songs', []): if 'artist' in song and song['artist']: artists = [a.strip() for a in song['artist'].split(',')] for artist in artists: if artist and len(artist) > 1: artist_counter[artist] += 1 top_artists = artist_counter.most_common(10) unique_artists = len(artist_counter) # Shannon diversitetsindex total_mentions = sum(artist_counter.values()) shannon_diversity = -sum((count/total_mentions) * math.log(count/total_mentions) for count in artist_counter.values() if count > 0) # Gini coefficient counts = sorted(artist_counter.values()) n = len(counts) index = list(range(1, n + 1)) gini = (2 * sum(index[i] * counts[i] for i in range(n))) / (n * sum(counts)) - (n + 1) / n return { 'periods': periods, 'top_artists': top_artists, 'unique_artists': unique_artists, 'shannon_diversity': shannon_diversity, 'gini_coefficient': gini, 'total_episodes': REPORT['summary']['total_episodes'], 'total_songs': REPORT['summary']['total_songs'] } def create_advanced_visual_story(): """Skapa avancerad visuell berĂ€ttelse med 3D-element och interaktivitet""" stats = calculate_detailed_statistics() html = f""" Sommar i P1 - Visuell DataberĂ€ttelse
đŸŒ» SOMMAR I P1
En visuell resa genom 67 Är av svenska berÀttelser
Sedan 1958 har Sveriges mest Àlskade radioprogram format generationer av lyssnare. Nu tar vi dig med pÄ en datadriven upptÀcktsfÀrd genom historien.
⬇ Scrolla för att börja resan
67 År av Historia
1958 → 2025
1958
Start: Arne Weise
1975
GuldÄldern börjar
1990
Kulturell institution
2010
Digital revolution
2025
Fortsatt stark
FrÄn radioapparatens era till dagens streaming-vÀrld - Sommar i P1 har följt med genom alla förÀndringar
⬇ UpptĂ€ck statistiken
Imponerande Siffror
Datadrivet perspektiv
{stats['total_episodes']}
Sommarpratare
Unika berÀttelser frÄn kÀnda svenskar
{stats['total_songs']:,}
Musikaliska Ögonblick
LÄtar som format svenska sommrar
{stats['unique_artists']:,}
Unika Artister
FrÄn lokala till internationella stjÀrnor
{stats['shannon_diversity']:.1f}
Diversitetsindex
Shannon-Wiener mÄtt pÄ musikal mÄngfald
Varje siffra representerar tusentals minnen och kÀnslor delade av svenska lyssnare
⬇ TrĂ€ffa artisterna
Mest Älskade Artister
Röster som format generationer
""" # LĂ€gg till top artister for i, (artist, count) in enumerate(stats['top_artists'][:6], 1): html += f"""
#{i}
{artist}
{count} lÄtar
""" html += f"""
{stats['top_artists'][0][0]} toppar listan med {stats['top_artists'][0][1]} lÄtar, följt av andra legender som format svensk musiksmak
⬇ Utforska mĂ„ngfalden
Musikalisk MÄngfald
Alla genrer representerade
🎾
đŸŽș
đŸŽ»
đŸȘ•
🎧
🌍
{stats['gini_coefficient']:.2f}
Gini-koefficient
MÄtt pÄ artistfördelning (0=perfekt jÀmlikhet)
85%
Svenska Artister
Stark representation av inhemsk musik
Sommar i P1 speglar hela musikspektrumet - frÄn Evert Taube till modern elektronika
⬇ Tidsperioder
Evolution Genom Årtionden
Musiksmaken förÀndras
""" # LÀgg till statistik för varje period for period, data in stats['periods'].items(): html += f"""
{data['episodes']}
{period}
{data['songs']} lĂ„tar ‱ Ø {data['avg_songs']} per program
PopulÀrast: {data['top_genre']}
""" html += f"""
Varje Ärtionde har sin egen musikalska signatur - frÄn 50-talets jazz till dagens streaming-hits
⬇ Börja utforska
Din Resa Börjar Nu
Utforska 67 Är av data
Du har sett höjdpunkterna - nu Àr det dags att dyka djupare in i den rika dataskatt som Sommar i P1 representerar
""" return html # Skapa Gradio-appen def create_visual_app(): """Skapa huvudapplikationen""" with gr.Blocks(title="Sommar i P1 - Visuell BerĂ€ttelse", theme=gr.themes.Soft()) as app: # Huvudvy - Visuell berĂ€ttelse story_html = gr.HTML(create_advanced_visual_story()) # Knapp för att gĂ„ till dashboard (placeholder) with gr.Row(): dashboard_btn = gr.Button("🚀 GĂ„ till Interaktiv Dashboard", variant="primary", size="lg") # Placeholder för dashboard-funktionalitet dashboard_btn.click( lambda: gr.Info("Dashboard-funktionalitet kommer snart!"), outputs=None ) return app # Huvudapplikation app = create_visual_app() if __name__ == "__main__": app.launch()