Add initial raport generator

This commit is contained in:
2025-12-03 00:36:34 +01:00
commit f884460eb0
5 changed files with 2260 additions and 0 deletions

290
create_dashboard.py Normal file
View File

@@ -0,0 +1,290 @@
#!/usr/bin/env python3
import argparse
import os
from pathlib import Path
from datetime import datetime
import base64
def create_html_dashboard(base_filename: str, charts_dir: str = "charts", output_file: str = None):
"""
Create an HTML dashboard with all generated charts.
Args:
base_filename: Base filename used for the data
charts_dir: Directory containing chart PNG files
output_file: Output HTML file path
"""
charts_path = Path(charts_dir)
if not charts_path.exists():
print(f"Charts directory not found: {charts_path}")
return
# Chart files to include (in display order)
chart_files = [
("monthly_comparison.png", "Porównanie miesięczne", "Porównanie zużycia energii w poszczególnych miesiącach"),
("cost_analysis_miesięczne.png", "Analiza kosztów - miesięczna", "Koszty i przychody z energii elektrycznej w ujęciu miesięcznym"),
("monthly_hourly_profiles.png", "Profile godzinowe miesięczne", "Średnie godzinowe zużycie energii dla każdego miesiąca"),
("monthly_timeseries.png", "Trend miesięczny", "Miesięczne zużycie energii w czasie"),
("cost_analysis_dzienne.png", "Analiza kosztów - dzienna", "Koszty i przychody z energii elektrycznej w ujęciu dziennym"),
("weekly_timeseries.png", "Trend tygodniowy", "Tygodniowe zużycie energii w czasie"),
("daily_timeseries.png", "Trend dzienny", "Dzienne zużycie energii w czasie"),
("daily_stacked.png", "Obszar skumulowany", "Dzienne zużycie - wykres obszarowy"),
("hourly_timeseries.png", "Dane godzinowe", "Zużycie energii w ciągu dnia (próbka 30 dni)")
]
# Encode images to base64 for embedding
encoded_images = {}
for filename, _, _ in chart_files:
chart_path = charts_path / filename
if chart_path.exists():
with open(chart_path, 'rb') as f:
encoded_images[filename] = base64.b64encode(f.read()).decode('utf-8')
# Generate HTML
html_content = f"""
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Raport PGE - Dashboard Energii</title>
<style>
* {{
margin: 0;
padding: 0;
box-sizing: border-box;
}}
body {{
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f5f5f5;
color: #333;
line-height: 1.6;
}}
.header {{
background: linear-gradient(135deg, #2E86AB, #A23B72);
color: white;
padding: 2rem 0;
text-align: center;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}}
.header h1 {{
font-size: 2.5rem;
margin-bottom: 0.5rem;
}}
.header p {{
font-size: 1.1rem;
opacity: 0.9;
}}
.container {{
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}}
.info-section {{
background: white;
margin: 2rem 0;
padding: 1.5rem;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}}
.chart-grid {{
display: grid;
gap: 2rem;
margin: 2rem 0;
}}
.chart-card {{
background: white;
border-radius: 10px;
padding: 1.5rem;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}}
.chart-card:hover {{
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0,0,0,0.15);
}}
.chart-card h3 {{
color: #2E86AB;
margin-bottom: 0.5rem;
font-size: 1.4rem;
}}
.chart-card p {{
color: #666;
margin-bottom: 1rem;
}}
.chart-card img {{
width: 100%;
height: auto;
border-radius: 5px;
}}
.energy-legend {{
display: flex;
justify-content: center;
gap: 2rem;
margin: 1rem 0;
flex-wrap: wrap;
}}
.legend-item {{
display: flex;
align-items: center;
gap: 0.5rem;
}}
.legend-color {{
width: 20px;
height: 20px;
border-radius: 3px;
}}
.legend-zbilansowana {{ background-color: #2E86AB; }}
.legend-oddana {{ background-color: #A23B72; }}
.legend-pobrana {{ background-color: #F18F01; }}
.footer {{
text-align: center;
padding: 2rem;
color: #666;
background: #f9f9f9;
margin-top: 2rem;
}}
@media (max-width: 768px) {{
.container {{
padding: 1rem;
}}
.header h1 {{
font-size: 2rem;
}}
.energy-legend {{
flex-direction: column;
align-items: center;
gap: 1rem;
}}
}}
</style>
</head>
<body>
<div class="header">
<h1>🔌 Dashboard Energii PGE</h1>
<p>Analiza zużycia energii elektrycznej</p>
</div>
<div class="container">
<div class="info-section">
<h2>📊 Informacje o raporcie</h2>
<p><strong>Plik źródłowy:</strong> {base_filename}</p>
<p><strong>Data generowania:</strong> {datetime.now().strftime('%d/%m/%Y %H:%M')}</p>
<p><strong>Typ analizy:</strong> Kompletna analiza czasowa (godzinowa, dzienna, tygodniowa, miesięczna)</p>
</div>
<div class="info-section">
<h3>🎨 Legenda typów energii</h3>
<div class="energy-legend">
<div class="legend-item">
<div class="legend-color legend-zbilansowana"></div>
<span><strong>Czynna zbilansowana</strong> - Energia netto</span>
</div>
<div class="legend-item">
<div class="legend-color legend-oddana"></div>
<span><strong>Czynna oddana</strong> - Energia oddana do sieci</span>
</div>
<div class="legend-item">
<div class="legend-color legend-pobrana"></div>
<span><strong>Czynna pobrana</strong> - Energia pobrana z sieci</span>
</div>
</div>
</div>
<div class="chart-grid">
"""
# Add charts to HTML
for filename, title, description in chart_files:
if filename in encoded_images:
html_content += f"""
<div class="chart-card">
<h3>{title}</h3>
<p>{description}</p>
<img src="data:image/png;base64,{encoded_images[filename]}" alt="{title}">
</div>
"""
html_content += """
</div>
</div>
<div class="footer">
<p>Generated by PGE Raport Converter | Dashboard automatically created from energy data</p>
</div>
</body>
</html>
"""
# Save HTML file
if output_file is None:
output_file = f"dashboard_{base_filename}.html"
output_path = Path(output_file)
with open(output_path, 'w', encoding='utf-8') as f:
f.write(html_content)
print(f"Dashboard saved: {output_path}")
return output_path
def main():
parser = argparse.ArgumentParser(
description="Generate HTML dashboard for PGE energy visualization charts"
)
parser.add_argument(
"base_filename",
help="Base filename used for the data and charts"
)
parser.add_argument(
"--charts-dir", "-c",
default="charts",
help="Directory containing chart PNG files (default: 'charts')"
)
parser.add_argument(
"--output", "-o",
help="Output HTML file path (default: dashboard_<base_filename>.html)"
)
args = parser.parse_args()
try:
dashboard_path = create_html_dashboard(
base_filename=args.base_filename,
charts_dir=args.charts_dir,
output_file=args.output
)
print(f"\\nDashboard created successfully!")
print(f"Open in browser: file://{dashboard_path.absolute()}")
except Exception as e:
print(f"Error: {e}")
return 1
return 0
if __name__ == "__main__":
exit(main())