coc.py icon indicating copy to clipboard operation
coc.py copied to clipboard

Support for Builder Base & Clan Capital clan rank events

Open bobflem opened this issue 2 years ago • 3 comments

Currently, we can track changes in the main base clan leaderboard sorted by trophies using ClanEvents.member_clan_rank(). I would like to be able to track changes to builder base and clan capital leaderboards as well.

bobflem avatar Sep 15 '22 01:09 bobflem

there is no information in the clan response about the member rank for other sorting except the normal trophies. That would mean you would have to sort the list of members yourself for the versus trophies and then get the index of your player.

For the clan capital, you would have request every players detail and sort them based on their contributions, but be aware that this number isnt the contributions only in this clan. So in my opinion sorting by clan capital contribution is kind of useless.

doluk avatar Sep 15 '22 07:09 doluk

@mathsman5133 @majordoobie what do you think would be the best way to implement a builder base rank? I think the one way would be to add the vs_rank before initializing the self._iter_members. So instead of directly passing the list of the response to the init function, we add the vs_ranking attribute to every member. -> Downside would be that it isn't very flexible and for most users completely irrelevant. The other way I can see, is to add like a get_ranking('ClanMember.attribute',ascending=True) function to the Clan object. This would allow everyone to get the ranking for whatever attribute they want. -> Downside would be that it isn't that compatible with the events.

What are your thoughts about this?

doluk avatar Sep 15 '22 08:09 doluk

Hmmm. Since this is very easy to create, it only really makes sense for events. But even though I love the builder base, I don't think that it makes sense to add such an attribute to the default player object that would overall barely be used by most people.

If that is possible, my preferred solution would be a new example in the docs where such an event is implemented using a custom player class.

Kuchenmampfer avatar Sep 18 '22 11:09 Kuchenmampfer

Alright, I tried to implement versus clan rank events using custom classes. Here is my code:

import coc


class CustomClan(coc.Clan):
    def __init__(self, *, data, client, **_):
        super().__init__(data=data, client=client)
        self.member_cls = CustomMember

        # update members globally. only available via /clans/{clanTag}
        member_cls = self.member_cls
        member_data = data.get("memberList", [])
        for rank, mdata in enumerate(sorted(member_data, key=lambda x: x["versusTrophies"], reverse=True), 1):
            mdata["versusRank"] = rank
        self._iter_members = (
            member_cls(data=mdata, client=self._client, clan=self) for mdata in member_data
        )


class CustomMember(coc.ClanMember):
    def __init__(self, *, data, client, clan=None, **_):
        super().__init__(data=data, client=client, clan=clan, **_)
        self.clan_cls = CustomClan
        self.versus_rank = data.get("versusRank")


async def events(coc_client):

    @coc_client.event
    @coc.ClanEvents.member_versus_rank(['#RLCC2VLL'], custom_class=CustomClan)
    async def clan_versus_rank(old_member, new_member):
        print(f'{new_member.name} changed versus clan rank from {old_member.versus_rank} to {new_member.versus_rank}')

Sadly this did not work with stock coc.py. For it to work, I needed to add the following two lines of code to the ClanEvents class in events.pyi:

    @classmethod
    def member_versus_rank(cls, tags: Iterable = None, custom_class: _ClanType = Clan, retry_interval: int = None) -> _EventDecoratorReturn: ...

Kuchenmampfer avatar Jan 25 '23 23:01 Kuchenmampfer

Just adding these two lines is not possible because that would give people type hinting for something that does not work with the default classes. So in my eyes the only option to support this is adding a versus_rank attribute to the ClanMember class like I did here. Even though this is irrelevant for most people, I would be up to do that.

Kuchenmampfer avatar Jan 25 '23 23:01 Kuchenmampfer

capital_rank sadly is not possible because the clan endpoint for whatever reason provides information on how members decorated their capital player house, but not their capital gold donations.

Kuchenmampfer avatar Jan 25 '23 23:01 Kuchenmampfer

I just implemented the member_versus_rank event here: https://github.com/mathsman5133/coc.py/commit/377ef8bd628ba9e58d4b715e63e6c9ef6c9a65bd

Kuchenmampfer avatar Jan 26 '23 17:01 Kuchenmampfer