--- /dev/null
+*.wls linguist-language=Mathematica
-[Unreleased]
+[0.2.6] - 2022-08-08
########################################################################
Added
~~~~~
- Recipes are stored in a ``csv`` format now with ``uuid`` instead of ``int``,
- and they can be viewed in a convenient ``tree`` output.
+ and they can be viewed in a convenient ``tree`` output
+ (**NOTE:** recipes is still a WIP).
- Calculate functions for body fat, BMR, 1-rep max, & lean body limits.
- Example recipe ``csv`` files.
- ``unittest`` compatibility, not sure this will stay.
May revert to ``pytest``.
-- Dedicated test file for calculate service.
+- Dedicated test file for ``calculate.py`` service.
Changed
~~~~~~~
- Start to split apart some of the original ``test_cli`` functions.
- Enable more verbose ``mypy`` flags.
+Fixed
+~~~~~
+
+- Faulty algebra in the ``orm_brzycki`` equation.
+- Missing rep ranges for ``dos_remedios`` equation.
-[0.2.4] - 2022-07-20
+
+[0.2.5] - 2022-07-20
########################################################################
Added
+[0.2.4] - 2022-07-12
+########################################################################
+
+Fixed
+~~~~~
+
+- Error when doing a pip install: ``NTSQLITE_DESTINATION`` is not defined.
+
+
+
[0.2.3] - 2022-07-12
########################################################################
recursive-include ntclient/resources/ *.csv
global-exclude *.sqlite3
+global-exclude *.wls
import sys
from enum import Enum
-try:
- from colorama import Fore, Style
- from colorama import init as colorama_init
-
- COLORAMA_CAPABLE = True
- colorama_init()
-except ImportError:
- COLORAMA_CAPABLE = False
-
from ntclient.ntsqlite.sql import NT_DB_NAME
+from ntclient.utils import colors
# Package info
__title__ = "nutra"
-__version__ = "0.2.6.dev5"
+__version__ = "0.2.6"
__author__ = "Shane Jaroch"
__email__ = "chown_tee@proton.me"
__license__ = "GPL v3"
THRESH_CRIT = 0.4
THRESH_OVER = 1.9
- if COLORAMA_CAPABLE:
- COLOR_WARN = Fore.YELLOW
- COLOR_CRIT = Style.DIM + Fore.RED
- COLOR_OVER = Style.DIM + Fore.MAGENTA
-
- COLOR_DEFAULT = Fore.CYAN
+ COLOR_WARN = colors.COLOR_WARN
+ COLOR_CRIT = colors.COLOR_CRIT
+ COLOR_OVER = colors.COLOR_OVER
- COLOR_RESET_ALL = Style.RESET_ALL
+ COLOR_DEFAULT = colors.COLOR_DEFAULT
- # Used in macro bars
- COLOR_YELLOW = Fore.YELLOW
- COLOR_BLUE = Fore.BLUE
- COLOR_RED = Fore.RED
- else:
- COLOR_WARN = str() # type: ignore
- COLOR_CRIT = str() # type: ignore
- COLOR_OVER = str() # type: ignore
+ STYLE_RESET_ALL = colors.STYLE_RESET_ALL
- COLOR_DEFAULT = str() # type: ignore
-
- COLOR_RESET_ALL = str() # type: ignore
-
- COLOR_YELLOW = str() # type: ignore
- COLOR_BLUE = str() # type: ignore
- COLOR_RED = str() # type: ignore
+ # Used in macro bars
+ COLOR_YELLOW = colors.COLOR_YELLOW
+ COLOR_BLUE = colors.COLOR_BLUE
+ COLOR_RED = colors.COLOR_RED
class _CliConfig:
self.color_over = RdaColors.COLOR_OVER.value
self.color_default = RdaColors.COLOR_DEFAULT.value
- self.color_reset_all = RdaColors.COLOR_RESET_ALL.value
+ self.style_reset_all = RdaColors.STYLE_RESET_ALL.value
+
self.color_yellow = RdaColors.COLOR_YELLOW.value
self.color_red = RdaColors.COLOR_RED.value
self.color_blue = RdaColors.COLOR_BLUE.value
"""BMR, 1 rep-max, and other calculators"""
calc_parser = subparsers.add_parser(
- "calc", help="find you 1 rep max, body fat, BMR"
+ "calc", help="calculate 1-rep max, body fat, BMR, etc."
)
calc_subparsers = calc_parser.add_subparsers(title="recipe subcommands")
reps = int(args.reps)
print("Reps: %s" % reps)
+ if weight < 0:
+ print("ERROR: weight must be greater than zero")
+ return 1, None
+ if reps < 1 or reps > 20:
+ print("ERROR: reps must be between 1 and 20")
+ return 1, None
+
_epley = calc.orm_epley(weight, reps)
_brzycki = calc.orm_brzycki(weight, reps)
_dos_remedios = calc.orm_dos_remedios(weight, reps)
for _rep in _epley.keys():
row = [_rep]
for _calc, _values in result.items():
- try:
- # Round down for now
- row.append(int(_values[_rep]))
- except KeyError:
- row.append(None)
+ # Round down for now
+ row.append(int(_values[_rep]))
_all.append(row)
# Print results
print()
print("Results for: epley, brzycki, and dos_remedios")
- if "errMsg" in _dos_remedios:
- print("WARN: Dos Remedios failed: %s" % _dos_remedios["errMsg"])
print()
_table = tabulate(_all, headers=["n", "epl", "brz", "rmds"])
print(_table)
--- /dev/null
+#!/usr/bin/env wolframscript
+(* ::Package:: *)
+
+(* ::Input:: *)
+(*(* Epley *)*)
+(*epley[n_]:=30/(29 +n)*)
+(**)
+(*(* Brzycki *)*)
+(*(*brzLin[n_]:=(37-n)/36*)*)
+(*brz[n_]:=(37-n+0.005n^2)/36*)
+(**)
+(*(* Dos Remedios *)*)
+(*dosPts={{1,1},{2,0.92},{3,0.9},{5,0.87},{6,0.82},{8,0.75},{10,0.7},{12,0.65},{15,0.6},{20,0.55}};*)
+(*(*ListLinePlot[{dosPts}, Filling->Axis]*)*)
+(*dos:=Interpolation[dosPts]*)
+(*(*dos[2]*)*)
+(*(*epley[20.]*)
+(*brz[20]*)
+(*dos[20]*)*)
+(*Plot[\!\(\**)
+(*TagBox[*)
+(*RowBox[{"{", *)
+(*RowBox[{*)
+(*RowBox[{"epley", "[", "n", "]"}], ",", *)
+(*RowBox[{"brz", "[", "n", "]"}], ",", *)
+(*RowBox[{"dos", "[", "n", "]"}]}], "}"}],*)
+(*Short[#, 2]& ]\),{n,1,20}, AxesLabel->{"# of reps", "% of 1-rep max"},PlotLegends->"Expressions"]*)
+(*dos[4]*)
+(*dos[7]*)
+(*dos[9]*)
+(*dos[11]*)
+(*dos[12] (* Known Value *)*)
+(*dos[13]*)
+(*dos[14]*)
+(*dos[15] (* Known Value *)*)
+(*dos[16]*)
+(*dos[17]*)
+(*dos[18]*)
+(*dos[19]*)
+(*dos[20]*)
+
+
+
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
print("--> %s" % header)
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
- print(CLI_CONFIG.color_reset_all)
+ print(CLI_CONFIG.style_reset_all)
def print_macro_bar(
_fat: float, _net_carb: float, _pro: float, _kcals_max: float, _buffer: int = 0
+ c_buf
+ CLI_CONFIG.color_red
+ p_buf
- + CLI_CONFIG.color_reset_all
+ + CLI_CONFIG.style_reset_all
)
# Bars
print(CLI_CONFIG.color_yellow + "=" * n_fat, end="")
print(CLI_CONFIG.color_blue + "=" * n_car, end="")
print(CLI_CONFIG.color_red + "=" * n_pro, end="")
- print(CLI_CONFIG.color_reset_all + ">")
+ print(CLI_CONFIG.style_reset_all + ">")
# Calorie footers
k_fat = str(round(fat * 9))
+ c_buf
+ CLI_CONFIG.color_red
+ p_buf
- + CLI_CONFIG.color_reset_all
+ + CLI_CONFIG.style_reset_all
)
def print_nute_bar(_n_id: int, amount: float, _nutrients: dict) -> tuple:
print(" {0}<".format(color), end="")
print("=" * left_pos + " " * (left_index - left_pos) + ">", end="")
print(" {0}%\t[{1}]".format(perc, detail_amount), end="")
- print(CLI_CONFIG.color_reset_all)
+ print(CLI_CONFIG.style_reset_all)
return True, perc
return round(_un_rounded_result, 1)
def weight_max_reps(target_reps: float) -> float:
- _un_rounded_result = one_rm() / (1 + (target_reps - 1) / 30)
+ _un_rounded_result = one_rm() * 30 / (29 + target_reps)
return round(_un_rounded_result, 1)
maxes = {n_reps: weight_max_reps(n_reps) for n_reps in common_n_reps}
def orm_brzycki(weight: float, reps: float) -> dict:
"""
Returns a dict {n_reps: max_weight, ...}
- for n_reps: (1, 2, 3, 5, 6, 8, 10, 12, 15)
+ for n_reps: (1, 2, 3, 5, 6, 8, 10, 12, 15, 20)
1 RM = weight * 36 / (37 - reps)
+ NOTE: Adjusted formula is below, with quadratic term.
+
+ 1 RM = weight * 36 / (37 - reps + 0.005 * reps^2)
+
Source: https://workoutable.com/one-rep-max-calculator/
"""
def _one_rm() -> float:
- _un_rounded_result = weight * 36 / (37 - reps)
+ _un_rounded_result = weight * 36 / (37 - reps + 0.005 * reps**2)
return round(_un_rounded_result, 1)
one_rm = _one_rm()
def weight_max_reps(target_reps: float) -> float:
- _un_rounded_result = one_rm * (37 - target_reps) / 36
+ _un_rounded_result = one_rm * (37 - target_reps + 0.005 * target_reps**2) / 36
return round(_un_rounded_result, 1)
maxes = {n_reps: weight_max_reps(n_reps) for n_reps in common_n_reps}
def orm_dos_remedios(weight: float, reps: int) -> dict:
"""
Returns dict {n_reps: max_weight, ...}
- for n_reps: (1, 2, 3, 5, 6, 8, 10, 12, 15)
+ for n_reps: (1, 2, 3, 5, 6, 8, 10, 12, 15, 20)
Or an {"errMsg": "INVALID_RANGE", ...}
1: 1,
2: 0.92,
3: 0.9,
+ 4: 0.89, # NOTE: I added this
5: 0.87,
6: 0.82,
+ 7: 0.781, # NOTE: I added this
8: 0.75,
+ 9: 0.72375, # NOTE: I added this
10: 0.7,
+ 11: 0.674286, # NOTE: I added this
12: 0.65,
+ 13: 0.628571, # NOTE: I added this
+ 14: 0.611429, # NOTE: I added this
15: 0.6,
+ 16: 0.588, # NOTE: I added this
+ 17: 0.5775, # NOTE: I added this
+ 18: 0.568, # NOTE: I added this
+ 19: 0.559, # NOTE: I added this
+ 20: 0.55, # NOTE: I added this, 20 reps is NOT in the original equation.
}
def _one_rm() -> float:
_un_rounded_result = weight / _multiplier
return round(_un_rounded_result, 1)
- try:
- one_rm = _one_rm()
- except KeyError:
- # _logger.debug(traceback.format_exc())
- valid_reps = list(_common_n_reps.keys())
- return {
- "errMsg": "INVALID_RANGE — "
- + "requires: reps in %s, got %s" % (valid_reps, reps),
- }
+ # Compute the 1-rep max
+ one_rm = _one_rm()
def max_weight(target_reps: int) -> float:
+ """Used to calculate max weight based on actual reps, e.g. 5 or 12"""
_multiplier = _common_n_reps[target_reps]
_un_rounded_result = one_rm * _multiplier
return round(_un_rounded_result, 1)
+# -*- coding: utf-8 -*-
+"""
+Created on Mon Aug 8 14:35:43 2022
+
+@author: shane
+
+Allows the safe avoidance of ImportError on non-colorama capable systems.
+"""
+
+try:
+ from colorama import Fore, Style
+ from colorama import init as colorama_init
+
+ # Made it this far, so run the init function (which is needed on Windows)
+ colorama_init()
+
+ # Styles
+ STYLE_BRIGHT = Style.BRIGHT
+ STYLE_DIM = Style.DIM
+ STYLE_RESET_ALL = Style.RESET_ALL
+
+ # Colors
+ COLOR_WARN = Fore.YELLOW
+ COLOR_CRIT = Style.DIM + Fore.RED
+ COLOR_OVER = Style.DIM + Fore.MAGENTA
+
+ COLOR_DEFAULT = Fore.CYAN
+
+ # Used in macro bars
+ COLOR_YELLOW = Fore.YELLOW
+ COLOR_BLUE = Fore.BLUE
+ COLOR_RED = Fore.RED
+
+ # Used by `tree.py` utility
+ COLOR_GREEN = Fore.GREEN
+ COLOR_CYAN = Fore.CYAN
+
+except ImportError:
+ # These will all just be empty strings if colorama isn't installed
+
+ # Styles
+ STYLE_BRIGHT = str()
+ STYLE_DIM = str()
+ STYLE_RESET_ALL = str()
+
+ # Colors
+ COLOR_WARN = str()
+ COLOR_CRIT = str()
+ COLOR_OVER = str()
+
+ COLOR_DEFAULT = str()
+
+ COLOR_YELLOW = str()
+ COLOR_BLUE = str()
+ COLOR_RED = str()
+
+ COLOR_GREEN = str()
+ COLOR_CYAN = str()
import os
import sys
-try:
- from colorama import Fore, Style
- from colorama import init as colorama_init
-
- COLORAMA_CAPABLE = True
- colorama_init()
-except ImportError:
- COLORAMA_CAPABLE = False
+from ntclient.utils import colors
chars = {"nw": "\u2514", "nws": "\u251c", "ew": "\u2500", "ns": "\u2502"}
" ",
]
-if COLORAMA_CAPABLE:
- # Colors and termination strings
- COLOR_DIR = Style.BRIGHT + Fore.BLUE
- COLOR_EXEC = Style.BRIGHT + Fore.GREEN
- COLOR_LINK = Style.BRIGHT + Fore.CYAN
- COLOR_DEAD_LINK = Style.BRIGHT + Fore.RED
-else:
- COLOR_DIR = str()
- COLOR_EXEC = str()
- COLOR_LINK = str()
- COLOR_DEAD_LINK = str()
+# Colors and termination strings
+COLOR_DIR = colors.STYLE_BRIGHT + colors.COLOR_BLUE
+COLOR_EXEC = colors.STYLE_BRIGHT + colors.COLOR_GREEN
+COLOR_LINK = colors.STYLE_BRIGHT + colors.COLOR_CYAN
+COLOR_DEAD_LINK = colors.STYLE_BRIGHT + colors.COLOR_RED
def colorize(path: str, full: bool = False) -> str:
[
COLOR_LINK,
file,
- Style.RESET_ALL,
+ colors.STYLE_RESET_ALL,
" -> ",
colorize(os.readlink(path), full=True),
]
)
if os.path.isdir(path):
- return "".join([COLOR_DIR, file, Style.RESET_ALL])
+ return "".join([COLOR_DIR, file, colors.STYLE_RESET_ALL])
if os.access(path, os.X_OK):
- return "".join([COLOR_EXEC, file, Style.RESET_ALL])
+ return "".join([COLOR_EXEC, file, colors.STYLE_RESET_ALL])
return file
n_size = 0
if not pre:
- print(COLOR_DIR + _dir + Style.RESET_ALL)
+ print(COLOR_DIR + _dir + colors.STYLE_RESET_ALL)
dir_len = len(os.listdir(_dir)) - 1
for i, file in enumerate(sorted(os.listdir(_dir), key=str.lower)):
@pytest.mark.parametrize("_eq", ["epley", "brzycki", "dos_remedios"])
@pytest.mark.parametrize(
"weight,reps",
- [
- (50.0, 1),
- (50.0, 2),
- (50.0, 3),
- (50.0, 5),
- (50.0, 6),
- (50.0, 8),
- (50.0, 10),
- (50.0, 12),
- (50.0, 15),
- (50.0, 20),
- ],
+ [(50.0, x) for x in (1, 2, 3, 5, 6, 8, 10, 12, 15, 20)],
)
def test_000_orm_same_in_same_out(_eq: str, weight: float, reps: int) -> None:
"""Test one rep max: Epley"""
- if _eq == "epley":
- result = calc.orm_epley(weight, reps)
-
- elif _eq == "brzycki":
- result = calc.orm_brzycki(weight, reps)
-
- else: # _eq == "dos_remedios"
- result = calc.orm_dos_remedios(weight, reps)
-
- try:
- # Check results
- assert result[reps] == weight
- except KeyError:
- # dose Remedios does not work for 20 reps currently
- assert _eq == "dos_remedios"
- assert reps == 20
+ result = {
+ "epley": calc.orm_epley(weight, reps),
+ "brzycki": calc.orm_brzycki(weight, reps),
+ "dos_remedios": calc.orm_dos_remedios(weight, reps),
+ }
+
+ # Check results
+ assert result[_eq][reps] == weight
code, _ = args.func(args)
assert code == 0
- # Invalid range for dos_remedios (11 instead of 12)
- args = arg_parser.parse_args(args=["calc", "1rm", "225", "11"])
+ # Reps > 20 (or reps < 1)
+ args = arg_parser.parse_args(args=["calc", "1rm", "225", "25"])
code, result = args.func(args)
- assert code == 0
- assert set(result.keys()) == {"epley", "brzycki", "dos_remedios"}
- assert "errMsg" in result["dos_remedios"]
+ assert code == 1
+
+ # Weight < 0
+ args = arg_parser.parse_args(args=["calc", "1rm", "-10", "10"])
+ code, result = args.func(args)
+ assert code == 1
# BMR
# -----------------------------------