cfb-data 0.4.1__py3-none-any.whl

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 (127) hide show
  1. cfb_data/__init__.py +234 -0
  2. cfb_data/_dataframes.py +279 -0
  3. cfb_data/_executor.py +129 -0
  4. cfb_data/_parquet.py +197 -0
  5. cfb_data/_request_rules.py +41 -0
  6. cfb_data/_requests.py +36 -0
  7. cfb_data/_tabular.py +676 -0
  8. cfb_data/_transport.py +452 -0
  9. cfb_data/adjusted_metrics/__init__.py +29 -0
  10. cfb_data/adjusted_metrics/models/__init__.py +1 -0
  11. cfb_data/adjusted_metrics/models/pydantic/__init__.py +29 -0
  12. cfb_data/adjusted_metrics/models/pydantic/requests.py +45 -0
  13. cfb_data/adjusted_metrics/models/pydantic/responses.py +88 -0
  14. cfb_data/adjusted_metrics/resource.py +220 -0
  15. cfb_data/base/__init__.py +6 -0
  16. cfb_data/base/types.py +112 -0
  17. cfb_data/betting/__init__.py +15 -0
  18. cfb_data/betting/models/__init__.py +1 -0
  19. cfb_data/betting/models/pydantic/__init__.py +6 -0
  20. cfb_data/betting/models/pydantic/requests.py +35 -0
  21. cfb_data/betting/models/pydantic/responses.py +62 -0
  22. cfb_data/betting/resource.py +91 -0
  23. cfb_data/client.py +305 -0
  24. cfb_data/coaches/__init__.py +57 -0
  25. cfb_data/coaches/models/__init__.py +1 -0
  26. cfb_data/coaches/models/pydantic/__init__.py +57 -0
  27. cfb_data/coaches/models/pydantic/requests.py +75 -0
  28. cfb_data/coaches/models/pydantic/responses.py +261 -0
  29. cfb_data/coaches/resource.py +216 -0
  30. cfb_data/conferences/__init__.py +23 -0
  31. cfb_data/conferences/models/__init__.py +1 -0
  32. cfb_data/conferences/models/pydantic/__init__.py +23 -0
  33. cfb_data/conferences/models/pydantic/requests.py +69 -0
  34. cfb_data/conferences/models/pydantic/responses.py +64 -0
  35. cfb_data/conferences/resource.py +175 -0
  36. cfb_data/draft/__init__.py +19 -0
  37. cfb_data/draft/models/__init__.py +1 -0
  38. cfb_data/draft/models/pydantic/__init__.py +12 -0
  39. cfb_data/draft/models/pydantic/requests.py +18 -0
  40. cfb_data/draft/models/pydantic/responses.py +65 -0
  41. cfb_data/draft/resource.py +132 -0
  42. cfb_data/drives/__init__.py +13 -0
  43. cfb_data/drives/models/__init__.py +1 -0
  44. cfb_data/drives/models/pydantic/__init__.py +17 -0
  45. cfb_data/drives/models/pydantic/requests.py +42 -0
  46. cfb_data/drives/models/pydantic/responses.py +46 -0
  47. cfb_data/drives/resource.py +94 -0
  48. cfb_data/enums.py +93 -0
  49. cfb_data/errors.py +234 -0
  50. cfb_data/games/__init__.py +42 -0
  51. cfb_data/games/models/__init__.py +1 -0
  52. cfb_data/games/models/pydantic/__init__.py +106 -0
  53. cfb_data/games/models/pydantic/requests.py +266 -0
  54. cfb_data/games/models/pydantic/responses.py +495 -0
  55. cfb_data/games/resource.py +486 -0
  56. cfb_data/info/__init__.py +25 -0
  57. cfb_data/info/models/__init__.py +1 -0
  58. cfb_data/info/models/pydantic/__init__.py +23 -0
  59. cfb_data/info/models/pydantic/requests.py +18 -0
  60. cfb_data/info/models/pydantic/responses.py +103 -0
  61. cfb_data/info/resource.py +88 -0
  62. cfb_data/metrics/__init__.py +53 -0
  63. cfb_data/metrics/models/__init__.py +1 -0
  64. cfb_data/metrics/models/pydantic/__init__.py +49 -0
  65. cfb_data/metrics/models/pydantic/requests.py +121 -0
  66. cfb_data/metrics/models/pydantic/responses.py +182 -0
  67. cfb_data/metrics/resource.py +371 -0
  68. cfb_data/players/__init__.py +44 -0
  69. cfb_data/players/models/__init__.py +1 -0
  70. cfb_data/players/models/pydantic/__init__.py +41 -0
  71. cfb_data/players/models/pydantic/requests.py +70 -0
  72. cfb_data/players/models/pydantic/responses.py +171 -0
  73. cfb_data/players/resource.py +258 -0
  74. cfb_data/playoffs/__init__.py +41 -0
  75. cfb_data/playoffs/models/__init__.py +1 -0
  76. cfb_data/playoffs/models/pydantic/__init__.py +37 -0
  77. cfb_data/playoffs/models/pydantic/requests.py +30 -0
  78. cfb_data/playoffs/models/pydantic/responses.py +173 -0
  79. cfb_data/playoffs/resource.py +149 -0
  80. cfb_data/plays/__init__.py +43 -0
  81. cfb_data/plays/models/__init__.py +1 -0
  82. cfb_data/plays/models/pydantic/__init__.py +35 -0
  83. cfb_data/plays/models/pydantic/requests.py +85 -0
  84. cfb_data/plays/models/pydantic/responses.py +231 -0
  85. cfb_data/plays/resource.py +249 -0
  86. cfb_data/py.typed +0 -0
  87. cfb_data/rankings/__init__.py +16 -0
  88. cfb_data/rankings/models/__init__.py +1 -0
  89. cfb_data/rankings/models/pydantic/__init__.py +6 -0
  90. cfb_data/rankings/models/pydantic/requests.py +36 -0
  91. cfb_data/rankings/models/pydantic/responses.py +42 -0
  92. cfb_data/rankings/resource.py +89 -0
  93. cfb_data/ratings/__init__.py +59 -0
  94. cfb_data/ratings/models/__init__.py +1 -0
  95. cfb_data/ratings/models/pydantic/__init__.py +55 -0
  96. cfb_data/ratings/models/pydantic/requests.py +87 -0
  97. cfb_data/ratings/models/pydantic/responses.py +215 -0
  98. cfb_data/ratings/resource.py +342 -0
  99. cfb_data/recruiting/__init__.py +26 -0
  100. cfb_data/recruiting/models/__init__.py +1 -0
  101. cfb_data/recruiting/models/pydantic/__init__.py +23 -0
  102. cfb_data/recruiting/models/pydantic/requests.py +69 -0
  103. cfb_data/recruiting/models/pydantic/responses.py +70 -0
  104. cfb_data/recruiting/resource.py +180 -0
  105. cfb_data/retry.py +49 -0
  106. cfb_data/stats/__init__.py +69 -0
  107. cfb_data/stats/models/__init__.py +1 -0
  108. cfb_data/stats/models/pydantic/__init__.py +65 -0
  109. cfb_data/stats/models/pydantic/requests.py +167 -0
  110. cfb_data/stats/models/pydantic/responses.py +291 -0
  111. cfb_data/stats/resource.py +400 -0
  112. cfb_data/teams/__init__.py +40 -0
  113. cfb_data/teams/models/__init__.py +1 -0
  114. cfb_data/teams/models/pydantic/__init__.py +26 -0
  115. cfb_data/teams/models/pydantic/requests.py +96 -0
  116. cfb_data/teams/models/pydantic/responses.py +116 -0
  117. cfb_data/teams/resource.py +270 -0
  118. cfb_data/venues/__init__.py +6 -0
  119. cfb_data/venues/models/__init__.py +1 -0
  120. cfb_data/venues/models/pydantic/__init__.py +5 -0
  121. cfb_data/venues/models/pydantic/responses.py +24 -0
  122. cfb_data/venues/resource.py +51 -0
  123. cfb_data-0.4.1.dist-info/METADATA +414 -0
  124. cfb_data-0.4.1.dist-info/RECORD +127 -0
  125. cfb_data-0.4.1.dist-info/WHEEL +5 -0
  126. cfb_data-0.4.1.dist-info/licenses/LICENSE +21 -0
  127. cfb_data-0.4.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,88 @@
1
+ """Expose typed Info endpoints through the primary client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Literal, overload
6
+
7
+ from pydantic import BaseModel, ConfigDict, TypeAdapter
8
+
9
+ from cfb_data._executor import _EndpointExecutor
10
+ from cfb_data._requests import _resolve_request
11
+ from cfb_data.enums import UserUsageApi
12
+ from cfb_data.info.models.pydantic.requests import InfoUsageRequest
13
+ from cfb_data.info.models.pydantic.responses import UserInfo, UserUsage
14
+
15
+ type _UserUsageApiArgument = UserUsageApi | Literal["all", "cfb", "cbb"]
16
+
17
+ _USER_INFO = TypeAdapter(UserInfo)
18
+ _USER_USAGE = TypeAdapter(UserUsage)
19
+
20
+
21
+ class _EmptyRequest(BaseModel):
22
+ """Represent the empty filter set accepted by ``GET /info``."""
23
+
24
+ model_config = ConfigDict(extra="forbid")
25
+
26
+
27
+ _EMPTY_REQUEST = _EmptyRequest()
28
+
29
+
30
+ class InfoResource:
31
+ """Provide validated operational account and usage metadata."""
32
+
33
+ def __init__(self, executor: _EndpointExecutor) -> None:
34
+ """Bind the namespace to shared endpoint execution."""
35
+ self._executor = executor
36
+
37
+ async def account(self) -> UserInfo:
38
+ """Return metadata for the authenticated API account.
39
+
40
+ :return: Validated account tier, quota, products, and feature access.
41
+ :raises CFBDError: If transport or response validation fails.
42
+ """
43
+ return await self._executor.fetch_one(
44
+ endpoint="/info",
45
+ request=_EMPTY_REQUEST,
46
+ response_adapter=_USER_INFO,
47
+ )
48
+
49
+ @overload
50
+ async def usage(self, request: InfoUsageRequest, /) -> UserUsage: ...
51
+
52
+ @overload
53
+ async def usage(
54
+ self,
55
+ request: None = None,
56
+ /,
57
+ *,
58
+ days: int | None = None,
59
+ limit: int | None = None,
60
+ api: _UserUsageApiArgument | None = None,
61
+ ) -> UserUsage: ...
62
+
63
+ async def usage(
64
+ self, request: InfoUsageRequest | None = None, /, **filters: object
65
+ ) -> UserUsage:
66
+ """Return recent shared-pool usage for the authenticated account.
67
+
68
+ :param request: Validated request model, mutually exclusive with filters.
69
+ :param filters: Explicit snake-case endpoint filters.
70
+ :return: Validated request totals, endpoint aggregates, and recent calls.
71
+ :raises TypeError: If request styles are mixed or the model type is wrong.
72
+ :raises CFBDError: If request, transport, or response validation fails.
73
+ """
74
+ endpoint = "/info/usage"
75
+ validated = _resolve_request(
76
+ endpoint=endpoint,
77
+ request_type=InfoUsageRequest,
78
+ request=request,
79
+ filters=filters,
80
+ )
81
+ return await self._executor.fetch_one(
82
+ endpoint=endpoint,
83
+ request=validated,
84
+ response_adapter=_USER_USAGE,
85
+ )
86
+
87
+
88
+ __all__ = ["InfoResource"]
@@ -0,0 +1,53 @@
1
+ """Export the supported Metrics namespace and public contracts."""
2
+
3
+ from cfb_data.enums import Classification, SeasonType
4
+
5
+ from .models.pydantic import (
6
+ FieldGoalExpectedPoints,
7
+ PlayerGamePPAAverage,
8
+ PlayerGamePPARequest,
9
+ PlayerGamePredictedPointsAdded,
10
+ PlayerSeasonPPARequest,
11
+ PlayerSeasonPPASplit,
12
+ PlayerSeasonPredictedPointsAdded,
13
+ PlayWinProbability,
14
+ PredictedPointsRequest,
15
+ PredictedPointsValue,
16
+ PregameWinProbability,
17
+ PregameWinProbabilityRequest,
18
+ TeamGamePPARequest,
19
+ TeamGamePPAUnit,
20
+ TeamGamePredictedPointsAdded,
21
+ TeamPPACumulative,
22
+ TeamSeasonPPARequest,
23
+ TeamSeasonPPAUnit,
24
+ TeamSeasonPredictedPointsAdded,
25
+ WinProbabilityRequest,
26
+ )
27
+ from .resource import MetricsResource
28
+
29
+ __all__ = [
30
+ "Classification",
31
+ "FieldGoalExpectedPoints",
32
+ "MetricsResource",
33
+ "PlayerGamePPAAverage",
34
+ "PlayerGamePPARequest",
35
+ "PlayerGamePredictedPointsAdded",
36
+ "PlayerSeasonPPARequest",
37
+ "PlayerSeasonPPASplit",
38
+ "PlayerSeasonPredictedPointsAdded",
39
+ "PlayWinProbability",
40
+ "PredictedPointsRequest",
41
+ "PredictedPointsValue",
42
+ "PregameWinProbability",
43
+ "PregameWinProbabilityRequest",
44
+ "SeasonType",
45
+ "TeamGamePPARequest",
46
+ "TeamGamePPAUnit",
47
+ "TeamGamePredictedPointsAdded",
48
+ "TeamPPACumulative",
49
+ "TeamSeasonPPARequest",
50
+ "TeamSeasonPPAUnit",
51
+ "TeamSeasonPredictedPointsAdded",
52
+ "WinProbabilityRequest",
53
+ ]
@@ -0,0 +1 @@
1
+ """Export Metrics model families."""
@@ -0,0 +1,49 @@
1
+ """Export validated Metrics request and response models."""
2
+
3
+ from .requests import (
4
+ PlayerGamePPARequest,
5
+ PlayerSeasonPPARequest,
6
+ PredictedPointsRequest,
7
+ PregameWinProbabilityRequest,
8
+ TeamGamePPARequest,
9
+ TeamSeasonPPARequest,
10
+ WinProbabilityRequest,
11
+ )
12
+ from .responses import (
13
+ FieldGoalExpectedPoints,
14
+ PlayerGamePPAAverage,
15
+ PlayerGamePredictedPointsAdded,
16
+ PlayerSeasonPPASplit,
17
+ PlayerSeasonPredictedPointsAdded,
18
+ PlayWinProbability,
19
+ PredictedPointsValue,
20
+ PregameWinProbability,
21
+ TeamGamePPAUnit,
22
+ TeamGamePredictedPointsAdded,
23
+ TeamPPACumulative,
24
+ TeamSeasonPPAUnit,
25
+ TeamSeasonPredictedPointsAdded,
26
+ )
27
+
28
+ __all__ = [
29
+ "FieldGoalExpectedPoints",
30
+ "PlayerGamePPAAverage",
31
+ "PlayerGamePPARequest",
32
+ "PlayerGamePredictedPointsAdded",
33
+ "PlayerSeasonPPARequest",
34
+ "PlayerSeasonPPASplit",
35
+ "PlayerSeasonPredictedPointsAdded",
36
+ "PlayWinProbability",
37
+ "PredictedPointsRequest",
38
+ "PredictedPointsValue",
39
+ "PregameWinProbability",
40
+ "PregameWinProbabilityRequest",
41
+ "TeamGamePPARequest",
42
+ "TeamGamePPAUnit",
43
+ "TeamGamePredictedPointsAdded",
44
+ "TeamPPACumulative",
45
+ "TeamSeasonPPARequest",
46
+ "TeamSeasonPPAUnit",
47
+ "TeamSeasonPredictedPointsAdded",
48
+ "WinProbabilityRequest",
49
+ ]
@@ -0,0 +1,121 @@
1
+ """Validate request parameters for implemented Metrics endpoints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Self
6
+
7
+ from pydantic import BaseModel, ConfigDict, Field, model_validator
8
+
9
+ from cfb_data.enums import Classification, SeasonType
10
+
11
+
12
+ class _MetricsRequest(BaseModel):
13
+ """Apply the closed-object contract shared by Metrics requests."""
14
+
15
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
16
+
17
+
18
+ def _require_year_or_team(year: int | None, team: str | None) -> None:
19
+ """Require a season or team selector."""
20
+ if year is None and team is None:
21
+ raise ValueError("year is required when team is not specified")
22
+
23
+
24
+ class PredictedPointsRequest(_MetricsRequest):
25
+ """Validate filters accepted by ``GET /ppa/predicted``."""
26
+
27
+ down: int = Field(ge=1, le=4)
28
+ distance: int = Field(ge=1, le=99)
29
+
30
+
31
+ class TeamSeasonPPARequest(_MetricsRequest):
32
+ """Validate filters accepted by ``GET /ppa/teams``."""
33
+
34
+ year: int | None = Field(default=None, ge=1869)
35
+ team: str | None = Field(default=None, min_length=1)
36
+ conference: str | None = Field(default=None, min_length=1)
37
+ exclude_garbage_time: bool | None = Field(default=None, alias="excludeGarbageTime")
38
+ classification: Classification | None = None
39
+
40
+ @model_validator(mode="after")
41
+ def validate_selectors(self) -> Self:
42
+ """Require a season or team selector."""
43
+ _require_year_or_team(self.year, self.team)
44
+ return self
45
+
46
+
47
+ class TeamGamePPARequest(_MetricsRequest):
48
+ """Validate filters accepted by ``GET /ppa/games``."""
49
+
50
+ year: int = Field(ge=1869)
51
+ week: int | None = Field(default=None, ge=0)
52
+ season_type: SeasonType | None = Field(default=None, alias="seasonType")
53
+ team: str | None = Field(default=None, min_length=1)
54
+ conference: str | None = Field(default=None, min_length=1)
55
+ exclude_garbage_time: bool | None = Field(default=None, alias="excludeGarbageTime")
56
+ classification: Classification | None = None
57
+
58
+
59
+ class PlayerGamePPARequest(_MetricsRequest):
60
+ """Validate filters accepted by ``GET /ppa/players/games``."""
61
+
62
+ year: int = Field(ge=1869)
63
+ week: int | None = Field(default=None, ge=0)
64
+ season_type: SeasonType | None = Field(default=None, alias="seasonType")
65
+ team: str | None = Field(default=None, min_length=1)
66
+ position: str | None = Field(default=None, min_length=1)
67
+ player_id: int | None = Field(default=None, alias="playerId", gt=0)
68
+ threshold: int | None = Field(default=None, ge=0)
69
+ exclude_garbage_time: bool | None = Field(default=None, alias="excludeGarbageTime")
70
+
71
+ @model_validator(mode="after")
72
+ def validate_selectors(self) -> Self:
73
+ """Require a week or team selector."""
74
+ if self.week is None and self.team is None:
75
+ raise ValueError("week is required when team is not specified")
76
+ return self
77
+
78
+
79
+ class PlayerSeasonPPARequest(_MetricsRequest):
80
+ """Validate filters accepted by ``GET /ppa/players/season``."""
81
+
82
+ year: int | None = Field(default=None, ge=1869)
83
+ conference: str | None = Field(default=None, min_length=1)
84
+ team: str | None = Field(default=None, min_length=1)
85
+ position: str | None = Field(default=None, min_length=1)
86
+ player_id: int | None = Field(default=None, alias="playerId", gt=0)
87
+ threshold: int | None = Field(default=None, ge=0)
88
+ exclude_garbage_time: bool | None = Field(default=None, alias="excludeGarbageTime")
89
+
90
+ @model_validator(mode="after")
91
+ def validate_selectors(self) -> Self:
92
+ """Require a season or player selector."""
93
+ if self.year is None and self.player_id is None:
94
+ raise ValueError("year is required when player_id is not specified")
95
+ return self
96
+
97
+
98
+ class WinProbabilityRequest(_MetricsRequest):
99
+ """Validate filters accepted by ``GET /metrics/wp``."""
100
+
101
+ game_id: int = Field(alias="gameId", gt=0)
102
+
103
+
104
+ class PregameWinProbabilityRequest(_MetricsRequest):
105
+ """Validate filters accepted by ``GET /metrics/wp/pregame``."""
106
+
107
+ year: int | None = Field(default=None, ge=1869)
108
+ week: int | None = Field(default=None, ge=0)
109
+ season_type: SeasonType | None = Field(default=None, alias="seasonType")
110
+ team: str | None = Field(default=None, min_length=1)
111
+
112
+
113
+ __all__ = [
114
+ "PlayerGamePPARequest",
115
+ "PlayerSeasonPPARequest",
116
+ "PredictedPointsRequest",
117
+ "PregameWinProbabilityRequest",
118
+ "TeamGamePPARequest",
119
+ "TeamSeasonPPARequest",
120
+ "WinProbabilityRequest",
121
+ ]
@@ -0,0 +1,182 @@
1
+ """Validate responses from implemented CFBD Metrics endpoints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pydantic import BaseModel, ConfigDict, Field
6
+
7
+ from cfb_data.enums import SeasonType
8
+
9
+
10
+ class _ResponseModel(BaseModel):
11
+ """Apply the upstream closed-object contract to Metrics responses."""
12
+
13
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
14
+
15
+
16
+ class PredictedPointsValue(_ResponseModel):
17
+ """Represent expected points at one field position."""
18
+
19
+ yard_line: int = Field(alias="yardLine", ge=0, le=100)
20
+ predicted_points: float = Field(alias="predictedPoints")
21
+
22
+
23
+ class TeamPPACumulative(_ResponseModel):
24
+ """Represent cumulative team predicted-points-added values."""
25
+
26
+ total: float
27
+ passing: float
28
+ rushing: float
29
+
30
+
31
+ class TeamSeasonPPAUnit(_ResponseModel):
32
+ """Represent one side of a team's season PPA metrics."""
33
+
34
+ overall: float
35
+ passing: float
36
+ rushing: float
37
+ first_down: float = Field(alias="firstDown")
38
+ second_down: float = Field(alias="secondDown")
39
+ third_down: float = Field(alias="thirdDown")
40
+ cumulative: TeamPPACumulative
41
+
42
+
43
+ class TeamSeasonPredictedPointsAdded(_ResponseModel):
44
+ """Represent team predicted-points-added metrics for a season."""
45
+
46
+ season: int = Field(ge=1869)
47
+ conference: str
48
+ team: str
49
+ offense: TeamSeasonPPAUnit
50
+ defense: TeamSeasonPPAUnit
51
+
52
+
53
+ class TeamGamePPAUnit(_ResponseModel):
54
+ """Represent one side of a team's game PPA metrics."""
55
+
56
+ overall: float
57
+ passing: float
58
+ rushing: float
59
+ first_down: float = Field(alias="firstDown")
60
+ second_down: float = Field(alias="secondDown")
61
+ third_down: float = Field(alias="thirdDown")
62
+
63
+
64
+ class TeamGamePredictedPointsAdded(_ResponseModel):
65
+ """Represent team predicted-points-added metrics for one game."""
66
+
67
+ game_id: int = Field(alias="gameId", gt=0)
68
+ season: int = Field(ge=1869)
69
+ week: int = Field(ge=0)
70
+ season_type: SeasonType = Field(alias="seasonType")
71
+ team: str
72
+ conference: str
73
+ opponent: str
74
+ offense: TeamGamePPAUnit
75
+ defense: TeamGamePPAUnit
76
+
77
+
78
+ class PlayerGamePPAAverage(_ResponseModel):
79
+ """Represent a player's per-play PPA averages for one game."""
80
+
81
+ all: float
82
+ passing: float | None = Field(default=None, alias="pass")
83
+ rush: float | None = None
84
+
85
+
86
+ class PlayerGamePredictedPointsAdded(_ResponseModel):
87
+ """Represent player predicted-points-added metrics for one game."""
88
+
89
+ season: int = Field(ge=1869)
90
+ week: int = Field(ge=0)
91
+ season_type: SeasonType = Field(alias="seasonType")
92
+ id: str
93
+ name: str
94
+ position: str
95
+ team: str
96
+ opponent: str
97
+ average_ppa: PlayerGamePPAAverage = Field(alias="averagePPA")
98
+
99
+
100
+ class PlayerSeasonPPASplit(_ResponseModel):
101
+ """Represent average or total player PPA split by play context."""
102
+
103
+ all: float
104
+ passing: float | None = Field(default=None, alias="pass")
105
+ rush: float | None = None
106
+ first_down: float | None = Field(default=None, alias="firstDown")
107
+ second_down: float | None = Field(default=None, alias="secondDown")
108
+ third_down: float | None = Field(default=None, alias="thirdDown")
109
+ standard_downs: float | None = Field(default=None, alias="standardDowns")
110
+ passing_downs: float | None = Field(default=None, alias="passingDowns")
111
+
112
+
113
+ class PlayerSeasonPredictedPointsAdded(_ResponseModel):
114
+ """Represent player predicted-points-added metrics for a season."""
115
+
116
+ season: int = Field(ge=1869)
117
+ id: str
118
+ name: str
119
+ position: str
120
+ team: str
121
+ conference: str
122
+ average_ppa: PlayerSeasonPPASplit = Field(alias="averagePPA")
123
+ total_ppa: PlayerSeasonPPASplit = Field(alias="totalPPA")
124
+
125
+
126
+ class PlayWinProbability(_ResponseModel):
127
+ """Represent the modeled home win probability after one play."""
128
+
129
+ game_id: int = Field(alias="gameId", gt=0)
130
+ play_id: str = Field(alias="playId")
131
+ play_text: str = Field(alias="playText")
132
+ home_id: int = Field(alias="homeId", gt=0)
133
+ home: str
134
+ away_id: int = Field(alias="awayId", gt=0)
135
+ away: str
136
+ spread: float
137
+ home_ball: bool = Field(alias="homeBall")
138
+ home_score: int = Field(alias="homeScore", ge=0)
139
+ away_score: int = Field(alias="awayScore", ge=0)
140
+ yard_line: int = Field(alias="yardLine", ge=0, le=100)
141
+ down: int = Field(ge=0, le=4)
142
+ distance: int = Field(ge=0)
143
+ home_win_probability: float = Field(alias="homeWinProbability", ge=0, le=1)
144
+ play_number: int = Field(alias="playNumber", ge=0)
145
+
146
+
147
+ class PregameWinProbability(_ResponseModel):
148
+ """Represent one game's pregame home win probability."""
149
+
150
+ season: int = Field(ge=1869)
151
+ season_type: SeasonType = Field(alias="seasonType")
152
+ week: int = Field(ge=0)
153
+ game_id: int = Field(alias="gameId", gt=0)
154
+ home_team: str = Field(alias="homeTeam")
155
+ away_team: str = Field(alias="awayTeam")
156
+ spread: float
157
+ home_win_probability: float = Field(alias="homeWinProbability", ge=0, le=1)
158
+
159
+
160
+ class FieldGoalExpectedPoints(_ResponseModel):
161
+ """Represent expected points for a field-goal distance."""
162
+
163
+ yards_to_goal: int = Field(alias="yardsToGoal", ge=0, le=100)
164
+ distance: int = Field(ge=0)
165
+ expected_points: float = Field(alias="expectedPoints")
166
+
167
+
168
+ __all__ = [
169
+ "FieldGoalExpectedPoints",
170
+ "PlayerGamePPAAverage",
171
+ "PlayerGamePredictedPointsAdded",
172
+ "PlayerSeasonPPASplit",
173
+ "PlayerSeasonPredictedPointsAdded",
174
+ "PlayWinProbability",
175
+ "PredictedPointsValue",
176
+ "PregameWinProbability",
177
+ "TeamGamePPAUnit",
178
+ "TeamGamePredictedPointsAdded",
179
+ "TeamPPACumulative",
180
+ "TeamSeasonPPAUnit",
181
+ "TeamSeasonPredictedPointsAdded",
182
+ ]