akiva 0.1.0 → 0.1.1

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +15 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +2 -0
  5. data/Gemfile.lock +80 -0
  6. data/Guardfile +11 -0
  7. data/LICENSE +9 -0
  8. data/README.md +131 -0
  9. data/Rakefile +5 -0
  10. data/akiva.gemspec +38 -0
  11. data/lib/akiva.rb +11 -0
  12. data/lib/akiva/brain.rb +47 -0
  13. data/lib/akiva/cli.rb +58 -0
  14. data/lib/akiva/core_brain/actions/get_answers_from_subjects_and_properties.rb +73 -0
  15. data/lib/akiva/core_brain/actions/preparators/compare_two_subjects_properties_from_comparison_adjective.rb +19 -0
  16. data/lib/akiva/core_brain/actions/preparators/extract_property_from_comparison_adjective.rb +10 -0
  17. data/lib/akiva/core_brain/actions/preparators/regroup_separated_subjects.rb +10 -0
  18. data/lib/akiva/core_brain/actions/preparators/sort_answers_by_units.rb +35 -0
  19. data/lib/akiva/core_brain/actions/template.rb +23 -0
  20. data/lib/akiva/core_brain/filters/get_answers_from_subjects_and_properties.rb +15 -0
  21. data/lib/akiva/core_brain/filters/template.rb +9 -0
  22. data/lib/akiva/core_brain/formatters/boolean_from_comparison.rb +17 -0
  23. data/lib/akiva/core_brain/formatters/list_all_answers.rb +28 -0
  24. data/lib/akiva/core_brain/formatters/template.rb +19 -0
  25. data/lib/akiva/core_brain/helpers/comparison_adjectives_to_properties.rb +151 -0
  26. data/lib/akiva/core_brain/helpers/misc.rb +28 -0
  27. data/lib/akiva/core_brain/helpers/units.rb +167 -0
  28. data/lib/akiva/core_brain/loader.rb +3 -0
  29. data/lib/akiva/question.rb +88 -0
  30. data/lib/akiva/version.rb +9 -0
  31. data/spec/lib/akiva/brain_spec.rb +89 -0
  32. data/spec/lib/akiva/core_brain/actions/get_answers_from_subjects_and_properties_spec.rb +77 -0
  33. data/spec/lib/akiva/core_brain/actions/preparators/compare_two_subjects_properties_from_comparison_adjective_spec.rb +22 -0
  34. data/spec/lib/akiva/core_brain/actions/preparators/extract_property_from_comparison_adjective_spec.rb +11 -0
  35. data/spec/lib/akiva/core_brain/actions/preparators/regroup_separated_subjects_spec.rb +11 -0
  36. data/spec/lib/akiva/core_brain/actions/preparators/sort_answers_by_units_spec.rb +36 -0
  37. data/spec/lib/akiva/core_brain/filters/get_answers_from_subjects_and_properties_spec.rb +44 -0
  38. data/spec/lib/akiva/core_brain/formatters/boolean_from_comparison_spec.rb +38 -0
  39. data/spec/lib/akiva/core_brain/formatters/list_all_answers_spec.rb +60 -0
  40. data/spec/lib/akiva/core_brain/helpers/misc_spec.rb +26 -0
  41. data/spec/lib/akiva/core_brain/helpers/units_spec.rb +141 -0
  42. data/spec/lib/akiva/core_brain/question_spec.rb +170 -0
  43. data/spec/spec_helper.rb +37 -0
  44. data/spec/support/akiva_brain_helpers.rb +13 -0
  45. data/spec/support/akiva_statements_helpers.rb +66 -0
  46. metadata +75 -16
@@ -0,0 +1,19 @@
1
+ Akiva::Brain.update do
2
+
3
+ add_action :compare_two_subjects_properties_from_comparison_adjective do |response|
4
+ answers_values = response[:answers].map{|hash| hash.last.first.last }
5
+
6
+ begin
7
+ units = Akiva::Brain::Helpers::Units.new(answers_values)
8
+ units.compare # in the future, you may want to pass a multiplicator here
9
+ rescue
10
+ # we fail silently for now, as the error probably comes from the data in TheBigDB anyway,
11
+ # which could well be invalid (= not convertible units)
12
+ else
13
+ property_comparator = Akiva::Brain::Helpers::ComparisonAdjectivesToProperties[response[:filter_captures]["comparison_adjective"]][:comparator]
14
+ response[:comparison_boolean_result] = (units.result == property_comparator)
15
+ end # begin
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,10 @@
1
+ Akiva::Brain.update do
2
+
3
+ add_action :extract_property_from_comparison_adjective do |response|
4
+
5
+ # Note: for now, we're only working with the first property listed for the adjective
6
+ response[:defined_properties] = [Akiva::Brain::Helpers::ComparisonAdjectivesToProperties[response[:filter_captures]["comparison_adjective"]][:properties].first]
7
+
8
+ end
9
+
10
+ end
@@ -0,0 +1,10 @@
1
+ Akiva::Brain.update do
2
+
3
+ add_action :regroup_separated_subjects do |response|
4
+ response[:defined_subjects] ||= []
5
+ response[:filter_captures].each_pair do |name, capture|
6
+ response[:defined_subjects] << Akiva::Brain::Helpers.cleanup_articles(capture) if name =~ /\Asubject\d+/
7
+ end
8
+ end
9
+
10
+ end
@@ -0,0 +1,35 @@
1
+ Akiva::Brain.update do
2
+
3
+ add_action :sort_answers_by_units do |response|
4
+ # This is supposed to sort one answer for one property for multiple subjects,
5
+ # you may want to create another action to do something more.
6
+
7
+ answers_values = response[:answers].map{|hash| hash.last.first.last }
8
+
9
+ begin
10
+ units = Akiva::Brain::Helpers::Units.new(answers_values)
11
+ units.sort
12
+ rescue
13
+ # we fail silently for now, as the error probably comes from the data in TheBigDB anyway,
14
+ # which could well be invalid (= not convertible units)
15
+ else
16
+ response[:sorted_answers_by_units] = []
17
+ units.result.each do |instantiated_value|
18
+ response[:answers].each do |hash|
19
+ if instantiated_value == hash.last.first.last
20
+ response[:sorted_answers_by_units] <<
21
+ {
22
+ hash.first => {
23
+ hash.last.first.first => {
24
+ value: instantiated_value.to_s
25
+ }
26
+ }
27
+ }
28
+ end
29
+ end
30
+ end
31
+ end # begin
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,23 @@
1
+ # Akiva::Brain.update do
2
+ #
3
+ # add_action :name_of_action do |response|
4
+ # # 'response' is the same hash passed to all before_actions and to the action itself
5
+ # # The following keys are set from the start:
6
+ # response[:filter_matched] => {regex: /[original regex capturing the following (?<stuff_captured>.+)/, action: :name_of_action, [other options]}
7
+ # response[:filter_captures] => Hash of the captures made in the regex e.g. {"stuff_captured" => "words captured from the question"}
8
+ # end
9
+ #
10
+ # # If you're going to work with a huge action, you may want to pass a class instance instead of a block,
11
+ # # the method #process will be called with the current response as an argument.
12
+ # # The important difference is that you must return the new response when exiting #process, instead of modifying "response" as you do in blocks
13
+ #
14
+ # class MyCustomAction
15
+ # def process(response)
16
+ # # do stuff
17
+ # return new_response
18
+ # end
19
+ # end
20
+ #
21
+ # add_action :name_of_action, MyCustomAction.new
22
+ #
23
+ # end
@@ -0,0 +1,15 @@
1
+ Akiva::Brain.update do
2
+ # The priority is based upon order of creation: last created -> highest priority.
3
+
4
+ add_filter :get_answers_from_subjects_and_properties,
5
+ /\A(?:What (?:is|are)|What's) the (?<properties>.+?) of (?:a |an |the )?(?<subjects>.+?)(?: \?)?\z/i,
6
+ formatter: :list_all_answers
7
+
8
+ add_filter :get_answers_from_subjects_and_properties,
9
+ /\AIs (?<subject1>.+?) (?<comparison_adjective>(#{Akiva::Brain::Helpers::ComparisonAdjectivesToProperties.keys.join("|")})?) than (?<subject2>.+?)(?: \?)?\z/i,
10
+ before_action: [:regroup_separated_subjects, :extract_property_from_comparison_adjective],
11
+ after_action: [:compare_two_subjects_properties_from_comparison_adjective],
12
+ formatter: :boolean_from_comparison
13
+
14
+
15
+ end
@@ -0,0 +1,9 @@
1
+ # Akiva::Brain.update do
2
+ #
3
+ # add_filter :name_of_the_action_that_will_be_called,
4
+ # /regex matching that will trigger this action/i,
5
+ # before_action: [:pre_action_one, :pre_action_two, [...]], # will be executed in this order
6
+ # after_action: [:post_action_one, :post_action_two, [...]], # will be executed in this order
7
+ # formatter: :name_of_formatter
8
+ #
9
+ # end
@@ -0,0 +1,17 @@
1
+ Akiva::Brain.update do
2
+
3
+ add_formatter :boolean_from_comparison do |response|
4
+ if response.has_key?(:comparison_boolean_result)
5
+ if response[:comparison_boolean_result]
6
+ response[:formatted] = "Yes"
7
+ else
8
+ response[:formatted] = "No"
9
+ end
10
+
11
+ if response.has_key?(:actions_chain) and response[:actions_chain].include?(:compare_two_subjects_properties_from_comparison_adjective)
12
+ response[:formatted] += " (#{Akiva::Brain.formatters[:list_all_answers].call(response)})"
13
+ end
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,28 @@
1
+ Akiva::Brain.update do
2
+
3
+ add_formatter :list_all_answers do |response|
4
+
5
+ describe_properties = lambda do |subject|
6
+ if (properties = response[:properties][subject]).size == 1 # if there is only one property
7
+ response[:answers][subject][properties.first]
8
+ else # if there are multiple properties
9
+ answers = response[:answers][subject].values
10
+ properties.map.with_index do |property, i|
11
+ property.capitalize + ": " + answers[i]
12
+ end.join(", ")
13
+ end
14
+ end
15
+
16
+ if response[:subjects]
17
+ if response[:subjects].size == 1 # if there's only one subject
18
+ response[:formatted] = describe_properties.call(response[:subjects].first)
19
+ else # if there are multiple subjects
20
+ response[:formatted] = response[:subjects].map do |subject|
21
+ subject + " => " + describe_properties.call(subject)
22
+ end.join("; ")
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,19 @@
1
+ # Akiva::Brain.update do
2
+ #
3
+ # add_formatter :formatter_name do |response|
4
+ # # you must set response[:formatted] as a textual answer to the question
5
+ # end
6
+ #
7
+ # # If you're going to work with a huge formatter, you may want to pass a class instance instead of a block,
8
+ # # the method #process will be called with the current response as an argument.
9
+ # # The important difference is that you must return the new response when exiting #process, instead of modifying "response" as you do in blocks
10
+ #
11
+ # class MyCustomFormatter
12
+ # def process(response)
13
+ # # do stuff
14
+ # return new_response
15
+ # end
16
+ # end
17
+ #
18
+ # add_formatter :name_of_action, MyCustomFormatter.new
19
+ # end
@@ -0,0 +1,151 @@
1
+ module Akiva
2
+ module Brain
3
+ module Helpers
4
+ ComparisonAdjectivesToProperties = {
5
+ "bigger" => {properties: %w(size), comparator: "superior"},
6
+ "blacker" => {properties: %w(blackness), comparator: "superior"},
7
+ "bolder" => {properties: %w(boldness), comparator: "superior"},
8
+ "braver" => {properties: %w(courage), comparator: "superior"},
9
+ "brighter" => {properties: %w(brightness), comparator: "superior"},
10
+ "busier" => {properties: %w(business), comparator: "superior"},
11
+ # "cleaner" => {properties: %w(cleanliness)},
12
+ "clearer" => {properties: %w(clearness), comparator: "superior"},
13
+ # "cleverer" => {properties: %w(cleverness)},
14
+ "colder" => {properties: %w(temperature), comparator: "inferior"},
15
+ "cooler" => {properties: %w(temperature), comparator: "inferior"},
16
+ "darker" => {properties: %w(luminosity), comparator: "inferior"},
17
+ # "dearer" => {properties: %w(dearness)},
18
+ "deeper" => {properties: %w(depth), comparator: "superior"},
19
+ # "dirtier" => {properties: %w(dirtiness)},
20
+ "drier" => {properties: %w(humidity), comparator: "inferior"},
21
+ # "easier" => {properties: %w(easiness)},
22
+ # "fairer" => {properties: %w(fairness)},
23
+ "faster" => {properties: %w(speed), comparator: "superior"},
24
+ "fatter" => {properties: %w(fatness), comparator: "superior"},
25
+ # "finer" => {properties: %w()},
26
+ "funnier" => {properties: %w(funniness), comparator: "superior"},
27
+ "greater" => {properties: %w(greatness), comparator: "superior"},
28
+ "greener" => {properties: %w(greeness), comparator: "superior"},
29
+ # "happier" => {properties: %w(happiness)},
30
+ # "harder" => {properties: %w(hardness)},
31
+ "healthier" => {properties: %w(healthiness)},
32
+ "heavier" => {properties: ["weight", "average weight"], comparator: "superior"},
33
+ # "higher" => {properties: %w(highness)},
34
+ "hotter" => {properties: %w(temperature), comparator: "superior"},
35
+ # "kinder" => {properties: %w(kindness)},
36
+ "larger" => {properties: %w(size), comparator: "superior"},
37
+ # "later" => {properties: %w(timing)},
38
+ # "lazier" => {properties: %w(laziness)},
39
+ "lighter" => {properties: ["weight", "average weight"], comparator: "inferior"},
40
+ "longer" => {properties: %w(size duration), comparator: "superior"},
41
+ # "lower" => {properties: %w(lowerness)},
42
+ # "luckier" => {properties: %w(luck)},
43
+ # "madder" => {properties: %w(madness)},
44
+ # "merrier" => {properties: %w(merriness)},
45
+ # "narrower" => {properties: %w(narrowness)},
46
+ # "naughtier" => {properties: %w(naughtiness)},
47
+ # "nearer" => {properties: %w(nearness)},
48
+ "newer" => {properties: ["age", "creation date", "release date"], comparator: "inferior"},
49
+ # "noiser" => {properties: %w(noisiness)},
50
+ "older" => {properties: ["age", "creation date", "release date"], comparator: "superior"},
51
+ # "paler" => {properties: %w(paleness)},
52
+ "poorer" => {properties: ["net worth"], comparator: "inferior"},
53
+ # "prettier" => {properties: %w(prettiness)},
54
+ # "prouder" => {properties: %w(proudness)},
55
+ "quicker" => {properties: %w(speed), comparator: "superior"},
56
+ # "redder" => {properties: %w(redness)},
57
+ "richer" => {properties: ["net worth"], comparator: "superior"},
58
+ # "sadder" => {properties: %w(sadness)},
59
+ # "saffer" => {properties: %w(safeness)},
60
+ # "shallower" => {properties: %w(shallowness)},
61
+ # "sharper" => {properties: %w(sharpness)},
62
+ "shorter" => {properties: %w(size duration), comparator: "inferior"},
63
+ # "shallower" => {properties: %w(shallowness)},
64
+ "slower" => {properties: %w(speed), comparator: "inferior"},
65
+ "smaller" => {properties: %w(size duration), comparator: "inferior"},
66
+ # "smoother" => {properties: %w(smoothness)},
67
+ "stronger" => {properties: %w(power), comparator: "superior"},
68
+ # "sweeter" => {properties: %w(sweetness)},
69
+ "taller" => {properties: %w(height size), comparator: "superior"},
70
+ # "thicker" => {properties: %w(thickness)},
71
+ "thinner" => {properties: %w(size), comparator: "inferior"},
72
+ "tinier" => {properties: %w(size), comparator: "inferior"},
73
+ # "uglier" => {properties: %w(ugliness)},
74
+ "warmer" => {properties: %w(temperature), comparator: "superior"},
75
+ "weakness" => {properties: %w(power), comparator: "inferior"},
76
+ "wealthier" => {properties: ["net worth"], comparator: "superior"},
77
+ "wetter" => {properties: %w(humidity), comparator: "superior"},
78
+ # "whither" => {properties: %w()},
79
+ "wider" => {properties: %w(wideness size), comparator: "superior"},
80
+ # "wilder" => {properties: %w(wildness)},
81
+ # "wiser" => {properties: %w(wiseness)},
82
+ "younger" => {properties: %w(age), comparator: "inferior"},
83
+
84
+
85
+ "more ancient" => {properties: ["age", "creation date", "release date"], comparator: "inferior"},
86
+ # "more beautiful" => {properties: %w(looks)},
87
+ # "more brilliant" => {properties: %w(brilliantness)},
88
+ # "more careful" => {properties: %w(carefulness)},
89
+ # "more careless" => {properties: %w(carefulness)},
90
+ # "more cheerful" => {properties: %w(cheerfulness)},
91
+ # "more comfortable" => {properties: %w(comfortableness)},
92
+ # "more dangerous" => {properties: %w(dangerousness)},
93
+ # "more delightful" => {properties: %w(delightfulness)},
94
+ # "more difficult" => {properties: %w(difficultness)},
95
+ # "more enjoyable" => {properties: %w(enjoyability)},
96
+ # "more foolish" => {properties: %w(foolishness)},
97
+ # "more forgetful" => {properties: %w(forgetfulness)},
98
+ # "more frightening" => {properties: %w(frighteningness)},
99
+ # "more generous" => {properties: %w(generousness)},
100
+ # "more handsome" => {properties: %w(handsomeness)},
101
+ # "more helpful" => {properties: %w(helpfulness)},
102
+ # "more ignorant" => {properties: %w(ignorantness)},
103
+ # "more important" => {properties: %w(importantness)},
104
+ # "more intelligent" => {properties: %w(intelligentness)},
105
+ # "more interesting" => {properties: %w(interestingness)},
106
+ # "more pleasant" => {properties: %w(pleasantness)},
107
+ "more powerful" => {properties: %w(power), comparator: "superior"},
108
+ "more prosperous" => {properties: ["gross domestic product"], comparator: "superior"},
109
+ # "more sensible" => {properties: %w(sensibleness)},
110
+ # "more terrible" => {properties: %w(terribleness)},
111
+ # "more thoughtful" => {properties: %w(thoughtfulness)},
112
+ # "more unusual" => {properties: %w(unusualness)},
113
+ # "more useful" => {properties: %w(usefulness)},
114
+ "more valuable" => {properties: ["worth", "price"], comparator: "superior"},
115
+ # "more wonderful" => {properties: %w(wonderfulness)},
116
+
117
+ "less ancient" => {properties: ["age", "creation date", "release date"], comparator: "inferior"},
118
+ # "less beautiful" => {properties: %w(looks)},
119
+ # "less brilliant" => {properties: %w(brilliantness)},
120
+ # "less careful" => {properties: %w(carefulness)},
121
+ # "less careless" => {properties: %w(carefulness)},
122
+ # "less cheerful" => {properties: %w(cheerfulness)},
123
+ # "less comfortable" => {properties: %w(comfortableness)},
124
+ # "less dangerous" => {properties: %w(dangerousness)},
125
+ # "less delightful" => {properties: %w(delightfulness)},
126
+ # "less difficult" => {properties: %w(difficultness)},
127
+ # "less enjoyable" => {properties: %w(enjoyability)},
128
+ # "less foolish" => {properties: %w(foolishness)},
129
+ # "less forgetful" => {properties: %w(forgetfulness)},
130
+ # "less frightening" => {properties: %w(frighteningness)},
131
+ # "less generous" => {properties: %w(generousness)},
132
+ # "less handsome" => {properties: %w(handsomeness)},
133
+ # "less helpful" => {properties: %w(helpfulness)},
134
+ # "less ignorant" => {properties: %w(ignorantness)},
135
+ # "less important" => {properties: %w(importantness)},
136
+ # "less intelligent" => {properties: %w(intelligentness)},
137
+ # "less interesting" => {properties: %w(interestingness)},
138
+ # "less pleasant" => {properties: %w(pleasantness)},
139
+ "less powerful" => {properties: %w(power), comparator: "superior"},
140
+ "less prosperous" => {properties: ["gross domestic product"], comparator: "superior"},
141
+ # "less sensible" => {properties: %w(sensibleness)},
142
+ # "less terrible" => {properties: %w(terribleness)},
143
+ # "less thoughtful" => {properties: %w(thoughtfulness)},
144
+ # "less unusual" => {properties: %w(unusualness)},
145
+ # "less useful" => {properties: %w(usefulness)},
146
+ "less valuable" => {properties: ["worth", "price"], comparator: "superior"},
147
+ # "less wonderful" => {properties: %w(wonderfulness)},
148
+ }
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,28 @@
1
+ module Akiva
2
+ module Brain
3
+ module Helpers
4
+
5
+ def self.degroup_multiple_values(string)
6
+ # NOTE: we probably should check the dictionary here to improve the values detections,
7
+ # and limit the number of requests made.
8
+ values = []
9
+
10
+ string.split(" && ").each do |sub0|
11
+ sub0.split(",").each do |sub1|
12
+ sub1.split(" and ").each do |sub2|
13
+ val = sub2.strip
14
+ val.gsub!(/\A(a|an|the) /i, "")
15
+ values << val
16
+ end
17
+ end
18
+ end
19
+
20
+ values.uniq
21
+ end
22
+
23
+ def self.cleanup_articles(string)
24
+ string.gsub(/\A(a|an|the) /i, "")
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,167 @@
1
+ module Akiva
2
+ module Brain
3
+ module Helpers
4
+ class Units
5
+ class UnitNotRecognizedError < StandardError; end
6
+ class IncompatibleUnitsError < StandardError; end
7
+ class TooLongToInstantiateError < StandardError; end
8
+ class NeedTwoValuesToCompareError < StandardError; end
9
+ class CantCompareMoreThanTwoValuesError < StandardError; end
10
+ class InputMustBeAnArray < StandardError; end
11
+
12
+ attr_reader :input, :result, :instantiated_values, :first_value, :last_value
13
+
14
+ def initialize(input)
15
+ @input = input
16
+ end
17
+
18
+ def compare(options = {})
19
+ check_presence_of_values
20
+ check_type_of_values
21
+ check_length_of_values_for_comparison
22
+ instantiate_values
23
+ check_compatibility_of_units
24
+
25
+ @first_value = @instantiated_values.first
26
+ @last_value = @instantiated_values.last
27
+
28
+ if multiplicators = options[:multiplicators]
29
+ @first_value = (@first_value * multiplicators[0]) if multiplicators[0]
30
+ @last_value = (@last_value * multiplicators[1]) if multiplicators[1]
31
+ end
32
+
33
+ @first_value, @last_value = self.class.adjust_units(@first_value, @last_value)
34
+
35
+ if @first_value > @last_value
36
+ @result = "superior"
37
+ elsif @first_value < @last_value
38
+ @result = "inferior"
39
+ else
40
+ @result = "equal"
41
+ end
42
+ end
43
+
44
+ def sort
45
+ check_presence_of_values
46
+ check_type_of_values
47
+ check_maximum_length_of_values
48
+ instantiate_values
49
+ check_compatibility_of_units
50
+
51
+ @result = @instantiated_values.sort
52
+ end
53
+
54
+ def convert(new_unit = "")
55
+ instantiate_values
56
+
57
+ begin
58
+ new_instantiated_value = @instantiated_value.convert_to(new_unit)
59
+ @result = new_instantiated_value.scalar.to_f.to_s
60
+ @result = @result[0..@result.size-3] if @result.match(/\.0$/) # 135.0 => 135
61
+ rescue ArgumentError => error_string
62
+ if error_string.to_s.include?("Unit not recognized") or error_string.to_s.include?("No Unit Specified")
63
+ raise UnitNotRecognizedError
64
+ elsif error_string.to_s.include?("Incompatible Units")
65
+ raise IncompatibleUnitsError
66
+ else
67
+ raise
68
+ end
69
+ end
70
+ end
71
+
72
+
73
+ def self.adjust_units(value_1, value_2)
74
+ if ((value_1.to_s.include?("e+") or value_1.to_s.include?("e-")) and (!value_2.to_s.include?("e+") and !value_2.to_s.include?("e-"))) or value_1.scalar.to_s.size > value_2.scalar.to_s.size
75
+ value_1 = value_1.convert_to(value_2)
76
+ elsif ((!value_1.to_s.include?("e+") and !value_1.to_s.include?("e-")) and (value_2.to_s.include?("e+") or value_2.to_s.include?("e-"))) or value_1.scalar.to_s.size < value_2.scalar.to_s.size
77
+ value_2 = value_2.convert_to(value_1)
78
+ end
79
+
80
+ [value_1, value_2]
81
+ end
82
+
83
+ private
84
+ def check_presence_of_value
85
+ if @input.nil?
86
+ raise NeedTwoValuesToCompareError
87
+ end
88
+ end
89
+
90
+ def check_presence_of_values
91
+ if @input.nil?
92
+ raise NeedTwoValuesToCompareError
93
+ end
94
+ end
95
+
96
+ def check_type_of_values
97
+ unless @input.is_a?(Array) or @input.is_a?(Hash)
98
+ raise InputMustBeAnArray
99
+ end
100
+ end
101
+
102
+ def check_length_of_values_for_comparison
103
+ if @input.size < 2
104
+ raise NeedTwoValuesToCompareError
105
+ elsif @input.size > 2
106
+ raise CantCompareMoreThanTwoValuesError
107
+ end
108
+ end
109
+
110
+ def check_maximum_length_of_values
111
+ if @input.size > 100
112
+ raise CantCompareMoreThanTwoValuesError
113
+ end
114
+ end
115
+
116
+ def instantiate_values
117
+ # we accept strings here specially for the "convert" action
118
+ # everywhere else it is filtered with check_type_of_values
119
+
120
+ if @input.is_a?(String)
121
+ values_strings = [@input]
122
+ elsif @input.is_a?(Hash)
123
+ values_strings = @input.values
124
+ else
125
+ values_strings = @input
126
+ end
127
+
128
+ begin
129
+ # we check how much time it takes because it can be REALLY slow be big textual values
130
+ # e.g. "900000000000000000000000000000000000 meters" took 5secs to instantiate (!)
131
+ Timeout::timeout(0.1) do
132
+ if @input.is_a?(String)
133
+ @instantiated_value = Unit(@input)
134
+ elsif values_strings.is_a?(Array)
135
+ @instantiated_values = values_strings.map{|_| Unit(_) }
136
+ end
137
+ end
138
+ rescue Timeout::Error
139
+ raise CantCompareMoreThanTwoValuesError
140
+ return false
141
+ rescue ArgumentError => error_string
142
+ if error_string.to_s.include?("Unit not recognized")
143
+ raise UnitNotRecognizedError
144
+ return false
145
+ else
146
+ raise # error unknown
147
+ end
148
+ end
149
+ end
150
+
151
+ def check_compatibility_of_units
152
+ # we simply check if it can be sorted
153
+ begin
154
+ @instantiated_values.sort
155
+ rescue ArgumentError => error_string
156
+ if error_string.to_s.include?("Incompatible Units")
157
+ raise IncompatibleUnitsError.new(error_string)
158
+ else
159
+ raise
160
+ end
161
+ end
162
+ end
163
+
164
+ end
165
+ end
166
+ end
167
+ end