Testing stats dashboard
This commit is contained in:
parent
d9ac2b67ed
commit
15a541f1de
96
app.py
96
app.py
@ -12,6 +12,10 @@ import rebrick #rebrickable api
|
||||
import requests # request img from web
|
||||
import shutil # save img locally
|
||||
import eventlet
|
||||
from collections import defaultdict
|
||||
import plotly.express as px
|
||||
import pandas as pd
|
||||
|
||||
from downloadRB import download_and_unzip,get_nil_images,get_retired_sets
|
||||
from db import initialize_database,get_rows,delete_tables
|
||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||
@ -1085,5 +1089,97 @@ def save_number(tmp):
|
||||
|
||||
return Response(status=204)
|
||||
|
||||
@app.route('/dashboard')
|
||||
def dashboard():
|
||||
|
||||
# Connect to the SQLite database
|
||||
conn = sqlite3.connect('app.db')
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Execute the query
|
||||
cursor.execute("SELECT year, set_num, theme_id FROM sets")
|
||||
rows = cursor.fetchall()
|
||||
|
||||
# Initialize defaultdict to count occurrences
|
||||
theme_counts = defaultdict(int)
|
||||
year_counts = defaultdict(int)
|
||||
|
||||
# Count unique occurrences (removing duplicates)
|
||||
seen = set() # To track unique combinations
|
||||
for year, set_num, theme_id in rows:
|
||||
# Create a unique identifier for each entry
|
||||
entry_id = f"{year}-{set_num}-{theme_id}"
|
||||
if entry_id not in seen:
|
||||
theme_counts[theme_id] += 1
|
||||
year_counts[year] += 1
|
||||
seen.add(entry_id)
|
||||
|
||||
# Convert to regular dictionaries and sort
|
||||
sets_by_theme = dict(sorted(
|
||||
{k: v for k, v in theme_counts.items() if v > 1}.items()
|
||||
))
|
||||
|
||||
sets_by_year = dict(sorted(
|
||||
{k: v for k, v in year_counts.items() if v > 0}.items()
|
||||
))
|
||||
|
||||
|
||||
# Graphs using Plotly
|
||||
fig_sets_by_theme = px.bar(
|
||||
x=list(sets_by_theme.keys()),
|
||||
y=list(sets_by_theme.values()),
|
||||
labels={'x': 'Theme ID', 'y': 'Number of Sets'},
|
||||
title='Number of Sets by Theme'
|
||||
)
|
||||
fig_sets_by_year = px.line(
|
||||
x=list(sets_by_year.keys()),
|
||||
y=list(sets_by_year.values()),
|
||||
labels={'x': 'Year', 'y': 'Number of Sets'},
|
||||
title='Number of Sets Released Per Year'
|
||||
)
|
||||
|
||||
|
||||
most_frequent_parts = {
|
||||
"Brick 1 x 1": 866,
|
||||
"Plate 1 x 1": 782,
|
||||
"Plate 1 x 2": 633,
|
||||
"Plate Round 1 x 1 with Solid Stud": 409,
|
||||
"Tile 1 x 2 with Groove": 382,
|
||||
}
|
||||
minifigs_by_set = {"10217-1": 12, "7595-1": 8, "10297-1": 7, "21338-1": 4, "4865-1": 4}
|
||||
missing_parts_by_set = {"10297-1": 4, "10280-1": 1, "21301-1": 1, "21338-1": 1, "7595-1": 1}
|
||||
|
||||
|
||||
fig_parts = px.bar(
|
||||
x=list(most_frequent_parts.keys()),
|
||||
y=list(most_frequent_parts.values()),
|
||||
labels={'x': 'Part Name', 'y': 'Quantity'},
|
||||
title='Most Frequent Parts'
|
||||
)
|
||||
fig_minifigs = px.bar(
|
||||
x=list(minifigs_by_set.keys()),
|
||||
y=list(minifigs_by_set.values()),
|
||||
labels={'x': 'Set Number', 'y': 'Number of Minifigures'},
|
||||
title='Minifigures by Set'
|
||||
)
|
||||
fig_missing_parts = px.bar(
|
||||
x=list(missing_parts_by_set.keys()),
|
||||
y=list(missing_parts_by_set.values()),
|
||||
labels={'x': 'Set Number', 'y': 'Missing Parts Count'},
|
||||
title='Missing Parts by Set'
|
||||
)
|
||||
|
||||
# Convert graphs to HTML
|
||||
graphs = {
|
||||
"sets_by_theme": fig_sets_by_theme.to_html(full_html=False),
|
||||
"sets_by_year": fig_sets_by_year.to_html(full_html=False),
|
||||
"parts": fig_parts.to_html(full_html=False),
|
||||
"minifigs": fig_minifigs.to_html(full_html=False),
|
||||
"missing_parts": fig_missing_parts.to_html(full_html=False),
|
||||
}
|
||||
|
||||
return render_template("dashboard.html", graphs=graphs)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
socketio.run(app.run(host='0.0.0.0', debug=True, port=3333))
|
||||
|
@ -1,6 +1,8 @@
|
||||
flask
|
||||
flask_socketio
|
||||
pathlib
|
||||
plotly
|
||||
pandas
|
||||
numpy
|
||||
rebrick
|
||||
requests
|
||||
|
60
templates/dashboard.html
Normal file
60
templates/dashboard.html
Normal file
@ -0,0 +1,60 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>LEGO Dashboard</title>
|
||||
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 20px;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: #333;
|
||||
}
|
||||
.chart-container {
|
||||
margin-bottom: 50px;
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.chart-container h2 {
|
||||
text-align: center;
|
||||
color: #555;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>LEGO Dashboard</h1>
|
||||
|
||||
<div class="chart-container">
|
||||
<h2>Sets by Theme</h2>
|
||||
{{ graphs['sets_by_theme']|safe }}
|
||||
</div>
|
||||
|
||||
<div class="chart-container">
|
||||
<h2>Sets Released Per Year</h2>
|
||||
{{ graphs['sets_by_year']|safe }}
|
||||
</div>
|
||||
|
||||
<div class="chart-container">
|
||||
<h2>Most Frequent Parts</h2>
|
||||
{{ graphs['parts']|safe }}
|
||||
</div>
|
||||
|
||||
<div class="chart-container">
|
||||
<h2>Minifigures by Set</h2>
|
||||
{{ graphs['minifigs']|safe }}
|
||||
</div>
|
||||
|
||||
<div class="chart-container">
|
||||
<h2>Missing Parts by Set</h2>
|
||||
{{ graphs['missing_parts']|safe }}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
Reference in New Issue
Block a user