ehbrs_ruby_utils 0.38.0 → 0.39.0

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: 375d67ec113f9773d1c7f89211884746357a5a56078b21d4f3dd0780385f87ac
4
- data.tar.gz: fc600162f063b6c2bcd529876687422d62abcb2b663f0903f234b1724c7147a5
3
+ metadata.gz: '089b6f1fa3dd8f8ce4ba9414e089d522d2e9eaaf78f6a6004c323c31392639aa'
4
+ data.tar.gz: 811149efacf1d16ce127eb68acc18ce078c4ea066276d321e0c176590690be06
5
5
  SHA512:
6
- metadata.gz: 3e5e2d657e5fec5a8938a70cb69616572dea93bfbce5b855f5e34f8b2d9d621a6cf0de651cec2420873fd437997e0ee146d67bcbffbcaf0f35df6174cb51c66b
7
- data.tar.gz: c23ae3131b15e9f96d8b59072950b916e36e52b4cfdf60c32498becc377d666acaefcd7e6a82f91c693bdb33bf689a3248f78af0057c2482b87bc085449ed550
6
+ metadata.gz: 9d4dab607225cf32244eabd21352ca551251ddd41bc789a46dc6bab10d2d298371d3dcb727acb2c1defb299409f1ccda2adf43f7213529d48267bd5cd636d815
7
+ data.tar.gz: 8fb1e6240cd3985f8b78b6932d778578dc3e88777561eb0f26bdc168195450ebaf1b3859a04f943558474cd7645baa483fbe9837d5ffa05cee93bc25375fb8e0
@@ -5,7 +5,7 @@ require 'eac_ruby_utils/core_ext'
5
5
  module EhbrsRubyUtils
6
6
  module Bga
7
7
  class Game
8
- common_constructor :code
8
+ common_constructor :code, :name
9
9
 
10
10
  # @param suffix [String]
11
11
  # @return [EhbrsRubyUtils::Bga::Game::Image]
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module EhbrsRubyUtils
6
+ module Bga
7
+ class GameStatistics
8
+ class WhatsappFormatter
9
+ class PlayerContent
10
+ acts_as_instance_method
11
+ common_constructor :formatter, :player
12
+
13
+ # @return [Hash<String, String>]
14
+ def result
15
+ formatter.ranks.to_h do |rank|
16
+ [rank_label(rank), rank_value(rank)]
17
+ end
18
+ end
19
+
20
+ # @param rank [Integer]
21
+ # @return [String]
22
+ def rank_label(rank)
23
+ "#{rank}º"
24
+ end
25
+
26
+ # @param rank [Integer]
27
+ # @return [String]
28
+ def rank_value(rank)
29
+ count = 0
30
+ formatter.normal_tables.each do |table|
31
+ count += 1 if table.player_by_id(player.id).if_present(false) do |v|
32
+ v.rank == rank
33
+ end
34
+ end
35
+ "#{count} (#{rank_percent(count)}%)"
36
+ end
37
+
38
+ # @param count [Integer]
39
+ # @return [String]
40
+ def rank_percent(count)
41
+ (count * 100 / formatter.normal_tables.count).round
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module EhbrsRubyUtils
6
+ module Bga
7
+ class GameStatistics
8
+ class WhatsappFormatter
9
+ class PlayerTitle
10
+ acts_as_instance_method
11
+ common_constructor :formatter, :player
12
+
13
+ # @return [String]
14
+ def result
15
+ username_by_tables || player.name
16
+ end
17
+
18
+ # @return [String, nil]
19
+ def username_by_tables
20
+ formatter.game_tables.lazy.map { |table| username_by_table(table) }.find(&:present?)
21
+ end
22
+
23
+ # @param table [EhbrsRubyUtils::Bga::Table]
24
+ # @return [String, nil]
25
+ def username_by_table(table)
26
+ table.player_by_id(player.id).if_present(&:name)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+ require 'ehbrs_ruby_utils/bga/whatsapp_formatter'
5
+
6
+ module EhbrsRubyUtils
7
+ module Bga
8
+ class GameStatistics
9
+ class WhatsappFormatter
10
+ include ::EhbrsRubyUtils::Bga::WhatsappFormatter
11
+
12
+ ROOT_TITLE = 'Estatísticas'
13
+ TITLE_ICON = 0x1F4CA.chr(::Encoding::UTF_8)
14
+
15
+ enable_simple_cache
16
+ common_constructor :game_statistics
17
+ delegate :game, :game_tables, :players, :until_table, to: :game_statistics
18
+
19
+ # @return [Integer]
20
+ def friendly_tables_count
21
+ game_tables.count - normal_tables.count
22
+ end
23
+
24
+ # @return [Hash]
25
+ def root_content
26
+ r = { 'Jogo' => game.name, 'Mesas normais' => normal_tables.count,
27
+ 'Mesas amigáveis' => friendly_tables_count }
28
+ until_table.if_present { |v| r['Após mesa'] = v.url }
29
+ r
30
+ end
31
+
32
+ # @return [Hash<String, String>] "title" => "content"
33
+ def sections
34
+ r = { ROOT_TITLE => root_content }
35
+ players.each do |player|
36
+ r[player_title(player)] = player_content(player)
37
+ end
38
+ r
39
+ end
40
+
41
+ # @return [String]
42
+ def title_icon
43
+ TITLE_ICON
44
+ end
45
+
46
+ private
47
+
48
+ # @return [Enumerable<EhbrsRubyUtils::Bga::Table>]
49
+ def normal_tables_uncached
50
+ with_players_tables.reject(&:friendly?)
51
+ end
52
+
53
+ # @param table [EhbrsRubyUtils::Bga::Table]
54
+ # @return [Boolean]
55
+ def with_players_table?(table)
56
+ table.players.count == players.count &&
57
+ players.all? { |player| table.player_by_id(player.id).present? }
58
+ end
59
+
60
+ # @return [Enumerable<EhbrsRubyUtils::Bga::Table>]
61
+ def with_players_tables_uncached
62
+ game_tables.select { |table| with_players_table?(table) }
63
+ end
64
+
65
+ # @return [Array<Integer>]
66
+ def ranks_uncached
67
+ r = ::Set.new
68
+ normal_tables.each do |table|
69
+ table.players.each do |player|
70
+ r.add(player.rank)
71
+ end
72
+ end
73
+ r.sort
74
+ end
75
+
76
+ require_sub __FILE__, require_mode: :kernel
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module EhbrsRubyUtils
6
+ module Bga
7
+ class GameStatistics
8
+ common_constructor :game, :game_tables, :players, :until_table, default: [nil]
9
+
10
+ require_sub __FILE__
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ehbrs_ruby_utils/bga/parsers/table/active_players'
4
+ require 'eac_ruby_utils/core_ext'
5
+
6
+ module EhbrsRubyUtils
7
+ module Bga
8
+ class Player
9
+ common_constructor :data
10
+
11
+ ::EhbrsRubyUtils::Bga::Parsers::Table::ActivePlayers.fields.map(&:name).each do |field|
12
+ define_method field do
13
+ data.fetch(field)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'eac_ruby_utils/core_ext'
4
+ require 'ehbrs_ruby_utils/bga/whatsapp_formatter/option'
4
5
 
5
6
  module EhbrsRubyUtils
6
7
  module Bga
@@ -11,8 +12,9 @@ module EhbrsRubyUtils
11
12
  acts_as_instance_method
12
13
  common_constructor :table_formatter, :option
13
14
 
15
+ # @return [String]
14
16
  def result
15
- "*#{option.label}:* #{option.value}"
17
+ ::EhbrsRubyUtils::Bga::WhatsappFormatter::Option.assert(option).to_s
16
18
  end
17
19
  end
18
20
  end
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'eac_ruby_utils/core_ext'
4
+ require 'ehbrs_ruby_utils/bga/whatsapp_formatter'
4
5
 
5
6
  module EhbrsRubyUtils
6
7
  module Bga
7
8
  class Table
8
9
  module WhatsappFormatters
9
10
  class Base
10
- acts_as_abstract :players_title, :root_items_title, :title_icon
11
+ include ::EhbrsRubyUtils::Bga::WhatsappFormatter
12
+ acts_as_abstract :players_title, :root_items_title
11
13
  enable_simple_cache
12
14
  common_constructor :table
13
15
 
@@ -18,24 +20,21 @@ module EhbrsRubyUtils
18
20
  'Duração' => :estimated_duration,
19
21
  'Endereço' => :url
20
22
  }.freeze
21
- SECTION_SEPARATOR = "\n\n"
22
23
 
23
- # @return [Pathname]
24
- def image_local_path
25
- table.game.box_large_image.local_path
26
- end
27
-
28
- def to_s
29
- [root_items_to_s, players_to_s, options_to_s].map(&:strip).join(SECTION_SEPARATOR)
30
- end
24
+ delegate :game, to: :table
31
25
 
32
- def root_items_to_s
33
- title_to_s(root_items_title) + ROOT_ITENS.map { |k, v| "*#{k}*: #{table.send(v)}" }
34
- .join("\n")
26
+ # @return [Hash<String, String>] "title" => "content"
27
+ def sections
28
+ {
29
+ root_items_title => root_items,
30
+ players_title => players_to_s,
31
+ 'Opções' => options
32
+ }
35
33
  end
36
34
 
37
- def options_to_s
38
- title_to_s('Opções') + options.join("\n")
35
+ # @return [Hash]
36
+ def root_items
37
+ ROOT_ITENS.transform_values { |v| table.send(v) }
39
38
  end
40
39
 
41
40
  # @return [String]
@@ -45,11 +44,7 @@ module EhbrsRubyUtils
45
44
 
46
45
  # @return [String]
47
46
  def players_to_s
48
- title_to_s(players_title) + players_extra + players.join("\n")
49
- end
50
-
51
- def title_to_s(title)
52
- "*#{[title_icon, title, title_icon].join(' ')}*\n\n"
47
+ players_extra + players.join("\n")
53
48
  end
54
49
 
55
50
  def players
@@ -13,6 +13,9 @@ module EhbrsRubyUtils
13
13
  enable_simple_cache
14
14
  common_constructor :data
15
15
 
16
+ GAME_MODE_KEY = 'Modo de Jogo'
17
+ GAME_MODE_FRIENDLY_VALUE = 'Modo Amigável'
18
+ GAME_MODE_NORMAL_VALUE = 'Modo Normal'
16
19
  SET_ITEMS = %i[options players].freeze
17
20
 
18
21
  ([:id] + ::EhbrsRubyUtils::Bga::Parsers::Table.fields.map(&:name) - SET_ITEMS)
@@ -22,11 +25,32 @@ module EhbrsRubyUtils
22
25
  end
23
26
  end
24
27
 
28
+ # @return [Boolean]
29
+ def friendly?
30
+ value = option_value(GAME_MODE_KEY)
31
+ return true if value == GAME_MODE_FRIENDLY_VALUE
32
+ return false if value == GAME_MODE_NORMAL_VALUE
33
+
34
+ raise "Unknown \"#{GAME_MODE_KEY}\" value: \"#{value}\""
35
+ end
36
+
25
37
  # @return [Boolean]
26
38
  def game_conceded?
27
39
  game_conceded
28
40
  end
29
41
 
42
+ # @param key [String]
43
+ # @return [String, nil]
44
+ def option_value(label)
45
+ options.find { |o| o.label == label }.if_present(&:value)
46
+ end
47
+
48
+ # @param id [Integer]
49
+ # @return [EhbrsRubyUtils::Bga::Table::Player, nil]
50
+ def player_by_id(id)
51
+ players.find { |p| p.id.to_s == id.to_s }
52
+ end
53
+
30
54
  # @return [Addressable::URI]
31
55
  def url
32
56
  table_url(id)
@@ -36,7 +60,7 @@ module EhbrsRubyUtils
36
60
 
37
61
  # @return [EhbrsRubyUtils::Bga::Game]
38
62
  def game_uncached
39
- ::EhbrsRubyUtils::Bga::Game.new(game_code)
63
+ ::EhbrsRubyUtils::Bga::Game.new(game_code, game_name)
40
64
  end
41
65
 
42
66
  SET_ITEMS.each do |item|
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module EhbrsRubyUtils
6
+ module Bga
7
+ module WhatsappFormatter
8
+ class Option
9
+ class << self
10
+ # @param obj [Object]
11
+ # @return [EhbrsRubyUtils::Bga::WhatsappFormatter::Option]
12
+ def assert(obj)
13
+ return obj if obj.is_a?(self)
14
+ return new(obj.label, obj.value) if obj.respond_to?(:label) && obj.respond_to?(:value)
15
+ return new(obj.fetch(:label), obj.fetch(:value)) if obj.is_a?(::Hash)
16
+ return new(*obj) if obj.is_a?(::Enumerable)
17
+
18
+ raise(::ArgumentError, "\"#{obj}\" não pôde ser convertido para #{self}")
19
+ end
20
+ end
21
+
22
+ common_constructor :label, :value
23
+
24
+ # @return [String]
25
+ def to_s
26
+ "*#{label}:* #{value}"
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module EhbrsRubyUtils
6
+ module Bga
7
+ module WhatsappFormatter
8
+ common_concern do
9
+ acts_as_abstract
10
+ end
11
+
12
+ LINE_SEPARATOR = "\n"
13
+ OPTION_SEPARATOR = LINE_SEPARATOR
14
+ SECTION_SEPARATOR = "#{LINE_SEPARATOR}#{LINE_SEPARATOR}"
15
+
16
+ # @param content [String, Enumerable]
17
+ # @return [String]
18
+ def content_to_s(content)
19
+ if content.is_a?(::Hash)
20
+ content_to_s(
21
+ content.map { |k, v| ::EhbrsRubyUtils::Bga::WhatsappFormatter::Option.new(k, v) }
22
+ )
23
+ elsif content.is_a?(::Enumerable)
24
+ content.to_a.join(OPTION_SEPARATOR)
25
+ else
26
+ content.to_s
27
+ end
28
+ end
29
+
30
+ # @return [EhbrsRubyUtils::Bga::Game]
31
+ def game
32
+ raise_abstract_method __method__
33
+ end
34
+
35
+ # @return [Pathname]
36
+ def image_local_path
37
+ game.box_large_image.local_path
38
+ end
39
+
40
+ # @param options [Enumerable<EhbrsRubyUtils::Bga::WhatsappFormatters::Option>]
41
+ # @return [String]
42
+ def options_to_s(options)
43
+ options.map { |o| "#{o}#{OPTION_SEPARATOR}" }
44
+ end
45
+
46
+ # @param title {String]
47
+ # @param content {String]
48
+ # @return [String]
49
+ def section_to_s(title, content)
50
+ [title_to_s(title), content_to_s(content)].map(&:strip).join(SECTION_SEPARATOR)
51
+ end
52
+
53
+ # @return [Hash<String, String>] "title" => "content"
54
+ def sections
55
+ raise_abstract_method __method__
56
+ end
57
+
58
+ # @return [String]
59
+ def title_icon
60
+ raise_abstract_method __method__
61
+ end
62
+
63
+ def to_s
64
+ sections.map { |title, content| section_to_s(title, content) }.join(SECTION_SEPARATOR)
65
+ end
66
+
67
+ def title_to_s(title)
68
+ "*#{[title_icon, title, title_icon].join(' ')}*"
69
+ end
70
+ end
71
+ end
72
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'ehbrs_ruby_utils/bga/session'
4
+ require 'ehbrs_ruby_utils/bga/game_statistics/whatsapp_formatter'
4
5
  require 'ehbrs_ruby_utils/executables'
5
6
  require 'ehbrs_ruby_utils/mudslide/message'
6
7
  require 'eac_ruby_utils/core_ext'
@@ -15,12 +16,21 @@ module EhbrsRubyUtils
15
16
  # @param table [EhbrsRubyUtils::Bga::Table]
16
17
  # @return [void]
17
18
  define_method "bga_table_#{type}_notify" do |table|
18
- formatter = ::EhbrsRubyUtils::Bga::Table::WhatsappFormatters.const_get(type.camelize)
19
- .new(table)
20
- whatsapp_send(formatter.to_s, formatter.image_local_path)
19
+ whatsapp_formatter_send(
20
+ ::EhbrsRubyUtils::Bga::Table::WhatsappFormatters.const_get(type.camelize),
21
+ table
22
+ )
21
23
  end
22
24
  end
23
25
 
26
+ # @param game_statistics [EhbrsRubyUtils::Bga::GameStatistics]
27
+ # @return [void]
28
+ def bga_game_statistics_notify(game_statistics)
29
+ whatsapp_formatter_send(
30
+ ::EhbrsRubyUtils::Bga::GameStatistics::WhatsappFormatter, game_statistics
31
+ )
32
+ end
33
+
24
34
  def on_bga_logged_session(&block)
25
35
  bga_session = new_bga_session
26
36
  begin
@@ -49,6 +59,12 @@ module EhbrsRubyUtils
49
59
  def mudslide_run(*args)
50
60
  ::EhbrsRubyUtils::Executables.mudslide.command(*args).system!
51
61
  end
62
+
63
+ # @return [void]
64
+ def whatsapp_formatter_send(formatter_class, formatter_owner)
65
+ formatter = formatter_class.new(formatter_owner)
66
+ whatsapp_send(formatter.to_s, formatter.image_local_path)
67
+ end
52
68
  end
53
69
  end
54
70
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EhbrsRubyUtils
4
- VERSION = '0.38.0'
4
+ VERSION = '0.39.0'
5
5
  end
@@ -9,7 +9,7 @@ module EhbrsRubyUtils
9
9
  module Rename
10
10
  class ResultsBuilder < LineResultGroup
11
11
  def initialize(files)
12
- super '', files
12
+ super('', files)
13
13
  end
14
14
 
15
15
  def line_out
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ehbrs_ruby_utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.38.0
4
+ version: 0.39.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eduardo H. Bogoni
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-26 00:00:00.000000000 Z
11
+ date: 2024-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aranha
@@ -50,14 +50,14 @@ dependencies:
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '0.7'
53
+ version: '0.8'
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '0.7'
60
+ version: '0.8'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: avm
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: '3.5'
88
88
  - - ">="
89
89
  - !ruby/object:Gem::Version
90
- version: 3.5.1
90
+ version: 3.5.2
91
91
  type: :runtime
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
@@ -97,35 +97,35 @@ dependencies:
97
97
  version: '3.5'
98
98
  - - ">="
99
99
  - !ruby/object:Gem::Version
100
- version: 3.5.1
100
+ version: 3.5.2
101
101
  - !ruby/object:Gem::Dependency
102
102
  name: eac_fs
103
103
  requirement: !ruby/object:Gem::Requirement
104
104
  requirements:
105
105
  - - "~>"
106
106
  - !ruby/object:Gem::Version
107
- version: '0.16'
107
+ version: '0.17'
108
108
  type: :runtime
109
109
  prerelease: false
110
110
  version_requirements: !ruby/object:Gem::Requirement
111
111
  requirements:
112
112
  - - "~>"
113
113
  - !ruby/object:Gem::Version
114
- version: '0.16'
114
+ version: '0.17'
115
115
  - !ruby/object:Gem::Dependency
116
116
  name: eac_rest
117
117
  requirement: !ruby/object:Gem::Requirement
118
118
  requirements:
119
119
  - - "~>"
120
120
  - !ruby/object:Gem::Version
121
- version: '0.10'
121
+ version: '0.12'
122
122
  type: :runtime
123
123
  prerelease: false
124
124
  version_requirements: !ruby/object:Gem::Requirement
125
125
  requirements:
126
126
  - - "~>"
127
127
  - !ruby/object:Gem::Version
128
- version: '0.10'
128
+ version: '0.12'
129
129
  - !ruby/object:Gem::Dependency
130
130
  name: eac_ruby_utils
131
131
  requirement: !ruby/object:Gem::Requirement
@@ -252,6 +252,10 @@ files:
252
252
  - lib/ehbrs_ruby_utils/bga.rb
253
253
  - lib/ehbrs_ruby_utils/bga/game.rb
254
254
  - lib/ehbrs_ruby_utils/bga/game/image.rb
255
+ - lib/ehbrs_ruby_utils/bga/game_statistics.rb
256
+ - lib/ehbrs_ruby_utils/bga/game_statistics/whatsapp_formatter.rb
257
+ - lib/ehbrs_ruby_utils/bga/game_statistics/whatsapp_formatter/player_content.rb
258
+ - lib/ehbrs_ruby_utils/bga/game_statistics/whatsapp_formatter/player_title.rb
255
259
  - lib/ehbrs_ruby_utils/bga/parsers/game_in_progress.rb
256
260
  - lib/ehbrs_ruby_utils/bga/parsers/game_stats.rb
257
261
  - lib/ehbrs_ruby_utils/bga/parsers/game_stats/players.rb
@@ -259,6 +263,7 @@ files:
259
263
  - lib/ehbrs_ruby_utils/bga/parsers/table/active_players.rb
260
264
  - lib/ehbrs_ruby_utils/bga/parsers/table/ended_players.rb
261
265
  - lib/ehbrs_ruby_utils/bga/parsers/table/options.rb
266
+ - lib/ehbrs_ruby_utils/bga/player.rb
262
267
  - lib/ehbrs_ruby_utils/bga/session.rb
263
268
  - lib/ehbrs_ruby_utils/bga/session/login.rb
264
269
  - lib/ehbrs_ruby_utils/bga/session/player.rb
@@ -279,6 +284,8 @@ files:
279
284
  - lib/ehbrs_ruby_utils/bga/table/whatsapp_formatters/ending.rb
280
285
  - lib/ehbrs_ruby_utils/bga/table/whatsapp_formatters/ending/format_player.rb
281
286
  - lib/ehbrs_ruby_utils/bga/urls.rb
287
+ - lib/ehbrs_ruby_utils/bga/whatsapp_formatter.rb
288
+ - lib/ehbrs_ruby_utils/bga/whatsapp_formatter/option.rb
282
289
  - lib/ehbrs_ruby_utils/circular_list_spreader.rb
283
290
  - lib/ehbrs_ruby_utils/circular_list_spreader/base_level.rb
284
291
  - lib/ehbrs_ruby_utils/circular_list_spreader/group_level.rb