games_dice 0.3.12 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop.yml +15 -0
- data/.travis.yml +7 -10
- data/CHANGELOG.md +6 -0
- data/Gemfile +2 -0
- data/Rakefile +14 -11
- data/ext/games_dice/extconf.rb +4 -22
- data/ext/games_dice/probabilities.c +1 -1
- data/games_dice.gemspec +26 -32
- data/lib/games_dice/bunch.rb +241 -247
- data/lib/games_dice/complex_die.rb +287 -270
- data/lib/games_dice/complex_die_helpers.rb +68 -60
- data/lib/games_dice/constants.rb +10 -10
- data/lib/games_dice/dice.rb +146 -143
- data/lib/games_dice/die.rb +101 -97
- data/lib/games_dice/die_result.rb +193 -189
- data/lib/games_dice/map_rule.rb +72 -70
- data/lib/games_dice/marshal.rb +18 -13
- data/lib/games_dice/parser.rb +219 -218
- data/lib/games_dice/reroll_rule.rb +76 -77
- data/lib/games_dice/version.rb +3 -1
- data/lib/games_dice.rb +19 -19
- data/spec/bunch_spec.rb +399 -420
- data/spec/complex_die_spec.rb +314 -305
- data/spec/dice_spec.rb +33 -34
- data/spec/die_result_spec.rb +162 -169
- data/spec/die_spec.rb +81 -81
- data/spec/helpers.rb +23 -21
- data/spec/map_rule_spec.rb +40 -44
- data/spec/parser_spec.rb +106 -82
- data/spec/probability_spec.rb +530 -526
- data/spec/readme_spec.rb +404 -390
- data/spec/reroll_rule_spec.rb +40 -44
- metadata +39 -28
- data/lib/games_dice/prob_helpers.rb +0 -259
- data/lib/games_dice/probabilities.rb +0 -244
data/lib/games_dice/map_rule.rb
CHANGED
@@ -1,70 +1,72 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
|
10
|
-
#
|
11
|
-
# rule.
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# rule
|
15
|
-
|
16
|
-
#
|
17
|
-
# rule.
|
18
|
-
#
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
return
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GamesDice
|
4
|
+
# This class models rules that convert numbers shown on a die to values used in a game. A
|
5
|
+
# common use for this is to count "successes" - dice that score a certain number or higher.
|
6
|
+
#
|
7
|
+
# An object of the class represents a single rule, such as "count a die result of 5 or more as 1
|
8
|
+
# _success_".
|
9
|
+
#
|
10
|
+
# @example A rule for counting successes
|
11
|
+
# rule = GamesDice::MapRule.new( 6, :<=, 1, 'Success' )
|
12
|
+
# # Test how the rule applies . . .
|
13
|
+
# rule.map_from 4 # => nil
|
14
|
+
# rule.map_from 6 # => 1
|
15
|
+
#
|
16
|
+
# @example A rule for counting "fumbles" which reduce total successes
|
17
|
+
# rule = GamesDice::MapRule.new( 1, :==, -1, 'Fumble' )
|
18
|
+
# # Test how the rule applies . . .
|
19
|
+
# rule.map_from 7 # => nil
|
20
|
+
# rule.map_from 1 # => -1
|
21
|
+
#
|
22
|
+
class MapRule
|
23
|
+
# Creates new instance of GamesDice::MapRule. The rule will be assessed as
|
24
|
+
# trigger_value.send( trigger_op, x )
|
25
|
+
# where x is the Integer value shown on a die.
|
26
|
+
# @param [Integer,Range<Integer>,Object] trigger_value Any object is allowed, but typically an Integer
|
27
|
+
# @param [Symbol] trigger_op A method of trigger_value that takes an Integer param and returns Boolean
|
28
|
+
# @param [Integer] mapped_value The value to use in place of the trigger value
|
29
|
+
# @param [String] mapped_name Name of mapped value, for use in descriptions
|
30
|
+
# @return [GamesDice::MapRule]
|
31
|
+
def initialize(trigger_value, trigger_op, mapped_value = 0, mapped_name = '')
|
32
|
+
unless trigger_value.respond_to?(trigger_op)
|
33
|
+
raise ArgumentError,
|
34
|
+
"trigger_value #{trigger_value.inspect} cannot respond to trigger_op #{trigger_value.inspect}"
|
35
|
+
end
|
36
|
+
|
37
|
+
@trigger_value = trigger_value
|
38
|
+
@trigger_op = trigger_op
|
39
|
+
raise TypeError unless mapped_value.is_a? Numeric
|
40
|
+
|
41
|
+
@mapped_value = Integer(mapped_value)
|
42
|
+
@mapped_name = mapped_name.to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
# Trigger operation. How the rule is assessed against #trigger_value.
|
46
|
+
# @return [Symbol] Method name to be sent to #trigger_value
|
47
|
+
attr_reader :trigger_op
|
48
|
+
|
49
|
+
# Trigger value. An object that will use #trigger_op to assess a die result for a reroll.
|
50
|
+
# @return [Integer,Range,Object] Object that receives (#trigger_op, die_result)
|
51
|
+
attr_reader :trigger_value
|
52
|
+
|
53
|
+
# Value that a die will use after the value has been mapped.
|
54
|
+
# @return [Integer]
|
55
|
+
attr_reader :mapped_value
|
56
|
+
|
57
|
+
# Name for mapped value, used in explanations.
|
58
|
+
# @return [String]
|
59
|
+
attr_reader :mapped_name
|
60
|
+
|
61
|
+
# Assesses the rule against a die result value.
|
62
|
+
# @param [Integer] test_value Value that is result of rolling a single die.
|
63
|
+
# @return [Integer,nil] Replacement value, or nil if this rule doesn't apply
|
64
|
+
def map_from(test_value)
|
65
|
+
op_result = @trigger_value.send(@trigger_op, test_value)
|
66
|
+
return nil unless op_result
|
67
|
+
return @mapped_value if op_result == true
|
68
|
+
|
69
|
+
op_result
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/games_dice/marshal.rb
CHANGED
@@ -1,13 +1,18 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GamesDice
|
4
|
+
# Probability calculations
|
5
|
+
class Probabilities
|
6
|
+
# @!visibility private
|
7
|
+
# Adds support for Marshal, via to_h and from_h methods
|
8
|
+
def _dump(*_ignored)
|
9
|
+
Marshal.dump to_h
|
10
|
+
end
|
11
|
+
|
12
|
+
# @!visibility private
|
13
|
+
def self._load(buf)
|
14
|
+
h = Marshal.load buf
|
15
|
+
from_h h
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/games_dice/parser.rb
CHANGED
@@ -1,218 +1,219 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
#
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
#
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
out_hash
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
out_hash[:
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
out_hash[:rerolls]
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
out_hash[:keep_mode]
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
out_hash[:maps] <<
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'parslet'
|
4
|
+
|
5
|
+
module GamesDice
|
6
|
+
# Based on the parslet gem, this class defines the dice mini-language used by GamesDice.create
|
7
|
+
#
|
8
|
+
# An instance of this class is a parser for the language. There are no user-definable instance
|
9
|
+
# variables.
|
10
|
+
#
|
11
|
+
class Parser < Parslet::Parser
|
12
|
+
# Parslet rules that define the dice string grammar.
|
13
|
+
rule(:integer) { match('[0-9]').repeat(1) }
|
14
|
+
rule(:plus_minus_integer) { (match('[+-]') >> integer) | integer }
|
15
|
+
rule(:range) { integer.as(:range_start) >> str('..') >> integer.as(:range_end) }
|
16
|
+
rule(:dlabel) { match('[d]') }
|
17
|
+
rule(:space) { match('\s').repeat(1) }
|
18
|
+
rule(:space?) { space.maybe }
|
19
|
+
rule(:underscore) { str('_').repeat(1) }
|
20
|
+
rule(:underscore?) { space.maybe }
|
21
|
+
|
22
|
+
rule(:bunch_start) { integer.as(:ndice) >> dlabel >> integer.as(:sides) }
|
23
|
+
|
24
|
+
rule(:reroll_label) { match(['r']).as(:reroll) }
|
25
|
+
rule(:keep_label) { match(['k']).as(:keep) }
|
26
|
+
rule(:map_label) { match(['m']).as(:map) }
|
27
|
+
rule(:alias_label) { match(['x']).as(:alias) }
|
28
|
+
|
29
|
+
rule(:single_modifier) { alias_label }
|
30
|
+
rule(:modifier_label) { reroll_label | keep_label | map_label }
|
31
|
+
rule(:simple_modifier) { modifier_label >> integer.as(:simple_value) }
|
32
|
+
rule(:comparison_op) { str('>=') | str('<=') | str('==') | str('>') | str('<') }
|
33
|
+
rule(:ctl_string) { match('[a-z_]').repeat(1) }
|
34
|
+
rule(:output_string) { match('[A-Za-z0-9_]').repeat(1) }
|
35
|
+
|
36
|
+
rule(:opint_or_int) { (comparison_op.as(:comparison) >> integer.as(:compare_num)) | integer.as(:compare_num) }
|
37
|
+
rule(:comma) { str(',') }
|
38
|
+
rule(:stop) { str('.') }
|
39
|
+
|
40
|
+
rule(:condition_only) { opint_or_int.as(:condition) }
|
41
|
+
rule(:num_only) { integer.as(:num) }
|
42
|
+
|
43
|
+
rule(:condition_and_type) { opint_or_int.as(:condition) >> comma >> ctl_string.as(:type) }
|
44
|
+
rule(:condition_and_num) { opint_or_int.as(:condition) >> comma >> plus_minus_integer.as(:num) }
|
45
|
+
|
46
|
+
rule(:condition_type_and_num) do
|
47
|
+
opint_or_int.as(:condition) >> comma >> ctl_string.as(:type) >> comma >> integer.as(:num)
|
48
|
+
end
|
49
|
+
rule(:condition_num_and_output) do
|
50
|
+
opint_or_int.as(:condition) >> comma >> plus_minus_integer.as(:num) >> comma >> output_string.as(:output)
|
51
|
+
end
|
52
|
+
rule(:num_and_type) { integer.as(:num) >> comma >> ctl_string.as(:type) }
|
53
|
+
|
54
|
+
rule(:reroll_params) { condition_type_and_num | condition_and_type | condition_only }
|
55
|
+
rule(:map_params) { condition_num_and_output | condition_and_num | condition_only }
|
56
|
+
rule(:keeper_params) { num_and_type | num_only }
|
57
|
+
|
58
|
+
rule(:full_reroll) { reroll_label >> str(':') >> reroll_params >> stop }
|
59
|
+
rule(:full_map) { map_label >> str(':') >> map_params >> stop }
|
60
|
+
rule(:full_keepers) { keep_label >> str(':') >> keeper_params >> stop }
|
61
|
+
|
62
|
+
rule(:complex_modifier) { full_reroll | full_map | full_keepers }
|
63
|
+
|
64
|
+
rule(:bunch_modifier) { complex_modifier | (single_modifier >> stop.maybe) | (simple_modifier >> stop.maybe) }
|
65
|
+
rule(:bunch) { bunch_start >> bunch_modifier.repeat.as(:mods) }
|
66
|
+
|
67
|
+
rule(:operator) { match('[+-]').as(:op) >> space? }
|
68
|
+
rule(:add_bunch) { operator >> bunch >> space? }
|
69
|
+
rule(:add_constant) { operator >> integer.as(:constant) >> space? }
|
70
|
+
rule(:dice_expression) { add_bunch | add_constant }
|
71
|
+
rule(:expressions) { dice_expression.repeat.as(:bunches) }
|
72
|
+
root :expressions
|
73
|
+
|
74
|
+
# Parses a string description in the dice mini-language, and returns data for feeding into
|
75
|
+
# GamesDice::Dice constructor.
|
76
|
+
# @param [String] dice_description Text to parse e.g. '1d6'
|
77
|
+
# @return [Hash] Analysis of dice_description
|
78
|
+
def parse(dice_description)
|
79
|
+
dice_description = dice_description.to_s.strip
|
80
|
+
# Force first item to start '+' for simpler parse rules
|
81
|
+
dice_description = "+#{dice_description}" unless dice_description =~ /\A[+-]/
|
82
|
+
dice_expressions = super(dice_description)
|
83
|
+
{ bunches: collect_bunches(dice_expressions), offset: collect_offset(dice_expressions) }
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def collect_bunches(dice_expressions)
|
89
|
+
dice_expressions[:bunches].select { |h| h[:ndice] }.map do |in_hash|
|
90
|
+
out_hash = {}
|
91
|
+
# Convert integers
|
92
|
+
%i[ndice sides].each do |s|
|
93
|
+
next unless in_hash[s]
|
94
|
+
|
95
|
+
out_hash[s] = in_hash[s].to_i
|
96
|
+
end
|
97
|
+
|
98
|
+
# Multiplier
|
99
|
+
if in_hash[:op]
|
100
|
+
optype = in_hash[:op].to_s
|
101
|
+
out_hash[:multiplier] = case optype
|
102
|
+
when '+' then 1
|
103
|
+
when '-' then -1
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Modifiers
|
108
|
+
in_hash[:mods]&.each do |mod|
|
109
|
+
if mod[:alias]
|
110
|
+
collect_alias_modifier mod, out_hash
|
111
|
+
elsif mod[:keep]
|
112
|
+
collect_keeper_rule mod, out_hash
|
113
|
+
elsif mod[:map]
|
114
|
+
out_hash[:maps] ||= []
|
115
|
+
collect_map_rule mod, out_hash
|
116
|
+
elsif mod[:reroll]
|
117
|
+
out_hash[:rerolls] ||= []
|
118
|
+
collect_reroll_rule mod, out_hash
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
out_hash
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def collect_offset(dice_expressions)
|
127
|
+
dice_expressions[:bunches].select { |h| h[:constant] }.inject(0) do |total, in_hash|
|
128
|
+
c = in_hash[:constant].to_i
|
129
|
+
optype = in_hash[:op].to_s
|
130
|
+
if optype == '+'
|
131
|
+
total += c
|
132
|
+
else
|
133
|
+
total -= c
|
134
|
+
end
|
135
|
+
total
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Called when we have a single letter convenient alias for common dice adjustments
|
140
|
+
def collect_alias_modifier(alias_mod, out_hash)
|
141
|
+
alias_name = alias_mod[:alias].to_s
|
142
|
+
case alias_name
|
143
|
+
when 'x' # Exploding re-roll
|
144
|
+
out_hash[:rerolls] ||= []
|
145
|
+
out_hash[:rerolls] << [out_hash[:sides], :==, :reroll_add]
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Called for any parsed reroll rule
|
150
|
+
def collect_reroll_rule(reroll_mod, out_hash)
|
151
|
+
out_hash[:rerolls] ||= []
|
152
|
+
if reroll_mod[:simple_value]
|
153
|
+
out_hash[:rerolls] << [reroll_mod[:simple_value].to_i, :>=, :reroll_replace]
|
154
|
+
return
|
155
|
+
end
|
156
|
+
|
157
|
+
# Typical reroll_mod: {:reroll=>"r"@5, :condition=>{:compare_num=>"10"@7}, :type=>"add"@10}
|
158
|
+
op = get_op_symbol(reroll_mod[:condition][:comparison] || '==')
|
159
|
+
v = reroll_mod[:condition][:compare_num].to_i
|
160
|
+
type = "reroll_#{reroll_mod[:type] || 'replace'}".to_sym
|
161
|
+
|
162
|
+
out_hash[:rerolls] << if reroll_mod[:num]
|
163
|
+
[v, op, type, reroll_mod[:num].to_i]
|
164
|
+
else
|
165
|
+
[v, op, type]
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# Called for any parsed keeper mode
|
170
|
+
def collect_keeper_rule(keeper_mod, out_hash)
|
171
|
+
raise 'Cannot set keepers for a bunch twice' if out_hash[:keep_mode]
|
172
|
+
|
173
|
+
if keeper_mod[:simple_value]
|
174
|
+
out_hash[:keep_mode] = :keep_best
|
175
|
+
out_hash[:keep_number] = keeper_mod[:simple_value].to_i
|
176
|
+
return
|
177
|
+
end
|
178
|
+
|
179
|
+
# Typical keeper_mod: {:keep=>"k"@5, :num=>"1"@7, :type=>"worst"@9}
|
180
|
+
out_hash[:keep_number] = keeper_mod[:num].to_i
|
181
|
+
out_hash[:keep_mode] = "keep_#{keeper_mod[:type] || 'best'}".to_sym
|
182
|
+
end
|
183
|
+
|
184
|
+
# Called for any parsed map mode
|
185
|
+
def collect_map_rule(map_mod, out_hash)
|
186
|
+
out_hash[:maps] ||= []
|
187
|
+
if map_mod[:simple_value]
|
188
|
+
out_hash[:maps] << [map_mod[:simple_value].to_i, :<=, 1]
|
189
|
+
return
|
190
|
+
end
|
191
|
+
|
192
|
+
# Typical map_mod: {:map=>"m"@4, :condition=>{:compare_num=>"5"@6}, :num=>"2"@8, :output=>"Qwerty"@10}
|
193
|
+
op = get_op_symbol(map_mod[:condition][:comparison] || '>=')
|
194
|
+
v = map_mod[:condition][:compare_num].to_i
|
195
|
+
out_val = 1
|
196
|
+
out_val = map_mod[:num].to_i if map_mod[:num]
|
197
|
+
|
198
|
+
out_hash[:maps] << if map_mod[:output]
|
199
|
+
[v, op, out_val, map_mod[:output].to_s]
|
200
|
+
else
|
201
|
+
[v, op, out_val]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# The dice description language uses (r).op.x, whilst GamesDice::RerollRule uses x.op.(r), so
|
206
|
+
# as well as converting to a symbol, we must reverse sense of input to constructor
|
207
|
+
OP_CONVERSION = {
|
208
|
+
'==' => :==,
|
209
|
+
'>=' => :<=,
|
210
|
+
'>' => :<,
|
211
|
+
'<' => :>,
|
212
|
+
'<=' => :>=
|
213
|
+
}.freeze
|
214
|
+
|
215
|
+
def get_op_symbol(parsed_op_string)
|
216
|
+
OP_CONVERSION[parsed_op_string.to_s]
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|