feat: Better filter implement for OS shops.
BIN
assets/shop/os/ActionPoint100_1.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
BIN
assets/shop/os/GearPartSpecialized_1.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
assets/shop/os/LoggerAbyssalT4_2.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
assets/shop/os/METARedBookT2_1.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
assets/shop/os/PlateRandomT4_1.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
assets/shop/os/PurpleCoins_1.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
assets/shop/os/RepairPackFull2_1.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
assets/shop/os/RepairPackFull_1.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
assets/shop/os/TuningCombatT2_1.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
@ -1617,7 +1617,9 @@
|
||||
"ServerUpdate": "00:00"
|
||||
},
|
||||
"OpsiShop": {
|
||||
"BuySupply": true
|
||||
"BuySupply": true,
|
||||
"PresetFilter": "max_benefit_meta",
|
||||
"CustomFilter": "Logger"
|
||||
},
|
||||
"Storage": {
|
||||
"Storage": {}
|
||||
|
||||
@ -45,7 +45,7 @@ class Filter:
|
||||
"""
|
||||
Args:
|
||||
objs (list): List of objects and strings
|
||||
func (callable): A function to filter object.
|
||||
List[func]|func (callable): A function or a list of funciton that to filter object.
|
||||
Function should receive an object as arguments, and return a bool.
|
||||
True means add it to output.
|
||||
|
||||
@ -68,6 +68,9 @@ class Filter:
|
||||
for obj in objs:
|
||||
if isinstance(obj, str):
|
||||
out.append(obj)
|
||||
elif isinstance(func, list):
|
||||
if all(f(obj) for f in func):
|
||||
out.append(obj)
|
||||
elif func(obj):
|
||||
out.append(obj)
|
||||
else:
|
||||
|
||||
@ -8076,6 +8076,21 @@
|
||||
"BuySupply": {
|
||||
"type": "checkbox",
|
||||
"value": true
|
||||
},
|
||||
"PresetFilter": {
|
||||
"type": "select",
|
||||
"value": "max_benefit_meta",
|
||||
"option": [
|
||||
"max_benefit",
|
||||
"max_benefit_meta",
|
||||
"no_meta",
|
||||
"all",
|
||||
"custom"
|
||||
]
|
||||
},
|
||||
"CustomFilter": {
|
||||
"type": "textarea",
|
||||
"value": "Logger"
|
||||
}
|
||||
},
|
||||
"Storage": {
|
||||
|
||||
@ -622,6 +622,16 @@ OpsiExplore:
|
||||
LastZone: 0
|
||||
OpsiShop:
|
||||
BuySupply: true
|
||||
PresetFilter:
|
||||
value: max_benefit_meta
|
||||
option:
|
||||
- max_benefit
|
||||
- max_benefit_meta
|
||||
- no_meta
|
||||
- all
|
||||
- custom
|
||||
CustomFilter: |-
|
||||
Logger
|
||||
OpsiVoucher:
|
||||
Filter: |-
|
||||
LoggerAbyssal > LoggerObscure > Book > Coin > Fragment
|
||||
|
||||
@ -381,6 +381,8 @@ class GeneratedConfig:
|
||||
|
||||
# Group `OpsiShop`
|
||||
OpsiShop_BuySupply = True
|
||||
OpsiShop_PresetFilter = 'max_benefit_meta' # max_benefit, max_benefit_meta, no_meta, all, custom
|
||||
OpsiShop_CustomFilter = 'Logger'
|
||||
|
||||
# Group `OpsiVoucher`
|
||||
OpsiVoucher_Filter = 'LoggerAbyssal > LoggerObscure > Book > Coin > Fragment'
|
||||
|
||||
@ -2215,6 +2215,19 @@
|
||||
"BuySupply": {
|
||||
"name": "Buy From Port Shops",
|
||||
"help": "Buy all items from port shops\nShop inventory consists of a fixed pool that is reset monthly, items not bought during a cycle has the chance of re-appearing and blocking preferable high value items"
|
||||
},
|
||||
"PresetFilter": {
|
||||
"name": "OpSi Shop Filter",
|
||||
"help": "Generally does not need to be modified. Use \"High value items and META material\"` if Voucher Coins spilled or \"Without META materials\" if you are newcomer.\nHigh value items include ActionPoint, Logger and T4 or higher items; META materials include METABook and META enhance materials.",
|
||||
"max_benefit": "High value items",
|
||||
"max_benefit_meta": "High value items and META materials",
|
||||
"no_meta": "Not to buy META materials",
|
||||
"all": "All",
|
||||
"custom": "custom"
|
||||
},
|
||||
"CustomFilter": {
|
||||
"name": "Custom Research Priority",
|
||||
"help": "To use your own filter, set \"OpSi Shop Filter Select\" to \"custom\". All options have been defined at <https://github.com/LmeSzinc/AzurLaneAutoScript/wiki/filter_string_en>"
|
||||
}
|
||||
},
|
||||
"OpsiVoucher": {
|
||||
|
||||
@ -2215,6 +2215,19 @@
|
||||
"BuySupply": {
|
||||
"name": "OpsiShop.BuySupply.name",
|
||||
"help": "OpsiShop.BuySupply.help"
|
||||
},
|
||||
"PresetFilter": {
|
||||
"name": "OpsiShop.PresetFilter.name",
|
||||
"help": "OpsiShop.PresetFilter.help",
|
||||
"max_benefit": "max_benefit",
|
||||
"max_benefit_meta": "max_benefit_meta",
|
||||
"no_meta": "no_meta",
|
||||
"all": "all",
|
||||
"custom": "custom"
|
||||
},
|
||||
"CustomFilter": {
|
||||
"name": "OpsiShop.CustomFilter.name",
|
||||
"help": "OpsiShop.CustomFilter.help"
|
||||
}
|
||||
},
|
||||
"OpsiVoucher": {
|
||||
|
||||
@ -2215,6 +2215,19 @@
|
||||
"BuySupply": {
|
||||
"name": "购买港口商店",
|
||||
"help": "每月港口商店可购买商品是固定的,未购买的物品下次仍会出现,并阻塞高价值物品,因此需要购买全部"
|
||||
},
|
||||
"PresetFilter": {
|
||||
"name": "港口商店过滤器",
|
||||
"help": "一般默认即可,白票溢出建议选 \"高价值物品与META材料\",萌新建议选 \"不购买META材料\",这会买除了META材料以外的所有东西。\n高价值物品为行动力、坐标和金或者更高级別的商品;META材料为META通用战术教材和4种强化材料。",
|
||||
"max_benefit": "高价值物品",
|
||||
"max_benefit_meta": "高价值物品与META材料",
|
||||
"no_meta": "不购买META材料",
|
||||
"all": "全部",
|
||||
"custom": "自定义"
|
||||
},
|
||||
"CustomFilter": {
|
||||
"name": "自定义过滤器",
|
||||
"help": "使用自定义过滤器需将 \"港口商店过滤器\" 设置为 \"自定义\",并阅读 https://github.com/LmeSzinc/AzurLaneAutoScript/wiki/filter_string_cn"
|
||||
}
|
||||
},
|
||||
"OpsiVoucher": {
|
||||
|
||||
@ -2215,6 +2215,19 @@
|
||||
"BuySupply": {
|
||||
"name": "購買港口商店",
|
||||
"help": "每月港口商店可購買商品是固定的,未購買的物品下次仍會出現,並阻擋高價值物品,因此需要購買全部"
|
||||
},
|
||||
"PresetFilter": {
|
||||
"name": "港口商店過濾器",
|
||||
"help": "一般用預設即可,白票溢出建議選 \"高價值物品與META材料\",新手建議選 \"不購買META材料\",這會買除了META材料以外的所有東西。\n高價值物品為行動點、坐標和金或者更高級別的物品;META材料為META通用戰術教材和4種強化材料。",
|
||||
"max_benefit": "高價值物品",
|
||||
"max_benefit_meta": "高價值物品與META材料",
|
||||
"no_meta": "不購買META材料",
|
||||
"all": "全部",
|
||||
"custom": "自定義過濾器"
|
||||
},
|
||||
"CustomFilter": {
|
||||
"name": "自定義過濾器",
|
||||
"help": "使用自定義過濾器需將 \"港口商店過濾器\" 設定為 \"自定義\",並閱讀 https://github.com/LmeSzinc/AzurLaneAutoScript/wiki/filter_string_cn"
|
||||
}
|
||||
},
|
||||
"OpsiVoucher": {
|
||||
|
||||
18
module/os_handler/preset.py
Normal file
@ -0,0 +1,18 @@
|
||||
OS_SHOP = {
|
||||
'max_benefit': """
|
||||
ActionPoint > DevelopmentMaterialT3 > GearDesignPlan > GearPart > Logger > OrdnanceTestingReport > PlateRandom
|
||||
""",
|
||||
'max_benefit_meta': """
|
||||
ActionPoint > DevelopmentMaterialT3 > GearDesignPlan > GearPart > Logger > OrdnanceTestingReport > PlateRandom >
|
||||
METARedBook > CrystallizedHeatResistantSteel > NanoceramicAlloy > NeuroplasticProstheticArm > SupercavitationGenerator
|
||||
""",
|
||||
'no_meta':"""
|
||||
ActionPoint > DevelopmentMaterial > EnergyStorageDevice > GearDesignPlan > GearPart >
|
||||
Logger > PurpleCoins > PlateRandom > RepairPack > Turing > TuringSample
|
||||
""",
|
||||
'all': """
|
||||
ActionPoint > CrystallizedHeatResistantSteel > DevelopmentMaterial > EnergyStorageDevice > GearDesignPlan > GearPart >
|
||||
Logger > METARedBook > NanoceramicAlloy > NeuroplasticProstheticArm > OrdnanceTestingReport > PurpleCoins > PlateRandom >
|
||||
RepairPack > SupercavitationGenerator > Turing > TuringSample
|
||||
"""
|
||||
}
|
||||
124
module/os_handler/selector.py
Normal file
@ -0,0 +1,124 @@
|
||||
import re
|
||||
from module.config.config_generated import GeneratedConfig
|
||||
|
||||
from module.os_handler.preset import *
|
||||
from module.base.filter import Filter
|
||||
|
||||
FILTER_REGEX = re.compile(
|
||||
'^(actionpoint|crystallizedheatresistantsteel|developmentmaterial'
|
||||
'|energystoragedevice|geardesignplan|gearpart|logger|metaredbook'
|
||||
'|nanoceramicalloy|neuroplasticprostheticarm|ordnancetestingreport'
|
||||
'|platerandom|purplecoins|repairpack|supercavitationgenerator|turingsample'
|
||||
'|turings)'
|
||||
|
||||
'(20|50|100|prototype|specialized|abyssal|obscure|full2|full|triple2|triple|2'
|
||||
'|combat|offence|survival)?'
|
||||
|
||||
'(t[1-6])?$',
|
||||
flags=re.IGNORECASE)
|
||||
FILTER_ATTR = ('group', 'sub_genre', 'tier')
|
||||
FILTER = Filter(FILTER_REGEX, FILTER_ATTR)
|
||||
|
||||
|
||||
class Selector():
|
||||
prise_yellow_coin = 0
|
||||
prise_purple_coin = 0
|
||||
|
||||
def clear_prise(self):
|
||||
self.prise_yellow_coin = 0
|
||||
self.prise_purple_coin = 0
|
||||
|
||||
def pretreatment(self, items) -> list:
|
||||
"""
|
||||
Pretreatment items.
|
||||
|
||||
Args:
|
||||
items:
|
||||
|
||||
Returns:
|
||||
list[Item]:
|
||||
"""
|
||||
_items = []
|
||||
for item in items:
|
||||
item.group, item.sub_genre, item.tier = None, None, None
|
||||
result = re.search(FILTER_REGEX, item.name.lower())
|
||||
if result:
|
||||
item.group, item.sub_genre, item.tier = [group.lower()
|
||||
if group is not None else None
|
||||
for group in result.groups()]
|
||||
_items.append(item)
|
||||
|
||||
return _items
|
||||
|
||||
def enough_coins(self, item) -> bool:
|
||||
"""
|
||||
Check if there are enough coins to buy the item.
|
||||
|
||||
Args:
|
||||
item:
|
||||
|
||||
Returns:
|
||||
bool: True if there are enough coins.
|
||||
"""
|
||||
if item.cost == 'YellowCoins' and self.prise_yellow_coin + item.price <= \
|
||||
self._shop_yellow_coins - (self.config.OS_CL1_YELLOW_COINS_PRESERVE if self.is_cl1_enabled else 0):
|
||||
self.prise_yellow_coin += item.price
|
||||
return True
|
||||
if item.cost == 'PurpleCoins' and self.prise_purple_coin + item.price <= self._shop_purple_coins:
|
||||
self.prise_purple_coin += item.price
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def check_cl1_purple_coins(self, item) -> bool:
|
||||
"""
|
||||
Check if cl1 is enable and item name is PurpleCoins.
|
||||
|
||||
Args:
|
||||
item:
|
||||
|
||||
Returns:
|
||||
bool: False if cl1 is enable and item name is PurpleCoins.
|
||||
"""
|
||||
return not (self.is_cl1_enabled and item.name == 'PurpleCoins')
|
||||
|
||||
def items_filter_in_akashi_shop(self, items) -> list:
|
||||
"""
|
||||
Returns items that can be bought.
|
||||
|
||||
Args:
|
||||
items: Irems to be filtered.
|
||||
|
||||
Returns:
|
||||
list[Item]:
|
||||
"""
|
||||
self.clear_prise()
|
||||
items = self.pretreatment(items)
|
||||
parser = self.config.OpsiGeneral_AkashiShopFilter
|
||||
if not parser.strip():
|
||||
parser = GeneratedConfig.OpsiGeneral_AkashiShopFilter
|
||||
FILTER.load(parser)
|
||||
return FILTER.apply(items, func=self.enough_coins)
|
||||
|
||||
def items_filter_in_os_shop(self, items) -> list:
|
||||
"""
|
||||
Returns items that can be bought.
|
||||
|
||||
Args:
|
||||
items: Items to be filtered.
|
||||
|
||||
Returns:
|
||||
list[Item]:
|
||||
"""
|
||||
self.clear_prise()
|
||||
items = self.pretreatment(items)
|
||||
preset = self.config.OpsiShop_PresetFilter
|
||||
parser = ''
|
||||
if preset == 'custom':
|
||||
parser = self.config.OpsiShop_CustomFilter
|
||||
if not parser.strip():
|
||||
parser = OS_SHOP[GeneratedConfig.OpsiShop_PresetFilter]
|
||||
else:
|
||||
parser = OS_SHOP[preset]
|
||||
FILTER.load(parser)
|
||||
return FILTER.apply(items, func=[self.enough_coins, self.check_cl1_purple_coins])
|
||||
@ -8,8 +8,9 @@ from module.os_handler.assets import *
|
||||
from module.os_handler.map_event import MapEventHandler
|
||||
from module.os_handler.os_status import OSStatus
|
||||
from module.os_handler.ui import OSShopUI
|
||||
from module.statistics.item import ItemGrid
|
||||
from module.os_handler.selector import Selector
|
||||
from module.base.decorator import Config
|
||||
from module.statistics.item import ItemGrid
|
||||
from module.ui.scroll import Scroll
|
||||
from module.shop.assets import AMOUNT_MAX, AMOUNT_MINUS, AMOUNT_PLUS, SHOP_BUY_CONFIRM_AMOUNT, SHOP_BUY_CONFIRM as OS_SHOP_BUY_CONFIRM
|
||||
from module.shop.clerk import OCR_SHOP_AMOUNT
|
||||
@ -37,7 +38,7 @@ class OSShopPrice(DigitYuv):
|
||||
return result
|
||||
|
||||
|
||||
class OSShopHandler(OSStatus, OSShopUI, MapEventHandler):
|
||||
class OSShopHandler(OSStatus, OSShopUI, Selector, MapEventHandler):
|
||||
_shop_yellow_coins = 0
|
||||
_shop_purple_coins = 0
|
||||
|
||||
@ -46,6 +47,13 @@ class OSShopHandler(OSStatus, OSShopUI, MapEventHandler):
|
||||
self._shop_purple_coins = self.get_purple_coins()
|
||||
logger.info(f'Yellow coins: {self._shop_yellow_coins}, purple coins: {self._shop_purple_coins}')
|
||||
|
||||
@Config.when(SERVER='tw')
|
||||
def os_shop_get_coins_in_os_shop(self):
|
||||
self._shop_yellow_coins = self.get_yellow_coins()
|
||||
self._shop_purple_coins = self.get_purple_coins()
|
||||
logger.info(f'Yellow coins: {self._shop_yellow_coins}, purple coins: {self._shop_purple_coins}')
|
||||
|
||||
@Config.when(SERVER=None)
|
||||
def os_shop_get_coins_in_os_shop(self):
|
||||
self._shop_yellow_coins = self.get_yellow_coins()
|
||||
self._shop_purple_coins = self.get_purple_coins_in_os_shop()
|
||||
@ -53,7 +61,7 @@ class OSShopHandler(OSStatus, OSShopUI, MapEventHandler):
|
||||
|
||||
@cached_property
|
||||
@Config.when(SERVER='tw')
|
||||
def os_shop_items(self):
|
||||
def os_shop_items(self) -> ItemGrid:
|
||||
"""
|
||||
Returns:
|
||||
ItemGrid:
|
||||
@ -69,7 +77,7 @@ class OSShopHandler(OSStatus, OSShopUI, MapEventHandler):
|
||||
|
||||
@cached_property
|
||||
@Config.when(SERVER='en')
|
||||
def os_shop_items(self):
|
||||
def os_shop_items(self) -> ItemGrid:
|
||||
"""
|
||||
Returns:
|
||||
ItemGrid:
|
||||
@ -85,7 +93,7 @@ class OSShopHandler(OSStatus, OSShopUI, MapEventHandler):
|
||||
|
||||
@cached_property
|
||||
@Config.when(SERVER=None)
|
||||
def os_shop_items(self):
|
||||
def os_shop_items(self) -> ItemGrid:
|
||||
"""
|
||||
Returns:
|
||||
ItemGrid:
|
||||
@ -207,55 +215,27 @@ class OSShopHandler(OSStatus, OSShopUI, MapEventHandler):
|
||||
"""
|
||||
costs = self._get_os_shop_cost()
|
||||
items = []
|
||||
|
||||
for cost in costs:
|
||||
shop_items = self._get_os_shop_items(cost)
|
||||
if self.config.SHOP_EXTRACT_TEMPLATE:
|
||||
shop_items.extract_template(self.device.image, './assets/shop/os')
|
||||
shop_items.predict(self.device.image, name=name, amount=name, cost=True, price=True)
|
||||
shop_items = shop_items.items
|
||||
|
||||
if len(shop_items):
|
||||
row = [str(item) for item in shop_items]
|
||||
logger.info(f'Shop items found: {row}')
|
||||
items += self.items_filter_in_os_shop(shop_items)
|
||||
items += shop_items
|
||||
else:
|
||||
logger.info('No shop items found')
|
||||
|
||||
return items
|
||||
|
||||
def items_filter_in_os_shop(self, items) -> list:
|
||||
def os_shop_get_item_to_buy_in_akashi(self) -> list:
|
||||
"""
|
||||
Returns items that can be bought.
|
||||
|
||||
Args:
|
||||
items: Items to be filtered.
|
||||
|
||||
Returns:
|
||||
list[Item]:
|
||||
"""
|
||||
_items = []
|
||||
prise_yellow_coin = 0
|
||||
prise_purple_coin = 0
|
||||
|
||||
for item in items:
|
||||
if self.is_cl1_enabled and item.name == 'PurpleCoins':
|
||||
continue
|
||||
if item.cost == 'YellowCoins' and prise_yellow_coin + item.price <= \
|
||||
self._shop_yellow_coins - (self.config.OS_CL1_YELLOW_COINS_PRESERVE if self.is_cl1_enabled else 0):
|
||||
prise_yellow_coin += item.price
|
||||
_items.append(item)
|
||||
continue
|
||||
if item.cost == 'PurpleCoins' and prise_purple_coin + item.price <= self._shop_purple_coins:
|
||||
prise_purple_coin += item.price
|
||||
_items.append(item)
|
||||
continue
|
||||
|
||||
return _items
|
||||
|
||||
def os_shop_get_item_to_buy_in_akashi(self):
|
||||
"""
|
||||
Returns:
|
||||
Item:
|
||||
"""
|
||||
self.os_shop_get_coins()
|
||||
items = self.os_shop_get_items_in_akashi(name=True)
|
||||
# Shop supplies do not appear immediately, need to confirm if shop is empty.
|
||||
@ -269,40 +249,8 @@ class OSShopHandler(OSStatus, OSShopUI, MapEventHandler):
|
||||
else:
|
||||
break
|
||||
|
||||
try:
|
||||
selection = self.config.OpsiGeneral_AkashiShopFilter.replace(' ', '').replace('\n', '').split('>')
|
||||
except Exception:
|
||||
logger.warning(f'Invalid OS akashi buy filter string: {self.config.OpsiGeneral_AkashiShopFilter}')
|
||||
return None
|
||||
return self.items_filter_in_os_shop(items)
|
||||
|
||||
# TODO: Better filter for Akashi shop.
|
||||
for select in selection:
|
||||
for item in items:
|
||||
if select not in item.name:
|
||||
continue
|
||||
if item.cost == 'YellowCoins':
|
||||
if item.price > self._shop_yellow_coins:
|
||||
continue
|
||||
if item.cost == 'PurpleCoins':
|
||||
if item.price > self._shop_purple_coins:
|
||||
continue
|
||||
|
||||
return item
|
||||
|
||||
return None
|
||||
|
||||
@Config.when(SERVER='tw')
|
||||
def os_shop_get_item_to_buy_in_port(self):
|
||||
"""
|
||||
Returns:
|
||||
Item:
|
||||
"""
|
||||
self.os_shop_get_coins()
|
||||
logger.attr('CL1 enabled', self.is_cl1_enabled)
|
||||
|
||||
return self.os_shop_get_items(name=True)
|
||||
|
||||
@Config.when(SERVER=None)
|
||||
def os_shop_get_item_to_buy_in_port(self) -> list:
|
||||
"""
|
||||
Returns:
|
||||
@ -320,12 +268,12 @@ class OSShopHandler(OSStatus, OSShopUI, MapEventHandler):
|
||||
items = self.os_shop_get_items(name=True)
|
||||
continue
|
||||
else:
|
||||
self.os_shop_items.items = items
|
||||
return items
|
||||
self.os_shop_items.items = self.items_filter_in_os_shop(items)
|
||||
return self.os_shop_items.items
|
||||
|
||||
return []
|
||||
|
||||
def os_shop_buy_execute(self, button, skip_first_screenshot=True):
|
||||
def os_shop_buy_execute(self, button, skip_first_screenshot=True) -> bool:
|
||||
"""
|
||||
Args:
|
||||
button: Item to buy
|
||||
@ -378,32 +326,7 @@ class OSShopHandler(OSStatus, OSShopUI, MapEventHandler):
|
||||
|
||||
return success
|
||||
|
||||
def os_shop_buy(self, select_func):
|
||||
"""
|
||||
Args:
|
||||
select_func:
|
||||
|
||||
Returns:
|
||||
int: Items bought.
|
||||
|
||||
Pages:
|
||||
in: PORT_SUPPLY_CHECK
|
||||
"""
|
||||
count = 0
|
||||
for _ in range(12):
|
||||
button = select_func()
|
||||
if button is None:
|
||||
logger.info('Shop buy finished')
|
||||
return count
|
||||
else:
|
||||
self.os_shop_buy_execute(button)
|
||||
count += 1
|
||||
continue
|
||||
|
||||
logger.warning('Too many items to buy, stopped')
|
||||
return count
|
||||
|
||||
def os_shop_buy_2(self, select_func) -> int:
|
||||
def os_shop_buy(self, select_func) -> int:
|
||||
"""
|
||||
Args:
|
||||
select_func:
|
||||
@ -422,7 +345,7 @@ class OSShopHandler(OSStatus, OSShopUI, MapEventHandler):
|
||||
logger.info('No items need to be purchased')
|
||||
continue
|
||||
for button in buttons:
|
||||
if count >= 5:
|
||||
if count >= 10:
|
||||
logger.info('Shop buy finished')
|
||||
return count
|
||||
else:
|
||||
@ -453,7 +376,7 @@ class OSShopHandler(OSStatus, OSShopUI, MapEventHandler):
|
||||
if item.cost == 'YellowCoins' else self._shop_purple_coins
|
||||
if (_currency < item.price):
|
||||
return False
|
||||
|
||||
|
||||
if self.appear(AMOUNT_MAX, offset=(50, 50)):
|
||||
limit = None
|
||||
for _ in range(3):
|
||||
@ -472,11 +395,11 @@ class OSShopHandler(OSStatus, OSShopUI, MapEventHandler):
|
||||
diff = limit - total
|
||||
if diff > 0:
|
||||
limit = total
|
||||
|
||||
self.ui_ensure_index(limit, letter=OCR_SHOP_AMOUNT, prev_button=AMOUNT_MINUS, next_button=AMOUNT_PLUS,
|
||||
skip_first_screenshot=True)
|
||||
|
||||
self.device.click(SHOP_BUY_CONFIRM_AMOUNT)
|
||||
skip_first_screenshot=True)
|
||||
|
||||
self.appear_then_click(OS_SHOP_BUY_CONFIRM, offset=(20, 20))
|
||||
self.appear_then_click(SHOP_BUY_CONFIRM_AMOUNT, offset=(20, 20))
|
||||
|
||||
return True
|
||||
|
||||
@ -503,23 +426,25 @@ class OSShopHandler(OSStatus, OSShopUI, MapEventHandler):
|
||||
Pages:
|
||||
in: PORT_SUPPLY_CHECK
|
||||
"""
|
||||
_count = 0
|
||||
for i in range(4):
|
||||
count = 0
|
||||
self.os_shop_side_navbar_ensure(upper=i + 1)
|
||||
OS_SHOP_SCROLL.set_top(main=self)
|
||||
self.os_shop_side_navbar_ensure(bottom=i + 1)
|
||||
OS_SHOP_SCROLL.set_bottom(main=self)
|
||||
|
||||
while True:
|
||||
count += self.os_shop_buy_2(select_func=self.os_shop_get_item_to_buy_in_port)
|
||||
if count >= 5:
|
||||
count += self.os_shop_buy(select_func=self.os_shop_get_item_to_buy_in_port)
|
||||
if count >= 10:
|
||||
break
|
||||
elif OS_SHOP_SCROLL.at_bottom(main=self):
|
||||
elif OS_SHOP_SCROLL.at_top(main=self):
|
||||
logger.info('OS shop reach bottom, stop')
|
||||
break
|
||||
else:
|
||||
OS_SHOP_SCROLL.next_page(main=self, page=0.66)
|
||||
OS_SHOP_SCROLL.prev_page(main=self, page=0.66)
|
||||
continue
|
||||
_count += count
|
||||
|
||||
return count > 0 or len(self.os_shop_items.items) == 0
|
||||
return _count > 0 or len(self.os_shop_items.items) == 0
|
||||
|
||||
def handle_akashi_supply_buy(self, grid):
|
||||
"""
|
||||
|
||||