bodhi-slam 0.7.3 → 0.8.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/lib/bodhi-slam/properties.rb +7 -2
- data/lib/bodhi-slam/simulation/normal_distribution.rb +103 -0
- data/lib/bodhi-slam/simulator.rb +94 -0
- data/lib/bodhi-slam/types.rb +2 -2
- data/lib/bodhi-slam.rb +8 -0
- metadata +19 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a728bbc653fe51f2aa54fd7fcc07874205616c8
|
4
|
+
data.tar.gz: ecd5e410504d479843dfcc4ebe2823815161c6fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ca39c510350b552edbd793a8b0c42700f0c3125ca103f613fd8ee1a8c618076e2063f9630a739b7e67a99c05378f0b0d9b2a05249c2c3162fbba64c60d3d3e4
|
7
|
+
data.tar.gz: 32749263d7225845eb31e8780a02b446c19ad2a559fcc295bc01767157f1f15a958f90fd32bb904346f4595bad27e3262794b696287e631ed734e1c5c2482fab
|
@@ -80,8 +80,13 @@ module Bodhi
|
|
80
80
|
# s.update_attributes(bar: 10)
|
81
81
|
# s.attributes # => { foo: "test", bar: 10 }
|
82
82
|
def update_attributes(params)
|
83
|
-
params.each do |
|
84
|
-
|
83
|
+
params.each do |property, value|
|
84
|
+
property_options = self.class.properties[property.to_sym]
|
85
|
+
if property_options.nil?
|
86
|
+
send("#{property}=", value)
|
87
|
+
else
|
88
|
+
send("#{property}=", Bodhi::Support.coerce(value, property_options))
|
89
|
+
end
|
85
90
|
end
|
86
91
|
end
|
87
92
|
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Bodhi
|
2
|
+
module Simulation
|
3
|
+
class NormalDistributionCurve
|
4
|
+
include Bodhi::Properties
|
5
|
+
include Bodhi::Validations
|
6
|
+
|
7
|
+
property :mean, type: Float
|
8
|
+
property :mean_range, type: Float, multi: true
|
9
|
+
|
10
|
+
property :std_dev, type: Float
|
11
|
+
property :std_dev_range, type: Float, multi: true
|
12
|
+
|
13
|
+
property :scale, type: Float
|
14
|
+
property :title, type: String
|
15
|
+
|
16
|
+
validates :mean, required: true
|
17
|
+
validates :std_dev, required: true, min: 0.0001
|
18
|
+
validates :scale, required: true, min: 0.0, max: 1.0
|
19
|
+
end
|
20
|
+
|
21
|
+
class NormalDistribution
|
22
|
+
include Bodhi::Properties
|
23
|
+
include Bodhi::Validations
|
24
|
+
|
25
|
+
GAUSSIAN_FUNCTION = lambda{|x,u,o,s| 1/Math.sqrt(2*Math::PI*(o**2)) * Math.exp(-((x-u)**2)/(2*(o**2))) * s }
|
26
|
+
|
27
|
+
property :curves, type: Bodhi::Simulation::NormalDistributionCurve, multi: true
|
28
|
+
validates :curves, required: true
|
29
|
+
|
30
|
+
# ================
|
31
|
+
# Class Methods
|
32
|
+
# ================
|
33
|
+
|
34
|
+
# Accepts an array of Bodhi::Simulation::NormalDistribution::Curves objects
|
35
|
+
# Randomizes the +mean+ and +std_dev+ properties based on the given
|
36
|
+
# +mean_range+ and +std_dev_range+ properties
|
37
|
+
# Returns a new Bodhi::Simulation::NormalDistribution object with the randomized properties
|
38
|
+
#
|
39
|
+
# curves = [{mean_range: [45.4, 50.0], std_dev_range: [1.2, 2.2], scale: 0.2, title: "Dinner rush"}]
|
40
|
+
#
|
41
|
+
# Bodhi::Simulation::NormalDistribution.randomize(curves)
|
42
|
+
# #=> #<Bodhi::Simulation::NormalDistribution @mean=47.1234 @std_dev=1.7543 @mean_range=[45.4, 50.0] @std_dev_range=[1.2, 2.2] @scale=0.2 @title="Dinner rush">
|
43
|
+
#
|
44
|
+
def self.randomize(curves)
|
45
|
+
unless curves.is_a?(Array)
|
46
|
+
raise ArgumentError.new("+curves+ must be an Array")
|
47
|
+
end
|
48
|
+
|
49
|
+
randomized_curves = curves.collect do |curve|
|
50
|
+
# Coerce the given +curve+ into a Bodhi::Simulation::NormalDistributionCurve
|
51
|
+
unless curve.is_a?(Bodhi::Simulation::NormalDistributionCurve)
|
52
|
+
begin
|
53
|
+
curve = Bodhi::Simulation::NormalDistributionCurve.new(curve)
|
54
|
+
rescue Exception => e
|
55
|
+
raise ArgumentError.new("The value: #{curve} is not a valid Bodhi::Simulation::NormalDistributionCurve object. Error: #{e}")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Check if the user supplied a range for mean and std_dev values
|
60
|
+
# These are optional properies, but a required for randomizing a curve
|
61
|
+
if curve.mean_range.nil? || curve.std_dev_range.nil?
|
62
|
+
raise ArgumentError.new("Unable to randomize the curve: #{curve.to_json}. Reason: missing mandatory +mean_range+ OR +std_dev_range+ properties.")
|
63
|
+
end
|
64
|
+
|
65
|
+
# Calculate a random mean and standard deviation
|
66
|
+
random_mean = rand(curve.mean_range[0]..curve.mean_range[1])
|
67
|
+
random_std_dev = rand(curve.std_dev_range[0]..curve.std_dev_range[1])
|
68
|
+
|
69
|
+
# Create a new randomized curve object
|
70
|
+
randomized_curve = curve.clone
|
71
|
+
randomized_curve.mean = random_mean
|
72
|
+
randomized_curve.std_dev = random_std_dev
|
73
|
+
|
74
|
+
# Check if the randomized curve is valid
|
75
|
+
if randomized_curve.invalid?
|
76
|
+
raise ArgumentError.new("Invalid Bodhi::Simulation::NormalDistributionCurve. Reasons: #{randomized_curve.errors.to_a}")
|
77
|
+
end
|
78
|
+
|
79
|
+
# return the randomized curve
|
80
|
+
randomized_curve
|
81
|
+
end
|
82
|
+
|
83
|
+
# Return a new NormalDistribution with the randomized curves
|
84
|
+
Bodhi::Simulation::NormalDistribution.new(curves: randomized_curves)
|
85
|
+
end
|
86
|
+
|
87
|
+
# ================
|
88
|
+
# Instance Methods
|
89
|
+
# ================
|
90
|
+
|
91
|
+
# Evaluates the value of +y+ at position +x+
|
92
|
+
# Raises ArgumentError if +x+ is not a Float or Integer
|
93
|
+
def calculate(x)
|
94
|
+
unless x.is_a?(Integer) || x.is_a?(Float)
|
95
|
+
raise ArgumentError.new("Expected Integer or Float but recieved: #{x.class}")
|
96
|
+
end
|
97
|
+
|
98
|
+
curves.collect{ |curve| GAUSSIAN_FUNCTION.call(x, curve.mean, curve.std_dev, curve.scale) }.reduce(:+)
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Bodhi
|
2
|
+
class SimulationFrame
|
3
|
+
include Bodhi::Properties
|
4
|
+
include Bodhi::Validations
|
5
|
+
|
6
|
+
property :iteration, type: Integer, default: 0
|
7
|
+
property :time, type: DateTime
|
8
|
+
end
|
9
|
+
|
10
|
+
class Simulator
|
11
|
+
include Bodhi::Properties
|
12
|
+
include Bodhi::Validations
|
13
|
+
|
14
|
+
# Initial conditions
|
15
|
+
property :starts_at, type: DateTime
|
16
|
+
property :iterations, type: Integer
|
17
|
+
property :time_units, type: String
|
18
|
+
property :time_scale, type: Integer, default: 1
|
19
|
+
|
20
|
+
# Dynamic attributes
|
21
|
+
# Updated every iteration
|
22
|
+
property :current_frame, type: SimulationFrame
|
23
|
+
|
24
|
+
# Model validations
|
25
|
+
validates :starts_at, required: true
|
26
|
+
validates :iterations, required: true, min: 1
|
27
|
+
validates :time_units, required: true
|
28
|
+
validates :time_scale, min: 1
|
29
|
+
|
30
|
+
# ================
|
31
|
+
# Class Methods
|
32
|
+
# ================
|
33
|
+
|
34
|
+
# Run a new simulation using the given +settings+ and +&block+
|
35
|
+
# Yields the +simulation.current_time+ to the user defined +&block+
|
36
|
+
# Ignores +current_frame+ settings and zero's them before the simulation
|
37
|
+
#
|
38
|
+
# Bodhi::Simulator.execute(starts_at: "2016-05-10", iterations: 10, time_units: "days") do |current_time|
|
39
|
+
# # do some simulation stuff!
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# # You can even go crazy and do things like:
|
43
|
+
# Bodhi::Simulator.execute(...) do |outer_time|
|
44
|
+
# # do some simulation stuff!
|
45
|
+
# Bodhi::Simulator.execute(...) do |inner_time|
|
46
|
+
# # do a nested simulation!
|
47
|
+
# end
|
48
|
+
# # do more stuff after the netsted simulation...
|
49
|
+
# end
|
50
|
+
def self.execute(settings, &block)
|
51
|
+
simulation = Bodhi::Simulator.new(settings)
|
52
|
+
|
53
|
+
if simulation.invalid?
|
54
|
+
raise ArgumentError.new("Invalid settings: #{simulation.errors.to_a}")
|
55
|
+
end
|
56
|
+
|
57
|
+
if simulation.current_frame.nil?
|
58
|
+
simulation.current_frame = Bodhi::SimulationFrame.new(iteration: 0, time: simulation.starts_at)
|
59
|
+
else
|
60
|
+
simulation.current_frame.iteration = 0
|
61
|
+
simulation.current_frame.time = simulation.starts_at
|
62
|
+
end
|
63
|
+
|
64
|
+
until simulation.complete?
|
65
|
+
yield simulation.current_frame.clone
|
66
|
+
simulation.increment
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# ================
|
71
|
+
# Instance Methods
|
72
|
+
# ================
|
73
|
+
|
74
|
+
# returns true if the simulation has processed all iterations
|
75
|
+
def complete?
|
76
|
+
self.current_frame.iteration == self.iterations
|
77
|
+
end
|
78
|
+
|
79
|
+
# Increments the simulation loop by one iteration
|
80
|
+
# Updates +current_time+ to the new time offset
|
81
|
+
# Updates +current_iteration+ to the next iteration
|
82
|
+
#
|
83
|
+
# simulation = Bodhi::Simulator.new(starts_at: "2016-05-13", iterations: 2, time_units: "days")
|
84
|
+
# simulation.increment
|
85
|
+
# simulation #=> #<Bodhi::Simulator @starts_at: "2016-05-13" @iterations: 2, @time_units: "days", @current_time: "2016-05-14", @current_iteration: 1 >
|
86
|
+
#
|
87
|
+
def increment
|
88
|
+
self.current_frame.iteration += 1
|
89
|
+
self.current_frame.time = self.starts_at + (self.current_frame.iteration * 1.send(self.time_units) * self.time_scale)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
Dir[File.dirname(__FILE__) + "/simulation/*.rb"].each { |file| require file }
|
data/lib/bodhi-slam/types.rb
CHANGED
@@ -148,13 +148,13 @@ module Bodhi
|
|
148
148
|
raise ArgumentError.new("Expected #{type.class} to be a Bodhi::Type")
|
149
149
|
end
|
150
150
|
|
151
|
-
klass = Object.const_set(type.name, Class.new { include Bodhi::Resource })
|
151
|
+
klass = Object.const_set(type.name, Class.new { include Bodhi::Resource, ActiveModel::Model })
|
152
152
|
|
153
153
|
type.properties.each_pair do |attr_name, attr_properties|
|
154
154
|
attr_properties = Bodhi::Support.symbolize_keys(attr_properties)
|
155
155
|
|
156
156
|
# remove Sanitizers
|
157
|
-
attr_properties.delete_if{ |key, value| [:trim, :unique, :default, :isCurrentUser, :toLower].include?(key) }
|
157
|
+
attr_properties.delete_if{ |key, value| [:trim, :unique, :default, :isCurrentUser, :toLower, :encrypt].include?(key) }
|
158
158
|
|
159
159
|
# Do not add factories or validations for system properties
|
160
160
|
unless attr_properties[:system] == true
|
data/lib/bodhi-slam.rb
CHANGED
@@ -7,6 +7,11 @@ require 'faraday-http-cache'
|
|
7
7
|
require 'net/http/persistent'
|
8
8
|
require 'regexp-examples'
|
9
9
|
|
10
|
+
# Active Support
|
11
|
+
require 'active_model'
|
12
|
+
require 'active_support'
|
13
|
+
require 'active_support/core_ext'
|
14
|
+
|
10
15
|
require 'bodhi-slam/support'
|
11
16
|
require 'bodhi-slam/validations'
|
12
17
|
require 'bodhi-slam/errors'
|
@@ -25,6 +30,9 @@ require 'bodhi-slam/users'
|
|
25
30
|
require 'bodhi-slam/profiles'
|
26
31
|
require 'bodhi-slam/queries'
|
27
32
|
|
33
|
+
# Discrete Event Simulator
|
34
|
+
require 'bodhi-slam/simulator'
|
35
|
+
|
28
36
|
class BodhiSlam
|
29
37
|
# Defines a context to interact with the Bodhi API
|
30
38
|
# Including a +server+, +namespace+, +username+, +password+ or +cookie+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bodhi-slam
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- willdavis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '2.9'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: activemodel
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '4.2'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '4.2'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: json
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -171,6 +185,8 @@ files:
|
|
171
185
|
- lib/bodhi-slam/properties.rb
|
172
186
|
- lib/bodhi-slam/queries.rb
|
173
187
|
- lib/bodhi-slam/resource.rb
|
188
|
+
- lib/bodhi-slam/simulation/normal_distribution.rb
|
189
|
+
- lib/bodhi-slam/simulator.rb
|
174
190
|
- lib/bodhi-slam/support.rb
|
175
191
|
- lib/bodhi-slam/types.rb
|
176
192
|
- lib/bodhi-slam/types/index.rb
|
@@ -209,7 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
209
225
|
version: '0'
|
210
226
|
requirements: []
|
211
227
|
rubyforge_project:
|
212
|
-
rubygems_version: 2.
|
228
|
+
rubygems_version: 2.5.1
|
213
229
|
signing_key:
|
214
230
|
specification_version: 4
|
215
231
|
summary: Ruby bindings for the Bodhi API & factories for random data generation
|