Class: Sashite::Epin::Identifier
- Inherits:
-
Object
- Object
- Sashite::Epin::Identifier
- Defined in:
- lib/sashite/epin/identifier.rb
Overview
Represents an identifier in EPIN (Extended Piece Identifier Notation) format.
An identifier consists of a PIN component with an optional derivation marker:
-
PIN component: [<state>]<letter> (from PIN specification)
-
Derivation marker: “‘” (foreign style) or none (native style)
The case of the letter determines ownership:
-
Uppercase (A-Z): first player
-
Lowercase (a-z): second player
Style derivation logic:
-
No suffix: piece has the native style of its current side
-
Apostrophe suffix: piece has the foreign style (opposite side’s native style)
All instances are immutable - state manipulation methods return new instances. This extends the Game Protocol’s piece model with Style support through derivation.
Constant Summary collapse
- DERIVATION_SUFFIX =
Valid derivation suffixes
"'"
- NATIVE_SUFFIX =
""
- NATIVE =
Derivation constants
true
- FOREIGN =
false
- VALID_DERIVATIONS =
Valid derivations
[NATIVE, FOREIGN].freeze
- ERROR_INVALID_EPIN =
Error messages
"Invalid EPIN string: %s"
- ERROR_INVALID_DERIVATION =
"Derivation must be true (native) or false (foreign), got: %s"
Instance Attribute Summary collapse
-
#native ⇒ Boolean
readonly
The style derivation (true for native, false for foreign).
Class Method Summary collapse
-
.parse(epin_string) ⇒ Identifier
Parse an EPIN string into an Identifier object.
-
.valid?(epin_string) ⇒ Boolean
Check if a string is a valid EPIN notation.
-
.validate_derivation(derivation) ⇒ Object
Validate that the derivation is a valid boolean.
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
(also: #eql?)
Custom equality comparison.
-
#derive ⇒ Identifier
Create a new identifier with foreign style (derivation marker).
-
#derived? ⇒ Boolean
(also: #foreign?)
Check if the identifier has foreign style (derivation marker).
-
#diminish ⇒ Identifier
Create a new identifier with diminished state.
-
#diminished? ⇒ Boolean
Check if the identifier has diminished state.
-
#enhance ⇒ Identifier
Create a new identifier with enhanced state.
-
#enhanced? ⇒ Boolean
Check if the identifier has enhanced state.
-
#first_player? ⇒ Boolean
Check if the identifier belongs to the first player.
-
#flip ⇒ Identifier
Create a new identifier with opposite side.
-
#hash ⇒ Integer
Custom hash implementation for use in collections.
-
#initialize(type, side, state = Pin::Identifier::NORMAL_STATE, native = NATIVE) ⇒ Identifier
constructor
Create a new identifier instance.
-
#letter ⇒ String
Get the letter representation (inherited from PIN logic).
-
#native? ⇒ Boolean
Check if the identifier has native style (no derivation marker).
-
#normal? ⇒ Boolean
Check if the identifier has normal state (no modifiers).
-
#normalize ⇒ Identifier
Create a new identifier with normal state (no modifiers).
-
#prefix ⇒ String
Get the prefix representation (inherited from PIN logic).
-
#same_side?(other) ⇒ Boolean
Check if this identifier belongs to the same side as another.
-
#same_state?(other) ⇒ Boolean
Check if this identifier has the same state as another.
-
#same_style?(other) ⇒ Boolean
Check if this identifier has the same style derivation as another.
-
#same_type?(other) ⇒ Boolean
Check if this identifier is the same type as another (ignoring side, state, and derivation).
-
#second_player? ⇒ Boolean
Check if the identifier belongs to the second player.
-
#side ⇒ Symbol
The player side (:first or :second).
-
#state ⇒ Symbol
The piece state (:normal, :enhanced, or :diminished).
-
#suffix ⇒ String
Get the suffix representation.
-
#to_s ⇒ String
Convert the identifier to its EPIN string representation.
-
#type ⇒ Symbol
The piece type (:A to :Z).
-
#underive ⇒ Identifier
Create a new identifier with native style (no derivation marker).
-
#undiminish ⇒ Identifier
Create a new identifier without diminished state.
-
#unenhance ⇒ Identifier
Create a new identifier without enhanced state.
-
#with_derivation(new_native) ⇒ Identifier
Create a new identifier with a different derivation (keeping same type, side, and state).
-
#with_side(new_side) ⇒ Identifier
Create a new identifier with a different side (keeping same type, state, and derivation).
-
#with_state(new_state) ⇒ Identifier
Create a new identifier with a different state (keeping same type, side, and derivation).
-
#with_type(new_type) ⇒ Identifier
Create a new identifier with a different type (keeping same side, state, and derivation).
Constructor Details
#initialize(type, side, state = Pin::Identifier::NORMAL_STATE, native = NATIVE) ⇒ Identifier
Create a new identifier instance
67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/sashite/epin/identifier.rb', line 67 def initialize(type, side, state = Pin::Identifier::NORMAL_STATE, native = NATIVE) # Validate using PIN class methods for type, side, and state Pin::Identifier.validate_type(type) Pin::Identifier.validate_side(side) Pin::Identifier.validate_state(state) self.class.validate_derivation(native) @pin_identifier = Pin::Identifier.new(type, side, state) @native = native freeze end |
Instance Attribute Details
#native ⇒ Boolean (readonly)
Returns the style derivation (true for native, false for foreign).
55 56 57 |
# File 'lib/sashite/epin/identifier.rb', line 55 def native @native end |
Class Method Details
.parse(epin_string) ⇒ Identifier
Parse an EPIN string into an Identifier object
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/sashite/epin/identifier.rb', line 89 def self.parse(epin_string) string_value = String(epin_string) # Check for derivation suffix if string_value.end_with?(DERIVATION_SUFFIX) pin_part = string_value[0...-1] # Remove the apostrophe foreign = true else pin_part = string_value foreign = false end # Validate and parse the PIN part using existing PIN logic raise ::ArgumentError, format(ERROR_INVALID_EPIN, string_value) unless Pin::Identifier.valid?(pin_part) pin_identifier = Pin::Identifier.parse(pin_part) identifier_native = !foreign new(pin_identifier.type, pin_identifier.side, pin_identifier.state, identifier_native) end |
.valid?(epin_string) ⇒ Boolean
Check if a string is a valid EPIN notation
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/sashite/epin/identifier.rb', line 121 def self.valid?(epin_string) return false unless epin_string.is_a?(::String) return false if epin_string.empty? # Check for derivation suffix if epin_string.end_with?(DERIVATION_SUFFIX) pin_part = epin_string[0...-1] # Remove the apostrophe return false if pin_part.empty? # Can't have just an apostrophe else pin_part = epin_string end # Validate the PIN part using existing PIN validation Pin::Identifier.valid?(pin_part) end |
.validate_derivation(derivation) ⇒ Object
Validate that the derivation is a valid boolean
425 426 427 428 429 |
# File 'lib/sashite/epin/identifier.rb', line 425 def self.validate_derivation(derivation) return if VALID_DERIVATIONS.include?(derivation) raise ::ArgumentError, format(ERROR_INVALID_DERIVATION, derivation.inspect) end |
Instance Method Details
#==(other) ⇒ Boolean Also known as: eql?
Custom equality comparison
405 406 407 408 409 |
# File 'lib/sashite/epin/identifier.rb', line 405 def ==(other) return false unless other.is_a?(self.class) @pin_identifier == other.instance_variable_get(:@pin_identifier) && native == other.native end |
#derive ⇒ Identifier
Create a new identifier with foreign style (derivation marker)
238 239 240 241 242 |
# File 'lib/sashite/epin/identifier.rb', line 238 def derive return self if derived? self.class.new(type, side, state, FOREIGN) end |
#derived? ⇒ Boolean Also known as: foreign?
Check if the identifier has foreign style (derivation marker)
352 353 354 |
# File 'lib/sashite/epin/identifier.rb', line 352 def derived? native == FOREIGN end |
#diminish ⇒ Identifier
Create a new identifier with diminished state
196 197 198 199 200 |
# File 'lib/sashite/epin/identifier.rb', line 196 def diminish return self if diminished? self.class.new(type, side, Pin::Identifier::DIMINISHED_STATE, native) end |
#diminished? ⇒ Boolean
Check if the identifier has diminished state
317 318 319 |
# File 'lib/sashite/epin/identifier.rb', line 317 def diminished? @pin_identifier.diminished? end |
#enhance ⇒ Identifier
Create a new identifier with enhanced state
174 175 176 177 178 |
# File 'lib/sashite/epin/identifier.rb', line 174 def enhance return self if enhanced? self.class.new(type, side, Pin::Identifier::ENHANCED_STATE, native) end |
#enhanced? ⇒ Boolean
Check if the identifier has enhanced state
310 311 312 |
# File 'lib/sashite/epin/identifier.rb', line 310 def enhanced? @pin_identifier.enhanced? end |
#first_player? ⇒ Boolean
Check if the identifier belongs to the first player
331 332 333 |
# File 'lib/sashite/epin/identifier.rb', line 331 def first_player? @pin_identifier.first_player? end |
#flip ⇒ Identifier
Create a new identifier with opposite side
229 230 231 |
# File 'lib/sashite/epin/identifier.rb', line 229 def flip self.class.new(type, opposite_side, state, native) end |
#hash ⇒ Integer
Custom hash implementation for use in collections
417 418 419 |
# File 'lib/sashite/epin/identifier.rb', line 417 def hash [self.class, @pin_identifier, native].hash end |
#letter ⇒ String
Get the letter representation (inherited from PIN logic)
151 152 153 |
# File 'lib/sashite/epin/identifier.rb', line 151 def letter @pin_identifier.letter end |
#native? ⇒ Boolean
Check if the identifier has native style (no derivation marker)
345 346 347 |
# File 'lib/sashite/epin/identifier.rb', line 345 def native? native == NATIVE end |
#normal? ⇒ Boolean
Check if the identifier has normal state (no modifiers)
324 325 326 |
# File 'lib/sashite/epin/identifier.rb', line 324 def normal? @pin_identifier.normal? end |
#normalize ⇒ Identifier
Create a new identifier with normal state (no modifiers)
218 219 220 221 222 |
# File 'lib/sashite/epin/identifier.rb', line 218 def normalize return self if normal? self.class.new(type, side, Pin::Identifier::NORMAL_STATE, native) end |
#prefix ⇒ String
Get the prefix representation (inherited from PIN logic)
158 159 160 |
# File 'lib/sashite/epin/identifier.rb', line 158 def prefix @pin_identifier.prefix end |
#same_side?(other) ⇒ Boolean
Check if this identifier belongs to the same side as another
375 376 377 378 379 |
# File 'lib/sashite/epin/identifier.rb', line 375 def same_side?(other) return false unless other.is_a?(self.class) @pin_identifier.same_side?(other.instance_variable_get(:@pin_identifier)) end |
#same_state?(other) ⇒ Boolean
Check if this identifier has the same state as another
385 386 387 388 389 |
# File 'lib/sashite/epin/identifier.rb', line 385 def same_state?(other) return false unless other.is_a?(self.class) @pin_identifier.same_state?(other.instance_variable_get(:@pin_identifier)) end |
#same_style?(other) ⇒ Boolean
Check if this identifier has the same style derivation as another
395 396 397 398 399 |
# File 'lib/sashite/epin/identifier.rb', line 395 def same_style?(other) return false unless other.is_a?(self.class) native == other.native end |
#same_type?(other) ⇒ Boolean
Check if this identifier is the same type as another (ignoring side, state, and derivation)
365 366 367 368 369 |
# File 'lib/sashite/epin/identifier.rb', line 365 def same_type?(other) return false unless other.is_a?(self.class) @pin_identifier.same_type?(other.instance_variable_get(:@pin_identifier)) end |
#second_player? ⇒ Boolean
Check if the identifier belongs to the second player
338 339 340 |
# File 'lib/sashite/epin/identifier.rb', line 338 def second_player? @pin_identifier.second_player? end |
#side ⇒ Symbol
Returns the player side (:first or :second).
45 46 47 |
# File 'lib/sashite/epin/identifier.rb', line 45 def side @pin_identifier.side end |
#state ⇒ Symbol
Returns the piece state (:normal, :enhanced, or :diminished).
50 51 52 |
# File 'lib/sashite/epin/identifier.rb', line 50 def state @pin_identifier.state end |
#suffix ⇒ String
Get the suffix representation
165 166 167 |
# File 'lib/sashite/epin/identifier.rb', line 165 def suffix native? ? NATIVE_SUFFIX : DERIVATION_SUFFIX end |
#to_s ⇒ String
Convert the identifier to its EPIN string representation
144 145 146 |
# File 'lib/sashite/epin/identifier.rb', line 144 def to_s "#{prefix}#{letter}#{suffix}" end |
#type ⇒ Symbol
Returns the piece type (:A to :Z).
40 41 42 |
# File 'lib/sashite/epin/identifier.rb', line 40 def type @pin_identifier.type end |
#underive ⇒ Identifier
Create a new identifier with native style (no derivation marker)
249 250 251 252 253 |
# File 'lib/sashite/epin/identifier.rb', line 249 def underive return self if native? self.class.new(type, side, state, NATIVE) end |
#undiminish ⇒ Identifier
Create a new identifier without diminished state
207 208 209 210 211 |
# File 'lib/sashite/epin/identifier.rb', line 207 def undiminish return self unless diminished? self.class.new(type, side, Pin::Identifier::NORMAL_STATE, native) end |
#unenhance ⇒ Identifier
Create a new identifier without enhanced state
185 186 187 188 189 |
# File 'lib/sashite/epin/identifier.rb', line 185 def unenhance return self unless enhanced? self.class.new(type, side, Pin::Identifier::NORMAL_STATE, native) end |
#with_derivation(new_native) ⇒ Identifier
Create a new identifier with a different derivation (keeping same type, side, and state)
300 301 302 303 304 305 |
# File 'lib/sashite/epin/identifier.rb', line 300 def with_derivation(new_native) self.class.validate_derivation(new_native) return self if native == new_native self.class.new(type, side, state, new_native) end |
#with_side(new_side) ⇒ Identifier
Create a new identifier with a different side (keeping same type, state, and derivation)
274 275 276 277 278 279 |
# File 'lib/sashite/epin/identifier.rb', line 274 def with_side(new_side) Pin::Identifier.validate_side(new_side) return self if side == new_side self.class.new(type, new_side, state, native) end |
#with_state(new_state) ⇒ Identifier
Create a new identifier with a different state (keeping same type, side, and derivation)
287 288 289 290 291 292 |
# File 'lib/sashite/epin/identifier.rb', line 287 def with_state(new_state) Pin::Identifier.validate_state(new_state) return self if state == new_state self.class.new(type, side, new_state, native) end |
#with_type(new_type) ⇒ Identifier
Create a new identifier with a different type (keeping same side, state, and derivation)
261 262 263 264 265 266 |
# File 'lib/sashite/epin/identifier.rb', line 261 def with_type(new_type) Pin::Identifier.validate_type(new_type) return self if type == new_type self.class.new(new_type, side, state, native) end |