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.
- data/.gitignore +1 -1
- data/README.md +18 -49
- data/TODO +7 -5
- data/examples/README.md +1 -0
- data/examples/generate_images.rb +48 -0
- data/examples/public/images/AggregatedVelocitator-haml-i18n-extractor-0.4.x.png +0 -0
- data/examples/public/images/Multiplexer-haml-i18n-extractor-0.0.17-0.0.16-0.4.x.png +0 -0
- data/examples/public/images/Multiplexer-haml-i18n-extractor-0.4.x-0.3.x.png +0 -0
- data/examples/public/images/SingleVelocitator-haml-i18n-extractor-0.0.16.png +0 -0
- data/examples/public/images/SingleVelocitator-haml-i18n-extractor-0.0.17.png +0 -0
- data/lib/gem_velocity/gem_data.rb +1 -1
- data/lib/gem_velocity/gruff_builder.rb +16 -13
- data/lib/gem_velocity/helpers.rb +26 -0
- data/lib/gem_velocity/velocitators/aggregated_velocitator.rb +24 -16
- data/lib/gem_velocity/velocitators/base_velocitator.rb +45 -39
- data/lib/gem_velocity/velocitators/factory.rb +52 -0
- data/lib/gem_velocity/velocitators/multiplexer.rb +65 -0
- data/lib/gem_velocity/velocitators/single_velocitator.rb +22 -14
- data/lib/gem_velocity/version.rb +1 -1
- data/lib/gem_velocity.rb +8 -1
- data/spec/aggregated_velocitor_spec.rb +53 -0
- data/spec/factory_spec.rb +54 -0
- data/spec/gruff_builder_spec.rb +0 -3
- data/spec/multiplexer_spec.rb +73 -0
- data/spec/no_time_cop_spec.rb +12 -28
- data/spec/single_velocitator_spec.rb +92 -0
- data/spec/spec_helper.rb +4 -0
- metadata +21 -11
- data/examples/rails-4.0.0-3.2.14-0.9.1.png +0 -0
- data/examples/rails-4.0.0-3.2.14-2.3.5.png +0 -0
- 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
- data/lib/gem_velocity/velocitators/all.rb +0 -4
- data/lib/gem_velocity/velocitators/multiple_velocitator.rb +0 -34
- data/spec/velocitator_spec.rb +0 -189
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,18 +1,22 @@
|
|
1
1
|
# GemVelocity
|
2
2
|
|
3
|
-
A way to see gem velocity. There are
|
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
|
-
|
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
|
-
|
13
|
+
See specs and examples for more info.
|
10
14
|
|
11
|
-
|
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
|
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
|
-
|
29
|
+
`brew install imagemagick && brew link imagemagick && gem install gem_velocity`
|
26
30
|
|
27
31
|
# Example
|
28
32
|
|
29
|
-
|
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
|
-
|
35
|
+
Important to note, you should be able to pass in specific start time, end time, max and min values.
|
48
36
|
|
49
|
-
|
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?
|
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
|
-
|
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.
|
data/examples/README.md
ADDED
@@ -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
|
Binary file
|
@@ -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
|
-
|
18
|
-
@
|
19
|
-
@
|
20
|
-
@
|
21
|
-
@
|
22
|
-
@
|
23
|
-
@
|
24
|
-
@
|
25
|
-
@
|
26
|
-
@
|
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
|
data/lib/gem_velocity/helpers.rb
CHANGED
@@ -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
|
-
@
|
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
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
37
|
+
range.each do |d|
|
34
38
|
ret[d] += downloads_per_day(v)[d] || 0
|
35
39
|
end
|
36
40
|
end
|
37
|
-
|
41
|
+
range.map{|d| ret[d] }
|
38
42
|
end
|
39
43
|
|
40
44
|
def title
|
41
|
-
"#{@gem_name}: #{@
|
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
|
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 #{
|
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
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
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
|
-
|
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(
|
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
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
data/lib/gem_velocity/version.rb
CHANGED