Skip to content

Commit

Permalink
remove some endpoints, update some model names, remove some models, c…
Browse files Browse the repository at this point in the history
…ombine some model files
  • Loading branch information
NodeJSmith committed Jan 19, 2025
1 parent 5bfa254 commit 2bc277b
Show file tree
Hide file tree
Showing 21 changed files with 267 additions and 331 deletions.
4 changes: 2 additions & 2 deletions examples/challenge_tracker_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def main():

# challenge tracker content is an overview of the challenges OTF runs
# and your participation in them
challenge_tracker_content = otf.get_challenge_tracker_content()
challenge_tracker_content = otf.get_challenge_tracker()
print(challenge_tracker_content.benchmarks[0].model_dump_json(indent=4))

"""
Expand Down Expand Up @@ -46,7 +46,7 @@ def main():

# challenge tracker details are detailed information about specific challenges
# this endpoint takes an equipment type and a challenge type as arguments
tread_challenge_details = otf.get_challenge_tracker_detail(EquipmentType.Treadmill, ChallengeType.Other)
tread_challenge_details = otf.get_benchmarks(EquipmentType.Treadmill, ChallengeType.Other)
print(tread_challenge_details[0].model_dump_json(indent=4))

"""
Expand Down
65 changes: 17 additions & 48 deletions src/otf_api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -629,20 +629,6 @@ def get_member_lifetime_stats(
stats = models.StatsResponse(**data["data"])
return stats

def get_latest_agreement(self) -> models.LatestAgreement:
"""Get the latest agreement for the member.
Returns:
LatestAgreement: The agreement.
Notes:
---
In this context, "latest" means the most recent agreement with a specific ID, not the most recent agreement
in general. The agreement ID is hardcoded in the endpoint, so it will always return the same agreement.
"""
data = self._default_request("GET", "/member/agreements/9d98fb27-0f00-4598-ad08-5b1655a59af6")
return models.LatestAgreement(**data["data"])

def get_out_of_studio_workout_history(self) -> list[models.OutOfStudioWorkoutHistory]:
"""Get the member's out of studio workout history.
Expand Down Expand Up @@ -827,21 +813,21 @@ def get_body_composition_list(self) -> list[models.BodyCompositionData]:
data = self._default_request("GET", f"/member/members/{self.user.cognito_id}/body-composition")
return [models.BodyCompositionData(**item) for item in data["data"]]

def get_challenge_tracker_content(self) -> models.ChallengeTrackerContent:
def get_challenge_tracker(self) -> models.ChallengeTracker:
"""Get the member's challenge tracker content.
Returns:
ChallengeTrackerContent: The member's challenge tracker content.
ChallengeTracker: The member's challenge tracker content.
"""
data = self._default_request("GET", f"/challenges/v3.1/member/{self.member_uuid}")
return models.ChallengeTrackerContent(**data["Dto"])
return models.ChallengeTracker(**data["Dto"])

def get_challenge_tracker_detail(
def get_benchmarks(
self,
equipment_id: models.EquipmentType,
challenge_type_id: models.ChallengeType,
challenge_sub_type_id: int = 0,
) -> list[models.ChallengeTrackerDetail]:
) -> list[models.FitnessBenchmark]:
"""Get the member's challenge tracker details.
Args:
Expand All @@ -850,7 +836,7 @@ def get_challenge_tracker_detail(
challenge_sub_type_id (int): The challenge sub type ID. Default is 0.
Returns:
list[ChallengeTrackerDetail]: The member's challenge tracker details.
list[FitnessBenchmark]: The member's challenge tracker details.
Notes:
---
Expand All @@ -864,30 +850,28 @@ def get_challenge_tracker_detail(
}

data = self._default_request("GET", f"/challenges/v3/member/{self.member_uuid}/benchmarks", params=params)
return [models.ChallengeTrackerDetail(**item) for item in data["Dto"]]
return [models.FitnessBenchmark(**item) for item in data["Dto"]]

def get_challenge_tracker_participation(self, challenge_type_id: models.ChallengeType) -> Any:
def get_challenge_tracker_detail(self, challenge_type_id: models.ChallengeType) -> models.FitnessBenchmark:
"""Get the member's participation in a challenge.
Args:
challenge_type_id (ChallengeType): The challenge type ID.
Returns:
Any: The member's participation in the challenge.
Notes:
---
I've never gotten this to return anything other than invalid response. I'm not sure if it's a bug
in my code or the API.
FitnessBenchmark: The member's participation in the challenge.
"""

data = self._default_request(
"GET",
f"/challenges/v1/member/{self.member_uuid}/participation",
params={"challengeTypeId": challenge_type_id.value},
)
return data["Dto"]

if len(data["Dto"]) > 1:
LOGGER.warning("Multiple challenge participations found, returning the first one.")

return models.FitnessBenchmark(**data["Dto"][0])

def get_performance_summaries(self, limit: int = 5) -> list[models.PerformanceSummaryEntry]:
"""Get a list of performance summaries for the authenticated user.
Expand Down Expand Up @@ -927,7 +911,7 @@ def get_performance_summary(self, performance_summary_id: str) -> models.Perform

return models.PerformanceSummaryDetail(**res)

def get_hr_history(self) -> list[models.HistoryItem]:
def get_hr_history(self) -> list[models.TelemetryHistoryItem]:
"""Get the heartrate history for the user.
Returns a list of history items that contain the max heartrate, start/end bpm for each zone,
Expand All @@ -940,23 +924,8 @@ def get_hr_history(self) -> list[models.HistoryItem]:
path = "/v1/physVars/maxHr/history"

params = {"memberUuid": self.member_uuid}
res = self._telemetry_request("GET", path, params=params)
return [models.HistoryItem(**item) for item in res["items"]]

def get_max_hr(self) -> models.TelemetryMaxHr:
"""Get the max heartrate for the user.
Returns a simple object that has the member_uuid and the max_hr.
Returns:
TelemetryMaxHr: The max heartrate for the user.
"""
path = "/v1/physVars/maxHr"

params = {"memberUuid": self.member_uuid}

res = self._telemetry_request("GET", path, params=params)
return models.TelemetryMaxHr(**res)
resp = self._telemetry_request("GET", path, params=params)
return [models.TelemetryHistoryItem(**item) for item in resp["history"]]

def get_telemetry(self, performance_summary_id: str, max_data_points: int = 120) -> models.Telemetry:
"""Get the telemetry for a performance summary.
Expand Down
17 changes: 7 additions & 10 deletions src/otf_api/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from .body_composition_list import BodyCompositionData
from .bookings import Booking
from .challenge_tracker_content import ChallengeTrackerContent
from .challenge_tracker_detail import ChallengeTrackerDetail
from .challenge_tracker_content import ChallengeTracker
from .challenge_tracker_detail import FitnessBenchmark
from .classes import OtfClass
from .enums import BookingStatus, ChallengeType, ClassType, DoW, EquipmentType, StatsTime, StudioStatus
from .latest_agreement import LatestAgreement
from .lifetime_stats import StatsResponse
from .member_detail import MemberDetail
from .member_membership import MemberMembership
Expand All @@ -14,21 +13,19 @@
from .performance_summary_list import PerformanceSummaryEntry
from .studio_detail import StudioDetail
from .studio_services import StudioService
from .telemetry import Telemetry
from .telemetry_hr_history import HistoryItem
from .telemetry_max_hr import TelemetryMaxHr
from .telemetry import Telemetry, TelemetryHistoryItem

__all__ = [
"BodyCompositionData",
"Booking",
"BookingStatus",
"ChallengeTrackerContent",
"ChallengeTrackerDetail",
"ChallengeParticipation",
"ChallengeTracker",
"ChallengeType",
"ClassType",
"DoW",
"EquipmentType",
"HistoryItem",
"FitnessBenchmark",
"LatestAgreement",
"MemberDetail",
"MemberMembership",
Expand All @@ -43,5 +40,5 @@
"StudioService",
"StudioStatus",
"Telemetry",
"TelemetryMaxHr",
"TelemetryHistoryItem",
]
1 change: 1 addition & 0 deletions src/otf_api/models/body_composition_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

ureg = pint.UnitRegistry()


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]
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]
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]
Expand Down
2 changes: 0 additions & 2 deletions src/otf_api/models/bookings.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ class Coach(OtfItemBase):
last_name: str | None = Field(None, alias="lastName")

# unused fields
image_url: str | None = Field(None, alias="imageUrl", exclude=True, repr=False)
name: str = Field(exclude=True, repr=False)
profile_picture_url: str | None = Field(None, alias="profilePictureUrl", exclude=True, repr=False)

@property
def full_name(self) -> str:
Expand Down
47 changes: 26 additions & 21 deletions src/otf_api/models/challenge_tracker_content.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,43 @@
from pydantic import Field

from otf_api.models.base import OtfItemBase
from otf_api.models.enums import EquipmentType


class Year(OtfItemBase):
year: str = Field(..., alias="Year")
is_participated: bool = Field(..., alias="IsParticipated")
in_progress: bool = Field(..., alias="InProgress")
year: int | None = Field(None, alias="Year")
is_participated: bool | None = Field(None, alias="IsParticipated")
in_progress: bool | None = Field(None, alias="InProgress")


class Program(OtfItemBase):
challenge_category_id: int = Field(..., alias="ChallengeCategoryId")
challenge_sub_category_id: int = Field(..., alias="ChallengeSubCategoryId")
challenge_name: str = Field(..., alias="ChallengeName")
years: list[Year] = Field(..., alias="Years")
logo_url: str = Field(..., alias="LogoUrl")
# NOTE: These ones do seem to match the ProgramType enums in the OTF app.
# Leaving them as int for now though in case older data or other user's
# data doesn't match up.
challenge_category_id: int | None = Field(None, alias="ChallengeCategoryId")
challenge_sub_category_id: int | None = Field(None, alias="ChallengeSubCategoryId")
challenge_name: str | None = Field(None, alias="ChallengeName")
years: list[Year] = Field(default_factory=list, alias="Years")


class Challenge(OtfItemBase):
challenge_category_id: int = Field(..., alias="ChallengeCategoryId")
challenge_sub_category_id: int = Field(..., alias="ChallengeSubCategoryId")
challenge_name: str = Field(..., alias="ChallengeName")
years: list[Year] = Field(..., alias="Years")
logo_url: str = Field(..., alias="LogoUrl")
# NOTE: The challenge category/subcategory ids here do not seem to be at
# all related to the ChallengeType enums or the few SubCategory enums I've
# been able to puzzle out. I haven't been able to link them to any code
# in the OTF app. Due to that, they are being excluded from the model for now.
challenge_category_id: int | None = Field(None, alias="ChallengeCategoryId", exclude=True, repr=False)
challenge_sub_category_id: int | None = Field(None, alias="ChallengeSubCategoryId", exclude=True, repr=False)
challenge_name: str | None = Field(None, alias="ChallengeName")
years: list[Year] = Field(default_factory=list, alias="Years")


class Benchmark(OtfItemBase):
equipment_id: int = Field(..., alias="EquipmentId")
equipment_name: str = Field(..., alias="EquipmentName")
years: list[Year] = Field(..., alias="Years")
logo_url: str = Field(..., alias="LogoUrl")
equipment_id: EquipmentType | None = Field(None, alias="EquipmentId")
equipment_name: str | None = Field(None, alias="EquipmentName")
years: list[Year] = Field(default_factory=list, alias="Years")


class ChallengeTrackerContent(OtfItemBase):
programs: list[Program] = Field(..., alias="Programs")
challenges: list[Challenge] = Field(..., alias="Challenges")
benchmarks: list[Benchmark] = Field(..., alias="Benchmarks")
class ChallengeTracker(OtfItemBase):
programs: list[Program] = Field(default_factory=list, alias="Programs")
challenges: list[Challenge] = Field(default_factory=list, alias="Challenges")
benchmarks: list[Benchmark] = Field(default_factory=list, alias="Benchmarks")
Loading

0 comments on commit 2bc277b

Please sign in to comment.