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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: bcf2292d9da70068c6595c31195265cacea43c9d
4
- data.tar.gz: 9dcab18064c2eeb25340182f22e26632141f82f0
2
+ SHA256:
3
+ metadata.gz: df4dc73d0b92dcd762d1c741eb30f8dcfc56fdd84d18bfdbc2435290d9a3df97
4
+ data.tar.gz: c7764c8ae13bb99ff51977d7b52f926eee9083e5db6f75e43c860c2eb9557715
5
5
  SHA512:
6
- metadata.gz: 404b14d5065305fa3c792bb6f3b43af65f292e99d3a2b50c89db45fa2fa16bf9e8468af4f5c65e95de6e401a21c3d46a06d752e93e8b97d85c0ec81f6267739d
7
- data.tar.gz: c41acda381c48132bee1dd21115db290059387f04d7c1b4ce914f2b780fc7de679a302d23a9c75a02e905f6856d4aba146d80cc9edc8e1465f54215c1ae95105
6
+ metadata.gz: eb0f6fcdf17d108b75ddd5af587ceb7fe2d6294e8134cfeae90807f62607d49e158754903526f49b22fb6522a4ded0cf2f1522ad9c1305f295b9bd858cad9714
7
+ data.tar.gz: 8b327f489cfa71d77eca28df39b4408fcf8c7c4c8e7ed233c10f05e242bcfee0936a96f97e5bb8eee0fa4f49a058bc7b754fc549ab47d8e70574e756ccdc1d93
@@ -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.
@@ -1,13 +1,12 @@
1
- require 'rafini/version'
2
-
3
- require 'rafini/array'
4
- require 'rafini/exception'
5
- require 'rafini/hash'
6
- require 'rafini/integer'
7
- require 'rafini/string'
8
-
9
- require 'rafini/odometers'
10
- require 'rafini/empty'
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`
@@ -1,59 +1,42 @@
1
1
  module Rafini
2
2
  module Array
3
3
  refine ::Array do
4
-
5
- # string = array.joins(sep1,sep2,sep3,...){|i| sep[i]}
4
+ # type _AToS = ::Array[(_AToS|_ToS)]
5
+ # _AToS#joins(*_AToS seps)?{(_ToS,_ToS)->_ToS}
6
6
  #
7
- # Returns a string created by converting each element of the array to
8
- # a string, separated by the given separators.
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 an iteration number.
11
- # Note that the iteration number starts at 1.
12
- # Lastly it uses an empty string.
13
- # ['a','b','c','d','e','f'].joins('-', '-', ' '){':'} #=> 'a-b-c d:e:f'
14
- # ['a','b','c'].joins{','} #=> 'a,b,c'
15
- # ['1','2','3'].joins('.') #=> '1.23'
16
- # ['a','b','c'].joins{|i|i} #=> 'a1b2c'
17
- def joins(*p, &block)
18
- str = ''
19
- if length > 1
20
- str << self[0]
21
- 1.upto(length-1) do |i|
22
- str << (p.empty? ? (block ? block.call(i).to_s : '') : p.shift.to_s)
23
- str << self[i]
24
- end
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 str
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
- self.each{|key| hash[key]=value}
37
+ each{|key| hash[key]=value}
54
38
  return hash
55
39
  end
56
-
57
40
  end
58
41
  end
59
42
  end
@@ -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 = [].freeze
7
- HASH = {}.freeze
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
@@ -1,7 +1,6 @@
1
1
  module Rafini
2
2
  module Exception
3
3
  refine ::Exception do
4
-
5
4
  # $!.puts outputs to standard error what went bang!
6
5
  # The given message is what you normally want to see.
7
6
  # The exeption message is also shown if in verbose mode.
@@ -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(*self.keys).new(*self.values)
6
+ def to_struct(&blk)
7
+ Struct.new(*keys, &blk).new(*values)
9
8
  end
10
9
 
11
- # hash0.modify(hash1,...) #=> hash
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.ammend(hash1,...)
27
+ # hash0.amend(hash1,...)
40
28
  #
41
29
  # Ammends hash with hashes.
42
- # Overwrites existing elements only.
43
- # {a:'A',b:'B'}.supplement({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {a:'A',b:'X'}
44
- def amend(*hashes)
45
- self.keys.each do |key|
46
- hashes.each do |hash|
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
@@ -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(*p)
12
- n = self
13
- m = p.inject(1,:*)
14
- r = []
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
- (p.length-1).downto(0) do |i|
17
- y = n/m; r.unshift y
18
- n = n%m
19
- f = p[i]; m = m/f
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
- return r
24
+ # in case of a float, round
25
+ readings.unshift remainder.round
24
26
  end
25
27
  end
26
28
  end
@@ -1,80 +1,103 @@
1
+ require 'rafini/integer'
2
+ require 'rafini/hash'
3
+
1
4
  module Rafini
2
5
  module Odometers
3
- refine ::Integer do
4
- # Need Rafini::Integer for #odometer
5
- # Need Rafini::Hash for #to_struct
6
- # Need Rafini::Array for #per
7
- [Rafini::Integer, Rafini::Hash, Rafini::Array].each{|mod| using mod}
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
- def odoread(scale)
10
- values = scale.values
11
- keys = scale.keys;
12
- counts = self.odometer(*values[0..-2])
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
- string = "#{counts[0]} #{keys[0]}#{(counts[0]==1)? '' : 's'}"
15
- (keys.length-1).downto(1) do |i|
16
- if counts[i] > 0
17
- string = "#{counts[i]} #{keys[i]}#{(counts[i]>1)? 's' : ''}"
18
- string << " and #{counts[i-1]} #{keys[i-1]}#{(counts[i-1]>1)? 's' : ''}" if counts[i-1]>0
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
- hash = {}
24
- keys.per(counts){|k,v| hash[k]=v}
25
- hash[:to_s]=string
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
- return hash.to_struct
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
- self.odoread(SEC2TIME)
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
- keys = SCALE[:base].keys + SCALE[type].keys
95
- values = SCALE[:base].values + SCALE[type].values
96
- counts = self.odometer(*values[0..-2])
97
-
98
- string = nil
99
- if self < 1_000
100
- string = self.to_s
101
- elsif self < 1_000_000
102
- d = (self<10_000)? 2 : (self<100_000)? 1 : 0
103
- m = (self/1000.0).round(d)
104
- string = "#{m}k"
105
- else
106
- (keys.length-1).downto(4) do |i|
107
- next unless counts[i]>0
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
- string = "#{n}#{keys[i][0].upcase}"
116
- break
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
- hash = {}
121
- keys.per(counts){|k,v| hash[k]=v}
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
@@ -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{ |word| word.capitalize }.join('')
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: 1.0.0
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: 2014-12-25 00:00:00.000000000 Z
11
+ date: 2021-01-12 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: |
14
- Just a collection of useful refinements.
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.rdoc
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 2.1.3p242 (2014-09-19 revision 47630) [x86_64-linux]'
53
- rubyforge_project:
54
- rubygems_version: 2.4.1
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:
@@ -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.
@@ -1,3 +0,0 @@
1
- module Rafini
2
- VERSION = '1.0.0'
3
- end