sashite-qpi 2.1.0 → 2.2.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 +1 -1
- data/README.md +30 -30
- data/lib/sashite/qpi/identifier.rb +13 -6
- data/lib/sashite/qpi.rb +2 -2
- metadata +5 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6174ad5c08247b566832cd22236980189b809f445cfca54ecda6f67938a8d9c5
|
|
4
|
+
data.tar.gz: 590406c9c7e14ec79fcb4b522f45b65f0872e88d1e4f3bdde849f4e912673ae6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 343523eefe8442e27e37b7f773a54e7b11925f7125d765ae5e85cfe51b12c453c89129f788c7eced0285cd3011442880bd39b57f113aaa40e91a2ab1f946aa8c
|
|
7
|
+
data.tar.gz: 2f506015f10416d449eae6ef2fd44969c6c36ce5ec2a11ab928798a0cbc7762dda53c30a7ecfa6a8abd207999a0f1819a2115543501caef035917b6788764ac9
|
data/LICENSE
CHANGED
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
same "printed page" as the copyright notice for easier
|
|
187
187
|
identification within third-party archives.
|
|
188
188
|
|
|
189
|
-
Copyright 2025 Cyril Kato
|
|
189
|
+
Copyright 2025-2026 Cyril Kato
|
|
190
190
|
|
|
191
191
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
192
|
you may not use this file except in compliance with the License.
|
data/README.md
CHANGED
|
@@ -51,8 +51,8 @@ qpi = Sashite::Qpi.parse("C:K^")
|
|
|
51
51
|
qpi.to_s # => "C:K^"
|
|
52
52
|
|
|
53
53
|
# Access the five Piece Identity attributes through components
|
|
54
|
-
qpi.sin.
|
|
55
|
-
qpi.pin.
|
|
54
|
+
qpi.sin.abbr # => :C (Piece Style)
|
|
55
|
+
qpi.pin.abbr # => :K (Piece Name)
|
|
56
56
|
qpi.pin.side # => :first (Piece Side)
|
|
57
57
|
qpi.pin.state # => :normal (Piece State)
|
|
58
58
|
qpi.pin.terminal? # => true (Terminal Status)
|
|
@@ -100,8 +100,8 @@ Sashite::Qpi.valid?(":K") # => false
|
|
|
100
100
|
qpi = Sashite::Qpi.parse("S:+R^")
|
|
101
101
|
|
|
102
102
|
# Get components
|
|
103
|
-
qpi.sin # => #<Sashite::Sin::Identifier
|
|
104
|
-
qpi.pin # => #<Sashite::Pin::Identifier
|
|
103
|
+
qpi.sin # => #<Sashite::Sin::Identifier S>
|
|
104
|
+
qpi.pin # => #<Sashite::Pin::Identifier +R^>
|
|
105
105
|
|
|
106
106
|
# Serialize components
|
|
107
107
|
qpi.sin.to_s # => "S"
|
|
@@ -117,10 +117,10 @@ All attributes come directly from the components:
|
|
|
117
117
|
qpi = Sashite::Qpi.parse("S:+R^")
|
|
118
118
|
|
|
119
119
|
# From SIN component
|
|
120
|
-
qpi.sin.
|
|
120
|
+
qpi.sin.abbr # => :S (Piece Style)
|
|
121
121
|
|
|
122
122
|
# From PIN component
|
|
123
|
-
qpi.pin.
|
|
123
|
+
qpi.pin.abbr # => :R (Piece Name)
|
|
124
124
|
qpi.pin.side # => :first (Piece Side)
|
|
125
125
|
qpi.pin.state # => :enhanced (Piece State)
|
|
126
126
|
qpi.pin.terminal? # => true (Terminal Status)
|
|
@@ -165,10 +165,10 @@ qpi.with_pin(new_pin).to_s # => "C:+Q^"
|
|
|
165
165
|
# Transform both
|
|
166
166
|
qpi.with_sin(new_sin).with_pin(new_pin).to_s # => "S:+Q^"
|
|
167
167
|
|
|
168
|
-
# Flip
|
|
169
|
-
qpi.flip.to_s # => "
|
|
168
|
+
# Flip PIN side (SIN unchanged)
|
|
169
|
+
qpi.flip.to_s # => "C:k^"
|
|
170
170
|
|
|
171
|
-
# Native/Derived transformations
|
|
171
|
+
# Native/Derived transformations (modify PIN only)
|
|
172
172
|
qpi = Sashite::Qpi.parse("C:r")
|
|
173
173
|
qpi.native.to_s # => "C:R" (PIN case aligned with SIN case)
|
|
174
174
|
qpi.derive.to_s # => "C:r" (already derived, unchanged)
|
|
@@ -183,16 +183,16 @@ qpi.derive.to_s # => "C:r" (PIN case differs from SIN case)
|
|
|
183
183
|
```ruby
|
|
184
184
|
qpi = Sashite::Qpi.parse("C:K^")
|
|
185
185
|
|
|
186
|
-
# Transform SIN via component
|
|
187
|
-
qpi.with_sin(qpi.sin.with_style(:S)).to_s # => "S:K^"
|
|
188
|
-
|
|
189
186
|
# Transform PIN via component
|
|
190
|
-
qpi.with_pin(qpi.pin.
|
|
191
|
-
qpi.with_pin(qpi.pin.with_state(:enhanced)).to_s
|
|
192
|
-
qpi.with_pin(qpi.pin.with_terminal(false)).to_s
|
|
187
|
+
qpi.with_pin(qpi.pin.with_abbr(:Q)).to_s # => "C:Q^"
|
|
188
|
+
qpi.with_pin(qpi.pin.with_state(:enhanced)).to_s # => "C:+K^"
|
|
189
|
+
qpi.with_pin(qpi.pin.with_terminal(false)).to_s # => "C:K"
|
|
190
|
+
|
|
191
|
+
# Replace SIN with new instance
|
|
192
|
+
qpi.with_sin(Sashite::Sin.parse("S")).to_s # => "S:K^"
|
|
193
193
|
|
|
194
194
|
# Chain transformations
|
|
195
|
-
qpi.flip.with_sin(
|
|
195
|
+
qpi.flip.with_sin(Sashite::Sin.parse("c")).to_s # => "c:k^"
|
|
196
196
|
```
|
|
197
197
|
|
|
198
198
|
### Component Queries
|
|
@@ -203,13 +203,13 @@ Since QPI is a composition, use the component APIs directly:
|
|
|
203
203
|
qpi = Sashite::Qpi.parse("S:+P^")
|
|
204
204
|
|
|
205
205
|
# SIN queries (style and side)
|
|
206
|
-
qpi.sin.
|
|
206
|
+
qpi.sin.abbr # => :S
|
|
207
207
|
qpi.sin.side # => :first
|
|
208
208
|
qpi.sin.first_player? # => true
|
|
209
|
-
qpi.sin.
|
|
209
|
+
qpi.sin.to_s # => "S"
|
|
210
210
|
|
|
211
|
-
# PIN queries (
|
|
212
|
-
qpi.pin.
|
|
211
|
+
# PIN queries (abbr, state, terminal)
|
|
212
|
+
qpi.pin.abbr # => :P
|
|
213
213
|
qpi.pin.state # => :enhanced
|
|
214
214
|
qpi.pin.terminal? # => true
|
|
215
215
|
qpi.pin.enhanced? # => true
|
|
@@ -219,10 +219,10 @@ qpi.pin.suffix # => "^"
|
|
|
219
219
|
|
|
220
220
|
# Compare QPIs via components
|
|
221
221
|
other = Sashite::Qpi.parse("C:+P^")
|
|
222
|
-
qpi.sin.
|
|
223
|
-
qpi.pin.
|
|
224
|
-
qpi.sin.same_side?(other.sin)
|
|
225
|
-
qpi.pin.same_state?(other.pin)
|
|
222
|
+
qpi.sin.same_abbr?(other.sin) # => false (S vs C)
|
|
223
|
+
qpi.pin.same_abbr?(other.pin) # => true (both P)
|
|
224
|
+
qpi.sin.same_side?(other.sin) # => true (both first)
|
|
225
|
+
qpi.pin.same_state?(other.pin) # => true (both enhanced)
|
|
226
226
|
```
|
|
227
227
|
|
|
228
228
|
## API Reference
|
|
@@ -296,10 +296,10 @@ def Sashite::Qpi.valid?(string)
|
|
|
296
296
|
def with_sin(new_sin) # => Identifier with different SIN
|
|
297
297
|
def with_pin(new_pin) # => Identifier with different PIN
|
|
298
298
|
|
|
299
|
-
# Flip transformation (
|
|
300
|
-
def flip # => Identifier with
|
|
299
|
+
# Flip transformation (modifies PIN only)
|
|
300
|
+
def flip # => Identifier with PIN side flipped
|
|
301
301
|
|
|
302
|
-
# Native/Derived transformations
|
|
302
|
+
# Native/Derived transformations (modify PIN only)
|
|
303
303
|
def native # => Identifier with PIN case aligned to SIN case
|
|
304
304
|
def derive # => Identifier with PIN case opposite to SIN case
|
|
305
305
|
```
|
|
@@ -323,8 +323,8 @@ QPI encodes complete **Piece Identity** as defined in the [Glossary](https://sas
|
|
|
323
323
|
|
|
324
324
|
| Piece Attribute | QPI Access | Encoding |
|
|
325
325
|
|---------------------|----------------------|--------------------------------------------------------|
|
|
326
|
-
| **Piece Style** | `qpi.sin.
|
|
327
|
-
| **Piece Name** | `qpi.pin.
|
|
326
|
+
| **Piece Style** | `qpi.sin.abbr` | SIN letter (case-insensitive identity) |
|
|
327
|
+
| **Piece Name** | `qpi.pin.abbr` | PIN letter (case-insensitive identity) |
|
|
328
328
|
| **Piece Side** | `qpi.pin.side` | PIN letter case (uppercase = first, lowercase = second)|
|
|
329
329
|
| **Piece State** | `qpi.pin.state` | PIN modifier (`+` = enhanced, `-` = diminished) |
|
|
330
330
|
| **Terminal Status** | `qpi.pin.terminal?` | PIN marker (`^` = terminal) |
|
|
@@ -336,7 +336,7 @@ Additionally, QPI provides a **Native/Derived relationship** via `native?`, `der
|
|
|
336
336
|
- **Pure composition**: QPI composes SIN and PIN without reimplementing features
|
|
337
337
|
- **Minimal API**: Core methods (`sin`, `pin`, `native?`, `derived?`, `native`, `derive`, `to_s`) plus transformations
|
|
338
338
|
- **Component transparency**: Access components directly, no wrapper methods
|
|
339
|
-
- **QPI-specific conveniences**: `flip`, `native`, `derive` (operations that
|
|
339
|
+
- **QPI-specific conveniences**: `flip`, `native`, `derive` (operations that modify PIN only, per spec)
|
|
340
340
|
- **Immutable identifiers**: Frozen instances prevent mutation
|
|
341
341
|
- **Ruby idioms**: `valid?` predicate, `to_s` conversion, `ArgumentError` for invalid input
|
|
342
342
|
- **No duplication**: Delegates to `sashite-sin` and `sashite-pin`
|
|
@@ -22,8 +22,8 @@ module Sashite
|
|
|
22
22
|
# qpi = Identifier.new(sin, pin)
|
|
23
23
|
#
|
|
24
24
|
# @example Accessing components
|
|
25
|
-
# qpi.sin.
|
|
26
|
-
# qpi.pin.
|
|
25
|
+
# qpi.sin.abbr # => :C
|
|
26
|
+
# qpi.pin.abbr # => :K
|
|
27
27
|
# qpi.pin.side # => :first
|
|
28
28
|
# qpi.pin.state # => :normal
|
|
29
29
|
# qpi.pin.terminal? # => true
|
|
@@ -181,15 +181,22 @@ module Sashite
|
|
|
181
181
|
self.class.new(sin, new_pin)
|
|
182
182
|
end
|
|
183
183
|
|
|
184
|
-
# Returns a new Identifier with
|
|
184
|
+
# Returns a new Identifier with PIN side flipped.
|
|
185
185
|
#
|
|
186
|
-
#
|
|
186
|
+
# The SIN component remains unchanged. This reflects the QPI specification
|
|
187
|
+
# constraint that SIN (Player Style + Player Side) is stable within a Match,
|
|
188
|
+
# while PIN side (Piece Side) may change via Mutation.
|
|
189
|
+
#
|
|
190
|
+
# @return [Identifier] A new Identifier with PIN side flipped
|
|
187
191
|
#
|
|
188
192
|
# @example
|
|
189
193
|
# qpi = Identifier.new(Sin.parse("C"), Pin.parse("K^"))
|
|
190
|
-
# qpi.flip.to_s # => "
|
|
194
|
+
# qpi.flip.to_s # => "C:k^"
|
|
195
|
+
#
|
|
196
|
+
# qpi = Identifier.new(Sin.parse("c"), Pin.parse("r"))
|
|
197
|
+
# qpi.flip.to_s # => "c:R"
|
|
191
198
|
def flip
|
|
192
|
-
self.class.new(sin
|
|
199
|
+
self.class.new(sin, pin.flip)
|
|
193
200
|
end
|
|
194
201
|
|
|
195
202
|
# ========================================================================
|
data/lib/sashite/qpi.rb
CHANGED
|
@@ -39,8 +39,8 @@ module Sashite
|
|
|
39
39
|
# == Examples
|
|
40
40
|
#
|
|
41
41
|
# qpi = Sashite::Qpi.parse("C:K^")
|
|
42
|
-
# qpi.sin.
|
|
43
|
-
# qpi.pin.
|
|
42
|
+
# qpi.sin.abbr # => :C
|
|
43
|
+
# qpi.pin.abbr # => :K
|
|
44
44
|
# qpi.pin.side # => :first
|
|
45
45
|
# qpi.pin.state # => :normal
|
|
46
46
|
# qpi.pin.terminal? # => true
|
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.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Cyril Kato
|
|
@@ -15,28 +15,28 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 4.
|
|
18
|
+
version: 4.1.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: 4.
|
|
25
|
+
version: 4.1.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: 3.
|
|
32
|
+
version: 3.1.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: 3.
|
|
39
|
+
version: 3.1.0
|
|
40
40
|
description: QPI (Qualified Piece Identifier) implementation for Ruby. Provides a
|
|
41
41
|
rule-agnostic format for complete piece identification in abstract strategy board
|
|
42
42
|
games by combining SIN and PIN primitives, with Native/Derived relationship support.
|