sashite-qpi 1.0.0 → 2.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.
- checksums.yaml +4 -4
- data/LICENSE +201 -0
- data/README.md +260 -210
- data/lib/sashite/qpi/constants.rb +13 -0
- data/lib/sashite/qpi/errors/argument/messages.rb +23 -0
- data/lib/sashite/qpi/errors/argument.rb +16 -0
- data/lib/sashite/qpi/errors.rb +3 -0
- data/lib/sashite/qpi/identifier.rb +153 -333
- data/lib/sashite/qpi/parser.rb +122 -0
- data/lib/sashite/qpi.rb +60 -188
- data/lib/sashite-qpi.rb +0 -11
- metadata +18 -17
- data/LICENSE.md +0 -22
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "sashite/sin"
|
|
4
|
+
require "sashite/pin"
|
|
5
|
+
|
|
6
|
+
require_relative "constants"
|
|
7
|
+
require_relative "errors"
|
|
8
|
+
|
|
9
|
+
module Sashite
|
|
10
|
+
module Qpi
|
|
11
|
+
# Parser for QPI (Qualified Piece Identifier) strings.
|
|
12
|
+
#
|
|
13
|
+
# This parser splits the QPI string on the colon separator and delegates
|
|
14
|
+
# parsing of each component to the SIN and PIN libraries.
|
|
15
|
+
#
|
|
16
|
+
# @example
|
|
17
|
+
# Parser.parse("C:K") # => { sin: <Sin::Identifier>, pin: <Pin::Identifier> }
|
|
18
|
+
# Parser.parse("s:+r^") # => { sin: <Sin::Identifier>, pin: <Pin::Identifier> }
|
|
19
|
+
#
|
|
20
|
+
# @see https://sashite.dev/specs/qpi/1.0.0/
|
|
21
|
+
module Parser
|
|
22
|
+
# Parses a QPI string into its components.
|
|
23
|
+
#
|
|
24
|
+
# @param input [String] The QPI string to parse
|
|
25
|
+
# @return [Hash] A hash with :sin and :pin keys containing Identifier instances
|
|
26
|
+
# @raise [Errors::Argument] If the input is not a valid QPI string
|
|
27
|
+
def self.parse(input)
|
|
28
|
+
validate_input_type(input)
|
|
29
|
+
validate_not_empty(input)
|
|
30
|
+
|
|
31
|
+
sin_string, pin_string = split_components(input)
|
|
32
|
+
|
|
33
|
+
sin = parse_sin(sin_string)
|
|
34
|
+
pin = parse_pin(pin_string)
|
|
35
|
+
|
|
36
|
+
{ sin: sin, pin: pin }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Validates a QPI string without raising an exception.
|
|
40
|
+
#
|
|
41
|
+
# @param input [String] The QPI string to validate
|
|
42
|
+
# @return [Boolean] true if valid, false otherwise
|
|
43
|
+
def self.valid?(input)
|
|
44
|
+
return false unless ::String === input
|
|
45
|
+
|
|
46
|
+
parse(input)
|
|
47
|
+
true
|
|
48
|
+
rescue Errors::Argument
|
|
49
|
+
false
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class << self
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
# Validates that input is a String.
|
|
56
|
+
#
|
|
57
|
+
# @param input [Object] The input to validate
|
|
58
|
+
# @raise [Errors::Argument] If input is not a String
|
|
59
|
+
def validate_input_type(input)
|
|
60
|
+
return if ::String === input
|
|
61
|
+
|
|
62
|
+
raise Errors::Argument, Errors::Argument::Messages::EMPTY_INPUT
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Validates that input is not empty.
|
|
66
|
+
#
|
|
67
|
+
# @param input [String] The input to validate
|
|
68
|
+
# @raise [Errors::Argument] If input is empty
|
|
69
|
+
def validate_not_empty(input)
|
|
70
|
+
return unless input.empty?
|
|
71
|
+
|
|
72
|
+
raise Errors::Argument, Errors::Argument::Messages::EMPTY_INPUT
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Splits the input into SIN and PIN components.
|
|
76
|
+
#
|
|
77
|
+
# @param input [String] The QPI string to split
|
|
78
|
+
# @return [Array<String>] An array with [sin_string, pin_string]
|
|
79
|
+
# @raise [Errors::Argument] If the separator is missing or components are empty
|
|
80
|
+
def split_components(input)
|
|
81
|
+
unless input.include?(Constants::SEPARATOR)
|
|
82
|
+
raise Errors::Argument, Errors::Argument::Messages::MISSING_SEPARATOR
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
sin_string, pin_string = input.split(Constants::SEPARATOR, 2)
|
|
86
|
+
|
|
87
|
+
if sin_string.nil? || sin_string.empty?
|
|
88
|
+
raise Errors::Argument, Errors::Argument::Messages::MISSING_SIN
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
if pin_string.nil? || pin_string.empty?
|
|
92
|
+
raise Errors::Argument, Errors::Argument::Messages::MISSING_PIN
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
[sin_string, pin_string]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Parses the SIN component.
|
|
99
|
+
#
|
|
100
|
+
# @param sin_string [String] The SIN string to parse
|
|
101
|
+
# @return [Sashite::Sin::Identifier] The parsed SIN identifier
|
|
102
|
+
# @raise [Errors::Argument] If the SIN is invalid
|
|
103
|
+
def parse_sin(sin_string)
|
|
104
|
+
Sashite::Sin.parse(sin_string)
|
|
105
|
+
rescue ::ArgumentError => e
|
|
106
|
+
raise Errors::Argument, "#{Errors::Argument::Messages::INVALID_SIN}: #{e.message}"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Parses the PIN component.
|
|
110
|
+
#
|
|
111
|
+
# @param pin_string [String] The PIN string to parse
|
|
112
|
+
# @return [Sashite::Pin::Identifier] The parsed PIN identifier
|
|
113
|
+
# @raise [Errors::Argument] If the PIN is invalid
|
|
114
|
+
def parse_pin(pin_string)
|
|
115
|
+
Sashite::Pin.parse(pin_string)
|
|
116
|
+
rescue ::ArgumentError => e
|
|
117
|
+
raise Errors::Argument, "#{Errors::Argument::Messages::INVALID_PIN}: #{e.message}"
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
data/lib/sashite/qpi.rb
CHANGED
|
@@ -1,220 +1,92 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "qpi/constants"
|
|
4
|
+
require_relative "qpi/errors"
|
|
3
5
|
require_relative "qpi/identifier"
|
|
6
|
+
require_relative "qpi/parser"
|
|
4
7
|
|
|
5
8
|
module Sashite
|
|
6
|
-
# QPI (Qualified Piece Identifier) implementation for Ruby
|
|
9
|
+
# QPI (Qualified Piece Identifier) implementation for Ruby.
|
|
7
10
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
# game styles and contexts.
|
|
11
|
+
# QPI provides complete piece identification by combining two primitive notations:
|
|
12
|
+
# - SIN (Style Identifier Notation) for Piece Style
|
|
13
|
+
# - PIN (Piece Identifier Notation) for Piece Name, Side, State, and Terminal Status
|
|
12
14
|
#
|
|
13
|
-
#
|
|
15
|
+
# == Format
|
|
14
16
|
#
|
|
15
|
-
#
|
|
16
|
-
# systems while maintaining complete attribute information. By combining SIN and PIN primitives,
|
|
17
|
-
# QPI provides explicit representation of all four fundamental piece attributes from the
|
|
18
|
-
# Sashité Protocol.
|
|
17
|
+
# <sin>:<pin>
|
|
19
18
|
#
|
|
20
|
-
#
|
|
19
|
+
# - *SIN*: Single ASCII letter encoding Piece Style and a side tag
|
|
20
|
+
# - *PIN*: Piece identifier with optional state modifier and terminal marker
|
|
21
21
|
#
|
|
22
|
-
#
|
|
23
|
-
# - **Family**: Style identification from SIN component
|
|
24
|
-
# - **Type**: Piece type from PIN component
|
|
25
|
-
# - **Side**: Player assignment from both components (must be consistent)
|
|
26
|
-
# - **State**: Piece state from PIN component
|
|
22
|
+
# == Piece Identity Attributes
|
|
27
23
|
#
|
|
28
|
-
#
|
|
24
|
+
# A QPI token encodes complete Piece Identity:
|
|
29
25
|
#
|
|
30
|
-
#
|
|
31
|
-
# -
|
|
32
|
-
# -
|
|
33
|
-
# -
|
|
26
|
+
# - *Piece Style* → SIN letter (case-insensitive identity)
|
|
27
|
+
# - *Piece Name* → PIN letter (case-insensitive identity)
|
|
28
|
+
# - *Piece Side* → PIN letter case (uppercase = first, lowercase = second)
|
|
29
|
+
# - *Piece State* → PIN modifier (+/-)
|
|
30
|
+
# - *Terminal Status* → PIN marker (^)
|
|
34
31
|
#
|
|
35
|
-
#
|
|
36
|
-
# the same player (first or second) through their respective case encodings.
|
|
32
|
+
# == Native/Derived Relationship
|
|
37
33
|
#
|
|
38
|
-
#
|
|
34
|
+
# QPI defines a deterministic relationship based on case comparison:
|
|
39
35
|
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
# piece ownership and style ownership remain aligned, preventing impossible combinations
|
|
43
|
-
# like a first player style with a second player piece.
|
|
36
|
+
# - *Native*: SIN case matches PIN case (sin.side == pin.side)
|
|
37
|
+
# - *Derived*: SIN case differs from PIN case (sin.side != pin.side)
|
|
44
38
|
#
|
|
45
|
-
# Examples
|
|
46
|
-
# - SIN "C" (first player) + PIN "K" (first player) = Valid
|
|
47
|
-
# - SIN "c" (second player) + PIN "k" (second player) = Valid
|
|
48
|
-
# - SIN "C" (first player) + PIN "k" (second player) = Invalid
|
|
49
|
-
# - SIN "c" (second player) + PIN "K" (first player) = Invalid
|
|
39
|
+
# == Examples
|
|
50
40
|
#
|
|
51
|
-
#
|
|
41
|
+
# qpi = Sashite::Qpi.parse("C:K^")
|
|
42
|
+
# qpi.sin.style # => :C
|
|
43
|
+
# qpi.pin.type # => :K
|
|
44
|
+
# qpi.pin.side # => :first
|
|
45
|
+
# qpi.pin.state # => :normal
|
|
46
|
+
# qpi.pin.terminal? # => true
|
|
47
|
+
# qpi.native? # => true
|
|
52
48
|
#
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
-
#
|
|
49
|
+
# qpi = Sashite::Qpi.parse("C:k")
|
|
50
|
+
# qpi.derived? # => true
|
|
51
|
+
# qpi.native.to_s # => "C:K"
|
|
56
52
|
#
|
|
57
|
-
#
|
|
53
|
+
# Sashite::Qpi.valid?("C:K^") # => true
|
|
54
|
+
# Sashite::Qpi.valid?("invalid") # => false
|
|
58
55
|
#
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
# Grammar (BNF):
|
|
62
|
-
# <qpi> ::= <uppercase-qpi> | <lowercase-qpi>
|
|
63
|
-
# <uppercase-qpi> ::= <uppercase-letter> ":" <uppercase-pin>
|
|
64
|
-
# <lowercase-qpi> ::= <lowercase-letter> ":" <lowercase-pin>
|
|
65
|
-
# <uppercase-pin> ::= ["+" | "-"] <uppercase-letter>
|
|
66
|
-
# <lowercase-pin> ::= ["+" | "-"] <lowercase-letter>
|
|
67
|
-
#
|
|
68
|
-
# Regular Expression: `/\A([A-Z]:[-+]?[A-Z]|[a-z]:[-+]?[a-z])\z/`
|
|
69
|
-
#
|
|
70
|
-
# ## Attribute Mapping
|
|
71
|
-
#
|
|
72
|
-
# QPI encodes piece attributes through primitive combination:
|
|
73
|
-
#
|
|
74
|
-
# | Piece Attribute | QPI Encoding | Examples |
|
|
75
|
-
# |-----------------|--------------|----------|
|
|
76
|
-
# | **Family** | SIN component | `C:K` = Chess family, `O:K` = Ogi family |
|
|
77
|
-
# | **Type** | PIN letter choice | `C:K` = King, `C:P` = Pawn |
|
|
78
|
-
# | **Side** | Component cases | `C:K` = First player, `c:k` = Second player |
|
|
79
|
-
# | **State** | PIN prefix modifier | `O:+P` = Enhanced, `C:-P` = Diminished |
|
|
80
|
-
#
|
|
81
|
-
# ## System Constraints
|
|
82
|
-
#
|
|
83
|
-
# - **Semantic Consistency**: SIN and PIN components must represent the same player
|
|
84
|
-
# - **Component Validation**: Each component must be valid according to its specification
|
|
85
|
-
# - **Complete Attribution**: All four fundamental piece attributes explicitly represented
|
|
86
|
-
# - **Cross-Style Support**: Enables multi-tradition gaming environments
|
|
87
|
-
#
|
|
88
|
-
# ## Examples
|
|
89
|
-
#
|
|
90
|
-
# ### Single-Style Games
|
|
91
|
-
#
|
|
92
|
-
# # Chess (both players use Chess style)
|
|
93
|
-
# white_king = Sashite::Qpi.parse("C:K") # Chess king, first player
|
|
94
|
-
# black_king = Sashite::Qpi.parse("c:k") # Chess king, second player
|
|
95
|
-
#
|
|
96
|
-
# # Ogi (both players use Ogi style)
|
|
97
|
-
# sente_king = Sashite::Qpi.parse("O:K") # Ogi king, first player (sente)
|
|
98
|
-
# gote_rook = Sashite::Qpi.parse("o:+r") # Ogi promoted rook, second player (gote)
|
|
99
|
-
#
|
|
100
|
-
# ### Cross-Style Games
|
|
101
|
-
#
|
|
102
|
-
# # Chess vs. Ogi match
|
|
103
|
-
# chess_player = Sashite::Qpi.parse("C:K") # First player uses Chess
|
|
104
|
-
# ogi_player = Sashite::Qpi.parse("o:k") # Second player uses Ogi
|
|
105
|
-
#
|
|
106
|
-
# # Verify cross-style scenario
|
|
107
|
-
# chess_player.cross_family?(ogi_player) # => true
|
|
108
|
-
#
|
|
109
|
-
# ### Attribute Access and Manipulation
|
|
110
|
-
#
|
|
111
|
-
# identifier = Sashite::Qpi.parse("O:+R")
|
|
112
|
-
#
|
|
113
|
-
# # Four fundamental attributes
|
|
114
|
-
# identifier.family # => :O
|
|
115
|
-
# identifier.type # => :R
|
|
116
|
-
# identifier.side # => :first
|
|
117
|
-
# identifier.state # => :enhanced
|
|
118
|
-
#
|
|
119
|
-
# # Component extraction
|
|
120
|
-
# identifier.to_sin # => "O"
|
|
121
|
-
# identifier.to_pin # => "+R"
|
|
122
|
-
#
|
|
123
|
-
# # Immutable transformations
|
|
124
|
-
# flipped = identifier.flip # => "o:+r"
|
|
125
|
-
# different_type = identifier.with_type(:Q) # => "O:+Q"
|
|
126
|
-
# different_family = identifier.with_family(:C) # => "C:+R"
|
|
127
|
-
#
|
|
128
|
-
# ## Design Properties
|
|
129
|
-
#
|
|
130
|
-
# - **Rule-agnostic**: Independent of specific game mechanics
|
|
131
|
-
# - **Complete identification**: Explicit representation of all four piece attributes
|
|
132
|
-
# - **Cross-style support**: Enables multi-tradition gaming environments
|
|
133
|
-
# - **Semantic validation**: Ensures consistency between style and piece ownership
|
|
134
|
-
# - **Primitive foundation**: Built from foundational SIN and PIN building blocks
|
|
135
|
-
# - **Extension-ready**: Can be enhanced by human-readable naming systems
|
|
136
|
-
# - **Context-flexible**: Adaptable to various identification needs
|
|
137
|
-
# - **Immutable**: All instances are frozen and transformations return new objects
|
|
138
|
-
# - **Functional**: Pure functions with no side effects
|
|
139
|
-
#
|
|
140
|
-
# @see https://sashite.dev/specs/qpi/1.0.0/ QPI Specification v1.0.0
|
|
141
|
-
# @see https://sashite.dev/specs/qpi/1.0.0/examples/ QPI Examples
|
|
142
|
-
# @see https://sashite.dev/specs/sin/1.0.0/ Style Identifier Notation (SIN)
|
|
143
|
-
# @see https://sashite.dev/specs/pin/1.0.0/ Piece Identifier Notation (PIN)
|
|
56
|
+
# @see https://sashite.dev/specs/qpi/1.0.0/
|
|
144
57
|
module Qpi
|
|
145
|
-
#
|
|
58
|
+
# Parses a QPI string into an Identifier.
|
|
146
59
|
#
|
|
147
|
-
#
|
|
148
|
-
#
|
|
149
|
-
#
|
|
60
|
+
# @param string [String] The QPI string to parse
|
|
61
|
+
# @return [Identifier] A new Identifier instance
|
|
62
|
+
# @raise [Errors::Argument] If the string is not a valid QPI
|
|
150
63
|
#
|
|
151
|
-
# @
|
|
152
|
-
#
|
|
64
|
+
# @example
|
|
65
|
+
# Sashite::Qpi.parse("C:K")
|
|
66
|
+
# # => #<Sashite::Qpi::Identifier C:K>
|
|
153
67
|
#
|
|
154
|
-
#
|
|
155
|
-
#
|
|
156
|
-
# Sashite::Qpi.valid?("c:k") # => true (Chess king, second player)
|
|
157
|
-
# Sashite::Qpi.valid?("O:+P") # => true (Ogi enhanced pawn, first player)
|
|
158
|
-
# Sashite::Qpi.valid?("o:-r") # => true (Ogi diminished rook, second player)
|
|
159
|
-
# Sashite::Qpi.valid?("C:k") # => false (semantic mismatch: first player style, second player piece)
|
|
160
|
-
# Sashite::Qpi.valid?("c:K") # => false (semantic mismatch: second player style, first player piece)
|
|
161
|
-
# Sashite::Qpi.valid?("CHESS:K") # => false (multi-character SIN component)
|
|
162
|
-
# Sashite::Qpi.valid?("C") # => false (missing PIN component)
|
|
163
|
-
def self.valid?(qpi_string)
|
|
164
|
-
Identifier.valid?(qpi_string)
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
# Parse a QPI string into an Identifier object
|
|
68
|
+
# Sashite::Qpi.parse("s:+r^")
|
|
69
|
+
# # => #<Sashite::Qpi::Identifier s:+r^>
|
|
168
70
|
#
|
|
169
|
-
#
|
|
170
|
-
#
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
#
|
|
176
|
-
# @example Parse different QPI formats with complete attribute access
|
|
177
|
-
# Sashite::Qpi.parse("C:K") # => #<Qpi::Identifier family=:C type=:K side=:first state=:normal>
|
|
178
|
-
# Sashite::Qpi.parse("c:k") # => #<Qpi::Identifier family=:C type=:K side=:second state=:normal>
|
|
179
|
-
# Sashite::Qpi.parse("O:+R") # => #<Qpi::Identifier family=:O type=:R side=:first state=:enhanced>
|
|
180
|
-
# Sashite::Qpi.parse("x:-s") # => #<Qpi::Identifier family=:X type=:S side=:second state=:diminished>
|
|
181
|
-
#
|
|
182
|
-
# @example Traditional game styles
|
|
183
|
-
# chess_king = Sashite::Qpi.parse("C:K") # Chess king, first player
|
|
184
|
-
# ogi_rook = Sashite::Qpi.parse("o:+r") # Ogi promoted rook, second player
|
|
185
|
-
# xiongqi_king = Sashite::Qpi.parse("X:K") # Xiongqi king, first player
|
|
186
|
-
def self.parse(qpi_string)
|
|
187
|
-
Identifier.parse(qpi_string)
|
|
71
|
+
# Sashite::Qpi.parse("invalid")
|
|
72
|
+
# # => raises Errors::Argument
|
|
73
|
+
def self.parse(string)
|
|
74
|
+
components = Parser.parse(string)
|
|
75
|
+
|
|
76
|
+
Identifier.new(components[:sin], components[:pin])
|
|
188
77
|
end
|
|
189
78
|
|
|
190
|
-
#
|
|
191
|
-
#
|
|
192
|
-
# Constructs a QPI identifier by directly specifying all four fundamental attributes.
|
|
193
|
-
# This method provides parameter-based construction as an alternative to string parsing,
|
|
194
|
-
# enabling immediate validation and clearer API usage.
|
|
195
|
-
#
|
|
196
|
-
# @param family [Symbol] style family identifier (single ASCII letter as symbol)
|
|
197
|
-
# @param type [Symbol] piece type (:A to :Z)
|
|
198
|
-
# @param side [Symbol] player side (:first or :second)
|
|
199
|
-
# @param state [Symbol] piece state (:normal, :enhanced, or :diminished)
|
|
200
|
-
# @return [Qpi::Identifier] new immutable identifier instance
|
|
201
|
-
# @raise [ArgumentError] if parameters are invalid or semantically inconsistent
|
|
202
|
-
#
|
|
203
|
-
# @example Create identifiers with explicit parameters
|
|
204
|
-
# Sashite::Qpi.identifier(:C, :K, :first, :normal) # => "C:K"
|
|
205
|
-
# Sashite::Qpi.identifier(:c, :K, :second, :normal) # => "c:k"
|
|
206
|
-
# Sashite::Qpi.identifier(:O, :R, :first, :enhanced) # => "O:+R"
|
|
207
|
-
# Sashite::Qpi.identifier(:x, :S, :second, :diminished) # => "x:-s"
|
|
79
|
+
# Checks if a string is a valid QPI notation.
|
|
208
80
|
#
|
|
209
|
-
# @
|
|
210
|
-
#
|
|
211
|
-
# ogi_player = Sashite::Qpi.identifier(:o, :K, :second, :normal) # Ogi king, second player
|
|
81
|
+
# @param string [String] The string to validate
|
|
82
|
+
# @return [Boolean] true if valid, false otherwise
|
|
212
83
|
#
|
|
213
|
-
#
|
|
214
|
-
#
|
|
215
|
-
#
|
|
216
|
-
|
|
217
|
-
|
|
84
|
+
# @example
|
|
85
|
+
# Sashite::Qpi.valid?("C:K") # => true
|
|
86
|
+
# Sashite::Qpi.valid?("s:+r^") # => true
|
|
87
|
+
# Sashite::Qpi.valid?("invalid") # => false
|
|
88
|
+
def self.valid?(string)
|
|
89
|
+
Parser.valid?(string)
|
|
218
90
|
end
|
|
219
91
|
end
|
|
220
92
|
end
|
data/lib/sashite-qpi.rb
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "sashite/qpi"
|
|
4
|
-
|
|
5
|
-
# Sashité namespace for board game notation libraries
|
|
6
|
-
#
|
|
7
|
-
# Sashité provides a collection of libraries for representing and manipulating
|
|
8
|
-
# board game concepts according to the Game Protocol specifications.
|
|
9
|
-
#
|
|
10
|
-
# @see https://sashite.dev/game-protocol/ Game Protocol Foundation
|
|
11
|
-
# @see https://sashite.dev/specs/ Sashité Specifications
|
|
12
|
-
# @author Sashité
|
|
13
|
-
module Sashite
|
|
14
|
-
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sashite-qpi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0
|
|
4
|
+
version: 2.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Cyril Kato
|
|
@@ -15,56 +15,57 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version:
|
|
18
|
+
version: 4.0.0
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version:
|
|
25
|
+
version: 4.0.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: sashite-sin
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
30
|
- - "~>"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version:
|
|
32
|
+
version: 3.0.0
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version:
|
|
40
|
-
description:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
Identifier Notation (PIN) primitives. This gem implements the QPI Specification v1.0.0 with
|
|
44
|
-
a modern Ruby interface featuring immutable identifier objects and functional programming
|
|
45
|
-
principles. QPI enables complete piece identification with all four fundamental attributes
|
|
46
|
-
(family, type, side, state) while supporting cross-style gaming environments. Perfect for
|
|
47
|
-
multi-tradition board games, hybrid gaming systems, and game engines requiring comprehensive
|
|
48
|
-
piece identification across different game styles and traditions.
|
|
39
|
+
version: 3.0.0
|
|
40
|
+
description: QPI (Qualified Piece Identifier) implementation for Ruby. Provides a
|
|
41
|
+
rule-agnostic format for complete piece identification in abstract strategy board
|
|
42
|
+
games by combining SIN and PIN primitives, with Native/Derived relationship support.
|
|
49
43
|
email: contact@cyril.email
|
|
50
44
|
executables: []
|
|
51
45
|
extensions: []
|
|
52
46
|
extra_rdoc_files: []
|
|
53
47
|
files:
|
|
54
|
-
- LICENSE
|
|
48
|
+
- LICENSE
|
|
55
49
|
- README.md
|
|
56
50
|
- lib/sashite-qpi.rb
|
|
57
51
|
- lib/sashite/qpi.rb
|
|
52
|
+
- lib/sashite/qpi/constants.rb
|
|
53
|
+
- lib/sashite/qpi/errors.rb
|
|
54
|
+
- lib/sashite/qpi/errors/argument.rb
|
|
55
|
+
- lib/sashite/qpi/errors/argument/messages.rb
|
|
58
56
|
- lib/sashite/qpi/identifier.rb
|
|
57
|
+
- lib/sashite/qpi/parser.rb
|
|
59
58
|
homepage: https://github.com/sashite/qpi.rb
|
|
60
59
|
licenses:
|
|
61
|
-
-
|
|
60
|
+
- Apache-2.0
|
|
62
61
|
metadata:
|
|
63
62
|
bug_tracker_uri: https://github.com/sashite/qpi.rb/issues
|
|
64
63
|
documentation_uri: https://rubydoc.info/github/sashite/qpi.rb/main
|
|
65
64
|
homepage_uri: https://github.com/sashite/qpi.rb
|
|
66
65
|
source_code_uri: https://github.com/sashite/qpi.rb
|
|
67
66
|
specification_uri: https://sashite.dev/specs/qpi/1.0.0/
|
|
67
|
+
wiki_uri: https://sashite.dev/specs/qpi/1.0.0/examples/
|
|
68
|
+
funding_uri: https://github.com/sponsors/sashite
|
|
68
69
|
rubygems_mfa_required: 'true'
|
|
69
70
|
rdoc_options: []
|
|
70
71
|
require_paths:
|
|
@@ -80,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
80
81
|
- !ruby/object:Gem::Version
|
|
81
82
|
version: '0'
|
|
82
83
|
requirements: []
|
|
83
|
-
rubygems_version:
|
|
84
|
+
rubygems_version: 4.0.3
|
|
84
85
|
specification_version: 4
|
|
85
86
|
summary: QPI (Qualified Piece Identifier) implementation for Ruby with immutable identifier
|
|
86
87
|
objects
|
data/LICENSE.md
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
Copyright (c) 2014-2025 Sashite
|
|
2
|
-
|
|
3
|
-
MIT License
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
-
a copy of this software and associated documentation files (the
|
|
7
|
-
"Software"), to deal in the Software without restriction, including
|
|
8
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
-
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
-
the following conditions:
|
|
12
|
-
|
|
13
|
-
The above copyright notice and this permission notice shall be
|
|
14
|
-
included in all copies or substantial portions of the Software.
|
|
15
|
-
|
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|