HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Cycling time trials

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
cyclingtrialstime

Problem

It would be helpful to know where I could improve the style of it, so it follows the style guide better, and also any ways I could compact it - especially at the end, where I have added items to a list then removed them. Is there a more elegant way to do that?

```
def reptillint(sentence,mini,maxi,error1):
maxi = int(maxi)
number = ''
while number == '':
number = input(sentence+' (whole number from ' + str(mini) + ' to ' + str(maxi) + ') ')
try:
number = int(number)
if (number maxi):
number = ''
print (error1)
except ValueError:
number = ''
print ('Needs to be a number')

return number

contestants = ''
while (contestants == ''):
contestants = input('How many people are competing (whole number, min 2)? ')
try:
int(contestants)
except ValueError:
contestants = ''
print ('Needs to be a number')

listOfContestantNumbers = [ i for i in range(1,int(contestants)+1)]
listOfContestantNumbersTimes = [ 'N/C' for i in range(1,int(contestants)+1)]
listOfContestantNumbersTimesSeconds = [ 'N/C' for i in range(1,int(contestants)+1)]
listOfContestantNumbersTimesSecondsstr = [ 'N/C' for i in range(1,int(contestants)+1)]

while 'N/C' in listOfContestantNumbersTimes:

number = reptillint('What is the number of the person who just finished?',0,contestants,'Needs to be a contestant\'s number')

print (number)

hours = reptillint('Hours?',0,10000,'Needs to be more than 0')
minutes = reptillint('Minutes?',0,59,'Needs to be more than 0 and less than 59')
seconds = reptillint('Seconds?',0,59,'Needs to be more than 0 and less than 59')
miliseconds = reptillint('Miliseconds?',0,100,'Needs to be more than 0 and less than 100')

listOfContestantNumbersTimes[number-1] = str(hours)+':'+str(minutes)+':'+str(seconds)+'.'+str(miliseconds)
listOfContestantNumbersTimesSeconds[number-1] = hours*3600+min

Solution

Here is how I would have approached it:

import datetime
from operator import itemgetter

def get_int_input(prompt, min_=0, max_=None):
    """Get a valid integer input."""
    while True:
        try:
            i = int(input(prompt))
        except ValueError:
            print("Please enter an integer.")
        else:
            if min_ is not None and i  max_:
                print("Must be at most {0}.".format(max_))
                continue
            return i

def get_time():
    """"Get a time input as a datetime.time object."""
    h = get_int_input("Hours (0-23): ", max_=23)
    m = get_int_input("Minutes (0-59): ", max_=59)
    s = get_int_input("Seconds (0-59): ", max_=59)
    ms = get_int_input("Milliseconds (0-999): ", max_=999)
    return datetime.time(h, m, s, ms*1000)

def get_results(competitors):
    """Get a dict of finishing times for all competitors."""
    results = {}
    for _ in range(competitors):
        while True:
            competitor = get_int_input("Enter competitor number: ", min_=1, 
                                       max_=competitors)
            if competitor not in results:
                results[competitor] = get_time()
                break
            print("Time already entered.")
    return results

def print_results(results):
    """Display the race results in a table, fastest first."""
    line = "-" * 32
    print(line)
    print("| Competitor | Time (H:M:S)    |")
    for n, t in sorted(results.items(), key=itemgetter(1)):
        print(line)
        print("| {0:<10d} | {1!s:<15} |".format(n, t))
    print(line)

def race():
    """Handle race times for a user-specified number of competitors."""
    n = get_int_input("Enter number of competitors (2-): ", min_=2)
    results = get_results(n)
    print_results(results)

if __name__ == "__main__":
    race()


Note the following:

  • Use of datetime.time to handle times more neatly;



  • Split up into single-purpose functions to minimise duplication and make development and testing easier;



  • if __name__ == "__main__": guard to allow easier import of functions elsewhere;



  • Use of str.format to handle the text; and



  • Adherence to the style guide, including variable and function names, docstrings and line lengths.

Code Snippets

import datetime
from operator import itemgetter

def get_int_input(prompt, min_=0, max_=None):
    """Get a valid integer input."""
    while True:
        try:
            i = int(input(prompt))
        except ValueError:
            print("Please enter an integer.")
        else:
            if min_ is not None and i < min_:
                print("Must be at least {0}.".format(min_))
                continue
            elif max_ is not None and i > max_:
                print("Must be at most {0}.".format(max_))
                continue
            return i

def get_time():
    """"Get a time input as a datetime.time object."""
    h = get_int_input("Hours (0-23): ", max_=23)
    m = get_int_input("Minutes (0-59): ", max_=59)
    s = get_int_input("Seconds (0-59): ", max_=59)
    ms = get_int_input("Milliseconds (0-999): ", max_=999)
    return datetime.time(h, m, s, ms*1000)

def get_results(competitors):
    """Get a dict of finishing times for all competitors."""
    results = {}
    for _ in range(competitors):
        while True:
            competitor = get_int_input("Enter competitor number: ", min_=1, 
                                       max_=competitors)
            if competitor not in results:
                results[competitor] = get_time()
                break
            print("Time already entered.")
    return results

def print_results(results):
    """Display the race results in a table, fastest first."""
    line = "-" * 32
    print(line)
    print("| Competitor | Time (H:M:S)    |")
    for n, t in sorted(results.items(), key=itemgetter(1)):
        print(line)
        print("| {0:<10d} | {1!s:<15} |".format(n, t))
    print(line)

def race():
    """Handle race times for a user-specified number of competitors."""
    n = get_int_input("Enter number of competitors (2-): ", min_=2)
    results = get_results(n)
    print_results(results)

if __name__ == "__main__":
    race()

Context

StackExchange Code Review Q#61656, answer score: 5

Revisions (0)

No revisions yet.