Home > OS >  how to improve the structure, organization, and overall quality of my code
how to improve the structure, organization, and overall quality of my code

Time:07-25

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()
  • Related