Hoje comecei o dia vendo este post que me inspirou a fazer um relógio analógico em ASCII art em Perl.
Ao contrário do post linkado, não tentei fazer golf, mas sim escrever um código legível para fazer o relógio.
Segue abaixo o código todo:
#!/usr/bin/perl
# para além do DateTime, o resto é meio que o cabeçalho padrão...
use 5.010;
use strict;
use warnings;
use utf8;
use DateTime;
# inicia as variáveis utilizadas para configurar o relógio
my $width = 32;
my $height = 32;
my $mark_at = 15;
my $length_m = 12;
my $length_h = 8;
my $length_s = 15;
my $pi = 3.14159265;
my $center_x = int(0.5 + ($width / 2));
my $center_y = int(0.5 + ($height / 2));
my $loop = 1;
# Limpa a tela e posiciona o cursor no início.
# isso é código ANSI para console
print "\x1b[0;0H\x1b[2J";
# fica em loop para renderizar o relógio várias vezes
while ($loop && sleep 1) {
# cria uma matriz da largura e altura configuradas
# com espaços vazios -- utilizo dois espaços em branco,
# porque a fonte do terminal normalmente tem a altura como
# duas vezes a largura.
my $data = [map {[ map { ' ' } 1..$width ]} 1..$height];
# pega a data e hora no fuso horário local e separa os componentes
my $now = DateTime->now(time_zone => 'local');
my $hour = $now->hour_12;
my $min = $now->minute;
my $sec = $now->second;
# converte a informação para os graus para posicionar os ponteiros.
my $degree_m = ($min * 6) + 270;
my $degree_h = ($hour * 30) + 270;
my $degree_s = ($sec * 6) + 270;
# veja a função place lá em baixo.
# Colocamos os números de 1 a 12 no relógio
place($data,($_ * 30) + 270,$mark_at,sprintf("%02d",$_)) for 1..12;
# Agora desenhamos o ponteiro dos minutos
place($data,$degree_m, $_ , '<>') for 0..$length_m;
# ponteiro das horas
place($data,$degree_h, $_ , '::') for 0..$length_h;
# ponteiro dos segundos
place($data,$degree_s, $_ , '..') for 0..$length_s;
# marcador do centro do relógio
$data->[$center_y][$center_x] = 'OO';
# posiciona o cursor no início da tela
print "\x1b[0;0H\n";
# converte a matriz em uma string e joga na tela
say join "\n", map { join '', @$_ } @$data;
};
# converte graus e distância em X e Y, usando trigonometria básica
sub vec2xy {
my ($deg, $len) = @_;
return $center_x + int(0.5 + ($len * cos($deg * ($pi/180)))),
$center_y + int(0.5 + ($len * sin($deg * ($pi/180))));
}
# coloca um valor de texto em um dos elementos da matriz
sub place {
my ($data, $deg, $len, $txt) = @_;
my ($x,$y) = vec2xy($deg,$len);
$data->[$y][$x] = $txt;
}
Leave a comment