X-Git-Url: https://plomlompom.com/repos/?a=blobdiff_plain;f=income_progress_bars.py;h=5d9a887323feb2cc7da85f1e81dae7bc696d83f2;hb=HEAD;hp=8a85a4c5a7402ff791a47a033678f1f6c352d1f7;hpb=6115737776cbf6ebd486de1849ea16272cdaff1a;p=misc diff --git a/income_progress_bars.py b/income_progress_bars.py index 8a85a4c..5d9a887 100644 --- a/income_progress_bars.py +++ b/income_progress_bars.py @@ -1,12 +1,12 @@ -from http.server import BaseHTTPRequestHandler, HTTPServer import os import json +import jinja2 +from plomlib import PlomDB, PlomException, run_server, PlomHandler -hostName = "localhost" -serverPort = 8080 +server_port = 8083 +db_path = '/home/plom/org/income.json' -header = """ - +tmpl = """ - -""" -footer = """
earnedprogresssurplus
-
+earnedprogresssurplus +{% for p in progress_bars %}{{p.title}} +{{p.earned|round(2)}} +{% if p.time_progress >= 0 %}
{% endif %}
+
{{p.diff_goal}}
+{% endfor %} + + - - - + + + +
hourly rateworked today
€ minutes
€ minutes
€ minutes
€ minutes
€ minutes
€ minutes
- - - - - - + + + + + +
yearly income goal€
monthly income goal%.2f€
weekly income goal%.2f€
workdays per month
workday income goal%.2f€
workdays per week%.2f€
yearly income goal€
monthly income goal{{month_goal|round(2)}}€
weekly income goal{{week_goal|round(2)}}€
workdays per month
workday income goal{{workday_goal|round(2)}}€
workdays per week{{workdays_per_week|round(2)}}
-""" +""" -db_default = { - "timestamp_year": 0, - "timestamp_month": 0, - "timestamp_week": 0, - "year_income": 0, - "month_income": 0, - "week_income": 0, - "workday_hourly_rate_1": 10, - "workday_minutes_worked_1": 0, - "workday_hourly_rate_2": 25, - "workday_minutes_worked_2": 0, - "workday_hourly_rate_3": 50, - "workday_minutes_worked_3": 0, - "year_goal": 20000, - "workdays_per_month": 16 -} -db_file = "db.json" -lock_file = "db.lock" -def load_db(): - if os.path.exists(db_file): - with open(db_file, "r") as f: - return json.load(f) - else: - return db_default -class MyServer(BaseHTTPRequestHandler): +class IncomeDB(PlomDB): + + def __init__(self): + # defaults + self.timestamp_year = 0, + self.timestamp_month = 0, + self.timestamp_week = 0, + self.year_income = 0, + self.month_income = 0, + self.week_income = 0, + self.workday_hourly_rate_1 = 10, + self.workday_hourly_rate_2 = 25, + self.workday_hourly_rate_3 = 50, + self.workday_minutes_worked_1 = 0, + self.workday_minutes_worked_2 = 0, + self.workday_minutes_worked_3 = 0, + self.year_goal = 20000, + self.workdays_per_month = 16 + super().__init__(db_path) + + def read_db_file(self, f): + d = json.load(f) + for k, v in d.items(): + if not hasattr(self, k): + raise PlomException("bad key in db: " + k) + setattr(self, k, v) + + def to_dict(self): + keys = [k for k in dir(self) if (not k.startswith('_')) and (not callable(getattr(self, k)))] + d = {} + for k in keys: + d[k] = getattr(self, k) + return d + + def write_db(self): + self.write_text_to_db(json.dumps(self.to_dict())) + + +class ProgressBar: + def __init__(self, title, earned, goal, time_progress=-1): + self.title = title + self.earned = earned + self.time_progress = int(time_progress * 100) + success_income = self.earned / goal + self.success_income_cut = int(min(success_income, 1.0) * 100) + self.success_income_bonus = int(max(success_income - 1.0, 0) * 100) + self.success = success_income + 0 + self.diff_goal = "%.2f€" % (self.earned - goal) + if title != "workday": + self.diff_goal += "(%.2f€)" % (self.earned - (goal * time_progress)) + if time_progress >= 0: + self.success = 1 + if time_progress > 0: + self.success = success_income / time_progress + + +class IncomeProgressHandler(PlomHandler): + + def app_init(self, handler): + default_path = '/income_progress' + handler.add_route('GET', default_path, self.display_income_progress) + handler.add_route('POST', default_path, self.post_income_update) + return 'income_progress', default_path def do_POST(self): + self.try_do(self.post_income_update) + + def post_income_update(self): from urllib.parse import parse_qs length = int(self.headers['content-length']) - postvars = parse_qs(self.rfile.read(length), keep_blank_values=1) - db = load_db() - db["workday_minutes_worked_1"] = int(postvars[b'workday_minutes_worked_1'][0].decode()) - db["workday_minutes_worked_2"] = int(postvars[b'workday_minutes_worked_2'][0].decode()) - db["workday_minutes_worked_3"] = int(postvars[b'workday_minutes_worked_3'][0].decode()) - db["workday_hourly_rate_1"] = int(postvars[b'workday_hourly_rate_1'][0].decode()) - db["workday_hourly_rate_2"] = int(postvars[b'workday_hourly_rate_2'][0].decode()) - db["workday_hourly_rate_3"] = int(postvars[b'workday_hourly_rate_3'][0].decode()) - db["year_goal"] = int(postvars[b'year_goal'][0].decode()) - db["workdays_per_month"] = int(postvars[b'workdays_per_month'][0].decode()) - if b'finish' in postvars.keys(): - day_income = (db["workday_minutes_worked_1"] / 60.0) * db["workday_hourly_rate_1"] - day_income += (db["workday_minutes_worked_2"] / 60.0) * db["workday_hourly_rate_2"] - day_income += (db["workday_minutes_worked_3"] / 60.0) * db["workday_hourly_rate_3"] - db["year_income"] += day_income - db["month_income"] += day_income - db["week_income"] += day_income - db["workday_minutes_worked_1"] = 0 - db["workday_minutes_worked_2"] = 0 - db["workday_minutes_worked_3"] = 0 - if not os.path.exists(lock_file): - with open(lock_file, "w+"): pass - with open(db_file, "w") as f: - json.dump(db, f) - os.remove(lock_file) - self.send_response(302) - self.send_header('Location', '/') - self.end_headers() - else: - self.send_response(400) - self.end_headers() - self.wfile.write(bytes("Sorry, lock file!", "utf-8")) + postvars = parse_qs(self.rfile.read(length).decode(), keep_blank_values=1) + db = IncomeDB() + db.workday_minutes_worked_1 = int(postvars['workday_minutes_worked_1'][0]) + db.workday_minutes_worked_2 = int(postvars['workday_minutes_worked_2'][0]) + db.workday_minutes_worked_3 = int(postvars['workday_minutes_worked_3'][0]) + db.workday_hourly_rate_1 = int(postvars['workday_hourly_rate_1'][0]) + db.workday_hourly_rate_2 = int(postvars['workday_hourly_rate_2'][0]) + db.workday_hourly_rate_3 = int(postvars['workday_hourly_rate_3'][0]) + db.year_goal = int(postvars['year_goal'][0]) + db.workdays_per_month = int(postvars['workdays_per_month'][0]) + if 'finish' in postvars.keys(): + day_income = (db.workday_minutes_worked_1 / 60.0) * db.workday_hourly_rate_1 + day_income += (db.workday_minutes_worked_2 / 60.0) * db.workday_hourly_rate_2 + day_income += (db.workday_minutes_worked_3 / 60.0) * db.workday_hourly_rate_3 + db.year_income += day_income + db.month_income += day_income + db.week_income += day_income + db.workday_minutes_worked_1 = 0 + db.workday_minutes_worked_2 = 0 + db.workday_minutes_worked_3 = 0 + db.write_db() + homepage = self.apps['income_progress'] if hasattr(self, 'apps') else self.homepage + self.redirect(homepage) def do_GET(self): + self.try_do(self.display_income_progress) + + def display_income_progress(self): import datetime - import calendar - self.send_response(200) - self.send_header("Content-type", "text/html") - self.end_headers() - db = load_db() + import calendar + db = IncomeDB() today = datetime.datetime.now() - if not os.path.exists(lock_file): - update_db = False - if today.year != db["timestamp_year"]: - db["timestamp_year"] = today.year - db["year_income"] = 0 - update_db = True - if today.month != db["timestamp_month"]: - db["timestamp_month"] = today.month - db["month_income"] = 0 - update_db = True - if today.isocalendar()[1] != db["timestamp_week"]: - db["timestamp_week"] = today.isocalendar()[1] - db["week_income"] = 0 - update_db = True - if update_db: - print("Resetting timestamp") - with open(lock_file, "w+"): pass - with open(db_file, "w") as f: - json.dump(db, f) - os.remove(lock_file) - else: - self.send_response(400) - self.end_headers() - self.wfile.write(bytes("Sorry, lock file!", "utf-8")) - return + update_db = False + if today.year != db.timestamp_year: + db.timestamp_year = today.year + db.timestamp_month = today.month + db.year_income = 0 + db.month_income = 0 + update_db = True + if today.month != db.timestamp_month: + db.timestamp_month = today.month + db.month_income = 0 + update_db = True + if today.isocalendar()[1] != db.timestamp_week: + db.timestamp_week = today.isocalendar()[1] + db.week_income = 0 + update_db = True + if update_db: + print("Resetting timestamp") + db.write_db() day_of_year = today.toordinal() - datetime.date(today.year, 1, 1).toordinal() + 1 year_length = 365 + calendar.isleap(today.year) - workday_goal = db["year_goal"] / 12 / db["workdays_per_month"] - workdays_per_week = (db["workdays_per_month"] * 12) / (year_length / 7) - month_goal = db["year_goal"] / 12 - week_goal = db["year_goal"] / (year_length / 7) - def success_color(success): - if success < 0.5: - return "red"; - elif success < 1: - return "yellow"; - else: - return "green" - def progressbar(title, earned, goal, time_progress=-1): - time_progress_indicator = "" - success_income = earned / goal - success_income_cut = min(success_income, 1.0) - success_income_bonus = max(success_income - 1.0, 0) - success = success_income + 0 - diff_goal = earned - goal - if time_progress >= 0: - success = 1 - if time_progress > 0: - success = success_income / time_progress - time_progress_indicator = "
" % int(time_progress * 100) - return "%s" \ - "%.2f€" \ - "%s
" \ - "
%.2f€
" % ( - title, earned, time_progress_indicator, success_color(success), int(success_income_cut * 100), diff_goal, int(success_income_bonus * 100)) - day_income = (db["workday_minutes_worked_1"] / 60.0) * db["workday_hourly_rate_1"] - day_income += (db["workday_minutes_worked_2"] / 60.0) * db["workday_hourly_rate_2"] - day_income += (db["workday_minutes_worked_3"] / 60.0) * db["workday_hourly_rate_3"] - year_plus = db["year_income"] + day_income - month_plus = db["month_income"] + day_income - week_plus = db["week_income"] + day_income - progress_time_year = day_of_year / year_length - progress_time_month = today.day / calendar.monthrange(today.year, today.month)[1] - progress_time_week = today.weekday() / 7 - year_line = progressbar("year", year_plus, db["year_goal"], progress_time_year) - month_line = progressbar("month", month_plus, month_goal, progress_time_month) - week_line = progressbar("week", week_plus, week_goal, progress_time_week) - day_line = progressbar("workday", day_income, workday_goal) - body = year_line + "\n" + month_line + "\n" + week_line + "\n" + day_line - page = header + body + footer % ( - db["workday_hourly_rate_1"], db["workday_minutes_worked_1"], - db["workday_hourly_rate_2"], db["workday_minutes_worked_2"], - db["workday_hourly_rate_3"], db["workday_minutes_worked_3"], - db["year_goal"], - month_goal, - week_goal, - db["workdays_per_month"], - workday_goal, - workdays_per_week, + workday_goal = db.year_goal / 12 / db.workdays_per_month + workdays_per_week = (db.workdays_per_month * 12) / (year_length / 7) + month_goal = db.year_goal / 12 + week_goal = db.year_goal / (year_length / 7) + day_income = (db.workday_minutes_worked_1 / 60.0) * db.workday_hourly_rate_1 + day_income += (db.workday_minutes_worked_2 / 60.0) * db.workday_hourly_rate_2 + day_income += (db.workday_minutes_worked_3 / 60.0) * db.workday_hourly_rate_3 + year_plus = db.year_income + day_income + month_plus = db.month_income + day_income + week_plus = db.week_income + day_income + progress_time_year = day_of_year / year_length + progress_time_month = today.day / calendar.monthrange(today.year, today.month)[1] + progress_time_week = today.weekday() / 7 + progress_bars = [ProgressBar("year", year_plus, db.year_goal, progress_time_year), + ProgressBar("month", month_plus, month_goal, progress_time_month), + ProgressBar("week", week_plus, week_goal, progress_time_week), + ProgressBar("workday", day_income, workday_goal)] + homepage = self.apps['income_progress'] if hasattr(self, 'apps') else self.homepage + page = jinja2.Template(tmpl).render( + homepage = homepage, + progress_bars = progress_bars, + workday_hourly_rate_1 = db.workday_hourly_rate_1, + workday_minutes_worked_1 = db.workday_minutes_worked_1, + workday_hourly_rate_2 = db.workday_hourly_rate_2, + workday_minutes_worked_2 = db.workday_minutes_worked_2, + workday_hourly_rate_3 = db.workday_hourly_rate_3, + workday_minutes_worked_3 = db.workday_minutes_worked_3, + year_goal = db.year_goal, + month_goal = month_goal, + week_goal = week_goal, + workdays_per_month = db.workdays_per_month, + workday_goal = workday_goal, + workdays_per_week = workdays_per_week, ) - self.wfile.write(bytes(page, "utf-8")) + self.send_HTML(page) + -if __name__ == "__main__": - webServer = HTTPServer((hostName, serverPort), MyServer) - print("Server started http://%s:%s" % (hostName, serverPort)) - try: - webServer.serve_forever() - except KeyboardInterrupt: - pass - webServer.server_close() - print("Server stopped.") +if __name__ == "__main__": + run_server(server_port, IncomeProgressHandler)