From ca782191631df5661a99e7896104197c05908dfe Mon Sep 17 00:00:00 2001 From: "DESKTOP-JVKHS7I\\Adam" Date: Fri, 8 Feb 2019 03:33:28 +0530 Subject: [PATCH] abstracted code into classes and different python files --- fishing_event.py | 60 +++++++++++ fishing_mode.py | 54 ++++++++++ fishy.py | 264 +++++++---------------------------------------- fishy_network.py | 7 +- init.py | 87 ++++++++++++++++ pixel_loc.py | 20 ++++ window.py | 32 ++++++ 7 files changed, 295 insertions(+), 229 deletions(-) create mode 100644 fishing_event.py create mode 100644 fishing_mode.py create mode 100644 init.py create mode 100644 pixel_loc.py create mode 100644 window.py diff --git a/fishing_event.py b/fishing_event.py new file mode 100644 index 0000000..41b62fd --- /dev/null +++ b/fishing_event.py @@ -0,0 +1,60 @@ +from fishing_mode import * + + +class FishEvent(ABC): + @abstractmethod + def onEnterCallback(self, previousMode): + pass + + @abstractmethod + def onExitCallback(self, currentMode): + pass + +class HookEvent(FishEvent): + + def onEnterCallback(self, previousMode): + G.fishCaught += 1 + timeToHook = time.time() - G.stickInitTime + print("HOOOOOOOOOOOOOOOOOOOOOOOK....... " + str(G.fishCaught) + " caught " + " in " + str( + round_float(timeToHook)) + " secs") + pyautogui.press('e') + + def onExitCallback(self, currentMode): + pass + + +class LookEvent(FishEvent): + + def onEnterCallback(self, previousMode): + pyautogui.press('e') + + def onExitCallback(self, currentMode): + pass + + +class IdleEvent(FishEvent): + + def __init__(self, use_net): + self.use_net = use_net + + def onEnterCallback(self, previousMode): + G.fishCaught = 0 + if self.use_net: + net.sendHoleDeplete(G.fishCaught) + + if previousMode.name == "hook": + print("HOLE DEPLETED") + elif previousMode.name == "stick": + print("FISHING INTERRUPTED") + + def onExitCallback(self, currentMode): + pass + + +class StickEvent(FishEvent): + + def onEnterCallback(self, previousMode): + G.stickInitTime = time.time() + + def onExitCallback(self, currentMode): + pass diff --git a/fishing_mode.py b/fishing_mode.py new file mode 100644 index 0000000..f9d0b7e --- /dev/null +++ b/fishing_mode.py @@ -0,0 +1,54 @@ +from window import * + + +class FishingMode: + HValues = [60, 18, 100] + Threshold = int(arguments["--hook-threshold"]) + + CurrentCount = 0 + PrevLabel = -1 + CurrentMode = None + PrevMode = None + + Modes = [] + + def __init__(self, name, label, event): + self.name = name + self.label = label + self.event = event + + FishingMode.Modes.append(self) + + @staticmethod + def GetByLabel(label): + for m in FishingMode.Modes: + if m.label == label: + return m + + @staticmethod + def Loop(hueValue, pause): + current_label = 3 + for i, val in enumerate(FishingMode.HValues): + if hueValue == val: + current_label = i + + # check if it passes threshold, if so change labelNum + if FishingMode.PrevLabel == current_label: + FishingMode.CurrentCount += 1 + else: + FishingMode.CurrentCount = 0 + FishingMode.PrevLabel = current_label + + if FishingMode.CurrentCount >= FishingMode.Threshold: + FishingMode.CurrentMode = FishingMode.GetByLabel(current_label) + + if not pause and FishingMode.CurrentMode != FishingMode.PrevMode and FishingMode.PrevMode is not None: + + if FishingMode.PrevMode.event is not None: + FishingMode.PrevMode.event.onExitCallback(FishingMode.CurrentMode) + + if FishingMode.CurrentMode.event is not None: + FishingMode.CurrentMode.event.onEnterCallback(FishingMode.PrevMode) + + FishingMode.PrevMode = FishingMode.CurrentMode + diff --git a/fishy.py b/fishy.py index 1d05896..90854f4 100644 --- a/fishy.py +++ b/fishy.py @@ -1,108 +1,4 @@ -"""Fishy - -Usage: - fishy.py -h | --help - fishy.py -v | --version - fishy.py [--ip=] [--hook-threshold=] [--check-frequency=] [--no-resize] - -Options: - -h, --help Show this screen. - -v, --version Show version. - --ip= Local Ip Address of the android phone. - --hook-threshold= Threshold amount for classifier after which label changes [default: 3]. - --check-frequency= Sleep after loop in s [default: 10]. -""" - -VERSION = "0.1.0" -print("Fishy " + VERSION + " for Elder Scrolls Online") - -try: - from docopt import docopt - - arguments = docopt(__doc__) - if arguments["--version"]: - quit() - - print("Loading, Please Wait...") - import imutils as imutils - import numpy as np - from PIL import ImageGrab - import cv2 - import pyautogui - import time - import fishy_network as net - from fishy_config import config_win - from pynput.keyboard import Key, Listener - from decimal import Decimal - from win32api import GetSystemMetrics - import pickle -except Exception: - raise - -controls = {"stop": [Key.f11, "f11"], "debug": [Key.f10, "f10"], "pause": [Key.f9, "f9"], "configPL": [Key.f8, "f8"]} - -stop = False -pause = False -debug = False -configPL = False - -IMG_SIZE = 100 -LR = 1e-3 -STICK_TIMEOUT = 30.0 -NONE_TIMEOUT = 5.0 -IP_ADDRESS = arguments["--ip"] -bbox = (0, 0, GetSystemMetrics(0), GetSystemMetrics(1)) - -try: - pixelLoc = pickle.load(open("pixelLoc.pickle", "rb")) -except (OSError, IOError) as e: - pixelLoc = [[240, 31], [241, 32]] - - -def process_img(original_img): - """ - Convert image into hsv and crop it to select the required pixel - :param original_img: image grabbed from screen - :return: processed image in hsv - """ - original_img = cv2.cvtColor(original_img, cv2.COLOR_BGR2HSV) - # y:y+h, x:x+w - croped_img = original_img[pixelLoc[0][1]:pixelLoc[1][1], pixelLoc[0][0]:pixelLoc[1][0]] - return croped_img - - -def process_show(original_img): - """ - Converts image into rgb and crop it to select the required pixel then scale it up for debuging - :param original_img: image grabbed from screen - :return: proessed image in rgb - """ - original_img = cv2.cvtColor(original_img, cv2.COLOR_BGR2RGB) - # y:y+h, x:x+w - croped_img = original_img[pixelLoc[0][1]:pixelLoc[1][1], pixelLoc[0][0]:pixelLoc[1][0]] - croped_img = imutils.resize(croped_img, width=200) - return croped_img - - -def round_float(v, ndigits=2, rt_str=False): - d = Decimal(v) - v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits)) - if rt_str: - return v_str - return Decimal(v_str) - - -def pullStick(fishCaught, timeToHook): - """ - Hooks the fish - :param fishCaught: fish cout to be displayed - :param timeToHook: time took to hook the fish - :return: void - """ - print("HOOOOOOOOOOOOOOOOOOOOOOOK....... " + str(fishCaught) + " caught " + " in " + str( - round_float(timeToHook)) + " secs") - pyautogui.press('e') - # Timer(0.5, pressE).start() +from pixel_loc import * def on_release(key): @@ -111,29 +7,22 @@ def on_release(key): :param key: key released :return: void """ - global stop, pause, debug, configPL - if controls["pause"][0] == key: - pause = not pause - if pause: + if G.controls["pause"][0] == key: + G.pause = not G.pause + if G.pause: print("PAUSED") else: print("STARTED") - elif controls["debug"][0] == key: - debug = not debug + elif G.controls["debug"][0] == key: + G.debug = not G.debug - elif controls["stop"][0] == key: - stop = True + elif G.controls["stop"][0] == key: + G.stop = True - elif controls["configPL"][0] == key: - configPL = not configPL - - -def updatePixelLoc(): - global pixelLoc - x, y = pyautogui.position() - pixelLoc = [[x, y], [x + 1, y + 1]] + elif G.controls["configPL"][0] == key: + G.configPL = not G.configPL def startFishing(): @@ -141,123 +30,44 @@ def startFishing(): Starts the fishing codde :return: void """ - global stop, pause, debug - - pause = True - showedControls = True - debug = False - stop = False - holeDepleteSent = True - timerStarted = False - use_net = False - hooked = False - configPixelSave = True - threwStick = False - - fishCaught = 0 - prevLabel = 0 - labelNum = 3 - hVals = [60, 18, 100] - current_thresh = 0 - stickInitTime = time.time() if not arguments["--no-resize"]: config_win() - ctrl_help = controls["configPL"][1] + ": config pixel value\n" + controls["pause"][1] + ": start or pause\n" + \ - controls["debug"][1] + ": start debug\n" + controls["stop"][1] + ": quit\n" - print(ctrl_help) + use_net = arguments["--ip"] is not None + if use_net: + net.initialize(arguments["--ip"]) - if IP_ADDRESS is not None: - use_net = True - net.initialize(IP_ADDRESS) - - threshold = int(arguments["--hook-threshold"]) sleepFor = (1 / float(arguments["--check-frequency"])) + FishingMode("hook", 0, HookEvent()) + FishingMode("stick", 1, StickEvent()) + FishingMode("look", 2, LookEvent()) + FishingMode("idle", 3, IdleEvent(use_net)) + + fishPixWindow = Window("fishPixWindow", PixelLoc.val, 1, cv2.COLOR_BGR2HSV) + fishPixDebugWindow = Window("fishPixDebugWindow", PixelLoc.val, 200, cv2.COLOR_BGR2RGB) + + Log.ctrl() + # todo with Listener(on_release=on_release): - while not stop: + while not G.stop: time.sleep(sleepFor) - # image grab - screen = np.array(ImageGrab.grab(bbox=bbox)) - new_screen = process_img(screen) - hueValue = new_screen[0][0][0] + Window.Loop() + Log.Loop() - # find currentlable - currentLabel = 3 - for i, val in enumerate(hVals): - if hueValue == val: - currentLabel = i + pixelVal = (PixelLoc.val[0], PixelLoc.val[1], PixelLoc.val[0] + 1, PixelLoc.val[1] + 1) + fishPixWindow.crop = pixelVal + fishPixDebugWindow.crop = pixelVal + hueValue = fishPixWindow.getCapture()[0][0][0] + FishingMode.Loop(hueValue, G.pause) + fishPixDebugWindow.show(G.debug or G.configPL) + if G.debug or G.configPL: + Log.ou(str(FishingMode.CurrentMode.label) + ":" + str(hueValue)) + PixelLoc.Loop() - # check if it passes threshold, if so change labelNum - if prevLabel == currentLabel: - current_thresh += 1 - else: - current_thresh = 0 - prevLabel = currentLabel - if current_thresh >= threshold: - labelNum = currentLabel - - # use label num - if not pause: - - # fish caught - if labelNum == 0: - if not hooked: - fishCaught += 1 - timeToHook = time.time() - stickInitTime - pullStick(fishCaught, timeToHook) - hooked = True - - # fishing - if labelNum == 1: - hooked = False - if not timerStarted: - stickInitTime = time.time() - timerStarted = True - if (time.time() - stickInitTime) >= STICK_TIMEOUT: - print("STICK TIMED OUT, THROWING AGAIN") - pyautogui.press('e') - timerStarted = False - else: - timerStarted = False - - # looking on hole - if labelNum == 2: - if not threwStick: - pyautogui.press('e') - threwStick = True - else: - threwStick = False - - # not looking on hole - if labelNum == 3: - if not holeDepleteSent: - if fishCaught > 0: - print("HOLE DEPLETED") - if use_net: - net.sendHoleDeplete(fishCaught) - fishCaught = 0 - holeDepleteSent = True - else: - holeDepleteSent = False - - if debug or configPL: - print(str(labelNum) + ":" + str(hueValue)) - cv2.imshow('image', process_show(screen)) - showedControls = False - else: - if not showedControls: - showedControls = True - print(ctrl_help) - cv2.destroyAllWindows() - - if configPL: - updatePixelLoc() - configPixelSave = False - elif not configPixelSave: - pickle.dump(pixelLoc, open("pixelLoc.pickle", "wb")) - cv2.waitKey(25) + Log.LoopEnd() + Window.LoopEnd() if __name__ == "__main__": diff --git a/fishy_network.py b/fishy_network.py index ef6eada..5292327 100644 --- a/fishy_network.py +++ b/fishy_network.py @@ -8,10 +8,12 @@ MESSAGE = "yo" RETRY_LIMIT = 5 IP = 0 + def initialize(ip): global s, IP IP = ip + def send_message(message, count=1): try: s = socket.socket() @@ -33,5 +35,6 @@ def sendHoleDeplete(count): send_message(jsonString) -##initialize("192.168.0.192") -##sendHoleDeplete(2) +if __name__ == "__main__": + initialize("192.168.0.192") + sendHoleDeplete(2) diff --git a/init.py b/init.py new file mode 100644 index 0000000..480e3ce --- /dev/null +++ b/init.py @@ -0,0 +1,87 @@ +"""Fishy + +Usage: + fishy.py -h | --help + fishy.py -v | --version + fishy.py [--ip=] [--hook-threshold=] [--check-frequency=] [--no-resize] + +Options: + -h, --help Show this screen. + -v, --version Show version. + --ip= Local Ip Address of the android phone. + --hook-threshold= Threshold amount for classifier after which label changes [default: 3]. + --check-frequency= Sleep after loop in s [default: 10]. +""" + +VERSION = "0.1.0" +print("Fishy " + VERSION + " for Elder Scrolls Online") + +try: + from docopt import docopt + + arguments = docopt(__doc__) + if arguments["--version"]: + quit() + + print("Loading, Please Wait...") + import imutils as imutils + import numpy as np + from PIL import ImageGrab + import cv2 + import pyautogui + import time + import fishy_network as net + from fishy_config import config_win + from pynput.keyboard import Key, Listener + from decimal import Decimal + from win32api import GetSystemMetrics + import pickle + import win32gui + from abc import ABC, abstractmethod +except Exception: + raise + + +class G: + fishCaught = 0 + stickInitTime = 0 + controls = {"stop": [Key.f11, "f11"], "debug": [Key.f10, "f10"], "pause": [Key.f9, "f9"], + "configPL": [Key.f8, "f8"]} + stop = False + pause = True + debug = False + configPL = False + + +class Log: + ouUsed = False + prevOuUsed = False + ctrl_help = G.controls["configPL"][1] + ": config pixel value\n" + G.controls["pause"][1] + ": start or pause\n" + \ + G.controls["debug"][1] + ": start debug\n" + G.controls["stop"][1] + ": quit\n" + + @staticmethod + def Loop(): + Log.ouUsed = False + + @staticmethod + def LoopEnd(): + if Log.prevOuUsed and not Log.ouUsed: + print(Log.ctrl_help) + Log.prevOuUsed = Log.ouUsed + + @staticmethod + def ctrl(): + print(Log.ctrl_help) + + @staticmethod + def ou(s): + Log.ouUsed = True + print(s) + + +def round_float(v, ndigits=2, rt_str=False): + d = Decimal(v) + v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits)) + if rt_str: + return v_str + return Decimal(v_str) diff --git a/pixel_loc.py b/pixel_loc.py new file mode 100644 index 0000000..51fc116 --- /dev/null +++ b/pixel_loc.py @@ -0,0 +1,20 @@ +from fishing_event import * + + +class PixelLoc: + configPixelSaved = True + + try: + val = pickle.load(open("pixelLoc.pickle", "rb")) + except (OSError, IOError) as e: + val = (240, 31) + + @staticmethod + def Loop(): + if G.configPL: + x, y = pyautogui.position() + PixelLoc.val = (x, y) + PixelLoc.configPixelSaved = False + elif not PixelLoc.configPixelSaved: + pickle.dump(PixelLoc.val, open("pixelLoc.pickle", "wb")) + PixelLoc.configPixelSaved = True diff --git a/window.py b/window.py new file mode 100644 index 0000000..02e3c64 --- /dev/null +++ b/window.py @@ -0,0 +1,32 @@ +from init import * + + +class Window: + Screen = None + + def __init__(self, name, crop, scale, color): + self.color = color + self.crop = crop + self.scale = scale + self.name = name + + @staticmethod + def Loop(): + bbox = (0, 0, GetSystemMetrics(0), GetSystemMetrics(1)) + Window.Screen = np.array(ImageGrab.grab(bbox=bbox)) + + @staticmethod + def LoopEnd(): + cv2.waitKey(25) + + def show(self, show): + if show: + cv2.imshow(self.name, self.getCapture()) + else: + cv2.destroyWindow(self.name) + + def getCapture(self): + temp_img = cv2.cvtColor(Window.Screen, self.color) + temp_img = temp_img[self.crop[1]:self.crop[3], self.crop[0]:self.crop[2]] + temp_img = imutils.resize(temp_img, width=self.scale) + return temp_img