mirror of
https://github.com/sui-feng-cb/AzurLaneAutoScript1.git
synced 2026-07-04 11:59:06 +08:00
196 lines
7.2 KiB
Python
196 lines
7.2 KiB
Python
from module.combat.assets import GET_ITEMS_1
|
|
from module.logger import logger
|
|
from module.meowfficer.assets import *
|
|
from module.meowfficer.base import MeowfficerBase
|
|
from module.ocr.ocr import Digit, DigitCounter
|
|
from module.ui.assets import MEOWFFICER_GOTO_DORMMENU
|
|
|
|
BUY_MAX = 15
|
|
BUY_PRIZE = 1500
|
|
MEOWFFICER = DigitCounter(OCR_MEOWFFICER, letter=(140, 113, 99), threshold=64)
|
|
MEOWFFICER_CHOOSE = Digit(OCR_MEOWFFICER_CHOOSE, letter=(140, 113, 99), threshold=64)
|
|
MEOWFFICER_COINS = Digit(OCR_MEOWFFICER_COINS, letter=(99, 69, 41), threshold=64)
|
|
|
|
|
|
class MeowfficerBuy(MeowfficerBase):
|
|
def meow_get_buy_count(self, buy_amount, overflow_th):
|
|
"""
|
|
OCR remaining buys and coins, combine with user configs to decide
|
|
how many meowfficer boxes to buy this run.
|
|
|
|
Args:
|
|
buy_amount (int): User configured purchase amount (Meowfficer_BuyAmount).
|
|
overflow_th (int): Coin overflow threshold (Meowfficer_OverflowCoins),
|
|
< 0 to disable overflow buy.
|
|
|
|
Pages:
|
|
in: page_meowfficer
|
|
|
|
Returns:
|
|
int: 0 to BUY_MAX, number of boxes to buy now.
|
|
"""
|
|
for _ in self.loop(timeout=2):
|
|
remain, bought, total = MEOWFFICER.ocr(self.device.image)
|
|
coins = MEOWFFICER_COINS.ocr(self.device.image)
|
|
if total > 0:
|
|
break
|
|
# else: retry if MEOWFFICER has ocr error
|
|
else:
|
|
logger.warning('Failed to get meowfficer buy status')
|
|
return 0
|
|
|
|
logger.attr('Meowfficer_remain', remain)
|
|
logger.attr('Meowfficer_coins', coins)
|
|
|
|
if total != BUY_MAX:
|
|
logger.warning(f'Invalid meowfficer buy limit: {total}, revise to {BUY_MAX}')
|
|
total = BUY_MAX
|
|
bought = total - remain
|
|
|
|
return self._meow_get_buy_count(bought, total, coins, buy_amount, overflow_th)
|
|
|
|
@staticmethod
|
|
def _meow_get_buy_count(bought, total, coins, buy_amount, overflow_th):
|
|
"""
|
|
Calculate how many meowfficer boxes to buy.
|
|
|
|
Baseline: buy up to Meowfficer_BuyAmount per day.
|
|
Overflow: when Meowfficer_OverflowCoins >= 0 and current coins
|
|
exceed it, keep buying extra boxes until coins drop to threshold or
|
|
today's quota runs out. The 1st box per day is free.
|
|
|
|
Args:
|
|
bought (int): Number of boxes already bought today.
|
|
total (int): Total available boxes per day (typically BUY_MAX=15).
|
|
coins (int): Current coins.
|
|
buy_amount (int): User configured purchase amount (Meowfficer_BuyAmount).
|
|
overflow_th (int): Coin overflow threshold (Meowfficer_OverflowCoins),
|
|
< 0 to disable overflow buy.
|
|
|
|
Returns:
|
|
int: 0 to BUY_MAX, number of boxes to buy now.
|
|
"""
|
|
today_left = max(0, total - bought)
|
|
if today_left <= 0:
|
|
logger.info(f'Already bought {bought}/{total} today, stopped')
|
|
return 0
|
|
|
|
# Baseline buy
|
|
baseline = min(max(0, buy_amount - bought), today_left)
|
|
|
|
# Overflow buy
|
|
extra = 0
|
|
if overflow_th >= 0 and coins > overflow_th:
|
|
if bought == 0:
|
|
# First box of the day is free, compensate so (extra-1)*BUY_PRIZE
|
|
# coins are spent, ensuring coins drop below overflow_th
|
|
extra = -(-(coins - overflow_th + BUY_PRIZE) // BUY_PRIZE)
|
|
else:
|
|
extra = -(-(coins - overflow_th) // BUY_PRIZE)
|
|
extra = min(extra, today_left - baseline)
|
|
extra = max(0, extra)
|
|
|
|
count = baseline + extra
|
|
|
|
# Cap by affordable coins, the 1st box per day is free
|
|
free = 1 if bought == 0 else 0
|
|
affordable = coins // BUY_PRIZE + free
|
|
if count > affordable:
|
|
logger.info(f'Current coins only afford to buy {affordable}')
|
|
count = affordable
|
|
|
|
logger.info(
|
|
f'Meowfficer buy plan: count={count}, baseline={baseline}, '
|
|
f'overflow={extra}, bought={bought}/{total}, coins={coins}'
|
|
)
|
|
return count
|
|
|
|
def meow_choose(self, count) -> None:
|
|
"""
|
|
Navigate to MEOWFFICER_BUY and set buy index to `count`.
|
|
|
|
Pages:
|
|
in: page_meowfficer
|
|
out: MEOWFFICER_BUY
|
|
|
|
Args:
|
|
count (int): 1 to BUY_MAX.
|
|
"""
|
|
self.meow_enter(MEOWFFICER_BUY_ENTER, check_button=MEOWFFICER_BUY)
|
|
|
|
# info_bar may covers OCR_MEOWFFICER_CHOOSE,
|
|
# and OCR_MEOWFFICER_CHOOSE may detected as 0 causing extra clickings
|
|
# info_bar is usually from the previous Dorm task or meowfficer fort
|
|
self.handle_info_bar()
|
|
|
|
self.ui_ensure_index(count, letter=MEOWFFICER_CHOOSE, prev_button=MEOWFFICER_BUY_PREV,
|
|
next_button=MEOWFFICER_BUY_NEXT, skip_first_screenshot=True)
|
|
|
|
def meow_confirm(self, skip_first_screenshot=True) -> None:
|
|
"""
|
|
Pages:
|
|
in: MEOWFFICER_BUY
|
|
out: page_meowfficer
|
|
"""
|
|
# Here uses a simple click, to avoid clicking MEOWFFICER_BUY multiple times.
|
|
logger.hr('Meow confirm')
|
|
executed = False
|
|
with self.stat.new(
|
|
genre="meowfficer_buy",
|
|
method=self.config.DropRecord_MeowfficerBuy,
|
|
) as drop:
|
|
while 1:
|
|
if skip_first_screenshot:
|
|
skip_first_screenshot = False
|
|
else:
|
|
self.device.screenshot()
|
|
|
|
if self.appear(MEOWFFICER_BUY, offset=(20, 20), interval=3):
|
|
if executed:
|
|
self.device.click(MEOWFFICER_GOTO_DORMMENU)
|
|
else:
|
|
self.device.click(MEOWFFICER_BUY)
|
|
continue
|
|
if self.handle_meow_popup_confirm():
|
|
executed = True
|
|
continue
|
|
if self.appear_then_click(MEOWFFICER_BUY_SKIP, interval=3):
|
|
executed = True
|
|
continue
|
|
if self.appear(GET_ITEMS_1, offset=5, interval=3):
|
|
if drop.save is True:
|
|
drop.handle_add(self, before=2)
|
|
self.device.click(MEOWFFICER_BUY_SKIP)
|
|
self.interval_clear(MEOWFFICER_BUY)
|
|
executed = True
|
|
continue
|
|
# Rare case that MEOWFFICER_INFO popups here
|
|
if self.meow_additional():
|
|
continue
|
|
|
|
# End
|
|
if self.match_template_color(MEOWFFICER_BUY_ENTER, offset=(20, 20)):
|
|
break
|
|
|
|
def meow_buy(self) -> None:
|
|
"""
|
|
Buy meowfficer boxes according to baseline and optional overflow plan.
|
|
|
|
Pages:
|
|
in: page_meowfficer
|
|
out: page_meowfficer
|
|
"""
|
|
logger.hr('Meowfficer buy', level=1)
|
|
|
|
buy_amount = self.config.Meowfficer_BuyAmount
|
|
buy_amount = max(min(buy_amount, 15), 1)
|
|
overflow_th = self.config.Meowfficer_OverflowCoins
|
|
|
|
count = self.meow_get_buy_count(buy_amount, overflow_th)
|
|
if count <= 0:
|
|
return
|
|
self.meow_choose(count)
|
|
self.meow_confirm()
|
|
|
|
logger.warning('Too many trial in meowfficer buy, stopped.')
|