Example #1
0
 def _conduct_sortie(self, sortie_map):
     if not self._validate_sortie_map(sortie_map):
         Log.log_warn(f"Map {sortie_map.value} is not available.")
         return False
     if cfg.config.combat.clear_stop and self._sortie_map_is_cleared:
         Log.log_msg(f"Map {sortie_map.value} has been cleared.")
         self.enabled = False
         return False
     self._select_world(sortie_map)
     time_to_rest = lbas.lbas.manage_lbas()
     if time_to_rest:
         Log.log_warn("LBAS is fatigued.")
         self.set_next_sortie_time(time_to_rest)
         return False
     self._select_map(sortie_map)
     if self._begin_sortie():
         self.nodes_run = []
         self.combat_nodes_run = []
         self.rescued_ships = []
         self.map_cleared = False
         sts.stats.combat.combat_sorties += 1
         self._handle_combat(sortie_map)
         self._check_map_clear()
         if self.enabled:
             self.set_next_sortie_time()
         return True
     return False
Example #2
0
    def _get_ship_name_data(suffixes):
        """Method for retrieving and parsing the WCTF ship name data with
        appropriate suffixes.

        Args:
            suffixes (dict): suffix dict

        Returns:
            dict: dict of ship names
        """
        db_res = requests.get(WCTF_DB_URL)
        name_db = {}
        if db_res.status_code == 200:
            db_split = db_res.text.split('\n')
            for line in db_split:
                line = line.strip()
                if not line:
                    continue

                line_dict = JsonData.load_json_str(line)
                suffix_id = line_dict['name']['suffix']
                jp_name = line_dict['name']['ja_jp']
                non_jp_name = line_dict['name']['ja_romaji'].title()
                if suffix_id:
                    jp_name += f" {suffixes[suffix_id]['jp']}"
                    if non_jp_name:
                        non_jp_name += f" {suffixes[suffix_id]['non_jp']}"
                name_db[line_dict['id']] = {
                    'jp': jp_name,
                    'non_jp': non_jp_name
                }
        else:
            Log.log_warn("Could not download WCTF ship data.")

        return name_db
Example #3
0
 def should_and_able_to_sortie(self):
     if not self.enabled or not self.time_to_sortie:
         return False
     if cfg.config.combat.port_check:
         if shp.ships.current_ship_count == shp.ships.max_ship_count:
             Log.log_msg("Port is full.")
             self.set_next_sortie_time(15)
             return False
     if cfg.config.combat.sortie_map.world == 'E':
         if shp.ships.current_ship_count >= shp.ships.max_ship_count - 5:
             Log.log_warn("Port is too full for event map.")
             self.set_next_sortie_time(15)
             return False
     if cfg.config.combat.check_fatigue:
         for fleet in flt.fleets.combat_fleets:
             if fleet.highest_fatigue > FatigueStateEnum.NO_FATIGUE:
                 Log.log_warn("Combat fleet is fatigued.")
                 self.set_next_sortie_time(49 - fleet.lowest_morale)
                 return False
     for fleet in flt.fleets.combat_fleets:
         if fleet.under_repair:
             Log.log_warn("Combat fleet is under repair.")
             self.set_next_sortie_time(rep.repair.soonest_complete_time)
             return False
         if fleet.needs_repair:
             Log.log_warn("Combat fleet needs repair.")
             if rep.repair.docks_are_available:
                 self.set_next_sortie_time()
             else:
                 self.set_next_sortie_time(rep.repair.soonest_complete_time)
             return False
         if fleet.needs_resupply:
             Log.log_warn("Combat fleet needs resupply.")
             return False
     return True
Example #4
0
    def _get_suffix_data():
        """Method for retrieving and parsing the WCTF suffix data needed to
        generate complete ship names.

        Returns:
            dict: suffix dict
        """
        suf_res = requests.get(WCTF_SUFFIX_URL)
        suffixes = {}

        if suf_res.status_code == 200:
            suf_split = suf_res.text.split('\n')
            for line in suf_split:
                line = line.strip()
                if not line:
                    continue

                line_dict = JsonData.load_json_str(line)
                suffixes[line_dict['id']] = {
                    'jp': line_dict['ja_jp'],
                    'non_jp': line_dict['ja_romaji']
                }
        else:
            Log.log_warn("Could not download WCTF suffix data.")

        return suffixes
Example #5
0
    def find_all(asset, similarity):
        region = Region()

        Log.log_warn(f"Searching for {asset} with similarity {similarity}.")
        Log.log_warn("Results:")
        results = region.find_all(asset, similarity)
        for result in results:
            print(result)
Example #6
0
 def enabled(self, value):
     if type(value) is not bool:
         raise TypeError(
             f"Enabled setting for module {self.module_display_name} "
             "is not a bool.")
     if value is True:
         Log.log_success(f"{self.module_display_name} module enabled.")
         self.time_disabled = None
     else:
         Log.log_warn(f"{self.module_display_name} module disabled")
         self.time_disabled = datetime.now()
     self._enabled = value
Example #7
0
    def recovery_from_catbomb(cls, screen=Region(), catbomb_201=False):
        """Method that contains steps for recovery attempt from catbombs. If
        the catbomb_201 flag is set to True the recovery is attempt is far less
        aggressive to not aggravate the fairies any further. Includes
        incremental fallback for retry attempts.

        Args:
            screen (Region, optional): screen region. Defaults to Region().
            catbomb_201 (bool, optional): whether or not this is a 201 catbomb.
                Defaults to False.

        Returns:
            bool: True if recovery was successful; False otherwise.
        """
        catbomb_count = 0 if not catbomb_201 else 2
        if catbomb_201:
            if sts.stats.recovery.catbomb_201_encountered > 0:
                Log.log_error(
                    "Multiple 201 catbombs encountered. Shutting down kcauto.")
                return False
            else:
                kca_u.kca.sleep(300)

        while catbomb_count < 3:
            cls._refresh_screen(screen)
            if kca_u.kca.start_kancolle():
                Log.log_success("Catbomb Recovery successful.")
                kca_u.kca.hook_chrome(port=cfg.config.general.chrome_dev_port)
                sts.stats.recovery.recoveries_done += 1
                if catbomb_201:
                    sts.stats.recovery.catbomb_201_encountered += 1
                    sts.stats.recovery.catbomb_201_recoveries_done += 1
                else:
                    sts.stats.recovery.catbomb_recoveries_done += 1
                return True
            elif kca_u.kca.exists(screen, 'global|catbomb.png'):
                if catbomb_201:
                    Log.log_error(
                        "Persistent 201 catbomb. Shutting down kcauto.")
                    return False

                catbomb_count += 1
                # incremental backoff; 16, 64, then 256 seconds
                sleep_len = pow(4, catbomb_count + 1)
                Log.log_warn(
                    f"Catbomb Recovery attempt {catbomb_count}. Sleeping for "
                    f"{sleep_len} seconds before next recovery attempt.")
                sleep(sleep_len)
            else:
                return False
        return False
Example #8
0
    def attempt_recovery(cls):
        """Primary method that runs through all the various recovery options.
        Runs through basic recovery, result screen recovery, catbomb recovery,
        then Chrome tab crash recoveries. Typically run when there has been a
        generic Exception caused.

        Returns:
            bool: True if recovery was successful; False otherwise.
        """
        Log.log_warn("Attempting recovery.")

        screen = Region()

        if cls.basic_recovery():
            Log.log_success("Basic Recovery successful.")
            sts.stats.recovery.recoveries_done += 1
            sts.stats.recovery.basic_recoveries_done += 1
            return True

        if (
                kca_u.kca.exists(screen, 'global|next.png')
                or kca_u.kca.exists(screen, 'global|next_alt.png')):
            Log.log_warn("Results screen detected.")
            if cls.recovery_from_results(screen):
                Log.log_success("Results Recovery successful.")
                sts.stats.recovery.recoveries_done += 1
                sts.stats.recovery.results_recoveries_done += 1
                return True
            return False

        if kca_u.kca.exists(screen, 'global|catbomb.png'):
            Log.log_warn("Catbomb detected.")
            if cls.recovery_from_catbomb(screen=screen):
                return True
            else:
                Log.log_error("Catbomb Recovery failed.")
            return False

        if kca_u.kca.exists(screen, 'global|chrome_crash.png'):
            Log.log_warn("Chrome Crash (Type 1) detected.")
            if cls.recovery_from_chrome_crash(screen, crash_type=1):
                return True

        visual_events = kca_u.kca.visual_hook.pop_messages()
        for event in visual_events:
            if event['method'] == 'Inspector.targetCrashed':
                Log.log_warn("Chrome Crash (Type 2) detected.")
                if cls.recovery_from_chrome_crash(screen, crash_type=2):
                    return True
Example #9
0
    def _begin_sortie(self):
        if kca_u.kca.click_existing('lower_right', 'global|sortie_select.png'):
            kca_u.kca.r['top'].hover()
            kca_u.sleep(2)

            sortie_button_asset = 'combat|combat_start.png'
            if lbas.lbas.enabled and len(lbas.lbas.assignable_lbas_groups) > 0:
                sortie_button_asset = 'combat|combat_start_lbas.png'

            if kca_u.kca.click_existing('lower_right', sortie_button_asset):
                for fleet in flt.fleets.combat_fleets:
                    Log.log_msg(fleet)
                    Log.log_msg(fleet.detailed_fleet_status)
                Log.log_msg("Starting sortie.")
                return True
            Log.log_warn(f"Cannot start combat.")
        return False
Example #10
0
    def _resolve_continue_sortie_prompt(self):
        Log.log_debug("Resolve continue sortie prompt.")
        continue_sortie = True
        retreat_limit = cfg.config.combat.retreat_limit
        if self.current_node in cfg.config.combat.push_nodes:
            Log.log_msg(f"{self.current_node} is specified as a push node.")
            return True
        for fleet in flt.fleets.combat_fleets:
            if fleet.weakest_state >= retreat_limit:
                Log.log_warn(
                    f"Fleet {fleet.fleet_id} has ships with "
                    f"{retreat_limit.display_name} damage or above.")
                continue_sortie = False
            elif fleet.visual_health['heavy'] > 0:
                Log.log_warn(
                    f"Fleet {fleet.fleet_id} has a critically damaged ship "
                    "not calculated from the API.")
                continue_sortie = False
        if (
                NodeEnum(self.current_node.name)
                in cfg.config.combat.retreat_points):
            Log.log_debug("Retreat specified in config.")
            continue_sortie = False
        if (
                NodeEnum(len(self.combat_nodes_run))
                in cfg.config.combat.retreat_points):
            Log.log_debug("Retreat specified combat # in config.")
            continue_sortie = False

        if continue_sortie:
            Log.log_msg("Continuing sortie.")
            kca_u.kca.click_existing(
                'kc', 'combat|combat_continue.png', cached=True)
        else:
            Log.log_msg("Retreating from sortie.")
            kca_u.kca.click_existing(
                'kc', 'combat|combat_retreat.png', cached=True)
        kca_u.kca.r['lbas'].hover()

        return continue_sortie
Example #11
0
    def _dispatch_expedition(self, fleet, expedition):
        if kca_u.kca.click_existing('lower_right', 'global|sortie_select.png'):
            fleet.select()
            kca_u.kca.r['top'].hover()

            if (fleet.needs_resupply
                    and res.resupply.exp_provisional_enabled in (True, None)):
                res.resupply.exp_provisional_resupply(fleet)

            if fleet.needs_resupply:
                Log.log_warn(f"Fleet {fleet.fleet_id} needs resupply.")
                return False

            if kca_u.kca.click_existing('lower_right',
                                        'expedition|expedition_dispatch.png'):
                result = api.api.update_from_api({KCSAPIEnum.EXPEDITION_START})
                sts.stats.expedition.expeditions_sent += 1
                fleet.at_base = False
                fleet.return_time = result[KCSAPIEnum.EXPEDITION_START.name][0]
                kca_u.kca.r['top'].hover()
                return True
            Log.log_warn(f"Fleet {fleet.fleet_id} is already away.")
            return False
        Log.log_warn(f"Expedition {expedition.expedition} already underway.")
        return False
Example #12
0
    def hook_health_check(self):
        """Method that runs through the different events reported to the api
        and visual hooks to ascertain whether or not the tab has crashed or
        was refreshed.

        Raises:
            ChromeCrashException: Chrome tab crash was detected.
        """
        api_events = self.api_hook.pop_messages()
        visual_events = self.visual_hook.pop_messages()
        for event in api_events:
            if event['method'] == 'Inspector.detached':
                Log.log_warn("Chrome API hook is stale. Reconnecting.")
                self.hook_chrome(port=cfg.config.general.chrome_dev_port)
                return
        visual_events = self.visual_hook.pop_messages()
        for event in visual_events:
            if event['method'] == 'Page.frameDetached':
                Log.log_warn("Chrome visual hook is stale. Reconnecting.")
                self.hook_chrome(port=cfg.config.general.chrome_dev_port)
                return
            if event['method'] == 'Inspector.targetCrashed':
                Log.log_warn("Chrome crash detected.")
                raise ChromeCrashException
Example #13
0
 def _check_for_chrome_crash(self):
     visual_events = kca_u.kca.visual_hook.pop_messages()
     for event in visual_events:
         if event['method'] == 'Inspector.targetCrashed':
             Log.log_warn("Chrome Crash detected.")
             raise ChromeCrashException