hazard 1.0.4 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Code Climate](https://codeclimate.com/github/czuger/hazard/badges/gpa.svg)](https://codeclimate.com/github/czuger/hazard)
|
6
6
|
[![Test Coverage](https://codeclimate.com/github/czuger/hazard/badges/coverage.svg)](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
|