Merge remote-tracking branch 'origin/master'

This commit is contained in:
Stefan Harmuth 2021-12-21 10:08:24 +01:00
commit b6bef1a78e
3 changed files with 102 additions and 42 deletions

View File

@ -1,23 +1,33 @@
from __future__ import annotations from __future__ import annotations
from .coordinate import Coordinate, DistanceAlgorithm from .coordinate import Coordinate, DistanceAlgorithm
from .types import Numeric
from enum import Enum from enum import Enum
from heapq import heappop, heappush from heapq import heappop, heappush
from typing import Any, Dict, List, Union from typing import Any, Dict, List, Union
OFF = False OFF = False
ON = True ON = True
Numeric = Union[int, float]
class GridTransformation(Enum): class GridTransformation(Enum):
FLIP_X = 1 # Rotations always take the axis to rotate around as if it were the z-axis and then rotate clockwise
FLIP_HORIZONTALLY = 1 # alias for FLIP_X; prep for 3d-transformations # Counter-Rotations likewise, just anti-clockwise
FLIP_VERTICALLY = 2 # 3D-only OPs have a number > 10
FLIP_DIAGONALLY = 3 ROTATE_Z = 3
FLIP_DIAGONALLY_REV = 4 ROTATE_X = 11
ROTATE_RIGHT = 5 ROTATE_Y = 12
ROTATE_LEFT = 6 COUNTER_ROTATE_X = 14
ROTATE_TWICE = 7 COUNTER_ROTATE_Y = 15
COUNTER_ROTATE_Z = 7
FLIP_X = 4
FLIP_Y = 5
FLIP_Z = 13
# Handy aliases
FLIP_HORIZONTALLY = 5
FLIP_VERTICALLY = 4
ROTATE_RIGHT = 3
ROTATE_LEFT = 7
class Grid: class Grid:
@ -162,40 +172,40 @@ class Grid:
self.set(c2, buf) self.set(c2, buf)
def transform(self, mode: GridTransformation): def transform(self, mode: GridTransformation):
if self.mode3D: if mode.value > 10 and not self.mode3D:
raise NotImplementedError() # that will take some time and thought raise ValueError("Operation not possible in 2D space", mode)
if mode == GridTransformation.FLIP_HORIZONTALLY: coords = self.__grid
for x in range(self.minX, (self.maxX - self.minX) // 2 + 1): self.__grid, self.minX, self.maxX, self.minY, self.maxY, self.minZ, self.maxZ = {}, 0, 0, 0, 0, 0, 0
for y in range(self.minY, self.maxY + 1): if mode == GridTransformation.ROTATE_X:
self.flip(Coordinate(x, y), Coordinate(self.maxX - x, y)) for c, v in coords.items():
elif mode == GridTransformation.FLIP_VERTICALLY: self.set(Coordinate(c.x, -c.z, c.y), v)
for y in range(self.minY, (self.maxY - self.minY) // 2 + 1): elif mode == GridTransformation.ROTATE_Y:
for x in range(self.minX, self.maxX + 1): for c, v in coords.items():
self.flip(Coordinate(x, y), Coordinate(x, self.maxY - y)) self.set(Coordinate(-c.z, c.y, c.x), v)
elif mode == GridTransformation.FLIP_DIAGONALLY: elif mode == GridTransformation.ROTATE_Z:
self.transform(GridTransformation.ROTATE_LEFT) for c, v in coords.items():
self.transform(GridTransformation.FLIP_HORIZONTALLY) self.set(Coordinate(c.y, -c.x, c.z), v)
elif mode == GridTransformation.FLIP_DIAGONALLY_REV: elif mode == GridTransformation.COUNTER_ROTATE_X:
self.transform(GridTransformation.ROTATE_RIGHT) for c, v in coords.items():
self.transform(GridTransformation.FLIP_HORIZONTALLY) self.set(Coordinate(c.x, c.z, -c.y), v)
elif mode == GridTransformation.ROTATE_LEFT: elif mode == GridTransformation.COUNTER_ROTATE_Y:
newGrid = Grid() for c, v in coords.items():
for x in range(self.maxX, self.minX - 1, -1): self.set(Coordinate(c.z, c.y, -c.x), v)
for y in range(self.minY, self.maxY + 1): elif mode == GridTransformation.COUNTER_ROTATE_Z:
newGrid.set(Coordinate(y, self.maxX - x), self.get(Coordinate(x, y))) for c, v in coords.items():
self.set(Coordinate(-c.y, c.x, c.z), v)
self.__dict__.update(newGrid.__dict__) elif mode == GridTransformation.FLIP_X:
elif mode == GridTransformation.ROTATE_RIGHT: for c, v in coords.items():
newGrid = Grid() self.set(Coordinate(-c.x, c.y, c.z), v)
for x in range(self.minX, self.maxX + 1): elif mode == GridTransformation.FLIP_Y:
for y in range(self.maxY, self.minY - 1, -1): for c, v in coords.items():
newGrid.set(Coordinate(self.maxY - y, x), self.get(Coordinate(x, y))) self.set(Coordinate(c.x, -c.y, c.z), v)
elif mode == GridTransformation.FLIP_Z:
self.__dict__.update(newGrid.__dict__) for c, v in coords.items():
elif mode == GridTransformation.ROTATE_TWICE: self.set(Coordinate(c.x, c.y, -c.z), v)
self.transform(GridTransformation.ROTATE_RIGHT) else:
self.transform(GridTransformation.ROTATE_RIGHT) raise NotImplementedError(mode)
def getPath(self, pos_from: Coordinate, pos_to: Coordinate, includeDiagonal: bool, walls: List[Any] = None, def getPath(self, pos_from: Coordinate, pos_to: Coordinate, includeDiagonal: bool, walls: List[Any] = None,
weighted: bool = False) -> Union[None, List[Coordinate]]: weighted: bool = False) -> Union[None, List[Coordinate]]:

View File

@ -1,4 +1,8 @@
from time import sleep
from .schedule import Scheduler
from .simplesocket import ClientSocket from .simplesocket import ClientSocket
from datetime import timedelta
from enum import Enum from enum import Enum
from typing import Callable, Dict, List, Union from typing import Callable, Dict, List, Union
@ -365,3 +369,43 @@ class Client:
def getChannelList(self) -> List[Channel]: def getChannelList(self) -> List[Channel]:
return list(self.__channellist.values()) return list(self.__channellist.values())
class IrcBot(Client):
def __init__(self, server: str, port: int, nick: str, username: str, realname: str = "Python Bot"):
super().__init__(server, port, nick, username, realname)
self._scheduler = Scheduler()
self._channel_commands = {}
self._privmsg_commands = {}
self.subscribe(ServerMessage.MSG_PRIVMSG, self.on_privmsg)
def on(self, *args, **kwargs):
self.subscribe(*args, **kwargs)
def schedule(self, name: str, every: timedelta, func: Callable):
self._scheduler.schedule(name, every, func)
def register_channel_command(self, command: str, channel: str, func: Callable):
if channel not in self._channel_commands:
self._channel_commands[channel] = {}
self._channel_commands[channel][command] = func
def register_privmsg_command(self, command: str, func: Callable):
self._privmsg_commands[command] = func
def on_privmsg(self, msg_from, msg_to, message):
if not message:
return
command = message.split()[0]
if msg_to in self._channel_commands and command in self._channel_commands[msg_to]:
self._channel_commands[msg_to][command](msg_from, " ".join(message.split()[1:]))
if msg_to == self.getUser().nickname and command in self._privmsg_commands:
self._privmsg_commands[command](msg_from, " ".join(message.split()[1:]))
def run(self):
while True:
self._scheduler.run_pending()
self.receive()
sleep(0.01)

6
tools/types.py Normal file
View File

@ -0,0 +1,6 @@
from typing import Union
Numeric = Union[int, float]
IntOrNone = Union[int, None]
FloatOrNone = Union[float, None]
NumericOrNone = Union[Numeric, None]