Ejemplo n.º 1
0
def breadthFirstSearch(gui: Gui, start: Node, end: Node) -> bool:
    """Runs A* algorithm

    This algorithm explores all of the neighbor nodes at the present
    depth prior to moving on to the nodes at the next depth level.

    Reference = [https://en.wikipedia.org/wiki/Breadth-first_search]

    Parameters
    ----------
    nodes : list
        A list of nodes present in the grid
    start : Node
        The starting point
    end : Node
        The ending point

    Returns
    -------
    bool
        True if the ending node was reached, else False
    """
    def buildReversePath(came_from: dict, current: Node):
        while current in came_from:
            current = came_from[current]
            current.setState("path")
            gui.updateContents()

    came_from = {}
    open_set = [
        start
    ]  # The FIFO data structure for exploring all of the neighbor nodes as soon as they shows up
    visited = []

    while open_set:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                gui.close()

        current = open_set.pop(0)
        visited.append(current)

        if current == end:
            buildReversePath(came_from, end)
            end.setState("end point")
            start.setState("start point")
            return True

        for neighbor in current.neighbors:
            if neighbor not in visited and neighbor.state != "watch":
                open_set.append(neighbor)
                came_from[neighbor] = current
                neighbor.setState("watch")
                gui.updateContents()

        if current != start:
            current.setState("visited")
            gui.updateContents()

    return False
Ejemplo n.º 2
0
def depthFirst(gui: Gui, start: Node, end: Node) -> bool:
    """Runs Depth-First Search Algorithm

    This algorithm explores as far as possible along each branch of a tree (or graph) before backtracking.

    Reference = [https://en.wikipedia.org/wiki/Depth-first_search]

    Parameters
    ----------
    nodes : list
        A list of nodes present in the grid
    start : Node
        The starting point
    end : Node
        The ending point

    Returns
    -------
    bool
        True if the ending node was reached, else False
    """
    def buildReversePath(came_from: dict, current: Node):
        while current in came_from:
            current = came_from[current]
            current.setState("path")
            gui.updateContents()

    came_from = {}
    open_set = [
        start
    ]  # The LIFO data structure for exploring as far as possible along each branch
    visited = []

    while open_set:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                gui.close()

        current = open_set.pop(-1)
        visited.append(current)

        if current == end:
            buildReversePath(came_from, end)
            end.setState("end point")
            start.setState("start point")
            return True

        for neighbor in current.neighbors:
            if neighbor not in visited:
                came_from[neighbor] = current
                open_set.append(neighbor)
                neighbor.setState("watch")
                gui.updateContents()

        if current != start:
            current.setState("visited")
            gui.updateContents()

    return False
Ejemplo n.º 3
0
def main():
    gui_fps = 120
    path_finding_fps = 30
    gui = Gui(fps=gui_fps)

    # Mapping the keys that triggers an algorithm initialization
    search_mapping = {
        pygame.K_a: aStar,
        pygame.K_d: depthFirst,
        pygame.K_b: breadthFirstSearch,
    }

    start_node = None
    end_node = None

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                gui.close()

            if pygame.mouse.get_pressed()[0]:  # LEFT MOUSE BUTTON
                mouse_xy = pygame.mouse.get_pos()
                start_node, end_node = gui.setNodeColor(
                    mouse_xy, start_node, end_node)

            if pygame.mouse.get_pressed()[2]:  # RIGHT MOUSE BUTTON
                mouse_xy = pygame.mouse.get_pos()
                start_node, end_node = gui.resetNodeColor(
                    mouse_xy, start_node, end_node)

            if event.type == pygame.KEYDOWN:
                # Look for the keys that triggers an algorithm initialization
                if event.key in search_mapping.keys():
                    if start_node and end_node:
                        gui.updateNodeNeighbors()
                        gui.reset(
                            exeptions=["wall", "start point", "end point"])
                        search = search_mapping[event.key]
                        gui.fps = path_finding_fps
                        search(gui, start_node, end_node)
                        gui.fps = gui_fps

                # Look for the keys that resets all blocks
                if event.key == pygame.K_SPACE:
                    start_node, end_node = None, None
                    gui.reset()

                # Look for the keys that resets all blocks except the maze configuration
                if event.key == pygame.K_c:
                    gui.reset(exeptions=["wall", "start point", "end point"])

        gui.updateContents()
Ejemplo n.º 4
0
class App(QApplication):
    def __init__(self):
        QApplication.__init__(self, sys.argv)
        # Establish loop as Quamash Event Loop
        loop = QEventLoop(self)
        self.loop = loop
        asyncio.set_event_loop(loop)

        self.idle = False
        self.trayIcon = None

        self.themes = themes
        self.options = Options
        try:
            self.theme = themes[self.options["theme"]["theme"]]
        except KeyError:
            self.theme = themes["Pesterchum 2.5"]
        self.theme_name = self.theme["name"]
        self.moods = Moods
        self.emojis = Emojis
        self.mentions = Mentions
        self.setStyleSheet(self.theme["styles"])

        self.nick = None
        self.client = DiscordClient(app=self, loop=self.loop)

        self.user, self.passwd, self.token, self.botAccount = UserAuth

        if not UserAuth[0] and not UserAuth[1] and not UserAuth[2]:
            self.openAuth(i=True)
            save_auth((
                self.user,
                self.passwd,
                self.token,
                self.botAccount,
            ))

        asyncio.ensure_future(self.connecting())
        asyncio.ensure_future(self.runbot())
        self.gui = Gui(self.loop, self)
        loop.run_forever()

    def cli(self):
        """
        Runs a REPL style loop, if eval(input) is awaitable (`inspect.isawaitable`)
        will await, runs in an executor
        """
        asyncio.ensure_future(self.run_exe())

    async def run_exe(self):
        while True:
            try:
                with QThreadExecutor(1) as exec:
                    line = await self.loop.run_in_executor(exec, input, ">>> ")
                evl = eval(line)
                if isawaitable(evl):
                    r = await evl
                    print(r)
                else:
                    print(evl)
            except Exception as e:
                print(e)

    async def connecting(self):
        self.connectingDialog = ConnectingDialog(self, self)
        self.connectingDialog.exec_()

    async def on_message(self, message):
        """Called on `Client.on_message`, Message handling happens here"""
        if message.content.startswith("_") and message.content.endswith("_"):
            message.content = "/me " + message.content[1:-1]
        if isinstance(message.channel, discord.PrivateChannel):
            if not message.channel.name:
                message.channel.name = ",".join(
                    map(lambda m: m.display_name, message.channel.recipients))
            if message.channel.type is discord.ChannelType.group:
                tab = self.gui.start_privmsg(message.channel)
            else:
                tab = self.gui.start_privmsg(message.channel)
            fmt = fmt_disp_msg(self,
                               message.content,
                               message,
                               user=message.author)
            if fmt:
                tab.display_text(fmt)
        else:
            if self.gui.memosWindow:
                if message.server in self.gui.memosWindow.open.keys():
                    fmt = fmt_disp_msg(self,
                                       message.content,
                                       message,
                                       user=message.author)
                    if fmt:
                        try:
                            self.gui.memosWindow.display_message(
                                message.channel, fmt)
                        except AttributeError as e:
                            print(e)

    async def on_ready(self):
        """Called on `Client.on_ready`, generally once the client is logged in and ready"""
        self.connectingDialog.close()
        self.nick = self.client.user.name
        self.quirks = Quirks(self)
        if "debug" in sys.argv:
            self.cli()
        playsound(os.path.join(self.theme["path"], "alarm.wav"), block=False)
        self.gui.initialize()

    def change_mood(self, mood):
        if mood == "offline" or mood == "abscond":
            asyncio.ensure_future(
                self.client.change_presence(status=discord.Status.invisible))
        else:
            asyncio.ensure_future(
                self.client.change_presence(
                    game=discord.Game(name="Feeling {}".format(mood.upper())),
                    status=discord.Status.online))

        if self.idle:
            self.gui.toggleIdle()

    def change_theme(self, theme, f=False):
        if f:
            self.refresh_themes()
        if theme != self.theme_name or f:
            self.theme = themes[theme]
            self.theme_name = self.theme["name"]
            self.setStyleSheet(self.theme["styles"])
            if hasattr(self, "gui"):
                self.gui.close()
                self.gui = Gui(self.loop, self)
                self.gui.initialize()

    def refresh_themes(self):
        self.themes = getThemes(dict())

    @staticmethod
    def getColor(member, type=str):
        """Get the given primary role color for a `Member`, returns a `Discord.Color` instance"""
        try:
            clr = member.color
        except AttributeError:
            clr = discord.Color.default()
        if type is str:
            return "rgb({clr.r},{clr.g},{clr.b})".format(clr=clr)
        elif type is QColor:
            return QColor(clr.r, clr.g, clr.b)

    def send_msg(self, message, channel):
        """Send message `message` to the User, Private Channel, or Channel `channel`"""
        message = message.strip()
        tts = False
        if message.startswith("/me"):
            message = "_" + message[3:] + "_"
        if message.startswith("/tts "):
            message = message[4:]
            tts = True
        if message.startswith("/ooc"):
            message = "((" + message[4:] + "))"
        message = self.quirks.process_quirks(message)
        asyncio.ensure_future(
            self.client.send_message(channel, message, tts=tts))

    def openAuth(self, f=False, i=True):
        auth = AuthDialog(self, self, f=f, i=i).auth
        self.user, self.passwd, self.token, self.botAccount = auth
        if hasattr(self, "gui") and auth and not f:
            self.exit()

    async def runbot(self):
        try:
            if (self.user and self.passwd) and not self.token:
                await self.client.start(self.user, self.passwd, bot=False)
            elif self.token and not (self.user or self.passwd):
                await self.client.start(self.token, bot=self.botAccount)
        except discord.LoginFailure:
            self.openAuth(f=True)
            save_auth((
                self.user,
                self.passwd,
                self.token,
                self.botAccount,
            ))
        finally:
            await self.runbot()

    def exit(self, code=0):
        """
        Called when exiting the client
        Save configurations and sys.exit
        """
        try:
            save_auth((
                self.user,
                self.passwd,
                self.token,
                self.botAccount,
            ))
            save_options(self.options)
            self.quirks.save_quirks()
        except:
            pass
        finally:
            sys.exit(code)

    def lastWindowClosed(self):
        self.exit()
Ejemplo n.º 5
0
def aStar(gui: Gui, start: Node, end: Node) -> bool:
    """Runs A* algorithm

    One important aspect of A* is f = g + h
    Where:
        f is the total cost of the node.
        g is the distance between the current node and the start node.
        h is the heuristic - estimated distance from the current node to the end node.

    This algorithm expoits the node with the lowest f and its neighbors.

    Reference = [https://medium.com/@nicholas.w.swift/easy-a-star-pathfinding-7e6689c7f7b2]
    Code adapted from = [https://morioh.com/p/cf0c6b11c848?f=5c21fb01c16e2556b555ab32]

    Parameters
    ----------
    nodes : list
        A list of nodes present in the grid
    start : Node
        The starting point
    end : Node
        The ending point

    Returns
    -------
    bool
        True if the ending node was reached, else False
    """
    def h(node1: Node, node2: Node):
        return abs(node1.row - node2.row) + abs(node1.col - node2.col)

    def buildReversePath(came_from: dict, current: Node):
        while current in came_from:
            current = came_from[current]
            current.setState("path")
            gui.updateContents()

    g = 0
    open_set = PriorityQueue(
    )  # tip: A structure that it's always sorted (first f then h...). Method get() gets the first element (lowest f).
    open_set.put((0, g, start))
    came_from = {}
    g_score = {node: float("inf") for node in gui.grid}
    g_score[start] = 0
    f_score = {node: float("inf") for node in gui.grid}
    f_score[start] = h(start, end)

    open_set_hash = {start}

    while not open_set.empty():
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                gui.close()

        *_, current = open_set.get()
        open_set_hash.remove(current)

        if current == end:
            buildReversePath(came_from, end)
            end.setState("end point")
            start.setState("start point")
            return True

        for neighbor in current.neighbors:
            temp_g_score = g_score[current] + 1

            if temp_g_score < g_score[neighbor]:
                came_from[neighbor] = current
                g_score[neighbor] = temp_g_score
                f_score[neighbor] = temp_g_score + h(neighbor, end)
                if neighbor not in open_set_hash:
                    g += 1
                    open_set.put((f_score[neighbor], g, neighbor))
                    open_set_hash.add(neighbor)
                    neighbor.setState("watch")
                    gui.updateContents()

        if current != start:
            current.setState("visited")
            gui.updateContents()

    return False