GithubHelp home page GithubHelp logo

alec-kr / f1pystats Goto Github PK

View Code? Open in Web Editor NEW
50.0 5.0 19.0 473 KB

An open-source Python3 package that provides Formula 1 data to developers.

License: GNU General Public License v3.0

Python 100.00%
ergast-api ergast-developer-api ergast-drivers-api f1 formula1 hacktoberfest pandas python codecov collaborate

f1pystats's Introduction

Hi there! ๐Ÿ‘‹ I'm Alec

Aspiring tech enthusiast and recent Computer Science graduate from the University of London. I'm a curious learner, creative problem solver, and passionate developer who loves diving into diverse projects that span software development, data analysis, and game design.

๐Ÿ”ญ What I Do

  • Software Development: Proficient in Python, C++, and C#, with hands-on experience in crafting versatile applications, games, and utilities.
  • Frontend Magic: Skilled in React and Node.js, adept at building engaging, user-friendly interfaces for web and mobile applications.
  • Data Insights: Leveraging Python, I transform raw data into meaningful insights, guiding decision-making through data-driven strategies.
  • Tech Explorer: Eager to explore new technologies and frameworks, adapting quickly to evolving industry trends.

๐Ÿ’ก My Projects

๐ŸŽ๏ธ F1PyStats - Formula 1 Data for Developers

As a passionate Formula 1 fan, I wanted to create a tool that fellow developers and enthusiasts could use to explore the exciting world of motorsport. Check it out!

๐ŸŽฎ Galactic Assault - 2D Space Shoot-em Game

Built using C# on the Unity platform, this game brings together my passion for game development and creativity. Check it out!

๐ŸŒฑ What I'm Excited About

Eager to contribute to innovative projects that merge technology with positive impact. Passionate about creating engaging user experiences, whether through data insights, interactive apps, or immersive games.

๐Ÿ“ซ Let's Connect!

Ready to collaborate, learn, and create? I'm just a message away! Feel free to reach out on LinkedIn.

f1pystats's People

Contributors

achiverram28 avatar adityakeshan avatar alec-kr avatar arungrace88 avatar atharvadeshmukh0909 avatar dan-pavlov avatar dependabot[bot] avatar domheadroom avatar exoutia avatar gauravkolekar avatar glowstik-yt avatar irahorecka avatar jidicula avatar lakshayainani avatar malay5 avatar nitrok avatar silvertux avatar youpong avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

f1pystats's Issues

Add an optional "driver" parameter to pit_stops()

The Problem

The package's pit_stop() function only accepts the year, and also the round # and pit stop # as optional parameters.
There is no way to get the pitstops made by a particular driver during the race.

The Proposed Solution

Therefore, the function can be improved by adding an optional driver parameter. An example function call
will be something like:

// Function call structure
fp.pit_stops(year, round, driver)

// Return the pitstops made by Max Verstappen in the 8th race of the 2022 season 
fp.pit_stops(2022, 8, "max_verstappen")

The data that should be returned by the example function call above can be found here.

NOTE: If the driver name is provided along with year and round, ONLY then should the data for that particular driver during the race will be returned.

Further Information

If incorrect data is passed to the function (incorrect driver name, the round # is left out, etc.), the function MUST be able to throw an error which can easily be understood by the user.

More information on pit stops can be found on the Ergast API website.

Implement tests for the current functions

When contributors make changes or submit PRs, there is no way to test if any part of the code is broken or malfunctioning.\

To resolve this, tests should be added to the GitHub workflow.

Create get_constructors()

This package should contain a function capable of returning constructor information such as team names and nationality. The reference page for this data can be found here.

A function called get_constructors() may be created, that accepts a year as an optional parameter, and returns a DataFrame of participating constructors in that year, and their nationality. If the year is not provided, return all constructors in F1 history.

Example:
get_constructors(2022) -> Returns all constructors in 2022 and the nationalities
get_constructors() -> Returns all constructors in F1 history, and the nationalities

Warning for deprecated option --dev

Describe the bug

Warning for deprecated option --dev on mypy static check.

To Reproduce
Steps to reproduce the behavior:

$ poetry run nox -s mypy

Expected behavior
No warn.

Screenshots

$ poetry run nox -s mypy
nox > Running session mypy
nox > Creating virtual environment (virtualenv) using python in .nox/mypy
nox > poetry export --format=requirements.txt --dev --without-hashes
The `--dev` option is deprecated, use the `--with dev` notation instead.
nox > python -m pip install --constraint=.nox/mypy/tmp/requirements.txt mypy types-requests numpy pytest nox_poetry types-toml
nox > mypy f1pystats tests noxfile.py docs/conf.py
Success: no issues found in 46 source files
nox > Session mypy was successful.

User System Specs (please complete the following information):

  • OS: Ubuntu 22.04.2 LTS
  • Python: 3.9.16

Additional context
None.

Develop finishing_status() function

This package should contain a function capable of returning the finishing status of a race. The reference page for this data can be found here.

A function called finishing_status() or similar may be created, that accepts a year, and returns a DataFrame with data similar to this. The function should also accept race round as an optional parameter. If the race round is also provided, return the finishing status for the particular race (example API data here)

Example:
finishing_status(2022) -> Returns finishing status for 2022. (Example data)
finishing_status(2022, 3) -> Returns finishing status for the 3rd race in 2022. (Example data)

[BUGFIX] Fix typo in pit_stops()

Background

The pit_stops() function currently accepts 3 parameters: year, race_round and stop_number. If stop_number is not provided in the function call, all pit stops during the race should be returned.

The issue

On L198-L201 of f1pystats.py, the if statement checks if int == 0, instead of checking if the value of stop_number == 0.

This error is also highlighted in our coverage reports, and it clearly shows that this line is not executed with our tests.

Expected Changes

This is quite a simple fix: The issue should be resolved by replacing int == 0 with stop_number == 0.

Use Poetry in CI

Is your feature request related to a problem? Please describe.
Since Poetry is being used for dependency and virtualenv management in this project, it should also be used in CI to ensure that contributors' changes meet the required checks, and so CI matches the developer loop as closely as possible.

Describe the solution you'd like
Use snok's Install Poetry action for setup and follow the example for setting up a workflow to invoke tests in CI.

Describe alternatives you've considered
The existing CI references requirements.txt, which isn't being used for dependency management. It also "manually" installs each dependency, rather than using the pinned versions in pyproject.toml.

Additional context
N/A

Refactoring modules

Hello - Iโ€™m wondering if I may contribute by refactoring some of your modules? I would like to make some functions more concise, and Iโ€™ll do my best to preserve the current module API.

f1pystats.pit_stops() does not return the fastest time

Describe the bug

f1pystats.pit_stops() does not return the fastest time.

To Reproduce

$ poetry run python
Python 3.10.7 (main, Oct  4 2022, 23:53:09) [GCC 11.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import f1pystats as fp
>>> fp.pit_stops(2021, 2, 0, True)
   Driver Stop Lap      Time   Duration
0  stroll    2  32  15:58:13  24:52.090

Expected behavior

returns below.

   Driver Stop Lap      Time   Duration
0  giovinazzi    4  40  16:36:13  29.742

Screenshots
None.

User System Specs (please complete the following information):

  • OS: Ubuntu 22.04.1 LTS
  • Python: 3.10.7

Additional context

None.

Refactor code to utilize Ergast API, instead of web scraping

By using the Ergast API, the code should be much cleaner, and easier to implement. If the structure of the F1 webpage were to change at some point, this entire project would have to be redesigned.

Therefore, utilizing an external API such as Ergast should reduce the time spent maintaining the repository, while simultaneously making it easier to read data.

Function to get pit stops

A pit_stops() function should be added to the package. This function can probably accept parameters such as the year, race round, and lap number. Example: pit_stops(year, round, lap_number)

If lap_number is not provided, then the code should return all pit stops for the specific race.

The output of the function can be a Pandas DataFrame containing pit stop duration, time, lap number and driver name.

Implement a function to return the lap times for a specified race

A lap_times() function would be a great addition to the project. This function can probably accept parameters such as the year, race round, and lap number. Example: lap_times(year, round, lap_number)

The output of the function can be a Pandas DataFrame containing each driver in the race, and their respective lap time.

Create PR template

Create PR template so that when a contributor wants to create a PR he/she know what all information needs to included

Add code coverage to workflow

The Problem

Every time we write a new function and add tests, we have no idea how much of the source code is tested. This can potentially result in certain bugs in the code going unnoticed.

Proposed Solution

To resolve this issue, a code coverage tool such as coverage.py or similar, should be added to this repo's workflow.

The tool should run on every push/PR to the repo, and display the results.

The README should also include a label similar to the following, to illustrate the code coverage:
image

Add the pandas and requests libraries to package dependencies

Currently, users must install the dependencies for the project manually, before running any code. To automate this process, the dependencies will be added to setup.py, where they will automatically be downloaded upon installation of the package.

The changes should be something similar to:

...
install_requires=[
          'requests', 'pandas'
      ],
...

Decision on the development tools that will be used

We should decide which development tools we'll be using:

Linting: Pylint
Dependency and package management: pipenv or poetry
CI: Github actions
Documentation: Spinx
Import sorting: isort
Testing: pytest or unittest
Code coverage: Coverage.py
Static type-checking: mypy
Security audit: Bandit

my[py], static typing reports some error

Describe the bug

my[py], static typing reports some error.

To Reproduce
Steps to reproduce the behavior:

$ poetry run mypy f1pystats tests

Expected behavior
No error should be reported.

Screenshots

$ poetry run mypy f1pystats tests
f1pystats/f1pystats.py:3: error: Skipping analyzing "pandas": module is installed, but missing library stubs or py.typed marker  [import]
f1pystats/f1pystats.py:3: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
f1pystats/f1pystats.py:68: error: Incompatible default for argument "round_num" (default has type "None", argument has type "int")  [assignment]
f1pystats/f1pystats.py:68: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True
f1pystats/f1pystats.py:68: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase
f1pystats/f1pystats.py:274: error: No overload variant of "zip" matches argument types "Any", "int", "Any", "Any", "Any"  [call-overload]
f1pystats/f1pystats.py:274: note: Possible overload variants:
f1pystats/f1pystats.py:274: note:     def [_T_co, _T1] zip(cls, Iterable[_T1], /, *, strict: bool = ...) -> zip[Tuple[_T1]]
f1pystats/f1pystats.py:274: note:     def [_T_co, _T1, _T2] zip(cls, Iterable[_T1], Iterable[_T2], /, *, strict: bool = ...) -> zip[Tuple[_T1, _T2]]
f1pystats/f1pystats.py:274: note:     def [_T_co, _T1, _T2, _T3] zip(cls, Iterable[_T1], Iterable[_T2], Iterable[_T3], /, *, strict: bool = ...) -> zip[Tuple[_T1, _T2, _T3]]
f1pystats/f1pystats.py:274: note:     def [_T_co, _T1, _T2, _T3, _T4] zip(cls, Iterable[_T1], Iterable[_T2], Iterable[_T3], Iterable[_T4], /, *, strict: bool = ...) -> zip[Tuple[_T1, _T2, _T3, _T4]]
f1pystats/f1pystats.py:274: note:     def [_T_co, _T1, _T2, _T3, _T4, _T5] zip(cls, Iterable[_T1], Iterable[_T2], Iterable[_T3], Iterable[_T4], Iterable[_T5], /, *, strict: bool = ...) -> zip[Tuple[_T1, _T2, _T3, _T4, _T5]]
f1pystats/f1pystats.py:274: note:     def [_T_co] zip(cls, Iterable[Any], Iterable[Any], Iterable[Any], Iterable[Any], Iterable[Any], Iterable[Any], /, *iterables: Iterable[Any], strict: bool = ...) -> zip[Tuple[Any, ...]]
f1pystats/f1pystats.py:332: error: Incompatible default for argument "year" (default has type "None", argument has type "int")  [assignment]
f1pystats/f1pystats.py:332: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True
f1pystats/f1pystats.py:332: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase
f1pystats/f1pystats.py:397: error: Incompatible default for argument "year" (default has type "None", argument has type "int")  [assignment]
f1pystats/f1pystats.py:397: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True
f1pystats/f1pystats.py:397: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase
Found 5 errors in 1 file (checked 44 source files)

User System Specs (please complete the following information):

  • OS: Ubuntu 22.04.2 LTS
  • Python: 3.11.2

Additional context
None.

Installation steps lead to an error

Describe the bug
The steps described in the installation section of the README.md lead to an error

To Reproduce

  1. Clone the repo
    $ git clone https://github.com/alec-kr/F1PyStats.git

  2. Install dependecies using poetry
    $ cd ../F1PyStats
    $ poetry install --only main

  3. installation fails

โžœ  F1PyStats git:(main) poetry install

  RuntimeError

  The Poetry configuration is invalid:
    - Additional properties are not allowed ('group' was unexpected)


  at ~/.pyenv/versions/3.10.0/lib/python3.10/site-packages/poetry/core/factory.py:43 in create_poetry
       39โ”‚             message = ""
       40โ”‚             for error in check_result["errors"]:
       41โ”‚                 message += "  - {}\n".format(error)
       42โ”‚
    โ†’  43โ”‚             raise RuntimeError("The Poetry configuration is invalid:\n" + message)
       44โ”‚
       45โ”‚         # Load package
       46โ”‚         name = local_config["name"]
       47โ”‚         version = local_config["version"]

Expected behavior
A clear and concise description of what you expected to happen.

User System Specs (please complete the following information):

  • OS: macOS 13.0 Beta (22A5358e)
  • Python: 3.10.0
  • Poetry 1.1.13

Create tests for the package functions

The current tests in the repo only evaluate the functions in the modules. This makes it difficult for contributors to determine if their changes affect/break anything in the actual package.

I will implement tests for the f1pystats package itself, so that contributors do not have to manually test functions every time an adjustment is made. This should potentially reduce the time spent debugging, and thus increase productivity in this repository.

Extract the year which is the last ergast having info about

Describe the bug
It would be good to have only one place where the code needs to be updated when new season data will be available.

To Reproduce
This is a code refactoring issue

Expected behavior
The behaviour of the code should be the same as before.

Additional info
f1pystats.py contains the year 2022 in lots of lines, those should be extracted.

Implement Object Oriented Programming concepts

Problem

Currently, we have no object-oriented programming (OOP) principles employed in the project. This will make it difficult when trying to implement new features later during the development of the package. There will also be increased complexity as we continue to develop the project without any OOP concepts.

Solution

Classes should be implemented in each of the function files.
Example: race_schedule.py can contain a class RaceSchedule, that accepts JSON data and processes it.

This change will potentially reduce the difficulty during debugging. The readability of the code will also be increased, thus making it easier for new developers to begin contributing.

Add function to get team info

A function that returns basic information about the team, such as:

  • Team name
  • Team headquarters
  • Team principal/chief
  • Chassis name
  • Number of fastest laps/ pole positions/ WCCs

Update noxfile.py

Description

Update noxfile.py to automate testing and generating documents.

  • generate docs
  • static check
  • lint
  • tests
  • code coverage

Add get_drivers() function

A get_drivers() function would be a great addition to the project. This function can probably accept the year as a parameter, and race round can be an optional parameter. The function should return a DataFrame containing driver names, numbers, nationality and data of birth.

Example:

  • lap_times(year) -> Returns drivers that raced in a specified year
  • lap_times(year, race_round) -> Returns drivers that raced in a particular race in a specified year

Fix None data for driver numbers

The get_drivers() function that was implemented in #45, contains a workaround for driver numbers at L36-L39.

The Ergast API states that not all drivers had a permanent number before 2014. However, there are some drivers in their database that have permanent numbers before 2014. (See this example with drivers from 2010)

To get driver numbers before 2014, get_drivers() should be modified to include driver numbers for each year, and simply return None, if a driver does not have a number.

Add a qualifying_results() function

A qualifying_results() function would be a great addition to the project. This function should accept year and race round as parameters. The function should return a DataFrame containing:

  • qualifying position
  • driver names
  • driver numbers
  • constructors
  • qualifying times for Q1, Q2, and Q3.

The function should also accept an optional parameter pos. This can be utilized to obtain qualifying results with a specific finishing position.

Example:

  • qualifying_results(2022, 3) -> Returns qualifying results for the 3rd race in 2022 (API data here)
  • lap_times(2022, pos=1) -> Returns drivers that got pole position in 2022 (API data here)

Update Python version in workflow

Is your feature request related to a problem? Please describe.

Python 3.11.0 is released. So, change the python version used in workflow.

As is
[ "3.8", "3.9", "3.10"]

To be(draft)
["3.9", "3.10", "3.11"]

Add sprint qualifying results

Add Function sprint_qualifying_results() to return a DataFrame containing sprint race results which will take year and round as parameters.

Add Pylint workflow and optimize code format

Pylint should be added to the workflow to ensure developers follow the best practices to write clean code, and meet all programming conventions.

The current code does not meet the PEP8 convention, so some changes will have to be made.

[BUGFIX] Raise ValueError for incorrect years

Recommended Bug Fix

The Problem

A nasty error is thrown when users enter an invalid year into certain functions such as get_drivers() and get_constructors().

The solution

A ValueError exception should be raised when the user enters an invalid year into get_drivers() and get_constructors().

Examples:

  • get_drivers(01)
  • get_constructors(3034)
  • get_drivers(1901)

The above functions should return a ValueError, stating that only values from 1950 to 2022 are considered valid years.

This same logic must be applied to pit_stops , finishing_status , and all other functions in the package. NOTE: Pit stop data is only available from 2012 onwards.

Create get_circuits()

This package should contain a function capable of returning circuit information such as circuit names and locations. The reference page for this data can be found here.

A function called get_circuits() may be created, that accepts race year as an optional parameter, and returns a DataFrame of circuits visited in that year, and their location. If the year is not provided, return all circuits used in F1 history.

Example:
get_circuits(2022) -> Returns all circuts visited in 2022 and the locations
get_circuits() -> Returns all circuits in F1 history, and the locations

Add FP3_results() function

Since it gives a good idea of how the race might go down. Can you assign me to work on this issue?
Do add the hacktoberfest or hacktoberfest-accepted label to it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.