Пример #1
0
    def __init__(self, name, sets_reps='4 x 10'):
        """Initialize a new static exercise. A static exercise
        is simply a placeholder for some text.
    
        Parameters
        ----------
        name
            The name of the exercise, e.g. 'Curls'.
            
        sets_reps
            A static set/rep scheme, e.g. '4 x 10', or '10 minutes'.
            This paramter can also be a function of one parameter,
            the current week. The function must return a string
            for that specific week.


        Returns
        -------
        StaticExercise
            A StaticExercise object.
    
    
        Examples
        -------
        >>> curls = StaticExercise('Curls', '4 x 10')
        >>> stretching = StaticExercise('Stretching', '10 minutes')
        """
        self.name = escape_string(name)
        if isinstance(sets_reps, str):
            self.sets_reps = self._function_from_string(sets_reps)
        else:
            self.sets_reps = sets_reps

        # Escape after function evaluation
        self.sets_reps = compose(self.sets_reps, escape_string)
Пример #2
0
    def __init__(self, name=None, exercises=None):
        """Initialize a new day object.

        Parameters
        ----------
        name
            The name of the day, e.g. 'Day A'. If no name is given then the day
            will automatically be given a numeric name such as 'Day 1', 'Day 2', etc.

        exercises
            A list of exercises. Exercises can also be associated with a day using
            the 'add_exercises' method later on.


        Examples
        -------
        >>> monday = Day(name='Monday')
        >>> curls = StaticExercise('Curls', '3 x 12')
        >>> monday.add_exercises(curls)
        >>> curls in monday.static_exercises
        True
        """
        self.name = escape_string(name)
        self.dynamic_exercises = []
        self.static_exercises = []

        self.program = None

        if exercises is not None:
            self.add_exercises(*tuple(exercises))
Пример #3
0
    def __init__(self, name=None, exercises=None):
        """Initialize a new day object.

        Parameters
        ----------
        name
            The name of the day, e.g. 'Day A'. If no name is given then the day
            will automatically be given a numeric name such as 'Day 1', 'Day 2', etc.

        exercises
            A list of exercises. Exercises can also be associated with a day using
            the 'add_exercises' method later on.

        Returns
        -------
        Day
            A day object.


        Examples
        -------
        >>> monday = Day(name = 'Monday')
        >>> curls = StaticExercise('Curls', '3 x 12')
        >>> monday.add_exercises(curls)
        >>> curls in monday.static_exercises
        True
        """
        self.name = escape_string(name)
        self.dynamic_exercises = []
        self.static_exercises = []

        if exercises is not None:
            self.add_exercises(*tuple(exercises))
Пример #4
0
    def __init__(self, name, sets_reps="4 x 10"):
        """Initialize a new static exercise. A static exercise
        is simply a placeholder for some text.

        Parameters
        ----------
        name
            The name of the exercise, e.g. 'Curls'.

        sets_reps
            A static set/rep scheme, e.g. '4 x 10', or '10 minutes'.
            This paramter can also be a function of one parameter,
            the current week. The function must return a string
            for that specific week.


        Returns
        -------
        StaticExercise
            A StaticExercise object.


        Examples
        -------
        >>> curls = StaticExercise('Curls', '4 x 10')
        >>> stretching = StaticExercise('Stretching', '10 minutes')
        """
        self.name = escape_string(name)
        self.sets_reps = sets_reps
        if isinstance(sets_reps, str):
            self.sets_reps_func = self._function_from_string(sets_reps)
        else:
            self.sets_reps_func = sets_reps

        # Escape after function evaluation
        self.sets_reps_func = compose(self.sets_reps_func, escape_string)
Пример #5
0
    def __init__(
        self,
        name,
        start_weight=None,
        final_weight=None,
        min_reps=None,
        max_reps=None,
        percent_inc_per_week=None,
        reps=None,
        intensity=None,
        round_to=None,
        shift=0,
    ):
        """Initialize a new dynamic exercise. A dynamic exercise is rendered by
        the program, and the set/rep scheme will vary from week to week.

        Parameters
        ----------
        name
            The name of the exercise, e.g. 'Squats'.

        start_weight
            Maximum weight you can lift at the start of the program, e.g. 80.

        final_weight
            The goal weight to work towards during the program. This should be
            set in relation to the duration of the training program, e.g. 90.
            If set, this overrides the optional `percent_inc_per_week` parameter.

        min_reps
            The minimum number of repetitions for this exercise, e.g. 3.

        max_reps
            The maximum number of repetitions for this exercise, e.g. 8.

        percent_inc_per_week
            If `final_weight` is not set, this value will be used. The increase is
            additive, not multipliactive. For instance, if the increase is set to
            `percent_inc_per_week=2`, then after 2 weeks the increase is 4, not
            (1.02 * 1.02 - 1) * 100 = 4.04. The `final_weight` parameter must be
            set to `None` for this parameter to have effect.

        reps
            The number of baseline repetitions for this exercise. If this
            parameter is set, it will override the global 'reps_per_exercise'
            parameter for the training program. The repetitions will still
            be scaled by the `rep_scaler_func` parameter in the training program.

        intensity
            The average intensity for this exercise. If set, this will
            override the `intensity` parameter in the training program.
            The intensity will still be scaled by the `intensity_scaler_func`
            parameter.

        round_to
            Round the output to the closest multiple of this number, e.g. 2.5.

        shift
            Shift evaluation of repetitions, intensity and progress `shift`
            weeks ahead in time. An exercise shifted by 1 will have its reps,
            intensity and strength evalated at week i + 1 instead of in week i.


        Examples
        -------
        >>> bench = DynamicExercise('Bench press', 100, 120, 3, 8)
        >>> bench2 = DynamicExercise('Bench press', 100, 120, 3, 8)
        >>> bench == bench2
        True


        """
        self.name = escape_string(name)
        self.start_weight = start_weight
        self.final_weight = final_weight
        self._min_reps = min_reps
        self._max_reps = max_reps
        self.percent_inc_per_week = percent_inc_per_week
        self.reps = reps
        self.intensity = intensity
        self.day = None

        var_names = ["start_weight", "final_weight", "percent_inc_per_week"]
        num_specified = sum(1 if (getattr(self, var) is not None) else 0
                            for var in var_names)
        if num_specified == 3:
            raise ValueError(
                f"At most 2 out of 3 variables may be set: {var_names}")

        self.round_to = round_to

        assert isinstance(shift, int), "'shift' must be an integer"
        # assert shift >= 0, "'shift' must be non-negative"
        self.shift = shift

        if round_to is None:
            self.round = None
        else:
            self.round = functools.partial(round_to_nearest, nearest=round_to)

        if self.final_weight and self.start_weight:
            if self.start_weight > self.final_weight:
                msg = "'start_weight' larger than 'final_weight' for exercise '{}'."
                warnings.warn(msg.format(self.name))

        if self.min_reps and self.max_reps:
            if self.min_reps > self.max_reps:
                msg = "'min_reps' larger than 'max_reps' for exercise '{}'."
                raise ValueError(msg.format(self.name))
Пример #6
0
    def __init__(self, name, start_weight, final_weight, min_reps=3, max_reps=8,
                 reps=None, intensity=None, round_to=None):
        """Initialize a new dynamic exercise. A dynamic exercise is rendered by
        the program, and the set/rep scheme will vary from week to week.
    
        Parameters
        ----------
        name
            The name of the exercise, e.g. 'Squats'.
            
        start_weight
            Maximum weight you can lift at the start of the program, e.g. 80.
            
        final_weight
            The goal weight to work towards during the program. This should be
            set in relation to the duration of the training program, e.g. 90.
            
        min_reps
            The minimum number of repetitions for this exercise, e.g. 3.
            
        max_reps
            The maximum number of repetitions for this exercise, e.g. 8.
            
        reps
            The number of baseline repetitions for this exercise. If this
            parameter is set, it will override the global 'reps_per_exercise'
            parameter for the training program. The repetitions will still
            be scaled by the 'reps_scalers' parameter in the training program.
            
        intensity
            The average intensity for this exercise. If set, this will
            override the 'intensity' parameter in the training program.
            The intensity will still be scaled by the 'intensity_scalers'
            parameter.
            
        round_to
            Round the output to the closest multiple of this number, e.g. 2.5.
            
    
        Returns
        -------
        DynamicExercise
            A DynamicExercise object.
    
    
        Examples
        -------
        >>> bench = DynamicExercise('Bench press', 100, 120, 3, 8)
        """
        self.name = escape_string(name)
        self.start_weight = start_weight
        self.final_weight = final_weight
        self.min_reps = min_reps
        self.max_reps = max_reps
        self.reps = reps
        self.intensity = intensity

        if round_to is None:
            self.round = None
        else:
            self.round = functools.partial(round_to_nearest, nearest=round_to)

        if self.start_weight > self.final_weight:
            msg = "Start weight larger than end weight for exericse '{}'."
            warnings.warn(msg.format(self.name))

        if self.min_reps > self.max_reps:
            msg = "'min_reps' larger than 'max_reps' for exercise '{}'."
            raise ValueError(msg.format(self.name))
Пример #7
0
    def __init__(
        self,
        name: str = "Untitled",
        duration: int = 8,
        reps_per_exercise: int = 25,
        min_reps: int = 3,
        max_reps: int = 8,
        rep_scaler_func: typing.Callable[[int], float] = None,
        intensity: float = 83,
        intensity_scaler_func: typing.Callable[[int], float] = None,
        units: str = "kg",
        round_to: float = 2.5,
        percent_inc_per_week: float = 1.5,
        progression_func: typing.Callable = None,
        reps_to_intensity_func: typing.Callable[[int], float] = None,
        verbose: bool = False,
    ):
        """Initialize a new program.


        Parameters
        ----------
        name
            The name of the training program, e.g. 'TommyAugust2017'.

        duration
            The duration of the training program in weeks, e.g. 8.

        reps_per_exercise
            The baseline number of repetitions per dynamic exercise.
            Typically a value in the range [15, 30].

        min_reps
            The minimum number of repetitions for the exercises, e.g. 3.
            This value can be set globally for the program, or for a specific
            dynamic exercise. If set at the dynamic exercise level, it will
            override the global program value.

        max_reps
            The maximum number of repetitions for the exercises, e.g. 8.
            This value can be set globally for the program, or for a specific
            dynamic exercise. If set at the dynamic exercise level, it will
            override the global program value.

        rep_scaler_func
            A function mapping from a week in the range [1, `duration`] to a
            scaling value (factor). The scaling value will be multiplied with
            the `reps_per_exercise` parameter for that week. Should typically
            return factors between 0.7 and 1.3.
            Alternatively, a list of length `duration` may be passed.

        intensity
            The baseline intensity for each dynamic exercise. The intensity
            of an exercise for a given week is how heavy the average
            repetition is compared to the expected 1RM (max weight one can
            lift) for that given week. Typically a value around 80.

        intensity_scaler_func
            A function mapping from a week in the range [1, `duration`] to a
            scaling value (factor). The scaling value will be multiplied with
            the `intensity` parameter for that week.
            Should typically return factors between 0.9 and 1.1.
            Alternatively, a list of length `duration` may be passed.

        units
            The units used for exporting and printing the program, e.g. 'kg'.

        round_to
            Round the dynamic exercise to the nearest multiple of this
            parameter. Typically 2.5, 5 or 10.
            This value can be set globally for the program, or for a specific
            dynamic exercise. If set at the dynamic exercise level, it will
            override the global program value.

        percent_inc_per_week
            If `final_weight` is not set, this value will be used. Percentage
            increase per week can be set globally for the program, or for each
            dynamic exercise. If set at the dynamic exercise level, it will
            override the global program value. The increase is  additive, not
            multipliactive. For instance, if the increase is set to
            `percent_inc_per_week=2`, then after 2 weeks the increase is 4,
            not (1.02 * 1.02 - 1) * 100 = 4.04. The `final_weight` parameter
            must be set to `None` for this parameter to have effect.

        progression_func
            The function used to model overall 1RM progression in the
            training program. The function must have a signature like:
                func(week, start_weight, final_weight, start_week, end_week)

        reps_to_intensity_func
            The function used to model the relationship between repetitions
            and intensity. Maps from a repetition to an intensity in the range 0-100.

        verbose
            If True, information will be outputted as the program is created.


        Returns
        -------
        Program
            A Program instance.


        Examples
        -------
        >>> program = Program('My training program')
        >>> program._rendered
        False

        """
        self.name = escape_string(name)

        assert isinstance(duration, numbers.Integral) and duration > 1
        self.duration = duration

        assert isinstance(reps_per_exercise,
                          numbers.Integral) and reps_per_exercise > 0
        self.reps_per_exercise = reps_per_exercise

        assert isinstance(min_reps, numbers.Integral) and min_reps > 0
        assert isinstance(max_reps, numbers.Integral) and max_reps > 0
        self.min_reps = min_reps
        self.max_reps = max_reps
        if self.min_reps and self.max_reps:
            if self.min_reps > self.max_reps:
                raise ValueError("'min_reps' larger than 'max_reps'")

        assert isinstance(intensity, numbers.Number) and intensity > 0
        self.intensity = intensity

        assert isinstance(units, str)
        self.units = units
        self.round_to = round_to
        self.round = functools.partial(round_to_nearest, nearest=round_to)
        self.verbose = verbose

        # ------ REP SCALERS ------
        # Set functions to user supplied, or defaults if None was passed
        user, default = (
            rep_scaler_func,
            functools.partial(self._default_rep_scaler_func,
                              final_week=self.duration),
        )
        rep_scaler_func = prioritized_not_None(user, default)
        if callable(rep_scaler_func):
            self.rep_scalers = [
                rep_scaler_func(w + 1) for w in range(self.duration)
            ]
            self.rep_scaler_func = rep_scaler_func
        else:
            self.rep_scalers = list(rep_scaler_func)
        assert isinstance(self.rep_scalers, list)

        # ------ INTENSITY SCALERS------
        user, default = (
            intensity_scaler_func,
            functools.partial(self._default_intensity_scaler_func,
                              final_week=self.duration),
        )
        intensity_scaler_func = prioritized_not_None(user, default)
        if callable(intensity_scaler_func):
            self.intensity_scalers = [
                intensity_scaler_func(w + 1) for w in range(self.duration)
            ]
            self.intensity_scaler_func = intensity_scaler_func
        else:
            self.intensity_scalers = list(intensity_scaler_func)
        assert isinstance(self.intensity_scalers, list)

        user, default = progression_func, self._default_progression_func
        self.progression_func = prioritized_not_None(user, default)
        assert callable(self.progression_func)

        user, default = reps_to_intensity_func, self._default_reps_to_intensity_func
        self.reps_to_intensity_func = prioritized_not_None(user, default)
        assert callable(self.reps_to_intensity_func)

        # Setup variables that the user has no control over
        self.days = []
        self.active_day = None  # Used for Program.Day context manager API
        self._rendered = False
        self._set_jinja2_enviroment()

        assert isinstance(percent_inc_per_week, numbers.Number)
        self.percent_inc_per_week = percent_inc_per_week

        # TODO: make explicit
        self.optimizer = RepSchemeOptimizer()
Пример #8
0
    def __init__(self, name='Untitled', duration=8, reps_per_exercise=25,
                 rep_scalers=None, intensity=75, intensity_scalers=None,
                 units='kg', round_to=2.5, progress_func=None,
                 reps_to_intensity_func=None, min_reps_consistency=None,
                 minimum_percentile=0.2, go_to_min=False, verbose=False):

        """Initialize a new program.
    
        Parameters
        ----------
        name
            The name of the training program, e.g. 'TommyAugust2017'.

        duration
            The duration of the training program in weeks, e.g. 8.

        reps_per_exercise
            The baseline number of repetitions per dynamic exercise.
            Typically a value in the range [20, ..., 35].

        rep_scalers
            A list of factors of length 'duration', e.g. [1, 0.9, 1.1, ...].
            For each week, the baseline number of repetitions is multiplied
            by the corresponding factor, adding variation to the training
            program. Each factor is typically in the range [0.7, ..., 1.3].
            If None, a list of random factors is generated.

        intensity
            The baseline intensity for each dynamic exercise. The intensity
            of an exercise for a given week is how heavy the average
            repetition is compared to the expected 1RM (max weight one can
            lift) for that given week. Typically a value around 75.

        intensity_scalers
            A list of factors of length 'duration', e.g. [1, 0.95, 1.05, ...].
            For each week, the baseline intensity is multiplied by the
            corresponding factor, adding variation to the training
            program. Each factor is typically in the range [0.95, ..., 1.05].
            If None, a list of random factors is generated.

        units
            The units used for exporting and printing the program, e.g. 'kg'.

        round_to
            Round the dynamic exercise to the nearest multiple of this
            parameter. Typically 2.5, 5 or 10.

        progress_func
            The function used to model overall 1RM progression in the
            training program. If None, the program uses
            :py:meth:`streprogen.progression_sinusoidal`. Custom functions
            may be used, but they must implement arguments like the
            :py:meth:`streprogen.progression_sinusoidal` and
            :py:meth:`streprogen.progression_linear` functions.

        reps_to_intensity_func
            The function used to model the relationship between repetitions
            and intensity. If None, the program uses
            :py:meth:`streprogen.reps_to_intensity`.
            Custom functions may be used,
            and the functions
            :py:meth:`streprogen.reps_to_intensity_tight`
            and
            :py:meth:`streprogen.reps_to_intensity_relaxed`
            are available.

        min_reps_consistency
            This is an advanced feature.  By default, the program will
            examine the dynamic exercises and try to set a minimum
            repetition consistency mode. If all dynamic exercises in the
            program use the same repetition range, it will be set to
            'weekly'. If all dynamic exercises in each day use the same
            repetition range, it will be set to 'daily'.
            If neither, it will be set to 'exercise'.

            The minimum reps consistency mode tells the program how often
            it should draw a new random value for the minimum repetition
            to work up to. If 'min_reps_consistency' is 'weekly' and
            the 'go_to_min' parameter is set to True, you can expect that
            every exercise will work up to the same minimum number of
            repetitions.

            The 'min_reps_consistency' argument will override the program
            default. If, for example, every exercise is set to the
            repetition range 3-8 but you wish to work up to different
            minimum values, set 'min_reps_consistency' to 'daily' or
            'exercise'.

        minimum_percentile
            This is an advanced feature. To protect the athlete against
            often working up to heavy weights, the repetition range is
            "clipped" randomly. A repetition range 1-8 might be clipped
            to, say, 3-8, 2-8 or 1-8. If clipped to 3-8, the repetitions
            are drawn from [3, ..., 8] instead of [1, ..., 8].

            The 'minimum_percentile' determines the percentile of the
            repetition range to clip away. If 0, no clipping occurs.
            If 0.5, half the repetition range could potentially be clipped
            away. How often the range is clipped and a new minimum
            repetition value is computed is determined by the minimum
            repetition consistency mode, which may be controlled by the
            'minimum_percentile' argument.

        go_to_min
            This is an advanced feature.
            Whether or not to force the program to work up to the minimum
            repetition possible for a given dynamic exercise. Consider a
            program where 'minimum_percentile' is 0.2, and a dynamic exercise
            has a repetition range 1-8. The program will drawn repetitions
            in ranges 1-8, 2-8 or 3-8. If 'go_to_min' is True, the program
            will be forced to work up to 1, 2 or 3 repetitions respectively.
            If 'go_to_min' is False, the same range will be used, but the
            program need not go to the minimum number of repeitions.

        verbose
            If True, information will be outputted as the program is created.

    
        Returns
        -------
        Program
            A Program instance.
    
    
        Examples
        -------
        >>> program = Program('My training program')
        >>> program._rendered
        False
        """
        self.name = escape_string(name)
        self.duration = duration
        self.reps_per_exercise = reps_per_exercise
        self.intensity = intensity
        self.rep_scalers = rep_scalers
        self.intensity_scalers = intensity_scalers
        self.units = units
        self.round = functools.partial(round_to_nearest, nearest=round_to)
        self.min_reps_consistency = min_reps_consistency
        self.minimum_percentile = minimum_percentile
        self.go_to_min = go_to_min
        self.verbose = verbose
        user, default = progress_func, progression_sinusoidal
        self.progression_func = prioritized_not_None(user, default)

        user, default = reps_to_intensity_func, reps_to_intensity
        self.reps_to_intensity_func = prioritized_not_None(user, default)

        self.days = []
        self._rendered = False
        self._set_jinja2_enviroment()