-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from AndreWohnsland/dev
v1.2 Merge
- Loading branch information
Showing
66 changed files
with
5,061 additions
and
975 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,4 +6,7 @@ venv | |
*.csv | ||
__pycache__ | ||
.env | ||
.venv | ||
.venv | ||
team.db | ||
Cocktail_database.db | ||
failed_data.db |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
[Desktop Entry] | ||
Type=Application | ||
Name=CocktailScreen | ||
NoDisplay=false | ||
Exec=/usr/bin/lxterminal -e /home/pi/launcher.sh |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,45 @@ | ||
class ConfigManager: | ||
"""Manager for all static configuration of the machine """ | ||
|
||
MASTERPASSWORD = "1337" | ||
USEDPINS = [14, 15, 18, 23, 24, 25, 8, 7, 17, 27, 22, 20] | ||
PUMP_VOLUMEFLOW = [30, 30, 25, 30, 30, 30, 25, 30, 30, 23, 30, 30] | ||
NUMBER_BOTTLES = 10 | ||
CLEAN_TIME = 20 | ||
SLEEP_TIME = 0.05 | ||
PARTYMODE = False | ||
LOGGERNAME = "cocktaillogger" | ||
LOGGERNAME_DEBUG = "debuglogger" | ||
USE_MICROSERVICE = True | ||
MICROSERVICE_BASE_URL = "http://127.0.0.1:5000" | ||
DEVENVIRONMENT = True | ||
class ConfigManager: | ||
"""Manager for all static configuration of the machine """ | ||
|
||
# Password to lock clean, delete and other critical operators | ||
MASTERPASSWORD = "1337" | ||
# RPi pins where pumps (ascending) are connected | ||
USEDPINS = [14, 15, 18, 23, 24, 25, 8, 7, 17, 27, 22, 20] | ||
# Volumeflow for the according pumps | ||
PUMP_VOLUMEFLOW = [30, 30, 25, 30, 30, 30, 25, 30, 30, 23, 30, 30] | ||
# Number of bottles possible at the machine | ||
NUMBER_BOTTLES = 10 | ||
# Time in seconds to execute clean programm | ||
CLEAN_TIME = 20 | ||
# time between each check loop when making cocktail | ||
SLEEP_TIME = 0.05 | ||
# Locks the recipe tab, making it impossible to acesss | ||
PARTYMODE = False | ||
# Names for the according logger files | ||
LOGGERNAME = "cocktaillogger" | ||
LOGGERNAME_DEBUG = "debuglogger" | ||
# If to use microservice (mostly docker on same device) to handle external API calls and according url | ||
USE_MICROSERVICE = False | ||
MICROSERVICE_BASE_URL = "http://127.0.0.1:5000" | ||
# if to use the teams function and according options. | ||
# URL should be 'device_ip:8080' where dashboard container is running and in the same network | ||
# Button names must be two strings in the list | ||
USE_TEAMS = True | ||
TEAM_BUTTON_NAMES = ["Team 1", "Team 2"] | ||
TEAM_API_URL = "http://127.0.0.1:8080" | ||
# Activating some dev features like mouse cursor | ||
DEVENVIRONMENT = True | ||
|
||
|
||
class Shared: | ||
"""Shared global variables which may dynamically change and are needed on different spaces""" | ||
|
||
def __init__(self): | ||
self.cocktail_started = False | ||
self.make_cocktail = True | ||
self.supress_error = False | ||
self.old_ingredient = [] | ||
self.selected_team = "Nothing" | ||
|
||
|
||
shared = Shared() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
FROM python:3.8-slim-buster | ||
|
||
WORKDIR /app | ||
|
||
COPY requirements.txt . | ||
RUN pip install -r requirements.txt | ||
|
||
COPY . . | ||
|
||
EXPOSE 8080 | ||
|
||
CMD ["python", "main.py"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import os | ||
import datetime | ||
from pathlib import Path | ||
import sqlite3 | ||
from typing import Optional | ||
import uvicorn | ||
from fastapi import FastAPI | ||
from pydantic import BaseModel | ||
|
||
DATABASE_NAME = "team" | ||
DIRPATH = os.path.dirname(__file__) | ||
database_path = os.path.join(DIRPATH, "storage", f"{DATABASE_NAME}.db") | ||
|
||
app = FastAPI() | ||
|
||
|
||
class Teaminfo(BaseModel): | ||
team: str | ||
volume: int | ||
|
||
|
||
class BoardConfig(BaseModel): | ||
hourrange: Optional[int] = None | ||
limit: Optional[int] = 5 | ||
count: Optional[bool] = True | ||
|
||
|
||
@app.get("/") | ||
def home(): | ||
return {"message": "Welcome to dashboard api"} | ||
|
||
|
||
@app.post("/cocktail") | ||
async def enter_cocktail_for_team(team: Teaminfo): | ||
conn = sqlite3.connect(database_path) | ||
cursor = conn.cursor() | ||
entry_datetime = datetime.datetime.now().replace(microsecond=0) | ||
sql = "INSERT INTO TEAM(Date, Team, Volume) VALUES(?,?,?)" | ||
cursor.execute(sql, (entry_datetime, team.team, team.volume,)) | ||
conn.commit() | ||
conn.close() | ||
return {"message": "Team entry was Successfull", "team": team.team, "volume": team.volume} | ||
|
||
|
||
def get_leaderboard(hourrange=None, limit=2, count=True): | ||
addition = "" | ||
if hourrange is not None: | ||
addition = f" WHERE Date >= datetime('now','-{hourrange} hours')" | ||
agg = "count(*)" if count else "sum(Volume)" | ||
conn = sqlite3.connect(database_path) | ||
cursor = conn.cursor() | ||
sql = f"SELECT Team, {agg} as amount FROM Team{addition} GROUP BY Team ORDER BY {agg} DESC LIMIT ?" | ||
cursor.execute(sql, (limit,)) | ||
return_data = dict(cursor.fetchall()) | ||
conn.close() | ||
return return_data | ||
|
||
|
||
@app.get("/leaderboard") | ||
def leaderboard(conf: BoardConfig): | ||
return get_leaderboard(conf.hourrange, conf.limit, conf.count) | ||
|
||
|
||
def create_tables(): | ||
conn = sqlite3.connect(database_path) | ||
cursor = conn.cursor() | ||
cursor.execute( | ||
"""CREATE TABLE IF NOT EXISTS | ||
Team(Date DATETIME NOT NULL, | ||
Team TEXT NOT NULL, | ||
Volume INTEGER NOT NULL);""" | ||
) | ||
conn.commit() | ||
conn.close() | ||
|
||
|
||
if __name__ == "__main__": | ||
if not Path(database_path).exists(): | ||
print("creating Database") | ||
create_tables() | ||
uvicorn.run("main:app", host="0.0.0.0", port=8080) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
fastapi==0.70.0 | ||
uvicorn==0.15.0 |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
version: '3' | ||
|
||
services: | ||
frontend: | ||
container_name: cocktail-dashboard-frontend | ||
restart: always | ||
build: frontend | ||
ports: | ||
- 8501:8501 | ||
depends_on: | ||
- backend | ||
volumes: | ||
- ./storage:/app/storage | ||
backend: | ||
container_name: cocktail-dashboard-backend | ||
restart: always | ||
build: backend | ||
ports: | ||
- 8080:8080 | ||
volumes: | ||
- ./storage:/app/storage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
version: '3' | ||
|
||
services: | ||
backend: | ||
image: cocktail-dashboard-backend | ||
container_name: cocktail-dashboard-backend | ||
restart: always | ||
build: backend | ||
ports: | ||
- 8080:8080 | ||
volumes: | ||
- ./storage:/app/storage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
FROM python:3.9-slim-buster | ||
|
||
WORKDIR /app | ||
|
||
COPY requirements.txt . | ||
RUN pip install -r requirements.txt | ||
|
||
COPY . . | ||
|
||
EXPOSE 8501 | ||
|
||
CMD ["streamlit", "run", "main.py", "--theme.base", "dark"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import math | ||
import os | ||
import sqlite3 | ||
import streamlit as st | ||
from streamlit_autorefresh import st_autorefresh | ||
import pandas as pd | ||
import matplotlib.pyplot as plt | ||
import matplotlib as mpl | ||
from pywaffle import Waffle | ||
import warnings | ||
|
||
st.set_page_config( | ||
page_title="Cocktail Dashboard", | ||
page_icon="🍸", | ||
layout="wide", | ||
initial_sidebar_state="collapsed", | ||
) | ||
warnings.filterwarnings("ignore", 'Starting a Matplotlib GUI outside of the main thread will likely fail.') | ||
mpl.rcParams.update({'text.color': "white", 'axes.labelcolor': "white"}) | ||
|
||
DATABASE_NAME = "team" | ||
DIRPATH = os.path.dirname(__file__) | ||
database_path = os.path.join(DIRPATH, "storage", f"{DATABASE_NAME}.db") | ||
|
||
|
||
def get_leaderboard(hourrange=None, limit=2, count=True): | ||
addition = "" | ||
if hourrange is not None: | ||
addition = f" WHERE Date >= datetime('now','-{hourrange} hours')" | ||
agg = "count(*)" if count else "sum(Volume)" | ||
conn = sqlite3.connect(database_path) | ||
SQL = f"SELECT Team, {agg} as amount FROM Team{addition} GROUP BY Team ORDER BY {agg} DESC LIMIT ?" | ||
board = pd.read_sql(SQL, conn, params=(limit,)) | ||
board.reset_index(drop=True, inplace=True) | ||
conn.close() | ||
return board | ||
|
||
|
||
def sort_dict_items(to_sort: dict): | ||
dictionary_items = to_sort.items() | ||
sorted_items = sorted(dictionary_items) | ||
return {x[0]: x[1] for x in sorted_items} | ||
|
||
|
||
def extract_data(sort: bool, df: pd.DataFrame): | ||
if df.empty or sum(df.amount.to_list()) < 3: | ||
waffle_data = {"Cocktails trinken zum starten ...": 3} | ||
else: | ||
waffle_data = {f"{x} ({y})": y for x, y in zip(df.Team.to_list(), df.amount.to_list())} | ||
if sort: | ||
waffle_data = sort_dict_items(waffle_data) | ||
return waffle_data | ||
|
||
|
||
def generate_dimensions(total: float, count=True): | ||
proportion = 3 | ||
threshold_upper = 1.2 | ||
threshold_lower = 0.77 | ||
one_row_until = 9 | ||
# use fixed grid for non count variables | ||
if not count: | ||
return {"rows": 10, "columns": 25} | ||
# don't split until given dimension | ||
if total < one_row_until: | ||
return {"rows": 1} | ||
row = max(math.floor(math.sqrt(total / proportion)), 1) | ||
# calculate current proportion, add one if exceeds th | ||
column = math.ceil(total / row) | ||
real_prop = column / row | ||
if real_prop >= proportion * threshold_upper: | ||
row += 1 | ||
# calculates adjusted proportion, rolls back if its too extreme | ||
column = math.ceil(total / row) | ||
adjusted_prop = column / row | ||
if adjusted_prop <= proportion * threshold_lower: | ||
row -= 1 | ||
return {"rows": row} | ||
|
||
|
||
def generate_figure(title: str, hourrange: int = None, limit=5, sort=False, count=True): | ||
df = get_leaderboard(hourrange, limit, count) | ||
waffle_data = extract_data(sort, df) | ||
dims = generate_dimensions(sum(df.amount.to_list()), count) | ||
fig = plt.figure( | ||
FigureClass=Waffle, | ||
**dims, | ||
values=waffle_data, | ||
title={ | ||
'label': title, | ||
'fontdict': { | ||
'fontsize': 20 | ||
} | ||
}, | ||
facecolor=(0.054, 0.066, 0.090, 1), | ||
legend={'loc': 'upper center', 'bbox_to_anchor': (0.5, 0.0), 'ncol': 2, 'framealpha': 0} | ||
) | ||
return fig | ||
|
||
|
||
st_autorefresh(interval=15000, key="autorefresh") | ||
st.markdown(""" <style> | ||
#MainMenu {visibility: hidden;} | ||
footer {visibility: hidden;} | ||
.block-container {padding: 1rem 1rem 1rem 1rem !important;} | ||
</style> """, unsafe_allow_html=True) | ||
|
||
st.sidebar.header("Zeit aussuchen") | ||
selected_display = st.sidebar.radio("", ("Heute", "All time")) | ||
st.sidebar.header("Aggregation aussuchen") | ||
selected_type = st.sidebar.radio("", ("Anzahl", "Volumen")) | ||
use_count = selected_type == "Anzahl" | ||
|
||
if selected_display == "Heute": | ||
st.pyplot(generate_figure(title=f"Leaderboard ({selected_type}, Heute)", hourrange=24, sort=True, count=use_count)) | ||
else: | ||
st.pyplot(generate_figure(title=f"Leaderboard ({selected_type}, All time)", limit=20, count=use_count)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
streamlit | ||
streamlit-autorefresh | ||
matplotlib | ||
pywaffle |
Empty file.
Oops, something went wrong.