Push Weight with Python

5 min read

Table of Contents:

Title Image for the Article

Introduction

Create a simple terminal application that can let you know how much weight you need to put on the barbell to get gains in the gym without doing the math.

Github @cobb208/weight-calculator

This is a refresh of a project that was originally created in TypeScript linked here: Push Weight With TypeScript

Creating projects in different languages can help you get an understanding of how languages and runtimes can accomplish the same goal. Python and JavaScript/TypeScript are different languages; however, they are able to do a lot of the same tasks. While langugages are built for certain tasks both of these languages have fallen into general programming languages. I recommend reading over both projects to see how they differ on running the same task.

Setup

You will need to have at least Python 3.10 installed on your computer for this to work.

Don't have Python? Install it here!

I would also recommend an Integrated Development Environment such as Visual Studio Code for ease of use.

Want Visual Studio Code? Install it here!

Now we will setup our project.

Folder Structure

Inside of a folder we will create three files.

  • main.py
  • barbellcalc.py
  • plateresult.py

PlateResult.py

The first file we will create is what we are using to store the result. We will use a class as an object so we can apply structure to the data.

class PlateResult:
    def __init__(self, weight: int, count: int) -> None:
        self.weight = weight
        self.count = count

    def __str__(self) -> str:
        return f"PlateResult: Weight:{self.weight} Count:{self.count}"

Self is a special word in Python that passes the "instance" of the class. It lets us target variables unique to each instance of the class. When we use the class to store information it creates its own version. Python uses self to say "hey use the data unique to us!"

The str dunder

"Dunder" methods are unique ways Python lets us customize our code. We use the str method to override Python's default behavior when we print the class. Without us changing this, whenever we wanted to print out the class it would just display the memory location of the class and other information that is not important to us for this.

def __str__(self) -> str:
    return f"PlateResult: Weight:{self.weight} Count:{self.count}

BarbellCalc.py

The next class we will create is what will solve our problem. The class will take in information from an external source and create the output we want to expect.

It will be given a weight the user wants on the barbell, and has an optional weight (it is defaulted to 45 for the standard weight of a barbell).

import math
import plateresult as p


class BarbellCalc:

    WEIGHT_VALUES = [45,35,25,15,10,5]

    def __init__(self, weight: int, barbellWeight = 45) -> None:
        self.weight = weight
        self.barbellWeight = barbellWeight
        self.barGoal = self.weight - self.barbellWeight

    def calculate(self):
        results = []

        for i in range(len(self.WEIGHT_VALUES)):
            count = math.floor(self.barGoal / (self.WEIGHT_VALUES[i] * 2))
            count *= 2
            results.append(p.PlateResult(self.WEIGHT_VALUES[i], count))

            self.barGoal -= self.WEIGHT_VALUES[i] * count

        self.printResults(results)

    def printResults(self, results: list):
        for i in range(len(results)):
            print(results[i])

The constant WEIGHT_VALUES holds default plate values that a gym should have. You can change these to fit what you would need.

The init function runs logic and creates a local variable to get what target weight we need to look at for the plates. The barGoal will be the amount we need to think about because it gets rid of the barbell's weight.

Calculate()

def calculate(self):
    results = []

    for i in range(len(self.WEIGHT_VALUES)):
        count = math.floor(self.barGoal / (self.WEIGHT_VALUES[i] * 2))
        count *= 2
        results.append(p.PlateResult(self.WEIGHT_VALUES[i], count))

        self.barGoal -= self.WEIGHT_VALUES[i] * count

    self.printResults(results)

We first create a results array/list that will hold the results of each calculation as a PlateResult.

It will itterate of the WEIGHT_VALUES and figure out how many times the highest weight can go in.

Then it multiples the count by 2, due to the weight needing to be on both sides of the bar.

We append the results by creating a new object that holds our data (the weight's value and how many of them) and then we substract how much we have accounted for.

Once the calculations are complete, we will print the results.

PrintResults()

def printResults(self, results: list):
    for i in range(len(results)):
        print(results[i])

This method was created to help ease of reading and to keep what the calculate's method is in tack. You can keep the code in the calculate function but this helps break it up.

The function will just itterate over the array/list of objects and output print it out. (This is where the str will modify Python's original output).

Main.py

Now that we have everything setup we will create a main function to run all the code for us.

We will recieve our data through command line arguements.

The first command line arguement that Python recieves is the filename so we will ignore it. We are asking for two inputs from the user; however, you will see throughout the main.py, we are looking for 2-3 arguements. The extra arguement makes us ask for one more!

from re import T
import sys

import barbellcalc as b


def mainLoop():
    n = len(sys.argv)
    errorSyntax = "Please enter your targeted weight, followed by the barbell weight, if it is a standard barbell you do not need to include the weight.
ex: main.py 255 65
ex2: main.py 365"

    if(n == 3):
        try:
            targetWeight = int(sys.argv[1])
            barbellWeight = int(sys.argv[2])
            if(barbellWeight):
                barbellCalc = b.BarbellCalc(targetWeight, barbellWeight)
            else:
                barbellCalc = b.BarbellCalc(targetWeight)

            barbellCalc.calculate()
        except:
            print(errorSyntax)
    elif(n == 2):
        try:
            targetWeight = int(sys.argv[1])
            print(f"target weight: {targetWeight}")
            barbellCalc = b.BarbellCalc(targetWeight).calculate()
        except:
            print(errorSyntax)
    else:
        print(errorSyntax)

if(__name__ == '__main__'):
    print(sys.argv)
    
    mainLoop()

Try-except

When we have an error in Python, well the majority of languages, if an error occurs we need to have a way to catch it. If we do not catch it the program will stop working and crash. We use the try-except in Python to ensure if we recieve an error that it is handled.

The error we are trying to stop is someone adding the correct arguments to the program. If they enter anything that is not a number they will receive the a warning message before the program stops.

Name and Main

These dunder methods let the program know, if you run this file, this the command we want to run. The main name is the initial entry point file that Python is using. All files in Python can be executed by the interpreter. If this project expanded and we outsourced the logic to another file this if statement would ensure that code would not run.

Conclusion

This project can help you create a little tool that can be implimeted into other projects or used by itself. Play around with it add it to another project! Stay tuned for more content!

Recent Articles

Push Weight with Python

Create a simple terminal application that can let you know how much weight you need to put on the ba...

Validate Forms in TypeScript

Relying on HTML to validate your forms is just one step in ensuring visitors enter their information...

Automation with NodeJS

NodeJS can help you automate simple tasks. Being a web developer you can achieve the same goals as o...

Automation with Python

Python can take boring tasks away from you so you can continue to do other things. It is a scripting...

Speed With Cache in WordPress

Most WordPress sites use Apache as their server. Apache has a lot of tools built into it to speed up...

Social Media