string_to_number 0.2.0 → 0.3.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: 94ccd123e31951522c7960a5140affb629f331e8f862e3f0336c3c15c2c86bcc
4
- data.tar.gz: b2d95e4cd38fda267ed0f73399c5af5b5e511d9f9f2baba3e14f349e6da4bf7b
3
+ metadata.gz: 336f985b755b77d9518187442a09e117175a12bcc8658abd46a98f0180efd5e3
4
+ data.tar.gz: acd54764a6df32c72067457f22de32f28a57a3c30c571ca608aba48bd9aa1f63
5
5
  SHA512:
6
- metadata.gz: 604ed5a2557ceb9813fee18765e0aacc33bdc6fd7a721f5d97568c65995a8e9d5609ff17eb2a44412b381a8ac10822ee602633ad9b5a0e67a984b4de0f33aba4
7
- data.tar.gz: bdff30862931f8d0d28d0c15ccf36b70056fe65c3b588c619c9452c7f92a4a732569ac4925e68af88fe67682f49854aa809b7468ee7d81005b44fd33b1c537ba
6
+ metadata.gz: 8ea31d03afc64fa5400ac6609748bf14e15916bdcc27a605e0e399d170b0db7f2be09b82c46ca43fc43eb5e2bb6ae71e4276eebc97e1b6356f43d230ef320c9a
7
+ data.tar.gz: 8b962962941a065def976540572e47534fe82ac270f2a5fd9121e640f82fc66aefa7270bedd068cdf02c32f66fd8307a013fe9b4382f6d8466f25f5a78c87e51
@@ -0,0 +1,81 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ matrix:
12
+ ruby-version: ['2.7', '3.0', '3.1', '3.2', '3.3']
13
+
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Set up Ruby ${{ matrix.ruby-version }}
18
+ uses: ruby/setup-ruby@v1
19
+ with:
20
+ ruby-version: ${{ matrix.ruby-version }}
21
+ bundler-cache: true
22
+
23
+ - name: Run tests
24
+ run: bundle exec rake spec
25
+
26
+ - name: Run performance tests
27
+ run: bundle exec rspec spec/performance_spec.rb
28
+
29
+ lint:
30
+ runs-on: ubuntu-latest
31
+ steps:
32
+ - uses: actions/checkout@v4
33
+
34
+ - name: Set up Ruby
35
+ uses: ruby/setup-ruby@v1
36
+ with:
37
+ ruby-version: '3.3'
38
+ bundler-cache: true
39
+
40
+ - name: Install RuboCop
41
+ run: gem install rubocop
42
+
43
+ - name: Run RuboCop
44
+ run: rubocop --format github
45
+
46
+ security:
47
+ runs-on: ubuntu-latest
48
+ steps:
49
+ - uses: actions/checkout@v4
50
+
51
+ - name: Set up Ruby
52
+ uses: ruby/setup-ruby@v1
53
+ with:
54
+ ruby-version: '3.3'
55
+ bundler-cache: true
56
+
57
+ - name: Install bundler-audit
58
+ run: gem install bundler-audit
59
+
60
+ - name: Run bundler-audit
61
+ run: bundle audit --update
62
+
63
+ gem-build:
64
+ runs-on: ubuntu-latest
65
+ steps:
66
+ - uses: actions/checkout@v4
67
+
68
+ - name: Set up Ruby
69
+ uses: ruby/setup-ruby@v1
70
+ with:
71
+ ruby-version: '3.3'
72
+ bundler-cache: true
73
+
74
+ - name: Build gem
75
+ run: gem build string_to_number.gemspec
76
+
77
+ - name: Install gem locally
78
+ run: gem install string_to_number-*.gem
79
+
80
+ - name: Test gem installation
81
+ run: ruby -e "require 'string_to_number'; puts StringToNumber.in_numbers('vingt et un')"
@@ -0,0 +1,62 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+ workflow_dispatch:
8
+ inputs:
9
+ tag:
10
+ description: 'Release tag (e.g., v1.0.0)'
11
+ required: true
12
+
13
+ jobs:
14
+ test:
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ matrix:
18
+ ruby-version: ['2.7', '3.0', '3.1', '3.2', '3.3']
19
+
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - name: Set up Ruby ${{ matrix.ruby-version }}
24
+ uses: ruby/setup-ruby@v1
25
+ with:
26
+ ruby-version: ${{ matrix.ruby-version }}
27
+ bundler-cache: true
28
+
29
+ - name: Run tests
30
+ run: bundle exec rake spec
31
+
32
+ publish:
33
+ needs: test
34
+ runs-on: ubuntu-latest
35
+ environment: release
36
+ permissions:
37
+ contents: write
38
+ id-token: write
39
+
40
+ steps:
41
+ - uses: actions/checkout@v4
42
+
43
+ - name: Set up Ruby
44
+ uses: ruby/setup-ruby@v1
45
+ with:
46
+ ruby-version: '3.3'
47
+ bundler-cache: true
48
+
49
+ - name: Build gem
50
+ run: gem build string_to_number.gemspec
51
+
52
+ - name: Configure RubyGems credentials
53
+ uses: rubygems/configure-rubygems-credentials@v1.0.0
54
+
55
+ - name: Publish to RubyGems
56
+ run: gem push string_to_number-*.gem
57
+
58
+ - name: Create GitHub Release
59
+ env:
60
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
61
+ TAG: ${{ github.ref_name }}
62
+ run: gh release create "$TAG" --generate-notes
data/.rubocop.yml ADDED
@@ -0,0 +1,110 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.7
3
+ NewCops: enable
4
+ Exclude:
5
+ - 'vendor/**/*'
6
+ - 'pkg/**/*'
7
+ - 'tmp/**/*'
8
+ - 'bin/**/*'
9
+ - 'spec/fixtures/**/*'
10
+ SuggestExtensions: false
11
+
12
+ # Prefer double quotes for strings
13
+ Style/StringLiterals:
14
+ EnforcedStyle: single_quotes
15
+
16
+ # Allow longer lines for readability
17
+ Layout/LineLength:
18
+ Max: 120
19
+ Exclude:
20
+ - 'spec/**/*'
21
+
22
+ # Allow longer methods for complex parsing logic
23
+ Metrics/MethodLength:
24
+ Max: 25
25
+ Exclude:
26
+ - 'spec/**/*'
27
+ - 'benchmark.rb'
28
+ - 'microbenchmark.rb'
29
+ - 'performance_comparison.rb'
30
+ - 'lib/string_to_number/parser.rb'
31
+ - 'lib/string_to_number/to_number.rb'
32
+
33
+ # Allow longer classes for main implementation
34
+ Metrics/ClassLength:
35
+ Max: 250
36
+
37
+ # Allow longer blocks for test files
38
+ Metrics/BlockLength:
39
+ Max: 300
40
+ Exclude:
41
+ - 'spec/**/*'
42
+
43
+ # Allow more complex methods in parser
44
+ Metrics/CyclomaticComplexity:
45
+ Max: 12
46
+ Exclude:
47
+ - 'benchmark.rb'
48
+ - 'microbenchmark.rb'
49
+ - 'performance_comparison.rb'
50
+ - 'lib/string_to_number/parser.rb'
51
+ - 'lib/string_to_number/to_number.rb'
52
+
53
+ # Allow higher ABC size for parsing methods
54
+ Metrics/AbcSize:
55
+ Max: 20
56
+ Exclude:
57
+ - 'spec/**/*'
58
+ - 'benchmark.rb'
59
+ - 'microbenchmark.rb'
60
+ - 'performance_comparison.rb'
61
+ - 'lib/string_to_number/parser.rb'
62
+ - 'lib/string_to_number/to_number.rb'
63
+
64
+ # Allow higher perceived complexity for performance-critical methods
65
+ Metrics/PerceivedComplexity:
66
+ Max: 8
67
+ Exclude:
68
+ - 'benchmark.rb'
69
+ - 'microbenchmark.rb'
70
+ - 'performance_comparison.rb'
71
+ - 'lib/string_to_number/parser.rb'
72
+ - 'lib/string_to_number/to_number.rb'
73
+
74
+ # Allow multiple assignments for performance reasons
75
+ Style/ParallelAssignment:
76
+ Enabled: false
77
+
78
+ # Allow guard clauses without else
79
+ Style/GuardClause:
80
+ Enabled: false
81
+
82
+ # Documentation requirements
83
+ Style/Documentation:
84
+ Enabled: false
85
+
86
+ # Allow frozen string literal comments
87
+ Style/FrozenStringLiteralComment:
88
+ Enabled: true
89
+ EnforcedStyle: always
90
+
91
+
92
+ # Layout preferences
93
+ Layout/MultilineMethodCallIndentation:
94
+ EnforcedStyle: aligned
95
+
96
+ Layout/MultilineOperationIndentation:
97
+ EnforcedStyle: aligned
98
+
99
+ # Naming conventions
100
+ Naming/PredicatePrefix:
101
+ ForbiddenPrefixes:
102
+ - is_
103
+
104
+ # Allow single line methods
105
+ Style/SingleLineMethods:
106
+ AllowIfMethodIsEmpty: true
107
+
108
+ # Gem specific rules
109
+ Gemspec/RequiredRubyVersion:
110
+ Enabled: false
data/CLAUDE.md CHANGED
@@ -4,100 +4,38 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
4
4
 
5
5
  ## Project Overview
6
6
 
7
- This is a Ruby gem that converts French words into numbers. The gem provides a single public method `StringToNumber.in_numbers(french_string)` that parses French number words and returns their numeric equivalent.
7
+ Ruby gem that converts French written numbers into integers. Single public entry point: `StringToNumber.in_numbers(french_string)`.
8
8
 
9
- ## Core Architecture
10
-
11
- - **Main module**: `StringToNumber` in `lib/string_to_number.rb` - provides the public API
12
- - **Optimized parser**: `StringToNumber::Parser` in `lib/string_to_number/parser.rb` - high-performance implementation
13
- - **Original implementation**: `StringToNumber::ToNumber` in `lib/string_to_number/to_number.rb` - legacy compatibility
14
- - **Version**: `StringToNumber::VERSION` in `lib/string_to_number/version.rb`
15
-
16
- ### Parser Architecture
17
-
18
- The optimized parser uses:
19
- - **WORD_VALUES**: Direct French word to number mappings (0-90, including regional variants)
20
- - **MULTIPLIERS**: Power-of-ten multipliers (cent=2, mille=3, million=6, etc.)
21
- - **Pre-compiled regex patterns**: Eliminate compilation overhead
22
- - **Multi-level caching**: Instance cache + LRU conversion cache
23
- - **Thread-safe design**: Concurrent access with mutex protection
24
-
25
- The algorithm maintains the proven recursive parsing logic from the original while adding:
26
- - Memoization for repeated conversions
27
- - Instance caching to reduce initialization costs
28
- - Optimized string operations and hash lookups
29
-
30
- ## Common Development Commands
9
+ ## Commands
31
10
 
32
11
  ```bash
33
- # Install dependencies
34
- bundle install
35
-
36
- # Run tests
37
- rake spec
38
-
39
- # Run specific test
40
- bundle exec rspec spec/string_to_number_spec.rb
41
-
42
- # Start interactive console
43
- rake console
44
- # or
45
- bundle exec irb -I lib -r string_to_number
46
-
47
- # Install gem locally
48
- bundle exec rake install
49
-
50
- # Release new version (updates version.rb, creates git tag, pushes to rubygems)
51
- bundle exec rake release
12
+ bundle install # Install dependencies
13
+ rake spec # Run all tests (correctness + performance)
14
+ bundle exec rspec spec/string_to_number_spec.rb # Correctness tests only
15
+ bundle exec rspec spec/performance_spec.rb # Performance tests only
16
+ bundle exec rspec spec/string_to_number_spec.rb -e "vingt" # Run single test by name
17
+ rake rubocop # Lint (or: bundle exec rubocop)
18
+ rake # Default: rubocop + spec
19
+ rake console # Interactive REPL with gem loaded
52
20
  ```
53
21
 
54
- ## Testing
55
-
56
- Uses RSpec with comprehensive test coverage for French number parsing from 0 to millions. Tests are organized by number ranges (0-9, 10-19, 20-29, etc.) and include complex multi-word numbers.
57
-
58
- ### Performance Testing
59
-
60
- Performance tests are available to measure and monitor the implementation's efficiency:
22
+ ## Architecture
61
23
 
62
- ```bash
63
- # Run comprehensive performance test suite
64
- bundle exec rspec spec/performance_spec.rb
65
-
66
- # Run standalone benchmark script
67
- ruby -I lib benchmark.rb
24
+ Three files under `lib/` matter:
68
25
 
69
- # Run micro-benchmarks to identify bottlenecks
70
- ruby -I lib microbenchmark.rb
71
-
72
- # Run profiling analysis
73
- ruby -I lib profile.rb
74
- ```
26
+ - `lib/string_to_number.rb` public API module. Delegates to `Parser` (default) or `ToNumber` (legacy, via `use_optimized: false`).
27
+ - `lib/string_to_number/parser.rb` — optimized implementation. Owns all caching (LRU + instance cache) and thread-safety (two mutexes). Imports data tables from `ToNumber` but never calls its methods.
28
+ - `lib/string_to_number/to_number.rb` — legacy implementation. Owns the canonical data tables: `EXCEPTIONS` (word→value) and `POWERS_OF_TEN` (multiplier→exponent). Must be loaded before `parser.rb`.
75
29
 
76
- **Performance Characteristics (Optimized Implementation):**
77
- - Simple numbers (0-100): ~0.001ms average, 800,000+ conversions/sec
78
- - Medium complexity (100-1000): ~0.001ms average, 780,000+ conversions/sec
79
- - Complex numbers (1000+): ~0.002ms average, 690,000+ conversions/sec
80
- - Exceptional scalability: minimal performance degradation with input length
81
- - Memory efficient: zero object creation during operation
82
- - Intelligent caching: repeated conversions benefit from memoization
30
+ **Key constraint:** New word mappings go in `ToNumber::EXCEPTIONS` or `ToNumber::POWERS_OF_TEN` — `Parser` inherits them automatically. Don't duplicate data between the two implementations.
83
31
 
84
- **Performance Improvements:**
85
- - **14-460x faster** than original implementation across all test cases
86
- - **Excellent scalability**: 1.3x degradation vs 43x in original
87
- - **Pre-compiled regex patterns** eliminate compilation overhead
88
- - **Instance caching** reduces initialization costs
89
- - **Memoization** speeds up repeated conversions
90
- - **Thread-safe** with concurrent performance >2M conversions/sec
32
+ Both parsers use the same recursive algorithm: decompose input into `factor × multiplier` pairs via regex, with special-case handling for `quatre-vingt` forms.
91
33
 
92
- **Usage Options:**
93
- ```ruby
94
- # Use optimized implementation (default)
95
- StringToNumber.in_numbers('vingt et un')
34
+ See `docs/ARCHITECTURE.md` for the full code map and invariants.
96
35
 
97
- # Use original implementation for compatibility
98
- StringToNumber.in_numbers('vingt et un', use_optimized: false)
36
+ ## Style
99
37
 
100
- # Cache management
101
- StringToNumber.clear_caches!
102
- StringToNumber.cache_stats
103
- ```
38
+ - RuboCop enforced (`rake rubocop`). Config in `.rubocop.yml`.
39
+ - Single quotes for strings. `frozen_string_literal: true` in every file.
40
+ - Max line length: 120 (specs exempt).
41
+ - Target Ruby: 2.7+.
data/Gemfile CHANGED
@@ -1,4 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in string_to_number.gemspec
4
6
  gemspec
7
+
8
+ group :development do
9
+ gem 'bundler'
10
+ gem 'rake'
11
+ gem 'rspec'
12
+ gem 'rubocop', '~> 1.21'
13
+ end
data/Gemfile.lock CHANGED
@@ -1,13 +1,25 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- string_to_number (0.2.0)
4
+ string_to_number (0.3.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ ast (2.4.3)
9
10
  diff-lcs (1.5.0)
11
+ json (2.12.2)
12
+ language_server-protocol (3.17.0.5)
13
+ lint_roller (1.1.0)
14
+ parallel (1.27.0)
15
+ parser (3.3.8.0)
16
+ ast (~> 2.4.1)
17
+ racc
18
+ prism (1.4.0)
19
+ racc (1.8.1)
20
+ rainbow (3.1.1)
10
21
  rake (13.0.6)
22
+ regexp_parser (2.10.0)
11
23
  rspec (3.11.0)
12
24
  rspec-core (~> 3.11.0)
13
25
  rspec-expectations (~> 3.11.0)
@@ -21,6 +33,24 @@ GEM
21
33
  diff-lcs (>= 1.2.0, < 2.0)
22
34
  rspec-support (~> 3.11.0)
23
35
  rspec-support (3.11.1)
36
+ rubocop (1.77.0)
37
+ json (~> 2.3)
38
+ language_server-protocol (~> 3.17.0.2)
39
+ lint_roller (~> 1.1.0)
40
+ parallel (~> 1.10)
41
+ parser (>= 3.3.0.2)
42
+ rainbow (>= 2.2.2, < 4.0)
43
+ regexp_parser (>= 2.9.3, < 3.0)
44
+ rubocop-ast (>= 1.45.1, < 2.0)
45
+ ruby-progressbar (~> 1.7)
46
+ unicode-display_width (>= 2.4.0, < 4.0)
47
+ rubocop-ast (1.45.1)
48
+ parser (>= 3.3.7.2)
49
+ prism (~> 1.4)
50
+ ruby-progressbar (1.13.0)
51
+ unicode-display_width (3.1.4)
52
+ unicode-emoji (~> 4.0, >= 4.0.4)
53
+ unicode-emoji (4.0.4)
24
54
 
25
55
  PLATFORMS
26
56
  x86_64-linux
@@ -29,6 +59,7 @@ DEPENDENCIES
29
59
  bundler
30
60
  rake
31
61
  rspec
62
+ rubocop (~> 1.21)
32
63
  string_to_number!
33
64
 
34
65
  BUNDLED WITH