sashite-qpi 2.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 +208 -491
- 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 +156 -153
- data/lib/sashite/qpi/parser.rb +122 -0
- data/lib/sashite/qpi.rb +57 -100
- data/lib/sashite-qpi.rb +0 -11
- metadata +18 -17
- data/LICENSE.md +0 -22
data/lib/sashite/qpi.rb
CHANGED
|
@@ -1,135 +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
|
-
# - SIN (Style Identifier Notation)
|
|
10
|
-
# - PIN (Piece Identifier Notation)
|
|
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
|
|
11
14
|
#
|
|
12
|
-
#
|
|
13
|
-
# both components must represent the same player.
|
|
15
|
+
# == Format
|
|
14
16
|
#
|
|
15
|
-
#
|
|
17
|
+
# <sin>:<pin>
|
|
16
18
|
#
|
|
17
|
-
#
|
|
19
|
+
# - *SIN*: Single ASCII letter encoding Piece Style and a side tag
|
|
20
|
+
# - *PIN*: Piece identifier with optional state modifier and terminal marker
|
|
18
21
|
#
|
|
19
|
-
#
|
|
20
|
-
# pin = Sashite::Pin.parse("K^")
|
|
21
|
-
# qpi = Sashite::Qpi.new(sin, pin)
|
|
22
|
-
# qpi.to_s # => "C:K^"
|
|
23
|
-
# qpi.sin # => SIN::Identifier instance
|
|
24
|
-
# qpi.pin # => PIN::Identifier instance
|
|
22
|
+
# == Piece Identity Attributes
|
|
25
23
|
#
|
|
26
|
-
#
|
|
24
|
+
# A QPI token encodes complete Piece Identity:
|
|
27
25
|
#
|
|
28
|
-
#
|
|
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 (^)
|
|
29
31
|
#
|
|
30
|
-
#
|
|
31
|
-
# - **Piece Style** — via qpi.sin.family
|
|
32
|
-
# - **Piece Name** — via qpi.pin.type
|
|
33
|
-
# - **Piece Side** — via qpi.sin.side or qpi.pin.side
|
|
34
|
-
# - **Piece State** — via qpi.pin.state
|
|
35
|
-
# - **Terminal Status** — via qpi.pin.terminal?
|
|
32
|
+
# == Native/Derived Relationship
|
|
36
33
|
#
|
|
37
|
-
#
|
|
34
|
+
# QPI defines a deterministic relationship based on case comparison:
|
|
38
35
|
#
|
|
39
|
-
#
|
|
36
|
+
# - *Native*: SIN case matches PIN case (sin.side == pin.side)
|
|
37
|
+
# - *Derived*: SIN case differs from PIN case (sin.side != pin.side)
|
|
40
38
|
#
|
|
41
|
-
#
|
|
42
|
-
# <qpi> ::= <uppercase-qpi> | <lowercase-qpi>
|
|
43
|
-
# <uppercase-qpi> ::= <uppercase-letter> ":" <uppercase-pin>
|
|
44
|
-
# <lowercase-qpi> ::= <lowercase-letter> ":" <lowercase-pin>
|
|
45
|
-
# <uppercase-pin> ::= ["+" | "-"] <uppercase-letter> ["^"]
|
|
46
|
-
# <lowercase-pin> ::= ["+" | "-"] <lowercase-letter> ["^"]
|
|
39
|
+
# == Examples
|
|
47
40
|
#
|
|
48
|
-
# Regular Expression: `/\A([A-Z]:[-+]?[A-Z]\^?|[a-z]:[-+]?[a-z]\^?)\z/`
|
|
49
|
-
#
|
|
50
|
-
# ## Semantic Constraint
|
|
51
|
-
#
|
|
52
|
-
# The SIN and PIN components must represent the same player:
|
|
53
|
-
# - Valid: "C:K" (both first player), "c:k" (both second player)
|
|
54
|
-
# - Invalid: "C:k" (side mismatch), "c:K" (side mismatch)
|
|
55
|
-
#
|
|
56
|
-
# ## Examples
|
|
57
|
-
#
|
|
58
|
-
# # Parse QPI string
|
|
59
41
|
# qpi = Sashite::Qpi.parse("C:K^")
|
|
60
|
-
# qpi.sin.
|
|
61
|
-
# qpi.pin.type
|
|
62
|
-
# qpi.
|
|
63
|
-
# qpi.pin.state
|
|
64
|
-
# qpi.pin.terminal?
|
|
65
|
-
#
|
|
66
|
-
# # Create from components
|
|
67
|
-
# sin = Sashite::Sin.parse("S")
|
|
68
|
-
# pin = Sashite::Pin.parse("+R^")
|
|
69
|
-
# qpi = Sashite::Qpi.new(sin, pin)
|
|
70
|
-
# qpi.to_s # => "S:+R^"
|
|
71
|
-
#
|
|
72
|
-
# # Transform via components
|
|
73
|
-
# qpi.with_sin(qpi.sin.with_family(:C)) # => "C:+R^"
|
|
74
|
-
# qpi.with_pin(qpi.pin.with_type(:B)) # => "S:+B^"
|
|
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
|
|
75
48
|
#
|
|
76
|
-
#
|
|
77
|
-
# qpi.
|
|
49
|
+
# qpi = Sashite::Qpi.parse("C:k")
|
|
50
|
+
# qpi.derived? # => true
|
|
51
|
+
# qpi.native.to_s # => "C:K"
|
|
78
52
|
#
|
|
79
|
-
#
|
|
53
|
+
# Sashite::Qpi.valid?("C:K^") # => true
|
|
54
|
+
# Sashite::Qpi.valid?("invalid") # => false
|
|
80
55
|
#
|
|
81
|
-
#
|
|
82
|
-
# - **Pure composition**: Zero feature duplication
|
|
83
|
-
# - **Minimal API**: Only 5 core methods
|
|
84
|
-
# - **Component transparency**: Direct primitive access
|
|
85
|
-
# - **Immutable**: Frozen instances
|
|
86
|
-
# - **Semantic validation**: Automatic side consistency
|
|
87
|
-
#
|
|
88
|
-
# @see https://sashite.dev/specs/qpi/1.0.0/ QPI Specification v1.0.0
|
|
89
|
-
# @see https://sashite.dev/specs/sin/1.0.0/ Style Identifier Notation (SIN)
|
|
90
|
-
# @see https://sashite.dev/specs/pin/1.0.0/ Piece Identifier Notation (PIN)
|
|
56
|
+
# @see https://sashite.dev/specs/qpi/1.0.0/
|
|
91
57
|
module Qpi
|
|
92
|
-
#
|
|
58
|
+
# Parses a QPI string into an Identifier.
|
|
93
59
|
#
|
|
94
|
-
# @param
|
|
95
|
-
# @return [
|
|
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
|
|
96
63
|
#
|
|
97
64
|
# @example
|
|
98
|
-
# Sashite::Qpi.
|
|
99
|
-
# Sashite::Qpi
|
|
100
|
-
def self.valid?(qpi_string)
|
|
101
|
-
Identifier.valid?(qpi_string)
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# Parse a QPI string into an Identifier object
|
|
65
|
+
# Sashite::Qpi.parse("C:K")
|
|
66
|
+
# # => #<Sashite::Qpi::Identifier C:K>
|
|
105
67
|
#
|
|
106
|
-
#
|
|
107
|
-
#
|
|
108
|
-
# @raise [ArgumentError] if invalid or semantically inconsistent
|
|
68
|
+
# Sashite::Qpi.parse("s:+r^")
|
|
69
|
+
# # => #<Sashite::Qpi::Identifier s:+r^>
|
|
109
70
|
#
|
|
110
|
-
#
|
|
111
|
-
#
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
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])
|
|
117
77
|
end
|
|
118
78
|
|
|
119
|
-
#
|
|
79
|
+
# Checks if a string is a valid QPI notation.
|
|
120
80
|
#
|
|
121
|
-
# @param
|
|
122
|
-
# @
|
|
123
|
-
# @return [Qpi::Identifier] new identifier instance
|
|
124
|
-
# @raise [ArgumentError] if components have different sides
|
|
81
|
+
# @param string [String] The string to validate
|
|
82
|
+
# @return [Boolean] true if valid, false otherwise
|
|
125
83
|
#
|
|
126
84
|
# @example
|
|
127
|
-
#
|
|
128
|
-
#
|
|
129
|
-
#
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
Identifier.new(sin, pin)
|
|
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)
|
|
133
90
|
end
|
|
134
91
|
end
|
|
135
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: 2.
|
|
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.
|