File Coverage

blib/lib/App/TimelogTxt/Day.pm
Criterion Covered Total %
statement 81 116 69.8
branch 21 26 80.7
condition 11 16 68.7
subroutine 15 22 68.1
pod 14 14 100.0
total 142 194 73.2


line stmt bran cond sub pod time code
1             package App::TimelogTxt::Day;
2              
3 2     2   67234 use warnings;
  2         4  
  2         137  
4 2     2   17 use strict;
  2         5  
  2         90  
5              
6 2     2   562 use App::TimelogTxt::Utils;
  2         4  
  2         82  
7 2     2   14 use List::Util qw/sum/;
  2         4  
  2         3854  
8              
9             our $VERSION = '0.21';
10              
11             sub new {
12 5     5 1 3095 my ($class, $stamp) = @_;
13 5 100       29 die "Missing required stamp.\n" unless $stamp;
14 4 100       20 die "Invalid stamp format.\n" unless App::TimelogTxt::Utils::is_datestamp( $stamp );
15              
16 3         35 return bless {
17             stamp => $stamp,
18             start => undef,
19             dur => 0,
20             tasks => {},
21             proj_dur => {},
22             last_start => 0,
23             }, $class;
24             }
25              
26 1     1 1 619 sub is_empty { return !$_[0]->{dur}; }
27 0     0 1 0 sub is_complete { return !$_[0]->{last_start}; }
28 0     0 1 0 sub date_stamp { return $_[0]->{stamp}; }
29 0     0 1 0 sub has_tasks { return !!keys %{$_[0]->{tasks}}; }
  0         0  
30              
31             sub update_dur
32             {
33 9     9 1 932 my ($self, $last, $epoch) = @_;
34 9 100       37 my $curr_dur = $last ? $epoch - $last->epoch : 0;
35              
36 9 100 100     51 $self->{tasks}->{$last->task}->{dur} += $curr_dur if $last && $last->task;
37 9 100 100     88 $self->{proj_dur}->{$last->project} += $curr_dur if $last && $last->project;
38 9         62 $self->{dur} += $curr_dur;
39              
40 9         20 return;
41             }
42              
43             sub day_filtered_by_project
44             {
45 0     0 1 0 my ($self, $project) = @_;
46 0         0 my $result = __PACKAGE__->new( $self->date_stamp );
47 0 0       0 $project = qr/$project/ unless ref $project;
48 0         0 my @tasks = grep { $self->{tasks}->{$_}->{proj} =~ $project } keys %{$self->{tasks}};
  0         0  
  0         0  
49 0         0 @{$result->{tasks}}{@tasks} = @{$self->{tasks}}{@tasks};
  0         0  
  0         0  
50 0         0 my @projs = grep { $_ =~ $project } keys %{$self->{proj_dur}};
  0         0  
  0         0  
51 0         0 @{$result->{proj_dur}}{@projs} = @{$self->{proj_dur}}{@projs};
  0         0  
  0         0  
52 0         0 $result->{dur} = sum( 0, values %{$result->{proj_dur}} );
  0         0  
53 0         0 return $result;
54             }
55              
56             sub close_day
57             {
58 0     0 1 0 my ($self, $last) = @_;
59 0 0       0 return if $self->is_complete();
60              
61 0         0 $self->update_dur( $last, $self->day_end() );
62 0         0 $self->{last_start} = 0;
63 0         0 return;
64             }
65              
66             sub start_task {
67 7     7 1 23 my ($self, $event) = @_;
68 7 100       19 if( $event->is_stop() )
69             {
70 1         7 $self->{last_start} = 0;
71 1         3 return;
72             }
73 6         36 my $task = $event->task;
74 6         28 $self->{last_start} = $event->epoch;
75 6 100       33 return if $self->{tasks}->{$task};
76 4         8 $self->{tasks}->{$task} = { start => $event->epoch, proj => $event->project, dur => 0 };
77 4         39 return;
78             }
79              
80             sub print_day_detail {
81 3     3 1 1482 my ($self, $fh) = @_;
82 3   50     17 $fh ||= \*STDOUT;
83              
84 3         6 my ($tasks, $proj_dur) = @{$self}{ qw/tasks proj_dur/ };
  3         13  
85 3         8 my $last_proj = '';
86              
87 3         4 print {$fh} "\n", _format_stamp_line( $self );
  3         13  
88 3 50       8 foreach my $t ( sort { ($tasks->{$a}->{proj} cmp $tasks->{$b}->{proj}) || ($tasks->{$b}->{start} <=> $tasks->{$a}->{start}) } keys %{$tasks} )
  5         23  
  3         23  
89             {
90 4         8 my $curr = $tasks->{$t};
91 4 100       14 if( $curr->{proj} ne $last_proj )
92             {
93 2         3 print {$fh} _format_project_line( $curr->{proj}, $proj_dur->{$curr->{proj}} );
  2         10  
94 2         7 $last_proj = $curr->{proj};
95             }
96 4         6 my $task = $t;
97 4         5 print {$fh} _format_task_line( $t, $curr->{dur} );
  4         17  
98             }
99 3         11 return;
100             }
101              
102             sub print_day_summary {
103 2     2 1 1668 my ($self, $fh) = @_;
104 2   50     11 $fh ||= \*STDOUT;
105              
106 2         5 my $proj_dur = $self->{proj_dur};
107              
108 2         5 print {$fh} _format_stamp_line( $self );
  2         8  
109 2         7 foreach my $p ( sort keys %{$proj_dur} )
  2         15  
110             {
111 2         3 print {$fh} _format_project_line( $p, $proj_dur->{$p} );
  2         9  
112             }
113 2         9 return;
114             }
115              
116             sub print_hours {
117 1     1 1 638 my ($self, $fh) = @_;
118 1   50     7 $fh ||= \*STDOUT;
119              
120 1         2 print {$fh} _format_stamp_line( $self, ':' );
  1         6  
121 1         4 return;
122             }
123              
124             sub print_duration {
125 0     0 1 0 my ($self, $fh) = @_;
126 0   0     0 $fh ||= \*STDOUT;
127              
128 0         0 print {$fh} _format_dur( $self->{dur} ), "\n";
  0         0  
129 0         0 return;
130             }
131              
132             sub day_end
133             {
134 0     0 1 0 my ($self) = @_;
135              
136 0         0 return App::TimelogTxt::Utils::stamp_to_localtime( $self->{stamp} );
137             }
138              
139             sub _format_dur
140             {
141 14     14   44 my ($dur) = @_;
142 14         20 $dur += 30; # round, don't truncate.
143 14         153 return sprintf( '%2d:%02d', int($dur/3600), int(($dur%3600)/60) );
144             }
145              
146             sub _format_stamp_line
147             {
148 6     6   11 my ($self, $sep) = @_;
149 6   100     29 $sep ||= '';
150              
151 6         29 return "$self->{stamp}$sep " . _format_dur( $self->{dur} ) . "\n";
152             }
153              
154             sub _format_task_line
155             {
156 4     4   7 my ($task, $dur) = @_;
157              
158 4         9 $task =~ s/\+\S+\s//;
159 4 100       28 if ( $task =~ s/\@(\S+)\s*// )
160             {
161 2 100       10 if ( $task ) {
162 1         5 return sprintf( " %-20s%s (%s)\n", $1, _format_dur( $dur ), $task );
163             }
164             else {
165 1         5 return sprintf( " %-20s%s\n", $1, _format_dur( $dur ) );
166             }
167             }
168             else {
169 2         7 return sprintf( " %-20s%s\n", $task, _format_dur( $dur ) );
170             }
171 0         0 return;
172             }
173              
174             sub _format_project_line
175             {
176 4     4   7 my ($proj, $dur) = @_;
177              
178 4         8 return sprintf( ' %-13s%s', $proj, _format_dur( $dur ). "\n" );
179             }
180              
181             1;
182             __END__