Advertisement
gruntfutuk

formula menu calculations

Mar 19th, 2023
895
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.73 KB | None | 0 0
  1. """ present menu of forumulas and calculate whatever user picks """
  2.  
  3. from math import pi
  4. from typing import NamedTuple
  5. import logging
  6.  
  7. # structure definitions
  8.  
  9. class Formula_arg(NamedTuple):
  10.     """ definition of an argument for a calculation function """
  11.     prompt: str  # what to ask user for on input
  12.     kind: int | float  # what data type should be accepted
  13.     keyword: str  # name to use in kwargs call to calculation function
  14.  
  15.  
  16. class Formula(NamedTuple):
  17.     """ definition of a calculation function arguments and function to call """
  18.     name: str  # friendly name for outputs/reports etc
  19.     args: tuple[Formula_arg]  # all the required arguments
  20.     func: object  # actual namespace identified of the function to call
  21.  
  22. def get_num(msg: str = 'Number? ', kind: float | int = int) -> float | int:
  23.     """ prompt user for numeric input and validate and return correct type, re-prompt if not valid """
  24.     valid = False
  25.     while not valid:
  26.         try:
  27.             number = kind(input(msg))
  28.         except ValueError:
  29.             print('That was not a valid input, please try again')
  30.         else:
  31.             valid = True
  32.     return number
  33.  
  34.  
  35. def get_args(formula: Formula) -> dict[str, int | float]:
  36.     """ obtain all user inputs for a particular function and return as kwargs ready dict """
  37.     kwargs = {}
  38.     for arg in formula.args:
  39.         kwargs[arg.keyword] = get_num(arg.prompt, arg.kind)
  40.     return kwargs
  41.  
  42. # calculation functions
  43.  
  44. def calc_k_factor(*, b_allowance: float, angle: float, thickness: float, radius: float) -> float:
  45.     return (180 * b_allowance) / (pi * angle * thickness) - (radius / thickness)
  46.  
  47.  
  48. def calc_bend_allowance(*, angle: float, thickness: float, k_factor: float, radius: float) -> float:
  49.     return angle * (pi / 180) * (radius + k_factor * thickness)
  50.  
  51. # menu operations
  52.  
  53. def pick_formula(formulas: dict[str, Formula]) -> Formula | None:
  54.     """ present menu of forumulas to pick from and return selected, or None to quit """
  55.  
  56.     # generate dictionary of options to present
  57.     options = {str(idx): name for idx, name in enumerate(formulas.keys(), start=1)}
  58.     options.update(EXIT_OPTION)
  59.  
  60.     # set up loop
  61.     valid = False  # exit condition
  62.     quit = False  # alternative exit condition, if user doesn't want to pick anything
  63.  
  64.     while not valid and not quit:
  65.         print(OPTION_MENU_HEADER)
  66.         for option, name in options.items():
  67.             print(f'\t{option:2}: {name}')
  68.         pick = input(OPTION_PICK_PROMPT).strip().casefold()
  69.  
  70.         if pick in EXIT_OPTION_KEYS:
  71.             quit = True
  72.             func = None
  73.             continue
  74.  
  75.         if pick in options.keys():
  76.             valid = True
  77.             func = formulas[options[pick]]
  78.             continue
  79.  
  80.         print('Unknown option, please pick again')
  81.  
  82.     return func
  83.  
  84.  
  85. # set up logging, set level to INFO or lower to see most output
  86. logging.basicConfig(level=logging.CRITICAL, format='** DEBUGGING ** %(message)s')
  87.  
  88. # define language specific options for menu and UI
  89. EXIT_OPTION = {'q': 'Quit'}  # could add addition options, and different languages
  90. EXIT_OPTION_KEYS = tuple(key.casefold() for key in EXIT_OPTION.keys())
  91. OPTION_MENU_HEADER = "Formulas to pick from:"
  92. OPTION_PICK_PROMPT = "Your pick? "
  93. FINI = "\n\nThank you. Goodbye.\n\n"
  94.  
  95. # define formulas to pick from
  96. formulas: dict[str, Formula] = {
  97.     'k_factor': Formula('k-factor',
  98.         (
  99.             Formula_arg('Angle? ', float, 'angle'),
  100.             Formula_arg('Radius? ', float, 'radius'),
  101.             Formula_arg('Bend Allowance? ', float, 'b_allowance'),
  102.             Formula_arg('Thickness? ', float, 'thickness')
  103.         ),
  104.         calc_k_factor
  105.     ),
  106.     'bend_allowance': Formula('Bend Allowance',
  107.         (
  108.             Formula_arg('Angle? ', float, 'angle'),
  109.             Formula_arg('Radius? ', float, 'radius'),
  110.             Formula_arg('K-Factor? ', float, 'k_factor'),
  111.             Formula_arg('Thickness? ', float, 'thickness')
  112.         ),
  113.         calc_bend_allowance
  114.     )
  115. }
  116.  
  117. """
  118. MAIN CODE
  119.  
  120. Repeatedly present menu of formula for user to choose from until they select quit
  121. For any selected, formula, get all inputs from user, apply the right calculation, output the result
  122. """
  123.  
  124.  
  125. def main() -> None:
  126.    
  127.     quit = False
  128.  
  129.     while not quit:
  130.    
  131.         forumula = pick_formula(formulas)
  132.         if forumula is None:
  133.             quit = True
  134.             continue
  135.    
  136.         kwargs = get_args(forumula)  # assuming argument definitions match actual function signature!
  137.         logging.info(f'Would call {forumula.name} with {kwargs} unpacked')
  138.         result = forumula.func(**kwargs)
  139.         print(f'\n\n{forumula.name} = {result}\n')
  140.  
  141.     print(FINI)
  142.    
  143. if __name__ == "__main__":
  144.     main()
  145.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement