type_balancer 0.1.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.
@@ -0,0 +1,85 @@
1
+ module TypeBalancer
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+
5
+ class Error < StandardError
6
+ end
7
+
8
+ class ConfigurationError < Error
9
+ end
10
+
11
+ class ValidationError < Error
12
+ end
13
+
14
+ # Main class responsible for balancing items in a collection based on their types
15
+ class Balancer
16
+ def initialize: (Array[untyped] collection, ?type_field: Symbol | String, ?types: Array[String]?) -> void
17
+ def call: -> Array[untyped]
18
+
19
+ private
20
+ def calculate_ratios: (Hash[String, Array[untyped]] items_by_type) -> Array[Float]
21
+ def get_type: (untyped item) -> String
22
+ def extract_types: -> Array[String]
23
+ end
24
+
25
+ module Ruby
26
+ class Calculator
27
+ def self.calculate_positions: (total_count: Integer, ratio: Float, ?available_items: Array[Integer]?) -> Array[Integer]
28
+
29
+ private
30
+ def self.validate_inputs: (Integer total_count, Float ratio) -> void
31
+ def self.validate_available_items: (Array[Integer]? available_items, Integer total_count) -> void
32
+ def self.calculate_positions_without_available: (Integer total_count, Integer target_count) -> Array[Integer]
33
+ def self.calculate_positions_with_available: (Integer total_count, Integer target_count, Array[Integer] available_items) -> Array[Integer]
34
+ end
35
+
36
+ class BatchCalculator
37
+ class PositionBatch
38
+ attr_reader total_count: Integer
39
+ attr_reader available_count: Integer
40
+ attr_reader ratio: Float
41
+
42
+ def initialize: (total_count: Integer, available_count: Integer, ratio: Float) -> void
43
+ def valid?: -> bool
44
+ end
45
+
46
+ def self.calculate_positions_batch: (PositionBatch batch, ?Integer iterations) -> Array[Integer]
47
+ private
48
+ def self.calculate_target_count: (PositionBatch batch) -> Integer
49
+ end
50
+ end
51
+
52
+ class OrderedCollectionManager
53
+ def initialize: (Integer size) -> void
54
+ def place_at_positions: (Array[untyped] items, Array[Integer] positions) -> void
55
+ def fill_gaps_alternating: (Array[untyped] primary_items, Array[untyped] secondary_items) -> void
56
+ def fill_remaining_gaps: (Array[Array[untyped]] items_arrays) -> void
57
+ def result: -> Array[untyped]
58
+ private
59
+ def find_empty_positions: -> Array[Integer]
60
+ end
61
+
62
+ class SequentialFiller
63
+ def initialize: (Array[untyped] collection, Array[Array[untyped]] items_arrays) -> void
64
+ def self.fill: (Array[untyped] collection, Array[Integer] positions, Array[Array[untyped]] items_arrays) -> void
65
+ def fill_gaps: (Array[Integer] positions) -> void
66
+ end
67
+
68
+ class AlternatingFiller
69
+ def initialize: (Array[untyped] collection, Array[untyped] primary_items, Array[untyped] secondary_items) -> void
70
+ def self.fill: (Array[untyped] collection, Array[Integer] positions, Array[untyped] primary_items, Array[untyped] secondary_items) -> void
71
+ def fill_gaps: (Array[Integer] positions) -> void
72
+ end
73
+
74
+ class DistributionCalculator
75
+ def initialize: (?Float target_ratio) -> void
76
+ def calculate_target_positions: (Integer total_count, Integer available_items_count, ?Float target_ratio) -> Array[Integer]
77
+ end
78
+
79
+ module Distributor
80
+ def self.calculate_target_positions: (Integer total_count, Integer available_count, Float ratio) -> Array[Integer]
81
+ end
82
+
83
+ def self.balance: (Array[untyped] collection, ?type_field: Symbol | String, ?type_order: Array[String]?) -> Array[untyped]
84
+ def self.extract_types: (Array[untyped] collection, Symbol | String type_field) -> Array[String]
85
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/type_balancer/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'type_balancer'
7
+ spec.version = TypeBalancer::VERSION
8
+ spec.authors = ['Carl Smith']
9
+ spec.email = ['carl@llweb.biz']
10
+
11
+ spec.summary = 'Balances types in collections'
12
+ spec.description = 'Balances types in collections by ensuring each type appears a similar number of times'
13
+ spec.homepage = 'https://github.com/llwebconsulting/type_balancer'
14
+ spec.license = 'MIT'
15
+ spec.required_ruby_version = '>= 3.2.0'
16
+
17
+ spec.metadata['homepage_uri'] = spec.homepage
18
+ spec.metadata['source_code_uri'] = 'https://github.com/llwebconsulting/type_balancer'
19
+ spec.metadata['changelog_uri'] = 'https://github.com/llwebconsulting/type_balancer/blob/main/CHANGELOG.md'
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(__dir__) do
24
+ `git ls-files -z`.split("\x0").reject do |f|
25
+ (File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor ext/
26
+ c_tests/])
27
+ end
28
+ end
29
+ spec.bindir = 'exe'
30
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ['lib']
32
+ spec.metadata['rubygems_mfa_required'] = 'true'
33
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: type_balancer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Carl Smith
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 2025-04-10 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: Balances types in collections by ensuring each type appears a similar
13
+ number of times
14
+ email:
15
+ - carl@llweb.biz
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".rubocop.yml"
21
+ - ".ruby-version"
22
+ - CHANGELOG.md
23
+ - Dockerfile
24
+ - Gemfile
25
+ - Gemfile.lock
26
+ - LICENSE.txt
27
+ - README.md
28
+ - Rakefile
29
+ - benchmark/README.md
30
+ - benchmark/end_to_end_benchmark.rb
31
+ - benchmark/quick_benchmark.rb
32
+ - benchmark_output.log
33
+ - benchmark_results/ruby3.2.8.txt
34
+ - benchmark_results/ruby3.2.8_yjit.txt
35
+ - benchmark_results/ruby3.3.7.txt
36
+ - benchmark_results/ruby3.3.7_yjit.txt
37
+ - benchmark_results/ruby3.4.2.txt
38
+ - benchmark_results/ruby3.4.2_yjit.txt
39
+ - docs/benchmarks/README.md
40
+ - examples/quality.rb
41
+ - lib/type_balancer.rb
42
+ - lib/type_balancer/alternating_filler.rb
43
+ - lib/type_balancer/balancer.rb
44
+ - lib/type_balancer/calculator.rb
45
+ - lib/type_balancer/distribution_calculator.rb
46
+ - lib/type_balancer/distributor.rb
47
+ - lib/type_balancer/ordered_collection_manager.rb
48
+ - lib/type_balancer/sequential_filler.rb
49
+ - lib/type_balancer/version.rb
50
+ - sig/type_balancer.rbs
51
+ - type_balancer.gemspec
52
+ homepage: https://github.com/llwebconsulting/type_balancer
53
+ licenses:
54
+ - MIT
55
+ metadata:
56
+ homepage_uri: https://github.com/llwebconsulting/type_balancer
57
+ source_code_uri: https://github.com/llwebconsulting/type_balancer
58
+ changelog_uri: https://github.com/llwebconsulting/type_balancer/blob/main/CHANGELOG.md
59
+ rubygems_mfa_required: 'true'
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 3.2.0
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubygems_version: 3.6.2
75
+ specification_version: 4
76
+ summary: Balances types in collections
77
+ test_files: []