zold-score 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/.0pdd.yml +9 -0
- data/.gitattributes +9 -0
- data/.gitignore +7 -0
- data/.pdd +7 -0
- data/.rubocop.yml +16 -0
- data/.rultor.yml +26 -0
- data/.simplecov +40 -0
- data/.travis.yml +17 -0
- data/Gemfile +24 -0
- data/LICENSE.txt +21 -0
- data/README.md +36 -0
- data/Rakefile +71 -0
- data/appveyor.yml +38 -0
- data/lib/zold/score.rb +239 -0
- data/test/zold/test_score.rb +160 -0
- data/zold-score.gemspec +48 -0
- metadata +147 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5ad77bc5ced6810f6d1e26f8032844499b395b3df3ad4cf385e2c07803e7c98f
|
4
|
+
data.tar.gz: f5e373d1aa2886380bd3e524b5fc3d504a12dba36892099f1d414ed6962e4229
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2927a86ebcd00fd33d404cfd6fad6a4a18cc2a9de0cfbea8b45f57a18c6b3b8c75c1fbcde32dbe37d6ad4fd7ca0f40f35657e8d709acd909336caa4ff23a99e1
|
7
|
+
data.tar.gz: 2a9194e4d45ef64ea965434ec2a6cc43879add8d4c939a963bdfb04ed05e780ad7d84f0b42083458413baae0c622854b793552691ad03727f54b476a6e1e2e33
|
data/.0pdd.yml
ADDED
data/.gitattributes
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# Check out all text files in UNIX format, with LF as end of line
|
2
|
+
# Don't change this file. If you have any ideas about it, please
|
3
|
+
# submit a separate issue about it and we'll discuss.
|
4
|
+
|
5
|
+
* text=auto eol=lf
|
6
|
+
*.rb ident
|
7
|
+
*.xml ident
|
8
|
+
*.png binary
|
9
|
+
*.pdf binary
|
data/.gitignore
ADDED
data/.pdd
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
AllCops:
|
2
|
+
DisplayCopNames: true
|
3
|
+
TargetRubyVersion: 2.3.3
|
4
|
+
|
5
|
+
Metrics/LineLength:
|
6
|
+
Max: 120
|
7
|
+
Metrics/AbcSize:
|
8
|
+
Max: 25
|
9
|
+
Metrics/MethodLength:
|
10
|
+
Max: 25
|
11
|
+
Metrics/ClassLength:
|
12
|
+
Max: 150
|
13
|
+
Metrics/ParameterLists:
|
14
|
+
Max: 7
|
15
|
+
Layout/AlignParameters:
|
16
|
+
Enabled: false
|
data/.rultor.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
assets:
|
2
|
+
rubygems.yml: zerocracy/home#assets/rubygems.yml
|
3
|
+
install: |-
|
4
|
+
export GEM_HOME=~/.ruby
|
5
|
+
export GEM_PATH=$GEM_HOME:$GEM_PATH
|
6
|
+
release:
|
7
|
+
script: |-
|
8
|
+
bundle install
|
9
|
+
rake
|
10
|
+
rm -rf *.gem
|
11
|
+
sed -i "s/0\.0\.0/${tag}/g" zold-score.gemspec
|
12
|
+
git add zold-score.gemspec
|
13
|
+
git commit -m "Version set to ${tag}"
|
14
|
+
gem build zold-score.gemspec
|
15
|
+
chmod 0600 ../rubygems.yml
|
16
|
+
gem push *.gem --config-file ../rubygems.yml
|
17
|
+
commanders:
|
18
|
+
- yegor256
|
19
|
+
architect:
|
20
|
+
- yegor256
|
21
|
+
merge:
|
22
|
+
commanders: []
|
23
|
+
script: |-
|
24
|
+
bundle install
|
25
|
+
rake
|
26
|
+
deploy: {}
|
data/.simplecov
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# Copyright (c) 2018 Yegor Bugayenko
|
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 NONINFINGEMENT. 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.
|
22
|
+
|
23
|
+
if Gem.win_platform? then
|
24
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
25
|
+
SimpleCov::Formatter::HTMLFormatter
|
26
|
+
]
|
27
|
+
SimpleCov.start do
|
28
|
+
add_filter "/test/"
|
29
|
+
add_filter "/features/"
|
30
|
+
end
|
31
|
+
else
|
32
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
|
33
|
+
[SimpleCov::Formatter::HTMLFormatter]
|
34
|
+
)
|
35
|
+
SimpleCov.start do
|
36
|
+
add_filter "/test/"
|
37
|
+
add_filter "/features/"
|
38
|
+
# minimum_coverage 30
|
39
|
+
end
|
40
|
+
end
|
data/.travis.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.3.1
|
4
|
+
- 2.3.3
|
5
|
+
cache: bundler
|
6
|
+
branches:
|
7
|
+
only:
|
8
|
+
- master
|
9
|
+
install:
|
10
|
+
- travis_retry bundle update
|
11
|
+
- gem install pdd
|
12
|
+
script:
|
13
|
+
- pdd -f /dev/null
|
14
|
+
- export RUBYOPT="-W0"
|
15
|
+
- rake --quiet
|
16
|
+
after_success:
|
17
|
+
- "bash <(curl -s https://codecov.io/bash)"
|
data/Gemfile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Yegor Bugayenko
|
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.
|
22
|
+
|
23
|
+
source 'https://rubygems.org'
|
24
|
+
gemspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Yegor Bugayenko
|
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/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
<img src="http://www.zold.io/logo.svg" width="92px" height="92px"/>
|
2
|
+
|
3
|
+
[![Donate via Zerocracy](https://www.0crat.com/contrib-badge/CAZPZR9FS.svg)](https://www.0crat.com/contrib/CAZPZR9FS)
|
4
|
+
|
5
|
+
[![EO principles respected here](http://www.elegantobjects.org/badge.svg)](http://www.elegantobjects.org)
|
6
|
+
[![Managed by Zerocracy](https://www.0crat.com/badge/CAZPZR9FS.svg)](https://www.0crat.com/p/CAZPZR9FS)
|
7
|
+
[![DevOps By Rultor.com](http://www.rultor.com/b/yegor256/zold)](http://www.rultor.com/p/yegor256/zold)
|
8
|
+
[![We recommend RubyMine](http://www.elegantobjects.org/rubymine.svg)](https://www.jetbrains.com/ruby/)
|
9
|
+
|
10
|
+
[![Build Status](https://travis-ci.org/zold-io/zold-score.svg)](https://travis-ci.org/zold-io/zold-score)
|
11
|
+
[![Build status](https://ci.appveyor.com/api/projects/status/f4ct91inx6nfb5eg?svg=true)](https://ci.appveyor.com/project/yegor256/zold-score)
|
12
|
+
[![PDD status](http://www.0pdd.com/svg?name=zold-io/zold-score)](http://www.0pdd.com/p?name=zold-io/zold-score)
|
13
|
+
[![Gem Version](https://badge.fury.io/rb/zold-score.svg)](http://badge.fury.io/rb/zold-score)
|
14
|
+
[![Test Coverage](https://img.shields.io/codecov/c/github/zold-io/zold-score.svg)](https://codecov.io/github/zold-io/zold-score?branch=master)
|
15
|
+
|
16
|
+
Here is the [White Paper](https://papers.zold.io/wp.pdf).
|
17
|
+
|
18
|
+
Join our [Telegram group](https://t.me/zold_io) to discuss it all live.
|
19
|
+
|
20
|
+
The license is [MIT](https://github.com/zold-io/zold-score/blob/master/LICENSE.txt).
|
21
|
+
|
22
|
+
This small Ruby Gem calculates the score for Zold nodes.
|
23
|
+
|
24
|
+
# How to contribute
|
25
|
+
|
26
|
+
Read [these guidelines](https://www.yegor256.com/2014/04/15/github-guidelines.html).
|
27
|
+
Make sure you build is green before you contribute
|
28
|
+
your pull request. You will need to have [Ruby](https://www.ruby-lang.org/en/) 2.3+ and
|
29
|
+
[Bundler](https://bundler.io/) installed. Then:
|
30
|
+
|
31
|
+
```
|
32
|
+
$ bundle update
|
33
|
+
$ rake
|
34
|
+
```
|
35
|
+
|
36
|
+
If it's clean and you don't see any error messages, submit your pull request.
|
data/Rakefile
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Yegor Bugayenko
|
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.
|
22
|
+
|
23
|
+
require 'rubygems'
|
24
|
+
require 'rake'
|
25
|
+
require 'rdoc'
|
26
|
+
require 'rake/clean'
|
27
|
+
|
28
|
+
def name
|
29
|
+
@name ||= File.basename(Dir['*.gemspec'].first, '.*')
|
30
|
+
end
|
31
|
+
|
32
|
+
def version
|
33
|
+
Gem::Specification.load(Dir['*.gemspec'].first).version
|
34
|
+
end
|
35
|
+
|
36
|
+
task default: %i[clean test rubocop copyright]
|
37
|
+
|
38
|
+
require 'rake/testtask'
|
39
|
+
desc 'Run all unit tests'
|
40
|
+
Rake::TestTask.new(:test) do |test|
|
41
|
+
ENV['TEST_QUIET_LOG'] = 'true' if ARGV.include?('--quiet')
|
42
|
+
Rake::Cleaner.cleanup_files(['coverage'])
|
43
|
+
test.libs << 'lib' << 'test'
|
44
|
+
test.pattern = 'test/**/test_*.rb'
|
45
|
+
test.verbose = true
|
46
|
+
test.warning = false
|
47
|
+
end
|
48
|
+
|
49
|
+
require 'rdoc/task'
|
50
|
+
desc 'Build RDoc documentation'
|
51
|
+
Rake::RDocTask.new do |rdoc|
|
52
|
+
rdoc.rdoc_dir = 'rdoc'
|
53
|
+
rdoc.title = "#{name} #{version}"
|
54
|
+
rdoc.rdoc_files.include('README*')
|
55
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
56
|
+
end
|
57
|
+
|
58
|
+
require 'rubocop/rake_task'
|
59
|
+
desc 'Run RuboCop on all directories'
|
60
|
+
RuboCop::RakeTask.new(:rubocop) do |task|
|
61
|
+
task.fail_on_error = true
|
62
|
+
task.requires << 'rubocop-rspec'
|
63
|
+
end
|
64
|
+
|
65
|
+
task :copyright do
|
66
|
+
sh "grep -q -r '#{Date.today.strftime('%Y')}' \
|
67
|
+
--include '*.rb' \
|
68
|
+
--include '*.txt' \
|
69
|
+
--include 'Rakefile' \
|
70
|
+
."
|
71
|
+
end
|
data/appveyor.yml
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
version: '{build}'
|
2
|
+
skip_tags: true
|
3
|
+
clone_depth: 10
|
4
|
+
branches:
|
5
|
+
only:
|
6
|
+
- master
|
7
|
+
except:
|
8
|
+
- gh-pages
|
9
|
+
os: Windows Server 2012
|
10
|
+
environment:
|
11
|
+
matrix:
|
12
|
+
- ruby_version: "23-x64"
|
13
|
+
- ruby_version: "24-x64"
|
14
|
+
- ruby_version: "25-x64"
|
15
|
+
install:
|
16
|
+
- ps: |
|
17
|
+
$Env:PATH = "C:\Ruby${Env:ruby_version}\bin;${Env:PATH}"
|
18
|
+
if ($Env:ruby_version -match "^23" ) {
|
19
|
+
# RubyInstaller; download OpenSSL headers from OpenKnapsack Project
|
20
|
+
$Env:openssl_dir = "C:\Ruby${Env:ruby_version}"
|
21
|
+
appveyor DownloadFile http://dl.bintray.com/oneclick/OpenKnapsack/x64/openssl-1.0.2j-x64-windows.tar.lzma
|
22
|
+
7z e openssl-1.0.2j-x64-windows.tar.lzma
|
23
|
+
7z x -y -oC:\Ruby${Env:ruby_version} openssl-1.0.2j-x64-windows.tar
|
24
|
+
} else {
|
25
|
+
# RubyInstaller2; openssl package seems to be installed already
|
26
|
+
$Env:openssl_dir = "C:\msys64\mingw64"
|
27
|
+
}
|
28
|
+
- bundle config --local path vendor/bundle
|
29
|
+
- bundle config build.openssl --with-openssl-dir=%openssl_dir%
|
30
|
+
- ruby -v
|
31
|
+
- bundle -v
|
32
|
+
build_script:
|
33
|
+
- bundle update
|
34
|
+
- bundle install
|
35
|
+
test_script:
|
36
|
+
- bundle exec rake --quiet
|
37
|
+
cache:
|
38
|
+
- vendor/bundle
|
data/lib/zold/score.rb
ADDED
@@ -0,0 +1,239 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Yegor Bugayenko
|
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 NONINFINGEMENT. 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.
|
22
|
+
|
23
|
+
require 'openssl'
|
24
|
+
require 'time'
|
25
|
+
|
26
|
+
# Zold score.
|
27
|
+
#
|
28
|
+
# To calculate a score you first have to create a zero score and then
|
29
|
+
# call its <tt>next()</tt> method:
|
30
|
+
#
|
31
|
+
# first = Score.new(host: 'example.org', invoice: 'PREFIX@0000000000000000')
|
32
|
+
# second = first.next
|
33
|
+
#
|
34
|
+
# More information about the algorithm you can find in the
|
35
|
+
# {White Paper}[https://papers.zold.io/wp.pdf].
|
36
|
+
#
|
37
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
38
|
+
# Copyright:: Copyright (c) 2018 Yegor Bugayenko
|
39
|
+
# License:: MIT
|
40
|
+
module Zold
|
41
|
+
# Score
|
42
|
+
class Score
|
43
|
+
# Default strength for the entire system, in production mode.
|
44
|
+
STRENGTH = 6
|
45
|
+
|
46
|
+
attr_reader :time, :host, :port, :invoice, :suffixes, :strength, :created
|
47
|
+
|
48
|
+
def initialize(time: Time.now, host:, port: 4096, invoice:, suffixes: [],
|
49
|
+
strength: Score::STRENGTH, created: Time.now)
|
50
|
+
@time = time
|
51
|
+
@host = host
|
52
|
+
@port = port
|
53
|
+
@invoice = invoice
|
54
|
+
@suffixes = suffixes
|
55
|
+
@strength = strength
|
56
|
+
@created = created
|
57
|
+
end
|
58
|
+
|
59
|
+
# The default no-value score.
|
60
|
+
ZERO = Score.new(time: Time.now, host: 'localhost', invoice: 'NOPREFIX@ffffffffffffffff')
|
61
|
+
|
62
|
+
# Parses it back from the JSON.
|
63
|
+
def self.parse_json(json)
|
64
|
+
raise "Time in JSON is broken: #{json}" unless json['time'] =~ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/
|
65
|
+
raise "Host is wrong: #{json}" unless json['host'] =~ /^[0-9a-z\.\-]+$/
|
66
|
+
raise "Port is wrong: #{json}" unless json['port'].is_a?(Integer)
|
67
|
+
raise "Invoice is wrong: #{json}" unless json['invoice'] =~ /^[a-zA-Z0-9]{8,32}@[a-f0-9]{16}$/
|
68
|
+
raise "Suffixes not array: #{json}" unless json['suffixes'].is_a?(Array)
|
69
|
+
Score.new(
|
70
|
+
time: Time.parse(json['time']), host: json['host'],
|
71
|
+
port: json['port'], invoice: json['invoice'], suffixes: json['suffixes'],
|
72
|
+
strength: json['strength']
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Parses it back from the text generated by <tt>to_s</tt>.
|
77
|
+
def self.parse(text)
|
78
|
+
re = Regexp.new(
|
79
|
+
'^' + [
|
80
|
+
'([0-9]+)/(?<strength>[0-9]+):',
|
81
|
+
' (?<time>[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z)',
|
82
|
+
' (?<host>[0-9a-z\.\-]+)',
|
83
|
+
' (?<port>[0-9]+)',
|
84
|
+
' (?<invoice>[a-zA-Z0-9]{8,32}@[a-f0-9]{16})',
|
85
|
+
'(?<suffixes>( [a-zA-Z0-9]+)*)'
|
86
|
+
].join + '$'
|
87
|
+
)
|
88
|
+
m = re.match(text.strip)
|
89
|
+
raise "Invalid score '#{text}', doesn't match: #{re}" if m.nil?
|
90
|
+
Score.new(
|
91
|
+
time: Time.parse(m[:time]), host: m[:host],
|
92
|
+
port: m[:port].to_i, invoice: m[:invoice],
|
93
|
+
suffixes: m[:suffixes].split(' '),
|
94
|
+
strength: m[:strength].to_i
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Parses it back from the text generated by <tt>to_text</tt>.
|
99
|
+
def self.parse_text(text)
|
100
|
+
parts = text.split(' ', 7)
|
101
|
+
Score.new(
|
102
|
+
time: Time.at(parts[1].hex),
|
103
|
+
host: parts[2],
|
104
|
+
port: parts[3].hex,
|
105
|
+
invoice: "#{parts[4]}@#{parts[5]}",
|
106
|
+
suffixes: parts[6] ? parts[6].split(' ') : [],
|
107
|
+
strength: parts[0].to_i
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Returns its crypto hash. Read the White Paper for more information.
|
112
|
+
def hash
|
113
|
+
raise 'Score has zero value, there is no hash' if @suffixes.empty?
|
114
|
+
@suffixes.reduce(prefix) do |pfx, suffix|
|
115
|
+
OpenSSL::Digest::SHA256.new("#{pfx} #{suffix}").hexdigest
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# A simple mnemo of the score.
|
120
|
+
def to_mnemo
|
121
|
+
"#{value}:#{@time.strftime('%H%M')}"
|
122
|
+
end
|
123
|
+
|
124
|
+
# Converts it to a text, which is console friendly. You can parse it back
|
125
|
+
# using <tt>parse_text()</tt>.
|
126
|
+
def to_text
|
127
|
+
pfx, bnf = @invoice.split('@')
|
128
|
+
[
|
129
|
+
@strength,
|
130
|
+
@time.to_i.to_s(16),
|
131
|
+
@host,
|
132
|
+
@port.to_s(16),
|
133
|
+
pfx,
|
134
|
+
bnf,
|
135
|
+
@suffixes.join(' ')
|
136
|
+
].join(' ')
|
137
|
+
end
|
138
|
+
|
139
|
+
# Converts it to a string. You can parse it back
|
140
|
+
# using <tt>parse()</tt>.
|
141
|
+
def to_s
|
142
|
+
[
|
143
|
+
"#{value}/#{@strength}:",
|
144
|
+
@time.utc.iso8601,
|
145
|
+
@host,
|
146
|
+
@port,
|
147
|
+
@invoice,
|
148
|
+
@suffixes.join(' ')
|
149
|
+
].join(' ').strip
|
150
|
+
end
|
151
|
+
|
152
|
+
# Converts the score to a hash, which can be used for JSON presentation
|
153
|
+
# of the score.
|
154
|
+
def to_h
|
155
|
+
{
|
156
|
+
value: value,
|
157
|
+
host: @host,
|
158
|
+
port: @port,
|
159
|
+
invoice: @invoice,
|
160
|
+
time: @time.utc.iso8601,
|
161
|
+
suffixes: @suffixes,
|
162
|
+
strength: @strength,
|
163
|
+
hash: value.zero? ? nil : hash,
|
164
|
+
expired: expired?,
|
165
|
+
valid: valid?,
|
166
|
+
age: (age / 60).round,
|
167
|
+
created: @created.utc.iso8601
|
168
|
+
}
|
169
|
+
end
|
170
|
+
|
171
|
+
# Returns a new score, which is a copy of the current one, but the amount
|
172
|
+
# of hash suffixes is reduced to the <tt>max</tt> provided.
|
173
|
+
def reduced(max = 4)
|
174
|
+
raise "Max can't be negative: #{max}" if max.negative?
|
175
|
+
Score.new(
|
176
|
+
time: @time, host: @host, port: @port, invoice: @invoice,
|
177
|
+
suffixes: @suffixes[0..[max, suffixes.count].min - 1],
|
178
|
+
strength: @strength
|
179
|
+
)
|
180
|
+
end
|
181
|
+
|
182
|
+
# Calculates and returns the next score after the current one. This
|
183
|
+
# operation may take some time, from a few milliseconds to hours, depending
|
184
|
+
# on the CPU power and the <tt>strength</tt> of the current score.
|
185
|
+
def next
|
186
|
+
raise 'This score is not valid' unless valid?
|
187
|
+
idx = 0
|
188
|
+
loop do
|
189
|
+
suffix = idx.to_s(16)
|
190
|
+
score = Score.new(
|
191
|
+
time: @time, host: @host, port: @port,
|
192
|
+
invoice: @invoice, suffixes: @suffixes + [suffix],
|
193
|
+
strength: @strength
|
194
|
+
)
|
195
|
+
return score if score.valid?
|
196
|
+
if score.expired?
|
197
|
+
return Score.new(
|
198
|
+
time: Time.now, host: @host, port: @port, invoice: @invoice,
|
199
|
+
suffixes: [], strength: @strength
|
200
|
+
)
|
201
|
+
end
|
202
|
+
idx += 1
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
# The age of the score in seconds.
|
207
|
+
def age
|
208
|
+
Time.now - @time
|
209
|
+
end
|
210
|
+
|
211
|
+
# Returns TRUE if the age of the score is over 24 hours.
|
212
|
+
def expired?(hours = 24)
|
213
|
+
age > hours * 60 * 60
|
214
|
+
end
|
215
|
+
|
216
|
+
# The prefix for the hash calculating algorithm. See the White Paper
|
217
|
+
# for more details.
|
218
|
+
def prefix
|
219
|
+
"#{@time.utc.iso8601} #{@host} #{@port} #{@invoice}"
|
220
|
+
end
|
221
|
+
|
222
|
+
# Returns TRUE if the score is valid: all its suffixes correctly consistute
|
223
|
+
# the hash, according to the algorithm explained in the White Paper.
|
224
|
+
def valid?
|
225
|
+
@suffixes.empty? || hash.end_with?('0' * @strength)
|
226
|
+
end
|
227
|
+
|
228
|
+
# Returns the value of the score, from zero and up. The value is basically
|
229
|
+
# the amount of hash suffixes inside the score.
|
230
|
+
def value
|
231
|
+
@suffixes.length
|
232
|
+
end
|
233
|
+
|
234
|
+
# Returns TRUE if the value of the score is zero.
|
235
|
+
def zero?
|
236
|
+
@suffixes.empty?
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Yegor Bugayenko
|
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 NONINFINGEMENT. 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.
|
22
|
+
|
23
|
+
require 'minitest/autorun'
|
24
|
+
require 'tmpdir'
|
25
|
+
require 'time'
|
26
|
+
require_relative '../../lib/zold/score'
|
27
|
+
|
28
|
+
# Score test.
|
29
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
30
|
+
# Copyright:: Copyright (c) 2018 Yegor Bugayenko
|
31
|
+
# License:: MIT
|
32
|
+
class TestScore < Minitest::Test
|
33
|
+
def test_reduces_itself
|
34
|
+
score = Zold::Score.new(
|
35
|
+
time: Time.parse('2017-07-19T21:24:51Z'),
|
36
|
+
host: 'localhost', port: 443, invoice: 'NOPREFIX@ffffffffffffffff',
|
37
|
+
suffixes: %w[A B C D E F G]
|
38
|
+
).reduced(2)
|
39
|
+
assert_equal(2, score.value)
|
40
|
+
assert_equal(64, score.hash.length)
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_drops_to_zero_when_expired
|
44
|
+
score = Zold::Score.new(
|
45
|
+
time: Time.now - 24 * 60 * 60,
|
46
|
+
host: 'some-host', port: 9999, invoice: 'NOPREFIX@ffffffffffffffff',
|
47
|
+
strength: 50
|
48
|
+
).next
|
49
|
+
assert(score.valid?)
|
50
|
+
assert(!score.expired?)
|
51
|
+
assert_equal(0, score.value)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_validates_wrong_score
|
55
|
+
score = Zold::Score.new(
|
56
|
+
time: Time.parse('2017-07-19T21:24:51Z'),
|
57
|
+
host: 'localhost', port: 443, invoice: 'NOPREFIX@ffffffffffffffff',
|
58
|
+
suffixes: %w[xxx yyy zzz]
|
59
|
+
)
|
60
|
+
assert_equal(3, score.value)
|
61
|
+
assert(!score.valid?)
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_prints_mnemo
|
65
|
+
score = Zold::Score.new(
|
66
|
+
time: Time.parse('2017-07-19T22:32:51Z'),
|
67
|
+
host: 'localhost', port: 443, invoice: 'NOPREFIX@ffffffffffffffff'
|
68
|
+
)
|
69
|
+
assert_equal('0:2232', score.to_mnemo)
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_prints_and_parses
|
73
|
+
time = Time.now
|
74
|
+
score = Zold::Score.parse(
|
75
|
+
Zold::Score.new(
|
76
|
+
time: time, host: 'localhost', port: 999, invoice: 'NOPREFIX@ffffffffffffffff',
|
77
|
+
strength: 1
|
78
|
+
).next.next.to_s
|
79
|
+
)
|
80
|
+
assert_equal(2, score.value)
|
81
|
+
assert_equal(score.time.to_s, time.to_s)
|
82
|
+
assert_equal('localhost', score.host)
|
83
|
+
assert_equal(999, score.port)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_prints_and_parses_text
|
87
|
+
time = Time.now
|
88
|
+
score = Zold::Score.parse_text(
|
89
|
+
Zold::Score.new(
|
90
|
+
time: time, host: 'a.example.com', port: 999, invoice: 'NOPREFIX@ffffffffffffffff',
|
91
|
+
strength: 1
|
92
|
+
).next.next.next.to_text
|
93
|
+
)
|
94
|
+
assert_equal(3, score.value)
|
95
|
+
assert_equal(score.time.utc.to_s, time.utc.to_s)
|
96
|
+
assert_equal('a.example.com', score.host)
|
97
|
+
assert_equal(999, score.port)
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_prints_and_parses_text_zero_score
|
101
|
+
time = Time.now
|
102
|
+
score = Zold::Score.parse_text(
|
103
|
+
Zold::Score.new(
|
104
|
+
time: time, host: '192.168.0.1', port: 1, invoice: 'NOPREFIX@ffffffffffffffff', suffixes: []
|
105
|
+
).to_text
|
106
|
+
)
|
107
|
+
assert_equal(0, score.value)
|
108
|
+
assert(!score.expired?)
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_prints_and_parses_zero_score
|
112
|
+
time = Time.now
|
113
|
+
score = Zold::Score.parse(
|
114
|
+
Zold::Score.new(
|
115
|
+
time: time, host: '192.168.0.1', port: 1, invoice: 'NOPREFIX@ffffffffffffffff', suffixes: []
|
116
|
+
).to_s
|
117
|
+
)
|
118
|
+
assert_equal(0, score.value)
|
119
|
+
assert(!score.expired?)
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_finds_next_score
|
123
|
+
score = Zold::Score.new(
|
124
|
+
time: Time.now, host: 'localhost', port: 443,
|
125
|
+
invoice: 'NOPREFIX@ffffffffffffffff', strength: 2
|
126
|
+
).next.next.next
|
127
|
+
assert_equal(3, score.value)
|
128
|
+
assert(score.valid?)
|
129
|
+
assert(!score.expired?)
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_dont_expire_correctly
|
133
|
+
score = Zold::Score.new(
|
134
|
+
time: Time.now - 10 * 60 * 60, host: 'localhost', port: 443,
|
135
|
+
invoice: 'NOPREFIX@ffffffffffffffff', strength: 2
|
136
|
+
).next.next.next
|
137
|
+
assert(!score.expired?)
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_correct_number_of_zeroes
|
141
|
+
score = Zold::Score.new(
|
142
|
+
time: Time.now, host: 'localhost', port: 443,
|
143
|
+
invoice: 'NOPREFIX@ffffffffffffffff', strength: 3
|
144
|
+
).next
|
145
|
+
assert(score.hash.end_with?('000'))
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_generates_hash_correctly
|
149
|
+
score = Zold::Score.new(
|
150
|
+
time: Time.parse('2018-06-27T06:22:41Z'), host: 'b2.zold.io', port: 4096,
|
151
|
+
invoice: 'THdonv1E@abcdabcdabcdabcd', suffixes: ['3a934b']
|
152
|
+
)
|
153
|
+
assert_equal('c9c72efbf6beeea13408c5e720ec42aec017c11c3db335e05595c03755000000', score.hash)
|
154
|
+
score = Zold::Score.new(
|
155
|
+
time: Time.parse('2018-06-27T06:22:41Z'), host: 'b2.zold.io', port: 4096,
|
156
|
+
invoice: 'THdonv1E@abcdabcdabcdabcd', suffixes: %w[3a934b 1421217]
|
157
|
+
)
|
158
|
+
assert_equal('e04ab4e69f86aa17be1316a52148e7bc3187c6d3df581d885a862d8850000000', score.hash)
|
159
|
+
end
|
160
|
+
end
|
data/zold-score.gemspec
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Yegor Bugayenko
|
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.
|
22
|
+
|
23
|
+
require 'English'
|
24
|
+
Gem::Specification.new do |s|
|
25
|
+
s.specification_version = 2 if s.respond_to? :specification_version=
|
26
|
+
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
|
27
|
+
s.rubygems_version = '2.2'
|
28
|
+
s.required_ruby_version = '>=2.3'
|
29
|
+
s.name = 'zold-score'
|
30
|
+
s.version = '0.1.0'
|
31
|
+
s.license = 'MIT'
|
32
|
+
s.summary = 'Zold score'
|
33
|
+
s.description = 'Score calculating Ruby Gem for Zold'
|
34
|
+
s.authors = ['Yegor Bugayenko']
|
35
|
+
s.email = 'yegor256@gmail.com'
|
36
|
+
s.homepage = 'http://github.com/zold-io/zold-score'
|
37
|
+
s.files = `git ls-files`.split($RS)
|
38
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
39
|
+
s.test_files = s.files.grep(%r{^(test|features)/})
|
40
|
+
s.rdoc_options = ['--charset=UTF-8']
|
41
|
+
s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
|
42
|
+
s.add_development_dependency 'codecov', '~>0'
|
43
|
+
s.add_development_dependency 'minitest', '~>5'
|
44
|
+
s.add_development_dependency 'rdoc', '~>4'
|
45
|
+
s.add_development_dependency 'rspec-rails', '~>3'
|
46
|
+
s.add_development_dependency 'rubocop', '0.58.1'
|
47
|
+
s.add_development_dependency 'rubocop-rspec', '~>1'
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: zold-score
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Yegor Bugayenko
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-11-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: codecov
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
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: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rdoc
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '4'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '4'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-rails
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.58.1
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.58.1
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop-rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1'
|
97
|
+
description: Score calculating Ruby Gem for Zold
|
98
|
+
email: yegor256@gmail.com
|
99
|
+
executables: []
|
100
|
+
extensions: []
|
101
|
+
extra_rdoc_files:
|
102
|
+
- README.md
|
103
|
+
- LICENSE.txt
|
104
|
+
files:
|
105
|
+
- ".0pdd.yml"
|
106
|
+
- ".gitattributes"
|
107
|
+
- ".gitignore"
|
108
|
+
- ".pdd"
|
109
|
+
- ".rubocop.yml"
|
110
|
+
- ".rultor.yml"
|
111
|
+
- ".simplecov"
|
112
|
+
- ".travis.yml"
|
113
|
+
- Gemfile
|
114
|
+
- LICENSE.txt
|
115
|
+
- README.md
|
116
|
+
- Rakefile
|
117
|
+
- appveyor.yml
|
118
|
+
- lib/zold/score.rb
|
119
|
+
- test/zold/test_score.rb
|
120
|
+
- zold-score.gemspec
|
121
|
+
homepage: http://github.com/zold-io/zold-score
|
122
|
+
licenses:
|
123
|
+
- MIT
|
124
|
+
metadata: {}
|
125
|
+
post_install_message:
|
126
|
+
rdoc_options:
|
127
|
+
- "--charset=UTF-8"
|
128
|
+
require_paths:
|
129
|
+
- lib
|
130
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '2.3'
|
135
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
requirements: []
|
141
|
+
rubyforge_project:
|
142
|
+
rubygems_version: 2.7.6
|
143
|
+
signing_key:
|
144
|
+
specification_version: 2
|
145
|
+
summary: Zold score
|
146
|
+
test_files:
|
147
|
+
- test/zold/test_score.rb
|