text-gen 0.10.1 → 0.11.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e428f6d3e941577501a173778ed8630413aaf73557d48692da86def7a8daa814
4
- data.tar.gz: 98f0050634808ed37898ae14de3becbd279b59c842b9231929c6008b25e13083
3
+ metadata.gz: ae82c6d0373286c09c677ea3c29fa7eb910884c130c8733251fa324b2f02b55e
4
+ data.tar.gz: d7c8715bb09f18bf47169964ddb1e9c3a050dd5535fe1ae615f3ef82258755ca
5
5
  SHA512:
6
- metadata.gz: dcf076afcb96bdcd66b653bce9d59123f3d0dae3f098c8f4b9156d66092168961fa1a5c1e03300eaf3aac595b3b41cabc3e2e1011a4d39e72aff437aa50fac1a
7
- data.tar.gz: 65728334bcc7b08f7135a690626ca64d8bf5870b25f20ed954b260d4024c017213f09aee29a7e9d4474a1a1c3305a726005349561ed46271c9b6e81bf9bdf65c
6
+ metadata.gz: 6430058076ee97e12004401ee935646f7ac2f3443e852b730a3b541c609691344fa15490306c69ef42ed932dd2e8efc40a7542d34bcc4bc7b2b65751700211cb
7
+ data.tar.gz: a985c9ebcb2f08492e7dcf7eb42c5f18766d9c4fc406f65bece512870a94f0e674bb14fb6212ca4ba56761f87a74af705a5248b8da10eaecaae8b82550019e0b
@@ -25,8 +25,6 @@ require_relative "filter/item/reject"
25
25
  module Text
26
26
  module Gen
27
27
  module Filter
28
- SEPARATORS = { "tab" => "\t", "newline" => "\n", "space" => " " }.freeze
29
-
30
28
  RESULT_FILTER_CLASSES = {
31
29
  "capitalize" => Filter::Result::Capitalize,
32
30
  "censor" => Filter::Result::Censor,
@@ -139,16 +137,6 @@ module Text
139
137
  citem
140
138
  end
141
139
 
142
- def separator(filters)
143
- return "" unless filters
144
-
145
- separator_filter = filter_by_type(filters, "separator")
146
- return "" unless separator_filter
147
- return separator_filter["value"] if separator_filter["key"] == "string"
148
-
149
- SEPARATORS.fetch(separator_filter["key"], "")
150
- end
151
-
152
140
  def filter_by_type(filters, type)
153
141
  filters&.find { |f| f["type"] == type }
154
142
  end
@@ -5,6 +5,8 @@ module Text
5
5
  # Result stores the generated text, value and metadata and context about
6
6
  # how it was created
7
7
  class Result
8
+ SEPARATORS = { "tab" => "\t", "newline" => "\n", "space" => " " }.freeze
9
+
8
10
  attr_reader :text, :type, :value, :multiplier, :meta, :components
9
11
 
10
12
  def initialize(text:, type:, value: 0, multiplier: 1)
@@ -73,11 +75,11 @@ module Text
73
75
  end
74
76
  end
75
77
 
76
- def merge(results, value: nil, multiplier: nil, filters: [], meta: {}, type: :sequence)
78
+ def merge(results, value: nil, multiplier: nil, separator: "", meta: {}, type: :sequence)
77
79
  results = results.compact
78
- sep = Filter.separator(filters)
79
80
  mul = multiplier || results.reduce(1) { |acc, r| acc * r.multiplier }
80
81
  val = value || results.sum(&:value)
82
+ sep = SEPARATORS[separator] || separator
81
83
  new(
82
84
  text: results.map(&:text).join(sep),
83
85
  type: type,
@@ -25,8 +25,6 @@ module Text
25
25
  @unique
26
26
  end
27
27
 
28
- # A filter of type "replace:key:value" creates a temporary builder
29
- # that always returns the given value.
30
28
  def populate_replace
31
29
  @request_filters.each do |f|
32
30
  store.add(f["key"], Filter.constant_builder(f["key"], f["value"])) if f["type"] == "replace"
@@ -85,7 +83,7 @@ module Text
85
83
 
86
84
  current_filters = merge_filters(builder, filters)
87
85
  current_items = apply_item_filters(builder["items"], current_filters)
88
- result = run_items(key, builder["strategy"], current_items, current_filters, builder["meta"], depth)
86
+ result = run_items(key, builder, current_items, current_filters, builder["meta"], depth)
89
87
  return unless result
90
88
 
91
89
  result.merge_meta(builder["meta"])
@@ -97,31 +95,32 @@ module Text
97
95
  Result.new(text:, type: :error)
98
96
  end
99
97
 
100
- def run_items(key, strategy, items, filters, meta, depth)
98
+ def run_items(key, builder, items, filters, meta, depth)
99
+ strategy, modifier = (builder["strategy"] || "random").split(":")
101
100
  case strategy
102
101
  when "sequence"
103
- run_item_sequence(key, items, filters, meta, depth)
102
+ run_item_sequence(key, modifier, items, filters, meta, depth)
104
103
  when "weighted"
105
- run_weighted_items(key, items, meta, depth)
104
+ run_weighted_items(key, modifier, items, meta, depth)
106
105
  else
107
- run_random_item(key, strategy, items, meta, depth)
106
+ run_random_item(key, modifier, items, meta, depth)
108
107
  end
109
108
  rescue StandardError => e
110
109
  error_result("{#{e.class.name}:#{e.message}}")
111
110
  end
112
111
 
113
- def random_item(strategy, items)
114
- return items.sample if strategy.nil? || strategy.empty? || strategy == "random"
112
+ def random_item(dice, items)
113
+ return items.sample if dice.nil? || dice.empty? || dice == "*"
115
114
 
116
- total, count = random_from_dice(strategy)
115
+ total, count = random_from_dice(dice)
117
116
  index = total - count # convert to 0-indexed
118
117
  raise NoItemMatched("roll #{total} exceeds #{items.length}") if index >= items.length
119
118
 
120
119
  items[index]
121
120
  end
122
121
 
123
- def run_random_item(key, strategy, items, meta, depth)
124
- item = random_item(strategy, items)
122
+ def run_random_item(key, dice, items, meta, depth)
123
+ item = random_item(dice, items)
125
124
  result = run_item(key, item, depth)
126
125
  return unless result
127
126
 
@@ -129,16 +128,30 @@ module Text
129
128
  result
130
129
  end
131
130
 
132
- def run_item_sequence(key, items, filters, meta, depth)
133
- results = items.map { |item| run_item(key, item, depth) }.compact
131
+ def run_item_sequence(key, separator, items, filters, meta, depth)
132
+ results = items.map do |item|
133
+ weight = item["weight"]&.to_i || 100
134
+ next unless rand(100) < weight.clamp(1, 100)
135
+
136
+ run_item(key, item, depth)
137
+ end
138
+
139
+ results = results.compact
134
140
  return if results.empty?
135
141
 
136
- Result.merge(results, filters:, meta:, type: :sequence)
142
+ Result.merge(results, separator: separator || "", meta:, type: :sequence)
137
143
  end
138
144
 
139
- def run_weighted_items(key, items, meta, depth)
145
+ def run_weighted_items(key, dice, items, meta, depth)
140
146
  total_weight = items.sum { |item| [item.fetch("weight", 1).to_i, 1].max }
141
- rand_weight = rand(total_weight)
147
+ rand_weight = if dice.nil? || dice.empty? || dice == "*"
148
+ rand(total_weight)
149
+ else
150
+ total, count = random_from_dice(dice)
151
+ total - count # convert to 0-indexed
152
+ end
153
+ return if rand_weight > total_weight
154
+
142
155
  current_weight = 0
143
156
  item = items.find do |item|
144
157
  current_weight += [item.fetch("weight", 1).to_i, 1].max
@@ -156,7 +169,6 @@ module Text
156
169
  result = Result.merge(results,
157
170
  value: item["value"],
158
171
  multiplier: item["multiplier"],
159
- filters: item["filters"],
160
172
  meta: item["meta"],
161
173
  type: key)
162
174
  result = apply_result_function(result, item["filters"])
@@ -179,7 +191,9 @@ module Text
179
191
  def random_from_dice(text)
180
192
  rolled = DiceNomShim.roll(text)
181
193
  parsed = JSON.parse(rolled).first["lhs"]
182
- count = parsed["values"].size
194
+
195
+ # Keep tracks the dice that weren't discarded
196
+ count = parsed["values"].select {|v| v["keep"] }.count
183
197
  total = parsed["total"]
184
198
  [total, count]
185
199
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Text
4
4
  module Gen
5
- VERSION = "0.10.1"
5
+ VERSION = "0.11.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: text-gen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.1
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - G Palmer