Pular para o conteúdo principal

Os métodos do ViewState

O ViewState (página anterior) guarda duas escolhas do usuário: se o caminho aparece e qual cor as paredes têm. O menu precisa mudar cada uma com uma tecla, e o desenho precisa ler a cor atual. Esta página escreve os quatro pedaços da classe: o estado inicial, os dois métodos que mudam o estado e a propriedade que dá a cor.

O estado inicial​

def __init__(self) -> None:
"""Start with the path hidden and white walls."""
self.show_path = False
self.colour_index = 0

O __init__ roda quando o objeto é criado, com ViewState(). O -> None é a anotação de tipo do retorno: o método não devolve nada.

O enunciado não diz como a tela começa. O projeto escolheu o caminho escondido (False) e as paredes brancas (índice 0, o primeiro da paleta): o primeiro desenho mostra o labirinto limpo, e o usuário pede o caminho se quiser.

Alternar o caminho​

def toggle_path(self) -> None:
"""Show the path when hidden and hide it when shown."""
self.show_path = not self.show_path

Toggle é "alternar". O not inverte o valor: not False é True, not True é False. A opção 2 do menu é "Show / Hide" ("mostrar / esconder"): uma tecla só, que inverte. Por isso não há um show() e um hide() separados; o menu nunca precisa de um dos dois sozinho.

O rodízio das cores​

def next_colour(self) -> None:
"""Move to the next wall colour, back to white after blue."""
self.colour_index = (self.colour_index + 1) % len(PALETTE)

O % dá o resto da divisão. Com 4 cores, len(PALETTE) é 4:

Índice antes+ 1% 4Cor depois
011amarelo
122verde
233azul
340branco de novo

O resto nunca chega a 4, então o índice nunca sai da paleta. Usar len(PALETTE) em vez de escrever 4 mantém o rodízio certo se alguém acrescentar uma cor à tupla.

A cor atual​

@property
def wall_colour(self) -> int:
"""SGR background code of the walls.

Returns:
The current colour of PALETTE.
"""
return PALETTE[self.colour_index]

O @property faz o método ser lido como se fosse um atributo, sem parênteses: quem desenha escreve state.wall_colour, e não state.wall_colour(). O RenderService precisa do código da cor (47, 43, 42 ou 44), não da posição dela na paleta; a propriedade faz a tradução, e ninguém fora do ViewState precisa saber que a paleta existe.

As duas metades do estado, e o que muda cada uma:

As duas metades são independentes: alternar o caminho não mexe na cor, e trocar a cor não mexe no caminho.

O arquivo completo​

amazeing/domain/entities/view_state.py
"""State of the display that survives regenerations."""

from amazeing.utils.ansi import Ansi

PALETTE = (Ansi.WHITE, Ansi.YELLOW, Ansi.GREEN, Ansi.BLUE)


class ViewState:
"""Whether the shortest path shows and which colour the walls have.

Attributes:
show_path: True when the shortest path is drawn.
colour_index: Position of the wall colour in PALETTE.
"""

def __init__(self) -> None:
"""Start with the path hidden and white walls."""
self.show_path = False
self.colour_index = 0

def toggle_path(self) -> None:
"""Show the path when hidden and hide it when shown."""
self.show_path = not self.show_path

def next_colour(self) -> None:
"""Move to the next wall colour, back to white after blue."""
self.colour_index = (self.colour_index + 1) % len(PALETTE)

@property
def wall_colour(self) -> int:
"""SGR background code of the walls.

Returns:
The current colour of PALETTE.
"""
return PALETTE[self.colour_index]

Experimente​

Na raiz do projeto:

.venv/bin/python -c '
from amazeing.domain.entities.view_state import ViewState
state = ViewState()
print(state.show_path, state.colour_index, state.wall_colour)
state.toggle_path()
for _ in range(5):
state.next_colour()
print(state.colour_index, state.wall_colour)
print(state.show_path)
'
False 0 47
1 43
2 42
3 44
0 47
1 43
True

A primeira linha é o estado inicial. Depois de cinco trocas de cor, o índice deu a volta (3 → 0) e parou no 1; o caminho, alternado uma vez, ficou True.