rollio 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bef6820ce929c27df6d2f18caed085a06e490809a720f95dcb19621724ce4b4b
4
- data.tar.gz: 5be947c8d951a0b3d9a3e586dfad03a14a49980c5c5da9b6e582dbcdd57bf07b
3
+ metadata.gz: e6d9919949718ff310a8dfdc0100df7c723b65674f43434e750412c52383b265
4
+ data.tar.gz: 7fd4483fd44dec675c22ace6269e1e4e95313c81ad4b84d8f0508cad7b8eb2fe
5
5
  SHA512:
6
- metadata.gz: e3e0f3f3b297919c07de06ec1be9610a4ecf2a994f94902002c5f6091a2ecd81b9996acba4e10f521d89d14a8dd5f8a6780a9391f7c1914dd370c1af49ddc245
7
- data.tar.gz: d200112f6ac80c0aed9306f6c56d53280dc341fa8e31ac597e99f58e15f1b4e95526579a918b9d91d5c24b4fefeeeb3f69be2dbf01e684a570bc16ccdc209d13
6
+ metadata.gz: 37ee8ea172926651aa22d54479b369752685278544ca5a93a8425361ba6e98ae63daad182485e0a789058638394b3998a6bd68eaf254072b358aed0966c1c7dc
7
+ data.tar.gz: 6c31a6c62645d7bfc6d93f8774ef5a864ae221e0d077fb37243e9105d561b16921040dbd64189233c502b6aa4a2a28ec92d44fdd88aae2b695405ec2bf957fff
data/Gemfile CHANGED
@@ -4,3 +4,5 @@ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in rollio.gemspec
6
6
  gemspec
7
+
8
+ gem 'byebug'
data/README.md CHANGED
@@ -4,14 +4,16 @@ A tool for loading random tables, rolling on those tables, and rendering the out
4
4
 
5
5
  ## Todo List
6
6
 
7
- - [ ] Create schema to define valid JSON document
7
+ - [X] Create schema to define valid JSON document
8
8
  - [ ] Integrate schema validation for loaded JSON document
9
- - [ ] Allow inner-table logic\*
10
- - [ ] Create structure for loading tables
9
+ - [X] Allow inner-table logic\*
10
+ - [X] Create structure for loading tables
11
11
  - [ ] Create command line tool
12
- - [ ] List available tables (with help) (e.g. `rollio roll -h`)
13
- - [ ] Look to parameterization of table rolls
14
- - [ ] Roll on tables (e.g. `rollio roll background`)
12
+ - [X] List available tables (with help) (e.g. `rollio roll -h`)
13
+ - [ ] Look to parameterization of table rolls
14
+ - [X] Roll on tables (e.g. `rollio roll background`)
15
+ - [ ] Create structure for SWN batch of tables to roll at once
16
+ - [ ] Add ability to roll a dice expression via `rollio roll`
15
17
 
16
18
  \* - By inner table logic I'm referring to "On a d10 table, when you roll a 9 or 10, roll on this table twice using a d8"
17
19
 
@@ -0,0 +1,10 @@
1
+ {
2
+ "key": "defy_danger",
3
+ "label": "Defy Danger",
4
+ "roll": "2d6",
5
+ "entries": [
6
+ { "range": [-1,0,1,2,3,4,5,6], "result": "You do it"},
7
+ { "range": [7,8,9], "result": "You stumble, hesitate, or flinch: the GM will offer you a worse outcome, hard bargain, or ugly choice." },
8
+ { "range": [10,11,12,13,14,15,16], "result": "You flounder: the GM will make a hard move"}
9
+ ]
10
+ }
@@ -0,0 +1,24 @@
1
+ [{
2
+ "key": "table-a",
3
+ "roll": "2d6",
4
+ "entries": [
5
+ { "range": [2,3,4,5,6], "roll_on": "table-b", "with": "1d3", "times": 2},
6
+ { "range": [7], "result": "Yolo" },
7
+ { "range": [8,9,10,11,12], "inner_table": {
8
+ "roll": "1d4",
9
+ "entries": [
10
+ { "range": [1,2,3], "result": "Yes" },
11
+ { "range": [4], "result": "No" }
12
+ ]
13
+ }
14
+ }
15
+ ]},{
16
+ "key": "table-b",
17
+ "roll": "1d6",
18
+ "entries": [
19
+ { "range": [1], "result": "least result from sub-table" },
20
+ { "range": [2,3,4,5], "result": "mid-range result from sub-table" },
21
+ { "range": [6], "result": "greatest result from sub-table" }
22
+ ]
23
+ }
24
+ ]
data/exe/rollio ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rollio/cli'
4
+
5
+ Rollio::CLI.start(ARGV)
data/lib/rollio.rb CHANGED
@@ -1,6 +1,75 @@
1
1
  require "rollio/version"
2
2
  require "rollio/registry"
3
+ require 'json'
4
+ require 'hanami/utils/hash'
3
5
 
4
6
  module Rollio
5
- # Your code goes here...
7
+ # @api private
8
+ # @example
9
+ # document = [{
10
+ # key: '1-a',
11
+ # roll: '2d6',
12
+ # entries: [
13
+ # { range: [2,3,4,5,6], roll_on: '1-b', with: '1d3', times: 2},
14
+ # { range: [7], result: 'Yolo' },
15
+ # { range: [8,9,10,11,12], inner_table: {
16
+ # roll: '1d4',
17
+ # entries: [
18
+ # { range: [1,2,3], result: 'Yes' },
19
+ # { range: [4], result: 'No' }
20
+ # ]
21
+ # }
22
+ # }
23
+ # },{
24
+ # key: '1-b',
25
+ # roll: '1d6',
26
+ # entries: [
27
+ # { range: [1,2,3,4,5,6], result: 'sub-table' }
28
+ # ]
29
+ # }
30
+ # ]
31
+ # registry = Rollio::Registry.load(document)
32
+ #
33
+ # @example
34
+ # registry = Rollio::Registry.load do
35
+ # table('1') do
36
+ # roll('1d5')
37
+ # entry(1, 'Yes!')
38
+ # entry(2..5, 'No!')
39
+ # end
40
+ # end
41
+ # @return [Rollio::Registry, #roll_on]
42
+ # @todo Add document schema and validation
43
+ def self.load(document = nil, context = self, &block)
44
+ if document
45
+ Registry.new do |registry|
46
+ document.each do |data|
47
+ context.load_a_table(registry: registry, data: data, context: context)
48
+ end
49
+ end
50
+ else
51
+ Registry.new(&block)
52
+ end
53
+ end
54
+
55
+ # @api private
56
+ # @todo Does the guts of this logic make sense here?
57
+ def self.load_a_table(registry: , data:, context: self, key: nil)
58
+ key ||= data.fetch(:key)
59
+ label = data.fetch(:label, key)
60
+ table = registry.table(key, label: label)
61
+ table.roll(data.fetch(:roll))
62
+ data.fetch(:entries).each do |table_entry|
63
+ range = table_entry.fetch(:range)
64
+ if table_entry.key?(:roll_on)
65
+ table.entry(range, **table_entry)
66
+ elsif table_entry.key?(:result)
67
+ table.entry(range, table_entry.fetch(:result))
68
+ elsif table_entry.key?(:inner_table)
69
+ inner_table = table_entry.fetch(:inner_table)
70
+ entry = table.entry(range, inner_table: true)
71
+ context.load_a_table(registry: registry, data: inner_table, context: context, key: entry.key)
72
+ end
73
+ end
74
+ end
6
75
  end
data/lib/rollio/cli.rb ADDED
@@ -0,0 +1,65 @@
1
+ require 'thor'
2
+ require 'rollio'
3
+ module Rollio
4
+ class CLI < Thor
5
+ option(
6
+ :source,
7
+ aliases: '-s',
8
+ required: true,
9
+ default: File.join(ENV['HOME'], '.rollio'),
10
+ desc: "The <source> directory for tables to load into rollio"
11
+ )
12
+ def initialize(*args)
13
+ super
14
+ register!
15
+ end
16
+
17
+ desc "list", "List the registered tables"
18
+ long_desc <<-LONGDESC
19
+ `rollio list` will print out a list of all registered tables
20
+ LONGDESC
21
+ option(
22
+ :delimiter,
23
+ aliases: '-d',
24
+ desc: "The <delimiter> used to separate the table entries"
25
+ )
26
+ option(:help, aliases: '-h')
27
+ def list
28
+ help(__method__) and return if options[:help]
29
+ $stdout.puts @registry.table_names.join(options.fetch(:delimiter, "\n"))
30
+ end
31
+
32
+ desc "audit", "Audit the tables in <source> to ensure validity"
33
+ option(:help, aliases: '-h')
34
+ def audit
35
+ end
36
+
37
+ desc "roll <table>", "Roll on the given table"
38
+ option(:help, aliases: '-h')
39
+ def roll(table)
40
+ help(__method__) and return if options[:help]
41
+ $stdout.puts @registry.roll_on(table)
42
+ end
43
+
44
+ desc "render", "Render the stored tables"
45
+ option(:help, aliases: '-h')
46
+ def render
47
+ help(__method__) and return if options[:help]
48
+ $stdout.puts @registry.render
49
+ end
50
+
51
+ private
52
+
53
+ def register!
54
+ @registry = Rollio.load
55
+ Dir.glob("#{options[:source]}/**/*.json").each do |filename|
56
+ tables = JSON.parse(File.read(filename))
57
+ tables = [tables] unless tables.is_a?(Array)
58
+ tables.each do |table|
59
+ data = Hanami::Utils::Hash.deep_symbolize(table)
60
+ Rollio.load_a_table(registry: @registry, data: data)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,121 @@
1
+ module Rollio
2
+ module Range
3
+ def self.new(table:, range:, result:, roll_on: nil, inner_table: nil, inner_table_config: nil, times: 1, with: nil)
4
+ if result
5
+ Result.new(table: table, range: range, result: result, times: times)
6
+ elsif roll_on
7
+ RollOn.new(table: table, range: range, roll_on: roll_on, times: times, with: with)
8
+ elsif inner_table
9
+ InnerRollOn.new(table: table, range: range, times: times)
10
+ elsif inner_table_config
11
+ InnerTable.new(table: table, range: range, inner_table: inner_table_config, times: times)
12
+ else
13
+ raise "Hello"
14
+ end
15
+ end
16
+
17
+ class Base
18
+ attr_reader :table, :range, :times
19
+ def initialize(table:, range:, times:, **kwargs)
20
+ @table = table
21
+ self.range = range
22
+ @times = times
23
+ end
24
+
25
+ def key
26
+ "#{table.key} (Sub #{range})"
27
+ end
28
+
29
+ extend Comparable
30
+ def <=>(other)
31
+ range.first <=> other.range.first
32
+ end
33
+
34
+ def render
35
+ if range.first == range.last
36
+ puts "#{range.first}\t#{result}"
37
+ else
38
+ puts "#{range.first}-#{range.last}\t#{result}"
39
+ end
40
+ end
41
+
42
+ def result
43
+ raise NotImplementedError
44
+ end
45
+
46
+ extend Forwardable
47
+ def_delegator :table, :table_set
48
+
49
+ def include?(value)
50
+ if @range.respond_to?(:include?)
51
+ @range.include?(value)
52
+ else
53
+ @range == value
54
+ end
55
+ end
56
+
57
+ def range=(input)
58
+ @range = Array(input)
59
+ end
60
+ end
61
+ private_constant :Base
62
+
63
+ class Result < Base
64
+ attr_reader :result
65
+ def initialize(result:, **kwargs)
66
+ super(**kwargs)
67
+ @result = result
68
+ end
69
+
70
+ def roll!
71
+ [@result]
72
+ end
73
+ end
74
+ private_constant :Result
75
+
76
+ class RollOn < Base
77
+ attr_reader :with
78
+ def initialize(roll_on:, **kwargs)
79
+ super(**kwargs)
80
+ @roll_on = roll_on
81
+ @with = kwargs[:with]
82
+ end
83
+
84
+ def roll!
85
+ (1..times).map { table_set.roll_on(@roll_on, with: with) }
86
+ end
87
+
88
+ def result
89
+ "Roll on #{@roll_on}"
90
+ end
91
+ end
92
+ private_constant :RollOn
93
+
94
+ class InnerRollOn < Base
95
+ def roll!
96
+ (1..times).map { table_set.roll_on(key) }
97
+ end
98
+
99
+ def result
100
+ "Roll on #{key}"
101
+ end
102
+ end
103
+
104
+ class InnerTable < Base
105
+ def initialize(inner_table:, **kwargs)
106
+ super(**kwargs)
107
+ @table.table_set.add(key, &inner_table)
108
+ end
109
+
110
+ def roll!
111
+ (1..times).map { table_set.roll_on(key) }
112
+ end
113
+
114
+ def result
115
+ "Roll on #{key}"
116
+ end
117
+ end
118
+ private_constant :InnerTable
119
+ end
120
+ private_constant :Range
121
+ end
@@ -0,0 +1,26 @@
1
+ require 'rollio/range'
2
+ module Rollio
3
+ class RangeSet
4
+ def initialize(table:)
5
+ @table = table
6
+ @ranges = []
7
+ end
8
+
9
+ def render
10
+ @ranges.sort.each do |range|
11
+ range.render
12
+ end
13
+ end
14
+
15
+ def resolve(roll:)
16
+ @ranges.detect { |range| range.include?(roll) }.roll!
17
+ end
18
+
19
+ def add(range:, **kwargs)
20
+ range_object = Range.new(range: range, **kwargs)
21
+ @ranges << range_object
22
+ range_object
23
+ end
24
+ end
25
+ private_constant :RangeSet
26
+ end
@@ -1,332 +1,36 @@
1
1
  require 'forwardable'
2
2
  require 'dice' # from dice_parser
3
+ require 'rollio/table_set'
3
4
 
4
5
  module Rollio
5
6
  # Responsible for registering random tables and exposing a means of rolling on those tables.
6
7
  class Registry
7
- # @api private
8
- # @example
9
- # document = [{
10
- # key: '1-a',
11
- # roll: '2d6',
12
- # entries: [
13
- # { range: [2,3,4,5,6], roll_on: '1-b'},
14
- # { range: [7], result: 'Yolo' },
15
- # { range: [8,9,10,11,12], inner_table: {
16
- # roll: '1d4',
17
- # entries: [
18
- # { range: [1,2,3], result: 'Yes' },
19
- # { range: [4], result: 'No' }
20
- # ]
21
- # }
22
- # }
23
- # },{
24
- # key: '1-b',
25
- # roll: '1d6',
26
- # entries: [
27
- # { range: [1,2,3,4,5,6], result: 'sub-table' }
28
- # ]
29
- # }
30
- # ]
31
- # registry = Rollio::Registry.load(document)
32
- #
33
- # @example
34
- # registry = Rollio::Registry.load do
35
- # table('1') do
36
- # roll('1d5')
37
- # entry(1, 'Yes!')
38
- # entry(2..5, 'No!')
39
- # end
40
- # end
41
- # @return [Rollio::Registry, #roll_on]
42
- # @todo Add document schema and validation
43
- # @todo Expose #load method to allow additional loading outside of initialization
44
- def self.load(document = nil, context = self, &block)
45
- if document
46
- Registry.new do |registry|
47
- document.each do |data|
48
- context.load_a_table(registry: registry, data: data, context: context)
49
- end
50
- end
51
- else
52
- Registry.new(&block)
53
- end
54
- end
55
-
56
- # @api private
57
- def self.load_a_table(registry:, data:, context:, key: nil)
58
- key ||= data.fetch(:key)
59
- label = data.fetch(:label, key)
60
- table = registry.table(key, label: label)
61
- table.roll(data.fetch(:roll))
62
- data.fetch(:entries).each do |table_entry|
63
- range = table_entry.fetch(:range)
64
- if table_entry.key?(:roll_on)
65
- table.entry(range, roll_on: table_entry.fetch(:roll_on), times: table_entry.fetch(:times, 1))
66
- elsif table_entry.key?(:result)
67
- table.entry(range, table_entry.fetch(:result))
68
- elsif table_entry.key?(:inner_table)
69
- inner_table = table_entry.fetch(:inner_table)
70
- entry = table.entry(range, inner_table: true)
71
- Registry.load_a_table(registry: registry, data: inner_table, context: context, key: entry.key)
72
- end
73
- end
74
- end
75
-
76
- attr_reader :table_set
8
+ # @api public
77
9
  def initialize(&block)
78
- @table_set = TableSet.new(registry: self)
10
+ self.table_set = TableSet.new(registry: self)
79
11
  instance_exec(self, &block) if block_given?
80
12
  end
81
13
 
14
+ attr_accessor :table_set
15
+ private :table_set=
16
+
82
17
  # @api private
83
18
  # @param key [String] The key of the table you want to roll on
84
19
  # @see Registry::Table#key for details
85
20
  # @todo Consider adding a modifier (eg. `roll_on(key, with: -2)`)
86
- def roll_on(key)
87
- @table_set.roll_on(key)
21
+ def roll_on(key, **kwargs)
22
+ table_set.roll_on(key, **kwargs)
88
23
  end
89
24
 
25
+ # @api private
26
+ # The exposed method for adding a table to the registry
90
27
  def table(*args, &block)
91
- @table_set.add(*args, &block)
28
+ table_set.add(*args, &block)
92
29
  end
93
30
 
94
31
  extend Forwardable
95
32
  def_delegator :table_set, :render
96
-
97
- class TableSet
98
- extend Forwardable
99
-
100
- def initialize(registry:)
101
- @registry = registry
102
- @tables = {}
103
- end
104
-
105
- private
106
-
107
- attr_reader :tables, :registry
108
-
109
- public
110
-
111
- def roll_on(table_name)
112
- table = @tables.fetch(table_name)
113
- table.roll!
114
- end
115
-
116
- def add(key, label: key, &block)
117
- @tables[key] = Table.new(table_set: self, key: key, label: label, &block)
118
- end
119
-
120
- def render(debug: false)
121
- puts "Table Set { object_id: #{object_id} }\n" if debug
122
- @tables.sort { |a,b| a[0] <=> b[0] }.each do |key, table|
123
- table.render
124
- end
125
- nil
126
- end
127
- end
128
- private_constant :TableSet
129
-
130
- class Table
131
- attr_reader :key, :table_set, :label, :roller
132
- private :roller
133
- def initialize(table_set:, key:, label:, &block)
134
- @key = key
135
- @table_set = table_set
136
- @label = label
137
- @range_set = RangeSet.new(table: self)
138
- instance_exec(self, &block) if block_given?
139
- end
140
-
141
- def render
142
- header = "Table: #{key}"
143
- header = "#{header} - #{label}" unless label == key
144
- puts header
145
- puts '-' * header.length
146
- roller.render
147
- @range_set.render
148
- end
149
-
150
- def roll!(the_roller: roller)
151
- roll = the_roller.roll!
152
- @range_set.resolve(roll: roll)
153
- end
154
-
155
- def roll(text)
156
- @roller = Roller.new(text)
157
- end
158
-
159
- def entry(range, result = nil, roll_on: nil, inner_table: nil, times: 1, &inner_table_config)
160
- @range_set.add(
161
- table: self,
162
- range: range,
163
- result: result,
164
- roll_on: roll_on,
165
- inner_table: inner_table,
166
- inner_table_config: inner_table_config,
167
- times: times
168
- )
169
- end
170
-
171
- protected
172
-
173
- class Roller
174
- def initialize(text)
175
- @text = text
176
- end
177
-
178
- def roll!
179
- Dice.roll(@text)
180
- end
181
-
182
- def render
183
- puts "#{@text}\tResult"
184
- end
185
- end
186
- private_constant :Roller
187
-
188
- class RangeSet
189
- def initialize(table:)
190
- @table = table
191
- @ranges = []
192
- end
193
-
194
- def render
195
- @ranges.sort.each do |range|
196
- range.render
197
- end
198
- end
199
-
200
- def resolve(roll:)
201
- @ranges.detect { |range| range.include?(roll) }.roll!
202
- end
203
-
204
- def add(range:, **kwargs)
205
- range_object = Range.new(range: range, **kwargs)
206
- @ranges << range_object
207
- range_object
208
- end
209
- end
210
- private_constant :RangeSet
211
-
212
- module Range
213
- def self.new(table:, range:, result:, roll_on:, inner_table:, inner_table_config:, times:)
214
- if result
215
- Result.new(table: table, range: range, result: result, times: times)
216
- elsif roll_on
217
- RollOn.new(table: table, range: range, roll_on: roll_on, times: times)
218
- elsif inner_table
219
- InnerRollOn.new(table: table, range: range, times: times)
220
- elsif inner_table_config
221
- InnerTable.new(table: table, range: range, inner_table: inner_table_config, times: times)
222
- else
223
- raise "Hello"
224
- end
225
- end
226
-
227
- class Base
228
- attr_reader :table, :range, :times
229
- def initialize(table:, range:, times:)
230
- @table = table
231
- self.range = range
232
- @times = times
233
- end
234
-
235
- def key
236
- "#{table.key} (Sub #{range})"
237
- end
238
-
239
- extend Comparable
240
- def <=>(other)
241
- range.first <=> other.range.first
242
- end
243
-
244
- def render
245
- if range.first == range.last
246
- puts "#{range.first}\t#{result}"
247
- else
248
- puts "#{range.first}-#{range.last}\t#{result}"
249
- end
250
- end
251
-
252
- def result
253
- raise NotImplementedError
254
- end
255
-
256
- extend Forwardable
257
- def_delegator :table, :table_set
258
-
259
- def include?(value)
260
- if @range.respond_to?(:include?)
261
- @range.include?(value)
262
- else
263
- @range == value
264
- end
265
- end
266
-
267
- def range=(input)
268
- @range = Array(input)
269
- end
270
- end
271
- private_constant :Base
272
-
273
- class Result < Base
274
- attr_reader :result
275
- def initialize(result:, **kwargs)
276
- super(**kwargs)
277
- @result = result
278
- end
279
-
280
- def roll!
281
- [@result]
282
- end
283
- end
284
- private_constant :Result
285
-
286
- class RollOn < Base
287
- def initialize(roll_on:, **kwargs)
288
- super(**kwargs)
289
- @roll_on = roll_on
290
- end
291
-
292
- def roll!
293
- (1..times).map { table_set.roll_on(@roll_on) }
294
- end
295
-
296
- def result
297
- "Roll on #{@roll_on}"
298
- end
299
- end
300
- private_constant :RollOn
301
-
302
- class InnerRollOn < Base
303
- def roll!
304
- (1..times).map { table_set.roll_on(key) }
305
- end
306
-
307
- def result
308
- "Roll on #{key}"
309
- end
310
- end
311
-
312
- class InnerTable < Base
313
- def initialize(inner_table:, **kwargs)
314
- super(**kwargs)
315
- @table.table_set.add(key, &inner_table)
316
- end
317
-
318
- def roll!
319
- (1..times).map { table_set.roll_on(key) }
320
- end
321
-
322
- def result
323
- "Roll on #{key}"
324
- end
325
- end
326
- private_constant :InnerTable
327
- end
328
- private_constant :Range
329
- end
330
- private_constant :Table
33
+ def_delegator :table_set, :table_names
331
34
  end
35
+ private_constant :Registry
332
36
  end
@@ -0,0 +1,18 @@
1
+ require 'dice' # from dice_parser
2
+
3
+ module Rollio
4
+ class Roller
5
+ def initialize(text)
6
+ @text = text
7
+ end
8
+
9
+ def roll!
10
+ Dice.roll(@text)
11
+ end
12
+
13
+ def render
14
+ puts "#{@text}\tResult"
15
+ end
16
+ end
17
+ private_constant :Roller
18
+ end
@@ -0,0 +1,24 @@
1
+ require 'dry-validation'
2
+ module Rollio
3
+ module Schemas
4
+ EntrySchema = Dry::Validation.Schema do
5
+ required(:range).each(:int?)
6
+ optional(:result).maybe(:str?)
7
+ optional(:roll_on).maybe(:str?)
8
+ optional(:inner_table).schema do
9
+ required(:roll).filled(:str?)
10
+ required(:entries).each do
11
+ schema do
12
+ required(:range).each(:int?)
13
+ optional(:result).maybe(:str?)
14
+ optional(:roll_on).maybe(:str?)
15
+ end
16
+ end
17
+ end
18
+
19
+ rule :result_or_inner_table_or_rolled_on_is_required do
20
+ value(:result).filled? ^ value(:roll_on).filled? ^ value(:inner_table).filled?
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ require 'dry-validation'
2
+ require 'rollio/schemas/entry_schema'
3
+ module Rollio
4
+ module Schemas
5
+ TableSchema = Dry::Validation.Schema do
6
+ required(:key).filled(:str?)
7
+ required(:roll).filled(:str?)
8
+ required(:entries).each do
9
+ schema(EntrySchema)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,45 @@
1
+ require 'rollio/roller'
2
+ require 'rollio/range_set'
3
+ module Rollio
4
+ class Table
5
+ attr_reader :key, :table_set, :label, :roller
6
+ private :roller
7
+ def initialize(table_set:, key:, label:, &block)
8
+ @key = key
9
+ @table_set = table_set
10
+ @label = label
11
+ @range_set = RangeSet.new(table: self)
12
+ instance_exec(self, &block) if block_given?
13
+ end
14
+
15
+ def render
16
+ header = "Table: #{key}"
17
+ header = "#{header} - #{label}" unless label == key
18
+ puts header
19
+ puts '-' * header.length
20
+ roller.render
21
+ @range_set.render
22
+ end
23
+
24
+ def roll!(with: roller)
25
+ the_roller = with.is_a?(Roller) ? with : Roller.new(with)
26
+ roll = the_roller.roll!
27
+ @range_set.resolve(roll: roll)
28
+ end
29
+
30
+ def roll(text)
31
+ @roller = Roller.new(text)
32
+ end
33
+
34
+ def entry(range, result = nil, **kwargs, &inner_table_config)
35
+ @range_set.add(
36
+ table: self,
37
+ range: range,
38
+ result: result,
39
+ inner_table_config: inner_table_config,
40
+ **kwargs
41
+ )
42
+ end
43
+ end
44
+ private_constant :Table
45
+ end
@@ -0,0 +1,40 @@
1
+ require 'rollio/table'
2
+
3
+ module Rollio
4
+ # The data store for all of the registered tables
5
+ class TableSet
6
+
7
+ def initialize(registry:)
8
+ @registry = registry
9
+ @tables = {}
10
+ end
11
+
12
+ private
13
+
14
+ attr_reader :tables, :registry
15
+
16
+ public
17
+
18
+ def table_names
19
+ tables.keys.sort
20
+ end
21
+
22
+ def roll_on(table_name, **kwargs)
23
+ table = tables.fetch(table_name)
24
+ table.roll!(**kwargs)
25
+ end
26
+
27
+ def add(key, label: key, &block)
28
+ tables[key] = Table.new(table_set: self, key: key, label: label, &block)
29
+ end
30
+
31
+ def render(debug: false)
32
+ puts "Table Set { object_id: #{object_id} }\n" if debug
33
+ tables.sort { |a,b| a[0] <=> b[0] }.each do |key, table|
34
+ table.render
35
+ end
36
+ nil
37
+ end
38
+ end
39
+ private_constant :TableSet
40
+ end
@@ -1,3 +1,3 @@
1
1
  module Rollio
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
data/rollio.gemspec CHANGED
@@ -27,4 +27,8 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency "rake", "~> 10.0"
28
28
  spec.add_development_dependency "rspec", "~> 3.0"
29
29
  spec.add_dependency "dice_parser"
30
+ spec.add_dependency "dry-validation"
31
+ spec.add_dependency "json"
32
+ spec.add_dependency "hanami-utils"
33
+ spec.add_dependency "thor"
30
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rollio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Friesen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-07-03 00:00:00.000000000 Z
11
+ date: 2018-07-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,10 +66,67 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: dry-validation
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: json
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: hanami-utils
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: thor
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
69
125
  description: A DSL and JSON Schema for RPG tables
70
126
  email:
71
127
  - jeremy.n.friesen@gmail.com
72
- executables: []
128
+ executables:
129
+ - rollio
73
130
  extensions: []
74
131
  extra_rdoc_files: []
75
132
  files:
@@ -83,8 +140,19 @@ files:
83
140
  - Rakefile
84
141
  - bin/console
85
142
  - bin/setup
143
+ - data/defy_danger.json
144
+ - data/examples.json
145
+ - exe/rollio
86
146
  - lib/rollio.rb
147
+ - lib/rollio/cli.rb
148
+ - lib/rollio/range.rb
149
+ - lib/rollio/range_set.rb
87
150
  - lib/rollio/registry.rb
151
+ - lib/rollio/roller.rb
152
+ - lib/rollio/schemas/entry_schema.rb
153
+ - lib/rollio/schemas/table_schema.rb
154
+ - lib/rollio/table.rb
155
+ - lib/rollio/table_set.rb
88
156
  - lib/rollio/version.rb
89
157
  - rollio.gemspec
90
158
  homepage: https://github.com/jeremyf/rollio