Commit f3e3c6372061a443ebae42f27b22e3019c231221

timelog-graph: detailed graph for groups
timelog-graph
(67 / 25)
  
33use warnings;
44use feature 'say';
55use DateTime;
6use GD;
67use GD::Graph::bars;
78use Getopt::Euclid;
89
3131 return %tasks_by_date;
3232}
3333
34sub 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}
3448sub 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
58sub default_graph {
3559 my ($date, %data) = @_;
3660 my %duration_by_group;
3761 foreach (@{$data{$date}}) {
6565 [ map { my $d = DateTime::Duration->new(minutes => $duration_by_group{$_}); sprintf("%s: %d:%02d", $_, $d->hours, $d->minutes) } keys %duration_by_group ],
6666 [ map { $duration_by_group{$_} / 60 } keys %duration_by_group ],
6767 );
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);
8669}
8770
71sub 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
8890my $today = DateTime->now;
89$today->add(days => -$ARGV{'<days>'});
91$today->add(days => -$ARGV{-d});
9092my %tasks_by_date = parse_timelog('/home/joenio/.gtimelog/timelog.txt');
9193if (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 }
93100}
94101else {
95102 warn "nao existem registros no dia: " . $today->ymd;
120120
121121=over
122122
123=item <days>
123=item -d <d>
124124
125Gerar relatorio de X dias atras.
125Gerar grafico de <d> dias atras.
126126
127127=for Euclid:
128 days.type: int >= 0
129 days.default: 0
128 d.type: int >= 0
129 d.default: 0
130130
131=item -g <g>
132
133Gerar grafico detalhado do grupo <g>.
134
131135=item --version
132136
133137=item --usage
166166
167167=item Gerar grafico de pizza com 24H
168168
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
173http://search.cpan.org/~jzucker/DBD-AnyData-0.09/AnyData.pm
174http://search.cpan.org/~jzucker/DBD-CSV-0.22/lib/DBD/CSV.pm
175http://search.cpan.org/~timb/DBI-1.607/lib/DBD/File.pm
170176
171177=back
172178