hazard 1.0.4 → 1.1.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
- data/README.md +67 -9
- data/lib/hazard/version.rb +1 -1
- data/lib/hazard.rb +1 -0
- data/lib/weighted_table.rb +88 -0
- data/test/test_helper.rb +1 -0
- data/test/weighted_table_test.rb +73 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f9ae47cda73390cc30cd6d81a594879a0f142308
|
4
|
+
data.tar.gz: 7eb73440367d32076ddbef3b9d2ded4ecb772fe5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7678295f955f7d2ddc157951b5da6d91746092eaf4f6eaad5c10dfbba7b19505bc676aa3d0baef9be415804e2ee5427d78802d45965ba486d94459d4453ada2d
|
7
|
+
data.tar.gz: 9c000fc08c2bd6debd467784dd728cd106f87958add39c9d8ab28d4b51d24a3f65930e22b55c9d80dee3e3f6b5f77a865b6a427a966552f3cf51da717ac976bb
|
data/README.md
CHANGED
@@ -5,8 +5,23 @@
|
|
5
5
|
[](https://codeclimate.com/github/czuger/hazard)
|
6
6
|
[](https://codeclimate.com/github/czuger/hazard/coverage)
|
7
7
|
|
8
|
-
Hazard is a very simple dice library for ruby
|
9
|
-
|
8
|
+
Hazard is a very simple dice library for ruby that allows you to :
|
9
|
+
* Roll dice and get the sum
|
10
|
+
* Roll dice and work with the detail
|
11
|
+
* Random pick elements from weighted lists
|
12
|
+
|
13
|
+
1. [Installation](#installation)
|
14
|
+
1. [Basic Usage](#basic-usage)
|
15
|
+
1. [Roll a simple die](#roll-a-simple-die)
|
16
|
+
1. [Roll multiple dice](#roll-multiple-dice)
|
17
|
+
1. [Advanced Usage](#advanced-usage)
|
18
|
+
1. [Roll dice and get the details](#roll-dice-and-get-the-details)
|
19
|
+
1. [Some real cases](#some-real-cases)
|
20
|
+
1. [Weighted Tables](#weighted-Tables)
|
21
|
+
1. [If you have the weights](#if-you-have-the-weights)
|
22
|
+
1. [If you don't have the weights (or are to lazy to get them)](#if-you-dont-have-the-weights-or-are-to-lazy-to-get-them)
|
23
|
+
1. [Saving and loading](#saving-and-loading)
|
24
|
+
|
10
25
|
## Installation
|
11
26
|
|
12
27
|
Add this line to your application's Gemfile:
|
@@ -27,9 +42,9 @@ If needed :
|
|
27
42
|
|
28
43
|
$ require 'hazard'
|
29
44
|
|
30
|
-
## Usage
|
45
|
+
## Basic Usage
|
31
46
|
|
32
|
-
|
47
|
+
### Roll a simple die
|
33
48
|
|
34
49
|
>> Hazard.d<n> # where n is an number
|
35
50
|
=> Roll a n-sided die
|
@@ -46,7 +61,7 @@ Examples :
|
|
46
61
|
=> 38
|
47
62
|
|
48
63
|
|
49
|
-
|
64
|
+
### Roll multiple dice
|
50
65
|
|
51
66
|
>> Hazard.r<m>d<n> # where m and n are numbers
|
52
67
|
=> Roll m n-sided dice and return the sum
|
@@ -72,8 +87,9 @@ Examples :
|
|
72
87
|
>> Hazard.d2d6
|
73
88
|
=> 8
|
74
89
|
|
90
|
+
## Advanced Usage
|
75
91
|
|
76
|
-
|
92
|
+
### Roll dice and get the details
|
77
93
|
|
78
94
|
>> Hazard.s<m>d<n> # where m and n are numbers
|
79
95
|
=> Roll m n-sided dice and return a RolledDice object
|
@@ -100,9 +116,9 @@ Examples :
|
|
100
116
|
>> Hazard.s2d6
|
101
117
|
=> #<RolledDice:0x007f62e55a0010 @rolls=[1, 6], @result=7>
|
102
118
|
|
103
|
-
|
119
|
+
### Some real cases
|
104
120
|
|
105
|
-
|
121
|
+
Assuming you are playing DD Next
|
106
122
|
|
107
123
|
# You may want to roll 2 d20 dice with advantage (take the greatest)
|
108
124
|
# This will rolls 2 d20, get the rolls and get the best of them
|
@@ -120,8 +136,50 @@ Examples :
|
|
120
136
|
# Should you have the Elemental Adept feat, which mean that you treat all 1 as 2
|
121
137
|
# If you cast a fireball, this will do the trick :
|
122
138
|
>> Hazard.s8d6.rolls.map{ |d| d == 1 ? 2 : d }.reduce(:+)
|
123
|
-
=> 24
|
139
|
+
=> 24
|
140
|
+
|
141
|
+
## Weighted Tables
|
124
142
|
|
143
|
+
Weighted tables are object that allow to get weighted random.
|
144
|
+
Example : if you have two time foo and one time bar in your table.
|
145
|
+
|
146
|
+
### If you have the weights
|
147
|
+
|
148
|
+
>> wt = WeightedTable.from_weighted_table( [ <weight1>, <object1> ], [ <weight2>, <object2> ], ... ]
|
149
|
+
# Create a weighted table storing objects according to theire weights
|
150
|
+
|
151
|
+
>> wt.sample
|
152
|
+
# Return weighted random object
|
153
|
+
|
154
|
+
Examples :
|
155
|
+
|
156
|
+
>> wt = WeightedTable.new.from_weighted_table( [ 2, :foo ], [ 1, :bar ] ]
|
157
|
+
>> wt.sample
|
158
|
+
# This ensure that you will get 66% foo and 33% bar
|
159
|
+
|
160
|
+
|
161
|
+
### If you don't have the weights (or are to lazy to get them)
|
162
|
+
|
163
|
+
>> wt = WeightedTable.from_flat_table( <object1>, <object1>, <object2>, ... ]
|
164
|
+
# Create a weighted table storing objects computing the weight of the objects according to theire occurences
|
165
|
+
|
166
|
+
>> wt.sample
|
167
|
+
# Return weighted random object
|
168
|
+
|
169
|
+
Examples :
|
170
|
+
|
171
|
+
>> wt = WeightedTable.new.from_flat_table( :foo, :foo, :bar ]
|
172
|
+
>> wt.sample
|
173
|
+
# This ensure that you will get 66% foo and 33% bar
|
174
|
+
|
175
|
+
### Saving and loading
|
176
|
+
|
177
|
+
# You can save your builded table for future usage
|
178
|
+
>> wt.to_file( filename )
|
179
|
+
|
180
|
+
# And load it
|
181
|
+
>> wt = WeightedTable.from_file( filename )
|
182
|
+
|
125
183
|
## Contributing
|
126
184
|
|
127
185
|
Bug reports and pull requests are welcome on GitHub at https://github.com/czuger/hazard. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
data/lib/hazard/version.rb
CHANGED
data/lib/hazard.rb
CHANGED
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
class WeightedTable
|
4
|
+
|
5
|
+
BASE_WEIGHT = 1
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@weights = {}
|
9
|
+
@max_weight = BASE_WEIGHT
|
10
|
+
end
|
11
|
+
|
12
|
+
# Load a WeightedTable with data
|
13
|
+
# Data format must be : [ [ weight, data ], [ weight, data ], ... ]
|
14
|
+
# Example : [ [ 2, :foo ], [ 1, :bar ] ]
|
15
|
+
#
|
16
|
+
# @return [WeightedTable] the current WeightedTable
|
17
|
+
def self.from_weighted_table( table )
|
18
|
+
WeightedTable.new.from_weighted_table( table )
|
19
|
+
end
|
20
|
+
|
21
|
+
# Load a WeightedTable with data
|
22
|
+
# Data format must be : [ [ weight, data ], [ weight, data ], ... ]
|
23
|
+
# Example : [ [ 2, :foo ], [ 1, :bar ] ]
|
24
|
+
#
|
25
|
+
# @return [WeightedTable] the current WeightedTable
|
26
|
+
def from_weighted_table( table )
|
27
|
+
raise 'Table must contain at least one element' if table.empty?
|
28
|
+
base = BASE_WEIGHT
|
29
|
+
table.each do |t|
|
30
|
+
w = base+t[0]
|
31
|
+
base = w
|
32
|
+
@weights[ w ] = t[1]
|
33
|
+
@max_weight = [ @max_weight, w-1 ].max
|
34
|
+
end
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
# Load a WeightedTable with data
|
39
|
+
# Data format must be : [ data, data, data ]
|
40
|
+
# Example : [ :foo, :foo, :bar ]
|
41
|
+
#
|
42
|
+
# @return [WeightedTable] the current WeightedTable
|
43
|
+
def self.from_flat_table( table )
|
44
|
+
from_weighted_table( table.group_by{ |e| e }.map{ |k, v| [ v.count, k ] } )
|
45
|
+
end
|
46
|
+
|
47
|
+
# Return a random item from a WeightedTable
|
48
|
+
#
|
49
|
+
# @return [Object] a random object given at the building of the table.
|
50
|
+
def sample
|
51
|
+
r = Kernel.rand( 1..@max_weight )
|
52
|
+
keys = @weights.keys.sort
|
53
|
+
|
54
|
+
low_mark = BASE_WEIGHT
|
55
|
+
|
56
|
+
until keys.empty?
|
57
|
+
high_mark = keys.shift
|
58
|
+
return @weights[high_mark] if r >= low_mark && r < high_mark
|
59
|
+
low_mark = high_mark
|
60
|
+
end
|
61
|
+
|
62
|
+
raise 'Rand not in key range'
|
63
|
+
end
|
64
|
+
|
65
|
+
# Load a WeightedTable with data
|
66
|
+
# Data format must be : [ data, data, data ]
|
67
|
+
# Example : [ :foo, :foo, :bar ]
|
68
|
+
#
|
69
|
+
# @return [WeightedTable] the current WeightedTable
|
70
|
+
def from_flat_table( table )
|
71
|
+
from_weighted_table( table.group_by{ |e| e }.map{ |k, v| [ v.count, k ] } )
|
72
|
+
end
|
73
|
+
|
74
|
+
# Save the table to a file
|
75
|
+
# @param filename [String] the filename where to save the table
|
76
|
+
def to_file( filename )
|
77
|
+
File.open( filename, 'w' ) do |f|
|
78
|
+
f.write( to_yaml )
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Read the table from a file
|
83
|
+
# @param filename [String] the filename from which to read the table
|
84
|
+
def self.from_file( filename )
|
85
|
+
YAML.load_file( filename )
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class HazardTest < Minitest::Test
|
4
|
+
|
5
|
+
def test_empty_table
|
6
|
+
assert_raises do
|
7
|
+
WeightedTable.from_weighted_table []
|
8
|
+
end
|
9
|
+
assert_raises do
|
10
|
+
WeightedTable.from_flat_table []
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_one_element_table
|
15
|
+
assert_equal :foo, WeightedTable.from_weighted_table( [ [ 3, :foo ] ] ).sample
|
16
|
+
assert_equal :foo, WeightedTable.from_flat_table( [ :foo, :foo, :foo ] ).sample
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_two_element_table
|
20
|
+
Kernel.stubs( :rand ).returns( 0 )
|
21
|
+
assert_raises do
|
22
|
+
WeightedTable.from_weighted_table []
|
23
|
+
end
|
24
|
+
assert_raises do
|
25
|
+
WeightedTable.from_flat_table []
|
26
|
+
end
|
27
|
+
|
28
|
+
Kernel.stubs( :rand ).returns( 1 )
|
29
|
+
assert_equal :foo, WeightedTable.from_weighted_table( [ [ 3, :foo ], [ 1, :bar ] ] ).sample
|
30
|
+
assert_equal :foo, WeightedTable.from_flat_table( [ :foo, :foo, :foo, :bar ] ).sample
|
31
|
+
Kernel.stubs( :rand ).returns( 2 )
|
32
|
+
assert_equal :foo, WeightedTable.from_weighted_table( [ [ 3, :foo ], [ 1, :bar ] ] ).sample
|
33
|
+
assert_equal :foo, WeightedTable.from_flat_table( [ :foo, :foo, :foo, :bar ] ).sample
|
34
|
+
Kernel.stubs( :rand ).returns( 3 )
|
35
|
+
assert_equal :foo, WeightedTable.from_weighted_table( [ [ 3, :foo ], [ 1, :bar ] ] ).sample
|
36
|
+
assert_equal :foo, WeightedTable.from_flat_table( [ :foo, :foo, :foo, :bar ] ).sample
|
37
|
+
Kernel.stubs( :rand ).returns( 4 )
|
38
|
+
assert_equal :bar, WeightedTable.from_weighted_table( [ [ 3, :foo ], [ 1, :bar ] ] ).sample
|
39
|
+
assert_equal :bar, WeightedTable.from_flat_table( [ :foo, :foo, :foo, :bar ] ).sample
|
40
|
+
|
41
|
+
Kernel.stubs( :rand ).returns( 5 )
|
42
|
+
assert_raises do
|
43
|
+
WeightedTable.from_weighted_table []
|
44
|
+
end
|
45
|
+
assert_raises do
|
46
|
+
WeightedTable.from_flat_table []
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_statistics
|
51
|
+
|
52
|
+
wt = WeightedTable.from_weighted_table [ [ 2, :foo ], [ 1, :bar ] ]
|
53
|
+
results = { foo: 0, bar: 0 }
|
54
|
+
1.upto(100).each do
|
55
|
+
results[ wt.sample ] += 1
|
56
|
+
end
|
57
|
+
|
58
|
+
assert_in_delta 0.33, (results[:bar]*0.01), 0.1
|
59
|
+
assert_in_delta 0.66, (results[:foo]*0.01), 0.1
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_save_and_load
|
63
|
+
wt = WeightedTable.from_weighted_table [ [ 2, :foo ], [ 1, :bar ] ]
|
64
|
+
wt.to_file( 'wt.yaml' )
|
65
|
+
wt = nil
|
66
|
+
wt = WeightedTable.from_file( 'wt.yaml' )
|
67
|
+
Kernel.stubs( :rand ).returns( 1 )
|
68
|
+
assert_equal :foo, wt.sample
|
69
|
+
assert_equal :foo, wt.sample
|
70
|
+
`rm wt.yaml`
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hazard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cédric ZUGER
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-04-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -71,8 +71,10 @@ files:
|
|
71
71
|
- lib/hazard.rb
|
72
72
|
- lib/hazard/version.rb
|
73
73
|
- lib/rolled_dice.rb
|
74
|
+
- lib/weighted_table.rb
|
74
75
|
- test/hazard_test.rb
|
75
76
|
- test/test_helper.rb
|
77
|
+
- test/weighted_table_test.rb
|
76
78
|
homepage: https://github.com/czuger/hazard
|
77
79
|
licenses:
|
78
80
|
- MIT
|
@@ -100,3 +102,4 @@ summary: Dice library for ruby
|
|
100
102
|
test_files:
|
101
103
|
- test/hazard_test.rb
|
102
104
|
- test/test_helper.rb
|
105
|
+
- test/weighted_table_test.rb
|