qi 10.0.0.beta12 → 10.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +63 -48
  3. data/lib/qi.rb +100 -114
  4. metadata +5 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7f3a609bb51c87ae5486c9244b948899f4e6ae46747ac80bf3be5f83ae76826a
4
- data.tar.gz: 1843fa6cc35f2dcaaab08a7772abeb9f56fa3e7d0dc5dc69f9a742ec47e81169
3
+ metadata.gz: 4a98ed653f1c1d21ae215f4a8ab481a0a19dd93551a9a3ba0faf9ee8e541291f
4
+ data.tar.gz: d1291d436f366c70e07a64a3a6390a3a9d99d56cfeb8b0b85c1002addbe7b540
5
5
  SHA512:
6
- metadata.gz: f79f7dc430f3e84b5cf816492c4f31c7776db329fffd18e161df929ccf18cb85b37cdd69e35c2b93da0e983e976d765bf69e8a33f1e946ec62d61c7b5583d164
7
- data.tar.gz: '059b84b8c426af80188f0b6885ff921ab86f7015756d5309d75fd0ab621f1d93322be5f83f603a02535850645da432219af815871c480b56dec0e8f67db738bb'
6
+ metadata.gz: 154aa839e292e2cadfbafe8c64e324285216da01a491ef98815479bf1bd735dc2ec747ad31e6ef479ea4d913b262dbcb9ad6399f13cdf5199dddb3403d7091ee
7
+ data.tar.gz: 52c5ca680fb11577fc2aa84931900b9f8c712e6c300ca5774f918f144fd1c999f1e34387e8827fe5f7f3d55ed192d04dabb310acc538c19bee3b941effb68637
data/README.md CHANGED
@@ -6,16 +6,19 @@
6
6
  [![RuboCop](https://github.com/sashite/qi.rb/workflows/RuboCop/badge.svg?branch=main)](https://github.com/sashite/qi.rb/actions?query=workflow%3Arubocop+branch%3Amain)
7
7
  [![License](https://img.shields.io/github/license/sashite/qi.rb?label=License&logo=github)](https://github.com/sashite/qi.rb/raw/main/LICENSE.md)
8
8
 
9
- Welcome to `Qi` (Chinese: 棋; pinyin: _qí_), a flexible and customizable library designed to represent and manipulate board game positions. `Qi` is ideal for a variety of board games, including chess, shogi, xiangqi, makruk, and more.
9
+ **Qi** (Chinese: 棋; pinyin: _qí_) is a lightweight, flexible, and adaptable tool for representing board game positions, built in Ruby. It is designed to be game-agnostic and can be used with a variety of board games such as Chess, Four-Player Chess, Go, Makruk, Shogi, and Xiangqi.
10
10
 
11
- With `Qi`, you can easily track the game state, including which pieces are on the board and where, as well as any captured pieces. The library allows for the application of game moves, updating the state of the game and generating a new position, all while preserving the original state.
11
+ Qi uses a unique approach where the state of a game is represented through capturing the pieces in play, the arrangement of pieces on the board, the sequence of turns, and other possible states that a game can have.
12
12
 
13
- ## Features:
13
+ ## Features
14
14
 
15
- - **Flexible representation of game states:** `Qi`'s design allows it to adapt to different games with varying rules and pieces.
16
- - **Immutable positions:** Every move generates a new position, preserving the original one. This is particularly useful for scenarios like undoing moves or exploring potential future states in the game.
17
- - **Compact serialization:** `Qi` provides a compact string serialization method for game states, which is useful for saving game progress or transmitting game states over the network.
18
- - **Check state tracking:** In addition to the positions and captured pieces, `Qi` also allows tracking of specific game states such as check in chess.
15
+ 1. **Game Agnostic:** Qi can be used to represent board game positions for a wide variety of games. Whether you are playing Chess, Makruk, Shogi, or Xiangqi, Qi's flexible structure allows you to accurately capture the state of your game.
16
+ 2. **Flexible Position Representation:** Qi captures the state of the game by recording the pieces in play, their arrangement on the board, the sequence of turns, and other additional states of the game. This enables a comprehensive view of the game at any given point.
17
+ 3. **State Manipulation:** Qi allows for manipulation and update of game states through the `commit` method, allowing transitions between game states.
18
+ 4. **Equality Checks:** With the `eql?` method, Qi allows for comparisons between different game states, which can be useful for tracking game progress, detecting repeats, or even in creating AI for your games.
19
+ 5. **Turn Management:** Qi keeps track of the sequence of turns allowing users to identify whose turn it is currently.
20
+ 6. **Access to Game Data:** Qi provides methods to access the current arrangement of pieces on the board (`squares_hash`) and the pieces captured by each player (`captures_hash`), helping users understand the current status of the game. It also allows access to a list of captured pieces (`captures_array`).
21
+ 7. **Customizability:** Qi is flexible and allows for customization as per your needs. The keys and values of the `captures_hash` and `squares_hash` can be any kind of object, as well as the items from `turns` and values from `state`.
19
22
 
20
23
  While `Qi` does not generate game moves itself, it serves as a solid foundation upon which game engines can be built. Its design is focused on providing a robust and adaptable representation of game states, paving the way for the development of diverse board game applications.
21
24
 
@@ -24,7 +27,7 @@ While `Qi` does not generate game moves itself, it serves as a solid foundation
24
27
  Add this line to your application's Gemfile:
25
28
 
26
29
  ```ruby
27
- gem "qi", ">= 10.0.0.beta12"
30
+ gem "qi"
28
31
  ```
29
32
 
30
33
  And then execute:
@@ -36,58 +39,70 @@ bundle install
36
39
  Or install it yourself as:
37
40
 
38
41
  ```sh
39
- gem install qi --pre
42
+ gem install qi
40
43
  ```
41
44
 
42
- ## Example
45
+ ## Usage
46
+
47
+ The following usage example is derived from a classic _tsume shogi_ (詰将棋) problem, which translates to _mate shogi_ - a popular genre of shogi problems where the goal is to checkmate the opponent's king.
48
+ In the provided setup, the attacking side is in possession of a silver general (S), a promoted bishop (+B) positioned on square 43, and a promoted pawn (+P) on square 22.
49
+
50
+ On the defending side, there is a king (k) situated on square 4, surrounded by two silver generals (s) on squares 3 and 5 respectively.
51
+
52
+ In this scenario, `Qi` allows us to represent the state of the game and apply changes as moves are made. Please follow the given example to understand how to create such a representation and how to update it:
43
53
 
44
54
  ```ruby
45
55
  require "qi"
46
56
 
47
- north_captures = %w[r r b g g g g s n n n n p p p p p p p p p p p p p p p p p]
48
- south_captures = %w[S]
49
- captures = north_captures + south_captures
50
- squares = { 3 => "s", 4 => "k", 5 => "s", 22 => "+P", 43 => "+B" }
51
-
52
- qi0 = Qi.new(*captures, **squares)
53
-
54
- qi0.captures # => ["S", "b", "g", "g", "g", "g", "n", "n", "n", "n", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "r", "r", "s"]
55
- qi0.squares # => {3=>"s", 4=>"k", 5=>"s", 22=>"+P", 43=>"+B"}
56
- qi0.in_check? # => false
57
- qi0.not_in_check? # => true
58
- qi0.north_turn? # => false
59
- qi0.south_turn? # => true
60
- qi0.serialize # => "{ S;b;g;g;g;g;n;n;n;n;p;p;p;p;p;p;p;p;p;p;p;p;p;p;p;p;p;r;r;s s@3;k@4;s@5;+P@22;+B@43 ."
61
- qi0.inspect # => "<Qi { S;b;g;g;g;g;n;n;n;n;p;p;p;p;p;p;p;p;p;p;p;p;p;p;p;p;p;r;r;s s@3;k@4;s@5;+P@22;+B@43 .>"
62
- qi0.to_a
63
- # [false,
64
- # ["S", "b", "g", "g", "g", "g", "n", "n", "n", "n", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "r", "r", "s"],
65
- # {3=>"s", 4=>"k", 5=>"s", 22=>"+P", 43=>"+B"},
66
- # false]
67
-
68
- qi1 = qi0.commit(is_in_check: true, 43 => nil, 13 => "+B")
69
-
70
- qi1.captures # => ["S", "b", "g", "g", "g", "g", "n", "n", "n", "n", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "r", "r", "s"]
71
- qi1.squares # => {3=>"s", 4=>"k", 5=>"s", 22=>"+P", 13=>"+B"}
72
- qi1.in_check? # => true
73
- qi1.not_in_check? # => false
74
- qi1.north_turn? # => true
75
- qi1.south_turn? # => false
76
- qi1.serialize # => "} S;b;g;g;g;g;n;n;n;n;p;p;p;p;p;p;p;p;p;p;p;p;p;p;p;p;p;r;r;s s@3;k@4;s@5;+B@13;+P@22 +"
77
- qi1.inspect # => "<Qi } S;b;g;g;g;g;n;n;n;n;p;p;p;p;p;p;p;p;p;p;p;p;p;p;p;p;p;r;r;s s@3;k@4;s@5;+B@13;+P@22 +>"
78
- qi1.to_a
79
- # [true,
80
- # ["S", "b", "g", "g", "g", "g", "n", "n", "n", "n", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "r", "r", "s"],
81
- # {3=>"s", 4=>"k", 5=>"s", 22=>"+P", 13=>"+B"},
82
- # true]
57
+ # Initialize an array for each player's captured pieces
58
+ north_captures = %w[r r b g g g g s n n n n p p p p p p p p p p p p p p p p p]
59
+ south_captures = %w[S]
60
+
61
+ # Combine and count each player's captured pieces
62
+ captures = Hash.new(0)
63
+ (north_captures + south_captures).each { |piece| captures[piece] += 1 }
64
+
65
+ # Define the squares occupied by each piece on the board
66
+ squares = { 3 => "s", 4 => "k", 5 => "s", 22 => "+P", 43 => "+B" }
67
+
68
+ # Create a new game position
69
+ qi0 = Qi.new(captures, squares, [0, 1])
70
+
71
+ # Verify the properties of the game position
72
+ qi0.captures_array # => ["S", "b", "g", "g", "g", "g", "n", "n", "n", "n", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "r", "r", "s"]
73
+ qi0.captures_hash # => {"r"=>2, "b"=>1, "g"=>4, "s"=>1, "n"=>4, "p"=>17, "S"=>1}
74
+ qi0.squares_hash # => {3=>"s", 4=>"k", 5=>"s", 22=>"+P", 43=>"+B"}
75
+ qi0.state # => {}
76
+ qi0.turn # => 0
77
+ qi0.turns # => [0, 1]
78
+ qi0.eql?(Qi.new(captures, squares, [0, 1])) # => true
79
+ qi0.eql?(Qi.new(captures, squares, [1, 0])) # => false
80
+
81
+ # Move a piece on the board and check the game state
82
+ qi1 = qi0.commit([], [], { 43 => nil, 13 => "+B" }, in_check: true)
83
+
84
+ qi1.captures_array # => ["S", "b", "g", "g", "g", "g", "n", "n", "n", "n", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "r", "r", "s"]
85
+ qi1.captures_hash # => {"r"=>2, "b"=>1, "g"=>4, "s"=>1, "n"=>4, "p"=>17, "S"=>1}
86
+ qi1.squares_hash # => {3=>"s", 4=>"k", 5=>"s", 22=>"+P", 13=>"+B"}
87
+ qi1.state # => {:in_check=>true}
88
+ qi1.turn # => 1
89
+ qi1.turns # => [1, 0]
90
+ qi1.eql?(Qi.new(captures, squares, [0, 1])) # => false
91
+ qi1.eql?(Qi.new(captures, squares, [1, 0])) # => false
83
92
  ```
84
93
 
94
+ In this example, we first create a `Qi` object to represent a game position with `Qi.new`. Then, we check various aspects of the game state using the methods provided by `Qi`. After that, we create a new game state `qi1` by committing changes to the existing state `qi0`. Finally, we again check various aspects of the new game state.
95
+
85
96
  ## License
86
97
 
87
98
  The code is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
88
99
 
89
100
  ## About Sashité
90
101
 
91
- This [gem](https://rubygems.org/gems/qi) is maintained by [Sashité](https://sashite.com/).
102
+ This [gem](https://rubygems.org/gems/qi) is proudly maintained and developed by [Sashité](https://sashite.com/). Our mission is to promote intercultural understanding and appreciation through the universal language of board games.
103
+
104
+ At Sashité, we believe in the power of games as a medium for sharing and appreciating the richness of different cultures. From Chinese to Japanese, and Western traditions, every culture has its unique representation in the world of board games, particularly in chess.
105
+
106
+ Our `Qi` gem is a testament to this belief - a flexible, efficient, and inclusive software that allows for the representation and interaction of diverse chess systems. This piece of software is not just a tool; it is a bridge connecting different cultures under the love of strategic play.
92
107
 
93
- With some [lines of code](https://github.com/sashite/), let's share the beauty of Chinese, Japanese and Western cultures through the game of chess!
108
+ Join us in our journey as we continue to write [code](https://github.com/sashite/) to share the beauty of these cultures, one game at a time.
data/lib/qi.rb CHANGED
@@ -1,132 +1,118 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "digest"
4
- require "kernel/boolean"
5
-
6
- # The Qi class represents a state of games such as Shogi.
3
+ # The Qi class provides a consistent representation of a game state
4
+ # and supports changes in the game state through the commit method.
5
+ # It is designed to be used in board games such as chess, makruk, shogi, xiangqi.
7
6
  class Qi
8
- # @return [Array] the pieces captured by the current player.
9
- attr_reader :captures
10
-
11
- # @return [Hash] the current state of the board.
12
- attr_reader :squares
13
-
14
- # Initializes a new game state.
7
+ # @!attribute [r] captures_hash
8
+ # @return [Hash<Object, Integer>] a hash of captured pieces
9
+ # @example
10
+ # {"r"=>2, "b"=>1, "g"=>4, "s"=>1, "n"=>4, "p"=>17, "S"=>1}
11
+
12
+ # @!attribute [r] squares_hash
13
+ # @return [Hash<Object, Object>] A hash where the keys represent square
14
+ # identifiers and the values represent the piece that will occupy each square.
15
+ # Both the keys and values can be any type of Ruby object, such as integers, strings, symbols, etc.
16
+ # @example
17
+ # {A3: "s", E4: "k", B5: "s", C22: "+P", D43: "+B"}
18
+
19
+ # @!attribute [r] state
20
+ # @return [Hash<Symbol, Object>] a hash of game states
21
+ # @example
22
+ # {:in_check=>true}
23
+
24
+ # @!attribute [r] turns
25
+ # @return [Array<Object>] a rotation of turns
26
+ # @example
27
+ # ["Sente", "Gote"]
28
+
29
+ attr_reader :captures_hash, :squares_hash, :state, :turns
30
+
31
+ # @param captures_hash [Hash<Object, Integer>] a hash of captured pieces
32
+ # @param squares_hash [Hash<Object, Object>] A hash where the keys represent square
33
+ # identifiers and the values represent the piece that will occupy each square.
34
+ # Both the keys and values can be any type of Ruby object, such as integers, strings, symbols, etc.
35
+ # @param turns [Array<Object>] a rotation of turns
36
+ # @param state [Hash<Symbol, Object>] a hash of game states
15
37
  #
16
- # @param capture [String, nil] the piece to be captured.
17
- # @param captures [Array] the pieces already captured.
18
- # @param drop [String, nil] the piece to be dropped.
19
- # @param is_in_check [Boolean] whether the current player is in check.
20
- # @param is_north_turn [Boolean] whether it's North's turn.
21
- # @param squares [Hash] the current state of the board.
22
- def initialize(capture = nil, *captures, drop: nil, is_in_check: false, is_north_turn: false, **squares)
23
- captures << capture unless capture.nil?
24
- captures.delete_at(captures.rindex(drop)) unless drop.nil?
25
-
26
- @captures = captures.sort
27
- @is_in_check = Boolean(is_in_check)
28
- @is_north_turn = Boolean(is_north_turn)
29
- @squares = squares.compact
30
- end
31
-
32
- # Commits a move and returns a new game state.
38
+ # @example
39
+ # captures = Hash.new(0)
40
+ # north_captures = %w[r r b g g g g s n n n n p p p p p p p p p p p p p p p p p]
41
+ # south_captures = %w[S]
42
+ # (north_captures + south_captures).each { |piece| captures[piece] += 1 }
43
+ # squares = { 3 => "s", 4 => "k", 5 => "s", 22 => "+P", 43 => "+B" }
44
+ # Qi.new(captures, squares, [0, 1])
45
+ def initialize(captures_hash, squares_hash, turns, **state)
46
+ @captures_hash = ::Hash.new(0).merge(captures_hash.select { |_, v| v > 0 })
47
+ @squares_hash = squares_hash.compact
48
+ @turns = turns
49
+ @state = state.transform_keys(&:to_sym)
50
+
51
+ freeze
52
+ end
53
+
54
+ # Return an array of captures containing piece names.
33
55
  #
34
- # @param capture [String, nil] the piece to be captured.
35
- # @param drop [String, nil] the piece to be dropped.
36
- # @param is_in_check [Boolean] whether the current player is in check.
37
- # @param diffs [Hash] the differences in the state of the board.
38
- # @return [Qi] the new game state.
39
- def commit(capture: nil, drop: nil, is_in_check: false, **diffs)
40
- self.class.new(capture, *captures, drop:, is_in_check:, is_north_turn: south_turn?, **squares.merge(diffs))
41
- end
42
-
43
- # @return [Boolean] whether the current player is in check.
44
- def in_check?
45
- @is_in_check
56
+ # @return [Array<Object>] an array of captures
57
+ # @example
58
+ # ["S", "b", "g", "g", "g", "g", "n", "n", "n", "n", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "r", "r", "s"]
59
+ def captures_array
60
+ captures_hash.flat_map { |piece, count| ::Array.new(count, piece) }.sort
46
61
  end
47
62
 
48
- # @return [Boolean] whether the current player is not in check.
49
- def not_in_check?
50
- !in_check?
51
- end
52
-
53
- # @return [Boolean] whether it's North's turn.
54
- def north_turn?
55
- @is_north_turn
56
- end
57
-
58
- # @return [Boolean] whether it's South's turn.
59
- def south_turn?
60
- !north_turn?
61
- end
62
-
63
- # @return [Boolean] whether the other game state is equal to this one.
63
+ # Commit a change to the game state and return a new Qi object.
64
+ #
65
+ # @param add_captures_array [Array<Object>] an array of pieces to be added to captures
66
+ # @param del_captures_array [Array<Object>] an array of pieces to be deleted from captures
67
+ # @param edit_squares_hash [Hash<Object, Object>] A hash where the keys represent square
68
+ # identifiers and the values represent the piece that will occupy each square.
69
+ # Both the keys and values can be any type of Ruby object, such as integers, strings, symbols, etc.
70
+ # @param state [Hash<Symbol, Object>] a hash of new game states
71
+ # @return [Qi] a new Qi object representing the updated game state
72
+ # @example
73
+ # qi0.commit([], [], { D43: nil, B13: "+B" }, in_check: true)
74
+ def commit(add_captures_array, del_captures_array, edit_squares_hash, **state)
75
+ self.class.new(
76
+ edit_captures_hash(add_captures_array.compact, del_captures_array.compact, **captures_hash),
77
+ squares_hash.merge(edit_squares_hash),
78
+ turns.rotate,
79
+ **state
80
+ )
81
+ end
82
+
83
+ # Check if the current Qi object is equal to another Qi object.
84
+ #
85
+ # @param other [Qi] another Qi object
86
+ # @return [Boolean] returns true if the captures_hash, squares_hash, turn, and state of both Qi objects are equal, false otherwise
64
87
  def eql?(other)
65
- return false unless other.respond_to?(:serialize)
88
+ return false unless other.captures_hash == captures_hash
89
+ return false unless other.squares_hash == squares_hash
90
+ return false unless other.turn == turn
91
+ return false unless other.state == state
66
92
 
67
- other.serialize == serialize
93
+ true
68
94
  end
69
95
  alias == eql?
70
96
 
71
- # @return [Array] the array representation of the game state.
72
- def to_a
73
- [
74
- north_turn?,
75
- captures,
76
- squares,
77
- in_check?
78
- ]
79
- end
80
-
81
- # @return [Hash] the hash representation of the game state.
82
- def to_h
83
- {
84
- is_north_turn: north_turn?,
85
- captures:,
86
- squares:,
87
- is_in_check: in_check?
88
- }
89
- end
90
-
91
- # @return [String] the SHA-256 hash of the serialized game state.
92
- def hash
93
- ::Digest::SHA256.hexdigest(serialize)
94
- end
95
-
96
- # @return [String] the string representation of the game state.
97
- def serialize
98
- [
99
- serialized_turn,
100
- serialized_captures,
101
- serialized_squares,
102
- serialized_in_check
103
- ].join(" ")
104
- end
105
-
106
- # @return [String] the string representation of the object.
107
- def inspect
108
- "<#{self.class} #{serialize}>"
97
+ # Get the current turn.
98
+ #
99
+ # @return [Object] the current turn
100
+ def turn
101
+ turns.fetch(0)
109
102
  end
110
103
 
111
104
  private
112
105
 
113
- # @return [String] the serialized turn.
114
- def serialized_turn
115
- north_turn? ? "}" : "{"
116
- end
117
-
118
- # @return [String] the serialized captures.
119
- def serialized_captures
120
- captures.join(";")
121
- end
122
-
123
- # @return [String] the serialized board state.
124
- def serialized_squares
125
- squares.keys.sort.map { |i| "#{squares.fetch(i)}@#{i}" }.join(";")
126
- end
127
-
128
- # @return [String] the serialized check state.
129
- def serialized_in_check
130
- in_check? ? "+" : "."
106
+ # Edits the captures hash and returns it.
107
+ #
108
+ # @param add_captures_array [Array<Object>] an array of pieces to be added to captures
109
+ # @param del_captures_array [Array<Object>] an array of pieces to be deleted from captures
110
+ # @param hash [Hash<Object, Integer>] the current captures hash
111
+ # @return [Hash<Object, Integer>] the updated captures hash
112
+ def edit_captures_hash(add_captures_array, del_captures_array, **hash)
113
+ add_captures_array.each { |piece_name| hash[piece_name] += 1 }
114
+ del_captures_array.each { |piece_name| hash[piece_name] -= 1 }
115
+
116
+ hash
131
117
  end
132
118
  end
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qi
3
3
  version: !ruby/object:Gem::Version
4
- version: 10.0.0.beta12
4
+ version: 10.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyril Kato
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-13 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: kernel-boolean
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
11
+ date: 2023-05-29 00:00:00.000000000 Z
12
+ dependencies: []
27
13
  description: A flexible and customizable library for representing and manipulating
28
14
  game states, ideal for developing board games like chess, shogi, or xiangqi.
29
15
  email: contact@cyril.email
@@ -50,9 +36,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
50
36
  version: 3.2.0
51
37
  required_rubygems_version: !ruby/object:Gem::Requirement
52
38
  requirements:
53
- - - ">"
39
+ - - ">="
54
40
  - !ruby/object:Gem::Version
55
- version: 1.3.1
41
+ version: '0'
56
42
  requirements: []
57
43
  rubygems_version: 3.4.10
58
44
  signing_key: