etw_math 1.0.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.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/example.rb +105 -0
  3. data/lib/etw_math.rb +516 -0
  4. metadata +44 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3413847b2d51689c22b3b14f40fe7694dba51b74707027fe2db2ac7db6180f4f
4
+ data.tar.gz: 41fcd3d5409d95f27fea39df5cf1428fae23926b5044760e9ee198933a20225f
5
+ SHA512:
6
+ metadata.gz: ef322f376904ed61799bbdc433d62edeef6f904e140f6fcceca5efc699e3311a2aedc9e61540eee6c8bc273630f0b0dbcb1ec0ea657a1328f31ba79f147e0c70
7
+ data.tar.gz: 7153d47d94bea65c19ea60c046db0290cf4d8cad4b81ffe50ed3686bf80f859c7db91ef60d79c734421fc1bb3c086f1d38e5b2b07df51cf7ce61de4e9f0a14e3
data/example.rb ADDED
@@ -0,0 +1,105 @@
1
+ # example.rb - EtwMath examples
2
+ # Copyright (C) 2025 Lazy Villain
3
+ # https://github.com/LazyAntihero/etw_math
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+ require_relative 'etw_math'
27
+
28
+ puts "Input tests..."
29
+ puts EtwMath.input_valid?(5)
30
+ puts EtwMath.input_valid?(5, 500, 2)
31
+ puts EtwMath.input_valid?(5, 200, -1)
32
+ puts EtwMath.input_valid?(5, 's')
33
+ puts EtwMath.input_valid?(5, 0)
34
+ puts EtwMath.input_valid?()
35
+
36
+ puts "\nMax brown crate reward for a max size of 7,000,000:"
37
+ puts EtwMath.brown_crate_max(7000000)
38
+ puts "\nMax yellow crate reward for a max size of 7,000,000:"
39
+ puts EtwMath.yellow_crate_max(7000000)
40
+ puts "\nMax purple crate reward for a max size of 7,000,000:"
41
+ puts EtwMath.purple_crate_max(7000000)
42
+ puts "\nMax jackpot amount for a max size of 7,000,000:"
43
+ puts EtwMath.jackpot_amount(7000000)
44
+ puts "\nWalk speed level for a walk speed value of 300:"
45
+ puts EtwMath.walk_speed_level(300)
46
+ puts "\nWalk speed value for a walk speed level of 150:"
47
+ puts EtwMath.walk_speed_value(150)
48
+ puts "\nMax size at size level 100 size is:"
49
+ puts EtwMath.size_at_level(100)
50
+ puts "\nSize level for a max size of 505,000 is:"
51
+ puts EtwMath.level_at_size(505000)
52
+ puts "\nOptimal size level for a multi of 100 using a factor of 5.5 is:"
53
+ puts EtwMath.optimal_size_level_threshold(100, 5.5)
54
+ puts "\nOptimal multi for a size level of 550 using a ratio of 5.5 is:"
55
+ puts EtwMath.optimal_multi(550, 5.5)
56
+ puts "\nSize upgrade cost at level 2 is:"
57
+ puts EtwMath.size_level_cost(2)
58
+ puts "\nWalk speed upgrade cost at level 2 is:"
59
+ puts EtwMath.walk_level_cost(2)
60
+ puts "\nMultiplier upgrade cost at level 2 is:"
61
+ puts EtwMath.multi_level_cost(2)
62
+ puts "\nEat speed upgrade cost at level 2 is:"
63
+ puts EtwMath.eat_level_cost(2)
64
+ puts "\nTotal cost of size upgrades at level 10 is:"
65
+ puts EtwMath.total_size_investment(10)
66
+ puts "\nTotal cost of walk speed upgrades at level 10 is:"
67
+ puts EtwMath.total_walk_investment(10)
68
+ puts "\nTotal cost of multi upgrades at level 10 is:"
69
+ puts EtwMath.total_multi_investment(10)
70
+ puts "\nTotal cost of eat speed upgrades at level 10 is:"
71
+ puts EtwMath.total_eat_investment(10)
72
+ puts "\nTotal cost of all upgrades at levels 83, 10, 15, and 11 is:"
73
+ puts EtwMath.total_upgrade_investment(83, 10, 15, 11)
74
+ puts "\nTotal cost of all upgrades at levels 1000, 400, 200, and 75 is:"
75
+ puts EtwMath.total_upgrade_investment(1000, 400, 200, 75)
76
+ puts "\nCost of size upgrades from level 5 to 10 is:"
77
+ puts EtwMath.size_range_cost(5, 10)
78
+ puts "\nCost of walk speed upgrades from level 5 to 10 is:"
79
+ puts EtwMath.walk_range_cost(5, 10)
80
+ puts "\nCost of multi upgrades from level 5 to 10 is:"
81
+ puts EtwMath.multi_range_cost(5, 10)
82
+ puts "\nCost of eat speed upgrades from level 5 to 10 is:"
83
+ puts EtwMath.eat_range_cost(5, 10)
84
+ puts "\nSmall bite amount at size 505,000 and 100 multi is:"
85
+ puts EtwMath.small_bite_amount(505000, 100)
86
+ puts "\nMedium bite amount at size 505,000 and 100 multi is:"
87
+ puts EtwMath.medium_bite_amount(505000, 100)
88
+ puts "\nBig bite amount at size 505,000 and 100 multi is:"
89
+ puts EtwMath.big_bite_amount(505000, 100)
90
+ puts "\nIf original size was 9,440 and size after eating a small bite is 10,954, the multi is:"
91
+ puts EtwMath.small_bite_delta_multi(9440, 10954)
92
+ puts "\nIf original size was 9,440 and size after eating a medium bite is 10,954, the multi is:"
93
+ puts EtwMath.medium_bite_delta_multi(9440, 10954)
94
+ puts "\nIf original size was 9,440 and size after eating a big bite is 10,954, the multi is:"
95
+ puts EtwMath.big_bite_delta_multi(9440, 10954)
96
+ puts "\nIf first small bite amount is 270, the multi is:"
97
+ puts EtwMath.small_first_bite_multi(270)
98
+ puts "\nIf first medium bite amount is 270, the multi is:"
99
+ puts EtwMath.medium_first_bite_multi(270)
100
+ puts "\nIf first big bite amount is 270, the multi is:"
101
+ puts EtwMath.big_first_bite_multi(270)
102
+ puts "\nTime to max for a size level of 565 at 101 multi is:"
103
+ puts EtwMath.time_to_max(565, 101)
104
+ puts "\nTime to max for a size level of 140 at 31 multi is:"
105
+ puts EtwMath.time_to_max_small(140, 31)
data/lib/etw_math.rb ADDED
@@ -0,0 +1,516 @@
1
+ # etw_math.rb - Various mathematical formulas for Roblox - Eat the World (ETW)
2
+ # Copyright (C) 2025 Lazy Villain
3
+ # https://github.com/LazyAntihero/etw_math
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+ # @author Lazy Villain
27
+
28
+ # This class contains various methods that perform Eat the World calculations
29
+ class EtwMath
30
+ # EtwMath version
31
+ VERSION = "1.0.0"
32
+
33
+ # Number of seconds in 1 day
34
+ SECONDS_PER_DAY = 86400
35
+
36
+ # Number of seconds in 1 hour
37
+ SECONDS_PER_HOUR = 3600
38
+
39
+ # Number of seconds in 1 minute
40
+ SECONDS_PER_MINUTE = 60
41
+
42
+ # Makes numbers more readable to humans by adding commas
43
+ # @param number [Numeric] Numerical value
44
+ # @param use_decimal [Boolean] Include decimal portion (excluded by default)
45
+ # @return [String] Numerical value represented as a string that may contain commas
46
+ # @example Example without decimal
47
+ # EtwMath.format_number(1234567.89) # 1,234,567
48
+ # @example Example containing decimal
49
+ # EtwMath.format_number(1234567.89, true) # 1,234,567.89
50
+ def self.format_number(number, use_decimal = false)
51
+ whole, decimal = number.to_s.split(".")
52
+ num_groups = whole.chars.to_a.reverse.each_slice(3)
53
+ whole_with_commas = num_groups.map(&:join).join(',').reverse
54
+ if use_decimal
55
+ [whole_with_commas, decimal].compact.join(".")
56
+ else
57
+ return whole_with_commas
58
+ end
59
+ end
60
+
61
+ # Converts seconds to be displayed as hours, minutes, and seconds
62
+ # @param total_seconds [Numeric] Total number of seconds
63
+ # @return [String] Human readable time format
64
+ # @example
65
+ # EtwMath.format_time(1234567) # 14d:06h:56m:07s
66
+ # EtwMath.format_time(123456789) # 1,428d:21h:33m:09s
67
+ def self.format_time(total_seconds)
68
+ days = total_seconds / SECONDS_PER_DAY
69
+ hours = (total_seconds % SECONDS_PER_DAY) / SECONDS_PER_HOUR
70
+ minutes = (total_seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE
71
+ seconds = total_seconds % SECONDS_PER_MINUTE
72
+ if days > 999
73
+ format("%sd:%02dh:%02dm:%02ds", format_number(days), hours, minutes, seconds)
74
+ else
75
+ format("%02dd:%02dh:%02dm:%02ds", days, hours, minutes, seconds)
76
+ end
77
+ end
78
+
79
+ # Displays float values with extraneous decimal positions omitted
80
+ # @param value [Numeric] Numerical value
81
+ # @return [String] A float with 2 decimal positions
82
+ # @example
83
+ # EtwMath.print_decimal(1234.56789) # 1234.56
84
+ def self.print_decimal(value)
85
+ printf('%0.2f', value)
86
+ end
87
+
88
+ # Validates numeric input
89
+ # @param inputs [Array] List of numeric inputs
90
+ # @return [Boolean] false if invalid, true otherwise
91
+ # @example
92
+ # EtwMath.input_valid?(5) # true
93
+ # EtwMath.input_valid?(5, 200, -1, 's', 0) # false
94
+ def self.input_valid?(*inputs)
95
+ return false if inputs.empty?
96
+ inputs.each do |input|
97
+ return false if !input.is_a?(Numeric)
98
+ return false if input <= 0
99
+ end
100
+ return true
101
+ end
102
+
103
+ # Calculates the maximum monetary reward from a brown crate
104
+ # @param size [Integer] Maximum size value
105
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
106
+ # @example
107
+ # EtwMath.brown_crate_max(7000000) # 7,000,000
108
+ def self.brown_crate_max(size)
109
+ return false if !input_valid?(size)
110
+ format_number(size * 1)
111
+ end
112
+
113
+ # Calculates the maximum monetary reward from a yellow crate
114
+ # @param size [Integer] Maximum size value
115
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
116
+ # @example
117
+ # EtwMath.yellow_crate_max(7000000) # 14,000,000
118
+ def self.yellow_crate_max(size)
119
+ return false if !input_valid?(size)
120
+ format_number(size * 2)
121
+ end
122
+
123
+ # Calculates the maximum monetary reward from a purple crate
124
+ # @param size [Integer] Maximum size value
125
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
126
+ # @example
127
+ # EtwMath.purple_crate_max(7000000) # 21,000,000
128
+ def self.purple_crate_max(size)
129
+ return false if !input_valid?(size)
130
+ format_number(size * 3)
131
+ end
132
+
133
+ # Calculates the jackpot reward from a daily spin
134
+ # @param size [Integer] Maximum size value
135
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
136
+ # @example
137
+ # EtwMath.jackpot_amount(7000000) # 35,000,000
138
+ def self.jackpot_amount(size)
139
+ return false if !input_valid?(size)
140
+ format_number(size * 5)
141
+ end
142
+
143
+ # Calculates walk speed value
144
+ # @param walk_speed_level [Integer] Walk speed level
145
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
146
+ # @example
147
+ # EtwMath.walk_speed_value(150) # 310
148
+ def self.walk_speed_value(walk_speed_level)
149
+ return false if !input_valid?(walk_speed_level)
150
+ format_number(walk_speed_level * 2 + 10)
151
+ end
152
+
153
+ # Calculates walk speed level
154
+ # @param walk_speed_value [Integer] Walk speed value
155
+ # @return [String, Boolean] String representation of an integer or false if input is invalid or division by zero occurs
156
+ # @example
157
+ # EtwMath.walk_speed_level(300) # 145
158
+ def self.walk_speed_level(walk_speed_value)
159
+ return false if !input_valid?(walk_speed_value)
160
+ begin
161
+ format_number((walk_speed_value - 10) / 2)
162
+ rescue # division by zero
163
+ return false
164
+ end
165
+ end
166
+
167
+ # Calculates maximum size
168
+ # @param level [Integer] Maximum size level
169
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
170
+ # @example
171
+ # EtwMath.size_at_level(100) # 505,000
172
+ def self.size_at_level(level)
173
+ return false if !input_valid?(level)
174
+ format_number(50 * level ** 2 + 50 * level)
175
+ end
176
+
177
+ # Calculates size level
178
+ # @param level [Integer] Maximum size
179
+ # @return [String, Boolean] String representation of an integer or false if input is invalid or division by zero occurs
180
+ # @example
181
+ # EtwMath.level_at_size(505000) # 100
182
+ def self.level_at_size(size)
183
+ return false if !input_valid?(size)
184
+ begin
185
+ format_number((-50 + Math.sqrt(2500 + 200 * size)) / 100)
186
+ rescue # division by zero
187
+ return false
188
+ end
189
+ end
190
+
191
+ # Calculates optimal size level threshold
192
+ # @param multi [Integer] Multiplier level
193
+ # @param ratio [Numeric] Ratio
194
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
195
+ # @example
196
+ # EtwMath.optimal_size_level_threshold(100, 5.5) # 550
197
+ def self.optimal_size_level_threshold(multi, ratio)
198
+ return false if !input_valid?(multi, ratio)
199
+ format_number(multi * ratio)
200
+ end
201
+
202
+ # Calculates optimal multiplier
203
+ # @param size_level [Integer] Size level
204
+ # @param ratio [Numeric] Ratio
205
+ # @return [String, Boolean] String representation of an integer or false if input is invalid or division by zero occurs
206
+ # @example
207
+ # EtwMath.optimal_multi(550, 5.5) # 100
208
+ def self.optimal_multi(size_level, ratio)
209
+ return false if !input_valid?(size_level, ratio)
210
+ begin
211
+ format_number(size_level / ratio)
212
+ rescue # division by zero
213
+ return false
214
+ end
215
+ end
216
+
217
+ # Calculates cost of a size level
218
+ # @param size_level [Integer] Size level
219
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
220
+ # @example
221
+ # EtwMath.size_level_cost(2) # 80
222
+ def self.size_level_cost(size_level)
223
+ return false if !input_valid?(size_level)
224
+ format_number(10 * size_level ** 3)
225
+ end
226
+
227
+ # Calculates cost of a walk speed level
228
+ # @param walk_level [Integer] Walk speed level
229
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
230
+ # @example
231
+ # EtwMath.walk_level_cost(2) # 1,080
232
+ def self.walk_level_cost(walk_level)
233
+ return false if !input_valid?(walk_level)
234
+ format_number(135 * walk_level ** 3)
235
+ end
236
+
237
+ # Calculates cost of a multiplier level
238
+ # @param multi_level [Integer] Multiplier level
239
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
240
+ # @example
241
+ # EtwMath.multi_level_cost(2) # 40,000
242
+ def self.multi_level_cost(multi_level)
243
+ return false if !input_valid?(multi_level)
244
+ format_number(5000 * multi_level ** 3)
245
+ end
246
+
247
+ # Calculates cost of an eat speed level
248
+ # @param eat_level [Numeric] Eat speed level
249
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
250
+ # @example
251
+ # EtwMath.eat_level_cost(2) # 80,000
252
+ def self.eat_level_cost(eat_level)
253
+ return false if !input_valid?(eat_level)
254
+ format_number(10000 * eat_level ** 3)
255
+ end
256
+
257
+ # Calculates total cost of size upgrades
258
+ # @param size_level [Integer] Size level
259
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
260
+ # @example
261
+ # EtwMath.total_size_investment(10) # 30,240
262
+ def self.total_size_investment(size_level)
263
+ return false if !input_valid?(size_level)
264
+ format_number(5 * (0.5 * size_level ** 4 + size_level ** 3 + 0.5 * size_level ** 2) - 10)
265
+ end
266
+
267
+ # Calculates total cost of walk speed upgrades
268
+ # @param walk_level [Integer] Walk speed level
269
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
270
+ # @example
271
+ # EtwMath.total_walk_investment(10) # 408,240
272
+ def self.total_walk_investment(walk_level)
273
+ return false if !input_valid?(walk_level)
274
+ format_number(67.5 * (0.5 * walk_level ** 4 + walk_level ** 3 + 0.5 * walk_level ** 2) - 135)
275
+ end
276
+
277
+ # Calculates total cost of multiplier upgrades
278
+ # @param multi_level [Integer] Multiplier level
279
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
280
+ # @example
281
+ # EtwMath.total_multi_investment(10) # 15,120,000
282
+ def self.total_multi_investment(multi_level)
283
+ return false if !input_valid?(multi_level)
284
+ format_number(2500 * (0.5 * multi_level ** 4 + multi_level ** 3 + 0.5 * multi_level ** 2) - 5000)
285
+ end
286
+
287
+ # Calculates total cost of eat speed upgrades
288
+ # @param eat_level [Integer] Eat speed level
289
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
290
+ # @example
291
+ # EtwMath.total_eat_investment(10) # 30,240,000
292
+ def self.total_eat_investment(eat_level)
293
+ return false if !input_valid?(eat_level)
294
+ format_number(5000 * (0.5 * eat_level ** 4 + eat_level ** 3 + 0.5 * eat_level ** 2) - 10000)
295
+ end
296
+
297
+ # Calculates total cost of all upgrades
298
+ # @param size_level [Integer] Size level
299
+ # @param walk_level [Integer] Walk speed level
300
+ # @param multi_level [Integer] Multiplier level
301
+ # @param eat_level [Integer] Eat speed level
302
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
303
+ # @example
304
+ # EtwMath.total_upgrade_investment(83, 10, 15, 11) # 237,475,190
305
+ # EtwMath.total_upgrade_investment(1000, 400, 200, 75) # 5,474,602,884,855
306
+ def self.total_upgrade_investment(size_level, walk_speed_level, multi, eat_speed_level)
307
+ return false if !input_valid?(size_level, walk_speed_level, multi, eat_speed_level)
308
+ format_number(5 * (0.5 * size_level ** 4 + size_level ** 3 + 0.5 * size_level ** 2) - 10 + 67.5 * (0.5 * walk_speed_level ** 4 + walk_speed_level ** 3 + 0.5 * walk_speed_level ** 2) - 135 + 2500 * (0.5 * multi ** 4 + multi ** 3 + 0.5 * multi ** 2) - 5000 + 5000 * (0.5 * eat_speed_level ** 4 + eat_speed_level ** 3 + 0.5 * eat_speed_level ** 2) - 10000)
309
+ end
310
+
311
+ # Calculates size cost using a range from a starting level to an ending level
312
+ # @param starting_level [Integer] Starting size level
313
+ # @param ending_level [Integer] Ending size level
314
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
315
+ # @example
316
+ # EtwMath.size_range_cost(5, 10) # 28,000
317
+ def self.size_range_cost(starting_level, ending_level)
318
+ return false if !input_valid?(starting_level, ending_level)
319
+ format_number(5 * (0.5 * ending_level ** 4 + ending_level ** 3 + 0.5 * ending_level ** 2) - 5 * (0.5 * starting_level ** 4 + starting_level ** 3 + 0.5 * starting_level ** 2))
320
+ end
321
+
322
+ # Calculates walk speed cost using a range from a starting level to an ending level
323
+ # @param starting_level [Integer] Starting walk speed level
324
+ # @param ending_level [Integer] Ending walk speed level
325
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
326
+ # @example
327
+ # EtwMath.walk_range_cost(5, 10) # 378,000
328
+ def self.walk_range_cost(starting_level, ending_level)
329
+ return false if !input_valid?(starting_level, ending_level)
330
+ format_number(67.5 * (0.5 * ending_level ** 4 + ending_level ** 3 + 0.5 * ending_level ** 2) - 67.5 * (0.5 * starting_level ** 4 + starting_level ** 3 + 0.5 * starting_level ** 2))
331
+ end
332
+
333
+ # Calculates multiplier cost using a range from a starting level to an ending level
334
+ # @param starting_level [Integer] Starting multiplier level
335
+ # @param ending_level [Integer] Ending multiplier level
336
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
337
+ # @example
338
+ # EtwMath.multi_range_cost(5, 10) # 14,000,000
339
+ def self.multi_range_cost(starting_level, ending_level)
340
+ return false if !input_valid?(starting_level, ending_level)
341
+ format_number(2500 * (0.5 * ending_level ** 4 + ending_level ** 3 + 0.5 * ending_level ** 2) - 2500 * (0.5 * starting_level ** 4 + starting_level ** 3 + 0.5 * starting_level ** 2))
342
+ end
343
+
344
+ # Calculates eat speed cost using a range from a starting level to an ending level
345
+ # @param starting_level [Integer] Starting eat speed level
346
+ # @param ending_level [Integer] Ending eat speed level
347
+ # @return [String, Boolean] String representation of an integer or false if input is invalid
348
+ # @example
349
+ # EtwMath.eat_range_cost(5, 10) # 28,000,000
350
+ def self.eat_range_cost(starting_level, ending_level)
351
+ return false if !input_valid?(starting_level, ending_level)
352
+ format_number(5000 * (0.5 * ending_level ** 4 + ending_level ** 3 + 0.5 * ending_level ** 2) - 5000 * (0.5 * starting_level ** 4 + starting_level ** 3 + 0.5 * starting_level ** 2))
353
+ end
354
+
355
+ # Calculates small bite amount
356
+ # @param current_size [Integer] Current size
357
+ # @param multi [Integer] Multiplier
358
+ # @return [String, Boolean] String representation of an integer or false if input is invalid or division by zero occurs
359
+ # @example
360
+ # EtwMath.small_bite_amount(505000, 100) # 20,300
361
+ def self.small_bite_amount(current_size, multi)
362
+ return false if !input_valid?(current_size, multi)
363
+ begin
364
+ format_number(((50 * (((-50 + Math.sqrt(2500 + 200 * current_size)) / 100) + 0.02 * multi) ** 2 + 50 * (((-50 + Math.sqrt(2500 + 200 * current_size)) / 100) + 0.02 * multi)) - current_size).round)
365
+ rescue # division by zero
366
+ return false
367
+ end
368
+ end
369
+
370
+ # Calculates medium bite amount
371
+ # @param current_size [Integer] Current size
372
+ # @param multi [Integer] Multiplier
373
+ # @return [String, Boolean] String representation of an integer or false if input is invalid or division by zero occurs
374
+ # @example
375
+ # EtwMath.medium_bite_amount(505000, 100) # 30,600
376
+ def self.medium_bite_amount(current_size, multi)
377
+ return false if !input_valid?(current_size, multi)
378
+ begin
379
+ format_number(((50 * (((-50 + Math.sqrt(2500 + 200 * current_size)) / 100) + 0.03 * multi) ** 2 + 50 * (((-50 + Math.sqrt(2500 + 200 * current_size)) / 100) + 0.03 * multi)) - current_size).round)
380
+ rescue # division by zero
381
+ return false
382
+ end
383
+ end
384
+
385
+ # Calculates big bite amount
386
+ # @param current_size [Integer] Current size
387
+ # @param multi [Integer] Multiplier
388
+ # @return [String, Boolean] String representation of an integer or false if input is invalid or division by zero occurs
389
+ # @example
390
+ # EtwMath.big_bite_amount(505000, 100) # 41,000
391
+ def self.big_bite_amount(current_size, multi)
392
+ return false if !input_valid?(current_size, multi)
393
+ begin
394
+ format_number(((50 * (((-50 + Math.sqrt(2500 + 200 * current_size)) / 100) + 0.04 * multi) ** 2 + 50 * (((-50 + Math.sqrt(2500 + 200 * current_size)) / 100) + 0.04 * multi)) - current_size).round)
395
+ rescue # division by zero
396
+ return false
397
+ end
398
+ end
399
+
400
+ # Calculates multiplier using a starting size and an ending size resulting from a small bite
401
+ # @param starting_size [Integer] Starting size
402
+ # @param ending_size [Integer] Ending size
403
+ # @return [String, Boolean] String representation of an integer or false if input is invalid or division by zero occurs
404
+ # @example
405
+ # EtwMath.small_bite_delta_multi(9440, 10954) # 53
406
+ def self.small_bite_delta_multi(starting_size, ending_size)
407
+ return false if !input_valid?(starting_size, ending_size)
408
+ begin
409
+ format_number(((((-50 + Math.sqrt(2500 + 200 * ending_size)) / 100) - ((-50 + Math.sqrt(2500 + 200 * starting_size)) / 100)) / 0.02).round)
410
+ rescue # division by zero
411
+ return false
412
+ end
413
+ end
414
+
415
+ # Calculates multiplier using a starting size and an ending size resulting from a medium bite
416
+ # @param starting_size [Integer] Starting size
417
+ # @param ending_size [Integer] Ending size
418
+ # @return [String, Boolean] String representation of an integer or false if input is invalid or division by zero occurs
419
+ # @example
420
+ # EtwMath.medium_bite_delta_multi(9440, 10954) # 35
421
+ def self.medium_bite_delta_multi(starting_size, ending_size)
422
+ return false if !input_valid?(starting_size, ending_size)
423
+ begin
424
+ format_number(((((-50 + Math.sqrt(2500 + 200 * ending_size)) / 100) - ((-50 + Math.sqrt(2500 + 200 * starting_size)) / 100)) / 0.03).round)
425
+ rescue # division by zero
426
+ return false
427
+ end
428
+ end
429
+
430
+ # Calculates multiplier using a starting size and an ending size resulting from a big bite
431
+ # @param starting_size [Integer] Starting size
432
+ # @param ending_size [Integer] Ending size
433
+ # @return [String, Boolean] String representation of an integer or false if input is invalid or division by zero occurs
434
+ # @example
435
+ # EtwMath.big_bite_delta_multi(9440, 10954) # 27
436
+ def self.big_bite_delta_multi(starting_size, ending_size)
437
+ return false if !input_valid?(starting_size, ending_size)
438
+ begin
439
+ format_number(((((-50 + Math.sqrt(2500 + 200 * ending_size)) / 100) - ((-50 + Math.sqrt(2500 + 200 * starting_size)) / 100)) / 0.04).round)
440
+ rescue # division by zero
441
+ return false
442
+ end
443
+ end
444
+
445
+ # Calculates multiplier using the first small bite amount
446
+ # @param bite_amount [Integer] Bite amount
447
+ # @return [String, Boolean] String representation of an integer or false if input is invalid or division by zero occurs
448
+ # @example
449
+ # EtwMath.small_first_bite_multi(270) # 94
450
+ def self.small_first_bite_multi(bite_amount)
451
+ return false if !input_valid?(bite_amount)
452
+ begin
453
+ format_number((((-50 + Math.sqrt(2500 + 200 * bite_amount)) / 100) / 0.02).round)
454
+ rescue # division by zero
455
+ return false
456
+ end
457
+ end
458
+
459
+ # Calculates multiplier using the first medium bite amount
460
+ # @param bite_amount [Integer] Bite amount
461
+ # @return [String, Boolean] String representation of an integer or false if input is invalid or division by zero occurs
462
+ # @example
463
+ # EtwMath.medium_first_bite_multi(270) # 63
464
+ def self.medium_first_bite_multi(bite_amount)
465
+ return false if !input_valid?(bite_amount)
466
+ begin
467
+ format_number((((-50 + Math.sqrt(2500 + 200 * bite_amount)) / 100) / 0.03).round)
468
+ rescue # division by zero
469
+ return false
470
+ end
471
+ end
472
+
473
+ # Calculates multiplier using the first big bite amount
474
+ # @param bite_amount [Integer] Bite amount
475
+ # @return [String, Boolean] String representation of an integer or false if input is invalid or division by zero occurs
476
+ # @example
477
+ # EtwMath.big_first_bite_multi(270) # 47
478
+ def self.big_first_bite_multi(bite_amount)
479
+ return false if !input_valid?(bite_amount)
480
+ begin
481
+ format_number((((-50 + Math.sqrt(2500 + 200 * bite_amount)) / 100) / 0.04).round)
482
+ rescue # division by zero
483
+ return false
484
+ end
485
+ end
486
+
487
+ # Calculates time to reach maximum size in minutes for maximum size levels >141
488
+ # @param size_level [Integer] Maximum size level
489
+ # @param multi [Integer] Multiplier
490
+ # @return [String, Boolean] String representation of an integer or false if input is invalid or division by zero occurs
491
+ # @example
492
+ # EtwMath.time_to_max(565, 101) # 4.82 minutes
493
+ def self.time_to_max(size_level, multi)
494
+ return false if !input_valid?(size_level, multi)
495
+ begin
496
+ format_time((((size_level.to_f / (multi.to_f * 0.03 * 3) * (141.0 / size_level.to_f)) * 3.3 + (size_level.to_f / (multi.to_f * 0.03 * 3.0) * (1 - 141.0 / size_level.to_f)) * 5.1)).round(2))
497
+ rescue # division by zero
498
+ return false
499
+ end
500
+ end
501
+
502
+ # Calculates time to reach maximum size in minutes for maximum size levels <=141
503
+ # @param size_level [Integer] Maximum size level
504
+ # @param multi [Integer] Multiplier
505
+ # @return [String, Boolean] String representation of an integer or false if input is invalid or division by zero occurs
506
+ # @example
507
+ # EtwMath.time_to_max_small(140, 31) # 2.75 minutes
508
+ def self.time_to_max_small(size_level, multi)
509
+ return false if !input_valid?(size_level, multi)
510
+ begin
511
+ format_time(((size_level.to_f / multi.to_f / (0.03 * 3) * 3.3 * (0.5 + size_level.to_f / (141 * 2)))).round(2))
512
+ rescue # division by zero
513
+ return false
514
+ end
515
+ end
516
+ end
metadata ADDED
@@ -0,0 +1,44 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: etw_math
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Lazy Villain
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-10-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Calculate the cost of upgrades, another player's multiplier, and more.
14
+ email:
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - example.rb
20
+ - lib/etw_math.rb
21
+ homepage: https://github.com/LazyAntihero/etw_math
22
+ licenses:
23
+ - BSD-2-Clause
24
+ metadata: {}
25
+ post_install_message:
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ requirements: []
40
+ rubygems_version: 3.0.3.1
41
+ signing_key:
42
+ specification_version: 4
43
+ summary: Various mathematical formulas for Roblox - Eat the World (ETW)
44
+ test_files: []