this is the client api main  client.py script "from typing import (
    Optional, List, Union
)
import string
import random
import time
import httpx
import asyncio
from .f_types import (
    DScaffold,
    APIResponse,
    AttackCardInfo,
    BattleRequest,
    BattleResponse,
    CardsSelection,
    CardInfo,
    CoolOffRequest,
    CoolOffResponse,
    DeviceConstants,
    DeviceConstantsRequest,
    ErrorMessages,
    ErrorMessagesRequest,
    FillPotionRequest,
    FillPotionResponse,
    FruitCardInfo,
    FruitExportContainer,
    FruitJsonExportRequest,
    GetOpponentsRequest,
    GetOpponentsResponse,
    GetPlayerInfoRequest,
    GetPlayerInfoResponse,
    GlobalRankingsRequest,
    GlobalRankingsResponse,
    LanguagePatchRequest,
    LanguagePathResponse,
    LeagueRankingsRequest,
    LeagueRankingsResponse,
    LeagueWinnerRanges,
    LiveBattleHelpRequest,
    LiveBattleHelpResponse,
    LiveBattleRequest,
    LiveBattleResponse,
    new_int_array,
    PlayerComebackRequest,
    PlayerComebackResponse,
    PlayerLoadRequest,
    PlayerLoadResponse,
    PotionizeRequest,
    PotionizeResponse,
    QuestRequest,
    QuestResponse,
    SetCardForLiveBattleRequest,
    SetCardForLiveBattleResponse,
    TribeMembersRequest,
    TribeMembersResponse,
    TribeRankingsRequest,
    TribeRankingsResponse,
    CollectGoldRequest,
    CollectGoldResponse,
    EvolveCardRequest,
    EvolveCardResponse,
)
from .f_types.utils import (
    xor_decrypt,
    choose_strongest_atk_ids,
    choose_strongest_atk_id,
    hash_q_string,
)
from .f_types.errors import (
    UnknownError,
    PlayerLoadException,
    FruitServerException,
)
import inspect
import json
import logging

_MAX_PASSPORT_LENGTH = 32

class FruitCraftClient():
    passport: str = ""
    http_client: httpx.AsyncClient = None
    cool_off_sleep_time: Optional[int] = None
    attacks_today: int = 0
    
    last_loaded_player: PlayerLoadResponse = None
    last_battle_request: BattleRequest = None
    login_options: PlayerLoadRequest = None
    cached_errors: ErrorMessages = None
    
    log_player_id_before_atk: bool = False
    log_before_resp_parsing: bool = False
    log_before_req_sending: bool = False
    last_q_value: str = ""
    logger: logging.Logger = None
    mut: asyncio.Lock = None
    _default_url = "\u0068\u0074\u0074\u0070\u003a\u002f\u002f\u0069\u0072\u0061\u006e\u002e\u0066\u0072\u0075\u0069\u0074\u0063\u0072\u0061\u0066\u0074\u002e\u0069\u0072"
    _serialize_key: str = None
    _error_codes_to_sleep = { # times are in seconds
        156: 4,
        124: 2,
        184: 2,
    }
    _max_login_tries: int = 50

    def __init__(self, passport: str = None):
        if not passport:
            passport = FruitCraftClient.generate_passport()
        
        self.mut = asyncio.Lock()
        self.http_client = httpx.AsyncClient()
        self.passport = passport
        if not self.logger:
            self.logger = logging.getLogger(__name__)
    
    async def evolve_card(self, sacrifices: Union[CardsSelection, int]) -> EvolveCardResponse:
        if isinstance(sacrifices, int):
            sacrifices = new_int_array([sacrifices])
        
        return await self.evolve_card_with_options(EvolveCardRequest(
            sacrifices=sacrifices,
        ))
    
    async def evolve_card_with_options(self, opt: EvolveCardRequest) -> EvolveCardResponse:
        api_response: APIResponse = await self.send_and_parse(
            "cards/evolve", opt, EvolveCardResponse)
        return api_response.data
    
    async def collect_gold(self) -> CollectGoldResponse:
        return await self.collect_gold_with_options(CollectGoldRequest())
    
    async def collect_gold_with_options(self, opt: CollectGoldRequest) -> CollectGoldResponse:
        opt.set_default_values()
        
        api_response: APIResponse = await self.send_and_parse(
            "cards/collectgold", opt, CollectGoldResponse)
        return api_response.data
    
    async def get_player_info(self, player_id: int) -> GetPlayerInfoResponse:
        return await self.get_player_info_with_options(GetPlayerInfoRequest(player_id=player_id))
    
    async def get_player_info_with_options(self, opt: GetPlayerInfoRequest) -> GetPlayerInfoResponse:
        api_response: APIResponse = await self.send_and_parse(
            "player/getplayerinfo", opt, GetPlayerInfoResponse)
        return api_response.data
    
    async def potionize(self, hero_id: int, amount: int) -> PotionizeResponse:
        return await self.potionize_with_options(PotionizeRequest(potion=amount, hero_id=hero_id))
    
    async def potionize_with_options(self, opt: PotionizeRequest) -> PotionizeResponse:
        api_response: APIResponse = await self.send_and_parse(
            "cards/potionize", opt, PotionizeResponse)
        
        player_potion = getattr(api_response.data, "player_potion", None)
        if player_potion != None and isinstance(player_potion, int):
            self.last_loaded_player.potion_number = player_potion
        
        return api_response.data
    
    async def fill_potions(self, amount: int = None) -> FillPotionResponse:
        return await self.fill_potions_with_options(FillPotionRequest(amount=amount))
    
    async def fill_potions_with_options(self, opt: FillPotionRequest) -> FillPotionResponse:
        if not opt.amount and self.last_loaded_player:
            opt.amount = 50 - self.last_loaded_player.potion_number
            
            if not opt.amount:
                return FillPotionResponse(potion_number=self.last_loaded_player.potion_number)
        
        api_response: APIResponse = await self.send_and_parse(
            "player/fillpotion", opt, FillPotionResponse)
        
        fill_result = api_response.data
        if not isinstance(fill_result, FillPotionResponse):
            return None
        
        if self.last_loaded_player:
            self.last_loaded_player.potion_number = fill_result.potion_number
        
        return api_response.data
    
    async def get_league_rankings(self) -> LeagueRankingsResponse:
        return await self.get_league_rankings_with_options(LeagueRankingsRequest())
    
    async def get_league_rankings_with_options(self, opt: LeagueRankingsRequest) -> LeagueRankingsResponse:
        opt.set_default_values()
        
        api_response: APIResponse = await self.send_and_parse(
            "ranking/league", opt, LeagueRankingsResponse)
        return api_response.data
    
    async def get_global_rankings(self) -> GlobalRankingsResponse:
        return await self.get_global_rankings_with_options(GlobalRankingsRequest())
    
    async def get_global_rankings_with_options(self, opt: GlobalRankingsRequest) -> GlobalRankingsResponse:
        opt.set_default_values()
        
        api_response: APIResponse = await self.send_and_parse(
            "ranking/global", opt, GlobalRankingsResponse)
        return api_response.data
    
    async def get_tribe_rankings(self) -> TribeRankingsResponse:
        return await self.get_tribe_rankings_with_options(TribeRankingsRequest())
    
    async def get_tribe_rankings_with_options(self, opt: TribeRankingsRequest) -> TribeRankingsResponse:
        opt.set_default_values()
        
        api_response: APIResponse = await self.send_and_parse(
            "ranking/tribe", opt, TribeRankingsResponse)
        return api_response.data
    
    async def live_battle_help(self, battle_id: int) -> bool:
        return await self.live_battle_help_with_options(LiveBattleHelpRequest(
            battle_id=battle_id,
        ))
    
    async def live_battle_help_with_options(self, opt: LiveBattleHelpRequest) -> bool:
        api_response: APIResponse = await self.send_and_parse(
            "live-battle/help", opt, LiveBattleHelpResponse)
        return api_response.status
    
    async def set_card_for_live_battle(self, opt: SetCardForLiveBattleRequest) -> SetCardForLiveBattleResponse:
        api_response: APIResponse = await self.send_and_parse(
            "live-battle/setcardforlivebattle", opt, SetCardForLiveBattleResponse)
        return api_response.data
    
    async def do_live_battle(self, opponent_id: int) -> LiveBattleResponse:
        return await self.do_live_battle_with_options(LiveBattleRequest(
            opponent_id=opponent_id,
        ))
    
    async def do_live_battle_with_options(self, opt: LiveBattleRequest) -> LiveBattleResponse:
        if not isinstance(opt.opponent_id, int) and opt.opponent_id != None:
            tmp_id = getattr(opt.opponent_id, "id", None)
            if isinstance(tmp_id, int):
                opt.opponent_id = tmp_id
        
        api_response: APIResponse = await self.send_and_parse(
            "live-battle/livebattle", opt, LiveBattleResponse)
        return api_response.data
    
    def set_cool_off_sleep_amount(self, sleep_amount: int) -> None:
        self.cool_off_sleep_time = sleep_amount
    
    async def heal_all(self, cards: CardsSelection) -> List[CoolOffResponse]:
        return await self.heal_all_with_ids(*cards.cards)
    
    async def heal_all_with_ids(self, *card_ids) -> List[CoolOffResponse]:
        results = []
        for current_id in card_ids:
            try:
                results.append(await self.cool_off(current_id))
            except Exception as ex:
                self.logger.warning(f"failed to heal card {current_id}: {ex}")
            
            if self.cool_off_sleep_time:
                await asyncio.sleep(self.cool_off_sleep_time)
        
        return results
    
    async def cool_off(self, card_id: int) -> CoolOffResponse:
        return await self.cool_off_with_options(
            CoolOffRequest(
                card_id=card_id,
            )
        )
    
    async def cool_off_with_options(self, opt: CoolOffRequest) -> CoolOffResponse:
        api_response: APIResponse = await self.send_and_parse("cards/cooloff", opt, CoolOffResponse)
        return api_response.data
    
    async def do_battle_and_heal(self, opponent_id: int, cards: CardsSelection) -> BattleResponse:
        battle_result = await self.do_battle(opponent_id=opponent_id, cards=cards)
        await self.heal_all(cards=cards)
        return battle_result
    
    async def do_battle(self, opponent_id: int, cards: CardsSelection) -> BattleResponse:
        return await self.do_battle_with_options(
            BattleRequest(
                cards=new_int_array(cards.cards),
                _cards_selection=cards,
                hero_id=cards.hero_id,
                opponent_id=opponent_id,
            )
        )
    
    async def do_battle_with_options(self, opt: BattleRequest) -> BattleResponse:
        await self.mut.acquire()
        
        try:
            resp = await self.__do_battle_with_options(opt)
            self.mut.release()
            return resp
        except Exception as e:
            # just don't forget to release the lock in case an exception occurs
            # because it's going to become a headache later on.
            self.mut.release()
            raise e
    
    async def __do_battle_with_options(self, opt: BattleRequest) -> BattleResponse:
        if self.last_q_value:
            opt.check = hash_q_string(self.last_q_value)
        
        opt._cards_selection
        
        api_response: APIResponse = await self.send_and_parse("battle/battle", opt, BattleResponse)
        if isinstance(api_response.data, BattleResponse):
            if api_response.data.q:
                self.last_q_value = str(api_response.data.q)
            
            return api_response.data
    
    async def get_opponents_from_others(self, other_pass: str) -> GetOpponentsResponse:
        return await self.get_opponents_with_options(GetOpponentsRequest(_other_pass=other_pass))
    
    async def get_opponents(self) -> GetOpponentsResponse:
        return await self.get_opponents_with_options(GetOpponentsRequest())
    
    async def get_opponents_with_options(self, opt: GetOpponentsRequest) -> GetOpponentsResponse:
        api_response: APIResponse = await self.send_and_parse("battle/getopponents", opt, GetOpponentsResponse)
        return api_response.data
    
    async def get_tribe_members(self) -> TribeMembersResponse:
        return await self.get_tribe_members_with_options(TribeMembersRequest())
    
    async def get_tribe_members_with_options(self, opt: TribeMembersRequest) -> TribeMembersResponse:
        api_response: APIResponse = await self.send_and_parse("tribe/members", opt, TribeMembersResponse)
        return api_response.data
    
    async def player_comeback(self) -> bool:
        return await self.player_comeback_with_options(PlayerComebackRequest())
    
    async def player_comeback_with_options(self, opt: PlayerComebackRequest) -> bool:
        opt.set_default_values()
        
        api_response: APIResponse = await self.send_and_parse("player/comeback", opt, PlayerComebackResponse)
        return api_response.status
    
    async def fruits_json_export(self) -> LanguagePathResponse:
        return await self.fruits_json_export_with_options(FruitJsonExportRequest())
    
    async def fruits_json_export_with_options(self, opt: FruitJsonExportRequest) -> FruitExportContainer:
        opt.set_default_values()
        
        api_response: APIResponse = await self.send_and_parse("cards/fruitsjsonexport", opt, FruitExportContainer)
        return api_response.data
    
    async def get_language_patch(self) -> LanguagePathResponse:
        return await self.get_language_patch_with_options(LanguagePatchRequest())
    
    async def get_language_patch_with_options(self, opt: LanguagePatchRequest) -> LanguagePathResponse:
        opt.set_default_values()
        
        api_response: APIResponse = await self.send_and_parse("player/languagepatch", opt, LanguagePathResponse)
        return api_response.data
    
    async def get_error_messages(self) -> ErrorMessages:
        return await self.get_error_messages_with_options(ErrorMessagesRequest())
    
    async def get_error_messages_with_options(self, opt: ErrorMessagesRequest) -> ErrorMessages:
        opt.set_default_values()
        
        api_response: APIResponse = await self.send_and_parse("error/messages", opt, ErrorMessages)
        return api_response.data
    
    async def get_device_constants(self) -> DeviceConstants:
        return await self.get_device_constants_with_options(DeviceConstantsRequest())
    
    async def get_device_constants_with_options(self, opt: DeviceConstantsRequest) -> DeviceConstants:
        opt.set_default_values()
        api_response: APIResponse = await self.send_and_parse("device/constants", opt, DeviceConstants)
        return api_response.data
    
    async def do_quest(self, cards: CardsSelection) -> QuestResponse:
        return await self.do_quest_with_options(
            QuestRequest(
                cards=new_int_array(cards.cards),
                _cards_selection=cards,
                hero_id=cards.hero_id,
            )
        )
    
    async def do_quest_with_options_str(self, value: str) -> QuestResponse:
        j_value = json.loads(value)
        the_req = QuestRequest(**j_value)
        return await self.do_quest_with_options(the_req)
    
    async def do_quest_with_hash(self, the_hash: str, *cards) -> QuestResponse:
        return await self.do_quest_with_options(
            QuestRequest(
                cards=new_int_array(list(cards)),
                check=the_hash,
            )
        )
    
    async def do_quest_with_options(self, opt: QuestRequest) -> QuestResponse:
        await self.mut.acquire()
        
        try:
            resp = await self.__do_quest_with_options(opt)
            self.mut.release()
            return resp
        except Exception as e:
            # just don't forget to release the lock in case an exception occurs
            # because it's going to become a headache later on.
            self.mut.release()
            raise e
    
    async def __do_quest_with_options(self, opt: QuestRequest) -> QuestResponse:
        if self.last_q_value:
            opt.check = hash_q_string(self.last_q_value)
        
        opt._cards_selection
        
        api_response: APIResponse = await self.send_and_parse("battle/quest", opt, QuestResponse)
        if isinstance(api_response.data, QuestResponse):
            if api_response.data.q:
                self.last_q_value = str(api_response.data.q)
            
            return api_response.data
    
    def get_strongest_cards(self) -> CardsSelection:
        if not self.last_loaded_player:
            raise Exception("No player loaded")
        
        cards = choose_strongest_atk_ids(4, *self.last_loaded_player.cards)
        
        if self.last_loaded_player.hero_id_set:
            hero_id = choose_strongest_atk_id(*self.last_loaded_player.hero_id_set)
            if hero_id:
                cards.append(hero_id)
        
        return CardsSelection(
            cards=cards,
            hero_id=hero_id,
        )
    
    
    def get_level1_card(self) -> CardsSelection:
        final_card: AttackCardInfo = None
        final_since: int = 0
        
        for current in self.last_loaded_player.cards:
            if current.power > 40:
                continue
            
            my_since = time.time() - current.internal_last_time_used
            if my_since < 16:
                continue
            
            if not final_card:
                final_card = current
                continue
            
            if my_since > final_since:
                final_card = current
                final_since = my_since
        
        if not final_card:
            return None
        
        final_card.set_as_used()
        return CardsSelection(
            cards=[final_card.id],
            no_heal=True,
        )
        
    
    def get_weakest_card(self) -> CardsSelection:
        if not self.last_loaded_player:
            raise Exception("No player loaded")
        
        level1_selection = self.get_level1_card()
        if level1_selection:
            return level1_selection
        
        target_card = self.last_loaded_player.cards[0]
        for current_card in self.last_loaded_player.cards:
            if current_card.power < target_card.power:
                target_card = current_card
                
        return CardsSelection(
            cards=[target_card.id],
        )
    
    async def load_player(
        self, 
        restore_key: str, 
        game_version: str = "", 
        uid: str = "",
        os_type: int = 0,
        os_version: str = "",
        phone_model: str = "",
        metrix_uid: str = "",
        apps_flyer_uid: str = "",
        device_name: str = "",
        store_type: str = "",
    ) -> PlayerLoadResponse:
        return await self.load_player_with_options(
            PlayerLoadRequest(
                game_version=game_version,
                udid=uid,
                os_type=os_type,
                restore_key=restore_key,
                os_version=os_version,
                model=phone_model,
                metrix_uid=metrix_uid,
                appsflyer_uid=apps_flyer_uid,
                device_name=device_name,
                store_type=store_type,
            )
        )
    
    async def load_player_with_options(self, opt: PlayerLoadRequest) -> PlayerLoadResponse:
        await self.mut.acquire()
        opt.set_default_values()
        
        try:
            self.login_options = opt
            resp = await self.__load_player_with_options(opt)
            self.mut.release()
            return resp
        except Exception as e:
            # just don't forget to release the lock in case an exception occurs
            # because it's going to become a headache later on.
            self.mut.release()
            raise e
    
    """
        Unsafe way of loading the player, please use the `load_player_with_options` method instead.
    """
    async def __load_player_with_options(self, opt: PlayerLoadRequest) -> PlayerLoadResponse:
        current_tries = 0
        while True:
            api_response: APIResponse = await self.send_and_parse(
                "player/load", opt, PlayerLoadResponse, no_err_handling=True)
            if api_response.data != None and self.is_sim_err_code(getattr(api_response.data, "code", None)):
                if current_tries > self._max_login_tries:
                    raise PlayerLoadException("Max login tries reached", api_response.data)
                
                sleep_amount: int = self._error_codes_to_sleep[getattr(api_response.data, "code")]
                self.logger.warning("player/load: sleeping for %i seconds", sleep_amount)
                await asyncio.sleep(sleep_amount)
                current_tries += 1
                
                # this might actually fix it.
                try:
                    await self.player_comeback()
                except: pass
                 
                continue
            
            break
        
        load_response = api_response.data
        if not isinstance(load_response, PlayerLoadResponse):
            raise PlayerLoadException("Unknown error occurred", api_response.data)
        
        self.login_options = opt
        self.last_q_value = str(load_response.q)
        self.last_loaded_player = load_response
        return load_response
            
        
    def is_sim_err_code(self, value: int) -> bool:
        if not value or not isinstance(value, int):
            return False

        return value in self._error_codes_to_sleep
    
    def set_login_options_str(self, value: str) -> PlayerLoadRequest:
        j_value = json.loads(value)
        
        load_req: PlayerLoadRequest = PlayerLoadRequest(**j_value)
        self.set_login_options(load_req)
        return load_req
    
    def set_login_options(self, login_options: PlayerLoadRequest) -> None:
        self.login_options = login_options
    
    def set_as_load_response(self, value: str) -> PlayerLoadResponse:
        j_value = json.loads(value)
        if not j_value or not j_value['status']:
            raise UnknownError(f"Unknown error occurred", value)
        
        loaded_response: PlayerLoadResponse = PlayerLoadResponse(**j_value['data'])
        self.set_as_player_loaded_value(loaded_response)
        return loaded_response
    
    def set_as_player_loaded_value(self, loaded_value: PlayerLoadResponse):
        self.last_loaded_player = loaded_value

    async def get_error_by_code(self, req_path: str, error_code: int, response: str = None) -> Exception:
        if not self.cached_errors:
            self.cached_errors = await self.get_error_messages()
        
        return FruitServerException(
            req_path=req_path, 
            error_code=error_code,
            message=self.cached_errors[str(error_code)],
            response=response
        )

    async def send_and_parse(
        self,
        req_path: str,
        req_data: DScaffold,
        return_type: type = None,
        no_err_handling: bool = False
    ) -> APIResponse:
        serialized_data = req_data.get_serialized(self._serialize_key)
        
        parser_method = getattr(req_data, 'parse_response', None)
        if not return_type and not parser_method:
            return None

        target_pass = getattr(req_data, "_other_pass", None)
        if not target_pass:
            target_pass = self.passport

        respond_bytes = await self.invoke_request(path=req_path, data=serialized_data, the_pass=target_pass)
        if parser_method and inspect.ismethod(parser_method):
            return parser_method(respond_bytes)
        
        if self.log_before_resp_parsing:
            print(f"Response: {respond_bytes}")
        
        the_err = None
        respond_decrypted = xor_decrypt(respond_bytes)
        j_value = json.loads(respond_decrypted)
        if not j_value or not j_value['status']:
            if j_value['data']['code'] != 0:
                the_err = await self.get_error_by_code(
                    req_path=req_data,
                    error_code=j_value['data']['code'],
                    response=respond_bytes,
                )
                
                if not no_err_handling and isinstance(the_err, Exception):
                    raise the_err
                    
            if not no_err_handling:
                raise UnknownError(f"Unknown error occurred for {req_path}", respond_bytes)
        
        api_response: APIResponse = APIResponse(j_value)
        api_response.the_err = the_err
        response_data = j_value['data']
        if return_type:
            api_response.data = return_type(**response_data)
        
        return api_response
        

    async def invoke_request(self, path: str, data: str, the_pass: str) -> bytes:
        data_value = f'edata={data}'.encode('utf-8')
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
            'Content-Length': str(len(data_value)),
            'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 7.1.2; google Pixel 2 Build/LMY47I)',
            'Host': 'iran.fruitcraft.ir'
        }

        if the_pass == "":
            the_pass = self.passport

        if the_pass != "" and the_pass != "none" and the_pass != "null":
            headers['Cookie'] = f"\u0046\u0052\u0055\u0049\u0054\u0050\u0041\u0053\u0053\u0050\u004f\u0052\u0054={the_pass};"

        response = await self.http_client.post(f"{self._default_url}/{path}", data=data_value, headers=headers)
        response.raise_for_status()
        return response.content
        
    async def aclose(self):
        try:
            return await self.http_client.aclose()
        except: pass
    
    @staticmethod
    def generate_passport() -> str:
        return ''.join(random.choices("abcdef0123456789", k=_MAX_PASSPORT_LENGTH))
    " and this is __init__.py from f_types "from pydantic import BaseModel
from .utils import xor_encrypt
from .cards import all_cards
from typing import (
    Any, List, Dict, Optional
)
import time
import random

class IntArray(str):
    pass

def get_all_cards() -> dict: return all_cards

LeagueWinnerRanges = Dict[str, int]

class LoadRequestDefaults:
	DEFAULT_GAME_VERSION      = "1.9.10691"
	DEFAULT_OS_TYPE           = 2
	DEFAULT_OS_VERSION        = "7.1.2"
	DEFAULT_PHONE_MODEL       = "google pixel 2"
	DEFAULT_METRIX_UID        = "-"
	DEFAULT_APPS_FLYER_UID     = "1686402669312-333768616178664406"
	DEFAULT_DEVICE_NAME       = "unknown"
	DEFAULT_CONSTANTS_VERSION = "142"
	DEFAULT_STORE_TYPE        = "myket"
	DEFAULT_CLIENT_VALUE      = "iOS"
	DEFAULT_LANG_VALUE        = "fa-IR"

def new_int_array(values: List[Any]) -> IntArray:
    output = "["
    for i, current in enumerate(values):
        output += str(current)

        if i != len(values)-1:
            output += ","
    
    output += "]"
    return IntArray(output)
    

class Scaffold():
    def get_action(self) -> str:
        pass
    

class DScaffold(Scaffold, BaseModel):
    """
    DScaffold is a base class for all data classes that need to be sent to the server.
    """
    pass
    
    def get_response_type(self) -> type:
        pass
    
    def get_serialized(self, key: str = None):
        return xor_encrypt(self.json(), key=key)

class APIResponse:
    status: Optional[bool] = False
    code: Optional[int] = 0
    data: DScaffold = None
    arguments: Optional[Any] = None
    the_err = None
    
    def __init__(self, j_value: dict) -> None:
        if not isinstance(j_value, dict):
            raise TypeError("j_value must be a dict")
        
        self.status = j_value.get('status', False)
        self.arguments = j_value.get('arguments', None)


class CollectGoldRequest(DScaffold):
    client: Optional[str] = ""
    
    def set_default_values(self):
        if not self.client:
            self.client = LoadRequestDefaults.DEFAULT_CLIENT_VALUE

class CollectGoldResponse(DScaffold):
    collected_gold: Optional[int] = 0
    player_gold: Optional[int] = 0
    gold_collection_allowed: Optional[bool] = False
    gold_collection_allowed_at: Optional[int] = 0
    gold_collection_extraction: Optional[int] = 0
    last_gold_collected_at: Optional[int] = 0
    needs_captcha: Optional[bool] = False

class CardInfo(DScaffold):
    type: Optional[int] = 0
    cards: Optional[Any] = None
    card_pack_type: int = int

class AttackCardInfo(DScaffold):
    id: Optional[int] = 0
    last_used_at: Optional[int] = 0
    power: Optional[int] = 0
    base_card_id: Optional[int] = 0
    player_id: Optional[int] = 0
    internal_last_time_used: Optional[int] = 0

    def set_as_used(self):
        self.internal_last_time_used = time.time()

class EvolveCardRequest(DScaffold):
    sacrifices: Optional[IntArray] = None

class EvolveCardResponse(DScaffold):
    gold: Optional[int] = 0
    card: Optional[AttackCardInfo] = None
    hero_max_rarity: Optional[int] = None

class QuestResponse(DScaffold):
    code: Optional[int] = 0
    arguments: Optional[List[Any]] = []
    outcome: Optional[bool] = False
    boss_mode: Optional[bool] = False
    gold: Optional[int] = 0
    gold_added: Optional[int] = 0
    level_up_gold_added: Optional[int] = 0
    xp: Optional[int] = 0
    xp_added: Optional[int] = 0
    rank: Optional[int] = 0
    tribe_rank: Optional[int] = 0
    attack_cards: Optional[List[AttackCardInfo]] = []
    tribe_gold: Optional[int] = 0
    # gift_card: Optional[Any] = None
    q: Optional[int] = 0
    total_quests: Optional[int] = 0
    needs_captcha: Optional[bool] = False
    league_id: Optional[int] = 0
    # tutorial_required_cards: Optional[Any] = None
    potion_number: Optional[int] = 0
    nectar: Optional[int] = 0
    
    raw_response: Optional[bytes] = b""



class Onsale(DScaffold):
    num1: Optional[List[int]] = None
    num2: Optional[List[int]] = None
    num3: Optional[List[int]] = None
    num4: Optional[List[int]] = None
    num7: Optional[List[int]] = None
    num8: Optional[List[int]] = None
    num10: Optional[List[int]] = None
    num12: Optional[List[int]] = None
    num13: Optional[List[int]] = None
    num14: Optional[List[int]] = None


class Price(DScaffold):
    num1: Optional[str] = ""
    num2: Optional[str] = ""
    num3: Optional[str] = ""
    num4: Optional[str] = ""
    num7: Optional[str] = ""
    num8: Optional[str] = ""
    num10: Optional[str] = ""
    num12: Optional[str] = ""
    num13: Optional[str] = ""
    num14: Optional[str] = ""

class GoldPackInfo(DScaffold):
    name: str = ''
    price: Price = None
    gold_amount: Optional[int] = 0
    gold_to_price_ratio: Optional[float] = 0.0
    product_uid: str = ''
    gives_avatar: Optional[bool] = False
    popularity: Optional[int] = 0
    onsale: Onsale = None

class ModulesVersion(DScaffold):
    Constants: Optional[str] = ""
    TutorialData: Optional[int] = 0
    TutorialLanguage_en: Optional[int] = 0
    TutorialLanguage_fa: Optional[int] = 0
    CardComboData: Optional[int] = 0
    CardComboLanguage_en: Optional[int] = 0
    CardComboLanguage_fa: Optional[int] = 0
    BaseHeroItems: Optional[int] = 0
    BaseHeroItemsLanguage_en: Optional[int] = 0
    BaseHeroItemsLanguage_fa: Optional[int] = 0
    BaseFruitLanguage_fa: Optional[int] = 0
    BaseFruitLanguage_en: Optional[int] = 0


class Coaching(DScaffold):
    trained_players: Optional[int] = 0

class DailyReward(DScaffold):
    next_reward_at: Optional[int] = 0



class Bundles(DScaffold):
    id: Optional[int] = 0
    description: Optional[str] = ""
    gold_pack_info: GoldPackInfo = None
    gold_amount: Optional[int] = 0
    nectar_amount: Optional[int] = 0
    fill_potion: Optional[bool] = False
    boost_pack_type: Optional[int] = 0
    card_info: CardInfo = None
    rewards_count: Optional[int] = 0
    duration: Optional[int] = 0
    start_date: Optional[int] = 0
    end_date: Optional[int] = 0
    max_level: Optional[int] = 0
    min_level: Optional[int] = 0
    show_on_home: Optional[bool] = False
    discount_ratio: Optional[float] = 0.0


class HeroItemInfo(DScaffold):
    id: Optional[int] = 0
    base_heroitem_id: Optional[int] = 0
    state: Optional[int] = 0
    position: Optional[int] = 0

class HeroIDSet(DScaffold):
    items: Optional[List[HeroItemInfo]] = None
    id: Optional[int] = 0
    power: Optional[int] = 0
    base_card_id: Optional[int] = 0
    potion: Optional[int] = 0

class HeroItems(DScaffold):
    id: Optional[int] = 0
    base_heroitem_id: Optional[int] = 0
    base_hero_id: Optional[int] = 0
    used_count: Optional[int] = 0
    state: Optional[int] = 0
    position: Optional[int] = 0


class Achievements(DScaffold):
    player_id: Optional[int] = 0
    achievement_id: Optional[int] = 0
    created_at: Optional[int] = 0
    id: Optional[int] = 0


class Tribe(DScaffold):
    id: Optional[int] = 0
    name: Optional[str] = ""
    description: Optional[str] = ""
    score: Optional[int] = 0
    rank: Optional[int] = 0
    gold: Optional[int] = 0
    member_count: Optional[int] = 0
    defense_building_level: Optional[int] = 0
    offense_building_level: Optional[int] = 0
    cooldown_building_level: Optional[int] = 0
    mainhall_building_level: Optional[int] = 0
    donates_number: Optional[int] = 0
    status: Optional[int] = 0
    weekly_score: Optional[int] = 0
    weekly_rank: Optional[int] = 0


class FruitCardInfo(DScaffold):
    id: Optional[int] = 0
    name: Optional[str] = ""
    small_image: Optional[str] = ""
    max_level: Optional[int] = 0
    min_level: Optional[int] = 0
    category: Optional[int] = 0
    description: Optional[str] = ""
    

class PlayerLoadResponse(DScaffold):
    code: Optional[int] = 0
    id: Optional[int] = 0
    name: Optional[str] = ""
    rank: Optional[int] = 0
    league_rank: Optional[int] = 0
    xp: Optional[int] = 0
    weekly_score: Optional[int] = 0
    level: Optional[int] = 0
    def_power: Optional[int] = 0
    league_id: Optional[int] = 0
    gold: Optional[int] = 0
    tribe_permission: Optional[int] = 0
    gold_building_level: Optional[int] = 0
    bank_building_level: Optional[int] = 0
    new_messages: Optional[int] = 0
    restore_key: Optional[str] = ""
    invite_key: Optional[str] = ""
    needs_captcha: Optional[bool] = False
    cooldowns_bought_today: Optional[int] = 0
    total_quests: Optional[int] = 0
    total_battles: Optional[int] = 0
    q: Optional[int] = 0
    bank_account_balance: Optional[int] = 0
    last_gold_collect_at: Optional[int] = 0
    tutorial_id: Optional[int] = 0
    tutorial_index: Optional[int] = 0
    potion_number: Optional[int] = 0
    nectar: Optional[int] = 0
    hero_id: Optional[int] = 0
    birth_year: Optional[int] = 0
    gender: Optional[int] = 0
    phone: Optional[str] = ""
    address: Optional[str] = ""
    realname: Optional[str] = ""
    prev_league_id: Optional[int] = 0
    prev_league_rank: Optional[int] = 0
    won_battle_num: Optional[int] = 0
    lost_battle_num: Optional[int] = 0
    mood_id: Optional[int] = 0
    avatar_id: Optional[int] = 0
    updated_at: Optional[int] = 0
    last_load_at: Optional[int] = 0
    medals: Optional[Any] = None
    avatar_slots: Optional[int] = 0
    avatars: Optional[List[str]] = []
    owned_avatars: Optional[List[int]] = []
    activity_status: Optional[int] = 0
    has_email: Optional[bool] = False
    cards: Optional[List[AttackCardInfo]] = []
    gold_building_assigned_cards: Optional[List[AttackCardInfo]] = []
    offense_building_assigned_cards: Optional[List[Any]] = []
    defense_building_assigned_cards: Optional[List[Any]] = []
    auction_building_assigned_cards: Optional[List[Any]] = []
    gold_collection_allowed: Optional[bool] = False
    gold_collection_allowed_at: Optional[int] = 0
    gold_collection_extraction: Optional[int] = 0
    collection: Optional[List[int]] = []
    cards_view: Optional[int] = 0
    tribe: Tribe = None
    achievements: Optional[List[Achievements]] = []
    achievements_blob: Optional[str] = ""
    now: Optional[int] = 0
    league_remaining_time: Optional[int] = 0
    bonus_remaining_time: Optional[float] = 0.0
    is_existing_player: Optional[bool] = False
    is_name_temp: Optional[bool] = False
    sale_info: Optional[List[Any]] = []
    heroitems: Optional[List[HeroItems]] = []
    base_hero_id: Optional[int] = 0
    hero_id_set: Optional[List[HeroIDSet]] = []
    hero_max_rarity: Optional[int] = 0
    available_combo_id_set: Optional[List[int]] = []
    potion_price: Optional[int] = 0
    nectar_price: Optional[int] = 0
    better_vitrin_promotion: Optional[bool] = False
    can_use_vitrin: Optional[bool] = False
    can_watch_advertisment: Optional[bool] = False
    purchase_deposits_to_bank: Optional[bool] = False
    advertisment_provider: Optional[int] = 0
    advertisment_providers_waterfall: Optional[List[int]] = []
    advertisment_providers_random: Optional[List[int]] = []
    better_choose_deck: Optional[bool] = False
    better_quest_map: Optional[bool] = False
    better_battle_outcome_navigation: Optional[bool] = False
    better_tutorial_background: Optional[bool] = False
    better_tutorial_steps: Optional[bool] = False
    more_xp: Optional[bool] = False
    better_gold_pack_multiplier: Optional[bool] = False
    better_gold_pack_ratio: Optional[bool] = False
    better_gold_pack_ratio_on_price: Optional[bool] = False
    better_league_tutorial: Optional[bool] = False
    better_enhance_tutorial: Optional[bool] = False
    better_mine_building_status: Optional[bool] = False
    is_mine_building_limited: Optional[bool] = False
    retouched_tutorial: Optional[bool] = False
    better_card_graphic: Optional[bool] = False
    durable_buildings_name: Optional[bool] = False
    show_task_until_levelup: Optional[bool] = False
    better_restore_button_label: Optional[bool] = False
    better_quest_tutorial: Optional[bool] = False
    hero_tutorial_at_first: Optional[bool] = False
    hero_tutorial_at_first_and_selected: Optional[bool] = False
    hero_tutorial_at_first_and_selected_and_animated: Optional[bool] = False
    hero_tutorial_at_level_four: Optional[bool] = False
    hero_tutorial_at_second_quest: Optional[bool] = False
    fall_background: Optional[bool] = False
    unified_gold_icon: Optional[bool] = False
    send_all_tutorial_steps: Optional[bool] = False
    rolling_gold: Optional[bool] = False
    bundles: Optional[List[Bundles]] = []
    daily_reward: Optional[Any] = None
    coach_info: Optional[List[Any]] = []
    coaching: Optional[Coaching] = None
    coach_test: Optional[bool] = False
    mobile_number_verified: Optional[bool] = False
    wheel_of_fortune_opens_in: Optional[int] = 0
    wheel_of_fortune: Optional[bool] = False
    latest_app_version: Optional[str] = ""
    latest_app_version_for_notice: Optional[str] = ""
    latest_constants_version: Optional[str] = ""
    modules_version: ModulesVersion = None
    emergency_message: Optional[str] = ""
    update_message: Optional[str] = ""
    

PlayerMedals: Dict[str, int] = dict
ErrorMessages: Dict[str, str] = dict
DeviceConstants: Dict[str, Any] = dict
FruitExportContainer: Dict[str, FruitCardInfo] = dict



class DeviceConstantsRequest(DScaffold):
    game_version: Optional[str] = ""
    os_version: Optional[str] = ""
    model: Optional[str] = ""
    constant_version: Optional[str] = ""
    store_type: Optional[str] = ""
    
    def set_default_values(self):
        if not self.game_version:
            self.game_version = LoadRequestDefaults.DEFAULT_GAME_VERSION
        
        if not self.os_version:
            self.os_version = LoadRequestDefaults.DEFAULT_OS_VERSION
        
        if not self.model:
            self.model = LoadRequestDefaults.DEFAULT_PHONE_MODEL
        
        if not self.constant_version:
            self.constant_version = LoadRequestDefaults.DEFAULT_CONSTANTS_VERSION
        
        if not self.store_type:
            self.store_type = LoadRequestDefaults.DEFAULT_STORE_TYPE


class PlayerLoadRequest(DScaffold):
    game_version: Optional[str] = ""
    udid: Optional[str] = ""
    os_type: Optional[int] = 0
    restore_key: Optional[str] = ""
    os_version: Optional[str] = ""
    model: Optional[str] = ""
    metrix_uid: Optional[str] = ""
    appsflyer_uid: Optional[str] = ""
    device_name: Optional[str] = ""
    store_type: Optional[str] = ""
    
    def set_default_values(self):
        if not self.game_version:
            self.game_version = LoadRequestDefaults.DEFAULT_GAME_VERSION
        
        if not self.udid:
            self.udid = ''.join(random.choices("abcdef0123456789", k=16))
        
        if not self.os_type:
            self.os_type = LoadRequestDefaults.DEFAULT_OS_TYPE
        
        if not self.os_version:
            self.os_version = LoadRequestDefaults.DEFAULT_OS_VERSION
        
        if not self.model:
            self.model = LoadRequestDefaults.DEFAULT_PHONE_MODEL
        
        if not self.metrix_uid:
            self.metrix_uid = LoadRequestDefaults.DEFAULT_METRIX_UID
        
        if not self.appsflyer_uid:
            self.appsflyer_uid = LoadRequestDefaults.DEFAULT_APPS_FLYER_UID
        
        if not self.device_name:
            self.device_name = LoadRequestDefaults.DEFAULT_DEVICE_NAME
        
        if not self.store_type:
            self.store_type = LoadRequestDefaults.DEFAULT_STORE_TYPE


class LanguagePathResponse(DScaffold):
    en: Dict[str, str] = {}
    fa: Dict[str, str] = {}


class PlayerComebackRequest(DScaffold):
    client: Optional[str] = ""
    
    def set_default_values(self):
        if not self.client:
            self.client = LoadRequestDefaults.DEFAULT_CLIENT_VALUE
    
class PlayerComebackResponse(DScaffold):
    dummy: Optional[str] = ""
    
class FruitJsonExportRequest(DScaffold):
    client: Optional[str] = ""
    
    def set_default_values(self):
        if not self.client:
            self.client = LoadRequestDefaults.DEFAULT_CLIENT_VALUE

class LanguagePatchRequest(DScaffold):
    client: Optional[str] = ""
    
    def set_default_values(self):
        if not self.client:
            self.client = LoadRequestDefaults.DEFAULT_CLIENT_VALUE

class ErrorMessagesRequest(DScaffold):
    lang_id: Optional[str] = ""
    
    def set_default_values(self):
        if not self.lang_id:
            self.lang_id = LoadRequestDefaults.DEFAULT_LANG_VALUE

class CardsSelection():
    cards: List[int] = None
    hero_id: int = 0
    
    # NoHeal indicates we shouldn't be trying to heal any of
    # the cards. This means we are 100% sure that they have already
    # been healed previously.
    no_heal: bool = False
    
    def __init__(self, cards: List[int], hero_id: int = 0, no_heal: bool = False) -> None:
        self.cards = cards
        self.hero_id = hero_id
        self.no_heal = no_heal


class QuestRequest(DScaffold):
    cards: IntArray = []
    hero_id: Optional[int] = 0
    check: Optional[str] = ""
    _cards_selection: Optional[CardsSelection] = None


class TribeMemberInfo(DScaffold):
    id: Optional[int] = 0
    name: Optional[str] = ""
    rank: Optional[int] = 0
    xp: Optional[int] = 0
    gold: Optional[int] = 0
    tribe_permission: Optional[int] = 0
    level: Optional[int] = 0
    def_power: Optional[int] = 0
    status: Optional[int] = 0
    league_id: Optional[int] = 0
    league_rank: Optional[int] = 0
    avatar_id: Optional[int] = 0
    poke_status: Optional[bool] = False


class OpponentInfo(DScaffold):
    id: Optional[int] = 0
    name: Optional[str] = ""
    rank: Optional[int] = 0
    xp: Optional[int] = 0
    gold: Optional[int] = 0
    tribe_permission: Optional[int] = 0
    level: Optional[int] = 0
    def_power: Optional[int] = 0
    status: Optional[int] = 0
    league_id: Optional[int] = 0
    league_rank: Optional[int] = 0
    avatar_id: Optional[int] = 0
    power_ratio: Optional[int] = 0
    tribe_name: Optional[str] = ""


class BattleResponse(DScaffold):
    code: Optional[int] = 0
    outcome: Optional[bool] = False
    won_by_chance: Optional[bool] = False
    gold: Optional[int] = 0
    gold_added: Optional[int] = 0
    league_bonus: Optional[int] = 0
    levelup_gold_added: Optional[int] = 0
    level: Optional[int] = 0
    xp: Optional[int] = 0
    xp_added: Optional[int] = 0
    rank: Optional[int] = 0
    tribe_rank: Optional[int] = 0
    attack_cards: Optional[List[AttackCardInfo]] = []
    opponent_cards: Optional[List[AttackCardInfo]] = []
    tribe_gold: Optional[int] = 0
    gift_card: Optional[Any] = None
    attack_power: Optional[float] = 0.0
    def_power: Optional[float] = 0.0
    q: Optional[int] = 0
    total_battles: Optional[int] = 0
    needs_captcha: Optional[bool] = False
    league_rank: Optional[int] = 0
    league_id: Optional[int] = 0
    weekly_score: Optional[int] = 0
    score_added: Optional[int] = 0
    won_battle_num: Optional[int] = 0
    lost_battle_num: Optional[int] = 0
    attack_bonus_power: Optional[float] = 0.0
    def_bonus_power: Optional[float] = 0.0
    tutorial_required_cards: Optional[Any] = None
    attacker_combo_info: Optional[List[Any]] = []
    defender_combo_info: Optional[List[Any]] = []
    potion_number: Optional[int] = 0
    nectar: Optional[int] = 0
    gift_potion: Optional[int] = 0
    gift_nectar: Optional[int] = 0
    available_combo_id_set: Optional[Any] = None
    purchase_deposits_to_bank: Optional[Any] = None
    attacker_hero_benefits_info: Optional[Any] = None
    defender_hero_benefits_info: Optional[Any] = None
    raw_response: Optional[bytes] = b""


class BattleRequest(DScaffold):
    opponent_id: Optional[int] = 0
    check: Optional[str] = ""
    cards: Optional[IntArray] = None
    hero_id: Optional[int] = 0
    attacks_in_today: Optional[int] = 0
    _cards_selection: Optional[CardsSelection] = None


class GetOpponentsResponse(DScaffold):
    players: Optional[List[OpponentInfo]] = []
    
    def get_strongest(self) -> OpponentInfo:
        strongest_opp: OpponentInfo = None
        for current in self.players:
            if not strongest_opp:
                strongest_opp = current
                continue
            
            if current and current.def_power > strongest_opp.def_power:
                strongest_opp = current
        
        return strongest_opp
    
    def get_weakest(self) -> OpponentInfo:
        weakest_opp: OpponentInfo = None
        for current in self.players:
            if not weakest_opp:
                weakest_opp = current
                continue
            
            if current and current.def_power < weakest_opp.def_power:
                weakest_opp = current
        
        return weakest_opp


class GetOpponentsRequest(DScaffold):
    client: Optional[str] = ""
    _other_pass: Optional[str] = ""

class TribeMembersResponse(DScaffold):
    members: Optional[List[TribeMemberInfo]] = []


class TribeMembersRequest(DScaffold):
    coach_tribe: Optional[bool] = False
    

class CoolOffResponse(DScaffold):
    code: Optional[int] = 0
    gold: Optional[int] = 0
    cooldowns_bought_today: Optional[int] = 0



class CoolOffRequest(DScaffold):
    card_id: Optional[int] = 0


class LiveBattleResponse(DScaffold):
    code: Optional[int] = 0
    arguments: Optional[Any] = None
    battle_id: Optional[int] = 0
    help_cost: Optional[int] = 0


class LiveBattleRequest(DScaffold):
    opponent_id: Optional[int] = 0


class SetCardForLiveBattleResponse(DScaffold):
    last_used_at: Optional[int] = 0


class SetCardForLiveBattleRequest(DScaffold):
    round: Optional[int] = 0
    card: Optional[int] = 0
    battle_id: Optional[int] = 0

class TribeInfo(DScaffold):
    id: Optional[int] = 0
    name: Optional[str] = ""
    description: Optional[str] = ""
    score: Optional[int] = 0
    rank: Optional[int] = 0
    member_count: Optional[int] = 0
    weekly_score: Optional[int] = 0
    weekly_rank: Optional[int] = 0


class TribeRankingsResponse(DScaffold):
    top_tribes: Optional[List[TribeInfo]] = []
    near_tribes: Optional[List[TribeInfo]] = []
    tribe_rank: Optional[int] = 0


class TribeRankingsRequest(DScaffold):
    client: Optional[str] = ""
    
    def set_default_values(self):
        if not self.client:
            self.client = LoadRequestDefaults.DEFAULT_CLIENT_VALUE


class LiveBattleHelpRequest(DScaffold):
    battle_id: Optional[int] = 0

class LiveBattleHelpResponse(DScaffold):
    dummy: Optional[str] = ""

class PlayerRankingInfo(DScaffold):
    id: Optional[int] = 0
    name: Optional[str] = ""
    rank: Optional[int] = 0
    xp: Optional[int] = 0
    level: Optional[int] = 0
    tribe_id: Optional[int] = 0
    tribe_name: Optional[str] = ""
    avatar_id: Optional[int] = 0


class GlobalRankingsResponse(DScaffold):
    top_players: Optional[List[PlayerRankingInfo]] = []
    near_players: Optional[List[PlayerRankingInfo]] = []
    rank: Optional[int] = 0


class GlobalRankingsRequest(DScaffold):
    client: Optional[str] = ""
    
    def set_default_values(self):
        if not self.client:
            self.client = LoadRequestDefaults.DEFAULT_CLIENT_VALUE


class PlayerLeagueRankingInfo(DScaffold):
    id: Optional[int] = 0
    name: Optional[str] = ""
    league_rank: Optional[int] = 0
    overall_score: Optional[int] = 0
    weekly_score: Optional[int] = 0
    level: Optional[int] = 0
    tribe_id: Optional[int] = 0
    tribe_name: Optional[str] = ""
    avatar_id: Optional[int] = 0


class LeagueRankingsResponse(DScaffold):
    top_players: Optional[List[PlayerLeagueRankingInfo]] = []
    near_players: Optional[List[PlayerLeagueRankingInfo]] = []
    league_rank: Optional[int] = 0
    winner_ranges: LeagueWinnerRanges = None
    league_rising_rank: Optional[int] = 0
    league_falling_rank: Optional[int] = 0
    current_league_bonus: Optional[int] = 0
    next_league_bonus: Optional[int] = 0


class FillPotionRequest(DScaffold):
    amount: Optional[int] = 0


class FillPotionResponse(DScaffold):
    code: Optional[int] = 0
    added_potion: Optional[int] = 0
    potion_number: Optional[int] = 0
    gold: Optional[int] = 0


class PotionizeRequest(DScaffold):
    potion: Optional[int] = 0
    hero_id: Optional[int] = 0


class PotionizeResponse(DScaffold):
    code: Optional[int] = 0
    player_potion: Optional[int] = 0
    nectar: Optional[int] = 0
    gold: Optional[int] = 0
    hero_potion: Optional[int] = 0


class GetPlayerInfoRequest(DScaffold):
    player_id: Optional[int] = 0


class GetPlayerInfoResponse(DScaffold):
    code: Optional[int] = 0
    name: Optional[str] = ""
    total_rank: Optional[int] = 0
    won_battle_num: Optional[int] = 0
    lost_battle_num: Optional[int] = 0
    mood_id: Optional[int] = 0
    avatar_id: Optional[int] = 0
    updated_at: Optional[int] = 0
    last_load_at: Optional[int] = 0
    tribe_name: Optional[str] = ""
    tribe_rank: Optional[int] = 0
    tribe_position: Optional[int] = 0
    league_id: Optional[int] = 0
    league_rank: Optional[int] = 0
    prev_league_id: Optional[int] = 0
    medals: Optional[Any] = None


class LeagueRankingsRequest(DScaffold):
    client: Optional[str] = ""
    
    def set_default_values(self):
        if not self.client:
            self.client = LoadRequestDefaults.DEFAULT_CLIENT_VALUE" now i want to use this data to manipulate this request "POST /cards/collectgold HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Cookie: FRUITPASSPORT=35f77af5578faedb4ab6914db5d347c2;
Content-Length: 34
User-Agent: Dalvik/2.1.0 (Linux; U; Android 7.1.2; SM-A908N Build/PPR1.180610.011)
Host: iran.fruitcraft.ir
Connection: Keep-Alive
Accept-Encoding: gzip

edata={"client":"iOS"}" i want to change the output response value named 'player_gold'