Make README a proper Markdown file
[munter.git] / munter / __init__.py
1 #! /usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4
5 """
6 Munter Time Calculation
7 Alexander Vasarab
8 Wylark Mountaineering LLC
9
10 Version 1.0.2
11
12 A rudimentary program which implements the Munter time calculation.
13 """
14
15 import sys
16 import argparse
17
18 class InvalidUnitsException(Exception):
19 pass
20
21 rates = {
22 'uphill': { 'rate': 4, 'direction': '↑' },
23 'flat': { 'rate': 6, 'direction': '→' }, # or downhill on foot
24 'downhill': { 'rate': 10, 'direction': '↓' },
25 'bushwhacking': { 'rate': 2, 'direction': '↹' },
26 }
27
28 unit_choices = ['metric', 'imperial']
29 travel_mode_choices = rates.keys()
30
31 def time_calc(distance, elevation, rate, units):
32 retval = {}
33
34 if units not in unit_choices:
35 raise InvalidUnitsException
36
37 unit_count = 0
38
39 if 'imperial' == units:
40 # convert to metric
41 distance = (distance * 1.609) # mi to km
42 elevation = (elevation * .305) # ft to m
43
44 unit_count = distance + (elevation / 100.0)
45
46 retval['time'] = (distance + (elevation / 100.0)) / rates[rate]['rate']
47 retval['unit_count'] = unit_count
48 retval['direction'] = rates[rate]['direction']
49 retval['pace'] = rates[rate]['rate']
50
51 return retval
52
53 def print_ugly_estimate(est):
54 hours = int(est['time'])
55 minutes = int((est['time'] - hours) * 60)
56 print("{human_time}".format(
57 human_time="{hours} hours {minutes} minutes".format(
58 hours=hours,
59 minutes=minutes)))
60
61 def print_pretty_estimate(est):
62 hours = int(est['time'])
63 minutes = int((est['time'] - hours) * 60)
64
65 # NOTE: Below, the line with the unicode up arrow uses an alignment
66 # value of 31. In the future, consider using e.g. wcwidth
67 # library so that this is more elegant.
68 print("\n\t╒═══════════════════════════════╕")
69 print("\t╎▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒╎╮")
70 print("\t╎▒{:^29}▒╎│".format(''))
71 print("\t╎▒{pace_readable:^31}▒╎│".format(
72 pace_readable="{units} {direction} @ {pace}".format(
73 units=round(est['unit_count']),
74 direction=est['direction'],
75 pace=est['pace'])))
76 print("\t╎▒{human_time:^29}▒╎│".format(
77 human_time="{hours} hours {minutes} minutes".format(
78 hours=hours,
79 minutes=minutes)))
80 print("\t╎▒{:^29}▒╎│".format(''))
81 print("\t╎▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒╎│")
82 print("\t╘═══════════════════════════════╛│")
83 print("\t └───────────────────────────────┘\n")
84
85 def get_parser():
86 parser = argparse.ArgumentParser(description='Munter Time Calculation')
87
88 parser.add_argument('--distance',
89 '-d',
90 type=float,
91 required=True,
92 help='Distance (in km, by default)')
93
94 parser.add_argument('--elevation',
95 '-e',
96 type=float,
97 required=True,
98 help='Elevation change (in m, by default)')
99
100 parser.add_argument('--travel-mode',
101 '-t',
102 type=str,
103 default='uphill',
104 choices=travel_mode_choices, required=False,
105 help='Travel mode (flat, by default)')
106
107 parser.add_argument('--units',
108 '-u',
109 type=str,
110 default='imperial',
111 required=False,
112 choices=unit_choices,
113 help='Units of input values')
114
115 parser.add_argument('--pretty',
116 '-p',
117 action='store_true',
118 default=False,
119 required=False);
120
121 return parser
122
123 def main():
124 parser = get_parser()
125 opts = parser.parse_args()
126
127 distance = opts.distance
128 elevation = opts.elevation
129 units = opts.units
130 travel_mode = opts.travel_mode
131
132 time_estimate = time_calc(distance, elevation, travel_mode, units=units)
133
134 if opts.pretty:
135 print_pretty_estimate(time_estimate)
136 else:
137 print_ugly_estimate(time_estimate)
138
139 return 0
140
141 if __name__ == "__main__":
142 sys.exit(main())