SPPTDPC (program that calculates the relative processing power and power usage of a computer based on the specs)

I'm super new to python and programming in general. I made this using my computer knowledge to calculate the processing power and power draw of a computer based on the specifications of all the parts.

from termcolor import colored
#COLORS:
#Magenta - welcome/version/credits
#Cyan - questions
#Yellow - scores
#Red - errors
#orange - might use this color later
def start():
global type
print(colored("* Welcome to Spicy's Processing Power / TDP Calculator! (SPPTDPC) *", "magenta"))
print(colored("* Version Alpha 2.2 *", "magenta"))
print(colored("** This program is still in alpha stage and isn't perfect **", "magenta"))
print(colored("If you are unsure about one of the questions, look up the specs of the part on a website like PCPartPicker or TechPowerUP", "magenta"))
type = float(input(colored("Is your computer a laptop or desktop? 1 for laptop, 2 for desktop.", "cyan")))
cpu()
def cpu():
global r
global cpus
global cputdp
name = input(colored("What is the name of your processor?", "cyan"))
c = float(input(colored("How many cores does the "+name+" have?", "cyan")))
t = float(input(colored("How many threads does the "+name+" have?", "cyan")))
l1 = float(input(colored("How much L1 cache (in total) does the "+name+" have in KB?", "cyan")))
l2 = float(input(colored("How much L2 cache (in total) does the "+name+" have in MB?", "cyan")))
l3 = float(input(colored("How much L3 cache (in total) does the "+name+" have in MB?", "cyan")))
g = float(input(colored("What is the clock speed (in GHz) of the "+name+"?", "cyan")))
n = float(input(colored("What is the fabrication process of the "+name+" in nm?", "cyan")))
r = float(input(colored("What type of RAM does the "+name+" use? Enter 3 for DDR3, 4 for DDR4, etc.", "cyan")))
cputdp = float(input(colored("What is the TDP of the "+name+"? (in W)", "cyan")))
cpus = ((c+t+g+r+l2+(l1/100)+(.3*l3))/n)*type #CPU Processing Power Formula
print(colored("** The "+name+" has a score of "+str(cpus)+". **", "yellow"))
ram()
def ram():
global rtdp
global rams
g = float(input(colored("How much RAM does your system have (in GB?)", "cyan")))
m = float(input(colored("What is the speed of your slowest installed DIMM? (in MHz)", "cyan")))
rtdp = float(input(colored("How many DIMMs do you have installed?", "cyan")))
rtdp = rtdp*4
rams = ((r+(m/500))*g)/150 #RAM Processing Power Formula
print(colored("** Your RAM score is "+str(rams)+". **", "yellow"))
gpu()
def gpu():
gputest()
print(colored("** The "+gpuname+" has a score of "+str(gpus)+". **", "yellow"))
gputdp = float(input(colored("What is the TDP of the "+gpuname+"?", "cyan")))
def gputest():
global gpuname
global memtyp
global gputdp
gpuname = input(colored("What is the name of your GPU?", "cyan"))
memtyp = int(input(colored("What type of memory does your GPU use? 0 for GDDR, 1 for HBM", "cyan")))
gputdp = float(input(colored("What is the TDP of your GPU? (in W)", "cyan")))
if memtyp == 0:
gddr()
if memtyp == 1:
hbm()
def gddr():
global gpus
gc = float(input(colored("How many cores does the "+gpuname+" have?", "cyan")))
gt = float(input(colored("How many TMUs does the "+gpuname+" have?", "cyan")))
go = float(input(colored("How many ROPs does the "+gpuname+" have?", "cyan")))
gm = float(input(colored("How much memory (in MB) does the "+gpuname+" have?", "cyan")))
gr = float(input(colored("What type of memory does the "+gpuname+" have? Enter 3 for GDDR3, 5 for GDDR5, and 8 for GDDR5X (to account for its additional data rate)", "cyan")))
gb = float(input(colored("What is the bus width of the "+gpuname+"?", "cyan")))
gg = float(input(colored("What is the clock speed of the "+gpuname+" in GHz?", "cyan")))
gmg = float(input(colored("What is the effective memory speed of the "+gpuname+" in MHz?", "cyan")))
gn = float(input(colored("What is the fabrication process of the "+gpuname+" in nm?", "cyan")))
gpus = ((((gc/400)+(gt/25)+(go/10)+(gm/1000)+(gb/30)+(gg*2)+(gmg/1000))*((gr/gn)/25)))*type #GDDR GPU Processing Power Formula
drive()
def hbm():
global gpus
hgc = float(input(colored("How many cores does the "+gpuname+" have?", "cyan")))
hgt = float(input(colored("How many TMUs does the "+gpuname+" have?", "cyan")))
hgo = float(input(colored("How many ROPs does the "+gpuname+" have?", "cyan")))
hgm = float(input(colored("How much memory (in MB) does the "+gpuname+" have?", "cyan")))
hgr = float(input(colored("What type of HBM does the "+gpuname+" have? Enter 1 for HBM, 2 for HBM2, etc.", "cyan")))
hgb = float(input(colored("What is the bus width of the "+gpuname+"?", "cyan")))
hgg = float(input(colored("What is the clock speed of the "+gpuname+" in GHz?", "cyan")))
hgmg = float(input(colored("What is the effective memory speed of the "+gpuname+" in MHz?", "cyan")))
hgn = float(input(colored("What is the fabrication process of the "+gpuname+" in nm?", "cyan")))
gpus = (((hgc/400)+(hgt/25)+(hgo/10)+(hgm/1000)+(hgb/250)+(hgg*2)+(hgmg/150))/((hgr/hgn)/25))*type #HBM GPU Processing Power Formula
drive()
def drive():
print(colored("** The "+gpuname+" has a score of "+str(gpus)+". **", "yellow"))
global typ
typ = float(input(colored("Is your boot drive an HDD or SSD? Enter 1 for HDD, 2 for SSD.", "cyan")))
if typ == 1:
hdd()
if typ == 2:
ssd()
def hdd():
global free
global total
global hds
rpm = float(input(colored("What is the RPM of your HDD?", "cyan")))
free = float(input(colored("How much storage is available (not filled) on your boot drive (in GB)", "cyan")))
total = float(input(colored("What is the total amount of storage on your boot drive (in GB)", "cyan")))
freespace()
hds = (((1/p)*100)*(rpm/1000))/30 #HDD Processing Power Formula
drivetdp()
def ssd():
global free
global total
global hds
free = float(input(colored("How much storage is available (not filled) on your boot drive (in GB)", "cyan")))
total = float(input(colored("What is the total amount of storage on your boot drive (in GB)", "cyan")))
freespace()
hds = ((((1/p)*100)*5)*typ)/30 #SSD Processing Power Formula
drivetdp()
def freespace():
global p
p = (free/total)*100
print(colored("* Your boot drive is "+str(p)+"% free. *", "yellow"))
def drivetdp():
global ssdtdp
global hddtdp
ssdtdp = float(input(colored("How many SSDs do you have installed in your system?", "cyan")))
ssdtdp = ssdtdp*3.25
hddtdp = float(input(colored("How many HDDs do you have installed in your system?", "cyan")))
hddtdp = hddtdp*8
print(colored("** Your boot drive's score is "+str(hds)+". **", "yellow"))
final()
def final():
global fns
global tdp
global psu
global fantdp
fns = (cpus+gpus+hds+rams) #Final Score Formula
dvdtdp = float(input(colored("How many optical drives do you have installed?", "cyan")))
dvdtdp = dvdtdp*10*type #1 ODD draws around 20 watts, I'm assuming laptop ODDs use half of that.
if type == 2:
fantdp = float(input(colored("How many case fans do you have installed? (counting CPU cooler)", "cyan")))
fantdp = fantdp*5 #1 120mm fan draws around 5 watts
if type == 1:
fantdp = 0
usbtdp = float(input(colored("How many USB ports does your computer have? (in total)", "cyan")))
usbtdp = usbtdp*2.5 #USB can only pull 2.5 watts
tdp = (((cputdp+gputdp)*(4/5))+rtdp+hddtdp+ssdtdp+dvdtdp+fantdp+usbtdp)+50 #estimated max load TDP equation, the +50 watts is for the motherboard
psu = cputdp+gputdp+rtdp+hddtdp+ssdtdp+dvdtdp+usbtdp+50 #max spec TDP equation
print(colored("Calculating final score...", "magenta"))
print(colored("** Your final score is... **", "yellow"))
print(str(fns))
print(str(tdp)+" Watts")
print(colored("** I would recommend using a power supply of at least "+str(psu)+" watts. **", "yellow"))
print(colored("Thank you for using SPPC!", "magenta"))
again()
def again():
again = input(colored("Do you want to use the calculator again? Y/N", "cyan"))
if again == "Y":
start()
start()

Welcome to CodeReview! I think that separation by colors looks very nice :)

Now, I suggest to take a look at PEP 8 style guide and try to follow it. Some text editors and IDEs even have support of highlighting the places where you violate it. They make life much easier.
Some points from there that you could apply to your code:

• Surround top-level function and class definitions with two blank lines.

• Use 4 spaces per indentation level.

• Limit all lines to a maximum of 79 characters.

• Inline comments should be separated by at least two spaces from the statement. They should start with a # and a single space.

• Add whitespaces around operators and after commas, for example:

Wrap start() line in the following construct:

if __name__ == '__main__':
start()

For explanations I suggest to read here.

Instead of using globals learn how to pass parameters to functions. For example, your cpu function could accept variable type like this:

def start():
...
type = float(input(colored("Is your computer a laptop or desktop? 1 for laptop, 2 for desktop.", "cyan")))
cpu(type)

def cpu(type):
...

Give better names to your variables, not one-letter names. For example:

g -> clock_speed
r -> ram_type
etc...

Note that type is a name of a built-in function. You are shadowing it.

Also, some variable names in your code are for different things, like g. In one place it's amount of RAM, in another it's a clock speed. Give different names for them.

If you are with Python 3.6 then you can use f-strings. For example, instead of your

"How many cores does the " + name + " have?"

you could write:

f"How many cores does the {name} have?"

Looks pretty.

You could use partial to reduce amount of code when printing colored output. For example:

from functools import partial

magenta = partial(colored,
color='magenta')
...
print(magenta("* Version Alpha 2.2 *"))

As it says by the link above: it just makes new version of a function colored with an argument color already filled in.

Finally, one of the most important things. Now your program runs in a following manner:

def start():
function_1()

def function_1():
function_2()

def function_2():
function_3()

...

if __name__ == '__main__':
start()

You are making a long chain of functions calling one another. Read When, if ever, should I daisy chain functions? for explanations about why it is bad and what you should do instead.

Probably there is more, I didn't go too much into details. But this should be enough for now. Happy coding! :)

Edit:

In the comment you said that you don't see the point of a lot of the things that I mentioned in my answer. I will try to give explanations to some of them and show you your code after refactoring (after applying all the points).

• Style guides. This is absolutely voluntary part. You are not obliged to follow them. But I think that it is very nice when you look at other person's code and it looks like it is something that you could write yourself as it looks very similar. Many of the points aren't taken out from thin air. For example, if you'd limit the lines up to 79 characters then we wouldn't need to scroll your code horizontally.

• if __name__ == '__main__'. If you don't use it then if someone wants to import a module with your code, your code will start to be executed automatically on import. Usually we don't want that. I will show how to use this in the refactored code.

• Self-explanatory names. Always think that you are writing code for other people. And other people will have no idea what you meant by hgmg or r. I had to look at input messages to understand what you meant by them.

• Global variables. Long time ago I also thought that there was nothing bad about them until I had to start working with the code where there were hundreds of them... That was pain... Everything could be accessed from anywhere. Whenever I had a problem I had a long process of tracking how and where exactly value for a variable was assigned. And it was always a relief when the problem was with a function that didn't have any global variables inside, it just accepted some parameters and returned a value. If it's not clear for you now then it will become clear later :)

Now refactored code based on the 2nd version that you inserted by edit (shouldn't have done that by the way). Also, note that I didn't fix everything here there is still some work left for you to do ;)

from functools import partial

from termcolor import colored

magenta = partial(colored,
color='magenta')
cyan = partial(colored,
color='cyan')
yellow = partial(colored,
color='yellow')

def run():
pc_type = start()
cpu_tdp, ram_type, cpu_score = cpu(pc_type)
ram_score, ram_tdp = ram(ram_type)
gputdp, gpu_score = gpu(pc_type)
drive_score, drive_type = drive()
hddtdp, ssdtdp = drivetdp(drive_score)
total_tdp = final(pc_type=pc_type,
cpu_score=cpu_score,
cpu_tdp=cpu_tdp,
drive_score=drive_score,
gpu_score=gpu_score,
gputdp=gputdp,
hddtdp=hddtdp,
ram_score=ram_score,
ram_tdp=ram_tdp,
ssdtdp=ssdtdp)
btlcalc1(pc_type=pc_type,
cpu_score=cpu_score,
drive_score=drive_score,
drive_type=drive_type,
gpu_score=gpu_score,
ram_score=ram_score)
hrscalc(total_tdp=total_tdp)
again()
thanks()

def start():
print(colored("'." * 70,
color='white',
print(magenta("* Welcome to Spicy's  Ultimate Computer Utility *"))
print(magenta("* Version Alpha 3.0 *"))
print(magenta("** This program is still in alpha stage "
"and isn't perfect **"))
print(magenta("If you are unsure about one of the questions, "
"look up the specs of the part on a website "
"like PCPartPicker or TechPowerUP"))
print(magenta("** Make sure to pay attention to the units "
"specified in the questions. **"))
return float(input(cyan("Is your computer a laptop or desktop? "
"1 for laptop, 2 for desktop.")))

def cpu(pc_type):
name = input(cyan("What is the name of your processor?"))
tdp = float(input(cyan(f"What is the TDP of the {name}? (in W)")))
cores_count = float(input(cyan(f"How many cores does the {name} have?")))
f"does the {name} have?")))
l1_cache = float(input(cyan(f"How much L1 cache (in total) "
f"does the {name} have in KB?")))
l2_cache = float(input(cyan(f"How much L2 cache (in total) "
f"does the {name} have in MB?")))
l3_cache = float(input(cyan(f"How much L3 cache (in total) "
f"does the {name} have in MB?")))
clock_speed = float(input(cyan(f"What is the clock speed (in GHz) "
f"of the {name}?")))
fabrication = float(input(cyan(f"What is the fabrication process "
f"of the {name} in nm?")))
ram_type = float(input(cyan(f"What type of RAM does the {name} use? "
f"Enter 3 for DDR3, 4 for DDR4, etc.")))
score = ((cores_count + threads_count + clock_speed + ram_type + l2_cache
+ (l1_cache / 100) + (.3 * l3_cache))
/ fabrication) * pc_type
print(yellow(f"** The {name} has a score of {round(score, 5)}. **"))
return tdp, ram_type, score

def ram(ram_type):
amount = float(input(cyan("How much RAM does your system have "
"(in GB?)")))
slowest_dimm_speed = float(input(cyan("What is the speed of your slowest "
"installed DIMM? (in MHz)")))
dimms_count = (float(input(cyan("How many DIMMs do you have installed?")))
* 4)
score = ((ram_type + (slowest_dimm_speed / 500)) * amount) / 150
print(yellow(f"** Your RAM score is {round(score, 5)} . **"))
return score, dimms_count

def gpu(pc_type):
name = input(cyan("What is the name of your GPU?"))
memory_type = int(input(cyan(f"What type of memory does the {name} use? "
f"0 for GDDR, 1 for HBM")))
tdp = float(input(cyan(f"What is the TDP of the {name}? (in W)")))

if memory_type == 0:
cores_count = float(input(cyan(f"How many cores "
f"does the {name} have?")))
tmus_count = float(input(cyan(f"How many TMUs "
f"does the {name} have?")))
rops_count = float(input(cyan(f"How many ROPs "
f"does the {name} have?")))
memory_size = float(input(cyan(f"How much memory (in MB) "
f"does the {name} have?")))
memory_type = float(input(cyan(f"What type of memory "
f"does the {name} have? "
f"Enter 3 for GDDR3, 5 for GDDR5, "
f"and 8 for GDDR5X.")))
# GDDR5X is 8 to account for its additional data rate
bus_width = float(input(cyan(f"What is the bus width "
f"of the {name}?")))
clock_speed = float(input(cyan(f"What is the clock speed "
f"of the {name} in GHz?")))
memory_speed = float(input(cyan(f"What is the effective memory speed "
f"of the {name} in MHz?")))
fabrication = float(input(cyan(f"What is the fabrication process "
f"of the {name} in nm?")))
score = ((((cores_count / 400) + (tmus_count / 25) + (rops_count / 10)
+ (memory_size / 1000) + (bus_width / 30)
+ (clock_speed * 2) + (memory_speed / 1000))
* ((memory_type / fabrication) / 25))) * pc_type

if memory_type == 1:
cores_count = float(input(cyan(f"How many cores "
f"does the {name} have?")))
tmus_count = float(input(cyan(f"How many TMUs "
f"does the {name} have?")))
rops_count = float(input(cyan(f"How many ROPs "
f"does the {name} have?")))
memory_size = float(input(cyan(f"How much memory (in MB) "
f"does the {name} have?")))
memory_type = float(input(cyan(f"What type of memory "
f"does the {name} have? "
f"Enter 1 for HBM, 2 for HBM2, etc.")))
# GDDR5X is 8 to account for its additional data rate
bus_width = float(input(cyan(f"What is the bus width "
f"of the {name}?")))
clock_speed = float(input(cyan(f"What is the clock speed "
f"of the {name} in GHz?")))
memory_speed = float(input(cyan(f"What is the effective memory speed "
f"of the {name} in MHz?")))
fabrication = float(input(cyan(f"What is the fabrication process "
f"of the {name} in nm?")))
score = (((cores_count / 400) + (tmus_count / 25) + (rops_count / 10)
+ (memory_size / 1000) + (bus_width / 250)
+ (clock_speed * 2) + (memory_speed / 150))
/ ((memory_type / fabrication) / 25)) * pc_type
print(yellow(f"** The {name} has a score of {round(score, 5)} . **"))

return tdp, score

def drive():
drive_type = float(input(cyan("Is your boot drive an HDD or SSD? "
"Enter 1 for HDD, 2 for SSD.")))
if drive_type == 1:
hdd_rpm = float(input(cyan("What is the RPM of your HDD?")))
drive_free = float(input(cyan("How much storage is available "
"(not filled) on your boot drive "
"(in GB)")))
drive_total = float(input(cyan("What is the total amount of storage "
"on your boot drive (in GB)")))
percent_free = (drive_free / drive_total) * 100
print(yellow(f"* Your boot drive is "
f"{round(percent_free, 3)} % free. *"))
drive_score = (((1 / percent_free) * 100) * (hdd_rpm / 1000)) / 30
if drive_type == 2:
drive_free = float(input(cyan(f"How much storage is available "
f"(not filled) on your boot drive "
f"(in GB)")))
drive_total = float(input(cyan("What is the total amount of storage "
"on your boot drive (in GB)")))
percent_free = (drive_free / drive_total) * 100
print(yellow(f"* Your boot drive is "
f"{round(percent_free, 3)} % free. *"))
drive_score = ((((1 / percent_free) * 100) * 5) * drive_type) / 30

return drive_score, drive_type

def drivetdp(drive_score):
ssdtdp = float(input(cyan("How many SSDs do you have "
ssdtdp *= 3.25  # 1 SSD draws this much watts
hddtdp = float(input(cyan(f"How many HDDs do you have "
hddtdp *= 8  # 1 HDD draws this much watts
print(colored(f"** Your boot drive's score is "
f"{round(drive_score, 5)} . **"))
return hddtdp, ssdtdp

def final(pc_type,
cpu_score,
gpu_score,
drive_score,
ram_score,
cpu_tdp,
gputdp,
ram_tdp,
hddtdp,
ssdtdp):
final_score = (cpu_score + gpu_score + drive_score + ram_score)
dvdtdp = float(input(cyan("How many optical drives "
"do you have installed?")))
# 1 ODD draws around 20 watts, I'm assuming laptop ODDs use half of that.
dvdtdp = dvdtdp * 10 * pc_type

if pc_type == 2:
fantdp = float(input(cyan("How many case fans do you have installed? "
"(counting CPU cooler)")))
fantdp *= 5  # 1 120mm fan draws around 5 watts
if pc_type == 1:
fantdp = 0

usbtdp = float(input(cyan("How many USB ports does your computer have? "
"(in total)")))
usbtdp *= 2.5  # USB can only pull 2.5 watts
# Estimated max load TDP equation, the +50 watts is for the motherboard
total_tdp = (((cpu_tdp + gputdp) * (4 / 5)) + ram_tdp + hddtdp + ssdtdp
+ dvdtdp + fantdp + usbtdp) + 50
# max spec TDP equation
recommended_psu = (cpu_tdp + gputdp + ram_tdp + hddtdp + ssdtdp + dvdtdp
+ usbtdp + 75)
print(magenta("Calculating final score..."))
print(yellow("** Your final score is... **"))
print(round(final_score, 5))
print(f"{round(total_tdp, 1)} Watts")
print(yellow(f"** I would recommend using a power supply of at least "
f"{int(round(recommended_psu, -1))} watts. **"))

def hrscalc(total_tdp):
hrscalc = input(cyan("Would you also like to factor in "
if hrscalc == "Y":
hrs = float(input(cyan("On average, how many hours do you use "
price = float(input(cyan("What is the price per kWh "
"where you live? (in dollars)")))
ktdp = total_tdp / 1000  # TDP in kW
dailycost = hrs * price * ktdp
hourcost = dailycost / 24
weeklycost = dailycost * 7
monthlycost = dailycost * 30.42
yearlycost = dailycost * 365
print(yellow(f"Your cost is ${round(hourcost, 2)} per hour, " f"${round(dailycost, 2)} per day, "
f"${round(weeklycost, 2)} per week, " f"${round(monthlycost, 2)} per month, "
f"and ${round(yearlycost, 2)} per year.")) def btlcalc1(pc_type, gpu_score, ram_score, drive_score, cpu_score, drive_type): print(yellow("Calculating bottleneck...")) if pc_type == 1: # laptop bgpus = gpu_score * 3.5 brams = ram_score * 4 bhds = drive_score * 5 bcpus = cpu_score * 2 if pc_type == 2: # desktop btlscore = ((gpu_score * 1.75) + (ram_score * 4) + (drive_score * 5) + (cpu_score * 2)) bgpus = gpu_score * 1.75 brams = ram_score * 4 bhds = drive_score * 5 bcpus = cpu_score if bgpus <= brams and bgpus <= bhds and bgpus <= bcpus: gpub = 1 cpub = 0 ramb = 0 hdb = 0 if bcpus <= brams and bcpus <= bhds and bcpus <= bgpus: gpub = 0 cpub = 1 ramb = 0 hdb = 0 if brams <= bcpus and brams <= bhds and brams <= bgpus: gpub = 0 cpub = 0 ramb = 1 hdb = 0 if bhds <= brams and bhds <= bcpus and bhds <= bgpus: gpub = 0 cpub = 0 ramb = 0 hdb = 1 if gpub == 1: print(yellow("Your GPU is the bottleneck in your system.")) print(yellow("You could improve your GPU score " "by overclocking or replacing your GPU.")) if cpub == 1: print(yellow("Your CPU is the bottleneck in your system.")) print(yellow("You could improve your CPU score " "by overclocking or replacing your CPU.")) if ramb == 1: print(yellow("Your RAM is the bottleneck in your system.")) print(yellow("You could improve your RAM score " "by overclocking, replacing, " "or installing more or faster RAM.")) if hdb == 1: print(yellow("Your boot disk is the bottleneck in your system.")) if drive_type == 1: print(yellow("You could improve your boot disk score " "by replacing your HDD with a faster HDD or an SSD, " "or by freeing up space.")) if drive_type == 2: print(yellow("You could improve your boot disk score " "by freeing up space.")) def thanks(): print(magenta("Thank you for using SPPC!")) print(colored("Copyright NFR 2018", color='green')) def again(): again = input(cyan("Do you want to use the calculator again? Y/N")) if again == 'Y': start() if __name__ == '__main__': run() Some other notes that came to mind after refactoring: 1. Python has augmented assignments. It means that instead of writing a = a * b you can write a *= b. 2. You don't need to convert numbers to strings when printing them. 3. btlscore is never used. 4. Function hrscalc has a variable with the same name in it. Why not name this function like calculate_energy_cost? Why not give more explanatory names to other functions as well? 5. again() now won't work as intended. Now as you eliminated that daisy-chaining, you will have to think of other way to repeat all the steps if user wants it. How about while-loop? 6. Now you are checking for positive answer if it is 'Y'. What if I type 'y'? What if I misclicked and typed something else? 7. You can see that in the refactored code I renamed some variables. For example, in function cpu all your variables were named like cpu_speed. But it is clear that this speed is of a cpu. So name it just speed. 8. You have many magic numbers in your code. You can make them constants or default function arguments. 9. You have some blocks of code that have many repetitions. You should fix that :) • The last point, I think, is the most important. The program is using functions as if they were goto labels, and that is absolutely inappropriate. Feb 19 '18 at 21:10 • See my newest edit, I addressed some of these concerns. However, I personally don't see the point of a lot of these things you want me to change. I still have NO IDEA how not to use globals or why they are bad, and I haven't figured out how to do the if main == name thing either. All the things you told me seem to be structural/formatting things that have little to no impact on the program itself. I'm only in high school and almost all the links you sent are beyond my years. I appreciate your input but frankly your suggestions seem to be a lot of work involved with little to no reward. Feb 22 '18 at 3:38 • @Spicy Please, see my edit. Feb 23 '18 at 20:28 • @Georgy Thanks for the detailed explanation, I appreciate it. I think there is some ways I can shorten the code and remove the need for magic numbers and solve some the other issues. And I think I'm beginning to understand how not to use globals. I really appreciate what you've done for the program and I'll work on it some more once school projects cool down a bit and I have more time. Is it fine if I put you in the credits? Feb 25 '18 at 18:34 • Oh, there is no need for that. I am just glad to be of some help :) Good luck with school projects! Feb 25 '18 at 18:55 Version Alpha 3.4 of the program is now out. Not sure what other features/improvements I could add to it. If anyone has suggestions please let me know. The main added feature in this update is the removal of magic numbers and removing unnecessary bits from the code, along with improving function names. Also special thanks to Georgy for help with pretty much the whole thing. from functools import partial from termcolor import colored magenta = partial(colored, color='magenta') cyan = partial(colored, color='cyan') yellow = partial(colored, color='yellow') def run(): pc_type = start() cpu_tdp, ram_type, cpu_score = cpu(pc_type) ram_score, ram_tdp = ram(ram_type) gputdp, gpu_score = gpu(pc_type) drive_score, drive_type = drive1() hddtdp, ssdtdp = drive2(drive_score) total_tdp = final(pc_type=pc_type, cpu_score=cpu_score, cpu_tdp=cpu_tdp, drive_score=drive_score, gpu_score=gpu_score, gputdp=gputdp, hddtdp=hddtdp, ram_score=ram_score, ram_tdp=ram_tdp, ssdtdp=ssdtdp) bottleneck(pc_type=pc_type, cpu_score=cpu_score, drive_score=drive_score, drive_type=drive_type, gpu_score=gpu_score, ram_score=ram_score) energy_cost_calc(total_tdp=total_tdp) again() thanks() def start(): print(colored("'." * 70, color='white', attrs=['blink'])) print(magenta("* Welcome to Spicy's Ultimate Computer Utility *")) print(magenta("* Version Alpha 3.4 *")) print(magenta("** This program is still in alpha stage " "and isn't perfect **")) print(magenta("If you are unsure about one of the questions, " "look up the specs of the part on a website " "like PCPartPicker or TechPowerUP")) print(magenta("** Make sure to pay attention to the units " "specified in the questions. **")) return float(input(cyan("Is your computer a laptop or desktop? " "1 for laptop, 2 for desktop."))) def cpu(pc_type): l1_factor = 100 #The smaller this is, the more L1 cache matters l3_factor = .3 #The larger this is, the more L3 cache matters name = input(cyan("What is the name of your processor?")) tdp = float(input(cyan(f"What is the TDP of the {name}? (in W)"))) cores_count = float(input(cyan(f"How many cores does the {name} have?"))) threads_count = float(input(cyan(f"How many threads " f"does the {name} have?"))) l1_cache = float(input(cyan(f"How much L1 cache (in total) " f"does the {name} have in KB?"))) l2_cache = float(input(cyan(f"How much L2 cache (in total) " f"does the {name} have in MB?"))) l3_cache = float(input(cyan(f"How much L3 cache (in total) " f"does the {name} have in MB?"))) clock_speed = float(input(cyan(f"What is the clock speed (in GHz) " f"of the {name}?"))) fabrication = float(input(cyan(f"What is the fabrication process " f"of the {name} in nm?"))) ram_type = float(input(cyan(f"What type of RAM does the {name} use? " f"Enter 3 for DDR3, 4 for DDR4, etc."))) score = ((cores_count + threads_count + clock_speed + ram_type + l2_cache + (l1_cache / l1_factor) + (l3_factor * l3_cache)) / fabrication) * pc_type print(yellow(f"** The {name} has a score of {round(score, 5)}. **")) return tdp, ram_type, score def ram(ram_type): ram_tdp_factor = 4 #1 RAM stick draws around 4W dimm_speed_factor = 500 #The smaller this is, the more speed matters ram_equation_factor = 150 #The smaller this is, the less RAM score matters overall amount = float(input(cyan("How much RAM does your system have " "(in GB?)"))) slowest_dimm_speed = float(input(cyan("What is the speed of your slowest " "installed DIMM? (in MHz)"))) dimms_count = (float(input(cyan("How many DIMMs do you have installed?"))) * ram_tdp_factor) score = ((ram_type + (slowest_dimm_speed / dimm_speed_factor)) * amount) / ram_equation_factor print(yellow(f"** Your RAM score is {round(score, 5)}. **")) return score, dimms_count def gpu(pc_type): name = input(cyan("What is the name of your GPU?")) memory_type = int(input(cyan(f"What type of memory does the {name} use? " f"0 for GDDR, 1 for HBM"))) tdp = float(input(cyan(f"What is the TDP of the {name}? (in W)"))) if memory_type == 0: cores_factor = 400 #The smaller this is, the more cores matter tmus_factor = 25 #the smaller this is, the more TMUs matter rops_factor = 10 #the smaller this is, the more ROPs matter memsize_factor = 1000 #the smaller this is, the more VRAM amount matters buswidth_factor = 30 #the smaller this is, the more bus width matters clockspeed_factor = 2 #the larger this is, the more clockspeed matters memspeed_factor = 1000 #the smaller this is, the more VRAM speed matters gpu_equation_factor = 25 #the smaller this is, the more GPU score matters overall cores_count = float(input(cyan(f"How many cores " f"does the {name} have?"))) tmus_count = float(input(cyan(f"How many TMUs " f"does the {name} have?"))) rops_count = float(input(cyan(f"How many ROPs " f"does the {name} have?"))) memory_size = float(input(cyan(f"How much memory (in MB) " f"does the {name} have?"))) memory_type = float(input(cyan(f"What type of memory " f"does the {name} have? " f"Enter 3 for GDDR3, 5 for GDDR5, " f"and 8 for GDDR5X."))) # GDDR5X is 8 to account for its additional data rate bus_width = float(input(cyan(f"What is the bus width " f"of the {name}?"))) clock_speed = float(input(cyan(f"What is the clock speed " f"of the {name} in GHz?"))) memory_speed = float(input(cyan(f"What is the effective memory speed " f"of the {name} in MHz?"))) fabrication = float(input(cyan(f"What is the fabrication process " f"of the {name} in nm?"))) score = ((((cores_count / cores_factor) + (tmus_count / tmus_factor) + (rops_count / rops_factor) + (memory_size / memsize_factor) + (bus_width / buswidth_factor) + (clock_speed * clockspeed_factor) + (memory_speed / memspeed_factor)) * ((memory_type / fabrication) / gpu_equation_factor))) * pc_type if memory_type == 1: cores_factor = 400 #The smaller this is, the more cores matter tmus_factor = 25 #the smaller this is, the more TMUs matter rops_factor = 10 #the smaller this is, the more ROPs matter memsize_factor = 1000 #the smaller this is, the more VRAM amount matters buswidth_factor = 250 #the smaller this is, the more bus width matters clockspeed_factor = 2 #the larger this is, the more clockspeed matters memspeed_factor = 150 #the smaller this is, the more VRAM speed matters gpu_equation_factor = 25 #the smaller this is, the more GPU score matters overall cores_count = float(input(cyan(f"How many cores " f"does the {name} have?"))) tmus_count = float(input(cyan(f"How many TMUs " f"does the {name} have?"))) rops_count = float(input(cyan(f"How many ROPs " f"does the {name} have?"))) memory_size = float(input(cyan(f"How much memory (in MB) " f"does the {name} have?"))) memory_type = float(input(cyan(f"What type of memory " f"does the {name} have? " f"Enter 1 for HBM, 2 for HBM2, etc."))) # GDDR5X is 8 to account for its additional data rate bus_width = float(input(cyan(f"What is the bus width " f"of the {name}?"))) clock_speed = float(input(cyan(f"What is the clock speed " f"of the {name} in GHz?"))) memory_speed = float(input(cyan(f"What is the effective memory speed " f"of the {name} in MHz?"))) fabrication = float(input(cyan(f"What is the fabrication process " f"of the {name} in nm?"))) score = (((cores_count / cores_factor) + (tmus_count / tmus_factor) + (rops_count / rops_factor) + (memory_size / memsize_factor) + (bus_width / buswidth_factor) + (clock_speed * clockspeed_factor) + (memory_speed / memspeed_factor)) / ((memory_type / fabrication) / gpu_equation_factor)) * pc_type print(yellow(f"** The {name} has a score of {round(score, 5)}. **")) return tdp, score def drive1(): drive_equation_factor = 30 #the smaller this is, the more drive score matters overall drive_type = float(input(cyan("Is your boot drive an HDD or SSD? " "Enter 1 for HDD, 2 for SSD."))) if drive_type == 1: rpm_factor = 1000 #the smaller this is, the more HDD RPM matters hdd_rpm = float(input(cyan("What is the RPM of your HDD?"))) drive_free = float(input(cyan("How much storage is available " "(not filled) on your boot drive " "(in GB)"))) drive_total = float(input(cyan("What is the total amount of storage " "on your boot drive (in GB)"))) percent_free = (drive_free / drive_total) * 100 print(yellow(f"* Your boot drive is " f"{round(percent_free, 3)}% free. *")) drive_score = (((1 / percent_free) * 100) * (hdd_rpm / rpm_factor)) / drive_equation_factor if drive_type == 2: ssd_factor = 5 #the larger this is, the more drive score will increase if SSD is boot drive drive_free = float(input(cyan(f"How much storage is available " f"(not filled) on your boot drive " f"(in GB)"))) drive_total = float(input(cyan("What is the total amount of storage " "on your boot drive (in GB)"))) percent_free = (drive_free / drive_total) * 100 print(yellow(f"* Your boot drive is " f"{round(percent_free, 3)}% free. *")) drive_score = ((((1 / percent_free) * 100) * ssd_factor) * drive_type) / drive_equation_factor return drive_score, drive_type def drive2(drive_score): ssdtdp = float(input(cyan("How many SSDs do you have " "installed in your system?"))) ssdtdp *= 3.25 # 1 SSD draws this much watts (the *= thing means ssdtdp = ssdtdp*3.25) hddtdp = float(input(cyan(f"How many HDDs do you have " f"installed in your system?"))) hddtdp *= 8 # 1 HDD draws this much watts print(yellow(f"** Your boot drive's score is " f"{round(drive_score, 5)}. **")) return hddtdp, ssdtdp def final(pc_type, cpu_score, gpu_score, drive_score, ram_score, cpu_tdp, gputdp, ram_tdp, hddtdp, ssdtdp): cpu_gpu_tdp_factor = 0.8 #the larger this is, the more to remove from CPU and GPU TDP (because they don't reach full spec) mainboard_tdp = 50 #the motherboard will draw around 50W by itself final_score = (cpu_score + gpu_score + drive_score + ram_score) dvdtdp = float(input(cyan("How many optical drives " "do you have installed?"))) # 1 ODD draws around 20 watts, I'm assuming laptop ODDs use half of that. dvdtdp = dvdtdp * 10 * pc_type if pc_type == 2: fantdp = float(input(cyan("How many case fans do you have installed? " "(counting CPU cooler)"))) fantdp *= 4 # 1 120mm fan draws around 4 watts if pc_type == 1: fantdp = 0.5 #I will assume that laptops' cooling solutions use 0.5 watts total usbtdp = float(input(cyan("How many USB ports does your computer have? " "(in total)"))) usbtdp *= 2.5 # USB can only pull 2.5 watts max # Estimated max load TDP equation total_tdp = (((cpu_tdp + gputdp) * cpu_gpu_tdp_factor) + ram_tdp + hddtdp + ssdtdp + dvdtdp + fantdp + usbtdp) + mainboard_tdp # max spec TDP equation psu_factor = 75 #The larger this is, the more "extra" watts to recommend for the PSU #since a PSU should never reach full spec recommended_psu = (cpu_tdp + gputdp + ram_tdp + hddtdp + ssdtdp + dvdtdp + usbtdp + psu_factor) print(magenta("Calculating final score...")) print(yellow("** Your final score is... **")) print(round(final_score, 5)) print(yellow("** Your predicted maximum load wattage is... **")) print(f"{round(total_tdp, 1)} Watts") print(yellow(f"** I would recommend using a power supply of at least " f"{int(round(recommended_psu, -1))} watts. **")) return total_tdp def energy_cost_calc(total_tdp): hrscalc = input(cyan("Would you also like to factor in " "your energy costs? Y/N")) if hrscalc == "Y": hrs = float(input(cyan("On average, how many hours do you use " "your computer daily?"))) price = float(input(cyan("What is the price per kWh " "where you live? (in dollars)"))) ktdp = total_tdp / 1000 # TDP in kW dailycost = hrs * price * ktdp hourcost = dailycost / 24 weeklycost = dailycost * 7 monthlycost = dailycost * 30.42 #an average month has 30.42 days yearlycost = dailycost * 365 print(yellow(f"Your cost is${round(hourcost, 2)} per hour, "
f"${round(dailycost, 2)} per day, " f"${round(weeklycost, 2)} per week, "
f"${round(monthlycost, 2)} per month, " f"and${round(yearlycost, 2)} per year."))

def bottleneck(pc_type,
gpu_score,
ram_score,
drive_score,
cpu_score,
drive_type):
print(yellow("Calculating bottleneck..."))
bram_factor = 4
bdrive_factor = 5
if pc_type == 1:  # laptop
bgpu_factor = 3.5
bcpu_factor = 2
bgpus = gpu_score * bgpu_factor
brams = ram_score * bram_factor
bhds = drive_score * bdrive_factor
bcpus = cpu_score * bcpu_factor

if pc_type == 2:  # desktop
bgpu_factor = 1.75
bgpus = gpu_score * bgpu_factor
brams = ram_score * bram_factor
bhds = drive_score * bdrive_factor
bcpus = cpu_score

if bgpus <= brams and bgpus <= bhds and bgpus <= bcpus:
gpub = 1
cpub = 0
ramb = 0
hdb = 0
if bcpus <= brams and bcpus <= bhds and bcpus <= bgpus:
cpub = 1
gpub = 0
ramb = 0
hdb = 0
if brams <= bcpus and brams <= bhds and brams <= bgpus:
ramb = 1
cpub = 0
gpub = 0
hdb = 0
if bhds <= brams and bhds <= bcpus and bhds <= bgpus:
hdb = 1
cpub = 0
ramb = 0
gpub = 0
if gpub == 1:
print(yellow("You could improve your GPU score "
"by overclocking or replacing your GPU."))

if cpub == 1:
print(yellow("You could improve your CPU score "
"by overclocking or replacing your CPU."))

if ramb == 1:
print(yellow("You could improve your RAM score "
"by overclocking, replacing, "
"or installing more or faster RAM."))

if hdb == 1:

if drive_type == 1:
print(yellow("You could improve your boot disk score "
"by replacing your HDD with a faster HDD or an SSD, "
"or by freeing up space."))

if drive_type == 2:
print(yellow("You could improve your boot disk score "
"by freeing up space."))

def thanks():
print(magenta("Thank you for using SPPC!"))