text: """Synapse Challenge Services"""
  import json
  from typing import Union, Iterator
  
  from synapseclient import Project, Synapse, Team
  from synapseclient.core.utils import id_of
  
  from .synapseservices.challenge import Challenge
  
  
  class ChallengeApi:
      """Challenge services
      https://docs.synapse.org/rest/index.html#org.sagebionetworks.repo.web.controller.ChallengeController
  
      Args:
          id: The ID of this Challenge object
          project: synapseclient.Project or its id
          team: synapseclient.Team or its id
  
      """
      def __init__(self, syn: Synapse):
          self.syn = syn
  
      def create_challenge(self, teamid: str, projectid: str) -> Challenge:
          """Creates a challenge
  
          Args:
              teamid: A Synapse Team id
              projectid: A Synapse Project id
  
          Returns:
              A synapseservices.Challenge
  
          """
          challenge_object = {'participantTeamId': teamid,
                              'projectId': projectid}
          challenge = self.syn.restPOST('/challenge',
                                        json.dumps(challenge_object))
          return Challenge(**challenge)
  
      def get_registered_challenges(self,
                                    participantId: str) -> Iterator[Challenge]:
          """Gets a list of challenges a participant is registered to
  
          Args:
              participantId: A Synapse User Id
  
          Yields:
              A synapseservices.Challenge
  
          """
          challenges = self.syn._GET_paginated(
              f'/challenge?participantId={participantId}'
          )
          for challenge in challenges:
              yield Challenge(**challenge)
  
      def get_challenge(self, challengeid: str = None,
                        projectid: str = None) -> Challenge:
          """Gets a challenge
  
          Args:
              challengeid: A Synapse Challenge id
              projectId: A Synapse Project id
  
          Returns:
              A synapseservices.Challenge
  
          """
          if challengeid is not None:
              url = f"/challenge/{challengeid}"
          elif projectid is not None:
              url = f"/entity/{projectid}/challenge"
          else:
              raise ValueError("Must pass in `challengeid` or `projectid`")
  
          return Challenge(**self.syn.restGET(url))
  
      def update_challenge(self, challengeid: str, teamid: str = None,
                           projectid: str = None) -> Challenge:
          """Updates a Synapse Challenge
  
          Args:
              challengeid: A Synapse Challenge id
              teamid: A Synapse Team id
              projectid: A Synapse Project id
  
          Returns:
              A synapseservices.Challenge
  
          """
          challenge_object = {'id': challengeid,
                              'participantTeamId': teamid,
                              'projectId': projectid}
          challenge = self.syn.restPUT(f'/challenge/{challengeid}',
                                       json.dumps(challenge_object))
          return Challenge(**challenge)
  
      def delete_challenge(self, challengeid: str):
          """Deletes a Synapse Challenge
  
          Args:
              challengeid: A Synapse Challenge id
  
          """
          return self.syn.restDELETE(f'/challenge/{challengeid}')
  
      def get_registered_participants(self, challengeid: str) -> list:
          """Get participants registered for a challenge
  
          Args:
              challengeid: A Synapse Challenge id
  
          Returns:
              Registered participants
  
          """
          url = f'/challenge/{challengeid}/participant'
          return self.syn._GET_paginated(url)
  
      def get_registered_teams(self, challengeid: str):
          """Get teams registered for a challenge
  
          Args:
              challengeid: A Synapse Challenge id
  
          Returns:
              Registered teams
  
          """
          url = f'/challenge/{challengeid}/challengeTeam'
          return self.syn._GET_paginated(url)
  
      def register_team(self, challengeid: str, teamid: str):
          """Register team
  
          Args:
              challengeid: A Synapse challenge id
              teamid: A Synapse Team id
  
          Returns:
              A Synapse team
  
          """
          team_dict = {'challengeId': challengeid, 'teamId': teamid}
          return self.syn.restPOST(f'/challenge/{challengeid}/challengeTeam',
                                   json.dumps(team_dict))
  
  
  def get_registered_challenges(syn: Synapse,
                                userid: str = None) -> Iterator[Project]:
      """Get the Synapse Challenge Projects a user is registered to.
      Defaults to the logged in synapse user.
  
      Args:
          syn: Synapse connection
          userid: Specify userid if you want to know the challenges
                  another Synapse user is registered to.
  
      Yields:
          A synapseclient.Project
  
      """
      challenge_api = ChallengeApi(syn=syn)
      # This will return the logged in user profile if None is passed in
      profile = syn.getUserProfile(userid)
      userid = profile.ownerId
      registered = challenge_api.get_registered_challenges(participantId=userid)
      for challenge in registered:
          challenge_ent = syn.get(challenge.projectId)
          print(challenge_ent.name)
          yield challenge_ent
  
  
  def get_challenge(syn: Synapse, project: Union[Project, str]) -> Challenge:
      """Get the Challenge associated with a Project.
  
      See the definition of a Challenge object here:
      https://docs.synapse.org/rest/org/sagebionetworks/repo/model/Challenge.html
  
      Args:
          syn: Synapse connection
          project: A synapseclient.Project or its id
  
      Returns:
          Challenge object
  
      """
      synid = id_of(project)
      challenge_api = ChallengeApi(syn=syn)
      challenge_obj = challenge_api.get_challenge(projectid=synid)
      return challenge_obj
  
  
  def create_challenge(syn: Synapse, project: Union[Project, str],
                       team: Union[Team, str]) -> Challenge:
      """Creates Challenge associated with a Project
  
      Args:
          syn: Synapse connection
          project: A synapseclient.Project or its id
          team: A synapseclient.Team or its id
  
      Returns:
          Challenge object
  
      """
      synid = id_of(project)
      teamid = id_of(team)
  
      challenge_api = ChallengeApi(syn=syn)
      challenge_obj = challenge_api.create_challenge(projectid=synid,
                                                     teamid=teamid)
      return challenge_obj
  