otf-api 0.2.2__py3-none-any.whl → 0.4.0__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.
- otf_api/__init__.py +14 -69
- otf_api/api.py +873 -66
- otf_api/auth.py +314 -0
- otf_api/cli/__init__.py +4 -0
- otf_api/cli/_utilities.py +60 -0
- otf_api/cli/app.py +172 -0
- otf_api/cli/bookings.py +231 -0
- otf_api/cli/prompts.py +162 -0
- otf_api/models/__init__.py +30 -23
- otf_api/models/base.py +205 -2
- otf_api/models/responses/__init__.py +29 -29
- otf_api/models/responses/body_composition_list.py +304 -0
- otf_api/models/responses/book_class.py +405 -0
- otf_api/models/responses/bookings.py +211 -37
- otf_api/models/responses/cancel_booking.py +93 -0
- otf_api/models/responses/challenge_tracker_content.py +6 -6
- otf_api/models/responses/challenge_tracker_detail.py +6 -6
- otf_api/models/responses/classes.py +205 -7
- otf_api/models/responses/enums.py +0 -35
- otf_api/models/responses/favorite_studios.py +5 -5
- otf_api/models/responses/latest_agreement.py +2 -2
- otf_api/models/responses/lifetime_stats.py +92 -0
- otf_api/models/responses/member_detail.py +17 -12
- otf_api/models/responses/member_membership.py +2 -2
- otf_api/models/responses/member_purchases.py +9 -9
- otf_api/models/responses/out_of_studio_workout_history.py +4 -4
- otf_api/models/responses/performance_summary_detail.py +1 -1
- otf_api/models/responses/performance_summary_list.py +13 -13
- otf_api/models/responses/studio_detail.py +10 -10
- otf_api/models/responses/studio_services.py +8 -8
- otf_api/models/responses/telemetry.py +6 -6
- otf_api/models/responses/telemetry_hr_history.py +6 -6
- otf_api/models/responses/telemetry_max_hr.py +3 -3
- otf_api/models/responses/total_classes.py +2 -2
- otf_api/models/responses/workouts.py +4 -4
- otf_api-0.4.0.dist-info/METADATA +54 -0
- otf_api-0.4.0.dist-info/RECORD +42 -0
- otf_api-0.4.0.dist-info/entry_points.txt +3 -0
- otf_api/__version__.py +0 -1
- otf_api/classes_api.py +0 -44
- otf_api/member_api.py +0 -380
- otf_api/models/auth.py +0 -141
- otf_api/performance_api.py +0 -54
- otf_api/studios_api.py +0 -96
- otf_api/telemetry_api.py +0 -95
- otf_api-0.2.2.dist-info/METADATA +0 -284
- otf_api-0.2.2.dist-info/RECORD +0 -38
- {otf_api-0.2.2.dist-info → otf_api-0.4.0.dist-info}/AUTHORS.md +0 -0
- {otf_api-0.2.2.dist-info → otf_api-0.4.0.dist-info}/LICENSE +0 -0
- {otf_api-0.2.2.dist-info → otf_api-0.4.0.dist-info}/WHEEL +0 -0
@@ -1,26 +1,21 @@
|
|
1
|
-
from .
|
1
|
+
from .body_composition_list import BodyCompositionList
|
2
|
+
from .book_class import BookClass
|
3
|
+
from .bookings import BookingList, BookingStatus
|
4
|
+
from .cancel_booking import CancelBooking
|
2
5
|
from .challenge_tracker_content import ChallengeTrackerContent
|
3
6
|
from .challenge_tracker_detail import ChallengeTrackerDetailList
|
4
|
-
from .classes import OtfClassList
|
5
|
-
from .enums import
|
6
|
-
ALL_CLASS_STATUS,
|
7
|
-
ALL_HISTORY_CLASS_STATUS,
|
8
|
-
ALL_STUDIO_STATUS,
|
9
|
-
BookingStatus,
|
10
|
-
ChallengeType,
|
11
|
-
EquipmentType,
|
12
|
-
HistoryClassStatus,
|
13
|
-
StudioStatus,
|
14
|
-
)
|
7
|
+
from .classes import ClassType, DoW, OtfClassList
|
8
|
+
from .enums import ChallengeType, EquipmentType, HistoryClassStatus
|
15
9
|
from .favorite_studios import FavoriteStudioList
|
16
10
|
from .latest_agreement import LatestAgreement
|
11
|
+
from .lifetime_stats import StatsResponse, StatsTime
|
17
12
|
from .member_detail import MemberDetail
|
18
13
|
from .member_membership import MemberMembership
|
19
14
|
from .member_purchases import MemberPurchaseList
|
20
15
|
from .out_of_studio_workout_history import OutOfStudioWorkoutHistoryList
|
21
16
|
from .performance_summary_detail import PerformanceSummaryDetail
|
22
17
|
from .performance_summary_list import PerformanceSummaryList
|
23
|
-
from .studio_detail import StudioDetail, StudioDetailList
|
18
|
+
from .studio_detail import Pagination, StudioDetail, StudioDetailList
|
24
19
|
from .studio_services import StudioServiceList
|
25
20
|
from .telemetry import Telemetry
|
26
21
|
from .telemetry_hr_history import TelemetryHrHistory
|
@@ -29,32 +24,37 @@ from .total_classes import TotalClasses
|
|
29
24
|
from .workouts import WorkoutList
|
30
25
|
|
31
26
|
__all__ = [
|
27
|
+
"BodyCompositionList",
|
28
|
+
"BookClass",
|
32
29
|
"BookingList",
|
30
|
+
"BookingStatus",
|
31
|
+
"CancelBooking",
|
33
32
|
"ChallengeTrackerContent",
|
34
33
|
"ChallengeTrackerDetailList",
|
34
|
+
"ChallengeType",
|
35
|
+
"ClassType",
|
36
|
+
"DoW",
|
37
|
+
"EquipmentType",
|
38
|
+
"FavoriteStudioList",
|
39
|
+
"HistoryClassStatus",
|
35
40
|
"LatestAgreement",
|
36
41
|
"MemberDetail",
|
37
42
|
"MemberMembership",
|
38
43
|
"MemberPurchaseList",
|
44
|
+
"OtfClassList",
|
39
45
|
"OutOfStudioWorkoutHistoryList",
|
46
|
+
"Pagination",
|
47
|
+
"PerformanceSummaryDetail",
|
48
|
+
"PerformanceSummaryList",
|
49
|
+
"StatsResponse",
|
50
|
+
"StatsTime",
|
51
|
+
"StudioDetail",
|
52
|
+
"StudioDetailList",
|
40
53
|
"StudioServiceList",
|
41
|
-
"TotalClasses",
|
42
|
-
"WorkoutList",
|
43
|
-
"ChallengeType",
|
44
|
-
"BookingStatus",
|
45
|
-
"EquipmentType",
|
46
|
-
"HistoryClassStatus",
|
47
54
|
"StudioStatus",
|
48
|
-
"FavoriteStudioList",
|
49
|
-
"OtfClassList",
|
50
|
-
"TelemetryHrHistory",
|
51
55
|
"Telemetry",
|
56
|
+
"TelemetryHrHistory",
|
52
57
|
"TelemetryMaxHr",
|
53
|
-
"
|
54
|
-
"
|
55
|
-
"ALL_CLASS_STATUS",
|
56
|
-
"ALL_HISTORY_CLASS_STATUS",
|
57
|
-
"ALL_STUDIO_STATUS",
|
58
|
-
"PerformanceSummaryDetail",
|
59
|
-
"PerformanceSummaryList",
|
58
|
+
"TotalClasses",
|
59
|
+
"WorkoutList",
|
60
60
|
]
|
@@ -0,0 +1,304 @@
|
|
1
|
+
import inspect
|
2
|
+
from datetime import datetime
|
3
|
+
from enum import Enum
|
4
|
+
|
5
|
+
import pint
|
6
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
7
|
+
|
8
|
+
ureg = pint.UnitRegistry()
|
9
|
+
|
10
|
+
DEFAULT_WEIGHT_DIVIDERS = [55.0, 70.0, 85.0, 100.0, 115.0, 130.0, 145.0, 160.0, 175.0, 190.0, 205.0]
|
11
|
+
DEFAULT_SKELETAL_MUSCLE_MASS_DIVIDERS = [70.0, 80.0, 90.0, 100.0, 110.0, 120.0, 130.0, 140.0, 150.0, 160.0, 170.0]
|
12
|
+
DEFAULT_BODY_FAT_MASS_DIVIDERS = [40.0, 60.0, 80.0, 100.0, 160.0, 220.0, 280.0, 340.0, 400.0, 460.0, 520.0]
|
13
|
+
|
14
|
+
|
15
|
+
class AverageType(str, Enum):
|
16
|
+
BELOW_AVERAGE = "BELOW_AVERAGE"
|
17
|
+
AVERAGE = "AVERAGE"
|
18
|
+
ABOVE_AVERAGE = "ABOVE_AVERAGE"
|
19
|
+
MINIMUM = "MINIMUM" # unused
|
20
|
+
|
21
|
+
|
22
|
+
class BodyFatPercentIndicator(str, Enum):
|
23
|
+
NO_INDICATOR = "NO_INDICATOR"
|
24
|
+
MINIMUM_BODY_FAT = "MINIMUM_BODY_FAT" # unused
|
25
|
+
LOW_BODY_FAT = "LOW_BODY_FAT" # unused
|
26
|
+
HEALTHY_BODY_FAT = "HEALTHY_BODY_FAT"
|
27
|
+
GOAL_SETTING_FAT = "GOAL_SETTING_FAT"
|
28
|
+
HIGH_BODY_FAT = "HIGH_BODY_FAT"
|
29
|
+
OBESE_BODY_FAT = "OBESE_BODY_FAT" # unused
|
30
|
+
|
31
|
+
|
32
|
+
class Gender(str, Enum):
|
33
|
+
MALE = "M"
|
34
|
+
FEMALE = "F"
|
35
|
+
|
36
|
+
|
37
|
+
def get_percent_body_fat_descriptor(
|
38
|
+
percent_body_fat: float, body_fat_percent_dividers: list[float]
|
39
|
+
) -> BodyFatPercentIndicator:
|
40
|
+
if not percent_body_fat or not body_fat_percent_dividers[3]:
|
41
|
+
return BodyFatPercentIndicator.NO_INDICATOR
|
42
|
+
|
43
|
+
if percent_body_fat < body_fat_percent_dividers[1]:
|
44
|
+
return BodyFatPercentIndicator.HEALTHY_BODY_FAT
|
45
|
+
|
46
|
+
if percent_body_fat < body_fat_percent_dividers[2]:
|
47
|
+
return BodyFatPercentIndicator.GOAL_SETTING_FAT
|
48
|
+
|
49
|
+
return BodyFatPercentIndicator.HIGH_BODY_FAT
|
50
|
+
|
51
|
+
|
52
|
+
def get_relative_descriptor(in_body_value: float, in_body_dividers: list[float]) -> AverageType:
|
53
|
+
if in_body_value <= in_body_dividers[2]:
|
54
|
+
return AverageType.BELOW_AVERAGE
|
55
|
+
|
56
|
+
if in_body_value <= in_body_dividers[4]:
|
57
|
+
return AverageType.AVERAGE
|
58
|
+
|
59
|
+
return AverageType.ABOVE_AVERAGE
|
60
|
+
|
61
|
+
|
62
|
+
def get_body_fat_percent_dividers(age: int, gender: Gender) -> list[float]:
|
63
|
+
if gender == Gender.MALE:
|
64
|
+
return get_body_fat_percent_dividers_male(age)
|
65
|
+
|
66
|
+
return get_body_fat_percent_dividers_female(age)
|
67
|
+
|
68
|
+
|
69
|
+
def get_body_fat_percent_dividers_male(age: int) -> list[float]:
|
70
|
+
match age:
|
71
|
+
case age if 0 <= age < 30:
|
72
|
+
return [0.0, 13.1, 21.1, 100.0]
|
73
|
+
case age if 30 <= age < 40:
|
74
|
+
return [0.0, 17.1, 23.1, 100.0]
|
75
|
+
case age if 40 <= age < 50:
|
76
|
+
return [0.0, 20.1, 25.1, 100.0]
|
77
|
+
case age if 50 <= age < 60:
|
78
|
+
return [0.0, 21.1, 26.1, 100.0]
|
79
|
+
case age if 60 <= age < 70:
|
80
|
+
return [0.0, 22.1, 27.1, 100.0]
|
81
|
+
case _:
|
82
|
+
return [0.0, 0.0, 0.0, 0.0]
|
83
|
+
|
84
|
+
|
85
|
+
def get_body_fat_percent_dividers_female(age: int) -> list[float]:
|
86
|
+
match age:
|
87
|
+
case age if 0 <= age < 30:
|
88
|
+
return [0.0, 19.1, 26.1, 100.0]
|
89
|
+
case age if 30 <= age < 40:
|
90
|
+
return [0.0, 20.1, 27.1, 100.0]
|
91
|
+
case age if 40 <= age < 50:
|
92
|
+
return [0.0, 22.1, 30.1, 100.0]
|
93
|
+
case age if 50 <= age < 60:
|
94
|
+
return [0.0, 25.1, 32.1, 100.0]
|
95
|
+
case age if 60 <= age < 70:
|
96
|
+
return [0.0, 26.1, 33.1, 100.0]
|
97
|
+
case _:
|
98
|
+
return [0.0, 0.0, 0.0, 0.0]
|
99
|
+
|
100
|
+
|
101
|
+
class LeanBodyMass(BaseModel):
|
102
|
+
model_config: ConfigDict = ConfigDict(extra="ignore")
|
103
|
+
left_arm: float = Field(..., alias="lbmOfLeftArm")
|
104
|
+
left_leg: float = Field(..., alias="lbmOfLeftLeg")
|
105
|
+
right_arm: float = Field(..., alias="lbmOfRightArm")
|
106
|
+
right_leg: float = Field(..., alias="lbmOfRightLeg")
|
107
|
+
trunk: float = Field(..., alias="lbmOfTrunk")
|
108
|
+
|
109
|
+
|
110
|
+
class LeanBodyMassPercent(BaseModel):
|
111
|
+
model_config: ConfigDict = ConfigDict(extra="ignore")
|
112
|
+
left_arm: float = Field(..., alias="lbmPercentOfLeftArm")
|
113
|
+
left_leg: float = Field(..., alias="lbmPercentOfLeftLeg")
|
114
|
+
right_arm: float = Field(..., alias="lbmPercentOfRightArm")
|
115
|
+
right_leg: float = Field(..., alias="lbmPercentOfRightLeg")
|
116
|
+
trunk: float = Field(..., alias="lbmPercentOfTrunk")
|
117
|
+
|
118
|
+
|
119
|
+
class BodyFatMass(BaseModel):
|
120
|
+
model_config: ConfigDict = ConfigDict(extra="ignore")
|
121
|
+
control: float = Field(..., alias="bfmControl")
|
122
|
+
left_arm: float = Field(..., alias="bfmOfLeftArm")
|
123
|
+
left_leg: float = Field(..., alias="bfmOfLeftLeg")
|
124
|
+
right_arm: float = Field(..., alias="bfmOfRightArm")
|
125
|
+
right_leg: float = Field(..., alias="bfmOfRightLeg")
|
126
|
+
trunk: float = Field(..., alias="bfmOfTrunk")
|
127
|
+
|
128
|
+
|
129
|
+
class BodyFatMassPercent(BaseModel):
|
130
|
+
model_config: ConfigDict = ConfigDict(extra="ignore")
|
131
|
+
left_arm: float = Field(..., alias="bfmPercentOfLeftArm")
|
132
|
+
left_leg: float = Field(..., alias="bfmPercentOfLeftLeg")
|
133
|
+
right_arm: float = Field(..., alias="bfmPercentOfRightArm")
|
134
|
+
right_leg: float = Field(..., alias="bfmPercentOfRightLeg")
|
135
|
+
trunk: float = Field(..., alias="bfmPercentOfTrunk")
|
136
|
+
|
137
|
+
|
138
|
+
class TotalBodyWeight(BaseModel):
|
139
|
+
model_config: ConfigDict = ConfigDict(extra="ignore")
|
140
|
+
right_arm: float = Field(..., alias="tbwOfRightArm")
|
141
|
+
left_arm: float = Field(..., alias="tbwOfLeftArm")
|
142
|
+
trunk: float = Field(..., alias="tbwOfTrunk")
|
143
|
+
right_leg: float = Field(..., alias="tbwOfRightLeg")
|
144
|
+
left_leg: float = Field(..., alias="tbwOfLeftLeg")
|
145
|
+
|
146
|
+
|
147
|
+
class IntraCellularWater(BaseModel):
|
148
|
+
model_config: ConfigDict = ConfigDict(extra="ignore")
|
149
|
+
right_arm: float = Field(..., alias="icwOfRightArm")
|
150
|
+
left_arm: float = Field(..., alias="icwOfLeftArm")
|
151
|
+
trunk: float = Field(..., alias="icwOfTrunk")
|
152
|
+
right_leg: float = Field(..., alias="icwOfRightLeg")
|
153
|
+
left_leg: float = Field(..., alias="icwOfLeftLeg")
|
154
|
+
|
155
|
+
|
156
|
+
class ExtraCellularWater(BaseModel):
|
157
|
+
model_config: ConfigDict = ConfigDict(extra="ignore")
|
158
|
+
right_arm: float = Field(..., alias="ecwOfRightArm")
|
159
|
+
left_arm: float = Field(..., alias="ecwOfLeftArm")
|
160
|
+
trunk: float = Field(..., alias="ecwOfTrunk")
|
161
|
+
right_leg: float = Field(..., alias="ecwOfRightLeg")
|
162
|
+
left_leg: float = Field(..., alias="ecwOfLeftLeg")
|
163
|
+
|
164
|
+
|
165
|
+
class ExtraCellularWaterOverTotalBodyWater(BaseModel):
|
166
|
+
model_config: ConfigDict = ConfigDict(extra="ignore")
|
167
|
+
right_arm: float = Field(..., alias="ecwOverTBWOfRightArm")
|
168
|
+
left_arm: float = Field(..., alias="ecwOverTBWOfLeftArm")
|
169
|
+
trunk: float = Field(..., alias="ecwOverTBWOfTrunk")
|
170
|
+
right_leg: float = Field(..., alias="ecwOverTBWOfRightLeg")
|
171
|
+
left_leg: float = Field(..., alias="ecwOverTBWOfLeftLeg")
|
172
|
+
|
173
|
+
|
174
|
+
class BodyCompositionData(BaseModel):
|
175
|
+
member_uuid: str = Field(..., alias="memberUUId")
|
176
|
+
member_id: str = Field(..., alias="memberId")
|
177
|
+
scan_result_uuid: str = Field(..., alias="scanResultUUId")
|
178
|
+
inbody_id: str = Field(..., alias="id", exclude=True, description="InBody ID, same as email address")
|
179
|
+
email: str
|
180
|
+
height: str = Field(..., description="Height in cm")
|
181
|
+
gender: Gender
|
182
|
+
age: int
|
183
|
+
scan_datetime: datetime = Field(..., alias="testDatetime")
|
184
|
+
provided_weight: float = Field(
|
185
|
+
..., alias="weight", description="Weight in pounds, provided by member at time of scan"
|
186
|
+
)
|
187
|
+
|
188
|
+
lean_body_mass_details: LeanBodyMass
|
189
|
+
lean_body_mass_percent_details: LeanBodyMassPercent
|
190
|
+
|
191
|
+
total_body_weight: float = Field(..., alias="tbw", description="Total body weight in pounds, based on scan results")
|
192
|
+
dry_lean_mass: float = Field(..., alias="dlm")
|
193
|
+
body_fat_mass: float = Field(..., alias="bfm")
|
194
|
+
lean_body_mass: float = Field(..., alias="lbm")
|
195
|
+
skeletal_muscle_mass: float = Field(..., alias="smm")
|
196
|
+
body_mass_index: float = Field(..., alias="bmi")
|
197
|
+
percent_body_fat: float = Field(..., alias="pbf")
|
198
|
+
basal_metabolic_rate: float = Field(..., alias="bmr")
|
199
|
+
in_body_type: str = Field(..., alias="inBodyType")
|
200
|
+
|
201
|
+
body_fat_mass: float = Field(..., alias="bfm")
|
202
|
+
skeletal_muscle_mass: float = Field(..., alias="smm")
|
203
|
+
|
204
|
+
# excluded because they are only useful for end result of calculations
|
205
|
+
body_fat_mass_dividers: list[float] = Field(..., alias="bfmGraphScale", exclude=True)
|
206
|
+
body_fat_mass_plot_point: float = Field(..., alias="pfatnew", exclude=True)
|
207
|
+
skeletal_muscle_mass_dividers: list[float] = Field(..., alias="smmGraphScale", exclude=True)
|
208
|
+
skeletal_muscle_mass_plot_point: float = Field(..., alias="psmm", exclude=True)
|
209
|
+
weight_dividers: list[float] = Field(..., alias="wtGraphScale", exclude=True)
|
210
|
+
weight_plot_point: float = Field(..., alias="pwt", exclude=True)
|
211
|
+
|
212
|
+
# excluded due to 0 values
|
213
|
+
body_fat_mass_details: BodyFatMass = Field(..., exclude=True)
|
214
|
+
body_fat_mass_percent_details: BodyFatMassPercent = Field(..., exclude=True)
|
215
|
+
total_body_weight_details: TotalBodyWeight = Field(..., exclude=True)
|
216
|
+
intra_cellular_water_details: IntraCellularWater = Field(..., exclude=True)
|
217
|
+
extra_cellular_water_details: ExtraCellularWater = Field(..., exclude=True)
|
218
|
+
extra_cellular_water_over_total_body_water_details: ExtraCellularWaterOverTotalBodyWater = Field(..., exclude=True)
|
219
|
+
visceral_fat_level: float = Field(..., alias="vfl", exclude=True)
|
220
|
+
visceral_fat_area: float = Field(..., alias="vfa", exclude=True)
|
221
|
+
body_comp_measurement: float = Field(..., alias="bcm", exclude=True)
|
222
|
+
total_body_weight_over_lean_body_mass: float = Field(..., alias="tbwOverLBM", exclude=True)
|
223
|
+
intracellular_water: float = Field(..., alias="icw", exclude=True)
|
224
|
+
extracellular_water: float = Field(..., alias="ecw", exclude=True)
|
225
|
+
lean_body_mass_control: float = Field(..., alias="lbmControl", exclude=True)
|
226
|
+
|
227
|
+
def __init__(self, **data):
|
228
|
+
# populate child models
|
229
|
+
child_model_dict = {
|
230
|
+
k: v.annotation
|
231
|
+
for k, v in self.model_fields.items()
|
232
|
+
if inspect.isclass(v.annotation) and issubclass(v.annotation, BaseModel)
|
233
|
+
}
|
234
|
+
for k, v in child_model_dict.items():
|
235
|
+
data[k] = v(**data)
|
236
|
+
|
237
|
+
super().__init__(**data)
|
238
|
+
|
239
|
+
@field_validator("member_id", mode="before")
|
240
|
+
@classmethod
|
241
|
+
def int_to_str(cls, v: int):
|
242
|
+
return str(v)
|
243
|
+
|
244
|
+
@field_validator("skeletal_muscle_mass_dividers", "weight_dividers", "body_fat_mass_dividers", mode="before")
|
245
|
+
@classmethod
|
246
|
+
def convert_dividers_to_float_list(cls, v: str):
|
247
|
+
return [float(i) for i in v.split(";")]
|
248
|
+
|
249
|
+
@field_validator("total_body_weight", mode="before")
|
250
|
+
@classmethod
|
251
|
+
def convert_body_weight_from_kg_to_pounds(cls, v: float):
|
252
|
+
return ureg.Quantity(v, ureg.kilogram).to(ureg.pound).magnitude
|
253
|
+
|
254
|
+
@property
|
255
|
+
def body_fat_mass_relative_descriptor(self) -> AverageType:
|
256
|
+
"""Get the relative descriptor for the body fat mass plot point.
|
257
|
+
|
258
|
+
For this item, a lower value is better.
|
259
|
+
|
260
|
+
Returns:
|
261
|
+
AverageType: The relative descriptor for the body fat mass plot point
|
262
|
+
"""
|
263
|
+
dividers = self.body_fat_mass_dividers or DEFAULT_BODY_FAT_MASS_DIVIDERS
|
264
|
+
return get_relative_descriptor(self.body_fat_mass_plot_point, dividers)
|
265
|
+
|
266
|
+
@property
|
267
|
+
def skeletal_muscle_mass_relative_descriptor(self) -> AverageType:
|
268
|
+
"""Get the relative descriptor for the skeletal muscle mass plot point.
|
269
|
+
|
270
|
+
For this item, a higher value is better.
|
271
|
+
|
272
|
+
Returns:
|
273
|
+
AverageType: The relative descriptor for the skeletal muscle mass plot point
|
274
|
+
|
275
|
+
"""
|
276
|
+
dividers = self.skeletal_muscle_mass_dividers or DEFAULT_SKELETAL_MUSCLE_MASS_DIVIDERS
|
277
|
+
return get_relative_descriptor(self.skeletal_muscle_mass_plot_point, dividers)
|
278
|
+
|
279
|
+
@property
|
280
|
+
def weight_relative_descriptor(self) -> AverageType:
|
281
|
+
"""Get the relative descriptor for the weight plot point.
|
282
|
+
|
283
|
+
For this item, a lower value is better.
|
284
|
+
|
285
|
+
Returns:
|
286
|
+
AverageType: The relative descriptor for the weight
|
287
|
+
"""
|
288
|
+
dividers = self.weight_dividers or DEFAULT_WEIGHT_DIVIDERS
|
289
|
+
return get_relative_descriptor(self.weight_plot_point, dividers)
|
290
|
+
|
291
|
+
@property
|
292
|
+
def body_fat_percent_relative_descriptor(self) -> BodyFatPercentIndicator:
|
293
|
+
"""Get the relative descriptor for the percent body fat.
|
294
|
+
|
295
|
+
Returns:
|
296
|
+
BodyFatPercentIndicator: The relative descriptor for the percent body fat
|
297
|
+
"""
|
298
|
+
return get_percent_body_fat_descriptor(
|
299
|
+
self.percent_body_fat, get_body_fat_percent_dividers(self.age, self.gender)
|
300
|
+
)
|
301
|
+
|
302
|
+
|
303
|
+
class BodyCompositionList(BaseModel):
|
304
|
+
data: list[BodyCompositionData]
|