X-Git-Url: https://wylark.com/src/munter.git/blobdiff_plain/d40d94ad9e7edcaaaeeb852624d263906bd32522..b2bbb21d18ada3297d03dd9f63eb64a1bf923148:/munter/__init__.py?ds=sidebyside diff --git a/munter/__init__.py b/munter/__init__.py new file mode 100755 index 0000000..2ee36d4 --- /dev/null +++ b/munter/__init__.py @@ -0,0 +1,142 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + + +""" +Munter Time Calculation +Alexander Vasarab +Wylark Mountaineering LLC + +Version 1.0.2 + +A rudimentary program which implements the Munter time calculation. +""" + +import sys +import argparse + +class InvalidUnitsException(Exception): + pass + +rates = { + 'uphill': { 'rate': 4, 'direction': '↑' }, + 'flat': { 'rate': 6, 'direction': '→' }, # or downhill on foot + 'downhill': { 'rate': 10, 'direction': '↓' }, + 'bushwhacking': { 'rate': 2, 'direction': '↹' }, +} + +unit_choices = ['metric', 'imperial'] +travel_mode_choices = rates.keys() + +def time_calc(distance, elevation, rate, units): + retval = {} + + if units not in unit_choices: + raise InvalidUnitsException + + unit_count = 0 + + if 'imperial' == units: + # convert to metric + distance = (distance * 1.609) # mi to km + elevation = (elevation * .305) # ft to m + + unit_count = distance + (elevation / 100.0) + + retval['time'] = (distance + (elevation / 100.0)) / rates[rate]['rate'] + retval['unit_count'] = unit_count + retval['direction'] = rates[rate]['direction'] + retval['pace'] = rates[rate]['rate'] + + return retval + +def print_ugly_estimate(est): + hours = int(est['time']) + minutes = int((est['time'] - hours) * 60) + print("{human_time}".format( + human_time="{hours} hours {minutes} minutes".format( + hours=hours, + minutes=minutes))) + +def print_pretty_estimate(est): + hours = int(est['time']) + minutes = int((est['time'] - hours) * 60) + + # NOTE: Below, the line with the unicode up arrow uses an alignment + # value of 31. In the future, consider using e.g. wcwidth + # library so that this is more elegant. + print("\n\t╒═══════════════════════════════╕") + print("\t╎▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒╎╮") + print("\t╎▒{:^29}▒╎│".format('')) + print("\t╎▒{pace_readable:^31}▒╎│".format( + pace_readable="{units} {direction} @ {pace}".format( + units=round(est['unit_count']), + direction=est['direction'], + pace=est['pace']))) + print("\t╎▒{human_time:^29}▒╎│".format( + human_time="{hours} hours {minutes} minutes".format( + hours=hours, + minutes=minutes))) + print("\t╎▒{:^29}▒╎│".format('')) + print("\t╎▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒╎│") + print("\t╘═══════════════════════════════╛│") + print("\t └───────────────────────────────┘\n") + +def get_parser(): + parser = argparse.ArgumentParser(description='Munter Time Calculation') + + parser.add_argument('--distance', + '-d', + type=float, + required=True, + help='Distance (in km, by default)') + + parser.add_argument('--elevation', + '-e', + type=float, + required=True, + help='Elevation change (in m, by default)') + + parser.add_argument('--travel-mode', + '-t', + type=str, + default='uphill', + choices=travel_mode_choices, required=False, + help='Travel mode (flat, by default)') + + parser.add_argument('--units', + '-u', + type=str, + default='imperial', + required=False, + choices=unit_choices, + help='Units of input values') + + parser.add_argument('--pretty', + '-p', + action='store_true', + default=False, + required=False); + + return parser + +def main(): + parser = get_parser() + opts = parser.parse_args() + + distance = opts.distance + elevation = opts.elevation + units = opts.units + travel_mode = opts.travel_mode + + time_estimate = time_calc(distance, elevation, travel_mode, units=units) + + if opts.pretty: + print_pretty_estimate(time_estimate) + else: + print_ugly_estimate(time_estimate) + + return 0 + +if __name__ == "__main__": + sys.exit(main())