Commit f3e3c6372061a443ebae42f27b22e3019c231221
- Diff rendering mode:
- inline
- side by side
timelog-graph
(67 / 25)
|   | |||
| 3 | 3 | use warnings; | |
| 4 | 4 | use feature 'say'; | |
| 5 | 5 | use DateTime; | |
| 6 | use GD; | ||
| 6 | 7 | use GD::Graph::bars; | |
| 7 | 8 | use Getopt::Euclid; | |
| 8 | 9 | ||
| … | … | ||
| 31 | 31 | return %tasks_by_date; | |
| 32 | 32 | } | |
| 33 | 33 | ||
| 34 | sub build_graph { | ||
| 35 | my ($title, $x_label, $y_label) = @_; | ||
| 36 | my $graph = GD::Graph::bars->new(700, 500); | ||
| 37 | $graph->set( | ||
| 38 | transparent => 0, | ||
| 39 | x_label => $x_label, | ||
| 40 | y_label => $y_label, | ||
| 41 | title => $title, | ||
| 42 | bar_spacing => 5, | ||
| 43 | cycle_clrs => 1, | ||
| 44 | overwrite => 1, | ||
| 45 | ) or die $graph->error; | ||
| 46 | return $graph; | ||
| 47 | } | ||
| 34 | 48 | sub plot_graph { | |
| 49 | my ($graph, $filename, @data) = @_; | ||
| 50 | my $gd = $graph->plot(\@data) or die $graph->error; | ||
| 51 | open IMG, '>', "$filename.png" or die $!; | ||
| 52 | binmode IMG; | ||
| 53 | print IMG $gd->png; | ||
| 54 | close IMG; | ||
| 55 | say "grafico salvo em: $filename.png"; | ||
| 56 | } | ||
| 57 | |||
| 58 | sub default_graph { | ||
| 35 | 59 | my ($date, %data) = @_; | |
| 36 | 60 | my %duration_by_group; | |
| 37 | 61 | foreach (@{$data{$date}}) { | |
| … | … | ||
| 65 | 65 | [ map { my $d = DateTime::Duration->new(minutes => $duration_by_group{$_}); sprintf("%s: %d:%02d", $_, $d->hours, $d->minutes) } keys %duration_by_group ], | |
| 66 | 66 | [ map { $duration_by_group{$_} / 60 } keys %duration_by_group ], | |
| 67 | 67 | ); | |
| 68 | my $graph = GD::Graph::bars->new(700, 500); | ||
| 69 | $graph->set( | ||
| 70 | transparent => 0, | ||
| 71 | x_label => 'Grupo', | ||
| 72 | y_label => 'Horas', | ||
| 73 | #y_max_value => 24, | ||
| 74 | #y_tick_number => 24, | ||
| 75 | title => "Horas trabalhadas por Grupo em $date", | ||
| 76 | dclrs => [qw( gray green red blue )], | ||
| 77 | cycle_clrs => 1, | ||
| 78 | bar_spacing => 5, | ||
| 79 | ) or die $graph->error; | ||
| 80 | my $gd = $graph->plot(\@data) or die $graph->error; | ||
| 81 | open IMG, '>', "$date.png" or die $!; | ||
| 82 | binmode IMG; | ||
| 83 | print IMG $gd->png; | ||
| 84 | close IMG; | ||
| 85 | say "grafico salvo em: $date.png"; | ||
| 68 | plot_graph(build_graph("Horas trabalhadas por grupo em $date", 'Grupo', 'Horas'), "$date", @data); | ||
| 86 | 69 | } | |
| 87 | 70 | ||
| 71 | sub detailed_graph { | ||
| 72 | my ($date, $group, %data) = @_; | ||
| 73 | my @tasks = map { [$_->{task}, $_->{minutes}] } grep { $_->{group} eq $group } @{$data{$date}}; | ||
| 74 | my %duration_by_task; | ||
| 75 | foreach (@tasks) { | ||
| 76 | $duration_by_task{$_->[0]} += $_->[1]; | ||
| 77 | } | ||
| 78 | my @data = ( | ||
| 79 | [ map { my $d = DateTime::Duration->new(minutes => $duration_by_task{$_}); sprintf("%d:%02d", $d->hours, $d->minutes) } keys %duration_by_task ], | ||
| 80 | #[ map { $duration_by_task{$_} / 60 } keys %duration_by_task ], | ||
| 81 | ); | ||
| 82 | foreach (keys %duration_by_task) { | ||
| 83 | push @data, [ map { $duration_by_task{$_} / 60 } keys %duration_by_task ], | ||
| 84 | } | ||
| 85 | my $graph = build_graph("Detalhe de horas trabalhadas do grupo $group em $date", 'Tarefas', 'Horas'); | ||
| 86 | $graph->set_legend(keys %duration_by_task); | ||
| 87 | plot_graph($graph, $date .'-'. lc($group), @data); | ||
| 88 | } | ||
| 89 | |||
| 88 | 90 | my $today = DateTime->now; | |
| 89 | $today->add(days => -$ARGV{'<days>'}); | ||
| 91 | $today->add(days => -$ARGV{-d}); | ||
| 90 | 92 | my %tasks_by_date = parse_timelog('/home/joenio/.gtimelog/timelog.txt'); | |
| 91 | 93 | if (exists $tasks_by_date{$today->ymd}) { | |
| 92 | plot_graph($today->ymd, %tasks_by_date); | ||
| 94 | if ($ARGV{-g}) { | ||
| 95 | detailed_graph($today->ymd, $ARGV{-g}, %tasks_by_date); | ||
| 96 | } | ||
| 97 | else { | ||
| 98 | default_graph($today->ymd, %tasks_by_date); | ||
| 99 | } | ||
| 93 | 100 | } | |
| 94 | 101 | else { | |
| 95 | 102 | warn "nao existem registros no dia: " . $today->ymd; | |
| … | … | ||
| 120 | 120 | ||
| 121 | 121 | =over | |
| 122 | 122 | ||
| 123 | =item <days> | ||
| 123 | =item -d <d> | ||
| 124 | 124 | ||
| 125 | Gerar relatorio de X dias atras. | ||
| 125 | Gerar grafico de <d> dias atras. | ||
| 126 | 126 | ||
| 127 | 127 | =for Euclid: | |
| 128 | days.type: int >= 0 | ||
| 129 | days.default: 0 | ||
| 128 | d.type: int >= 0 | ||
| 129 | d.default: 0 | ||
| 130 | 130 | ||
| 131 | =item -g <g> | ||
| 132 | |||
| 133 | Gerar grafico detalhado do grupo <g>. | ||
| 134 | |||
| 131 | 135 | =item --version | |
| 132 | 136 | ||
| 133 | 137 | =item --usage | |
| … | … | ||
| 166 | 166 | ||
| 167 | 167 | =item Gerar grafico de pizza com 24H | |
| 168 | 168 | ||
| 169 | =item Detalhar tarefas do grupo no grafico de barras | ||
| 169 | =item Corrigir problemas de codificação | ||
| 170 | |||
| 171 | =item Acessar arquivo timelog.txt usando uma intreface SQL | ||
| 172 | |||
| 173 | http://search.cpan.org/~jzucker/DBD-AnyData-0.09/AnyData.pm | ||
| 174 | http://search.cpan.org/~jzucker/DBD-CSV-0.22/lib/DBD/CSV.pm | ||
| 175 | http://search.cpan.org/~timb/DBI-1.607/lib/DBD/File.pm | ||
| 170 | 176 | ||
| 171 | 177 | =back | |
| 172 | 178 |

