From: Alexander Vasarab Date: Sun, 21 Jun 2020 02:28:53 +0000 (-0700) Subject: Merge branch 'packaging' X-Git-Tag: v2.0.0^0 X-Git-Url: https://wylark.com/src/munter.git/commitdiff_plain/199c4afc24dd503212cde2ca87f2c16aa4dd384b?hp=d40d94ad9e7edcaaaeeb852624d263906bd32522 Merge branch 'packaging' --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f98771d --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# Distribution / packaging +build/ +dist/ +wheels/ +*.egg-info/ +*.egg +MANIFEST + +# Environments +env/ +venv/ diff --git a/README b/README deleted file mode 100644 index fe396e9..0000000 --- a/README +++ /dev/null @@ -1,59 +0,0 @@ -========= -Munter.py -========= - -Helps you speed up your tour and trip planning. - -Disclaimer -========== - -The time calculations produced by this program are not guaranteed to be -accurate. Any harm or hazard encountered due to blindly trusting these -estimates is your own fault. - -Installation -============ - -There is no installation and there are no dependencies external to the Python -standard library. - -How to use it -============= - -./munter.py --help - -My workflow involves planning my tour using tools like ArcGIS or CalTopo. Then, -I take the stats between each leg (distance, vertical gain/loss) of the tour -and run them through Munter.py and thence record its output to my field -notebook. - -The rudimentary "GUI" can be directly transferred to e.g. the format used by -SnowPit Technologies' "Avalanche Field Notebook" or your own personal format -(e.g. RitR No. 471). - -Future plans -============ - -* Personal "fitness" switch (to help fine tune your estimates based on - your personal fitness level as observed - over time) -* GTK mode -* Use as a Python library from within another project -* Lint it (e.g. therapist) -* Pip? - -Version History -=============== - -1.0.2 (Jun 2020) - * A few small bugfixes. - -1.0.1 (Jun 2020) - * Add LICENSE and README. - -1.0.0 (Jun 2020) - * First released version. Includes sensible defaults and a rudimentary CLI - "GUI". - -pre-1.0.0 (Mar 2017) - * In use privately/internally since 2017. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a61f2d9 --- /dev/null +++ b/README.md @@ -0,0 +1,67 @@ +Munter.py +========= + +Helps you speed up your tour and trip planning. + +Disclaimer +---------- + +The time calculations produced by this program are not guaranteed to be +accurate. Any harm or hazard encountered due to blindly trusting these +estimates is your own fault. + +Installation +------------ + +There is no installation and there are no dependencies external to the Python +standard library. + +How to use it +------------- + +`./munter.py --help` + +My workflow involves planning my tour using tools like ArcGIS or CalTopo. Then, +I take the stats between each leg (distance, vertical gain/loss) of the tour +and run them through Munter.py and thence record its output to my field +notebook. + +The rudimentary "GUI" can be directly transferred to e.g. the format used by +SnowPit Technologies' "Avalanche Field Notebook" or your own personal format +(e.g. RitR No. 471). + +Future plans +------------ + +* Personal "fitness" switch (to help fine tune your estimates based on + your personal fitness level as observed + over time) +* GTK mode +* Use as a Python library from within another project +* Lint it (e.g. therapist) +* Pip? +* Sphinx/autodoc? + +Version History +--------------- + +- 2.0.0 (Jun 2020) + + Packaged for distribution as a standalone program (and library). + +- 1.0.2 (Jun 2020) + + A few small bugfixes. + +- 1.0.1 (Jun 2020) + + Add LICENSE and README. + +- 1.0.0 (Jun 2020) + + First released version. Includes sensible defaults and a rudimentary CLI + "GUI". + +- pre-1.0.0 (Mar 2017) + + In use privately/internally since 2017. diff --git a/munter.py b/munter.py index 2ee36d4..485db19 100755 --- a/munter.py +++ b/munter.py @@ -1,142 +1,9 @@ #! /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. -""" - +"""Wrapper for running directly from the source code directory""" 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 +from munter.munter import main if __name__ == "__main__": sys.exit(main()) diff --git a/munter/__init__.py b/munter/__init__.py new file mode 100755 index 0000000..3f73639 --- /dev/null +++ b/munter/__init__.py @@ -0,0 +1,3 @@ +"""Main package for Munter.py""" +__version__ = "2.0.0" +from .munter import time_calc diff --git a/munter/__main__.py b/munter/__main__.py new file mode 100644 index 0000000..389c8a2 --- /dev/null +++ b/munter/__main__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- + +"""entry point for program and library""" + +from .munter import main +main() + diff --git a/munter/munter.py b/munter/munter.py new file mode 100644 index 0000000..7179e52 --- /dev/null +++ b/munter/munter.py @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- + + +""" +Munter Time Calculation +Alexander Vasarab +Wylark Mountaineering LLC + +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()) diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..f30ca70 --- /dev/null +++ b/setup.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +"""munter.py distutils configuration.""" +import os +import re +from setuptools import setup + +cur_dir = os.path.dirname(__file__) +version = re.search( + '^__version__\s*=\s*"(.*)"', + open(os.path.join(cur_dir, 'munter/__init__.py')).read(), + re.M + ).group(1) + +with open(os.path.join(cur_dir, 'README.md'), encoding='utf-8') as readme_file: + readme = readme_file.read() + +setup( + name='munter.py', + version=version, + description=( + 'An easy-to-use implementation of the Munter time calculation' + ), + long_description=readme, + long_description_content_type='text/markdown', + author='Alexander Vasarab', + author_email='alexander@wylark.com', + url='https://wylark.com/munter', + packages=['munter'], + package_dir={'munter': 'munter'}, + entry_points={'console_scripts': ['munter = munter.munter:main']}, + include_package_data=True, + python_requires='>=3.6', + license='ISC', + classifiers=[ + "Development Status :: 5 - Production/Stable", + "Environment :: Console", + "Intended Audience :: Other Audience", + "Intended Audience :: Developers", + "Natural Language :: English", + "License :: OSI Approved :: ISC License (ISCL)", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python", + "Topic :: Software Development", + "Topic :: Software Development :: Libraries :: Python Modules", + ], + keywords=[ + "munter", + "tour planning", + "trip planning", + "time estimate", + ], +) diff --git a/tests/test.py b/tests/test.py new file mode 100755 index 0000000..bf5b01b --- /dev/null +++ b/tests/test.py @@ -0,0 +1,6 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +import munter + +est = munter.time_calc(3.2, 2300, 'uphill', 'imperial') +print("Time Estimate: %s hours" % est['time'])