danica 2.4.4 → 2.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7e650cc12cd4ccaaf7eaebd6f8084ae46211f0cf
4
- data.tar.gz: 7b9cef3c43db7851160e95f6a2700dfde13f5a28
3
+ metadata.gz: dbc5e0d585c75c30257524380ed56a556daa08c5
4
+ data.tar.gz: 429e5c4ed8845329ebd79f9bfa9353b809e1e763
5
5
  SHA512:
6
- metadata.gz: 0acaff19e60a377126d74cfa90441098329f19603b7467e208f672e1ba7a95242beed67125028cd8c1979f5fb9b4443b877aa27ec24bf8e421f6f44970f983b3
7
- data.tar.gz: 3d5be06b0da8ea1569f17354b711ce328f0577b169af1a8a191f6de883d6cbb2b3aab38fe3c2f03511f0f1aa5f72d819146d3bac3107e32364d9e6030d0ace14
6
+ metadata.gz: 4fb11c37df1b65c3b960d5d9cf1fecd828e445171e950b16c9f532190e490d37b733923be0d3fc809e54eb1d8cd27fcf9f05b02af60eb4772d13280ffbf825f0
7
+ data.tar.gz: e737d1f7f965f29bc7d95a44744385400f12c6b863544a52ea06f851cb137b0a0a33ce90d669c5d2effe79e575d4eeb92a1cff49dbd2fc2ebacd6796542e35b3
@@ -5,8 +5,11 @@ module Danica
5
5
  autoload :BaseOperations, 'danica/base_operations'
6
6
  autoload :VariablesHolder, 'danica/variables_holder'
7
7
  autoload :Common, 'danica/common'
8
+ autoload :Expression, 'danica/expression'
9
+ autoload :Equation, 'danica/equation'
8
10
  autoload :Function, 'danica/function'
9
11
  autoload :Exception, 'danica/exception'
12
+ autoload :Expressable, 'danica/expressable'
10
13
 
11
14
  autoload :DSL, 'danica/dsl'
12
15
  autoload :Wrapper, 'danica/wrapper'
@@ -0,0 +1,17 @@
1
+ module Danica
2
+ class Equation
3
+ include Common
4
+ include VariablesHolder
5
+
6
+ variables :left, :right
7
+
8
+ def initialize(*args)
9
+ self.variables = args.flatten
10
+ end
11
+
12
+ def to(format)
13
+ "#{left.to(format)} = #{right.to(format)}"
14
+ end
15
+ end
16
+ end
17
+
@@ -0,0 +1,39 @@
1
+ module Danica
2
+ module Expressable extend ::ActiveSupport::Concern
3
+ included do
4
+ include VariablesHolder
5
+
6
+ class << self
7
+ def built_with(block_name)
8
+ self.send(:delegate, :to_f, to: block_name)
9
+
10
+ self.send(:define_singleton_method, :build) do |*vars, &block|
11
+ Class.new(self) do
12
+ variables(*vars)
13
+
14
+ private
15
+
16
+ module_eval("define_method :#{block_name} do
17
+ @#{block_name} ||= instance_eval(&block) if block
18
+ end")
19
+ end
20
+ end
21
+
22
+ self.send(:define_singleton_method, :create) do |*vars, &block|
23
+ build(*vars, &block).new
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ def initialize(*args)
30
+ options = args.extract_options!
31
+
32
+ attributes = { variables: args.flatten }.merge(options)
33
+
34
+ attributes.each do |key, value|
35
+ self.public_send("#{key}=", value)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,14 @@
1
+ module Danica
2
+ class Expression
3
+ include Common
4
+ include DSL
5
+ include BaseOperations
6
+ include Expressable
7
+
8
+ autoload :Gauss, 'danica/expression/gauss'
9
+
10
+ delegate :to, :is_grouped?, :priority, to: :expression_block
11
+
12
+ built_with(:expression_block)
13
+ end
14
+ end
@@ -1,5 +1,5 @@
1
1
  module Danica
2
- class Function::Gauss < Function.build(:x, average: { latex: '\mu', gnu: :u }, variance_root: { latex: '\sigma', gnu: :v }) { num(1) / denominator * exponential(exp) }
2
+ class Expression::Gauss < Expression.build(:x, average: { latex: '\mu', gnu: :u }, variance_root: { latex: '\sigma', gnu: :v }) { num(1) / denominator * exponential(exp) }
3
3
 
4
4
  private
5
5
 
@@ -1,80 +1,32 @@
1
1
  module Danica
2
- class Function
2
+ class Function < Equation
3
3
  include Common
4
- include VariablesHolder
5
4
  include DSL
5
+ include Expressable
6
6
 
7
- autoload :Gauss, 'danica/function/gauss'
8
7
  autoload :Name, 'danica/function/name'
9
-
10
8
  attr_accessor :name
11
9
 
12
- default_value :priority, 3
13
- default_value :is_grouped?, false
14
- delegate :to_f, :to, to: :function_block
15
-
16
- def self.build(*vars, &block)
17
- Class.new(self) do
18
- variables(*vars)
19
-
20
- private
21
-
22
- define_method :function_block do
23
- @function_block ||= instance_eval(&block) if block
24
- end
25
- end
26
- end
27
-
28
- def self.create(*vars, &block)
29
- build(*vars, &block).new
30
- end
31
-
32
- def initialize(*args)
33
- options = args.extract_options!
34
-
35
- attributes = { variables: args.flatten }.merge(options)
36
-
37
- attributes.each do |key, value|
38
- self.public_send("#{key}=", value)
39
- end
40
- end
41
-
42
- def calculate(*args)
43
- vars_map = args.extract_options!
44
- vars_map = variables_value_hash.merge(vars_map)
45
- vars_map.each do |k, v|
46
- unless v && (v.is_a?(Integer) || v.valued?)
47
- vars_map[k] = args.shift
48
- end
49
- end
50
-
51
- self.class.new(vars_map).to_f
52
- end
53
-
54
- def describe(format)
55
- "#{name.to(format)} = #{to(format)}"
56
- end
10
+ reset_variables
57
11
 
58
- def describe_tex
59
- describe(:tex)
60
- end
61
-
62
- def describe_gnu
63
- describe(:gnu)
64
- end
12
+ built_with(:function_block)
65
13
 
66
14
  def name
67
- @name_object ||= Name.new(name: @name, variables: containers)
15
+ containers_hash[:left] ||= Danica::Wrapper::Container.new Name.new(name: @name, variables: containers)
68
16
  end
69
17
 
70
- private
18
+ def expression
19
+ @expression ||= Expression.build(:x) do
20
+ x
21
+ end.new(function_block)
22
+ end
71
23
 
72
- def description_variables(format)
73
- non_constant_variables.map { |v| v.to(format) }.join(', ')
24
+ def left
25
+ name
74
26
  end
75
27
 
76
- def non_constant_variables
77
- variables.reject(&:constant?)
28
+ def right
29
+ expression
78
30
  end
79
31
  end
80
32
  end
@@ -8,7 +8,9 @@ module Danica
8
8
  default_value :is_grouped?, false
9
9
 
10
10
  def initialize(*args)
11
- self.variables = args.flatten
11
+ args = args.flatten
12
+ args = args.first if (args.length == 1) && args.first.is_a?(Hash) && args.first.keys == self.class.variables_names
13
+ self.variables = args
12
14
  end
13
15
 
14
16
  def ==(other)
@@ -1,6 +1,8 @@
1
1
  module Danica
2
2
  module VariablesHolder extend ::ActiveSupport::Concern
3
- require 'danica/variables_holder/variables_builder'
3
+ autoload :VariablesBuilder, 'danica/variables_holder/variables_builder'
4
+ autoload :AliasBuilder, 'danica/variables_holder/alias_builder'
5
+ autoload :Calculator, 'danica/variables_holder/calculator'
4
6
 
5
7
  included do
6
8
  class << self
@@ -8,12 +10,25 @@ module Danica
8
10
  VariablesBuilder.new(names, self).build
9
11
  end
10
12
 
13
+ def variable_alias(origin, destiny)
14
+ AliasBuilder.new(origin, destiny, self).build
15
+ end
16
+
11
17
  def variables_names
12
18
  variables_hash.keys
13
19
  end
14
20
 
15
21
  def variables_hash
16
- @variables_hash ||= (superclass.try(:variables_hash) || {}).dup
22
+ @variables_hash ||= superclass_variables_hash.dup
23
+ end
24
+
25
+ def reset_variables
26
+ @superclass_variables_hash = {}
27
+ @variables_hash = nil
28
+ end
29
+
30
+ def superclass_variables_hash
31
+ @superclass_variables_hash ||= (superclass.try(:variables_hash) || {})
17
32
  end
18
33
  end
19
34
  end
@@ -26,6 +41,20 @@ module Danica
26
41
  end
27
42
  end
28
43
 
44
+ def extract_variables
45
+ variables.select do |var|
46
+ var.is_a?(VariablesHolder)
47
+ end.inject({}) do |hash, container|
48
+ hash.merge!(container.content.extract_variables)
49
+ end.tap do |hash|
50
+ containers_hash.select do |_, container|
51
+ container.content.is_a?(Wrapper::Variable)
52
+ end.each do |key, container|
53
+ hash[(container.content.name || key).to_sym] = container
54
+ end
55
+ end
56
+ end
57
+
29
58
  def variables
30
59
  containers.map(&:content)
31
60
  end
@@ -49,5 +78,9 @@ module Danica
49
78
  var.try(:value)
50
79
  end.as_hash(self.class.variables_names)
51
80
  end
81
+
82
+ def calculate(*args)
83
+ Calculator.new(self, *args).calculate
84
+ end
52
85
  end
53
86
  end
@@ -0,0 +1,20 @@
1
+ module Danica::VariablesHolder
2
+ class AliasBuilder
3
+
4
+ attr_reader :clazz, :origin, :destiny
5
+
6
+ def initialize(origin, destiny, clazz)
7
+ @origin = origin
8
+ @destiny = destiny
9
+ @clazz = clazz
10
+ end
11
+
12
+ def build
13
+ clazz.variables_hash.change_keys! { |k| k == origin ? destiny : k }
14
+ VariablesBuilder.new([ destiny ], clazz).build
15
+ clazz.send(:alias_method, "#{origin}=", "#{destiny}=")
16
+ clazz.send(:alias_method, origin, destiny)
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,45 @@
1
+ module Danica
2
+ module VariablesHolder
3
+ class Calculator
4
+ attr_accessor :object, :args
5
+
6
+ def initialize(object, *args)
7
+ @object = object
8
+ @args = args
9
+ end
10
+
11
+ def calculate
12
+ raise Exception::NotDefined unless all_valued?
13
+
14
+ clazz.new(vars_map).to_f
15
+ end
16
+
17
+ private
18
+
19
+ def vars_map
20
+ @vars_map ||= variables_value_hash.tap do |map|
21
+ vars = args.dup
22
+ map.merge! vars.extract_options!
23
+ vars_map = vars.as_hash(map.keys).select { |_, v| valued?(v) }
24
+ map.merge! vars_map
25
+ end
26
+ end
27
+
28
+ def all_valued?
29
+ vars_map.values.all? { |v| valued?(v) }
30
+ end
31
+
32
+ def valued?(value)
33
+ value.is_a?(Integer) || value.try(:valued?)
34
+ end
35
+
36
+ def variables_value_hash
37
+ @variables_value_hash ||= object.variables_value_hash.dup
38
+ end
39
+
40
+ def clazz
41
+ @clazz ||= object.class
42
+ end
43
+ end
44
+ end
45
+ end
@@ -30,13 +30,7 @@ module Danica::VariablesHolder
30
30
 
31
31
  def add_setter(name)
32
32
  instance.send(:define_method, "#{name}=") do |value|
33
- if(containers_hash[name.to_sym].try(:container?))
34
- containers_hash[name.to_sym].content = wrap_value(value)
35
- else
36
- value = wrap_value(value)
37
- value = Danica::Wrapper::Container.new value unless value.container?
38
- containers_hash[name.to_sym] = value
39
- end
33
+ containers_hash[name.to_sym].content = wrap_value(value)
40
34
  end
41
35
  end
42
36
 
@@ -1,3 +1,3 @@
1
1
  module Danica
2
- VERSION = '2.4.4'
2
+ VERSION = '2.5.0'
3
3
  end
@@ -4,7 +4,8 @@ module Danica
4
4
  attr_accessor :content
5
5
 
6
6
  delegate :to_f, :contentd?, :to, :to_tex, :to_gnu, :priority, :grouped?,
7
- :signaled?, :constant?, :valued?, :*, :+, :-, :/, :**, to: :content
7
+ :signaled?, :constant?, :valued?, :*, :+, :-, :/, :**,
8
+ :variables, to: :content
8
9
 
9
10
  default_value :container?, true
10
11
 
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe Danica::Equation do
4
+ let(:left) do
5
+ Danica::Expression.create(:y) { y }
6
+ end
7
+ let(:right) do
8
+ Danica::Expression.create(:x) { x ** 2 }
9
+ end
10
+
11
+ subject { described_class.new(left, right) }
12
+
13
+ describe '#to_f' do
14
+ it do
15
+ expect { subject.to_f }.to raise_error(Danica::Exception::NotImplemented)
16
+ end
17
+ end
18
+
19
+ describe '#to_tex' do
20
+ it 'joins the expressions in a equation' do
21
+ expect(subject.to_tex).to eq('y = x^{2}')
22
+ end
23
+ end
24
+
25
+ describe '#to_gnu' do
26
+ it 'joins the expressions in a equation' do
27
+ expect(subject.to_gnu).to eq('y = x**(2)')
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ class Danica::Expressable::Dummy
4
+ include Danica::Expressable
5
+
6
+ built_with :the_block
7
+ end
8
+
9
+ describe Danica::Expressable do
10
+ let(:clazz) { described_class::Dummy }
11
+
12
+ describe '.build' do
13
+ it 'responds to build' do
14
+ expect(clazz).to respond_to(:build)
15
+ end
16
+
17
+ it 'returns a child class object' do
18
+ expect(clazz.build(:x) do
19
+ x
20
+ end.superclass).to be(clazz)
21
+ end
22
+ end
23
+
24
+ describe '.create' do
25
+ it 'responds to create' do
26
+ expect(clazz).to respond_to(:create)
27
+ end
28
+
29
+ it do
30
+ expect(clazz.create(:x) do
31
+ x
32
+ end).to be_a(clazz)
33
+ end
34
+ end
35
+ end