danica 2.4.4 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|