Skip to content
Open
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ var/
.idea/
.vscode/
venv
env39
tests/validation_images/*.png
Comment on lines +30 to +31
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Por curiosidade, o que gerou esses folders?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

env39/
pasta do venv que criei dentro da pasta.

Fiz um metodo pra criar imagens desenhando um quadrado na parte selecinada baseado na posição recebida pelos metodos, pra validação visual dos metodos
tests/validation_images/*.png

12 changes: 9 additions & 3 deletions src/repositories/gameWindow/core.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
from typing import Tuple, Union
from typing import Tuple, Union, Dict
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eu sugeria eu ordenar os imports para ficar mais organizado:

Suggested change
from typing import Tuple, Union, Dict
from typing import Dict, Tuple, Union

from src.shared.typings import BBox, Coordinate, GrayImage, Slot
from src.utils.core import hashit, locate
from .config import arrowsImagesHashes, gameWindowCache, images

def get_global_game_cache_window_cache() -> Dict:
"""
function to ease mocking the cache
"""
global gameWindowCache
return gameWindowCache
Comment on lines +6 to +11
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pode explicar o que aconteceu aqui? Evita o snake, estou usando o lowerUpperCase getGlobalGameCacheWindow

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flake8 usa o snake case, criei o metodo pra facilitar o mock, o mock anterior não funcionava


# TODO: add unit tests
# TODO: add perf
def getLeftArrowPosition(screenshot: GrayImage) -> Union[BBox, None]:
global gameWindowCache
gameWindowCache = get_global_game_cache_window_cache()
if gameWindowCache['left']['position'] is not None:
leftArrowImage = images['arrows'][gameWindowCache['left']['arrow']]
leftArrowImageHash = hashit(leftArrowImage)
Expand Down Expand Up @@ -38,7 +44,7 @@ def getLeftArrowPosition(screenshot: GrayImage) -> Union[BBox, None]:
# TODO: add unit tests
# TODO: add perf
def getRightArrowPosition(screenshot: GrayImage) -> Union[BBox, None]:
global gameWindowCache
gameWindowCache = get_global_game_cache_window_cache()
if gameWindowCache['right']['position'] is not None:
images['arrows'][gameWindowCache['right']['arrow']]
rightArrowImage = images['arrows'][gameWindowCache['right']['arrow']]
Expand Down
16 changes: 16 additions & 0 deletions src/utils/camera.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

import pyautogui
import cv2
import numpy as np

class PyCamera():
is_capturing = True

def get_latest_frame(self, path='screen.png'):
img = pyautogui.screenshot()
img = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2GRAY)
if path:
# import cv2; cv2.imwrite('screen_test.png', screenshot)
cv2.imwrite(path, img)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deveria evitar qualquer escrita em disco uma vez que atrasa muito o processamento.

return img

Comment on lines +1 to +16
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seria legal criar uma classe com Polimorfismo para decidir qual SO usar e qual lib usar.

o DxCam serve para o windows, dxlib serve para linux, tb deve ser para mac, que tal tentar? Performance interessa muito nesse projeto.

Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
from src.utils.image import loadFromRGBToGray


actionBarPath = 'src/features/actionBar'
actionBarPath = 'src/repositories/actionBar'
currentPath = pathlib.Path(__file__).parent.resolve()
screenshotImage = loadFromRGBToGray(f'{currentPath}/screenshot.png')
listOfCooldownsImage = loadFromRGBToGray(f'{currentPath}/listOfCooldownsImage.png')
cooldownImage = loadFromRGBToGray(f'{actionBarPath}/images/cooldowns/exori.png')


def test_should_return_None_when_getCooldownsImage_return_None(mocker):
getCooldownsImageSpy = mocker.patch('src.repositories.actionBar.extractors.getCooldownsImage', return_value=None)
getCooldownsImageSpy = mocker.patch('src.repositories.actionBar.core.getCooldownsImage', return_value=None)
locateSpy = mocker.patch('src.utils.core.locate', return_value=None)
hasCooldown = hasCooldownByImage(screenshotImage, cooldownImage)
expectedHasCooldownByImage = None
Expand All @@ -21,8 +21,8 @@ def test_should_return_None_when_getCooldownsImage_return_None(mocker):


def test_should_return_False_when_locate_return_None(mocker):
getCooldownsImageSpy = mocker.patch('src.repositories.actionBar.extractors.getCooldownsImage', return_value=listOfCooldownsImage)
locateSpy = mocker.patch('src.utils.core.locate', return_value=None)
getCooldownsImageSpy = mocker.patch('src.repositories.actionBar.core.getCooldownsImage', return_value=listOfCooldownsImage)
locateSpy = mocker.patch('src.repositories.actionBar.core.locate', return_value=None)
hasCooldown = hasCooldownByImage(screenshotImage, cooldownImage)
expectedHasCooldownByImage = False
assert hasCooldown == expectedHasCooldownByImage
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pode remover essa linha em branco?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pode, desculpa

import numpy as np
import pathlib
from src.repositories.actionBar.extractors import getCooldownsImage
Expand All @@ -10,10 +11,8 @@


def test_should_return_None_when_cannot_get_left_arrows_position(mocker):
getLeftArrowsPositionSpy = mocker.patch(
'actionBar.locators.getLeftArrowsPosition', return_value=None)
getRightArrowsPositionSpy = mocker.patch(
'actionBar.locators.getRightArrowsPosition', return_value=None)
getLeftArrowsPositionSpy = mocker.patch('src.repositories.actionBar.extractors.getLeftArrowsPosition', return_value=None)
getRightArrowsPositionSpy = mocker.patch('src.repositories.actionBar.extractors.getRightArrowsPosition', return_value=None)
cooldownsImage = getCooldownsImage(screenshotImage)
expectedCooldownsImage = None
assert cooldownsImage is expectedCooldownsImage
Expand All @@ -23,9 +22,9 @@ def test_should_return_None_when_cannot_get_left_arrows_position(mocker):

def test_should_return_None_when_cannot_get_right_arrows_position(mocker):
getLeftArrowsPositionSpy = mocker.patch(
'actionBar.locators.getLeftArrowsPosition', return_value=(0, 392, 17, 34))
'src.repositories.actionBar.extractors.getLeftArrowsPosition', return_value=(0, 392, 17, 34))
getRightArrowsPositionSpy = mocker.patch(
'actionBar.locators.getRightArrowsPosition', return_value=None)
'src.repositories.actionBar.extractors.getRightArrowsPosition', return_value=None)
result = getCooldownsImage(screenshotImage)
assert result == None
getLeftArrowsPositionSpy.assert_called_once_with(screenshotImage)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@


def test_should_return_an_empty_array_when_filled_slots_count_is_zero(mocker):
getFilledSlotsCountSpy = mocker.patch('battleList.core.getFilledSlotsCount', return_value=0)
getBeingAttackedCreaturesSpy = mocker.patch('battleList.core.getBeingAttackedCreatures')
getCreaturesNamesSpy = mocker.patch('battleList.core.getCreaturesNames')
getFilledSlotsCountSpy = mocker.patch('src.repositories.battleList.core.getFilledSlotsCount', return_value=0)
getBeingAttackedCreaturesSpy = mocker.patch('src.repositories.battleList.core.getBeingAttackedCreatures')
getCreaturesNamesSpy = mocker.patch('src.repositories.battleList.core.getCreaturesNames')
content = np.array([], dtype=np.uint8)
creatures = getCreatures(content)
expectedCreatures = np.array([], dtype=Creature)
Expand All @@ -18,9 +18,9 @@ def test_should_return_an_empty_array_when_filled_slots_count_is_zero(mocker):

def test_should_return_an_array_of_creatures_when_filled_slots_count_is_greater_than_zero(mocker):
creature = ('Rat', True)
getFilledSlotsCountSpy = mocker.patch('battleList.core.getFilledSlotsCount', return_value=1)
getBeingAttackedCreaturesSpy = mocker.patch('battleList.core.getBeingAttackedCreatures', return_value=[True])
getCreaturesNamesSpy = mocker.patch('battleList.core.getCreaturesNames', return_value=['Rat'])
getFilledSlotsCountSpy = mocker.patch('src.repositories.battleList.core.getFilledSlotsCount', return_value=1)
getBeingAttackedCreaturesSpy = mocker.patch('src.repositories.battleList.core.getBeingAttackedCreatures', return_value=[True])
getCreaturesNamesSpy = mocker.patch('src.repositories.battleList.core.getCreaturesNames', return_value=['Rat'])
content = np.array([], dtype=np.uint8)
creatures = getCreatures(content)
expectedCreatures = np.array([creature], dtype=Creature)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@


def test_should_return_None_when_container_top_bar_position_is_None(mocker):
getContainerTopBarPositionSpy = mocker.patch('battleList.extractors.getContainerTopBarPosition', return_value=None)
getContainerBottomBarPositionSpy = mocker.patch('battleList.extractors.getContainerBottomBarPosition', return_value=None)
getContainerTopBarPositionSpy = mocker.patch('src.repositories.battleList.extractors.getContainerTopBarPosition', return_value=None)
getContainerBottomBarPositionSpy = mocker.patch('src.repositories.battleList.extractors.getContainerBottomBarPosition', return_value=None)
content = getContent(screenshotImage)
expectedContent = None
assert content == expectedContent
Expand All @@ -19,8 +19,8 @@ def test_should_return_None_when_container_top_bar_position_is_None(mocker):


def test_should_return_None_when_container_bottom_bar_position_is_None(mocker):
getContainerTopBarPositionSpy = mocker.patch('battleList.extractors.getContainerTopBarPosition', return_value=(1572, 25, 81, 13))
getContainerBottomBarPositionSpy = mocker.patch('battleList.extractors.getContainerBottomBarPosition', return_value=None)
getContainerTopBarPositionSpy = mocker.patch('src.repositories.battleList.extractors.getContainerTopBarPosition', return_value=(1572, 25, 81, 13))
getContainerBottomBarPositionSpy = mocker.patch('src.repositories.battleList.extractors.getContainerBottomBarPosition', return_value=None)
content = getContent(screenshotImage)
expectedContent = None
assert content == expectedContent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from src.repositories.battleList.locators import getContainerBottomBarPosition
from src.utils.image import loadFromRGBToGray

from tests.utils import result_pos_draw

Comment on lines 2 to +6
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
from src.repositories.battleList.locators import getContainerBottomBarPosition
from src.utils.image import loadFromRGBToGray
from tests.utils import result_pos_draw
from src.repositories.battleList.locators import getContainerBottomBarPosition
from src.utils.image import loadFromRGBToGray
from tests.utils import result_pos_draw


currentPath = pathlib.Path(__file__).parent.resolve()

Expand All @@ -10,5 +12,8 @@
def test_should_get_container_bottom_bar_pos():
screenshotImage = loadFromRGBToGray(f'{currentPath}/screenshot.png')
containerBottomBarPos = getContainerBottomBarPosition(screenshotImage)
expectedContainerBottomBarPos = (1748, 621, 156, 4)
# save for conference
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove o comentário

result_pos_draw(screenshotImage, containerBottomBarPos, 'test_should_get_container_bottom_bar_pos.png')

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove essa linh

expectedContainerBottomBarPos = (1572, 1036, 156, 4)
assert containerBottomBarPos == expectedContainerBottomBarPos
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Essa screenshot serve para qual caso? Renomeia para o caso em especifico.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seria interessante se as imagens fossem sempre em RGB pois o load automaticamente converte para gray.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Essa screenshot serve para qual caso? Renomeia para o caso em especifico.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Essa screenshot serve para qual caso? Renomeia para o caso em especifico.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Essa screenshot serve para qual caso? Renomeia para o caso em especifico.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
84 changes: 84 additions & 0 deletions tests/unit/repositories/gameWindow/test_arrows.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import pathlib
import cv2
import numpy as np
import pytest

from src.repositories.gameWindow.core import getLeftArrowPosition, getRightArrowPosition

from tests.utils import result_pos_draw
Comment on lines +1 to +8
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import pathlib
import cv2
import numpy as np
import pytest
from src.repositories.gameWindow.core import getLeftArrowPosition, getRightArrowPosition
from tests.utils import result_pos_draw
import cv2
import numpy as np
import pathlib
import pytest
from src.repositories.gameWindow.core import getLeftArrowPosition, getRightArrowPosition
from tests.utils import result_pos_draw



currentPath = pathlib.Path(__file__).parent.resolve()
img01 = f'{currentPath}/screenshot01.png'
img02_gray = f'{currentPath}/screenshot02_gray.png'
img03 = f'{currentPath}/screenshot03.png'
img04 = f'{currentPath}/screenshot04.png'


def rgb_to_gray(img_path: str, is_gray=False):
img = cv2.imread(img_path)
if is_gray:
return cv2.cvtColor(np.array(img), cv2.COLOR_RGB2GRAY)
else:
return cv2.cvtColor(np.array(img), cv2.COLOR_RGB2GRAY)


@pytest.mark.parametrize("img, is_gray", [
(img01, False),
(img02_gray, True),
(img03, False),
(img04, False),
])
Comment on lines +26 to +31
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Qual a idéia aqui?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

usar diversas imagens como input do teste unitario, sendo alguns 1920X1080 e outras resolução mac os(16:10)

def test_getLeftArrowPosition(mocker, img, is_gray):
# clean preview test
this_gameWindowCache = {
'left': {'arrow': None, 'position': None},
'right': {'arrow': None, 'position': None},
}
mocker.patch('src.repositories.gameWindow.core.get_global_game_cache_window_cache', return_value=this_gameWindowCache)
# ----------------------------------
img_gray = rgb_to_gray(img, is_gray)
result = getLeftArrowPosition(img_gray)
assert result is not None
assert result == (2, 23, 7, 54)


@pytest.mark.parametrize("img, is_gray", [
(img01, False),
(img02_gray, True),
(img03, False),
])
Comment on lines +46 to +50
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Qual a idéia aqui?

def test_getRightArrowPosition(mocker, img, is_gray):
# clean preview test
this_gameWindowCache = {
'left': {'arrow': None, 'position': None},
'right': {'arrow': None, 'position': None},
}
mocker.patch('src.repositories.gameWindow.core.get_global_game_cache_window_cache', return_value=this_gameWindowCache)
# ----------------------------------
img_gray = rgb_to_gray(img, is_gray)
result = getRightArrowPosition(img_gray)
# result == x, y, width, height
assert result is not None
# img04 should be differrent
result_pos_draw(img_gray,result,f"test_getRightArrowPosition__{img[-15:]}")
assert result == (1561, 23, 7, 54)

def test_getRightArrowPosition_04(mocker, img=img04, is_gray=False):
# clean preview test
this_gameWindowCache = {
'left': {'arrow': None, 'position': None},
'right': {'arrow': None, 'position': None},
}
mocker.patch('src.repositories.gameWindow.core.get_global_game_cache_window_cache', return_value=this_gameWindowCache)
# ----------------------------------

from src.repositories.gameWindow.config import gameWindowCache

img_gray = rgb_to_gray(img, is_gray)
result = getRightArrowPosition(img_gray)
# result == x, y, width, height
assert result is not None
# img04 should be differrent
result_pos_draw(img_gray,result,"test_getRightArrowPosition__04.png")
assert result == (1385, 23, 7, 54)
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,22 @@

def test_should_return_2_when_closest_waypoint_is_in_index_2():
currentCoordinate = (33094, 32790, 7)
closestWaypoint = ('walk', (33099, 32790, 7), 0)
closestDiagonalWaypoint = ('walk', (33098, 32794, 7), 0)
closestWaypointFromAnotherFloor = ('walk', (33099, 32790, 6), 0)
furthestWaypoint = ('walk', (33082, 32790, 7), 0)
closestWaypoint = ('', 'walk', (33099, 32790, 7), 0)
closestDiagonalWaypoint = ('', 'walk', (33098, 32794, 7), 0)
closestWaypointFromAnotherFloor = ('', 'walk', (33099, 32790, 6), 0)
furthestWaypoint = ('', 'walk', (33082, 32790, 7), 0)
waypoints = np.array(
[furthestWaypoint, closestWaypointFromAnotherFloor, closestWaypoint, closestDiagonalWaypoint], dtype=Waypoint)
result = getClosestWaypointIndexFromCoordinate(
currentCoordinate, waypoints)
assert result == 2

def test_should_return_2_when_closest_waypoint_is_in_index_2_optioons_dict():
currentCoordinate = (33094, 32790, 7)
closestWaypoint = ('', 'walk', (33099, 32790, 7), {})
closestDiagonalWaypoint = ('', 'walk', (33098, 32794, 7), {})
closestWaypointFromAnotherFloor = ('', 'walk', (33099, 32790, 6), {})
furthestWaypoint = ('', 'walk', (33082, 32790, 7), {})
waypoints = np.array(
[furthestWaypoint, closestWaypointFromAnotherFloor, closestWaypoint, closestDiagonalWaypoint], dtype=Waypoint)
result = getClosestWaypointIndexFromCoordinate(
Expand Down
12 changes: 12 additions & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

import cv2
import pathlib

currentPath = pathlib.Path(__file__).parent.resolve()
import cv2

def result_pos_draw(image, result_position, name, color_bgr = (255, 255, 0), thickness=2):
path = f"{currentPath}/validation_images/{name}"
x, y, width, height = result_position
cv2.rectangle(image, (x, y), (x+width, y+height), color_bgr, thickness)
cv2.imwrite(path, image)
Comment on lines +1 to +12
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pode formatar o file, organizar os imports e usar lowerUpperCase na função? Pode também explicar para o que serve a função?

Empty file added tests/validation_images/.keep
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Não versiona isso

Empty file.