rubella 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/LICENSE +12 -0
- data/README.md +21 -0
- data/Rakefile +36 -0
- data/lib/rubella.rb +4 -0
- data/lib/rubella/input/base.rb +33 -0
- data/lib/rubella/input/json.rb +47 -0
- data/lib/rubella/map.rb +87 -0
- data/lib/rubella/output/ascii.rb +102 -0
- data/lib/rubella/output/base.rb +37 -0
- data/lib/rubella/output/image.rb +68 -0
- data/lib/rubella/storage.rb +94 -0
- data/lib/rubella/weighting/base.rb +58 -0
- data/lib/rubella/weighting/exponential.rb +48 -0
- data/lib/rubella/weighting/per_count.rb +61 -0
- data/lib/rubella/weighting/per_overall_load.rb +54 -0
- data/lib/rubella/weighting/per_value.rb +43 -0
- data/spec/fixtures/json/test_01.json +1 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/unit/rubella/input/base/data_spec.rb +11 -0
- data/spec/unit/rubella/input/base/each_spec.rb +16 -0
- data/spec/unit/rubella/input/base/new_spec.rb +17 -0
- data/spec/unit/rubella/input/json/data_spec.rb +11 -0
- data/spec/unit/rubella/input/json/each_spec.rb +16 -0
- data/spec/unit/rubella/input/json/self_file_spec.rb +17 -0
- data/spec/unit/rubella/input/json/self_string_spec.rb +17 -0
- data/spec/unit/rubella/storage/add_spec.rb +29 -0
- data/spec/unit/rubella/storage/data_spec.rb +11 -0
- data/spec/unit/rubella/storage/dataset_length_spec.rb +29 -0
- data/spec/unit/rubella/storage/each_spec.rb +16 -0
- data/spec/unit/rubella/storage/length_eql_spec.rb +68 -0
- data/spec/unit/rubella/storage/length_spec.rb +11 -0
- data/spec/unit/rubella/storage/new_spec.rb +43 -0
- metadata +97 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c1a3fa7e3e6308ae4c40b2eafed842d45becec8f
|
4
|
+
data.tar.gz: cb9fba9155a39f45d4ad1b2b7bb07bde8d9c1005
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6d06ae6ad7da68feeb86e7cfcccabd78a29ce56d385dcea9e52d32b36eef1e875a956f47d718bd3eef647bfbacc14959969279859a8e511a170e0fe7bffbd579
|
7
|
+
data.tar.gz: 23f46a46d389a7598e9019ed02ebd75ad5353056c9ab96f407bd1dcb66de8db952cb1942ebf5762472744ceb9781d0b1782e370b3eb081c1ae43702ddbcd8db4
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
Copyright (c) 2015, Rebecca Dietrich
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
5
|
+
|
6
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
7
|
+
|
8
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
9
|
+
|
10
|
+
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
11
|
+
|
12
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Rubella heatmap library
|
2
|
+
=======================
|
3
|
+
|
4
|
+
Rubella is a library to generate heatmaps to monitor visualize measured values
|
5
|
+
easier. Like the load of multiple CPU cores over time.
|
6
|
+
|
7
|
+
Therefore every CPU core gets its own JSON array over the measured time. So the
|
8
|
+
array gets it's own row in the headmap. The more the color itensity the higher
|
9
|
+
is the load.
|
10
|
+
(The values are in percent. So they must be beween 0 and 100.)
|
11
|
+
|
12
|
+
During the time you can see, if an unusual behavior occurs, because the image
|
13
|
+
shows a different load distribution.
|
14
|
+
|
15
|
+
see also:
|
16
|
+
http://dtrace.org/blogs/brendan/2011/12/18/visualizing-device-utilization/
|
17
|
+
|
18
|
+
Usage
|
19
|
+
-----
|
20
|
+
|
21
|
+
Coming soon.
|
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rake'
|
4
|
+
|
5
|
+
FileList['tasks/**/*.rake'].each { |task| import task }
|
6
|
+
desc 'run all specs'
|
7
|
+
|
8
|
+
task :spec => ['spec:unit', 'spec:integration']
|
9
|
+
desc 'run all integration tests'
|
10
|
+
|
11
|
+
task :integration => ['spec:integration']
|
12
|
+
|
13
|
+
namespace :spec do
|
14
|
+
spec_defaults = lambda do |spec|
|
15
|
+
spec.rspec_opts = ['--options', 'spec/spec.opts']
|
16
|
+
end
|
17
|
+
|
18
|
+
require 'rspec/core/rake_task'
|
19
|
+
RSpec::Core::RakeTask.new('unit') do |task|
|
20
|
+
spec_defaults.call(task)
|
21
|
+
task.pattern = 'spec/unit/**/*_spec.rb'
|
22
|
+
end
|
23
|
+
|
24
|
+
RSpec::Core::RakeTask.new('integration') do |task|
|
25
|
+
spec_defaults.call(task)
|
26
|
+
task.pattern = 'spec/integration/**/*_spec.rb'
|
27
|
+
end
|
28
|
+
|
29
|
+
RSpec::Core::RakeTask.new('coverage') do |task|
|
30
|
+
spec_defaults.call(task)
|
31
|
+
task.pattern = 'spec/{unit,integration}/*_spec.rb'
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
task :default => :spec
|
data/lib/rubella.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Rubella
|
2
|
+
module Input
|
3
|
+
|
4
|
+
# Gets the raw data and translate it into a readable format for the
|
5
|
+
# Rubella::Weighting::Base class.
|
6
|
+
# This must be an array within subarrays, which have all the same lenght
|
7
|
+
# and contains only numeric data.
|
8
|
+
#
|
9
|
+
class Base
|
10
|
+
attr_reader :data
|
11
|
+
|
12
|
+
# Constructor
|
13
|
+
# Create a new Rubella::Input::Base object using the given data
|
14
|
+
#
|
15
|
+
# @param var Input data
|
16
|
+
# @return Rubell::Input::Base
|
17
|
+
#
|
18
|
+
def initialize data
|
19
|
+
@data = data
|
20
|
+
end
|
21
|
+
|
22
|
+
# Passes each dataset trought the given block.
|
23
|
+
#
|
24
|
+
# @param pointer to block
|
25
|
+
#
|
26
|
+
def each &block
|
27
|
+
@data.each &block
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rubella/input/base'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Rubella
|
5
|
+
module Input
|
6
|
+
|
7
|
+
# Gets data in JSON formate and translate it into a Ruby readable form to
|
8
|
+
# make it possible to handle the data.
|
9
|
+
#
|
10
|
+
class JSON < Base
|
11
|
+
|
12
|
+
# Constructor
|
13
|
+
# This constructer can create a new Rubella::Input::JSON object, but it
|
14
|
+
# is supposed to be private. Please use Rubella::Input::JSON.string or
|
15
|
+
# Rubella::Input::JSON.file to create a new instance.
|
16
|
+
#
|
17
|
+
# @param json_string string A string, which contains the data as json
|
18
|
+
# @return Rubella::Input::JSON
|
19
|
+
#
|
20
|
+
def initialize json_string
|
21
|
+
@data = ::JSON::load json_string
|
22
|
+
end
|
23
|
+
|
24
|
+
# Constructor
|
25
|
+
# Creates a new Rubella::Input::JSON object, from the given json.
|
26
|
+
#
|
27
|
+
# @param json_string string A string, which contains the data as json
|
28
|
+
# @return Rubella::Input::JSON
|
29
|
+
def self.string json_string
|
30
|
+
self.new json_string
|
31
|
+
end
|
32
|
+
|
33
|
+
# Constructor
|
34
|
+
# Creates a new Rubella::Input::JSON object, from the given file.
|
35
|
+
# Only the file name is required.
|
36
|
+
#
|
37
|
+
# @param json_file string The name of the file, which json contains
|
38
|
+
# @return Rubella:Input::JSON
|
39
|
+
#
|
40
|
+
def self.file json_file
|
41
|
+
self.new File.new json_file, 'r'
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
data/lib/rubella/map.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
module Rubella
|
2
|
+
|
3
|
+
# Helps to process and create the heatmap
|
4
|
+
#
|
5
|
+
class Map
|
6
|
+
attr_reader :input
|
7
|
+
attr_reader :output
|
8
|
+
attr_reader :weighting
|
9
|
+
|
10
|
+
# Constructor
|
11
|
+
#
|
12
|
+
# @param input_name string Name of the input type in CamelCase
|
13
|
+
# @param output_name string Name of the output type in CamelCase
|
14
|
+
# @param weighting_name string Name of the weighting type in CamelCase
|
15
|
+
# @return Rubella::Map
|
16
|
+
# @raise NotImplementedError
|
17
|
+
def initialize(input_name, output_name, weighting_name)
|
18
|
+
|
19
|
+
# set the input type
|
20
|
+
input_by_name input_name
|
21
|
+
|
22
|
+
# set the output type
|
23
|
+
output_by_name output_name
|
24
|
+
|
25
|
+
# set the weighting
|
26
|
+
weighting_by_name weighting_name
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
# Set the input type by the given name
|
31
|
+
#
|
32
|
+
# @param input_name string Name of the input type in CamelCase
|
33
|
+
# @raise NotImplementedError
|
34
|
+
def input_by_name input_name
|
35
|
+
@input = load_by_name "Input", input_name
|
36
|
+
end
|
37
|
+
|
38
|
+
# Set the output type by the given name
|
39
|
+
#
|
40
|
+
# @param output_name string Name of the output type in CamelCase
|
41
|
+
# @raise NotImplementedError
|
42
|
+
def output_by_name output_name
|
43
|
+
@output = load_by_name "Output", output_name
|
44
|
+
end
|
45
|
+
|
46
|
+
# Set the weighting type by the given name
|
47
|
+
#
|
48
|
+
# @param weighting_name string Name of the weighting type in CamelCase
|
49
|
+
# @raise NotImplementedError
|
50
|
+
def weighting_by_name weighting_name
|
51
|
+
@weighting = load_by_name "Weighting", weighting_name
|
52
|
+
end
|
53
|
+
|
54
|
+
# Loads and returns the given class
|
55
|
+
#
|
56
|
+
# @param module_name string The Name of the module in CamelCase
|
57
|
+
# @param class_name string The Name of the class in CamelCase
|
58
|
+
# @return Class
|
59
|
+
# @raise NotImplementedError
|
60
|
+
def load_by_name module_name, class_name
|
61
|
+
# Remove the class, if someone wants to do this
|
62
|
+
if class_name == nil or class_name == ""
|
63
|
+
return nil
|
64
|
+
end
|
65
|
+
|
66
|
+
# Try to load the given class
|
67
|
+
require "rubella/"+underscore(module_name)+"/"+underscore(class_name)
|
68
|
+
|
69
|
+
# Try to get a class by the given name
|
70
|
+
return Object.const_get("Rubella").const_get(module_name).const_get(class_name)
|
71
|
+
|
72
|
+
# TODO raise this error, if class is not found
|
73
|
+
# raise NotImplementedError, "Not supported input type "+input_name+" given"
|
74
|
+
end
|
75
|
+
|
76
|
+
# Converts CamelCase words into snake_case
|
77
|
+
#
|
78
|
+
# @param camel_cased_word string Word in CamelCase
|
79
|
+
# @return string
|
80
|
+
def underscore(camel_cased_word)
|
81
|
+
camel_cased_word.to_s.gsub(/::/, '/').
|
82
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
83
|
+
tr("-", "_").downcase
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require "rubella/output/base"
|
2
|
+
|
3
|
+
module Rubella
|
4
|
+
module Output
|
5
|
+
|
6
|
+
# Creates a ascii art representation of the given storage data.
|
7
|
+
# In @data will a ordenary String be stored. Print the String to your
|
8
|
+
# output field and it will shows a nice ascii art graphic.
|
9
|
+
# There are also different ascii art themes available. Including the
|
10
|
+
# possibility to add own themes.
|
11
|
+
# You only need to push an Array within 10 chars for the representation
|
12
|
+
# into the :symbols Hash. Then you can select it with set the used_symbols
|
13
|
+
# variable to you theme name.
|
14
|
+
#
|
15
|
+
# TODO Use setted field_size for representation
|
16
|
+
#
|
17
|
+
class ASCII < Base
|
18
|
+
attr_accessor :symbols
|
19
|
+
attr_reader :used_symbols
|
20
|
+
|
21
|
+
# Constructor
|
22
|
+
# Sets the default field_size to 1.
|
23
|
+
# Also sets the used ascii art theme to "shades_ascii". See the
|
24
|
+
# used_symbols= for further information.
|
25
|
+
#
|
26
|
+
# @param data Rubella::Storage
|
27
|
+
# @param field_size int Used chars for one value
|
28
|
+
# @return Rubella::Output::ASCII
|
29
|
+
#
|
30
|
+
def initialize data, field_size = 1
|
31
|
+
@symbols = Hash.new
|
32
|
+
@symbols["shades"] =
|
33
|
+
[" ", " ", "░", "░", "▒", "▒", "▓", "▓", "█", "█"]
|
34
|
+
@symbols["shades_ascii"] =
|
35
|
+
[" ", "·", "⚬", "∞", "@", "#", "░", "▒", "▓", "█"]
|
36
|
+
@symbols["ascii"] =
|
37
|
+
[" ", "·", ",", ";", "o", "O", "%", "8", "@", "#"]
|
38
|
+
@symbols["numbers"] =
|
39
|
+
[" ", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
|
40
|
+
|
41
|
+
self.used_symbols = "shades_ascii"
|
42
|
+
super data, field_size
|
43
|
+
end
|
44
|
+
|
45
|
+
# Sets the used ascii theme by the given name.
|
46
|
+
# The theme must exist. You can also choose your custom theme here.
|
47
|
+
# The at default avaliable themes are:
|
48
|
+
# * shades
|
49
|
+
# * shades_ascii
|
50
|
+
# * ascii
|
51
|
+
# * numbers
|
52
|
+
#
|
53
|
+
# @param value String The theme name
|
54
|
+
# @raise ArgumentError
|
55
|
+
#
|
56
|
+
def used_symbols= value
|
57
|
+
if @symbols.has_key? value
|
58
|
+
@used_symbols = value
|
59
|
+
return
|
60
|
+
end
|
61
|
+
raise ArgumentError, "Symbol set not found, must be one of: " +
|
62
|
+
@symbols.keys.join(", ")
|
63
|
+
end
|
64
|
+
|
65
|
+
# Creates an ascii art representation.
|
66
|
+
#
|
67
|
+
# @return String
|
68
|
+
#
|
69
|
+
def render
|
70
|
+
buckets = @data.dataset_length
|
71
|
+
# columns = @data.length
|
72
|
+
|
73
|
+
# image size
|
74
|
+
# x = columns*@field_size
|
75
|
+
# y = buckets*@field_size
|
76
|
+
|
77
|
+
# start drawing the damn thing
|
78
|
+
ascii_arr = []
|
79
|
+
0.upto(buckets-1).each { |i| ascii_arr[i] = "" }
|
80
|
+
|
81
|
+
@data.each do |point|
|
82
|
+
i = 0
|
83
|
+
point.reverse.each do |part|
|
84
|
+
part = (part*10).to_i
|
85
|
+
|
86
|
+
# Fix to prevent possible overflow.. should never happen, but we
|
87
|
+
# are careful
|
88
|
+
if part > 9
|
89
|
+
part = 9
|
90
|
+
end
|
91
|
+
|
92
|
+
ascii_arr[i] << @symbols[@used_symbols][part]
|
93
|
+
i = i+1
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
ascii_arr.join("\n")
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Rubella
|
2
|
+
module Output
|
3
|
+
|
4
|
+
# Output base class
|
5
|
+
# The output class gets the storage within the already weighted and in
|
6
|
+
# buckets sorted content. It creates a visual representation of the given
|
7
|
+
# data and stores this local.
|
8
|
+
#
|
9
|
+
class Base
|
10
|
+
attr_accessor :field_size
|
11
|
+
|
12
|
+
# Constructor
|
13
|
+
# Gets the field size to store it local. It's the size of one value of
|
14
|
+
# the later created visual representation. The unit depends on the kind
|
15
|
+
# of representation.
|
16
|
+
#
|
17
|
+
# @param data Rubella::Storage
|
18
|
+
# @param field_size int size of one value
|
19
|
+
# @return Rubella::Output::Base
|
20
|
+
#
|
21
|
+
def initialize data, field_size
|
22
|
+
@data = data
|
23
|
+
@field_size = field_size
|
24
|
+
end
|
25
|
+
|
26
|
+
# Creates a visual representation.
|
27
|
+
#
|
28
|
+
# @return rendered data
|
29
|
+
#
|
30
|
+
def render
|
31
|
+
raise NotImplementedError.new "Please override 'render' in your "+
|
32
|
+
"concrete implementation"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "rubella/output/base"
|
2
|
+
require 'RMagick'
|
3
|
+
|
4
|
+
module Rubella
|
5
|
+
module Output
|
6
|
+
|
7
|
+
# Creates a pixel based graphic as representation of the given storage
|
8
|
+
# data using ImageMagick.
|
9
|
+
# By the RMagick extention. @data will contain a Magick image for futher
|
10
|
+
# handling the data please read the RMagick library documentation:
|
11
|
+
# http://www.imagemagick.org/RMagick/doc/
|
12
|
+
#
|
13
|
+
class Image < Base
|
14
|
+
|
15
|
+
# Constructor
|
16
|
+
# Has a default field_size of 15 pixel.
|
17
|
+
#
|
18
|
+
# @param data Rubella::Storage
|
19
|
+
# @param field_size int How many pixel one value has
|
20
|
+
# @return Rubella::Output::Image
|
21
|
+
#
|
22
|
+
def initialize data, field_size = 15
|
23
|
+
super data, field_size
|
24
|
+
end
|
25
|
+
|
26
|
+
# Creates a pixel based graphic.
|
27
|
+
#
|
28
|
+
# @return RMagick::Image
|
29
|
+
#
|
30
|
+
def render
|
31
|
+
# image size
|
32
|
+
x = @data.length*@field_size # columns x field_size
|
33
|
+
y = @data.dataset_length*@field_size # buckets x field_size
|
34
|
+
|
35
|
+
# start drawing the damn thing
|
36
|
+
image = Magick::Image.new(x, y) { self.background_color = "white" }
|
37
|
+
|
38
|
+
i = 0
|
39
|
+
@data.each do |point|
|
40
|
+
j = 0
|
41
|
+
point.reverse.each do |part|
|
42
|
+
# draw a red rectangle on the white background
|
43
|
+
core = Magick::Draw.new
|
44
|
+
|
45
|
+
idensity = 127.5 * part
|
46
|
+
# Fix for float stupidity
|
47
|
+
idensity = 127.5 if idensity > 127.5
|
48
|
+
|
49
|
+
# Get the correct value
|
50
|
+
l = (255-idensity).round
|
51
|
+
|
52
|
+
# Draw
|
53
|
+
core.fill(Magick::Pixel.from_hsla(0, 255, l, 1).to_color)
|
54
|
+
core.rectangle((i*@field_size), (j*@field_size), ((i+1)*@field_size), ((j+1)*@field_size))
|
55
|
+
core.draw image
|
56
|
+
j = j + 1
|
57
|
+
end
|
58
|
+
i = i + 1
|
59
|
+
end
|
60
|
+
|
61
|
+
image
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Rubella
|
2
|
+
|
3
|
+
# The Rubella::Storage holds the weighted data.
|
4
|
+
# Storages can be added to get a timeline. But the Storage has no concrete
|
5
|
+
# knowledge of time.
|
6
|
+
# The Storage can have a defined length. If new data is added, it will drop
|
7
|
+
# the oldest entries.
|
8
|
+
#
|
9
|
+
class Storage
|
10
|
+
attr_reader :data
|
11
|
+
# :length
|
12
|
+
|
13
|
+
def initialize data, length = 0
|
14
|
+
@data = data
|
15
|
+
self.length = length
|
16
|
+
end
|
17
|
+
|
18
|
+
# Defines the length of the Storage.
|
19
|
+
#
|
20
|
+
# Be careful, if your Storage has more entries, tha the new length, the
|
21
|
+
# oldest entries will immediately be dropped. If your Storage has less
|
22
|
+
# entries, it will be filled up with empty entries.
|
23
|
+
# Happens only if data has entries.
|
24
|
+
#
|
25
|
+
# Setting the length to 0 will disable this feature
|
26
|
+
#
|
27
|
+
# TODO fill up with 0 values, if data is not multidemensional
|
28
|
+
#
|
29
|
+
# @param length Integer The size of the storage
|
30
|
+
# @return Integer The new size
|
31
|
+
#
|
32
|
+
def length= length
|
33
|
+
@length = length
|
34
|
+
|
35
|
+
# Use length only, if length is valid
|
36
|
+
if @length != 0 and self.length != 0
|
37
|
+
# Drop entries, if more than new length
|
38
|
+
while self.length > @length
|
39
|
+
@data.pop
|
40
|
+
end
|
41
|
+
# Prefill with empty content, if less than new length
|
42
|
+
dummy_data = Array.new(self.dataset_length, 0)
|
43
|
+
while self.length < @length
|
44
|
+
@data.unshift dummy_data
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
@length
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns the current length of the storage.
|
52
|
+
# (How many datasets it holds.)
|
53
|
+
#
|
54
|
+
# @return Integer length
|
55
|
+
#
|
56
|
+
def length
|
57
|
+
@data.length
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns the length of a dataset.
|
61
|
+
# Will return 0, if no datasets in storage.
|
62
|
+
#
|
63
|
+
# TODO Throw an error, if data has different lengths
|
64
|
+
#
|
65
|
+
# @return Integer length of one dataset
|
66
|
+
#
|
67
|
+
def dataset_length
|
68
|
+
return 0 if self.length == 0
|
69
|
+
return 1 unless @data[0].respond_to? "length"
|
70
|
+
|
71
|
+
@data[0].length
|
72
|
+
end
|
73
|
+
|
74
|
+
# Adds the data from the given storage to the own data and return this as a
|
75
|
+
# new Storage. Does not modify one of the storages.
|
76
|
+
#
|
77
|
+
# @param storage Rubella::Storage Storage with new data
|
78
|
+
# @return Rubella::Storage
|
79
|
+
#
|
80
|
+
def add storage
|
81
|
+
Storage.new (storage.data+@data), @length
|
82
|
+
end
|
83
|
+
|
84
|
+
# Passes each dataset through the given block.
|
85
|
+
#
|
86
|
+
# @param pointer to block
|
87
|
+
#
|
88
|
+
def each &block
|
89
|
+
@data.each &block
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Rubella
|
2
|
+
module Weighting
|
3
|
+
|
4
|
+
|
5
|
+
# The Rubella::Weighting object processes the given input data to an valid
|
6
|
+
# output processable Array.
|
7
|
+
# These arrays contain a subarray for every unit of time. And these Array
|
8
|
+
# contain the buckets within the values for the output objects.
|
9
|
+
# The Weighting of the print intensitiy is done here, so that the output
|
10
|
+
# objects job is simply to print the stuff.
|
11
|
+
#
|
12
|
+
class Base
|
13
|
+
attr_reader :buckets
|
14
|
+
# :steps
|
15
|
+
|
16
|
+
# Constructor
|
17
|
+
# Creates a new Rubella::Weighting::xy object.
|
18
|
+
#
|
19
|
+
# @param buckets int must be one of 1, 2, 5, 10, 20, 50 default is 10
|
20
|
+
# @return Rubella::Weighting::Base
|
21
|
+
# @raise ArgumentError
|
22
|
+
#
|
23
|
+
def initialize buckets = 10
|
24
|
+
self.buckets = buckets
|
25
|
+
end
|
26
|
+
|
27
|
+
# Sets the buckets, if the value is valid
|
28
|
+
#
|
29
|
+
# @param buckets int The amount of buckets
|
30
|
+
# @raise ArgumentError
|
31
|
+
#
|
32
|
+
def buckets= buckets
|
33
|
+
# Must be divideable by 100
|
34
|
+
if [1, 2, 5, 10, 20, 50].index(buckets) == nil
|
35
|
+
raise ArgumentError.new "Amount of buckets must be 1, 2, 5, 10, 20 "+
|
36
|
+
"or 50"
|
37
|
+
end
|
38
|
+
|
39
|
+
@steps = 100/buckets
|
40
|
+
@buckets = buckets
|
41
|
+
end
|
42
|
+
|
43
|
+
# Creates a output readable list.
|
44
|
+
# This list is Array within a subarrays, which contain the buckets for
|
45
|
+
# every time value unit.
|
46
|
+
#
|
47
|
+
# @param input Rubella::Input An input object
|
48
|
+
# @return Rubella::Storage
|
49
|
+
#
|
50
|
+
def parse input
|
51
|
+
raise NotImplementedError.new "Please override 'parse' in your "+
|
52
|
+
"concrete implementation"
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "rubella/weighting/base"
|
2
|
+
|
3
|
+
module Rubella
|
4
|
+
module Weighting
|
5
|
+
|
6
|
+
# The Rubella::Weighting::Exponential object weights every bucket per
|
7
|
+
# amount of cores. But the cores with higher load get a visualisation
|
8
|
+
# boost, which is exponential. So one high load core, will have much more
|
9
|
+
# color, than serveral less load cores.
|
10
|
+
#
|
11
|
+
class Exponential < Base
|
12
|
+
|
13
|
+
# Creates a output readable list.
|
14
|
+
# This list is Array within a subarrays, which contain the buckets for
|
15
|
+
# every time value unit.
|
16
|
+
#
|
17
|
+
# @param input Rubella::Input An input object
|
18
|
+
# @return Rubella::Storage
|
19
|
+
def parse input
|
20
|
+
# prepare data
|
21
|
+
data_list = Array.new()
|
22
|
+
bucket_no = 0
|
23
|
+
|
24
|
+
input.each do |cores|
|
25
|
+
# every 10 load percent one heatpoint
|
26
|
+
i = 0
|
27
|
+
data_list << Array.new(buckets) do
|
28
|
+
current_cores = cores.select do |core|
|
29
|
+
core >= i and
|
30
|
+
((core < (i+@steps)) or (core <= (i+@steps) and i+@steps == 100))
|
31
|
+
end
|
32
|
+
|
33
|
+
amount = current_cores.length
|
34
|
+
i = i + @steps
|
35
|
+
core = (amount.to_f*bucket_no**0.8)/cores.length
|
36
|
+
bucket_no = bucket_no + 1
|
37
|
+
|
38
|
+
core
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
Rubella::Storage.new data_list
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "rubella/weighting/base"
|
2
|
+
|
3
|
+
module Rubella
|
4
|
+
module Weighting
|
5
|
+
|
6
|
+
# The Rubella::Weighting::PerCount create a field of each given value.
|
7
|
+
# The weighting is based on the maximum value.
|
8
|
+
#
|
9
|
+
class PerCount < Base
|
10
|
+
|
11
|
+
# Constructor
|
12
|
+
# Creates a new Rubella::Weighting::PerCount object.
|
13
|
+
#
|
14
|
+
# @param buckets int
|
15
|
+
# @return Rubella::Weighting::Base
|
16
|
+
# @raise ArgumentError
|
17
|
+
#
|
18
|
+
def initialize buckets = 7
|
19
|
+
super buckets
|
20
|
+
end
|
21
|
+
|
22
|
+
# Sets the buckets
|
23
|
+
#
|
24
|
+
# @param buckets int The amount of buckets
|
25
|
+
# @raise ArgumentError
|
26
|
+
#
|
27
|
+
def buckets= buckets
|
28
|
+
@buckets = buckets
|
29
|
+
end
|
30
|
+
|
31
|
+
# Creates a output readable list.
|
32
|
+
# This list is Array within a subarrays, which contain the buckets for
|
33
|
+
# every time value unit.
|
34
|
+
#
|
35
|
+
# @param input Rubella::Input An input object
|
36
|
+
# @return Rubella::Storage
|
37
|
+
def parse input
|
38
|
+
# prepare data
|
39
|
+
data_list = Array.new()
|
40
|
+
|
41
|
+
# Get the maximum of commits
|
42
|
+
max = input.sort.pop
|
43
|
+
|
44
|
+
i = 0
|
45
|
+
input.each do |commits|
|
46
|
+
data_list << Array.new() if i == 0
|
47
|
+
data_list.last << commits.to_f/max
|
48
|
+
if i == (buckets-1)
|
49
|
+
i = 0
|
50
|
+
else
|
51
|
+
i = i + 1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
Rubella::Storage.new data_list
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "rubella/weighting/base"
|
2
|
+
|
3
|
+
module Rubella
|
4
|
+
module Weighting
|
5
|
+
|
6
|
+
# The Rubella::Weighting::PerOverallValue object summarizes the load of all
|
7
|
+
# cores in a time and computes how much load is one percent. Then it uses
|
8
|
+
# this as factor to weight the summarized load of every bucket.
|
9
|
+
# So your representation will show you the higher load cores more
|
10
|
+
# intensive, then the cores with lower load, depending on the current load.
|
11
|
+
#
|
12
|
+
class PerOverallLoad < Base
|
13
|
+
|
14
|
+
# Creates a output readable list.
|
15
|
+
# This list is Array within a subarrays, which contain the buckets for
|
16
|
+
# every time value unit.
|
17
|
+
#
|
18
|
+
# @param input Rubella::Input An input object
|
19
|
+
# @return Rubella::Storage
|
20
|
+
def parse input
|
21
|
+
# prepare data
|
22
|
+
data_list = Array.new()
|
23
|
+
|
24
|
+
input.each do |cores|
|
25
|
+
|
26
|
+
# Add all loads to compute how much % is one % load
|
27
|
+
load_sum = 0
|
28
|
+
cores.each { |core| load_sum = load_sum + core }
|
29
|
+
percent_load = 100.0/load_sum
|
30
|
+
|
31
|
+
# every 10 load percent one heatpoint
|
32
|
+
i = 0
|
33
|
+
data_list << Array.new(buckets) do
|
34
|
+
# Select all current cores
|
35
|
+
selected_cores = cores.select do |core|
|
36
|
+
core >= i and
|
37
|
+
((core < (i+@steps)) or (core <= (i+@steps) and i+@steps == 100))
|
38
|
+
end
|
39
|
+
i = i + @steps
|
40
|
+
|
41
|
+
# add the load of the resulting cores and multiply it with the overall value
|
42
|
+
load_sum = 0
|
43
|
+
selected_cores.each { |core| load_sum = load_sum + core }
|
44
|
+
(load_sum.to_f*percent_load)/100
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
Rubella::Storage.new data_list
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "rubella/weighting/base"
|
2
|
+
|
3
|
+
module Rubella
|
4
|
+
module Weighting
|
5
|
+
|
6
|
+
# The Rubella::Weighting::PerValue object weights every bucket set to 1 in
|
7
|
+
# amount. So if you have have for example four cores, every core is
|
8
|
+
# weighted to 0.25 no matter how much the load of a single core is. It's
|
9
|
+
# just a "as is" weighting.
|
10
|
+
#
|
11
|
+
class PerValue < Base
|
12
|
+
|
13
|
+
# Creates a output readable list.
|
14
|
+
# This list is Array within a subarrays, which contain the buckets for
|
15
|
+
# every time value unit.
|
16
|
+
#
|
17
|
+
# @param input Rubella::Input An input object
|
18
|
+
# @return Rubella::Storage
|
19
|
+
def parse input
|
20
|
+
# prepare data
|
21
|
+
data_list = Array.new()
|
22
|
+
|
23
|
+
input.each do |cores|
|
24
|
+
# every 10 load percent one heatpoint
|
25
|
+
i = 0
|
26
|
+
data_list << Array.new(buckets) do
|
27
|
+
current_cores = cores.select do |core|
|
28
|
+
core >= i and
|
29
|
+
((core < (i+@steps)) or (core <= (i+@steps) and i+@steps == 100))
|
30
|
+
end
|
31
|
+
amount = current_cores.length
|
32
|
+
i = i + @steps
|
33
|
+
amount.to_f/cores.length
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
Rubella::Storage.new data_list
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
[1, 2, 3]
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rubella::Input::Base, '.each' do
|
4
|
+
|
5
|
+
it "passes the data through the given block" do
|
6
|
+
input = Rubella::Input::Base.new [3, 4, 5]
|
7
|
+
|
8
|
+
sum = 0
|
9
|
+
input.each do |value|
|
10
|
+
sum = sum + value
|
11
|
+
end
|
12
|
+
|
13
|
+
expect(sum).to eq(12)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rubella::Input::Base, '.new' do
|
4
|
+
|
5
|
+
it "creates a new Input instance" do
|
6
|
+
input = Rubella::Input::Base.new nil
|
7
|
+
|
8
|
+
expect(input).to be_instance_of(Rubella::Input::Base)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "uses the given data" do
|
12
|
+
input = Rubella::Input::Base.new 54
|
13
|
+
|
14
|
+
expect(input.data).to eq(54)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rubella::Input::JSON, '.each' do
|
4
|
+
|
5
|
+
it "passes the data through the given block" do
|
6
|
+
input = Rubella::Input::JSON.string "[3, 4, 5]"
|
7
|
+
|
8
|
+
sum = 0
|
9
|
+
input.each do |value|
|
10
|
+
sum = sum + value
|
11
|
+
end
|
12
|
+
|
13
|
+
expect(sum).to eq(12)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rubella::Input::JSON, '#self.file' do
|
4
|
+
|
5
|
+
it 'returns a Rubella::Input::JSON object' do
|
6
|
+
input = Rubella::Input::JSON.file 'spec/fixtures/json/test_01.json'
|
7
|
+
|
8
|
+
expect(input).to be_instance_of(Rubella::Input::JSON)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "uses the given data" do
|
12
|
+
input = Rubella::Input::JSON.file 'spec/fixtures/json/test_01.json'
|
13
|
+
|
14
|
+
expect(input.data).to eq([1, 2, 3])
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rubella::Input::JSON, '#self.string' do
|
4
|
+
|
5
|
+
it 'returns a Rubella::Input::JSON object' do
|
6
|
+
input = Rubella::Input::JSON.string '[]'
|
7
|
+
|
8
|
+
expect(input).to be_instance_of(Rubella::Input::JSON)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "uses the given data" do
|
12
|
+
input = Rubella::Input::JSON.string '[1, 2, 3]'
|
13
|
+
|
14
|
+
expect(input.data).to eq([1, 2, 3])
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rubella::Storage, '.add' do
|
4
|
+
|
5
|
+
it "returns a new Storage with the given Storages data before the old" do
|
6
|
+
storage_1 = Rubella::Storage.new [3, 4, 5]
|
7
|
+
storage_2 = Rubella::Storage.new [0, 1, 2]
|
8
|
+
|
9
|
+
storage_new = storage_1.add storage_2
|
10
|
+
expect(storage_new.data).to eq([0, 1, 2, 3, 4, 5])
|
11
|
+
end
|
12
|
+
|
13
|
+
it "uses the length of the first given Storage" do
|
14
|
+
storage_1 = Rubella::Storage.new [3, 4, 5, 6, 7], 4
|
15
|
+
storage_2 = Rubella::Storage.new [0, 1, 2], 3
|
16
|
+
|
17
|
+
storage_new = storage_1.add storage_2
|
18
|
+
expect(storage_new.length).to eq 4
|
19
|
+
end
|
20
|
+
|
21
|
+
it "chops the data to the given length" do
|
22
|
+
storage_1 = Rubella::Storage.new [3, 4, 5, 6, 7], 4
|
23
|
+
storage_2 = Rubella::Storage.new [0, 1, 2], 3
|
24
|
+
|
25
|
+
storage_new = storage_1.add storage_2
|
26
|
+
expect(storage_new.data).to eq([0, 1, 2, 3])
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rubella::Storage, '.dataset_length' do
|
4
|
+
|
5
|
+
it "returns 0 if Storage is empty" do
|
6
|
+
storage = Rubella::Storage.new []
|
7
|
+
|
8
|
+
expect(storage.dataset_length).to eq(0)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "returns 1 if Storage holds one dimensional array" do
|
12
|
+
storage = Rubella::Storage.new [1, 2, 3]
|
13
|
+
|
14
|
+
expect(storage.dataset_length).to eq(1)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "returns 1 if Storage datasets have a length of 1" do
|
18
|
+
storage = Rubella::Storage.new [[1], [2], [3]]
|
19
|
+
|
20
|
+
expect(storage.dataset_length).to eq(1)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "returns the length of the datasets" do
|
24
|
+
storage = Rubella::Storage.new [[1, 2], [3, 4], [5, 6]]
|
25
|
+
|
26
|
+
expect(storage.dataset_length).to eq(2)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rubella::Storage, '.each' do
|
4
|
+
|
5
|
+
it "passes the data through the given block" do
|
6
|
+
storage = Rubella::Storage.new [3, 4, 5]
|
7
|
+
|
8
|
+
sum = 0
|
9
|
+
storage.each do |value|
|
10
|
+
sum = sum + value
|
11
|
+
end
|
12
|
+
|
13
|
+
expect(sum).to eq(12)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rubella::Storage, '.length=' do
|
4
|
+
|
5
|
+
it "sets the length to the given value" do
|
6
|
+
storage = Rubella::Storage.new [3, 4, 5]
|
7
|
+
|
8
|
+
storage.length = 2
|
9
|
+
|
10
|
+
expect(storage.length).to eq(2)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "chops the data to the given length" do
|
14
|
+
storage = Rubella::Storage.new [3, 4, 5]
|
15
|
+
|
16
|
+
storage.length = 2
|
17
|
+
|
18
|
+
expect(storage.data.length).to eq(2)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "disables the length chopping, if its set to 0" do
|
22
|
+
storage = Rubella::Storage.new [3, 4, 5]
|
23
|
+
|
24
|
+
storage.length = 0
|
25
|
+
|
26
|
+
expect(storage.data.length).to eq(3)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "grows the data to the given length" do
|
30
|
+
storage = Rubella::Storage.new [[0, 1], [2, 3], [4, 5]]
|
31
|
+
|
32
|
+
storage.length = 5
|
33
|
+
|
34
|
+
expect(storage.data.length).to eq(5)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "grows the data by using the length of the dataset as array length" do
|
38
|
+
storage = Rubella::Storage.new [[0, 1], [2, 3], [4, 5]]
|
39
|
+
|
40
|
+
storage.length = 5
|
41
|
+
|
42
|
+
expect(storage.data[0].length).to eq(2)
|
43
|
+
expect(storage.data[1].length).to eq(2)
|
44
|
+
expect(storage.data[2].length).to eq(2)
|
45
|
+
expect(storage.data[3].length).to eq(2)
|
46
|
+
expect(storage.data[4].length).to eq(2)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "grows the data by using 0 values" do
|
50
|
+
storage = Rubella::Storage.new [[0, 1], [2, 3], [4, 5]]
|
51
|
+
|
52
|
+
storage.length = 5
|
53
|
+
|
54
|
+
expect(storage.data[0][0]).to eq(0)
|
55
|
+
expect(storage.data[0][1]).to eq(0)
|
56
|
+
expect(storage.data[1][0]).to eq(0)
|
57
|
+
expect(storage.data[1][1]).to eq(0)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "does not grow the data, if Storage is empty" do
|
61
|
+
storage = Rubella::Storage.new []
|
62
|
+
|
63
|
+
storage.length = 5
|
64
|
+
|
65
|
+
expect(storage.data.length).to eq(0)
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rubella::Storage, '.new' do
|
4
|
+
|
5
|
+
it "creates a new Storage" do
|
6
|
+
storage = Rubella::Storage.new []
|
7
|
+
|
8
|
+
expect(storage).to be_an_instance_of(Rubella::Storage)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "fills the Storage with the given data" do
|
12
|
+
storage = Rubella::Storage.new [1, 2, 3]
|
13
|
+
|
14
|
+
expect(storage.data).to eq([1, 2, 3])
|
15
|
+
end
|
16
|
+
|
17
|
+
it "disable length feature, if no length is given" do
|
18
|
+
storage = Rubella::Storage.new [1, 2, 3]
|
19
|
+
|
20
|
+
expect(storage.length).to eq(3)
|
21
|
+
expect(storage.data.length).to eq(3)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "disable length feature, if length is 0" do
|
25
|
+
storage = Rubella::Storage.new [1, 2, 3], 0
|
26
|
+
|
27
|
+
expect(storage.length).to eq(3)
|
28
|
+
expect(storage.data.length).to eq(3)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "sets the length" do
|
32
|
+
storage = Rubella::Storage.new [1, 2, 3], 2
|
33
|
+
|
34
|
+
expect(storage.length).to eq(2)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "uses length feature, if length is given" do
|
38
|
+
storage = Rubella::Storage.new [1, 2, 3], 2
|
39
|
+
|
40
|
+
expect(storage.data.length).to eq(2)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubella
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stormwind
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-05-05 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: |-
|
14
|
+
Rubella is a library to generate heatmaps to monitor visualize measured values
|
15
|
+
easier. Like the load of multiple CPU cores over time.
|
16
|
+
email: rebecca@quantenteilchen.de
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files:
|
20
|
+
- README.md
|
21
|
+
files:
|
22
|
+
- Gemfile
|
23
|
+
- LICENSE
|
24
|
+
- README.md
|
25
|
+
- Rakefile
|
26
|
+
- lib/rubella.rb
|
27
|
+
- lib/rubella/input/base.rb
|
28
|
+
- lib/rubella/input/json.rb
|
29
|
+
- lib/rubella/map.rb
|
30
|
+
- lib/rubella/output/ascii.rb
|
31
|
+
- lib/rubella/output/base.rb
|
32
|
+
- lib/rubella/output/image.rb
|
33
|
+
- lib/rubella/storage.rb
|
34
|
+
- lib/rubella/weighting/base.rb
|
35
|
+
- lib/rubella/weighting/exponential.rb
|
36
|
+
- lib/rubella/weighting/per_count.rb
|
37
|
+
- lib/rubella/weighting/per_overall_load.rb
|
38
|
+
- lib/rubella/weighting/per_value.rb
|
39
|
+
- spec/fixtures/json/test_01.json
|
40
|
+
- spec/spec.opts
|
41
|
+
- spec/spec_helper.rb
|
42
|
+
- spec/unit/rubella/input/base/data_spec.rb
|
43
|
+
- spec/unit/rubella/input/base/each_spec.rb
|
44
|
+
- spec/unit/rubella/input/base/new_spec.rb
|
45
|
+
- spec/unit/rubella/input/json/data_spec.rb
|
46
|
+
- spec/unit/rubella/input/json/each_spec.rb
|
47
|
+
- spec/unit/rubella/input/json/self_file_spec.rb
|
48
|
+
- spec/unit/rubella/input/json/self_string_spec.rb
|
49
|
+
- spec/unit/rubella/storage/add_spec.rb
|
50
|
+
- spec/unit/rubella/storage/data_spec.rb
|
51
|
+
- spec/unit/rubella/storage/dataset_length_spec.rb
|
52
|
+
- spec/unit/rubella/storage/each_spec.rb
|
53
|
+
- spec/unit/rubella/storage/length_eql_spec.rb
|
54
|
+
- spec/unit/rubella/storage/length_spec.rb
|
55
|
+
- spec/unit/rubella/storage/new_spec.rb
|
56
|
+
homepage: https://github.com/Stormwind/rubella
|
57
|
+
licenses:
|
58
|
+
- 3-clause BSD
|
59
|
+
metadata: {}
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
requirements: []
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 2.4.6
|
77
|
+
signing_key:
|
78
|
+
specification_version: 4
|
79
|
+
summary: Library to generate heatmaps
|
80
|
+
test_files:
|
81
|
+
- spec/fixtures/json/test_01.json
|
82
|
+
- spec/spec.opts
|
83
|
+
- spec/spec_helper.rb
|
84
|
+
- spec/unit/rubella/input/base/data_spec.rb
|
85
|
+
- spec/unit/rubella/input/base/each_spec.rb
|
86
|
+
- spec/unit/rubella/input/base/new_spec.rb
|
87
|
+
- spec/unit/rubella/input/json/data_spec.rb
|
88
|
+
- spec/unit/rubella/input/json/each_spec.rb
|
89
|
+
- spec/unit/rubella/input/json/self_file_spec.rb
|
90
|
+
- spec/unit/rubella/input/json/self_string_spec.rb
|
91
|
+
- spec/unit/rubella/storage/add_spec.rb
|
92
|
+
- spec/unit/rubella/storage/data_spec.rb
|
93
|
+
- spec/unit/rubella/storage/dataset_length_spec.rb
|
94
|
+
- spec/unit/rubella/storage/each_spec.rb
|
95
|
+
- spec/unit/rubella/storage/length_eql_spec.rb
|
96
|
+
- spec/unit/rubella/storage/length_spec.rb
|
97
|
+
- spec/unit/rubella/storage/new_spec.rb
|