├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ ├── check-standard.yaml │ ├── pkgdown.yaml │ ├── style.yaml │ └── test-coverage.yaml ├── .gitignore ├── CRAN-SUBMISSION ├── DESCRIPTION ├── GAfile.html ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── NEWS.md ├── R ├── circuit_details.R ├── clear_f1_cache.R ├── load_circuits.R ├── load_constructors.R ├── load_driver_telemetry.R ├── load_drivers.R ├── load_laps.R ├── load_pitstops.R ├── load_quali.R ├── load_race_session.R ├── load_results.R ├── load_schedule.R ├── load_session_laps.R ├── load_sprint.R ├── load_standings.R ├── plot_fastest.R ├── plotting_style.R ├── theme_dark_f1.R ├── utils.R └── zzz.R ├── README.Rmd ├── README.md ├── _pkgdown.yml ├── cran-comments.md ├── doc ├── ergast-data-analysis.R ├── ergast-data-analysis.Rmd ├── ergast-data-analysis.html ├── introduction.R ├── introduction.Rmd ├── introduction.html ├── plotting-turn-info.R ├── plotting-turn-info.Rmd ├── plotting-turn-info.html ├── setup_fastf1.R ├── setup_fastf1.Rmd └── setup_fastf1.html ├── docs ├── 404.html ├── LICENSE-text.html ├── LICENSE.html ├── apple-touch-icon-120x120.png ├── apple-touch-icon-152x152.png ├── apple-touch-icon-180x180.png ├── apple-touch-icon-60x60.png ├── apple-touch-icon-76x76.png ├── apple-touch-icon.png ├── articles │ ├── ergast-data-analysis-driver_laptime_scatterplot-1.png │ ├── ergast-data-analysis-drivers_laptimes-1.png │ ├── ergast-data-analysis-grid_to_finish_one-1.png │ ├── ergast-data-analysis-grid_to_finish_season-1.png │ ├── ergast-data-analysis-quali_compare-1.png │ ├── ergast-data-analysis-round_position-1.png │ ├── ergast-data-analysis-rounds_points-1.png │ ├── ergast-data-analysis.html │ ├── index.html │ ├── introduction-pitstop-1.png │ ├── introduction-session_laps-1.png │ ├── introduction-simple_plot-1.png │ ├── introduction-telem_plotting-1.png │ ├── introduction-triple_plot-1.png │ ├── introduction-use_builtin-1.png │ ├── introduction-use_theme-1.png │ ├── introduction.html │ ├── introduction_files │ │ ├── accessible-code-block-0.0.1 │ │ │ └── empty-anchor.js │ │ └── figure-html │ │ │ ├── pitstop-1.png │ │ │ ├── session_laps-1.png │ │ │ ├── simple_plot-1.png │ │ │ ├── telem plotting-1.png │ │ │ ├── triple_plot-1.png │ │ │ ├── unnamed-chunk-1-1.png │ │ │ ├── unnamed-chunk-2-1.png │ │ │ ├── unnamed-chunk-3-1.png │ │ │ ├── unnamed-chunk-4-1.png │ │ │ ├── unnamed-chunk-5-1.png │ │ │ ├── unnamed-chunk-6-1.png │ │ │ ├── unnamed-chunk-7-1.png │ │ │ ├── use_builtin-1.png │ │ │ └── use_theme-1.png │ └── setup_fastf1.html ├── authors.html ├── bootstrap-toc.css ├── bootstrap-toc.js ├── deps │ ├── bootstrap-5.1.0 │ │ ├── bootstrap.bundle.min.js │ │ ├── bootstrap.bundle.min.js.map │ │ ├── bootstrap.min.css │ │ ├── font.css │ │ └── fonts │ │ │ ├── 1Ptxg8zYS_SKggPN4iEgvnHyvveLxVs9pbCIPrc.woff │ │ │ ├── 1Ptxg8zYS_SKggPN4iEgvnHyvveLxVvaorCIPrc.woff │ │ │ ├── 4iCs6KVjbNBYlgo6ew.woff │ │ │ ├── 4iCs6KVjbNBYlgoKfw7w.woff │ │ │ ├── 4iCv6KVjbNBYlgoCxCvTtA.woff │ │ │ ├── 4iCv6KVjbNBYlgoCxCvjsGyL.woff │ │ │ ├── 6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7nsDQ.woff │ │ │ ├── 6xK1dSBYKcSV-LCoeQqfX1RYOo3qPa7j.woff │ │ │ ├── 6xK3dSBYKcSV-LCoeQqfX1RYOo3aPA.woff │ │ │ ├── 6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7j.woff │ │ │ ├── 6xKydSBYKcSV-LCoeQqfX1RYOo3i54rAkw.woff │ │ │ ├── 6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vAkw.woff │ │ │ ├── 6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdo.woff │ │ │ ├── 6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zAkw.woff │ │ │ ├── 6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwlxdo.woff │ │ │ ├── CSR54z1Qlv-GDxkbKVQ_dFsvWNRevw.woff │ │ │ ├── CSR54z1Qlv-GDxkbKVQ_dFsvaNA.woff │ │ │ ├── CSR64z1Qlv-GDxkbKVQ_TOQ.woff │ │ │ ├── CSR64z1Qlv-GDxkbKVQ_fOAKSw.woff │ │ │ ├── JTURjIg1_i6t8kCHKm45_ZpC7g0.woff │ │ │ ├── JTURjIg1_i6t8kCHKm45_dJE7g0.woff │ │ │ ├── JTUSjIg1_i6t8kCHKm45xW0.woff │ │ │ ├── KFOlCnqEu92Fr1MmEU9fBBc-.woff │ │ │ ├── KFOlCnqEu92Fr1MmEU9vAA.woff │ │ │ ├── KFOlCnqEu92Fr1MmSU5fBBc-.woff │ │ │ ├── KFOlCnqEu92Fr1MmSU5vAA.woff │ │ │ ├── KFOlCnqEu92Fr1MmWUlfBBc-.woff │ │ │ ├── KFOlCnqEu92Fr1MmWUlvAA.woff │ │ │ ├── KFOmCnqEu92Fr1Me5g.woff │ │ │ ├── KFOmCnqEu92Fr1Mu4mxM.woff │ │ │ ├── QGYpz_kZZAGCONcK2A4bGOj8mNhL.woff │ │ │ ├── S6u8w4BMUTPHjxsAXC-s.woff │ │ │ ├── S6u8w4BMUTPHjxswWA.woff │ │ │ ├── S6u9w4BMUTPHh6UVSwiPHw.woff │ │ │ ├── S6u9w4BMUTPHh6UVeww.woff │ │ │ ├── S6u9w4BMUTPHh7USSwiPHw.woff │ │ │ ├── S6u9w4BMUTPHh7USeww.woff │ │ │ ├── S6uyw4BMUTPHjx4wWA.woff │ │ │ ├── S6uyw4BMUTPHvxo.woff │ │ │ ├── UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuFuYMZs.woff │ │ │ ├── UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuI6fMZs.woff │ │ │ ├── UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfMZs.woff │ │ │ ├── XRXV3I6Li01BKof4MQ.woff │ │ │ ├── XRXW3I6Li01BKofA6sKkZQ.woff │ │ │ ├── XRXW3I6Li01BKofAjsOkZQ.woff │ │ │ ├── memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk5hkWVAexg.woff │ │ │ ├── memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk5hkaVQ.woff │ │ │ ├── memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk8ZkWVAexg.woff │ │ │ ├── memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk8ZkaVQ.woff │ │ │ ├── memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0RkyFjWVAexg.woff │ │ │ ├── memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0RkyFjaVQ.woff │ │ │ ├── memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsg-1x4gaVQ.woff │ │ │ ├── memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsg-1y4k.woff │ │ │ ├── memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsiH0B4gaVQ.woff │ │ │ ├── memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsiH0C4k.woff │ │ │ ├── memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0B4gaVQ.woff │ │ │ ├── memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0C4k.woff │ │ │ ├── pe03MImSLYBIv1o4X1M8cc9iB_5p.woff │ │ │ ├── pe0qMImSLYBIv1o4X1M8cfe5.woff │ │ │ └── q5uGsou0JOdh94bfvQlr.woff │ ├── data-deps.txt │ └── jquery-3.6.0 │ │ ├── jquery-3.6.0.js │ │ ├── jquery-3.6.0.min.js │ │ └── jquery-3.6.0.min.map ├── docsearch.css ├── docsearch.js ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon.ico ├── index.html ├── link.svg ├── logo.svg ├── news │ └── index.html ├── pkgdown.css ├── pkgdown.js ├── pkgdown.yml ├── reference │ ├── Rplot001.png │ ├── change_cache.html │ ├── clear_cache.html │ ├── clear_f1_cache.html │ ├── constructor_data.html │ ├── correct_track_ratio.html │ ├── dot-get_current_season.html │ ├── dot-get_fastf1_version.html │ ├── dot-load_circuits.html │ ├── dot-load_constructors.html │ ├── dot-load_drivers.html │ ├── dot-load_laps.html │ ├── dot-load_pitstops.html │ ├── dot-load_quali.html │ ├── dot-load_results.html │ ├── dot-load_schedule.html │ ├── dot-load_sprint.html │ ├── dot-load_standings.html │ ├── driver_constructor_data.html │ ├── figures │ │ ├── README-plot-1.png │ │ ├── logo.png │ │ └── logo.svg │ ├── get_current_season.html │ ├── get_driver_telemetry.html │ ├── get_driver_telemtery.html │ ├── get_ergast_content.html │ ├── get_fastf1_version.html │ ├── index.html │ ├── load_circuits.html │ ├── load_constructors.html │ ├── load_driver_telemetry.html │ ├── load_driver_telemtery.html │ ├── load_drivers.html │ ├── load_laps.html │ ├── load_pitstops.html │ ├── load_quali.html │ ├── load_race_session.html │ ├── load_results.html │ ├── load_schedule.html │ ├── load_session_laps.html │ ├── load_sprint.html │ ├── load_standings.html │ ├── plot_fastest.html │ ├── setup_fastf1.html │ ├── theme_dark_f1.html │ └── time_to_sec.html ├── search.json └── sitemap.xml ├── man ├── add_col_if_absent.Rd ├── change_cache.Rd ├── check_ff1_session_loaded.Rd ├── check_ff1_version.Rd ├── clear_cache.Rd ├── correct_track_ratio.Rd ├── driver_team_lookup.Rd ├── figures │ ├── README-plot-1.png │ ├── logo.png │ └── logo.svg ├── get_aesthetics.Rd ├── get_current_season.Rd ├── get_driver_telemetry.Rd ├── get_ergast_content.Rd ├── get_fastf1_version.Rd ├── get_jolpica_content.Rd ├── get_session.Rd ├── get_tire_compounds.Rd ├── load_circuit_details.Rd ├── load_circuits.Rd ├── load_constructors.Rd ├── load_driver_telemetry.Rd ├── load_drivers.Rd ├── load_laps.Rd ├── load_pitstops.Rd ├── load_quali.Rd ├── load_race_session.Rd ├── load_results.Rd ├── load_schedule.Rd ├── load_session_laps.Rd ├── load_sprint.Rd ├── load_standings.Rd ├── plot_fastest.Rd ├── setup_fastf1.Rd ├── theme_dark_f1.Rd └── time_to_sec.Rd ├── pkgdown ├── _pkgdown.yml └── favicon │ ├── apple-touch-icon-120x120.png │ ├── apple-touch-icon-152x152.png │ ├── apple-touch-icon-180x180.png │ ├── apple-touch-icon-60x60.png │ ├── apple-touch-icon-76x76.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ └── favicon.ico ├── tests ├── testthat.R └── testthat │ ├── setup.R │ ├── test-clear_f1_cache.R │ ├── test-load_circuit_details.R │ ├── test-load_circuits.R │ ├── test-load_constructors.R │ ├── test-load_driver_telemetry.R │ ├── test-load_drivers.R │ ├── test-load_laps.R │ ├── test-load_pitstops.R │ ├── test-load_quali.R │ ├── test-load_race_session.R │ ├── test-load_results.R │ ├── test-load_schedule.R │ ├── test-load_session_laps.R │ ├── test-load_sprint.R │ ├── test-load_standings.R │ ├── test-plot_fastest.R │ ├── test-plotting_style.R │ └── test-utils.R └── vignettes ├── .gitignore ├── alonso-penalty-2024-alo-plots-1.png ├── alonso-penalty-2024-alo-throttle-1.png ├── alonso-penalty-2024-rus-plots-1.png ├── alonso-penalty-2024.Rmd ├── alonso-penalty-2024.Rmd.orig ├── introduction-pitstop-1.png ├── introduction-simple_plot-1.png ├── introduction-telem_plotting-1.png ├── introduction-triple_plot-1.png ├── introduction-tyre_life-1.png ├── introduction-use_builtin-1.png ├── introduction-use_theme-1.png ├── introduction.Rmd ├── introduction.Rmd.orig ├── jolpica-data-analysis-driver_laptime_scatterplot-1.png ├── jolpica-data-analysis-drivers_laptimes-1.png ├── jolpica-data-analysis-grid_to_finish_one-1.png ├── jolpica-data-analysis-grid_to_finish_season-1.png ├── jolpica-data-analysis-quali_compare-1.png ├── jolpica-data-analysis-remade_rounds_points-1.png ├── jolpica-data-analysis-round_position-1.png ├── jolpica-data-analysis-rounds_points-1.png ├── jolpica-data-analysis.Rmd ├── jolpica-data-analysis.Rmd.orig ├── plotting-turn-info-basic_track_plot-1.png ├── plotting-turn-info-relabelled_gear_plot-1.png ├── plotting-turn-info-telem_plot-1.png ├── plotting-turn-info-telem_with_corners-1.png ├── plotting-turn-info.Rmd ├── plotting-turn-info.Rmd.orig ├── precompile.R └── setup_fastf1.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^f1dataR\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^_pkgdown\.yml$ 4 | ^docs$ 5 | ^pkgdown$ 6 | ^\.github$ 7 | ^GAFile\.html$ 8 | ^README\.Rmd$ 9 | ^data-raw$ 10 | ^vignettes/\d{4}/*$ 11 | ^fastf1_http_cache.sqlite$ 12 | ^LICENSE\.md$ 13 | ^\d{4}/*$ 14 | ^cran-comments\.md$ 15 | ^vignettes/jolpica-data-analysis.Rmd.orig$ 16 | ^vignettes/introduction.Rmd.orig$ 17 | ^doc$ 18 | ^Meta$ 19 | ^CRAN-SUBMISSION$ 20 | ^\w*.pem$ 21 | ^revdep$ 22 | cobertura.xml 23 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | release: 9 | types: [published] 10 | workflow_dispatch: 11 | 12 | name: pkgdown 13 | 14 | permissions: read-all 15 | 16 | jobs: 17 | pkgdown: 18 | runs-on: ubuntu-latest 19 | # Only restrict concurrency for non-PR jobs 20 | concurrency: 21 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} 22 | env: 23 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 24 | permissions: 25 | contents: write 26 | steps: 27 | - uses: actions/checkout@v4 28 | 29 | - uses: r-lib/actions/setup-pandoc@v2 30 | 31 | - uses: r-lib/actions/setup-r@v2 32 | with: 33 | use-public-rspm: true 34 | 35 | - uses: r-lib/actions/setup-r-dependencies@v2 36 | with: 37 | extra-packages: any::pkgdown, local::. 38 | needs: website 39 | 40 | - name: Build site 41 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) 42 | shell: Rscript {0} 43 | 44 | - name: Deploy to GitHub pages 🚀 45 | if: github.event_name != 'pull_request' 46 | uses: JamesIves/github-pages-deploy-action@v4.5.0 47 | with: 48 | clean: false 49 | branch: gh-pages 50 | folder: docs 51 | -------------------------------------------------------------------------------- /.github/workflows/style.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | paths: ["**.[rR]", "**.[qrR]md", "**.[rR]markdown", "**.[rR]nw", "**.[rR]profile"] 6 | 7 | name: Style 8 | 9 | jobs: 10 | style: 11 | runs-on: ubuntu-latest 12 | env: 13 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 14 | steps: 15 | - name: Checkout repo 16 | uses: actions/checkout@v3 17 | with: 18 | fetch-depth: 0 19 | 20 | - name: Setup R 21 | uses: r-lib/actions/setup-r@v2 22 | with: 23 | use-public-rspm: true 24 | 25 | - name: Install dependencies 26 | uses: r-lib/actions/setup-r-dependencies@v2 27 | with: 28 | extra-packages: any::styler, any::roxygen2, any::devtools 29 | needs: styler 30 | 31 | - name: Enable styler cache 32 | run: styler::cache_activate() 33 | shell: Rscript {0} 34 | 35 | - name: Determine cache location 36 | id: styler-location 37 | run: | 38 | cat( 39 | "location=", 40 | styler::cache_info(format = "tabular")$location, 41 | "\n", 42 | file = Sys.getenv("GITHUB_OUTPUT"), 43 | append = TRUE, 44 | sep = "" 45 | ) 46 | shell: Rscript {0} 47 | 48 | - name: Cache styler 49 | uses: actions/cache@v3 50 | with: 51 | path: ${{ steps.styler-location.outputs.location }} 52 | key: ${{ runner.os }}-styler-${{ github.sha }} 53 | restore-keys: | 54 | ${{ runner.os }}-styler- 55 | ${{ runner.os }}- 56 | 57 | - name: Style 58 | run: | 59 | styler::style_pkg() 60 | devtools::document() 61 | shell: Rscript {0} 62 | 63 | - name: Commit and push changes 64 | run: | 65 | if FILES_TO_COMMIT=($(git diff-index --name-only ${{ github.sha }} \ 66 | | egrep --ignore-case '\.(R|[qR]md|Rmarkdown|Rnw|Rprofile)$')) 67 | then 68 | git config --local user.name "$GITHUB_ACTOR" 69 | git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com" 70 | git commit ${FILES_TO_COMMIT[*]} -m "Style & Document code" 71 | git pull --ff-only 72 | git push origin 73 | else 74 | echo "No changes to commit." 75 | fi 76 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | inst/doc 3 | fastf1_http_cache.sqlite 4 | *.pkl 5 | *.ff1pkl 6 | .Rhistory 7 | tests/testthat/tst_* 8 | f1dataR.Rproj 9 | /Meta/ 10 | /tst_*go 11 | Rplots.pdf 12 | .DS_Store 13 | docs 14 | /doc/ 15 | .RData 16 | /revdep/ 17 | Thumbs.db 18 | cobertura.xml 19 | -------------------------------------------------------------------------------- /CRAN-SUBMISSION: -------------------------------------------------------------------------------- 1 | Version: 2.0.1 2 | Date: 2025-03-27 00:56:02 UTC 3 | SHA: 5003f7e68c8c930f4c6ed0b9d426516d7ce79635 4 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: f1dataR 2 | Title: Access Formula 1 Data 3 | Version: 2.0.1.9000 4 | Authors@R: c( 5 | person("Santiago", "Casanova", , "santiago.casanova@yahoo.com", role = c("aut", "cre", "cph")), 6 | person("Philip", "Bulsink", , "bulsinkp@gmail.com", role = "aut", 7 | comment = c(ORCID = "0000-0001-9668-2429")) 8 | ) 9 | Description: Obtain Formula 1 data via the 'Jolpica API' and the unofficial API via the 'fastf1' 'Python' library . 10 | Config/reticulate: 11 | list( 12 | packages = list( 13 | list(package = "fastf1", pip = TRUE) 14 | ) 15 | ) 16 | License: MIT + file LICENSE 17 | Encoding: UTF-8 18 | Roxygen: list(markdown = TRUE) 19 | RoxygenNote: 7.3.2 20 | Depends: 21 | R (>= 3.5.0), 22 | reticulate (>= 1.14), 23 | Imports: 24 | glue, 25 | magrittr, 26 | tibble, 27 | jsonlite, 28 | httr2, 29 | memoise, 30 | janitor, 31 | dplyr, 32 | tidyr, 33 | rlang, 34 | lifecycle, 35 | cli, 36 | rappdirs, 37 | cachem, 38 | withr 39 | Suggests: 40 | ggplot2, 41 | httptest2, 42 | knitr, 43 | rmarkdown, 44 | testthat (>= 3.0.0), 45 | VignetteBuilder: knitr 46 | URL: https://scasanova.github.io/f1dataR/, https://github.com/SCasanova/f1dataR 47 | BugReports: https://github.com/SCasanova/f1dataR/issues 48 | Config/testthat/edition: 3 49 | -------------------------------------------------------------------------------- /GAfile.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2023 2 | COPYRIGHT HOLDER: f1dataR authors 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2023 f1dataR authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(change_cache) 4 | export(clear_cache) 5 | export(clear_f1_cache) 6 | export(correct_track_ratio) 7 | export(get_current_season) 8 | export(get_driver_abbreviation) 9 | export(get_driver_color) 10 | export(get_driver_color_map) 11 | export(get_driver_colour) 12 | export(get_driver_colour_map) 13 | export(get_driver_name) 14 | export(get_driver_style) 15 | export(get_driver_telemetry) 16 | export(get_drivers_by_team) 17 | export(get_fastf1_version) 18 | export(get_session_drivers_and_teams) 19 | export(get_team_by_driver) 20 | export(get_team_color) 21 | export(get_team_colour) 22 | export(get_team_name) 23 | export(get_tire_compounds) 24 | export(load_circuit_details) 25 | export(load_circuits) 26 | export(load_constructors) 27 | export(load_driver_telemetry) 28 | export(load_drivers) 29 | export(load_laps) 30 | export(load_pitstops) 31 | export(load_quali) 32 | export(load_race_session) 33 | export(load_results) 34 | export(load_schedule) 35 | export(load_session_laps) 36 | export(load_sprint) 37 | export(load_standings) 38 | export(plot_fastest) 39 | export(setup_fastf1) 40 | export(theme_dark_f1) 41 | import(reticulate) 42 | importFrom(magrittr,"%>%") 43 | importFrom(rlang,.data) 44 | -------------------------------------------------------------------------------- /R/circuit_details.R: -------------------------------------------------------------------------------- 1 | #' Load Circuit Information 2 | #' 3 | #' @description Loads circuit details for a specific race session. Note that different track layouts are used at some 4 | #' circuits depending on the year of the race. 5 | #' 6 | #' Useful for visualizing or annotating data. Contains information on corners, marshal_lights and marshal_sectors. 7 | #' 8 | #' Each set of these track marker types is returned as a tibble. 9 | #' 10 | #' Also returns an angle (in degrees) to indicate the amount of rotation of the telemetry to visually align the two. 11 | #' 12 | #' More information on the data provided (and uses) can be seen at https://docs.fastf1.dev/circuit_info.html#fastf1.mvapi.CircuitInfo.corners 13 | #' 14 | #' Note that this is an exposition of FastF1 data. As such, caching is recommended (and default behavior). 15 | #' Cache directory can be set by setting `option(f1dataR.cache = [cache dir])`, 16 | #' default is the current working directory. 17 | #' 18 | #' If you have trouble with errors mentioning 'fastf1' or 'get_fastf1_version()' read the 19 | #' 'Setup FastF1 Connection vignette (run \code{vignette('setup_fastf1', 'f1dataR')}). 20 | #' 21 | #' @param season number from 2018 to current season. Defaults to current season. 22 | #' @param round number from 1 to 23 (depending on season selected). Also accepts race name. 23 | #' @param log_level Detail of logging from fastf1 to be displayed. Choice of: 24 | #' `'DEBUG'`, `'INFO'`, `'WARNING'`, `'ERROR'` and `'CRITICAL'`. See 25 | #' \href{https://docs.fastf1.dev/fastf1.html#configure-logging-verbosity}{fastf1 documentation}. 26 | #' @import reticulate 27 | #' @return A list of tibbles containing corner number, marshall post number, or marshall segment, plus a numeric value for 28 | #' rotational offset of the data compared to telemetry data. 29 | #' 30 | #' The tibbles all have the following structure: 31 | #' `x` and `y` specify the position on the track map 32 | #' `number` is the number of the corner. Letter is optionally used to differentiate corners with the same number on some circuits, e.g. “2A”. 33 | #' `angle` is an angle in degrees, used to visually offset the marker’s placement on a track map in a logical direction (usually orthogonal to the track). 34 | #' `distance` is the location of the marker as a distance from the start/finish line. 35 | #' 36 | #' @export 37 | load_circuit_details <- function(season = get_current_season(), round = 1, log_level = "WARNING") { 38 | # Deprecation Checks 39 | check_ff1_version() 40 | 41 | # Function Code 42 | status <- load_race_session(obj_name = "session", season = season, round = round, session = "R", log_level = log_level) 43 | 44 | if (is.null(status)) { 45 | # Failure to load - escape 46 | return(NULL) 47 | } 48 | 49 | py_env <- reticulate::py_run_string("circuit_info = session.get_circuit_info()") 50 | 51 | circuit_info <- reticulate::py_to_r(reticulate::py_get_item(py_env, "circuit_info")) 52 | 53 | corners <- circuit_info$corners %>% 54 | tibble::tibble() %>% 55 | janitor::clean_names() 56 | 57 | marshal_post <- circuit_info$marshal_lights %>% 58 | tibble::tibble() %>% 59 | janitor::clean_names() 60 | 61 | marshal_sectors <- circuit_info$marshal_sectors %>% 62 | tibble::tibble() %>% 63 | janitor::clean_names() 64 | 65 | rotation <- circuit_info$rotation 66 | 67 | return(list( 68 | "corners" = corners, "marshal_posts" = marshal_post, "marshal_sectors" = marshal_sectors, 69 | "rotation" = rotation 70 | )) 71 | } 72 | -------------------------------------------------------------------------------- /R/load_circuits.R: -------------------------------------------------------------------------------- 1 | #' Load Circuit Info 2 | #' 3 | #' @description Loads circuit info for all circuits in a given season. Use `.load_circuits()` 4 | #' for an uncached version of this function 5 | #' 6 | #' @param season number from 1950 to current season (defaults to current season). 7 | #' @export 8 | #' @return A tibble with one row per circuit 9 | load_circuits <- function(season = get_current_season()) { 10 | if (season != "current" && (season < 1950 || season > get_current_season())) { 11 | cli::cli_abort('{.var season} must be between 1950 and {get_current_season()} (or use "current")') 12 | } 13 | 14 | url <- glue::glue("{season}/circuits.json?limit=40", 15 | season = season 16 | ) 17 | 18 | data <- get_jolpica_content(url) 19 | 20 | if (is.null(data)) { 21 | return(NULL) 22 | } 23 | 24 | data$MRData$CircuitTable$Circuits %>% 25 | tidyr::unnest(cols = c("Location")) %>% 26 | dplyr::select( 27 | "circuitId", 28 | "circuitName", 29 | "lat":"country" 30 | ) %>% 31 | tibble::as_tibble() %>% 32 | janitor::clean_names() 33 | } 34 | -------------------------------------------------------------------------------- /R/load_constructors.R: -------------------------------------------------------------------------------- 1 | #' Load Constructor Info 2 | #' 3 | #' @description Loads constructor info for all participants in a given season. 4 | #' Use `.load_constructors()`for an uncached version of this function 5 | #' 6 | #' @importFrom magrittr "%>%" 7 | #' @export 8 | #' @return A tibble with one row per constructor 9 | load_constructors <- function() { 10 | lim <- 100 11 | url <- glue::glue("constructors.json?limit={lim}", lim = lim) 12 | data <- get_jolpica_content(url) 13 | 14 | if (is.null(data)) { 15 | return(NULL) 16 | } 17 | 18 | total <- data$MRData$total %>% as.numeric() 19 | offset <- data$MRData$offset %>% as.numeric() 20 | 21 | full <- data$MRData$ConstructorTable$Constructors 22 | 23 | # Iterate over the request until completed 24 | while (offset + lim <= total) { 25 | offset <- offset + lim 26 | 27 | url <- glue::glue("constructors.json?limit={lim}&offset={offset}", 28 | lim = lim, offset = offset 29 | ) 30 | data <- get_jolpica_content(url) 31 | 32 | if (is.null(data)) { 33 | return(NULL) 34 | } 35 | 36 | full <- dplyr::bind_rows(full, data$MRData$ConstructorTable$Constructors) 37 | } 38 | 39 | return(full %>% 40 | dplyr::select("constructorId", "name", "nationality") %>% 41 | janitor::clean_names()) 42 | } 43 | -------------------------------------------------------------------------------- /R/load_driver_telemetry.R: -------------------------------------------------------------------------------- 1 | #' Load Telemetry Data for a Driver 2 | #' 3 | #' @description Receives season, race number, driver code, and an optional fastest lap only 4 | #' argument to output car telemetry for the selected situation. 5 | #' Example usage of this code can be seen in the Introduction vignette (run 6 | #' \code{vignette('introduction', 'f1dataR')} to read). Multiple drivers' telemetry can be appended 7 | #' to one data frame by the user. 8 | #' 9 | #' If you have trouble with errors mentioning 'fastf1' or 'get_fastf1_version()' read the 10 | #' "Setup FastF1 Connection" vignette (run \code{vignette('setup_fastf1', 'f1dataR')}). 11 | #' 12 | #' @param season number from 2018 to current season (defaults to current season). 13 | #' @param round number from 1 to 23 (depending on season selected). Also accepts race name. 14 | #' @param session the code for the session to load Options are `'FP1'`, `'FP2'`, `'FP3'`, 15 | #' `'Q'`, `'S'`, `'SS'`, `'SQ'`, and `'R'`. Default is `'R'`, which refers to Race. 16 | #' @param driver three letter driver code (see `load_drivers()` for a list) 17 | #' @param laps which lap's telemetry to return. One of an integer lap number (<= total laps in the race), `fastest`, 18 | #' or `all`. Note that integer lap choice requires `fastf1` version 3.0 or greater. 19 | #' @param log_level Detail of logging from fastf1 to be displayed. Choice of: 20 | #' `'DEBUG'`, `'INFO'`, `'WARNING'`, `'ERROR'` and `'CRITICAL'`. See \href{https://docs.fastf1.dev/fastf1.html#configure-logging-verbosity}{fastf1 documentation}. 21 | #' @param race `r lifecycle::badge("deprecated")` `race` is no longer supported, use `round`. 22 | #' @param fastest_only `r lifecycle::badge("deprecated")` `fastest_only` is no longer supported, indicated preferred 23 | #' laps in `laps`. 24 | #' @importFrom magrittr "%>%" 25 | #' @return A tibble with telemetry data for selected driver/session. 26 | #' @import reticulate 27 | #' @export 28 | #' @examples 29 | #' if (interactive()) { 30 | #' telem <- load_driver_telemetry( 31 | #' season = 2023, 32 | #' round = "Bahrain", 33 | #' session = "Q", 34 | #' driver = "HAM", 35 | #' laps = "fastest" 36 | #' ) 37 | #' } 38 | #' 39 | load_driver_telemetry <- function(season = get_current_season(), round = 1, session = "R", driver, laps = "fastest", 40 | log_level = "WARNING", race = lifecycle::deprecated(), 41 | fastest_only = lifecycle::deprecated()) { 42 | # Deprecation Checks 43 | if (lifecycle::is_present(race)) { 44 | lifecycle::deprecate_stop("1.4.0", "load_driver_telemetry(race)", "load_driver_telemetry(round)") 45 | } 46 | if (lifecycle::is_present(fastest_only)) { 47 | lifecycle::deprecate_stop("1.4.0", "load_driver_telemetry(fastest_only)", "load_driver_telemetry(laps)") 48 | } 49 | check_ff1_version() 50 | 51 | # Function Code 52 | # Param checks 53 | if (!(laps %in% c("fastest", "all"))) { 54 | if (is.numeric(laps)) { 55 | if (as.numeric(laps) != as.integer(laps)) { 56 | cli::cli_abort("{.var laps} must be one of `fastest`, `all` or an integer value") 57 | } 58 | } else { 59 | cli::cli_abort("{.var laps} must be one of `fastest`, `all` or an integer value") 60 | } 61 | } 62 | 63 | status <- load_race_session(obj_name = "session", season = season, round = round, session = session, log_level = log_level) 64 | 65 | if (is.null(status)) { 66 | # Failure to load - escape 67 | return(NULL) 68 | } 69 | 70 | if (laps == "fastest") { 71 | reticulate::py_run_string(glue::glue("tel = session.laps.pick_drivers('{driver}').pick_fastest().get_telemetry().add_distance().add_driver_ahead()", 72 | driver = driver 73 | )) 74 | } else if (laps != "all") { 75 | reticulate::py_run_string(glue::glue("tel = session.laps.pick_drivers('{driver}').pick_lap({laps}).get_telemetry().add_distance().add_driver_ahead()", 76 | driver = driver, laps = laps 77 | )) 78 | } else { 79 | reticulate::py_run_string(glue::glue("tel = session.laps.pick_drivers('{driver}').get_telemetry().add_distance().add_driver_ahead()", 80 | driver = driver 81 | )) 82 | } 83 | py_env <- reticulate::py_run_string(paste("tel.SessionTime = tel.SessionTime.dt.total_seconds()", 84 | "tel.Time = tel.Time.dt.total_seconds()", 85 | sep = "\n" 86 | )) 87 | 88 | tel <- reticulate::py_to_r(reticulate::py_get_item(py_env, "tel")) 89 | 90 | tel %>% 91 | dplyr::mutate(driverCode = driver) %>% 92 | tibble::tibble() %>% 93 | janitor::clean_names() 94 | } 95 | 96 | #' @inherit load_driver_telemetry title return params 97 | #' @description 98 | #' `r lifecycle::badge("deprecated")` 99 | #' 100 | #' `get_driver_telemetry()` was renamed to `load_driver_telemetry()` to create a more 101 | #' consistent API. 102 | #' @keywords internal 103 | #' @export 104 | 105 | get_driver_telemetry <- 106 | function(season = get_current_season(), 107 | round = 1, 108 | session = "R", 109 | driver, 110 | laps = "fastest", 111 | log_level = "WARNING", 112 | fastest_only = lifecycle::deprecated(), 113 | race = lifecycle::deprecated()) { 114 | lifecycle::deprecate_stop( 115 | "1.4.0", 116 | "get_driver_telemetry()", 117 | "load_driver_telemetry()" 118 | ) 119 | } 120 | -------------------------------------------------------------------------------- /R/load_drivers.R: -------------------------------------------------------------------------------- 1 | #' Load Driver Info 2 | #' 3 | #' @description Loads driver info for all participants in a given season. 4 | #' Use `.load_drivers()` for an uncached version of this function. 5 | #' 6 | #' @param season number from 1950 to current season (defaults to current season). 7 | #' @importFrom magrittr "%>%" 8 | #' @export 9 | #' @return A tibble with columns driver_id (unique and recurring), first name, 10 | #' last name, nationality, date of birth (yyyy-mm-dd format), driver code, and 11 | #' permanent number (for post-2014 drivers). 12 | load_drivers <- function(season = get_current_season()) { 13 | if (season != "current" && (season < 1950 || season > get_current_season())) { 14 | cli::cli_abort('{.var season} must be between 1950 and {get_current_season()} (or use "current")') 15 | } 16 | 17 | url <- glue::glue("{season}/drivers.json?limit=50", 18 | season = season 19 | ) 20 | data <- get_jolpica_content(url) 21 | 22 | if (is.null(data)) { 23 | return(NULL) 24 | } 25 | 26 | data <- data$MRData$DriverTable$Drivers 27 | 28 | data <- add_col_if_absent(data, "code", NA_character_) 29 | data <- add_col_if_absent(data, "permanentNumber", NA_integer_) 30 | 31 | data %>% 32 | dplyr::select( 33 | "driverId", 34 | "givenName", 35 | "familyName", 36 | "nationality", 37 | "dateOfBirth", 38 | "code", 39 | "permanentNumber" 40 | ) %>% 41 | tibble::as_tibble() %>% 42 | janitor::clean_names() 43 | } 44 | -------------------------------------------------------------------------------- /R/load_laps.R: -------------------------------------------------------------------------------- 1 | #' Load Lap by Lap Time Data 2 | #' 3 | #' @description Loads basic lap-by-lap time data for all drivers in a given season 4 | #' and round. Lap time data is available from 1996 onward. Use `.load_laps()` for a uncached version. 5 | #' 6 | #' @param season number from 1996 to current season (defaults to current season). 7 | #' @param round number from 1 to 23 (depending on season selected) and defaults 8 | #' to most recent. Also accepts `'last'`. 9 | #' @param race `r lifecycle::badge("deprecated")` `race` is no longer supported, use `round`. 10 | #' @importFrom magrittr "%>%" 11 | #' @export 12 | #' @return A tibble with columns driver_id (unique and recurring), position 13 | #' during lap, time (in clock form), lap number, time (in seconds), and season. 14 | load_laps <- function(season = get_current_season(), round = "last", race = lifecycle::deprecated()) { 15 | # Deprecation Check 16 | if (lifecycle::is_present(race)) { 17 | lifecycle::deprecate_stop("1.4.0", "load_laps(race)", "load_laps(round)") 18 | } 19 | 20 | # Parameter Check 21 | if (season != "current" && (season < 1996 || season > get_current_season())) { 22 | cli::cli_abort('{.var season} must be between 1996 and {get_current_season()} (or use "current")') 23 | } 24 | 25 | lim <- 100 26 | 27 | # Function Code 28 | url <- glue::glue("{season}/{round}/laps.json?limit={lim}", 29 | season = season, round = round, lim = lim 30 | ) 31 | data <- get_jolpica_content(url) 32 | 33 | if (is.null(data)) { 34 | return(NULL) 35 | } 36 | 37 | total <- data$MRData$total %>% as.numeric() 38 | offset <- data$MRData$offset %>% as.numeric() 39 | 40 | full <- data$MRData$RaceTable$Races$Laps[[1]][2] 41 | 42 | # Iterate over the request until completed 43 | while (offset + lim <= total) { 44 | offset <- offset + lim 45 | 46 | url <- glue::glue("{season}/{round}/laps.json?limit={lim}&offset={offset}", 47 | lim = lim, season = season, round = round, offset = offset 48 | ) 49 | data <- get_jolpica_content(url) 50 | 51 | if (is.null(data)) { 52 | return(NULL) 53 | } 54 | 55 | full <- dplyr::bind_rows(full, data$MRData$RaceTable$Races$Laps[[1]][2]) 56 | } 57 | 58 | laps <- tibble::tibble() 59 | season_text <- ifelse(season == "current", get_current_season(), season) 60 | for (i in seq_len(nrow(full))) { 61 | laps <- dplyr::bind_rows( 62 | laps, 63 | full[[1]][i][[1]] %>% 64 | dplyr::mutate( 65 | lap = i, 66 | time_sec = time_to_sec(.data$time), 67 | season = season_text 68 | ) 69 | ) 70 | } 71 | laps %>% 72 | tibble::tibble() %>% 73 | janitor::clean_names() 74 | } 75 | -------------------------------------------------------------------------------- /R/load_pitstops.R: -------------------------------------------------------------------------------- 1 | #' Load Pitstop Data 2 | #' 3 | #' @description Loads pit stop info (number, lap, time elapsed) for a given race 4 | #' in a season. Pit stop data is available from 2012 onward. 5 | #' Call `.load_pitstops()` for an uncached version. 6 | #' 7 | #' @param season number from 2011 to current season (defaults to current season). 8 | #' @param round number from 1 to 23 (depending on season selected) and defaults 9 | #' to most recent.Also accepts `'last'`. 10 | #' @param race `r lifecycle::badge("deprecated")` `race` is no longer supported, please use `round`. 11 | #' @importFrom magrittr "%>%" 12 | #' @export 13 | #' @return A tibble with columns driver_id, lap, stop (number), time (of day), 14 | #' and stop duration 15 | load_pitstops <- function(season = get_current_season(), round = "last", race = lifecycle::deprecated()) { 16 | # Deprecation check 17 | if (lifecycle::is_present(race)) { 18 | lifecycle::deprecate_stop("1.4.0", "load_pitstops(race)", "load_pitstops(round)") 19 | } 20 | 21 | # Parameter Check 22 | if (season != "current" && (season < 2011 || season > get_current_season())) { 23 | cli::cli_abort('{.var season} must be between 2011 and {get_current_season()} (or use "current")') 24 | } 25 | 26 | # Function Code 27 | url <- glue::glue("{season}/{round}/pitstops.json?limit=100", 28 | season = season, round = round 29 | ) 30 | data <- get_jolpica_content(url) 31 | 32 | if (is.null(data)) { 33 | return(NULL) 34 | } 35 | 36 | data$MRData$RaceTable$Races$PitStops[[1]] %>% 37 | tibble::as_tibble() %>% 38 | janitor::clean_names() 39 | } 40 | -------------------------------------------------------------------------------- /R/load_quali.R: -------------------------------------------------------------------------------- 1 | #' Load Qualifying Results 2 | #' 3 | #' @description Loads qualifying session results for a given season and round. 4 | #' Use `.load_quali()` for an uncached version. 5 | #' 6 | #' @param season number from 2003 to current season (defaults to current season). 7 | #' @param round number from 1 to 23 (depending on season), and defaults 8 | #' to most recent. Also accepts `'last'`. 9 | #' @importFrom magrittr "%>%" 10 | #' @importFrom rlang .data 11 | #' @export 12 | #' @return A tibble with one row per driver 13 | load_quali <- function(season = get_current_season(), round = "last") { 14 | if (season != "current" && (season < 2003 || season > get_current_season())) { 15 | cli::cli_abort('{.var season} must be between 2003 and {get_current_season()} (or use "current")') 16 | } 17 | 18 | url <- glue::glue("{season}/{round}/qualifying.json?limit=40", 19 | season = season, round = round 20 | ) 21 | 22 | data <- get_jolpica_content(url) 23 | 24 | if (is.null(data)) { 25 | return(NULL) 26 | } 27 | 28 | data <- data$MRData$RaceTable$Races$QualifyingResults[[1]] 29 | 30 | data <- add_col_if_absent(data, "Q2", NA_character_) 31 | data <- add_col_if_absent(data, "Q3", NA_character_) 32 | 33 | data <- data %>% 34 | tidyr::unnest(cols = c("Driver")) %>% 35 | dplyr::select("driverId", "position", "Q1", "Q2", "Q3") %>% 36 | suppressWarnings() %>% 37 | suppressMessages() %>% 38 | dplyr::mutate( 39 | Q1_sec = time_to_sec(.data$Q1), 40 | Q2_sec = time_to_sec(.data$Q2), 41 | Q3_sec = time_to_sec(.data$Q3) 42 | ) %>% 43 | tibble::as_tibble() %>% 44 | janitor::clean_names() 45 | 46 | if (season < 2006) { 47 | return(data %>% dplyr::select(-c("q2", "q3", "q2_sec", "q3_sec"))) 48 | } else { 49 | return(data) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /R/load_results.R: -------------------------------------------------------------------------------- 1 | #' Load Results 2 | #' 3 | #' @description Loads final race results for a given year and round. Use `.load_results()` for an uncached version 4 | #' 5 | #' @param season number from 1950 to current season (or the word 'current') (defaults to current season). 6 | #' @param round number from 1 to 23 (depending on season), and defaults to most recent. Also accepts `'last'`. 7 | #' @importFrom magrittr "%>%" 8 | #' @importFrom rlang .data 9 | #' @export 10 | #' @return A tibble with one row per driver, with columns for driver & constructor ID, the points won by each driver in 11 | #' the race, their finishing position, their starting (grid) position, number of completed laps, status code, gap to 12 | #' leader (or time of race), fastest lap ranking, drivers' fastest lap time, top speed achieved, and fastest lap time 13 | #' in seconds. 14 | load_results <- function(season = get_current_season(), round = "last") { 15 | if (season != "current" && (season < 1950 || season > get_current_season())) { 16 | cli::cli_abort( 17 | '{.var season} must be between 1950 and {get_current_season()} (or use "current")' 18 | ) 19 | } 20 | 21 | url <- glue::glue( 22 | "{season}/{round}/results.json?limit=40", 23 | season = season, 24 | round = round 25 | ) 26 | data <- get_jolpica_content(url) 27 | 28 | if (is.null(data)) { 29 | return(NULL) 30 | } 31 | 32 | data <- data$MRData$RaceTable$Races$Results[[1]] 33 | 34 | if (!("FastestLap" %in% colnames(data))) { 35 | # all races from before 2004 will have no 'Fastest Lap' column, 36 | # but also 2021 round 12 (Belgian GP) where no racing laps were run 37 | data %>% 38 | tidyr::unnest( 39 | cols = c("Driver", "Time", "Constructor"), 40 | names_sep = ".", 41 | names_repair = "universal" 42 | ) %>% 43 | suppressWarnings() %>% 44 | suppressMessages() %>% 45 | dplyr::select( 46 | "driverId" = "Driver.driverId", 47 | "constructorId" = "Constructor.constructorId", 48 | "points", 49 | "position", 50 | "grid", 51 | "laps", 52 | "status", 53 | gap = "Time.time" 54 | ) %>% 55 | dplyr::mutate( 56 | fastest_rank = NA_integer_, 57 | fastest = NA_character_, 58 | top_speed_kph = NA_real_, 59 | time_sec = NA_real_ 60 | ) %>% 61 | tibble::as_tibble() %>% 62 | janitor::clean_names() 63 | } else if (!("AverageSpeed" %in% colnames(data$FastestLap))) { 64 | data %>% 65 | tidyr::unnest( 66 | cols = c("Driver", "Constructor", "Time", "FastestLap"), 67 | names_sep = ".", 68 | names_repair = "universal" 69 | ) %>% 70 | tidyr::unnest( 71 | cols = "FastestLap.Time", 72 | names_sep = ".", 73 | names_repair = "universal" 74 | ) %>% 75 | suppressWarnings() %>% 76 | suppressMessages() %>% 77 | dplyr::mutate(top_speed_kph = NA_real_) %>% 78 | dplyr::select( 79 | "driverId" = "Driver.driverId", 80 | "constructorId" = "Constructor.constructorId", 81 | "points", 82 | "position", 83 | "grid", 84 | "laps", 85 | "status", 86 | gap = "Time.time", 87 | fastest_rank = "FastestLap.rank", 88 | fastest = "FastestLap.Time.time", 89 | top_speed_kph 90 | ) %>% 91 | dplyr::mutate(time_sec = time_to_sec(.data$fastest)) %>% 92 | tibble::as_tibble() %>% 93 | janitor::clean_names() 94 | } else { 95 | data %>% 96 | tidyr::unnest( 97 | cols = c("Driver", "Constructor", "Time", "FastestLap"), 98 | names_sep = ".", 99 | names_repair = "universal" 100 | ) %>% 101 | tidyr::unnest( 102 | cols = c("FastestLap.Time", "FastestLap.AverageSpeed"), 103 | names_sep = ".", 104 | names_repair = "universal" 105 | ) %>% 106 | suppressWarnings() %>% 107 | suppressMessages() %>% 108 | dplyr::select( 109 | "driverId" = "Driver.driverId", 110 | "constructorId" = "Constructor.constructorId", 111 | "points", 112 | "position", 113 | "grid", 114 | "laps", 115 | "status", 116 | gap = "Time.time", 117 | fastest_rank = "FastestLap.rank", 118 | fastest = "FastestLap.Time.time", 119 | top_speed_kph = "FastestLap.AverageSpeed.speed", 120 | ) %>% 121 | dplyr::mutate(time_sec = time_to_sec(.data$fastest)) %>% 122 | tibble::as_tibble() %>% 123 | janitor::clean_names() 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /R/load_schedule.R: -------------------------------------------------------------------------------- 1 | #' Load Schedule 2 | #' 3 | #' @description Loads schedule information for a given F1 season. 4 | #' Use `.load_schedule()` for an uncached version. 5 | #' 6 | #' @param season number from 1950 to current season (defaults to current season). `'current'` also accepted. 7 | #' @importFrom magrittr "%>%" 8 | #' @export 9 | #' @return A tibble with one row per round in season. Indicates in sprint_date if a specific round has a sprint race 10 | load_schedule <- function(season = get_current_season()) { 11 | if (season != "current" && (season < 1950 || season > get_current_season())) { 12 | cli::cli_abort('{.var season} must be between 1950 and {get_current_season()} (or use "current")') 13 | } 14 | 15 | url <- glue::glue("{season}.json?limit=30", season = season) 16 | 17 | data <- get_jolpica_content(url) 18 | if (is.null(data)) { 19 | return(NULL) 20 | } 21 | 22 | data <- data$MRData$RaceTable$Races 23 | 24 | if ("url" %in% colnames(data)) { 25 | data$url <- NULL 26 | } 27 | 28 | if ("Circuit" %in% colnames(data)) { 29 | if (inherits(data$Circuit, "data.frame")) { 30 | data <- data %>% 31 | tidyr::unnest(cols = c("Circuit"), names_repair = "universal") 32 | } 33 | } 34 | 35 | if ("Location" %in% colnames(data)) { 36 | if (inherits(data$Location, "data.frame")) { 37 | data <- data %>% 38 | tidyr::unnest(cols = c("Location"), names_repair = "universal") 39 | } 40 | } 41 | 42 | if ("Sprint" %in% colnames(data)) { 43 | if (inherits(data$Sprint, "data.frame")) { 44 | data <- data %>% 45 | tidyr::unnest(cols = c("Sprint"), names_sep = "_") 46 | } 47 | } 48 | 49 | data <- add_col_if_absent(data, "time", NA_character_) 50 | data <- add_col_if_absent(data, "sprint_date", NA_character_) 51 | 52 | data <- data %>% 53 | janitor::clean_names() %>% 54 | suppressWarnings() %>% 55 | suppressMessages() %>% 56 | dplyr::select( 57 | "season", 58 | "round", 59 | "race_name", 60 | "circuit_id", 61 | "circuit_name", 62 | "lat", 63 | "long", 64 | "locality", 65 | "country", 66 | "date", 67 | "time", 68 | "sprint_date" 69 | ) %>% 70 | tibble::as_tibble() %>% 71 | janitor::clean_names() 72 | 73 | return(data) 74 | } 75 | -------------------------------------------------------------------------------- /R/load_session_laps.R: -------------------------------------------------------------------------------- 1 | #' Load Lapwise Data 2 | #' 3 | #' @description Loads lapwise data for a race session. 4 | #' 5 | #' Includes each driver's each lap's laptime, pit in/out time, tyre information, track status, and (optionally) weather information. 6 | #' The resulting data frame contains a column for the session type. Note that quali sessions are labelled Q1, Q2 & Q3. 7 | #' 8 | #' Cache directory can be set by setting `option(f1dataR.cache = [cache dir])`, 9 | #' default is the current working directory. 10 | #' 11 | #' If you have trouble with errors mentioning 'fastf1' or 'get_fastf1_version()' read the 12 | #' 'Setup FastF1 Connection vignette (run \code{vignette('setup_fastf1', 'f1dataR')}). 13 | #' 14 | #' @inheritParams load_race_session 15 | #' @param add_weather Whether to add weather information to the laps. See 16 | #' \href{https://docs.fastf1.dev/core.html#fastf1.core.Laps.get_weather_data}{fastf1 documentation} for info on weather. 17 | #' 18 | #' @return A tibble. Note time information is in seconds, see \href{https://docs.fastf1.dev/time_explanation.html}{fastf1 documentation} for more information on timing. 19 | #' @export 20 | load_session_laps <- function(season = get_current_season(), round = 1, session = "R", log_level = "WARNING", 21 | add_weather = FALSE, race = lifecycle::deprecated()) { 22 | # Deprecation Checks 23 | if (lifecycle::is_present(race)) { 24 | lifecycle::deprecate_stop("1.4.0", "load_session_laps(race)", "load_session_laps(round)") 25 | } 26 | check_ff1_version() 27 | 28 | # Function Code 29 | status <- load_race_session(obj_name = "session", season = season, round = round, session = session, log_level = log_level) 30 | 31 | if (is.null(status)) { 32 | # Failure to load - escape 33 | return(NULL) 34 | } 35 | 36 | reticulate::py_run_string("laps = session.laps") 37 | if (add_weather) { 38 | reticulate::py_run_string(paste("import pandas as pd", 39 | "weather_data = laps.get_weather_data()", 40 | "laps = laps.reset_index(drop=True)", 41 | "weather_data = weather_data.reset_index(drop=True)", 42 | "laps = pd.concat([laps, weather_data.loc[:, ~(weather_data.columns == 'Time')]], axis=1)", 43 | sep = "\n" 44 | )) 45 | } 46 | 47 | if (session %in% c("Q", "SQ")) { 48 | # prepping for Q1/Q2/Q3 labels - this has to happen before timedelta64 is converted to seconds 49 | reticulate::py_run_string(paste("q1, q2, q3 = session.laps.split_qualifying_sessions()", 50 | "q1len = len(q1.index)", 51 | "q2len = len(q2.index)", 52 | "q3len = len(q3.index)", 53 | sep = "\n" 54 | )) 55 | } 56 | 57 | # The FF1 function returns timedelta64 results for the below columns, which don't properly convert to 58 | # R compatible types. Instead, use the dt.total_seconds() function inherent to the type to convert in 59 | # Python before extracting the DataFrame to the R data.frame 60 | py_env <- reticulate::py_run_string(paste("laps.Time = laps.Time.dt.total_seconds()", 61 | "laps.LapTime = laps.LapTime.dt.total_seconds()", 62 | "laps.PitOutTime = laps.PitOutTime.dt.total_seconds()", 63 | "laps.PitInTime = laps.PitInTime.dt.total_seconds()", 64 | "laps.Sector1SessionTime = laps.Sector1SessionTime.dt.total_seconds()", 65 | "laps.Sector1Time = laps.Sector1Time.dt.total_seconds()", 66 | "laps.Sector2SessionTime = laps.Sector2SessionTime.dt.total_seconds()", 67 | "laps.Sector2Time = laps.Sector2Time.dt.total_seconds()", 68 | "laps.Sector3SessionTime = laps.Sector3SessionTime.dt.total_seconds()", 69 | "laps.Sector3Time = laps.Sector3Time.dt.total_seconds()", 70 | "laps.LapStartTime = laps.LapStartTime.dt.total_seconds()", 71 | sep = "\n" 72 | )) 73 | laps <- reticulate::py_to_r(reticulate::py_get_item(py_env, "laps")) 74 | 75 | laps <- laps %>% 76 | dplyr::mutate("Time" = .data$Time) 77 | 78 | if (session %in% c("Q", "SQ")) { 79 | # pull the lengths of each Quali session from the python env. 80 | q1len <- reticulate::py_to_r(reticulate::py_get_item(py_env, "q1len")) 81 | q2len <- reticulate::py_to_r(reticulate::py_get_item(py_env, "q2len")) 82 | q3len <- reticulate::py_to_r(reticulate::py_get_item(py_env, "q3len")) 83 | 84 | if (session == "Q") { 85 | laps$SessionType <- c(rep("Q1", q1len), rep("Q2", q2len), rep("Q3", q3len)) 86 | } else { 87 | laps$SessionType <- c(rep("SQ1", q1len), rep("SQ2", q2len), rep("SQ3", q3len)) 88 | } 89 | } else { 90 | laps$SessionType <- session 91 | } 92 | laps %>% 93 | tibble::tibble() %>% 94 | janitor::clean_names() 95 | } 96 | -------------------------------------------------------------------------------- /R/load_sprint.R: -------------------------------------------------------------------------------- 1 | #' Load Sprint Results 2 | #' 3 | #' Loads final race results for a given year and round. Note not all rounds have 4 | #' sprint results. Use `.load_sprint()` for an uncached version of this function. 5 | #' 6 | #' @param season number from 2021 to current season (defaults to current season). 7 | #' @param round number from 1 to 23 (depending on season), and defaults 8 | #' to most recent. Also accepts `'last'`. 9 | #' @importFrom magrittr "%>%" 10 | #' @importFrom rlang .data 11 | #' @export 12 | #' @return A dataframetibble with columns driver_id, constructor_id, points awarded, finishing position, 13 | #' grid position, laps completed, race status (finished or otherwise), gap to 14 | #' first place, fastest lap, fastest lap time, fastest lap in seconds, 15 | #' or NULL if no sprint exists for this season/round combo 16 | load_sprint <- function(season = get_current_season(), round = "last") { 17 | if (season != "current" && (season < 2021 || season > get_current_season())) { 18 | cli::cli_abort( 19 | '{.var season} must be between 2021 and {get_current_season()} (or use "current")' 20 | ) 21 | } 22 | 23 | url <- glue::glue( 24 | "{season}/{round}/sprint.json?limit=40", 25 | season = season, 26 | round = round 27 | ) 28 | 29 | data <- get_jolpica_content(url) 30 | 31 | if (is.null(data)) { 32 | return(NULL) 33 | } 34 | 35 | if (length(data$MRData$RaceTable$Races) == 0) { 36 | cli::cli_alert_warning(glue::glue( 37 | "No Sprint data for season = {season}, round = {round}", 38 | season = season, 39 | round = round 40 | )) 41 | return(NULL) 42 | } 43 | 44 | data <- data$MRData$RaceTable$Races$SprintResults[[1]] 45 | 46 | data <- data %>% 47 | tidyr::unnest( 48 | cols = c("Driver", "Constructor", "Time", "FastestLap"), 49 | names_repair = "universal", 50 | names_sep = "." 51 | ) %>% 52 | tidyr::unnest( 53 | cols = c("FastestLap.Time"), 54 | names_repair = "universal", 55 | names_sep = "." 56 | ) %>% 57 | suppressWarnings() %>% 58 | suppressMessages() %>% 59 | dplyr::select( 60 | "driverId" = "Driver.driverId", 61 | "constructorId" = "Constructor.constructorId", 62 | "points", 63 | "position", 64 | "grid", 65 | "laps", 66 | "status", 67 | "position", 68 | "gap" = "Time.time", 69 | "lap" = "FastestLap.lap", 70 | "fastest" = "FastestLap.Time.time" 71 | ) %>% 72 | dplyr::mutate(time_sec = time_to_sec(.data$fastest)) %>% 73 | tibble::as_tibble() %>% 74 | janitor::clean_names() 75 | } 76 | -------------------------------------------------------------------------------- /R/load_standings.R: -------------------------------------------------------------------------------- 1 | #' Load Standings 2 | #' 3 | #' @description Loads standings at the end of a given season and round for drivers' or 4 | #' constructors' championships. Use `.load_standings()` for an uncached version of this function. 5 | #' 6 | #' @param season number from 2003 to current season (defaults to current season). 7 | #' @param round number from 1 to 23 (depending on season), and defaults 8 | #' to most recent. Also accepts `'last'`. 9 | #' @param type select `'driver'` or `'constructor'` championship data. Defaults to 10 | #' `'driver'` 11 | #' @importFrom magrittr "%>%" 12 | #' @export 13 | #' @return A tibble with columns driver_id (or constructor_id), position, 14 | #' points, wins (and constructors_id in the case of drivers championship). 15 | load_standings <- function(season = get_current_season(), round = "last", type = "driver") { 16 | if (season != "current" && (season < 2003 || season > get_current_season())) { 17 | cli::cli_abort('{.var season} must be between 2003 and {get_current_season()} (or use "current")') 18 | } 19 | 20 | if (!(type %in% c("driver", "constructor"))) { 21 | cli::cli_abort('{.var type} must be either "driver" or "constructor"') 22 | } 23 | 24 | url <- glue::glue("{season}/{round}/{type}Standings.json?limit=40", 25 | season = season, round = round, type = type 26 | ) 27 | 28 | data <- get_jolpica_content(url) 29 | 30 | if (is.null(data)) { 31 | return(NULL) 32 | } 33 | 34 | if (type == "driver") { 35 | data$MRData$StandingsTable$StandingsLists$DriverStandings[[1]] %>% 36 | tidyr::unnest(cols = c("Driver")) %>% 37 | dplyr::select("driverId", "position", "points", "wins", "Constructors") %>% 38 | tidyr::unnest(cols = c("Constructors")) %>% 39 | suppressWarnings() %>% 40 | suppressMessages() %>% 41 | dplyr::select("driverId", "position", "points", "wins", "constructorId") %>% 42 | tibble::as_tibble() %>% 43 | janitor::clean_names() 44 | } else if (type == "constructor") { 45 | data$MRData$StandingsTable$StandingsLists$ConstructorStandings[[1]] %>% 46 | tidyr::unnest(cols = c("Constructor")) %>% 47 | suppressWarnings() %>% 48 | suppressMessages() %>% 49 | dplyr::select("constructorId", "position", "points", "wins") %>% 50 | tibble::as_tibble() %>% 51 | janitor::clean_names() 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /R/theme_dark_f1.R: -------------------------------------------------------------------------------- 1 | #' Dark F1-style Theme for ggplot 2 | #' 3 | #' @description Theme for all f1dataR plot functions. Mimics Formula 1 style. 4 | #' 5 | #' @param axis_marks True or false, whether axis line, ticks and title should 6 | #' be shown or not. Defaults to false 7 | #' @importFrom magrittr "%>%" 8 | #' @return A ggplot object that indicates grand prix, driver, time and selected 9 | #' color variable. 10 | #' @export 11 | 12 | 13 | theme_dark_f1 <- function(axis_marks = FALSE) { 14 | if (axis_marks) { 15 | ggplot2::theme_gray() + 16 | ggplot2::theme( 17 | panel.grid = ggplot2::element_blank(), 18 | axis.line = ggplot2::element_line(colour = "white"), 19 | axis.text = ggplot2::element_text(colour = "white"), 20 | axis.title = ggplot2::element_text(colour = "white"), 21 | axis.ticks = ggplot2::element_line(colour = "white"), 22 | plot.title = ggplot2::element_text(face = "bold", size = 17, color = "#cf1b1f"), 23 | plot.subtitle = ggplot2::element_text(face = "bold", size = 14), 24 | plot.background = ggplot2::element_rect(fill = "grey10"), 25 | panel.background = ggplot2::element_blank(), 26 | legend.background = ggplot2::element_blank(), 27 | legend.key = ggplot2::element_blank(), 28 | plot.caption = ggplot2::element_text(size = 8, color = "white"), 29 | text = ggplot2::element_text(color = "white") 30 | ) 31 | } else { 32 | ggplot2::theme_gray() + 33 | ggplot2::theme( 34 | panel.grid = ggplot2::element_blank(), 35 | axis.line = ggplot2::element_blank(), 36 | axis.text = ggplot2::element_blank(), 37 | axis.title = ggplot2::element_blank(), 38 | axis.ticks = ggplot2::element_blank(), 39 | plot.title = ggplot2::element_text(face = "bold", size = 17, color = "#cf1b1f"), 40 | plot.subtitle = ggplot2::element_text(face = "bold", size = 14), 41 | plot.background = ggplot2::element_rect(fill = "grey10"), 42 | panel.background = ggplot2::element_blank(), 43 | legend.background = ggplot2::element_blank(), 44 | legend.key = ggplot2::element_blank(), 45 | plot.caption = ggplot2::element_text(size = 8, color = "white"), 46 | text = ggplot2::element_text(color = "white") 47 | ) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | url: https://scasanova.github.io/f1dataR/ 2 | template: 3 | bootstrap: 5 4 | 5 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## Resubmission 2 | 3 | This is a minor patch to adapt to upstream data format changes. 4 | 5 | Minor other bugfixes are included. 6 | -------------------------------------------------------------------------------- /doc/ergast-data-analysis.R: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /doc/introduction.R: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /doc/plotting-turn-info.R: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /doc/setup_fastf1.R: -------------------------------------------------------------------------------- 1 | ## ----include = FALSE---------------------------------------------------------- 2 | knitr::opts_chunk$set( 3 | collapse = TRUE, 4 | comment = "#>" 5 | ) 6 | 7 | -------------------------------------------------------------------------------- /doc/setup_fastf1.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Setup FastF1 Connection" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Setup FastF1 Connection} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r, include = FALSE} 11 | knitr::opts_chunk$set( 12 | collapse = TRUE, 13 | comment = "#>" 14 | ) 15 | ``` 16 | 17 | # Introduction 18 | 19 | This vignette briefly describes setting up the `f1dataR` package to work properly with with 20 | the Python package [`FastF1`](https://docs.fastf1.dev/). This guide may help resolve some issues 21 | that might arise when you get the following warning or error messages: 22 | 23 | - `Ensure fastf1 python package is installed. Please run this to install the most recent version: setup_fastf1()` 24 | - `Error in if (get_fastf1_version() < '3.1') { :` 25 | `missing value where TRUE/FALSE needed` 26 | 27 | If these happen to you (particularly if you're a new user of `f1dataR`) read on! 28 | 29 | # `f1dataR`'s Relationship to Python 30 | 31 | At the core of the `f1dataR` package, the connection to the Python package is created 32 | by using [`reticulate`](https://rstudio.github.io/reticulate/). This provides the 33 | connection used to call on Python and return objects to R. However, it has to be 34 | set up properly to work. 35 | 36 | > **_NOTE:_** If you are comfortable with `reticulate`, set up a virtualenv or 37 | condaenv and point reticulate to that with your .RProfile before calling `library(fastf1)`, 38 | and you can skip the rest of this guide. 39 | 40 | # Setting up `reticulate` 41 | 42 | There are a few options to get the `reticulate` set up in a way that works well for 43 | `f1dataR` to use it. 44 | 45 | ## Accept all defaults 46 | 47 | To use all of the defaults and set up the `reticulate` package, you can use the below 48 | helper function. 49 | 50 | ```r 51 | setup_fastf1() 52 | ``` 53 | 54 | This will create a virtual environment using your system's default Python version, 55 | and install `fastf1` in that python environment. It will also tell `reticulate` to use that 56 | environment instead of just running in your main system. Many resources exist online to explain python environments in more detail. 57 | 58 | # Repeat/Recurring Issues 59 | 60 | If you have repeat issues with the package failing to connect to your proper environment, 61 | you can force a complete recreation of the virtual environment by calling: 62 | 63 | ```r 64 | setup_fastf1(new_env = TRUE) 65 | ``` 66 | 67 | If you've configured the package to use a custom environment name, the above function will require that name supplied as 68 | the `envname` parameter. 69 | -------------------------------------------------------------------------------- /docs/LICENSE-text.html: -------------------------------------------------------------------------------- 1 | 2 | License • f1dataR 3 | Skip to contents 4 | 5 | 6 |
36 |
37 |
41 | 42 |
YEAR: 2023
43 | COPYRIGHT HOLDER: f1dataR authors
44 | 
45 | 46 |
47 | 48 | 49 |
52 | 53 | 56 | 57 |
58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /docs/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /docs/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /docs/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /docs/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /docs/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /docs/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/apple-touch-icon.png -------------------------------------------------------------------------------- /docs/articles/ergast-data-analysis-driver_laptime_scatterplot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/ergast-data-analysis-driver_laptime_scatterplot-1.png -------------------------------------------------------------------------------- /docs/articles/ergast-data-analysis-drivers_laptimes-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/ergast-data-analysis-drivers_laptimes-1.png -------------------------------------------------------------------------------- /docs/articles/ergast-data-analysis-grid_to_finish_one-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/ergast-data-analysis-grid_to_finish_one-1.png -------------------------------------------------------------------------------- /docs/articles/ergast-data-analysis-grid_to_finish_season-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/ergast-data-analysis-grid_to_finish_season-1.png -------------------------------------------------------------------------------- /docs/articles/ergast-data-analysis-quali_compare-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/ergast-data-analysis-quali_compare-1.png -------------------------------------------------------------------------------- /docs/articles/ergast-data-analysis-round_position-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/ergast-data-analysis-round_position-1.png -------------------------------------------------------------------------------- /docs/articles/ergast-data-analysis-rounds_points-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/ergast-data-analysis-rounds_points-1.png -------------------------------------------------------------------------------- /docs/articles/introduction-pitstop-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction-pitstop-1.png -------------------------------------------------------------------------------- /docs/articles/introduction-session_laps-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction-session_laps-1.png -------------------------------------------------------------------------------- /docs/articles/introduction-simple_plot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction-simple_plot-1.png -------------------------------------------------------------------------------- /docs/articles/introduction-telem_plotting-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction-telem_plotting-1.png -------------------------------------------------------------------------------- /docs/articles/introduction-triple_plot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction-triple_plot-1.png -------------------------------------------------------------------------------- /docs/articles/introduction-use_builtin-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction-use_builtin-1.png -------------------------------------------------------------------------------- /docs/articles/introduction-use_theme-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction-use_theme-1.png -------------------------------------------------------------------------------- /docs/articles/introduction_files/accessible-code-block-0.0.1/empty-anchor.js: -------------------------------------------------------------------------------- 1 | // Hide empty tag within highlighted CodeBlock for screen reader accessibility (see https://github.com/jgm/pandoc/issues/6352#issuecomment-626106786) --> 2 | // v0.0.1 3 | // Written by JooYoung Seo (jooyoung@psu.edu) and Atsushi Yasumoto on June 1st, 2020. 4 | 5 | document.addEventListener('DOMContentLoaded', function() { 6 | const codeList = document.getElementsByClassName("sourceCode"); 7 | for (var i = 0; i < codeList.length; i++) { 8 | var linkList = codeList[i].getElementsByTagName('a'); 9 | for (var j = 0; j < linkList.length; j++) { 10 | if (linkList[j].innerHTML === "") { 11 | linkList[j].setAttribute('aria-hidden', 'true'); 12 | } 13 | } 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /docs/articles/introduction_files/figure-html/pitstop-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction_files/figure-html/pitstop-1.png -------------------------------------------------------------------------------- /docs/articles/introduction_files/figure-html/session_laps-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction_files/figure-html/session_laps-1.png -------------------------------------------------------------------------------- /docs/articles/introduction_files/figure-html/simple_plot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction_files/figure-html/simple_plot-1.png -------------------------------------------------------------------------------- /docs/articles/introduction_files/figure-html/telem plotting-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction_files/figure-html/telem plotting-1.png -------------------------------------------------------------------------------- /docs/articles/introduction_files/figure-html/triple_plot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction_files/figure-html/triple_plot-1.png -------------------------------------------------------------------------------- /docs/articles/introduction_files/figure-html/unnamed-chunk-1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction_files/figure-html/unnamed-chunk-1-1.png -------------------------------------------------------------------------------- /docs/articles/introduction_files/figure-html/unnamed-chunk-2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction_files/figure-html/unnamed-chunk-2-1.png -------------------------------------------------------------------------------- /docs/articles/introduction_files/figure-html/unnamed-chunk-3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction_files/figure-html/unnamed-chunk-3-1.png -------------------------------------------------------------------------------- /docs/articles/introduction_files/figure-html/unnamed-chunk-4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction_files/figure-html/unnamed-chunk-4-1.png -------------------------------------------------------------------------------- /docs/articles/introduction_files/figure-html/unnamed-chunk-5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction_files/figure-html/unnamed-chunk-5-1.png -------------------------------------------------------------------------------- /docs/articles/introduction_files/figure-html/unnamed-chunk-6-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction_files/figure-html/unnamed-chunk-6-1.png -------------------------------------------------------------------------------- /docs/articles/introduction_files/figure-html/unnamed-chunk-7-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction_files/figure-html/unnamed-chunk-7-1.png -------------------------------------------------------------------------------- /docs/articles/introduction_files/figure-html/use_builtin-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction_files/figure-html/use_builtin-1.png -------------------------------------------------------------------------------- /docs/articles/introduction_files/figure-html/use_theme-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/articles/introduction_files/figure-html/use_theme-1.png -------------------------------------------------------------------------------- /docs/bootstrap-toc.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | 6 | /* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */ 7 | 8 | /* All levels of nav */ 9 | nav[data-toggle='toc'] .nav > li > a { 10 | display: block; 11 | padding: 4px 20px; 12 | font-size: 13px; 13 | font-weight: 500; 14 | color: #767676; 15 | } 16 | nav[data-toggle='toc'] .nav > li > a:hover, 17 | nav[data-toggle='toc'] .nav > li > a:focus { 18 | padding-left: 19px; 19 | color: #563d7c; 20 | text-decoration: none; 21 | background-color: transparent; 22 | border-left: 1px solid #563d7c; 23 | } 24 | nav[data-toggle='toc'] .nav > .active > a, 25 | nav[data-toggle='toc'] .nav > .active:hover > a, 26 | nav[data-toggle='toc'] .nav > .active:focus > a { 27 | padding-left: 18px; 28 | font-weight: bold; 29 | color: #563d7c; 30 | background-color: transparent; 31 | border-left: 2px solid #563d7c; 32 | } 33 | 34 | /* Nav: second level (shown on .active) */ 35 | nav[data-toggle='toc'] .nav .nav { 36 | display: none; /* Hide by default, but at >768px, show it */ 37 | padding-bottom: 10px; 38 | } 39 | nav[data-toggle='toc'] .nav .nav > li > a { 40 | padding-top: 1px; 41 | padding-bottom: 1px; 42 | padding-left: 30px; 43 | font-size: 12px; 44 | font-weight: normal; 45 | } 46 | nav[data-toggle='toc'] .nav .nav > li > a:hover, 47 | nav[data-toggle='toc'] .nav .nav > li > a:focus { 48 | padding-left: 29px; 49 | } 50 | nav[data-toggle='toc'] .nav .nav > .active > a, 51 | nav[data-toggle='toc'] .nav .nav > .active:hover > a, 52 | nav[data-toggle='toc'] .nav .nav > .active:focus > a { 53 | padding-left: 28px; 54 | font-weight: 500; 55 | } 56 | 57 | /* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */ 58 | nav[data-toggle='toc'] .nav > .active > ul { 59 | display: block; 60 | } 61 | -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/font.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Roboto'; 3 | font-style: normal; 4 | font-weight: 400; 5 | font-display: swap; 6 | src: url(fonts/KFOmCnqEu92Fr1Me5g.woff) format('woff'); 7 | } 8 | @font-face { 9 | font-family: 'Roboto'; 10 | font-style: normal; 11 | font-weight: 500; 12 | font-display: swap; 13 | src: url(fonts/KFOlCnqEu92Fr1MmEU9vAA.woff) format('woff'); 14 | } 15 | @font-face { 16 | font-family: 'Roboto'; 17 | font-style: normal; 18 | font-weight: 700; 19 | font-display: swap; 20 | src: url(fonts/KFOlCnqEu92Fr1MmWUlvAA.woff) format('woff'); 21 | } 22 | -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/1Ptxg8zYS_SKggPN4iEgvnHyvveLxVs9pbCIPrc.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/1Ptxg8zYS_SKggPN4iEgvnHyvveLxVs9pbCIPrc.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/1Ptxg8zYS_SKggPN4iEgvnHyvveLxVvaorCIPrc.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/1Ptxg8zYS_SKggPN4iEgvnHyvveLxVvaorCIPrc.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/4iCs6KVjbNBYlgo6ew.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/4iCs6KVjbNBYlgo6ew.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/4iCs6KVjbNBYlgoKfw7w.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/4iCs6KVjbNBYlgoKfw7w.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/4iCv6KVjbNBYlgoCxCvTtA.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/4iCv6KVjbNBYlgoCxCvTtA.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/4iCv6KVjbNBYlgoCxCvjsGyL.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/4iCv6KVjbNBYlgoCxCvjsGyL.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7nsDQ.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7nsDQ.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPa7j.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPa7j.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3aPA.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3aPA.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7j.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7j.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rAkw.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rAkw.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vAkw.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vAkw.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdo.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdo.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zAkw.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zAkw.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwlxdo.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwlxdo.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/CSR54z1Qlv-GDxkbKVQ_dFsvWNRevw.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/CSR54z1Qlv-GDxkbKVQ_dFsvWNRevw.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/CSR54z1Qlv-GDxkbKVQ_dFsvaNA.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/CSR54z1Qlv-GDxkbKVQ_dFsvaNA.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/CSR64z1Qlv-GDxkbKVQ_TOQ.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/CSR64z1Qlv-GDxkbKVQ_TOQ.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/CSR64z1Qlv-GDxkbKVQ_fOAKSw.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/CSR64z1Qlv-GDxkbKVQ_fOAKSw.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/JTURjIg1_i6t8kCHKm45_ZpC7g0.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/JTURjIg1_i6t8kCHKm45_ZpC7g0.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/JTURjIg1_i6t8kCHKm45_dJE7g0.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/JTURjIg1_i6t8kCHKm45_dJE7g0.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/JTUSjIg1_i6t8kCHKm45xW0.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/JTUSjIg1_i6t8kCHKm45xW0.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/KFOlCnqEu92Fr1MmEU9fBBc-.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/KFOlCnqEu92Fr1MmEU9fBBc-.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/KFOlCnqEu92Fr1MmEU9vAA.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/KFOlCnqEu92Fr1MmEU9vAA.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/KFOlCnqEu92Fr1MmSU5fBBc-.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/KFOlCnqEu92Fr1MmSU5fBBc-.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/KFOlCnqEu92Fr1MmSU5vAA.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/KFOlCnqEu92Fr1MmSU5vAA.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/KFOlCnqEu92Fr1MmWUlfBBc-.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/KFOlCnqEu92Fr1MmWUlfBBc-.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/KFOlCnqEu92Fr1MmWUlvAA.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/KFOlCnqEu92Fr1MmWUlvAA.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/KFOmCnqEu92Fr1Me5g.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/KFOmCnqEu92Fr1Me5g.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/KFOmCnqEu92Fr1Mu4mxM.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/KFOmCnqEu92Fr1Mu4mxM.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/QGYpz_kZZAGCONcK2A4bGOj8mNhL.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/QGYpz_kZZAGCONcK2A4bGOj8mNhL.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/S6u8w4BMUTPHjxsAXC-s.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/S6u8w4BMUTPHjxsAXC-s.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/S6u8w4BMUTPHjxswWA.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/S6u8w4BMUTPHjxswWA.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/S6u9w4BMUTPHh6UVSwiPHw.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/S6u9w4BMUTPHh6UVSwiPHw.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/S6u9w4BMUTPHh6UVeww.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/S6u9w4BMUTPHh6UVeww.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/S6u9w4BMUTPHh7USSwiPHw.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/S6u9w4BMUTPHh7USSwiPHw.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/S6u9w4BMUTPHh7USeww.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/S6u9w4BMUTPHh7USeww.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/S6uyw4BMUTPHjx4wWA.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/S6uyw4BMUTPHjx4wWA.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/S6uyw4BMUTPHvxo.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/S6uyw4BMUTPHvxo.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuFuYMZs.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuFuYMZs.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuI6fMZs.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuI6fMZs.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfMZs.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfMZs.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/XRXV3I6Li01BKof4MQ.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/XRXV3I6Li01BKof4MQ.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/XRXW3I6Li01BKofA6sKkZQ.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/XRXW3I6Li01BKofA6sKkZQ.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/XRXW3I6Li01BKofAjsOkZQ.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/XRXW3I6Li01BKofAjsOkZQ.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk5hkWVAexg.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk5hkWVAexg.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk5hkaVQ.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk5hkaVQ.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk8ZkWVAexg.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk8ZkWVAexg.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk8ZkaVQ.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk8ZkaVQ.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0RkyFjWVAexg.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0RkyFjWVAexg.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0RkyFjaVQ.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0RkyFjaVQ.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsg-1x4gaVQ.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsg-1x4gaVQ.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsg-1y4k.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsg-1y4k.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsiH0B4gaVQ.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsiH0B4gaVQ.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsiH0C4k.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsiH0C4k.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0B4gaVQ.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0B4gaVQ.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0C4k.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0C4k.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/pe03MImSLYBIv1o4X1M8cc9iB_5p.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/pe03MImSLYBIv1o4X1M8cc9iB_5p.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/pe0qMImSLYBIv1o4X1M8cfe5.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/pe0qMImSLYBIv1o4X1M8cfe5.woff -------------------------------------------------------------------------------- /docs/deps/bootstrap-5.1.0/fonts/q5uGsou0JOdh94bfvQlr.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/deps/bootstrap-5.1.0/fonts/q5uGsou0JOdh94bfvQlr.woff -------------------------------------------------------------------------------- /docs/deps/data-deps.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /docs/docsearch.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // register a handler to move the focus to the search bar 4 | // upon pressing shift + "/" (i.e. "?") 5 | $(document).on('keydown', function(e) { 6 | if (e.shiftKey && e.keyCode == 191) { 7 | e.preventDefault(); 8 | $("#search-input").focus(); 9 | } 10 | }); 11 | 12 | $(document).ready(function() { 13 | // do keyword highlighting 14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 15 | var mark = function() { 16 | 17 | var referrer = document.URL ; 18 | var paramKey = "q" ; 19 | 20 | if (referrer.indexOf("?") !== -1) { 21 | var qs = referrer.substr(referrer.indexOf('?') + 1); 22 | var qs_noanchor = qs.split('#')[0]; 23 | var qsa = qs_noanchor.split('&'); 24 | var keyword = ""; 25 | 26 | for (var i = 0; i < qsa.length; i++) { 27 | var currentParam = qsa[i].split('='); 28 | 29 | if (currentParam.length !== 2) { 30 | continue; 31 | } 32 | 33 | if (currentParam[0] == paramKey) { 34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 35 | } 36 | } 37 | 38 | if (keyword !== "") { 39 | $(".contents").unmark({ 40 | done: function() { 41 | $(".contents").mark(keyword); 42 | } 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | mark(); 49 | }); 50 | }); 51 | 52 | /* Search term highlighting ------------------------------*/ 53 | 54 | function matchedWords(hit) { 55 | var words = []; 56 | 57 | var hierarchy = hit._highlightResult.hierarchy; 58 | // loop to fetch from lvl0, lvl1, etc. 59 | for (var idx in hierarchy) { 60 | words = words.concat(hierarchy[idx].matchedWords); 61 | } 62 | 63 | var content = hit._highlightResult.content; 64 | if (content) { 65 | words = words.concat(content.matchedWords); 66 | } 67 | 68 | // return unique words 69 | var words_uniq = [...new Set(words)]; 70 | return words_uniq; 71 | } 72 | 73 | function updateHitURL(hit) { 74 | 75 | var words = matchedWords(hit); 76 | var url = ""; 77 | 78 | if (hit.anchor) { 79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 80 | } else { 81 | url = hit.url + '?q=' + escape(words.join(" ")); 82 | } 83 | 84 | return url; 85 | } 86 | -------------------------------------------------------------------------------- /docs/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/favicon-16x16.png -------------------------------------------------------------------------------- /docs/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/favicon-32x32.png -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/favicon.ico -------------------------------------------------------------------------------- /docs/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | /* http://gregfranko.com/blog/jquery-best-practices/ */ 2 | (function($) { 3 | $(function() { 4 | 5 | $('nav.navbar').headroom(); 6 | 7 | Toc.init({ 8 | $nav: $("#toc"), 9 | $scope: $("main h2, main h3, main h4, main h5, main h6") 10 | }); 11 | 12 | if ($('#toc').length) { 13 | $('body').scrollspy({ 14 | target: '#toc', 15 | offset: $("nav.navbar").outerHeight() + 1 16 | }); 17 | } 18 | 19 | // Activate popovers 20 | $('[data-bs-toggle="popover"]').popover({ 21 | container: 'body', 22 | html: true, 23 | trigger: 'focus', 24 | placement: "top", 25 | sanitize: false, 26 | }); 27 | 28 | $('[data-bs-toggle="tooltip"]').tooltip(); 29 | 30 | /* Clipboard --------------------------*/ 31 | 32 | function changeTooltipMessage(element, msg) { 33 | var tooltipOriginalTitle=element.getAttribute('data-bs-original-title'); 34 | element.setAttribute('data-bs-original-title', msg); 35 | $(element).tooltip('show'); 36 | element.setAttribute('data-bs-original-title', tooltipOriginalTitle); 37 | } 38 | 39 | if(ClipboardJS.isSupported()) { 40 | $(document).ready(function() { 41 | var copyButton = ""; 42 | 43 | $("div.sourceCode").addClass("hasCopyButton"); 44 | 45 | // Insert copy buttons: 46 | $(copyButton).prependTo(".hasCopyButton"); 47 | 48 | // Initialize tooltips: 49 | $('.btn-copy-ex').tooltip({container: 'body'}); 50 | 51 | // Initialize clipboard: 52 | var clipboard = new ClipboardJS('[data-clipboard-copy]', { 53 | text: function(trigger) { 54 | return trigger.parentNode.textContent.replace(/\n#>[^\n]*/g, ""); 55 | } 56 | }); 57 | 58 | clipboard.on('success', function(e) { 59 | changeTooltipMessage(e.trigger, 'Copied!'); 60 | e.clearSelection(); 61 | }); 62 | 63 | clipboard.on('error', function(e) { 64 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 65 | }); 66 | 67 | }); 68 | } 69 | 70 | /* Search marking --------------------------*/ 71 | var url = new URL(window.location.href); 72 | var toMark = url.searchParams.get("q"); 73 | var mark = new Mark("main#main"); 74 | if (toMark) { 75 | mark.mark(toMark, { 76 | accuracy: { 77 | value: "complementary", 78 | limiters: [",", ".", ":", "/"], 79 | } 80 | }); 81 | } 82 | 83 | /* Search --------------------------*/ 84 | /* Adapted from https://github.com/rstudio/bookdown/blob/2d692ba4b61f1e466c92e78fd712b0ab08c11d31/inst/resources/bs4_book/bs4_book.js#L25 */ 85 | // Initialise search index on focus 86 | var fuse; 87 | $("#search-input").focus(async function(e) { 88 | if (fuse) { 89 | return; 90 | } 91 | 92 | $(e.target).addClass("loading"); 93 | var response = await fetch($("#search-input").data("search-index")); 94 | var data = await response.json(); 95 | 96 | var options = { 97 | keys: ["what", "text", "code"], 98 | ignoreLocation: true, 99 | threshold: 0.1, 100 | includeMatches: true, 101 | includeScore: true, 102 | }; 103 | fuse = new Fuse(data, options); 104 | 105 | $(e.target).removeClass("loading"); 106 | }); 107 | 108 | // Use algolia autocomplete 109 | var options = { 110 | autoselect: true, 111 | debug: true, 112 | hint: false, 113 | minLength: 2, 114 | }; 115 | var q; 116 | async function searchFuse(query, callback) { 117 | await fuse; 118 | 119 | var items; 120 | if (!fuse) { 121 | items = []; 122 | } else { 123 | q = query; 124 | var results = fuse.search(query, { limit: 20 }); 125 | items = results 126 | .filter((x) => x.score <= 0.75) 127 | .map((x) => x.item); 128 | if (items.length === 0) { 129 | items = [{dir:"Sorry 😿",previous_headings:"",title:"No results found.",what:"No results found.",path:window.location.href}]; 130 | } 131 | } 132 | callback(items); 133 | } 134 | $("#search-input").autocomplete(options, [ 135 | { 136 | name: "content", 137 | source: searchFuse, 138 | templates: { 139 | suggestion: (s) => { 140 | if (s.title == s.what) { 141 | return `${s.dir} >
${s.title}
`; 142 | } else if (s.previous_headings == "") { 143 | return `${s.dir} >
${s.title}
> ${s.what}`; 144 | } else { 145 | return `${s.dir} >
${s.title}
> ${s.previous_headings} > ${s.what}`; 146 | } 147 | }, 148 | }, 149 | }, 150 | ]).on('autocomplete:selected', function(event, s) { 151 | window.location.href = s.path + "?q=" + q + "#" + s.id; 152 | }); 153 | }); 154 | })(window.jQuery || window.$) 155 | 156 | document.addEventListener('keydown', function(event) { 157 | // Check if the pressed key is '/' 158 | if (event.key === '/') { 159 | event.preventDefault(); // Prevent any default action associated with the '/' key 160 | document.getElementById('search-input').focus(); // Set focus to the search input 161 | } 162 | }); 163 | -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: 3.6.4 2 | pkgdown: 2.1.1 3 | pkgdown_sha: ~ 4 | articles: 5 | alonso-penalty-2024: alonso-penalty-2024.html 6 | introduction: introduction.html 7 | jolpica-data-analysis: jolpica-data-analysis.html 8 | plotting-turn-info: plotting-turn-info.html 9 | setup_fastf1: setup_fastf1.html 10 | last_built: 2025-03-27T00:49Z 11 | urls: 12 | reference: https://scasanova.github.io/f1dataR/reference 13 | article: https://scasanova.github.io/f1dataR/articles 14 | -------------------------------------------------------------------------------- /docs/reference/Rplot001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/reference/Rplot001.png -------------------------------------------------------------------------------- /docs/reference/figures/README-plot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/reference/figures/README-plot-1.png -------------------------------------------------------------------------------- /docs/reference/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/docs/reference/figures/logo.png -------------------------------------------------------------------------------- /man/add_col_if_absent.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{add_col_if_absent} 4 | \alias{add_col_if_absent} 5 | \title{Add Column if Absent} 6 | \usage{ 7 | add_col_if_absent(data, column_name, na_type = NA) 8 | } 9 | \arguments{ 10 | \item{data}{a data.frame or tibble to which a column may be added} 11 | 12 | \item{column_name}{the name of the column to be added if it doesn't exist} 13 | 14 | \item{na_type}{the type of NA value to use for the column values. Default to basic \code{NA}} 15 | } 16 | \value{ 17 | the data.frame as provided (converted to tibble) 18 | } 19 | \description{ 20 | Adds a column (with the name specified in column_name) of NA values to a data.frame or tibble. If that 21 | column already exists, no change will be made to data. NA value type (character, integer, real, logical) 22 | may be specified. 23 | } 24 | \keyword{internal} 25 | -------------------------------------------------------------------------------- /man/change_cache.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/clear_f1_cache.R 3 | \name{change_cache} 4 | \alias{change_cache} 5 | \title{Change Caching Settings} 6 | \usage{ 7 | change_cache(cache = "memory", create_dir = FALSE, persist = FALSE) 8 | } 9 | \arguments{ 10 | \item{cache}{One of \code{'memory'}, \code{'filesystem'}, \code{'off'} or a directory. 11 | 12 | If the selection is \code{'filesystem'} the package will automatically write the cache to 13 | the operating system's default location for permanent or temporary caches (see \code{persist})} 14 | 15 | \item{create_dir}{Whether to create the directory if it doesn't already exist if 16 | a path cache directory is provided. By default this doesn't occur for provided 17 | cache paths, but will always happen if the cache choice is set to \code{'filesystem'}.} 18 | 19 | \item{persist}{Whether to make this change permanent (\code{TRUE}) or a temporary cache 20 | change only (default, \code{FALSE}). Note if you set \code{cache} to \code{'off'} and \code{persist} to 21 | \code{TRUE} the existing cache will be cleared by calling \code{clear_cache()}. 22 | 23 | If \code{filesystem} is chosen for \code{cache} and \code{persist} is set to \code{TRUE}, then a cache 24 | directory will be placed in the default location for the operating system. If instead 25 | \code{persist} is set to \code{FALSE}, then a temporary directory will be used instead, and this 26 | will be removed at the end of the session. This essentially has the same effect as 27 | having \code{cache} set to \code{'memory'}.} 28 | } 29 | \value{ 30 | No return, called for side effects 31 | } 32 | \description{ 33 | Change caching settings for the package. By default, the cache will be 34 | set to keep the results of function calls in memory to reduce the number of requests 35 | made to online services for the same data. However, if preferred, the cache can be 36 | set to a file directory to make the results persist between sessions. 37 | 38 | This is a particularly good idea if you're using functions like \code{load_driver_telemetry()}, 39 | \code{load_session_laps()}, \code{load_race_session()} or \code{plot_fastest()} as they take 40 | significant time and download large amounts of data each time you run the function. 41 | 42 | If preferred for testing or waiting for data updates on race weekends, you may wish to 43 | set the cache to \code{'off'} instead. 44 | 45 | Changes to cache can be made for the session (mark the argument \code{persist} as \code{FALSE}) 46 | or apply to the next session(s) by setting \code{persist} to \code{TRUE} 47 | } 48 | \examples{ 49 | \dontrun{ 50 | change_cache("~/f1dataRcache", create_dir = TRUE) 51 | 52 | change_cache("off", persist = FALSE) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /man/check_ff1_session_loaded.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{check_ff1_session_loaded} 4 | \alias{check_ff1_session_loaded} 5 | \title{Check FastF1 Session Loaded} 6 | \usage{ 7 | check_ff1_session_loaded(session_name = "session") 8 | } 9 | \arguments{ 10 | \item{session_name}{Name of the python session object. For internal functions, typically \code{session}.} 11 | } 12 | \value{ 13 | invisible TRUE, no real return, called for effect 14 | } 15 | \description{ 16 | Used to verify that the fastf1 session is loaded before trying to work with it. 17 | 18 | Prevents errors in automated processing code. 19 | } 20 | \keyword{internal} 21 | -------------------------------------------------------------------------------- /man/check_ff1_version.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{check_ff1_version} 4 | \alias{check_ff1_version} 5 | \title{Check FastF1 Version} 6 | \usage{ 7 | check_ff1_version() 8 | } 9 | \value{ 10 | Invisibly \code{TRUE} if not raising an error for unsupported \code{FastF1} version. 11 | } 12 | \description{ 13 | This function checks the version of \code{FastF1} and ensures it's at or above the minimum supported version for 14 | \code{f1dataR} (currently requires 3.1.0 or better). 15 | 16 | This function is a light wrapper around get_fastf1_version() 17 | } 18 | \keyword{internal} 19 | -------------------------------------------------------------------------------- /man/clear_cache.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/clear_f1_cache.R 3 | \name{clear_f1_cache} 4 | \alias{clear_f1_cache} 5 | \alias{clear_cache} 6 | \title{Clear f1dataR Cache} 7 | \usage{ 8 | clear_f1_cache() 9 | 10 | clear_cache() 11 | } 12 | \value{ 13 | No return value, called to erase cached data 14 | } 15 | \description{ 16 | Clears the cache for f1dataR telemetry and Jolpica API results. 17 | Note that the cache directory can be set by setting \verb{option(f1dataR.cache = [cache dir])}, 18 | but the default is a temporary directory. 19 | 20 | You can also call the alias \code{clear_cache()} for the same result 21 | } 22 | \examples{ 23 | \dontrun{ 24 | clear_f1_cache() 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /man/correct_track_ratio.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plot_fastest.R 3 | \name{correct_track_ratio} 4 | \alias{correct_track_ratio} 5 | \title{Correct Track Ratios} 6 | \usage{ 7 | correct_track_ratio(trackplot, x = "x", y = "y", background = "grey10") 8 | } 9 | \arguments{ 10 | \item{trackplot}{A GGPlot object, ideally showing a track layout for ratio correction} 11 | 12 | \item{x, y}{Names of columns in the original data used for the plot's x and y values. 13 | Defaults to 'x' and 'y'} 14 | 15 | \item{background}{Background colour to use for filling out the plot edges. Defaults to 16 | \code{"grey10"} which is the default background colour if you use \code{\link[f1dataR]{theme_dark_f1}()} 17 | to theme your plots.} 18 | } 19 | \value{ 20 | a ggplot object with \code{ggplot2::scale_x_continuous()} and \code{ggplot2::scale_y_continuous()} set to the 21 | same limits to produce an image with shared x and y limits and with \code{ggplot2::coord_fixed()} set. 22 | } 23 | \description{ 24 | Correct Track Ratios helps ensure that ggplot objects are plotted with 1:1 unit ratio. 25 | Without this function, plots have different x & y ratios and the tracks come out misshapen. 26 | This is particularly evident at long tracks like Saudi Arabia or Canada. 27 | 28 | Note that this leaves the plot object on a dark background, any plot borders will be maintained 29 | } 30 | \examples{ 31 | \dontrun{ 32 | # Note that plot_fastest plots have already been ratio corrected 33 | fast_plot <- plot_fastest(season = 2022, round = 1, session = "Q", driver = V) 34 | correct_track_ratio(fast_plot) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /man/driver_team_lookup.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plotting_style.R 3 | \name{driver_team_lookup} 4 | \alias{driver_team_lookup} 5 | \alias{get_driver_abbreviation} 6 | \alias{get_driver_name} 7 | \alias{get_team_name} 8 | \alias{get_drivers_by_team} 9 | \alias{get_team_by_driver} 10 | \alias{get_session_drivers_and_teams} 11 | \title{Driver & Team Look-ups} 12 | \usage{ 13 | get_driver_abbreviation( 14 | driver_name, 15 | season = get_current_season(), 16 | round = 1, 17 | session = "R" 18 | ) 19 | 20 | get_driver_name( 21 | driver_name, 22 | season = get_current_season(), 23 | round = 1, 24 | session = "R" 25 | ) 26 | 27 | get_team_name(team_name, season = get_current_season(), short = FALSE) 28 | 29 | get_drivers_by_team( 30 | team_name, 31 | season = get_current_season(), 32 | round = 1, 33 | session = "R" 34 | ) 35 | 36 | get_team_by_driver( 37 | driver_name, 38 | season = get_current_season(), 39 | round = 1, 40 | short = FALSE 41 | ) 42 | 43 | get_session_drivers_and_teams(season, round, session = "R") 44 | } 45 | \arguments{ 46 | \item{driver_name}{Driver name (or unique part thereof) to look up.} 47 | 48 | \item{season}{The season for which the look-up should occur. Should be a number from 2018 to current season. 49 | Defaults to current season.} 50 | 51 | \item{round}{number from 1 to 24 (depending on season selected) and defaults 52 | to most recent. Also accepts race name.} 53 | 54 | \item{session}{the code for the session to load. Options are \code{'FP1'}, \code{'FP2'}, \code{'FP3'}, 55 | \code{'Q'}, \code{'S'}, \code{'SS'},\code{'SQ'}, and \code{'R'}. Default is \code{'R'}, which refers to Race.} 56 | 57 | \item{team_name}{The team name (as a string) to use for lookup.} 58 | 59 | \item{short}{whether to provide a shortened version of the team name. Default False.} 60 | } 61 | \value{ 62 | for \code{get_session_drivers_and_teams()} a data.frame, 63 | for \code{get_drivers_by_team()} a unnamed character vector with all drivers for the requested team, 64 | for all other functions a character result with the requested value. 65 | } 66 | \description{ 67 | These functions provide the ability to look-up drivers or teams (and match the two) for given 68 | races or seasons. 69 | 70 | \code{get_driver_abbreviation()} looks up the driver abbreviation (typically 3 letters) as used in the provided season. 71 | 72 | \code{get_team_name()} looks up the officially recorded team name based on fuzzy matching to the supplied string. This is 73 | fairly inconsistent, for example, "Haas" is recorded as "Haas F1 Team", but not all sponsor names are recorded nor are 74 | all names indicating 'F1 Team' -- "RB" is recorded as "RB" and not "Visa Cash App RB F1 Team". If \code{short = TRUE} then 75 | a short form for the team is provided ("Haas" instead of "Haas F1 Team"). 76 | 77 | \code{get_driver_name()} looks up a driver's full name based on fuzzy matching to the supplied string. The driver has to 78 | have participated in the session (season, round, session) for this to match properly. For full-time drivers this is 79 | easy, but for rookies who do test FP1 this is a more important note. 80 | 81 | \code{get_drivers_by_team()} looks up a team's drivers for the provided race session (season, round, session). If looking 82 | for practice rookies, they typically participate in \code{session = FP1}. 83 | 84 | \code{get_team_by_driver()} looks up the team for the specified driver (at the specified race event). 85 | 86 | \code{get_session_drivers_and_teams()} returns a data frame of all drivers and their team for a provided session. 87 | } 88 | -------------------------------------------------------------------------------- /man/figures/README-plot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/man/figures/README-plot-1.png -------------------------------------------------------------------------------- /man/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/man/figures/logo.png -------------------------------------------------------------------------------- /man/get_aesthetics.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plotting_style.R 3 | \name{get_aesthetics} 4 | \alias{get_aesthetics} 5 | \alias{get_driver_style} 6 | \alias{get_driver_color} 7 | \alias{get_driver_colour} 8 | \alias{get_team_color} 9 | \alias{get_team_colour} 10 | \alias{get_driver_color_map} 11 | \alias{get_driver_colour_map} 12 | \title{Get Aesthetics} 13 | \usage{ 14 | get_driver_style(driver, season = get_current_season(), round = 1) 15 | 16 | get_driver_color(driver, season = get_current_season(), round = 1) 17 | 18 | get_driver_colour(driver, season = get_current_season(), round = 1) 19 | 20 | get_team_color(team, season = get_current_season(), round = 1) 21 | 22 | get_team_colour(team, season = get_current_season(), round = 1) 23 | 24 | get_driver_color_map(season = get_current_season(), round = 1, session = "R") 25 | 26 | get_driver_colour_map(season = get_current_season(), round = 1, session = "R") 27 | } 28 | \arguments{ 29 | \item{driver}{Driver abbreviation or name (FastF1 performs a fuzzy-match to ambiguous strings).} 30 | 31 | \item{season}{A season corresponding to the race being referenced for collecting colour/style. Should be a number 32 | from 2018 to current season. Defaults to current season.} 33 | 34 | \item{round}{A round corresponding to the race being referenced for collecting colour/style. Should be a string name 35 | or a number from 1 to the number of rounds in the season and defaults to 1.} 36 | 37 | \item{team}{Team abbreviation or name (FastF1 performs a fuzzy-match to ambiguous strings).} 38 | 39 | \item{session}{the code for the session to load. Options are \code{'FP1'}, \code{'FP2'}, \code{'FP3'}, 40 | \code{'Q'}, \code{'S'}, \code{'SS'},\code{'SQ'}, and \code{'R'}. Default is \code{'R'}, which refers to Race.} 41 | } 42 | \value{ 43 | for \code{get_driver_style()} a named list of graphic parameters for the provided driver, plus the driver 44 | identifier provided and the official abbreviation matched to that driver (names are \code{linestyle}, \code{marker}, \code{color}, 45 | \code{driver}, \code{abbreviation}). 46 | 47 | for \code{get_driver_color()} and \code{get_team_color()}, a hexidecimal RGB color value. 48 | } 49 | \description{ 50 | Various aesthetics can be retrieved for a driver or team for a specific session/event. 51 | 52 | \code{get_driver_style()} gets the FastF1 style for a driver for a session - this includes team colour and line/marker 53 | style which should be reasonably (but not guaranteed) consistent across a season. Based on FastF1's 54 | \href{https://docs.fastf1.dev/plotting.html#fastf1.plotting.get_driver_style}{get_driver_style}. 55 | 56 | \code{get_driver_color()} and its alias \code{get_driver_colour()} return a hexidecimal RGB colour code for a driver at a 57 | given season & race. Note that, in contrast to earlier versions, both drivers for a team will be provided the same 58 | color. Use \code{get_driver_style()} to develop a unique marker/linestyle for each driver in a team. Data is provided by 59 | the python FastF1 package. 60 | 61 | \code{get_driver_color_mapping()} and its alias \code{get_driver_colour_mapping()} return a data.frame of driver short-codes 62 | and their hexidecimal colour. Like \code{get_driver_color()}, both drivers on a team will get the same colour returned. 63 | Data is provided by the python FastF1 package. Requires provision of a specific race event (season/round/session). 64 | 65 | \code{get_team_color()} and its alias \code{get_team_colour()} return a hexidecimal RGB colour code for a a team at a given 66 | season & race. Data is provided by the python FastF1 package. 67 | } 68 | \examples{ 69 | if (interactive()) { 70 | # To get a specific season/race, specify them. 71 | get_driver_style(driver = "ALO", season = 2024, round = 3) 72 | 73 | # For drivers who haven't moved around recently, get their current season's style: 74 | get_driver_style(driver = "LEC") 75 | 76 | # Get all driver abbreviations and colors quickly: 77 | get_driver_color_mapping(season = 2023, round = "Montreal", session = "R") 78 | 79 | get_team_color(team = "Alpine", season = 2023, round = 1) 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /man/get_current_season.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{get_current_season} 4 | \alias{get_current_season} 5 | \title{Get Current Season} 6 | \usage{ 7 | get_current_season() 8 | } 9 | \value{ 10 | Year (four digit number) representation of current season, as numeric. 11 | } 12 | \description{ 13 | Determines current season by System Date. Note returns the season prior to the current year 14 | in January and February 15 | } 16 | -------------------------------------------------------------------------------- /man/get_driver_telemetry.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_driver_telemetry.R 3 | \name{get_driver_telemetry} 4 | \alias{get_driver_telemetry} 5 | \title{Load Telemetry Data for a Driver} 6 | \usage{ 7 | get_driver_telemetry( 8 | season = get_current_season(), 9 | round = 1, 10 | session = "R", 11 | driver, 12 | laps = "fastest", 13 | log_level = "WARNING", 14 | fastest_only = lifecycle::deprecated(), 15 | race = lifecycle::deprecated() 16 | ) 17 | } 18 | \arguments{ 19 | \item{season}{number from 2018 to current season (defaults to current season).} 20 | 21 | \item{round}{number from 1 to 23 (depending on season selected). Also accepts race name.} 22 | 23 | \item{session}{the code for the session to load Options are \code{'FP1'}, \code{'FP2'}, \code{'FP3'}, 24 | \code{'Q'}, \code{'S'}, \code{'SS'}, \code{'SQ'}, and \code{'R'}. Default is \code{'R'}, which refers to Race.} 25 | 26 | \item{driver}{three letter driver code (see \code{load_drivers()} for a list)} 27 | 28 | \item{laps}{which lap's telemetry to return. One of an integer lap number (<= total laps in the race), \code{fastest}, 29 | or \code{all}. Note that integer lap choice requires \code{fastf1} version 3.0 or greater.} 30 | 31 | \item{log_level}{Detail of logging from fastf1 to be displayed. Choice of: 32 | \code{'DEBUG'}, \code{'INFO'}, \code{'WARNING'}, \code{'ERROR'} and \code{'CRITICAL'}. See \href{https://docs.fastf1.dev/fastf1.html#configure-logging-verbosity}{fastf1 documentation}.} 33 | 34 | \item{fastest_only}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} \code{fastest_only} is no longer supported, indicated preferred 35 | laps in \code{laps}.} 36 | 37 | \item{race}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} \code{race} is no longer supported, use \code{round}.} 38 | } 39 | \value{ 40 | A tibble with telemetry data for selected driver/session. 41 | } 42 | \description{ 43 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} 44 | 45 | \code{get_driver_telemetry()} was renamed to \code{load_driver_telemetry()} to create a more 46 | consistent API. 47 | } 48 | \keyword{internal} 49 | -------------------------------------------------------------------------------- /man/get_ergast_content.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{get_ergast_content} 4 | \alias{get_ergast_content} 5 | \title{Get Ergast Content} 6 | \usage{ 7 | get_ergast_content(url) 8 | } 9 | \arguments{ 10 | \item{url}{the Ergast URL tail to get from the API (for example, 11 | \code{"{season}/circuits.json?limit=40"} is called from \code{load_circuits()}).} 12 | } 13 | \value{ 14 | the result of \code{jsonlite::fromJSON} called on Ergast's return content. 15 | Further processing is performed by specific functions 16 | } 17 | \description{ 18 | Gets Ergast content and returns the processed json object if 19 | no Ergast errors are found. This will automatically fall back from https:// 20 | to http:// if Ergast suffers errors, and will automatically retry up to 5 21 | times by each protocol 22 | 23 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} 24 | 25 | Note the Ergast Motor Racing Database API will shut down at the end of 2024. 26 | This function willbe replaced with a new data-source when one is made available. 27 | } 28 | \keyword{internal} 29 | -------------------------------------------------------------------------------- /man/get_fastf1_version.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{get_fastf1_version} 4 | \alias{get_fastf1_version} 5 | \title{Get current FastF1 version} 6 | \usage{ 7 | get_fastf1_version() 8 | } 9 | \value{ 10 | version as class \code{package_version} 11 | } 12 | \description{ 13 | Gets the current installed FastF1 version available (via \code{reticulate}) to the function. 14 | Displays a note if significantly out of date. 15 | } 16 | -------------------------------------------------------------------------------- /man/get_jolpica_content.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{get_jolpica_content} 4 | \alias{get_jolpica_content} 5 | \title{Get Jolpica Content} 6 | \usage{ 7 | get_jolpica_content(url) 8 | } 9 | \arguments{ 10 | \item{url}{the Jolpica URL tail to get from the API (for example, 11 | \code{"{season}/circuits.json?limit=40"} is called from \code{load_circuits()}).} 12 | } 13 | \value{ 14 | the result of \code{jsonlite::fromJSON} called on Jolpica's return content. 15 | Further processing is performed by specific functions 16 | } 17 | \description{ 18 | Gets Jolpica-F1 content and returns the processed json object if 19 | no errors are found. This will automatically fall back from https:// 20 | to http:// if Jolpica suffers errors, and will automatically retry up to 5 21 | times by each protocol 22 | 23 | Note in 2024 this replaced the deprecated Ergast API. Much of the historical data 24 | is duplicated in Jolpica 25 | } 26 | \keyword{internal} 27 | -------------------------------------------------------------------------------- /man/get_session.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plotting_style.R 3 | \name{get_session} 4 | \alias{get_session} 5 | \title{Get Session} 6 | \usage{ 7 | get_session(season = get_current_season(), round = 1, session = "R") 8 | } 9 | \arguments{ 10 | \item{season}{number from 2018 to current season. Defaults to current season.} 11 | 12 | \item{round}{number from 1 to 23 (depending on season selected) and defaults 13 | to most recent. Also accepts race name.} 14 | 15 | \item{session}{the code for the session to load. Options are \code{'FP1'}, \code{'FP2'}, \code{'FP3'}, 16 | \code{'Q'}, \code{'S'}, \code{'SS'},\code{'SQ'}, and \code{'R'}. Default is \code{'R'}, which refers to Race.} 17 | } 18 | \value{ 19 | invisibly, the python environment 20 | } 21 | \description{ 22 | This preps a \code{fastf1.get_session()} python call and returns invisibly the python environment 23 | } 24 | \keyword{internal} 25 | -------------------------------------------------------------------------------- /man/get_tire_compounds.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plotting_style.R 3 | \name{get_tire_compounds} 4 | \alias{get_tire_compounds} 5 | \title{Get Tire Compounds} 6 | \usage{ 7 | get_tire_compounds(season = get_current_season()) 8 | } 9 | \arguments{ 10 | \item{season}{number from 2018 to current season. Defaults to current season.} 11 | } 12 | \value{ 13 | a data.frame with two columns: \code{compound} and \code{color} 14 | } 15 | \description{ 16 | Get a data.frame of all tire compound names and associated colours for a season. 17 | } 18 | \examples{ 19 | if (interactive()) { 20 | # To get this season's tires 21 | get_tire_compounds() 22 | 23 | # Compare to 2018 tires: 24 | get_tire_compounds(2018) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /man/load_circuit_details.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/circuit_details.R 3 | \name{load_circuit_details} 4 | \alias{load_circuit_details} 5 | \title{Load Circuit Information} 6 | \usage{ 7 | load_circuit_details( 8 | season = get_current_season(), 9 | round = 1, 10 | log_level = "WARNING" 11 | ) 12 | } 13 | \arguments{ 14 | \item{season}{number from 2018 to current season. Defaults to current season.} 15 | 16 | \item{round}{number from 1 to 23 (depending on season selected). Also accepts race name.} 17 | 18 | \item{log_level}{Detail of logging from fastf1 to be displayed. Choice of: 19 | \code{'DEBUG'}, \code{'INFO'}, \code{'WARNING'}, \code{'ERROR'} and \code{'CRITICAL'}. See 20 | \href{https://docs.fastf1.dev/fastf1.html#configure-logging-verbosity}{fastf1 documentation}.} 21 | } 22 | \value{ 23 | A list of tibbles containing corner number, marshall post number, or marshall segment, plus a numeric value for 24 | rotational offset of the data compared to telemetry data. 25 | 26 | The tibbles all have the following structure: 27 | \code{x} and \code{y} specify the position on the track map 28 | \code{number} is the number of the corner. Letter is optionally used to differentiate corners with the same number on some circuits, e.g. “2A”. 29 | \code{angle} is an angle in degrees, used to visually offset the marker’s placement on a track map in a logical direction (usually orthogonal to the track). 30 | \code{distance} is the location of the marker as a distance from the start/finish line. 31 | } 32 | \description{ 33 | Loads circuit details for a specific race session. Note that different track layouts are used at some 34 | circuits depending on the year of the race. 35 | 36 | Useful for visualizing or annotating data. Contains information on corners, marshal_lights and marshal_sectors. 37 | 38 | Each set of these track marker types is returned as a tibble. 39 | 40 | Also returns an angle (in degrees) to indicate the amount of rotation of the telemetry to visually align the two. 41 | 42 | More information on the data provided (and uses) can be seen at https://docs.fastf1.dev/circuit_info.html#fastf1.mvapi.CircuitInfo.corners 43 | 44 | Note that this is an exposition of FastF1 data. As such, caching is recommended (and default behavior). 45 | Cache directory can be set by setting \verb{option(f1dataR.cache = [cache dir])}, 46 | default is the current working directory. 47 | 48 | If you have trouble with errors mentioning 'fastf1' or 'get_fastf1_version()' read the 49 | 'Setup FastF1 Connection vignette (run \code{vignette('setup_fastf1', 'f1dataR')}). 50 | } 51 | -------------------------------------------------------------------------------- /man/load_circuits.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_circuits.R 3 | \name{load_circuits} 4 | \alias{load_circuits} 5 | \title{Load Circuit Info} 6 | \usage{ 7 | load_circuits(season = get_current_season()) 8 | } 9 | \arguments{ 10 | \item{season}{number from 1950 to current season (defaults to current season).} 11 | } 12 | \value{ 13 | A tibble with one row per circuit 14 | } 15 | \description{ 16 | Loads circuit info for all circuits in a given season. Use \code{.load_circuits()} 17 | for an uncached version of this function 18 | } 19 | -------------------------------------------------------------------------------- /man/load_constructors.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_constructors.R 3 | \name{load_constructors} 4 | \alias{load_constructors} 5 | \title{Load Constructor Info} 6 | \usage{ 7 | load_constructors() 8 | } 9 | \value{ 10 | A tibble with one row per constructor 11 | } 12 | \description{ 13 | Loads constructor info for all participants in a given season. 14 | Use \code{.load_constructors()}for an uncached version of this function 15 | } 16 | -------------------------------------------------------------------------------- /man/load_driver_telemetry.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_driver_telemetry.R 3 | \name{load_driver_telemetry} 4 | \alias{load_driver_telemetry} 5 | \title{Load Telemetry Data for a Driver} 6 | \usage{ 7 | load_driver_telemetry( 8 | season = get_current_season(), 9 | round = 1, 10 | session = "R", 11 | driver, 12 | laps = "fastest", 13 | log_level = "WARNING", 14 | race = lifecycle::deprecated(), 15 | fastest_only = lifecycle::deprecated() 16 | ) 17 | } 18 | \arguments{ 19 | \item{season}{number from 2018 to current season (defaults to current season).} 20 | 21 | \item{round}{number from 1 to 23 (depending on season selected). Also accepts race name.} 22 | 23 | \item{session}{the code for the session to load Options are \code{'FP1'}, \code{'FP2'}, \code{'FP3'}, 24 | \code{'Q'}, \code{'S'}, \code{'SS'}, \code{'SQ'}, and \code{'R'}. Default is \code{'R'}, which refers to Race.} 25 | 26 | \item{driver}{three letter driver code (see \code{load_drivers()} for a list)} 27 | 28 | \item{laps}{which lap's telemetry to return. One of an integer lap number (<= total laps in the race), \code{fastest}, 29 | or \code{all}. Note that integer lap choice requires \code{fastf1} version 3.0 or greater.} 30 | 31 | \item{log_level}{Detail of logging from fastf1 to be displayed. Choice of: 32 | \code{'DEBUG'}, \code{'INFO'}, \code{'WARNING'}, \code{'ERROR'} and \code{'CRITICAL'}. See \href{https://docs.fastf1.dev/fastf1.html#configure-logging-verbosity}{fastf1 documentation}.} 33 | 34 | \item{race}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} \code{race} is no longer supported, use \code{round}.} 35 | 36 | \item{fastest_only}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} \code{fastest_only} is no longer supported, indicated preferred 37 | laps in \code{laps}.} 38 | } 39 | \value{ 40 | A tibble with telemetry data for selected driver/session. 41 | } 42 | \description{ 43 | Receives season, race number, driver code, and an optional fastest lap only 44 | argument to output car telemetry for the selected situation. 45 | Example usage of this code can be seen in the Introduction vignette (run 46 | \code{vignette('introduction', 'f1dataR')} to read). Multiple drivers' telemetry can be appended 47 | to one data frame by the user. 48 | 49 | If you have trouble with errors mentioning 'fastf1' or 'get_fastf1_version()' read the 50 | "Setup FastF1 Connection" vignette (run \code{vignette('setup_fastf1', 'f1dataR')}). 51 | } 52 | \examples{ 53 | if (interactive()) { 54 | telem <- load_driver_telemetry( 55 | season = 2023, 56 | round = "Bahrain", 57 | session = "Q", 58 | driver = "HAM", 59 | laps = "fastest" 60 | ) 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /man/load_drivers.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_drivers.R 3 | \name{load_drivers} 4 | \alias{load_drivers} 5 | \title{Load Driver Info} 6 | \usage{ 7 | load_drivers(season = get_current_season()) 8 | } 9 | \arguments{ 10 | \item{season}{number from 1950 to current season (defaults to current season).} 11 | } 12 | \value{ 13 | A tibble with columns driver_id (unique and recurring), first name, 14 | last name, nationality, date of birth (yyyy-mm-dd format), driver code, and 15 | permanent number (for post-2014 drivers). 16 | } 17 | \description{ 18 | Loads driver info for all participants in a given season. 19 | Use \code{.load_drivers()} for an uncached version of this function. 20 | } 21 | -------------------------------------------------------------------------------- /man/load_laps.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_laps.R 3 | \name{load_laps} 4 | \alias{load_laps} 5 | \title{Load Lap by Lap Time Data} 6 | \usage{ 7 | load_laps( 8 | season = get_current_season(), 9 | round = "last", 10 | race = lifecycle::deprecated() 11 | ) 12 | } 13 | \arguments{ 14 | \item{season}{number from 1996 to current season (defaults to current season).} 15 | 16 | \item{round}{number from 1 to 23 (depending on season selected) and defaults 17 | to most recent. Also accepts \code{'last'}.} 18 | 19 | \item{race}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} \code{race} is no longer supported, use \code{round}.} 20 | } 21 | \value{ 22 | A tibble with columns driver_id (unique and recurring), position 23 | during lap, time (in clock form), lap number, time (in seconds), and season. 24 | } 25 | \description{ 26 | Loads basic lap-by-lap time data for all drivers in a given season 27 | and round. Lap time data is available from 1996 onward. Use \code{.load_laps()} for a uncached version. 28 | } 29 | -------------------------------------------------------------------------------- /man/load_pitstops.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_pitstops.R 3 | \name{load_pitstops} 4 | \alias{load_pitstops} 5 | \title{Load Pitstop Data} 6 | \usage{ 7 | load_pitstops( 8 | season = get_current_season(), 9 | round = "last", 10 | race = lifecycle::deprecated() 11 | ) 12 | } 13 | \arguments{ 14 | \item{season}{number from 2011 to current season (defaults to current season).} 15 | 16 | \item{round}{number from 1 to 23 (depending on season selected) and defaults 17 | to most recent.Also accepts \code{'last'}.} 18 | 19 | \item{race}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} \code{race} is no longer supported, please use \code{round}.} 20 | } 21 | \value{ 22 | A tibble with columns driver_id, lap, stop (number), time (of day), 23 | and stop duration 24 | } 25 | \description{ 26 | Loads pit stop info (number, lap, time elapsed) for a given race 27 | in a season. Pit stop data is available from 2012 onward. 28 | Call \code{.load_pitstops()} for an uncached version. 29 | } 30 | -------------------------------------------------------------------------------- /man/load_quali.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_quali.R 3 | \name{load_quali} 4 | \alias{load_quali} 5 | \title{Load Qualifying Results} 6 | \usage{ 7 | load_quali(season = get_current_season(), round = "last") 8 | } 9 | \arguments{ 10 | \item{season}{number from 2003 to current season (defaults to current season).} 11 | 12 | \item{round}{number from 1 to 23 (depending on season), and defaults 13 | to most recent. Also accepts \code{'last'}.} 14 | } 15 | \value{ 16 | A tibble with one row per driver 17 | } 18 | \description{ 19 | Loads qualifying session results for a given season and round. 20 | Use \code{.load_quali()} for an uncached version. 21 | } 22 | -------------------------------------------------------------------------------- /man/load_race_session.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_race_session.R 3 | \name{load_race_session} 4 | \alias{load_race_session} 5 | \title{Load Session Data} 6 | \usage{ 7 | load_race_session( 8 | obj_name = "session", 9 | season = get_current_season(), 10 | round = 1, 11 | session = "R", 12 | log_level = "WARNING", 13 | race = lifecycle::deprecated() 14 | ) 15 | } 16 | \arguments{ 17 | \item{obj_name}{name assigned to the loaded session to be referenced later. 18 | Leave as \code{'session'} unless otherwise required.} 19 | 20 | \item{season}{number from 2018 to current season. Defaults to current season.} 21 | 22 | \item{round}{number from 1 to 24 (depending on season selected) and defaults 23 | to most recent. Also accepts race name.} 24 | 25 | \item{session}{the code for the session to load. Options are \code{'FP1'}, \code{'FP2'}, \code{'FP3'}, 26 | \code{'Q'}, \code{'S'}, \code{'SS'},\code{'SQ'}, and \code{'R'}. Default is \code{'R'}, which refers to Race.} 27 | 28 | \item{log_level}{Detail of logging from fastf1 to be displayed. Choice of: 29 | \code{'DEBUG'}, \code{'INFO'}, \code{'WARNING'}, \code{'ERROR'} and \code{'CRITICAL.'} See 30 | \href{https://docs.fastf1.dev/fastf1.html#configure-logging-verbosity}{fastf1 documentation}.} 31 | 32 | \item{race}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} \code{race} is no longer supported, use \code{round}} 33 | } 34 | \value{ 35 | A session object to be used in other functions invisibly. 36 | } 37 | \description{ 38 | Loads telemetry and general data from the official F1 data stream via 39 | the fastf1 python library. Data is available from 2018 onward. 40 | 41 | The data loaded can optionally be assigned to a R variable, and then interrogated for 42 | session data streams. See the \href{https://docs.fastf1.dev/}{fastf1 documentation} 43 | for more details on the data returned by the python API. 44 | 45 | If you have trouble with errors mentioning 'fastf1' or 'get_fastf1_version()' read the 46 | 'Setup FastF1 Connection vignette (run \code{vignette('setup_fastf1', 'f1dataR')}). 47 | 48 | Cache directory can be set by setting \verb{option(f1dataR.cache = [cache dir])}, 49 | default is the current working directory. 50 | } 51 | \examples{ 52 | # Load the quali session from 2019 first round 53 | if (interactive()) { 54 | session <- load_race_session(season = 2019, round = 1, session = "Q") 55 | } 56 | } 57 | \seealso{ 58 | \code{\link[=load_session_laps]{load_session_laps()}} \code{\link[=plot_fastest]{plot_fastest()}} 59 | } 60 | -------------------------------------------------------------------------------- /man/load_results.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_results.R 3 | \name{load_results} 4 | \alias{load_results} 5 | \title{Load Results} 6 | \usage{ 7 | load_results(season = get_current_season(), round = "last") 8 | } 9 | \arguments{ 10 | \item{season}{number from 1950 to current season (or the word 'current') (defaults to current season).} 11 | 12 | \item{round}{number from 1 to 23 (depending on season), and defaults to most recent. Also accepts \code{'last'}.} 13 | } 14 | \value{ 15 | A tibble with one row per driver, with columns for driver & constructor ID, the points won by each driver in 16 | the race, their finishing position, their starting (grid) position, number of completed laps, status code, gap to 17 | leader (or time of race), fastest lap ranking, drivers' fastest lap time, top speed achieved, and fastest lap time 18 | in seconds. 19 | } 20 | \description{ 21 | Loads final race results for a given year and round. Use \code{.load_results()} for an uncached version 22 | } 23 | -------------------------------------------------------------------------------- /man/load_schedule.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_schedule.R 3 | \name{load_schedule} 4 | \alias{load_schedule} 5 | \title{Load Schedule} 6 | \usage{ 7 | load_schedule(season = get_current_season()) 8 | } 9 | \arguments{ 10 | \item{season}{number from 1950 to current season (defaults to current season). \code{'current'} also accepted.} 11 | } 12 | \value{ 13 | A tibble with one row per round in season. Indicates in sprint_date if a specific round has a sprint race 14 | } 15 | \description{ 16 | Loads schedule information for a given F1 season. 17 | Use \code{.load_schedule()} for an uncached version. 18 | } 19 | -------------------------------------------------------------------------------- /man/load_session_laps.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_session_laps.R 3 | \name{load_session_laps} 4 | \alias{load_session_laps} 5 | \title{Load Lapwise Data} 6 | \usage{ 7 | load_session_laps( 8 | season = get_current_season(), 9 | round = 1, 10 | session = "R", 11 | log_level = "WARNING", 12 | add_weather = FALSE, 13 | race = lifecycle::deprecated() 14 | ) 15 | } 16 | \arguments{ 17 | \item{season}{number from 2018 to current season. Defaults to current season.} 18 | 19 | \item{round}{number from 1 to 24 (depending on season selected) and defaults 20 | to most recent. Also accepts race name.} 21 | 22 | \item{session}{the code for the session to load. Options are \code{'FP1'}, \code{'FP2'}, \code{'FP3'}, 23 | \code{'Q'}, \code{'S'}, \code{'SS'},\code{'SQ'}, and \code{'R'}. Default is \code{'R'}, which refers to Race.} 24 | 25 | \item{log_level}{Detail of logging from fastf1 to be displayed. Choice of: 26 | \code{'DEBUG'}, \code{'INFO'}, \code{'WARNING'}, \code{'ERROR'} and \code{'CRITICAL.'} See 27 | \href{https://docs.fastf1.dev/fastf1.html#configure-logging-verbosity}{fastf1 documentation}.} 28 | 29 | \item{add_weather}{Whether to add weather information to the laps. See 30 | \href{https://docs.fastf1.dev/core.html#fastf1.core.Laps.get_weather_data}{fastf1 documentation} for info on weather.} 31 | 32 | \item{race}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} \code{race} is no longer supported, use \code{round}} 33 | } 34 | \value{ 35 | A tibble. Note time information is in seconds, see \href{https://docs.fastf1.dev/time_explanation.html}{fastf1 documentation} for more information on timing. 36 | } 37 | \description{ 38 | Loads lapwise data for a race session. 39 | 40 | Includes each driver's each lap's laptime, pit in/out time, tyre information, track status, and (optionally) weather information. 41 | The resulting data frame contains a column for the session type. Note that quali sessions are labelled Q1, Q2 & Q3. 42 | 43 | Cache directory can be set by setting \verb{option(f1dataR.cache = [cache dir])}, 44 | default is the current working directory. 45 | 46 | If you have trouble with errors mentioning 'fastf1' or 'get_fastf1_version()' read the 47 | 'Setup FastF1 Connection vignette (run \code{vignette('setup_fastf1', 'f1dataR')}). 48 | } 49 | -------------------------------------------------------------------------------- /man/load_sprint.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_sprint.R 3 | \name{load_sprint} 4 | \alias{load_sprint} 5 | \title{Load Sprint Results} 6 | \usage{ 7 | load_sprint(season = get_current_season(), round = "last") 8 | } 9 | \arguments{ 10 | \item{season}{number from 2021 to current season (defaults to current season).} 11 | 12 | \item{round}{number from 1 to 23 (depending on season), and defaults 13 | to most recent. Also accepts \code{'last'}.} 14 | } 15 | \value{ 16 | A dataframetibble with columns driver_id, constructor_id, points awarded, finishing position, 17 | grid position, laps completed, race status (finished or otherwise), gap to 18 | first place, fastest lap, fastest lap time, fastest lap in seconds, 19 | or NULL if no sprint exists for this season/round combo 20 | } 21 | \description{ 22 | Loads final race results for a given year and round. Note not all rounds have 23 | sprint results. Use \code{.load_sprint()} for an uncached version of this function. 24 | } 25 | -------------------------------------------------------------------------------- /man/load_standings.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_standings.R 3 | \name{load_standings} 4 | \alias{load_standings} 5 | \title{Load Standings} 6 | \usage{ 7 | load_standings(season = get_current_season(), round = "last", type = "driver") 8 | } 9 | \arguments{ 10 | \item{season}{number from 2003 to current season (defaults to current season).} 11 | 12 | \item{round}{number from 1 to 23 (depending on season), and defaults 13 | to most recent. Also accepts \code{'last'}.} 14 | 15 | \item{type}{select \code{'driver'} or \code{'constructor'} championship data. Defaults to 16 | \code{'driver'}} 17 | } 18 | \value{ 19 | A tibble with columns driver_id (or constructor_id), position, 20 | points, wins (and constructors_id in the case of drivers championship). 21 | } 22 | \description{ 23 | Loads standings at the end of a given season and round for drivers' or 24 | constructors' championships. Use \code{.load_standings()} for an uncached version of this function. 25 | } 26 | -------------------------------------------------------------------------------- /man/plot_fastest.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plot_fastest.R 3 | \name{plot_fastest} 4 | \alias{plot_fastest} 5 | \title{Plot Fastest Lap} 6 | \usage{ 7 | plot_fastest( 8 | season = get_current_season(), 9 | round = 1, 10 | session = "R", 11 | driver, 12 | color = "gear", 13 | race = lifecycle::deprecated() 14 | ) 15 | } 16 | \arguments{ 17 | \item{season}{number from 2018 to current season (defaults to current season).} 18 | 19 | \item{round}{number from 1 to 23 (depending on season selected) and defaults 20 | to most recent.} 21 | 22 | \item{session}{the code for the session to load Options are \code{'FP1'}, \code{'FP2'}, \code{'FP3'}, 23 | \code{'Q'}, \code{'S'}, \code{'SS'}, \code{'SQ'}, and \code{'R'}. Default is \code{'R'}, which refers to Race.} 24 | 25 | \item{driver}{three letter driver code (see load_drivers() for a list) or name to be 26 | fuzzy matched to a driver from the session if FastF1 >= 3.4.0 is available.} 27 | 28 | \item{color}{argument that indicates which variable to plot along the 29 | circuit. Choice of \code{'gear'} or \code{'speed'}, default \code{'gear'}.} 30 | 31 | \item{race}{number from 1 to 23 (depending on season selected) and defaults 32 | to most recent.} 33 | } 34 | \value{ 35 | A ggplot object that indicates grand prix, driver, time and selected 36 | color variable. 37 | } 38 | \description{ 39 | Creates a ggplot graphic that details the fastest lap for a driver in a race. 40 | Complete with a gearshift or speed analysis. 41 | } 42 | \examples{ 43 | # Plot Verstappen's fastest lap (speed) from Bahrain 2023: 44 | if (interactive()) { 45 | plot_fastest(2023, 1, "R", "VER", "speed") 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /man/setup_fastf1.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{setup_fastf1} 4 | \alias{setup_fastf1} 5 | \title{Setup fastf1 connection} 6 | \usage{ 7 | setup_fastf1( 8 | ..., 9 | envname = "f1dataR_env", 10 | new_env = identical(envname, "f1dataR_env") 11 | ) 12 | } 13 | \arguments{ 14 | \item{...}{Additional parameters to pass to \link[reticulate]{py_install}} 15 | 16 | \item{envname}{Optionally pass an environment name used. Defaults to package default of \code{f1dataR_env}.} 17 | 18 | \item{new_env}{Whether or not to completely remove and recreate the environment provided in \code{envname}. This will fix 19 | any issues experienced by \code{fastf1} related to package dependencies.} 20 | } 21 | \value{ 22 | No return value, called to install or update \code{fastf1} Python package. 23 | } 24 | \description{ 25 | Installs or optionally updates \code{fastf1} Python package in the current active Python 26 | environment/virtualenv/conda env. 27 | 28 | More information on how to manage complex environment needs can be read in the 29 | \href{https://rstudio.github.io/reticulate/articles/python_dependencies.html}{reticulate docs}, and tools for 30 | managing virtual environments are documented in \link[reticulate]{virtualenv-tools} and 31 | \link[reticulate]{conda-tools} 32 | } 33 | \examples{ 34 | \dontrun{ 35 | # Install fastf1 into the currently active Python environment 36 | setup_fastf1() 37 | 38 | # Reinstall fastf1 and recreate the environment. 39 | setup_fastf1(envname = "f1dataR_env", new_env = TRUE) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /man/theme_dark_f1.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/theme_dark_f1.R 3 | \name{theme_dark_f1} 4 | \alias{theme_dark_f1} 5 | \title{Dark F1-style Theme for ggplot} 6 | \usage{ 7 | theme_dark_f1(axis_marks = FALSE) 8 | } 9 | \arguments{ 10 | \item{axis_marks}{True or false, whether axis line, ticks and title should 11 | be shown or not. Defaults to false} 12 | } 13 | \value{ 14 | A ggplot object that indicates grand prix, driver, time and selected 15 | color variable. 16 | } 17 | \description{ 18 | Theme for all f1dataR plot functions. Mimics Formula 1 style. 19 | } 20 | -------------------------------------------------------------------------------- /man/time_to_sec.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{time_to_sec} 4 | \alias{time_to_sec} 5 | \title{Convert Clock time to seconds} 6 | \usage{ 7 | time_to_sec(time) 8 | } 9 | \arguments{ 10 | \item{time}{character string with clock format (0:00.000)} 11 | } 12 | \value{ 13 | A numeric variable that represents that time in seconds 14 | } 15 | \description{ 16 | This function converts clock format time (0:00.000) to seconds (0.000s) 17 | } 18 | -------------------------------------------------------------------------------- /pkgdown/_pkgdown.yml: -------------------------------------------------------------------------------- 1 | destination: docs 2 | 3 | url: https://scasanova.github.io/f1dataR 4 | 5 | reference: 6 | - title: Telemetry 7 | desc: Access car and driver telemetry from any session and any race 8 | contents: 9 | - load_driver_telemetry 10 | - title: General Data 11 | contents: 12 | - starts_with("load_") 13 | - title: Plotting 14 | contents: 15 | - starts_with("plot_") 16 | - theme_dark_f1 17 | - correct_track_ratio 18 | - load_circuit_details 19 | - title: Metadata and Lookups 20 | contents: 21 | - get_driver_abbreviation 22 | - get_driver_color 23 | - get_driver_color_map 24 | - get_driver_colour 25 | - get_driver_colour_map 26 | - get_driver_name 27 | - get_driver_style 28 | - get_driver_telemetry 29 | - get_drivers_by_team 30 | - get_session_drivers_and_teams 31 | - get_team_by_driver 32 | - get_team_color 33 | - get_team_colour 34 | - get_team_name 35 | - get_tire_compounds 36 | - title: Extras 37 | contents: 38 | - time_to_sec 39 | - clear_f1_cache 40 | - change_cache 41 | - setup_fastf1 42 | - get_current_season 43 | - get_fastf1_version 44 | 45 | authors: 46 | Santiago Casanova: 47 | href: https://twitter.com/BrotoFFCasanova 48 | Philip Bulsink: 49 | href: https://twitter.com/pbulsink 50 | -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/pkgdown/favicon/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/pkgdown/favicon/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/pkgdown/favicon/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/pkgdown/favicon/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/pkgdown/favicon/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/pkgdown/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/pkgdown/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/pkgdown/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/pkgdown/favicon/favicon.ico -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | # This file is part of the standard setup for testthat. 2 | # It is recommended that you do not modify it. 3 | # 4 | # Where should you do additional test configuration? 5 | # Learn more about the roles of various files in: 6 | # * https://r-pkgs.org/tests.html 7 | # * https://testthat.r-lib.org/reference/test_package.html#special-files 8 | 9 | library(testthat) 10 | library(f1dataR) 11 | 12 | test_check("f1dataR") 13 | -------------------------------------------------------------------------------- /tests/testthat/setup.R: -------------------------------------------------------------------------------- 1 | require(httptest2, quietly = TRUE) 2 | 3 | 4 | # helper function to skip tests if we don't have the fastf1 module 5 | skip_if_no_ff1 <- function() { 6 | if (!require("reticulate", quietly = TRUE)) { 7 | testthat::skip("Reticulate unavailable for testing") 8 | } 9 | have_ff1 <- "fastf1" %in% reticulate::py_list_packages()$package 10 | if (!have_ff1) { 11 | testthat::skip("fastf1 not available for testing") 12 | } 13 | } 14 | 15 | 16 | # helper function to skip tests if we don't have ggplot2 17 | skip_if_no_ggplot2 <- function() { 18 | if (!require("ggplot2", quietly = TRUE)) { 19 | testthat::skip("ggplot2 not available for testing") 20 | } 21 | } 22 | 23 | 24 | # helper function to skip if python isn't available by reticulate 25 | skip_if_no_py <- function() { 26 | if (!require("reticulate", quietly = TRUE)) { 27 | testthat::skip("Reticulate unavailable for testing") 28 | } 29 | if (!reticulate::py_available(initialize = TRUE)) { 30 | testthat::skip("Python not available for testing") 31 | } 32 | } 33 | 34 | 35 | # helper function to skip if jolpica isn't working 36 | skip_if_no_jolpica <- function() { 37 | testthat::skip_if_offline("jolpi.ca") # This will also skip on CRAN 38 | if (is.null(get_jolpica_content("current/circuits.json?limit=40"))) { 39 | testthat::skip("No Jolpica connection available for testing") 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/testthat/test-clear_f1_cache.R: -------------------------------------------------------------------------------- 1 | test_that("Cache Clearing works for memoised functions to file", { 2 | skip_if_no_jolpica() 3 | # Note: cache clearing for fastf1 is not our responsibility, it's performed 4 | # by a call to fastf1 itself. 5 | 6 | # Set testing specific parameters - this disposes after the test finishes 7 | if (dir.exists(file.path(tempdir(), "tst_clear_cache"))) { 8 | unlink(file.path(tempdir(), "tst_clear_cache"), recursive = TRUE, force = TRUE) 9 | } 10 | withr::local_file(file.path(tempdir(), "tst_clear_cache")) 11 | dir.create(file.path(tempdir(), "tst_clear_cache"), recursive = TRUE) 12 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_clear_cache")) 13 | 14 | expect_false(memoise::has_cache(load_schedule)()) 15 | tmp <- load_schedule() 16 | expect_true(memoise::has_cache(load_schedule)()) 17 | clear_f1_cache() 18 | expect_false(memoise::has_cache(load_schedule)()) 19 | }) 20 | 21 | 22 | test_that("load_ciruits (off cache) works", { 23 | skip_if_no_jolpica() 24 | # Set testing specific parameters - this disposes after the test finishes 25 | change_cache("off", persist = FALSE) 26 | 27 | ciruits_2021 <- load_circuits(2021) 28 | 29 | expect_equal(nrow(ciruits_2021), 21) 30 | expect_equal(ciruits_2021$circuit_id[3], "baku") 31 | expect_equal(ciruits_2021$locality[1], "Austin") 32 | }) 33 | 34 | 35 | test_that("load_ciruits (memory cache) works", { 36 | skip_if_no_jolpica() 37 | 38 | # Set testing specific parameters - this disposes after the test finishes 39 | withr::local_options("f1dataR.cache" = NULL) 40 | change_cache("memory", persist = TRUE) 41 | expect_equal(getOption("f1dataR.cache"), "memory") 42 | 43 | ciruits_2021 <- load_circuits(2021) 44 | 45 | expect_equal(nrow(ciruits_2021), 21) 46 | expect_equal(ciruits_2021$circuit_id[3], "baku") 47 | expect_equal(ciruits_2021$locality[1], "Austin") 48 | }) 49 | 50 | 51 | test_that("load_ciruits (bad path cache) works", { 52 | # Set testing specific parameters - this disposes after the test finishes 53 | expect_error(change_cache("fakedirectory"), "Attempt to set cache to fakedirectory failed*") 54 | }) 55 | 56 | 57 | test_that("load_ciruits (filesystem cache) works", { 58 | skip_if_no_jolpica() 59 | 60 | # Set testing specific parameters - this disposes after the test finishes 61 | withr::local_options("f1dataR.cache" = NULL) 62 | change_cache(cache = "filesystem") 63 | 64 | ciruits_2021 <- load_circuits(2021) 65 | 66 | expect_equal(nrow(ciruits_2021), 21) 67 | expect_equal(ciruits_2021$circuit_id[3], "baku") 68 | expect_equal(ciruits_2021$locality[1], "Austin") 69 | }) 70 | -------------------------------------------------------------------------------- /tests/testthat/test-load_circuit_details.R: -------------------------------------------------------------------------------- 1 | test_that("load circuit details works", { 2 | testthat::skip_if_offline("livetiming.formula1.com") 3 | skip_if_no_py() 4 | skip_if_no_ff1() 5 | 6 | # Set testing specific parameters - this disposes after the test finishes 7 | # Note: The test suite can't delete the old fastf1_http_cache.sqlite file 8 | # because python's process has it locked. 9 | if (dir.exists(file.path(tempdir(), "tst_circuit_details"))) { 10 | unlink(file.path(tempdir(), "tst_circuit_details"), recursive = TRUE, force = TRUE) 11 | } 12 | withr::local_file(file.path(tempdir(), "tst_circuit_details")) 13 | dir.create(file.path(tempdir(), "tst_circuit_details"), recursive = TRUE) 14 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_circuit_details")) 15 | 16 | # Ensure failure if old ff1, then skip 17 | ff1_ver <- get_fastf1_version() 18 | if (ff1_ver < "3.1") { 19 | expect_error( 20 | circuit_details <- load_circuit_details(2023, "bahrain"), 21 | "An old version of FastF1 is in use" 22 | ) 23 | skip("Skipping load_circuit_details tests as FastF1 is out of date.") 24 | } 25 | 26 | circuit_details <- load_circuit_details(2023, "bahrain") 27 | expect_type(circuit_details, "list") 28 | expect_length(circuit_details, 4) 29 | 30 | # Check corners tibble 31 | expect_named(circuit_details[[1]], c("x", "y", "number", "letter", "angle", "distance")) 32 | expect_true(is.data.frame(circuit_details[[1]])) 33 | corners <- circuit_details[[1]]$number 34 | 35 | expect_true(all(corners > 0)) 36 | expect_true(all(corners == as.integer(corners))) 37 | 38 | # Check marshal_post tibble 39 | expect_named(circuit_details[[2]], c("x", "y", "number", "letter", "angle", "distance")) 40 | expect_true(is.data.frame(circuit_details[[2]])) 41 | 42 | # Check marshal_sectors tibble 43 | expect_named(circuit_details[[3]], c("x", "y", "number", "letter", "angle", "distance")) 44 | expect_true(is.data.frame(circuit_details[[3]])) 45 | 46 | # Check rotation value 47 | expect_type(circuit_details[[4]], "double") 48 | expect_true(circuit_details[[4]] >= 0 & circuit_details[[4]] <= 360) 49 | }) 50 | 51 | test_that("Load Circuit Details works without internet", { 52 | skip_if_no_py() 53 | skip_if_no_ff1() 54 | 55 | # Set testing specific parameters - this disposes after the test finishes 56 | # Note: The test suite can't delete the old fastf1_http_cache.sqlite file 57 | # because python's process has it locked. 58 | if (dir.exists(file.path(tempdir(), "tst_telem2"))) { 59 | unlink(file.path(tempdir(), "tst_telem2"), recursive = TRUE, force = TRUE) 60 | } 61 | withr::local_file(file.path(tempdir(), "tst_telem2")) 62 | dir.create(file.path(tempdir(), "tst_telem2"), recursive = TRUE) 63 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_telem2")) 64 | 65 | ff1_ver <- get_fastf1_version() 66 | if (ff1_ver < "3.1") { 67 | skip("Skipping load_circuit_details (no internet) test as FastF1 is out of date.") 68 | } 69 | 70 | clear_cache() 71 | 72 | if (requireNamespace("httptest2", quietly = TRUE)) { 73 | # This will normally print many warnings and errors to the test log, we don't need those (we expect them as 74 | # a byproduct of the without_internet call 75 | suppressWarnings({ 76 | suppressMessages({ 77 | httptest2::without_internet({ 78 | expect_message(load_circuit_details(2023, "bahrain"), "f1dataR: Can't connect to F1 Live Timing for FastF1 data download") 79 | expect_null(load_circuit_details(2023, "bahrain")) 80 | }) 81 | }) 82 | }) 83 | } 84 | }) 85 | -------------------------------------------------------------------------------- /tests/testthat/test-load_circuits.R: -------------------------------------------------------------------------------- 1 | test_that("load_ciruits works", { 2 | # Set testing specific parameters - this disposes after the test finishes 3 | if (dir.exists(file.path(tempdir(), "tst_load_circuits"))) { 4 | unlink(file.path(tempdir(), "tst_load_circuits"), recursive = TRUE, force = TRUE) 5 | } 6 | withr::local_file(file.path(tempdir(), "tst_load_circuits")) 7 | dir.create(file.path(tempdir(), "tst_load_circuits"), recursive = TRUE) 8 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_circuits")) 9 | 10 | skip_if_no_jolpica() 11 | 12 | circuits_2021 <- load_circuits(2021) 13 | 14 | skip_if(is.null(circuits_2021)) 15 | 16 | expect_equal(nrow(circuits_2021), 21) 17 | expect_equal(circuits_2021$circuit_id[3], "baku") 18 | expect_equal(circuits_2021$locality[1], "Austin") 19 | 20 | expect_error(load_circuits(3050), "`season` must be between 1950 and *") 21 | }) 22 | 23 | test_that("load_circuits works without internet", { 24 | # Set testing specific parameters - this disposes after the test finishes 25 | if (dir.exists(file.path(tempdir(), "tst_load_circuits2"))) { 26 | unlink(file.path(tempdir(), "tst_load_circuits2"), recursive = TRUE, force = TRUE) 27 | } 28 | withr::local_file(file.path(tempdir(), "tst_load_circuits2")) 29 | dir.create(file.path(tempdir(), "tst_load_circuits2"), recursive = TRUE) 30 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_circuits2")) 31 | 32 | clear_cache() 33 | 34 | if (requireNamespace("httptest2", quietly = TRUE)) { 35 | # This will normally print many warnings and errors to the test log, we don't need those (we expect them as 36 | # a byproduct of the without_internet call 37 | suppressWarnings({ 38 | suppressMessages({ 39 | httptest2::without_internet({ 40 | expect_message(load_circuits(2021), "f1dataR: Error getting data from Jolpica") 41 | expect_null(load_circuits(2021)) 42 | }) 43 | }) 44 | }) 45 | } 46 | }) 47 | -------------------------------------------------------------------------------- /tests/testthat/test-load_constructors.R: -------------------------------------------------------------------------------- 1 | test_that("load_constructors works", { 2 | # Set testing specific parameters - this disposes after the test finishes 3 | if (dir.exists(file.path(tempdir(), "tst_load_constructors"))) { 4 | unlink(file.path(tempdir(), "tst_load_constructors"), recursive = TRUE, force = TRUE) 5 | } 6 | withr::local_file(file.path(tempdir(), "tst_load_constructors")) 7 | dir.create(file.path(tempdir(), "tst_load_constructors"), recursive = TRUE) 8 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_constructors")) 9 | 10 | skip_if_no_jolpica() 11 | 12 | constructors <- load_constructors() 13 | 14 | skip_if(is.null(constructors)) 15 | 16 | expect_equal(ncol(constructors), 3) 17 | expect_equal(constructors[1, ]$constructor_id, "adams") 18 | expect_true(nrow(unique(constructors)) >= 212) 19 | }) 20 | 21 | test_that("load_constructors works without internet", { 22 | # Set testing specific parameters - this disposes after the test finishes 23 | if (dir.exists(file.path(tempdir(), "tst_load_constructors2"))) { 24 | unlink(file.path(tempdir(), "tst_load_constructors2"), recursive = TRUE, force = TRUE) 25 | } 26 | withr::local_file(file.path(tempdir(), "tst_load_constructors2")) 27 | dir.create(file.path(tempdir(), "tst_load_constructors2"), recursive = TRUE) 28 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_constructors2")) 29 | 30 | clear_cache() 31 | 32 | if (requireNamespace("httptest2", quietly = TRUE)) { 33 | # This will normally print many warnings and errors to the test log, we don't need those (we expect them as 34 | # a byproduct of the without_internet call 35 | suppressWarnings({ 36 | suppressMessages({ 37 | httptest2::without_internet({ 38 | expect_message(load_constructors(), "f1dataR: Error getting data from Jolpica") 39 | expect_null(load_constructors()) 40 | }) 41 | }) 42 | }) 43 | } 44 | }) 45 | -------------------------------------------------------------------------------- /tests/testthat/test-load_driver_telemetry.R: -------------------------------------------------------------------------------- 1 | test_that("driver telemetry", { 2 | testthat::skip_if_offline("livetiming.formula1.com") 3 | skip_if_no_py() 4 | skip_if_no_ff1() 5 | 6 | # Set testing specific parameters - this disposes after the test finishes 7 | # Note: The test suite can't delete the old fastf1_http_cache.sqlite file 8 | # because python's process has it locked. 9 | withr::local_file(file.path(tempdir(), "tst_telem")) 10 | if (dir.exists(file.path(tempdir(), "tst_telem"))) { 11 | unlink(file.path(tempdir(), "tst_telem"), recursive = TRUE, force = TRUE) 12 | } 13 | dir.create(file.path(tempdir(), "tst_telem"), recursive = TRUE) 14 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_telem")) 15 | 16 | # Tests 17 | # Ensure failure if old ff1, then skip 18 | ff1_ver <- get_fastf1_version() 19 | if (ff1_ver < "3.1") { 20 | expect_error( 21 | telem <- load_driver_telemetry(season = 2023, round = "Brazil", session = "S", driver = "HAM", laps = "all"), 22 | "An old version of FastF1 is in use" 23 | ) 24 | skip("Skipping load_driver_telemetry tests as FastF1 is out of date.") 25 | } 26 | 27 | telem <- load_driver_telemetry(season = 2023, round = "Brazil", session = "S", driver = "HAM", laps = "all") 28 | telem_fast <- load_driver_telemetry(season = 2023, round = "Brazil", session = "S", driver = "HAM", laps = "fastest") 29 | 30 | expect_true(nrow(telem) > nrow(telem_fast)) 31 | expect_true(ncol(telem) == ncol(telem_fast)) 32 | 33 | expect_equal(round(telem_fast$session_time[[1]]), round(3517.868)) 34 | 35 | telem_lap <- load_driver_telemetry(season = 2023, round = "Brazil", session = "S", driver = "HAM", laps = 1) 36 | expect_equal(telem_lap$time[[1]], 0) 37 | expect_equal(telem_lap$speed[[1]], 0) 38 | expect_error( 39 | load_driver_telemetry(season = 2023, round = "Brazil", session = "S", driver = "HAM", laps = 1.5), 40 | "* must be one of `fastest`, `all` or an integer value" 41 | ) 42 | 43 | expect_error( 44 | load_driver_telemetry(season = 2023, round = "Brazil", session = "S", driver = "HAM", fastest_only = TRUE), 45 | "The `fastest_only` argument of `load_driver_telemetry\\(\\)` was deprecated in f1dataR 1.4.0 and is now defunct.*" 46 | ) 47 | 48 | expect_error( 49 | load_driver_telemetry(season = 2023, race = "Brazil", session = "S", driver = "HAM"), 50 | "The `race` argument of `load_driver_telemetry\\(\\)` was deprecated in f1dataR 1.4.0 and is now defunct.*" 51 | ) 52 | 53 | expect_error( 54 | get_driver_telemetry(season = 2023, round = "Brazil", session = "S", driver = "HAM"), 55 | "`get_driver_telemetry\\(\\)` was deprecated in f1dataR 1.4.0 and is now defunct.*" 56 | ) 57 | 58 | expect_error( 59 | get_driver_telemetry(season = 2023, race = "Brazil", session = "S", driver = "HAM", fastest_only = TRUE), 60 | "`get_driver_telemetry\\(\\)` was deprecated in f1dataR 1.4.0 and is now defunct.*" 61 | ) 62 | }) 63 | 64 | test_that("Load Driver Telemetry works without internet", { 65 | skip_if_no_py() 66 | skip_if_no_ff1() 67 | 68 | # Set testing specific parameters - this disposes after the test finishes 69 | # Note: The test suite can't delete the old fastf1_http_cache.sqlite file 70 | # because python's process has it locked. 71 | if (dir.exists(file.path(tempdir(), "tst_telem2"))) { 72 | unlink(file.path(tempdir(), "tst_telem2"), recursive = TRUE, force = TRUE) 73 | } 74 | withr::local_file(file.path(tempdir(), "tst_telem2")) 75 | dir.create(file.path(tempdir(), "tst_telem2"), recursive = TRUE) 76 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_telem2")) 77 | 78 | ff1_ver <- get_fastf1_version() 79 | if (ff1_ver < "3.1") { 80 | skip("Skipping load_driver_telemetry (no internet) test as FastF1 is out of date.") 81 | } 82 | 83 | clear_cache() 84 | 85 | if (requireNamespace("httptest2", quietly = TRUE)) { 86 | # This will normally print many warnings and errors to the test log, we don't need those (we expect them as 87 | # a byproduct of the without_internet call 88 | suppressWarnings({ 89 | suppressMessages({ 90 | httptest2::without_internet({ 91 | expect_message( 92 | load_driver_telemetry(season = 2023, round = "Brazil", session = "S", driver = "HAM", laps = "all"), 93 | "f1dataR: Can't connect to F1 Live Timing for FastF1 data download" 94 | ) 95 | expect_null(load_driver_telemetry(season = 2023, round = "Brazil", session = "S", driver = "HAM", laps = "all")) 96 | }) 97 | }) 98 | }) 99 | } 100 | }) 101 | -------------------------------------------------------------------------------- /tests/testthat/test-load_drivers.R: -------------------------------------------------------------------------------- 1 | test_that("Drivers Load works", { 2 | if (dir.exists(file.path(getwd(), "tst_load_drivers"))) { 3 | unlink(file.path(getwd(), "tst_load_drivers"), recursive = TRUE, force = TRUE) 4 | } 5 | withr::local_file(file.path(getwd(), "tst_load_drivers")) 6 | dir.create(file.path(getwd(), "tst_load_drivers"), recursive = TRUE) 7 | withr::local_options(f1dataR.cache = file.path(getwd(), "tst_load_drivers")) 8 | 9 | skip_if_no_jolpica() 10 | 11 | drivers_2021 <- load_drivers(2021) 12 | 13 | skip_if(is.null(drivers_2021)) 14 | 15 | expect_equal(nrow(drivers_2021), 21) 16 | expect_equal(drivers_2021$driver_id[2], "bottas") 17 | expect_equal(drivers_2021$code[1], "ALO") 18 | 19 | drivers_1999 <- load_drivers(1999) 20 | expect_equal(nrow(drivers_1999), 24) 21 | expect_equal(drivers_1999$driver_id[1], "alesi") 22 | 23 | expect_error(load_drivers(3050), "`season` must be between 1950 and *") 24 | }) 25 | 26 | test_that("load_drivers works without internet", { 27 | # Set testing specific parameters - this disposes after the test finishes 28 | if (dir.exists(file.path(tempdir(), "tst_load_drivers2"))) { 29 | unlink(file.path(tempdir(), "tst_load_drivers2"), recursive = TRUE, force = TRUE) 30 | } 31 | withr::local_file(file.path(tempdir(), "tst_load_drivers2")) 32 | dir.create(file.path(tempdir(), "tst_load_drivers2"), recursive = TRUE) 33 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_drivers2")) 34 | 35 | clear_cache() 36 | 37 | if (requireNamespace("httptest2", quietly = TRUE)) { 38 | # This will normally print many warnings and errors to the test log, we don't need those (we expect them as 39 | # a byproduct of the without_internet call 40 | suppressWarnings({ 41 | suppressMessages({ 42 | httptest2::without_internet({ 43 | expect_message(load_drivers(2021), "f1dataR: Error getting data from Jolpica") 44 | expect_null(load_drivers(2021)) 45 | }) 46 | }) 47 | }) 48 | } 49 | }) 50 | -------------------------------------------------------------------------------- /tests/testthat/test-load_laps.R: -------------------------------------------------------------------------------- 1 | test_that("load_laps works", { 2 | # Set testing specific parameters - this disposes after the test finishes 3 | if (dir.exists(file.path(tempdir(), "tst_load_laps"))) { 4 | unlink(file.path(tempdir(), "tst_load_laps"), recursive = TRUE, force = TRUE) 5 | } 6 | withr::local_file(file.path(tempdir(), "tst_load_laps")) 7 | dir.create(file.path(tempdir(), "tst_load_laps"), recursive = TRUE) 8 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_laps")) 9 | 10 | skip_if_no_jolpica() 11 | 12 | laps_2021_1 <- load_laps(2021, 1) 13 | 14 | skip_if(is.null(laps_2021_1)) 15 | 16 | expect_equal(nrow(unique(laps_2021_1)), 1026) 17 | expect_equal(laps_2021_1$driver_id[3], "leclerc") 18 | expect_equal(laps_2021_1$position[1], "1") 19 | 20 | expect_equal(laps_2021_1$driver_id[1026], "raikkonen") 21 | expect_equal(laps_2021_1$position[1026], "11") 22 | expect_equal(round(laps_2021_1$time_sec[1026]), round(95.96)) 23 | 24 | expect_error(load_laps(3050, 3), "`season` must be between 1996 and *") 25 | expect_error(load_laps(2021, race = 1)) 26 | 27 | # 2021 Spa had very few laps 28 | laps_short <- load_laps(2021, 12) 29 | expect_equal(nrow(laps_short), 20) 30 | 31 | # 2021 Monaco had very many laps, this checks >1000 return code 32 | laps_long <- load_laps(2021, 5) 33 | expect_equal(nrow(laps_long), 1418) 34 | }) 35 | 36 | test_that("load_laps works without internet", { 37 | # Set testing specific parameters - this disposes after the test finishes 38 | if (dir.exists(file.path(tempdir(), "tst_load_laps2"))) { 39 | unlink(file.path(tempdir(), "tst_load_laps2"), recursive = TRUE, force = TRUE) 40 | } 41 | withr::local_file(file.path(tempdir(), "tst_load_laps2")) 42 | dir.create(file.path(tempdir(), "tst_load_laps2"), recursive = TRUE) 43 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_laps2")) 44 | 45 | clear_cache() 46 | 47 | if (requireNamespace("httptest2", quietly = TRUE)) { 48 | # This will normally print many warnings and errors to the test log, we don't need those (we expect them as 49 | # a byproduct of the without_internet call 50 | suppressWarnings({ 51 | suppressMessages({ 52 | httptest2::without_internet({ 53 | expect_message(load_laps(2021, 1), "f1dataR: Error getting data from Jolpica") 54 | expect_null(load_laps(2021, 1)) 55 | }) 56 | }) 57 | }) 58 | } 59 | }) 60 | -------------------------------------------------------------------------------- /tests/testthat/test-load_pitstops.R: -------------------------------------------------------------------------------- 1 | test_that("load_pitstops works", { 2 | # Set testing specific parameters - this disposes after the test finishes 3 | if (dir.exists(file.path(tempdir(), "tst_load_pitstops"))) { 4 | unlink(file.path(tempdir(), "tst_load_pitstops"), recursive = TRUE, force = TRUE) 5 | } 6 | withr::local_file(file.path(tempdir(), "tst_load_pitstops")) 7 | dir.create(file.path(tempdir(), "tst_load_pitstops"), recursive = TRUE) 8 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_pitstops")) 9 | 10 | skip_if_no_jolpica() 11 | 12 | pitstop_2021_1 <- load_pitstops(2021, 1) 13 | 14 | skip_if(is.null(pitstop_2021_1)) 15 | 16 | expect_equal(nrow(pitstop_2021_1), 40) 17 | expect_equal(pitstop_2021_1$driver_id[1], "perez") 18 | expect_equal(pitstop_2021_1$stop[2], "1") 19 | 20 | expect_error(load_pitstops(3050, 1), "`season` must be between 2011 and *") 21 | 22 | expect_error(load_pitstops(2021, race = 1)) 23 | }) 24 | 25 | test_that("load_pitstops works without internet", { 26 | # Set testing specific parameters - this disposes after the test finishes 27 | if (dir.exists(file.path(tempdir(), "tst_load_pitstops2"))) { 28 | unlink(file.path(tempdir(), "tst_load_pitstops2"), recursive = TRUE, force = TRUE) 29 | } 30 | withr::local_file(file.path(tempdir(), "tst_load_pitstops2")) 31 | dir.create(file.path(tempdir(), "tst_load_pitstops2"), recursive = TRUE) 32 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_pitstops2")) 33 | 34 | clear_cache() 35 | 36 | if (requireNamespace("httptest2", quietly = TRUE)) { 37 | # This will normally print many warnings and errors to the test log, we don't need those (we expect them as 38 | # a byproduct of the without_internet call 39 | suppressWarnings({ 40 | suppressMessages({ 41 | httptest2::without_internet({ 42 | expect_message(load_pitstops(2021, 1), "f1dataR: Error getting data from Jolpica") 43 | expect_null(load_pitstops(2021, 1)) 44 | }) 45 | }) 46 | }) 47 | } 48 | }) 49 | -------------------------------------------------------------------------------- /tests/testthat/test-load_quali.R: -------------------------------------------------------------------------------- 1 | test_that("load_quali works", { 2 | # Set testing specific parameters - this disposes after the test finishes 3 | if (dir.exists(file.path(tempdir(), "tst_load_quali"))) { 4 | unlink(file.path(tempdir(), "tst_load_quali"), recursive = TRUE, force = TRUE) 5 | } 6 | withr::local_file(file.path(tempdir(), "tst_load_quali")) 7 | dir.create(file.path(tempdir(), "tst_load_quali"), recursive = TRUE) 8 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_quali")) 9 | 10 | skip_if_no_jolpica() 11 | 12 | quali_2021_1 <- load_quali(2021, 1) 13 | 14 | skip_if(is.null(quali_2021_1)) 15 | 16 | expect_equal(nrow(quali_2021_1), 20) 17 | expect_equal(quali_2021_1$driver_id[2], "hamilton") 18 | expect_equal(quali_2021_1$position[1], "1") 19 | 20 | quali_2004 <- load_quali(2004, 1) 21 | expect_equal(nrow(quali_2004), 20) 22 | expect_equal(quali_2004$driver_id[2], "barrichello") 23 | expect_false("q2" %in% quali_2004) 24 | 25 | expect_equal(nrow(load_quali(2015, 16)), 20) 26 | 27 | expect_error(load_quali(3050, 2), "`season` must be between 2003 and *") 28 | }) 29 | 30 | test_that("load_quali works without internet", { 31 | # Set testing specific parameters - this disposes after the test finishes 32 | if (dir.exists(file.path(tempdir(), "tst_load_quali2"))) { 33 | unlink(file.path(tempdir(), "tst_load_quali2"), recursive = TRUE, force = TRUE) 34 | } 35 | withr::local_file(file.path(tempdir(), "tst_load_quali2")) 36 | dir.create(file.path(tempdir(), "tst_load_quali2"), recursive = TRUE) 37 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_quali2")) 38 | 39 | clear_cache() 40 | 41 | if (requireNamespace("httptest2", quietly = TRUE)) { 42 | # This will normally print many warnings and errors to the test log, we don't need those (we expect them as 43 | # a byproduct of the without_internet call 44 | suppressWarnings({ 45 | suppressMessages({ 46 | httptest2::without_internet({ 47 | expect_message(load_quali(2021, 1), "f1dataR: Error getting data from Jolpica") 48 | expect_null(load_quali(2021, 1)) 49 | }) 50 | }) 51 | }) 52 | } 53 | }) 54 | -------------------------------------------------------------------------------- /tests/testthat/test-load_race_session.R: -------------------------------------------------------------------------------- 1 | test_that("Load Session (file cached) Works", { 2 | testthat::skip_if_offline("livetiming.formula1.com") 3 | skip_if_no_py() 4 | skip_if_no_ff1() 5 | 6 | # Set testing specific parameters - this disposes after the test finishes 7 | # Note: The test suite can't delete the old fastf1_http_cache.sqlite file 8 | # because python's process has it locked. 9 | if (dir.exists(file.path(tempdir(), "tst_session"))) { 10 | unlink(file.path(tempdir(), "tst_session"), recursive = TRUE, force = TRUE) 11 | } 12 | withr::local_file(file.path(tempdir(), "tst_session")) 13 | dir.create(file.path(tempdir(), "tst_session"), recursive = TRUE) 14 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_session")) 15 | 16 | # Tests 17 | 18 | # Ensure failure if old ff1, then skip 19 | ff1_ver <- get_fastf1_version() 20 | if (ff1_ver < "3.1") { 21 | expect_error( 22 | session <- load_race_session(season = 2023, round = 1), 23 | "An old version of FastF1 is in use" 24 | ) 25 | skip("Skipping load_race_session as FastF1 is out of date.") 26 | } 27 | 28 | # test with all parameters but session provided 29 | expect_invisible(load_race_session(season = 2023, round = 1)) 30 | # validate the cache is there now 31 | expect_true(file.exists(file.path(tempdir(), "tst_session", "fastf1_http_cache.sqlite"))) 32 | 33 | # test without race provided - loads from cache 34 | expect_invisible(load_race_session(season = 2023, session = "R")) 35 | 36 | # test without season provided - default is current year assigned at argument 37 | session1 <- load_race_session(session = "R") 38 | # likewise, load it with 'current' 39 | session2 <- load_race_session(session = "R", season = "current") 40 | expect_equal(session1$api_path, session2$api_path) 41 | 42 | # verify character and numeric race can draw the same endpoint 43 | session1 <- load_race_session(season = 2023, round = 1, session = "R") 44 | session2 <- load_race_session(season = 2023, round = "Bahrain", session = "R") 45 | expect_equal(session1$api_path, session2$api_path) 46 | expect_equal(session1$event$OfficialEventName, "FORMULA 1 GULF AIR BAHRAIN GRAND PRIX 2023") 47 | 48 | expect_error( 49 | load_race_session(season = 2017), 50 | "`season` must be between 2018 and *" 51 | ) 52 | expect_error( 53 | load_race_session(session = "ZZZ"), 54 | '`session` must be one of "FP1", "FP2", "FP3", "Q", "SQ", "SS", "S", or "R"' 55 | ) 56 | expect_error(load_race_session(season = 2023, round = 1, session = "R", log_level = "ZZZ")) 57 | 58 | expect_error(load_race_session(season = 2023, race = "Bahrain", session = "R")) 59 | 60 | expect_error(load_race_session(season = 2023, round = 100, session = "R")) 61 | 62 | expect_message( 63 | load_race_session(season = 2023, round = 1, session = "R", log_level = "INFO"), 64 | "The first time a session is loaded, some time is required. Please*" 65 | ) 66 | }) 67 | 68 | test_that("Load Session (memory cached) Works", { 69 | # Most tests run in the (file cached) version 70 | 71 | skip_if_no_py() 72 | skip_if_no_ff1() 73 | 74 | # Set testing specific parameters - this disposes after the test finishes 75 | # Note: The test suite can't delete the old fastf1_http_cache.sqlite file 76 | # because python's process has it locked. 77 | withr::local_options(f1dataR.cache = "memory") 78 | 79 | # Ensure failure if old ff1, then skip 80 | ff1_ver <- get_fastf1_version() 81 | if (ff1_ver < "3.1") { 82 | expect_error( 83 | session <- load_race_session(season = 2023, round = 1), 84 | "An old version of FastF1 is in use" 85 | ) 86 | skip("Skipping load_race_session (memory cache) test as FastF1 is out of date.") 87 | } 88 | 89 | session1 <- load_race_session(season = 2023, round = 1, session = "R") 90 | expect_equal(session1$event$OfficialEventName, "FORMULA 1 GULF AIR BAHRAIN GRAND PRIX 2023") 91 | }) 92 | 93 | test_that("Load Session works without internet", { 94 | skip_if_no_py() 95 | skip_if_no_ff1() 96 | 97 | # Set testing specific parameters - this disposes after the test finishes 98 | # Note: The test suite can't delete the old fastf1_http_cache.sqlite file 99 | # because python's process has it locked. 100 | if (dir.exists(file.path(tempdir(), "tst_session2"))) { 101 | unlink(file.path(tempdir(), "tst_session2"), recursive = TRUE, force = TRUE) 102 | } 103 | withr::local_file(file.path(tempdir(), "tst_session2")) 104 | dir.create(file.path(tempdir(), "tst_session2"), recursive = TRUE) 105 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_session2")) 106 | 107 | ff1_ver <- get_fastf1_version() 108 | if (ff1_ver < "3.1") { 109 | skip("Skipping load_race_session (no internet) test as FastF1 is out of date.") 110 | } 111 | 112 | clear_cache() 113 | 114 | if (requireNamespace("httptest2", quietly = TRUE)) { 115 | # This will normally print many warnings and errors to the test log, we don't need those (we expect them as 116 | # a byproduct of the without_internet call 117 | suppressWarnings({ 118 | suppressMessages({ 119 | httptest2::without_internet({ 120 | expect_message(load_race_session(season = 2023, round = 1), "f1dataR: Can't connect to F1 Live Timing for FastF1 data download") 121 | expect_null(load_race_session(season = 2023, round = 1)) 122 | }) 123 | }) 124 | }) 125 | } 126 | }) 127 | -------------------------------------------------------------------------------- /tests/testthat/test-load_results.R: -------------------------------------------------------------------------------- 1 | test_that("load_results works", { 2 | # Set testing specific parameters - this disposes after the test finishes 3 | if (dir.exists(file.path(tempdir(), "tst_load_results"))) { 4 | unlink(file.path(tempdir(), "tst_load_results"), recursive = TRUE, force = TRUE) 5 | } 6 | withr::local_file(file.path(tempdir(), "tst_load_results")) 7 | dir.create(file.path(tempdir(), "tst_load_results"), recursive = TRUE) 8 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_results")) 9 | 10 | skip_if_no_jolpica() 11 | 12 | results_2021_1 <- load_results(2021, 1) 13 | 14 | skip_if(is.null(results_2021_1)) 15 | 16 | expect_equal(nrow(results_2021_1), 20) 17 | expect_equal(results_2021_1$driver_id[4], "norris") 18 | expect_equal(results_2021_1$position[1], "1") 19 | 20 | results_2003 <- load_results(2003, 1) 21 | expect_equal(nrow(results_2003), 20) 22 | expect_equal(results_2003$driver_id[2], "montoya") 23 | 24 | results_2025 <- load_results(2025, 1) 25 | expect_equal(nrow(results_2025), 20) 26 | expect_equal(results_2025$driver_id[5], "albon") 27 | 28 | # Special Case: 29 | results_2021_12 <- load_results(2021, 12) 30 | expect_equal(nrow(results_2021_1), nrow(results_2021_12)) 31 | expect_equal(ncol(results_2003), ncol(results_2021_12)) 32 | expect_equal(ncol(results_2021_1), ncol(results_2021_12)) 33 | 34 | expect_error(load_results(3050, 2), "`season` must be between 1950 and *") 35 | }) 36 | 37 | test_that("load_results works without internet", { 38 | # Set testing specific parameters - this disposes after the test finishes 39 | if (dir.exists(file.path(tempdir(), "tst_load_results2"))) { 40 | unlink(file.path(tempdir(), "tst_load_results2"), recursive = TRUE, force = TRUE) 41 | } 42 | withr::local_file(file.path(tempdir(), "tst_load_results2")) 43 | dir.create(file.path(tempdir(), "tst_load_results2"), recursive = TRUE) 44 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_results2")) 45 | 46 | clear_cache() 47 | 48 | if (requireNamespace("httptest2", quietly = TRUE)) { 49 | # This will normally print many warnings and errors to the test log, we don't need those (we expect them as 50 | # a byproduct of the without_internet call 51 | suppressWarnings({ 52 | suppressMessages({ 53 | httptest2::without_internet({ 54 | expect_message(load_results(2003, 1), "f1dataR: Error getting data from Jolpica") 55 | expect_null(load_results(2003, 1)) 56 | }) 57 | }) 58 | }) 59 | } 60 | }) 61 | -------------------------------------------------------------------------------- /tests/testthat/test-load_schedule.R: -------------------------------------------------------------------------------- 1 | test_that("load_schedule works", { 2 | # Set testing specific parameters - this disposes after the test finishes 3 | if (dir.exists(file.path(tempdir(), "tst_load_schedule"))) { 4 | unlink(file.path(tempdir(), "tst_load_schedule"), recursive = TRUE, force = TRUE) 5 | } 6 | withr::local_file(file.path(tempdir(), "tst_load_schedule")) 7 | dir.create(file.path(tempdir(), "tst_load_schedule"), recursive = TRUE) 8 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_schedule")) 9 | 10 | skip_if_no_jolpica() 11 | 12 | schedule_2021 <- load_schedule(2021) 13 | 14 | skip_if(is.null(schedule_2021)) 15 | 16 | expect_equal(nrow(schedule_2021), 22) 17 | expect_equal(schedule_2021$season[1], "2021") 18 | expect_equal(schedule_2021$race_name[2], "Emilia Romagna Grand Prix") 19 | 20 | schedule_1999 <- load_schedule(1999) 21 | expect_equal(nrow(schedule_1999), 16) 22 | expect_equal(schedule_1999$circuit_id[1], "albert_park") 23 | 24 | expect_error(load_schedule(3050), "`season` must be between 1950 and *") 25 | 26 | schedule_2018 <- load_schedule(2018) 27 | expect_true(all(is.na(schedule_1999$sprint_date))) 28 | expect_true(all(is.na(schedule_2018$sprint_date))) 29 | expect_equal(sum(!is.na(schedule_2021$sprint_date)), 3) 30 | }) 31 | 32 | test_that("load_schedule works without internet", { 33 | # Set testing specific parameters - this disposes after the test finishes 34 | if (dir.exists(file.path(tempdir(), "tst_load_schedule2"))) { 35 | unlink(file.path(tempdir(), "tst_load_schedule2"), recursive = TRUE, force = TRUE) 36 | } 37 | withr::local_file(file.path(tempdir(), "tst_load_schedule2")) 38 | dir.create(file.path(tempdir(), "tst_load_schedule2"), recursive = TRUE) 39 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_schedule2")) 40 | 41 | clear_cache() 42 | 43 | if (requireNamespace("httptest2", quietly = TRUE)) { 44 | # This will normally print many warnings and errors to the test log, we don't need those (we expect them as 45 | # a byproduct of the without_internet call 46 | suppressWarnings({ 47 | suppressMessages({ 48 | httptest2::without_internet({ 49 | expect_message(load_schedule(2021), "f1dataR: Error getting data from Jolpica") 50 | expect_null(load_schedule(2021)) 51 | }) 52 | }) 53 | }) 54 | } 55 | }) 56 | -------------------------------------------------------------------------------- /tests/testthat/test-load_session_laps.R: -------------------------------------------------------------------------------- 1 | test_that("load session laps works", { 2 | testthat::skip_if_offline("livetiming.formula1.com") 3 | skip_if_no_py() 4 | skip_if_no_ff1() 5 | 6 | # Set testing specific parameters - this disposes after the test finishes 7 | # Note: The test suite can't delete the old fastf1_http_cache.sqlite file 8 | # because python's process has it locked. 9 | if (dir.exists(file.path(tempdir(), "tst_session_laps"))) { 10 | unlink(file.path(tempdir(), "tst_session_laps"), recursive = TRUE, force = TRUE) 11 | } 12 | withr::local_file(file.path(tempdir(), "tst_session_laps")) 13 | dir.create(file.path(tempdir(), "tst_session_laps"), recursive = TRUE) 14 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_session_laps")) 15 | 16 | # Ensure failure if old ff1, then skip 17 | ff1_ver <- get_fastf1_version() 18 | if (ff1_ver < "3.1") { 19 | expect_error( 20 | laps <- load_session_laps(season = 2023, round = "bahrain"), 21 | "An old version of FastF1 is in use" 22 | ) 23 | skip("Skipping load_session_laps tests as FastF1 is out of date.") 24 | } 25 | 26 | laps <- load_session_laps(season = 2023, round = "bahrain") 27 | laps2 <- load_session_laps(season = 2023, round = "bahrain", add_weather = TRUE) 28 | lapsq <- load_session_laps(season = 2023, round = "bahrain", session = "Q") 29 | lapsqw <- load_session_laps(season = 2023, round = "bahrain", session = "Q", add_weather = TRUE) 30 | lapssq <- load_session_laps(season = 2024, round = "china", session = "SQ") 31 | 32 | expect_true("tbl" %in% class(laps)) 33 | expect_true(ncol(laps) %in% c(28, 32)) 34 | expect_true(ncol(laps2) %in% c(35, 39)) 35 | expect_equal(laps$time, laps2$time) 36 | expect_true(!is.na(laps$time[1])) 37 | expect_equal(nrow(laps), nrow(laps2)) 38 | expect_true(all(lapsq$session_type %in% c("Q1", "Q2", "Q3"))) 39 | expect_true(all(c("Q1", "Q2", "Q3") %in% unique(lapsq$session_type))) 40 | expect_true(all(c("SQ1", "SQ2", "SQ3") %in% unique(lapssq$session_type))) 41 | expect_true(!is.na(lapsq$time[1])) 42 | expect_equal(round(min(lapsq$lap_time, na.rm = TRUE)), round(89.708)) 43 | expect_equal(nrow(lapsq), nrow(lapsqw)) 44 | expect_equal(min(lapsq$lap_time, na.rm = TRUE), min(lapsqw$lap_time, na.rm = TRUE)) 45 | expect_lt(ncol(lapsq), ncol(lapsqw)) 46 | expect_true("wind_speed" %in% colnames(lapsqw)) 47 | 48 | expect_error(load_session_laps(season = 2023, race = "bahrain", session = "Q")) 49 | }) 50 | 51 | test_that("Load Session Laps works without internet", { 52 | skip_if_no_py() 53 | skip_if_no_ff1() 54 | 55 | # Set testing specific parameters - this disposes after the test finishes 56 | # Note: The test suite can't delete the old fastf1_http_cache.sqlite file 57 | # because python's process has it locked. 58 | if (dir.exists(file.path(tempdir(), "tst_session_laps2"))) { 59 | unlink(file.path(tempdir(), "tst_session_laps2"), recursive = TRUE, force = TRUE) 60 | } 61 | withr::local_file(file.path(tempdir(), "tst_session_laps2")) 62 | dir.create(file.path(tempdir(), "tst_session_laps2"), recursive = TRUE) 63 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_session_laps2")) 64 | 65 | ff1_ver <- get_fastf1_version() 66 | if (ff1_ver < "3.1") { 67 | skip("Skipping load_session_laps (no internet) test as FastF1 is out of date.") 68 | } 69 | 70 | clear_cache() 71 | 72 | if (requireNamespace("httptest2", quietly = TRUE)) { 73 | # This will normally print many warnings and errors to the test log, we don't need those (we expect them as 74 | # a byproduct of the without_internet call 75 | suppressWarnings({ 76 | suppressMessages({ 77 | httptest2::without_internet({ 78 | expect_message(load_session_laps(season = 2023, round = "bahrain"), "f1dataR: Can't connect to F1 Live Timing for FastF1 data download") 79 | expect_null(load_session_laps(season = 2023, round = "bahrain")) 80 | }) 81 | }) 82 | }) 83 | } 84 | }) 85 | -------------------------------------------------------------------------------- /tests/testthat/test-load_sprint.R: -------------------------------------------------------------------------------- 1 | test_that("load_sprint works", { 2 | if (dir.exists(file.path(tempdir(), "tst_load_sprint"))) { 3 | unlink(file.path(tempdir(), "tst_load_sprint"), recursive = TRUE, force = TRUE) 4 | } 5 | withr::local_file(file.path(tempdir(), "tst_load_sprint")) 6 | dir.create(file.path(tempdir(), "tst_load_sprint"), recursive = TRUE) 7 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_sprint")) 8 | 9 | skip_if_no_jolpica() 10 | 11 | # A sprint exists for season = 2021, round = 10 12 | sprint_2021_10 <- load_sprint(2021, 10) 13 | 14 | skip_if(is.null(sprint_2021_10)) 15 | 16 | expect_equal(nrow(sprint_2021_10), 20) 17 | expect_equal(sprint_2021_10$driver_id[3], "bottas") 18 | expect_equal(sprint_2021_10$position[1], "1") 19 | 20 | sprint_2025_2 <- load_sprint(2025, 2) 21 | 22 | expect_equal(nrow(sprint_2025_2), 20) 23 | expect_equal(sprint_2025_2$driver_id[1], "hamilton") 24 | expect_equal(sprint_2025_2$position[1], "1") 25 | 26 | expect_error(load_sprint(3050, 2), "`season` must be between 2021 and *") 27 | 28 | # A sprint doesn't exist for season = 2021, round = 11 29 | expect_null(suppressMessages(load_sprint(2021, 11))) 30 | }) 31 | 32 | test_that("load_sprint works without internet", { 33 | # Set testing specific parameters - this disposes after the test finishes 34 | if (dir.exists(file.path(tempdir(), "tst_load_sprint2"))) { 35 | unlink(file.path(tempdir(), "tst_load_sprint2"), recursive = TRUE, force = TRUE) 36 | } 37 | withr::local_file(file.path(tempdir(), "tst_load_sprint2")) 38 | dir.create(file.path(tempdir(), "tst_load_sprint2"), recursive = TRUE) 39 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_sprint2")) 40 | 41 | clear_cache() 42 | 43 | if (requireNamespace("httptest2", quietly = TRUE)) { 44 | # This will normally print many warnings and errors to the test log, we don't need those (we expect them as 45 | # a byproduct of the without_internet call 46 | suppressWarnings({ 47 | suppressMessages({ 48 | httptest2::without_internet({ 49 | expect_message(load_sprint(2021, 10), "f1dataR: Error getting data from Jolpica") 50 | expect_null(load_sprint(2021, 10)) 51 | }) 52 | }) 53 | }) 54 | } 55 | }) 56 | -------------------------------------------------------------------------------- /tests/testthat/test-load_standings.R: -------------------------------------------------------------------------------- 1 | test_that("load_standings works", { 2 | if (dir.exists(file.path(tempdir(), "tst_load_standings"))) { 3 | unlink(file.path(tempdir(), "tst_load_standings"), recursive = TRUE, force = TRUE) 4 | } 5 | withr::local_file(file.path(tempdir(), "tst_load_standings")) 6 | dir.create(file.path(tempdir(), "tst_load_standings"), recursive = TRUE) 7 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_standings")) 8 | 9 | skip_if_no_jolpica() 10 | 11 | standings_2021 <- load_standings(2021) 12 | 13 | skip_if(is.null(standings_2021)) 14 | 15 | expect_equal(nrow(standings_2021), 21) 16 | 17 | standings_2021_constructor <- load_standings(2021, type = "constructor") 18 | expect_equal(nrow(standings_2021_constructor), 10) 19 | 20 | expect_error(load_standings(3050), "`season` must be between 2003 and *") 21 | expect_error(load_standings(2012, "last", "bob"), '`type` must be either "driver" or "constructor"') 22 | }) 23 | 24 | test_that("load_standings works without internet", { 25 | # Set testing specific parameters - this disposes after the test finishes 26 | if (dir.exists(file.path(tempdir(), "tst_load_standings2"))) { 27 | unlink(file.path(tempdir(), "tst_load_standings2"), recursive = TRUE, force = TRUE) 28 | } 29 | withr::local_file(file.path(tempdir(), "tst_load_standings2")) 30 | dir.create(file.path(tempdir(), "tst_load_standings2"), recursive = TRUE) 31 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_load_standings2")) 32 | 33 | clear_cache() 34 | 35 | if (requireNamespace("httptest2", quietly = TRUE)) { 36 | # This will normally print many warnings and errors to the test log, we don't need those (we expect them as 37 | # a byproduct of the without_internet call 38 | suppressWarnings({ 39 | suppressMessages({ 40 | httptest2::without_internet({ 41 | expect_message(load_standings(2021), "f1dataR: Error getting data from Jolpica") 42 | expect_null(load_standings(2021)) 43 | }) 44 | }) 45 | }) 46 | } 47 | }) 48 | -------------------------------------------------------------------------------- /tests/testthat/test-plot_fastest.R: -------------------------------------------------------------------------------- 1 | test_that("graphics work", { 2 | testthat::skip_if_offline("livetiming.formula1.com") 3 | skip_if_no_py() 4 | skip_if_no_ff1() 5 | 6 | # Set testing specific parameters - this disposes after the test finishes 7 | # Note: The test suite can't delete the old fastf1_http_cache.sqlite file 8 | # because python's process has it locked. 9 | if (dir.exists(file.path(tempdir(), "tst_graphics"))) { 10 | unlink(file.path(tempdir(), "tst_graphics"), recursive = TRUE, force = TRUE) 11 | } 12 | withr::local_file(file.path(tempdir(), "tst_graphics")) 13 | dir.create(file.path(tempdir(), "tst_graphics"), recursive = TRUE) 14 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_graphics")) 15 | withr::local_seed(1234) 16 | 17 | # Ensure caught failure if no ggplot2, then skip remainder 18 | if (!require("ggplot2", quietly = TRUE)) { 19 | expect_error( 20 | plot_fastest(season = 2023, round = 1, session = "R", driver = "HAM", color = "gear"), 21 | "f1dataR::plot_fastest() requires ggplot2 package installation" 22 | ) 23 | testthat::skip("ggplot2 not available for testing graphics") 24 | } 25 | 26 | # Ensure caught failure if old ff1, then skip remainder 27 | ff1_ver <- get_fastf1_version() 28 | if (ff1_ver < "3.1") { 29 | expect_error( 30 | session <- load_race_session(season = 2023, round = 1), 31 | "An old version of FastF1 is in use" 32 | ) 33 | skip("Skipping graphics tests as FastF1 is out of date.") 34 | } 35 | 36 | # Check deprecation 37 | expect_error( 38 | plot_fastest(season = 2023, race = 1, session = "R", driver = "HAM", color = "gear"), 39 | "was deprecated in f1dataR" 40 | ) 41 | 42 | # Snapshot Tests of graphics 43 | suppressMessages({ 44 | suppressWarnings({ 45 | gear <- plot_fastest(2023, 1, "R", "HAM", "gear") 46 | speed <- plot_fastest(2023, 1, "R", "HAM", "speed") 47 | qualiplot <- plot_fastest(2023, 1, "Q", "HAM", "gear") 48 | }) 49 | }) 50 | expect_equal(gear$label$title, speed$label$title) 51 | expect_equal(gear$label$caption, "Generated by {f1dataR} package") 52 | expect_true(grepl("Lewis Hamilton Fastest Lap", gear$label$subtitle)) 53 | 54 | expect_equal(qualiplot$label$title, "2023 Bahrain Grand Prix Qualifying") 55 | 56 | qp_axis <- qualiplot + theme_dark_f1(axis_marks = TRUE) 57 | 58 | expect_equal(qp_axis$labels, qualiplot$labels) 59 | }) 60 | 61 | test_that("correct_track_ratio works", { 62 | # Ensure caught failure if no ggplot2, then skip remainder 63 | if (!require("ggplot2", quietly = TRUE)) { 64 | expect_error( 65 | correct_track_ratio("bob"), 66 | "requires ggplot2 package installation" 67 | ) 68 | testthat::skip("ggplot2 not available for testing graphics") 69 | } 70 | expect_error(correct_track_ratio("bob"), "`trackplot` must be a `ggplot` object") 71 | }) 72 | 73 | test_that("graphics works without internet", { 74 | skip_if_no_py() 75 | skip_if_no_ff1() 76 | 77 | # Set testing specific parameters - this disposes after the test finishes 78 | # Note: The test suite can't delete the old fastf1_http_cache.sqlite file 79 | # because python's process has it locked. 80 | if (dir.exists(file.path(tempdir(), "tst_graphics2"))) { 81 | unlink(file.path(tempdir(), "tst_graphics2"), recursive = TRUE, force = TRUE) 82 | } 83 | withr::local_file(file.path(tempdir(), "tst_graphics2")) 84 | dir.create(file.path(tempdir(), "tst_graphics2"), recursive = TRUE) 85 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_graphics2")) 86 | 87 | ff1_ver <- get_fastf1_version() 88 | if (ff1_ver < "3.1") { 89 | skip("Skipping load_circuit_details (no internet) test as FastF1 is out of date.") 90 | } 91 | # if no ggplot2, then skip remainder 92 | if (!require("ggplot2", quietly = TRUE)) { 93 | testthat::skip("ggplot2 not available for testing graphics") 94 | } 95 | 96 | clear_cache() 97 | 98 | if (requireNamespace("httptest2", quietly = TRUE)) { 99 | # This will normally print many warnings and errors to the test log, we don't need those (we expect them as 100 | # a byproduct of the without_internet call 101 | suppressWarnings({ 102 | suppressMessages({ 103 | httptest2::without_internet({ 104 | expect_message(plot_fastest(2023, 1, "R", "HAM", "gear"), "f1dataR: Can't connect to F1 Live Timing for FastF1 data download") 105 | expect_null(plot_fastest(2023, 1, "R", "HAM", "gear")) 106 | }) 107 | }) 108 | }) 109 | } 110 | }) 111 | -------------------------------------------------------------------------------- /tests/testthat/test-utils.R: -------------------------------------------------------------------------------- 1 | test_that("utility functions work", { 2 | # Set testing specific parameters - this disposes after the test finishes 3 | if (dir.exists(file.path(tempdir(), "tst_utils"))) { 4 | unlink(file.path(tempdir(), "tst_utils"), recursive = TRUE, force = TRUE) 5 | } 6 | withr::local_file(file.path(tempdir(), "tst_utils")) 7 | dir.create(file.path(tempdir(), "tst_utils"), recursive = TRUE) 8 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_utils")) 9 | 10 | # current season function - also naturally tested in some load_x functions 11 | expect_true(is.numeric(get_current_season())) 12 | expect_gte(get_current_season(), 2022) 13 | 14 | # get_jolpica_content() is inherently tested in load_x functions too 15 | url <- "2022/circuits.json?limit=40" 16 | 17 | expect_warning(get_ergast_content(url), regexp = "was deprecated in f1dataR") 18 | # Test for ergast deprecation 19 | 20 | # Test add_col_if_absent() 21 | testdf <- tibble::tibble("a" = 1:5, "b" = letters[1:5]) 22 | testdf2 <- testdf 23 | testdf2$col1 <- NA 24 | expect_equal(testdf2, add_col_if_absent(testdf, "col1")) 25 | expect_equal(testdf, add_col_if_absent(testdf, "a", NA_real_)) 26 | expect_error(add_col_if_absent(testdf, c("col1", "col2"))) 27 | expect_error(add_col_if_absent(testdf, "col1", 0)) 28 | expect_error(add_col_if_absent(list(a = 1:5), "col1", NA_real_)) 29 | 30 | # add_col_if_absent is also inherently tested in many load_x functions too 31 | 32 | # Test time format changes 33 | expect_equal(time_to_sec("12.345"), 12.345) 34 | expect_equal(time_to_sec("1:23.456"), 83.456) 35 | expect_equal(time_to_sec("12:34:56.789"), 45296.789) 36 | expect_equal(time_to_sec("12.3456"), 12.3456) 37 | expect_equal(time_to_sec(12.345), 12.345) 38 | 39 | expect_equal( 40 | time_to_sec(c("12.345", "1:23.456", "12:34:56.789", "12.3456")), 41 | c(12.345, 83.456, 45296.789, 12.3456) 42 | ) 43 | 44 | expect_error(check_ff1_network_connection(), "f1dataR: Specific race path must be provided") 45 | }) 46 | 47 | test_that("Utility Functions work without internet", { 48 | # Set testing specific parameters - this disposes after the test finishes 49 | if (dir.exists(file.path(tempdir(), "tst_utils2"))) { 50 | unlink(file.path(tempdir(), "tst_utils2"), recursive = TRUE, force = TRUE) 51 | } 52 | withr::local_file(file.path(tempdir(), "tst_utils2")) 53 | dir.create(file.path(tempdir(), "tst_utils2"), recursive = TRUE) 54 | withr::local_options(f1dataR.cache = file.path(tempdir(), "tst_utils2")) 55 | 56 | clear_cache() 57 | 58 | if (requireNamespace("httptest2", quietly = TRUE)) { 59 | # This will normally print many warnings and errors to the test log, we don't need those (we expect them as 60 | # a byproduct of the without_internet call 61 | suppressWarnings({ 62 | suppressMessages({ 63 | httptest2::without_internet(( 64 | expect_false(check_ff1_network_connection("/static/2024/2024-03-02_Bahrain_Grand_Prix/2024-03-02_Race/")) 65 | )) 66 | }) 67 | }) 68 | } 69 | }) 70 | -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | -------------------------------------------------------------------------------- /vignettes/alonso-penalty-2024-alo-plots-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/alonso-penalty-2024-alo-plots-1.png -------------------------------------------------------------------------------- /vignettes/alonso-penalty-2024-alo-throttle-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/alonso-penalty-2024-alo-throttle-1.png -------------------------------------------------------------------------------- /vignettes/alonso-penalty-2024-rus-plots-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/alonso-penalty-2024-rus-plots-1.png -------------------------------------------------------------------------------- /vignettes/introduction-pitstop-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/introduction-pitstop-1.png -------------------------------------------------------------------------------- /vignettes/introduction-simple_plot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/introduction-simple_plot-1.png -------------------------------------------------------------------------------- /vignettes/introduction-telem_plotting-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/introduction-telem_plotting-1.png -------------------------------------------------------------------------------- /vignettes/introduction-triple_plot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/introduction-triple_plot-1.png -------------------------------------------------------------------------------- /vignettes/introduction-tyre_life-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/introduction-tyre_life-1.png -------------------------------------------------------------------------------- /vignettes/introduction-use_builtin-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/introduction-use_builtin-1.png -------------------------------------------------------------------------------- /vignettes/introduction-use_theme-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/introduction-use_theme-1.png -------------------------------------------------------------------------------- /vignettes/jolpica-data-analysis-driver_laptime_scatterplot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/jolpica-data-analysis-driver_laptime_scatterplot-1.png -------------------------------------------------------------------------------- /vignettes/jolpica-data-analysis-drivers_laptimes-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/jolpica-data-analysis-drivers_laptimes-1.png -------------------------------------------------------------------------------- /vignettes/jolpica-data-analysis-grid_to_finish_one-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/jolpica-data-analysis-grid_to_finish_one-1.png -------------------------------------------------------------------------------- /vignettes/jolpica-data-analysis-grid_to_finish_season-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/jolpica-data-analysis-grid_to_finish_season-1.png -------------------------------------------------------------------------------- /vignettes/jolpica-data-analysis-quali_compare-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/jolpica-data-analysis-quali_compare-1.png -------------------------------------------------------------------------------- /vignettes/jolpica-data-analysis-remade_rounds_points-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/jolpica-data-analysis-remade_rounds_points-1.png -------------------------------------------------------------------------------- /vignettes/jolpica-data-analysis-round_position-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/jolpica-data-analysis-round_position-1.png -------------------------------------------------------------------------------- /vignettes/jolpica-data-analysis-rounds_points-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/jolpica-data-analysis-rounds_points-1.png -------------------------------------------------------------------------------- /vignettes/plotting-turn-info-basic_track_plot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/plotting-turn-info-basic_track_plot-1.png -------------------------------------------------------------------------------- /vignettes/plotting-turn-info-relabelled_gear_plot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/plotting-turn-info-relabelled_gear_plot-1.png -------------------------------------------------------------------------------- /vignettes/plotting-turn-info-telem_plot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/plotting-turn-info-telem_plot-1.png -------------------------------------------------------------------------------- /vignettes/plotting-turn-info-telem_with_corners-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SCasanova/f1dataR/0282790f12d7a1c6d6bfc9a64b480a9c2730d0b0/vignettes/plotting-turn-info-telem_with_corners-1.png -------------------------------------------------------------------------------- /vignettes/precompile.R: -------------------------------------------------------------------------------- 1 | # Vignettes that depend on internet access have been precompiled 2 | # Per guidance in: 3 | # https://ropensci.org/blog/2019/12/08/precompute-vignettes/#the-solution-locally-knitting-rmarkdown 4 | # Must manually move figures from package root ./ to ./vignettes if they don't go by themselves. 5 | 6 | # Install optipng for your system to enable auto-compression of png files output by knitr. 7 | # See https://bookdown.org/yihui/rmarkdown-cookbook/optipng.html 8 | 9 | knitr::knit("vignettes/jolpica-data-analysis.Rmd.orig", "vignettes/jolpica-data-analysis.Rmd") 10 | knitr::knit("vignettes/introduction.Rmd.orig", "vignettes/introduction.Rmd") 11 | knitr::knit("vignettes/plotting-turn-info.Rmd.orig", "vignettes/plotting-turn-info.Rmd") 12 | knitr::knit("vignettes/alonso-penalty-2024.Rmd.orig", "vignettes/alonso-penalty-2024.Rmd") 13 | cat("Successfully compiled vignettes. Now moving figures to ./vignettes") 14 | 15 | vig_images<-list.files(pattern = "(jolpica-data-analysis|introduction|plotting-turn-info|alonso-penalty)-[(a-z)(A-Z)(0-9)_]*-1.png") 16 | file.copy(paste0("./", vig_images), 17 | paste0("./vignettes/", vig_images), overwrite = T) 18 | unlink(vig_images) 19 | 20 | # If you have the optipng tool installed on your system run this to reduce png size 21 | # xfun::optipng("./vignettes/") 22 | 23 | # Optional 24 | devtools::build_vignettes() 25 | devtools::build_readme() 26 | -------------------------------------------------------------------------------- /vignettes/setup_fastf1.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Setup FastF1 Connection" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Setup FastF1 Connection} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r, include = FALSE} 11 | knitr::opts_chunk$set( 12 | collapse = TRUE, 13 | comment = "#>" 14 | ) 15 | ``` 16 | 17 | # Introduction 18 | 19 | This vignette briefly describes setting up the `f1dataR` package to work properly with with 20 | the Python package [`FastF1`](https://docs.fastf1.dev/). This guide may help resolve some issues 21 | that might arise when you get the following warning or error messages: 22 | 23 | - `Ensure fastf1 python package is installed. Please run this to install the most recent version: setup_fastf1()` 24 | - `Error in if (get_fastf1_version() < '3.1') { :` 25 | `missing value where TRUE/FALSE needed` 26 | 27 | If these happen to you (particularly if you're a new user of `f1dataR`) read on! 28 | 29 | # `f1dataR`'s Relationship to Python 30 | 31 | At the core of the `f1dataR` package, the connection to the Python package is created 32 | by using [`reticulate`](https://rstudio.github.io/reticulate/). This provides the 33 | connection used to call on Python and return objects to R. However, it has to be 34 | set up properly to work. 35 | 36 | > **_NOTE:_** If you are comfortable with `reticulate`, set up a virtualenv or 37 | condaenv and point reticulate to that with your .RProfile before calling `library(fastf1)`, 38 | and you can skip the rest of this guide. 39 | 40 | # Setting up `reticulate` 41 | 42 | There are a few options to get the `reticulate` set up in a way that works well for 43 | `f1dataR` to use it. 44 | 45 | ## Accept all defaults 46 | 47 | To use all of the defaults and set up the `reticulate` package, you can use the below 48 | helper function. 49 | 50 | ```r 51 | setup_fastf1() 52 | ``` 53 | 54 | This will create a virtual environment using your system's default Python version, 55 | and install `fastf1` in that python environment. It will also tell `reticulate` to use that 56 | environment instead of just running in your main system. Many resources exist online to explain python environments in more detail. 57 | 58 | # Repeat/Recurring Issues 59 | 60 | If you have repeat issues with the package failing to connect to your proper environment, 61 | you can force a complete recreation of the virtual environment by calling: 62 | 63 | ```r 64 | setup_fastf1(new_env = TRUE) 65 | ``` 66 | 67 | If you've configured the package to use a custom environment name, the above function will require that name supplied as 68 | the `envname` parameter. 69 | --------------------------------------------------------------------------------