scout-essentials 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.vimproject +33 -1
- data/VERSION +1 -1
- data/lib/scout/annotation/annotated_object.rb +69 -0
- data/lib/scout/annotation/annotation_module.rb +59 -0
- data/lib/scout/annotation/array.rb +74 -0
- data/lib/scout/annotation.rb +45 -0
- data/lib/scout/concurrent_stream.rb +4 -1
- data/lib/scout/config.rb +3 -3
- data/lib/scout/exceptions.rb +2 -1
- data/lib/scout/indiferent_hash/options.rb +2 -1
- data/lib/scout/log/color.rb +1 -1
- data/lib/scout/log.rb +11 -11
- data/lib/scout/misc/digest.rb +39 -8
- data/lib/scout/misc/filesystem.rb +23 -0
- data/lib/scout/misc/format.rb +32 -0
- data/lib/scout/misc/helper.rb +37 -0
- data/lib/scout/misc/math.rb +109 -0
- data/lib/scout/misc/system.rb +2 -2
- data/lib/scout/misc.rb +1 -0
- data/lib/scout/named_array.rb +8 -6
- data/lib/scout/open/remote.rb +8 -3
- data/lib/scout/open/stream.rb +5 -1
- data/lib/scout/open/util.rb +1 -1
- data/lib/scout/path/find.rb +18 -6
- data/lib/scout/path/util.rb +1 -1
- data/lib/scout/path.rb +10 -4
- data/lib/scout/persist/open.rb +1 -1
- data/lib/scout/persist/serialize.rb +6 -2
- data/lib/scout/persist.rb +49 -20
- data/lib/scout/resource/path.rb +1 -1
- data/lib/scout/resource/scout.rb +2 -0
- data/lib/scout/resource/util.rb +8 -3
- data/lib/scout/resource.rb +15 -3
- data/scout-essentials.gemspec +21 -13
- data/test/scout/annotation/test_annotated_object.rb +0 -0
- data/test/scout/annotation/test_array.rb +119 -0
- data/test/scout/misc/test_digest.rb +54 -0
- data/test/scout/misc/test_filesystem.rb +28 -0
- data/test/scout/misc/test_helper.rb +14 -0
- data/test/scout/misc/test_math.rb +9 -0
- data/test/scout/path/test_find.rb +32 -0
- data/test/scout/test_annotation.rb +169 -0
- data/test/scout/test_persist.rb +17 -1
- data/test/scout/test_resource.rb +8 -8
- metadata +13 -5
- data/lib/scout/meta_extension.rb +0 -101
- data/test/scout/test_meta_extension.rb +0 -80
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 01ebe0cbbfda369f1d1b3de5009566eed0749cdb0a418c19c663a21ec68214c1
|
4
|
+
data.tar.gz: 2303029301ea7b4ef1f9d7cf44bd906cb8db637b31a5147ae2950e4eb1c6e37e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 707278b8bdd09658049035622021bd822d8b53ecef993f4136b550f2acb47be30cf515a460b07f5c45ed51769d782639b06e128947dab80832a4de3b6b66f574
|
7
|
+
data.tar.gz: d8a5ce01ca753d159734871447f961a39d48992af934f7ad69a0f95ff708794d00962cd36fbabbcd535a721611f5d0fa9194f87d5662cd8ab66ed80d8abeed38
|
data/.vimproject
CHANGED
@@ -5,7 +5,12 @@ scout-essentials=/$PWD filter="*.rb *.txt *.md *.conf *.yaml" {
|
|
5
5
|
scout-essentials.rb
|
6
6
|
scout=scout{
|
7
7
|
exceptions.rb
|
8
|
-
|
8
|
+
annotation.rb
|
9
|
+
annotation=annotation{
|
10
|
+
array.rb
|
11
|
+
annotated_object.rb
|
12
|
+
annotation_module.rb
|
13
|
+
}
|
9
14
|
misc.rb
|
10
15
|
misc=misc{
|
11
16
|
digest.rb
|
@@ -15,6 +20,7 @@ scout-essentials=/$PWD filter="*.rb *.txt *.md *.conf *.yaml" {
|
|
15
20
|
insist.rb
|
16
21
|
monitor.rb
|
17
22
|
system.rb
|
23
|
+
math.rb
|
18
24
|
}
|
19
25
|
named_array.rb
|
20
26
|
indiferent_hash.rb
|
@@ -74,5 +80,31 @@ scout-essentials=/$PWD filter="*.rb *.txt *.md *.conf *.yaml" {
|
|
74
80
|
}
|
75
81
|
test=test{
|
76
82
|
test_helper.rb
|
83
|
+
scout=scout{
|
84
|
+
test_annotation.rb
|
85
|
+
annotation=annotation{
|
86
|
+
test_annotated_object.rb
|
87
|
+
test_array.rb
|
88
|
+
}
|
89
|
+
test_cmd.rb
|
90
|
+
test_concurrent_stream.rb
|
91
|
+
test_config.rb
|
92
|
+
test_indiferent_hash.rb
|
93
|
+
test_log.rb
|
94
|
+
test_misc.rb
|
95
|
+
test_named_array.rb
|
96
|
+
test_open.rb
|
97
|
+
test_path.rb
|
98
|
+
test_persist.rb
|
99
|
+
test_resource.rb
|
100
|
+
test_tmpfile.rb
|
101
|
+
misc=misc{
|
102
|
+
test_digest.rb
|
103
|
+
test_filesystem.rb
|
104
|
+
test_helper.rb
|
105
|
+
test_insist.rb
|
106
|
+
test_system.rb
|
107
|
+
}
|
108
|
+
}
|
77
109
|
}
|
78
110
|
}
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.4.0
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Annotation
|
2
|
+
module AnnotatedObject
|
3
|
+
def annotations
|
4
|
+
@annotations ||= []
|
5
|
+
end
|
6
|
+
|
7
|
+
def annotation_types
|
8
|
+
@annotation_types ||= []
|
9
|
+
end
|
10
|
+
|
11
|
+
def annotation_hash
|
12
|
+
attr_hash = {}
|
13
|
+
@annotations.each do |name|
|
14
|
+
attr_hash[name] = self.instance_variable_get("@#{name}")
|
15
|
+
end if @annotations
|
16
|
+
attr_hash
|
17
|
+
end
|
18
|
+
|
19
|
+
def annotation_info
|
20
|
+
annotation_hash.merge(annotation_types: annotation_types, annotated_array: (AnnotatedArray === self))
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.serialize(obj)
|
24
|
+
Annotation.purge(obj.annotation_info.merge(literal: obj))
|
25
|
+
end
|
26
|
+
|
27
|
+
def serialize
|
28
|
+
AnnotatedObject.serialize(self)
|
29
|
+
end
|
30
|
+
|
31
|
+
def annotation_id
|
32
|
+
Misc.digest([self, annotation_info])
|
33
|
+
end
|
34
|
+
|
35
|
+
alias id annotation_id
|
36
|
+
|
37
|
+
def annotate(other)
|
38
|
+
annotation_types.each do |type|
|
39
|
+
type.setup(other, annotation_hash)
|
40
|
+
end
|
41
|
+
other
|
42
|
+
end
|
43
|
+
|
44
|
+
def purge
|
45
|
+
new = self.dup
|
46
|
+
|
47
|
+
if new.instance_variables.include?(:@annotations)
|
48
|
+
new.instance_variable_get(:@annotations).each do |a|
|
49
|
+
var_name = "@#{a}".to_sym
|
50
|
+
new.remove_instance_variable(var_name) if new.instance_variables.include? var_name
|
51
|
+
end
|
52
|
+
new.remove_instance_variable(:@annotations)
|
53
|
+
end
|
54
|
+
|
55
|
+
if new.instance_variables.include?(:@annotation_types)
|
56
|
+
new.remove_instance_variable(:@annotation_types)
|
57
|
+
end
|
58
|
+
|
59
|
+
new
|
60
|
+
end
|
61
|
+
|
62
|
+
def make_array
|
63
|
+
new = [self]
|
64
|
+
self.annotate(new)
|
65
|
+
new.extend AnnotatedArray
|
66
|
+
new
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Annotation
|
2
|
+
module AnnotationModule
|
3
|
+
def annotation(*attrs)
|
4
|
+
self.instance_variable_get("@annotations").concat attrs
|
5
|
+
attrs.each do |a|
|
6
|
+
self.attr_accessor a
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def annotations
|
11
|
+
@annotations ||= []
|
12
|
+
end
|
13
|
+
|
14
|
+
def included(mod)
|
15
|
+
mod.instance_variable_set(:@annotations, []) unless mod.instance_variables.include?(:@annotations)
|
16
|
+
mod.instance_variable_get(:@annotations).concat self.instance_variable_get(:@annotations)
|
17
|
+
end
|
18
|
+
|
19
|
+
def extended(obj)
|
20
|
+
attrs = self.instance_variable_get("@annotations")
|
21
|
+
|
22
|
+
obj.instance_variable_set(:@annotations, []) unless obj.instance_variables.include?(:@annotations)
|
23
|
+
obj.annotation_types << self
|
24
|
+
|
25
|
+
annotations = obj.instance_variable_get(:@annotations)
|
26
|
+
annotations.concat attrs
|
27
|
+
end
|
28
|
+
|
29
|
+
def setup(*args,&block)
|
30
|
+
if block_given?
|
31
|
+
obj, rest = block, args
|
32
|
+
else
|
33
|
+
obj, *rest = args
|
34
|
+
end
|
35
|
+
obj = block if obj.nil?
|
36
|
+
return nil if obj.nil?
|
37
|
+
obj.extend self unless self === obj
|
38
|
+
attrs = self.instance_variable_get("@annotations")
|
39
|
+
|
40
|
+
return obj if attrs.nil? || attrs.empty?
|
41
|
+
|
42
|
+
if rest.length == 1 && Hash === (rlast = rest.last) &&
|
43
|
+
((! (rlkey = rlast.keys.first).nil? && attrs.include?(rlkey.to_sym)) ||
|
44
|
+
(! attrs.length != 1 ))
|
45
|
+
|
46
|
+
pairs = rlast
|
47
|
+
else
|
48
|
+
pairs = attrs.zip(rest)
|
49
|
+
end
|
50
|
+
|
51
|
+
pairs.each do |name,value|
|
52
|
+
next if name.to_sym === :annotation_types
|
53
|
+
obj.instance_variable_set("@#{name}", value) unless value.nil?
|
54
|
+
end
|
55
|
+
|
56
|
+
obj
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module AnnotatedArray
|
2
|
+
|
3
|
+
module AnnotatedArrayItem
|
4
|
+
attr_accessor :container, :container_index
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.is_contained?(obj)
|
8
|
+
AnnotatedArrayItem === obj
|
9
|
+
end
|
10
|
+
|
11
|
+
def annotate_item(obj, position = nil)
|
12
|
+
obj = obj.dup if obj.frozen?
|
13
|
+
obj.extend AnnotatedArray if Array === obj
|
14
|
+
obj.extend AnnotatedArrayItem
|
15
|
+
obj.container = self
|
16
|
+
obj.container_index = position
|
17
|
+
self.annotate(obj)
|
18
|
+
end
|
19
|
+
|
20
|
+
def [](pos, clean = false)
|
21
|
+
item = super(pos)
|
22
|
+
return item if item.nil? or clean
|
23
|
+
annotate_item(item, pos)
|
24
|
+
end
|
25
|
+
|
26
|
+
def first
|
27
|
+
annotate_item(super, 0)
|
28
|
+
end
|
29
|
+
|
30
|
+
def last
|
31
|
+
annotate_item(super, self.length - 1)
|
32
|
+
end
|
33
|
+
|
34
|
+
def each_with_index(&block)
|
35
|
+
super do |item,i|
|
36
|
+
block.call annotate_item(item, i)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def each(&block)
|
41
|
+
i = 0
|
42
|
+
super do |item|
|
43
|
+
block.call annotate_item(item, i)
|
44
|
+
i += 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def inject(acc, &block)
|
49
|
+
each do |item|
|
50
|
+
acc = block.call acc, item
|
51
|
+
end
|
52
|
+
acc
|
53
|
+
end
|
54
|
+
|
55
|
+
def collect(&block)
|
56
|
+
if block_given?
|
57
|
+
inject([]){|acc,item| acc.push(block.call(item)); acc }
|
58
|
+
else
|
59
|
+
inject([]){|acc,item| acc.push(item); acc }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
%w(compact uniq flatten reverse sort_by).each do |method|
|
64
|
+
|
65
|
+
self.define_method(method) do |*args|
|
66
|
+
res = super(*args)
|
67
|
+
|
68
|
+
annotate(res)
|
69
|
+
res.extend AnnotatedArray
|
70
|
+
|
71
|
+
res
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require_relative 'annotation/array'
|
2
|
+
require_relative 'annotation/annotated_object'
|
3
|
+
require_relative 'annotation/annotation_module'
|
4
|
+
|
5
|
+
module Annotation
|
6
|
+
|
7
|
+
def self.setup(obj, annotation_types, annotation_hash)
|
8
|
+
return nil if obj.nil?
|
9
|
+
annotation_types = annotation_types.split("|") if String === annotation_types
|
10
|
+
annotation_types = [annotation_types] unless Array === annotation_types
|
11
|
+
annotation_types.each do |type|
|
12
|
+
type = Kernel.const_get(type) if String === type
|
13
|
+
type.setup(obj, annotation_hash)
|
14
|
+
end
|
15
|
+
obj
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.extended(base)
|
19
|
+
base.instance_variable_set(:@annotations, []) unless base.instance_variables.include?(:@annotations)
|
20
|
+
base.include Annotation::AnnotatedObject
|
21
|
+
base.extend Annotation::AnnotationModule
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.is_annotated?(obj)
|
25
|
+
obj.instance_variables.include?(:@annotation_types)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.purge(obj)
|
29
|
+
case obj
|
30
|
+
when nil
|
31
|
+
nil
|
32
|
+
when Array
|
33
|
+
obj = obj.purge if is_annotated?(obj)
|
34
|
+
obj.collect{|e| purge(e) }
|
35
|
+
when Hash
|
36
|
+
new = {}
|
37
|
+
obj.each do |k,v|
|
38
|
+
new[purge(k)] = purge(v)
|
39
|
+
end
|
40
|
+
new
|
41
|
+
else
|
42
|
+
is_annotated?(obj) ? obj.purge : obj
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/scout/config.rb
CHANGED
@@ -17,16 +17,16 @@ module Scout::Config
|
|
17
17
|
|
18
18
|
def self.load_file(file)
|
19
19
|
Log.debug "Loading config file: #{ file }"
|
20
|
-
|
20
|
+
Open.read(file).split("\n").each do |line|
|
21
21
|
next if line =~ /^#/
|
22
|
-
key, value, *tokens = line.strip.split(/\s
|
22
|
+
key, value, *tokens = line.strip.split(/\s+/)
|
23
23
|
|
24
24
|
self.add_entry(key, value, tokens) if key
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
28
|
def self.load_config
|
29
|
-
|
29
|
+
Path.setup("etc").config.find_all.reverse.each do |file|
|
30
30
|
self.load_file(file)
|
31
31
|
end
|
32
32
|
end
|
data/lib/scout/exceptions.rb
CHANGED
@@ -28,7 +28,8 @@ module IndiferentHash
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def self.pull_keys(hash, prefix)
|
31
|
-
|
31
|
+
IndiferentHash.setup(hash)
|
32
|
+
new = hash.include?("#{prefix}_options") ? hash.delete("#{prefix}_options") : {}
|
32
33
|
prefix = prefix.to_s
|
33
34
|
hash.keys.each do |key|
|
34
35
|
if key.to_s =~ /#{ prefix }_(.*)/
|
data/lib/scout/log/color.rb
CHANGED
data/lib/scout/log.rb
CHANGED
@@ -109,20 +109,19 @@ module Log
|
|
109
109
|
|
110
110
|
def self.logfile(file=nil)
|
111
111
|
if file.nil?
|
112
|
-
|
112
|
+
@@logfile = nil
|
113
113
|
else
|
114
114
|
case file
|
115
115
|
when String
|
116
|
-
|
117
|
-
|
116
|
+
@@logfile = File.open(file, :mode => 'a')
|
117
|
+
@@logfile.sync = true
|
118
118
|
when IO, File
|
119
|
-
|
119
|
+
@@logfile = file
|
120
120
|
else
|
121
121
|
raise "Unkown logfile format: #{file.inspect}"
|
122
122
|
end
|
123
123
|
end
|
124
124
|
end
|
125
|
-
|
126
125
|
def self.up_lines(num = 1)
|
127
126
|
nocolor ? "" : "\033[#{num+1}F\033[2K"
|
128
127
|
end
|
@@ -142,26 +141,26 @@ module Log
|
|
142
141
|
MUTEX = Mutex.new
|
143
142
|
def self.log_write(str)
|
144
143
|
MUTEX.synchronize do
|
145
|
-
if logfile
|
144
|
+
if defined?(@@logfile) && @@logfile
|
145
|
+
@@logfile.write str
|
146
|
+
else
|
146
147
|
begin
|
147
148
|
STDERR.write str
|
148
149
|
rescue
|
149
150
|
end
|
150
|
-
else
|
151
|
-
logfile.write str
|
152
151
|
end
|
153
152
|
end
|
154
153
|
end
|
155
154
|
|
156
155
|
def self.log_puts(str)
|
157
156
|
MUTEX.synchronize do
|
158
|
-
if logfile
|
157
|
+
if defined?(@@logfile) && @@logfile
|
158
|
+
@@logfile.puts str
|
159
|
+
else
|
159
160
|
begin
|
160
161
|
STDERR.puts str
|
161
162
|
rescue
|
162
163
|
end
|
163
|
-
else
|
164
|
-
logfile.puts str
|
165
164
|
end
|
166
165
|
end
|
167
166
|
end
|
@@ -309,6 +308,7 @@ module Log
|
|
309
308
|
end
|
310
309
|
end
|
311
310
|
end
|
311
|
+
Log::LAST.replace "log"
|
312
312
|
end
|
313
313
|
|
314
314
|
def self.stack(stack)
|
data/lib/scout/misc/digest.rb
CHANGED
@@ -5,14 +5,24 @@ module Misc
|
|
5
5
|
obj.digest_str
|
6
6
|
else
|
7
7
|
case obj
|
8
|
-
when
|
9
|
-
|
10
|
-
|
11
|
-
'\'' << obj << '\''
|
12
|
-
elsif File.directory?(obj)
|
8
|
+
when Path
|
9
|
+
case
|
10
|
+
when File.directory?(obj)
|
13
11
|
"Directory MD5: #{digest_str(Dir.glob(File.join(obj, "*")))}"
|
12
|
+
when obj.located? && File.exist?(obj)
|
13
|
+
"File MD5: #{Misc.digest_file(obj)}"
|
14
14
|
else
|
15
|
-
|
15
|
+
'\'' << obj << '\''
|
16
|
+
end
|
17
|
+
when String
|
18
|
+
if Path.is_filename?(obj) && Open.exists?(obj)
|
19
|
+
if File.directory?(obj)
|
20
|
+
"Directory MD5: #{digest_str(Dir.glob(File.join(obj, "*")))}"
|
21
|
+
else
|
22
|
+
"File MD5: #{Misc.digest_file(obj)}"
|
23
|
+
end
|
24
|
+
else
|
25
|
+
obj.dup
|
16
26
|
end
|
17
27
|
when Integer, Symbol
|
18
28
|
obj.to_s
|
@@ -57,8 +67,29 @@ module Misc
|
|
57
67
|
def self.file_md5(file)
|
58
68
|
file = file.find if Path === file
|
59
69
|
file = File.expand_path(file)
|
60
|
-
|
61
|
-
|
70
|
+
Digest::MD5.file(file).hexdigest
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.fast_file_md5(file, sample = 3_000_000)
|
74
|
+
size = File.size(file)
|
75
|
+
sample_txt = size.to_s << ":"
|
76
|
+
File.open(file) do |f|
|
77
|
+
sample_txt << f.read(sample)
|
78
|
+
f.seek(size/2)
|
79
|
+
sample_txt << f.read(sample)
|
80
|
+
f.seek(size - sample - 1)
|
81
|
+
sample_txt << f.read(sample)
|
82
|
+
end
|
83
|
+
Digest::MD5.hexdigest(sample_txt)
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.digest_file(file)
|
87
|
+
file = file.find if Path === file
|
88
|
+
file = File.expand_path(file)
|
89
|
+
if File.size(file) > 10_000_000
|
90
|
+
fast_file_md5(file)
|
91
|
+
else
|
92
|
+
file_md5(file)
|
62
93
|
end
|
63
94
|
end
|
64
95
|
end
|
@@ -22,4 +22,27 @@ module Misc
|
|
22
22
|
return nil
|
23
23
|
end
|
24
24
|
end
|
25
|
+
|
26
|
+
def self.tarize(path, dest = nil)
|
27
|
+
Misc.in_dir(path) do
|
28
|
+
if dest
|
29
|
+
CMD.cmd("tar cvfz '#{dest}' '.'")
|
30
|
+
else
|
31
|
+
CMD.cmd("tar cvfz - '.'", :pipe => true)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.untar(file, target = '.')
|
37
|
+
target = target.find if Path === target
|
38
|
+
file = file.find if Path === file
|
39
|
+
Misc.in_dir target do
|
40
|
+
if IO === file
|
41
|
+
CMD.cmd("tar xvfz -", in: file)
|
42
|
+
else
|
43
|
+
CMD.cmd("tar xvfz '#{file}'")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
25
48
|
end
|
data/lib/scout/misc/format.rb
CHANGED
@@ -252,4 +252,36 @@ module Misc
|
|
252
252
|
end
|
253
253
|
values
|
254
254
|
end
|
255
|
+
|
256
|
+
def self.timespan(str, default = "s")
|
257
|
+
|
258
|
+
return - timespan(str[1..-1], default) if str[0] == "-"
|
259
|
+
|
260
|
+
if str.include?(":")
|
261
|
+
seconds, minutes, hours = str.split(":").reverse
|
262
|
+
return seconds.to_i + minutes.to_i * 60 + hours.to_i * 60 * 60
|
263
|
+
end
|
264
|
+
|
265
|
+
tokens = {
|
266
|
+
"s" => (1),
|
267
|
+
"sec" => (1),
|
268
|
+
"m" => (60),
|
269
|
+
"min" => (60),
|
270
|
+
"''" => (1),
|
271
|
+
"'" => (60),
|
272
|
+
"h" => (60 * 60),
|
273
|
+
"d" => (60 * 60 * 24),
|
274
|
+
"w" => (60 * 60 * 24 * 7),
|
275
|
+
"mo" => (60 * 60 * 24 * 31),
|
276
|
+
"y" => (60 * 60 * 24 * 365),
|
277
|
+
}
|
278
|
+
|
279
|
+
tokens[nil] = tokens[default]
|
280
|
+
tokens[""] = tokens[default]
|
281
|
+
time = 0
|
282
|
+
str.scan(/(\d+)(\w*)/).each do |amount, measure|
|
283
|
+
time += amount.to_i * tokens[measure]
|
284
|
+
end
|
285
|
+
time
|
286
|
+
end
|
255
287
|
end
|
data/lib/scout/misc/helper.rb
CHANGED
@@ -28,4 +28,41 @@ module Misc
|
|
28
28
|
counts
|
29
29
|
end
|
30
30
|
|
31
|
+
def self.chunk(array, num)
|
32
|
+
total = array.length
|
33
|
+
current = 0
|
34
|
+
while current < total
|
35
|
+
last = current + num - 1
|
36
|
+
yield array[current..last]
|
37
|
+
current = last + 1
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Divides the array into +num+ chunks of the same size by placing one
|
42
|
+
# element in each chunk iteratively.
|
43
|
+
def self.divide(array, num)
|
44
|
+
num = 1 if num == 0
|
45
|
+
chunks = []
|
46
|
+
num.to_i.times do chunks << [] end
|
47
|
+
array.each_with_index{|e, i|
|
48
|
+
c = i % num
|
49
|
+
chunks[c] << e
|
50
|
+
}
|
51
|
+
chunks
|
52
|
+
end
|
53
|
+
|
54
|
+
# Divides the array into chunks of +num+ same size by placing one
|
55
|
+
# element in each chunk iteratively.
|
56
|
+
def self.ordered_divide(array, num)
|
57
|
+
last = array.length - 1
|
58
|
+
chunks = []
|
59
|
+
current = 0
|
60
|
+
while current <= last
|
61
|
+
next_current = [last, current + num - 1].min
|
62
|
+
chunks << array[current..next_current]
|
63
|
+
current = next_current + 1
|
64
|
+
end
|
65
|
+
chunks
|
66
|
+
end
|
67
|
+
|
31
68
|
end
|