Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/cn/island/ISLAND_STORAGE_SCROLL_AREA.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/cn/island/TEMPLATE_ISLAND_SEASON_TASK_OBTAINED.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/cn/ui/ISLAND_COMMISSION_CHECK.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/cn/ui/ISLAND_MANAGE_CHECK.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/cn/ui/ISLAND_MAP_CHECK.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/cn/ui/ISLAND_ORDER_CHECK.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/cn/ui/ISLAND_SEASON_CHECK.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/cn/ui/ISLAND_STORAGE_CHECK.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/cn/ui/ISLAND_TECHNOLOGY_CHECK.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/shop/island/Apple Juice.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/shop/island/Apple.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/shop/island/Autumn Bouquet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/shop/island/Autumn Chrysanthemum.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/shop/island/Avocado.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/shop/island/Baa Baa Sheep Feed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/shop/island/Banana and Mango Juice.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/shop/island/Banana.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/shop/island/Bauxite Ore.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/shop/island/Berry and Orange Dessert.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/shop/island/Cable.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/shop/island/Carrot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/shop/island/Cheese.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/shop/island/Citrus Coffee.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/shop/island/Citrus Fruit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/shop/island/Classic Tofu Combo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/shop/island/Clucky Clucky Bird Feed.png
Binary file added assets/shop/island/Coal-Roasted Skewer.png
Binary file added assets/shop/island/Coal.png
Binary file added assets/shop/island/Coffee Beans.png
Binary file added assets/shop/island/Colorful Fruit Paradise.png
Binary file added assets/shop/island/Copper Ore.png
Binary file added assets/shop/island/Corn Cup.png
Binary file added assets/shop/island/Corn.png
Binary file added assets/shop/island/Cotton.png
Binary file added assets/shop/island/Eggs.png
Binary file added assets/shop/island/Elegant Wood.png
Binary file added assets/shop/island/Filing Cabinet.png
Binary file added assets/shop/island/Flax.png
Binary file added assets/shop/island/Floral and Fruity.png
Binary file added assets/shop/island/Flour.png
Binary file added assets/shop/island/Fresh Honey.png
Binary file added assets/shop/island/Fresh Meat.png
Binary file added assets/shop/island/Grass.png
Binary file added assets/shop/island/Hearty Meal.png
Binary file added assets/shop/island/Honey and Lemon Water.png
Binary file added assets/shop/island/Iced Coffee.png
Binary file added assets/shop/island/Iron Ore.png
Binary file added assets/shop/island/Lavender Tea.png
Binary file added assets/shop/island/Lavender.png
Binary file added assets/shop/island/Leather.png
Binary file added assets/shop/island/Lemon.png
Binary file added assets/shop/island/Mango.png
Binary file added assets/shop/island/Matsutake.png
Binary file added assets/shop/island/Milk.png
Binary file added assets/shop/island/Moo Moo Cow Feed.png
Binary file added assets/shop/island/Nails.png
Binary file added assets/shop/island/Napa Cabbage.png
Binary file added assets/shop/island/Oinky Oinky Pig Feed.png
Binary file added assets/shop/island/Omelette.png
Binary file added assets/shop/island/Omurice.png
Binary file added assets/shop/island/Onion.png
Binary file added assets/shop/island/Orange Pie.png
Binary file added assets/shop/island/Peanut Oil.png
Binary file added assets/shop/island/Peanuts.png
Binary file added assets/shop/island/Pelt.png
Binary file added assets/shop/island/Potato.png
Binary file added assets/shop/island/Poultry.png
Binary file added assets/shop/island/Premium Wood.png
Binary file added assets/shop/island/Raw Timber.png
Binary file added assets/shop/island/Reed Flowers.png
Binary file added assets/shop/island/Rice.png
Binary file added assets/shop/island/Rubber.png
Binary file added assets/shop/island/Shoes.png
Binary file added assets/shop/island/Silver Ore.png
Binary file added assets/shop/island/Soy Beans.png
Binary file added assets/shop/island/Steak Bowl.png
Binary file added assets/shop/island/Sticky Rice with Mango.png
Binary file added assets/shop/island/Stir-Fried Chicken.png
Binary file added assets/shop/island/Strawberries.png
Binary file added assets/shop/island/Strawberry Charlotte.png
Binary file added assets/shop/island/Strawberry Honey Frappé.png
Binary file added assets/shop/island/Strawberry Lemon Drink.png
Binary file added assets/shop/island/Succulently Sweet.png
Binary file added assets/shop/island/Sulfur.png
Binary file added assets/shop/island/Sunny Honey.png
Binary file added assets/shop/island/Tea Leaves.png
Binary file added assets/shop/island/Tofu with Minced Meat.png
Binary file added assets/shop/island/Tofu.png
Binary file added assets/shop/island/Utensils.png
Binary file added assets/shop/island/Wheat.png
Binary file added assets/shop/island/Wool.png
Binary file added assets/shop/island/Workable Wood.png
1 change: 1 addition & 0 deletions module/island/assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
# Don't modify it manually.

ISLAND_SEASON_TASK_SCROLL_AREA = Button(area={'cn': (1236, 171, 1237, 604), 'en': (1236, 171, 1237, 604), 'jp': (1236, 171, 1237, 604), 'tw': (1236, 171, 1237, 604)}, color={'cn': (186, 192, 191), 'en': (186, 192, 191), 'jp': (186, 192, 191), 'tw': (186, 192, 191)}, button={'cn': (1236, 171, 1237, 604), 'en': (1236, 171, 1237, 604), 'jp': (1236, 171, 1237, 604), 'tw': (1236, 171, 1237, 604)}, file={'cn': './assets/cn/island/ISLAND_SEASON_TASK_SCROLL_AREA.png', 'en': './assets/cn/island/ISLAND_SEASON_TASK_SCROLL_AREA.png', 'jp': './assets/cn/island/ISLAND_SEASON_TASK_SCROLL_AREA.png', 'tw': './assets/cn/island/ISLAND_SEASON_TASK_SCROLL_AREA.png'})
ISLAND_STORAGE_SCROLL_AREA = Button(area={'cn': (1149, 135, 1153, 547), 'en': (1149, 135, 1153, 547), 'jp': (1149, 135, 1153, 547), 'tw': (1149, 135, 1153, 547)}, color={'cn': (216, 218, 218), 'en': (216, 218, 218), 'jp': (216, 218, 218), 'tw': (216, 218, 218)}, button={'cn': (1149, 135, 1153, 547), 'en': (1149, 135, 1153, 547), 'jp': (1149, 135, 1153, 547), 'tw': (1149, 135, 1153, 547)}, file={'cn': './assets/cn/island/ISLAND_STORAGE_SCROLL_AREA.png', 'en': './assets/cn/island/ISLAND_STORAGE_SCROLL_AREA.png', 'jp': './assets/cn/island/ISLAND_STORAGE_SCROLL_AREA.png', 'tw': './assets/cn/island/ISLAND_STORAGE_SCROLL_AREA.png'})
TEMPLATE_ISLAND_SEASON_TASK_ICON = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_SEASON_TASK_ICON.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_SEASON_TASK_ICON.png', 'jp': './assets/cn/island/TEMPLATE_ISLAND_SEASON_TASK_ICON.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_SEASON_TASK_ICON.png'})
TEMPLATE_ISLAND_SEASON_TASK_OBTAINED = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_SEASON_TASK_OBTAINED.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_SEASON_TASK_OBTAINED.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_SEASON_TASK_OBTAINED.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_SEASON_TASK_OBTAINED.png'})
284 changes: 284 additions & 0 deletions module/island/storage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
import cv2
import numpy as np

import module.config.server as server

from module.base.button import ButtonGrid
from module.base.decorator import cached_property, del_cached_property
from module.base.timer import Timer
from module.base.utils import color_similarity_2d, rgb2gray, xywh2xyxy
from module.island.assets import *
from module.island.data import DIC_ISLAND_ITEM
from module.island.ui import IslandUI, ISLAND_STORAGE_SCROLL
from module.logger import logger
from module.map_detection.utils import Points
from module.ocr.ocr import Digit
from module.statistics.item import Item, ItemGrid
from module.ui.page import page_island_storage


class AmountOcr(Digit):
def pre_process(self, image):
mask = color_similarity_2d(image, color=(75, 76, 78))
bg = np.mean(mask > 230, axis=0)
match = np.where(bg > 0.8)[0]
if len(match):
left = match[0]
total = mask.shape[1]
if left < total:
image = image[:, left:]
image = super().pre_process(image)
return image


if server.server == 'jp':
AMOUNT_OCR = AmountOcr([], letter=(255, 255, 255), name='Amount_ocr')
else:
AMOUNT_OCR = AmountOcr([], lang='cnocr', letter=(218, 218, 218), name='Amount_ocr')


class StorageItem(Item):
def predict_valid(self):
return np.mean(rgb2gray(self.image) > 230) < 0.9


class StorageItemGrid(ItemGrid):
item_class = StorageItem

def match_template(self, image, similarity=None, threshold=5):
return super().match_template(self, image, similarity=similarity, threshold=threshold)

@staticmethod
def item_id_parse(string):
for key, value in DIC_ISLAND_ITEM.items():
if string == value['name']['en']:
return key
logger.warning(f'Unknown item name: {string}')
return None

def predict(self, image, name=True, amount=True, cost=False, price=False, tag=False):
super().predict(image, name, amount, cost, price, tag)
items = []
for item in self.items:
item.item_id = self.item_id_parse(item.name)
if item.item_id is not None:
items.append(item)
self.items = items
return self.items


class IslandStorage(IslandUI):
def _get_bars(self):
"""
Returns:
np.array: [[x1, y1], [x2, y2]], location of the item name icon upper left corner.
"""
area = (299, 135, 1116, 574)
image = self.image_crop(area, copy=True)
gray = color_similarity_2d(image, color=(116, 116, 118))
cv2.inRange(gray, 250, 255, dst=gray)
bars = []
contours, _ = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for cont in contours:
rect = cv2.boundingRect(cv2.convexHull(cont).astype(np.float32))
rect = xywh2xyxy(rect)
# Check max_height
if rect[3] - rect[1] < 10:
continue
# Check item grid should be in the area
if rect[1] < 93:
continue
bars.append(rect)
bars = Points([(0., b[1]) for b in bars]).group(threshold=5)
logger.attr('Items_icon', len(bars))
return bars

def wait_until_bar_appear(self, skip_first_screenshot=True):
"""
After entering island storage page,
items are not loaded that fast,
wait until any bar icon appears
"""
confirm_timer = Timer(1.5, count=3).start()
for _ in self.loop(skip_first=skip_first_screenshot):
bars = self._get_bars()
if len(bars):
if confirm_timer.reached():
return
else:
pass
else:
confirm_timer.reset()

@cached_property
def storage_grid(self):
return self.storage_bar_grid()

def storage_bar_grid(self):
"""
Returns:
ButtonGrid:
"""
bars = self._get_bars()
count = len(bars)
if count == 0:
logger.warning('Unable to find bar icon, assume task list is at top')
origin_y = 169
delta_y = 167
row = 2
elif count == 1:
y_list = bars[:, 1]
# -93 to adjust the bar position to grid position
origin_y = y_list[0] - 93 + 135
delta_y = 167
row = 1
elif count == 2:
y_list = bars[:, 1]
origin_y = min(y_list) - 93 + 135
delta_y = abs(y_list[1] - y_list[0])
row = 2
else:
logger.warning(f'Too many bars found ({count}), assume max rows')
y_list = bars[:, 1]
origin_y = min(y_list) - 93 + 135
delta_y = abs(y_list[1] - y_list[0])
row = 2
storage_grid = ButtonGrid(
origin=(321, origin_y), delta=(142, delta_y),
button_shape=(64, 64), grid_shape=(6, row),
name='STORAGE_ITEM_GRID'
)
return storage_grid

storage_template_folder = './assets/shop/island'

@cached_property
def storage_items(self):
"""
Returns:
ItemGrid:
"""
storage_grid = self.storage_grid
storage_items = StorageItemGrid(
storage_grid,
templates={},
template_area=(0, 0, 64, 54),
amount_area=(18, 74, 77, 91),
)
storage_items.load_template_folder(self.storage_template_folder)
storage_items.amount_ocr = AMOUNT_OCR
return storage_items

def storage_has_loaded(self, items):
"""
Returns:
bool
"""
return any(bool(item.amount) for item in items)

def storage_get_items(self, skip_first_screenshot=True):
"""
Args:
skip_first_screenshot (bool):

Returns:
list[Item]:
"""
storage_items = self.storage_items
if storage_items is None:
logger.warning('Expected type \'StorageItemGrid\' but was None')
return []

# Loop on predict to ensure items
# have loaded and can accurately
# be read
record = 0
timeout = Timer(3, count=9).start()
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()

if self.config.SHOP_EXTRACT_TEMPLATE:
if self.storage_template_folder:
logger.info(f'Extract item templates to {self.storage_template_folder}')
storage_items.extract_template(self.device.image, self.storage_template_folder)
else:
logger.warning('SHOP_EXTRACT_TEMPLATE enabled but shop_template_folder is not set, skip extracting')

storage_items.predict(self.device.image)

if timeout.reached():
logger.warning('Items loading timeout; continue and assumed has loaded')
break

# Check unloaded items, because AL loads items too slow.
items = storage_items.items
known = len([item for item in items if item.is_known_item])
logger.attr('Item detected', known)
if known == 0 or known != record:
record = known
continue
else:
record = known

# End
if self.storage_has_loaded(items):
break

# Log final result on predicted items
items = storage_items.items
grids = storage_items.grids
if len(items):
min_row = grids[0, 0].area[1]
row = [str(item) for item in items if item.button[1] == min_row]
logger.info(f'Storage row 1: {row}')
row = [str(item) for item in items if item.button[1] != min_row]
logger.info(f'Storage row 2: {row}')
return items
else:
logger.info('No storage items found')
return []

def scan_all(self):
"""
Scans all items on the island storage page.

Returns:
dict: {item_id: amount}
"""
logger.hr('Scanning storage items', level=2)
ISLAND_STORAGE_SCROLL.set_top(main=self)
self.wait_until_bar_appear()
items_dict = {}
while 1:
items = self.storage_get_items()
for item in items:
if not items_dict.get(item.item_id):
items_dict[item.item_id] = item.amount

if ISLAND_STORAGE_SCROLL.at_bottom(main=self):
logger.info('Scroll bar reached end, stop')
break
else:
ISLAND_STORAGE_SCROLL.next_page(main=self, page=0.66)
self.device.click_record.pop()
del_cached_property(self, 'storage_grid')
del_cached_property(self, 'storage_items')
continue
return items_dict

def run(self):
"""
Pages:
in: Any page
out: page_island

Returns:
dict: {item_id: amount}
"""
self.ui_ensure(page_island_storage)
self.island_storage_side_navbar_ensure(upper=1)
result = self.scan_all()
return result
45 changes: 43 additions & 2 deletions module/island/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from module.base.decorator import cached_property
from module.island.assets import *
from module.ui.navbar import Navbar
from module.ui.scroll import Scroll
from module.ui.scroll import AdaptiveScroll, Scroll
from module.ui.ui import UI


Expand All @@ -12,6 +12,12 @@
name="ISLAND_SEASON_TASK_SCROLL"
)

ISLAND_STORAGE_SCROLL = AdaptiveScroll(
ISLAND_STORAGE_SCROLL_AREA.button,
background=1,
name="ISLAND_STORAGE_SCROLL"
)


class IslandUI(UI):
def ui_additional(self, get_ship=True):
Expand All @@ -38,6 +44,25 @@ def _island_season_bottom_navbar(self):
active_count=500,
inactive_count=500)

@cached_property
def _island_storage_side_navbar(self):
"""
3 options:
material,
consumable,
special
"""
island_storage_side_navbar = ButtonGrid(
origin=(164, 154), delta=(0, 106.5),
button_shape=(64, 64), grid_shape=(1, 3),
name='ISLAND_STORAGE_SIDE_NAVBAR'
)
return Navbar(grids=island_storage_side_navbar,
active_color=(57, 189, 255),
inactive_color=(57, 58, 64),
active_count=500,
inactive_count=500)

def island_season_bottom_navbar_ensure(self, left=None, right=None):
"""
Args:
Expand All @@ -56,4 +81,20 @@ def island_season_bottom_navbar_ensure(self, left=None, right=None):
"""
if self._island_season_bottom_navbar.set(self, left=left, right=right):
return True
return False
return False

def island_storage_side_navbar_ensure(self, upper=None, bottom=None):
"""
Args:
upper (int):
1 for material,
2 for consumable,
3 for special
bottom (int):
1 for special,
2 for consumable,
3 for material
"""
if self._island_storage_side_navbar.set(self, upper=upper, bottom=bottom):
return True
return False
5 changes: 3 additions & 2 deletions module/statistics/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,13 +217,14 @@ def load_cost_template_folder(self, folder):
self.next_cost_template_index += 1
self.next_cost_template_index = max(self.next_cost_template_index, max_digit + 1)

def match_template(self, image, similarity=None):
def match_template(self, image, similarity=None, threshold=30):
"""
Match templates, try most frequent hit templates first.

Args:
image (np.ndarray):
similarity (float):
threshold (int):

Returns:
str: Template name.
Expand All @@ -236,7 +237,7 @@ def match_template(self, image, similarity=None):
# Match known templates first
names = [name for name in names if not name.isdigit()] + [name for name in names if name.isdigit()]
for name in names:
if color_similar(color1=color, color2=self.colors[name], threshold=30):
if color_similar(color1=color, color2=self.colors[name], threshold=threshold):
res = cv2.matchTemplate(image, self.templates[name], cv2.TM_CCOEFF_NORMED)
_, sim, _, _ = cv2.minMaxLoc(res)
if sim > similarity:
Expand Down
Loading