Class: Sashite::Lcn::Conditions
- Inherits:
-
Object
- Object
- Sashite::Lcn::Conditions
- Includes:
- Enumerable
- Defined in:
- lib/sashite/lcn/conditions.rb
Overview
Represents a set of location conditions in LCN format
This class provides an immutable, functional interface for working with location conditions. All instances are frozen after creation to ensure thread safety and prevent accidental mutations.
Conditions are stored internally with symbol keys for Ruby idiomatic access while supporting flexible input formats (string or symbol keys).
Constant Summary collapse
- EMPTY_KEYWORD =
Reserved keywords from LCN specification
"empty"
- ENEMY_KEYWORD =
"enemy"
- RESERVED_KEYWORDS =
[EMPTY_KEYWORD, ENEMY_KEYWORD].freeze
- ERROR_INVALID_LOCATION =
Error messages
"Invalid CELL coordinate: %s"
- ERROR_INVALID_STATE =
"Invalid state value: %s"
- ERROR_NOT_HASH =
"Conditions data must be a Hash"
Class Method Summary collapse
-
.parse(data) ⇒ Conditions
Parse and create a Conditions instance from raw data.
-
.valid_state_value?(value) ⇒ Boolean
Check if a state value is valid (class method for internal use).
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
(also: #eql?)
Check equality with another Conditions instance.
-
#[](location) ⇒ String?
Get state value for a location.
-
#each {|location, state_value| ... } ⇒ Enumerator
Iterate over location-state pairs.
-
#each_location {|location| ... } ⇒ Enumerator
Iterate over locations only.
-
#each_state_value {|state_value| ... } ⇒ Enumerator
Iterate over state values only.
-
#empty? ⇒ Boolean
Check if no conditions are specified.
-
#empty_locations ⇒ Array<Symbol>
Get locations requiring empty state.
-
#enemy_locations ⇒ Array<Symbol>
Get locations requiring enemy pieces.
-
#hash ⇒ Integer
Generate hash code for use in Hash and Set.
-
#initialize(**conditions_hash) ⇒ Conditions
constructor
Create a new Conditions instance.
-
#inspect ⇒ String
String representation for debugging.
-
#keywords ⇒ Array<String>
Get array of keyword state values used.
-
#keywords? ⇒ Boolean
Check if any keywords are used.
-
#location?(location) ⇒ Boolean
Check if location has a condition.
-
#locations ⇒ Array<Symbol>
Get array of all location symbols.
-
#piece_locations ⇒ Array<Symbol>
Get locations requiring specific pieces.
-
#qpi_identifiers ⇒ Array<String>
Get array of QPI identifiers used.
-
#qpi_identifiers? ⇒ Boolean
Check if any QPI identifiers are used.
-
#size ⇒ Integer
Get number of conditions.
-
#to_h ⇒ Hash
Convert to hash with symbol keys.
-
#to_s ⇒ String
String representation.
-
#valid_location?(location) ⇒ Boolean
Check if location uses valid CELL coordinate.
-
#valid_state_value?(value) ⇒ Boolean
Check if state value is valid.
Constructor Details
#initialize(**conditions_hash) ⇒ Conditions
The hash is duplicated and frozen to ensure immutability
Create a new Conditions instance
58 59 60 61 62 |
# File 'lib/sashite/lcn/conditions.rb', line 58 def initialize(**conditions_hash) # Deep duplicate to ensure complete isolation @conditions = conditions_hash.dup.freeze freeze end |
Class Method Details
.parse(data) ⇒ Conditions
Parse and create a Conditions instance from raw data
Accepts both string and symbol keys, normalizing to symbols internally. Validates all locations and state values before creating the instance.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/sashite/lcn/conditions.rb', line 84 def self.parse(data) raise ArgumentError, ERROR_NOT_HASH unless data.is_a?(Hash) validated = {} data.each do |location, state_value| location_str = location.to_s raise ArgumentError, format(ERROR_INVALID_LOCATION, location_str) unless Cell.valid?(location_str) raise ArgumentError, format(ERROR_INVALID_STATE, state_value) unless valid_state_value?(state_value) validated[location_str.to_sym] = state_value end new(**validated) end |
.valid_state_value?(value) ⇒ Boolean
Check if a state value is valid (class method for internal use)
318 319 320 321 322 323 324 325 326 |
# File 'lib/sashite/lcn/conditions.rb', line 318 def self.valid_state_value?(value) return false unless value.is_a?(String) # Check if it's a reserved keyword return true if RESERVED_KEYWORDS.include?(value) # Otherwise, check if it's a valid QPI identifier Qpi.valid?(value) end |
Instance Method Details
#==(other) ⇒ Boolean Also known as: eql?
Check equality with another Conditions instance
284 285 286 287 288 |
# File 'lib/sashite/lcn/conditions.rb', line 284 def ==(other) return false unless other.is_a?(self.class) @conditions == other.to_h end |
#[](location) ⇒ String?
Get state value for a location
118 119 120 |
# File 'lib/sashite/lcn/conditions.rb', line 118 def [](location) @conditions[location.to_sym] end |
#each {|location, state_value| ... } ⇒ Enumerator
Iterate over location-state pairs
242 243 244 245 246 |
# File 'lib/sashite/lcn/conditions.rb', line 242 def each(&) return enum_for(:each) unless block_given? @conditions.each(&) end |
#each_location {|location| ... } ⇒ Enumerator
Iterate over locations only
258 259 260 261 262 |
# File 'lib/sashite/lcn/conditions.rb', line 258 def each_location(&) return enum_for(:each_location) unless block_given? @conditions.each_key(&) end |
#each_state_value {|state_value| ... } ⇒ Enumerator
Iterate over state values only
274 275 276 277 278 |
# File 'lib/sashite/lcn/conditions.rb', line 274 def each_state_value(&) return enum_for(:each_state_value) unless block_given? @conditions.each_value(&) end |
#empty? ⇒ Boolean
Check if no conditions are specified
139 140 141 |
# File 'lib/sashite/lcn/conditions.rb', line 139 def empty? @conditions.empty? end |
#empty_locations ⇒ Array<Symbol>
Get locations requiring empty state
207 208 209 |
# File 'lib/sashite/lcn/conditions.rb', line 207 def empty_locations @conditions.select { |_, v| v == EMPTY_KEYWORD }.keys end |
#enemy_locations ⇒ Array<Symbol>
Get locations requiring enemy pieces
217 218 219 |
# File 'lib/sashite/lcn/conditions.rb', line 217 def enemy_locations @conditions.select { |_, v| v == ENEMY_KEYWORD }.keys end |
#hash ⇒ Integer
Generate hash code for use in Hash and Set
296 297 298 |
# File 'lib/sashite/lcn/conditions.rb', line 296 def hash [self.class, @conditions].hash end |
#inspect ⇒ String
String representation for debugging
303 304 305 |
# File 'lib/sashite/lcn/conditions.rb', line 303 def inspect "#<#{self.class.name} #{@conditions.inspect}>" end |
#keywords ⇒ Array<String>
Get array of keyword state values used
173 174 175 |
# File 'lib/sashite/lcn/conditions.rb', line 173 def keywords @conditions.values.select { |v| RESERVED_KEYWORDS.include?(v) }.uniq end |
#keywords? ⇒ Boolean
Check if any keywords are used
190 191 192 |
# File 'lib/sashite/lcn/conditions.rb', line 190 def keywords? @conditions.values.any? { |v| RESERVED_KEYWORDS.include?(v) } end |
#location?(location) ⇒ Boolean
Check if location has a condition
147 148 149 |
# File 'lib/sashite/lcn/conditions.rb', line 147 def location?(location) @conditions.key?(location.to_sym) end |
#locations ⇒ Array<Symbol>
Get array of all location symbols
125 126 127 |
# File 'lib/sashite/lcn/conditions.rb', line 125 def locations @conditions.keys end |
#piece_locations ⇒ Array<Symbol>
Get locations requiring specific pieces
227 228 229 |
# File 'lib/sashite/lcn/conditions.rb', line 227 def piece_locations @conditions.reject { |_, v| RESERVED_KEYWORDS.include?(v) }.keys end |
#qpi_identifiers ⇒ Array<String>
Get array of QPI identifiers used
183 184 185 |
# File 'lib/sashite/lcn/conditions.rb', line 183 def qpi_identifiers @conditions.values.reject { |v| RESERVED_KEYWORDS.include?(v) }.uniq end |
#qpi_identifiers? ⇒ Boolean
Check if any QPI identifiers are used
197 198 199 |
# File 'lib/sashite/lcn/conditions.rb', line 197 def qpi_identifiers? @conditions.values.any? { |v| !RESERVED_KEYWORDS.include?(v) } end |
#size ⇒ Integer
Get number of conditions
132 133 134 |
# File 'lib/sashite/lcn/conditions.rb', line 132 def size @conditions.size end |
#to_h ⇒ Hash
Convert to hash with symbol keys
105 106 107 |
# File 'lib/sashite/lcn/conditions.rb', line 105 def to_h @conditions.dup end |
#to_s ⇒ String
String representation
310 311 312 |
# File 'lib/sashite/lcn/conditions.rb', line 310 def to_s @conditions.to_s end |
#valid_location?(location) ⇒ Boolean
Check if location uses valid CELL coordinate
155 156 157 |
# File 'lib/sashite/lcn/conditions.rb', line 155 def valid_location?(location) Cell.valid?(location.to_s) end |
#valid_state_value?(value) ⇒ Boolean
Check if state value is valid
163 164 165 |
# File 'lib/sashite/lcn/conditions.rb', line 163 def valid_state_value?(value) self.class.valid_state_value?(value) end |