endurancepy 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. endurancepy-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
  2. endurancepy-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
  3. endurancepy-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +32 -0
  4. endurancepy-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +29 -0
  5. endurancepy-0.1.0/.github/workflows/ci.yml +47 -0
  6. endurancepy-0.1.0/.github/workflows/integration.yml +23 -0
  7. endurancepy-0.1.0/.github/workflows/release.yml +47 -0
  8. endurancepy-0.1.0/.gitignore +75 -0
  9. endurancepy-0.1.0/CHANGELOG.md +143 -0
  10. endurancepy-0.1.0/CODE_OF_CONDUCT.md +52 -0
  11. endurancepy-0.1.0/CONTRIBUTING.md +129 -0
  12. endurancepy-0.1.0/LICENSE +21 -0
  13. endurancepy-0.1.0/PKG-INFO +240 -0
  14. endurancepy-0.1.0/README.md +177 -0
  15. endurancepy-0.1.0/RELEASING.md +40 -0
  16. endurancepy-0.1.0/docs/analyse_fastf1.md +757 -0
  17. endurancepy-0.1.0/docs/plan_implementation.md +398 -0
  18. endurancepy-0.1.0/docs/usage.md +113 -0
  19. endurancepy-0.1.0/examples/README.md +27 -0
  20. endurancepy-0.1.0/examples/lap_analysis.py +52 -0
  21. endurancepy-0.1.0/examples/plot_pace_by_class.py +59 -0
  22. endurancepy-0.1.0/examples/quickstart.ipynb +122 -0
  23. endurancepy-0.1.0/examples/quickstart.py +51 -0
  24. endurancepy-0.1.0/pyproject.toml +102 -0
  25. endurancepy-0.1.0/src/endurancepy/__init__.py +59 -0
  26. endurancepy-0.1.0/src/endurancepy/_types.py +110 -0
  27. endurancepy-0.1.0/src/endurancepy/alkamel/__init__.py +12 -0
  28. endurancepy-0.1.0/src/endurancepy/alkamel/analysis.py +209 -0
  29. endurancepy-0.1.0/src/endurancepy/alkamel/classification.py +143 -0
  30. endurancepy-0.1.0/src/endurancepy/alkamel/client.py +69 -0
  31. endurancepy-0.1.0/src/endurancepy/alkamel/discovery.py +251 -0
  32. endurancepy-0.1.0/src/endurancepy/alkamel/headers.py +72 -0
  33. endurancepy-0.1.0/src/endurancepy/alkamel/timecards.py +14 -0
  34. endurancepy-0.1.0/src/endurancepy/alkamel/timeparse.py +47 -0
  35. endurancepy-0.1.0/src/endurancepy/alkamel/weather.py +55 -0
  36. endurancepy-0.1.0/src/endurancepy/cache.py +195 -0
  37. endurancepy-0.1.0/src/endurancepy/core.py +425 -0
  38. endurancepy-0.1.0/src/endurancepy/events.py +250 -0
  39. endurancepy-0.1.0/src/endurancepy/exceptions.py +23 -0
  40. endurancepy-0.1.0/src/endurancepy/logger.py +20 -0
  41. endurancepy-0.1.0/src/endurancepy/plotting.py +101 -0
  42. endurancepy-0.1.0/src/endurancepy/py.typed +0 -0
  43. endurancepy-0.1.0/src/endurancepy/results.py +90 -0
  44. endurancepy-0.1.0/src/endurancepy/standings.py +127 -0
  45. endurancepy-0.1.0/src/endurancepy/track_status.py +63 -0
  46. endurancepy-0.1.0/tests/conftest.py +33 -0
  47. endurancepy-0.1.0/tests/fixtures/analysis_sample.csv +12 -0
  48. endurancepy-0.1.0/tests/fixtures/classification_race_sample.csv +5 -0
  49. endurancepy-0.1.0/tests/fixtures/weather_sample.csv +4 -0
  50. endurancepy-0.1.0/tests/test_analysis.py +120 -0
  51. endurancepy-0.1.0/tests/test_cache.py +58 -0
  52. endurancepy-0.1.0/tests/test_classification.py +75 -0
  53. endurancepy-0.1.0/tests/test_client.py +75 -0
  54. endurancepy-0.1.0/tests/test_discovery.py +57 -0
  55. endurancepy-0.1.0/tests/test_discovery_resolve.py +49 -0
  56. endurancepy-0.1.0/tests/test_events.py +67 -0
  57. endurancepy-0.1.0/tests/test_examples.py +35 -0
  58. endurancepy-0.1.0/tests/test_integration_network.py +52 -0
  59. endurancepy-0.1.0/tests/test_load.py +64 -0
  60. endurancepy-0.1.0/tests/test_plotting.py +43 -0
  61. endurancepy-0.1.0/tests/test_results.py +83 -0
  62. endurancepy-0.1.0/tests/test_smoke.py +49 -0
  63. endurancepy-0.1.0/tests/test_standings.py +60 -0
  64. endurancepy-0.1.0/tests/test_track_status.py +47 -0
  65. endurancepy-0.1.0/tests/test_weather.py +42 -0
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: Bug report
3
+ about: Report something that isn't working as expected
4
+ title: "[Bug] "
5
+ labels: bug
6
+ assignees: ''
7
+ ---
8
+
9
+ ## Description
10
+
11
+ A clear and concise description of the bug.
12
+
13
+ ## To reproduce
14
+
15
+ Steps (or a minimal code snippet) to reproduce the behaviour:
16
+
17
+ ```python
18
+ import endurancepy as ep
19
+ # ...
20
+ ```
21
+
22
+ ## Expected behaviour
23
+
24
+ What you expected to happen.
25
+
26
+ ## Actual behaviour
27
+
28
+ What actually happened (include the full error traceback if any).
29
+
30
+ ## Context
31
+
32
+ - Series / season / event / session involved (e.g. WEC 2024 Le Mans, Race):
33
+ - EndurancePy version / commit:
34
+ - Python version:
35
+ - OS:
36
+
37
+ ## Additional notes
38
+
39
+ Anything else that might help — but **do not attach raw Al Kamel timing files**
40
+ (they are not redistributable). A small synthetic example is fine.
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: true
2
+ contact_links:
3
+ - name: Question / discussion
4
+ url: https://github.com/RomainFl50/EndurancePy/discussions
5
+ about: Ask a question or discuss ideas before opening an issue.
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest a feature, an API, or a series/season to support
4
+ title: "[Feature] "
5
+ labels: enhancement
6
+ assignees: ''
7
+ ---
8
+
9
+ ## Problem / motivation
10
+
11
+ What are you trying to do, and what's missing today?
12
+
13
+ ## Proposed solution
14
+
15
+ Describe the feature or API you'd like. If it mirrors something in FastF1, please
16
+ link or name the equivalent.
17
+
18
+ ```python
19
+ # Sketch of the desired API, if relevant
20
+ ```
21
+
22
+ ## Series / scope
23
+
24
+ Which series or seasons does this concern (WEC, ELMS, AsLMS, Le Mans Cup, IMSA)?
25
+
26
+ ## Alternatives considered
27
+
28
+ Any alternative approaches you've thought about.
29
+
30
+ ## Additional context
31
+
32
+ Anything else (links to public result pages, references, etc.).
@@ -0,0 +1,29 @@
1
+ ## Summary
2
+
3
+ Briefly describe what this PR does and why.
4
+
5
+ ## Related issue
6
+
7
+ Closes #<!-- issue number, if any -->
8
+
9
+ ## Type of change
10
+
11
+ - [ ] Bug fix
12
+ - [ ] New feature
13
+ - [ ] Documentation
14
+ - [ ] Refactor / chore
15
+ - [ ] Tests
16
+
17
+ ## Checklist
18
+
19
+ - [ ] I have read the [CONTRIBUTING](../CONTRIBUTING.md) guide.
20
+ - [ ] My change follows the design in `docs/` (analysis & implementation plan).
21
+ - [ ] `ruff` (format + check) and `mypy` pass.
22
+ - [ ] Tests pass (`pytest`) and I added tests for new logic.
23
+ - [ ] I did **not** commit any raw Al Kamel timing data; fixtures are synthetic
24
+ or otherwise redistributable.
25
+ - [ ] Documentation / docstrings updated where relevant.
26
+
27
+ ## Notes for reviewers
28
+
29
+ Anything specific you'd like reviewers to focus on.
@@ -0,0 +1,47 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: ["main"]
6
+ pull_request:
7
+ branches: ["main"]
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ lint:
12
+ name: Lint & type-check
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-python@v5
17
+ with:
18
+ python-version: "3.12"
19
+ - name: Install dev dependencies
20
+ run: |
21
+ python -m pip install --upgrade pip
22
+ pip install -e ".[dev]"
23
+ - name: Ruff (format check)
24
+ run: ruff format --check .
25
+ - name: Ruff (lint)
26
+ run: ruff check .
27
+ - name: Mypy
28
+ run: mypy src
29
+
30
+ test:
31
+ name: Tests (Python ${{ matrix.python-version }})
32
+ runs-on: ubuntu-latest
33
+ strategy:
34
+ fail-fast: false
35
+ matrix:
36
+ python-version: ["3.10", "3.11", "3.12"]
37
+ steps:
38
+ - uses: actions/checkout@v4
39
+ - uses: actions/setup-python@v5
40
+ with:
41
+ python-version: ${{ matrix.python-version }}
42
+ - name: Install package with dev extras
43
+ run: |
44
+ python -m pip install --upgrade pip
45
+ pip install -e ".[dev]"
46
+ - name: Run tests
47
+ run: pytest -m "not network" --cov=endurancepy --cov-report=term-missing
@@ -0,0 +1,23 @@
1
+ name: integration
2
+
3
+ # On-demand end-to-end test against the live Al Kamel portal. Runs only when
4
+ # manually dispatched (GitHub Actions runners have open internet access, unlike
5
+ # the default development environment).
6
+
7
+ on:
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ integration:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.12"
18
+ - name: Install package with dev extras
19
+ run: |
20
+ python -m pip install --upgrade pip
21
+ pip install -e ".[dev]"
22
+ - name: Run network integration tests
23
+ run: pytest -m network -q
@@ -0,0 +1,47 @@
1
+ name: release
2
+
3
+ # Build the package and publish it to PyPI when a version tag is pushed.
4
+ # Publishing uses PyPI Trusted Publishing (OIDC) — no API token/secret is stored
5
+ # in the repo. See RELEASING.md for the one-time PyPI setup.
6
+
7
+ on:
8
+ push:
9
+ tags: ["v*"]
10
+ workflow_dispatch:
11
+
12
+ jobs:
13
+ build:
14
+ name: Build distributions
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.12"
21
+ - name: Build sdist and wheel
22
+ run: |
23
+ python -m pip install --upgrade pip build
24
+ python -m build
25
+ - name: Check metadata
26
+ run: |
27
+ python -m pip install --upgrade "twine>=6" "packaging>=24.2"
28
+ python -m twine check dist/*
29
+ - uses: actions/upload-artifact@v4
30
+ with:
31
+ name: dist
32
+ path: dist/
33
+
34
+ publish:
35
+ name: Publish to PyPI
36
+ needs: build
37
+ runs-on: ubuntu-latest
38
+ if: startsWith(github.ref, 'refs/tags/v')
39
+ environment: pypi
40
+ permissions:
41
+ id-token: write # required for Trusted Publishing
42
+ steps:
43
+ - uses: actions/download-artifact@v4
44
+ with:
45
+ name: dist
46
+ path: dist/
47
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,75 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution / packaging
7
+ .Python
8
+ build/
9
+ develop-eggs/
10
+ dist/
11
+ downloads/
12
+ eggs/
13
+ .eggs/
14
+ lib/
15
+ lib64/
16
+ parts/
17
+ sdist/
18
+ var/
19
+ wheels/
20
+ share/python-wheels/
21
+ *.egg-info/
22
+ .installed.cfg
23
+ *.egg
24
+ MANIFEST
25
+
26
+ # Unit test / coverage reports
27
+ htmlcov/
28
+ .tox/
29
+ .nox/
30
+ .coverage
31
+ .coverage.*
32
+ .cache
33
+ nosetests.xml
34
+ coverage.xml
35
+ *.cover
36
+ *.py,cover
37
+ .hypothesis/
38
+ .pytest_cache/
39
+
40
+ # Jupyter Notebook
41
+ .ipynb_checkpoints
42
+
43
+ # Environments
44
+ .env
45
+ .venv
46
+ env/
47
+ venv/
48
+ ENV/
49
+ env.bak/
50
+ venv.bak/
51
+
52
+ # IDEs
53
+ .idea/
54
+ .vscode/
55
+ *.swp
56
+
57
+ # OS
58
+ .DS_Store
59
+ Thumbs.db
60
+
61
+ # EndurancePy data cache (downloaded Al Kamel / timing archives)
62
+ cache/
63
+ *.cache
64
+ .endurancepy_cache/
65
+
66
+ # Documentation builds
67
+ docs/_build/
68
+ site/
69
+
70
+ # mypy / type checkers
71
+ .mypy_cache/
72
+ .dmypy.json
73
+ dmypy.json
74
+ .pyre/
75
+ .ruff_cache/
@@ -0,0 +1,143 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-06-16
11
+
12
+ First release: load endurance racing timing & results data (WEC, ELMS, AsLMS,
13
+ Le Mans Cup, IMSA) from the Al Kamel archives, with a FastF1-style API.
14
+
15
+ ### Fixed
16
+
17
+ - Discovery: decode (`unquote`) the portal's percent-encoded result paths so
18
+ built URLs are encoded exactly once (no more `%2520`), and make event/session
19
+ matching prefer substring containment then `partial_ratio` (short queries like
20
+ `"Spa"` no longer mis-resolve). Verified end-to-end against the live portal.
21
+
22
+ ### Added
23
+
24
+ - Championship standings (milestone 3.1): `compute_standings(results, ...)`
25
+ aggregates points across rounds into a `Standings` table — configurable points
26
+ system (named / sequence / mapping), `by` car/crew/team/manufacturer, overall
27
+ or `per_class`. A generic calculator, not a replica of any series' exact rules.
28
+ Exposed as `ep.compute_standings` / `ep.Standings`.
29
+ - Event schedule (milestone 3.0): `get_event_schedule(year, series, season=...)`
30
+ builds an `EventSchedule` (one row per event: round, name, date, sessions)
31
+ from a season's discovered files; `get_event(...)`, `EventSchedule`
32
+ `get_event_by_round`/`get_event_by_name`, and `Event.get_session`/`get_race`
33
+ (the returned session carries its season so `load()` needs no `season=`).
34
+ `discovery.build_events` / `session_datetime` underpin it.
35
+ - Examples (`examples/`): `quickstart.py` and `quickstart.ipynb` (load a real
36
+ session via `season=`), `lap_analysis.py` (offline analysis of a local
37
+ Analysis CSV) and `plot_pace_by_class.py` (green-flag pace box plot). The
38
+ offline examples are executed in the test suite so they don't rot.
39
+ - Top-level convenience re-exports: `read_analysis`, `read_classification`,
40
+ `read_weather`.
41
+ - Project groundwork: MIT `LICENSE`, `README`, `.gitignore`.
42
+ - Design documentation:
43
+ - `docs/analyse_fastf1.md` — exhaustive inventory of FastF1's content and its
44
+ mapping onto endurance / Al Kamel data.
45
+ - `docs/plan_implementation.md` — phase-2 implementation plan.
46
+ - Community health files: `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, GitHub issue
47
+ templates and a pull request template.
48
+ - Continuous integration workflow (ruff, mypy, pytest).
49
+ - Package skeleton under `src/endurancepy/` (milestone 2.0): the public API
50
+ surface (`get_session`, `get_event`, `get_event_schedule`, `Cache`, `Series`,
51
+ `set_log_level`), data-object class stubs (`Session`, `Laps`/`Lap`,
52
+ `SessionResults`/`CarResult`, `Event`/`EventSchedule`), the `Series` registry,
53
+ reference column schemas, exceptions, logging, and the Al Kamel parser module
54
+ layout (data loading not implemented yet). Project tooling (`pyproject.toml`
55
+ with Hatchling, ruff, mypy, pytest) and a smoke-test suite.
56
+ - Cache and Al Kamel client (milestone 2.1):
57
+ - `Cache`: two-stage on-disk cache — stage 1 raw HTTP via `requests-cache`
58
+ (SQLite), stage 2 parsed `DataFrame`s as Parquet plus JSON metadata,
59
+ namespaced by `PARSER_VERSION`. Includes `enable_cache`, `clear_cache`,
60
+ `get_cache_info`, `set_disabled`/`set_enabled`, `disabled()` context
61
+ manager, `offline_mode`, and dataframe/metadata save/load helpers.
62
+ - `alkamel.client`: `build_results_url` (verified `Results/...` tree, URL
63
+ encoding, optional `Hour N`) and a cache-aware `download`.
64
+ - Offline tests covering URL building, Parquet round-trips and the
65
+ download path.
66
+ - Analysis CSV parser (milestone 2.2 — the core):
67
+ - `alkamel.timeparse`: tolerant duration parsing (`SS.mmm` / `M:SS.mmm` /
68
+ `H:MM:SS.mmm`, including the >24h rollover).
69
+ - `alkamel.headers.read_alkamel_csv`: tolerant CSV reading (BOM, leading-space
70
+ headers, trailing separator, all values as stripped strings).
71
+ - `alkamel.analysis.to_laps`/`read_analysis`: map the Analysis CSV to `Laps`
72
+ and derive `Stint`, `PitInTime`/`PitOutTime`, `LapStartTime`, the cumulative
73
+ `SectorNSessionTime`, overall and in-class `Position`, `IsPersonalBest`,
74
+ `IsAccurate` and `DriverChange`. (Gaps, `Hour` and `LapStartDate` need
75
+ session context and are filled later.)
76
+ - `Laps.pick_*` filters implemented: `pick_cars`, `pick_classes`,
77
+ `pick_manufacturers`, `pick_stints`, `pick_drivers`, `pick_teams`,
78
+ `pick_laps`, `pick_fastest`, `pick_quicklaps`, `pick_track_status`,
79
+ `pick_wo_box`, `pick_box_laps`, `pick_accurate`; plus
80
+ `SessionResults.pick_classes`.
81
+ - Synthetic Analysis-CSV fixture and tests (multi-class, multi-driver, a pit
82
+ stop and an FCY lap).
83
+ - Session results from laps (milestone 2.3):
84
+ - `results.from_laps`: reconstructs `SessionResults` (one row per car/crew)
85
+ from the laps — final order by laps then total time, overall and per class,
86
+ with each car's `Crew`, `BestLapTime`, lap count and total time. (The
87
+ Classification-CSV parser is deferred until its format is verified.)
88
+ - `Session.results` now derives from `laps` when available; `Session.cars`
89
+ (finishing order) and `Session.get_car` implemented.
90
+ - Added `Crew` and `BestLapTime` to the results schema; tests for the
91
+ derivation and the session car helpers.
92
+ - Track-status timeline (milestone 2.4):
93
+ - `track_status.from_laps`: reconstructs the session flag timeline (one row
94
+ per change) from the laps' finish-line flags, with a flag registry mapping
95
+ raw codes (GF/FCY/SC/SF/FF/Code60/…) to readable statuses.
96
+ - `Session.track_status` now derives from `laps` when available.
97
+ - (The Weather-CSV parser is deferred until its format is verified.)
98
+ - Session loading (milestone 2.5):
99
+ - `Session.load(source=...)` reads an Analysis CSV from a path, bytes or
100
+ `http(s)` URL into `Session.laps` (results and track status derive from it);
101
+ parsed laps are cached as Parquet and reused on a subsequent `load()`.
102
+ - Raises `SessionNotAvailableError` when no source is given and the laps are
103
+ not cached. (Automatic discovery of remote files and the `Event`/
104
+ `EventSchedule` layer remain to be implemented.)
105
+ - Automatic discovery in `Session.load` (milestone 2.9):
106
+ - `Session.load(season="<NN_YYYY>")` downloads the portal `?season=` index,
107
+ fuzzy-matches the event and session names, and downloads the Analysis,
108
+ Classification and Weather CSVs automatically (latest hour for races).
109
+ - `discovery.resolve_session_files` / `fetch_index`; `Series.keyword` to
110
+ select the right series folder.
111
+ - Offline tests for the resolution logic; a `network`-marked end-to-end
112
+ integration test (self-skips when the portal is unreachable) plus a manual
113
+ `integration` GitHub Actions workflow to run it on a networked runner.
114
+ - Race Classification parser (milestone 2.8):
115
+ - `alkamel.classification.read_classification`/`to_results`: parse the race
116
+ Classification CSV (`POSITION;NUMBER;TEAM;DRIVER_1..5;VEHICLE;CLASS;STATUS;
117
+ LAPS;TOTAL_TIME;FL_TIME;...`) into `SessionResults`, handling the
118
+ apostrophe time format (`5:44'41.101`) and deriving per-class positions and
119
+ each car's crew/manufacturer. Tolerant of the wider practice/qualifying
120
+ layouts (missing columns left empty).
121
+ - `Session.load(results_source=...)` populates `results` from a Classification
122
+ CSV (otherwise results are derived from the laps).
123
+ - Weather parser & file discovery (milestone 2.7), based on the **verified**
124
+ real Al Kamel formats (captured via a one-off GitHub Actions probe, since the
125
+ development sandbox cannot reach the portal):
126
+ - `alkamel.weather.read_weather`/`to_weather`: parse the Weather CSV
127
+ (`TIME_UTC_SECONDS;TIME_UTC_STR;AIR_TEMP;TRACK_TEMP;HUMIDITY;PRESSURE;
128
+ WIND_SPEED;WIND_DIRECTION`) into FastF1-style `weather_data` (`Time`
129
+ relative to the first sample; `Rainfall` not provided).
130
+ - `alkamel.discovery`: parse a portal `?season=` page into structured
131
+ `ResultFile` records (season/event/series/session/hour/kind + URL builder)
132
+ by reading the embedded `Results/...CSV` paths.
133
+ - `Session.load(weather_source=...)` populates `weather_data`.
134
+ - Confirmed the Analysis CSV format (old & modern) and the Classification CSV
135
+ headers (race `05_`, practice `03_`, qualifying `90_`) against real files.
136
+ - Plotting colour helpers (milestone 2.6):
137
+ - `plotting.get_class_color` / `get_manufacturer_color` (pure functions
138
+ returning hex colours, case-insensitive, with a default fallback) plus
139
+ `list_classes`/`list_manufacturers` and `setup_mpl` (needs the `plot`
140
+ extra). Colours are organised by class and manufacturer rather than driver.
141
+
142
+ [Unreleased]: https://github.com/RomainFl50/EndurancePy/compare/v0.1.0...HEAD
143
+ [0.1.0]: https://github.com/RomainFl50/EndurancePy/releases/tag/v0.1.0
@@ -0,0 +1,52 @@
1
+ # Code of Conduct
2
+
3
+ ## Our commitment
4
+
5
+ EndurancePy is an open, welcoming community. We are committed to providing a
6
+ friendly, safe and inclusive environment for everyone who participates —
7
+ contributors, maintainers and users alike — regardless of background or
8
+ experience level.
9
+
10
+ ## Our standards
11
+
12
+ We expect everyone in the project to:
13
+
14
+ - Be respectful, considerate and patient.
15
+ - Welcome newcomers and help them get started.
16
+ - Give and accept constructive feedback gracefully.
17
+ - Focus on what is best for the community and the project.
18
+ - Show empathy towards other community members.
19
+
20
+ Behaviour that makes others feel unwelcome or unsafe is not acceptable and may
21
+ result in removal from project spaces at the maintainers' discretion.
22
+
23
+ ## Adopted standard
24
+
25
+ This project adopts the **Contributor Covenant, version 2.1**, as its full Code
26
+ of Conduct. Please read the complete text here:
27
+
28
+ - <https://www.contributor-covenant.org/version/2/1/code_of_conduct/>
29
+
30
+ It defines the expected standards of behaviour, the responsibilities of
31
+ maintainers, the scope of this policy, and the enforcement guidelines in full.
32
+
33
+ ## Scope
34
+
35
+ This Code of Conduct applies within all project spaces (the repository, issues,
36
+ pull requests, discussions) and when an individual is representing the project
37
+ in public spaces.
38
+
39
+ ## Reporting
40
+
41
+ If you experience or witness a problem, please report it privately to the project
42
+ maintainer:
43
+
44
+ - **Romain Flambard** — romain.flambard@hotmail.fr
45
+
46
+ All reports will be reviewed and handled confidentially. Maintainers are
47
+ obligated to respect the privacy and security of the reporter of any incident.
48
+
49
+ ## Attribution
50
+
51
+ This Code of Conduct is adapted from the
52
+ [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
@@ -0,0 +1,129 @@
1
+ # Contributing to EndurancePy
2
+
3
+ First off — thank you for taking the time to contribute! EndurancePy aims to do
4
+ for endurance racing (WEC, ELMS, Asian Le Mans Series, Le Mans Cup, IMSA) what
5
+ [FastF1](https://github.com/theOehrly/Fast-F1) did for Formula 1, and it is very
6
+ much a community effort.
7
+
8
+ This project is in an **early / design phase** — there is no runnable package
9
+ yet, only the design groundwork. That means there is a lot of high-impact work
10
+ available, and good first contributions are easy to find.
11
+
12
+ By participating, you agree to abide by our
13
+ [Code of Conduct](CODE_OF_CONDUCT.md).
14
+
15
+ ---
16
+
17
+ ## Ways to contribute
18
+
19
+ - **Code** — implement one of the milestones (parsers, cache, core objects…).
20
+ - **Documentation** — improve docs, examples, docstrings.
21
+ - **Test data** — help build small, shareable fixtures (see the legal note
22
+ below — do **not** commit raw Al Kamel archives).
23
+ - **Issues** — report bugs, request a series/season, or propose an API design.
24
+ - **Review** — review open pull requests.
25
+
26
+ If you are unsure where to start, **open an issue** describing what you'd like to
27
+ work on, so we can avoid duplicated effort and agree on the approach before you
28
+ write code.
29
+
30
+ ## Understand the design first
31
+
32
+ Before writing code, please read the design documents — they are the functional
33
+ and technical spec for the package:
34
+
35
+ - [`docs/analyse_fastf1.md`](docs/analyse_fastf1.md) — exhaustive inventory of
36
+ FastF1's content and how each piece maps onto endurance / Al Kamel data.
37
+ - [`docs/plan_implementation.md`](docs/plan_implementation.md) — the
38
+ implementation plan: package layout, target column schemas, parsing pipeline,
39
+ derivation algorithms, cache design, milestones and test strategy.
40
+
41
+ The guiding principle: **mirror FastF1's API and content** wherever the
42
+ underlying public data exists.
43
+
44
+ ## Development setup
45
+
46
+ > The package skeleton is being bootstrapped; once `pyproject.toml` lands, the
47
+ > setup below applies.
48
+
49
+ ```bash
50
+ # 1. Fork and clone
51
+ git clone https://github.com/<your-username>/EndurancePy.git
52
+ cd EndurancePy
53
+
54
+ # 2. Create a virtual environment (Python 3.10+)
55
+ python -m venv .venv
56
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
57
+
58
+ # 3. Install in editable mode with dev extras
59
+ pip install -e ".[dev]"
60
+
61
+ # 4. (optional) install pre-commit hooks
62
+ pre-commit install
63
+ ```
64
+
65
+ ## Coding guidelines
66
+
67
+ - **Python 3.10+**, with type hints on public functions.
68
+ - **Formatting & linting**: [`ruff`](https://docs.astral.sh/ruff/)
69
+ (`ruff format` + `ruff check`).
70
+ - **Type checking**: `mypy`.
71
+ - **Docstrings** on all public classes/functions (NumPy or Google style).
72
+ - **Mirror FastF1 naming** where it makes sense (`get_session`, `Session.load`,
73
+ `Session.laps`, `pick_*`, `Cache`) so FastF1 users feel at home. Document any
74
+ deliberate divergence (see the plan).
75
+ - Keep parsers **tolerant**: Al Kamel CSV headers drift across seasons/series —
76
+ match columns by name, handle the BOM and leading-space header variants.
77
+
78
+ ## Tests
79
+
80
+ - Use `pytest`. Run the suite with:
81
+ ```bash
82
+ pytest
83
+ ```
84
+ - New parsing logic must come with tests.
85
+ - Prefer **small, synthetic fixtures** that reproduce the format (a couple of
86
+ cars, two classes, a few laps, a pit stop, a caution period). **Do not commit
87
+ real Al Kamel timing files** (see the legal note).
88
+ - Network-dependent tests must be marked (e.g. `@pytest.mark.network`) and stay
89
+ off by default.
90
+
91
+ ## Commit messages
92
+
93
+ Use clear, descriptive messages. We loosely follow
94
+ [Conventional Commits](https://www.conventionalcommits.org/), e.g.:
95
+
96
+ ```
97
+ feat(alkamel): parse Analysis CSV into Laps
98
+ fix(timeparse): handle the 24: elapsed-time rollover
99
+ docs: clarify per-class position derivation
100
+ test(headers): cover the IMSA WithSections variant
101
+ ```
102
+
103
+ ## Pull request workflow
104
+
105
+ 1. Create a topic branch from `main` (`feat/...`, `fix/...`, `docs/...`).
106
+ 2. Make focused commits; keep PRs reasonably small and single-purpose.
107
+ 3. Ensure `ruff`, `mypy` and `pytest` pass locally.
108
+ 4. Fill in the pull request template and link any related issue.
109
+ 5. Be responsive to review feedback. Maintainers may request changes before merge.
110
+
111
+ ## ⚖️ Legal note (please read)
112
+
113
+ EndurancePy parses **publicly published** timing archives. **Al Kamel Systems
114
+ explicitly asserts ownership of its timing data and warns against
115
+ redistribution.** Therefore:
116
+
117
+ - **Never commit raw Al Kamel data** (CSV/PDF archives) to this repository, and
118
+ do not bundle or republish it in any artifact.
119
+ - Test fixtures must be **synthetic** or otherwise clearly redistributable.
120
+ - Always respect each site's Terms of Service and `robots.txt`, identify your
121
+ client honestly, and keep request rates reasonable (the cache exists partly
122
+ for this reason).
123
+
124
+ Contributions that redistribute proprietary data will not be accepted.
125
+
126
+ ## License
127
+
128
+ By contributing, you agree that your contributions will be licensed under the
129
+ project's [MIT License](LICENSE).
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Romain Flambard and the EndurancePy contributors
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.