Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """ present menu of forumulas and calculate whatever user picks """
- from math import pi
- from typing import NamedTuple
- import logging
- # structure definitions
- class Formula_arg(NamedTuple):
- """ definition of an argument for a calculation function """
- prompt: str # what to ask user for on input
- kind: int | float # what data type should be accepted
- keyword: str # name to use in kwargs call to calculation function
- class Formula(NamedTuple):
- """ definition of a calculation function arguments and function to call """
- name: str # friendly name for outputs/reports etc
- args: tuple[Formula_arg] # all the required arguments
- func: object # actual namespace identified of the function to call
- def get_num(msg: str = 'Number? ', kind: float | int = int) -> float | int:
- """ prompt user for numeric input and validate and return correct type, re-prompt if not valid """
- valid = False
- while not valid:
- try:
- number = kind(input(msg))
- except ValueError:
- print('That was not a valid input, please try again')
- else:
- valid = True
- return number
- def get_args(formula: Formula) -> dict[str, int | float]:
- """ obtain all user inputs for a particular function and return as kwargs ready dict """
- kwargs = {}
- for arg in formula.args:
- kwargs[arg.keyword] = get_num(arg.prompt, arg.kind)
- return kwargs
- # calculation functions
- def calc_k_factor(*, b_allowance: float, angle: float, thickness: float, radius: float) -> float:
- return (180 * b_allowance) / (pi * angle * thickness) - (radius / thickness)
- def calc_bend_allowance(*, angle: float, thickness: float, k_factor: float, radius: float) -> float:
- return angle * (pi / 180) * (radius + k_factor * thickness)
- # menu operations
- def pick_formula(formulas: dict[str, Formula]) -> Formula | None:
- """ present menu of forumulas to pick from and return selected, or None to quit """
- # generate dictionary of options to present
- options = {str(idx): name for idx, name in enumerate(formulas.keys(), start=1)}
- options.update(EXIT_OPTION)
- # set up loop
- valid = False # exit condition
- quit = False # alternative exit condition, if user doesn't want to pick anything
- while not valid and not quit:
- print(OPTION_MENU_HEADER)
- for option, name in options.items():
- print(f'\t{option:2}: {name}')
- pick = input(OPTION_PICK_PROMPT).strip().casefold()
- if pick in EXIT_OPTION_KEYS:
- quit = True
- func = None
- continue
- if pick in options.keys():
- valid = True
- func = formulas[options[pick]]
- continue
- print('Unknown option, please pick again')
- return func
- # set up logging, set level to INFO or lower to see most output
- logging.basicConfig(level=logging.CRITICAL, format='** DEBUGGING ** %(message)s')
- # define language specific options for menu and UI
- EXIT_OPTION = {'q': 'Quit'} # could add addition options, and different languages
- EXIT_OPTION_KEYS = tuple(key.casefold() for key in EXIT_OPTION.keys())
- OPTION_MENU_HEADER = "Formulas to pick from:"
- OPTION_PICK_PROMPT = "Your pick? "
- FINI = "\n\nThank you. Goodbye.\n\n"
- # define formulas to pick from
- formulas: dict[str, Formula] = {
- 'k_factor': Formula('k-factor',
- (
- Formula_arg('Angle? ', float, 'angle'),
- Formula_arg('Radius? ', float, 'radius'),
- Formula_arg('Bend Allowance? ', float, 'b_allowance'),
- Formula_arg('Thickness? ', float, 'thickness')
- ),
- calc_k_factor
- ),
- 'bend_allowance': Formula('Bend Allowance',
- (
- Formula_arg('Angle? ', float, 'angle'),
- Formula_arg('Radius? ', float, 'radius'),
- Formula_arg('K-Factor? ', float, 'k_factor'),
- Formula_arg('Thickness? ', float, 'thickness')
- ),
- calc_bend_allowance
- )
- }
- """
- MAIN CODE
- Repeatedly present menu of formula for user to choose from until they select quit
- For any selected, formula, get all inputs from user, apply the right calculation, output the result
- """
- def main() -> None:
- quit = False
- while not quit:
- forumula = pick_formula(formulas)
- if forumula is None:
- quit = True
- continue
- kwargs = get_args(forumula) # assuming argument definitions match actual function signature!
- logging.info(f'Would call {forumula.name} with {kwargs} unpacked')
- result = forumula.func(**kwargs)
- print(f'\n\n{forumula.name} = {result}\n')
- print(FINI)
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement