Skip to content

Instantly share code, notes, and snippets.

@serhiitytarenko
Created April 29, 2020 14:11
Show Gist options
  • Save serhiitytarenko/1de02504e1f151ddb9bd2cb885bb5ca7 to your computer and use it in GitHub Desktop.
Save serhiitytarenko/1de02504e1f151ddb9bd2cb885bb5ca7 to your computer and use it in GitHub Desktop.
import re
import datetime
from collections import OrderedDict
def create_racer_abbreviations_dict(file_name):
"""Retrieves {'abbreviation': (name, team)}" format dict from abbreviations.txt"""
abbreviations_dict = {}
with open(file_name, 'r') as fn:
for line in fn:
matchObj = re.match(r'^(\w+)_([a-zA-Z\s]+)_([a-zA-Z\s]+)$', line)
# group(1) is abbreviation, i.e 'SVM'
abbreviations_dict[matchObj.group(1)] = (
matchObj.group(2), # name of a pilot
matchObj.group(3).rstrip(), # team
)
return abbreviations_dict
# {'abbreviation of pilot': ('name of pilot, 'team')}
abbr_dict = create_racer_abbreviations_dict(
'abbreviations.txt')
# returns timing log from start.log or end.log in {'abbreviation': time} format
def retrieve_timings_from_log(file_name):
timing_log = {}
with open(file_name, 'r') as fn:
for line in fn:
# matches 2 groups: abbreviation of a racer and time
matchObj = re.match(r'^([A-Z]+).*(\d{2}:\d+:\d+\.\d+)$', line)
# converts time from a string to datetime object
lap_time = datetime.datetime.strptime(
matchObj.group(2).rstrip(), '%H:%M:%S.%f')
# adds key, value to a timing_log
timing_log[matchObj.group(1)] = lap_time
return timing_log
start_timings = retrieve_timings_from_log('start.log')
end_timings = retrieve_timings_from_log('end.log')
def sorted_individual_results(start_timings_, end_timings_, abbr_dict_, reverse_order=False):
"""
Receives start and end timings and returns an OrderedDict with
{abbreviations:timedeltas}
"""
# creating dict with best lap results
lap_results = {key: end_timings_[key] - start_timings_.get(key, 0)
for key in start_timings_.keys()}
sorted_results = dict(
sorted(lap_results.items(), key=lambda x: x[1], reverse=reverse_order))
return sorted_results
sorted_lap_results = sorted_individual_results(
start_timings, end_timings, abbr_dict)
# prints result board to a console
def print_result_board(sorted_lap_results_):
counter = 1
for key, value in sorted_lap_results_.items():
racer_name = abbr_dict[key][0]
team_name = abbr_dict[key][1]
best_time = str(value)[2:-3]
print(("{: <3} {: <18} | {: <30} | {}".format(
str(counter)+'.', racer_name, team_name, best_time)))
if counter == 15:
print(
'----------------------------------------------------------------------')
counter += 1
print_result_board(sorted_lap_results)
@Nerphist
Copy link

Consider renaming your variables in order to naming convention https://www.python.org/dev/peps/pep-0008/#function-and-variable-names

@Nerphist
Copy link

Function declaration and invocation should be separated in order not to split business logic

@Nerphist
Copy link

Consider putting program logic into
if __name__ == '__main__':

@Nerphist
Copy link

sorted_individual_results should be renamed into sort_individual_results

@Nerphist
Copy link

create_racer_abbreviations_dict doc string shouldn't contain hardcoded file name

@Nerphist
Copy link

In condition if counter == 15: '15' looks like a magic number, please consider moving it's value to some constant

@Nerphist
Copy link

Also consider indicating function variables' names types to make functions logic more clear

@Taraslut
Copy link

Taraslut commented Jun 9, 2021

Active items to improve code

  1. Imports have to be in alphabetical order

  2. Functions definition follow imports

  3. Main logic follows functions definition

  4. Replase commets before function definition with docstring

  5. Keep unified variable naming (PEP8 advises snake_case ) (bed matchObj, good match_obj)

  6. Good practice: variable names avoid words (dict, list, obj, object, so far).

  7. Hardcoded repetitive strings (like in 11, 31 lines) have to be declared as CONSTANTS.

@VolodymyrBor
Copy link

Add typing for functions: it will help better understand functions and IDE will able to provide hints and code completion.

PEP 484 -- Type Hints

@VolodymyrBor
Copy link

Regex string should be declared as const at the top of the program.

@VolodymyrBor
Copy link

Use python conventions for variables names:
Naming Conventions

it is better not to use names like matchObj

@VolodymyrBor
Copy link

It will be nice to keep all functions at the top and move all logic that declared out of functions to a separated function for example main().

@VolodymyrBor
Copy link

Add if __name__ == '__main__': statement to show the entry point of the script.

@VolodymyrBor
Copy link

Use some docstring style. For example:

@levko-art
Copy link

levko-art commented Oct 8, 2021

  1. Add if __name__ == '__main__': as entry point
  2. Bad naming in with open(file_name, 'r') as fn:
  3. Regex should be declared as constants.
  4. Bad naming in variable matchObj. Should be snake_case (match_obj).
  5. Should be in one line:
abbr_dict = create_racer_abbreviations_dict(
    'abbreviations.txt')
sorted_lap_results = sorted_individual_results(
    start_timings, end_timings, abbr_dict)
    sorted_results = dict(
        sorted(lap_results.items(), key=lambda x: x[1], reverse=reverse_order))
print(
                '----------------------------------------------------------------------')
  1. In 67 line best practice is using f-string. Not .format() method.
  2. sorted_lap_results_ bad naming - _ in the end of name
  3. Developer don`t use type hints.
  4. Imports should be in alphabetical order.
  5. Developer use others styles for docstrings.

@Korulag
Copy link

Korulag commented Jan 7, 2022

create_racer_abbreviations_dict:

  1. Use snake-case code style for all the variables;
  2. Check if string was matched to regular expression before adding items to the dictionary;

retrieve_timings_from_log:

  1. Same thing here as above

sorted_individual_results:

  1. abbr_dict_ variable is not used inside the function, consider removing it from arguments or check function logic for errors;
  2. Consider renaming function to sort_individual_results;

Overall:

  1. Split function definitions from actual logic (first all needed functions, then main logic);
  2. Use if __name__ == '__main__': construct to execute main logic of the file;
  3. Comments above the functions could be moved into docstrings;
  4. Make file paths with input data configurable and check their existence before making any operations with them;
  5. Use code-specific exceptions and add reactions to them (like if the exception is critical to workflow or not);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment