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