rollio 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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