logstats 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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')}") }