Last active
January 31, 2018 03:07
-
-
Save ckuhl/5deff586dc07db6272b918cab83b4bee to your computer and use it in GitHub Desktop.
Generate an ASCII punchcard from a series of timestamps
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
''' | |
punchcard - generate a punchcard from a series of timestamps | |
Example: | |
$ git --no-pager log | punchcard | |
╔═════╦════════════════════════════════════════════════════════════════════════╗ | |
║ Sun ║ ║ | |
║ Mon ║ o . ║ | |
║ Tue ║ . . .║ | |
║ Wed ║ * o * . . . . . . ║ | |
║ Thu ║ . 0 * ║ | |
║ Fri ║ . . * * . . . . ║ | |
║ Sat ║ . * . . ║ | |
╠═════╬════════════════════════════════════════════════════════════════════════╣ | |
║ ║ 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23║ | |
╚═════╩════════════════════════════════════════════════════════════════════════╝ | |
Optional arguments: | |
-h, --help show this help message and exit | |
--version print version and exit | |
--week-start WEEK_START | |
specify the first day of the week | |
<Sun|Mon|Tue|...|Sat> | |
--colour, --color toggle optional heatmap | |
''' | |
import argparse | |
import sys | |
# metadata | |
__author__ = 'Christian Kuhl' | |
__licence__ = 'GPLv3' | |
__version__ = (1, 0, 0) | |
# take input | |
parser = argparse.ArgumentParser( | |
prog='punchcard', | |
description='produce an ASCII punchcard from datestamped logs') | |
parser.add_argument( | |
'--version', | |
action='store_true', | |
help='print version and exit') | |
parser.add_argument( | |
'--week-start', | |
action='store', | |
default='Sun', | |
dest='week_start', | |
help='specify the first day of the week <Sun|Mon|Tue|...|Sat>') | |
parser.add_argument( | |
'--colour', '--color', | |
action='store_true', | |
help='toggle optional heatmap') | |
args = parser.parse_args() | |
# handle version request | |
if args.version: | |
print('punchcard {}.{}.{}'.format(*__version__)) | |
sys.exit(0) | |
# set up global vars | |
hours = ['%02d' % x for x in range(0, 24)] | |
days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] | |
if args.week_start in days: | |
if args.week_start != 'Sun': | |
ws = days.index(args.week_start) | |
days = days[ws:] + days[:ws] | |
else: | |
print('ERROR: %s not a valid day of the week' % args.week_start, | |
file=sys.stderr) | |
sys.exit(1) | |
occur = {(x, y): 0 for x in days for y in hours} | |
# main operation functions | |
def print_ascii(value): | |
if value >= 1: # should be at most == 1 | |
print(' 0', end='') | |
elif value >= 0.80: | |
print(' 8', end='') | |
elif value >= 0.60: | |
print(' O', end='') | |
elif value >= 0.40: | |
print(' o', end='') | |
elif value >= 0.20: | |
print(' *', end='') | |
elif value: | |
print(' .', end='') | |
else: | |
print(' ', end='') | |
def print_colour(value): | |
''' | |
Print a given colour and space | |
''' | |
BASE = '\033[48;05;' | |
BASE_END = ';m' | |
END_COL = '\033[0m' | |
start = 232 | |
end = 255 | |
c = str(int((start - end) * value) + end) | |
print(BASE + c + BASE_END + ' ' + END_COL, end='') | |
def draw_card(occur): | |
''' | |
Draw the punchcard | |
''' | |
most = 0 | |
for k in occur: | |
if occur[k] > most: | |
most = occur[k] | |
print('╔', '═' * 5, '╦', '═' * (3 * 24), '╗', sep='') | |
for d in days: | |
print('║', d, '║', end='') | |
for h in hours: | |
if args.colour: | |
print_colour(occur[(d, h)] / most) | |
else: | |
print_ascii(occur[(d, h)] / most) | |
print('║') | |
print('╠', '═' * 5, '╬', '═' * (3 * 24), '╣', sep='') | |
print('║', ' ' * 5 , '║', sep='', end='') | |
for h in hours: | |
print(' ', h, sep='', end='') | |
print('║') | |
print('╚', '═' * 5, '╩', '═' * 72, '╝', sep='') | |
sys.exit(0) | |
def read_input(): | |
''' | |
Read in from stdin and create occurence dict | |
''' | |
log = sys.stdin.read() | |
for line in log.split('\n'): | |
if 'Date:' in line: | |
ts = line.split() | |
occur[(ts[1], ts[4].split(':')[0])] += 1 | |
return occur | |
def main(): | |
''' | |
Run script components | |
''' | |
draw_card(read_input()) | |
sys.exit(0) | |
# run the script | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example of
git --no-pager log | punchcard --colour
: