twstats 0.1.4 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: c03859f83739b7704e23e9df4faba575ea6f3aa6
4
- data.tar.gz: 5906375e59625f9a5ffef39dbd8905325e2ea4f4
2
+ SHA256:
3
+ metadata.gz: b03a403d2eac6f0356f6e8bad78c073c93565139101566472b67d1a2901c0368
4
+ data.tar.gz: 44e5e4ae4cd5eff7e937882fdf01dcddb12d3130a2427ee0ea08cee0a3ed8a1e
5
5
  SHA512:
6
- metadata.gz: 3a6d20cc0fe85c57ad9872e33f16237d54440725cbed8e6cc17dc155a090e96cdf970b2a56dab224e5fc403275872bb470e34128a39747ad7b3a622f3e6667ef
7
- data.tar.gz: 7d25b85fb90cfc3da98763eca74f47c4f3d6377fab7075e2faf3be86912e7000c6ce585797bc5155ef9e73f555e5ee0196f198de94de18ae4b619ec4f63ee287
6
+ metadata.gz: f97828091ec24a7edc400dbf79a82ff4861ea9b17ee4cc937c2709c1fde0c1fae919534c1b89f39efcf22e31062dc37ea0c306e1e9f3f82dac1ef6854af7acff
7
+ data.tar.gz: f7aac1d4b1569fe79b5218601f59305f2b73409281f1cdeafd7eaa06c89b9ed28200d5913d915b779800cbd9aa537110509db078a41011fb72593af128ae2eff
data/.gitignore CHANGED
@@ -6,6 +6,7 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ /vendor/
9
10
 
10
11
  # rspec failure tracking
11
12
  .rspec_status
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- twstats (0)
4
+ twstats (0.1.4)
5
+ rainbow (~> 3.0)
5
6
  tty-prompt (~> 0.17)
6
7
 
7
8
  GEM
@@ -14,6 +15,7 @@ GEM
14
15
  pastel (0.7.2)
15
16
  equatable (~> 0.5.0)
16
17
  tty-color (~> 0.4.0)
18
+ rainbow (3.0.0)
17
19
  rake (10.5.0)
18
20
  rspec (3.8.0)
19
21
  rspec-core (~> 3.8.0)
@@ -13,9 +13,8 @@ module Twstats
13
13
  {name: 'Projects', value: 0},
14
14
  {name: 'People', value: 1},
15
15
  {name: 'Tags', value: 2},
16
- {name: 'Billable vs non-villable', value: 3},
17
- {name: 'Full stats', value: 4},
18
- {name: 'Back', value: 5}
16
+ {name: 'Full stats', value: 3},
17
+ {name: 'Back', value: 4}
19
18
  ]
20
19
  MENU_CHOICES = [
21
20
  {name: 'Stats', value: 0},
@@ -29,19 +29,45 @@ module Twstats
29
29
  @logs << log
30
30
  end
31
31
 
32
- def get_total_time(object, element)
32
+ def mean_time
33
+ logs.inject(0) {|sum, log| sum + log.decimal_time }.to_f/logs.size
34
+ end
35
+
36
+ def mean_time_per_task
37
+ time_per_task = []
38
+ tasks.each do |task|
39
+ time_per_task << logs.select{|ll| ll.task == task}.inject(0){|sum, ll| sum + ll.decimal_time}
40
+ end
41
+ time_per_task.inject(0){|sum, x| sum + x}/time_per_task.size
42
+ end
43
+
44
+ def get_total_time(object, element, filter_billable)
45
+ billable = 0
46
+ non_billable = 0
33
47
  case object
34
48
  when :projects
35
- logs.select{|log| log.project == element}.inject(0){ |sum, l| sum + l.decimal_time}
49
+ billable = logs.select{|log| log.project == element && log.billable}.inject(0){ |sum, l| sum + l.decimal_time}
50
+ non_billable = logs.select{|log| log.project == element && !log.billable}.inject(0){ |sum, l| sum + l.decimal_time}
36
51
  when :tags
37
- logs.select{|log| log.tags.include?(element)}.inject(0){ |sum, l| sum + l.decimal_time}
52
+ billable = logs.select{|log| log.tags.include?(element) && log.billable}.inject(0){ |sum, l| sum + l.decimal_time}
53
+ non_billable = logs.select{|log| log.tags.include?(element) && !log.billable}.inject(0){ |sum, l| sum + l.decimal_time}
38
54
  when :people
39
- logs.select{|log| log.who == element}.inject(0){ |sum, l| sum + l.decimal_time}
55
+ billable = logs.select{|log| log.who == element && log.billable}.inject(0){ |sum, l| sum + l.decimal_time}
56
+ non_billable = logs.select{|log| log.who == element && !log.billable}.inject(0){ |sum, l| sum + l.decimal_time}
40
57
  when :tasks
41
- logs.select{|log| log.task == element}.inject(0){ |sum, l| sum + l.decimal_time}
58
+ billable = logs.select{|log| log.task == element && log.billable}.inject(0){ |sum, l| sum + l.decimal_time}
59
+ non_billable = logs.select{|log| log.task == element && !log.billable}.inject(0){ |sum, l| sum + l.decimal_time}
60
+ when :all
61
+ billable = logs.select{|log| log.billable}.inject(0){ |sum, l| sum + l.decimal_time}
62
+ non_billable = logs.select{|log| !log.billable}.inject(0){ |sum, l| sum + l.decimal_time}
42
63
  else
43
- -99999
64
+ return -99999
65
+ end
66
+ if filter_billable
67
+ return billable, non_billable
68
+ else
69
+ return billable + non_billable
44
70
  end
45
71
  end
46
72
  end
47
- end
73
+ end
@@ -1,20 +1,22 @@
1
1
  require 'tty-prompt'
2
+ require 'rainbow/refinement'
3
+ using Rainbow
2
4
 
3
5
  require_relative 'csv_reader'
4
6
 
5
7
  module Twstats
6
8
  class Runner
7
- def initialize
9
+ def initialize(file = nil)
8
10
  # Load interactive console
9
11
  @prompt = TTY::Prompt.new
10
- puts WELLCOME_MESSAGE
12
+ puts WELLCOME_MESSAGE.bright
11
13
  # Ask for the csv file
12
- file = @prompt.ask('Specify the CSV file from a Teamwork time log export', default: 'exportTimeLog.csv') do |input|
14
+ file ||= @prompt.ask('Specify the CSV file from a Teamwork time log export', default: 'exportTimeLog.csv') do |input|
13
15
  input.modify :chomp
14
16
  end
15
17
  @csv = CSVReader.new(file)
16
18
  loop do
17
- option = @prompt.select("Choose an option", Twstats::MENU_CHOICES)
19
+ option = @prompt.select("Choose an option", Twstats::MENU_CHOICES, cycle: true)
18
20
  case option
19
21
  when 0
20
22
  show_stats_menu
@@ -30,7 +32,7 @@ module Twstats
30
32
 
31
33
  def show_stats_menu
32
34
  loop do
33
- option = @prompt.select("Select what time logging stats you want to see", Twstats::STATS_MENU_CHOICES)
35
+ option = @prompt.select("Select what time logging stats you want to see", Twstats::STATS_MENU_CHOICES, cycle: true)
34
36
  case option
35
37
  when 0
36
38
  show_stats :projects
@@ -39,10 +41,8 @@ module Twstats
39
41
  when 2
40
42
  show_stats :tags
41
43
  when 3
42
- show_bil_vs_non_stats
43
- when 4
44
44
  show_full_stats
45
- when 5
45
+ when 4
46
46
  return
47
47
  else
48
48
  puts 'Option not recognized'
@@ -50,16 +50,22 @@ module Twstats
50
50
  end
51
51
  end
52
52
 
53
- def show_stats(obj)
54
- puts "Time logged vs #{obj.to_s}:"
53
+ def show_stats(obj, filter_billable = nil)
54
+ puts "Time logged vs #{obj.to_s}:" if filter_billable.nil?
55
55
  toshow = {}
56
56
  max = 0
57
+ filter_billable ||= @prompt.yes?('Do you want to filter billable and non-billable time?', default: true)
57
58
  @csv.send(obj).each do |element|
58
- toshow[element] = @csv.get_total_time(obj, element).round(2)
59
+ toshow[element] = @csv.get_total_time(obj, element, filter_billable)
59
60
  max = element.size if max < element.size
60
61
  end
61
62
  toshow.sort_by{ |k,v| v}.reverse.to_h.each do |k,v|
62
- puts " - #{k.ljust(max,' ')} -> #{v}"
63
+ if filter_billable
64
+ puts " - #{k.ljust(max,' ').bright.blue} | #{"Billable:".ljust(13," ").bright} #{v[0].round(2)} (#{((v[0]/(v[0]+v[1]))*100).round(2)} %)" unless v[0].zero?
65
+ puts " #{"".ljust(max,' ').bright.blue} | #{"Non-billable:".bright} #{v[1].round(2)}" unless v[1].zero?
66
+ else
67
+ puts " - #{k.ljust(max,' ').bright.blue} | #{v.round(2)}" unless v.zero?
68
+ end
63
69
  end
64
70
  end
65
71
 
@@ -67,5 +73,36 @@ module Twstats
67
73
 
68
74
  end
69
75
 
76
+ def show_full_stats
77
+ billable, non_billable = @csv.get_total_time(:all, nil, true)
78
+ to_bill = @prompt.yes? 'Do you want to calculate the billed amount?'
79
+ if to_bill
80
+ amount_per_hour = @prompt.ask 'What the amount billed per hour?', default: 46
81
+ end
82
+ section "Total time spent"
83
+ puts " - Billable ".bright.blue + " | " + billable.round(2).to_s
84
+ puts " - Non-billable ".bright.blue + " | " + non_billable.round(2).to_s
85
+ if to_bill
86
+ puts " - Billed amount ".bright.blue + " | " + (billable*amount_per_hour).round(2).to_s + " € "
87
+ end
88
+ section "People involved"
89
+ show_stats :people, true
90
+ section "Tags used"
91
+ show_stats :tags, true
92
+ section "Usefull metrics"
93
+ show_metrics
94
+ end
95
+
96
+ def section(text)
97
+ puts ""
98
+ puts (" "+text+" ").center(70,"*").bright
99
+ end
100
+
101
+ def show_metrics
102
+ mean = @csv.logs.inject(0) {|sum, log| sum + log.decimal_time }.to_f/@csv.logs.size
103
+ mean_per_task = @csv.mean_time_per_task
104
+ puts " - Mean time logged: ".bright.blue + mean.round(2).to_s
105
+ puts " - Mean time per task: ".bright.blue + mean_per_task.round(2).to_s
106
+ end
70
107
  end
71
- end
108
+ end
@@ -8,6 +8,7 @@ module Twstats
8
8
  attr_reader :tags
9
9
  attr_reader :project
10
10
  attr_reader :task
11
+ attr_reader :billable
11
12
 
12
13
 
13
14
  # Class use to store the information needed form a given log
@@ -20,7 +21,7 @@ module Twstats
20
21
  @tags = row["Tags"].split(',')
21
22
  @project = row["Project"]
22
23
  @task = row["Task"]
23
- @billable = row["Is it Billable?"]
24
+ @billable = !row["Is it Billable?"].to_i.zero?
24
25
  end
25
26
  end
26
- end
27
+ end
@@ -36,6 +36,7 @@ Gem::Specification.new do |spec|
36
36
  spec.add_development_dependency "rake", "~> 10.0"
37
37
  spec.add_development_dependency "rspec", "~> 3.0"
38
38
  spec.add_runtime_dependency "tty-prompt", "~> 0.17"
39
+ spec.add_runtime_dependency "rainbow", "~> 3.0"
39
40
 
40
- spec.required_ruby_version = '~> 2.0'
41
+ spec.required_ruby_version = '~> 2.1'
41
42
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twstats
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: '0.2'
5
5
  platform: ruby
6
6
  authors:
7
7
  - J.P. Araque
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0.17'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rainbow
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
69
83
  description: Teamwork allows to log time for all tasks within a project but the stats
70
84
  capabilities do not allow for a quick overview of time loggin stats. TWStats produces
71
85
  useful stats from a CSV file exported from Teamwork
@@ -107,7 +121,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
107
121
  requirements:
108
122
  - - "~>"
109
123
  - !ruby/object:Gem::Version
110
- version: '2.0'
124
+ version: '2.1'
111
125
  required_rubygems_version: !ruby/object:Gem::Requirement
112
126
  requirements:
113
127
  - - ">="
@@ -115,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
115
129
  version: '0'
116
130
  requirements: []
117
131
  rubyforge_project:
118
- rubygems_version: 2.6.11
132
+ rubygems_version: 2.7.7
119
133
  signing_key:
120
134
  specification_version: 4
121
135
  summary: Read a csv file generate by Teamwork to quickly get some stats from time