From 56ff1a72473620fe01de5a2645edff3806ff23f8 Mon Sep 17 00:00:00 2001 From: Andrew Ridgway Date: Wed, 11 Sep 2024 05:45:21 +0000 Subject: [PATCH 1/5] fix up to get running and some feature add --- flask.Dockerfile | 5 +-- src/flask/add_user.py | 2 +- src/flask/beer_data.py | 60 ++++++++++++++++++-------------- src/flask/charts/BeerCharts.py | 2 +- src/flask/mongo/build_db.py | 7 ++-- src/flask/mongo/get_conn.py | 2 +- src/flask/templates/updater.html | 3 +- 7 files changed, 45 insertions(+), 36 deletions(-) diff --git a/flask.Dockerfile b/flask.Dockerfile index 4cdfe2d..7650a39 100644 --- a/flask.Dockerfile +++ b/flask.Dockerfile @@ -1,4 +1,5 @@ -FROM git.aridgwayweb.com/armistace/beer_base_image AS flask +#FROM git.aridgwayweb.com/armistace/beer_base_image AS flask +FROM beer_base_image AS flask COPY requirements.txt . @@ -8,6 +9,6 @@ ENV FLASK_ENV production ENV FLASK_DEBUG 1 -ENTRYPOINT ["flask", "--app", "/pool_data/src/flask/beer_data", "run", "--host=0.0.0.0"] +ENTRYPOINT ["flask", "--app", "/beer_data/src/flask/beer_data", "run", "--host=0.0.0.0"] #ENTRYPOINT ["python", "/pool_data/src/flask/pool_data.py"] diff --git a/src/flask/add_user.py b/src/flask/add_user.py index 76fb24d..d03f7d2 100644 --- a/src/flask/add_user.py +++ b/src/flask/add_user.py @@ -20,7 +20,7 @@ def main(username, password): "password" : f"{password}" } if user_collection.user_exists(new_record["username"]): - user_collect.update_user(user_collection.existing_record["_id"], new_record["password"]) + user_collection.update_user(user_collection.existing_record["_id"], new_record["password"]) else: user_collection.add_user(new_record["username"], new_record["password"]) diff --git a/src/flask/beer_data.py b/src/flask/beer_data.py index 4664592..871c192 100644 --- a/src/flask/beer_data.py +++ b/src/flask/beer_data.py @@ -1,11 +1,11 @@ from bokeh.core.enums import SpatialUnitsType -import mongo.build_db as pool_database -import mongo.query_db as pool_database_query +import mongo.build_db as beer_database +import mongo.query_db as beer_database_query from flask import Flask, render_template, request, jsonify, redirect, session from flask_wtf import FlaskForm, CSRFProtect from flask_bootstrap import Bootstrap5 -from wtforms import StringField, SubmitField, DateField, IntegerField, PasswordField, DecimalField, RadioField, TextAreaField +from wtforms import StringField, SubmitField, DateField, IntegerField, PasswordField, DecimalField, RadioField, TextAreaField, BooleanField from wtforms.validators import DataRequired, Length, Optional from waitress import serve from bokeh.models.layouts import HBox @@ -26,7 +26,7 @@ output_file("/beer_data/src/flask/static/data_plot.html") def create_graphs(): chart = BeerCharts.BeerCharts() sg = chart.line_chart("SG", "sg", 30) - show(row(column(sg))) + show(column(sg)) class userForm(FlaskForm): @@ -39,6 +39,7 @@ class dataForm(FlaskForm): beer_run_type = TextAreaField("Beer Type") Date = DateField("Date:") sg = IntegerField("SG Reading") + final_run = BooleanField("Final Reading?") comment = TextAreaField("Any Comments?", validators=[Optional()]) submit = SubmitField("Write it, Write it REAAAAAAL GOOOD") @@ -48,7 +49,7 @@ def index(): if form.validate_on_submit(): username = form.username.data password = form.password.data - db = pool_database_query.pool_query() + db = beer_database_query.pool_query() if db.user_check(username, password): session['logged_in'] = True return redirect("/updater") @@ -62,17 +63,18 @@ def updater(): if 'logged_in' not in session: return redirect("/") create_graphs() - query_db = pool_database_query.pool_query() + query_db = beer_database_query.pool_query() query = query_db.get_top(10, "sg") form = dataForm() if form.validate_on_submit(): - database = pool_database.pool_data() + database = beer_database.beer_data() new_record = { "date": f'{form.Date.data}', "beer_run_id": f'{form.beer_run_id.data}', "beer_type": f'{form.beer_run_type.data}', "sg" : f'{form.sg.data}', + "final_reading" : F'{form.final_run.data}', "comment": f'{form.comment.data}' } if database.record_exists(new_record["date"], new_record["beer_run_id"]): @@ -82,34 +84,38 @@ def updater(): if database.existing_record[field] != new_record[field]: database.update_re_record(database.existing_record["_id"], field, new_record[field]) else: + if new_record["final_reading"] == "True": + final_run_value = True + else: + final_run_value = False database.create_re_record(new_record["beer_run_id"], new_record["beer_type"], new_record["sg"], - new_record["date"], new_record["comment"]) + new_record["date"], final_run_value, new_record["comment"]) - return render_template("updater.html", list=query, form=form, success=True, updater_name = new_record["test_user"]) + return render_template("updater.html", list=query, form=form, success=True, updater_name = "Saucy Beer Maker") else: return render_template("updater.html", list=query, form=form, sucess=False) -@app.route("/update_db", methods=["POST"]) -def pool_data_update(): - database = pool_database.pool_data() - new_record = request.json - if database.record_exists(new_record["date"], new_record["test_user"]): - for field in database.existing_record: - for new_field in new_record: - if field == new_field: - if database.existing_record[field] != new_record[field]: - database.update_re_record(database.existing_record["_id"], field, new_record[field]) - else: - database.create_re_record(new_record["beer_run_id"], new_record["beer_type"], new_record["sg"], - new_record["date"], new_record["comment"]) +# @app.route("/update_db", methods=["POST"]) +# def beer_data_update(): +# database = beer_database.beer_data() +# new_record = request.json +# if database.record_exists(new_record["date"], new_record["test_user"]): +# for field in database.existing_record: +# for new_field in new_record: +# if field == new_field: +# if database.existing_record[field] != new_record[field]: +# database.update_re_record(database.existing_record["_id"], field, new_record[field]) +# else: +# database.create_re_record(new_record["beer_run_id"], new_record["beer_type"], new_record["sg"], +# new_record["date"], new_record["comment"]) -@app.route("/pool_top//") -def user_detail(id): - query_db = pool_database_query.pool_query() - query = query_db.get_top(return_number, field) - return jsonify([row.to_json() for row in query]) +# @app.route("/pool_top//") +# def user_detail(id): +# query_db = beer_database_query.pool_query() +# query = query_db.get_top(return_number, field) +# return jsonify([row.to_json() for row in query]) if __name__ == '__main__': #app.run(host='0.0.0.0') diff --git a/src/flask/charts/BeerCharts.py b/src/flask/charts/BeerCharts.py index 451b927..3895067 100644 --- a/src/flask/charts/BeerCharts.py +++ b/src/flask/charts/BeerCharts.py @@ -11,7 +11,7 @@ class BeerCharts(): def line_chart(self, title, field, limit): - data = self.db.pool_db + data = self.db.beer_db data = data.find({}).sort("date", -1).limit(limit) dates = [] data_list = [] diff --git a/src/flask/mongo/build_db.py b/src/flask/mongo/build_db.py index 1e70c46..1b92353 100644 --- a/src/flask/mongo/build_db.py +++ b/src/flask/mongo/build_db.py @@ -15,14 +15,14 @@ class beer_data: #we can get self.db.real_db etc self.db = db_conn() - def record_exists(self, date, test_user): + def record_exists(self, date, beer_run_id): """ This function will accept an address if it find that address in the database it will return True and set set the existing_record variable of the class to the queried record """ - query = { "date" : f"{date}", "test_user": f"{test_user}"} + query = { "date" : f"{date}", "beer_run_id": f"{beer_run_id}"} record = self.db.beer_db.find_one(query) if record: self.existing_record = record @@ -31,7 +31,7 @@ class beer_data: return False - def create_re_record(self, beer_run_id, beer_type, sg, date, comment=""): + def create_re_record(self, beer_run_id, beer_type, sg, date, final_reading=False, comment=""): """ create_re_record creates a whole new record takes the required 7 inputs @@ -51,6 +51,7 @@ class beer_data: "beer_type": f"{beer_type}", "sg": f"{sg}", "date": f"{date}", + "final_reading": f"{final_reading}", "comment": f"{comment}" } diff --git a/src/flask/mongo/get_conn.py b/src/flask/mongo/get_conn.py index 20ad979..9f71b0d 100644 --- a/src/flask/mongo/get_conn.py +++ b/src/flask/mongo/get_conn.py @@ -8,7 +8,7 @@ class db_conn: self.db_host = os.getenv('MONGO_HOST') self.client = self.get_client() self.db = self.client['beer_db'] - self.pool_db = self.db['beer_data'] + self.beer_db = self.db['beer_data'] self.users = self.db['users'] self.inspections = self.db['inspections_db'] diff --git a/src/flask/templates/updater.html b/src/flask/templates/updater.html index 8c8c088..52e8f57 100644 --- a/src/flask/templates/updater.html +++ b/src/flask/templates/updater.html @@ -49,7 +49,8 @@
-
-- 2.39.5 From 3524acfb40e7583e93595f974b19548f4bfc53c4 Mon Sep 17 00:00:00 2001 From: Andrew Ridgway Date: Wed, 11 Sep 2024 05:47:47 +0000 Subject: [PATCH 2/5] add README --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..505bdc4 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# BEER SG data storer + +This container will store SG data for beer runs in Mongo and then use that data to calculate Alchohol Content of each beer + +It's pretty loose and requires the Data Entry operator to know whats happening + +Luck for me... That's me! \ No newline at end of file -- 2.39.5 From d4c1c76be454118095ae73e8a341c4c0da0e7f5b Mon Sep 17 00:00:00 2001 From: Andrew Ridgway Date: Fri, 13 Sep 2024 06:17:56 +0000 Subject: [PATCH 3/5] working out the auto calc --- requirements.txt | 1 + src/flask/beer_data.py | 2 +- src/flask/chart_test.html | 61 -------------------------------- src/flask/chart_test.py | 17 --------- src/flask/table/__init__.py | 0 src/flask/table/table_builder.py | 29 +++++++++++++++ src/flask/templates/updater.html | 2 +- src/flask/test.py | 5 +++ 8 files changed, 37 insertions(+), 80 deletions(-) delete mode 100644 src/flask/chart_test.html delete mode 100644 src/flask/chart_test.py create mode 100644 src/flask/table/__init__.py create mode 100644 src/flask/table/table_builder.py create mode 100644 src/flask/test.py diff --git a/requirements.txt b/requirements.txt index aaf30fa..85a7cae 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,3 +7,4 @@ Flask-WTF bootstrap-flask waitress bokeh +pandas diff --git a/src/flask/beer_data.py b/src/flask/beer_data.py index 871c192..f294de3 100644 --- a/src/flask/beer_data.py +++ b/src/flask/beer_data.py @@ -62,7 +62,7 @@ def index(): def updater(): if 'logged_in' not in session: return redirect("/") - create_graphs() + #create_graphs() query_db = beer_database_query.pool_query() query = query_db.get_top(10, "sg") form = dataForm() diff --git a/src/flask/chart_test.html b/src/flask/chart_test.html deleted file mode 100644 index 0ce9862..0000000 --- a/src/flask/chart_test.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - Bokeh Plot - - - - - -
- - - - - \ No newline at end of file diff --git a/src/flask/chart_test.py b/src/flask/chart_test.py deleted file mode 100644 index d30feaa..0000000 --- a/src/flask/chart_test.py +++ /dev/null @@ -1,17 +0,0 @@ -from bokeh.models.layouts import HBox -from bokeh.plotting import column -from charts import PoolCharts -from bokeh.io import output_file, show -from bokeh.layouts import row - -output_file("static/data_plot.html") - -chart = PoolCharts.PoolCharts() - -ph = chart.line_chart("Pool PH", "ph", 50) - -total_chlorine = chart.line_chart("Pool Total Chlorine", "total_chlorine", 50) - -free_chlorine = chart.line_chart("Pool Free Chlorine", "free_chlorine", 50) - -show(column(ph, total_chlorine, free_chlorine)) diff --git a/src/flask/table/__init__.py b/src/flask/table/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/flask/table/table_builder.py b/src/flask/table/table_builder.py new file mode 100644 index 0000000..4be46b4 --- /dev/null +++ b/src/flask/table/table_builder.py @@ -0,0 +1,29 @@ +import sys + +from mongo.get_conn import db_conn +import pandas as pd + +class TableBuilder(): + def __init__(self) -> None: + self.db = db_conn() + + def table_build(self, field, read_count=3, runs=5) -> pd.DataFrame: + data = self.db.beer_db + data = data.find({}).sort("date", -1) + df_dict = {} + df_dict["beer_run_id"]=[] + df_dict["sg"] = [] + df_dict["date"] = [] + df_dict["final_reading"] = [] + + for record in data: + df_dict["beer_run_id"].append(record["beer_run_id"]) + df_dict["sg"].append(record["sg"]) + df_dict["date"].append(record["date"]) + df_dict["final_reading"].append(record["final_reading"]) + + df = pd.DataFrame(data=df_dict) + df_sum = df.groupby('beer_run_id').agg({'sg': ['max', 'min']}) + return df_sum + + diff --git a/src/flask/templates/updater.html b/src/flask/templates/updater.html index 52e8f57..09d0d63 100644 --- a/src/flask/templates/updater.html +++ b/src/flask/templates/updater.html @@ -49,7 +49,7 @@
-
diff --git a/src/flask/test.py b/src/flask/test.py new file mode 100644 index 0000000..562a65e --- /dev/null +++ b/src/flask/test.py @@ -0,0 +1,5 @@ +import table.table_builder as table_builder + +test = table_builder.TableBuilder() + +print(test.table_build("sg")) -- 2.39.5 From 436836d4ac32080b89f3b70d8a9a019a52f119a5 Mon Sep 17 00:00:00 2001 From: Andrew Ridgway Date: Mon, 16 Sep 2024 02:22:42 +0000 Subject: [PATCH 4/5] get alco prediction and table working --- requirements.txt | 1 + src/flask/beer_data.py | 15 ++++++++++++--- src/flask/table/table_builder.py | 28 ++++++++++++++++++++++++---- src/flask/templates/updater.html | 13 +++++-------- src/flask/test.py | 2 +- 5 files changed, 43 insertions(+), 16 deletions(-) diff --git a/requirements.txt b/requirements.txt index 85a7cae..ef76f0b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,3 +8,4 @@ bootstrap-flask waitress bokeh pandas +duckdb \ No newline at end of file diff --git a/src/flask/beer_data.py b/src/flask/beer_data.py index f294de3..755fecd 100644 --- a/src/flask/beer_data.py +++ b/src/flask/beer_data.py @@ -1,6 +1,7 @@ from bokeh.core.enums import SpatialUnitsType import mongo.build_db as beer_database import mongo.query_db as beer_database_query +from table import table_builder from flask import Flask, render_template, request, jsonify, redirect, session from flask_wtf import FlaskForm, CSRFProtect @@ -14,6 +15,7 @@ from charts import BeerCharts from bokeh.io import output_file, show from bokeh.layouts import row + app = Flask(__name__) app.secret_key = 'testsecret' #this value will change @@ -62,11 +64,16 @@ def index(): def updater(): if 'logged_in' not in session: return redirect("/") - #create_graphs() + predicted_alc_table = table_builder.TableBuilder().table_build() + tr_replace_string = '' + beer_html = predicted_alc_table.to_html(col_space='75px', index=False, + justify='center', border=3).replace('', tr_replace_string) query_db = beer_database_query.pool_query() query = query_db.get_top(10, "sg") form = dataForm() + + if form.validate_on_submit(): database = beer_database.beer_data() new_record = { @@ -91,9 +98,11 @@ def updater(): database.create_re_record(new_record["beer_run_id"], new_record["beer_type"], new_record["sg"], new_record["date"], final_run_value, new_record["comment"]) - return render_template("updater.html", list=query, form=form, success=True, updater_name = "Saucy Beer Maker") + return render_template("updater.html", beer_data = beer_html + , list=query, form=form, success=True, updater_name = "Saucy Beer Maker") else: - return render_template("updater.html", list=query, form=form, sucess=False) + return render_template("updater.html", beer_data = beer_html + , list=query, form=form, sucess=False) # @app.route("/update_db", methods=["POST"]) # def beer_data_update(): diff --git a/src/flask/table/table_builder.py b/src/flask/table/table_builder.py index 4be46b4..9b4201a 100644 --- a/src/flask/table/table_builder.py +++ b/src/flask/table/table_builder.py @@ -2,12 +2,13 @@ import sys from mongo.get_conn import db_conn import pandas as pd +import duckdb class TableBuilder(): def __init__(self) -> None: self.db = db_conn() - def table_build(self, field, read_count=3, runs=5) -> pd.DataFrame: + def table_build(self, limit=10) -> pd.DataFrame: data = self.db.beer_db data = data.find({}).sort("date", -1) df_dict = {} @@ -21,9 +22,28 @@ class TableBuilder(): df_dict["sg"].append(record["sg"]) df_dict["date"].append(record["date"]) df_dict["final_reading"].append(record["final_reading"]) - df = pd.DataFrame(data=df_dict) - df_sum = df.groupby('beer_run_id').agg({'sg': ['max', 'min']}) - return df_sum + sql = f""" + SELECT x.beer_run_id as "Beer Run", + max(sg) as "Max", + min(sg) as "Min" + FROM df x + JOIN + ( SELECT DISTINCT beer_run_id + FROM df + WHERE final_reading = 'True' + ) y ON x.beer_run_id = y.beer_run_id + GROUP BY x.beer_run_id + ORDER BY x.beer_run_id desc + LIMIT {limit} + """ + df_sum = duckdb.sql(sql).df() + sql = f""" + SELECT *, + ROUND(((CAST (max AS INTEGER) - CAST(min AS INTEGER)) / 7.36) + 0.5, 2) AS "Alcohol Prediction" + FROM df_sum + """ + df_calc = duckdb.sql(sql).df() + return df_calc diff --git a/src/flask/templates/updater.html b/src/flask/templates/updater.html index 09d0d63..b7745a7 100644 --- a/src/flask/templates/updater.html +++ b/src/flask/templates/updater.html @@ -46,18 +46,15 @@
--> - -
-
- - -
-
- +
+ {{ beer_data | safe }} + +
diff --git a/src/flask/test.py b/src/flask/test.py index 562a65e..8a4794c 100644 --- a/src/flask/test.py +++ b/src/flask/test.py @@ -2,4 +2,4 @@ import table.table_builder as table_builder test = table_builder.TableBuilder() -print(test.table_build("sg")) +print(test.table_build()) -- 2.39.5 From dc7fa20e9241e5f04d0d932e56b1a9af332e4b45 Mon Sep 17 00:00:00 2001 From: Andrew Ridgway Date: Mon, 16 Sep 2024 03:25:20 +0000 Subject: [PATCH 5/5] mvp table with alc predict and ready date --- src/flask/charts/BeerCharts.py | 3 +++ src/flask/table/table_builder.py | 21 +++++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/flask/charts/BeerCharts.py b/src/flask/charts/BeerCharts.py index 3895067..3655e22 100644 --- a/src/flask/charts/BeerCharts.py +++ b/src/flask/charts/BeerCharts.py @@ -9,6 +9,9 @@ class BeerCharts(): def __init__(self): self.db = db_conn() + def bar_chart(self, items, data): + return 0 + def line_chart(self, title, field, limit): data = self.db.beer_db diff --git a/src/flask/table/table_builder.py b/src/flask/table/table_builder.py index 9b4201a..20df83b 100644 --- a/src/flask/table/table_builder.py +++ b/src/flask/table/table_builder.py @@ -24,24 +24,29 @@ class TableBuilder(): df_dict["final_reading"].append(record["final_reading"]) df = pd.DataFrame(data=df_dict) sql = f""" - SELECT x.beer_run_id as "Beer Run", - max(sg) as "Max", - min(sg) as "Min" + SELECT x.beer_run_id as beer_run_id, + max(sg) as max, + min(sg) as min, + y.date as final_reading_date FROM df x JOIN - ( SELECT DISTINCT beer_run_id + ( SELECT DISTINCT beer_run_id, date FROM df WHERE final_reading = 'True' ) y ON x.beer_run_id = y.beer_run_id - GROUP BY x.beer_run_id + GROUP BY x.beer_run_id, y.date ORDER BY x.beer_run_id desc LIMIT {limit} """ df_sum = duckdb.sql(sql).df() sql = f""" - SELECT *, - ROUND(((CAST (max AS INTEGER) - CAST(min AS INTEGER)) / 7.36) + 0.5, 2) AS "Alcohol Prediction" - FROM df_sum + SELECT x.beer_run_id as "Beer Run", + x.max as "Max", + x.min as "Min", + ROUND(((CAST (max AS INTEGER) - CAST(min AS INTEGER)) / 7.36) + 0.5, 2) AS "Alcohol Prediction", + cast(final_reading_date as DATE) + INTERVAL 14 DAY as "Ready Date" + + FROM df_sum x """ df_calc = duckdb.sql(sql).df() return df_calc -- 2.39.5