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   139056 use warnings;
  2         3  
  2         77  
4 2     2   10 use strict;
  2         3  
  2         57  
5              
6 2     2   462 use App::TimelogTxt::Utils;
  2         3  
  2         61  
7 2     2   13 use List::Util qw/sum/;
  2         2  
  2         2906  
8              
9             our $VERSION = '0.22';
10              
11             sub new {
12 5     5 1 2929 my ($class, $stamp) = @_;
13 5 100       24 die "Missing required stamp.\n" unless $stamp;
14 4 100       18 die "Invalid stamp format.\n" unless App::TimelogTxt::Utils::is_datestamp( $stamp );
15              
16 3         34 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 615 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 846 my ($self, $last, $epoch) = @_;
34 9 100       34 my $curr_dur = $last ? $epoch - $last->epoch : 0;
35              
36 9 100 100     47 $self->{tasks}->{$last->task}->{dur} += $curr_dur if $last && $last->task;
37 9 100 100     80 $self->{proj_dur}->{$last->project} += $curr_dur if $last && $last->project;
38 9         56 $self->{dur} += $curr_dur;
39              
40 9         17 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         5 $self->{last_start} = 0;
71 1         4 return;
72             }
73 6         37 my $task = $event->task;
74 6         23 $self->{last_start} = $event->epoch;
75 6 100       30 return if $self->{tasks}->{$task};
76 4         10 $self->{tasks}->{$task} = { start => $event->epoch, proj => $event->project, dur => 0 };
77 4         35 return;
78             }
79              
80             sub print_day_detail {
81 3     3 1 1331 my ($self, $fh) = @_;
82 3   50     16 $fh ||= \*STDOUT;
83              
84 3         7 my ($tasks, $proj_dur) = @{$self}{ qw/tasks proj_dur/ };
  3         11  
85 3         4 my $last_proj = '';
86              
87 3         5 print {$fh} "\n", _format_stamp_line( $self );
  3         12  
88 3 50       7 foreach my $t ( sort { ($tasks->{$a}->{proj} cmp $tasks->{$b}->{proj}) || ($tasks->{$b}->{start} <=> $tasks->{$a}->{start}) } keys %{$tasks} )
  4         20  
  3         20  
89             {
90 4         7 my $curr = $tasks->{$t};
91 4 100       13 if( $curr->{proj} ne $last_proj )
92             {
93 2         3 print {$fh} _format_project_line( $curr->{proj}, $proj_dur->{$curr->{proj}} );
  2         7  
94 2         7 $last_proj = $curr->{proj};
95             }
96 4         6 my $task = $t;
97 4         2 print {$fh} _format_task_line( $t, $curr->{dur} );
  4         14  
98             }
99 3         10 return;
100             }
101              
102             sub print_day_summary {
103 2     2 1 1609 my ($self, $fh) = @_;
104 2   50     9 $fh ||= \*STDOUT;
105              
106 2         5 my $proj_dur = $self->{proj_dur};
107              
108 2         3 print {$fh} _format_stamp_line( $self );
  2         8  
109 2         6 foreach my $p ( sort keys %{$proj_dur} )
  2         13  
110             {
111 2         3 print {$fh} _format_project_line( $p, $proj_dur->{$p} );
  2         7  
112             }
113 2         7 return;
114             }
115              
116             sub print_hours {
117 1     1 1 668 my ($self, $fh) = @_;
118 1   50     6 $fh ||= \*STDOUT;
119              
120 1         2 print {$fh} _format_stamp_line( $self, ':' );
  1         4  
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   36 my ($dur) = @_;
142 14         15 $dur += 30; # round, don't truncate.
143 14         134 return sprintf( '%2d:%02d', int($dur/3600), int(($dur%3600)/60) );
144             }
145              
146             sub _format_stamp_line
147             {
148 6     6   9 my ($self, $sep) = @_;
149 6   100     25 $sep ||= '';
150              
151 6         26 return "$self->{stamp}$sep " . _format_dur( $self->{dur} ) . "\n";
152             }
153              
154             sub _format_task_line
155             {
156 4     4   6 my ($task, $dur) = @_;
157              
158 4         7 $task =~ s/\+\S+\s//;
159 4 100       27 if ( $task =~ s/\@(\S+)\s*// )
160             {
161 2 100       12 if ( $task ) {
162 1         3 return sprintf( " %-20s%s (%s)\n", $1, _format_dur( $dur ), $task );
163             }
164             else {
165 1         4 return sprintf( " %-20s%s\n", $1, _format_dur( $dur ) );
166             }
167             }
168             else {
169 2         13 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         7 return sprintf( ' %-13s%s', $proj, _format_dur( $dur ). "\n" );
179             }
180              
181             1;
182             __END__