示例#1
0
def agent():  #Game bot
    listener = Listener(on_click=tools.on_click)  #Init of listener
    listener.start(
    )  #Starting the listener in another thread in a non-blocking fashion
    i = 0  #Shoot and wait counter
    aoe = [0,
           0]  #Area of effect memory of last shot to not hit falling enemies
    while (listener.running):  #As long as the listener is running:
        time.sleep(.03)  #Wait 30 ms till next search
        img = tools.getImg()  #Get grayscale image to np array
        pos = tools.findEnemy(img)  #Search for a enemy and get position: [x,y]
        if pos is not None and not tools.comparePos(
                pos, aoe
        ):  #If the bot didnt shoot at this position lately then and there are enemies:
            i = i + 1  #Increment counter
            aoe = pos  #Memory is current enemies position
            mouse.position = (
                (pos[0], pos[1]))  #Put the pointer on pos on screen
            mouse.click(Button.left, count=2)  #Click the enemy twice
        else:  #If the bot did shoot at this position lately or there are no enemies then:
            i = i + 1  #Increment counter
            if i > 50:  #If the counter is greater 50
                mouse.position = (
                    (973, 594)
                )  #Position the mouse around the middle of the game window
                keyboard.press(Key.space)  #Press space
                time.sleep(.06)  #Wait 60 ms
                keyboard.release(Key.space)  #Release space
                i = 0  #Reset counter
示例#2
0
def on_release(key):
    print('{0} release'.format(
        key))
    if key == Key.esc:
        # Stop listener
        mListener.stop()
        return False
示例#3
0
class MouseListener:
    def __init__(self):
        self._status = {'position': (0, 0), 'click': dict(), 'scroll': 0}

        self._listener = Listener(on_move=self._on_move,
                                  on_click=self._on_click,
                                  on_scroll=self._on_scroll)

    def _on_move(self, x, y):
        self._status['position'] = (x, y)

    def _on_click(self, x, y, button, pressed):
        if pressed:
            self._status['click'][button] = None
        elif button in self._status['click']:
            self._status['click'].pop(button, None)

    def _on_scroll(self, x, y, dx, dy):
        self._status['scroll'] = dy

    def get_state(self):
        status = copy.deepcopy(self._status)
        status['click'] = list(self._status['click'].keys())
        return status

    def start_listening(self):
        self._listener.start()
示例#4
0
def listen():
    "Listen for inputs and forward them to the TV (CTRL-C to exit)"

    try:
        from pynput.mouse import Listener as MListener
        c = Client()
        c.ic.connect_input()
        c.last_x = c.last_y = None

        def on_move(x, y):
            if c.last_x == None:
                c.last_x, c.last_y = x, y
            else:
                c.ic.move(x - c.last_x, y - c.last_y)
                c.last_x, c.last_y = x, y
                # print('Pointer moved to {0}'.format((x, y)))

        def on_click(x, y, button, pressed):
            c.ic.click()

        def on_scroll(x, y, dx, dy):
            print(f"Scrolled {'down' if dy < 0 else 'up'} at {(x,y)}")

        m = MListener(on_move=on_move, on_click=on_click, on_scroll=on_scroll)
        m.start()

        while True:
            inp = click.getchar()
            mapped = KEYMAP.get(inp)
            if not mapped:
                click.echo(f"Don't know what to do with '{inp}'", err=True)
            else:
                getattr(getattr(c, mapped[0]), mapped[1])()
    except KeyboardInterrupt:
        m.stop()
 def on_click(x, y, button, pressed):
     global total_mouse_clicks
     get_active_window()
     total_mouse_clicks += 1
     if running == False:
         MouseListener.stop()
         return False
示例#6
0
class globalMouseHook(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.isLeftDown = False
        self.isRightDown = False

    def on_move(self, x, y):
        # print('Pointer at {0}'.format((x, y)))
        return

    def on_click(self, x, y, button, pressed):
        # print('{0} at {1} with {2}'.format('Pressed' if pressed else 'Released', (x, y), button))
        if button == Button.left:
            self.isLeftDown = not self.isLeftDown
        elif button == Button.right:
            self.isRightDown = not self.isRightDown

    def is_leftDown(self):
        return self.isLeftDown

    def is_rightDown(self):
        return self.isRightDown

    def run(self):
        # Collect events until released
        self.listener = Listener(on_move=self.on_move, on_click=self.on_click)
        self.listener.start()

    def stop(self):
        self.listener.stop()
示例#7
0
 def start_listening(self):
     # non-blocking
     # a Listener can only be started once, so I must create a new one every time
     if hasattr(self, "_listener") and self._listener.running is True:
         self._listener.stop()
     self._listener = Listener(on_click=self.on_click)
     self._listener.start()
示例#8
0
    def __init__(self, filename: str):
        self._filename = filename
        self._listener = Listener(on_click=self._on_click)
        signal.signal(signal.SIGINT, self._signal_handler)

        self._output = open(self._filename, 'w')
        self._write("MACRO macro_name {")
示例#9
0
def listen_event():
    def on_click(x, y, button, pressed):

        # print('{0} {1} at {1}'.format(
        #     button,
        #     'Pressed' if pressed else 'Released',
        #     (x, y)))

        if f'{button}' == 'Button.middle' and pressed:
            print('Button Middle pressed.')
            tiles = realtime_shot()
            sync(tiles)

        # if keyboard.is_pressed('1'):
        #     return False

    def on_press(key):
        # print("Key pressed: {0}".format(key))

        if key == Key.esc:
            print("Key pressed: {0}".format(key))
            # return False
            KeyboardListener.stop()
            MouseListener.stop()

    keyboard_listener = KeyboardListener(on_press=on_press)
    mouse_listener = MouseListener(on_click=on_click)

    keyboard_listener.start()
    mouse_listener.start()
    keyboard_listener.join()
    mouse_listener.join()
示例#10
0
class SlotRandomizer():
    def __init__(self):
        self.keyboard = KeyboardController()
        self.listener = MouseListener(on_click=self.onClick)
        self.slotWeights = [0] * 9

    def onClick(self, x, y, button, pressed):
        if button != Button.right or not pressed:
            return True

        time.sleep(0.05)
        slot = random.choices(
            population=range(1, 10), weights=self.slotWeights
        )[0]
        key = KeyCode.from_vk(0x30 + slot)
        self.keyboard.press(key)
        time.sleep(0.05)
        self.keyboard.release(key)

    def startListener(self):
        self.listener = MouseListener(on_click=self.onClick)
        self.listener.start()

    def stopListener(self):
        self.listener.stop()
        self.listener = None
示例#11
0
 def ConnectMouse(self,state=True):
     if state:
         print("CONNECTING MOUSE")
         self.l= Listener(on_click=self.selectArea)
         self.l.start()
             
         print('se')
def main():
    global gTimeLeftClick, gTimeRightClick
    global gPressedLeft, gPressedRight

    print("Main Started")

    mouseCont = Controller()
    print("Mouse Controller Started")

    listener = Listener(on_click=on_click)
    listener.start()

    while True:
        if gPressedLeft:
            print("Left Click duration =" +
                  str(time.time() * 1000 - gTimeLeftClick))
            if ((time.time() * 1000 - gTimeLeftClick) > HOLD_DURATION * 1000):
                mouseCont.click(Button.left, 2)

        if gPressedRight:
            print("Right Click duration =" +
                  str(time.time() * 1000 - gTimeRightClick))
            if ((time.time() * 1000 - gTimeRightClick) > HOLD_DURATION * 1000):
                mouseCont.click(Button.right, 2)

        time.sleep(RAPIDFIRE_PERIOD)
示例#13
0
    def scroll_to_roll(self, area):  # 手动滚动模式
        x, y, w, h = area
        self.rollermask.tips.setText("向下滚动,单击结束")
        QApplication.processEvents()
        screen = QApplication.primaryScreen()
        winid = QApplication.desktop().winId()
        self.id = self.rid = 0
        self.a_step = 0

        def onclick(x, y, button, pressed):
            if pressed:

                pix = screen.grabWindow(winid, x, y, w, h)
                newimg = Image.fromqpixmap(pix)
                img = cv2.cvtColor(asarray(newimg), cv2.COLOR_RGB2BGR)
                self.img_list.append(img)
            else:
                print("click to stop", len(self.img_list))
                self.in_rolling = False
                listener.stop()

        def on_scroll(px, py, x_axis, y_axis):
            # print(px, py, x_axis, y_axis)
            # if not self.inthearea((px,py),area):
            #     return
            self.a_step += 1
            if self.a_step < 2:
                return
            else:
                self.a_step = 0
            if y_axis < 0:
                if self.rid >= self.id:  # 当滚动id与真实id一样时说明
                    pix = screen.grabWindow(winid, x, y, w, h)  # 滚动段距离进行截屏
                    newimg = Image.fromqpixmap(pix)
                    img = cv2.cvtColor(asarray(newimg), cv2.COLOR_RGB2BGR)
                    self.img_list.append(img)
                    # cv2.imwrite("j_temp/{}.png".format(self.id), img)
                    self.id += 1  # 记录当前滚动的id
                    self.rid = self.id
                else:  # 不一样时说明用户往回滚了,跳过
                    print("跳过")
                    self.rid += 1
            else:  # 方向往回滚时id-1,以记录往回的步数
                self.rid -= 1
                print("方向错误")

        listener = MouseListenner(on_click=onclick,
                                  on_scroll=on_scroll)  # 鼠标监听器,传入函数句柄
        self.match_thread = Commen_Thread(
            self.match_and_merge)  # 也是把拼接函数放入后台线程中
        self.in_rolling = True
        i = 0
        listener.start()  # 鼠标监听器启动
        self.match_thread.start()  # 拼接线程启动
        while self.in_rolling:  # 等待结束滚动
            time.sleep(0.2)
        listener.stop()
        # self.showrect.hide()
        self.match_thread.wait()  # 等待拼接线程结束
示例#14
0
 def __init__(self, output_file: str):
     self.file = None
     try:
         self.file = open(output_file, mode='w', encoding='utf-8')
     except ValueError:
         print('error : text.txt doesn\' exists .', file=sys.stderr)
     self.listener = Listener(on_move=self.on_move,
                              on_click=self.on_click)
示例#15
0
    def on_press(key):
        # print("Key pressed: {0}".format(key))

        if key == Key.esc:
            print("Key pressed: {0}".format(key))
            # return False
            KeyboardListener.stop()
            MouseListener.stop()
示例#16
0
    def start_listening(self):
        try:
            self.stop_listening()
        except:
            pass
        self.listener = Listener(on_move=self.on_move, on_click=self.on_click)

        self.listener.start()
示例#17
0
    def scroll_to_roll(self, area):
        x, y, w, h = area
        self.rollermask.tips.setText("向下滚动,单击结束")
        QApplication.processEvents()
        screen = QApplication.primaryScreen()
        winid = QApplication.desktop().winId()
        self.id = self.rid = 0
        self.a_step = 0

        def onclick(x, y, button, pressed):
            if pressed:

                pix = screen.grabWindow(winid, x, y, w, h)
                newimg = Image.fromqpixmap(pix)
                img = cv2.cvtColor(asarray(newimg), cv2.COLOR_RGB2BGR)
                self.img_list.append(img)
            else:
                print("click to stop", len(self.img_list))
                self.in_rolling = False
                listener.stop()

        def on_scroll(px, py, x_axis, y_axis):
            print(px, py, x_axis, y_axis)
            # if not self.inthearea((px,py),area):
            #     return
            self.a_step += 1
            if self.a_step < 2:
                return
            else:
                self.a_step = 0
            if y_axis < 0:
                if self.rid >= self.id:
                    pix = screen.grabWindow(winid, x, y, w, h)
                    newimg = Image.fromqpixmap(pix)
                    img = cv2.cvtColor(asarray(newimg), cv2.COLOR_RGB2BGR)
                    self.img_list.append(img)
                    # cv2.imwrite("j_temp/{}.png".format(self.id), img)
                    self.id += 1
                    self.rid = self.id
                else:
                    print("跳过")
                    self.rid += 1
            else:
                self.rid -= 1
                print("方向错误")

        listener = MouseListenner(on_click=onclick, on_scroll=on_scroll)
        self.match_thread = Commen_Thread(self.match_and_merge)
        self.in_rolling = True
        i = 0
        listener.start()
        self.match_thread.start()
        while self.in_rolling:
            time.sleep(0.2)
        listener.stop()
        # self.showrect.hide()
        self.match_thread.wait()
示例#18
0
def on_click(x, y, button, pressed):   
    print('{0} at {1}'.format('pressed' if pressed else 'released',(x, y)))
    
    click_location = (x,y)  #actually prints the location of the mouse when clicked
    print('Click location =',click_location) 
    
    
    print('exeted listener')
    Listener.stop()                                                                 #Gotta remember the cap
示例#19
0
def on_click(x, y, button, pressed):
    if pressed:
    logging.info ("Mouse clicked at ({1}, {0}) with {2}".format(x, y, button))

def on_scroll(x, y, dx, dy):
    logging.info ("Mouse scrolled at ({0}, {1})({2}, {3})".format(x, y, dx, dy))
    
with Listener(on_move=on_move, on_click=on_click, on_scroll=on_scroll) as listener:
    Listener.join()
示例#20
0
 def __init__(self):
     AbstractSensor.__init__(self)
     self.lastClicked = datetime.now()
     self.movetimeout = 2
     listener = Listener(on_move=self.on_move, on_click=self.on_click, on_scroll=self.on_scroll)
     listener.start()
     self.measurements = {
             "Interaction" : [False,""],
         }
def on_release(key):
    print('{0} release'.format(key))
    if key == Key.esc:
        # Stop listener
        mListener.stop()
        return False
    # set trigger for a detector?
    if key == Key.shift:
        print(mouse.position)
示例#22
0
    def listen(self):
        " Listen and send keys and mouse event until CTRL LEFT is pressed "
        print('Press on CTRL LEFT to stop listening')
        s = S()
        s.ic.connect_input()

        keymap = {
            'esc': s.ic.exit,
            'enter': s.ic.click,
            'backspace': s.ic.back,
            '=': s.ic.volume_up,
            '-': s.ic.volume_down,
            'i': s.ic.info,
            'h': s.ic.home,
            'm': self.mute
        }

        def on_press(key):
            print(key)
            if key == pynput.keyboard.Key.ctrl_l:
                return False

            if hasattr(key, 'name'):
                if key.name in keymap:
                    keymap.get(key.name)()
                elif key.name in InputControl.INPUT_COMMANDS:
                    getattr(s.ic, key.name)()
            elif hasattr(key, 'char'):
                if key.char in keymap:
                    keymap.get(key.char)()
                elif key.char in InputControl.INPUT_COMMANDS:
                    getattr(s.ic, key.char)()

        def on_move(x, y):
            if self.last_x == None:
                self.last_x, self.last_y = x, y
            else:
                s.ic.move(x - self.last_x, y - self.last_y)
                self.last_x, self.last_y = x, y
                # print('Pointer moved to {0}'.format((x, y)))

        def on_click(x, y, button, pressed):
            s.ic.click()

        def on_scroll(x, y, dx, dy):
            print('Scrolled {0} at {1}'.format('down' if dy < 0 else 'up',
                                               (x, y)))

        # Collect events until released
        m = MListener(on_move=on_move, on_click=on_click, on_scroll=on_scroll)
        m.start()
        with KListener(on_press=on_press) as listener:
            listener.join()
        m.stop()
        s.ic.disconnect_input()
示例#23
0
    def check_click_coordinates(self):
        def set_storm_coordinates(x, y, button, pressed):
            self.db['storm_coordinates'] = [x, y]
            return False

        def set_storm_middle_coordinates(x, y, button, pressed):
            self.db['storm_middle_coordinates'] = [x, y]
            return False

        def set_tracker_app_coordinates(x, y, button, pressed):
            self.db['tracker_app_coordinates'] = [x, y]
            return False

        if self.argument_value and self.argument_value not in self.db.keys():
            print('Invalid argument value')
            exit()

        if self.db.get('storm_coordinates', False) and (
                False if self.argument_value == 'storm_coordinates' else True):
            print(
                f"storm_coordinates is a{bcolors.OKGREEN} {self.db['storm_coordinates'][0]} and {self.db['storm_coordinates'][1]}{bcolors.ENDC} \U0001F44D"
            )
        else:
            print('Please click in PhpStorm Icon')
            with Listener(on_click=set_storm_coordinates) as listener:
                listener.join()
                time.sleep(1)
            print('PhpStorm icon coordinates saved successfully \U0001F44D')

        if self.db.get('storm_middle_coordinates',
                       False) and (False if self.argument_value
                                   == 'storm_middle_coordinates' else True):
            print(
                f"storm_middle_coordinates is a{bcolors.OKGREEN} {self.db['storm_middle_coordinates'][0]} and {self.db['storm_middle_coordinates'][1]}{bcolors.ENDC} \U0001F44D"
            )
        else:
            print('Please click in middle of PhpStorm')
            with Listener(on_click=set_storm_middle_coordinates) as listener:
                listener.join()
                time.sleep(1)
            print('PhpStorm middle coordinates saved successfully \U0001F44D')

        if self.db.get('sleep_command', False) and (
                False if self.argument_value == 'sleep_command' else True):
            print(
                f"sleep_command is a{bcolors.OKGREEN} {self.db['sleep_command']}{bcolors.ENDC} \U0001F44D"
            )

        else:
            sleep_command = input('set sleep command - ')
            self.db['sleep_command'] = sleep_command

        print('Cool! \U0001F60E')
        self.db.close()
示例#24
0
def pyK():
    print('Welcome to the pyk Tool to capture keyboard and mouse inputs')
    print('1) To capture the key board input ')
    print(
        '2) To move you mouse on screen based on x and y pixal position (Top left is your (0, 0) position '
    )
    print('3) To capture the mouse position ')
    func = input('Select Your Option? :- ')

    if func == '1':
        file_name = input(
            'Specify the file name in which you would like to capture (For Example: default=capture.txt '
        )
        if not file_name:
            file_name = "captured_input.txt"
        print('the capture has been started...')

        def writeToFile(keys):
            letter = str(keys)
            letter = letter.replace("'", "")

            if letter == 'Key.space':
                letter = ' '
            if letter == 'Key.enter':
                letter = '\n'
            with open(file_name, mode='a') as file:
                file.write(letter)

        with Listener(on_press=writeToFile) as l:
            l.join()
    elif func == '2':
        import mouse
        x, y = input(
            'Please specify the x nd y position (For example: 300 500)').split(
            )

        def controlMouse(x, y):
            mouse = Controller()
            mouse.position = (x, y)

        controlMouse(x, y)
    elif func == '3':
        import livemouse
        print('The Capture has been started...')

        def mousemove(x, y):
            print(f"\rx-axis: " + str(x), end="")
            print(f"\rY-axis: " + str(y), end="")

        with Listener(on_move=mousemove) as l_mouse:
            l_mouse.join()
    else:
        print('Select a Valid Input >:) ')
        pyK()
示例#25
0
 def start_record(self):
     self.log = open(self.replay_file, "w")
     self.init_time = time.time() * 1000  # To make microseconds
     keyboard_listener = KeyboardListener(on_press=self.__on_press,
                                          on_release=self.__on_release)
     mouse_listener = MouseListener(on_click=self.__on_click,
                                    on_scroll=self.__on_scroll)
     keyboard_listener.start()
     mouse_listener.start()
     keyboard_listener.join()
     mouse_listener.stop()
     keyboard_listener.stop()
     self.log.flush()
     self.log.close()
示例#26
0
class Recorder:

    _filename: str
    _listener: Listener
    _output: TextIO
    _start_time: datetime
    _stop_time: datetime

    def __init__(self, filename: str):
        self._filename = filename
        self._listener = Listener(on_click=self._on_click)
        signal.signal(signal.SIGINT, self._signal_handler)

        self._output = open(self._filename, 'w')
        self._write("MACRO macro_name {")

    def record(self):
        with self._listener:
            self._listener.join()

    def _signal_handler(self, sig, frame):
        print('Exiting...')
        self._listener.stop()
        self._write("}")
        self._output.close()

    def _write(self, data: str):
        self._output.write(f"{data}\n")
        self._output.flush()

    def _get_second_delta(self) -> Optional[int]:
        try:
            return int((self._stop_time - self._start_time).total_seconds())
        except (AttributeError, ValueError):
            return None

    def _on_click(self, x, y, button, pressed):
        self._stop_time = datetime.now()
        x = int(x)
        y = int(y)

        if self._get_second_delta() is not None \
                and self._get_second_delta() > 0:
            print(f"Wait {self._get_second_delta()} seconds")
            self._write(f"  WAIT {self._get_second_delta()}s")

        if pressed:
            print(f"Mouse clicked at ({x}, {y})")
            self._write(f"  CLICK {x},{y}")
            self._start_time = datetime.now()
示例#27
0
    def __init__(self):
        """The builder of the 'Mouselog' class

        attribute list:
        move : list with all movement from the mouse
        clic : list with all clic and their position
        scroll : list with scroll's position and the direction of the scrolling
        listener : object used to listen mouse's activities

        """
        self.a_move = []
        self.a_clic = []
        self.a_scroll = []
        self.a_listener = Listener(on_move=self.on_move, on_click=self.on_click, on_scroll=self.on_scroll)
示例#28
0
def start_record():
    global record
    global keyboard_listen_thread
    global mouse_listen_thread

    record.clear()

    # 连接事件以及释放
    mouse_listen_thread = Mouse_Listener(on_click=on_click, on_scroll=on_scroll)
    mouse_listen_thread.start()

    # 连接事件以及释放
    keyboard_listen_thread = Keyboard_Listener(on_press=on_press, on_release=on_release)
    keyboard_listen_thread.start()
示例#29
0
    def auto_roll(self, area):  # 自动滚动模式
        x, y, w, h = area
        self.rollermask.tips.setText("单击停止")
        QApplication.processEvents()
        speed = round(1 / self.roll_speed, 2)
        screen = QApplication.primaryScreen()
        winid = QApplication.desktop().winId()

        def onclick(x, y, button, pressed):  # 点击退出的函数句柄
            if pressed:
                print("click to stop")
                self.in_rolling = False
                listener.stop()

        controler = MouseController()  # 鼠标控制器
        listener = MouseListenner(on_click=onclick)  # 鼠标监听器
        self.match_thread = Commen_Thread(
            self.match_and_merge)  # 把match_and_merge放入一个线程中
        self.in_rolling = True
        i = 0
        controler.position = (area[0] + int(area[2] / 2),
                              area[1] + int(area[3] / 2))  # 控制鼠标点击到滚动区域中心
        oldimg = Image.new("RGB", (128, 128), "#FF0f00")
        listener.start()
        while self.in_rolling:
            st = time.time()
            pix = screen.grabWindow(winid, x, y, w, h)  # 截屏
            newimg = Image.fromqpixmap(pix)  # 转化为pil的格式
            img = cv2.cvtColor(asarray(newimg), cv2.COLOR_RGB2BGR)
            self.img_list.append(img)  # 图片数据存入self.img_list中被后台的拼接线程使用

            # cv2.imshow("FSd", img)
            # cv2.waitKey(0)
            if i >= 1:
                if i == 1:
                    self.match_thread.start()  # 当截第二张图片时拼接线程才启动
                if self.is_same(oldimg, newimg):  # 每帧检查是否停止
                    self.in_rolling = False
                    i += 1
                    break
            oldimg = newimg
            controler.scroll(dx=0, dy=-3)  # 控制鼠标滚动
            time.sleep(speed)  # 通过sleep控制自动滚动速度
            # cv2.imwrite('j_temp/{0}.png'.format(i), img)
            i += 1
        print("结束滚动,共截屏{}张".format(i))
        listener.stop()
        # self.showrect.hide()
        self.match_thread.wait()
示例#30
0
class Listener:
    def __init__(self):
        self.keyboard_listener = KeyboardListener(on_press=on_press,
                                                  on_release=on_release)
        self.mouse_listener = MouseListener(on_click=on_click,
                                            on_scroll=on_scroll,
                                            on_move=on_move)

    def start(self):
        self.keyboard_listener.start()
        self.mouse_listener.start()

    def stop(self):
        self.keyboard_listener.stop()
        self.mouse_listener.stop()
示例#31
0
 def __init__(self):
     """Initialize as Thread and create attributes"""
     Thread.__init__(self)
     self._stats = {p: {k: 0.0 for k in self.STATS} for p in self.POOLS}
     self._lock = Lock()
     self._exit_queue = Queue()
     self.primary = "PrimaryWeapon"
     self.__delays = dict()
     self._internal_q = Queue()
     self._match = False
     self._ms_listener = MSListener(on_click=self._on_click)
     self._kb_listener = KBListener(on_press=self._on_press)
     self._mouse = False
     self._string = str()
     print("[DelayParser] Initialized")
示例#32
0
class DelayParser(Thread):
    """Parser that checks Regeneration Delays and controls an overlay"""

    DELAYS = {
        "Power_Shield_Regen_Delay": "Shield",
        "Power_Weapon_Regen_Delay": "Weapon",
        "Power_Engine_Regen_Delay": "Engine"
    }

    POOLS = ["Weapon", "Shield", "Engine"]
    STATS = {
        "Delay": "Power_{}_Regen_Delay",
        "Regen": "Power_{}_Regen_Rate",
        "Recent": "Power_{}_Regen_Rate_(when_Recently_Consumed)"
    }

    def __init__(self):
        """Initialize as Thread and create attributes"""
        Thread.__init__(self)
        self._stats = {p: {k: 0.0 for k in self.STATS} for p in self.POOLS}
        self._lock = Lock()
        self._exit_queue = Queue()
        self.primary = "PrimaryWeapon"
        self.__delays = dict()
        self._internal_q = Queue()
        self._match = False
        self._ms_listener = MSListener(on_click=self._on_click)
        self._kb_listener = KBListener(on_press=self._on_press)
        self._mouse = False
        self._string = str()
        print("[DelayParser] Initialized")

    def set_ship_stats(self, ship: ShipStats):
        """Update the ship statistics used for delay tracking"""
        self._lock.acquire()
        self._stats = {
            p: {k: ship["Ship"][v.format(p)] for k, v in self.STATS.items()}
            for p in self.POOLS
        }
        self.primary = "PrimaryWeapon"
        self._lock.release()
        print("[DelayParser] Updated ship to: {}".format(ship.ship.name))

    def primary_weapon_swap(self):
        """Swap the primary weapon key"""
        self.primary = "PrimaryWeapon2" if self.primary == "PrimaryWeapon" else "PrimaryWeapon"
        print("[DelayParser] Swapped Primary Weapons")

    def match_end(self):
        """Match ended callback"""
        self._internal_q.put("end")

    def match_start(self):
        """Match start callback"""
        self._internal_q.put("start")

    def update(self):
        """Update the state of the DelayParser"""
        self._lock.acquire()
        stats, key = self._stats.copy(), self.primary
        self._lock.release()

        while not self._internal_q.empty():
            v = self._internal_q.get()
            if v == "start":
                self._match = True
            elif v == "end":
                self._match = False
            elif v == "mouse":
                self._mouse = not self._mouse
            else:
                pool, time = v
                self.__delays[pool] = time
        if self._match is False:
            return
        if self._mouse is True:
            self.__delays["Weapon"] = datetime.now()
        string, time = "\n", datetime.now()
        for pool, start in self.__delays.items():
            elapsed = (time - start).total_seconds()
            remaining = max(stats[pool]["Delay"] - elapsed, 0.0)
            rate = stats[pool]["Regen"] if remaining == 0.0 else stats[pool]["Recent"]
            string += "{}: {:.1f}s, {:.1f}pps\n".format(pool[0], remaining, rate)
        self._lock.acquire()
        self._string = string
        self._lock.release()
        sleep(0.1)

    def process_event(self, event: dict, active_ids: list):
        """Process an event to check for shield power pool usage"""
        ctg = Parser.get_event_category(event, active_ids)
        if event["self"] is True and ctg == "engine":
            self._internal_q.put(("Engine", event["time"]))
            return
        if event["self"] is True or Parser.compare_ids(event["target"], active_ids) is False:
            return
        if "Damage" not in event["effect"]:
            return
        # event: Damage dealt to self
        self._internal_q.put(("Shield", event["time"]))

    def cleanup(self):
        """Clean up everything in use"""
        self._ms_listener.stop()
        self._kb_listener.stop()

    def run(self):
        """Run the Thread"""
        self._ms_listener.start()
        self._kb_listener.start()
        print("[DelayParser] Keyboard and Mouse Listeners started")
        while True:
            if not self._exit_queue.empty():
                break
            self.update()
        self.cleanup()

    def stop(self):
        """Stop activities and join Thread"""
        if not self.is_alive():
            return
        self._exit_queue.put(True)
        self.join(timeout=1)

    def _on_click(self, x: int, y: int, button: Button, state: bool):
        """Process a click to check for weapon power usage"""
        if button == Button.left:
            self._internal_q.put("mouse")

    def _on_press(self, key: (Key, KeyCode)):
        """Process a key press to check for engine power usage"""
        if key == Key.space:
            self._internal_q.put(("Engine", datetime.now()))

    @property
    def string(self):
        """String to show in the Overlay"""
        self._lock.acquire()
        string = self._string
        self._lock.release()
        return string