#!/usr/bin/env python import datetime import sys import math import argparse from scipy import stats argparser = argparse.ArgumentParser() argparser.add_argument('--reddit', '-r', action='store_true') args = argparser.parse_args() parse_date = lambda s: datetime.datetime.strptime(s, "%Y-%m-%d") goal = 225 goal_date = parse_date("2019-06-01") window = 30 height = 1.91 # meters kg_per_lb = 0.453592 points = [] def parse(ln): date, weight = ln.split() date = datetime.datetime.strptime(date, '%Y-%m-%d') weight = float(weight) return (date, weight) lines = list(sys.stdin) start_date, start = parse(lines[0]) points = map(parse, lines) num_points = len(points) num_decrease = sum(1 for p, q in zip(points, points[1:]) if p[1] > q[1]) points = points[-window:] first = points[0] last = points[-1] reg_x = [p[0].toordinal() for p in points] reg_y = [p[1] for p in points] slope, intercept, r_value, p_value, stderr = stats.linregress(reg_x, reg_y) #rate = (first[1] - last[1]) / (last[0] - first[0]).days rate = -slope if rate <= 0.0: print "Sorry, you're getting fatter at %.2f lb/wk (r^2 = %.2f)" % (-7.0*rate, r_value**2.0) sys.exit(1) def output_stat(label, value): if args.reddit: print '**' + label + '**|' + value.lstrip() else: print (label + ':').ljust(17) + value done = start - last[1] days_done = (last[0] - start_date).days remainder = last[1] - goal remaining_time = datetime.timedelta(days = remainder / rate) finish_date = last[0] + remaining_time margin = (goal_date - finish_date).days + 1 required_rate = remainder / (goal_date - last[0]).days excess_rate = rate - required_rate def project(date): projection = last[1] - (rate * (parse_date(date) - last[0]).days) print 'Weight on %s: %6.2f lbs = %6.2f lbs lost' % (date, projection, start - projection) if args.reddit: print 'Stat|Value' print ':-|:-' output_stat('Current weight', '%6.2f lbs' % (last[1],)) #output_stat('BMI', '%6.2f' % ((kg_per_lb * last[1]) / (height ** 2.0),)) output_stat('Lost so far', '%6.2f lbs = %5.2f%% of starting weight' % (done, 100.0 * done / start)) output_stat('Remaining', '%6.2f lbs = %5.2f%% of current weight' % (remainder, 100.0 * remainder / last[1])) output_stat('Progress', '%6.2f %%' % (done / (start - goal) * 100.0,)) output_stat('Required rate', '%6.2f lbs / wk' % (7.0 * required_rate,)) output_stat('Actual rate', '%6.2f lbs / wk = %.2f%% per week (r^2 = %4.2f)' % (7.0*rate, 100*7.0*rate / last[1], r_value**2.0)) #output_stat('Excess rate', '%6.2f lbs / wk' % (7.0*excess_rate,)) output_stat('Deficit', ' %4d kcal / day' % (rate*3500,)) #output_stat('Excess deficit', ' %4d kcal/day' % (excess_rate*3500,)) output_stat('All-time rate', '%6.2f lbs / wk' % (7.0 * done / days_done,)) output_stat('Average drops', '%6.2f %% of the time (%d out of %d points)' % (100.0 * num_decrease / float(num_points), num_decrease, num_points)) print print 'Goal will be reached on %s' % (finish_date.strftime('%Y-%m-%d'),), if margin > 0: print '(%d days early)' % (margin,) else: print '(%d days late)' % (-margin,) if args.reddit: print print days_done, 'days done, only', remaining_time.days, 'left to go! Keep it up, you\'re doing great!' print project('2019-06-01') with open('regression_line', 'w') as f: line_out = lambda pt: f.write(pt[0].strftime('%Y-%m-%d') + ' ' + str(intercept + slope*pt[0].toordinal()) + '\n') line_out(points[0]) line_out(points[-1])