text-gen 0.12.6 → 0.13.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: 96d238eb66df5e222ca033cbdcbc4c96a24756e9d3a24b0fedaa3f8b8c71af7f
4
- data.tar.gz: 2310d7a4f9b6d290d75fefe757be1a766198bed7d5fa6835327500f7f6c11171
3
+ metadata.gz: 2afbd1cd20f4be4fa1c6ebb125fda4894f46026a078b8b54f808ed1e9fb684e6
4
+ data.tar.gz: '043274280f1ff52837206196ee489932b64c85f1a2af037b9b29cf1127ae1236'
5
5
  SHA512:
6
- metadata.gz: 24b4e5056f75e5c862ccf4ae21638af665a7ceb0f0a1bdc739ee0ce95f856b398e61a09cc450ed3e5e2329c2c7052765dff3e7ab8daf0dd0c87f91bbe754acff
7
- data.tar.gz: 4c2b802d548be347b3e674fc174648554a4627944f600a30cd9dca3e6806aa014e71952221db0f0fcd329d154151c6583afdb51d40cf05b564bbb838457a0edf
6
+ metadata.gz: cce97e373664b52db5752f18d0a672041246486fdd4848aeb74febf96f099543ac04ac97c5609ea71877ac867afa9a805a51862d5099ddad3dc74be81f9579ea
7
+ data.tar.gz: 5762c3a92aca626f66e5127ab9aef91bc7a14bce1111e44836f7b083b7cc35ee387b4f8f5f0ea4351d38fad789a3bdde015dfce7f81257f78740f5627870f8c6
data/CHANGELOG.md CHANGED
@@ -1,4 +1,7 @@
1
- ## [Unreleased]
1
+ ## [0.13.0] - 2026-06-20
2
+
3
+ - Builder items can be concatonated by using the `+` operator (e.g. `key1+key2`)
4
+ - Cleaned up the strategy behavior to default to "weigted" and renamed "random" to "sample"
2
5
 
3
6
  ## [0.1.0] - 2025-12-28
4
7
 
@@ -4,6 +4,8 @@ module Text
4
4
  module Gen
5
5
  # Keep the context for one run.
6
6
  class Context
7
+ KNOWN_STRATEGIES = Set.new(%w[random weighted sequence sample])
8
+
7
9
  attr_reader :store, :depth
8
10
 
9
11
  def initialize(store:, filters: nil, meta: nil, max_recursion: 10)
@@ -22,10 +24,19 @@ module Text
22
24
  def descend!(builder)
23
25
  @depth += 1
24
26
  @keys << builder["key"]
25
- @strategy_stack << (builder["strategy"] || "random").split(":", 2)
27
+ @strategy_stack << strategy_to_stack_item(builder)
26
28
  raise MaxRecursionError if @depth > @max_recursion
27
29
  end
28
30
 
31
+ def strategy_to_stack_item(builder)
32
+ strategy, modifier = builder.fetch("strategy", "weighted").split(":", 2)
33
+ unless KNOWN_STRATEGIES.include?(strategy)
34
+ modifier = strategy
35
+ strategy = "weighted"
36
+ end
37
+ [strategy, modifier]
38
+ end
39
+
29
40
  def ascend!
30
41
  @depth -= 1
31
42
  @keys.pop
@@ -50,7 +61,7 @@ module Text
50
61
  end
51
62
 
52
63
  def current_strategy
53
- @strategy_stack.last&.first || "random"
64
+ @strategy_stack.last&.first || "weighted"
54
65
  end
55
66
 
56
67
  def current_modifier
@@ -68,12 +68,12 @@ module Text
68
68
  return if items.empty?
69
69
 
70
70
  case context.current_strategy
71
+ when "sample"
72
+ run_random_item(context, items)
71
73
  when "sequence"
72
74
  run_item_sequence(context, items)
73
- when "weighted"
74
- run_weighted_items(context, items)
75
75
  else
76
- run_random_item(context, items)
76
+ run_weighted_items(context, items)
77
77
  end
78
78
  end
79
79
 
@@ -94,7 +94,7 @@ module Text
94
94
  end
95
95
 
96
96
  def run_weighted_items(context, items)
97
- total_weight = items.sum { |item| [item.fetch("weight", 1).to_i, 1].max }
97
+ total_weight = calculate_total_weight(context, items)
98
98
  dice = context.current_modifier
99
99
  rand_weight = if dice.nil? || dice.empty? || dice == "*"
100
100
  rand(total_weight)
@@ -104,6 +104,7 @@ module Text
104
104
  end
105
105
  return if rand_weight > total_weight
106
106
 
107
+
107
108
  current_weight = 0
108
109
  item = items.find do |item|
109
110
  current_weight += [item.fetch("weight", 1).to_i, 1].max
@@ -201,6 +202,36 @@ module Text
201
202
  end
202
203
  end
203
204
 
205
+ def calculate_weight(context, item)
206
+ weight = item["weight"]
207
+ if weight == "*"
208
+ reference = item["segments"]&.find { |s| s["type"] == "reference" }
209
+ key = reference&.fetch("text")
210
+ weight = lookup_and_count_items(context, key)
211
+ end
212
+
213
+ weight.to_i < 1 ? 1 : weight.to_i
214
+ end
215
+
216
+ def lookup_and_count_items(context, key)
217
+ return 0 unless key
218
+
219
+ builder = context.store.fetch(key)
220
+ return 0 unless builder
221
+
222
+ builder["items"]&.size || 1
223
+ end
224
+
225
+ def calculate_total_weight(context, items)
226
+ sum = 0
227
+ items.each do |item|
228
+ weight = calculate_weight(context, item)
229
+ item["weight"] = weight
230
+ sum += weight
231
+ end
232
+ sum
233
+ end
234
+
204
235
  def random_from_dice(text)
205
236
  rolled = DiceNomShim.roll(text)
206
237
  parsed = JSON.parse(rolled).first["lhs"]
@@ -6,6 +6,7 @@ module Text
6
6
  # to save time on database lookups or transformations.
7
7
  class Store
8
8
  NOT_FOUND_BUILDER = {
9
+ "strategy" => "sample",
9
10
  "filters" => [],
10
11
  "meta" => {},
11
12
  "items" => []
@@ -33,12 +34,30 @@ module Text
33
34
  builder = find(key)
34
35
  return builder if builder
35
36
 
36
- builder = @lookup.call(key)
37
- return not_found(key) unless builder
37
+ keys = key.split("+")
38
+ builders = keys.map do |key|
39
+ builder = @lookup.call(key)
40
+ builder = not_found(key) unless builder
41
+ builder
42
+ end
38
43
 
44
+ builder = merge_builders(builders) if builders.length > 1
39
45
  add(key, builder.merge("key" => key.to_s.downcase))
40
46
  end
41
47
 
48
+ def merge_builders(builders)
49
+ all_filters = builders.map { |b| b["filters"] }.flatten
50
+ all_meta = builders.inject({}) { |b, acc| acc = Text::Gen::Meta.merge_meta(acc, b["meta"]) }
51
+ all_items = builders.map { |b| b["items"] }.flatten
52
+ strategy = builders.all? {|b| b["strategy"] == "weighted" } ? "weighted" : "sample"
53
+ {
54
+ "strategy" => strategy,
55
+ "filters" => all_filters,
56
+ "meta" => all_meta,
57
+ "items" => all_items,
58
+ }
59
+ end
60
+
42
61
  def not_found(key)
43
62
  hsh = NOT_FOUND_BUILDER.dup
44
63
  hsh["key"] = key
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Text
4
4
  module Gen
5
- VERSION = "0.12.6"
5
+ VERSION = "0.13.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.12.6
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - G Palmer