Coffee
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
January 2020
- 1 discussions

13 Jul '20
---
Že se tak blížíme ke konci roku 2019, dlouho očekávaný patch na logování věcí
přímo na terminálu.
app.py | 14 +++++++--
coffee_db.py | 53 ++++++++++++++++++++++++++++++++
coffee_db.sql | 25 +++++++++++++++
templates/main.js | 31 ++++++++++++++++++-
templates/user.html | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 207 insertions(+), 3 deletions(-)
diff --git a/app.py b/app.py
index a3e3088..8dea885 100644
--- a/app.py
+++ b/app.py
@@ -68,11 +68,14 @@ def user():
count_mate=counts.get("Club-Mate", 0),
identifiers=db.list_user_identifiers(uid),
iid=session["iid"],
- stamp=time.time()
+ stamp=time.time(),
+ events=db.event_list_last(display=False)
)
# TODO: Replace stamp parameter with proper cache control HTTP
# headers in response
- return render_template('user.html', stamp=time.time())
+ return render_template('user.html', stamp=time.time(),
+ event_list=db.event_list_last()
+ )
@app.route('/user/rename')
@@ -210,6 +213,13 @@ def coffee_add():
db.add_coffee(session["iid"], json["flavor"], json["time"])
return redirect(url_for('user'))
+(a)app.route("/event/add", methods=["POST"])
+def event_add():
+ if request.method == "POST":
+ json = request.json
+ print("User '%(uid)s' registered event ID %(event_id) at %(time)s" % json)
+ db.add_event(json["uid"], json["event_id"], json["time"])
+ return redirect(url_for('user'))
@app.route("/coffee/count")
def coffee_count():
diff --git a/coffee_db.py b/coffee_db.py
index f0ad407..8f3e663 100644
--- a/coffee_db.py
+++ b/coffee_db.py
@@ -99,6 +99,17 @@ def add_coffee(uid, flavor, time=None):
c.execute("insert or ignore into coffees (id, flavor, time) values (?,?,?)", (uid, flavor, time))
close_db(conn)
+
+def add_event(uid, event_id, time=None):
+ conn, c = open_db()
+ if time is None:
+ c.execute("insert into events (user_id, event_id) values (?,?)", (uid, event_id))
+ else:
+ c.execute("insert or ignore into events (user_id, event_id, time) values (?,?,?)", (uid, event_id, time))
+ close_db(conn)
+
+
+
def flavors():
conn, c = open_db()
res = list(c.execute("select distinct name, ord from flavors"))
@@ -186,3 +197,45 @@ def drink_count(uid=None, start=None, stop=None):
return dict(c.execute("select case when flavor like 'Club%' then 'Club-Mate' else 'Coffee' end as drink, count(*) "
"from coffees co left join identifiers ids on co.id = ids.id where "
+ " and ".join(clauses) + " group by drink", args))
+
+
+def event_list_last(display = True):
+ conn, c = open_db()
+ # Tohle je trochu slozitejsi. Kazdopadne to dela tak, ze pokud ma udalost nastavenou hodnotu 'trigger', tak jeji ohlaseni plati i na tu druhou.
+ event_list = list(c.execute("""
+ select name, status, action, id, strftime('%s', 'now', 'localtime') - strftime('%s', time, 'localtime')
+ from (select * from event_types e
+ left join event_types e2 on e2.trigger=e.id
+ left join events on event_id in (e.id, e2.id)
+ """ + ("where e.display = 1" if display else "") + """ order by time asc)
+ group by id order by name asc
+ """))
+ close_db(conn)
+ res = list()
+ last_event = ""
+ for event in event_list:
+ if event[0] != last_event:
+ res.append(list())
+ res[-1].append(event[0])
+ last_event = event[0]
+
+ t = ""
+ if event[-1] is None:
+ t = "never"
+ else:
+ if event[-1] < 60:
+ t = "%d secs ago" % (event[-1])
+ elif event[-1] < 3600:
+ t = "%d mins ago" % (event[-1]/60)
+ elif event[-1] < 86400:
+ t = "%d hrs ago" % (event[-1]/3600)
+ else:
+ t = "%d days ago" % (event[-1]/86400)
+ #res[event[0]].append((event[1], t))
+ r = dict()
+ r["status"] = event[1]
+ r["action"] = event[2]
+ r["id"] = event[3]
+ r["time"] = t
+ res[-1].append(r)
+ return res
diff --git a/coffee_db.sql b/coffee_db.sql
index 23011af..f44148a 100644
--- a/coffee_db.sql
+++ b/coffee_db.sql
@@ -37,6 +37,31 @@ insert or ignore into days values
(0),(1),(2),(3),(4),(5),(6)
;
+create table if not exists event_types (
+ id integer primary key,
+ name varchar(255) not null,
+ status varchar(32) not null,
+ action varchar(32) not null,
+ display integer default 1,
+ trigger integer references event_types(id) default NULL
+);
+
+insert or ignore into event_types values
+ (0, "coffee pack", "opened", "open", 1, NULL),
+ (1, "coffee pack", "", "open last", 0, 0),
+ (2, "coffee machine", "cleaned", "clean", 1, NULL),
+ (3, "milk container", "cleaned", "clean", 1, NULL),
+ (4, "milk container", "pilled", "pill clean", 0, 3)
+;
+
+create table if not exists events (
+ num integer primary key,
+ event_id integer references event_types(id),
+ user_id varchar(24) references users(id),
+ time datetime default current_timestamp,
+ UNIQUE (event_id, user_id, time)
+);
+
CREATE TABLE if not exists identifiers (
`userid` varchar ( 24 ) NOT NULL,
`id` varchar ( 24 ) PRIMARY KEY NOT NULL,
diff --git a/templates/main.js b/templates/main.js
index 417dc40..5650b94 100644
--- a/templates/main.js
+++ b/templates/main.js
@@ -29,6 +29,9 @@ function replayOfflineQueue() {
}
var flavorChosen;
+var eventName;
+var eventStatus;
+var eventAction;
// Central function to update UI elements. To ensure that the UI is
// consistent, other code should only change state variables and then
@@ -48,8 +51,14 @@ function updateUI()
if (id_user !== undefined) {
document.getElementById("nextStep").innerHTML = "Now select a beverage on the coffee machine…";
- } else {
+ } else if (flavorChosen !== undefined) {
document.getElementById("nextStep").innerHTML = "Enjoy your " + flavorChosen + "!";
+ // clean the coffee machine makes it cleaned
+ // ^ Action ^ Name ^ Status
+ } else if (eventStatus !== undefined && eventStatus !== "") {
+ document.getElementById("nextStep").innerHTML = "You have " + eventStatus + " the " + eventName + ". Thanks!";
+ } else {
+ document.getElementById("nextStep").innerHTML = "Event '" + eventAction + "' reported for the " + eventName + ". Thanks!";
}
if (timeToLogout !== undefined)
@@ -171,6 +180,7 @@ function logout() {
id_user = undefined;
timeToLogout = undefined;
identifier_registration = false;
+ window.scrollTo(0, 0); // Scroll up
}
function countingTimeLogout(count_time)
@@ -212,6 +222,25 @@ function addCoffee(flavor, time = new Date()) {
}
}
+
+function addEvent(event_id, name, status, action, time = new Date()) {
+ var data = JSON.stringify({
+ time: time.toISOString(),
+ event_id: event_id,
+ uid: id_user
+ });
+ if (id_user) {
+ ajax("POST", "event/add", data, "user");
+ id_user = undefined;
+ eventName = name;
+ eventStatus = status;
+ eventAction = action;
+ countingTimeLogout(10); //mean 10 seconds
+ window.scrollTo(0, 0); // Scroll up
+ }
+}
+
+
function addIdentifier_start() {
identifier_registration = true;
document.getElementById("addIdentifier").disabled = true;
diff --git a/templates/user.html b/templates/user.html
index e0be310..40d3eeb 100644
--- a/templates/user.html
+++ b/templates/user.html
@@ -1,3 +1,27 @@
+<style>
+table.events {
+ margin: 0.8em;
+ margin-bottom: 1.5em;
+ padding: 2px;
+ border-spacing: 2em 0;
+ text-align: center;
+}
+
+td.events-list {
+ border: 1px solid black;
+ padding: 0.5em;
+}
+
+td.events-name {
+ border-bottom: 1px dashed black;
+}
+
+td.events-options {
+ border-top: 0;
+ line-height: 125%;
+}
+</style>
+
{% if name %}
<form style="position: absolute; right: 15%; width: 15%; height: 15%;">
<button type="button" id="logout_button" onclick="logout()" style="width: 100%; height: 100%;">logout</button>
@@ -51,9 +75,72 @@
</tr>
</table>
</form>
+ {% if events %}
+ <br />
+ <form>
+ <table class="events">
+ <tr>
+ <td colspan="{{ events|length }}" align="center"><b>Events:</b></td>
+ </tr>
+ <tr>
+ {% for event in events %}
+ <td class="events-list events-name">
+ <b>{{ event[0] }}</b>
+ </td>
+ {% endfor %}
+ </tr>
+ <tr>
+ {% for event in events %}
+ <td class="events-list events-options">
+ {% for details in event %}
+ {% if not loop.first %}
+ <input type="button" value="{{ details['action'] }}" onclick="addEvent('{{ details['id'] }}', '{{ event[0] }}', '{{ details['status'] }}', '{{ details['action'] }}')" /> ( {{ details['time'] }} )
+ {% if not loop.last %}
+ <br />
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+ </td>
+ {% endfor %}
+ </tr>
+ </table>
+ </form>
+ {% endif %}
{% else %}
<p>Use your card/token to log in...</p>
<img src="{{ url_for('coffee_graph_history', _external=True, stamp=stamp) }}">
<img src="{{ url_for('coffee_graph_flavors', _external=True, stamp=stamp, days=7) }}">
+
+ {% if event_list %}
+ <form>
+ <table class="events">
+ <tr>
+ {% for event in event_list %}
+ <td class="events-list events-name">
+ <b>{{ event[0] }}</b>
+ </td>
+ {% endfor %}
+ </tr>
+ <tr>
+ {% for event in event_list %}
+ <td class="events-list events-options">
+ {% for details in event %}
+ {% if not loop.first %}
+ {% if details['time'] == "never" %}
+ {{ details['time'] }} {{ details['status'] }}
+ {% else %}
+ {{ details['status'] }} {{ details['time'] }}
+ {% endif %}
+ {% if not loop.last %}
+ <br />
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+ </td>
+ {% endfor %}
+ </tr>
+ </table>
+ </form>
+ {% endif %}
{% endif %}
--
2.7.4
2
1