-
Notifications
You must be signed in to change notification settings - Fork 0
/
canvas.py
60 lines (47 loc) · 1.91 KB
/
canvas.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
from __future__ import annotations
from collections.abc import Iterable
from client.message.extra_types import XY
from .constants import X, Y, Color
class Canvas:
def __init__(self, size: XY, fill_char: str = '·'):
self.size: XY = size
self.fill_char: str = fill_char
self.grid: list[list[str]] = [
[self.fill_char] * self.size[X] for _ in range(self.size[Y])
]
self.color: list[list[Color | None]] = [
[None] * self.size[X] for _ in range(self.size[Y])
]
def clean(self) -> None:
for y in range(self.size[Y]):
for x in range(self.size[X]):
self.grid[y][x] = self.fill_char
self.color[y][x] = None
def highlight(self, pts: Iterable[XY], color: Color) -> None:
for pt in pts:
self.color[pt[Y]][pt[X]] = color
def highlight_except(self, pts: set[XY], color: Color) -> None:
for y in range(self.size[Y]):
for x in range(self.size[X]):
if (x, y) not in pts:
self.color[y][x] = color
@staticmethod
def colored(s: str, color: Color) -> str:
return f'\033[{color}m{s}\033[{Color.CLEAR}m'
def print(self, y_reversed: bool = True):
def tens(val: int) -> int:
return val // 10 % 10
lines = [
(str(tens(y)) if tens(y) else ' ') + str(y % 10) + ' ' + ''.join(
self.colored(ch, self.color[y][x]) if self.color[y][x] else ch
for x, ch in enumerate(row)
) for y, row in enumerate(self.grid)
]
if y_reversed:
lines.reverse()
ruler_x = [
' ' + ''.join(str(tens(x)) if tens(x) else ' ' for x in range(self.size[X])),
' ' + ''.join(str(x % 10) for x in range(self.size[X])),
]
lines = ruler_x + [''] + lines + [''] + ruler_x
print('\n'.join(lines))