Exemplo n.º 1
0
class Name(Decodable):

    def __init__(
        self,
        first_name: str,
        other_name: str,
        last_name: str
    ) -> None:

        self._first_name = first_name
        self._other_name = other_name
        self._last_name = last_name

        return

    first = Immutable(lambda s: s._first_name)
    other = Immutable(lambda s: s._other_name)
    last = Immutable(lambda s: s._last_name)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(
            first_name=data['first_name'],
            other_name=data['other_name'],
            last_name=data['last_name']
        )
Exemplo n.º 2
0
class Position(Decodable):
    def __init__(self, indexid: int, name: str,
                 categories: List[PositionCategory]) -> None:

        self._indexid = indexid
        self._name = name
        self._categories = categories

        return

    name = Immutable(lambda s: s._name)
    categories = Immutable(lambda s: s._categories)

    lowercase_name = Immutable(lambda s: s._name.lower())
    sole_category = Immutable(lambda s: s._categories[0]
                              if len(s._categories) == 1 else None)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(indexid=data['indexid'],
                   name=data['name'],
                   categories=PositionCategory.optionally_decode_many(
                       data['categories'], default_to_empty_list=True))

    def __eq__(self, other) -> bool:
        if not isinstance(other, Position):
            return False
        if self._indexid == other._indexid:
            return True
        return False

    def __ne__(self, other) -> bool:
        return not other == self
Exemplo n.º 3
0
class Round(Decodable):
    """Points attributed to a player in a particular round"""
    def __init__(self, sequence: int, scores: List[Score]) -> None:

        self._round_sequence = sequence
        self._scores = scores

        return

    round_sequence = Immutable(lambda s: s._round_sequence)
    scores = Immutable(lambda s: s._scores)

    total_points = Immutable(lambda s: sum([k.value for k in s._scores]))

    def score_for_metric(self, metric: FantasyMetric) -> Optional[int]:

        for score in self._scores:
            if score.fantasy_metric == metric:
                return score.value
            continue

        return None

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(sequence=data['round_sequence'],
                   scores=Score.decode_many(data['scores']))
Exemplo n.º 4
0
class Team:
    def __init__(self, name: str) -> None:

        self._name = name

        return

    name = Immutable(lambda s: s._name)
    lowercase_name = Immutable(lambda s: s._name.lower())
Exemplo n.º 5
0
class League(Decodable):

    _PATH = '/league'

    def __init__(self, public_id: str, teams: List[TeamSummary],
                 commissioner_id: str, name: str, created: NozomiTime) -> None:

        self._public_id = public_id
        self._teams = teams
        self._commissioner_id = commissioner_id
        self._name = name
        self._created = created

        return

    name = Immutable(lambda s: s._name)
    public_id = Immutable(lambda s: s._public_id)
    teams = Immutable(lambda s: s._teams)

    def is_commissioned_by(self, human: Human) -> bool:
        """Return True if the supplied human is the league commissioner"""
        return human.public_id == self._commissioner_id

    @classmethod
    def retrieve(cls: Type[T], public_id: str, credentials: RequestCredentials,
                 configuration: Configuration) -> Optional[T]:
        """
        Optionally return a League with the given public ID, if it exists
        """

        assert isinstance(public_id, str)

        parameters = URLParameters([
            URLParameter('league', public_id),
            URLParameter('season', '2020')  # MVP hardcode
        ])

        request = ApiRequest(path=cls._PATH,
                             method=HTTPMethod.GET,
                             configuration=configuration,
                             data=None,
                             url_parameters=parameters,
                             credentials=credentials)

        return cls.optionally_decode(request.response_data)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(public_id=data['public_id'],
                   teams=TeamSummary.decode_many(data['teams']),
                   commissioner_id=data['commissioner_id'],
                   name=data['name'],
                   created=NozomiTime.decode(data['created']))
Exemplo n.º 6
0
class PositionRequirement(Decodable):
    def __init__(self, count: int, position_name: str) -> None:

        self._count = count
        self._position_name = position_name

        return

    count: int = Immutable(lambda s: s._count)
    position_name: str = Immutable(lambda s: s._position_name)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(count=data['count'], position_name=data['position_name'])
Exemplo n.º 7
0
class Price(Decodable):
    def __init__(self, magnitude: Decimal, denomination: Denomination) -> None:

        self._magnitude = magnitude
        self._denomination = denomination

        return

    magnitude = Immutable(lambda s: s._magnitude)
    denomination = Immutable(lambda s: s._denomination)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(magnitude=Decimal(data['magnitude']),
                   denomination=Denomination.decode(data['denomination']))
Exemplo n.º 8
0
class PositionCategory(Decodable):

    def __init__(
        self,
        indexid: int,
        name: str
    ) -> None:

        self._indexid = indexid
        self._name = name

        return

    name = Immutable(lambda s: s._name)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(
            indexid=data['indexid'],
            name=data['name']
        )

    def __eq__(self, other) -> bool:
        if not isinstance(other, PositionCategory):
            return False
        if self._indexid == other._indexid:
            return True
        return False

    def __ne__(self, other) -> bool:
        return not other == self
Exemplo n.º 9
0
class Human(Decodable):

    _PATH = '/human'

    def __init__(self, public_id: str, email: CommunicationMethod,
                 handle: str) -> None:

        self._email = email
        self._public_id = public_id
        self._handle = handle

        return

    display_name: str = Immutable(
        lambda s: s._handle if s._handle else s._email.body.split('@')[0])
    public_id: str = Immutable(lambda s: s._public_id)
    email: CommunicationMethod = Immutable(lambda s: s._email)
    handle: str = Immutable(lambda s: s._handle)

    @classmethod
    def retrieve(cls: Type[T], public_id: str, credentials: RequestCredentials,
                 configuration: Configuration) -> Optional[T]:
        """
        Optionally return a Human with the given public ID, if it exists
        """

        assert isinstance(public_id, str)

        target = URLParameter('public_id', public_id)
        parameters = URLParameters([target])

        request = ApiRequest(path=cls._PATH,
                             method=HTTPMethod.GET,
                             configuration=configuration,
                             data=None,
                             url_parameters=parameters,
                             credentials=credentials)

        return cls.optionally_decode(request.response_data)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(public_id=data['public_id'],
                   email=CommunicationMethod.decode(data['email']),
                   handle=data['handle'])
Exemplo n.º 10
0
class Profile(Decodable):
    def __init__(self, first_name: str, last_name: str,
                 position: Optional[Position], public_id: str,
                 team_name: str) -> None:

        self._first_name = first_name
        self._last_name = last_name
        self._position = position
        self._public_id = public_id
        self._team_name = team_name

        return

    first_name = Immutable(lambda s: s._first_name)
    last_name = Immutable(lambda s: s._last_name)
    public_id = Immutable(lambda s: s._public_id)
    position = Immutable(lambda s: s._position)
    position_name = Immutable(lambda s: s._position.name
                              if s._position else None)
    team_name = Immutable(lambda s: s._team_name)

    full_name = Immutable(lambda s: s._first_name + ' ' + s._last_name)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(first_name=data['first_name'],
                   last_name=data['last_name'],
                   position=Position.optionally_decode(data['position']),
                   public_id=data['public_id'],
                   team_name=data['team_name'])
Exemplo n.º 11
0
class Score(Decodable):
    """An integer score with respect to some fantasy metric"""
    def __init__(self, fantasy_metric: FantasyMetric, score: int) -> None:

        self._fantasy_metric = fantasy_metric
        self._score = score

        return

    value = Immutable(lambda s: s._score)
    fantasy_metric = Immutable(lambda s: s._fantasy_metric)
    fantasy_metric_name = Immutable(lambda s: s._fantasy_metric.value)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(fantasy_metric=FantasyMetric.decode(
            data['fantasy_metric_name']),
                   score=data['score'])
Exemplo n.º 12
0
class Denomination(Decodable):
    def __init__(self, name: str, iso_4217: str, symbol: str) -> None:

        self._name = name
        self._iso_4217 = iso_4217
        self._symbol = symbol

        return

    name: str = Immutable(lambda s: s._name)
    iso_4217: str = Immutable(lambda s: s._iso_4217)
    symbol: str = Immutable(lambda s: s._symbol)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(name=data['name'],
                   iso_4217=data['iso_4217'],
                   symbol=data['symbol'])
Exemplo n.º 13
0
class Composition(Decodable):
    def __init__(self, position_requirements: List[PositionRequirement],
                 category_requirements: List[CategoryRequirement]) -> None:

        self._position_requirements = position_requirements
        self._category_requirements = category_requirements

        return

    position_requirements = Immutable(lambda s: s._position_requirements)
    category_requirements = Immutable(lambda s: s._category_requirements)
    unique_positions: List[str] = Immutable(
        lambda s: list(set(r.position for r in s._position_requirements)))

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(position_requirements=PositionRequirement.decode_many(
            data['position_requirements']),
                   category_requirements=CategoryRequirement.decode_many(
                       data['category_requirements']))
Exemplo n.º 14
0
class CommunicationMethod(Decodable):
    def __init__(self, public_id: str, mode: int, body: str,
                 confirmed: bool) -> None:

        self._public_id = public_id
        self._mode = mode
        self._body = body
        self._confirmed = confirmed

        return

    body = Immutable(lambda s: s._body)
    public_id = Immutable(lambda s: s._public_id)
    confirmed = Immutable(lambda s: s._confirmed)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(public_id=data['public_id'],
                   mode=data['mode'],
                   body=data['body'],
                   confirmed=data['confirmed'])
Exemplo n.º 15
0
class Offer(Decodable):

    _PATH = '/offer'

    def __init__(self, public_id: str, name: str, prices: List[Price],
                 products: List[Product], frequency: Frequency) -> None:

        self._public_id = public_id
        self._name = name
        self._prices = prices
        self._products = products
        self._frequency = frequency

        return

    public_id: str = Immutable(lambda s: s._public_id)
    name: str = Immutable(lambda s: s._name)
    prices: List[Price] = Immutable(lambda s: s._prices)
    products: List[Product] = Immutable(lambda s: s._products)
    features: List[str] = Immutable(lambda s: s._flatten_features())
    frequency: Frequency = Immutable(lambda s: s._frequency)
    price_map: Dict[str, Decimal] = Immutable(
        lambda s:
        {p.denomination.iso_4217: str(p.magnitude)
         for p in s._prices})

    def _flatten_features(self) -> List[str]:
        flat_features: List[str] = list()
        for product in self._products:
            for feature in product.features:
                flat_features.append(feature)
        return flat_features

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(public_id=data['public_id'],
                   name=data['name'],
                   prices=Price.decode_many(data['prices']),
                   products=Product.decode_many(data['products']),
                   frequency=Frequency(data['frequency']))

    @classmethod
    def retrieve(cls: Type[T], public_id: str, credentials: RequestCredentials,
                 configuration: Configuration) -> Optional[T]:

        parameters = URLParameters([URLParameter('offer', public_id)])

        request = ApiRequest(path=cls._PATH,
                             method=HTTPMethod.GET,
                             configuration=configuration,
                             data=None,
                             url_parameters=parameters,
                             credentials=credentials)

        return cls.optionally_decode(request.response_data)
Exemplo n.º 16
0
class Challenge(Decodable):

    _PATH = '/communication-method/challenge'

    def __init__(self, expiration: NozomiTime, completed: Optional[NozomiTime],
                 is_expired: bool, method_id: str) -> None:

        self._expiration = expiration
        self._is_expired = is_expired
        self._completed = completed
        self._method_id = method_id

        return

    is_completed: bool = Immutable(lambda s: s._completed is not None)
    is_expired: bool = Immutable(lambda s: s._is_expired)
    method_id: str = Immutable(lambda s: s._method_id)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(expiration=NozomiTime.decode(data['expiration']),
                   completed=NozomiTime.optionally_decode(data['completed']),
                   is_expired=data['is_expired'],
                   method_id=data['method_id'])

    @classmethod
    def retrieve(cls: Type[T], code: str, credentials: RequestCredentials,
                 configuration: Configuration) -> Optional[T]:

        parameters = URLParameters([URLParameter('code', code)])

        request = ApiRequest(path=cls._PATH,
                             method=HTTPMethod.GET,
                             configuration=configuration,
                             data=None,
                             url_parameters=parameters,
                             credentials=credentials)

        return cls.optionally_decode(request.response_data)
Exemplo n.º 17
0
class TeamSummary(Decodable):
    def __init__(self, manager_id: str, manager_name: str, team_name: str,
                 league_id: str) -> None:

        self._manager_id = manager_id
        self._manager_name = manager_name
        self._team_name = team_name
        self._league_id = league_id

        return

    manager_id = Immutable(lambda s: s._manager_id)
    manager_name = Immutable(lambda s: s._manager_name)
    team_name = Immutable(lambda s: s._team_name)
    league_id = Immutable(lambda s: s._league_id)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(manager_id=data['manager_public_id'],
                   manager_name=data['manager_name'],
                   league_id=data['league_public_id'],
                   team_name=data['team_name'])
Exemplo n.º 18
0
class CategoryRequirement(Decodable):

    def __init__(
        self,
        count: int,
        category: PositionCategory
    ) -> None:

        self._count = count
        self._category = category

        return

    count: int = Immutable(lambda s: s._count)
    category: PositionCategory = Immutable(lambda s: s._category)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(
            count=data['count'],
            category=PositionCategory.decode(data['category'])
        )
class FilledComposition:
    """
    A utility class coralling Composition and Player data into a combined unit.
    Useful on the client side for presentation purposes. There is no
    equivalent object in the Draft Sport API
    """
    def __init__(self, requirements: List[FilledRequirement]) -> None:

        self._requirements = requirements

        return

    requirements: List[FilledRequirement] = Immutable(
        lambda s: s._requirements)
Exemplo n.º 20
0
class Product(Decodable):
    def __init__(self, public_id: str, name: str, features: List[str]) -> None:

        self._public_id = public_id
        self._name = name
        self._features = features

        return

    features = Immutable(lambda s: s._features)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(public_id=data['public_id'],
                   name=data['name'],
                   features=data['features'])
class SecretResetRequest(Decodable):

    _PATH = '/human/secret-reset-request'

    def __init__(self, created: NozomiTime) -> None:

        self._created = created

        return

    created = Immutable(lambda s: s._created)

    @classmethod
    def decode(cls: Type[T], data: Any) -> None:
        return cls(created=NozomiTime.decode(data['created']))

    @classmethod
    def create(cls: Type[T], email_address: str,
               configuration: Configuration) -> T:

        target = URLParameter('email', email_address)
        parameters = URLParameters([target])

        request = ApiRequest(path=cls._PATH,
                             method=HTTPMethod.POST,
                             configuration=configuration,
                             url_parameters=parameters)

        return cls.decode(request.response_data)

    @classmethod
    def retrieve(cls: Type[T], reset_key: str,
                 configuration: Configuration) -> Optional[T]:

        target = URLParameter('reset-key', reset_key)
        parameters = URLParameters([target])

        request = ApiRequest(path=cls._PATH,
                             method=HTTPMethod.GET,
                             configuration=configuration,
                             url_parameters=parameters)

        return cls.optionally_decode(request.response_data)
Exemplo n.º 22
0
class Pick(Decodable):
    def __init__(self, created: NozomiTime, manager_id: str, profile: Profile,
                 league_id: str, as_at: NozomiTime) -> None:

        self._created = created
        self._manager_id = manager_id
        self._profile = profile
        self._league_id = league_id
        self._as_at = as_at

        return

    profile = Immutable(lambda s: s._profile)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(created=NozomiTime.decode(data['created']),
                   manager_id=data['manager_id'],
                   profile=Profile.decode(data['player']),
                   league_id=data['league_id'],
                   as_at=NozomiTime.decode(data['as_at']))
Exemplo n.º 23
0
class Points(Decodable):
    def __init__(self, average_points: int, total_points: int,
                 points_last_round: int, points_per_minute_played: int,
                 rounds: List[Round]) -> None:

        self._average_points = average_points
        self._total_points = total_points
        self._points_last_round = points_last_round
        self._points_per_minute_played = points_per_minute_played
        self._rounds = sorted(rounds, key=lambda r: r.round_sequence)

        self._cached_flattened_rounds: Optional[Dict[str, List[int]]] = None

        return

    average_points = Immutable(lambda s: s._average_points)
    total_points = Immutable(lambda s: s._total_points)
    points_last_round = Immutable(lambda s: s._points_last_round)
    points_per_minute_played = Immutable(lambda s: s._points_per_minute_played)
    rounds = Immutable(lambda s: s._rounds)

    normalised_rounds = Immutable(lambda s: s._compute_normalised_rounds())
    flattened_rounds = Immutable(lambda s: s._retrieved_flattened_rounds())

    _all_metric_keys = Immutable(lambda s: s._compute_all_metric_keys())

    def score_for_metric(self, metric: FantasyMetric,
                         in_round: Union[int, SemanticRound]) -> Optional[int]:

        if len(self._rounds) < 0:
            return None

        def compute_index(intention: Union[int, SemanticRound]) -> int:

            if isinstance(intention, SemanticRound):
                if intention == SemanticRound.LATEST:
                    return -1
                if intention == SemanticRound.FIRST:
                    return 0
                pass

            assert isinstance(intention, int)
            return intention

        rounds = sorted(self.rounds, key=lambda r: r.round_sequence)
        index = compute_index(in_round)

        if len(rounds) - 1 < index:
            return None

        target_round = rounds[index]
        return target_round.score_for_metric(metric)

    def _compute_all_metric_keys(self) -> List[str]:
        keys: Set[str] = set()
        for rou in self._rounds:
            for score in rou.scores:
                keys.add(score.fantasy_metric_name)
        return sorted(keys)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(points_per_minute_played=data['points_per_minute_played'],
                   average_points=data['average_points'],
                   total_points=data['total_points'],
                   points_last_round=data['points_last_round'],
                   rounds=Round.decode_many(data['rounds']))

    def _compute_normalised_rounds(self) -> List[Round]:

        all_keys = self._all_metric_keys

        def _scores_for_round(rou: Round) -> List[Score]:

            scores: List[Score] = list()

            for key in all_keys:

                found = False

                for score in rou.scores:
                    if score.fantasy_metric_name == key:
                        scores.append(score)
                        found = True
                        break

                if found is True:
                    break

                scores.append(
                    Score(fantasy_metric=FantasyMetric.decode(key), score=0))

            return sorted(scores, key=lambda s: s.fantasy_metric_name)

        rounds: List[Round] = list()

        for rou in self._rounds:

            rounds.append(
                Round(sequence=rou.round_sequence,
                      scores=_scores_for_round(rou)))

        return sorted(rounds, key=lambda r: r.round_sequence)

    def _retrieved_flattened_rounds(self) -> Dict[str, List[int]]:
        if self._cached_flattened_rounds is None:
            self._cached_flattened_rounds = self._compute_flattened_rounds()
        return self._cached_flattened_rounds

    def _compute_flattened_rounds(self) -> Dict[str, List[int]]:

        flat_rounds: Dict[str, List[int]] = dict()

        for key in self._all_metric_keys:

            metric_stats: List[int] = list()

            for rou in self._rounds:

                found = False

                for score in rou.scores:
                    if score.fantasy_metric_name == key:
                        metric_stats.append(score.value)
                        found = True
                        break
                    continue

                if found is True:
                    continue

                metric_stats.append(0)
                continue

            flat_rounds[key] = metric_stats

            continue

        return flat_rounds
Exemplo n.º 24
0
class FilledRequirement:
    """
    Utility class coralling Requirement & Player data. Useful for client
    presentation purposes. There is no equivalent object in the
    Draft Sport API
    """
    def __init__(self, requirement: Requirement, picks: List[Pick]) -> None:

        self._picks = picks
        self._requirement = requirement

        return

    picks = Immutable(lambda s: s._picks)
    name = Immutable(lambda s: s._compute_requirement_name())
    position_name = Immutable(lambda s: s._requirement.position_name)
    count = Immutable(lambda s: s._requirement.count)

    is_position: bool = Immutable(
        lambda s: isinstance(s._requirement, PositionRequirement))
    is_category: bool = Immutable(
        lambda s: isinstance(s._requirement, CategoryRequirement))
    is_plural: bool = Immutable(lambda s: s.count > 1)
    number_filled: int = Immutable(lambda s: len(s.picks))
    empty: bool = Immutable(lambda s: len(s.picks) < 1)
    satisfied: bool = Immutable(lambda s: len(s.picks) == s.count)
    not_satisfied: bool = Immutable(lambda s: not s.satisfied)

    def _compute_requirement_name(self) -> str:

        if isinstance(self._requirement, CategoryRequirement):
            name = self._requirement.category.name
            return name[0].upper() + name[1:].lower()

        if isinstance(self._requirement, PositionRequirement):
            return self._requirement.position_name

        raise TypeError
Exemplo n.º 25
0
class ScoreCard(Decodable, Encodable):

    _PATH = '/fantasy/score-card'
    _LIST_PATH = '/fantasy/score-card/list'

    def __init__(self, profile: Profile, season_id: str, limit: int,
                 offset: int, query_count: int, sequence: int,
                 requesting_agent_id: str, points: Points,
                 query_time: int) -> None:

        self._profile = profile
        self._season_id = season_id
        self._limit = limit
        self._offset = offset
        self._query_count = query_count
        self._sequence = sequence
        self._requesting_agent_id = requesting_agent_id
        self._points = points
        self._query_time = query_time

        return

    public_id = Immutable(lambda s: s._profile.public_id)

    profile = Immutable(lambda s: s._profile)
    season_id = Immutable(lambda s: s._season_id)
    limit = Immutable(lambda s: s._limit)
    offset = Immutable(lambda s: s._offset)
    query_count = Immutable(lambda s: s._query_count)
    sequence = Immutable(lambda s: s._sequence)
    requesting_agent_id = Immutable(lambda s: s._requesting_agent_id)
    points = Immutable(lambda s: s._points)
    query_time = Immutable(lambda s: s._query_time)

    query_time_seconds = Immutable(lambda s: str(int(s._query_time) / 1000000))

    def has_position_with_name(self, name: str) -> bool:
        """Return True if this Player has the named position"""
        return self._profile.position_name == name

    def has_position_in_category(self, category: PositionCategory) -> bool:
        """Return True if this Player has a position in the supplied category"""
        return category in self._profile.position.categories

    def encode(self) -> Dict[str, Any]:
        return {
            'player': self._profile.encode(),
            'limit': self._limit,
            'offset': self._offset,
            'sequence': self._sequence,
            'requesting_agent_id': self._requesting_agent_id,
            'points': self._points.encode(),
            'query_time': self._query_time,
            'query_count': self._query_coun
        }

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(profile=Profile.decode(data['player']),
                   season_id=data['fantasy_season_id'],
                   limit=data['limit'],
                   offset=data['offset'],
                   query_count=data['query_count'],
                   sequence=data['sequence'],
                   requesting_agent_id=data['requesting_agent_id'],
                   points=Points.decode(data['points']),
                   query_time=data['query_time'])

    @classmethod
    def retrieve(cls: Type[T], public_id: str, season: Season,
                 credentials: Optional[RequestCredentials],
                 configuration: Optional[Configuration]) -> Optional[T]:

        parameters = URLParameters([
            URLParameter('public_id', public_id),
            URLParameter('season', season.public_id)
        ])

        request = ApiRequest(path=cls._PATH,
                             method=HTTPMethod.GET,
                             data=None,
                             url_parameters=parameters,
                             credentials=credentials,
                             configuration=configuration)

        return cls.optionally_decode(request.response_data)

    @classmethod
    def retrieve_many(
            cls: Type[T],
            season: Season,
            offset: int,
            limit: int,
            configuration: Configuration,
            order_by: OrderBy = OrderBy.TOTAL_SEASON_POINTS,
            order: Order = Order.DESCENDING,
            name_fragment: Optional[str] = None,
            credentials: Optional[RequestCredentials] = None) -> List[T]:

        parameters = URLParameters([
            URLParameter('season', season.public_id),
            URLParameter('offset', offset),
            URLParameter('limit', limit),
            URLParameter('order_by', order_by.value),
            URLParameter('order', order.value)
        ])

        if name_fragment is not None:
            parameters.append(URLParameter('fragment', name_fragment))

        request = ApiRequest(path=cls._LIST_PATH,
                             method=HTTPMethod.GET,
                             data=None,
                             url_parameters=parameters,
                             credentials=credentials,
                             configuration=configuration)

        return cls.optionally_decode_many(request.response_data,
                                          default_to_empty_list=True)
Exemplo n.º 26
0
class Team(Decodable):

    _PATH = '/league/team'

    def __init__(self, league_id: str, picks: List[Pick], manager_id: str,
                 manager_display_name: str, name: Optional[str],
                 as_at: NozomiTime, as_at_round_sequence: int,
                 composition: Composition) -> None:

        self._league_id = league_id
        self._picks = picks
        self._manager_id = manager_id
        self._manager_display_name = manager_display_name
        self._name = name
        self._as_at = as_at
        self._as_at_round_sequence = as_at_round_sequence
        self._composition = composition

        return

    league_id = Immutable(lambda s: s._league_id)
    picks = Immutable(lambda s: s._picks)
    manager_id = Immutable(lambda s: s._manager_id)
    manager_display_name = Immutable(lambda s: s._manager_display_name)
    name = Immutable(lambda s: s._name)
    total_points = Immutable(lambda s: s._total_points)
    as_at = Immutable(lambda s: s._as_at)
    as_at_round_sequence = Immutable(lambda s: s._as_at_round_sequence)

    filled_composition = Immutable(lambda s: s._compute_filled_composition())

    def _compute_filled_composition(self) -> FilledComposition:

        filled_requirements: List[FilledRequirement] = list()

        remaining_picks = list(self._picks)

        for requirement in self._composition.position_requirements:

            picks_satisfying_requirement: List[Pick] = list()
            potential_picks = list(remaining_picks)

            for pick in potential_picks:

                if pick.score_card.has_position_with_name(
                        name=requirement.position_name):
                    picks_satisfying_requirement.append(pick)
                    remaining_picks.remove(pick)

                continue

            filled_requirements.append(
                FilledRequirement(requirement=requirement,
                                  picks=picks_satisfying_requirement))

            continue

        for category_requirement in self._composition.category_requirements:

            picks_satisfying_requirement: List[Pick] = list()
            potential_picks = list(remaining_picks)

            for pick in potential_picks:
                if pick.score_card.has_position_in_category(
                        category=category_requirement.category):
                    picks_satisfying_requirement.append(pick)
                    remaining_picks.remove(pick)

                continue

            filled_requirements.append(
                FilledRequirement(requirement=category_requirement,
                                  picks=picks_satisfying_requirement))

            continue

        return FilledComposition(requirements=filled_requirements)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(league_id=data['league_id'],
                   picks=Pick.decode_many(data['picks']),
                   manager_id=data['manager_id'],
                   manager_display_name=data['manager_display_name'],
                   name=data['name'],
                   as_at=NozomiTime.decode(data['as_at']),
                   as_at_round_sequence=data['as_at_round_sequence'],
                   composition=Composition.decode(data['composition']))

    @classmethod
    def retrieve(cls: Type[T],
                 league_id: str,
                 manager_id: str,
                 credentials: RequestCredentials,
                 configuration: Configuration,
                 as_at_round: Optional[int] = None) -> Optional[T]:
        """
        Return a Team in the supplied League, managed by the supplied Manager,
        if it exists.
        """

        parameters = [
            URLParameter('league', league_id),
            URLParameter('manager', manager_id)
        ]

        if as_at_round:
            parameters.append(URLParameter('as_at_round', as_at_round))

        request = ApiRequest(path=cls._PATH,
                             method=HTTPMethod.GET,
                             configuration=configuration,
                             data=None,
                             url_parameters=URLParameters(parameters),
                             credentials=credentials)

        return cls.optionally_decode(request.response_data)
Exemplo n.º 27
0
class Season(Decodable):

    _PATH = '/fantasy/season'
    _LIST_PATH = '/fantasy/season/list'

    def __init__(self, public_id: str, name: str, start_date: NozomiDate,
                 competition: Competition) -> None:

        self._public_id = public_id
        self._name = name
        self._start_date = start_date
        self._competition = competition

        return

    public_id = Immutable(lambda s: s._public_id)
    name = Immutable(lambda s: s._name)
    start_date = Immutable(lambda s: s._start_date)
    competition = Immutable(lambda s: s._competition)

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        return cls(public_id=data['public_id'],
                   name=data['name'],
                   start_date=NozomiDate.decode(data['start_date']),
                   competition=Competition.decode(data['competition']))

    @classmethod
    def retrieve(
            cls: Type[T],
            public_id: str,
            configuration: Configuration,
            credentials: Optional[RequestCredentials] = None) -> Optional[T]:

        if not isinstance(public_id, str):
            raise TypeError('public_id must be of type `str`')

        parameters = URLParameters([URLParameter('public_id', public_id)])

        request = ApiRequest(path=cls._PATH,
                             method=HTTPMethod.GET,
                             data=None,
                             url_parameters=parameters,
                             credentials=credentials,
                             configuration=configuration)

        return cls.optionally_decode(request.response_data)

    @classmethod
    def retrieve_list(
            cls: Type[T],
            configuration: Configuration,
            credentials: Optional[RequestCredentials] = None) -> List[T]:

        request = ApiRequest(path=cls._LIST_PATH,
                             method=HTTPMethod.GET,
                             data=None,
                             url_parameters=None,
                             credentials=credentials,
                             configuration=configuration)

        return cls.optionally_decode_many(request.response_data,
                                          default_to_empty_list=True)
Exemplo n.º 28
0
class Session(NozomiAppSession):

    API_PATH = '/session'

    def __init__(self, session_id: str, session_key: str, api_key: str,
                 agent: Agent, created: NozomiTime, last_utilised: NozomiTime,
                 perspective: Perspective, requires_challenge: bool,
                 has_completed_challenge: bool) -> None:

        assert isinstance(session_id, str)
        assert isinstance(session_key, str)
        assert isinstance(api_key, str)
        assert isinstance(agent, Agent)
        assert isinstance(created, NozomiTime)
        assert isinstance(last_utilised, NozomiTime)
        assert isinstance(perspective, Perspective)
        assert isinstance(requires_challenge, bool)
        assert isinstance(has_completed_challenge, bool)

        self._session_id = session_id
        self._session_key = session_key
        self._api_key = api_key
        self._agent = agent
        self._created = created
        self._last_utilised = last_utilised
        self._perspective = perspective
        self._requires_challenge = requires_challenge
        self._has_completed_challenge = has_completed_challenge

        return

    agent: Agent = Immutable(lambda s: s._agent)
    perspective: Perspective = Immutable(lambda s: s._perspective)
    api_key: str = Immutable(lambda s: s._api_key)
    session_id: int = Immutable(lambda s: s._session_id)
    has_completed_challenge: bool = Immutable(
        lambda s: s._has_completed_challenge)
    requires_challenge: bool = Immutable(lambda s: s._requires_challenge)

    agent_id = Immutable(lambda s: s._agent.agent_id)

    def delete(self, credentials: RequestCredentials,
               configuration: Configuration) -> None:
        """Delete this Session, AKA logout the user"""
        target = URLParameter('session_id', str(self._session_id))
        parameters = URLParameters([target])

        ApiRequest(path=self.API_PATH,
                   method=HTTPMethod.DELETE,
                   configuration=configuration,
                   credentials=credentials,
                   data=None,
                   url_parameters=parameters)
        return None

    @classmethod
    def retrieve(cls: Type[T], session_id: str,
                 credentials: RequestCredentials,
                 configuration: Configuration) -> Optional[T]:
        """Return a Session with the given Session ID, if it exists"""

        assert isinstance(session_id, str)

        target = URLParameter('session_id', str(session_id))
        parameters = URLParameters([target])

        request = ApiRequest(path=cls.API_PATH,
                             method=HTTPMethod.GET,
                             configuration=configuration,
                             credentials=credentials,
                             data=None,
                             url_parameters=parameters)

        if request.response_data is None:
            return None

        return cls.decode(request.response_data)

    @classmethod
    def create(cls: Type[T], email: str, secret: str,
               configuration: Configuration) -> T:

        data = {'email': email, 'secret': secret}

        raise NotImplementedError

    @classmethod
    def decode(cls: Type[T], data: Any) -> T:
        """Return a Session decoded from API response data"""

        return cls(data['session_id'],
                   data['session_key'],
                   data['api_key'],
                   StandaloneAgent.decode(data),
                   NozomiTime.decode(data['created']),
                   NozomiTime.decode(data['last_utilised']),
                   Perspective.with_id(data['perspective']),
                   requires_challenge=data['requires_challenge'],
                   has_completed_challenge=data['has_completed_challenge'])