2024-06-26 19:32:28 +08:00
import yaml
2026-06-20 18:57:53 +08:00
from module . base . utils import random_rectangle_point , point2str
from module . device . method . utils import HierarchyButton
2024-06-26 19:32:28 +08:00
from module . equipment . assets import *
from module . logger import logger
2026-06-20 00:57:57 +08:00
from module . retire . assets import TEMPLATE_BOGUE , TEMPLATE_HERMES , TEMPLATE_RANGER , TEMPLATE_LANGLEY
2024-06-26 19:32:28 +08:00
from module . storage . assets import EQUIPMENT_FULL
from module . storage . storage import StorageHandler
2026-06-20 00:57:57 +08:00
EMPTY_CODE = " MC8wLzAvMC8wXDA= "
EQUIPMENT_PREVIEW = list ( [
EQUIPMENT_CODE_EQUIP_0 ,
EQUIPMENT_CODE_EQUIP_1 ,
EQUIPMENT_CODE_EQUIP_2 ,
EQUIPMENT_CODE_EQUIP_3 ,
EQUIPMENT_CODE_EQUIP_4 ,
EQUIPMENT_CODE_EQUIP_5 ,
] )
2024-06-26 19:32:28 +08:00
2026-06-20 00:57:57 +08:00
class EquipmentCodeHandler ( StorageHandler ) :
last_code : str = None
def get_code ( self , name ) :
try :
config = { }
for item in yaml . safe_load_all ( self . config . GemsFarming_EquipmentCode ) :
config . update ( item )
except Exception :
logger . error ( " Fail to load equipment code config " )
return None
try :
name : str = config . pop ( name )
return name
except Exception :
logger . error ( f " Config does not contain equipment code for { name } " )
return None
def set_code ( self , name , code ) :
config = { }
try :
for item in yaml . safe_load_all ( self . config . GemsFarming_EquipmentCode ) :
config . update ( item )
except Exception :
pass
try :
config . update ( { name : code } )
config_yaml = yaml . safe_dump ( config )
self . config . GemsFarming_EquipmentCode = config_yaml
except Exception :
logger . error ( " Fail to set equipment code config " )
2024-06-26 19:32:28 +08:00
2026-06-20 00:57:57 +08:00
def current_ship ( self ) :
2024-06-26 19:32:28 +08:00
"""
2026-06-20 00:57:57 +08:00
Currently , only supports common CV recognization
2024-06-26 19:32:28 +08:00
2026-06-20 00:57:57 +08:00
Pages :
in : equipment_code
2024-06-26 19:32:28 +08:00
"""
2026-06-20 00:57:57 +08:00
for _ in self . loop ( ) :
if not self . appear ( EMPTY_SHIP_R ) :
break
if TEMPLATE_BOGUE . match ( self . device . image , scaling = 1.46 ) : # image has rotation
return ' bogue '
elif TEMPLATE_HERMES . match ( self . device . image , scaling = 124 / 89 ) :
return ' hermes '
elif TEMPLATE_RANGER . match ( self . device . image , scaling = 4 / 3 ) :
return ' ranger '
elif TEMPLATE_LANGLEY . match ( self . device . image , scaling = 25 / 21 ) :
return ' langley '
else :
return ' DD '
2024-06-26 19:32:28 +08:00
2026-06-20 00:57:57 +08:00
def _code_enter ( self ) :
2024-06-26 19:32:28 +08:00
"""
Pages :
in : ship_detail
2026-06-20 00:57:57 +08:00
out : equipment_code
2024-06-26 19:32:28 +08:00
"""
2026-06-20 00:57:57 +08:00
for _ in self . loop ( ) :
2025-11-06 22:54:14 +08:00
if self . appear ( EQUIPMENT_CODE_PAGE_CHECK , offset = ( 5 , 5 ) ) :
2024-06-26 19:32:28 +08:00
break
2025-11-06 22:54:14 +08:00
if self . appear_then_click ( EQUIPMENT_CODE_ENTRANCE , offset = ( 5 , 5 ) , interval = 2 ) :
2024-06-26 19:32:28 +08:00
continue
2026-06-20 00:57:57 +08:00
def _code_exit ( self ) :
2024-09-21 18:02:26 +08:00
"""
2026-06-20 00:57:57 +08:00
Pages :
in : equipment_code
out : ship_detail
2024-09-21 18:02:26 +08:00
"""
2026-06-20 00:57:57 +08:00
self . ui_back ( check_button = EQUIPMENT_CODE_ENTRANCE )
2024-06-26 19:32:28 +08:00
2026-06-20 00:57:57 +08:00
def is_code_preview_loaded ( self ) :
if self . appear ( EQUIPMENT_CODE_EQUIP_5_LOCKED , offset = ( 5 , 5 ) ) :
2025-05-10 15:54:08 +08:00
max_index = 5
else :
max_index = 6
for index in range ( max_index ) :
2026-06-20 00:57:57 +08:00
if not self . appear ( EQUIPMENT_PREVIEW [ index ] , offset = ( 5 , 5 ) ) :
return True
2024-06-26 19:32:28 +08:00
2026-06-20 00:57:57 +08:00
return False
2024-06-26 19:32:28 +08:00
2026-06-20 00:57:57 +08:00
def _code_preview_clear ( self ) :
for _ in self . loop ( timeout = 2 ) :
if not self . is_code_preview_loaded ( ) :
return True
2024-06-26 19:32:28 +08:00
2026-06-20 00:57:57 +08:00
if self . appear_then_click ( EQUIPMENT_CODE_CLEAR , offset = ( 5 , 5 ) ) :
2024-06-26 19:32:28 +08:00
continue
2026-06-20 00:57:57 +08:00
else :
return False
2026-06-20 18:57:53 +08:00
def fastinput_ime_enable ( self ) :
self . device . adb_shell ( [ ' am ' , ' start ' , ' -a ' , ' android.settings.INPUT_METHOD_SETTINGS ' ] )
while 1 :
h = self . device . dump_hierarchy_adb ( )
def appear ( xpath ) :
return bool ( HierarchyButton ( h , xpath ) )
def appear_then_click ( xpath ) :
b = HierarchyButton ( h , xpath )
if b :
point = random_rectangle_point ( b . button )
logger . info ( f ' Click { point2str ( * point ) } @ { b } ' )
self . device . click_adb ( * point )
return True
else :
return False
if appear_then_click ( ' //*[@resource-id= " android:id/title " and @text= " FastInputIME " ]/following-sibling::*[@resource-id= " android:id/switch_widget " and @checked= " false " ] ' ) :
continue
if appear_then_click ( ' //*[@resource-id= " android:id/button1 " ] ' ) :
continue
# Disable one other enabled IME at a time
if appear_then_click ( ' (//*[@resource-id= " android:id/title " and @text!= " FastInputIME " ]/following-sibling::*[@resource-id= " android:id/switch_widget " and @enabled= " true " and @checked= " true " ])[1] ' ) :
continue
if appear ( ' //*[@resource-id= " android:id/title " and @text= " FastInputIME " ]/following-sibling::*[@resource-id= " android:id/switch_widget " and @checked= " true " ] ' ) \
and not appear ( ' //*[@resource-id= " android:id/title " and @text!= " FastInputIME " ]/following-sibling::*[@resource-id= " android:id/switch_widget " and @enabled= " true " and @checked= " true " ] ' ) :
break
self . device . adb_shell ( [ ' input ' , ' keyevent ' , ' 4 ' ] )
2026-06-20 00:57:57 +08:00
def _code_input ( self , code ) :
logger . info ( f " Code input: { code } " )
d = self . device . u2
for _ in self . loop ( timeout = 10 ) :
2026-06-20 18:57:53 +08:00
name , shown = d . current_ime ( )
2026-06-20 00:57:57 +08:00
if shown :
2026-06-20 18:57:53 +08:00
if name != ' com.github.uiautomator/.FastInputIME ' :
self . fastinput_ime_enable ( )
continue
else :
break
2026-06-20 00:57:57 +08:00
self . device . click ( EQUIPMENT_CODE_TEXTBOX )
else :
logger . warning ( " Equipment code load failed " )
return False
d . send_keys ( text = code , clear = True )
d . send_action ( code = " done " )
self . device . sleep ( ( 0.3 , 0.5 ) )
for _ in self . loop ( timeout = 10 , skip_first = False ) :
_ , shown = d . current_ime ( )
if shown :
2024-06-26 19:32:28 +08:00
continue
2026-06-20 00:57:57 +08:00
if self . is_code_preview_loaded ( ) :
2024-06-26 19:32:28 +08:00
return True
2026-06-20 00:57:57 +08:00
if self . appear_then_click ( EQUIPMENT_CODE_ENTER , offset = ( 5 , 5 ) , interval = 3 ) :
2024-06-26 19:32:28 +08:00
continue
2026-06-20 00:57:57 +08:00
else :
logger . warning ( " Equipment code load failed " )
return False
2024-06-26 19:32:28 +08:00
2026-06-20 00:57:57 +08:00
def _code_confirm ( self ) :
logger . info ( " Code apply " )
for _ in self . loop ( timeout = 10 ) :
2025-11-06 22:54:14 +08:00
if self . appear ( EQUIPMENT_CODE_ENTRANCE , offset = ( 5 , 5 ) ) :
2024-06-26 19:32:28 +08:00
return True
if self . appear ( EQUIPMENT_FULL , offset = ( 30 , 30 ) ) :
return False
2026-06-20 00:57:57 +08:00
if self . handle_popup_confirm ( " EQUIPMENT_CODE " ) :
continue
if self . appear_then_click ( EQUIPMENT_CODE_CONFIRM , offset = ( 5 , 5 ) , interval = 3 ) :
continue
2024-06-26 19:32:28 +08:00
else :
2026-06-20 00:57:57 +08:00
return False
def _code_apply ( self , code = None ) :
2025-05-10 15:54:08 +08:00
for _ in range ( 5 ) :
2026-06-20 00:57:57 +08:00
self . _code_preview_clear ( )
if code is not None and code != EMPTY_CODE :
success = self . _code_input ( code )
2024-09-21 18:02:26 +08:00
if not success :
continue
2026-06-20 00:57:57 +08:00
success = self . _code_confirm ( )
2024-06-26 19:32:28 +08:00
if success :
2026-06-20 00:57:57 +08:00
logger . info ( " Equipment code apply complete. " )
2025-05-10 15:54:08 +08:00
return True
2024-06-26 19:32:28 +08:00
else :
self . handle_storage_full ( )
2026-06-20 00:57:57 +08:00
else :
return False
2025-05-10 15:54:08 +08:00
2026-06-20 00:57:57 +08:00
def _code_export ( self ) :
self . handle_info_bar ( )
d = self . device . u2
for _ in self . loop ( timeout = 10 ) :
if self . info_bar_count ( ) :
break
if self . appear_then_click ( EQUIPMENT_CODE_EXPORT , offset = ( 5 , 5 ) , interval = 3 ) :
continue
code = d . clipboard
return code
def code_clear ( self , name = None ) :
self . _code_enter ( )
if name is None :
name = self . current_ship ( )
if self . get_code ( name = name ) is None :
self . last_code = self . _code_export ( )
self . set_code ( name = name , code = self . last_code )
self . _code_apply ( code = None )
def code_apply ( self , name = None ) :
self . _code_enter ( )
if name is None :
name = self . current_ship ( )
code = self . get_code ( name = name )
if code is None :
code = self . last_code
self . _code_apply ( code = code )