Skip to content

Instantly share code, notes, and snippets.

@narthur
Last active April 30, 2019 20:31
Show Gist options
  • Save narthur/3c1dac894b413979121c3aba53df32b7 to your computer and use it in GitHub Desktop.
Save narthur/3c1dac894b413979121c3aba53df32b7 to your computer and use it in GitHub Desktop.
Script for generating Beeminder journal updates
#!/usr/bin/env python3
import os
import yaml
from beeminderpy import Beeminder
import json
from pprint import pprint
from tabulate import tabulate
import datetime
import time
import random
class Bm:
config = None
b = None
username = None
goals = []
time_floor = time.time() - (60 * 60 * 24 * 7)
_new_derails = {}
def __init__(self, configuration):
self.config = configuration
self.b = Beeminder(configuration["auth"]["beeminder"]["token"])
self.username = self.config["auth"]["beeminder"]["username"]
self._load_goals()
def _load_goals(self):
goals = json.loads(self.b.get_goals(self.username))
self.goals = [goal for goal in goals if goal['slug'] not in self.config["journal"]["excluded"]]
def get_highest_pledge_goal(self):
candidate = self.goals[0]
for goal in self.goals:
if goal['pledge'] > candidate['pledge']:
candidate = goal
return candidate
def get_oldest_goal(self):
candidate = self.goals[0]
for goal in self.goals:
if goal['initday'] < candidate['initday']:
candidate = goal
return candidate
def get_newest_goal(self):
candidate = self.goals[0]
for goal in self.goals:
if goal['initday'] > candidate['initday']:
candidate = goal
return candidate
def get_new_goals(self):
return [goal for goal in self.goals if goal['initday'] > self.time_floor]
def total_pledges(self):
total = 0
for goal in self.goals:
total += goal['pledge']
return total
def get_new_derails(self):
if self._new_derails:
return self._new_derails
derails = {}
for goal in self.goals:
datapoints = json.loads(self.b.get_datapoints(self.username, goal['slug']))
derails[goal["slug"]] = [point for point in datapoints if point["timestamp"] > self.time_floor and "RECOMMITTED" in point["comment"]]
self._new_derails = {slug: points for slug, points in derails.items() if len(points) > 0}
return self._new_derails
def count_new_derails(self):
new_derails = self.get_new_derails()
count = 0
for _slug, _points in new_derails.items():
count += len(_points)
return count
def count_systems_upgrades(self):
points = json.loads(self.b.get_datapoints(self.username, "systems-upgrade"))
return len([point for point in points if point['timestamp'] > self.time_floor])
def get_graph(self, slug):
return json.loads(self.b.get_goal(self.username, slug))['graph_url']
def get_random_goal(self):
date = time_to_string(time.time())
random.seed(date)
return random.choice(self.goals)
def time_to_string(unix):
return datetime.datetime.fromtimestamp(unix).strftime("%Y-%m-%d")
def link_slug(slug):
return f'[{slug}](https://www.beeminder.com/narthur/{slug})'
def markdown_list(items):
return "\n".join([f"- {item}" for item in items])
directory = os.path.dirname(os.path.realpath(__file__))
config = yaml.load(open(f"{directory}/config.yaml", "r"))
bm = Bm(config)
highest_pledge_goal = bm.get_highest_pledge_goal()
oldest_goal = bm.get_oldest_goal()
newest_goal = bm.get_newest_goal()
new_goals = bm.get_new_goals()
headers = ["Key", "Value"]
table = [
["Number of goals", len(bm.goals)],
["New goals this week", len(new_goals)],
["Newest goal", f'{link_slug(newest_goal["slug"])} ({time_to_string(newest_goal["initday"])})'],
["Oldest goal", f'{link_slug(oldest_goal["slug"])} ({time_to_string(oldest_goal["initday"])})'],
["Highest pledge", f'{link_slug(highest_pledge_goal["slug"])} (${highest_pledge_goal["pledge"]})'],
["Total pledges", f'${bm.total_pledges()}'],
["Derails this week", bm.count_new_derails()],
["Systems upgrades this week", bm.count_systems_upgrades()]
]
summary_table = tabulate(table, headers, tablefmt="github")
rand_goal = bm.get_random_goal()
markdown_new_goals = [f'**{link_slug(new_goal["slug"])}:** Created {time_to_string(new_goal["initday"])}. TK' for new_goal in new_goals]
derails = bm.get_new_derails()
markdown_derails = []
for slug, points in derails.items():
dates = [time_to_string(point["timestamp"]) for point in points]
markdown_derails.append(f'**{link_slug(slug)}:** {", ".join(dates)}. TK')
output = f"""
# Update {time_to_string(time.time())}
## Summary
{summary_table}
## Random Goal: {link_slug(rand_goal['slug'])}
TK
## New Goals
{markdown_list(markdown_new_goals)}
## Derails
{markdown_list(markdown_derails)}
## Max-Min Buffer Over Time
This chart shows the largest that the minimum buffer for any goal was during each day. (I really need a better way to
explain this.)
{bm.get_graph("buffer")}
*A skeleton of this summary generated using a Python script and then carefully filled-in by hand.*
"""
print(output)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment