rafini 1.0.0 → 3.0.210112
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +159 -0
- data/lib/rafini.rb +10 -11
- data/lib/rafini/array.rb +25 -42
- data/lib/rafini/empty.rb +6 -5
- data/lib/rafini/exception.rb +0 -1
- data/lib/rafini/hash.rb +16 -31
- data/lib/rafini/integer.rb +13 -11
- data/lib/rafini/odometers.rb +115 -87
- data/lib/rafini/string.rb +11 -2
- metadata +13 -18
- data/README.rdoc +0 -114
- data/lib/rafini/version.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: df4dc73d0b92dcd762d1c741eb30f8dcfc56fdd84d18bfdbc2435290d9a3df97
|
4
|
+
data.tar.gz: c7764c8ae13bb99ff51977d7b52f926eee9083e5db6f75e43c860c2eb9557715
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eb0f6fcdf17d108b75ddd5af587ceb7fe2d6294e8134cfeae90807f62607d49e158754903526f49b22fb6522a4ded0cf2f1522ad9c1305f295b9bd858cad9714
|
7
|
+
data.tar.gz: 8b327f489cfa71d77eca28df39b4408fcf8c7c4c8e7ed233c10f05e242bcfee0936a96f97e5bb8eee0fa4f49a058bc7b754fc549ab47d8e70574e756ccdc1d93
|
data/README.md
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
# Rafini
|
2
|
+
|
3
|
+
* [VERSION 3.0.210112](https://github.com/carlosjhr64/rafini/releases)
|
4
|
+
* [github](https://github.com/carlosjhr64/rafini)
|
5
|
+
* [rubygems](https://rubygems.org/gems/rafini)
|
6
|
+
|
7
|
+
## DESCRIPTION:
|
8
|
+
|
9
|
+
Just a collection of useful refinements.
|
10
|
+
|
11
|
+
## INSTALL:
|
12
|
+
|
13
|
+
```shell
|
14
|
+
$ gem install rafini
|
15
|
+
```
|
16
|
+
|
17
|
+
## SYNOPSIS:
|
18
|
+
|
19
|
+
### using Rafini::Array
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
require 'rafini/array'
|
23
|
+
using Rafini::Array
|
24
|
+
|
25
|
+
# joins
|
26
|
+
['Y','M','D','h','m','s'].joins('-','-',' '){':'}
|
27
|
+
#=> "Y-M-D h:m:s"
|
28
|
+
[1,9,2,8,3,7,4,6,5,5].joins{|a,b|a>b ? '>': a<b ? '<': '='}
|
29
|
+
#=> "1<9>2<8>3<7>4<6>5=5"
|
30
|
+
|
31
|
+
# is
|
32
|
+
[:a,:b,:c].is(true) #=> {:a=>true, :b=>true, :c=>true}
|
33
|
+
```
|
34
|
+
### Rafini::Empty
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
require 'rafini/empty'
|
38
|
+
include Rafini::Empty
|
39
|
+
s0 #=> ""
|
40
|
+
a0 #=> []
|
41
|
+
h0 #=> {}
|
42
|
+
[s0,a0,h0].all?(&:frozen?) #=> true
|
43
|
+
```
|
44
|
+
|
45
|
+
### using Rafini::Exception
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
require 'rafini/exception'
|
49
|
+
using Rafini::Exception
|
50
|
+
|
51
|
+
# $!.puts
|
52
|
+
# Normally stderr.puts your "Nice" message.
|
53
|
+
# Additionally puts your "Ugly" message when $VERBOSE.
|
54
|
+
# Additionally puts backtrace when $DEBUG
|
55
|
+
# No output when $VERBOSE is nil.
|
56
|
+
begin
|
57
|
+
raise 'Ugly Message'
|
58
|
+
rescue RuntimeError
|
59
|
+
$!.puts 'Nice Message'
|
60
|
+
end
|
61
|
+
|
62
|
+
# Rafini.bang!
|
63
|
+
error = Rafini.bang!('Nice Message') do
|
64
|
+
raise 'Ugly Message'
|
65
|
+
# Outputs as $!.puts "Nice Message"
|
66
|
+
end
|
67
|
+
error.class #=> RuntimeError
|
68
|
+
error.to_s #=> "Ugly Message"
|
69
|
+
|
70
|
+
# Rafini.thread_bang!
|
71
|
+
thread = Rafini.thread_bang!('Nice Message') do
|
72
|
+
# this is in a thread
|
73
|
+
raise 'Ugly Message' # outputs as $!.puts 'Nice Message'
|
74
|
+
end
|
75
|
+
# The returned value joined from the thread
|
76
|
+
# will not re-raise the error(but gives the error).
|
77
|
+
thread.value.class #=> RuntimeError
|
78
|
+
```
|
79
|
+
|
80
|
+
### using Rafini::Hash
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
require 'rafini/hash'
|
84
|
+
using Rafini::Hash
|
85
|
+
|
86
|
+
# to_struc
|
87
|
+
struct = {a:'A',b:'C',c:'C'}.to_struct{ def ok = "OK" }
|
88
|
+
struct #=> #<struct a="A", b="C", c="C">
|
89
|
+
struct.a #=> "A"
|
90
|
+
struct.ok #=> "OK"
|
91
|
+
|
92
|
+
# supplement
|
93
|
+
{a:'A',b:'B'}.supplement({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {:a=>"A", :b=>"B", :c=>"C", :d=>"D"}
|
94
|
+
|
95
|
+
# amend
|
96
|
+
{a:'A',b:'B'}.amend({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {:a=>"A", :b=>"X"}
|
97
|
+
```
|
98
|
+
|
99
|
+
### using Rafini::Integer
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
require 'rafini/integer'
|
103
|
+
using Rafini::Integer
|
104
|
+
|
105
|
+
# odometer
|
106
|
+
123.odometer(10,10) #=> [3, 2, 1]
|
107
|
+
30.odometer(2,3,5) #=> [0, 0, 0, 1]
|
108
|
+
```
|
109
|
+
|
110
|
+
### using Rafini::Odometers
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
require 'rafini/odometers'
|
114
|
+
using Rafini::Odometers
|
115
|
+
|
116
|
+
# sec2time
|
117
|
+
12501.sec2time.to_s #=> "3 hours and 28 minutes"
|
118
|
+
|
119
|
+
# illion
|
120
|
+
3_512_325.illion.to_s #=> "3.51M"
|
121
|
+
```
|
122
|
+
|
123
|
+
### using Rafini::String
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
require 'rafini/string'
|
127
|
+
using Rafini::String
|
128
|
+
|
129
|
+
# camelize
|
130
|
+
'a_camel_kick'.camelize #=> "ACamelKick"
|
131
|
+
|
132
|
+
# semantic
|
133
|
+
'1.2.3'.semantic(0..1) #=> "1.2"
|
134
|
+
```
|
135
|
+
|
136
|
+
## LICENSE:
|
137
|
+
|
138
|
+
(The MIT License)
|
139
|
+
|
140
|
+
Copyright (c) 2021 carlosjhr64
|
141
|
+
|
142
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
143
|
+
a copy of this software and associated documentation files (the
|
144
|
+
'Software'), to deal in the Software without restriction, including
|
145
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
146
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
147
|
+
permit persons to whom the Software is furnished to do so, subject to
|
148
|
+
the following conditions:
|
149
|
+
|
150
|
+
The above copyright notice and this permission notice shall be
|
151
|
+
included in all copies or substantial portions of the Software.
|
152
|
+
|
153
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
154
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
155
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
156
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
157
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
158
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
159
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/lib/rafini.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
1
|
+
module Rafini
|
2
|
+
VERSION = '3.0.210112'
|
3
|
+
autoload :Array, 'rafini/array'
|
4
|
+
autoload :Exception, 'rafini/exception'
|
5
|
+
autoload :Hash, 'rafini/hash'
|
6
|
+
autoload :Integer, 'rafini/integer'
|
7
|
+
autoload :String, 'rafini/string'
|
8
|
+
autoload :Odometers, 'rafini/odometers'
|
9
|
+
autoload :Empty, 'rafini/empty'
|
10
|
+
end
|
12
11
|
# Requires:
|
13
12
|
#`ruby`
|
data/lib/rafini/array.rb
CHANGED
@@ -1,59 +1,42 @@
|
|
1
1
|
module Rafini
|
2
2
|
module Array
|
3
3
|
refine ::Array do
|
4
|
-
|
5
|
-
#
|
4
|
+
# type _AToS = ::Array[(_AToS|_ToS)]
|
5
|
+
# _AToS#joins(*_AToS seps)?{(_ToS,_ToS)->_ToS}
|
6
6
|
#
|
7
|
-
# Returns a string created by
|
8
|
-
#
|
7
|
+
# Returns a string created by joining the elements of the (flatten) array,
|
8
|
+
# separated by the given (flatten) separators.
|
9
9
|
# If no separators are given or are used up,
|
10
|
-
# it uses the value of the executed block, which is passed
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# [
|
15
|
-
# [
|
16
|
-
# [
|
17
|
-
|
18
|
-
|
19
|
-
if length
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
10
|
+
# it uses the value of the executed block, which is passed the next neigboring iteration items.
|
11
|
+
# Else, it just joins the items.
|
12
|
+
# ['2021','Jan','09','07','29','05'].joins('-', '-', ' '){':'}
|
13
|
+
# #=> "2021-Jan-09 07:29:05"
|
14
|
+
# [:a,[1,2],:b].joins{','} #=> 'a,1,2,b'
|
15
|
+
# [3,1,4,1,5,9].joins('.') #=> '3.14159'
|
16
|
+
# [1,9,2,8,3,7,4,6,5,5].joins{|a,b|a>b ? '>': a<b ? '<': '='}
|
17
|
+
# #=> "1<9>2<8>3<7>4<6>5=5"
|
18
|
+
def joins(*seps, &block)
|
19
|
+
return '' if length < 1
|
20
|
+
items = flatten
|
21
|
+
previous = items.shift
|
22
|
+
string = ::String.new previous.to_s
|
23
|
+
return string if items.empty?
|
24
|
+
seps.flatten!
|
25
|
+
while item = items.shift
|
26
|
+
sep = seps.shift&.to_s || block&.call(previous,item).to_s and string << sep
|
27
|
+
string << item.to_s
|
28
|
+
previous = item
|
25
29
|
end
|
26
|
-
return
|
27
|
-
end
|
28
|
-
|
29
|
-
# array1.per(array2){|obj1, obj2| ... }
|
30
|
-
#
|
31
|
-
# Gives the block each two elements of two array respectively.
|
32
|
-
# If the second array is not given, it passes the block the index number instead.
|
33
|
-
# h={} # say you have a hash h, then
|
34
|
-
# ['a','b','c'].per(['A','B','C']){|l,n| h[l]=n} # h=={'a'=>'A','b'=>'B','c'=>'C'}
|
35
|
-
# ['a','b','c'].per{|l,i| h[l]=i} # h=={'a'=>0,'b'=>1,'c'=>2}
|
36
|
-
def per(b=nil)
|
37
|
-
0.upto(length-1){|i| yield self[i], (b)? b[i] : i}
|
38
|
-
end
|
39
|
-
|
40
|
-
# array.which{|a|...}
|
41
|
-
#
|
42
|
-
# Returns first object for which block is true.
|
43
|
-
# ['dog','cat','bunny'].which{|a|a=~/c/} #=> "cat"
|
44
|
-
def which
|
45
|
-
self.each{|obj| return obj if yield(obj)}
|
46
|
-
return nil
|
30
|
+
return string
|
47
31
|
end
|
48
32
|
|
49
33
|
# [:a,:b,:c].is(true) #=> {:a=>true,:b=>true,:c=>true}
|
50
34
|
#
|
51
35
|
# Updates a hash with the keys given by the array to the given value.
|
52
36
|
def is(value, hash={})
|
53
|
-
|
37
|
+
each{|key| hash[key]=value}
|
54
38
|
return hash
|
55
39
|
end
|
56
|
-
|
57
40
|
end
|
58
41
|
end
|
59
42
|
end
|
data/lib/rafini/empty.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
module Rafini
|
2
|
-
# In a world where objects are allowed to represent infinities,
|
3
|
-
# Rafini dares to introduce empty sets. But WHY!???
|
4
|
-
# Ta-ta-TUM...
|
5
2
|
module Empty
|
6
|
-
ARRAY
|
7
|
-
HASH
|
3
|
+
ARRAY = [].freeze
|
4
|
+
HASH = {}.freeze
|
8
5
|
STRING = ''.freeze
|
6
|
+
|
7
|
+
def a0 = ARRAY
|
8
|
+
def h0 = HASH
|
9
|
+
def s0 = STRING
|
9
10
|
end
|
10
11
|
end
|
data/lib/rafini/exception.rb
CHANGED
data/lib/rafini/hash.rb
CHANGED
@@ -1,33 +1,18 @@
|
|
1
1
|
module Rafini
|
2
2
|
module Hash
|
3
3
|
refine ::Hash do
|
4
|
-
|
5
4
|
# struct = hash.to_struct
|
6
5
|
# Why not?
|
7
|
-
def to_struct
|
8
|
-
Struct.new(*
|
6
|
+
def to_struct(&blk)
|
7
|
+
Struct.new(*keys, &blk).new(*values)
|
9
8
|
end
|
10
9
|
|
11
|
-
# hash0.
|
12
|
-
#
|
13
|
-
# Updates hash with hashes.
|
14
|
-
# Overwrites existing elements and adds elements.
|
15
|
-
# {a:'A',b:'B'}.modify({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {a:'A',b:'X',c:'Y',d:'D'}
|
16
|
-
def modify(*hashes)
|
17
|
-
hashes.each do |hash|
|
18
|
-
hash.each do |key, value|
|
19
|
-
self[key] = value
|
20
|
-
end
|
21
|
-
end
|
22
|
-
self
|
23
|
-
end
|
24
|
-
|
25
|
-
# hash0.supplement(hash1,...) #=> hash
|
10
|
+
# hash0.supplement!(hash1,...) #=> hash
|
26
11
|
#
|
27
12
|
# Supplements hash with hashes.
|
28
13
|
# Adds missing elements only.
|
29
14
|
# {a:'A',b:'B'}.supplement({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {a:'A',b:'B',c:'C',d:'D'}
|
30
|
-
def supplement(*hashes)
|
15
|
+
def supplement!(*hashes)
|
31
16
|
hashes.each do |hash|
|
32
17
|
hash.each do |key, value|
|
33
18
|
self[key] = value unless self.has_key?(key)
|
@@ -35,24 +20,24 @@ module Rafini
|
|
35
20
|
end
|
36
21
|
self
|
37
22
|
end
|
23
|
+
def supplement(...)
|
24
|
+
self.dup.supplement!(...)
|
25
|
+
end
|
38
26
|
|
39
|
-
# hash0.
|
27
|
+
# hash0.amend(hash1,...)
|
40
28
|
#
|
41
29
|
# Ammends hash with hashes.
|
42
|
-
# Overwrites existing
|
43
|
-
# {a:'A',b:'B'}.
|
44
|
-
def amend(*hashes)
|
45
|
-
self.
|
46
|
-
hashes.
|
47
|
-
if hash.has_key?(key)
|
48
|
-
self[key] = hash[key]
|
49
|
-
break
|
50
|
-
end
|
51
|
-
end
|
30
|
+
# Overwrites existing keys only with first key value found in amending hashes.
|
31
|
+
# {a:'A',b:'B'}.amend({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {a:'A',b:'X'}
|
32
|
+
def amend!(*hashes)
|
33
|
+
self.each_key do |key|
|
34
|
+
value=hashes.find{_1.has_key? key}&.fetch(key) and self[key]=value
|
52
35
|
end
|
53
36
|
self
|
54
37
|
end
|
55
|
-
|
38
|
+
def amend(...)
|
39
|
+
self.dup.amend!(...)
|
40
|
+
end
|
56
41
|
end
|
57
42
|
end
|
58
43
|
end
|
data/lib/rafini/integer.rb
CHANGED
@@ -1,26 +1,28 @@
|
|
1
1
|
module Rafini
|
2
2
|
module Integer
|
3
3
|
refine ::Integer do
|
4
|
-
|
5
4
|
# odometer
|
6
5
|
# Kinda hard to explain...
|
7
6
|
# 123.odometer(10,10) #=> [3,2,1]
|
8
7
|
# 30.odometer(2,3,5) #=> [0,0,0,1]
|
9
8
|
# ((60*60*24)*3 + (60*60)*12 + 60*15 + 30).odometer(60,60,24) #=> [30, 15, 12, 3]
|
10
9
|
# Useful for making clocks, number scales, mayan long count... etc.
|
11
|
-
def odometer(*
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
def odometer(*levels, factors: true)
|
11
|
+
raise RangeError, 'negative odometer' if self < 0
|
12
|
+
readings, remainder = [], self
|
13
|
+
|
14
|
+
levels = levels.inject([1]){|m, f| m.push(m.last*f)} if factors
|
15
|
+
levels.shift
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
levels.reverse_each do |level|
|
18
|
+
# in case of a float, floor
|
19
|
+
reading = (remainder/level).floor
|
20
|
+
readings.unshift reading
|
21
|
+
remainder = remainder%level
|
20
22
|
end
|
21
|
-
r.unshift n
|
22
23
|
|
23
|
-
|
24
|
+
# in case of a float, round
|
25
|
+
readings.unshift remainder.round
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|
data/lib/rafini/odometers.rb
CHANGED
@@ -1,80 +1,103 @@
|
|
1
|
+
require 'rafini/integer'
|
2
|
+
require 'rafini/hash'
|
3
|
+
|
1
4
|
module Rafini
|
2
5
|
module Odometers
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
# Sidereal Year: https://en.wikipedia.org/wiki/Year
|
7
|
+
year = 365*24*60*60 + 6*60*60 + 9*60 + 9.76
|
8
|
+
SEC2TIME = { # levels
|
9
|
+
second: 1,
|
10
|
+
minute: 60,
|
11
|
+
hour: 60*60,
|
12
|
+
day: 24*60*60,
|
13
|
+
week: 7*24*60*60,
|
14
|
+
month: year/12.0,
|
15
|
+
year: year,
|
16
|
+
decade: 10*year,
|
17
|
+
centurie: 100*year,
|
18
|
+
millennium: 1_000*year,
|
19
|
+
age: 10_000*year,
|
20
|
+
epoch: 100_000*year,
|
21
|
+
era: 1_000_000*year,
|
22
|
+
eon: 5_000_000*year,
|
23
|
+
gigaannum: 10_000_000*year,
|
24
|
+
}
|
8
25
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
26
|
+
SCALE = { # levels
|
27
|
+
base: {
|
28
|
+
one: 1,
|
29
|
+
ten: 10,
|
30
|
+
hundred: 100,
|
31
|
+
thousand: 10**3,
|
32
|
+
million: 10**6,
|
33
|
+
},
|
34
|
+
short: {
|
35
|
+
billion: 10**9,
|
36
|
+
trillion: 10**12,
|
37
|
+
quadrillion: 10**15,
|
38
|
+
},
|
39
|
+
long: {
|
40
|
+
billion: 10**12,
|
41
|
+
trillion: 10**18,
|
42
|
+
quadrillion: 10**24,
|
43
|
+
},
|
44
|
+
}
|
13
45
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
46
|
+
refine ::Hash do
|
47
|
+
def description
|
48
|
+
string = ''
|
49
|
+
reverse_each do |key, count|
|
50
|
+
s = (count==1)? '' : 's'
|
51
|
+
unless string.empty?
|
52
|
+
string << " and #{count} #{key}#{s}" if count > 0
|
19
53
|
break
|
20
54
|
end
|
55
|
+
next if count == 0
|
56
|
+
string << "#{count} #{key}#{s}"
|
21
57
|
end
|
58
|
+
return string
|
59
|
+
end
|
60
|
+
end
|
22
61
|
|
23
|
-
|
24
|
-
|
25
|
-
|
62
|
+
refine ::Integer do
|
63
|
+
using Rafini::Integer # Need Rafini::Integer for #odometer
|
64
|
+
using Rafini::Hash # Need Rafini::Hash for #to_struct
|
26
65
|
|
27
|
-
|
66
|
+
def odoread(scale, **kw, &blk)
|
67
|
+
counts = odometer(*scale.values, **kw)
|
68
|
+
::Hash[scale.keys.zip(counts)].to_struct(&blk)
|
28
69
|
end
|
29
70
|
|
30
|
-
SEC2TIME = {
|
31
|
-
second: 60,
|
32
|
-
minute: 60,
|
33
|
-
hour: 24,
|
34
|
-
day: 7,
|
35
|
-
week: 4,
|
36
|
-
month: 13,
|
37
|
-
year: 10,
|
38
|
-
decade: 10,
|
39
|
-
centurie: 10,
|
40
|
-
millennium: 10,
|
41
|
-
age: 10,
|
42
|
-
epoch: 10,
|
43
|
-
era: 5,
|
44
|
-
eon: 2,
|
45
|
-
gigaannum: nil,
|
46
|
-
}
|
47
|
-
|
48
71
|
# Integer#sec2time
|
49
72
|
# Returns a struct with the different time scales for number of seconds.
|
50
|
-
# Note that the month(4 weeks)/year(13 months) are not meant to be exact.
|
51
73
|
# 10_000.sec2time.to_s #=> "2 hours and 46 minutes"
|
52
74
|
# 10_000.sec2time.hour #=> 2
|
53
75
|
def sec2time
|
54
|
-
|
76
|
+
odoread(SEC2TIME, factors:false) do
|
77
|
+
def to_s
|
78
|
+
string = nil
|
79
|
+
SEC2TIME.keys.reverse_each do |key|
|
80
|
+
count=self[key]
|
81
|
+
if string
|
82
|
+
if count > 0
|
83
|
+
string << " and #{count} #{key}"
|
84
|
+
string << 's' if count > 1
|
85
|
+
end
|
86
|
+
break
|
87
|
+
end
|
88
|
+
next if count==0
|
89
|
+
string = "#{count} #{key}"
|
90
|
+
string << 's' if count > 1
|
91
|
+
end
|
92
|
+
string = "0 #{SEC2TIME.first[0]}s" unless string
|
93
|
+
string
|
94
|
+
end
|
95
|
+
def to_i
|
96
|
+
SEC2TIME.to_a.map{|k,v|v*self[k]}.sum.round
|
97
|
+
end
|
98
|
+
end
|
55
99
|
end
|
56
100
|
|
57
|
-
SCALE = {
|
58
|
-
base: {
|
59
|
-
ones: 10,
|
60
|
-
tens: 10,
|
61
|
-
hundreds: 10,
|
62
|
-
thousands: 1_000,
|
63
|
-
},
|
64
|
-
short: {
|
65
|
-
millions: 1_000,
|
66
|
-
billions: 1_000,
|
67
|
-
trillions: 1_000,
|
68
|
-
quadrillions: nil,
|
69
|
-
},
|
70
|
-
long: {
|
71
|
-
millions: 1_000_000,
|
72
|
-
billions: 1_000_000,
|
73
|
-
trillions: 1_000_000,
|
74
|
-
quadrillions: nil,
|
75
|
-
},
|
76
|
-
}
|
77
|
-
|
78
101
|
# 1_230.illion.to_s #=> "1.23k"
|
79
102
|
# 1_230_000.illion.to_s #=> "1.23M"
|
80
103
|
# ...etc
|
@@ -91,37 +114,42 @@ module Rafini
|
|
91
114
|
# m.quadrillions #=> 888
|
92
115
|
# m.to_s #=> "888Q" It rounds up 888.7!
|
93
116
|
def illion(type=:short)
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
n = counts[i]
|
109
|
-
if n < 1_000
|
110
|
-
d = (n<10)? 2 : (n<100)? 1 : 0
|
111
|
-
n = (n + counts[i-1]/values[i-1].to_f).round(d)
|
112
|
-
else
|
113
|
-
n = n.illion
|
117
|
+
scale = SCALE[:base].merge SCALE[type]
|
118
|
+
struct = odoread(scale, factors:false) do
|
119
|
+
def scale=(scale)
|
120
|
+
@scale=scale
|
121
|
+
end
|
122
|
+
def type=(type)
|
123
|
+
@type=type
|
124
|
+
end
|
125
|
+
def to_s
|
126
|
+
number = to_i
|
127
|
+
return number.to_s if number < 1_000
|
128
|
+
if number < 1_000_000
|
129
|
+
precision = (number<10_000)? 2 : (number<100_000)? 1 : 0
|
130
|
+
return "#{(number/1000.0).round(precision)}K"
|
114
131
|
end
|
115
|
-
|
116
|
-
|
132
|
+
keys = @scale.keys.reverse_each
|
133
|
+
loop do
|
134
|
+
key = keys.next
|
135
|
+
n = self[key]
|
136
|
+
next if n == 0
|
137
|
+
if n < 1_000
|
138
|
+
precision = (n<10)? 2 : (n<100)? 1 : 0
|
139
|
+
scale = @scale[key].to_f
|
140
|
+
f = (number/scale).round(precision)
|
141
|
+
return "#{f}#{key[0].upcase}"
|
142
|
+
end
|
143
|
+
return "#{n.illion}#{key[0].upcase}"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
def to_i
|
147
|
+
@scale.to_a.map{|k,v|v*self[k]}.sum
|
117
148
|
end
|
118
149
|
end
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
hash[:to_s] = string
|
123
|
-
|
124
|
-
return hash.to_struct
|
150
|
+
struct.type = type
|
151
|
+
struct.scale = scale
|
152
|
+
return struct
|
125
153
|
end
|
126
154
|
end
|
127
155
|
end
|
data/lib/rafini/string.rb
CHANGED
@@ -4,8 +4,17 @@ module Rafini
|
|
4
4
|
# camelize:
|
5
5
|
# 1) A camel kick, as in "I gotz camelized".
|
6
6
|
# 2) "a_camel_kick" => "ACamelKick"
|
7
|
-
def camelize(sep
|
8
|
-
self.split(sep).map
|
7
|
+
def camelize(sep='_')
|
8
|
+
self.split(sep).map(&:capitalize).join
|
9
|
+
end
|
10
|
+
|
11
|
+
# semantic:
|
12
|
+
# 'a.b.c'.semantic(1) #=> 'b'
|
13
|
+
# 'a.b.c'.semantic(0..1) #=> 'a.b'
|
14
|
+
# 'a.b.c'.semantic(0..2, join:'/') #=> 'b/c'
|
15
|
+
# 'a/b/c'.semantic(0..2, split:'/', join:'.') #=> 'a.b.c'
|
16
|
+
def semantic(v=(0..2), split:'.', join:'.')
|
17
|
+
[*self.split(split)[v]].join(join)
|
9
18
|
end
|
10
19
|
end
|
11
20
|
end
|
metadata
CHANGED
@@ -1,24 +1,24 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rafini
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.210112
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- carlosjhr64
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description:
|
14
|
-
|
13
|
+
description: 'Just a collection of useful refinements.
|
14
|
+
|
15
|
+
'
|
15
16
|
email: carlosjhr64@gmail.com
|
16
17
|
executables: []
|
17
18
|
extensions: []
|
18
|
-
extra_rdoc_files:
|
19
|
-
- README.rdoc
|
19
|
+
extra_rdoc_files: []
|
20
20
|
files:
|
21
|
-
- README.
|
21
|
+
- README.md
|
22
22
|
- lib/rafini.rb
|
23
23
|
- lib/rafini/array.rb
|
24
24
|
- lib/rafini/empty.rb
|
@@ -27,15 +27,12 @@ files:
|
|
27
27
|
- lib/rafini/integer.rb
|
28
28
|
- lib/rafini/odometers.rb
|
29
29
|
- lib/rafini/string.rb
|
30
|
-
- lib/rafini/version.rb
|
31
30
|
homepage: https://github.com/carlosjhr64/rafini
|
32
31
|
licenses:
|
33
32
|
- MIT
|
34
33
|
metadata: {}
|
35
|
-
post_install_message:
|
36
|
-
rdoc_options:
|
37
|
-
- "--main"
|
38
|
-
- README.rdoc
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
39
36
|
require_paths:
|
40
37
|
- lib
|
41
38
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -49,11 +46,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
49
46
|
- !ruby/object:Gem::Version
|
50
47
|
version: '0'
|
51
48
|
requirements:
|
52
|
-
- 'ruby: ruby
|
53
|
-
|
54
|
-
|
55
|
-
signing_key:
|
49
|
+
- 'ruby: ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-linux]'
|
50
|
+
rubygems_version: 3.2.3
|
51
|
+
signing_key:
|
56
52
|
specification_version: 4
|
57
53
|
summary: Just a collection of useful refinements.
|
58
54
|
test_files: []
|
59
|
-
has_rdoc:
|
data/README.rdoc
DELETED
@@ -1,114 +0,0 @@
|
|
1
|
-
= rafini
|
2
|
-
|
3
|
-
== DESCRIPTION:
|
4
|
-
|
5
|
-
Just a collection of useful refinements.
|
6
|
-
|
7
|
-
== SYNOPSIS:
|
8
|
-
|
9
|
-
=== using Rafini::Array
|
10
|
-
|
11
|
-
# joins
|
12
|
-
['a','b','c','d','e','f'].joins('-','-',' '){':'} #=> "a-b-c d:e:f"
|
13
|
-
|
14
|
-
# per
|
15
|
-
h={}
|
16
|
-
['a','b','c'].per(['A','B','C']){|l,u| h[l]=u}
|
17
|
-
h #=> {'a'=>'A','b'=>'B','c'=>'C'}
|
18
|
-
|
19
|
-
# which
|
20
|
-
['dog','cat','bunny'].which{|a|a=~/c/} #=> "cat"
|
21
|
-
|
22
|
-
# is
|
23
|
-
[:a,:b,:c].is(true) #=> {a: true, b: true, c: true}
|
24
|
-
|
25
|
-
# any?
|
26
|
-
[:a,:b,:c].any?(:b,:d) #=> true
|
27
|
-
|
28
|
-
=== using Rafini::Exception
|
29
|
-
|
30
|
-
# $!.puts
|
31
|
-
begin
|
32
|
-
raise 'Ugly Message'
|
33
|
-
rescue RuntimeError
|
34
|
-
$!.puts 'Nice Message'
|
35
|
-
end
|
36
|
-
|
37
|
-
# Rafini.bang!
|
38
|
-
value = Rafini.bang!('Nice Message') do
|
39
|
-
raise 'Ugly Message'
|
40
|
-
end
|
41
|
-
value #=> return value of block or error object
|
42
|
-
|
43
|
-
# Rafini.thread_bang!
|
44
|
-
Rafini.thread_bang!('Nice Message') do
|
45
|
-
# this is in a thread
|
46
|
-
raise 'Ugly Message'
|
47
|
-
end
|
48
|
-
|
49
|
-
=== using Rafini::Hash
|
50
|
-
|
51
|
-
# to_struc
|
52
|
-
struct = {a:'A',b:'C',c:'C'}.to_struct
|
53
|
-
struct.a #=> 'A'
|
54
|
-
|
55
|
-
# modify
|
56
|
-
{a:'A',b:'B'}.modify({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {a:'A',b:'X',c:'Y',d:'D'}
|
57
|
-
|
58
|
-
# supplement
|
59
|
-
{a:'A',b:'B'}.supplement({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {a:'A',b:'B',c:'C',d:'D'}
|
60
|
-
|
61
|
-
# amend
|
62
|
-
{a:'A',b:'B'}.amend({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {a:'A',b:'X'}
|
63
|
-
|
64
|
-
=== using Rafini::Integer
|
65
|
-
|
66
|
-
# odometer
|
67
|
-
123.odometer(10,10) #=> [3,2,1]
|
68
|
-
30.odometer(2,3,5) #=> [0,0,0,1]
|
69
|
-
|
70
|
-
=== using Rafini::Odometers
|
71
|
-
|
72
|
-
# sec2time
|
73
|
-
12501.sec2time.to_s #=> "3 hours and 28 minutes"
|
74
|
-
|
75
|
-
# illion
|
76
|
-
3_512_325.illion.to_s #=> "3.51M"
|
77
|
-
|
78
|
-
=== using Rafini::String
|
79
|
-
|
80
|
-
# camelize
|
81
|
-
'a_camel_kick'.camelize #=> "ACamelKick"
|
82
|
-
|
83
|
-
=== Rafini::Empty
|
84
|
-
|
85
|
-
STRING, ARRAY, HASH = ''.frozen, [].frozen, {}.frozen
|
86
|
-
|
87
|
-
== INSTALL:
|
88
|
-
|
89
|
-
$ sudo gem install rafini
|
90
|
-
|
91
|
-
== LICENSE:
|
92
|
-
|
93
|
-
(The MIT License)
|
94
|
-
|
95
|
-
Copyright (c) 2014 carlosjhr64
|
96
|
-
|
97
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
98
|
-
a copy of this software and associated documentation files (the
|
99
|
-
'Software'), to deal in the Software without restriction, including
|
100
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
101
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
102
|
-
permit persons to whom the Software is furnished to do so, subject to
|
103
|
-
the following conditions:
|
104
|
-
|
105
|
-
The above copyright notice and this permission notice shall be
|
106
|
-
included in all copies or substantial portions of the Software.
|
107
|
-
|
108
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
109
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
110
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
111
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
112
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
113
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
114
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/lib/rafini/version.rb
DELETED