logstats 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore CHANGED
@@ -2,4 +2,7 @@ pkg/*
2
2
  *.gem
3
3
  .bundle
4
4
  scratch/
5
+ examples/
6
+ watchr/
5
7
  logstats.html
8
+ .rvmrc
data/CHANGELOG CHANGED
@@ -1,4 +1,8 @@
1
+ 0.0.3 (08Dec2011)
2
+ BUGFIX: Update to correctly distinguish between billable (with project code) and non-billable (without project code).
3
+ Added basic "% billable" statistic, and total time for the period. Default display is now billable.
4
+ Tweaked styles to work better with the additional data.
1
5
  0.0.2 (08Dec2011)
2
- BUGFIX: Failed to calculate today's time when there wasn't an open task
6
+ BUGFIX: Failed to calculate today's time when there wasn't an open task.
3
7
  0.0.1 (08Dec2011)
4
- Initial Release
8
+ Initial Release.
@@ -9,6 +9,9 @@ module Helpers
9
9
  o=[]
10
10
  o << "<span class=\"hour\">#{hrs}</span> hr" if hrs.to_i > 0
11
11
  o << "<span class=\"minute\">#{min}</span> min" if min.to_i > 0
12
+ if o.size == 0 then
13
+ o << "<span class=\"none\">NONE :(</span>"
14
+ end
12
15
  o.join(' ')
13
16
  end
14
17
 
@@ -19,8 +22,40 @@ module Helpers
19
22
  "<span class=\"#{options[:class]}\">#{self.time_to_html(seconds)}</span>"
20
23
  end
21
24
 
25
+ def self.threshold_met?(seconds, period)
26
+ (self.threshold_for_period(period) - seconds) < 0
27
+ end
28
+
22
29
  def self.remaining_tag(seconds_so_far, period)
23
- seconds_required=case period
30
+ seconds=self.threshold_for_period(period) - seconds_so_far
31
+
32
+ css_class=[ 'remaining ']
33
+ if seconds < 0 then
34
+ content=self.time_to_html(seconds.abs) + ' over!'
35
+ css_class << 'met'
36
+ else
37
+ content=self.time_to_html(seconds) + ' remaining'
38
+ end
39
+ "<div class=\"#{css_class.join(' ')}\">#{content}</div>"
40
+ end
41
+
42
+ # Outputs some basic productivity statistics
43
+ def self.productivity_tag(data)
44
+ o=[]
45
+ css_classes=[ 'productivity' ]
46
+
47
+ if data[:total] > 0 then
48
+ o << self.time_to_html(data[:total]) if data[:total] > 0
49
+ percent=((data[:billable] / data[:total]) * 100).ceil
50
+ o << "#{percent}% billable"
51
+ end
52
+
53
+ "<div class=\"#{css_classes.join(' ')}\">#{o.join(' | ')}</div>"
54
+ end
55
+
56
+ # Returns the threshold number of seconds that need to be attained each period
57
+ def self.threshold_for_period(period)
58
+ case period
24
59
  when :day
25
60
  # 5 hrs per day
26
61
  5 * 3600
@@ -30,17 +65,6 @@ module Helpers
30
65
  else
31
66
  raise "Unknown period: #{period}"
32
67
  end
33
-
34
- seconds=seconds_required - seconds_so_far
35
-
36
- css_class=[ 'remaining ']
37
- if seconds.nil? || seconds < 0 then
38
- content=self.time_to_html(seconds.abs) + ' over!'
39
- css_class << 'met'
40
- else
41
- content=self.time_to_html(seconds) + ' remaining'
42
- end
43
- "<div class=\"#{css_class.join(' ')}\">(#{content})</div>"
44
68
  end
45
69
  end
46
70
  end
@@ -46,23 +46,30 @@
46
46
  :padding 0
47
47
 
48
48
  .duration
49
- :font-size 200%
50
49
  :color $text_faded_color
51
50
  :line-height 40px
51
+ :font-variant small-caps
52
+ :font-size 150%
52
53
 
53
54
  span
54
55
  :color $text_color
56
+ // 1.5x bigger than the HR/MIN
57
+ :font-size 150%
55
58
 
56
59
  .met
57
60
  :color $success_color
58
61
 
62
+ .remaining
63
+ :color $success_color
64
+
59
65
  .duration
60
66
  :color $success_faded_color
61
67
 
62
68
  span
63
69
  :color $success_color
64
70
 
65
- //.remaining, .average
71
+ .remaining
72
+ :color red
66
73
 
67
74
  .recent, .history
68
75
  :width 200px
@@ -86,6 +93,9 @@
86
93
  :padding 5px
87
94
  :border-left 1px solid $border_color
88
95
 
96
+ .duration
97
+ :line-height 35px
98
+
89
99
  .today, .week
90
100
  :border-bottom 1px solid $border-color
91
101
 
@@ -96,28 +106,31 @@
96
106
  .current
97
107
  %h1 Current Task
98
108
  - if current then
99
- = duration_tag(current)
109
+ = duration_tag(current[:total])
100
110
  - else
101
111
  N/A
102
112
  .today
103
- %h1 Projects
113
+ %h1 Today's Projects
104
114
  %ul.projects
105
115
  - today[:projects].each do |project, time|
106
116
  %li
107
- %span.project= project
117
+ %span.project= project || "Misc."
108
118
  = duration_tag(time)
109
119
  .history
110
- .today{ :class => (today[:remaining].nil? ? 'met' : nil )}
120
+ .today{ :class => (threshold_met?(today[:billable], :day) ? 'met' : nil )}
111
121
  %h1 Today
112
- = duration_tag(today[:total])
113
- = remaining_tag(today[:total], :day)
122
+ = duration_tag(today[:billable])
123
+ = remaining_tag(today[:billable], :day)
124
+ = productivity_tag(today)
114
125
 
115
- .week{ :class => (week[:remaining].nil? ? 'met' : nil )}
126
+ .week{ :class => (threshold_met?(week[:billable], :week) ? 'met' : nil )}
116
127
  %h1 Week
117
- = duration_tag(week[:total])
118
- = remaining_tag(week[:total], :week)
128
+ = duration_tag(week[:billable])
129
+ = remaining_tag(week[:billable], :week)
130
+ = productivity_tag(week)
119
131
  .month
120
132
  %h1 Month
121
- = duration_tag(month[:total])
133
+ = duration_tag(month[:billable])
122
134
  .average
123
- (#{time_to_html(month[:average])} average)
135
+ #{time_to_html(month[:average])} / day avg.
136
+ = productivity_tag(month)
@@ -1,3 +1,3 @@
1
1
  module Logstats
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -55,19 +55,21 @@ class WorkLog < TailFromSentinel::Base
55
55
  when DATE_SENTINEL_REGEX
56
56
  # It's a date marker - set current_time
57
57
  current_time=Time.parse(WorkLog.parse_sentinel($1,$2,$3).reverse.join('-'))
58
- days[current_time]={ :total => 0, :projects => {} }
58
+ days[current_time]={ :total => 0, :billable => 0, :projects => {} }
59
59
 
60
60
  when WORKLOG_RECORD_REGEX
61
61
  # It's a worklog record - parse it, and add it to the relevant buckets
62
62
  duration, project=parse_worklog_record(current_time, $1, $2, $3, $4, $5)
63
63
 
64
64
  days[current_time][:total] += duration
65
+ days[current_time][:billable] += duration if project
65
66
  days[current_time][:projects][project] ||= 0
66
67
  days[current_time][:projects][project] += duration
67
68
 
68
69
  when OPEN_WORKLOG_RECORD_REGEX
69
70
  duration, project=parse_worklog_record(current_time, $1, $2, $3)
70
- days[:current]=duration
71
+ days[:current]={ :total => duration, :billable => 0 }
72
+ days[:current][:billable] = duration if project
71
73
 
72
74
  when /^\s*$/
73
75
  # Blank line - ignore
@@ -92,7 +94,7 @@ class WorkLog < TailFromSentinel::Base
92
94
  if msg.match(/^([A-Z0-9]{3})/) then
93
95
  project=$1
94
96
  else
95
- project='MISC'
97
+ project=false
96
98
  end
97
99
  [ duration, project ]
98
100
  end
@@ -100,14 +102,19 @@ class WorkLog < TailFromSentinel::Base
100
102
  def compile_day_data(days)
101
103
  stats={ :current => days[:current],
102
104
  :today => { :total => 0,
105
+ :billable => 0,
103
106
  :projects => { }
104
107
  },
105
108
  :week => { :total => 0,
109
+ :billable => 0,
106
110
  :average => 0,
111
+ :average_billable => 0,
107
112
  :projects => { }
108
113
  },
109
114
  :month => { :total => 0,
115
+ :billable => 0,
110
116
  :average => 0,
117
+ :average_billable => 0,
111
118
  :days_logged => 0,
112
119
  :projects => { }
113
120
  }
@@ -124,25 +131,40 @@ class WorkLog < TailFromSentinel::Base
124
131
 
125
132
  if time_to_date(time).cweek == today.cweek then
126
133
  stats[:week][:total] += data[:total]
134
+ stats[:week][:billable] += data[:billable]
127
135
  stats[:week][:average] = (stats[:week][:total] / time_to_date(time).wday.to_f)
136
+ stats[:week][:average_billable] = (stats[:week][:billable] / time_to_date(time).wday.to_f)
128
137
  data[:projects].each do |project, duration|
129
- stats[:week][:projects][project] ||= 0
130
- stats[:week][:projects][project] += duration
138
+ if project then
139
+ stats[:week][:projects][project] ||= 0
140
+ stats[:week][:projects][project] += duration
141
+ end
131
142
  end
132
143
  end
133
144
 
134
145
  # Everything is included in this month
135
146
  stats[:month][:total] += data[:total]
147
+ stats[:month][:billable] += data[:billable]
136
148
  stats[:month][:days_logged] += 1
137
149
  stats[:month][:average] = (stats[:month][:total] / stats[:month][:days_logged])
150
+ stats[:month][:average_billable] = (stats[:month][:billable] / stats[:month][:days_logged])
138
151
  data[:projects].each do |project, duration|
139
- stats[:month][:projects][project] ||= 0
140
- stats[:month][:projects][project] += duration
152
+ if project then
153
+ stats[:month][:projects][project] ||= 0
154
+ stats[:month][:projects][project] += duration
155
+ end
141
156
  end
142
157
  end
143
158
 
144
- stats[:today][:total] += days[:current] unless days[:current].nil?
145
- #stats[:today][:projects]['WIP'] = days[:current]
159
+ # Now add in the current task, if it is present
160
+ if days[:current] then
161
+ stats[:today][:total] += days[:current][:total]
162
+ stats[:today][:billable] += days[:current][:billable]
163
+ stats[:week][:total] += days[:current][:total]
164
+ stats[:week][:billable] += days[:current][:billable]
165
+ stats[:month][:total] += days[:current][:total]
166
+ stats[:month][:billable] += days[:current][:billable]
167
+ end
146
168
 
147
169
  return stats
148
170
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstats
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 3
10
+ version: 0.0.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jason Stirk
@@ -61,21 +61,18 @@ extra_rdoc_files: []
61
61
 
62
62
  files:
63
63
  - .gitignore
64
- - .rvmrc
65
64
  - CHANGELOG
66
65
  - Gemfile
67
66
  - Gemfile.lock
68
67
  - README
69
68
  - Rakefile
70
69
  - bin/logstats
71
- - examples/example.haml
72
70
  - lib/logstats.rb
73
71
  - lib/logstats/haml/helpers.rb
74
72
  - lib/logstats/template.haml
75
73
  - lib/logstats/version.rb
76
74
  - lib/logstats/worklog.rb
77
75
  - logstats.gemspec
78
- - watchr/all.watchr
79
76
  has_rdoc: true
80
77
  homepage: http://github.com/jstirk/logstats
81
78
  licenses: []
data/.rvmrc DELETED
@@ -1,7 +0,0 @@
1
-
2
- if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
3
- && -s "${rvm_path:-$HOME/.rvm}/environments/ruby-1.8.7-p299@logstats" ]] ; then
4
- \. "${rvm_path:-$HOME/.rvm}/environments/ruby-1.8.7-p299@logstats"
5
- else
6
- rvm --create use "ruby-1.8.7-p299@logstats"
7
- fi
@@ -1,128 +0,0 @@
1
- !!!
2
- %html
3
- %head
4
- %title Log Stats @ 2011-01-18 07:09
5
- %style
6
- :sass
7
- $background_color_light: #454342
8
- $background_color_dark: #333335
9
- $text_color: white
10
- $link_color: #a9c743
11
- $border_color: #272b3b
12
-
13
- body
14
- :font-size 62.5%
15
- :font-family Helvetica, sans-serif
16
- :background $background_color_light
17
- :color $text_color
18
-
19
- #logstats
20
- :width 400px
21
- :height 241px
22
- :background $background_color_dark
23
- :border 1px solid $border_color
24
- :text-align center
25
-
26
- h1
27
- :font-size 120%
28
- :text-decoration underline
29
- :font-variant small-caps
30
- :text-align center
31
- :margin 0 0 10px 0
32
- :padding 0
33
-
34
- ul
35
- :list-style-type none
36
- :margin 0
37
- :padding 0
38
- :text-align left
39
-
40
- li
41
- :margin 0
42
- :padding 0
43
-
44
- .duration
45
- :font-size 200%
46
- :color #cacaca
47
-
48
- span
49
- :color $text_color
50
-
51
- .remaining, .average
52
- :margin-top 5px
53
-
54
- .recent, .history
55
- :width 200px
56
- :float left
57
-
58
- .recent
59
- .current, .today
60
- :padding 5px
61
-
62
- .current
63
- :height 50px
64
- :border-bottom 1px solid $border-color
65
-
66
- .history
67
- .today, .week, .month
68
- :height 70px
69
- :padding 5px
70
- :border-left 1px solid $border_color
71
-
72
- .today, .week
73
- :border-bottom 1px solid $border-color
74
-
75
-
76
- %body
77
- #logstats
78
- .recent
79
- .current
80
- %h1 Current
81
- %span.duration
82
- %span.minute 45
83
- min
84
- .today
85
- %h1 Projects
86
- %ul.projects
87
- %li
88
- %span.project MB1
89
- %span.duration
90
- %span.hour 1
91
- hr
92
- %span.minute 57
93
- min
94
- %li
95
- %span.project MY1
96
- %span.duration
97
- %span.hour 2
98
- hr
99
- %span.minute 30
100
- min
101
- .history
102
- .today
103
- %h1 Today
104
- %span.duration
105
- %span.hour 5
106
- hr
107
- %span.minute 57
108
- min
109
- .remaining
110
- (target met!)
111
- .week
112
- %h1 Week
113
- %span.duration
114
- %span.hour 5
115
- hr
116
- %span.minute 57
117
- min
118
- .remaining
119
- (20 hr 3 min remaining)
120
- .month
121
- %h1 Month
122
- %span.duration
123
- %span.hour 35
124
- hr
125
- %span.minute 57
126
- min
127
- .average
128
- (6 hr 12 min average)
@@ -1 +0,0 @@
1
- watch( 'examples/.*\.haml' ) {|md| system("haml #{md[0]} #{md[0].gsub(/haml$/,'html')}") }