eco-helpers 1.1.5 → 1.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/eco-helpers.gemspec +0 -2
- data/lib/eco-helpers.rb +0 -1
- data/lib/eco/api.rb +0 -1
- data/lib/eco/api/common/people/person_entry_attribute_mapper.rb +41 -21
- data/lib/eco/api/session/batch/feedback.rb +4 -1
- data/lib/eco/api/session/batch/job.rb +1 -1
- data/lib/eco/api/session/batch/status.rb +8 -7
- data/lib/eco/api/session/config/workflow.rb +1 -1
- data/lib/eco/data.rb +0 -1
- data/lib/eco/version.rb +1 -1
- metadata +1 -47
- data/lib/eco/api/eco_faker.rb +0 -59
- data/lib/eco/data/random.rb +0 -10
- data/lib/eco/data/random/distribution.rb +0 -133
- data/lib/eco/data/random/fake.rb +0 -320
- data/lib/eco/data/random/values.rb +0 -80
- data/lib/eco/tester.rb +0 -97
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0c1cca427dcc2ced629146debcbe71a05f062002919b68b32e88ebddd86c25c
|
4
|
+
data.tar.gz: e74e5b3c8007af145e1255903a4a1a26dc785b84004434291524275a5ac38734
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55e089b0827e28aafb5ac51e5b7ff37a09a81ab71160087080ecff70a10a44397dec6d0e2d847f8a5767b52c44a6ae548affd06c28a6e4ccb3d2edf37472f81a
|
7
|
+
data.tar.gz: 4801acfeedc39e1287808f812845c915316e0bac92d16594fe412899483104cba6604f30e1cf717dae6438c2f4e69a4e1adb1ea7af863d3a2a27273a36b1ec3a
|
data/eco-helpers.gemspec
CHANGED
@@ -33,7 +33,5 @@ Gem::Specification.new do |s|
|
|
33
33
|
s.add_dependency 'aws-sdk-ses', '~> 1.14', '>= 1.14.0'
|
34
34
|
s.add_dependency 'dotenv', '~> 2.6', '>= 2.6.0'
|
35
35
|
s.add_dependency 'net-sftp', '~> 2.1', '>= 2.1.2'
|
36
|
-
s.add_dependency 'faker', '~> 2', '>= 2.1'
|
37
|
-
s.add_dependency 'distribution', '~> 0.7', '>= 0.7.3'
|
38
36
|
|
39
37
|
end
|
data/lib/eco-helpers.rb
CHANGED
data/lib/eco/api.rb
CHANGED
@@ -31,10 +31,10 @@ module Eco
|
|
31
31
|
raise "Constructor needs a PersonParser. Given: #{parser}" if !person_parser.is_a?(Eco::API::Common::People::PersonParser)
|
32
32
|
raise "Expecting Mapper object. Given: #{attr_map}" if attr_map && !attr_map.is_a?(Eco::Data::Mapper)
|
33
33
|
|
34
|
-
@source
|
34
|
+
@source = data
|
35
35
|
@person_parser = person_parser
|
36
|
-
@attr_map
|
37
|
-
@logger
|
36
|
+
@attr_map = attr_map
|
37
|
+
@logger = logger
|
38
38
|
|
39
39
|
if parsing?
|
40
40
|
@external_entry = data
|
@@ -142,34 +142,54 @@ module Eco
|
|
142
142
|
|
143
143
|
# when parsing:
|
144
144
|
def init_attr_trackers
|
145
|
-
# internal
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
#
|
150
|
-
|
151
|
-
|
145
|
+
# (def) all internal attributes we can expect
|
146
|
+
def_all_attrs = @person_parser.all_attrs
|
147
|
+
# (def) internal attrs with no aliasing nor parser definition (expected to be direct)
|
148
|
+
def_unlinked = @person_parser.undefined_attrs.select { |attr| !to_external(attr) }
|
149
|
+
# (def) those with parser or alias:
|
150
|
+
def_linked = def_all_attrs - def_unlinked
|
151
|
+
|
152
|
+
# (data) data attributes (actual attributes of the entry)
|
153
|
+
data_attrs = attributes(@external_entry)
|
154
|
+
# (data) attributes of the data that come directly as internal attribute names
|
155
|
+
data_direct_attrs = data_attrs & def_all_attrs
|
156
|
+
|
157
|
+
# (def) configured as alised (internal <-> external attributes)
|
158
|
+
def_int_aliased = def_all_attrs.select { |attr| to_external(attr) }
|
159
|
+
def_ext_alias = def_int_aliased.map { |attr| to_external(attr) }
|
160
|
+
|
161
|
+
# (data) virtual attrs (external alias of non native internal attr in data):
|
162
|
+
data_vi_ext_alias = data_attrs.select do |attr|
|
163
|
+
!def_ext_alias.include?(attr) && @attr_map&.external?(attr)
|
152
164
|
end
|
153
|
-
|
154
|
-
|
155
|
-
int_vi_aliased = ext_vi_aliased.map do |attr|
|
165
|
+
# (data) virtual internal attrs (the internal names of those virtual attrs)
|
166
|
+
data_vi_int_aliased = data_vi_ext_alias.map do |attr|
|
156
167
|
# to_internal(attr) can't be used here, becauase virtual fields would get filtered out,
|
157
168
|
# as they are not recognized by @parser.all_attrs.include?(attr)
|
158
169
|
@attr_map.to_internal(attr)
|
159
170
|
end.compact
|
160
171
|
|
161
|
-
|
172
|
+
# (data) attrs that could come aliased in the current data
|
173
|
+
# => modify aliased based on those that came directly as internal attrs in the entry
|
174
|
+
data_def_int_aliased = def_int_aliased - data_direct_attrs
|
175
|
+
data_def_ext_alias = data_def_int_aliased.map { |attr| to_external(attr) }
|
176
|
+
# (data) actual attrs of the data that come aliased
|
177
|
+
data_ext_alias = data_def_ext_alias & data_attrs
|
162
178
|
|
163
|
-
|
164
|
-
|
165
|
-
|
179
|
+
# (data) all internal attributes that could come aliased, with given the entry
|
180
|
+
@aliased_attrs = data_def_int_aliased + data_vi_int_aliased
|
181
|
+
# (data) all those ext attrs present that will require aliasing
|
182
|
+
#data_ext_alias_all = data_def_ext_alias + data_vi_ext_alias
|
183
|
+
data_ext_alias_all = data_ext_alias + data_vi_ext_alias
|
166
184
|
|
167
|
-
ext_aliased = ext_alias + ext_vi_aliased
|
168
185
|
# those that are direct external to internal:
|
169
|
-
|
186
|
+
data_ext_direct = data_attrs - data_ext_alias_all
|
187
|
+
|
188
|
+
# (data) attributes that do not require aliasing
|
170
189
|
# to avoid collisions between internal names:
|
171
|
-
|
172
|
-
@
|
190
|
+
#@direct_attrs = data_ext_direct - def_linked
|
191
|
+
@direct_attrs = data_ext_direct
|
192
|
+
@internal_attrs = @aliased_attrs | @direct_attrs
|
173
193
|
end
|
174
194
|
|
175
195
|
def attributes(value)
|
@@ -100,8 +100,11 @@ module Eco
|
|
100
100
|
end
|
101
101
|
msg << "#{sample.slice(0, sample_length).pretty_inspect}"
|
102
102
|
end
|
103
|
-
|
103
|
+
stats_str = "#{"+"*3} #{type.to_s.upcase} length: #{requests.length} #{"+"*3} STATS (job '#{name}') #{"+"*3}"
|
104
|
+
msg << "#{"-"*stats_str.length}" if only_stats
|
105
|
+
msg << stats_str
|
104
106
|
msg << "#{request_stats(requests).message}"
|
107
|
+
msg << "#{"-"*stats_str.length}" if only_stats
|
105
108
|
msg << "*" * header.length unless only_stats
|
106
109
|
end
|
107
110
|
end.join("\n")
|
@@ -29,7 +29,7 @@ module Eco
|
|
29
29
|
attr_reader :usecase
|
30
30
|
attr_reader :status, :feedback
|
31
31
|
|
32
|
-
# @param e [Eco::API::Common::Session::Environment] requires a session
|
32
|
+
# @param e [Eco::API::Common::Session::Environment] requires a session environment, as any child of `Eco::API::Common::Session::BaseSession`
|
33
33
|
# @param name [String] the name of this `batch job`
|
34
34
|
# @param type [Symbol] a valid batch operation
|
35
35
|
# @param usecase [Eco::API::UseCases::UseCase, nil] when provided: `usecase` that generated this `batch job`
|
@@ -27,7 +27,7 @@ module Eco
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
# @param e [Eco::API::Common::Session::Environment] requires a session
|
30
|
+
# @param e [Eco::API::Common::Session::Environment] requires a session environment, as any child of `Eco::API::Common::Session::BaseSession`
|
31
31
|
# @param queue [Array<Hash>, Array<Ecoportal::API::V1::Person>, Array<Ecoportal::API::Internal::Person>] the `source_queue`
|
32
32
|
# @param method [Symbol] the type of `batch operation`
|
33
33
|
# @param mode [Symbol] the mode of `batch operation` (search)
|
@@ -83,7 +83,7 @@ module Eco
|
|
83
83
|
# 1. `Integer`: index/position of the entry in the final `queue`
|
84
84
|
# 2. `Hash`: entry queries can be raw `Hash` objects
|
85
85
|
# 3. `Person` object: the most common case is to use the person wrapper classes of the `Ecoportal::API` namespace.
|
86
|
-
# @return
|
86
|
+
# @return [Ecoportal::API::Common::BatchResponse]
|
87
87
|
def [](key)
|
88
88
|
@responses[to_index(key)]
|
89
89
|
end
|
@@ -97,10 +97,10 @@ module Eco
|
|
97
97
|
end
|
98
98
|
|
99
99
|
# The _person_ we got from the Server wrapped to the `Person` object for the input entry object `key`
|
100
|
-
# @note it only makes sense when the batch method
|
100
|
+
# @note it only makes sense when the used batch method was `get`
|
101
101
|
# @param key [Integer, Hash, Ecoportal::API::V1::Person, Ecoportal::API::Internal::Person]
|
102
102
|
# @see Eco::API::Session::Batch::Status#[] for `key` options
|
103
|
-
# return [Ecoportal::API::V1::Person, Ecoportal::API::Internal::Person]
|
103
|
+
# @return [Ecoportal::API::V1::Person, Ecoportal::API::Internal::Person]
|
104
104
|
def person(key)
|
105
105
|
return self[key].result if success?(key)
|
106
106
|
nil
|
@@ -112,7 +112,7 @@ module Eco
|
|
112
112
|
# - **found using a search criteria** (`mode` == `:search`), as opposite to find the person directly by `external_id`
|
113
113
|
# @param key [Integer, Hash, Ecoportal::API::V1::Person, Ecoportal::API::Internal::Person]
|
114
114
|
# @see Eco::API::Session::Batch::Status#[] for `key` options
|
115
|
-
# return [Ecoportal::API::V1::Person, Ecoportal::API::Internal::Person]
|
115
|
+
# @return [Ecoportal::API::V1::Person, Ecoportal::API::Internal::Person]
|
116
116
|
def person_match(key)
|
117
117
|
@person_match[to_index(key)]
|
118
118
|
end
|
@@ -130,14 +130,14 @@ module Eco
|
|
130
130
|
end
|
131
131
|
|
132
132
|
# Has the _entry_ `key` been queried to the server?
|
133
|
-
# @param key [Hash, Ecoportal::API::V1::Person, Ecoportal::API::Internal::Person]
|
133
|
+
# @param key [Integer, Hash, Ecoportal::API::V1::Person, Ecoportal::API::Internal::Person]
|
134
134
|
# @return [Boolean] `true` if input entry `key` has an associated `Ecoportal::API::Common::BatchResponse`
|
135
135
|
def received?(key)
|
136
136
|
!!self[key]
|
137
137
|
end
|
138
138
|
|
139
139
|
# Has the _entry_ `key` 's query to the server been successful
|
140
|
-
# @param key [Hash, Ecoportal::API::V1::Person, Ecoportal::API::Internal::Person]
|
140
|
+
# @param key [Integer, Hash, Ecoportal::API::V1::Person, Ecoportal::API::Internal::Person]
|
141
141
|
# @return [Boolean] `true` if input entry `key` has not had a server Error during the query
|
142
142
|
def success?(key)
|
143
143
|
self[key]&.success?
|
@@ -169,6 +169,7 @@ module Eco
|
|
169
169
|
end
|
170
170
|
|
171
171
|
# Helper to transform any `key` to an `Integer` index
|
172
|
+
# @param key [Integer, Hash, Ecoportal::API::V1::Person, Ecoportal::API::Internal::Person]
|
172
173
|
# @return [Integer] the index that `key` has in the final `queue`
|
173
174
|
def to_index(key)
|
174
175
|
key.is_a?(Integer) ? valid_index(index: key) : valid_index(entry: key)
|
data/lib/eco/data.rb
CHANGED
data/lib/eco/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eco-helpers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oscar Segura
|
@@ -198,46 +198,6 @@ dependencies:
|
|
198
198
|
- - ">="
|
199
199
|
- !ruby/object:Gem::Version
|
200
200
|
version: 2.1.2
|
201
|
-
- !ruby/object:Gem::Dependency
|
202
|
-
name: faker
|
203
|
-
requirement: !ruby/object:Gem::Requirement
|
204
|
-
requirements:
|
205
|
-
- - "~>"
|
206
|
-
- !ruby/object:Gem::Version
|
207
|
-
version: '2'
|
208
|
-
- - ">="
|
209
|
-
- !ruby/object:Gem::Version
|
210
|
-
version: '2.1'
|
211
|
-
type: :runtime
|
212
|
-
prerelease: false
|
213
|
-
version_requirements: !ruby/object:Gem::Requirement
|
214
|
-
requirements:
|
215
|
-
- - "~>"
|
216
|
-
- !ruby/object:Gem::Version
|
217
|
-
version: '2'
|
218
|
-
- - ">="
|
219
|
-
- !ruby/object:Gem::Version
|
220
|
-
version: '2.1'
|
221
|
-
- !ruby/object:Gem::Dependency
|
222
|
-
name: distribution
|
223
|
-
requirement: !ruby/object:Gem::Requirement
|
224
|
-
requirements:
|
225
|
-
- - "~>"
|
226
|
-
- !ruby/object:Gem::Version
|
227
|
-
version: '0.7'
|
228
|
-
- - ">="
|
229
|
-
- !ruby/object:Gem::Version
|
230
|
-
version: 0.7.3
|
231
|
-
type: :runtime
|
232
|
-
prerelease: false
|
233
|
-
version_requirements: !ruby/object:Gem::Requirement
|
234
|
-
requirements:
|
235
|
-
- - "~>"
|
236
|
-
- !ruby/object:Gem::Version
|
237
|
-
version: '0.7'
|
238
|
-
- - ">="
|
239
|
-
- !ruby/object:Gem::Version
|
240
|
-
version: 0.7.3
|
241
201
|
description:
|
242
202
|
email:
|
243
203
|
- oscar@ecoportal.co.nz
|
@@ -291,7 +251,6 @@ files:
|
|
291
251
|
- lib/eco/api/common/version_patches/exception.rb
|
292
252
|
- lib/eco/api/common/version_patches/hash.rb
|
293
253
|
- lib/eco/api/common/version_patches/hash/deep_merge.rb
|
294
|
-
- lib/eco/api/eco_faker.rb
|
295
254
|
- lib/eco/api/error.rb
|
296
255
|
- lib/eco/api/error/handler.rb
|
297
256
|
- lib/eco/api/error/handlers.rb
|
@@ -390,10 +349,6 @@ files:
|
|
390
349
|
- lib/eco/data/files/file_pattern.rb
|
391
350
|
- lib/eco/data/files/helpers.rb
|
392
351
|
- lib/eco/data/mapper.rb
|
393
|
-
- lib/eco/data/random.rb
|
394
|
-
- lib/eco/data/random/distribution.rb
|
395
|
-
- lib/eco/data/random/fake.rb
|
396
|
-
- lib/eco/data/random/values.rb
|
397
352
|
- lib/eco/language.rb
|
398
353
|
- lib/eco/language/curry.rb
|
399
354
|
- lib/eco/language/hash_transform.rb
|
@@ -406,7 +361,6 @@ files:
|
|
406
361
|
- lib/eco/language/models/parser_serializer.rb
|
407
362
|
- lib/eco/language/models/wrap.rb
|
408
363
|
- lib/eco/language/values_at.rb
|
409
|
-
- lib/eco/tester.rb
|
410
364
|
- lib/eco/version.rb
|
411
365
|
homepage: https://www.ecoportal.com
|
412
366
|
licenses:
|
data/lib/eco/api/eco_faker.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
module Eco
|
2
|
-
module API
|
3
|
-
# faker object
|
4
|
-
@@faker = nil
|
5
|
-
class EcoFaker
|
6
|
-
@@api = nil
|
7
|
-
@org = nil
|
8
|
-
# attr_accessor
|
9
|
-
attr_reader :org
|
10
|
-
def initialize(init = {})
|
11
|
-
set_settings(init)
|
12
|
-
end
|
13
|
-
# allows to change certain configuration settings on an existing Faker instance object
|
14
|
-
def set_settings (init = {})
|
15
|
-
@today = (aux = init['today'])? aux : Time.now
|
16
|
-
api = init.fetch('api', nil)
|
17
|
-
@@api = api.instance_of?(Ecoportal::API::Internal) && api
|
18
|
-
# this will initialize org basics (i.e. people_schemas, policy_groups, login_providers)
|
19
|
-
@org = Organization.new(init)
|
20
|
-
end
|
21
|
-
def newPerson ()
|
22
|
-
|
23
|
-
end
|
24
|
-
def modifyPerson(person)
|
25
|
-
|
26
|
-
end
|
27
|
-
private
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.new(init = {})
|
31
|
-
@@faker = EcoFaker.new(init)
|
32
|
-
end
|
33
|
-
|
34
|
-
class FakePerson < Ecoportal::API::Internal::Person
|
35
|
-
@@faker
|
36
|
-
def initialize(faker, *args)
|
37
|
-
raise "You must initialize the faker first" unless faker && faker.instance_of(Faker)
|
38
|
-
@@faker = faker
|
39
|
-
super(*args)
|
40
|
-
@@faker.set_details
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
class FakeField
|
45
|
-
@@types = ["boolean", "number", "text", "select", "date", "phone_number"]
|
46
|
-
@@multiple = false
|
47
|
-
attr_accessor :type, :multiple
|
48
|
-
#attr_reader
|
49
|
-
def initialize (init = {})
|
50
|
-
init_values_generator(init)
|
51
|
-
end
|
52
|
-
private
|
53
|
-
def init_values_faker (init = {})
|
54
|
-
include
|
55
|
-
@fake_values = API::Data::Random::ValuesGenerator.new(init)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
data/lib/eco/data/random.rb
DELETED
@@ -1,133 +0,0 @@
|
|
1
|
-
require 'distribution' # source: https://github.com/sciruby/distribution
|
2
|
-
|
3
|
-
# todo: remove distribution dependency by developing a normal distribution generator
|
4
|
-
# - Reference: https://stackoverflow.com/a/6178290/4352306
|
5
|
-
|
6
|
-
module Eco
|
7
|
-
module Data
|
8
|
-
module Random
|
9
|
-
class Distribution
|
10
|
-
|
11
|
-
MAX_DECIMALS = 10
|
12
|
-
BALANCE = ["uniform", "normal", "half-normal", "forged"]
|
13
|
-
|
14
|
-
attr_accessor :decimals
|
15
|
-
attr_reader :calls
|
16
|
-
attr_reader :range, :min, :max, :balance, :mean, :sigma
|
17
|
-
attr_reader :weights, :weights_distribution
|
18
|
-
def initialize(init = {})
|
19
|
-
@calls = 0
|
20
|
-
@weight_positions = 0
|
21
|
-
|
22
|
-
@decimals = init.fetch('decimals', MAX_DECIMALS)
|
23
|
-
self.range = init.fetch('range', 0..1)
|
24
|
-
self.weights = init.fetch('weights', nil)
|
25
|
-
self.balance = init.fetch('balance', nil)
|
26
|
-
|
27
|
-
@normal = ::Distribution::Normal.rng(@mean, @sigma)
|
28
|
-
@random = ::Random.new
|
29
|
-
end
|
30
|
-
|
31
|
-
def balance=(value)
|
32
|
-
@balance = value
|
33
|
-
@balance = BALANCE[0] if !BALANCE.include?(@balance)
|
34
|
-
case @balance
|
35
|
-
when 'forged'
|
36
|
-
if @weights&.instance_of?(Array)
|
37
|
-
top = @weights.length - 1
|
38
|
-
self.range = (0..top)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def range=(value)
|
44
|
-
@range = value
|
45
|
-
@min = @range.first; @max = @range.last
|
46
|
-
@mean = @max / 2
|
47
|
-
@sigma = (@max - @mean) / 3.5
|
48
|
-
end
|
49
|
-
|
50
|
-
def weights=(value)
|
51
|
-
@weights = nil; @weights_distribution = nil; @weight_positions = 0
|
52
|
-
@weights = value if value && value.instance_of?(Array)
|
53
|
-
if @weights
|
54
|
-
total = @weights.inject(0, :+)
|
55
|
-
@weight_positions = total * 20
|
56
|
-
@weights_distribution = Array.new(@weight_positions)
|
57
|
-
|
58
|
-
i = 0; j = 0
|
59
|
-
while i < @weights.length
|
60
|
-
positions = (@weights[i] * @weight_positions / total).round
|
61
|
-
positions.times do
|
62
|
-
@weights_distribution[j] = i
|
63
|
-
j += 1
|
64
|
-
end
|
65
|
-
i += 1
|
66
|
-
end
|
67
|
-
if (missing = @weight_positions - j) >= 0
|
68
|
-
(missing + 1).times {
|
69
|
-
@weights_distribution[j] = 0
|
70
|
-
j += 1
|
71
|
-
}
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def generate
|
77
|
-
@calls += 1
|
78
|
-
case @balance
|
79
|
-
when 'uniform'
|
80
|
-
num = generate_uniform
|
81
|
-
when 'normal'
|
82
|
-
num = generate_normal
|
83
|
-
when 'half-normal'
|
84
|
-
num = generate_half_normal
|
85
|
-
when 'forged'
|
86
|
-
num = generate_forged
|
87
|
-
else
|
88
|
-
num = generate_uniform
|
89
|
-
end
|
90
|
-
|
91
|
-
num = generate if num && !@range.member?(num.round)
|
92
|
-
return num && num.round(@decimals)
|
93
|
-
end
|
94
|
-
|
95
|
-
private
|
96
|
-
|
97
|
-
def generate_uniform
|
98
|
-
@random.rand(@range)
|
99
|
-
end
|
100
|
-
|
101
|
-
def generate_normal
|
102
|
-
@normal.call
|
103
|
-
end
|
104
|
-
|
105
|
-
def generate_half_normal
|
106
|
-
num = generate_normal
|
107
|
-
num = normal_mirror(num, @mean) if num.round < @mean
|
108
|
-
num = generate_half_normal if num.round == @mean
|
109
|
-
num -= @mean
|
110
|
-
num = num - 1 if num.round > 0 # move distribution to left (mirroring doubles density except at mean)
|
111
|
-
return num
|
112
|
-
end
|
113
|
-
|
114
|
-
def generate_forged
|
115
|
-
#raise "You need to assign weights to be able to use the forge balance!" if !@weights_distribution&.instance_of?(Array)
|
116
|
-
if @weights_distribution&.instance_of?(Array)
|
117
|
-
top = @weight_positions - 1
|
118
|
-
pos = @random.rand(0..top)
|
119
|
-
return weights_distribution[pos]
|
120
|
-
end
|
121
|
-
return generate_normal # should raise error at the beginning of the function
|
122
|
-
end
|
123
|
-
|
124
|
-
def normal_mirror (num, mean)
|
125
|
-
return mean + (mean - num) if num.round < mean
|
126
|
-
return mean - (num - mean) if num.round > mean
|
127
|
-
return num
|
128
|
-
end
|
129
|
-
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
data/lib/eco/data/random/fake.rb
DELETED
@@ -1,320 +0,0 @@
|
|
1
|
-
require 'faker'
|
2
|
-
|
3
|
-
module Eco
|
4
|
-
module Data
|
5
|
-
module Random
|
6
|
-
class Fake
|
7
|
-
|
8
|
-
MAX_UNIQUE_ERRORS = 13
|
9
|
-
DEFAULT_LOCALE = 'en'
|
10
|
-
DEFAULT_EMAIL_PATTERN = 'oscar+name@ecoportal.co.nz'
|
11
|
-
LOCALES_MAPS = {'en' => 'en', 'nz' => 'en-NZ', 'ca' => 'en-CA', 'uk' => 'en-GB', 'usa' => 'en-USA'}
|
12
|
-
TOPICS_MAPS = {
|
13
|
-
'general' => ['General', 'Vehicle', 'University', 'Address'],
|
14
|
-
'fantasy' => ['LordOfTheRings', 'Hobbit', 'HarryPotter', 'BackToTheFuture', 'FunnyName', 'GameOfThrones', 'PricesBride', 'StarWars', 'StarkTrek'],
|
15
|
-
'medieval-fantasy' => ['LordOfTheRings', 'Hobbit', 'GameOfThrones', 'PricesBride'],
|
16
|
-
'futuristic-fantasy' => ['BackToTheFuture', 'StarWars', 'StarTrek'],
|
17
|
-
'tolkien' => ['LordOfTheRings', 'Hobbit'],
|
18
|
-
'funny' => ['FunnyName', 'Simpsons', 'Superhero'],
|
19
|
-
'famous' => ['Book', 'GreekPhilosophers' ,'Scientists', 'SiliconValley', 'Space', 'WorldCup'],
|
20
|
-
'philosophers' => 'GreekPhilosophers'
|
21
|
-
}
|
22
|
-
@name = nil; @name_topics = nil
|
23
|
-
@location = nil; @location_topics = nil
|
24
|
-
|
25
|
-
attr_reader :local, :topic, :general_topic_on_fail
|
26
|
-
attr_reader :today, :email_pattern, :unique_errors, :unique_resets, :force_unique
|
27
|
-
|
28
|
-
def initialize(init = {})
|
29
|
-
@unique_resets = 0; @unique_errors = 0
|
30
|
-
init_topics
|
31
|
-
self.topic = init.fetch('topic', TOPICS_MAPS.keys.sample)
|
32
|
-
self.general_topic_on_fail = init.fetch('general_topic_on_fail', false)
|
33
|
-
self.force_unique = init.fetch('force_unique', false)
|
34
|
-
|
35
|
-
self.local = init.fetch('local', nil)
|
36
|
-
self.today = init.fetch('today', Date.today)
|
37
|
-
self.email_pattern = init.fetch('email_pattern', DEFAULT_EMAIL_PATTERN)
|
38
|
-
|
39
|
-
@boolean = Faker::Boolean.method('boolean')
|
40
|
-
@date_between = Faker::Date.method('between')
|
41
|
-
|
42
|
-
@gender = Faker::Gender.method('binary_type')
|
43
|
-
|
44
|
-
@name = get_topic_wrapper(@name_topics)
|
45
|
-
@company = get_topic_wrapper(@company_topics)
|
46
|
-
@location = get_topic_wrapper(@location_topics)
|
47
|
-
|
48
|
-
@community = wrap_method { Faker::Address.community }
|
49
|
-
@address = wrap_method { Faker::Address.unique.full_address }
|
50
|
-
@country = wrap_method { Faker::Address.country }
|
51
|
-
@city = wrap_method { Faker::Address.city }
|
52
|
-
@postcode = wrap_method { Faker::Address.postcode }
|
53
|
-
@timezone = Faker::Address.method('time_zone')
|
54
|
-
|
55
|
-
@phone = wrap_method { Faker::PhoneNumber.unique.phone_number }
|
56
|
-
@mobile = wrap_method { Faker::PhoneNumber.unique.cell_phone }
|
57
|
-
@mobile_code = wrap_method { Faker::Code.unique.imei }
|
58
|
-
end
|
59
|
-
|
60
|
-
def topic=(value)
|
61
|
-
@topic = TOPICS_MAPS.values.first # 'General'
|
62
|
-
@topic = TOPICS_MAPS[value.downcase] if value && TOPICS_MAPS.keys.include?(value.downcase)
|
63
|
-
init_topic_wrappers
|
64
|
-
end
|
65
|
-
|
66
|
-
def general_topic_on_fail=(value)
|
67
|
-
@general_topic_on_fail = value
|
68
|
-
end
|
69
|
-
|
70
|
-
def today=(value)
|
71
|
-
@today = nil
|
72
|
-
@today = value if value.instance_of?(Date)
|
73
|
-
@today = Date.today if !@today
|
74
|
-
end
|
75
|
-
|
76
|
-
def email_pattern=(value)
|
77
|
-
@email_pattern = value
|
78
|
-
@email_pattern = DEFAULT_EMAIL_PATTERN if !@mail_pattern&.include?('@ecoportal.co.nz')
|
79
|
-
end
|
80
|
-
|
81
|
-
def local=(value)
|
82
|
-
@local = DEFAULT_LOCALE
|
83
|
-
alias_locales = LOCALES_MAPS.keys; locales = LOCALES_MAPS.values
|
84
|
-
permitted = value && (alias_locales.include?(value.downcase) || locales.include?(value))
|
85
|
-
@local = LOCALES_MAPS[value.downcase] if permitted
|
86
|
-
::Faker::Config.locale = @local
|
87
|
-
end
|
88
|
-
|
89
|
-
def force_unique=(value)
|
90
|
-
@force_unique = !!value
|
91
|
-
end
|
92
|
-
|
93
|
-
def reset_unique
|
94
|
-
@unique_errors = 0
|
95
|
-
@unique_resets += 1
|
96
|
-
::Faker::UniqueGenerator.clear
|
97
|
-
end
|
98
|
-
|
99
|
-
def boolean
|
100
|
-
@boolean.call
|
101
|
-
end
|
102
|
-
|
103
|
-
def past_date(years = 3)
|
104
|
-
@date_between.call(previous_date(years), @today)
|
105
|
-
end
|
106
|
-
|
107
|
-
def future_date(years = 3)
|
108
|
-
@date_between.call(@today, later_date(years))
|
109
|
-
end
|
110
|
-
|
111
|
-
def birthday(min_age = 18, max_age = 65)
|
112
|
-
@date_between.call(previous_date(min_age), previous_date(max_age))
|
113
|
-
end
|
114
|
-
|
115
|
-
def name
|
116
|
-
new_value = get_unique(@name, @name_topics)
|
117
|
-
@name = get_topic_wrapper(@name_topics)
|
118
|
-
return new_value
|
119
|
-
end
|
120
|
-
|
121
|
-
def company
|
122
|
-
new_value = get_unique(@company, @company_topics)
|
123
|
-
@company = get_topic_wrapper(@company_topics)
|
124
|
-
return new_value
|
125
|
-
end
|
126
|
-
|
127
|
-
def community
|
128
|
-
@community.call
|
129
|
-
end
|
130
|
-
|
131
|
-
def location
|
132
|
-
new_value = get_unique(@location, @location_topics)
|
133
|
-
@location = get_topic_wrapper(@location_topics)
|
134
|
-
return new_value
|
135
|
-
end
|
136
|
-
|
137
|
-
def address
|
138
|
-
@address.call
|
139
|
-
end
|
140
|
-
|
141
|
-
def contry
|
142
|
-
@country.call
|
143
|
-
end
|
144
|
-
|
145
|
-
def city
|
146
|
-
@city.call
|
147
|
-
end
|
148
|
-
|
149
|
-
def postcode
|
150
|
-
@postcode.call
|
151
|
-
end
|
152
|
-
|
153
|
-
def timezone
|
154
|
-
@timezone.call
|
155
|
-
end
|
156
|
-
|
157
|
-
def gender
|
158
|
-
@geneder.call
|
159
|
-
end
|
160
|
-
|
161
|
-
def email(str_name = nil)
|
162
|
-
str_name = self.name if !str_name&.strip
|
163
|
-
@email_pattern.gsub('name', email_encode(str_name))
|
164
|
-
end
|
165
|
-
|
166
|
-
def phone
|
167
|
-
@phone.call
|
168
|
-
end
|
169
|
-
|
170
|
-
def mobile
|
171
|
-
@mobile.call
|
172
|
-
end
|
173
|
-
|
174
|
-
def mobile_code
|
175
|
-
@mobile_code.call
|
176
|
-
end
|
177
|
-
|
178
|
-
private
|
179
|
-
|
180
|
-
def unique_error_count
|
181
|
-
@unique_errors += 1
|
182
|
-
unique_overflow = @unique_errors > MAX_UNIQUE_ERRORS
|
183
|
-
err_msg = "Error uniqueness broken"
|
184
|
-
raise Faker::UniqueGenerator::RetryLimitExceeded.new(err_msg), err_msg if self.force_unique && unique_overflow
|
185
|
-
self.reset_unique if unique_overflow
|
186
|
-
end
|
187
|
-
|
188
|
-
def previous_date(years = 3)
|
189
|
-
@today - (years * 365)
|
190
|
-
end
|
191
|
-
|
192
|
-
def later_date(years = 3)
|
193
|
-
@today + (years * 365)
|
194
|
-
end
|
195
|
-
|
196
|
-
def init_topics
|
197
|
-
@name_topics = {
|
198
|
-
'General' => wrap_method { Faker::Name.unique.name },
|
199
|
-
'LordOfTheRings' => wrap_method { Faker::LordOfTheRings.unique.character },
|
200
|
-
'Hobbit' => wrap_method { Faker::Hobbit.unique.character },
|
201
|
-
'BackToTheFuture' => wrap_method { Faker::BackToTheFuture.unique.character },
|
202
|
-
'HarryPotter' => wrap_method { Faker::HarryPotter.unique.character },
|
203
|
-
'GameOfThrones' => wrap_method { Faker::GameOfThrones.unique.character },
|
204
|
-
'PrincesBride' => wrap_method { Faker::PrincesBride.unique.character },
|
205
|
-
'StarWars' => wrap_method { Faker::StarWars.unique.character },
|
206
|
-
'StarTrek' => wrap_method { Faker::StarTrek.unique.character },
|
207
|
-
'Simpsons' => wrap_method { Faker::Simpsons.unique.character },
|
208
|
-
'Superhero' => wrap_method { Faker::Superhero.unique.name },
|
209
|
-
'FunnyName' => wrap_method { Faker::FunnyName.unique.name },
|
210
|
-
'Book' => wrap_method { Faker::Book.unique.author },
|
211
|
-
'GreekPhilosophers' => wrap_method { Faker::GreekPhilosophers.unique.name },
|
212
|
-
'Scientists' => wrap_method { Faker::Science.unique.scientist },
|
213
|
-
'SiliconValley' => wrap_method { Faker::SiliconValley.unique.character },
|
214
|
-
'WorldCup' => wrap_method { Faker::WorldCup.unique.roster }
|
215
|
-
}
|
216
|
-
|
217
|
-
@location_topics = {
|
218
|
-
'General' => wrap_method { Faker::Nation.capital_city },
|
219
|
-
'LordOfTheRings' => wrap_method { Faker::LordOfTheRings.location },
|
220
|
-
'Hobbit' => wrap_method { Faker::Hobbit.location },
|
221
|
-
'HarryPotter' => wrap_method { Faker::HarryPotter.location },
|
222
|
-
'GameOfThrones' => wrap_method { Faker::GameOfThrones.city },
|
223
|
-
'Simpsons' => wrap_method { Faker::Simpsons.location },
|
224
|
-
'StarTrek' => wrap_method { Faker::StarTrek.location },
|
225
|
-
'WorldCup' => wrap_method { Faker::WorldCup.city },
|
226
|
-
'University' => wrap_method { Faker::University.name },
|
227
|
-
'Address' => wrap_method { Faker::Address.city }
|
228
|
-
}
|
229
|
-
|
230
|
-
@company_topics = {
|
231
|
-
'General' => wrap_method { Faker::Company.name },
|
232
|
-
'Vehicle' => wrap_method { Faker::Vehicle.manufacture },
|
233
|
-
'SiliconValley' => wrap_method { Faker::SiliconValley.company },
|
234
|
-
'Space' => wrap_method { Faker::Space.company }
|
235
|
-
}
|
236
|
-
|
237
|
-
@deparment_topics = {
|
238
|
-
'General' => wrap_method { Faker::Commerce.department }
|
239
|
-
}
|
240
|
-
end
|
241
|
-
|
242
|
-
def init_topic_wrappers
|
243
|
-
@name = get_topic_wrapper(@name_topics)
|
244
|
-
@location = get_topic_wrapper(@location_topics)
|
245
|
-
end
|
246
|
-
|
247
|
-
def get_topic_wrapper(type_topics)
|
248
|
-
all_topics = @topic.instance_of?(Array)? @topic : [@topic]
|
249
|
-
topics = filter_by_key(type_topics, all_topics)
|
250
|
-
failed_topic = !@topic || !topics || topics.values.length < 1
|
251
|
-
|
252
|
-
if !failed_topic
|
253
|
-
topic = topics.values.sample
|
254
|
-
#puts "\"Custom!!!!\""
|
255
|
-
else
|
256
|
-
if @general_topic_on_fail
|
257
|
-
topic = type_topics.fetch('General', nil)
|
258
|
-
#puts "\"Genearal!!!!\""
|
259
|
-
else
|
260
|
-
topic = type_topics.values.sample
|
261
|
-
#puts "\"Force Random!!!!\""
|
262
|
-
end
|
263
|
-
end
|
264
|
-
return topic
|
265
|
-
end
|
266
|
-
|
267
|
-
def get_unique(wrapper, related_topics)
|
268
|
-
begin
|
269
|
-
new_value = wrapper.call
|
270
|
-
rescue Faker::UniqueGenerator::RetryLimitExceeded
|
271
|
-
unique_error_count
|
272
|
-
wrapper = get_topic_wrapper(related_topics)
|
273
|
-
new_value = get_unique(wrapper, related_topics)
|
274
|
-
end
|
275
|
-
return new_value
|
276
|
-
end
|
277
|
-
|
278
|
-
def filter_by_key (hash, keys)
|
279
|
-
hash.select { |k,v| keys.include?(k) }
|
280
|
-
end
|
281
|
-
|
282
|
-
# should allow different topics
|
283
|
-
def email_encode(str)
|
284
|
-
return nil if !str.is_a?(String)
|
285
|
-
return str.gsub(/\s+/,"_")&.gsub(/\W/,"")&.slice(0,25).downcase
|
286
|
-
end
|
287
|
-
|
288
|
-
def wrap_method(&block)
|
289
|
-
block
|
290
|
-
end
|
291
|
-
|
292
|
-
def self.test(test_times = 500, fantasy: true, force_unique: false)
|
293
|
-
pp "########## Testing Faker wrapper ###########"
|
294
|
-
topic = if fantasy then 'fantasy' else nil end
|
295
|
-
faker = self.new({
|
296
|
-
'today' => Date.new(2018,1,1),
|
297
|
-
'locale' => 'nz',
|
298
|
-
'topic' => topic,
|
299
|
-
'general_topic_on_fail' => true,
|
300
|
-
'force_unique' => force_unique
|
301
|
-
})
|
302
|
-
begin
|
303
|
-
items = 0
|
304
|
-
test_times.times {
|
305
|
-
pp "#{name=faker.name} - #{faker.birthday(20, 40).to_s} : #{faker.mobile} : #{faker.email(name)}" + \
|
306
|
-
" : #{faker.location} : #{faker.company} : #{faker.community}"
|
307
|
-
items += 1
|
308
|
-
}
|
309
|
-
rescue ::Faker::UniqueGenerator::RetryLimitExceeded => e
|
310
|
-
puts "### Error: #{e.message} ###"
|
311
|
-
end
|
312
|
-
puts "total generated: #{items}"
|
313
|
-
puts "locale: #{faker.local}; topic: #{topic}"
|
314
|
-
puts "unique errors: #{faker.unique_errors} & #{faker.unique_resets} resets"
|
315
|
-
end
|
316
|
-
|
317
|
-
end
|
318
|
-
end
|
319
|
-
end
|
320
|
-
end
|
@@ -1,80 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
|
3
|
-
module Eco
|
4
|
-
module Data
|
5
|
-
module Random
|
6
|
-
class Values
|
7
|
-
|
8
|
-
attr_accessor :multiple, :unique
|
9
|
-
attr_reader :options, :weights, :options_weight, :quantity
|
10
|
-
attr_reader :generator, :generator_config
|
11
|
-
|
12
|
-
def initialize(init = {})
|
13
|
-
@multiple = init.fetch('multiple', false)
|
14
|
-
@unique = init.fetch('unique', true)
|
15
|
-
self.quantity = init.fetch('quantity', nil)
|
16
|
-
@options_weight = init.fetch('options_weight', nil)
|
17
|
-
@options = init.fetch('options', @options_weight&.keys)
|
18
|
-
@weights = @options_weight&.values
|
19
|
-
|
20
|
-
@generator_config = init.fetch('generator_config', { "decimals" => 0 })
|
21
|
-
if @weights
|
22
|
-
@generator_config['weights'] = @weights unless @generator_config.key?('weights')
|
23
|
-
@generator_config['balance'] = 'forged' unless @generator_config.key?('balance')
|
24
|
-
else
|
25
|
-
case
|
26
|
-
when @options&.instance_of?(Array)
|
27
|
-
@generator_config['weights'] = @weights unless @generator_config.key?('weights')
|
28
|
-
end
|
29
|
-
end
|
30
|
-
@generator = Distribution.new(@generator_config)
|
31
|
-
@random = ::Random.new
|
32
|
-
end
|
33
|
-
|
34
|
-
def quantity=(num_or_range) # attr_writer
|
35
|
-
val = num_or_range
|
36
|
-
case
|
37
|
-
when val.is_a?(Numeric)
|
38
|
-
num = val.round
|
39
|
-
rng = (num..num)
|
40
|
-
when val.instance_of?(Range)
|
41
|
-
rng = val
|
42
|
-
else
|
43
|
-
rng = (0..1)
|
44
|
-
end
|
45
|
-
@quantity = rng
|
46
|
-
end
|
47
|
-
|
48
|
-
def generate
|
49
|
-
if @multiple
|
50
|
-
quantity = @random.rand(@quantity)
|
51
|
-
value = []
|
52
|
-
quantity.times {
|
53
|
-
val = @unique? generate_option(exclude: value): generate_option
|
54
|
-
value.push(val)
|
55
|
-
}
|
56
|
-
value = value.uniq if @unique
|
57
|
-
else
|
58
|
-
value = generate_option
|
59
|
-
end
|
60
|
-
return value
|
61
|
-
end
|
62
|
-
|
63
|
-
def generate_option(exclude: [])
|
64
|
-
case
|
65
|
-
when @options&.instance_of?(Array)
|
66
|
-
val = @options[@generator.generate]
|
67
|
-
else
|
68
|
-
puts "something bad with @options"
|
69
|
-
end
|
70
|
-
#exclude_aux = Marshal.load(Marshal::dump(exclude))
|
71
|
-
exclude_aux = JSON.parse(exclude.to_json)
|
72
|
-
exclude_aux.pop
|
73
|
-
val = generate_option(exclude: exclude_aux) if exclude.include?(val)
|
74
|
-
return val
|
75
|
-
end
|
76
|
-
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
data/lib/eco/tester.rb
DELETED
@@ -1,97 +0,0 @@
|
|
1
|
-
require 'pp'
|
2
|
-
|
3
|
-
module Eco
|
4
|
-
TEST_TIMES = 5000
|
5
|
-
RANDOM = Eco::Data::Random
|
6
|
-
class Tester
|
7
|
-
include Data
|
8
|
-
|
9
|
-
def test_normal(test_times = TEST_TIMES)
|
10
|
-
pp "########## Testing Normal Distribution ###########"
|
11
|
-
generator_config = {
|
12
|
-
"range" => (1..100),
|
13
|
-
"decimals" => 0,
|
14
|
-
"balance" => 'normal'
|
15
|
-
}
|
16
|
-
generator = RANDOM::Distribution.new(generator_config)
|
17
|
-
frequency = frequency_sample(generator, test_times)
|
18
|
-
draw_frequency(frequency)
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_half_normal(test_times = TEST_TIMES)
|
22
|
-
pp "########## Testing Half-Normal Distribution ###########"
|
23
|
-
generator_config = {
|
24
|
-
"range" => (1..100),
|
25
|
-
"decimals" => 0,
|
26
|
-
"balance" => 'half-normal'
|
27
|
-
}
|
28
|
-
generator = RANDOM::Distribution.new(generator_config)
|
29
|
-
frequency = frequency_sample(generator, test_times)
|
30
|
-
draw_frequency(frequency)
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_forged(test_times = TEST_TIMES)
|
34
|
-
pp "########## Testing Forged Distribution ###########"
|
35
|
-
generator_config = {
|
36
|
-
"range" => (1..100),
|
37
|
-
"decimals" => 0,
|
38
|
-
"balance" => 'forged'
|
39
|
-
}
|
40
|
-
options_weight = {"One" => 10, "Two" => 5, "Three" => 2, "Four" => 1, "Five" => 1}
|
41
|
-
options_config = {
|
42
|
-
#'generator_config' => generator_config,
|
43
|
-
'options_weight' => options_weight,
|
44
|
-
'multiple' => false,
|
45
|
-
'quantity' => 2
|
46
|
-
}
|
47
|
-
|
48
|
-
generator = RANDOM::Values.new(options_config)
|
49
|
-
frequency = frequency_sample(generator, test_times)
|
50
|
-
draw_frequency(frequency)
|
51
|
-
end
|
52
|
-
|
53
|
-
private
|
54
|
-
|
55
|
-
def frequency_sample (generator, test_times = TEST_TIMES)
|
56
|
-
frequency = Hash.new {|hash, key| hash[key]=0}
|
57
|
-
test_times.times.map {
|
58
|
-
val = generator.generate
|
59
|
-
"here a nil!!" if !val
|
60
|
-
val = val.round if val.is_a? Numeric
|
61
|
-
frequency[val] += 1 if val
|
62
|
-
}
|
63
|
-
return frequency
|
64
|
-
end
|
65
|
-
|
66
|
-
def draw_frequency(frequency, generator = nil, histogram: true)
|
67
|
-
#pp frequency
|
68
|
-
vals = frequency.values
|
69
|
-
test_times = vals.inject(0, :+)
|
70
|
-
opts = vals.length
|
71
|
-
|
72
|
-
raise "no tests to show" if !test_times || test_times < 1
|
73
|
-
dimension = Math::log10(test_times)
|
74
|
-
draw_unit = (10**(dimension - 1) / (opts * 3)).round
|
75
|
-
|
76
|
-
total = 0; sum = 0
|
77
|
-
frequency.keys.sort.each do |k|
|
78
|
-
f = frequency[k]
|
79
|
-
percent = (f * 100 / test_times ).round
|
80
|
-
puts "#{k} (#{percent}/100): #{'*' * (f / draw_unit).round}" if :historgram
|
81
|
-
#puts "#{k} (#{percent}/100): #{'*' * f}" if :historgram
|
82
|
-
puts "#{k} (#{percent}/100): #{f}" if !:historgram
|
83
|
-
total += frequency[k]
|
84
|
-
v = k
|
85
|
-
v = 1 if !k.is_a? Numeric
|
86
|
-
sum += (frequency[k] * v)
|
87
|
-
end
|
88
|
-
|
89
|
-
summary = "total: #{total}; mean: #{sum / total}"
|
90
|
-
summary += "; draw unit #{draw_unit}" if :historgram
|
91
|
-
puts summary
|
92
|
-
pp "generator weights (config): #{generator.weights}" if generator
|
93
|
-
pp "generator unique (config): #{generator.unique}" if generator
|
94
|
-
end
|
95
|
-
|
96
|
-
end
|
97
|
-
end
|