norikra-udf-percentile 0.0.1-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/README.md +29 -0
- data/Rakefile +27 -0
- data/jar/norikra-udf-percentile.jar +0 -0
- data/java/is/tagomor/norikra/udf/Percentile.class +0 -0
- data/java/is/tagomor/norikra/udf/Percentile.java +88 -0
- data/java/is/tagomor/norikra/udf/PercentileFactory.class +0 -0
- data/java/is/tagomor/norikra/udf/PercentileFactory.java +53 -0
- data/java/is/tagomor/norikra/udf/Percentiles.class +0 -0
- data/java/is/tagomor/norikra/udf/Percentiles.java +94 -0
- data/java/is/tagomor/norikra/udf/PercentilesFactory.class +0 -0
- data/java/is/tagomor/norikra/udf/PercentilesFactory.java +53 -0
- data/lib/norikra/udf/percentile.rb +23 -0
- data/norikra-udf-percentile.gemspec +24 -0
- data/spec/percentile_spec.rb +64 -0
- data/spec/percentiles_spec.rb +82 -0
- metadata +131 -0
data/.gitignore
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
jruby-1.7.4
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Norikra::Udf::Percentile
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'norikra-udf-percentile'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install norikra-udf-percentile
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
5
|
+
t.rspec_opts = ["-c", "-f progress"] # '--format specdoc'
|
6
|
+
t.pattern = 'spec/**/*_spec.rb'
|
7
|
+
end
|
8
|
+
|
9
|
+
task :compile do
|
10
|
+
require 'rubygems'
|
11
|
+
|
12
|
+
jarname = FileList['norikra-udf-*.gemspec'].first.gsub(/\.gemspec$/, '.jar')
|
13
|
+
|
14
|
+
jarfiles = FileList['jar/**/*.jar'].select{|f| not f.end_with?('/' + jarname)}
|
15
|
+
jarfiles << Gem.find_files('esper-*.jar').first
|
16
|
+
classpath = "-classpath java:#{jarfiles.join(':')}"
|
17
|
+
|
18
|
+
FileList['java/**/*.java'].each do |fn|
|
19
|
+
sh "env LC_ALL=C javac #{classpath} #{fn}"
|
20
|
+
end
|
21
|
+
sh "env LC_ALL=C jar -cf jar/#{jarname} -C java ."
|
22
|
+
end
|
23
|
+
|
24
|
+
task :test => [:compile, :spec]
|
25
|
+
task :default => :test
|
26
|
+
|
27
|
+
task :all => [:compile, :spec, :build]
|
Binary file
|
Binary file
|
@@ -0,0 +1,88 @@
|
|
1
|
+
package is.tagomor.norikra.udf;
|
2
|
+
|
3
|
+
import com.espertech.esper.epl.agg.aggregator.AggregationMethod;
|
4
|
+
|
5
|
+
import java.util.ArrayList;
|
6
|
+
import java.util.Random;
|
7
|
+
|
8
|
+
public class Percentile implements AggregationMethod {
|
9
|
+
private static int initSize = 100000;
|
10
|
+
|
11
|
+
private ArrayList<Double> valueList;
|
12
|
+
private Integer target;
|
13
|
+
|
14
|
+
private Double last;
|
15
|
+
|
16
|
+
public Percentile() {
|
17
|
+
valueList = null;
|
18
|
+
last = null;
|
19
|
+
}
|
20
|
+
|
21
|
+
public long valueListSize() {
|
22
|
+
return valueList.size();
|
23
|
+
}
|
24
|
+
|
25
|
+
public Class getValueType() {
|
26
|
+
return Double.class;
|
27
|
+
}
|
28
|
+
|
29
|
+
public Double convertValue(Object v) {
|
30
|
+
if (v.getClass() == Double.class)
|
31
|
+
return (Double) v;
|
32
|
+
else if (v.getClass() == Float.class)
|
33
|
+
return new Double( ((Float) v).doubleValue() );
|
34
|
+
else if (v.getClass() == Integer.class)
|
35
|
+
return new Double( ((Integer) v).doubleValue() );
|
36
|
+
else if (v.getClass() == Long.class)
|
37
|
+
return new Double( ((Long) v).doubleValue() );
|
38
|
+
else
|
39
|
+
return new Double((String) v);
|
40
|
+
}
|
41
|
+
|
42
|
+
public void enter(Object value) {
|
43
|
+
if (value == null)
|
44
|
+
return;
|
45
|
+
|
46
|
+
Object[] objs = (Object[]) value;
|
47
|
+
if (valueList == null) {
|
48
|
+
target = (Integer) objs[1];
|
49
|
+
valueList = new ArrayList<Double>(initSize);
|
50
|
+
}
|
51
|
+
|
52
|
+
Double d = convertValue(objs[0]);
|
53
|
+
synchronized (valueList) {
|
54
|
+
valueList.add(d);
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
public void leave(Object value) {
|
59
|
+
if (value == null)
|
60
|
+
return;
|
61
|
+
|
62
|
+
Object[] objs = (Object[]) value;
|
63
|
+
Double d = convertValue(objs[0]);
|
64
|
+
synchronized (valueList) {
|
65
|
+
valueList.remove(d);
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
public Object getValue() {
|
70
|
+
if (valueList.size() == 0)
|
71
|
+
return last;
|
72
|
+
|
73
|
+
Double[] values = (Double[]) valueList.toArray(new Double[]{});
|
74
|
+
|
75
|
+
// for thread safety
|
76
|
+
if (values.length == 0)
|
77
|
+
return last;
|
78
|
+
|
79
|
+
java.util.Arrays.sort(values);
|
80
|
+
int size = values.length;
|
81
|
+
last = values[size * target / 100];
|
82
|
+
return last;
|
83
|
+
}
|
84
|
+
|
85
|
+
public void clear() {
|
86
|
+
valueList = null;
|
87
|
+
}
|
88
|
+
}
|
Binary file
|
@@ -0,0 +1,53 @@
|
|
1
|
+
package is.tagomor.norikra.udf;
|
2
|
+
|
3
|
+
import com.espertech.esper.client.hook.AggregationFunctionFactory;
|
4
|
+
import com.espertech.esper.epl.agg.service.AggregationValidationContext;
|
5
|
+
import com.espertech.esper.epl.agg.aggregator.AggregationMethod;
|
6
|
+
|
7
|
+
// import java.util.Map;
|
8
|
+
|
9
|
+
public class PercentileFactory implements AggregationFunctionFactory {
|
10
|
+
public void setFunctionName(String functionName) {
|
11
|
+
// no action taken
|
12
|
+
}
|
13
|
+
|
14
|
+
/*
|
15
|
+
percentile(field_name, {percentile_specifications_array}[, samples])
|
16
|
+
ex: percentile(response_time, 50)
|
17
|
+
*/
|
18
|
+
public void validate(AggregationValidationContext validationContext) {
|
19
|
+
if (validationContext.getParameterTypes().length != 2)
|
20
|
+
throw new IllegalArgumentException("percentile() accepts 2 arguments (fieldname,percentiles)");
|
21
|
+
|
22
|
+
Class first = validationContext.getParameterTypes()[0];
|
23
|
+
if (! (first == int.class || first == long.class || first == double.class || first == float.class ||
|
24
|
+
first == Integer.class || first == Long.class || first == Double.class || first == Float.class ||
|
25
|
+
first == String.class))
|
26
|
+
throw new IllegalArgumentException("percentile() first argument must be string or number, but " + first.toString());
|
27
|
+
|
28
|
+
Class second = validationContext.getParameterTypes()[1];
|
29
|
+
boolean f_second = validationContext.getIsConstantValue()[1];
|
30
|
+
if ((second != Integer.class && second != int.class) || !f_second)
|
31
|
+
throw new IllegalArgumentException("percentile() second argument must be Constant Integer");
|
32
|
+
|
33
|
+
if (validationContext.isDistinct())
|
34
|
+
throw new IllegalArgumentException("percentile() doesn't permit DISTINCT modifier");
|
35
|
+
}
|
36
|
+
|
37
|
+
/*
|
38
|
+
In order for the engine to validate the type returned by the aggregation function against
|
39
|
+
the types expected by enclosing expressions, the getValueType must return the result type
|
40
|
+
of any values produced by the aggregation function:
|
41
|
+
*/
|
42
|
+
public Class getValueType() {
|
43
|
+
return Double.class;
|
44
|
+
}
|
45
|
+
|
46
|
+
/*
|
47
|
+
Finally the factory implementation must provide a newAggregator method that returns instances
|
48
|
+
of AggregationMethod. The engine invokes this method for each new aggregation state to be allocated.
|
49
|
+
*/
|
50
|
+
public AggregationMethod newAggregator() {
|
51
|
+
return new Percentile();
|
52
|
+
}
|
53
|
+
}
|
Binary file
|
@@ -0,0 +1,94 @@
|
|
1
|
+
package is.tagomor.norikra.udf;
|
2
|
+
|
3
|
+
import com.espertech.esper.epl.agg.aggregator.AggregationMethod;
|
4
|
+
|
5
|
+
import java.util.ArrayList;
|
6
|
+
import java.util.Random;
|
7
|
+
|
8
|
+
public class Percentiles implements AggregationMethod {
|
9
|
+
private static int initSize = 100000;
|
10
|
+
|
11
|
+
private ArrayList<Double> valueList;
|
12
|
+
private Integer[] targets;
|
13
|
+
|
14
|
+
private Double[] last;
|
15
|
+
|
16
|
+
public Percentiles() {
|
17
|
+
valueList = null;
|
18
|
+
last = null;
|
19
|
+
}
|
20
|
+
|
21
|
+
public long valueListSize() {
|
22
|
+
return valueList.size();
|
23
|
+
}
|
24
|
+
|
25
|
+
public Class getValueType() {
|
26
|
+
return Double[].class;
|
27
|
+
}
|
28
|
+
|
29
|
+
public Double convertValue(Object v) {
|
30
|
+
if (v.getClass() == Double.class)
|
31
|
+
return (Double) v;
|
32
|
+
else if (v.getClass() == Float.class)
|
33
|
+
return new Double( ((Float) v).doubleValue() );
|
34
|
+
else if (v.getClass() == Integer.class)
|
35
|
+
return new Double( ((Integer) v).doubleValue() );
|
36
|
+
else if (v.getClass() == Long.class)
|
37
|
+
return new Double( ((Long) v).doubleValue() );
|
38
|
+
else
|
39
|
+
return new Double((String) v);
|
40
|
+
}
|
41
|
+
|
42
|
+
public void enter(Object value) {
|
43
|
+
if (value == null)
|
44
|
+
return;
|
45
|
+
|
46
|
+
Object[] objs = (Object[]) value;
|
47
|
+
if (valueList == null) {
|
48
|
+
targets = (Integer[]) objs[1];
|
49
|
+
valueList = new ArrayList<Double>(initSize);
|
50
|
+
}
|
51
|
+
|
52
|
+
Double d = convertValue(objs[0]);
|
53
|
+
synchronized (valueList) {
|
54
|
+
valueList.add(d);
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
public void leave(Object value) {
|
59
|
+
if (value == null)
|
60
|
+
return;
|
61
|
+
|
62
|
+
Object[] objs = (Object[]) value;
|
63
|
+
Double d = convertValue(objs[0]);
|
64
|
+
synchronized (valueList) {
|
65
|
+
valueList.remove(d);
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
public Object getValue() {
|
70
|
+
if (valueList.size() == 0)
|
71
|
+
return last;
|
72
|
+
|
73
|
+
ArrayList<Double> percentiles = new ArrayList<Double>(targets.length);
|
74
|
+
Double[] values = (Double[]) valueList.toArray(new Double[]{});
|
75
|
+
|
76
|
+
// for thread safety
|
77
|
+
if (values.length == 0)
|
78
|
+
return last;
|
79
|
+
|
80
|
+
java.util.Arrays.sort(values);
|
81
|
+
int size = values.length;
|
82
|
+
|
83
|
+
for (int i = 0 ; i < targets.length ; i += 1) {
|
84
|
+
percentiles.add(values[size * targets[i] / 100]);
|
85
|
+
}
|
86
|
+
|
87
|
+
last = (Double[]) percentiles.toArray(new Double[]{});
|
88
|
+
return last;
|
89
|
+
}
|
90
|
+
|
91
|
+
public void clear() {
|
92
|
+
valueList = null;
|
93
|
+
}
|
94
|
+
}
|
Binary file
|
@@ -0,0 +1,53 @@
|
|
1
|
+
package is.tagomor.norikra.udf;
|
2
|
+
|
3
|
+
import com.espertech.esper.client.hook.AggregationFunctionFactory;
|
4
|
+
import com.espertech.esper.epl.agg.service.AggregationValidationContext;
|
5
|
+
import com.espertech.esper.epl.agg.aggregator.AggregationMethod;
|
6
|
+
|
7
|
+
// import java.util.Map;
|
8
|
+
|
9
|
+
public class PercentilesFactory implements AggregationFunctionFactory {
|
10
|
+
public void setFunctionName(String functionName) {
|
11
|
+
// no action taken
|
12
|
+
}
|
13
|
+
|
14
|
+
/*
|
15
|
+
percentiles(field_name, {percentile_specifications_array}[, samples])
|
16
|
+
ex: percentiles(response_time, {50,90,95,98,99})
|
17
|
+
*/
|
18
|
+
public void validate(AggregationValidationContext validationContext) {
|
19
|
+
if (validationContext.getParameterTypes().length != 2)
|
20
|
+
throw new IllegalArgumentException("percentiles() accepts 2 arguments (fieldname,percentiles)");
|
21
|
+
|
22
|
+
Class first = validationContext.getParameterTypes()[0];
|
23
|
+
if (! (first == int.class || first == long.class || first == double.class || first == float.class ||
|
24
|
+
first == Integer.class || first == Long.class || first == Double.class || first == Float.class ||
|
25
|
+
first == String.class))
|
26
|
+
throw new IllegalArgumentException("percentiles() first argument must be string or number, but " + first.toString());
|
27
|
+
|
28
|
+
Class second = validationContext.getParameterTypes()[1];
|
29
|
+
boolean f_second = validationContext.getIsConstantValue()[1];
|
30
|
+
if (second != Integer[].class || !f_second)
|
31
|
+
throw new IllegalArgumentException("percentiles() second argument must be Constant Array of Integer");
|
32
|
+
|
33
|
+
if (validationContext.isDistinct())
|
34
|
+
throw new IllegalArgumentException("percentiles() doesn't permit DISTINCT modifier");
|
35
|
+
}
|
36
|
+
|
37
|
+
/*
|
38
|
+
In order for the engine to validate the type returned by the aggregation function against
|
39
|
+
the types expected by enclosing expressions, the getValueType must return the result type
|
40
|
+
of any values produced by the aggregation function:
|
41
|
+
*/
|
42
|
+
public Class getValueType() {
|
43
|
+
return Double[].class;
|
44
|
+
}
|
45
|
+
|
46
|
+
/*
|
47
|
+
Finally the factory implementation must provide a newAggregator method that returns instances
|
48
|
+
of AggregationMethod. The engine invokes this method for each new aggregation state to be allocated.
|
49
|
+
*/
|
50
|
+
public AggregationMethod newAggregator() {
|
51
|
+
return new Percentiles();
|
52
|
+
}
|
53
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'norikra/udf'
|
2
|
+
|
3
|
+
module Norikra
|
4
|
+
module UDF
|
5
|
+
class Percentile < Norikra::UDF::AggregationSingle
|
6
|
+
def self.init
|
7
|
+
require 'norikra-udf-percentile.jar'
|
8
|
+
end
|
9
|
+
def definition
|
10
|
+
["percentile", "is.tagomor.norikra.udf.PercentileFactory"]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Percentiles < Norikra::UDF::AggregationSingle
|
15
|
+
def self.init
|
16
|
+
require 'norikra-udf-percentile.jar'
|
17
|
+
end
|
18
|
+
def definition
|
19
|
+
["percentiles", "is.tagomor.norikra.udf.PercentilesFactory"]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "norikra-udf-percentile"
|
5
|
+
spec.version = "0.0.1"
|
6
|
+
spec.authors = ["TAGOMORI Satoshi"]
|
7
|
+
spec.email = ["tagomoris@gmail.com"]
|
8
|
+
spec.description = %q{This plugin adds functions named percentile/percentiles, which calculate percentile for specified fields}
|
9
|
+
spec.summary = %q{Norikra UDF percentile() and percentiles()}
|
10
|
+
spec.homepage = "https://github.com/tagomoris/norikra-udf-percentile"
|
11
|
+
spec.license = "GPLv2"
|
12
|
+
spec.platform = "java"
|
13
|
+
|
14
|
+
spec.files = `git ls-files`.split($/)
|
15
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
16
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
17
|
+
spec.require_paths = ["lib", "jar"]
|
18
|
+
|
19
|
+
spec.add_runtime_dependency "norikra", ">= 0.0.9"
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'norikra/udf_spec_helper'
|
2
|
+
|
3
|
+
include Norikra::UDFSpecHelper
|
4
|
+
|
5
|
+
require 'norikra/udf/percentile'
|
6
|
+
|
7
|
+
describe Norikra::UDF::Percentile do
|
8
|
+
f = udf_function(
|
9
|
+
Norikra::UDF::Percentile,
|
10
|
+
:valueType => java.lang.Double,
|
11
|
+
:parameters => [
|
12
|
+
[java.lang.String, false],
|
13
|
+
[java.lang.Integer, true, 50],
|
14
|
+
]
|
15
|
+
)
|
16
|
+
|
17
|
+
it 'returns Double values' do
|
18
|
+
expect(f.getValueType).to eql(java.lang.Double.java_class)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'returns 9 values as percentiles, and reflect for leve()' do
|
22
|
+
(0...100).each do |i|
|
23
|
+
f._call(:enter, [i.to_s, 50.to_java(:Integer)].to_java)
|
24
|
+
end
|
25
|
+
|
26
|
+
r = f.getValue
|
27
|
+
expect(r).to eql(50.0)
|
28
|
+
|
29
|
+
(0...50).each do |i|
|
30
|
+
f._call(:leave, [i.to_s, 50.to_java(:Integer)].to_java)
|
31
|
+
end
|
32
|
+
|
33
|
+
expect(f.instance_eval{ @func.valueListSize }).to eql(50)
|
34
|
+
|
35
|
+
r = f.getValue
|
36
|
+
expect(r).to eql(75.0)
|
37
|
+
end
|
38
|
+
|
39
|
+
f2 = udf_function(
|
40
|
+
Norikra::UDF::Percentile,
|
41
|
+
:valueType => java.lang.Double,
|
42
|
+
:parameters => [
|
43
|
+
[java.lang.Integer, false],
|
44
|
+
[java.lang.Integer, true, 90],
|
45
|
+
]
|
46
|
+
)
|
47
|
+
it 'returns 5 values as percentiles, and returns same value after all values leaving' do
|
48
|
+
(0...2000).to_a.shuffle.each do |i|
|
49
|
+
f2._call(:enter, [i, 90.to_java(:Integer)].to_java)
|
50
|
+
end
|
51
|
+
|
52
|
+
expect(f2.instance_eval{ @func.valueListSize }).to eql(2000)
|
53
|
+
|
54
|
+
r = f2.getValue
|
55
|
+
expect(r).to eql(1800.0)
|
56
|
+
|
57
|
+
(0...2000).to_a.shuffle.each do |i|
|
58
|
+
f2._call(:leave, [i, 90.to_java(:Integer)].to_java)
|
59
|
+
end
|
60
|
+
|
61
|
+
r2 = f2.getValue
|
62
|
+
expect(r2).to eql(r)
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'norikra/udf_spec_helper'
|
2
|
+
|
3
|
+
include Norikra::UDFSpecHelper
|
4
|
+
|
5
|
+
require 'norikra/udf/percentile'
|
6
|
+
|
7
|
+
describe Norikra::UDF::Percentiles do
|
8
|
+
f = udf_function(
|
9
|
+
Norikra::UDF::Percentiles,
|
10
|
+
:valueType => java.lang.Double[],
|
11
|
+
:parameters => [
|
12
|
+
[java.lang.String, false],
|
13
|
+
[java.lang.Integer[], true, [10,20,30,40,50,60,70,80,90].to_java(:Integer)].to_java,
|
14
|
+
]
|
15
|
+
)
|
16
|
+
|
17
|
+
it 'returns Double[] values' do
|
18
|
+
expect(f.getValueType).to eql(java.lang.Double[].java_class)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'returns 9 values as percentiles, and reflect for leve()' do
|
22
|
+
(0...100).each do |i|
|
23
|
+
f._call(:enter, [i.to_s, [10,20,30,40,50,60,70,80,90].to_java(:Integer)].to_java)
|
24
|
+
end
|
25
|
+
|
26
|
+
r = f.getValue
|
27
|
+
expect(r.size).to eql(9)
|
28
|
+
expect(r[0]).to eql(10.0)
|
29
|
+
expect(r[1]).to eql(20.0)
|
30
|
+
expect(r[2]).to eql(30.0)
|
31
|
+
expect(r[3]).to eql(40.0)
|
32
|
+
expect(r[4]).to eql(50.0)
|
33
|
+
expect(r[5]).to eql(60.0)
|
34
|
+
expect(r[6]).to eql(70.0)
|
35
|
+
expect(r[7]).to eql(80.0)
|
36
|
+
expect(r[8]).to eql(90.0)
|
37
|
+
|
38
|
+
(0...50).each do |i|
|
39
|
+
f._call(:leave, [i.to_s, [10,20,30,40,50,60,70,80,90].to_java(:Integer)].to_java)
|
40
|
+
end
|
41
|
+
|
42
|
+
expect(f.instance_eval{ @func.valueListSize }).to eql(50)
|
43
|
+
|
44
|
+
r = f.getValue
|
45
|
+
expect(r.size).to eql(9)
|
46
|
+
expect(r[0]).to eql(55.0)
|
47
|
+
expect(r[1]).to eql(60.0)
|
48
|
+
expect(r[2]).to eql(65.0)
|
49
|
+
expect(r[3]).to eql(70.0)
|
50
|
+
expect(r[4]).to eql(75.0)
|
51
|
+
expect(r[5]).to eql(80.0)
|
52
|
+
expect(r[6]).to eql(85.0)
|
53
|
+
expect(r[7]).to eql(90.0)
|
54
|
+
expect(r[8]).to eql(95.0)
|
55
|
+
end
|
56
|
+
|
57
|
+
f2 = udf_function(
|
58
|
+
Norikra::UDF::Percentiles,
|
59
|
+
:valueType => java.lang.Double[],
|
60
|
+
:parameters => [
|
61
|
+
[java.lang.Integer, false],
|
62
|
+
[java.lang.Integer[], true, [50,90,95,98,99].to_java(:Integer)].to_java,
|
63
|
+
]
|
64
|
+
)
|
65
|
+
it 'returns 5 values as percentiles, and returns same value after all values leaving' do
|
66
|
+
(0...2000).to_a.shuffle.each do |i|
|
67
|
+
f2._call(:enter, [i, [50,90,95,98,99].to_java(:Integer), 100].to_java)
|
68
|
+
end
|
69
|
+
|
70
|
+
expect(f2.instance_eval{ @func.valueListSize }).to eql(2000)
|
71
|
+
|
72
|
+
r = f2.getValue
|
73
|
+
expect(r.size).to eql(5)
|
74
|
+
|
75
|
+
(0...2000).to_a.shuffle.each do |i|
|
76
|
+
f2._call(:leave, [i, [50,90,95,98,99].to_java(:Integer), 100].to_java)
|
77
|
+
end
|
78
|
+
|
79
|
+
r2 = f2.getValue
|
80
|
+
expect(r2).to eql(r)
|
81
|
+
end
|
82
|
+
end
|
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: norikra-udf-percentile
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: java
|
7
|
+
authors:
|
8
|
+
- TAGOMORI Satoshi
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-08-20 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: norikra
|
16
|
+
version_requirements: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - '>='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 0.0.9
|
21
|
+
none: false
|
22
|
+
requirement: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.0.9
|
27
|
+
none: false
|
28
|
+
prerelease: false
|
29
|
+
type: :runtime
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
version_requirements: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - ~>
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '1.3'
|
37
|
+
none: false
|
38
|
+
requirement: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ~>
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '1.3'
|
43
|
+
none: false
|
44
|
+
prerelease: false
|
45
|
+
type: :development
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
version_requirements: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
none: false
|
54
|
+
requirement: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
none: false
|
60
|
+
prerelease: false
|
61
|
+
type: :development
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
none: false
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
none: false
|
76
|
+
prerelease: false
|
77
|
+
type: :development
|
78
|
+
description: This plugin adds functions named percentile/percentiles, which calculate percentile for specified fields
|
79
|
+
email:
|
80
|
+
- tagomoris@gmail.com
|
81
|
+
executables: []
|
82
|
+
extensions: []
|
83
|
+
extra_rdoc_files: []
|
84
|
+
files:
|
85
|
+
- .gitignore
|
86
|
+
- .ruby-version
|
87
|
+
- Gemfile
|
88
|
+
- README.md
|
89
|
+
- Rakefile
|
90
|
+
- jar/norikra-udf-percentile.jar
|
91
|
+
- java/is/tagomor/norikra/udf/Percentile.class
|
92
|
+
- java/is/tagomor/norikra/udf/Percentile.java
|
93
|
+
- java/is/tagomor/norikra/udf/PercentileFactory.class
|
94
|
+
- java/is/tagomor/norikra/udf/PercentileFactory.java
|
95
|
+
- java/is/tagomor/norikra/udf/Percentiles.class
|
96
|
+
- java/is/tagomor/norikra/udf/Percentiles.java
|
97
|
+
- java/is/tagomor/norikra/udf/PercentilesFactory.class
|
98
|
+
- java/is/tagomor/norikra/udf/PercentilesFactory.java
|
99
|
+
- lib/norikra/udf/percentile.rb
|
100
|
+
- norikra-udf-percentile.gemspec
|
101
|
+
- spec/percentile_spec.rb
|
102
|
+
- spec/percentiles_spec.rb
|
103
|
+
homepage: https://github.com/tagomoris/norikra-udf-percentile
|
104
|
+
licenses:
|
105
|
+
- GPLv2
|
106
|
+
post_install_message:
|
107
|
+
rdoc_options: []
|
108
|
+
require_paths:
|
109
|
+
- lib
|
110
|
+
- jar
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - '>='
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
none: false
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - '>='
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
none: false
|
123
|
+
requirements: []
|
124
|
+
rubyforge_project:
|
125
|
+
rubygems_version: 1.8.24
|
126
|
+
signing_key:
|
127
|
+
specification_version: 3
|
128
|
+
summary: Norikra UDF percentile() and percentiles()
|
129
|
+
test_files:
|
130
|
+
- spec/percentile_spec.rb
|
131
|
+
- spec/percentiles_spec.rb
|