nerd_dice 0.1.0 → 0.4.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
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/main.yml +67 -0
- data/.rubocop.yml +114 -0
- data/CHANGELOG.md +76 -2
- data/Gemfile +2 -2
- data/Gemfile.lock +54 -32
- data/README.md +372 -5
- data/bin/generate_checksums +13 -0
- data/bin/nerd_dice_benchmark +322 -0
- data/certs/msducheminjr.pem +26 -0
- data/checksum/nerd_dice-0.1.0.gem.sha256 +1 -0
- data/checksum/nerd_dice-0.1.0.gem.sha512 +1 -0
- data/checksum/nerd_dice-0.1.1.gem.sha256 +1 -0
- data/checksum/nerd_dice-0.1.1.gem.sha512 +1 -0
- data/checksum/nerd_dice-0.2.0.gem.sha256 +1 -0
- data/checksum/nerd_dice-0.2.0.gem.sha512 +1 -0
- data/checksum/nerd_dice-0.3.0.gem.sha256 +1 -0
- data/checksum/nerd_dice-0.3.0.gem.sha512 +1 -0
- data/lib/nerd_dice/class_methods/configure.rb +50 -0
- data/lib/nerd_dice/class_methods/execute_die_roll.rb +47 -0
- data/lib/nerd_dice/class_methods/harvest_totals.rb +40 -0
- data/lib/nerd_dice/class_methods/refresh_seed.rb +83 -0
- data/lib/nerd_dice/class_methods/roll_ability_scores.rb +73 -0
- data/lib/nerd_dice/class_methods/roll_dice.rb +45 -0
- data/lib/nerd_dice/class_methods/total_ability_scores.rb +52 -0
- data/lib/nerd_dice/class_methods/total_dice.rb +44 -0
- data/lib/nerd_dice/class_methods.rb +30 -0
- data/lib/nerd_dice/configuration.rb +91 -0
- data/lib/nerd_dice/convenience_methods.rb +279 -0
- data/lib/nerd_dice/dice_set.rb +166 -0
- data/lib/nerd_dice/die.rb +51 -0
- data/lib/nerd_dice/sets_randomization_technique.rb +19 -0
- data/lib/nerd_dice/version.rb +1 -1
- data/lib/nerd_dice.rb +15 -33
- data/nerd_dice.gemspec +12 -7
- data.tar.gz.sig +0 -0
- metadata +97 -21
- metadata.gz.sig +0 -0
- data/.travis.yml +0 -6
@@ -0,0 +1,322 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "benchmark"
|
6
|
+
require "nerd_dice"
|
7
|
+
|
8
|
+
n = 50_000
|
9
|
+
|
10
|
+
RATIOS = {
|
11
|
+
total_dice_securerandom: 2.1,
|
12
|
+
total_dice_random_rand: 11.1,
|
13
|
+
total_dice_random_object: 13.0,
|
14
|
+
total_dice_randomized: 5.5,
|
15
|
+
total_dice_securerandom_3d6: 5.5,
|
16
|
+
total_dice_random_rand_3d6: 30.0,
|
17
|
+
total_dice_random_object_3d6: 25.5,
|
18
|
+
total_dice_randomized_3d6: 15.5,
|
19
|
+
total_magic_securerandom: 6.04,
|
20
|
+
total_magic_random_rand: 85.9,
|
21
|
+
total_magic_random_object: 89.42,
|
22
|
+
total_magic_randomized: 20.27,
|
23
|
+
roll_dice_securerandom: 4.0,
|
24
|
+
roll_dice_random_rand: 42.0,
|
25
|
+
roll_dice_random_object: 44.0,
|
26
|
+
roll_dice_randomized: 14.5,
|
27
|
+
roll_magic_securerandom: 6.04,
|
28
|
+
roll_magic_random_rand: 85.9,
|
29
|
+
roll_magic_random_object: 89.42,
|
30
|
+
roll_magic_randomized: 20.27,
|
31
|
+
roll_dice_securerandom_3d6: 13.0,
|
32
|
+
roll_dice_random_rand_3d6: 79.0,
|
33
|
+
roll_dice_random_object_3d6: 86.0,
|
34
|
+
roll_dice_randomized_3d6: 26.5,
|
35
|
+
roll_magic_securerandom_3d6: 18.38,
|
36
|
+
roll_magic_random_rand_3d6: 108.54,
|
37
|
+
roll_magic_random_object_3d6: 118.36,
|
38
|
+
roll_magic_randomized_3d6: 44.39,
|
39
|
+
roll_ability_scores_randomized: 30.5,
|
40
|
+
total_ability_scores_randomized: 30.5
|
41
|
+
}.freeze
|
42
|
+
|
43
|
+
def check_against_baseline!(baseline_value, test_value)
|
44
|
+
ratio = RATIOS[test_value.label.to_sym]
|
45
|
+
error_message = "Failed benchmark for #{test_value.label}. "
|
46
|
+
error_message += "Allowed ratio was #{ratio} actual ratio was #{test_value.real / baseline_value}"
|
47
|
+
raise NerdDice::Error, error_message if test_value.real > baseline_value * ratio
|
48
|
+
end
|
49
|
+
|
50
|
+
puts "Set baseline"
|
51
|
+
baselines = Benchmark.bm do |x|
|
52
|
+
# Random.rand()
|
53
|
+
x.report("Random.rand") do # standard rand()
|
54
|
+
n.times { Random.rand(1000) }
|
55
|
+
end
|
56
|
+
|
57
|
+
# SecureRandom.rand()
|
58
|
+
x.report("Sec.rand") do
|
59
|
+
n.times { SecureRandom.rand(1000) }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
random_rand_baseline = baselines[0].real
|
64
|
+
securerandom_baseline = baselines[1].real
|
65
|
+
|
66
|
+
puts "Roll d1000s"
|
67
|
+
|
68
|
+
puts "total_dice"
|
69
|
+
total_dice_d1000_results = Benchmark.bm do |x|
|
70
|
+
# NerdDice.total_dice securerandom
|
71
|
+
x.report("total_dice_securerandom") do
|
72
|
+
NerdDice.configuration.randomization_technique = :securerandom
|
73
|
+
n.times { NerdDice.total_dice(1000) }
|
74
|
+
end
|
75
|
+
|
76
|
+
x.report("total_dice_random_rand") do
|
77
|
+
NerdDice.configuration.randomization_technique = :random_rand
|
78
|
+
n.times { NerdDice.total_dice(1000) }
|
79
|
+
end
|
80
|
+
|
81
|
+
x.report("total_dice_random_object") do
|
82
|
+
NerdDice.configuration.randomization_technique = :random_object
|
83
|
+
n.times { NerdDice.total_dice(1000) }
|
84
|
+
end
|
85
|
+
|
86
|
+
x.report("total_dice_randomized") do
|
87
|
+
NerdDice.configuration.randomization_technique = :randomized
|
88
|
+
n.times { NerdDice.total_dice(1000) }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
total_dice_securerandom = total_dice_d1000_results[0]
|
93
|
+
check_against_baseline! securerandom_baseline, total_dice_securerandom
|
94
|
+
total_dice_random_rand = total_dice_d1000_results[1]
|
95
|
+
check_against_baseline! random_rand_baseline, total_dice_random_rand
|
96
|
+
total_dice_random_object = total_dice_d1000_results[2]
|
97
|
+
check_against_baseline! random_rand_baseline, total_dice_random_object
|
98
|
+
total_dice_randomized = total_dice_d1000_results[3]
|
99
|
+
check_against_baseline! ((random_rand_baseline * 0.75) + (securerandom_baseline * 0.25)), total_dice_randomized
|
100
|
+
|
101
|
+
puts "total_ d1000s ConvenienceMethods"
|
102
|
+
|
103
|
+
# NOTE: Due to method_missing overhead, using roll_ ratios for ConvenienceMethods total_dice
|
104
|
+
total_d1000_results = Benchmark.bm do |x|
|
105
|
+
# NerdDice.total_dice securerandom
|
106
|
+
x.report("total_magic_securerandom") do
|
107
|
+
NerdDice.configuration.randomization_technique = :securerandom
|
108
|
+
n.times { NerdDice.total_d1000 }
|
109
|
+
end
|
110
|
+
|
111
|
+
x.report("total_magic_random_rand") do
|
112
|
+
NerdDice.configuration.randomization_technique = :random_rand
|
113
|
+
n.times { NerdDice.total_d1000 }
|
114
|
+
end
|
115
|
+
|
116
|
+
x.report("total_magic_random_object") do
|
117
|
+
NerdDice.configuration.randomization_technique = :random_object
|
118
|
+
n.times { NerdDice.total_d1000 }
|
119
|
+
end
|
120
|
+
|
121
|
+
x.report("total_magic_randomized") do
|
122
|
+
NerdDice.configuration.randomization_technique = :randomized
|
123
|
+
n.times { NerdDice.total_d1000 }
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
total_magic_securerandom = total_d1000_results[0]
|
128
|
+
check_against_baseline! securerandom_baseline, total_magic_securerandom
|
129
|
+
total_magic_random_rand = total_d1000_results[1]
|
130
|
+
check_against_baseline! random_rand_baseline, total_magic_random_rand
|
131
|
+
total_magic_random_object = total_d1000_results[2]
|
132
|
+
check_against_baseline! random_rand_baseline, total_magic_random_object
|
133
|
+
total_magic_randomized = total_d1000_results[3]
|
134
|
+
check_against_baseline! ((random_rand_baseline * 0.75) + (securerandom_baseline * 0.25)), total_magic_randomized
|
135
|
+
|
136
|
+
puts "roll_dice"
|
137
|
+
roll_dice_d1000_results = Benchmark.bm do |x|
|
138
|
+
# NerdDice.roll_dice securerandom
|
139
|
+
x.report("roll_dice_securerandom") do
|
140
|
+
NerdDice.configuration.randomization_technique = :securerandom
|
141
|
+
n.times { NerdDice.roll_dice(1000) }
|
142
|
+
end
|
143
|
+
|
144
|
+
x.report("roll_dice_random_rand") do
|
145
|
+
NerdDice.configuration.randomization_technique = :random_rand
|
146
|
+
n.times { NerdDice.roll_dice(1000) }
|
147
|
+
end
|
148
|
+
|
149
|
+
x.report("roll_dice_random_object") do
|
150
|
+
NerdDice.configuration.randomization_technique = :random_object
|
151
|
+
n.times { NerdDice.roll_dice(1000) }
|
152
|
+
end
|
153
|
+
|
154
|
+
x.report("roll_dice_randomized") do
|
155
|
+
NerdDice.configuration.randomization_technique = :randomized
|
156
|
+
n.times { NerdDice.roll_dice(1000) }
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
roll_dice_securerandom = roll_dice_d1000_results[0]
|
161
|
+
check_against_baseline! securerandom_baseline, roll_dice_securerandom
|
162
|
+
roll_dice_random_rand = roll_dice_d1000_results[1]
|
163
|
+
check_against_baseline! random_rand_baseline, roll_dice_random_rand
|
164
|
+
roll_dice_random_object = roll_dice_d1000_results[2]
|
165
|
+
check_against_baseline! random_rand_baseline, roll_dice_random_object
|
166
|
+
roll_dice_randomized = roll_dice_d1000_results[3]
|
167
|
+
check_against_baseline! ((random_rand_baseline * 0.75) + (securerandom_baseline * 0.25)), roll_dice_randomized
|
168
|
+
|
169
|
+
puts "roll_ d1000s ConvenienceMethods"
|
170
|
+
roll_d1000_results = Benchmark.bm do |x|
|
171
|
+
# NerdDice.roll_dice securerandom
|
172
|
+
x.report("roll_magic_securerandom") do
|
173
|
+
NerdDice.configuration.randomization_technique = :securerandom
|
174
|
+
n.times { NerdDice.roll_d1000 }
|
175
|
+
end
|
176
|
+
|
177
|
+
x.report("roll_magic_random_rand") do
|
178
|
+
NerdDice.configuration.randomization_technique = :random_rand
|
179
|
+
n.times { NerdDice.roll_d1000 }
|
180
|
+
end
|
181
|
+
|
182
|
+
x.report("roll_magic_random_object") do
|
183
|
+
NerdDice.configuration.randomization_technique = :random_object
|
184
|
+
n.times { NerdDice.roll_d1000 }
|
185
|
+
end
|
186
|
+
|
187
|
+
x.report("roll_magic_randomized") do
|
188
|
+
NerdDice.configuration.randomization_technique = :randomized
|
189
|
+
n.times { NerdDice.roll_d1000 }
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
roll_magic_securerandom = roll_d1000_results[0]
|
194
|
+
check_against_baseline! securerandom_baseline, roll_magic_securerandom
|
195
|
+
roll_magic_random_rand = roll_d1000_results[1]
|
196
|
+
check_against_baseline! random_rand_baseline, roll_magic_random_rand
|
197
|
+
roll_magic_random_object = roll_d1000_results[2]
|
198
|
+
check_against_baseline! random_rand_baseline, roll_magic_random_object
|
199
|
+
roll_magic_randomized = roll_d1000_results[3]
|
200
|
+
check_against_baseline! ((random_rand_baseline * 0.75) + (securerandom_baseline * 0.25)), roll_magic_randomized
|
201
|
+
|
202
|
+
puts "Roll 3d6"
|
203
|
+
puts "total_dice 3d6"
|
204
|
+
total_dice_3d6_results = Benchmark.bm do |x|
|
205
|
+
# NerdDice.total_dice securerandom
|
206
|
+
x.report("total_dice_securerandom_3d6") do
|
207
|
+
NerdDice.configuration.randomization_technique = :securerandom
|
208
|
+
n.times { NerdDice.total_dice(6, 3) }
|
209
|
+
end
|
210
|
+
|
211
|
+
x.report("total_dice_random_rand_3d6") do
|
212
|
+
NerdDice.configuration.randomization_technique = :random_rand
|
213
|
+
n.times { NerdDice.total_dice(6, 3) }
|
214
|
+
end
|
215
|
+
|
216
|
+
x.report("total_dice_random_object_3d6") do
|
217
|
+
NerdDice.configuration.randomization_technique = :random_object
|
218
|
+
n.times { NerdDice.total_dice(6, 3) }
|
219
|
+
end
|
220
|
+
|
221
|
+
x.report("total_dice_randomized_3d6") do
|
222
|
+
NerdDice.configuration.randomization_technique = :randomized
|
223
|
+
n.times { NerdDice.total_dice(6, 3) }
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
total_dice_3d6_securerandom = total_dice_3d6_results[0]
|
228
|
+
check_against_baseline! securerandom_baseline, total_dice_3d6_securerandom
|
229
|
+
total_dice_3d6_random_rand = total_dice_3d6_results[1]
|
230
|
+
check_against_baseline! random_rand_baseline, total_dice_3d6_random_rand
|
231
|
+
total_dice_3d6_random_object = total_dice_3d6_results[2]
|
232
|
+
check_against_baseline! random_rand_baseline, total_dice_3d6_random_object
|
233
|
+
total_dice_3d6_randomized = total_dice_3d6_results[3]
|
234
|
+
check_against_baseline! ((random_rand_baseline * 0.75) + (securerandom_baseline * 0.25)), total_dice_3d6_randomized
|
235
|
+
|
236
|
+
puts "roll_dice 3d6"
|
237
|
+
roll_dice_3d6_results = Benchmark.bm do |x|
|
238
|
+
# NerdDice.roll_dice securerandom
|
239
|
+
x.report("roll_dice_securerandom_3d6") do
|
240
|
+
NerdDice.configuration.randomization_technique = :securerandom
|
241
|
+
n.times { NerdDice.roll_dice(6, 3) }
|
242
|
+
end
|
243
|
+
|
244
|
+
x.report("roll_dice_random_rand_3d6") do
|
245
|
+
NerdDice.configuration.randomization_technique = :random_rand
|
246
|
+
n.times { NerdDice.roll_dice(6, 3) }
|
247
|
+
end
|
248
|
+
|
249
|
+
x.report("roll_dice_random_object_3d6") do
|
250
|
+
NerdDice.configuration.randomization_technique = :random_object
|
251
|
+
n.times { NerdDice.roll_dice(6, 3) }
|
252
|
+
end
|
253
|
+
|
254
|
+
x.report("roll_dice_randomized_3d6") do
|
255
|
+
NerdDice.configuration.randomization_technique = :randomized
|
256
|
+
n.times { NerdDice.roll_dice(6, 3) }
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
roll_dice_3d6_securerandom = roll_dice_3d6_results[0]
|
261
|
+
check_against_baseline! securerandom_baseline, roll_dice_3d6_securerandom
|
262
|
+
roll_dice_3d6_random_rand = roll_dice_3d6_results[1]
|
263
|
+
check_against_baseline! random_rand_baseline, roll_dice_3d6_random_rand
|
264
|
+
roll_dice_3d6_random_object = roll_dice_3d6_results[2]
|
265
|
+
check_against_baseline! random_rand_baseline, roll_dice_3d6_random_object
|
266
|
+
roll_dice_3d6_randomized = roll_dice_3d6_results[3]
|
267
|
+
check_against_baseline! ((random_rand_baseline * 0.75) + (securerandom_baseline * 0.25)), roll_dice_3d6_randomized
|
268
|
+
|
269
|
+
puts "roll_3d6 ConvenienceMethods"
|
270
|
+
roll_magic_3d6_results = Benchmark.bm do |x|
|
271
|
+
# NerdDice.roll_magic securerandom
|
272
|
+
x.report("roll_magic_securerandom_3d6") do
|
273
|
+
NerdDice.configuration.randomization_technique = :securerandom
|
274
|
+
n.times { NerdDice.roll_3d6 }
|
275
|
+
end
|
276
|
+
|
277
|
+
x.report("roll_magic_random_rand_3d6") do
|
278
|
+
NerdDice.configuration.randomization_technique = :random_rand
|
279
|
+
n.times { NerdDice.roll_3d6 }
|
280
|
+
end
|
281
|
+
|
282
|
+
x.report("roll_magic_random_object_3d6") do
|
283
|
+
NerdDice.configuration.randomization_technique = :random_object
|
284
|
+
n.times { NerdDice.roll_3d6 }
|
285
|
+
end
|
286
|
+
|
287
|
+
x.report("roll_magic_randomized_3d6") do
|
288
|
+
NerdDice.configuration.randomization_technique = :randomized
|
289
|
+
n.times { NerdDice.roll_3d6 }
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
roll_magic_3d6_securerandom = roll_magic_3d6_results[0]
|
294
|
+
check_against_baseline! securerandom_baseline, roll_magic_3d6_securerandom
|
295
|
+
roll_magic_3d6_random_rand = roll_magic_3d6_results[1]
|
296
|
+
check_against_baseline! random_rand_baseline, roll_magic_3d6_random_rand
|
297
|
+
roll_magic_3d6_random_object = roll_magic_3d6_results[2]
|
298
|
+
check_against_baseline! random_rand_baseline, roll_magic_3d6_random_object
|
299
|
+
roll_magic_3d6_randomized = roll_magic_3d6_results[3]
|
300
|
+
check_against_baseline! ((random_rand_baseline * 0.75) + (securerandom_baseline * 0.25)), roll_magic_3d6_randomized
|
301
|
+
|
302
|
+
puts "Setting n down to 5,000 due to more intensive methods"
|
303
|
+
n = 5_000
|
304
|
+
|
305
|
+
puts "Roll and total ability scores"
|
306
|
+
roll_ability_scores_results = Benchmark.bm do |x|
|
307
|
+
x.report("roll_ability_scores_randomized") do
|
308
|
+
NerdDice.configuration.randomization_technique = :randomized
|
309
|
+
n.times { NerdDice.roll_ability_scores }
|
310
|
+
end
|
311
|
+
|
312
|
+
x.report("total_ability_scores_randomized") do
|
313
|
+
NerdDice.configuration.randomization_technique = :randomized
|
314
|
+
n.times { NerdDice.total_ability_scores }
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
roll_ability_scores_randomized = roll_ability_scores_results[0]
|
319
|
+
check_against_baseline! ((random_rand_baseline * 0.75) + (securerandom_baseline * 0.25)), roll_ability_scores_randomized
|
320
|
+
total_ability_scores_randomized = roll_ability_scores_results[1]
|
321
|
+
check_against_baseline! ((random_rand_baseline * 0.75) + (securerandom_baseline * 0.25)),
|
322
|
+
total_ability_scores_randomized
|
@@ -0,0 +1,26 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIETTCCArWgAwIBAgIBATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDDB1zdGF0
|
3
|
+
ZWxlc3Njb2RlL0RDPWdtYWlsL0RDPWNvbTAeFw0yMDEyMDYyMzQ1NTZaFw0yMTEy
|
4
|
+
MDYyMzQ1NTZaMCgxJjAkBgNVBAMMHXN0YXRlbGVzc2NvZGUvREM9Z21haWwvREM9
|
5
|
+
Y29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAyHIMJi0o3bwBZsx5
|
6
|
+
TQ35XByFsdDRsro3T+0NY7EAILtOiU04o9C2NPOp/RQE7BXQgMjGebwp6bT6QvzN
|
7
|
+
6noV4jPL7Fi5pWw08QygG7f+73YUBb+8d8o+3xGrC+UO5h1PZEtVcZwUWUG18QBE
|
8
|
+
fbDinQT6P4IDQoZwhfrPCB+aBfUyQp4Ok7oD7MEWqsq9SjrSxqxfk4+oZdXUySe7
|
9
|
+
Vi5vnzVQ5uFf56NHwWnNKCzJzmH84mBO5MzHaQpHNzKGJPoUmzLU5RBlCH6YXqBG
|
10
|
+
KhXTMUDBWKJmJ3RDry/FpGgJLKu4wzFRYjXla6IjeKozWGuPNNJ+2mesXKhsX7bo
|
11
|
+
vVCzRxPEupbEg/0FkJiWpiGlSPOdd6oJiwX8E6rlEeV605xrbOQewkbovHkYTMtG
|
12
|
+
+NH+u08x0z4Oj71kmDLwuj812uS0mtrCg2VhiYO0ZCQ4XrwBsBfK+/MtMlR+o6sG
|
13
|
+
/zvz/vHVJKaLTQxRp5oGo4QH6HfbOnwzTkXdZnt5AlN31ErJAgMBAAGjgYEwfzAJ
|
14
|
+
BgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUC7seYydsGO6O1qT4nVVD
|
15
|
+
G/LkiHYwIgYDVR0RBBswGYEXc3RhdGVsZXNzY29kZUBnbWFpbC5jb20wIgYDVR0S
|
16
|
+
BBswGYEXc3RhdGVsZXNzY29kZUBnbWFpbC5jb20wDQYJKoZIhvcNAQELBQADggGB
|
17
|
+
ADPRFRB1cjqdcE2O0jtqiDRmrR62uEYBiUbkRPVhyoEp/cK0TVhAs9mGWAyCWu0M
|
18
|
+
LewUeqNTUvQ9MgvagcKcnxa2RTjdrP3nGnwpStMr9bm3ArNJEzvWEs0Eusk9y73x
|
19
|
+
fjy0qH2pw5WPfWcKYlDehMXqOP+a4udYsz0YSNiI8qEfkDCSqTJN11d5kSjVjwGB
|
20
|
+
xkauxDT68j1JZRjPmQl3dl+DCgxkoziWX2mFTPLfGg5vZ0t6gmhdUtLvJtNIo0IX
|
21
|
+
477E5UjmE1+rULQp/fsH6n5+H+t2eCED41ST+gkKbaQBUfIuUaCmdHz9sJaIIBw2
|
22
|
+
6ordFa1nrLV4w5Uf6qYFnWVhIWX4GToyZSPO2s0DPYp3PWFJ4VtzKa2vp1TR5ZEA
|
23
|
+
dkij2eQ9M8bzWWmW+A7RNaI0CzLl967bKGBSaMVCsZGBarggWD8UwJnBhTuOPZGR
|
24
|
+
WQ4faXJSevxT+x9TgyUNJINPkz/KqreClzdL83cwxPzFFQto7zF6zMCsj0slqJjW
|
25
|
+
EQ==
|
26
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1 @@
|
|
1
|
+
39c9724b0b40e17b309b71343c5b6838f401fa9660ac53c4be8d4b0050904da3
|
@@ -0,0 +1 @@
|
|
1
|
+
58f15bb3c270b530f3620afd53d17981c48871aba61b205c8cb012ae8f396bbac905d46d32f657399f787b4c8aaf3572aab030a4bfa81c1b7d9ff1b060aa5b82
|
@@ -0,0 +1 @@
|
|
1
|
+
3b8e94b12954afbeb9c08746c57a19e06dc2405cb0e74f500d0111ef99e97f72
|
@@ -0,0 +1 @@
|
|
1
|
+
469f2104263dbf07ab0e83e04a3b08087b3f64a7702143ed2387a04601c7db2c0e43404dd325de1d2fbe394858973e6d9bb214d9b0f602cead65b7dc4fbcb46b
|
@@ -0,0 +1 @@
|
|
1
|
+
0a2d4765e24c21fecf99229b0cc4fad806ca256d2187c45c442b25771af1b9cc
|
@@ -0,0 +1 @@
|
|
1
|
+
e345190f870eabd2a4fd6993f1a1d70d008ef8e6464767ba5697a46f7c4d6912c78a18039cec06c18dd6f0ee9f425453c078f780d36ccf65043ec3f7fba790a2
|
@@ -0,0 +1 @@
|
|
1
|
+
30f9d3809362099e81e414bf987b711c8dad59703c68579809bb36ce9b199d58
|
@@ -0,0 +1 @@
|
|
1
|
+
1a8913b8f2878c1471f32dadaddf9965fd61c7ef2e9a255961babdb9586f2c18b7eca1cd0f1021061fb69c96a330151a97df9a102b2871e1e1c5e5675f34a511
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#############################
|
4
|
+
# Configuration class methods
|
5
|
+
#############################
|
6
|
+
# Usage:
|
7
|
+
# NerdDice.configure takes a block and yields the NerdDice::Configuration
|
8
|
+
# properties:
|
9
|
+
# If you wanted to configure several properties in a block:
|
10
|
+
# <tt>
|
11
|
+
# NerdDice.configure do |config|
|
12
|
+
# config.randomization_technique = :randomized
|
13
|
+
# config.die_background_color = "#FF0000"
|
14
|
+
# end
|
15
|
+
# </tt>
|
16
|
+
#
|
17
|
+
# NerdDice.configuration returns the NerdDice::Configuration object and lets you
|
18
|
+
# set properties on the NerdDice::Configuration object without using a block:
|
19
|
+
# <tt>
|
20
|
+
# config = NerdDice.configuration
|
21
|
+
# config.randomization_technique = :randomized
|
22
|
+
# config.die_background_color = "#FF0000"
|
23
|
+
# </tt>
|
24
|
+
module NerdDice
|
25
|
+
class << self
|
26
|
+
############################
|
27
|
+
# configure class method
|
28
|
+
############################
|
29
|
+
# Arguments: None
|
30
|
+
# Expects and yields to a block where configuration is specified.
|
31
|
+
# See README and NerdDice::Configuration class for config options
|
32
|
+
# Return (NerdDice::Configuration) the Configuration object tied to the
|
33
|
+
# @configuration class instance variable
|
34
|
+
def configure
|
35
|
+
yield configuration
|
36
|
+
configuration
|
37
|
+
end
|
38
|
+
|
39
|
+
############################
|
40
|
+
# configuration class method
|
41
|
+
############################
|
42
|
+
# Arguments: None
|
43
|
+
# Provides the lazy-loaded class instance variable @configuration
|
44
|
+
# Return (NerdDice::Configuration) the Configuration object tied to the
|
45
|
+
# @configuration class instance variable
|
46
|
+
def configuration
|
47
|
+
@configuration ||= Configuration.new
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
###############################
|
4
|
+
# execute_die_roll class method
|
5
|
+
###############################
|
6
|
+
# Usage:
|
7
|
+
# If you wanted to execute a single d4 die roll without a Die object, you would execute:
|
8
|
+
# <tt>NerdDice.execute_die_roll(4)</tt>
|
9
|
+
#
|
10
|
+
# If you wanted to execute a die roll with a different randomization technique
|
11
|
+
# than the one in NerdDice.configuration, you can supply an optional second argument
|
12
|
+
# <tt>NerdDice.execute_die_roll(4, :randomized)</tt>
|
13
|
+
module NerdDice
|
14
|
+
class << self
|
15
|
+
# Arguments:
|
16
|
+
# number_of_sides (Integer) => the number of sides of the die to roll
|
17
|
+
# using_generator (Symbol) => must be one of the symbols in
|
18
|
+
# RANDOMIZATION_TECHNIQUES or nil
|
19
|
+
#
|
20
|
+
# Return (Integer) => Value of the single die rolled
|
21
|
+
def execute_die_roll(number_of_sides, using_generator = nil)
|
22
|
+
@count_since_last_refresh ||= 0
|
23
|
+
gen = get_number_generator(using_generator)
|
24
|
+
result = gen.rand(number_of_sides) + 1
|
25
|
+
increment_and_evalutate_refresh_seed
|
26
|
+
result
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def get_number_generator(using_generator = nil)
|
32
|
+
using_generator ||= configuration.randomization_technique
|
33
|
+
case using_generator
|
34
|
+
when :securerandom then SecureRandom
|
35
|
+
when :random_rand then Random
|
36
|
+
when :random_object then @random_object ||= Random.new
|
37
|
+
when :randomized then random_generator
|
38
|
+
else raise ArgumentError, "Unrecognized generator. Must be one of #{RANDOMIZATION_TECHNIQUES.join(', ')}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def random_generator
|
43
|
+
gen = RANDOMIZATION_TECHNIQUES.reject { |el| el == :randomized }.sample
|
44
|
+
get_number_generator(gen)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
############################
|
4
|
+
# harvest_totals method
|
5
|
+
############################
|
6
|
+
# Usage:
|
7
|
+
# This method will take any collection of objects where each element responds to
|
8
|
+
# :total and return an array of the results of the total method.
|
9
|
+
#
|
10
|
+
# Example
|
11
|
+
# <tt>
|
12
|
+
# ability_score_array = NerdDice.roll_ability_scores
|
13
|
+
# => Array of 6 DiceSet objects
|
14
|
+
# totals_array = NerdDice.harvest_totals(totals_array)
|
15
|
+
# => [15, 14, 13, 12, 10, 8]
|
16
|
+
# # yes, it just happened to be the standard array by amazing coincidence
|
17
|
+
# </tt>
|
18
|
+
module NerdDice
|
19
|
+
class << self
|
20
|
+
# Arguments:
|
21
|
+
# collection (Enumerable) a collection where each element responds to total
|
22
|
+
#
|
23
|
+
# Return (Array) => Data type of each element will be whatever is returned by total method
|
24
|
+
def harvest_totals(collection)
|
25
|
+
collection.map(&:total)
|
26
|
+
rescue NoMethodError => e
|
27
|
+
specific_message = get_harvest_totals_error_message(e)
|
28
|
+
specific_message ? raise(ArgumentError, "You must provide a valid collection. #{specific_message}") : raise
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def get_harvest_totals_error_message(rescued_error)
|
34
|
+
case rescued_error.message
|
35
|
+
when /`total'/ then "Each element must respond to :total."
|
36
|
+
when /`map'/ then "Argument must respond to :map."
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
############################
|
4
|
+
# refresh_seed! class method
|
5
|
+
############################
|
6
|
+
# Usage:
|
7
|
+
# NerdDice.refresh_seed! by default will refresh the seed for the generator
|
8
|
+
# configured in NerdDice.configuration. It can also be used with arguments
|
9
|
+
# to set a particular seed for use with deterministic testing. It sets
|
10
|
+
# the count_since_last_refresh to 0 whenever called.
|
11
|
+
#
|
12
|
+
# It cannot refresh or manipulate the seed for SecureRandom
|
13
|
+
#
|
14
|
+
# <tt>NerdDice.refresh_seed!</tt>
|
15
|
+
#
|
16
|
+
# With options
|
17
|
+
# <tt>
|
18
|
+
# previous_seed_data = NerdDice.refresh_seed!(
|
19
|
+
# randomization_technique: :randomized,
|
20
|
+
# random_rand_seed: 1337,
|
21
|
+
# random_object_seed: 24601
|
22
|
+
# )
|
23
|
+
# </tt>
|
24
|
+
module NerdDice
|
25
|
+
class << self
|
26
|
+
# Options: (none required)
|
27
|
+
# randomization_technique (Symbol) => must be one of the symbols in
|
28
|
+
# RANDOMIZATION_TECHNIQUES if specified
|
29
|
+
# random_rand_seed (Integer) => Seed to set for Random
|
30
|
+
# random_object_seed (Integer) => Seed to set for new Random object
|
31
|
+
# Return (Hash or nil) => Previous values of generator seeds that were refreshed
|
32
|
+
def refresh_seed!(**opts)
|
33
|
+
technique, random_rand_new_seed, random_object_new_seed = parse_refresh_options(opts)
|
34
|
+
@count_since_last_refresh = 0
|
35
|
+
return nil if technique == :securerandom
|
36
|
+
|
37
|
+
reset_appropriate_seeds!(technique, random_rand_new_seed, random_object_new_seed)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def parse_refresh_options(opts)
|
43
|
+
[
|
44
|
+
opts[:randomization_technique] || configuration.randomization_technique,
|
45
|
+
opts[:random_rand_seed],
|
46
|
+
opts[:random_object_seed]
|
47
|
+
]
|
48
|
+
end
|
49
|
+
|
50
|
+
# rubocop:disable Metrics/MethodLength
|
51
|
+
def reset_appropriate_seeds!(technique, random_rand_new_seed, random_object_new_seed)
|
52
|
+
return_hash = {}
|
53
|
+
case technique
|
54
|
+
when :random_rand
|
55
|
+
return_hash[:random_rand_prior_seed] = refresh_random_rand_seed!(random_rand_new_seed)
|
56
|
+
when :random_object
|
57
|
+
return_hash[:random_object_prior_seed] = refresh_random_object_seed!(random_object_new_seed)
|
58
|
+
when :randomized
|
59
|
+
return_hash[:random_rand_prior_seed] = refresh_random_rand_seed!(random_rand_new_seed)
|
60
|
+
return_hash[:random_object_prior_seed] = refresh_random_object_seed!(random_object_new_seed)
|
61
|
+
end
|
62
|
+
return_hash
|
63
|
+
end
|
64
|
+
# rubocop:enable Metrics/MethodLength
|
65
|
+
|
66
|
+
def refresh_random_rand_seed!(new_seed)
|
67
|
+
new_seed ? Random.srand(new_seed) : Random.srand
|
68
|
+
end
|
69
|
+
|
70
|
+
def refresh_random_object_seed!(new_seed)
|
71
|
+
old_seed = @random_object&.seed
|
72
|
+
@random_object = new_seed ? Random.new(new_seed) : Random.new
|
73
|
+
old_seed
|
74
|
+
end
|
75
|
+
|
76
|
+
def increment_and_evalutate_refresh_seed
|
77
|
+
@count_since_last_refresh += 1
|
78
|
+
return unless configuration.refresh_seed_interval
|
79
|
+
|
80
|
+
refresh_seed! if @count_since_last_refresh >= configuration.refresh_seed_interval
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
############################
|
4
|
+
# roll_ability_scores method
|
5
|
+
############################
|
6
|
+
# Usage:
|
7
|
+
# If you wanted to get an array of DiceSet objects with your ability scores and
|
8
|
+
# default configuration you would execute:
|
9
|
+
# <tt>ability_score_array = NerdDice.roll_ability_scores</tt>
|
10
|
+
#
|
11
|
+
# If you wanted to specify configuration for the current operation without
|
12
|
+
# modifying the NerdDice.configuration, you can supply options for both the
|
13
|
+
# ability_score configuration and the properties of the DiceSet objects returned.
|
14
|
+
# Properties are specified in the method comment
|
15
|
+
# <tt>
|
16
|
+
# ability_score_array = NerdDice.roll_ability_scores(
|
17
|
+
# ability_score_array_size: 7,
|
18
|
+
# ability_score_number_of_sides: 8,
|
19
|
+
# ability_score_dice_rolled: 5,
|
20
|
+
# ability_score_dice_kept: 4,
|
21
|
+
# randomization_technique: :randomized,
|
22
|
+
# foreground_color: "#FF0000",
|
23
|
+
# background_color: "#FFFFFF"
|
24
|
+
# )
|
25
|
+
# </tt>
|
26
|
+
module NerdDice
|
27
|
+
class << self
|
28
|
+
# Arguments:
|
29
|
+
# opts (options Hash, DEFAULT: {}) any options you wish to include
|
30
|
+
# ABILITY SCORE OPTIONS
|
31
|
+
# :ability_score_array_size DEFAULT NerdDice.configuration.ability_score_array_size
|
32
|
+
# :ability_score_number_of_sides DEFAULT NerdDice.configuration.ability_score_number_of_sides
|
33
|
+
# :ability_score_dice_rolled DEFAULT NerdDice.configuration.ability_score_dice_rolled
|
34
|
+
# :ability_score_dice_kept DEFAULT NerdDice.configuration.ability_score_dice_kept
|
35
|
+
#
|
36
|
+
# DICE SET OPTIONS
|
37
|
+
# :randomization_technique (Symbol) => must be one of the symbols in
|
38
|
+
# RANDOMIZATION_TECHNIQUES or nil
|
39
|
+
# :foreground_color (String) => should resolve to a valid CSS color (format flexible)
|
40
|
+
# :background_color (String) => should resolve to a valid CSS color (format flexible)
|
41
|
+
#
|
42
|
+
# Return (Array of NerdDice::DiceSet) => One NerdDice::DiceSet element for each ability score
|
43
|
+
# rubocop:disable Metrics/MethodLength
|
44
|
+
def roll_ability_scores(**opts)
|
45
|
+
dice_opts = opts.reject { |key, _value| key.to_s.match?(/\Aability_score_[a-z_]+\z/) }
|
46
|
+
ability_score_options = interpret_ability_score_options(opts)
|
47
|
+
ability_score_array = []
|
48
|
+
ability_score_options[:ability_score_array_size].times do
|
49
|
+
ability_score_array << roll_dice(
|
50
|
+
ability_score_options[:ability_score_number_of_sides],
|
51
|
+
ability_score_options[:ability_score_dice_rolled],
|
52
|
+
**dice_opts
|
53
|
+
).highest(
|
54
|
+
ability_score_options[:ability_score_dice_kept]
|
55
|
+
)
|
56
|
+
end
|
57
|
+
ability_score_array
|
58
|
+
end
|
59
|
+
# rubocop:enable Metrics/MethodLength
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def interpret_ability_score_options(opts)
|
64
|
+
return_hash = {}
|
65
|
+
ABILITY_SCORE_KEYS.each { |key| return_hash[key] = parse_ability_score_option(opts, key) }
|
66
|
+
return_hash
|
67
|
+
end
|
68
|
+
|
69
|
+
def parse_ability_score_option(option_hash, option_key)
|
70
|
+
option_hash[option_key] || configuration.send(option_key.to_s)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|