pcbr 0.3.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (10) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +21 -0
  3. data/lib/pcbr.rb +16 -31
  4. data/pcbr.gemspec +11 -12
  5. metadata +16 -46
  6. data/.rspec +0 -1
  7. data/Gemfile +0 -3
  8. data/README.md +0 -29
  9. data/Rakefile +0 -8
  10. data/spec/_spec.rb +0 -172
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2ce39501eee28e4881d896c138a0049899912b8a
4
- data.tar.gz: 68060e95d3921de4b105fd48227fc776d93ff744
3
+ metadata.gz: 479e8f9785c73a1569d807a1f311599f1285df24
4
+ data.tar.gz: 59569e2a2ac7eeeed617655e351fd3ea07743908
5
5
  SHA512:
6
- metadata.gz: b7c3edd47fd4012722dffd750833187b5951943543aca19b3b507409f787f5ec60ea1e08adb337967770a9d4494ec8e0cc7d18337a0ae68230f0b42f226101be
7
- data.tar.gz: 93051d2392065a23d4cb2918c79771e11cb08a1c6df7a13489f6bc58fe2284beb5410b850eec86251f94eed3f28e015664c3bf9d93ea1e073965fcafd160003a
6
+ metadata.gz: 280c5a469bb446ec87f1fbc47e47cf77f4325e9c1162b6d4836c79f370d472dc99c71169fd0c58cecffbcf302cc583c8605dc163088b383f19b826bd0c33b62e
7
+ data.tar.gz: 5a8b362448c8d3276ea54257ead0c2fbdd8337c0ae3e1a48e5bc78acae17002f479ba63db68d025749bdad4f51c402f3401e71dfdc5bb74617be724b61f100cb
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Victor Maslov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/lib/pcbr.rb CHANGED
@@ -1,8 +1,4 @@
1
- require "deep_dup"
2
-
3
1
  module PCBR
4
- VERSION = "0.3.0"
5
-
6
2
  class Error < RuntimeError
7
3
  # def initialize body
8
4
  # super "#{Module.nesting[1]} error: #{body}"
@@ -13,37 +9,35 @@ module PCBR
13
9
  Storage.new &block
14
10
  end
15
11
 
16
- ARRAY_101 = [0, 0, 0]
17
12
  class Storage
18
13
  attr_reader :table
14
+ attr_reader :set
15
+ @@default_lambda = lambda do |a_, b_|
16
+ raise Error.new "comparison vectors are of the different length" unless a_.size == b_.size
17
+ tt = [0, 0, 0]
18
+ [*a_].zip([*b_]) do |a, b|
19
+ t = a <=> b and tt[t] = t
20
+ end
21
+ tt[0] + tt[1] + tt[2]
22
+ end
19
23
 
20
24
  def initialize &block
25
+ require "set"
26
+ @set = ::Set.new
21
27
  @table = []
22
- @callback = block || lambda{ |a_, b_|
23
- ARRAY_101.dup.tap do |array|
24
- [*a_].zip([*b_]) do |a, b|
25
- t = a <=> b and array[t] = t
26
- end
27
- end.inject :+
28
- }
28
+ @callback = block || @@default_lambda
29
29
  end
30
30
 
31
31
  def store key, vector = nil
32
- raise Error.new "duplicating key" if @table.assoc key
33
- key = DeepDup.deep_dup key
34
- vector = if vector
35
- DeepDup.deep_dup vector
36
- else
37
- Array key
38
- end
32
+ raise Error.new "duplicating key" if @set.include? key
33
+ vector = Array key if vector.nil?
39
34
  score = 0
40
35
  @table.each do |item|
41
- # TODO test of this exception
42
- raise Error.new "comparison vectors are of the different length" unless vector.size == item[1].size
43
36
  point = @callback.call vector, item[1]
44
- score += point
45
37
  item[2] -= point
38
+ score += point
46
39
  end
40
+ @set.add key
47
41
  @table.push [key, vector, score]
48
42
  end
49
43
 
@@ -56,14 +50,5 @@ module PCBR
56
50
  @table.sort_by.with_index{ |item, i| [-item[2], i] }.map(&:first)
57
51
  end
58
52
 
59
- # def quality
60
- # factorial = ->x{ (1..x).inject(:*) }
61
- # (2...@table.size).each do |sublength|
62
- # combinations = factorial[@table.size] / factorial[sublength] / factorial[@table.size - sublength]
63
- # comparisons = sublength * (sublength - 1) / 2
64
- # p [sublength, combinations, comparisons, combinations * comparisons]
65
- # end
66
- # end
67
-
68
53
  end
69
54
  end
data/pcbr.gemspec CHANGED
@@ -1,20 +1,19 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "pcbr"
3
- spec.version = (require_relative "lib/pcbr"; PCBR::VERSION)
3
+ spec.version = "0.5.0"
4
+ spec.summary = "Pair Comparison Based Rating"
5
+
4
6
  spec.author = "Victor Maslov"
5
7
  spec.email = "nakilon@gmail.com"
6
- spec.summary = "Pair Comparison Based Rating"
7
- spec.description = "Making ratings is fun. After applying my method several times I've decided to gemify it."
8
- spec.homepage = "https://github.com/Nakilon/pcbr"
9
8
  spec.license = "MIT"
9
+ spec.metadata = {"source_code_uri" => "https://github.com/nakilon/pcbr"}
10
+ spec.description = <<-EOF
11
+ Making ratings is fun. After applying my method several times I've decided to gemify it.
12
+ This is one of the first gems I made so it's far for being nicely done.
13
+ EOF
10
14
 
11
- spec.files = `git ls-files -z`.split("\x0")
12
- spec.test_files = ["spec/"]
13
-
14
- spec.add_dependency "deep_dup"
15
-
16
- spec.add_development_dependency "bundler"
17
- spec.add_development_dependency "rspec", "~> 3.3.0"
15
+ spec.required_ruby_version = ">=2"
16
+ spec.add_development_dependency "minitest"
18
17
 
19
- spec.required_ruby_version = ">= 2.0.0"
18
+ spec.files = %w{ LICENSE pcbr.gemspec lib/pcbr.rb }
20
19
  end
metadata CHANGED
@@ -1,92 +1,62 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pcbr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Maslov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-06 00:00:00.000000000 Z
11
+ date: 2021-08-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: deep_dup
14
+ name: minitest
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - '>='
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: bundler
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - '>='
17
+ - - ">="
32
18
  - !ruby/object:Gem::Version
33
19
  version: '0'
34
20
  type: :development
35
21
  prerelease: false
36
22
  version_requirements: !ruby/object:Gem::Requirement
37
23
  requirements:
38
- - - '>='
24
+ - - ">="
39
25
  - !ruby/object:Gem::Version
40
26
  version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: rspec
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ~>
46
- - !ruby/object:Gem::Version
47
- version: 3.3.0
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ~>
53
- - !ruby/object:Gem::Version
54
- version: 3.3.0
55
- description: Making ratings is fun. After applying my method several times I've decided
56
- to gemify it.
27
+ description: |2
28
+ Making ratings is fun. After applying my method several times I've decided to gemify it.
29
+ This is one of the first gems I made so it's far for being nicely done.
57
30
  email: nakilon@gmail.com
58
31
  executables: []
59
32
  extensions: []
60
33
  extra_rdoc_files: []
61
34
  files:
62
- - .rspec
63
- - Gemfile
64
- - README.md
65
- - Rakefile
35
+ - LICENSE
66
36
  - lib/pcbr.rb
67
37
  - pcbr.gemspec
68
- - spec/_spec.rb
69
- homepage: https://github.com/Nakilon/pcbr
38
+ homepage:
70
39
  licenses:
71
40
  - MIT
72
- metadata: {}
41
+ metadata:
42
+ source_code_uri: https://github.com/nakilon/pcbr
73
43
  post_install_message:
74
44
  rdoc_options: []
75
45
  require_paths:
76
46
  - lib
77
47
  required_ruby_version: !ruby/object:Gem::Requirement
78
48
  requirements:
79
- - - '>='
49
+ - - ">="
80
50
  - !ruby/object:Gem::Version
81
- version: 2.0.0
51
+ version: '2'
82
52
  required_rubygems_version: !ruby/object:Gem::Requirement
83
53
  requirements:
84
- - - '>='
54
+ - - ">="
85
55
  - !ruby/object:Gem::Version
86
56
  version: '0'
87
57
  requirements: []
88
58
  rubyforge_project:
89
- rubygems_version: 2.0.14.1
59
+ rubygems_version: 2.5.2.3
90
60
  signing_key:
91
61
  specification_version: 4
92
62
  summary: Pair Comparison Based Rating
data/.rspec DELETED
@@ -1 +0,0 @@
1
- --color
data/Gemfile DELETED
@@ -1,3 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gemspec
data/README.md DELETED
@@ -1,29 +0,0 @@
1
- # PCBR (Pairs Comparison Based Rating)
2
-
3
- Making ratings is fun. After applying my method several times I've decided to gemify it.
4
-
5
- ### Examples
6
-
7
- See [`describe "examples" do` in specs](spec/_spec.rb).
8
-
9
- ### How it works
10
-
11
- The first idea of rating items by one-to-one comparison was about QuakeLive players in 2013 or so and it didn't work well. At that time I was thinking about tree data structure. Later in May 2015 I've realised that it's really about dots in n-dimensional space and sectors. Applying it to Reddit RSS made my feed 50% more interesting.
12
-
13
- TODO: describe/illustrate algorithm?
14
-
15
- ~~At the moment it's a "proof of concept" -- it needs huge optimisations for lookups, maybe using trees.~~
16
-
17
- It worked fine in production for a project with huge computations where you can't find the best solution but have to find anything good in adequate time. Traversing the tree using this with a vector of `[leaf's quality, depth]` made things better than depth-first search with lots of ueristics.
18
-
19
- ### Installation
20
-
21
- $ gem install pcbr
22
-
23
- ### Testing with RSpec before contributing
24
-
25
- rspec
26
-
27
- or
28
-
29
- rake spec
data/Rakefile DELETED
@@ -1,8 +0,0 @@
1
- require "bundler/gem_tasks"
2
-
3
- task :default => %w{ spec }
4
-
5
- require "rspec/core/rake_task"
6
- RSpec::Core::RakeTask.new(:spec) do |t|
7
- t.verbose = false
8
- end
data/spec/_spec.rb DELETED
@@ -1,172 +0,0 @@
1
- require_relative "../lib/pcbr"
2
-
3
-
4
- require "pp"
5
-
6
-
7
- describe "basic specs" do
8
-
9
- example "scalar key without vector and without &block" do
10
- rating = PCBR.new
11
- rating.store 1
12
- rating.store 2
13
- expect(rating.sorted).to eq([2, 1])
14
- end
15
-
16
- # example "#size" do
17
- # rating = PCBR.new
18
- # rating.store 1
19
- # rating.store 2
20
- # expect(rating.size).to eq(2)
21
- # end
22
-
23
- example "Nil elements in vector are ignored" do
24
- rating = PCBR.new
25
- rating.store 1, [1, nil]
26
- rating.store 2, [2, nil]
27
- rating.store 3, [nil, 3]
28
- rating.store 4, [nil, 4]
29
- expect(rating.sorted).to eq([2, 4, 1, 3])
30
- end
31
-
32
- example "&block" do
33
- n = 0
34
- rating = PCBR.new do |a, b|
35
- n += 1
36
- a <=> b
37
- end
38
- rating.store 1
39
- rating.store 2
40
- rating.store 3
41
- rating.store 4
42
- expect(rating.sorted).to eq([4, 3, 2, 1])
43
- expect(n).to eq(6)
44
- end
45
-
46
- example "#sorted and #score[key]" do
47
- rating = PCBR.new
48
- table = [
49
- [1, [1, 1], -1],
50
- [2, [2, 2], 5],
51
- [3, [0, 0], -5],
52
- [4, [1, 2], 3],
53
- [6, [1, 1], -1],
54
- [5, [0, 2], -1],
55
- ].each do |key, vector, |
56
- rating.store key, vector
57
- end
58
- expect(rating.sorted).to eq([2, 4, 1, 6, 5, 3])
59
- expect(rating.table.map{ |i| i[2] }.inject(:+)).to be_zero
60
- table.each do |key, _, score|
61
- expect(rating.score(key)).to eq(score)
62
- end
63
- expect(rating.table).to eq(table)
64
- end
65
-
66
- # example "quality estimation" do
67
- # rating = PCBR.new
68
- # table = [
69
- # [1, [1, 1]],
70
- # [2, [2, 2]],
71
- # [3, [0, 0]],
72
- # [4, [1, 2]],
73
- # [6, [1, 1]],
74
- # [5, [0, 2]],
75
- # ].each do |key, vector, |
76
- # rating.store key, vector
77
- # end
78
- # end
79
-
80
- example "duplicating keys are forbidden" do
81
- rating = PCBR.new
82
- rating.store 0
83
- expect{ rating.store 0 }.to raise_error PCBR::Error
84
- end
85
-
86
- example "keys and vectors are dupped" do
87
- rating = PCBR.new
88
- a = [[1]]
89
- v = [0]
90
- rating.store a, v
91
- a[0][0] = 2
92
- rating.store [[2]], [1] # expect no PCBR::Error
93
- v[0] = 3
94
- rating.store [[3]], [2]
95
- expect(rating.sorted).to eq [[[3]], [[2]], [[1]]]
96
- end
97
-
98
- end
99
-
100
-
101
- describe "examples" do
102
-
103
- example "github repos" do
104
- repos = {
105
- # Image Processing Library
106
- "IPL: ImageMagick/ImageMagick" => {issue: 36, pr: 0, watch: 29, star: 375, fork: 89},
107
- "IPL: jcupitt/libvips" => {issue: 32, pr: 1, watch: 43, star: 753, fork: 72},
108
- # Packet Manager
109
- "PM: Homebrew/brew" => {issue: 14, pr: 13, watch: 61, star: 1207, fork: 345},
110
- "PM: Linuxbrew/brew" => {issue: 21, pr: 2, watch: 5, star: 52, fork: 345},
111
- # one gem depending on another one
112
- "gem: dblock/slack-ruby-bot" => {issue: 15, pr: 0, watch: 13, star: 251, fork: 55},
113
- "gem: dblock/slack-ruby-client" => {issue: 22, pr: 2, watch: 4, star: 206, fork: 37},
114
- # Programming Language
115
- "PL: crystal-lang/crystal" => {issue: 267, pr: 44, watch: 255, star: 4952, fork: 412},
116
- "PL: elixir-lang/elixir" => {issue: 21, pr: 1, watch: 518, star: 7029, fork: 975},
117
- "PL: golang/go" => {issue: 2293, pr: 1, watch: 1521, star: 17067, fork: 2147},
118
- "PL: racket/racket" => {issue: 33, pr: 53, watch: 124, star: 1455, fork: 301},
119
- "PL: rust-lang/rust" => {issue: 2411, pr: 119, watch: 1012, star: 16790, fork: 3200},
120
- # Ruby Web Framework
121
- "RWF: padrino/padrino-framework" => {issue: 44, pr: 2, watch: 137, star: 2782, fork: 454},
122
- "RWF: sinatra/sinatra" => {issue: 12, pr: 11, watch: 377, star: 7892, fork: 1467},
123
- # Ruby Version Manager
124
- "RVM: rbenv/rbenv" => {issue: 24, pr: 12, watch: 301, star: 8257, fork: 769},
125
- "RVM: rvm/rvm" => {issue: 160, pr: 5, watch: 154, star: 3328, fork: 793},
126
- # DevOps Tool
127
- "DOT: ansible/ansible" => {issue: 1074, pr: 322, watch: 1339, star: 16926, fork: 5075},
128
- "DOT: chef/chef" => {issue: 422, pr: 52, watch: 387, star: 4265, fork: 1774},
129
- "DOT: capistrano/capistrano" => {issue: 38, pr: 6, watch: 339, star: 8392, fork: 1365},
130
- }
131
-
132
- create_rating = lambda do |&callback|
133
- PCBR.new.tap do |rating|
134
- repos.each do |repo_name, repo_stats|
135
- rating.store repo_name, callback[repo_stats, repo_name]
136
- end
137
- end
138
- end
139
-
140
- contribution_intensivity_rating = create_rating.call do |repo_stats| [
141
- repo_stats[:pr],
142
- -repo_stats[:fork],
143
- ] end
144
-
145
- quality_rating = create_rating.call do |repo_stats| [
146
- repo_stats[:star],
147
- -repo_stats[:issue],
148
- ] end
149
-
150
- resulting_rating = create_rating.call do |repo_stats, repo_name| [
151
- contribution_intensivity_rating.score(repo_name),
152
- quality_rating.score(repo_name),
153
- ] end
154
-
155
- aggregate_failures do
156
- expect(
157
- resulting_rating.sorted.map(&:split).group_by(&:first).each do |category, group|
158
- group.map! &:last
159
- end.to_a
160
- ).to eq( [
161
- ["PM:", %w{ Homebrew/brew Linuxbrew/brew }],
162
- ["RVM:", %w{ rbenv/rbenv rvm/rvm }],
163
- ["PL:", %w{ racket/racket crystal-lang/crystal elixir-lang/elixir rust-lang/rust golang/go }],
164
- ["DOT:", %w{ ansible/ansible capistrano/capistrano chef/chef }],
165
- ["RWF:", %w{ sinatra/sinatra padrino/padrino-framework }],
166
- ["gem:", %w{ dblock/slack-ruby-bot dblock/slack-ruby-client }],
167
- ["IPL:", %w{ jcupitt/libvips ImageMagick/ImageMagick }],
168
- ] )
169
- end
170
- end
171
-
172
- end