Module: Sashite::Qpi
- Defined in:
- lib/sashite/qpi.rb,
lib/sashite/qpi/identifier.rb
Overview
QPI (Qualified Piece Identifier) implementation for Ruby
Provides complete piece identification by combining two primitive notations:
-
SIN (Style Identifier Notation) — identifies the piece style
-
PIN (Piece Identifier Notation) — identifies the piece attributes
A QPI identifier is simply a pair of (SIN, PIN) with one constraint: both components must represent the same player.
## Core Concept
QPI is pure composition:
sin = Sashite::Sin.parse("C")
pin = Sashite::Pin.parse("K^")
qpi = Sashite::Qpi.new(sin, pin)
qpi.to_s # => "C:K^"
qpi.sin # => SIN::Identifier instance
qpi.pin # => PIN::Identifier instance
All piece attributes come from the components.
## Five Fundamental Attributes
QPI exposes all five attributes from the Sashité Game Protocol:
-
**Piece Style** — via qpi.sin.family
-
**Piece Name** — via qpi.pin.type
-
**Piece Side** — via qpi.sin.side or qpi.pin.side
-
**Piece State** — via qpi.pin.state
-
**Terminal Status** — via qpi.pin.terminal?
## Format Specification
Structure: ‘<sin>:<pin>`
Grammar (BNF):
<qpi> ::= <uppercase-qpi> | <lowercase-qpi>
<uppercase-qpi> ::= <uppercase-letter> ":" <uppercase-pin>
<lowercase-qpi> ::= <lowercase-letter> ":" <lowercase-pin>
<uppercase-pin> ::= ["+" | "-"] <uppercase-letter> ["^"]
<lowercase-pin> ::= ["+" | "-"] <lowercase-letter> ["^"]
Regular Expression: ‘/A(:[-+]?[A-Z]^?|:[-+]?[a-z]^?)z/`
## Semantic Constraint
The SIN and PIN components must represent the same player:
-
Valid: “C:K” (both first player), “c:k” (both second player)
-
Invalid: “C:k” (side mismatch), “c:K” (side mismatch)
## Examples
# Parse QPI string
qpi = Sashite::Qpi.parse("C:K^")
qpi.sin.family # => :C (Piece Style)
qpi.pin.type # => :K (Piece Name)
qpi.sin.side # => :first (Piece Side)
qpi.pin.state # => :normal (Piece State)
qpi.pin.terminal? # => true (Terminal Status)
# Create from components
sin = Sashite::Sin.parse("S")
pin = Sashite::Pin.parse("+R^")
qpi = Sashite::Qpi.new(sin, pin)
qpi.to_s # => "S:+R^"
# Transform via components
qpi.with_sin(qpi.sin.with_family(:C)) # => "C:+R^"
qpi.with_pin(qpi.pin.with_type(:B)) # => "S:+B^"
# Flip both components (only convenience method)
qpi.flip # => "s:+r^"
## Design Properties
-
Rule-agnostic: Independent of game mechanics
-
**Pure composition**: Zero feature duplication
-
**Minimal API**: Only 5 core methods
-
**Component transparency**: Direct primitive access
-
Immutable: Frozen instances
-
**Semantic validation**: Automatic side consistency
Defined Under Namespace
Classes: Identifier
Class Method Summary collapse
-
.new(sin, pin) ⇒ Qpi::Identifier
Create a new identifier from SIN and PIN components.
-
.parse(qpi_string) ⇒ Qpi::Identifier
Parse a QPI string into an Identifier object.
-
.valid?(qpi_string) ⇒ Boolean
Check if a string is a valid QPI notation.
Class Method Details
.new(sin, pin) ⇒ Qpi::Identifier
Create a new identifier from SIN and PIN components
131 132 133 |
# File 'lib/sashite/qpi.rb', line 131 def self.new(sin, pin) Identifier.new(sin, pin) end |
.parse(qpi_string) ⇒ Qpi::Identifier
Parse a QPI string into an Identifier object
115 116 117 |
# File 'lib/sashite/qpi.rb', line 115 def self.parse(qpi_string) Identifier.parse(qpi_string) end |
.valid?(qpi_string) ⇒ Boolean
Check if a string is a valid QPI notation
100 101 102 |
# File 'lib/sashite/qpi.rb', line 100 def self.valid?(qpi_string) Identifier.valid?(qpi_string) end |