type_balancer 0.1.0 → 0.1.3

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.
@@ -2,16 +2,16 @@
2
2
  + bundle exec ruby -I lib benchmark/end_to_end_benchmark.rb
3
3
  Ruby version: 3.4.2
4
4
  RUBY_PLATFORM: aarch64-linux
5
- YJIT enabled: false
5
+ YJIT enabled: true
6
6
 
7
7
  Running benchmarks...
8
8
 
9
9
  Benchmarking Tiny Dataset (10 items)
10
- ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [aarch64-linux]
10
+ ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +YJIT +PRISM [aarch64-linux]
11
11
  Warming up --------------------------------------
12
- Ruby Implementation 6.784k i/100ms
12
+ Ruby Implementation 15.310k i/100ms
13
13
  Calculating -------------------------------------
14
- Ruby Implementation 66.579k 4.7%) i/s (15.02 μs/i) - 135.680k in 2.042522s
14
+ Ruby Implementation 152.742k10.9%) i/s (6.55 μs/i) - 306.200k in 2.025235s
15
15
 
16
16
  Distribution Stats:
17
17
  Video: 4 (40.0%)
@@ -19,11 +19,11 @@ Image: 3 (30.0%)
19
19
  Article: 3 (30.0%)
20
20
 
21
21
  Benchmarking Small Dataset (100 items)
22
- ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [aarch64-linux]
22
+ ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +YJIT +PRISM [aarch64-linux]
23
23
  Warming up --------------------------------------
24
- Ruby Implementation 168.000 i/100ms
24
+ Ruby Implementation 2.912k i/100ms
25
25
  Calculating -------------------------------------
26
- Ruby Implementation 1.768k (± 6.2%) i/s (565.69 μs/i) - 3.528k in 2.003878s
26
+ Ruby Implementation 32.388k (± 6.8%) i/s (30.88 μs/i) - 66.976k in 2.077301s
27
27
 
28
28
  Distribution Stats:
29
29
  Video: 34 (34.0%)
@@ -31,11 +31,11 @@ Image: 33 (33.0%)
31
31
  Article: 33 (33.0%)
32
32
 
33
33
  Benchmarking Medium Dataset (1000 items)
34
- ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [aarch64-linux]
34
+ ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +YJIT +PRISM [aarch64-linux]
35
35
  Warming up --------------------------------------
36
- Ruby Implementation 1.000 i/100ms
36
+ Ruby Implementation 368.000 i/100ms
37
37
  Calculating -------------------------------------
38
- Ruby Implementation 19.919 5.0%) i/s (50.20 ms/i) - 60.000 in 3.023325s
38
+ Ruby Implementation 3.646k14.2%) i/s (274.30 μs/i) - 10.672k in 3.009052s
39
39
 
40
40
  Distribution Stats:
41
41
  Video: 334 (33.4%)
@@ -43,11 +43,11 @@ Image: 333 (33.3%)
43
43
  Article: 333 (33.3%)
44
44
 
45
45
  Benchmarking Large Dataset (10000 items)
46
- ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [aarch64-linux]
46
+ ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +YJIT +PRISM [aarch64-linux]
47
47
  Warming up --------------------------------------
48
- Ruby Implementation 1.000 i/100ms
48
+ Ruby Implementation 42.000 i/100ms
49
49
  Calculating -------------------------------------
50
- Ruby Implementation 0.2120.0%) i/s (4.71 s/i) - 1.000 in 4.706258s
50
+ Ruby Implementation 424.2615.2%) i/s (2.36 ms/i) - 1.302k in 3.077566s
51
51
 
52
52
  Distribution Stats:
53
53
  Video: 3334 (33.34%)
data/docs/README.md ADDED
@@ -0,0 +1,8 @@
1
+ # Documentation Index
2
+
3
+ Welcome to the TypeBalancer documentation! Below you'll find links to all major documentation resources for the gem.
4
+
5
+ - [Quality Script](quality.md): Integration and example script for verifying gem functionality, with instructions for running locally or from other projects.
6
+ - [Balance Method Details](balance.md): In-depth documentation for the `TypeBalancer.balance` method, including arguments, usage, and edge cases.
7
+ - [Calculate Positions Method Details](calculate_positions.md): Detailed documentation for `TypeBalancer.calculate_positions`, with examples and caveats.
8
+ - [Benchmarks](benchmarks/README.md): Performance metrics and benchmarking methodology for the gem.
data/docs/balance.md ADDED
@@ -0,0 +1,71 @@
1
+ # Detailed Documentation: `TypeBalancer.balance`
2
+
3
+ `TypeBalancer.balance` is the main method for distributing items of different types across a sequence, ensuring optimal spacing and respecting type ratios. It is highly configurable and supports custom type fields and type orderings.
4
+
5
+ ## Method Signature
6
+
7
+ ```ruby
8
+ TypeBalancer.balance(items, type_field: :type, type_order: nil)
9
+ ```
10
+
11
+ ### Arguments
12
+ - `items` (Array<Hash>): The collection of items to balance. Each item should have a type field (default: `:type`).
13
+ - `type_field` (Symbol/String, optional): The key to use for extracting the type from each item. Default is `:type`.
14
+ - `type_order` (Array<String>, optional): An array specifying the desired order of types in the output. If omitted, the gem determines the order automatically.
15
+
16
+ ## Return Value
17
+ - Returns a new array of items, balanced by type and spaced as evenly as possible.
18
+ - The output array will have the same length as the input.
19
+
20
+ ## Usage Examples
21
+
22
+ ### 1. Basic Balancing
23
+ ```ruby
24
+ items = [
25
+ { type: 'video', title: 'Video 1' },
26
+ { type: 'image', title: 'Image 1' },
27
+ { type: 'article', title: 'Article 1' },
28
+ { type: 'article', title: 'Article 2' },
29
+ { type: 'image', title: 'Image 2' },
30
+ { type: 'video', title: 'Video 2' }
31
+ ]
32
+ balanced = TypeBalancer.balance(items)
33
+ # => [ { type: 'article', ... }, { type: 'image', ... }, { type: 'video', ... }, ... ]
34
+ ```
35
+
36
+ ### 2. Custom Type Order
37
+ ```ruby
38
+ # Prioritize images, then videos, then articles
39
+ balanced = TypeBalancer.balance(items, type_order: %w[image video article])
40
+ # => [ { type: 'image', ... }, { type: 'video', ... }, { type: 'article', ... }, ... ]
41
+ ```
42
+
43
+ ### 3. Custom Type Field
44
+ ```ruby
45
+ items = [
46
+ { category: 'video', title: 'Video 1' },
47
+ { category: 'image', title: 'Image 1' },
48
+ { category: 'article', title: 'Article 1' }
49
+ ]
50
+ balanced = TypeBalancer.balance(items, type_field: :category)
51
+ # => [ { category: 'article', ... }, { category: 'image', ... }, { category: 'video', ... } ]
52
+ ```
53
+
54
+ ### 4. Handling Missing Types
55
+ If a type in `type_order` is not present in the input, it is simply ignored in the output order.
56
+
57
+ ### 5. Edge Cases
58
+ - **Empty Input:** Raises an exception (`Collection cannot be empty`).
59
+ - **Single Type:** All items are returned in their original order.
60
+ - **Missing Type Field:** If an item is missing the type field, it is ignored or may cause an error depending on context.
61
+
62
+ ## Notes and Caveats
63
+ - The method is deterministic: the same input will always produce the same output.
64
+ - The `type_order` argument must be an array of strings matching the type values in your items.
65
+ - If you use a custom `type_field`, ensure all items have that field.
66
+ - The method does not mutate the input array.
67
+
68
+ ## See Also
69
+ - [README.md](../README.md) for general usage
70
+ - [Quality Script Documentation](quality.md) for integration tests and examples
71
+ - [Detailed Position Calculation Documentation](calculate_positions.md)
@@ -21,27 +21,27 @@ Each benchmark test evaluates performance across different collection sizes, fro
21
21
  1. Tiny Dataset (Content Widget):
22
22
  - Total Items: 10
23
23
  - Distribution: Video (40%), Image (30%), Article (30%)
24
- - Processing Time: ~12 microseconds
24
+ - Processing Time: ~6-7 microseconds
25
25
 
26
26
  2. Small Dataset (Content Feed):
27
27
  - Total Items: 100
28
28
  - Distribution: Video (34%), Image (33%), Article (33%)
29
- - Processing Time: ~464 microseconds
29
+ - Processing Time: ~30-31 microseconds
30
30
 
31
31
  3. Medium Dataset (Category Page):
32
32
  - Total Items: 1,000
33
33
  - Distribution: Video (33.4%), Image (33.3%), Article (33.3%)
34
- - Processing Time: ~19 milliseconds
34
+ - Processing Time: ~274-280 microseconds
35
35
 
36
36
  4. Large Dataset (Site-wide Content):
37
37
  - Total Items: 10,000
38
38
  - Distribution: Video (33.34%), Image (33.33%), Article (33.33%)
39
- - Processing Time: ~191 milliseconds
39
+ - Processing Time: ~2.4-2.8 milliseconds
40
40
 
41
41
  ### Real-world Application
42
42
 
43
43
  TypeBalancer is designed for practical use in content management and display systems:
44
- - Process 10,000 items in under 200ms
44
+ - Process 10,000 items in under 3ms
45
45
  - Maintain perfect distribution ratios
46
46
  - Suitable for real-time web applications
47
47
  - Efficient enough for on-the-fly content organization
@@ -60,62 +60,69 @@ TypeBalancer is designed for practical use in content management and display sys
60
60
 
61
61
  | Metric | Tiny Dataset | Small Dataset | Medium Dataset | Large Dataset |
62
62
  |--------|--------------|---------------|----------------|---------------|
63
- | Speed (no YJIT) | 73.3K ops/sec | 2.0K ops/sec | 46.9 ops/sec | 4.8 ops/sec |
64
- | Speed (YJIT) | 102.0K ops/sec | 2.1K ops/sec | 46.2 ops/sec | 4.8 ops/sec |
65
- | Time/Op (no YJIT) | 13.63 μs | 494.84 μs | 21.34 ms | 207.62 ms |
66
- | Time/Op (YJIT) | 9.80 μs | 478.05 μs | 21.64 ms | 208.85 ms |
67
- | YJIT Impact | +39.1% | +3.5% | -1.4% | -0.6% |
68
- | Distribution Quality | Perfect | Excellent | Excellent | Excellent |
63
+ | Speed (no YJIT) | 109.0K ops/sec | 21.9K ops/sec | 2.0K ops/sec | 264 ops/sec |
64
+ | Speed (YJIT) | 152.7K ops/sec | 32.4K ops/sec | 3.6K ops/sec | 424 ops/sec |
65
+ | Time/Op (no YJIT) | 9.18 μs | 45.71 μs | 498.96 μs | 3.79 ms |
66
+ | Time/Op (YJIT) | 6.55 μs | 30.88 μs | 274.30 μs | 2.36 ms |
67
+ | YJIT Impact | +40.1% | +48.0% | +80.0% | +60.6% |
68
+ | Distribution Quality | Perfect | Excellent | Excellent | Perfect |
69
69
 
70
70
  ### Ruby 3.3.7 Performance
71
71
 
72
72
  | Metric | Tiny Dataset | Small Dataset | Medium Dataset | Large Dataset |
73
73
  |--------|--------------|---------------|----------------|---------------|
74
- | Speed (no YJIT) | 74.8K ops/sec | 2.1K ops/sec | 49.2 ops/sec | 5.1 ops/sec |
75
- | Speed (YJIT) | 108.1K ops/sec | 2.3K ops/sec | 48.8 ops/sec | 5.2 ops/sec |
76
- | Time/Op (no YJIT) | 13.37 μs | 477.95 μs | 20.34 ms | 196.05 ms |
77
- | Time/Op (YJIT) | 9.25 μs | 437.36 μs | 20.49 ms | 193.08 ms |
78
- | YJIT Impact | +44.5% | +9.3% | -0.7% | +1.5% |
79
- | Distribution Quality | Perfect | Excellent | Excellent | Excellent |
74
+ | Speed (no YJIT) | 102.4K ops/sec | 20.8K ops/sec | 1.9K ops/sec | 245 ops/sec |
75
+ | Speed (YJIT) | 148.2K ops/sec | 31.2K ops/sec | 3.5K ops/sec | 394 ops/sec |
76
+ | Time/Op (no YJIT) | 9.77 μs | 48.08 μs | 526.32 μs | 4.08 ms |
77
+ | Time/Op (YJIT) | 6.75 μs | 32.05 μs | 277.78 μs | 2.54 ms |
78
+ | YJIT Impact | +44.7% | +50.0% | +84.2% | +60.8% |
79
+ | Distribution Quality | Perfect | Excellent | Excellent | Perfect |
80
80
 
81
81
  ### Ruby 3.2.8 Performance
82
82
 
83
83
  | Metric | Tiny Dataset | Small Dataset | Medium Dataset | Large Dataset |
84
84
  |--------|--------------|---------------|----------------|---------------|
85
- | Speed (no YJIT) | 72.2K ops/sec | 2.2K ops/sec | 46.3 ops/sec | 4.7 ops/sec |
86
- | Speed (YJIT) | 108.8K ops/sec | 2.2K ops/sec | 47.3 ops/sec | 5.2 ops/sec |
87
- | Time/Op (no YJIT) | 13.86 μs | 451.35 μs | 21.59 ms | 215.04 ms |
88
- | Time/Op (YJIT) | 9.19 μs | 449.99 μs | 21.15 ms | 193.67 ms |
89
- | YJIT Impact | +50.8% | +0.3% | +2.1% | +11.0% |
90
- | Distribution Quality | Perfect | Excellent | Excellent | Excellent |
85
+ | Speed (no YJIT) | 98.7K ops/sec | 19.2K ops/sec | 1.8K ops/sec | 223 ops/sec |
86
+ | Speed (YJIT) | 142.8K ops/sec | 30.1K ops/sec | 3.4K ops/sec | 356 ops/sec |
87
+ | Time/Op (no YJIT) | 10.13 μs | 52.08 μs | 555.56 μs | 4.48 ms |
88
+ | Time/Op (YJIT) | 7.00 μs | 33.22 μs | 280.70 μs | 2.81 ms |
89
+ | YJIT Impact | +44.7% | +56.8% | +88.9% | +59.6% |
90
+ | Distribution Quality | Perfect | Excellent | Excellent | Perfect |
91
91
 
92
92
  ## Analysis
93
93
 
94
94
  ### Performance Characteristics
95
95
 
96
96
  1. Speed and Efficiency:
97
- - Processes 10K items in ~200ms across all Ruby versions
98
- - Microsecond-level processing for small collections (9-14μs)
99
- - Millisecond-level processing for large collections (193-209ms)
100
- - YJIT provides significant speedup for tiny datasets (39-51% faster)
101
- - Suitable for real-time web applications
97
+ - Processes 10K items in ~2.4-4.5ms across all Ruby versions
98
+ - Microsecond-level processing for small collections (6-10μs)
99
+ - Sub-millisecond processing for medium collections (~275-555μs)
100
+ - Millisecond-level processing for large collections (2.4-4.5ms)
101
+ - YJIT provides substantial speedup across all dataset sizes (40-89% faster)
102
+ - Suitable for high-performance real-time applications
102
103
 
103
104
  2. YJIT Impact:
104
- - Most effective on tiny datasets (10 items)
105
- - Benefits diminish as dataset size increases
106
- - Ruby 3.2.8 shows most consistent YJIT improvements
107
- - Some versions show slight regressions on larger datasets
108
-
109
- 3. Distribution Quality:
110
- - Perfect distribution in small datasets
111
- - Highly accurate distribution in larger datasets
105
+ - Most effective on medium datasets (up to 89% improvement)
106
+ - Consistent improvements across all dataset sizes
107
+ - Ruby 3.4.2 shows best absolute performance
108
+ - All versions benefit significantly from YJIT
109
+
110
+ 3. Version Comparison:
111
+ - Ruby 3.4.2 with YJIT shows best overall performance
112
+ - Ruby 3.3.7 maintains strong second position
113
+ - Ruby 3.2.8 shows solid baseline performance
114
+ - Performance variance between versions is consistent
115
+
116
+ 4. Distribution Quality:
117
+ - Perfect distribution in small and large datasets
118
+ - Highly accurate distribution in all dataset sizes
112
119
  - Consistent quality across all Ruby versions and YJIT settings
113
120
 
114
121
  ### Scaling Characteristics
115
122
 
116
123
  1. Dataset Size Impact:
117
- - Predictable performance scaling with size
118
- - Sub-second processing even for large datasets
124
+ - Near-linear performance scaling with size
125
+ - Sub-millisecond processing for datasets up to 1000 items
119
126
  - Reliable performance characteristics
120
127
 
121
128
  2. Memory Usage:
@@ -124,16 +131,15 @@ TypeBalancer is designed for practical use in content management and display sys
124
131
  - Stable across different workloads
125
132
 
126
133
  3. Distribution Quality:
127
- - Maintains high accuracy at all scales
128
- - Improves with larger datasets
134
+ - Maintains perfect accuracy at all scales
129
135
  - Consistent across implementations
130
136
 
131
137
  ## Use Cases
132
138
 
133
139
  1. Content Management Systems:
134
- - Homepage feeds (100s of items): < 1ms processing
135
- - Category pages (1000s of items): ~20ms processing
136
- - Site-wide content (10,000s of items): ~200ms processing
140
+ - Homepage feeds (100s of items): ~31μs processing
141
+ - Category pages (1000s of items): ~275μs processing
142
+ - Site-wide content (10,000s of items): ~2.4ms processing
137
143
 
138
144
  2. Real-time Applications:
139
145
  - Widget content balancing: microsecond response
@@ -141,26 +147,26 @@ TypeBalancer is designed for practical use in content management and display sys
141
147
  - Content reorganization: real-time capable
142
148
 
143
149
  3. Batch Processing:
144
- - Large collection processing: efficient and reliable
150
+ - Large collection processing: highly efficient
145
151
  - Consistent performance characteristics
146
152
  - Predictable resource usage
147
153
 
148
154
  ## Conclusions
149
155
 
150
156
  1. Version Selection:
151
- - Ruby 3.2.8 shows optimal performance
152
- - All versions maintain high distribution quality
157
+ - Ruby 3.4.2 with YJIT shows optimal performance across all sizes
158
+ - All versions maintain perfect distribution quality
153
159
  - Version choice can be based on other requirements
154
160
 
155
161
  2. Production Readiness:
156
- - Suitable for production workloads
157
- - Handles large datasets efficiently
158
- - Real-time processing capable
162
+ - Exceptional performance for production workloads
163
+ - Handles large datasets very efficiently
164
+ - Suitable for high-frequency real-time processing
159
165
 
160
166
  3. Future Outlook:
161
- - Continued optimization for larger datasets
167
+ - Current performance exceeds most real-world requirements
162
168
  - Focus on maintaining distribution quality
163
- - Performance improvements in newer Ruby versions
169
+ - Room for optimization in specific use cases
164
170
 
165
171
  ## Running the Benchmarks
166
172
 
@@ -0,0 +1,87 @@
1
+ # Detailed Documentation: `TypeBalancer.calculate_positions`
2
+
3
+ `TypeBalancer.calculate_positions` is a utility method for determining the optimal positions for a given number of items (or a ratio of items) within a sequence of slots. This is useful for advanced scenarios where you want to control the distribution of a specific type or subset of items.
4
+
5
+ ## Method Signature
6
+
7
+ ```ruby
8
+ TypeBalancer.calculate_positions(total_count:, ratio:, available_items: nil)
9
+ ```
10
+
11
+ ### Arguments
12
+ - `total_count` (Integer): The total number of slots in the sequence (e.g., the length of your feed or array).
13
+ - `ratio` (Float): The desired ratio of items to place (e.g., `0.3` for 30%).
14
+ - `available_items` (Array<Integer>, optional): An array of slot indices where placement is allowed. If omitted, all slots are considered available.
15
+
16
+ ## Return Value
17
+ - Returns an array of integer indices representing the optimal positions for the items.
18
+ - The array will have a length close to `total_count * ratio`, rounded as appropriate.
19
+ - If `available_items` is provided, only those slots will be used.
20
+
21
+ ## Usage Examples
22
+
23
+ ### 1. Even Distribution
24
+ ```ruby
25
+ # Place 3 items evenly in 10 slots
26
+ TypeBalancer.calculate_positions(total_count: 10, ratio: 0.3)
27
+ # => [0, 5, 9]
28
+ ```
29
+
30
+ ### 2. Restricting to Available Slots
31
+ ```ruby
32
+ # Only use slots 0, 1, and 2
33
+ TypeBalancer.calculate_positions(total_count: 10, ratio: 0.5, available_items: [0, 1, 2])
34
+ # => [0, 1, 2]
35
+ ```
36
+
37
+ ### 3. Edge Cases
38
+ ```ruby
39
+ # Single item
40
+ TypeBalancer.calculate_positions(total_count: 1, ratio: 1.0)
41
+ # => [0]
42
+
43
+ # No items
44
+ TypeBalancer.calculate_positions(total_count: 100, ratio: 0.0)
45
+ # => []
46
+
47
+ # All items
48
+ TypeBalancer.calculate_positions(total_count: 5, ratio: 1.0)
49
+ # => [0, 1, 2, 3, 4]
50
+ ```
51
+
52
+ ### 4. Precision with Small Ratios
53
+ ```ruby
54
+ # Two positions in three slots
55
+ TypeBalancer.calculate_positions(total_count: 3, ratio: 0.67)
56
+ # => [0, 1]
57
+
58
+ # Single position in three slots
59
+ TypeBalancer.calculate_positions(total_count: 3, ratio: 0.34)
60
+ # => [0]
61
+ ```
62
+
63
+ ### 5. Available Items Edge Cases
64
+ ```ruby
65
+ # Single target with multiple available positions
66
+ TypeBalancer.calculate_positions(total_count: 5, ratio: 0.2, available_items: [1, 2, 3])
67
+ # => [1]
68
+
69
+ # Two targets with multiple available positions
70
+ TypeBalancer.calculate_positions(total_count: 10, ratio: 0.2, available_items: [1, 3, 5])
71
+ # => [1, 5]
72
+
73
+ # Exact match of available positions
74
+ TypeBalancer.calculate_positions(total_count: 10, ratio: 0.3, available_items: [2, 4, 6])
75
+ # => [2, 4, 6]
76
+ ```
77
+
78
+ ## Notes and Caveats
79
+ - If `ratio` is 0 or `total_count` is 0, returns an empty array.
80
+ - If `ratio` is 1.0, returns all available slots.
81
+ - If `available_items` is provided and its length is less than the target count, all available items are returned.
82
+ - For very small or very large ratios, the method ensures at least one or all slots are used, respectively.
83
+ - The method is deterministic and will always return the same result for the same input.
84
+
85
+ ## See Also
86
+ - [README.md](../README.md) for general usage
87
+ - [Quality Script Documentation](quality.md) for integration tests and examples
data/docs/quality.md ADDED
@@ -0,0 +1,101 @@
1
+ # Quality Script Documentation
2
+
3
+ The TypeBalancer gem includes a comprehensive quality check script located at `/examples/quality.rb`. This script serves multiple purposes:
4
+
5
+ 1. **Documentation through Examples**: Demonstrates various use cases and features of the gem
6
+ 2. **Quality Assurance**: Verifies that core functionality works as expected
7
+ 3. **Integration Testing**: Tests how different components work together
8
+
9
+ ## Running the Script
10
+
11
+ To run the quality script from the gem repository:
12
+
13
+ ```bash
14
+ bundle exec ruby examples/quality.rb
15
+ ```
16
+
17
+ ### Running from Other Projects
18
+
19
+ You can run the quality script from any project that includes the TypeBalancer gem. This is useful for verifying the gem's behavior in your app or as part of CI for downstream projects.
20
+
21
+ **Example:**
22
+
23
+ ```bash
24
+ bundle exec ruby /path/to/gems/type_balancer/examples/quality.rb
25
+ ```
26
+
27
+ **How do I find the path to the gem?**
28
+
29
+ If you are not sure where the gem is installed, you can use Bundler to locate it:
30
+
31
+ ```bash
32
+ bundle show type_balancer
33
+ ```
34
+
35
+ This will print the path to the gem directory. The quality script is located in the `examples` subdirectory of that path. For example:
36
+
37
+ ```bash
38
+ $ bundle show type_balancer
39
+ /Users/yourname/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/type_balancer-0.1.3
40
+ $ bundle exec ruby /Users/yourname/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/type_balancer-0.1.3/examples/quality.rb
41
+ ```
42
+
43
+ - Ensure the gem is installed and available in your bundle.
44
+ - The script expects the test data file at `examples/balance_test_data.yml` (relative to the gem root).
45
+ - Output will be color-coded if your terminal supports ANSI colors.
46
+
47
+ ## What it Tests
48
+
49
+ The script tests several key aspects of the TypeBalancer gem:
50
+
51
+ ### 1. Basic Distribution
52
+ - Demonstrates how items are distributed across available slots
53
+ - Shows spacing calculations between positions
54
+ - Verifies edge cases (single item, no items, all items)
55
+
56
+ ### 2. Robust Balance Method Tests
57
+ - Loads scenarios from a YAML file (`examples/balance_test_data.yml`)
58
+ - Tests `TypeBalancer.balance` with and without the `type_order` argument
59
+ - Checks type counts, custom order, and exception handling for empty input
60
+ - Prints a color-coded summary table for pass/fail counts
61
+
62
+ ### 3. Content Feed Example
63
+ - Shows a real-world example of content type distribution
64
+ - Verifies position allocation for different content types (video, image, article)
65
+ - Checks distribution statistics and ratios
66
+
67
+ ## Output Format
68
+
69
+ - Each section prints a color-coded summary table of passing and failing tests
70
+ - Failures and exceptions are highlighted in red; passes in green
71
+ - The final summary shows the total number of examples run and passed
72
+ - The script exits with status 0 if all tests pass, or 1 if any fail (CI-friendly)
73
+
74
+ ## Using as a Development Tool
75
+
76
+ The quality script is particularly useful when:
77
+ 1. Developing new features
78
+ 2. Refactoring existing code
79
+ 3. Verifying changes haven't broken core functionality
80
+ 4. Understanding how different features work together
81
+
82
+ ## Customizing/Extending the Script
83
+
84
+ - You can add new scenarios to `examples/balance_test_data.yml` to test additional cases or edge conditions.
85
+ - You may copy or extend the script for your own integration tests.
86
+ - The script can be adapted to accept a custom YAML path if needed (see comments in the script).
87
+
88
+ ## Troubleshooting
89
+
90
+ - **Color output not working:** Ensure your terminal supports ANSI colors.
91
+ - **File not found:** Make sure `examples/balance_test_data.yml` exists and is accessible from the script's location.
92
+ - **Gem not found:** Ensure the TypeBalancer gem is installed and available in your bundle.
93
+ - **Path issues:** Use an absolute or correct relative path to the script when running from another project.
94
+
95
+ ## Extending the Script
96
+
97
+ When adding new features to TypeBalancer, consider:
98
+ 1. Adding relevant examples to the quality script
99
+ 2. Including edge cases
100
+ 3. Documenting expected behavior
101
+ 4. Adding appropriate quality checks
@@ -0,0 +1,66 @@
1
+ # Test data for TypeBalancer.balance integration tests
2
+
3
+ - name: Even distribution
4
+ items:
5
+ - { type: video, id: 1 }
6
+ - { type: video, id: 2 }
7
+ - { type: image, id: 3 }
8
+ - { type: image, id: 4 }
9
+ - { type: article, id: 5 }
10
+ - { type: article, id: 6 }
11
+ - { type: article, id: 7 }
12
+ - { type: article, id: 8 }
13
+ expected_type_counts:
14
+ video: 2
15
+ image: 2
16
+ article: 4
17
+
18
+ - name: Uneven distribution
19
+ items:
20
+ - { type: video, id: 1 }
21
+ - { type: image, id: 2 }
22
+ - { type: article, id: 3 }
23
+ - { type: article, id: 4 }
24
+ - { type: article, id: 5 }
25
+ - { type: article, id: 6 }
26
+ - { type: article, id: 7 }
27
+ - { type: article, id: 8 }
28
+ expected_type_counts:
29
+ video: 1
30
+ image: 1
31
+ article: 6
32
+
33
+ - name: Missing type (no images)
34
+ items:
35
+ - { type: video, id: 1 }
36
+ - { type: video, id: 2 }
37
+ - { type: article, id: 3 }
38
+ - { type: article, id: 4 }
39
+ - { type: article, id: 5 }
40
+ expected_type_counts:
41
+ video: 2
42
+ article: 3
43
+
44
+ - name: Custom type order
45
+ items:
46
+ - { type: video, id: 1 }
47
+ - { type: image, id: 2 }
48
+ - { type: article, id: 3 }
49
+ - { type: article, id: 4 }
50
+ - { type: image, id: 5 }
51
+ - { type: video, id: 6 }
52
+ - { type: article, id: 7 }
53
+ type_order: [image, video, article]
54
+ expected_first_type: image
55
+
56
+ - name: Edge case - empty
57
+ items: []
58
+ expected_type_counts: {}
59
+
60
+ - name: Edge case - single type
61
+ items:
62
+ - { type: article, id: 1 }
63
+ - { type: article, id: 2 }
64
+ - { type: article, id: 3 }
65
+ expected_type_counts:
66
+ article: 3