Polished program
This commit is contained in:
parent
4ed58bf2dc
commit
74e9e36c19
45
edit.py
Normal file
45
edit.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import sqlite3
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def displayDB(cursor):
|
||||||
|
cursor.execute("SELECT * FROM doses")
|
||||||
|
|
||||||
|
for line in cursor:
|
||||||
|
print(line)
|
||||||
|
|
||||||
|
def update(uid, timestamp, stim, mg, cursor):
|
||||||
|
cursor.execute("UPDATE doses SET timestamp = ?, type = ?, amount = ? WHERE id = ?", (timestamp, stim, mg, uid))
|
||||||
|
|
||||||
|
def insert(timestamp, stim, mg, cursor):
|
||||||
|
cursor.execute("INSERT INTO doses (timestamp, type, amount) VALUES (?,?,?)", (timestamp, stim, mg))
|
||||||
|
|
||||||
|
def delete(uid,cursor):
|
||||||
|
cursor.execute("DELETE FROM doses WHERE id = ?", (uid,))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
conn = sqlite3.connect('stimulants.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
|
||||||
|
timestamp = "2025-10-10 05:45:00"
|
||||||
|
stim = "amphetamine"
|
||||||
|
#stim = "caffeine"
|
||||||
|
mg = 20
|
||||||
|
|
||||||
|
#update(1,timestamp,stim,mg,c)
|
||||||
|
delete(6,c)
|
||||||
|
#delete(2,c)
|
||||||
|
insert("2025-10-09 13:00:00", stim, 20, c)
|
||||||
|
insert("2025-10-09 13:00:00", "caffeine", 50, c)
|
||||||
|
insert("2025-10-09 16:30:00", stim, 10, c)
|
||||||
|
|
||||||
|
displayDB(c)
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
139
main.py
Normal file
139
main.py
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
from flask import Flask, render_template, request, redirect, url_for
|
||||||
|
import sqlite3
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import matplotlib
|
||||||
|
import io
|
||||||
|
import base64
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
import os
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
# Pharmacokinetics parameters (in minutes)
|
||||||
|
# ln(2) / (Half-life-in-minutes)
|
||||||
|
CAFFEINE_ABSORPTION_RATE = 0.05 # per minute (half-life ~15 min)
|
||||||
|
CAFFEINE_ELIMINATION_RATE = 0.0023 # per minute (half-life ~5 hours)
|
||||||
|
AMPHETAMINE_ABSORPTION_RATE = 0.03 # per minute (half-life ~20 min)
|
||||||
|
AMPHETAMINE_ELIMINATION_RATE = 0.0013 # per minute (half-life ~9 hours)
|
||||||
|
|
||||||
|
# Initialize database
|
||||||
|
def init_db():
|
||||||
|
conn = sqlite3.connect('stimulants.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute('''CREATE TABLE IF NOT EXISTS doses
|
||||||
|
(id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
timestamp DATETIME,
|
||||||
|
type TEXT,
|
||||||
|
amount INTEGER)''')
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
# Calculate stimulant amount at given time
|
||||||
|
def calculate_amount(doses, time, k_abs, k_elim):
|
||||||
|
total = 0
|
||||||
|
for dose in doses:
|
||||||
|
dose_time = datetime.strptime(dose[0], '%Y-%m-%d %H:%M:%S')
|
||||||
|
t = (time - dose_time).total_seconds() / 60 # convert to minutes
|
||||||
|
if t >= 0:
|
||||||
|
# One-compartment model with first-order absorption
|
||||||
|
total += dose[1] * (k_abs / (k_abs - k_elim)) * (
|
||||||
|
np.exp(-k_elim * t) - np.exp(-k_abs * t)
|
||||||
|
)
|
||||||
|
return total
|
||||||
|
|
||||||
|
# Generate graph for past 24 hours
|
||||||
|
def generate_graph():
|
||||||
|
# Get current time and 24 hours ago
|
||||||
|
now = datetime.now()
|
||||||
|
start_time = now - timedelta(hours=24)
|
||||||
|
|
||||||
|
# Create time points (every 10 minutes)
|
||||||
|
times = [start_time + timedelta(minutes=i*10) for i in range(144)]
|
||||||
|
|
||||||
|
# Get all doses from database
|
||||||
|
conn = sqlite3.connect('stimulants.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute("SELECT timestamp, amount FROM doses WHERE type='caffeine'")
|
||||||
|
caffeine_doses = c.fetchall()
|
||||||
|
c.execute("SELECT timestamp, amount FROM doses WHERE type='amphetamine'")
|
||||||
|
amphetamine_doses = c.fetchall()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
# Calculate amounts for each time point
|
||||||
|
caffeine_levels = [calculate_amount(caffeine_doses, t,
|
||||||
|
CAFFEINE_ABSORPTION_RATE,
|
||||||
|
CAFFEINE_ELIMINATION_RATE) for t in times]
|
||||||
|
amphetamine_levels = [calculate_amount(amphetamine_doses, t,
|
||||||
|
AMPHETAMINE_ABSORPTION_RATE,
|
||||||
|
AMPHETAMINE_ELIMINATION_RATE) for t in times]
|
||||||
|
|
||||||
|
# Create plot
|
||||||
|
plt.figure(figsize=(12, 6))
|
||||||
|
plt.plot(times, caffeine_levels, 'b-', label='Caffeine (mg)')
|
||||||
|
plt.plot(times, amphetamine_levels, 'r-', label='Amphetamine (mg)')
|
||||||
|
plt.xlabel('Time')
|
||||||
|
plt.ylabel('Estimated Amount (mg)')
|
||||||
|
plt.title('Stimulant Levels in Body (Past 24 Hours)')
|
||||||
|
plt.legend()
|
||||||
|
plt.grid(True)
|
||||||
|
|
||||||
|
# Format x-axis
|
||||||
|
ax = plt.gca()
|
||||||
|
ax.xaxis.set_major_locator(matplotlib.dates.HourLocator(interval=4))
|
||||||
|
ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%H:%M'))
|
||||||
|
|
||||||
|
# Convert to base64 string
|
||||||
|
img = io.BytesIO()
|
||||||
|
plt.savefig(img, format='png')
|
||||||
|
img.seek(0)
|
||||||
|
graph_url = base64.b64encode(img.getvalue()).decode()
|
||||||
|
plt.close()
|
||||||
|
return graph_url
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def index():
|
||||||
|
# Calculate current amounts
|
||||||
|
now = datetime.now()
|
||||||
|
|
||||||
|
conn = sqlite3.connect('stimulants.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute("SELECT timestamp, amount FROM doses WHERE type='caffeine'")
|
||||||
|
caffeine_doses = c.fetchall()
|
||||||
|
c.execute("SELECT timestamp, amount FROM doses WHERE type='amphetamine'")
|
||||||
|
amphetamine_doses = c.fetchall()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
caffeine_amount = calculate_amount(caffeine_doses, now,
|
||||||
|
CAFFEINE_ABSORPTION_RATE,
|
||||||
|
CAFFEINE_ELIMINATION_RATE)
|
||||||
|
amphetamine_amount = calculate_amount(amphetamine_doses, now,
|
||||||
|
AMPHETAMINE_ABSORPTION_RATE,
|
||||||
|
AMPHETAMINE_ELIMINATION_RATE)
|
||||||
|
|
||||||
|
# Generate graph
|
||||||
|
graph_url = generate_graph()
|
||||||
|
|
||||||
|
return render_template('index.html',
|
||||||
|
caffeine_amount=round(caffeine_amount, 2),
|
||||||
|
amphetamine_amount=round(amphetamine_amount, 2),
|
||||||
|
graph_url=graph_url)
|
||||||
|
|
||||||
|
@app.route('/add_dose', methods=['POST'])
|
||||||
|
def add_dose():
|
||||||
|
stim_type = request.form['type']
|
||||||
|
amount = 10 # Fixed 10mg amount
|
||||||
|
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
conn = sqlite3.connect('stimulants.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute("INSERT INTO doses (timestamp, type, amount) VALUES (?, ?, ?)",
|
||||||
|
(timestamp, stim_type, amount))
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
init_db()
|
||||||
|
app.run(debug=True)
|
||||||
120
templates/index.html
Normal file
120
templates/index.html
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Stimulant Tracker</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
background-color: white;
|
||||||
|
padding: 30px;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
color: #333;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.stimulant-info {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.stimulant-box {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
text-align: center;
|
||||||
|
width: 45%;
|
||||||
|
}
|
||||||
|
.stimulant-box h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
.amount {
|
||||||
|
font-size: 2em;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
.caffeine { color: #0066cc; }
|
||||||
|
.amphetamine { color: #cc0000; }
|
||||||
|
.buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 20px;
|
||||||
|
margin: 30px 0;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
padding: 12px 30px;
|
||||||
|
font-size: 16px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.caffeine-btn { background-color: #0066cc; }
|
||||||
|
.amphetamine-btn { background-color: #cc0000; }
|
||||||
|
button:hover {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
.graph-container {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
.graph-container img {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
.disclaimer {
|
||||||
|
margin-top: 30px;
|
||||||
|
padding: 15px;
|
||||||
|
background-color: #fff8e1;
|
||||||
|
border-left: 4px solid #ffc107;
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: #856404;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Stimulant Tracker</h1>
|
||||||
|
|
||||||
|
<div class="stimulant-info">
|
||||||
|
<div class="stimulant-box">
|
||||||
|
<h2>Caffeine</h2>
|
||||||
|
<div class="amount caffeine">{{ caffeine_amount }} mg</div>
|
||||||
|
</div>
|
||||||
|
<div class="stimulant-box">
|
||||||
|
<h2>Amphetamine</h2>
|
||||||
|
<div class="amount amphetamine">{{ amphetamine_amount }} mg</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="buttons">
|
||||||
|
<form action="/add_dose" method="post">
|
||||||
|
<input type="hidden" name="type" value="caffeine">
|
||||||
|
<button type="submit" class="caffeine-btn">Add 10mg Caffeine</button>
|
||||||
|
</form>
|
||||||
|
<form action="/add_dose" method="post">
|
||||||
|
<input type="hidden" name="type" value="amphetamine">
|
||||||
|
<button type="submit" class="amphetamine-btn">Add 10mg Amphetamine</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="graph-container">
|
||||||
|
<h2>Stimulant Levels (Past 24 Hours)</h2>
|
||||||
|
<img src="data:image/png;base64,{{ graph_url }}" alt="Stimulant Levels Graph">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="disclaimer">
|
||||||
|
CAFFEINE_ABSORPTION_RATE half-life ~15 min, CAFFEINE_ELIMINATION_RATE half-life ~5 hours, AMPHETAMINE_ABSORPTION_RATE half-life ~20 min, AMPHETAMINE_ELIMINATION_RATE half-life ~9 hours
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
x
Reference in New Issue
Block a user