identicon/identicon/identicon.py

90 lines
2.5 KiB
Python

from dataclasses import dataclass
from copy import deepcopy
@dataclass
class Coordinate:
x: int
y: int
def __add__(self, other):
return self.__class__(
self.x+other.x,
self.y+other.y
)
class Identicon:
WIDTH = 17
HEIGHT = 9
SYMBOLS = ' .o+=*BOX@%&#/^'
START_SYMBOL = 'S'
END_SYMBOL = 'E'
BISHOP_START = Coordinate(8, 4)
MOVES = {
0: Coordinate(-1, -1), # 00 ↖
1: Coordinate( 1, -1), # 01 ↗
2: Coordinate(-1, 1), # 10 ↙
3: Coordinate( 1, 1), # 11 ↘
}
def __init__(self, data):
self._data = data
self._grid = [[0] * self.WIDTH for _ in range(self.HEIGHT)]
self._bishop_position = deepcopy(self.BISHOP_START)
self._end_position = None
def calculate(self):
for command in self._get_commands():
self._execute(command)
self._end_position = self._bishop_position
def _get_commands(self):
commands = []
for octet in self._data:
commands.extend([
octet & 0b11, # 00 00 00 [00]
(octet >> 2) & 0b11, # 00 00 [00] 00
(octet >> 4) & 0b11, # 00 [00] 00 00
(octet >> 6) & 0b11, # [00] 00 00 00
])
return commands
def _execute(self, command):
move = self.MOVES[command]
self._bishop_position = self._ensure_within_grid_borders(self._bishop_position + move)
self._increment_current_position()
def _ensure_within_grid_borders(self, coordinate: Coordinate):
coordinate.x = max(0, min(self.WIDTH-1, coordinate.x))
coordinate.y = max(0, min(self.HEIGHT-1, coordinate.y))
return coordinate
def _increment_current_position(self):
self._grid[self._bishop_position.y][self._bishop_position.x] += 1
def __str__(self):
icon = self._header+'\n'
for y, row in enumerate(self._grid):
icon += '|'
for x, cell in enumerate(row):
icon += self._determine_symbol(Coordinate(x, y), cell)
icon += '|\n'
icon += self._header
return icon
@property
def _header(self):
return f'+{self.WIDTH*"-"}+'
def _determine_symbol(self, coordinate, cell):
symbol = self.SYMBOLS[min(cell, len(self.SYMBOLS)-1)]
if coordinate == self.BISHOP_START:
symbol = self.START_SYMBOL
elif coordinate == self._end_position:
symbol = self.END_SYMBOL
return symbol