Relógio Analógico em ASCII

| No Comments | No TrackBacks

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;
}

No TrackBacks

TrackBack URL: http://daniel.ruoso.com/cgi-bin/mt/mt-tb.cgi/202

Leave a comment

About this Entry

This page contains a single entry by Daniel Ruoso published on December 14, 2009 2:30 PM.

Diferenças entre métodos ágeis e tradicionais was the previous entry in this blog.

Minha jornada para o SDL em Perl is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.