gem_velocity 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/.gitignore +1 -1
  2. data/README.md +18 -49
  3. data/TODO +7 -5
  4. data/examples/README.md +1 -0
  5. data/examples/generate_images.rb +48 -0
  6. data/examples/public/images/AggregatedVelocitator-haml-i18n-extractor-0.4.x.png +0 -0
  7. data/examples/public/images/Multiplexer-haml-i18n-extractor-0.0.17-0.0.16-0.4.x.png +0 -0
  8. data/examples/public/images/Multiplexer-haml-i18n-extractor-0.4.x-0.3.x.png +0 -0
  9. data/examples/public/images/SingleVelocitator-haml-i18n-extractor-0.0.16.png +0 -0
  10. data/examples/public/images/SingleVelocitator-haml-i18n-extractor-0.0.17.png +0 -0
  11. data/lib/gem_velocity/gem_data.rb +1 -1
  12. data/lib/gem_velocity/gruff_builder.rb +16 -13
  13. data/lib/gem_velocity/helpers.rb +26 -0
  14. data/lib/gem_velocity/velocitators/aggregated_velocitator.rb +24 -16
  15. data/lib/gem_velocity/velocitators/base_velocitator.rb +45 -39
  16. data/lib/gem_velocity/velocitators/factory.rb +52 -0
  17. data/lib/gem_velocity/velocitators/multiplexer.rb +65 -0
  18. data/lib/gem_velocity/velocitators/single_velocitator.rb +22 -14
  19. data/lib/gem_velocity/version.rb +1 -1
  20. data/lib/gem_velocity.rb +8 -1
  21. data/spec/aggregated_velocitor_spec.rb +53 -0
  22. data/spec/factory_spec.rb +54 -0
  23. data/spec/gruff_builder_spec.rb +0 -3
  24. data/spec/multiplexer_spec.rb +73 -0
  25. data/spec/no_time_cop_spec.rb +12 -28
  26. data/spec/single_velocitator_spec.rb +92 -0
  27. data/spec/spec_helper.rb +4 -0
  28. metadata +21 -11
  29. data/examples/rails-4.0.0-3.2.14-0.9.1.png +0 -0
  30. data/examples/rails-4.0.0-3.2.14-2.3.5.png +0 -0
  31. data/examples/rails-4.0.1.rc1-4.0.0-4.0.0.rc2-4.0.0.rc1-4.0.0.beta1.png +0 -0
  32. data/lib/gem_velocity/velocitators/all.rb +0 -4
  33. data/lib/gem_velocity/velocitators/multiple_velocitator.rb +0 -34
  34. data/spec/velocitator_spec.rb +0 -189
data/.gitignore CHANGED
@@ -16,7 +16,7 @@ test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
18
  spec/tmp
19
+ ./public/images/
19
20
  public/
20
- images/
21
21
  spec/fixtures/vcr_cassettes
22
22
  spec/fixtures/vcr_cassettes/
data/README.md CHANGED
@@ -1,18 +1,22 @@
1
1
  # GemVelocity
2
2
 
3
- A way to see gem velocity. There are three ways you can view graphs.
3
+ A way to see gem velocity. There are two ways you can view graphs.
4
+
5
+ `SingleVelocitator`
6
+
7
+ This is a single line graph of a single version.
4
8
 
5
9
  `AggregatedVelocitator`
6
10
 
7
- `SingleVelocitator`
11
+ This is a signle line graph that has an aggregated view of a major version (or bunch of single minor versions, etc).
8
12
 
9
- `MultipleVelocitator`
13
+ See specs and examples for more info.
10
14
 
11
- Some examples are noted below.
15
+ There is also the `Multiplexer`, this is a wrapper around being able to draw multiple lines at once. You pass it any number of the above and it will graph multiple lines together in one graph.
12
16
 
13
17
  ## Note
14
18
 
15
- There may be some inconstancies. These are outlined in:
19
+ There may be some inconstancies due to bad data coming back from the api. These are outlined in:
16
20
 
17
21
  [https://gist.github.com/shaiguitar/d2af997b7f58e24fd305](https://gist.github.com/shaiguitar/d2af997b7f58e24fd305)
18
22
 
@@ -20,60 +24,25 @@ It seems it happens with older data. I'm investigating though with the help of t
20
24
 
21
25
  ## Requirements
22
26
 
23
- It draws graphs. So...you'll need imagemagick/rmagick. Any problems with installation let me know and I'll try to help out.
27
+ It draws graphs. So you'll need imagemagick/rmagick. Any problems with installation let me know and I'll try to help out.
24
28
 
25
- There are plans to put it on the web somewhere, so if you wait long enough you may not even need to install it.
29
+ `brew install imagemagick && brew link imagemagick && gem install gem_velocity`
26
30
 
27
31
  # Example
28
32
 
29
- <pre>
30
- velocitator = MultipleVelocitator.new("rails", ["4.0.0","3.2.14","2.3.5"])
31
- file = velocitator.graph("/tmp")
32
- </pre>
33
-
34
- Produces:
35
-
36
- ![here](examples/rails-4.0.0-3.2.14-2.3.5.png)
37
-
38
- Notice the date range:
39
-
40
- <pre>
41
- velocitator = MultipleVelocitator.new("rails", ["4.0.0","3.2.14","0.9.1"])
42
- file = velocitator.graph("/tmp", [3.months.ago, Time.now])
43
- </pre>
44
-
45
- Produces:
33
+ See [examples](examples/) for pictures. The specs have more examples as well.
46
34
 
47
- ![here](examples/rails-4.0.0-3.2.14-0.9.1.png)
35
+ Important to note, you should be able to pass in specific start time, end time, max and min values.
48
36
 
49
- <pre>
50
- velocitator = AggregatedVelocitator.new("rails", "4")
51
- # matches any version /^4.\d/ etc
52
- file = velocitator.graph("/tmp")
53
- </pre>
54
-
55
- Produces:
56
-
57
- ![here](examples/rails-4.0.1.rc1-4.0.0-4.0.0.rc2-4.0.0.rc1-4.0.0.beta1.png)
58
-
59
- Another: [celluloid](https://gist.github.com/shaiguitar/7e6d95971c5254fa3665)
60
-
61
- You could do the same with a `SingleVelocitator` as well:
62
-
63
- <pre>
64
- velocitator = SingleVelocitator.new("rails", "4.0.0")
65
- file = velocitator.graph("/tmp")
66
- </pre>
67
-
68
- That image is left as an excerise to the reader. Actually it's late. But try it and see.
69
-
70
- Also, you should be able to pass in max,min values which completes you being able to manipulate the boundries of the graph in question.
37
+ This essentially completes you being able to manipulate the boundries of the graph in question.
71
38
 
72
39
  ## Web UI
73
40
 
74
- Do you want to see this with ease (Hey, the api is easy. Whatever) on the web at `http://rubygems-velocity.org/gem/rails/4.0.0,3.2.14` or something similar? I could do it, but I need to know it's worth the hassle.
41
+ Do you want to see this with ease (Hey, the api is easy. Whatever) on the web at `http://rubygems-velocity.org/gem/rails/4.0.0,3.2.14` or something similar?
42
+
43
+ [Work](https://github.com/shaiguitar/gem_velocity_web) has been started to put it on a UI, but your feedback in necessary for it to be useful:
75
44
 
76
- Also, if you have any idea of how you'd like to use it, please leave a comment on the [issue](https://github.com/shaiguitar/gem_velocities/issues/3)
45
+ So if you have any idea of how you'd like to use it, please put your thoughts on the [issue](https://github.com/shaiguitar/gem_velocities/issues/3)
77
46
 
78
47
  Lemme know.
79
48
 
data/TODO CHANGED
@@ -1,11 +1,7 @@
1
- Web ui/embeddable links with those images.
2
- can't remove images
3
- have uniq name: hash the date_range,max,min,name,versions. (and time?)
4
- shard the directories of where the image goes so it doesn't bomb out?
5
-
6
1
  Add a Version?
7
2
 
8
3
  currently, the versions in the base class are single versions, but they are essentially used for representing a specific line
4
+
9
5
  in default_line_datas.
10
6
  (and then used for titles, abd bs).
11
7
 
@@ -14,3 +10,9 @@ if rubygems 606 isn't solved, why not just put a total on there and let the inco
14
10
  rename time_format_str_small alias
15
11
 
16
12
  swap out gruff_builder to some other composing object of a builder, that can mash up the various velocitators?
13
+
14
+ consolidate velocitator fixtrues or at least repeatable generators in specs.
15
+
16
+ cassandra says to have an option to have the multiplexer start them from the same data (to see curve/adoption rate). I see it.
17
+
18
+ hardcode a time limit of earliest_time since historical data is not reliable.
@@ -0,0 +1 @@
1
+ See generated images for the script here in [the images directory](public/images)
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'fileutils'
4
+
5
+ examples_dir = File.expand_path(File.dirname(__FILE__))
6
+ images_dir = File.join(examples_dir, "public","images")
7
+ project_root = File.join(examples_dir, "..")
8
+ project_lib = File.join(project_root,"lib")
9
+
10
+ $:.unshift(project_root)
11
+ $:.unshift(project_lib)
12
+ require 'lib/gem_velocity'
13
+
14
+ puts "Cleaning images directory before generating again."
15
+ FileUtils.rm_rf(images_dir)
16
+
17
+ puts "SINGLE VELOCITATOR"
18
+ @v1 = SingleVelocitator.new("haml-i18n-extractor", "0.0.17")
19
+ @v1.max_value = 800
20
+ file = @v1.graph
21
+
22
+ puts "SINGLE VELOCITATOR"
23
+ # these are basically equivalet:
24
+ # BaseVelocitator.create(:gem_name => "haml-i18n-extractor", :version => "0.0.16")
25
+ # BaseVelocitator.create(:full_name => "haml-i18n-extractor-0.0.16")
26
+ @v2 = SingleVelocitator.new("haml-i18n-extractor", "0.0.16")
27
+ @v2.max_value = 800
28
+ file = @v2.graph
29
+
30
+ puts "AGGREGATED VELOCITATOR"
31
+ # these are basically equivalet:
32
+ # BaseVelocitator.create(:gem_name => "haml-i18n-extractor", :version => "0.4.x")
33
+ # BaseVelocitator.create(:full_name => "haml-i18n-extractor-0.4.x")
34
+ @v3 = AggregatedVelocitator.new("haml-i18n-extractor", "0.4.x")
35
+ @v3.max_value = 800
36
+ file = @v3.graph
37
+
38
+ puts "MULTIPLEXING"
39
+ @velocitators = [@v1,@v2,@v3]
40
+ @multiplexer = Multiplexer.new(@velocitators)
41
+ file = @multiplexer.graph
42
+
43
+ puts "MULIPLEXING AGAIN"
44
+ @velocitators = []
45
+ @velocitators << BaseVelocitator.create(:gem_name => "haml-i18n-extractor", :version => "0.4.x")
46
+ @velocitators << BaseVelocitator.create(:full_name => "haml-i18n-extractor-0.3.x")
47
+ @multiplexer = Multiplexer.new(@velocitators)
48
+ file = @multiplexer.graph
@@ -24,7 +24,7 @@ class GemData
24
24
  # it should be a hash
25
25
  if @versions_metadata.is_a?(String)
26
26
  if @versions_metadata.match(/This rubygem could not be found/)
27
- raise(NoSuchGem, "This rubygem could not be found")
27
+ raise(NoSuchGem, "This rubygem #{gem_name} could not be found")
28
28
  end
29
29
  end
30
30
  @versions_metadata
@@ -14,16 +14,18 @@ class GruffBuilder
14
14
  attr_accessor :title, :labels, :line_datas, :min_value, :max_value, :hide_legend
15
15
 
16
16
  def initialize(root, relative_path, versions, gem_name, gruff_options = {})
17
- @root = root || raise(ArgumentError,"you must set a root. default is root/public/images")
18
- @relative_path = relative_path || "public/images/"
19
- @versions = versions.is_a?(Array) ? versions : raise(ArgumentError,"versions must be an array")
20
- @gem_name = gem_name
21
- @title = gruff_options[:title] || ""
22
- @labels = gruff_options[:labels] || {}
23
- @line_datas = gruff_options[:line_datas]
24
- @min_value = gruff_options[:min_value] || MIN_VALUE
25
- @max_value = gruff_options[:max_value] || MAX_VALUE
26
- @hide_legend = gruff_options[:hide_legend] || false
17
+ # just pass it in all in gruff_options?
18
+ @root = root || raise(ArgumentError,"you must set a root. default is root/public/images")
19
+ @relative_path = relative_path || "public/images/"
20
+ @versions = versions.is_a?(Array) ? versions : raise(ArgumentError,"versions must be an array")
21
+ @gem_name = gem_name
22
+ @title = gruff_options[:title] || ""
23
+ @labels = gruff_options[:labels] || {}
24
+ @line_datas = gruff_options[:line_datas]
25
+ @min_value = gruff_options[:min_value] || MIN_VALUE
26
+ @max_value = gruff_options[:max_value] || MAX_VALUE
27
+ @hide_legend = gruff_options[:hide_legend] || false
28
+ @type = gruff_options[:type]
27
29
  end
28
30
 
29
31
  def relative_filename
@@ -31,7 +33,7 @@ class GruffBuilder
31
33
  end
32
34
 
33
35
  def filename
34
- "#{graph_name(versions.join("-"))}.png"
36
+ "#{graph_name(@type, versions.join("-"))}.png"
35
37
  end
36
38
 
37
39
  def absolute_filename
@@ -63,9 +65,10 @@ class GruffBuilder
63
65
  FileUtils.mkdir_p(File.expand_path(absolute_destination))
64
66
  end
65
67
 
66
- def graph_name(append_text = nil)
68
+ def graph_name(prepend_text = nil, append_text = nil)
69
+ prepend_text = prepend_text.nil? ? "" : "#{prepend_text}-"
67
70
  append_text = append_text.nil? ? "" : "-#{append_text}"
68
- "#{gem_name}"+ append_text
71
+ prepend_text + "#{gem_name}"+ append_text
69
72
  end
70
73
 
71
74
  def gruff
@@ -10,4 +10,30 @@ module Helpers
10
10
  Date.parse(whatever.to_s).strftime("%Y-%m-%d")
11
11
  end
12
12
 
13
+ def earliest_for(whatevers)
14
+ whatevers = whatevers.map{|s| Date.parse(s) } if whatevers.first.is_a?(String)
15
+ time_format_str(whatevers.sort.first)
16
+ end
17
+
18
+ def latest_for(whatevers)
19
+ whatevers = whatevers.map{|s| Date.parse(s) } if whatevers.first.is_a?(String)
20
+ time_format_str(whatevers.sort.last)
21
+ end
22
+
23
+ def compute_day_range_from_start_end(s,e)
24
+ all_days = []
25
+ s = Date.parse(s)
26
+ e = Date.parse(e)
27
+ i = s
28
+ while (i <= e )
29
+ all_days << i
30
+ i += 1.day
31
+ end
32
+ all_days.map{|d| time_format_str_small(d)}
33
+ end
34
+
35
+ def remove_trailing_x(str)
36
+ str.gsub(/[xX]$/,"")
37
+ end
38
+
13
39
  end
@@ -1,10 +1,18 @@
1
1
  class AggregatedVelocitator < BaseVelocitator
2
2
 
3
+ # TODO can probably get rid of this
3
4
  attr_reader :aggregated_versions
5
+
6
+ # the one with the wildcard
7
+ attr_reader :version
8
+
9
+ # all of the ones matched, aggregated_versions
10
+ attr_reader :versions
11
+
4
12
  def initialize(gem_name, top_level_ver)
5
13
  @gem_name = gem_name
6
- @top_level_ver = top_level_ver
7
- @aggregated_versions = gem_data.versions.select{|v| v.match(/^#{Regexp.escape(top_level_ver)}/) }
14
+ @version = top_level_ver #with a wildcard/x
15
+ @versions = @aggregated_versions = gem_data.versions.select{|v| v.match(/^#{Regexp.escape(remove_trailing_x(top_level_ver))}/) }
8
16
  super(gem_name, @aggregated_versions)
9
17
  end
10
18
 
@@ -16,29 +24,29 @@ class AggregatedVelocitator < BaseVelocitator
16
24
  base_max_for(@aggregated_versions) * @aggregated_versions.size
17
25
  end
18
26
 
19
- def graph_options
20
- opts = {
21
- :title => title,
22
- :labels => ({1 => time_format_str_small(effective_start_time), (line_datas.first.size-2) => time_format_str_small(effective_end_time) }),
23
- :max_value => effective_max_value,
24
- :min_value => effective_min_value,
25
- :line_datas => line_datas,
26
- :hide_legend => true
27
- }
28
- end
27
+ def line_data(start_t = nil, end_t = nil)
28
+ range = nil
29
+ if start_t && end_t
30
+ range = compute_day_range_from_start_end(start_t,end_t)
31
+ else
32
+ range = effective_days_in_range
33
+ end
29
34
 
30
- def line_datas
31
35
  ret = Hash.new(0)
32
36
  @aggregated_versions.each do |v|
33
- effective_days_in_range.each do |d|
37
+ range.each do |d|
34
38
  ret[d] += downloads_per_day(v)[d] || 0
35
39
  end
36
40
  end
37
- [effective_days_in_range.map{|d| ret[d] }]
41
+ range.map{|d| ret[d] }
38
42
  end
39
43
 
40
44
  def title
41
- "#{@gem_name}: #{@top_level_ver}X\n(downloads: #{num_downloads})"
45
+ "#{@gem_name}: #{@version}\n(downloads: #{num_downloads})"
46
+ end
47
+
48
+ def hide_legend?
49
+ true
42
50
  end
43
51
 
44
52
  end
@@ -10,9 +10,27 @@ class BaseVelocitator
10
10
 
11
11
  attr_accessor :gem_name, :versions
12
12
 
13
- def graph(root_arg = nil, range = nil, min = nil, max = nil)
13
+ def self.create(options)
14
+ Factory.new(options).velocitator
15
+ end
16
+
17
+ def graph(root_arg = root, range = effective_date_range, min = effective_min_value, max = effective_max_value)
14
18
  set_overwritable_attrs(root_arg,range,min,max)
15
- gruff_builder.write
19
+ file = gruff_builder(root, graph_options).write
20
+ puts "Wrote graph to #{file}"
21
+ file
22
+ end
23
+
24
+ def graph_options
25
+ opts = {
26
+ :title => title,
27
+ :labels => ({1 => time_format_str_small(effective_start_time), (line_datas.first.size-2) => time_format_str_small(effective_end_time) }),
28
+ :max_value => effective_max_value,
29
+ :min_value => effective_min_value,
30
+ :line_datas => line_datas,
31
+ :hide_legend => hide_legend?,
32
+ :type => self.class.to_s
33
+ }
16
34
  end
17
35
 
18
36
  # modifiers on the end result image being rendered. Essentially these are the boundries
@@ -25,6 +43,13 @@ class BaseVelocitator
25
43
 
26
44
  def effective_date_range
27
45
  @passed_date_range || default_date_range
46
+ end
47
+ # some sugar
48
+ def effective_start_time; effective_date_range.first ;end
49
+ def effective_end_time; effective_date_range.last ;end
50
+
51
+ def effective_days_in_range
52
+ compute_day_range_from_start_end(effective_start_time,effective_end_time)
28
53
  end
29
54
 
30
55
  def effective_max_value
@@ -46,6 +71,11 @@ class BaseVelocitator
46
71
  ActiveSupport::NumberHelper.number_to_delimited(sum)
47
72
  end
48
73
 
74
+ def time_built(version)
75
+ gem_data.versions_built_at[version]
76
+ end
77
+ alias :built_at :time_built
78
+
49
79
  private
50
80
 
51
81
  def initialize(gem_name, versions)
@@ -57,7 +87,7 @@ class BaseVelocitator
57
87
 
58
88
  def validate_correct_versions
59
89
  versions.each do |v|
60
- gem_data.versions.include?(v) || raise(NoSuchVersion,"version not found for #{versions}.")
90
+ gem_data.versions.include?(v) || raise(NoSuchVersion,"version #{v} not found for #{gem_name}.")
61
91
  end
62
92
  end
63
93
 
@@ -85,12 +115,14 @@ class BaseVelocitator
85
115
  0
86
116
  end
87
117
 
88
- def default_line_datas
89
- versions.map do |v|
90
- effective_days_in_range.map do |d|
91
- downloads_per_day(v)[d] || 0
92
- end
93
- end
118
+ def line_datas
119
+ # aggregated and single are both just one, just line_data, but default to this
120
+ # because of the multiplexer, since it does have line_datas
121
+ [line_data]
122
+ end
123
+
124
+ def versions_for_legends
125
+ [version]
94
126
  end
95
127
 
96
128
  def base_earliest_time_for(verzionz)
@@ -106,11 +138,7 @@ class BaseVelocitator
106
138
  totals.flatten.compact.max
107
139
  end
108
140
 
109
- def downloads_per_day(version)
110
- # returns # "2013-10-10" => 45
111
- accumulated_downloads_per_day(version)
112
- end
113
-
141
+ # returns # "2013-10-10" => 45
114
142
  def accumulated_downloads_per_day(version)
115
143
  # downloads_metadata comes back ordered by date
116
144
  ret = Hash.new(0)
@@ -123,37 +151,15 @@ class BaseVelocitator
123
151
  end
124
152
  ret
125
153
  end
126
-
127
- # a little sugar
128
- def effective_start_time; effective_date_range.first ;end
129
- def effective_end_time; effective_date_range.last ;end
130
-
131
- # helper method to convert [start,end] into a
132
- # start..end range of days like "2013-10-10"
133
- def effective_days_in_range
134
- all_days = []
135
- s = Date.parse(effective_start_time)
136
- e = Date.parse(effective_end_time)
137
- i = s
138
- while (i <= e )
139
- all_days << i
140
- i += 1.day
141
- end
142
- all_days.map{|d| time_format_str_small(d)}
143
- end
154
+ alias :downloads_per_day :accumulated_downloads_per_day
144
155
 
145
156
  def gem_data
146
157
  # need this memoized so the gem_data memoization works for the same instance
147
158
  @gem_data ||= GemData.new(@gem_name)
148
159
  end
149
160
 
150
- def gruff_builder
151
- GruffBuilder.new(@root || Dir.pwd,nil,versions,gem_name,graph_options)
161
+ def gruff_builder(path,graph_opts)
162
+ GruffBuilder.new(path || Dir.pwd, nil, versions_for_legends, gem_name, graph_opts)
152
163
  end
153
164
 
154
- # it's just shorter syntax
155
- def time_built(version)
156
- gem_data.versions_built_at[version]
157
- end
158
-
159
165
  end
@@ -0,0 +1,52 @@
1
+ class Factory
2
+
3
+ include Helpers
4
+
5
+ attr_reader :gem_name, :version, :versions, :type
6
+
7
+ def initialize(options)
8
+
9
+ # one ver passed
10
+ if options[:gem_name] && options[:version]
11
+ @gem_name = options[:gem_name]
12
+ @version = options[:version]
13
+ @type = type_from_version(@version)
14
+ @versions = self.velocitator.versions
15
+ elsif options[:full_name]
16
+ @gem_name = name_from_full_name(options[:full_name])
17
+ @version = version_from_full_name(options[:full_name])
18
+ @type = type_from_version(@version)
19
+ @versions = self.velocitator.versions
20
+ end
21
+ end
22
+
23
+ def velocitator
24
+ if @type == :aggregated
25
+ AggregatedVelocitator.new(@gem_name, @version)
26
+ elsif @type == :single
27
+ SingleVelocitator.new(@gem_name, @version)
28
+ else
29
+ raise 'no velocitor found to generate!'
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def name_from_full_name(str)
36
+ str.split("-")[0..-2].join("-")
37
+ end
38
+
39
+ def version_from_full_name(str)
40
+ str.split("-").last
41
+ end
42
+
43
+ def type_from_version(str)
44
+ if str.last.downcase == "x"
45
+ :aggregated
46
+ else
47
+ :single
48
+ end
49
+ end
50
+
51
+ end
52
+
@@ -0,0 +1,65 @@
1
+ class Multiplexer < BaseVelocitator
2
+
3
+ include ::Helpers
4
+ attr_reader :velocitators
5
+
6
+ def initialize(velocitators)
7
+ @velocitators = velocitators
8
+ # TODO what if there are multiple gem_names being multiplexed?
9
+ super(velocitators.first.gem_name, velocitators.map(&:versions).flatten)
10
+ end
11
+
12
+ def version
13
+ raise "The multiplexer does not have a single version. try @versions."
14
+ end
15
+
16
+ def root
17
+ velocitator_with_root = velocitators.detect{|v| v.root }
18
+ if velocitator_with_root
19
+ velocitator_with_root.root
20
+ else
21
+ Dir.pwd
22
+ end
23
+ end
24
+
25
+ def default_start
26
+ earliest_for(velocitators.map(&:effective_start_time))
27
+ end
28
+
29
+ def effective_end_time
30
+ latest_for(velocitators.map(&:effective_end_time))
31
+ end
32
+
33
+ def effective_min_value
34
+ velocitators.map(&:effective_min_value).min
35
+ end
36
+
37
+ def effective_max_value
38
+ velocitators.map(&:effective_max_value).max
39
+ end
40
+
41
+ def line_datas
42
+ velocitators.map do |velocitator|
43
+ velocitator.line_data(effective_start_time, effective_end_time)
44
+ end
45
+ end
46
+
47
+ def hide_legend?
48
+ false
49
+ end
50
+
51
+ def versions_for_legends
52
+ velocitators.map(&:version)
53
+ end
54
+
55
+ def title
56
+ "Composite: #{gem_names}"
57
+ end
58
+
59
+ private
60
+
61
+ def gem_names
62
+ velocitators.map(&:gem_name).sort.uniq.join(" ")
63
+ end
64
+
65
+ end
@@ -1,5 +1,7 @@
1
1
  class SingleVelocitator < BaseVelocitator
2
2
 
3
+ # the one passed in
4
+ # for :versions, it's just [version]
3
5
  attr_reader :version
4
6
 
5
7
  def initialize(gem_name, version)
@@ -19,24 +21,30 @@ class SingleVelocitator < BaseVelocitator
19
21
  accumulated_downloads_per_day(@version).map {|day,total| total}.max
20
22
  end
21
23
 
22
- def graph_options
23
- opts = {
24
- :title => title,
25
- # todo change the -2 to -4? so if ifits in? if it's abvoe 4 fcors
26
- :labels => ({1 => time_format_str_small(effective_start_time), (line_datas.first.size-2) => time_format_str_small(effective_end_time) }),
27
- :max_value => effective_max_value,
28
- :min_value => effective_min_value,
29
- :line_datas => line_datas,
30
- :hide_legend => true
31
- }
32
- end
33
-
34
- def line_datas
35
- default_line_datas
24
+ def line_data(start_t = nil, end_t = nil)
25
+ range = nil
26
+ if start_t && end_t
27
+ range = compute_day_range_from_start_end(start_t,end_t)
28
+ else
29
+ range = effective_days_in_range
30
+ end
31
+
32
+ range.map do |d|
33
+ downloads_per_day(version)[d] || 0
34
+ end
36
35
  end
37
36
 
38
37
  def title
39
38
  "#{gem_name}-#{version}\n(downloads: #{num_downloads})"
40
39
  end
41
40
 
41
+ def time_built
42
+ super(@version)
43
+ end
44
+
45
+ def hide_legend?
46
+ true
47
+ end
48
+
49
+
42
50
  end
@@ -1,3 +1,3 @@
1
1
  module GemVelocity
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end