rafini 2.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
2
  SHA256:
3
- metadata.gz: b81e63f8b4651660cd62560692546173a7ae971ce0a0a76b6bc772c573f2d181
4
- data.tar.gz: 37146803ff33ddcf74da2cd90bb5ddd4a2b1da0fe2be0c55b1b5b984a14029ca
3
+ metadata.gz: df4dc73d0b92dcd762d1c741eb30f8dcfc56fdd84d18bfdbc2435290d9a3df97
4
+ data.tar.gz: c7764c8ae13bb99ff51977d7b52f926eee9083e5db6f75e43c860c2eb9557715
5
5
  SHA512:
6
- metadata.gz: ecb3a3935d9892365a7568e304994605657b0ff0ed9c4e5adab0eee83c4d42d9584b0b6c6cdcd2d602f2817371d3a632f51396bf62b9ca134153c7eae926f22a
7
- data.tar.gz: a1795c03155fbaa64fd90b4a5a8ab4ad033fa5489bb925168a765ab4be71b742cca5bc61d282c88c9c4af75c2b9c24feb8c2bd87f5d01189a5b32e34fd2a8c89
6
+ metadata.gz: eb0f6fcdf17d108b75ddd5af587ceb7fe2d6294e8134cfeae90807f62607d49e158754903526f49b22fb6522a4ded0cf2f1522ad9c1305f295b9bd858cad9714
7
+ data.tar.gz: 8b327f489cfa71d77eca28df39b4408fcf8c7c4c8e7ed233c10f05e242bcfee0936a96f97e5bb8eee0fa4f49a058bc7b754fc549ab47d8e70574e756ccdc1d93
data/README.md CHANGED
@@ -1,101 +1,143 @@
1
- # rafini 2.0.0
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)
2
6
 
3
7
  ## DESCRIPTION:
4
8
 
5
9
  Just a collection of useful refinements.
6
10
 
11
+ ## INSTALL:
12
+
13
+ ```shell
14
+ $ gem install rafini
15
+ ```
16
+
7
17
  ## SYNOPSIS:
8
18
 
9
19
  ### using Rafini::Array
10
20
 
11
- # joins
12
- ['a','b','c','d','e','f'].joins('-','-',' '){':'} #=> "a-b-c d:e:f"
21
+ ```ruby
22
+ require 'rafini/array'
23
+ using Rafini::Array
13
24
 
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'}
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"
18
30
 
19
- # which
20
- ['dog','cat','bunny'].which{|a|a=~/c/} #=> "cat"
31
+ # is
32
+ [:a,:b,:c].is(true) #=> {:a=>true, :b=>true, :c=>true}
33
+ ```
34
+ ### Rafini::Empty
21
35
 
22
- # is
23
- [:a,:b,:c].is(true) #=> {a: true, b: true, c: true}
36
+ ```ruby
37
+ require 'rafini/empty'
38
+ include Rafini::Empty
39
+ s0 #=> ""
40
+ a0 #=> []
41
+ h0 #=> {}
42
+ [s0,a0,h0].all?(&:frozen?) #=> true
43
+ ```
24
44
 
25
45
  ### using Rafini::Exception
26
46
 
27
- # $!.puts
28
- begin
29
- raise 'Ugly Message'
30
- rescue RuntimeError
31
- $!.puts 'Nice Message'
32
- end
33
-
34
- # Rafini.bang!
35
- value = Rafini.bang!('Nice Message') do
36
- raise 'Ugly Message'
37
- end
38
- value #=> return value of block or error object
39
-
40
- # Rafini.thread_bang!
41
- Rafini.thread_bang!('Nice Message') do
42
- # this is in a thread
43
- raise 'Ugly Message'
44
- end
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
+ ```
45
79
 
46
80
  ### using Rafini::Hash
47
81
 
48
- # to_struc
49
- struct = {a:'A',b:'C',c:'C'}.to_struct
50
- struct.a #=> 'A'
51
-
52
- # modify
53
- {a:'A',b:'B'}.modify({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {a:'A',b:'X',c:'Y',d:'D'}
82
+ ```ruby
83
+ require 'rafini/hash'
84
+ using Rafini::Hash
54
85
 
55
- # supplement
56
- {a:'A',b:'B'}.supplement({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {a:'A',b:'B',c:'C',d:'D'}
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"
57
91
 
58
- # amend
59
- {a:'A',b:'B'}.amend({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {a:'A',b:'X'}
92
+ # supplement
93
+ {a:'A',b:'B'}.supplement({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {:a=>"A", :b=>"B", :c=>"C", :d=>"D"}
60
94
 
61
- # maps
62
- {a:'A',b:'B',c:'C',c:'D'}.maps(:c,:a,:b) #=> ['C','A','B']
95
+ # amend
96
+ {a:'A',b:'B'}.amend({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {:a=>"A", :b=>"X"}
97
+ ```
63
98
 
64
99
  ### using Rafini::Integer
65
100
 
66
- # odometer
67
- 123.odometer(10,10) #=> [3,2,1]
68
- 30.odometer(2,3,5) #=> [0,0,0,1]
101
+ ```ruby
102
+ require 'rafini/integer'
103
+ using Rafini::Integer
69
104
 
70
- ### using Rafini::Odometers
105
+ # odometer
106
+ 123.odometer(10,10) #=> [3, 2, 1]
107
+ 30.odometer(2,3,5) #=> [0, 0, 0, 1]
108
+ ```
71
109
 
72
- # sec2time
73
- 12501.sec2time.to_s #=> "3 hours and 28 minutes"
74
-
75
- # illion
76
- 3_512_325.illion.to_s #=> "3.51M"
110
+ ### using Rafini::Odometers
77
111
 
78
- ### using Rafini::String
112
+ ```ruby
113
+ require 'rafini/odometers'
114
+ using Rafini::Odometers
79
115
 
80
- # camelize
81
- 'a_camel_kick'.camelize #=> "ACamelKick"
116
+ # sec2time
117
+ 12501.sec2time.to_s #=> "3 hours and 28 minutes"
82
118
 
83
- # semantic
84
- '1.2.3'.semantic(0..1) #=> '1.2'
119
+ # illion
120
+ 3_512_325.illion.to_s #=> "3.51M"
121
+ ```
85
122
 
86
- ### Rafini::Empty
123
+ ### using Rafini::String
87
124
 
88
- STRING, ARRAY, HASH = ''.frozen, [].frozen, {}.frozen
125
+ ```ruby
126
+ require 'rafini/string'
127
+ using Rafini::String
89
128
 
90
- ## INSTALL:
129
+ # camelize
130
+ 'a_camel_kick'.camelize #=> "ACamelKick"
91
131
 
92
- $ gem install rafini
132
+ # semantic
133
+ '1.2.3'.semantic(0..1) #=> "1.2"
134
+ ```
93
135
 
94
136
  ## LICENSE:
95
137
 
96
138
  (The MIT License)
97
139
 
98
- Copyright (c) 2020 carlosjhr64
140
+ Copyright (c) 2021 carlosjhr64
99
141
 
100
142
  Permission is hereby granted, free of charge, to any person obtaining
101
143
  a copy of this software and associated documentation files (the
@@ -1,12 +1,12 @@
1
1
  module Rafini
2
- VERSION = '2.0.0'
3
- require 'rafini/array'
4
- require 'rafini/exception'
5
- require 'rafini/hash'
6
- require 'rafini/integer'
7
- require 'rafini/string'
8
- require 'rafini/odometers'
9
- require 'rafini/empty'
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
10
  end
11
11
  # Requires:
12
12
  #`ruby`
@@ -1,52 +1,40 @@
1
1
  module Rafini
2
2
  module Array
3
3
  refine ::Array do
4
- # string = array.joins(sep1,sep2,sep3,...){|i| sep[i]}
4
+ # type _AToS = ::Array[(_AToS|_ToS)]
5
+ # _AToS#joins(*_AToS seps)?{(_ToS,_ToS)->_ToS}
5
6
  #
6
- # Returns a string created by converting each element of the array to
7
- # 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.
8
9
  # If no separators are given or are used up,
9
- # it uses the value of the executed block, which is passed an iteration number.
10
- # Note that the iteration number starts at 1.
11
- # Lastly it uses an empty string.
12
- # ['a','b','c','d','e','f'].joins('-', '-', ' '){':'} #=> 'a-b-c d:e:f'
13
- # ['a','b','c'].joins{','} #=> 'a,b,c'
14
- # ['1','2','3'].joins('.') #=> '1.23'
15
- # ['a','b','c'].joins{|i|i} #=> 'a1b2c'
16
- def joins(*p, &block)
17
- str = ''
18
- if length > 0
19
- str << self[0]
20
- 1.upto(length-1) do |i|
21
- str << (p.empty? ? (block ? block.call(i).to_s : '') : p.shift.to_s)
22
- str << self[i]
23
- 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
24
29
  end
25
- return str
30
+ return string
26
31
  end
27
32
 
28
- # array1.per(array2){|obj1, obj2| ... }
29
- #
30
- # Gives the block each two elements of two array respectively.
31
- # If the second array is not given, it passes the block the index number instead.
32
- # h={} # say you have a hash h, then
33
- # ['a','b','c'].per(['A','B','C']){|l,n| h[l]=n} # h=={'a'=>'A','b'=>'B','c'=>'C'}
34
- # ['a','b','c'].per{|l,i| h[l]=i} # h=={'a'=>0,'b'=>1,'c'=>2}
35
- def per(b=nil)
36
- 0.upto(length-1){|i| yield self[i], (b)? b[i] : i}
37
- end
38
-
39
- # array.which{|a|...}
40
- #
41
- # Returns first object for which block is true.
42
- # ['dog','cat','bunny'].which{|a|a=~/c/} #=> "cat"
43
- alias which detect
44
-
45
33
  # [:a,:b,:c].is(true) #=> {:a=>true,:b=>true,:c=>true}
46
34
  #
47
35
  # Updates a hash with the keys given by the array to the given value.
48
36
  def is(value, hash={})
49
- self.each{|key| hash[key]=value}
37
+ each{|key| hash[key]=value}
50
38
  return hash
51
39
  end
52
40
  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
@@ -3,30 +3,16 @@ module Rafini
3
3
  refine ::Hash do
4
4
  # struct = hash.to_struct
5
5
  # Why not?
6
- def to_struct
7
- Struct.new(*self.keys).new(*self.values)
6
+ def to_struct(&blk)
7
+ Struct.new(*keys, &blk).new(*values)
8
8
  end
9
9
 
10
- # hash0.modify(hash1,...) #=> hash
11
- #
12
- # Updates hash with hashes.
13
- # Overwrites existing elements and adds elements.
14
- # {a:'A',b:'B'}.modify({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {a:'A',b:'X',c:'Y',d:'D'}
15
- def modify(*hashes)
16
- hashes.each do |hash|
17
- hash.each do |key, value|
18
- self[key] = value
19
- end
20
- end
21
- self
22
- end
23
-
24
- # hash0.supplement(hash1,...) #=> hash
10
+ # hash0.supplement!(hash1,...) #=> hash
25
11
  #
26
12
  # Supplements hash with hashes.
27
13
  # Adds missing elements only.
28
14
  # {a:'A',b:'B'}.supplement({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {a:'A',b:'B',c:'C',d:'D'}
29
- def supplement(*hashes)
15
+ def supplement!(*hashes)
30
16
  hashes.each do |hash|
31
17
  hash.each do |key, value|
32
18
  self[key] = value unless self.has_key?(key)
@@ -34,30 +20,23 @@ module Rafini
34
20
  end
35
21
  self
36
22
  end
23
+ def supplement(...)
24
+ self.dup.supplement!(...)
25
+ end
37
26
 
38
- # hash0.ammend(hash1,...)
27
+ # hash0.amend(hash1,...)
39
28
  #
40
29
  # Ammends hash with hashes.
41
- # Overwrites existing elements only.
42
- # {a:'A',b:'B'}.supplement({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {a:'A',b:'X'}
43
- def amend(*hashes)
44
- self.keys.each do |key|
45
- hashes.each do |hash|
46
- if hash.has_key?(key)
47
- self[key] = hash[key]
48
- break
49
- end
50
- 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
51
35
  end
52
36
  self
53
37
  end
54
-
55
- # hash.maps(key1,...)
56
- #
57
- # Maps parameters list with hash.
58
- # {a:'A",b:'B',c:'C'}.maps(:c,:a,:b) #=> ['C','A','B']
59
- def maps(*keys)
60
- keys.map{|_|self[_]}
38
+ def amend(...)
39
+ self.dup.amend!(...)
61
40
  end
62
41
  end
63
42
  end
@@ -7,19 +7,22 @@ module Rafini
7
7
  # 30.odometer(2,3,5) #=> [0,0,0,1]
8
8
  # ((60*60*24)*3 + (60*60)*12 + 60*15 + 30).odometer(60,60,24) #=> [30, 15, 12, 3]
9
9
  # Useful for making clocks, number scales, mayan long count... etc.
10
- def odometer(*p)
11
- n = self
12
- m = p.inject(1,:*)
13
- r = []
10
+ def odometer(*levels, factors: true)
11
+ raise RangeError, 'negative odometer' if self < 0
12
+ readings, remainder = [], self
14
13
 
15
- (p.length-1).downto(0) do |i|
16
- y = n/m; r.unshift y
17
- n = n%m
18
- f = p[i]; m = m/f
14
+ levels = levels.inject([1]){|m, f| m.push(m.last*f)} if factors
15
+ levels.shift
16
+
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
19
22
  end
20
- r.unshift n
21
23
 
22
- return r
24
+ # in case of a float, round
25
+ readings.unshift remainder.round
23
26
  end
24
27
  end
25
28
  end
@@ -1,78 +1,101 @@
1
+ require 'rafini/integer'
2
+ require 'rafini/hash'
3
+
1
4
  module Rafini
2
5
  module Odometers
3
- SEC2TIME = {
4
- second: 60,
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,
5
10
  minute: 60,
6
- hour: 24,
7
- day: 7,
8
- week: 4,
9
- month: 13,
10
- year: 10,
11
- decade: 10,
12
- centurie: 10,
13
- millennium: 10,
14
- age: 10,
15
- epoch: 10,
16
- era: 5,
17
- eon: 2,
18
- gigaannum: nil,
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,
19
24
  }
20
25
 
21
- SCALE = {
26
+ SCALE = { # levels
22
27
  base: {
23
- ones: 10,
24
- tens: 10,
25
- hundreds: 10,
26
- thousands: 1_000,
28
+ one: 1,
29
+ ten: 10,
30
+ hundred: 100,
31
+ thousand: 10**3,
32
+ million: 10**6,
27
33
  },
28
34
  short: {
29
- millions: 1_000,
30
- billions: 1_000,
31
- trillions: 1_000,
32
- quadrillions: nil,
35
+ billion: 10**9,
36
+ trillion: 10**12,
37
+ quadrillion: 10**15,
33
38
  },
34
39
  long: {
35
- millions: 1_000_000,
36
- billions: 1_000_000,
37
- trillions: 1_000_000,
38
- quadrillions: nil,
40
+ billion: 10**12,
41
+ trillion: 10**18,
42
+ quadrillion: 10**24,
39
43
  },
40
44
  }
41
45
 
42
- refine ::Integer do
43
- # Need Rafini::Integer for #odometer
44
- # Need Rafini::Hash for #to_struct
45
- # Need Rafini::Array for #per
46
- [Rafini::Integer, Rafini::Hash, Rafini::Array].each{|mod| using mod}
47
-
48
- def odoread(scale)
49
- values = scale.values
50
- keys = scale.keys;
51
- counts = self.odometer(*values[0..-2])
52
-
53
- string = "#{counts[0]} #{keys[0]}#{(counts[0]==1)? '' : 's'}"
54
- (keys.length-1).downto(1) do |i|
55
- if counts[i] > 0
56
- string = "#{counts[i]} #{keys[i]}#{(counts[i]>1)? 's' : ''}"
57
- 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
58
53
  break
59
54
  end
55
+ next if count == 0
56
+ string << "#{count} #{key}#{s}"
60
57
  end
58
+ return string
59
+ end
60
+ end
61
61
 
62
- hash = {}
63
- keys.per(counts){|k,v| hash[k]=v}
64
- 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
65
65
 
66
- 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)
67
69
  end
68
70
 
69
71
  # Integer#sec2time
70
72
  # Returns a struct with the different time scales for number of seconds.
71
- # Note that the month(4 weeks)/year(13 months) are not meant to be exact.
72
73
  # 10_000.sec2time.to_s #=> "2 hours and 46 minutes"
73
74
  # 10_000.sec2time.hour #=> 2
74
75
  def sec2time
75
- 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
76
99
  end
77
100
 
78
101
  # 1_230.illion.to_s #=> "1.23k"
@@ -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,17 +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
9
  end
10
10
 
11
11
  # semantic:
12
12
  # 'a.b.c'.semantic(1) #=> 'b'
13
13
  # 'a.b.c'.semantic(0..1) #=> 'a.b'
14
- # 'a.b.c'.semantic(0..2, '/') #=> 'b/c'
15
- # 'a/b/c'.semantic(0..2, '.', /\//) #=> 'a.b.c'
16
- def semantic(v,s='.',sx=/\./)
17
- [*self.split(sx)[v]].join(s)
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)
18
18
  end
19
19
  end
20
20
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rafini
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.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: 2020-08-15 00:00:00.000000000 Z
11
+ date: 2021-01-12 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: 'Just a collection of useful refinements.
14
14
 
@@ -31,7 +31,7 @@ homepage: https://github.com/carlosjhr64/rafini
31
31
  licenses:
32
32
  - MIT
33
33
  metadata: {}
34
- post_install_message:
34
+ post_install_message:
35
35
  rdoc_options: []
36
36
  require_paths:
37
37
  - lib
@@ -46,9 +46,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  requirements:
49
- - 'ruby: ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]'
50
- rubygems_version: 3.1.2
51
- 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:
52
52
  specification_version: 4
53
53
  summary: Just a collection of useful refinements.
54
54
  test_files: []