bodhi-slam 0.7.3 → 0.8.0

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
  SHA1:
3
- metadata.gz: 1fbe5ba6be9aceacf0acdc118e78a1a95ddd32ee
4
- data.tar.gz: a7eae1661963319627d4694dfc90dd8bc5b1e327
3
+ metadata.gz: 7a728bbc653fe51f2aa54fd7fcc07874205616c8
4
+ data.tar.gz: ecd5e410504d479843dfcc4ebe2823815161c6fe
5
5
  SHA512:
6
- metadata.gz: 938995fe271d5b2085a80c153931e3d0378c05daf587e247ef7baad00c2f48d4741b59299842c4042c0bbb3cf56ab44445983c200fbd6936e445d6ba3fb07dd1
7
- data.tar.gz: 8f72e7317218ece3d876e7b803f738e55176e2de400bc368fa1c4d50bb1700c40f58be5d219fa1c2841d63a00a5d8a3cf18b0d1d393c64b30ae96213ef30ff75
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 |param_key, param_value|
84
- send("#{param_key}=", param_value)
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 }
@@ -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.7.3
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-01-14 00:00:00.000000000 Z
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.4.5
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