I was wondering if anyone would be able to provide some feedback on how I can improve my code quality. I teach python to students and wrote a simple translator game that I want to work on with them, but I want to make sure I have a polished version first. I'm looking for mostly improvements to how to structure/order my code as well as different techniques I could have used more effectively or alternatively to what I currently have. Thank you for any feedback in advance. Below I've included a link to my program to link as well as the code itself:
Link: https://replit.com/@hunter-macias/translator#main.py
Code:
import random
import time
import os
from difflib import SequenceMatcher
def getAccuracy(a, b):
return SequenceMatcher(None, a, b).ratio()
def translateConlang(message):
conlang = {
"a" : "æ",
"b" : "ß",
"c" : "ç",
"d" : "∂",
"e" : "∊",
"f" : "ƒ",
"g" : "❡",
"h" : "ℌ",
"i" : "î",
"j" : "ʝ",
"k" : "₭",
"l" : "ł",
"m" : "Պ",
"n" : "ℵ",
"o" : "œ",
"p" : "℘",
"q" : "ǭ",
"r" : "®",
"s" : "ş",
"t" : "✞",
"u" : "μ",
"v" : "√",
"w" : "ഡ",
"x" : "✖",
"y" : "ɣ",
"z" : "ℤ",
"." : "ඞ",
" " : " ",
"-" : "-",
"," : ",",
"\n" : "",
";" : ";",
"’" : "’",
"'" : "'"
}
return "".join([conlang.get(let) for let in message])
def generateSentence(language="english"):
if language == "english":
with open("englishSentences.txt") as file:
sentences = file.readlines()
return random.choice(sentences)
def calculatePoints(accuracy, timeEllapsed):
return round(accuracy * 1000 - (timeEllapsed * 10), 2)
def showStats(accuracy, score, time, award=0):
print('stats: ')
if award != 0:
print(f'\n\tAward: {award}')
print(f'\tAccuracy: {round(accuracy, 3)}%')
print(f'\tScore: {round(score, 3)}')
print(f'\ttime: {round(time, 3)}s\n')
def instructions():
print(
'''
earn points by deciphering randomly generated sentences
points are awarded based on your accuracy and time to type
accuracy is calculated by comparing the ratio between the message and guess that is inputed
''')
def playGame():
play = input("\t1. press enter to continue\n\t2. type -h for instructions\n> ")
return play
def main():
score = 0
print("Welcome to the fake language translator!")
play = playGame()
print("----------------------------------------")
while not play:
message = generateSentence().lower()
conlangMessage = translateConlang(message)
print(f'conlang: {conlangMessage}')
start = time.time()
guess = input("english: ")
end = time.time()
timeEllapsed = end-start
accuracy = getAccuracy(message, guess)
award = calculatePoints(accuracy, timeEllapsed)
score = award
print(f"\ntranslation: {message}")
showStats(accuracy, score, timeEllapsed, award=0)
print("----------------------------------------")
time.sleep(1)
play = playGame()
os.system('clear')
showStats(accuracy, score, timeEllapsed)
if play == '-h':
instructions()
else:
print('invalid entry. rerun')
main()
CodePudding user response:
You could add at the beginning of the program:
if __name__ == '__main__':
# the rest of the program
This makes it so that if the functions you have made are used in another program, none of the code will be run automatically. For example:
file1.py:
import file2
print('starting...')
file2Function()
file2.py:
print('starting...')
def file2Function():
print('I'm the file2 function')
In this hypothetical example, when I import file2, the print(starting...) is still going to run, so the output will be:
starting... # from file2
starting... # from file1
I'm the file2 function # from file2Function
However if you had added the
if __name__ == '__main__':
# other code
this problem would not occur and you would be able to use the functions. You run this code yourself and remove and add the added if statement to see how it functions.
CodePudding user response:
I have a bunch of annotations. I added them all with a FB:
tag as comments in your code.
I think we should move this question to codereview
, though.
import random
import time
import os
from difflib import SequenceMatcher
def getAccuracy(a, b):
return SequenceMatcher(None, a, b).ratio()
def translateConlang(message):
conlang = {
"a": "æ",
"b": "ß",
"c": "ç",
"d": "∂",
"e": "∊",
"f": "ƒ",
"g": "❡",
"h": "ℌ",
"i": "î",
"j": "ʝ",
"k": "₭",
"l": "ł",
"m": "Պ",
"n": "ℵ",
"o": "œ",
"p": "℘",
"q": "ǭ",
"r": "®",
"s": "ş",
"t": "✞",
"u": "μ",
"v": "√",
"w": "ഡ",
"x": "✖",
"y": "ɣ",
"z": "ℤ",
".": "ඞ",
" ": " ",
"-": "-",
",": ",",
"\n": "",
";": ";",
"’": "’",
"'": "'"
}
# FB: `let` is a keyword in many languages, don't use `let` as a variable name
return "".join([conlang.get(let) for let in message])
def generateSentence(language="english"):
if language == "english":
with open("englishSentences.txt") as file:
sentences = file.readlines()
return random.choice(sentences)
# FB: missing return value in the else case
# FB: typo in elapsed
def calculatePoints(accuracy, timeEllapsed):
return round(accuracy * 1000 - (timeEllapsed * 10), 2)
def showStats(accuracy, score, time, award=0):
print('stats: ')
# FB: pythonic would be `if award:`; the `!= 0` is unnecessary, `0` is already falsy, and `!=0` is already truthy.
if award != 0:
print(f'\n\tAward: {award}')
print(f'\tAccuracy: {round(accuracy, 3)}%')
print(f'\tScore: {round(score, 3)}')
print(f'\ttime: {round(time, 3)}s\n')
def instructions():
print(
'''
earn points by deciphering randomly generated sentences
points are awarded based on your accuracy and time to type
accuracy is calculated by comparing the ratio between the message and guess that is inputed
''')
# FB: playGame is a weird name for what this function does, i don't think any game is being played here
def playGame():
# FB: play is a weird name for this variable, it doesn't actually represent anything being played
play = input("\t1. press enter to continue\n\t2. type -h for instructions\n> ")
return play
def main():
score = 0
print("Welcome to the fake language translator!")
play = playGame()
print("----------------------------------------")
# FB: while this code seems to work, it's very unintuitive.
# `not play` indicates that you don't want to play to me.
# so to enter the main play loop if `not play` seems weird.
# I think the main problem here is that the `play` variable is
# named badly; its name does not represent its meaning.
while not play:
message = generateSentence().lower()
conlangMessage = translateConlang(message)
print(f'conlang: {conlangMessage}')
start = time.time()
guess = input("english: ")
end = time.time()
# FB: typo - elapsed
timeEllapsed = end-start
accuracy = getAccuracy(message, guess)
award = calculatePoints(accuracy, timeEllapsed)
score = award
print(f"\ntranslation: {message}")
showStats(accuracy, score, timeEllapsed, award=0)
print("----------------------------------------")
time.sleep(1)
play = playGame()
os.system('clear')
# FB: what's the point of the `award` argument in `showStats`?
# seems like it never gets used
showStats(accuracy, score, timeEllapsed)
if play == '-h':
# FB: might want to not exit the program after printing instructions, seems like it should
# try to play again afterwards
instructions()
else:
print('invalid entry. rerun')
# FB: wrap in `if __name__ == "__main__":`
main()