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 +4 -4
- data/lib/danica.rb +3 -0
- data/lib/danica/equation.rb +17 -0
- data/lib/danica/expressable.rb +39 -0
- data/lib/danica/expression.rb +14 -0
- data/lib/danica/{function → expression}/gauss.rb +1 -1
- data/lib/danica/function.rb +14 -62
- data/lib/danica/operator.rb +3 -1
- data/lib/danica/variables_holder.rb +35 -2
- data/lib/danica/variables_holder/alias_builder.rb +20 -0
- data/lib/danica/variables_holder/calculator.rb +45 -0
- data/lib/danica/variables_holder/variables_builder.rb +1 -7
- data/lib/danica/version.rb +1 -1
- data/lib/danica/wrapper/container.rb +2 -1
- data/spec/lib/danica/equation_spec.rb +30 -0
- data/spec/lib/danica/expressable_spec.rb +35 -0
- data/spec/lib/danica/{function → expression}/gauss_spec.rb +1 -1
- data/spec/lib/danica/expression_spec.rb +366 -0
- data/spec/lib/danica/function_spec.rb +38 -258
- data/spec/lib/danica/variables_holder_spec.rb +198 -13
- data/spec/support/models/{functions → expression}/baskara.rb +1 -1
- data/spec/support/models/{functions → expression}/hyperbole.rb +2 -2
- data/spec/support/models/{functions → expression}/spatial.rb +1 -1
- data/spec/support/models/function/hyperbole.rb +16 -0
- data/spec/support/models/variables_holder/dummy.rb +34 -0
- metadata +27 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dbc5e0d585c75c30257524380ed56a556daa08c5
|
4
|
+
data.tar.gz: 429e5c4ed8845329ebd79f9bfa9353b809e1e763
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4fb11c37df1b65c3b960d5d9cf1fecd828e445171e950b16c9f532190e490d37b733923be0d3fc809e54eb1d8cd27fcf9f05b02af60eb4772d13280ffbf825f0
|
7
|
+
data.tar.gz: e737d1f7f965f29bc7d95a44744385400f12c6b863544a52ea06f851cb137b0a0a33ce90d669c5d2effe79e575d4eeb92a1cff49dbd2fc2ebacd6796542e35b3
|
data/lib/danica.rb
CHANGED
@@ -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
|
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
|
|
data/lib/danica/function.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
15
|
+
containers_hash[:left] ||= Danica::Wrapper::Container.new Name.new(name: @name, variables: containers)
|
68
16
|
end
|
69
17
|
|
70
|
-
|
18
|
+
def expression
|
19
|
+
@expression ||= Expression.build(:x) do
|
20
|
+
x
|
21
|
+
end.new(function_block)
|
22
|
+
end
|
71
23
|
|
72
|
-
def
|
73
|
-
|
24
|
+
def left
|
25
|
+
name
|
74
26
|
end
|
75
27
|
|
76
|
-
def
|
77
|
-
|
28
|
+
def right
|
29
|
+
expression
|
78
30
|
end
|
79
31
|
end
|
80
32
|
end
|
data/lib/danica/operator.rb
CHANGED
@@ -8,7 +8,9 @@ module Danica
|
|
8
8
|
default_value :is_grouped?, false
|
9
9
|
|
10
10
|
def initialize(*args)
|
11
|
-
|
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
|
-
|
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 ||=
|
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
|
-
|
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
|
|
data/lib/danica/version.rb
CHANGED
@@ -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?, :*, :+, :-, :/, :**,
|
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
|